Exemplo n.º 1
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]);
      }
    }
  }
Exemplo n.º 2
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);

}