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); }
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]]; }
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]); } } }
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); }