Example #1
0
      void Orderizer::load_data(const char* filename)
      {
        FILE* f = fopen(filename, "rb");
        if (f == NULL) error("Could not open %s for reading.", filename);
        lock_data();

        struct { char magic[4]; int ver; } hdr;
        if (fread(&hdr, sizeof(hdr), 1, f) != 1)
          error("Error reading %s", filename);

        if (hdr.magic[0] != 'H' || hdr.magic[1] != '2' || hdr.magic[2] != 'D' || hdr.magic[3] != 'O')
          error("File %s is not a Hermes2D Orderizer<Scalar> file.", filename);
        if (hdr.ver > 1)
          error("File %s -- unsupported file version.", filename);

#define read_array(array, type, n, c, what) \
  if (fread(&n, sizeof(int), 1, f) != 1) \
  error("Error reading the number of " what " from %s", filename); \
  lin_init_array(array, type, c, n); \
  if (fread(array, sizeof(type), n, f) != (unsigned) n) \
  error("Error reading " what " from %s", filename);

        read_array(verts, double3, nv, cv,  "vertices");
        read_array(tris,  int3,    nt, ct,  "triangles");
        read_array(edges, int3,    ne, ce,  "edges");
        read_array(lvert, int,     nl, cl1, "label vertices");

        lin_init_array(lbox, double2, cl3, nl);
        if (fread(lbox, sizeof(double2), nl, f) != (unsigned) nl)
          error("Error reading label bounding boxes from %s", filename);

        int* orders = new int[nl];
        if (fread(orders, sizeof(int), nl, f) != (unsigned) nl)
          error("Error reading element orders from %s", filename);

        lin_init_array(ltext, char*, cl2, nl);
        for (int i = 0; i < nl; i++)
          ltext[i] = labels[H2D_GET_H_ORDER(orders[i])][H2D_GET_V_ORDER(orders[i])];

        find_min_max();
        unlock_data();
        fclose(f);
      }
