16 #include "mesh_util.h"
20 #include "mesh_reader_h2d.h"
21 #include "neighbor_search.h"
29 unsigned g_mesh_seq = 0;
30 static const int H2D_DG_INNER_EDGE_INT = -54125631;
31 static const std::string H2D_DG_INNER_EDGE =
"-54125631";
33 Mesh::Mesh() : HashTable(), meshHashGrid(nullptr), nbase(0), nactive(0), ntopvert(0), ninitial(0), seq(g_mesh_seq++),
34 bounding_box_calculated(0)
47 if (this->elements.get_size() < 1)
49 if (this->nodes.get_size() < 1)
63 ref_mesh->
copy(this->coarse_mesh);
65 return MeshSharedPtr(ref_mesh);
72 Quad2D* quad = &g_quad_2d_std;
73 for_all_active_elements(e,
this)
77 int i, mo = quad->get_max_order(e->get_mode());
79 int k = e->is_triangle() ? 2 : 3;
81 double const_m[2][2] =
83 { e->
vn[1]->
x - e->
vn[0]->
x, e->
vn[k]->
x - e->
vn[0]->
x },
84 { e->
vn[1]->y - e->
vn[0]->y, e->
vn[k]->y - e->
vn[0]->y }
87 double const_jacobian = 0.25 * (const_m[0][0] * const_m[1][1] - const_m[0][1] * const_m[1][0]);
88 if (const_jacobian <= 0.0)
89 throw Hermes::Exceptions::MeshLoadFailureException(
"Element #%d is concave or badly oriented in initial_single_check().", e->
id);
92 double3* pt = quad->get_points(mo, e->get_mode());
97 for (i = 0; i < quad->get_num_points(mo, e->get_mode()); i++)
99 throw Hermes::Exceptions::MeshLoadFailureException(
"Element #%d is concave or badly oriented in initial_single_check().", e->
id);
111 while (size < 2 * nv) size *= 2;
115 for (
int i = 0; i < nv; i++)
118 assert(node->
id == i);
119 node->
ref = TOP_LEVEL_REF;
120 node->
type = HERMES_TYPE_VERTEX;
122 node->
p1 = node->p2 = -1;
124 node->
x = verts[i][0];
125 node->y = verts[i][1];
131 for (
int i = 0; i < nt; i++)
133 e = create_triangle(this->element_markers_conversion.
insert_marker(tri_markers[i]), &
nodes[tris[i][0]], &
nodes[tris[i][1]],
134 &
nodes[tris[i][2]],
nullptr);
138 for (
int i = 0; i < nq; i++)
140 e = create_quad(this->element_markers_conversion.
insert_marker(quad_markers[i]), &
nodes[quads[i][0]], &
nodes[quads[i][1]],
141 &
nodes[quads[i][2]], &
nodes[quads[i][3]],
nullptr);
145 for (
int i = 0; i < nm; i++)
149 throw Hermes::Exceptions::Exception(
"Boundary data error (edge does not exist)");
153 nodes[mark[i][0]].bnd = 1;
154 nodes[mark[i][1]].bnd = 1;
158 nbase = nactive = ninitial = nt + nq;
164 if (
this ==
nullptr)
throw Hermes::Exceptions::Exception(
"this == nullptr in Mesh::get_num_elements().");
168 return elements.get_num_items();
173 if (
this ==
nullptr)
throw Hermes::Exceptions::Exception(
"this == nullptr in Mesh::get_num_base_elements().");
185 throw Hermes::Exceptions::Exception(
"this == nullptr in Mesh::get_num_base_elements().");
192 for_all_base_elements(e,
this)
201 throw Hermes::Exceptions::Exception(
"this == nullptr in Mesh::get_num_active_elements().");
211 throw Hermes::Exceptions::Exception(
"this == nullptr in Mesh::get_max_element_id().");
215 return elements.get_size();
221 throw Hermes::Exceptions::Exception(
"this == nullptr in Mesh::get_num_vertex_nodes().");
239 throw Hermes::Exceptions::Exception(
"this == nullptr in Mesh::get_num_vertex_nodes().");
256 if (id < 0 || id >= elements.get_size())
257 throw Hermes::Exceptions::Exception(
"Invalid element ID %d, current range:[0; %d]",
id, elements.get_size());
258 return &(elements[
id]);
266 void Mesh::calc_bounding_box()
271 for_all_vertex_nodes(n,
this)
275 this->bottom_left_x = this->top_right_x = n->
x;
276 this->bottom_left_y = this->top_right_y = n->y;
281 if (n->
x > this->top_right_x)
282 this->top_right_x = n->
x;
283 if (n->
x < this->bottom_left_x)
284 this->bottom_left_x = n->
x;
285 if (n->y > this->top_right_y)
286 this->top_right_y = n->y;
287 if (n->y < this->bottom_left_y)
288 this->bottom_left_y = n->y;
295 if (!this->bounding_box_calculated)
296 this->calc_bounding_box();
298 top_right_x_ = this->top_right_x;
299 bottom_left_x_ = this->bottom_left_x;
300 top_right_y_ = this->top_right_y;
301 bottom_left_y_ = this->bottom_left_y;
303 bounding_box_calculated =
true;
313 return &(elements[
id]);
334 if (v0 == v1 || v1 == v2 || v2 == v0)
335 throw Hermes::Exceptions::MeshLoadFailureException(
"Some of the vertices of element #%d are identical which is impossible.", e->
id);
337 if (v0->
x == v1->
x && v0->
x == v2->
x)
338 throw Hermes::Exceptions::MeshLoadFailureException(
"Vertices [%i, %i, %i] in element %i share x-coordinates: [%f, %f, %f].", e->
id, v0->
id, v1->
id, v2->
id, v0->
x, v1->
x, v2->
x);
340 if (v0->y == v1->y && v0->y == v2->y)
341 throw Hermes::Exceptions::MeshLoadFailureException(
"Vertices [%i, %i, %i] in element %i share y-coordinates: [%f, %f, %f].", e->
id, v0->
id, v1->
id, v2->
id, v0->y, v1->y, v2->y);
357 Element* Mesh::create_quad(
int marker, Node* v0, Node* v1, Node* v2, Node* v3,
361 Element* e = elements.add();
376 if (v0 == v1 || v1 == v2 || v2 == v3 || v3 == v0 || v2 == v0 || v3 == v1)
377 throw Hermes::Exceptions::MeshLoadFailureException(
"Some of the vertices of element #%d are identical which is not right.", e->id);
379 if ((v0->x == v1->x && v0->x == v2->x) || (v0->x == v1->x && v0->x == v3->x) || (v0->x == v2->x && v0->x == v3->x) || (v1->x == v2->x && v2->x == v3->x))
380 throw Hermes::Exceptions::MeshLoadFailureException(
"Some of the vertices [%i, %i, %i, %i] in element %i share x-coordinates: [%f, %f, %f, %f].", e->id, v0->id, v1->id, v2->id, v0->x, v1->x, v2->x, v3->x);
382 if ((v0->y == v1->y && v0->y == v2->y) || (v0->y == v1->y && v0->y == v3->y) || (v0->y == v2->y && v0->y == v3->y) || (v1->y == v2->y && v2->y == v3->y))
383 throw Hermes::Exceptions::MeshLoadFailureException(
"Some of the vertices [%i, %i, %i, %i] in element %i share y-coordinates: [%f, %f, %f, %f].", e->id, v0->id, v1->id, v2->id, v0->y, v1->y, v2->y, v3->y);
401 void Mesh::refine_triangle_to_triangles(Element* e, Element** sons_out)
404 int bnd[3] = { e->en[0]->bnd, e->en[1]->bnd, e->en[2]->bnd };
405 int mrk[3] = { e->en[0]->marker, e->en[1]->marker, e->en[2]->marker };
419 double2 pt[3] = { { 0.0, -1.0 }, { 0.0, 0.0 }, { -1.0, 0.0 } };
420 e->cm->get_mid_edge_points(e, pt, 3);
421 x0->x = pt[0][0]; x0->y = pt[0][1];
422 x1->x = pt[1][0]; x1->y = pt[1][1];
423 x2->x = pt[2][0]; x2->y = pt[2][1];
426 for (
int i = 0; i < 4; i++)
427 cm[i] = CurvMap::create_son_curv_map(e, i);
432 sons[0] = create_triangle(e->marker, e->vn[0], x0, x2, cm[0]);
433 sons[1] = create_triangle(e->marker, x0, e->vn[1], x1, cm[1]);
434 sons[2] = create_triangle(e->marker, x2, x1, e->vn[2], cm[2]);
435 sons[3] = create_triangle(e->marker, x1, x2, x0, cm[3]);
438 for (
int i = 0; i < 4; i++)
439 if (sons[i]->is_curved())
440 sons[i]->cm->update_refmap_coeffs(sons[i]);
445 e->unref_all_nodes(
this);
449 sons[0]->en[0]->bnd = bnd[0]; sons[0]->en[0]->marker = mrk[0];
450 sons[0]->en[2]->bnd = bnd[2]; sons[0]->en[2]->marker = mrk[2];
451 sons[1]->en[0]->bnd = bnd[0]; sons[1]->en[0]->marker = mrk[0];
452 sons[1]->en[1]->bnd = bnd[1]; sons[1]->en[1]->marker = mrk[1];
453 sons[2]->en[1]->bnd = bnd[1]; sons[2]->en[1]->marker = mrk[1];
454 sons[2]->en[2]->bnd = bnd[2]; sons[2]->en[2]->marker = mrk[2];
455 sons[3]->vn[0]->bnd = bnd[1];
456 sons[3]->vn[1]->bnd = bnd[2];
457 sons[3]->vn[2]->bnd = bnd[0];
460 for (
int i = 0; i < 4; i++)
462 if (sons[i] !=
nullptr) sons[i]->parent = e;
466 memcpy(e->sons, sons, 4 *
sizeof(Element*));
469 if (sons_out !=
nullptr)
471 for (
int i = 0; i < 3; i++) sons_out[i] = sons[i];
478 Node* newnode =
new Node();
479 newnode->type = HERMES_TYPE_VERTEX;
484 newnode->x = (v1->x + v2->x) * 0.5;
485 newnode->y = (v1->y + v2->y) * 0.5;
493 Node* newnode =
new Node();
494 newnode->type = HERMES_TYPE_EDGE;
500 newnode->elem[0] = newnode->elem[1] =
nullptr;
521 memset(cm, 0,
sizeof(cm));
527 Node* x0, *x1, *x2, *x3, *mid;
537 double2 pt[5] = { { 0.0, -1.0 }, { 1.0, 0.0 }, { 0.0, 1.0 }, { -1.0, 0.0 }, { 0.0, 0.0 } };
538 e->
cm->get_mid_edge_points(e, pt, 5);
539 x0->
x = pt[0][0]; x0->y = pt[0][1];
540 x1->
x = pt[1][0]; x1->y = pt[1][1];
541 x2->
x = pt[2][0]; x2->y = pt[2][1];
542 x3->
x = pt[3][0]; x3->y = pt[3][1];
543 mid->
x = pt[4][0]; mid->y = pt[4][1];
547 cm[i] = CurvMap::create_son_curv_map(e, i);
551 sons[0] = create_quad(e->
marker, e->
vn[0], x0, mid, x3, cm[0]);
552 sons[1] = create_quad(e->
marker, x0, e->
vn[1], x1, mid, cm[1]);
553 sons[2] = create_quad(e->
marker, mid, x1, e->
vn[2], x2, cm[2]);
554 sons[3] = create_quad(e->
marker, x3, mid, x2, e->
vn[3], cm[3]);
562 j = (i > 0) ? i - 1 : 3;
563 sons[i]->
en[j]->
bnd = bnd[j]; sons[i]->
en[j]->
marker = mrk[j];
564 sons[i]->
en[i]->
bnd = bnd[i]; sons[i]->
en[i]->
marker = mrk[i];
565 sons[i]->
vn[j]->
bnd = bnd[j];
570 else if (refinement == 1)
579 double2 pt[2] = { { 1.0, 0.0 }, { -1.0, 0.0 } };
580 e->
cm->get_mid_edge_points(e, pt, 2);
581 x1->
x = pt[0][0]; x1->y = pt[0][1];
582 x3->
x = pt[1][0]; x3->y = pt[1][1];
585 for (i = 0; i < 2; i++)
586 cm[i] = CurvMap::create_son_curv_map(e, i + 4);
589 sons[0] = create_quad(e->
marker, e->
vn[0], e->
vn[1], x1, x3, cm[0]);
590 sons[1] = create_quad(e->
marker, x3, x1, e->
vn[2], e->
vn[3], cm[1]);
591 sons[2] = sons[3] =
nullptr;
595 sons[0]->
en[0]->
bnd = bnd[0]; sons[0]->
en[0]->
marker = mrk[0];
596 sons[0]->
en[1]->
bnd = bnd[1]; sons[0]->
en[1]->
marker = mrk[1];
597 sons[0]->
en[3]->
bnd = bnd[3]; sons[0]->
en[3]->
marker = mrk[3];
598 sons[1]->
en[1]->
bnd = bnd[1]; sons[1]->
en[1]->
marker = mrk[1];
599 sons[1]->
en[2]->
bnd = bnd[2]; sons[1]->
en[2]->
marker = mrk[2];
600 sons[1]->
en[3]->
bnd = bnd[3]; sons[1]->
en[3]->
marker = mrk[3];
601 sons[0]->
vn[2]->
bnd = bnd[1];
602 sons[0]->
vn[3]->
bnd = bnd[3];
606 else if (refinement == 2)
615 double2 pt[2] = { { 0.0, -1.0 }, { 0.0, 1.0 } };
616 e->
cm->get_mid_edge_points(e, pt, 2);
617 x0->
x = pt[0][0]; x0->y = pt[0][1];
618 x2->
x = pt[1][0]; x2->y = pt[1][1];
621 for (i = 0; i < 2; i++)
622 cm[i] = CurvMap::create_son_curv_map(e, i + 6);
625 sons[0] = sons[1] =
nullptr;
626 sons[2] = create_quad(e->
marker, e->
vn[0], x0, x2, e->
vn[3], cm[0]);
627 sons[3] = create_quad(e->
marker, x0, e->
vn[1], e->
vn[2], x2, cm[1]);
631 sons[2]->
en[0]->
bnd = bnd[0]; sons[2]->
en[0]->
marker = mrk[0];
632 sons[2]->
en[2]->
bnd = bnd[2]; sons[2]->
en[2]->
marker = mrk[2];
633 sons[2]->
en[3]->
bnd = bnd[3]; sons[2]->
en[3]->
marker = mrk[3];
634 sons[3]->
en[0]->
bnd = bnd[0]; sons[3]->
en[0]->
marker = mrk[0];
635 sons[3]->
en[1]->
bnd = bnd[1]; sons[3]->
en[1]->
marker = mrk[1];
636 sons[3]->
en[2]->
bnd = bnd[2]; sons[3]->
en[2]->
marker = mrk[2];
637 sons[2]->
vn[1]->
bnd = bnd[0];
638 sons[2]->
vn[2]->
bnd = bnd[2];
643 for (i = 0; i < 4; i++)
651 for (
int i = 0; i < 4; i++)
652 if (sons[i] !=
nullptr)
656 memcpy(e->
sons, sons,
sizeof(sons));
659 if (sons_out !=
nullptr)
661 for (
int i = 0; i < 4; i++)
662 sons_out[i] = sons[i];
666 void Mesh::unrefine_element_internal(
Element* e)
668 this->
refinements.push_back(std::pair<unsigned int, int>(e->
id, -1));
675 for (
unsigned i = 0; i < e->get_nvert(); i++)
686 Element* son = e->
sons[i];
690 if (son->cm !=
nullptr)
695 elements.remove(son->id);
701 for (i = 0; i < e->get_nvert(); i++)
709 for (i = 0; i < e->get_nvert(); i++)
712 e->
en[i]->
bnd = bnd[i];
716 void Mesh::refine_element(Element* e,
int refinement)
718 this->
refinements.push_back(std::pair<unsigned int, int>(e->id, refinement));
720 if (e->is_triangle())
724 refine_triangle_to_quads(e);
728 this->refine_triangle_to_triangles(e);
735 e->sons[i]->iro_cache = e->iro_cache;
737 this->seq = g_mesh_seq++;
742 if (refinement == -1)
746 throw Hermes::Exceptions::Exception(
"Invalid element id number.");
748 throw Hermes::Exceptions::Exception(
"Attempt to refine element #%d which has been refined already.", e->
id);
749 this->refine_element(e, refinement);
756 if (refinement == -1)
759 elements.set_append_only(
true);
763 for_all_active_elements(e,
this)
764 refine_element(e, refinement);
766 elements.set_append_only(
false);
772 static int rtb_marker;
773 static bool rtb_aniso;
774 static char* rtb_vert;
779 elements.set_append_only(
true);
780 for (
int r, i = 0; i < depth; i++)
782 for_all_active_elements(e,
this)
784 if ((r = criterion(e)) >= 0)
788 elements.set_append_only(
false);
796 static int rtv_criterion(
Element* e)
798 for (
unsigned int i = 0; i < e->get_nvert(); i++)
799 if (e->
vn[i]->
id == rtv_id)
815 for (i = 0; i < e->get_nvert(); i++)
817 if (e->
en[i]->
marker == rtb_marker || rtb_vert[e->
vn[i]->
id])
823 if (i >= e->get_nvert())
return -1;
828 if (e->is_triangle() || !rtb_aniso)
return 0;
831 if ((e->
en[0]->
marker == rtb_marker && !rtb_vert[e->
vn[2]->
id] && !rtb_vert[e->
vn[3]->
id]) ||
832 (e->
en[2]->
marker == rtb_marker && !rtb_vert[e->
vn[0]->
id] && !rtb_vert[e->
vn[1]->
id]) ||
834 e->
en[1]->
marker != rtb_marker && e->
en[3]->
marker != rtb_marker))
return 1;
837 if ((e->
en[1]->
marker == rtb_marker && !rtb_vert[e->
vn[3]->
id] && !rtb_vert[e->
vn[0]->
id]) ||
838 (e->
en[3]->
marker == rtb_marker && !rtb_vert[e->
vn[1]->
id] && !rtb_vert[e->
vn[2]->
id]) ||
840 e->
en[0]->
marker != rtb_marker && e->
en[2]->
marker != rtb_marker))
return 2;
851 for (
int i = 0; i < depth; i++)
855 rtb_vert =
new char[size];
856 memset(rtb_vert, 0,
sizeof(
char)* size);
859 for_all_active_elements(e,
this)
860 for (
unsigned int j = 0; j < e->get_nvert(); j++)
862 bool marker_matched =
false;
863 for (
unsigned int marker_i = 0; marker_i < markers.size(); marker_i++)
864 if (e->
en[j]->
marker == this->boundary_markers_conversion.get_internal_marker(markers[marker_i]).marker)
865 marker_matched =
true;
880 throw Hermes::Exceptions::Exception(
"None of the markers in Mesh::refine_towards_boundary found in the Mesh.");
885 if (marker == HERMES_ANY)
886 for (std::map<int, std::string>::iterator it = this->boundary_markers_conversion.
conversion_table.begin(); it != this->boundary_markers_conversion.
conversion_table.end(); ++it)
896 for (
int i = 0; i < depth; i++)
900 rtb_vert =
new char[size];
901 memset(rtb_vert, 0,
sizeof(
char)* size);
904 for_all_active_elements(e,
this)
905 for (
unsigned int j = 0; j < e->get_nvert(); j++)
921 throw Hermes::Exceptions::Exception(
"None of the markers in Mesh::refine_towards_boundary found in the Mesh.");
927 std::vector<std::string> markers;
928 markers.push_back(marker);
934 std::vector<int> internal_markers;
935 bool any_marker =
false;
936 for (
unsigned int marker_i = 0; marker_i < markers.size(); marker_i++)
938 if (markers[marker_i] == HERMES_ANY)
943 int marker = this->element_markers_conversion.
get_internal_marker(markers[marker_i]).marker;
945 internal_markers.push_back(marker);
949 for (
int i = 0; i < depth; i++)
955 for_all_active_elements(e,
this)
957 this->refine_element(e, refinement);
963 for_all_active_elements(e,
this)
965 for (
unsigned int marker_i = 0; marker_i < internal_markers.size(); marker_i++)
966 if (e->
marker == internal_markers[marker_i])
968 this->refine_element(e, refinement);
978 throw Hermes::Exceptions::Exception(
"None of the markers in Mesh::refine_in_areas found in the Mesh.");
984 if (!e->
used)
throw Hermes::Exceptions::Exception(
"Invalid element id number.");
987 for (
int i = 0; i < 4; i++)
988 if (e->
sons[i] !=
nullptr)
991 unrefine_element_internal(e);
998 std::vector<int> list;
1000 for_all_inactive_elements(e,
this)
1003 for (
unsigned int i = 0; i < 4; i++)
1004 if (e->
sons[i] !=
nullptr &&
1005 (!e->
sons[i]->
active || (keep_initial_refinements && e->
sons[i]->
id < ninitial))
1008 found =
false;
break;
1011 if (found) list.push_back(e->
id);
1015 for (
unsigned int i = 0; i < list.size(); i++)
1021 return sqrt(sqr(a_1) + sqr(a_2));
1024 bool Mesh::same_line(
double p_1,
double p_2,
double q_1,
double q_2,
double r_1,
double r_2)
1026 double pq_1 = q_1 - p_1, pq_2 = q_2 - p_2, pr_1 = r_1 - p_1, pr_2 = r_2 - p_2;
1029 double sin_angle = (pq_1*pr_2 - pq_2*pr_1) / (length_pq*length_pr);
1030 if (fabs(sin_angle) < Hermes::HermesEpsilon)
return true;
1036 if (a_1*b_2 - a_2*b_1 > 0)
return true;
1040 void Mesh::check_triangle(
int i,
Node *&v0,
Node *&v1,
Node *&v2)
1047 if (length_1 < Hermes::HermesSqrtEpsilon || length_2 < Hermes::HermesSqrtEpsilon || length_3 < Hermes::HermesSqrtEpsilon)
1048 throw Hermes::Exceptions::Exception(
"Edge of triangular element #%d has length less than Hermes::HermesSqrtEpsilon.", i);
1051 if (
same_line(v0->
x, v0->y, v1->
x, v1->y, v2->
x, v2->y))
1052 throw Hermes::Exceptions::Exception(
"Triangular element #%d: all vertices lie on the same line.", i);
1055 if (!
is_convex(v1->
x - v0->
x, v1->y - v0->y, v2->
x - v0->
x, v2->y - v0->y))
1061 void Mesh::check_quad(
int i, Node *&v0, Node *&v1, Node *&v2, Node *&v3)
1069 if (length_1 < Hermes::HermesSqrtEpsilon || length_2 < Hermes::HermesSqrtEpsilon || length_3 < Hermes::HermesSqrtEpsilon || length_4 < Hermes::HermesSqrtEpsilon)
1070 throw Hermes::Exceptions::Exception(
"Edge of quad element #%d has length less than Hermes::HermesSqrtEpsilon.", i);
1076 if (diag_1 < Hermes::HermesSqrtEpsilon || diag_2 < Hermes::HermesSqrtEpsilon)
1077 throw Hermes::Exceptions::Exception(
"Diagonal of quad element #%d has length less than Hermes::HermesSqrtEpsilon.", i);
1080 if (
same_line(v0->x, v0->y, v1->x, v1->y, v2->x, v2->y))
1081 throw Hermes::Exceptions::Exception(
"Quad element #%d: vertices v0, v1, v2 lie on the same line.", i);
1083 if (
same_line(v0->x, v0->y, v1->x, v1->y, v3->x, v3->y))
1084 throw Hermes::Exceptions::Exception(
"Quad element #%d: vertices v0, v1, v3 lie on the same line.", i);
1086 if (
same_line(v0->x, v0->y, v2->x, v2->y, v3->x, v3->y))
1087 throw Hermes::Exceptions::Exception(
"Quad element #%d: vertices v0, v2, v3 lie on the same line.", i);
1089 if (
same_line(v1->x, v1->y, v2->x, v2->y, v3->x, v3->y))
1090 throw Hermes::Exceptions::Exception(
"Quad element #%d: vertices v1, v2, v3 lie on the same line.", i);
1093 int vertex_1_ok =
is_convex(v1->x - v0->x, v1->y - v0->y, v2->x - v0->x, v2->y - v0->y);
1094 if (!vertex_1_ok)
throw Hermes::Exceptions::Exception(
"Vertex v1 of quad element #%d does not lie on the right of the diagonal v2-v0.", i);
1096 int vertex_3_ok =
is_convex(v2->x - v0->x, v2->y - v0->y, v3->x - v0->x, v3->y - v0->y);
1097 if (!vertex_3_ok)
throw Hermes::Exceptions::Exception(
"Vertex v3 of quad element #%d does not lie on the left of the diagonal v2-v0.", i);
1099 int vertex_2_ok =
is_convex(v2->x - v1->x, v2->y - v1->y, v3->x - v1->x, v3->y - v1->y);
1100 if (!vertex_2_ok)
throw Hermes::Exceptions::Exception(
"Vertex v2 of quad element #%d does not lie on the right of the diagonal v3-v1.", i);
1102 int vertex_0_ok =
is_convex(v3->x - v1->x, v3->y - v1->y, v0->x - v1->x, v0->y - v1->y);
1103 if (!vertex_0_ok)
throw Hermes::Exceptions::Exception(
"Vertex v0 of quad element #%d does not lie on the left of the diagonal v2-v1.", i);
1110 for_all_vertex_nodes(n,
this) {
1117 for_all_used_elements(e,
this)
1118 if (e->
cm !=
nullptr)
1120 throw CurvedException(e->
id);
1134 elements.copy(mesh->elements);
1139 for_all_used_elements(e,
this)
1142 for (i = 0; i < e->get_nvert(); i++)
1148 for (i = 0; i < e->get_nvert(); i++)
1154 for (i = 0; i < 4; i++)
1155 if (e->
sons[i] !=
nullptr)
1160 if (e->
cm !=
nullptr)
1164 e->
cm->parent = &elements[e->
cm->parent->
id];
1168 if (e->
parent !=
nullptr)
1174 for_all_edge_nodes(node,
this)
1175 for (i = 0; i < 2; i++)
1176 if (node->
elem[i] !=
nullptr)
1177 node->
elem[i] = &elements[node->
elem[i]->
id];
1179 nbase = mesh->nbase;
1180 nactive = mesh->nactive;
1181 ntopvert = mesh->ntopvert;
1182 ninitial = mesh->ninitial;
1184 boundary_markers_conversion = mesh->boundary_markers_conversion;
1185 element_markers_conversion = mesh->element_markers_conversion;
1200 for (
int i = 0; i < mesh->get_max_node_id(); i++)
1202 Node* node = &(mesh->nodes[i]);
1203 if (node->
ref < TOP_LEVEL_REF)
break;
1205 assert(newnode->
id == i && node->
type == HERMES_TYPE_VERTEX);
1206 memcpy(newnode, node,
sizeof(
Node));
1207 newnode->
ref = TOP_LEVEL_REF;
1212 for (
int id = 0;
id < mesh->get_num_base_elements();
id++)
1214 e = mesh->get_element_fast(
id);
1217 Element* e_temp = elements.add();
1218 e_temp->
used =
false;
1219 e_temp->
cm =
nullptr;
1224 if (e->is_triangle())
1225 enew = this->create_triangle(e->
marker, v0, v1, v2,
nullptr);
1227 enew = this->create_quad(e->
marker, v0, v1, v2, &
nodes[e->
vn[3]->
id],
nullptr);
1230 for (
unsigned int j = 0; j < e->get_nvert(); j++)
1242 this->boundary_markers_conversion = mesh->boundary_markers_conversion;
1243 this->element_markers_conversion = mesh->element_markers_conversion;
1245 nbase = nactive = ninitial = mesh->nbase;
1246 ntopvert = mesh->ntopvert;
1253 for_all_elements(e,
this)
1255 if (e->
cm !=
nullptr)
1264 if (this->meshHashGrid)
1265 delete this->meshHashGrid;
1274 for (std::map<int, MarkerArea*>::iterator p = marker_areas.begin(); p != marker_areas.end(); p++)
1276 marker_areas.clear();
1282 if (!this->meshHashGrid)
1287 if (this->
get_seq() != this->meshHashGrid->get_mesh_seq())
1289 delete this->meshHashGrid;
1294 return this->meshHashGrid->getElement(x, y);
1297 double Mesh::get_marker_area(
int marker)
1299 std::map<int, MarkerArea*>::iterator area = marker_areas.find(marker);
1300 bool recalculate =
false;
1301 if (area == marker_areas.end())
1307 if (area->second->get_mesh_seq() != this->
get_seq())
1309 delete area->second;
1310 marker_areas.erase(area);
1316 marker_areas.insert(std::pair<int, MarkerArea*>(marker,
new MarkerArea(
this, marker)));
1318 return marker_areas.find(marker)->second->get_area();
1325 this->boundary_markers_conversion = mesh->boundary_markers_conversion;
1326 this->element_markers_conversion = mesh->element_markers_conversion;
1329 for (
int i = 0; i <
nodes.get_size(); i++)
1332 if (node.
type == HERMES_TYPE_EDGE) {
1333 for (
int k = 0; k < 2; k++)
1334 node.
elem[k] =
nullptr;
1341 for_all_active_elements(e, mesh)
1346 if (e->is_triangle())
1349 enew = elements.add();
1369 enew = elements.add();
1390 for (
unsigned int j = 0; j < e->get_nvert(); j++)
1401 nbase = nactive = ninitial = mesh->nactive;
1406 void Mesh::convert_quads_to_triangles()
1410 elements.set_append_only(
true);
1411 for_all_active_elements(e,
this)
1412 refine_element_to_triangles_id(e->
id);
1413 elements.set_append_only(false);
1415 MeshSharedPtr mesh_tmp_for_convert(new
Mesh);
1418 for (
int i = 0; i < mesh_tmp_for_convert->ntopvert; i++)
1420 if (mesh_tmp_for_convert->nodes[i].type == 1)
1422 mesh_tmp_for_convert->nodes[i].y = 0.0;
1425 MeshReaderH2D loader_mesh_tmp_for_convert;
1426 char* mesh_file_tmp =
nullptr;
1427 mesh_file_tmp = tmpnam(
nullptr);
1428 loader_mesh_tmp_for_convert.save(mesh_file_tmp, mesh_tmp_for_convert);
1429 loader_mesh_tmp_for_convert.load(mesh_file_tmp, mesh_tmp_for_convert);
1430 remove(mesh_file_tmp);
1431 copy(mesh_tmp_for_convert);
1434 void Mesh::convert_to_base()
1438 elements.set_append_only(
true);
1439 for_all_active_elements(e,
this)
1440 convert_element_to_base_id(e->
id);
1441 elements.set_append_only(false);
1443 MeshSharedPtr mesh_tmp_for_convert(new Mesh);
1445 for (
int i = 0; i < mesh_tmp_for_convert->ntopvert; i++)
1447 if (mesh_tmp_for_convert->nodes[i].type == 1)
1449 mesh_tmp_for_convert->nodes[i].y = 0.0;
1452 MeshReaderH2D loader_mesh_tmp_for_convert;
1453 char* mesh_file_tmp =
nullptr;
1454 mesh_file_tmp = tmpnam(
nullptr);
1455 loader_mesh_tmp_for_convert.save(mesh_file_tmp, mesh_tmp_for_convert);
1456 loader_mesh_tmp_for_convert.load(mesh_file_tmp, mesh_tmp_for_convert);
1457 remove(mesh_file_tmp);
1458 copy(mesh_tmp_for_convert);
1461 void Mesh::refine_triangle_to_quads(Element* e, Element** sons_out)
1464 int bnd[3] = { e->en[0]->bnd, e->en[1]->bnd, e->en[2]->bnd };
1465 int mrk[3] = { e->en[0]->marker, e->en[1]->marker, e->en[2]->marker };
1473 mid->x = (x0->x + x1->x + x2->x) / 3;
1474 mid->y = (x0->y + x1->y + x2->y) / 3;
1477 bool e_inter =
true;
1478 for (
unsigned int n = 0; n < e->get_nvert(); n++)
1485 memset(cm, 0,
sizeof(cm));
1492 double2 pt[4] = { { 0.0, -1.0 }, { 0.0, 0.0 }, { -1.0, 0.0 }, { -0.33333333, -0.33333333 } };
1493 e->cm->get_mid_edge_points(e, pt, 4);
1494 x0->x = pt[0][0]; x0->y = pt[0][1];
1495 x1->x = pt[1][0]; x1->y = pt[1][1];
1496 x2->x = pt[2][0]; x2->y = pt[2][1];
1497 mid->x = pt[3][0]; mid->y = pt[3][1];
1502 double refinement_angle[3] = { 0.0, 0.0, 0.0 };
1503 if (e->is_curved() && (!e_inter))
1506 Element* e_temp = e;
1507 double multiplier = 1.0;
1508 while (!e_temp->cm->toplevel)
1510 e_temp = e_temp->parent;
1514 for (
unsigned int n = 0; n < e->get_nvert(); n++)
1516 if (e_temp->cm->curves[n] !=
nullptr && e_temp->cm->curves[n]->type == ArcType)
1517 refinement_angle[n] = ((Arc*)e_temp->cm->curves[n])->angle / multiplier;
1521 double angle2 = 0.0;
1524 if ((e->is_curved()) && (!e_inter))
1526 for (idx = 0; idx < 2; idx++)
1528 if (e->cm->curves[idx] !=
nullptr)
1530 cm[idx] =
new CurvMap;
1531 memset(cm[idx], 0,
sizeof(CurvMap));
1532 cm[idx + 1] =
new CurvMap;
1533 memset(cm[idx + 1], 0,
sizeof(CurvMap));
1538 if (e->cm->curves[idx] !=
nullptr)
1540 angle2 = refinement_angle[0] / 2;
1541 Node* node_temp = this->
get_vertex_node(e->vn[idx % 3]->id, e->vn[(idx + 1) % 3]->id);
1543 for (
int k = 0; k < 2; k++)
1550 p1 = e->vn[(idx) % 3]->
id;
1552 if (idx == 0) idx2 = 0;
1553 if (idx == 1) idx2 = 1;
1554 if (idx == 2)
continue;
1559 p2 = e->vn[(idx + 1) % 3]->
id;
1560 idx = (idx + 1) % 3;
1561 if (idx == 0)
continue;
1562 if (idx == 1) idx2 = 0;
1563 if (idx == 2) idx2 = 0;
1566 Arc* curve =
new Arc(angle2);
1568 int inner = 1, outer = 0;
1570 curve->pt[0][0] =
nodes[p1].x;
1571 curve->pt[0][1] =
nodes[p1].y;
1572 curve->pt[0][2] = 1.0;
1574 curve->pt[2][0] =
nodes[p2].x;
1575 curve->pt[2][1] =
nodes[p2].y;
1576 curve->pt[2][2] = 1.0;
1578 double a = (180.0 - angle2) / 180.0 * M_PI;
1581 double x = 1.0 / tan(a * 0.5);
1582 curve->pt[1][0] = 0.5*((curve->pt[2][0] + curve->pt[0][0]) + (curve->pt[2][1] - curve->pt[0][1]) * x);
1583 curve->pt[1][1] = 0.5*((curve->pt[2][1] + curve->pt[0][1]) - (curve->pt[2][0] - curve->pt[0][0]) * x);
1584 curve->pt[1][2] = cos((M_PI - a) * 0.5);
1586 cm[idx]->toplevel =
true;
1588 cm[idx]->curves[idx2] = curve;
1593 if (e->cm->curves[idx] !=
nullptr)
1595 angle2 = refinement_angle[1] / 2;
1596 Node* node_temp = this->
get_vertex_node(e->vn[idx % 3]->id, e->vn[(idx + 1) % 3]->id);
1597 for (
int k = 0; k < 2; k++)
1603 p1 = e->vn[(idx) % 3]->
id;
1605 if (idx == 0) idx2 = 0;
1606 if (idx == 1) idx2 = 1;
1607 if (idx == 2)
continue;
1612 p2 = e->vn[(idx + 1) % 3]->
id;
1613 idx = (idx + 1) % 3;
1614 if (idx == 0)
continue;
1615 if (idx == 1) idx2 = 0;
1616 if (idx == 2) idx2 = 0;
1619 Arc* curve =
new Arc(angle2);
1621 int inner = 1, outer = 0;
1623 curve->pt[0][0] =
nodes[p1].x;
1624 curve->pt[0][1] =
nodes[p1].y;
1625 curve->pt[0][2] = 1.0;
1627 curve->pt[inner + 1][0] =
nodes[p2].x;
1628 curve->pt[inner + 1][1] =
nodes[p2].y;
1629 curve->pt[inner + 1][2] = 1.0;
1631 double a = (180.0 - angle2) / 180.0 * M_PI;
1634 double x = 1.0 / tan(a * 0.5);
1635 curve->pt[1][0] = 0.5*((curve->pt[2][0] + curve->pt[0][0]) + (curve->pt[2][1] - curve->pt[0][1]) * x);
1636 curve->pt[1][1] = 0.5*((curve->pt[2][1] + curve->pt[0][1]) - (curve->pt[2][0] - curve->pt[0][0]) * x);
1637 curve->pt[1][2] = cos((M_PI - a) * 0.5);
1639 cm[idx]->toplevel =
true;
1641 cm[idx]->curves[idx2] = curve;
1648 sons[0] = this->create_quad(e->marker, e->vn[0], x0, mid, x2, cm[0]);
1649 sons[1] = this->create_quad(e->marker, x0, e->vn[1], x1, mid, cm[1]);
1650 sons[2] = this->create_quad(e->marker, x1, e->vn[2], x2, mid, cm[2]);
1653 for (
int i = 0; i < 3; i++)
1654 if (sons[i]->is_curved())
1655 sons[i]->cm->update_refmap_coeffs(sons[i]);
1659 if (
this !=
nullptr)
1662 e->unref_all_nodes(
this);
1667 sons[0]->en[0]->bnd = bnd[0]; sons[0]->en[0]->marker = mrk[0];
1668 sons[0]->en[3]->bnd = bnd[2]; sons[0]->en[3]->marker = mrk[2];
1669 sons[1]->en[0]->bnd = bnd[0]; sons[1]->en[0]->marker = mrk[0];
1670 sons[1]->en[1]->bnd = bnd[1]; sons[1]->en[1]->marker = mrk[1];
1671 sons[2]->en[0]->bnd = bnd[1]; sons[2]->en[0]->marker = mrk[1];
1672 sons[2]->en[1]->bnd = bnd[2]; sons[2]->en[1]->marker = mrk[2];
1675 for (
int i = 0; i < 3; i++)
1677 if (sons[i] !=
nullptr)
1678 sons[i]->parent = e;
1682 memcpy(e->sons, sons, 3 *
sizeof(Element*));
1685 if (sons_out !=
nullptr)
1687 for (
int i = 0; i < 3; i++) sons_out[i] = sons[i];
1691 void Mesh::refine_element_to_quads_id(
int id)
1694 if (!e->used)
throw Hermes::Exceptions::Exception(
"Invalid element id number.");
1695 if (!e->active)
throw Hermes::Exceptions::Exception(
"Attempt to refine element #%d which has been refined already.", e->id);
1697 if (e->is_triangle())
1698 refine_triangle_to_quads(e);
1700 refine_quad_to_quads(e);
1705 void Mesh::refine_quad_to_triangles(Element* e)
1708 int bnd[
H2D_MAX_NUMBER_EDGES] = { e->en[0]->bnd, e->en[1]->bnd, e->en[2]->bnd, e->en[3]->bnd };
1709 int mrk[
H2D_MAX_NUMBER_EDGES] = { e->en[0]->marker, e->en[1]->marker, e->en[2]->marker, e->en[3]->marker };
1714 e->unref_all_nodes(
this);
1719 double length_x_0_2 = (e->vn[0]->x - e->vn[2]->x)*(e->vn[0]->x - e->vn[2]->x);
1720 double length_x_1_3 = (e->vn[1]->x - e->vn[3]->x)*(e->vn[1]->x - e->vn[3]->x);
1722 double length_y_0_2 = (e->vn[0]->y - e->vn[2]->y)*(e->vn[0]->y - e->vn[2]->y);
1723 double length_y_1_3 = (e->vn[1]->y - e->vn[3]->y)*(e->vn[1]->y - e->vn[3]->y);
1725 if ((length_x_0_2 + length_y_0_2) > (length_x_1_3 + length_y_1_3))
1733 memset(cm, 0,
sizeof(cm));
1741 if ((e->cm->curves[0] !=
nullptr) || (e->cm->curves[1] !=
nullptr))
1743 cm[0] =
new CurvMap;
1744 memset(cm[0], 0,
sizeof(CurvMap));
1746 if ((e->cm->curves[2] !=
nullptr) || (e->cm->curves[3] !=
nullptr))
1748 cm[1] =
new CurvMap;
1749 memset(cm[1], 0,
sizeof(CurvMap));
1752 else if (bcheck ==
false)
1754 if ((e->cm->curves[1] !=
nullptr) || (e->cm->curves[2] !=
nullptr))
1756 cm[0] =
new CurvMap;
1757 memset(cm[0], 0,
sizeof(CurvMap));
1759 if ((e->cm->curves[3] !=
nullptr) || (e->cm->curves[0] !=
nullptr))
1761 cm[1] =
new CurvMap;
1762 memset(cm[1], 0,
sizeof(CurvMap));
1768 for (
unsigned int k = 0; k < 2; k++)
1770 for (idx = 0 + 2 * k; idx < 2 + 2 * k; idx++)
1772 if (e->cm->curves[(idx + i_case2) % 4] !=
nullptr)
1774 angle2 = ((Arc*)e->cm->curves[(idx + i_case2) % 4])->angle;
1778 p1 = e->vn[(idx + i_case2) % 4]->
id;
1780 p2 = e->vn[(idx + i_case2 + 1) % 4]->
id;
1782 Arc* curve =
new Arc(angle2);
1784 curve->pt[0][0] =
nodes[p1].x;
1785 curve->pt[0][1] =
nodes[p1].y;
1786 curve->pt[0][2] = 1.0;
1788 curve->pt[2][0] =
nodes[p2].x;
1789 curve->pt[2][1] =
nodes[p2].y;
1790 curve->pt[2][2] = 1.0;
1792 double a = (180.0 - angle2) / 180.0 * M_PI;
1795 double x = 1.0 / tan(a * 0.5);
1796 curve->pt[1][0] = 0.5*((curve->pt[2][0] + curve->pt[0][0]) + (curve->pt[2][1] - curve->pt[0][1]) * x);
1797 curve->pt[1][1] = 0.5*((curve->pt[2][1] + curve->pt[0][1]) - (curve->pt[2][0] - curve->pt[0][0]) * x);
1798 curve->pt[1][2] = cos((M_PI - a) * 0.5);
1800 cm[k]->toplevel =
true;
1802 cm[k]->curves[idx % 2] = curve;
1812 sons[0] = this->create_triangle(e->marker, e->vn[0], e->vn[1], e->vn[2], cm[0]);
1813 sons[1] = this->create_triangle(e->marker, e->vn[2], e->vn[3], e->vn[0], cm[1]);
1819 sons[0] = this->create_triangle(e->marker, e->vn[1], e->vn[2], e->vn[3], cm[0]);
1820 sons[1] = this->create_triangle(e->marker, e->vn[3], e->vn[0], e->vn[1], cm[1]);
1826 for (
int i = 0; i < 2; i++)
1828 if (sons[i]->is_curved())
1830 sons[i]->cm->update_refmap_coeffs(sons[i]);
1838 sons[0]->en[0]->bnd = bnd[0]; sons[0]->en[0]->marker = mrk[0];
1839 sons[0]->en[1]->bnd = bnd[1]; sons[0]->en[1]->marker = mrk[1];
1840 sons[0]->vn[1]->bnd = bnd[0];
1842 sons[1]->en[0]->bnd = bnd[2]; sons[1]->en[0]->marker = mrk[2];
1843 sons[1]->en[1]->bnd = bnd[3]; sons[1]->en[1]->marker = mrk[3];
1844 sons[1]->vn[2]->bnd = bnd[1];
1848 sons[0]->en[0]->bnd = bnd[1]; sons[0]->en[0]->marker = mrk[1];
1849 sons[0]->en[1]->bnd = bnd[2]; sons[0]->en[1]->marker = mrk[2];
1850 sons[0]->vn[1]->bnd = bnd[1];
1852 sons[1]->en[0]->bnd = bnd[3]; sons[1]->en[0]->marker = mrk[3];
1853 sons[1]->en[1]->bnd = bnd[0]; sons[1]->en[1]->marker = mrk[0];
1854 sons[1]->vn[2]->bnd = bnd[0];
1859 if (sons[i] !=
nullptr)
1860 sons[i]->parent = e;
1863 memcpy(e->sons, sons, H2D_MAX_ELEMENT_SONS *
sizeof(Element*));
1866 void Mesh::refine_element_to_triangles_id(
int id)
1869 if (!e->used)
throw Hermes::Exceptions::Exception(
"Invalid element id number.");
1870 if (!e->active)
throw Hermes::Exceptions::Exception(
"Attempt to refine element #%d which has been refined already.", e->id);
1872 if (e->is_triangle())
1875 refine_quad_to_triangles(e);
1880 void Mesh::convert_element_to_base_id(
int id)
1883 if (!e->used)
throw Hermes::Exceptions::Exception(
"Invalid element id number.");
1884 if (!e->active)
throw Hermes::Exceptions::Exception(
"Attempt to refine element #%d which has been refined already.", e->id);
1886 if (e->is_triangle())
1887 convert_triangles_to_base(e);
1890 convert_quads_to_base(e);
1895 Mesh::MarkersConversion::MarkersConversion() : min_marker_unused(1)
1899 Mesh::MarkersConversion::StringValid::StringValid()
1903 Mesh::MarkersConversion::StringValid::StringValid(
std::string marker,
bool valid) : marker(marker), valid(valid)
1907 Mesh::MarkersConversion::IntValid::IntValid()
1911 Mesh::MarkersConversion::IntValid::IntValid(
int marker,
bool valid) : marker(marker), valid(valid)
1915 Mesh::ElementMarkersConversion::ElementMarkersConversion()
1919 Mesh::MarkersConversion::MarkersConversionType Mesh::ElementMarkersConversion::get_type()
const
1921 return HERMES_ELEMENT_MARKERS_CONVERSION;
1924 Mesh::BoundaryMarkersConversion::BoundaryMarkersConversion()
1928 Mesh::MarkersConversion::MarkersConversionType Mesh::BoundaryMarkersConversion::get_type()
const
1930 return HERMES_BOUNDARY_MARKERS_CONVERSION;
1933 const Mesh::ElementMarkersConversion &Mesh::get_element_markers_conversion()
const
1935 return element_markers_conversion;
1938 const Mesh::BoundaryMarkersConversion &Mesh::get_boundary_markers_conversion()
const
1940 return boundary_markers_conversion;
1943 Mesh::ElementMarkersConversion &Mesh::get_element_markers_conversion()
1945 return element_markers_conversion;
1948 Mesh::BoundaryMarkersConversion &Mesh::get_boundary_markers_conversion()
1950 return boundary_markers_conversion;
1956 std::map<std::string, int>::iterator it = conversion_table_inverse.find(user_marker);
1957 if (it != conversion_table_inverse.end())
1959 conversion_table.insert(std::pair<int, std::string>(this->min_marker_unused, user_marker));
1960 conversion_table_inverse.insert(std::pair<std::string, int>(user_marker, this->min_marker_unused));
1961 return this->min_marker_unused++;
1964 int Mesh::MarkersConversion::size()
const
1966 return this->conversion_table.size();
1971 if (internal_marker == H2D_DG_INNER_EDGE_INT)
1974 std::map<int, std::string>::const_iterator marker = conversion_table.find(internal_marker);
1975 if (marker == conversion_table.end())
1983 if (user_marker == H2D_DG_INNER_EDGE)
1984 return IntValid(H2D_DG_INNER_EDGE_INT,
true);
1986 std::map<std::string, int>::const_iterator marker = conversion_table_inverse.find(user_marker);
1987 if (marker == conversion_table_inverse.end())
1990 return IntValid(marker->second,
true);
1993 Mesh::CurvedException::CurvedException(
int elementId) : elementId(elementId)
1995 this->message <<
"Element id " << elementId <<
" is curved, this is not supported in this method.";
1998 Mesh::CurvedException::CurvedException(
const CurvedException & e)
2000 this->message << e.message.str();
2001 elementId = e.elementId;
2004 int Mesh::CurvedException::getElementId()
const
2006 return this->elementId;
2009 void Mesh::convert_triangles_to_base(Element *e)
2012 int bnd[3] = { e->en[0]->bnd, e->en[1]->bnd, e->en[2]->bnd };
2013 int mrk[3] = { e->en[0]->marker, e->en[1]->marker, e->en[2]->marker };
2016 bool e_inter =
true;
2017 for (
unsigned int n = 0; n < e->get_nvert(); n++)
2024 double refinement_angle[3] = { 0.0, 0.0, 0.0 };
2025 if (e->is_curved() && (!e_inter))
2028 Element* e_temp = e;
2029 double multiplier = 1.0;
2030 while (!e_temp->cm->toplevel)
2032 e_temp = e_temp->parent;
2036 for (
unsigned int n = 0; n < e->get_nvert(); n++)
2038 if (e_temp->cm->curves[n] !=
nullptr && e_temp->cm->curves[n]->type == ArcType)
2039 refinement_angle[n] = ((Arc*)e_temp->cm->curves[n])->angle / multiplier;
2045 e->unref_all_nodes(
this);
2047 double angle2 = 0.0;
2050 memset(&cm, 0,
sizeof(cm));
2053 if ((e->is_curved()) && (!e_inter))
2056 memset(cm, 0,
sizeof(CurvMap));
2058 for (idx = 0; idx < 3; idx++)
2059 if ((e->cm->curves[idx] !=
nullptr) && (bnd[idx] == 1))
2061 angle2 = refinement_angle[idx];
2063 p1 = e->en[idx]->p1;
2064 p2 = e->en[idx]->p2;
2065 if (p1 > p2) std::swap(p1, p2);
2067 Arc* curve =
new Arc(angle2);
2069 curve->pt[0][0] =
nodes[p1].x;
2070 curve->pt[0][1] =
nodes[p1].y;
2071 curve->pt[0][2] = 1.0;
2073 curve->pt[2][0] =
nodes[p2].x;
2074 curve->pt[2][1] =
nodes[p2].y;
2075 curve->pt[2][2] = 1.0;
2077 double a = (180.0 - angle2) / 180.0 * M_PI;
2080 double x = 1.0 / tan(a * 0.5);
2081 curve->pt[1][0] = 0.5*((curve->pt[2][0] + curve->pt[0][0]) + (curve->pt[2][1] - curve->pt[0][1]) * x);
2082 curve->pt[1][1] = 0.5*((curve->pt[2][1] + curve->pt[0][1]) - (curve->pt[2][0] - curve->pt[0][0]) * x);
2083 curve->pt[1][2] = cos((M_PI - a) * 0.5);
2085 cm->toplevel =
true;
2087 cm->curves[idx] = curve;
2093 Node *v0 = &
nodes[e->vn[0]->id], *v1 = &
nodes[e->vn[1]->id], *v2 = &
nodes[e->vn[2]->id];
2094 enew = this->create_triangle(e->marker, v0, v1, v2, cm);
2096 if (enew->is_curved())
2098 enew->cm->update_refmap_coeffs(enew);
2103 enew->en[0]->bnd = bnd[0];
2104 enew->en[1]->bnd = bnd[1];
2105 enew->en[2]->bnd = bnd[2];
2106 enew->en[0]->marker = mrk[0];
2107 enew->en[1]->marker = mrk[1];
2108 enew->en[2]->marker = mrk[2];
2112 void Mesh::convert_quads_to_base(Element *e)
2115 int bnd[
H2D_MAX_NUMBER_EDGES] = { e->en[0]->bnd, e->en[1]->bnd, e->en[2]->bnd, e->en[3]->bnd };
2116 int mrk[
H2D_MAX_NUMBER_EDGES] = { e->en[0]->marker, e->en[1]->marker, e->en[2]->marker, e->en[3]->marker };
2119 bool e_inter =
true;
2120 for (
unsigned int n = 0; n < e->get_nvert(); n++)
2128 if (e->is_curved() && (!e_inter))
2131 Element* e_temp = e;
2132 double multiplier = 1.0;
2133 while (!e_temp->cm->toplevel)
2135 e_temp = e_temp->parent;
2139 for (
unsigned int n = 0; n < e->get_nvert(); n++)
2141 if (e_temp->cm->curves[n] !=
nullptr && e_temp->cm->curves[n]->type == ArcType && (bnd[n] == 1))
2142 refinement_angle[n] = ((Arc*)e_temp->cm->curves[n])->angle / multiplier;
2148 for (
unsigned int i = 0; i < e->get_nvert(); i++)
2149 refinement_angle[i] = refinement_angle[i] * 2;
2153 e->unref_all_nodes(
this);
2155 double angle2 = 0.0;
2158 memset(&cm, 0,
sizeof(cm));
2161 if ((e->is_curved()) && (!e_inter))
2163 bool create_new =
false;
2164 for (
unsigned int i = 0; i < e->get_nvert(); i++)
2166 if (fabs(refinement_angle[i] - 0.0) > 1e-4)
2176 memset(cm, 0,
sizeof(CurvMap));
2179 for (idx = 0; idx < 4; idx++)
2180 if (fabs(refinement_angle[idx] - 0.0) > 1e-4)
2182 angle2 = refinement_angle[idx];
2184 p1 = e->en[idx]->p1;
2185 p2 = e->en[idx]->p2;
2186 if (p1 > p2) std::swap(p1, p2);
2188 Arc* curve =
new Arc(angle2);
2190 curve->pt[0][0] =
nodes[p1].x;
2191 curve->pt[0][1] =
nodes[p1].y;
2192 curve->pt[0][2] = 1.0;
2194 curve->pt[2][0] =
nodes[p2].x;
2195 curve->pt[2][1] =
nodes[p2].y;
2196 curve->pt[2][2] = 1.0;
2198 double a = (180.0 - angle2) / 180.0 * M_PI;
2201 double x = 1.0 / tan(a * 0.5);
2202 curve->pt[1][0] = 0.5*((curve->pt[2][0] + curve->pt[0][0]) + (curve->pt[2][1] - curve->pt[0][1]) * x);
2203 curve->pt[1][1] = 0.5*((curve->pt[2][1] + curve->pt[0][1]) - (curve->pt[2][0] - curve->pt[0][0]) * x);
2204 curve->pt[1][2] = cos((M_PI - a) * 0.5);
2206 cm->toplevel =
true;
2208 cm->curves[idx] = curve;
2214 Node *v0 = &
nodes[e->vn[0]->id], *v1 = &
nodes[e->vn[1]->id], *v2 = &
nodes[e->vn[2]->id], *v3 = &
nodes[e->vn[3]->id];
2215 enew = this->create_quad(e->marker, v0, v1, v2, v3, cm);
2217 if (enew->is_curved())
2219 enew->cm->update_refmap_coeffs(enew);
2224 enew->en[0]->bnd = bnd[0];
2225 enew->en[1]->bnd = bnd[1];
2226 enew->en[2]->bnd = bnd[2];
2227 enew->en[3]->bnd = bnd[3];
2228 enew->en[0]->marker = mrk[0];
2229 enew->en[1]->marker = mrk[1];
2230 enew->en[2]->marker = mrk[2];
2231 enew->en[3]->marker = mrk[3];
2235 void Mesh::refine_quad_to_quads(Element* e,
int refinement)
2238 int bnd[
H2D_MAX_NUMBER_EDGES] = { e->en[0]->bnd, e->en[1]->bnd, e->en[2]->bnd, e->en[3]->bnd };
2239 int mrk[
H2D_MAX_NUMBER_EDGES] = { e->en[0]->marker, e->en[1]->marker, e->en[2]->marker, e->en[3]->marker };
2242 bool e_inter =
true;
2243 for (
unsigned int n = 0; n < e->get_nvert(); n++)
2251 if (e->is_curved() && (!e_inter))
2254 Element* e_temp = e;
2255 double multiplier = 1.0;
2256 while (!e_temp->cm->toplevel)
2258 e_temp = e_temp->parent;
2262 for (
unsigned int n = 0; n < e->get_nvert(); n++)
2264 if (e_temp->cm->curves[n] !=
nullptr && e_temp->cm->curves[n]->type == ArcType && (bnd[n] == 1))
2265 refinement_angle[n] = ((Arc*)e_temp->cm->curves[n])->angle / multiplier;
2272 e->unref_all_nodes(
this);
2274 double angle2 = 0.0;
2279 memset(cm, 0,
sizeof(cm));
2282 if (refinement == 0)
2294 double2 pt[5] = { { 0.0, -1.0 }, { 1.0, 0.0 }, { 0.0, 1.0 }, { -1.0, 0.0 }, { 0.0, 0.0 } };
2295 e->cm->get_mid_edge_points(e, pt, 5);
2296 x0->x = pt[0][0]; x0->y = pt[0][1];
2297 x1->x = pt[1][0]; x1->y = pt[1][1];
2298 x2->x = pt[2][0]; x2->y = pt[2][1];
2299 x3->x = pt[3][0]; x3->y = pt[3][1];
2300 mid->x = pt[4][0]; mid->y = pt[4][1];
2304 if ((e->is_curved()) && (!e_inter))
2307 for (
unsigned int i = 0; i < e->get_nvert(); i++)
2309 if (fabs(refinement_angle[i] - 0.0) > 1e-4)
2311 cm[i % 4] =
new CurvMap;
2312 memset(cm[i % 4], 0,
sizeof(CurvMap));
2313 cm[(i + 1) % 4] =
new CurvMap;
2314 memset(cm[(i + 1) % 4], 0,
sizeof(CurvMap));
2318 for (idx = 0; idx < 4; idx++)
2319 if (cm[idx] !=
nullptr)
2321 if ((fabs(refinement_angle[idx % 4] - 0.0) > 1e-4))
2323 angle2 = refinement_angle[idx % 4] / 2;
2324 Node* node_temp = this->
get_vertex_node(e->vn[idx % 4]->id, e->vn[(idx + 1) % 4]->id);
2327 p1 = e->vn[(idx) % 4]->
id;
2330 Arc* curve =
new Arc(angle2);
2332 curve->pt[0][0] =
nodes[p1].x;
2333 curve->pt[0][1] =
nodes[p1].y;
2334 curve->pt[0][2] = 1.0;
2336 curve->pt[2][0] =
nodes[p2].x;
2337 curve->pt[2][1] =
nodes[p2].y;
2338 curve->pt[2][2] = 1.0;
2340 double a = (180.0 - angle2) / 180.0 * M_PI;
2343 double x = 1.0 / tan(a * 0.5);
2344 curve->pt[1][0] = 0.5*((curve->pt[2][0] + curve->pt[0][0]) + (curve->pt[2][1] - curve->pt[0][1]) * x);
2345 curve->pt[1][1] = 0.5*((curve->pt[2][1] + curve->pt[0][1]) - (curve->pt[2][0] - curve->pt[0][0]) * x);
2346 curve->pt[1][2] = cos((M_PI - a) * 0.5);
2348 cm[idx]->toplevel =
true;
2350 cm[idx]->curves[idx % 4] = curve;
2353 if ((fabs(refinement_angle[(idx + 3) % 4] - 0.0) > 1e-4))
2355 angle2 = refinement_angle[(idx + 3) % 4] / 2;
2356 Node* node_temp = this->
get_vertex_node(e->vn[idx % 4]->id, e->vn[(idx + 1) % 4]->id);
2359 p1 = e->vn[(idx) % 4]->
id;
2362 Arc* curve =
new Arc(angle2);
2364 curve->pt[0][0] =
nodes[p1].x;
2365 curve->pt[0][1] =
nodes[p1].y;
2366 curve->pt[0][2] = 1.0;
2368 curve->pt[2][0] =
nodes[p2].x;
2369 curve->pt[2][1] =
nodes[p2].y;
2370 curve->pt[2][2] = 1.0;
2372 double a = (180.0 - angle2) / 180.0 * M_PI;
2375 double x = 1.0 / tan(a * 0.5);
2376 curve->pt[1][0] = 0.5*((curve->pt[2][0] + curve->pt[0][0]) + (curve->pt[2][1] - curve->pt[0][1]) * x);
2377 curve->pt[1][1] = 0.5*((curve->pt[2][1] + curve->pt[0][1]) - (curve->pt[2][0] - curve->pt[0][0]) * x);
2378 curve->pt[1][2] = cos((M_PI - a) * 0.5);
2380 cm[idx]->toplevel =
true;
2382 cm[idx]->curves[(idx + 3) % 4] = curve;
2388 sons[0] = this->create_quad(e->marker, e->vn[0], x0, mid, x3, cm[0]);
2389 sons[1] = this->create_quad(e->marker, x0, e->vn[1], x1, mid, cm[1]);
2390 sons[2] = this->create_quad(e->marker, mid, x1, e->vn[2], x2, cm[2]);
2391 sons[3] = this->create_quad(e->marker, x3, mid, x2, e->vn[3], cm[3]);
2397 for (i = 0; i < 4; i++)
2399 j = (i > 0) ? i - 1 : 3;
2400 sons[i]->en[j]->bnd = bnd[j]; sons[i]->en[j]->marker = mrk[j];
2401 sons[i]->en[i]->bnd = bnd[i]; sons[i]->en[i]->marker = mrk[i];
2402 sons[i]->vn[j]->bnd = bnd[j];
2408 for (i = 0; i < 4; i++)
2409 if (sons[i] !=
nullptr && sons[i]->cm !=
nullptr)
2410 sons[i]->cm->update_refmap_coeffs(sons[i]);
2413 for (
int i = 0; i < 4; i++)
2414 if (sons[i] !=
nullptr)
2415 sons[i]->parent = e;
2418 memcpy(e->sons, sons,
sizeof(sons));
2421 int Mesh::get_edge_degree(Node* v1, Node* v2)
2427 degree = 1 + std::max(get_edge_degree(v1, v3), get_edge_degree(v3, v2));
2432 void Mesh::regularize_triangle(Element* e)
2438 int eo[3] = { get_edge_degree(e->vn[0], e->vn[1]),
2439 get_edge_degree(e->vn[1], e->vn[2]),
2440 get_edge_degree(e->vn[2], e->vn[0]) };
2442 int sum = eo[0] + eo[1] + eo[2];
2450 int bnd[3] = { e->en[0]->bnd, e->en[1]->bnd, e->en[2]->bnd };
2451 int mrk[3] = { e->en[0]->marker, e->en[1]->marker, e->en[2]->marker };
2456 for (i = 0; i < 3; i++)
2457 if (eo[i] == 1) k = i;
2458 k1 = e->next_vert(k);
2459 k2 = e->prev_vert(k);
2464 e->unref_all_nodes(
this);
2466 t[0] = this->create_triangle(e->marker, e->vn[k], v4, e->vn[k2],
nullptr);
2467 t[1] = this->create_triangle(e->marker, v4, e->vn[k1], e->vn[k2],
nullptr);
2470 t[0]->en[2]->bnd = bnd[k2];
2471 t[1]->en[1]->bnd = bnd[k1];
2472 t[0]->en[2]->marker = mrk[k2];
2473 t[1]->en[1]->marker = mrk[k1];
2477 e->sons[2] =
nullptr;
2478 e->sons[3] =
nullptr;
2483 for (i = 0; i < 3; i++)
2484 if (eo[i] == 0) k = i;
2485 k1 = e->next_vert(k);
2486 k2 = e->prev_vert(k);
2492 e->unref_all_nodes(
this);
2494 t[0] = this->create_triangle(e->marker, e->vn[k], e->vn[k1], v4,
nullptr);
2495 t[1] = this->create_triangle(e->marker, v4, v5, e->vn[k],
nullptr);
2496 t[2] = this->create_triangle(e->marker, v4, e->vn[k2], v5,
nullptr);
2499 t[0]->en[0]->bnd = bnd[k];
2500 t[0]->en[0]->marker = mrk[k];
2505 e->sons[3] =
nullptr;
2512 for (i = 0; i < 4; i++)
2513 assign_parent(e, i);
2517 void Mesh::regularize_quad(Element* e)
2519 int i, k = 0, k1, k2, k3, n = 0, m = 0;
2523 int eo[4] = { get_edge_degree(e->vn[0], e->vn[1]),
2524 get_edge_degree(e->vn[1], e->vn[2]),
2525 get_edge_degree(e->vn[2], e->vn[3]),
2526 get_edge_degree(e->vn[3], e->vn[0]) };
2528 int sum = eo[0] + eo[1] + eo[2] + eo[3];
2536 int bnd[
H2D_MAX_NUMBER_EDGES] = { e->en[0]->bnd, e->en[1]->bnd, e->en[2]->bnd, e->en[3]->bnd };
2537 int mrk[
H2D_MAX_NUMBER_EDGES] = { e->en[0]->marker, e->en[1]->marker, e->en[2]->marker, e->en[3]->marker };
2541 for (i = 0; i < 4; i++)
2542 if (eo[i] == 1) k = i;
2543 k1 = e->next_vert(k);
2544 k2 = e->next_vert(k1);
2545 k3 = e->prev_vert(k);
2550 e->unref_all_nodes(
this);
2552 t[0] = this->create_triangle(e->marker, e->vn[k], v4, e->vn[k3],
nullptr);
2553 t[1] = this->create_triangle(e->marker, v4, e->vn[k1], e->vn[k2],
nullptr);
2554 t[2] = this->create_triangle(e->marker, v4, e->vn[k2], e->vn[k3],
nullptr);
2557 t[0]->en[2]->bnd = bnd[k3];
2558 t[1]->en[1]->bnd = bnd[k1];
2559 t[2]->en[1]->bnd = bnd[k2];
2560 t[0]->en[2]->marker = mrk[k3];
2561 t[1]->en[1]->marker = mrk[k1];
2562 t[2]->en[1]->marker = mrk[k2];
2567 e->sons[3] =
nullptr;
2576 for (i = 0; i < 4; i++)
2577 if (eo[i] == 1 && eo[e->next_vert(i)] == 1) k = i;
2578 k1 = e->next_vert(k);
2579 k2 = e->next_vert(k1);
2580 k3 = e->prev_vert(k);
2586 e->unref_all_nodes(
this);
2588 t[0] = this->create_triangle(e->marker, e->vn[k1], v5, v4,
nullptr);
2589 t[1] = this->create_triangle(e->marker, v5, e->vn[k2], e->vn[k3],
nullptr);
2590 t[2] = this->create_triangle(e->marker, v4, v5, e->vn[k3],
nullptr);
2591 t[3] = this->create_triangle(e->marker, v4, e->vn[k3], e->vn[k],
nullptr);
2593 t[1]->en[1]->bnd = bnd[k2];
2594 t[3]->en[1]->bnd = bnd[k3];
2595 t[1]->en[1]->marker = mrk[k2];
2596 t[3]->en[1]->marker = mrk[k3];
2606 if (eo[0] == 1 && eo[2] == 1)
2609 for (i = 0; i < 4; i++)
2610 assign_parent(e, i);
2613 else if (eo[1] == 1 && eo[3] == 1)
2616 for (i = 0; i < 4; i++)
2617 assign_parent(e, i);
2621 regularize_quad(e->sons[n]);
2622 regularize_quad(e->sons[m]);
2629 for (i = 0; i < 4; i++)
2630 assign_parent(e, i);
2634 void Mesh::flatten()
2637 for_all_edge_nodes(node,
this)
2639 if (node->elem[0] !=
nullptr) node->elem[0] = (Element*)(node->elem[0]->id + 1);
2640 if (node->elem[1] !=
nullptr) node->elem[1] = (Element*)(node->elem[1]->id + 1);
2643 int* idx =
new int[elements.get_size() + 1];
2644 Array<Element> new_elements;
2646 for_all_active_elements(e,
this)
2648 Element* ee = new_elements.add();
2653 parents[ee->id] = parents[e->id];
2656 elements.copy(new_elements);
2657 nbase = nactive = elements.get_num_items();
2659 for_all_edge_nodes(node,
this)
2661 if (node->elem[0] !=
nullptr) node->elem[0] = &(elements[idx[((int)(
long)node->elem[0]) - 1]]);
2662 if (node->elem[1] !=
nullptr) node->elem[1] = &(elements[idx[((
int)(
long)node->elem[1]) - 1]]);
2668 void Mesh::assign_parent(Element* e,
int i)
2670 if (e->sons[i] !=
nullptr)
2672 if (e->sons[i]->id >= parents_size)
2674 parents_size = 2 * parents_size;
2675 parents = (
int*)realloc(parents,
sizeof(
int)* parents_size);
2678 parents[e->sons[i]->id] = parents[e->id];
2696 parents = malloc_with_check<int>(parents_size);
2697 for_all_active_elements(e,
this)
2698 parents[e->
id] = e->
id;
2703 for_all_active_elements(e,
this)
2706 if (e->is_triangle())
2708 for (
unsigned int i = 0; i < e->get_nvert(); i++)
2711 if (get_edge_degree(e->
vn[i], e->
vn[j]) > n)
2713 iso = 0; ok =
false;
break;
2719 if (((get_edge_degree(e->
vn[0], e->
vn[1]) > n) || (get_edge_degree(e->
vn[2], e->
vn[3]) > n))
2720 && (get_edge_degree(e->
vn[1], e->
vn[2]) <= n) && (get_edge_degree(e->
vn[3], e->
vn[0]) <= n))
2722 iso = 2; ok =
false;
2724 else if ((get_edge_degree(e->
vn[0], e->
vn[1]) <= n) && (get_edge_degree(e->
vn[2], e->
vn[3]) <= n)
2725 && ((get_edge_degree(e->
vn[1], e->
vn[2]) > n) || (get_edge_degree(e->
vn[3], e->
vn[0]) > n)))
2727 iso = 1; ok =
false;
2731 for (
unsigned int i = 0; i < e->get_nvert(); i++)
2734 if (get_edge_degree(e->
vn[i], e->
vn[j]) > n)
2736 iso = 0; ok =
false;
break;
2745 for (
int i = 0; i < 4; i++)
2746 assign_parent(e, i);
2753 for_all_active_elements(e,
this)
2755 if (e->is_curved())
throw Hermes::Exceptions::Exception(
"Regularization of curved elements is not supported.");
2757 if (e->is_triangle())
2758 regularize_triangle(e);
2768 const std::string EggShell::eggShellInnerMarker =
"Eggshell-inner";
2778 throw Hermes::Exceptions::ValueException(
"levels", levels, 2);
2779 return MeshSharedPtr(
new Mesh());
2781 std::vector<std::string> markers;
2782 markers.push_back(marker);
2783 return get_egg_shell(mesh, markers, levels);
2790 throw Hermes::Exceptions::ValueException(
"levels", levels, 2);
2791 return MeshSharedPtr(
new Mesh);
2794 MeshSharedPtr target_mesh(
new Mesh);
2795 target_mesh->copy(mesh);
2797 int eggShell_marker_0 = target_mesh->get_boundary_markers_conversion().insert_marker(eggShell0Marker);
2798 int eggShell_marker_1 = target_mesh->get_boundary_markers_conversion().insert_marker(eggShell1Marker);
2799 int eggShell_marker_inner = target_mesh->get_boundary_markers_conversion().insert_marker(eggShellInnerMarker);
2800 int eggShell_marker_volume = target_mesh->get_element_markers_conversion().insert_marker(eggShellMarker);
2806 get_egg_shell_structures(target_mesh, markers, levels);
2811 EggShell::fix_hanging_nodes(target_mesh);
2857 for_all_active_elements(e, target_mesh)
2868 for_all_elements(e, target_mesh)
2870 if (e->
marker == eggShell_marker_volume)
2883 target_mesh->nactive = 0;
2884 for_all_active_elements(e, target_mesh)
2886 target_mesh->nactive++;
2889 for (
int edge = 0; edge < e->get_nvert(); edge++)
2892 if (e->
en[edge]->
marker == eggShell_marker_1 || e->
en[edge]->
bnd)
2896 bool neighbors_eggshell =
false;
2901 if (neighbors_eggshell)
2902 assert(neighbor_el->
marker == eggShell_marker_volume);
2903 else if (neighbor_el->
marker == eggShell_marker_volume)
2904 neighbors_eggshell =
true;
2906 if (neighbors_eggshell)
2908 e->
en[edge]->
marker = eggShell_marker_inner;
2911 else if (e->
en[edge]->
marker != eggShell_marker_1)
2913 e->
en[edge]->
marker = eggShell_marker_0;
2918 for_all_active_elements(e, target_mesh)
2920 for (
int edge = 0; edge < e->get_nvert(); edge++)
2922 if (e->
en[edge]->
marker == eggShell_marker_0 || e->
en[edge]->
marker == eggShell_marker_1)
2924 e->
en[edge]->
bnd =
true;
2925 e->
vn[edge]->
bnd =
true;
2926 e->
vn[(edge + 1) % e->get_nvert()]->
bnd =
true;
2928 else if (e->
en[edge]->
bnd)
2930 e->
en[edge]->
marker = eggShell_marker_0;
2936 fix_markers(target_mesh, mesh);
2941 void EggShell::get_egg_shell_structures(MeshSharedPtr target_mesh, std::vector<std::string> markers,
unsigned int levels)
2945 throw Exceptions::ValueException(
"levels", levels, 1);
2947 int eggShell_marker_1 = target_mesh->get_boundary_markers_conversion().get_internal_marker(eggShell1Marker).marker;
2948 int eggShell_marker_volumetric = target_mesh->get_element_markers_conversion().get_internal_marker(eggShellMarker).marker;
2950 std::vector<int> internal_markers;
2951 for (
int i = 0; i < markers.size(); i++)
2954 if (internalMarker.valid)
2955 internal_markers.push_back(internalMarker.marker);
2957 throw Exceptions::Exception(
"Marker %s not valid in target_mesh::get_egg_shell.", markers[i].c_str());
2961 int* neighbors_target = calloc_with_check<int>(target_mesh->get_max_element_id());
2962 int* neighbor_targets_local = calloc_with_check<int>(target_mesh->get_max_element_id());
2964 for_all_active_elements(e, target_mesh)
2966 bool target_marker =
false;
2967 for (
int i = 0; i < internal_markers.size(); i++)
2969 if (e->marker == internal_markers[i])
2971 target_marker =
true;
2976 neighbor_targets_local[e->id] = 1;
2980 for (
int level = 1; level <= levels; level++)
2982 memcpy(neighbors_target, neighbor_targets_local, target_mesh->get_max_element_id() *
sizeof(int));
2983 for_all_active_elements(e, target_mesh)
2985 if (neighbors_target[e->id] == level)
2987 NeighborSearch<double> ns(e, target_mesh);
2988 for (
int edge = 0; edge < e->get_nvert(); edge++)
2992 handle_vertex_on_target_mesh(e, edge, target_mesh, internal_markers, neighbor_targets_local);
2994 if (e->en[edge]->bnd)
2997 ns.set_active_edge(edge);
2998 for (
int neighbor = 0; neighbor < ns.get_num_neighbors(); neighbor++)
3000 ns.set_active_segment(neighbor);
3001 Element* neighbor_el = ns.get_neighb_el();
3005 if (neighbor_targets_local[neighbor_el->id] > 0 && level > 1)
3011 e->en[edge]->marker = eggShell_marker_1;
3012 neighbor_el->en[ns.get_neighbor_edge().local_num_of_edge]->marker = eggShell_marker_1;
3015 if (neighbor_targets_local[neighbor_el->id] > 0)
3019 neighbor_targets_local[ns.get_neighb_el()->id] = level + 1;
3020 ns.get_neighb_el()->marker = eggShell_marker_volumetric;
3026 free_with_check(neighbors_target);
3029 void EggShell::handle_vertex_on_target_mesh(Element* e,
int vertex, MeshSharedPtr target_mesh, std::vector<int> markers,
int* neighbor_targets_local)
3031 int eggShell_marker_volumetric = target_mesh->get_element_markers_conversion().get_internal_marker(eggShellMarker).marker;
3033 Node* v = e->vn[vertex];
3034 int max_id = target_mesh->get_max_node_id();
3035 for (
int i = 0; i < max_id; i++)
3037 n = &target_mesh->nodes[i];
3038 if ((n->p1 == v->id || n->p2 == v->id) && n->used && n->type)
3040 bool marker_check_failed[2] = {
false,
false };
3041 for (
unsigned short marker_i = 0; marker_i < markers.size(); marker_i++)
3044 if (n->elem[0]->marker == markers[marker_i])
3045 marker_check_failed[0] =
true;
3047 if (n->elem[1]->marker == markers[marker_i])
3048 marker_check_failed[1] =
true;
3050 for (
unsigned char i = 0; i < 2; i++)
3051 if (n->elem[i] && !marker_check_failed[i])
3055 n->elem[i]->marker = eggShell_marker_volumetric;
3061 void EggShell::fix_hanging_nodes(MeshSharedPtr target_mesh)
3063 int marker = target_mesh->get_element_markers_conversion().get_internal_marker(eggShellMarker).marker;
3064 for_all_active_elements_fast(target_mesh)
3066 if (e->marker != marker)
3069 for (
int edge = 0; edge < e->nvert; edge++)
3071 Node* en = e->en[edge];
3076 if (!(en->elem[0] && en->elem[1]))
3079 if (!target_mesh->peek_vertex_node(en->p1, en->p2))
3081 bool processed =
false;
3084 Node* parent_edge = target_mesh->peek_edge_node(e->parent->vn[edge]->id, e->parent->vn[(edge + 1) % e->nvert]->id);
3088 if (parent_edge->elem[0] || parent_edge->elem[1])
3090 mark_elements_down_used(marker, e->parent);
3106 void EggShell::mark_elements_down_used(
int eggShell_marker_volume, Element* element)
3108 if (element->active)
3109 element->marker = eggShell_marker_volume;
3114 if (element->sons[i])
3115 EggShell::mark_elements_down_used(eggShell_marker_volume, element->sons[i]);
3120 void EggShell::fix_markers(MeshSharedPtr target_mesh, MeshSharedPtr original_mesh)
3123 for_all_active_elements(e, target_mesh)
3124 e->marker = original_mesh->
get_element(e->
id)->marker;
::xsd::cxx::tree::id< char, ncname > id
C++ type corresponding to the ID XML Schema built-in type.
double x
vertex node coordinates
Node * peek_edge_node(int p1, int p2) const
Returns an edge node with parent id's p1 and p2 if it exists, nullptr otherwise.
void refine_quad(Element *e, int refinement, Element **sons_out=nullptr)
unsigned type
0 = vertex node; 1 = edge node
Element * element_on_physical_coordinates(double x, double y)
std::map< std::string, int > conversion_table_inverse
void refine_all_elements(int refinement=0, bool mark_as_initial=false)
Node * get_vertex_node(int p1, int p2)
unsigned char next_vert(unsigned char i) const
Helper functions to obtain the index of the next or previous vertex/edge.
unsigned used
array item usage flag
static bool egg_shell_verbose
void init(int size=H2D_DEFAULT_HASH_SIZE)
Node * get_edge_node(int p1, int p2)
Node * next_hash
next node in hash synonym list
bool rescale(double x_ref, double y_ref)
Rescales the mesh.
StringValid get_user_marker(int internal_marker) const
Stores one element of a mesh.
int get_num_edge_nodes() const
Returns the number of edge nodes.
int get_num_base_elements() const
Returns the number of base mesh elements.
Represents a finite element mesh. Typical usage: MeshSharedPtr mesh; Hermes::Hermes2D::MeshReaderH2DX...
void copy_converted(MeshSharedPtr mesh)
Copies the active elements of a converted mesh.
bool visited
true if the element has been visited during assembling
Element * elem[2]
elements sharing the edge node
void free()
Frees all data associated with the mesh.
void refine_towards_boundary(std::vector< std::string > markers, int depth=1, bool aniso=true, bool mark_as_initial=false)
Node * get_node(int id) const
Retrieves a node by its id number.
Element * get_element_fast(int id) const
For internal use.
void initial_single_check()
For internal use.
void refine_towards_vertex(int vertex_id, int depth=1, bool mark_as_initial=false)
CurvMap * cm
curved mapping, nullptr if not curvilinear
void unrefine_element_id(int id)
void get_bounding_box(double &bottom_left_x, double &bottom_left_y, double &top_right_x, double &top_right_y)
void set_ignore_errors(bool value)
Function that sets the variable ignore_errors. See the variable description.
NeighborEdgeInfo get_neighbor_edge() const
Returns the current active neighbor edge according to the current active segment. ...
std::map< int, std::string > conversion_table
Common definitions for Hermes2D.
Stores one node of a mesh.
static bool same_line(double p_1, double p_2, double q_1, double q_2, double r_1, double r_2)
Checking whether the points p, q, r lie on the same line.
Struct for return type of get_user_marker().
bool is_jacobian_const() const
IntValid get_internal_marker(std::string user_marker) const
Find an internal marker for this user_marker.
bool used
array item usage flag
int get_num_vertex_nodes() const
Returns the number of vertex nodes.
void copy(MeshSharedPtr mesh)
Creates a copy of another mesh.
unsigned char nvert
number of vertices (3 or 4)
virtual bool isOkay() const
State querying helpers.
unsigned get_seq() const
For internal use.
void ref_all_nodes()
Internal.
void unref_all_nodes(HashTable *ht)
Internal.
static MeshSharedPtr get_egg_shell(MeshSharedPtr mesh, std::string marker, unsigned int levels)
ReferenceMeshCreator(MeshSharedPtr coarse_mesh, int refinement=0)
int insert_marker(std::string user_marker)
int get_max_element_id() const
Returns the maximum node id number plus one.
Element * get_neighb_el() const
Returns the current neighbor element according to the current active segment.
#define H2D_MAX_NUMBER_EDGES
A maximum number of edges of an element.
void free()
Frees all memory used by the instance.
double * get_jacobian(int order)
Node * peek_vertex_node(int p1, int p2) const
Returns a vertex node with parent id's p1 and p2 if it exists, nullptr otherwise. ...
Node * en[H2D_MAX_NUMBER_EDGES]
edge node pointers
unsigned short iro_cache
Increase in integration order, see RefMap::calc_inv_ref_order()
int get_num_nodes() const
Returns the total number of nodes stored.
void refine_by_criterion(int(*criterion)(Element *e), int depth=1, bool mark_as_initial=false)
void refine_in_area(std::string marker, int depth=1, int refinement=0, bool mark_as_initial=false)
Refines all element sharing the marker passed.
static const std::string eggShell0Marker
The mesh returned from get_egg_shell has this marker on the "0" boundary.
void unrefine_all_elements(bool keep_initial_refinements=true)
Array< Node > nodes
Array storing all nodes.
std::vector< std::pair< unsigned int, int > > refinements
Element * get_element(int id) const
Retrieves an element by its id number.
int get_num_elements() const
Returns the total number of elements stored.
Struct for return type of get_internal_marker().
unsigned bnd
1 = boundary node; 0 = inner node
void create(int nv, double2 *verts, int nt, int3 *tris, std::string *tri_markers, int nq, int4 *quads, std::string *quad_markers, int nm, int2 *mark, std::string *boundary_markers)
Creates a mesh from given vertex, triangle, quad, and marker arrays.
int get_num_neighbors() const
static const std::string eggShell1Marker
The mesh returned from get_egg_shell has this marker on the "1" boundary.
static double vector_length(double a_1, double a_2)
Computing vector length.
int get_num_used_base_elements() const
Returns the number of used base mesh elements.
::xsd::cxx::tree::string< char, simple_type > string
C++ type corresponding to the string XML Schema built-in type.
static const std::string eggShellMarker
Internal marker for eggshell elements.
Represents the reference mapping.
unsigned ref
the number of elements using the node
static bool is_convex(double a_1, double a_2, double b_1, double b_2)
Checking whether the angle of vectors 'a' and 'b' is between zero and Pi.
void update_refmap_coeffs(Element *e)
#define H2D_MAX_ELEMENT_SONS
Macros.
double2x2 * get_inv_ref_map(int order)
Element * sons[H2D_MAX_ELEMENT_SONS]
son elements (up to four)
void copy(const HashTable *ht)
Copies another hash table contents.
This class characterizes a neighborhood of a given edge in terms of adjacent elements and provides me...
int get_num_active_elements() const
Returns the current number of active elements in the mesh.
void copy_base(MeshSharedPtr mesh)
Copies the coarsest elements of another mesh.
bool active
0 = active, no sons; 1 = inactive (refined), has sons
void refine_in_areas(std::vector< std::string > markers, int depth=1, int refinement=0, bool mark_as_initial=false)
Refines all element sharing the markers passed.
void set_seq(unsigned seq)
For internal use.
virtual MeshSharedPtr create_ref_mesh()
Element * parent
pointer to the parent element for the current son
static Node * get_base_edge_node(Element *base, int edge)
For internal use.
void init(int size=H2D_DEFAULT_HASH_SIZE)
int get_max_node_id() const
Returns the maximum node id number plus one.
virtual void set_active_element(Element *e)
Node * vn[H2D_MAX_NUMBER_VERTICES]
vertex node pointers
void set_active_edge(int edge)
static int get_edge_sons(Element *e, int edge, int &son1, int &son2)
For internal use.
void refine_element_id(int id, int refinement=0)