Example #2
0
void Orderizer::process_solution(Space* space)
{
  // sanity check
  if (space == NULL) error("Space is NULL in Orderizer:process_solution().");

  if (!space->is_up_to_date())
    error("The space is not up to date.");

  int type = 1;

  nv = nt = ne = nl = 0;
  del_slot = -1;

  // estimate the required number of vertices and triangles
  Mesh* mesh = space->get_mesh();
  if (mesh == NULL) {
    error("Mesh is NULL in Orderizer:process_solution().");
  }
  int nn = mesh->get_num_active_elements();
  int ev = 77 * nn, et = 64 * nn, ee = 16 * nn, el = nn + 10;

  // reuse or allocate vertex, triangle and edge arrays
  lin_init_array(verts, double3, cv, ev);
  lin_init_array(tris, int3, ct, et);
  lin_init_array(edges, int3, ce, ee);
  lin_init_array(lvert, int, cl1, el);
  lin_init_array(ltext, char*, cl2, el);
  lin_init_array(lbox, double2, cl3, el);
  info = NULL;

  int oo, o[6];

  RefMap refmap;
  refmap.set_quad_2d(&quad_ord);

  // make a mesh illustrating the distribution of polynomial orders over the space
  Element* e;
  for_all_active_elements(e, mesh)
  {
    oo = o[4] = o[5] = space->get_element_order(e->id);
    for (unsigned int k = 0; k < e->nvert; k++)
      o[k] = space->get_edge_order(e, k);

    refmap.set_active_element(e);
    double* x = refmap.get_phys_x(type);
    double* y = refmap.get_phys_y(type);

    double3* pt = quad_ord.get_points(type);
    int np = quad_ord.get_num_points(type);
    int id[80];
    assert(np <= 80);

    #define make_vert(index, x, y, val) \
      { (index) = add_vertex(); \
      verts[index][0] = (x); \
      verts[index][1] = (y); \
      verts[index][2] = (val); }

    int mode = e->get_mode();
    if (e->is_quad())
    {
      o[4] = H2D_GET_H_ORDER(oo);
      o[5] = H2D_GET_V_ORDER(oo);
    }
    make_vert(lvert[nl], x[0], y[0], o[4]);

    for (int i = 1; i < np; i++)
      make_vert(id[i-1], x[i], y[i], o[(int) pt[i][2]]);

    for (int i = 0; i < num_elem[mode][type]; i++)
      add_triangle(id[ord_elem[mode][type][i][0]], id[ord_elem[mode][type][i][1]], id[ord_elem[mode][type][i][2]]);

    for (int i = 0; i < num_edge[mode][type]; i++)
    {
      if (e->en[ord_edge[mode][type][i][2]]->bnd || (y[ord_edge[mode][type][i][0] + 1] < y[ord_edge[mode][type][i][1] + 1]) ||
          ((y[ord_edge[mode][type][i][0] + 1] == y[ord_edge[mode][type][i][1] + 1]) &&
           (x[ord_edge[mode][type][i][0] + 1] <  x[ord_edge[mode][type][i][1] + 1])))
      {
        add_edge(id[ord_edge[mode][type][i][0]], id[ord_edge[mode][type][i][1]], 0);
      }
    }

    double xmin = 1e100, ymin = 1e100, xmax = -1e100, ymax = -1e100;
    for (unsigned int k = 0; k < e->nvert; k++)
    {
      if (e->vn[k]->x < xmin) xmin = e->vn[k]->x;
      if (e->vn[k]->x > xmax) xmax = e->vn[k]->x;
      if (e->vn[k]->y < ymin) ymin = e->vn[k]->y;
      if (e->vn[k]->y > ymax) ymax = e->vn[k]->y;
    }
    lbox[nl][0] = xmax - xmin;
    lbox[nl][1] = ymax - ymin;
    ltext[nl++] = labels[o[4]][o[5]];
  }
Example #3
0
void Linearizer::process_solution(MeshFunction* sln, int item, double eps, double max_abs,
                                  MeshFunction* xdisp, MeshFunction* ydisp, double dmult)
{
  lock_data();
  begin_time();

  // initialization
  this->sln = sln;
  this->item = item;
  this->eps = eps;
  this->xdisp = xdisp;
  this->ydisp = ydisp;
  this->dmult = dmult;
  nv = nt = ne = 0;
  del_slot = -1;

  if (!item) error("'item' cannot be zero.");
  get_gv_a_b(item, ia, ib);
  if (ib >= 6) error("Invalid 'item'.");

  disp = (xdisp != NULL || ydisp != NULL);
  if (disp && (xdisp == NULL || ydisp == NULL))
    error("Both displacement components must be supplied.");

  // estimate the required number of vertices and triangles
  Mesh* mesh = sln->get_mesh();
  int nn = mesh->get_num_elements();
  int ev = std::max(32 * nn, 10000);  // todo: check this
  int et = std::max(64 * nn, 20000);
  int ee = std::max(24 * nn, 7500);

  // check that displacement meshes are the same
  if (disp)
  {
    unsigned seq1 = mesh->get_seq();
    unsigned seq2 = xdisp->get_mesh()->get_seq();
    unsigned seq3 = ydisp->get_mesh()->get_seq();
    if (seq1 != seq2 || seq1 != seq3)
      error("Displacements must be defined on the same mesh as the solution.");
  }

  // reuse or allocate vertex, triangle and edge arrays
  lin_init_array(verts, double3, cv, ev);
  lin_init_array(tris, int3, ct, et);
  lin_init_array(edges, int3, ce, ee);
  info = (int4*) malloc(sizeof(int4) * cv);

  // initialize the hash table
  int size = 0x2000;
  while (size*2 < cv) size *= 2;
  hash_table = (int*) malloc(sizeof(int) * size);
  memset(hash_table, 0xff, sizeof(int) * size);
  mask = size-1;

  // select the linearization quadrature
  Quad2D *old_quad, *old_quad_x, *old_quad_y;
  old_quad = sln->get_quad_2d();
  sln->set_quad_2d(&quad_lin);
  if (disp) { old_quad_x = xdisp->get_quad_2d();
              old_quad_y = ydisp->get_quad_2d();
              xdisp->set_quad_2d(&quad_lin);
              ydisp->set_quad_2d(&quad_lin); }

  // create all top-level vertices (corresponding to vertex nodes), with
  // all parent-son relations preserved; this is necessary for regularization to
  // work on irregular meshes
  nn = mesh->get_max_node_id();
  int* id2id = new int[nn];
  memset(id2id, 0xff, sizeof(int) * nn);
  bool finished;
  do
  {
    finished = true;
    Node* node;
    for_all_vertex_nodes(node, mesh)
    {
      if (id2id[node->id] < 0 && node->ref != TOP_LEVEL_REF)
        if (node->p1 < 0)
          id2id[node->id] = get_vertex(node->id, node->id, node->x, node->y, 0);
        else if (id2id[node->p1] >= 0 && id2id[node->p2] >= 0)
          id2id[node->id] = get_vertex(id2id[node->p1], id2id[node->p2], node->x, node->y, 0);
        else
          finished = false;
    }
  }
  while (!finished);

  auto_max = (max_abs < 0.0);
  max = auto_max ? 0.0 : max_abs;

  // obtain the solution in vertices, estimate the maximum solution value
  Element* e;
  for_all_active_elements(e, mesh)
  {
    sln->set_active_element(e);
    sln->set_quad_order(0, item);
    scalar* val = sln->get_values(ia, ib);
    if (val == NULL) error("item not defined in the solution.");

    scalar *dx, *dy;
    if (disp)
    {
      xdisp->set_active_element(e);
      ydisp->set_active_element(e);
      xdisp->set_quad_order(0, FN_VAL);
      ydisp->set_quad_order(0, FN_VAL);
      dx = xdisp->get_fn_values();
      dy = ydisp->get_fn_values();
    }

    for (unsigned int i = 0; i < e->nvert; i++)
    {
      double f = getval(i);
      if (auto_max && finite(f) && fabs(f) > max) max = fabs(f);
      int id = id2id[e->vn[i]->id];
      verts[id][2] = f;

      if (disp)
      {
        verts[id][0] = e->vn[i]->x + dmult*realpart(dx[i]);
        verts[id][1] = e->vn[i]->y + dmult*realpart(dy[i]);
      }
    }
  }
Example #4
0
void Vectorizer::process_solution(MeshFunction* xsln, int xitem, MeshFunction* ysln, int yitem, double eps)
{
  // sanity check
  if (xsln == NULL || ysln == NULL) error("One of the solutions is NULL in Vectorizer:process_solution().");


  lock_data();
  TimePeriod cpu_time;

  // initialization
  this->xsln = xsln;
  this->ysln = ysln;
  this->xitem = xitem;
  this->yitem = yitem;
  this->eps = eps;
  nv = nt = ne = nd = 0;
  del_slot = -1;

  Mesh* meshes[2] = { xsln->get_mesh(), ysln->get_mesh() };
  if (meshes[0] == NULL || meshes[1] == NULL) {
    error("One of the meshes is NULL in Vectorizer:process_solution().");
  }

  Transformable* fns[2] = { xsln, ysln };
  Traverse trav;

  // estimate the required number of vertices and triangles
  // (based on the assumption that the linear mesh will be
  // about four-times finer than the original mesh).
  int nn = meshes[0]->get_num_elements() + meshes[1]->get_num_elements();
  int ev = std::max(32 * nn, 10000);
  int et = std::max(64 * nn, 20000);
  int ee = std::max(24 * nn, 7500);
  int ed = ee;

  lin_init_array(verts, double4, cv, ev);
  lin_init_array(tris, int3, ct, et);
  lin_init_array(edges, int3, ce, ee);
  lin_init_array(dashes, int2, cd, ed);

  info = (int4*) malloc(sizeof(int4) * cv);

  // initialize the hash table
  int size = 0x1000;
  while (size*2 < cv) size *= 2;
  hash_table = (int*) malloc(sizeof(int) * size);
  memset(hash_table, 0xff, sizeof(int) * size);
  mask = size-1;


  // select the linearization quadrature
  Quad2D *old_quad_x, *old_quad_y;
  old_quad_x = xsln->get_quad_2d();
  old_quad_y = ysln->get_quad_2d();

  xsln->set_quad_2d((Quad2D*) &quad_lin);
  ysln->set_quad_2d((Quad2D*) &quad_lin);

  if (!xitem) error("Parameter 'xitem' cannot be zero.");
  if (!yitem) error("Parameter 'yitem' cannot be zero.");
  get_gv_a_b(xitem, xia, xib);
  get_gv_a_b(yitem, yia, yib);
  if (xib >= 6) error("Invalid value of paremeter 'xitem'.");
  if (yib >= 6) error("Invalid value of paremeter 'yitem'.");

  max = 1e-10;
  trav.begin(2, meshes, fns);
  Element** e;
  while ((e = trav.get_next_state(NULL, NULL)) != NULL)
  {
    xsln->set_quad_order(0, xitem);
    ysln->set_quad_order(0, yitem);
    scalar* xval = xsln->get_values(xia, xib);
    scalar* yval = ysln->get_values(yia, yib);

    for (unsigned int i = 0; i < e[0]->nvert; i++)
    {
      double fx = getvalx(i);
      double fy = getvaly(i);
      if (fabs(sqrt(fx*fx + fy*fy)) > max) max = fabs(sqrt(fx*fx + fy*fy));
    }
  }
  trav.finish();

  trav.begin(2, meshes, fns);
  // process all elements of the mesh
  while ((e = trav.get_next_state(NULL, NULL)) != NULL)
  {
    xsln->set_quad_order(0, xitem);
    ysln->set_quad_order(0, yitem);
    scalar* xval = xsln->get_values(xia, xib);
    scalar* yval = ysln->get_values(yia, yib);

    double* x = xsln->get_refmap()->get_phys_x(0);
    double* y = ysln->get_refmap()->get_phys_y(0);

    int iv[4];
    for (unsigned int i = 0; i < e[0]->nvert; i++)
    {
      double fx = getvalx(i);
      double fy = getvaly(i);
      iv[i] = create_vertex(x[i], y[i], fx, fy);
    }

    // we won't bother calculating physical coordinates from the refmap if this is not a curved element
    curved = (e[0]->cm != NULL);

    // recur to sub-elements
    if (e[0]->is_triangle())
      process_triangle(iv[0], iv[1], iv[2], 0, NULL, NULL, NULL, NULL, NULL);
    else
      process_quad(iv[0], iv[1], iv[2], iv[3], 0, NULL, NULL, NULL, NULL, NULL);

    // process edges and dashes (bold line for edge in both meshes, dashed line for edge in one of the meshes)
    Trf* xctm = xsln->get_ctm();
    Trf* yctm = ysln->get_ctm();
    double r[4] = { -1.0, 1.0, 1.0, -1.0 };
    double ref[4][2] = { {-1.0,-1.0}, {1.0,-1.0}, {1.0,1.0}, {-1.0,1.0} };
    for (unsigned int i = 0; i < e[0]->nvert; i++)
    {
      bool bold = false;
      double px = ref[i][0];
      double py = ref[i][1];
      // for odd edges (1, 3) we check x coordinate after ctm transformation, if it's the same (1 or -1) in both meshes => bold
      if (i & 1) {
        if ((xctm->m[0]*px + xctm->t[0] == r[i]) && (yctm->m[0]*px + yctm->t[0] == r[i]))
          bold = true;
      }
      // for even edges (0, 4) we check y coordinate after ctm transformation, if it's the same (-1 or 1) in both meshes => bold
      else {
        if ((xctm->m[1]*py + xctm->t[1] == r[i]) && (yctm->m[1]*py + yctm->t[1] == r[i]))
          bold = true;
      }
      int j = e[0]->next_vert(i);
      // we draw a line only if both edges lies on the boundary or if the line is from left top to right bottom
      if (((e[0]->en[i]->bnd) && (e[1]->en[i]->bnd)) ||
         (verts[iv[i]][1] < verts[iv[j]][1]) ||
         (verts[iv[i]][1] == verts[iv[j]][1] && verts[iv[i]][0] < verts[iv[j]][0]))
      {
        if (bold)
          process_edge(iv[i], iv[j], e[0]->en[i]->marker);
        else
          process_dash(iv[i], iv[j]);
      }
    }
  }
  trav.finish();

  find_min_max();

  verbose("Vectorizer created %d verts and %d tris in %0.3g s", nv, nt, cpu_time.tick().last());
  //if (verbose_mode) print_hash_stats();
  unlock_data();

   // select old quadratrues
  xsln->set_quad_2d(old_quad_x);
  ysln->set_quad_2d(old_quad_y);

  // clean up
  ::free(hash_table);
  ::free(info);

}