26 #ifndef OOMPH_TRIANGLE_MESH_TEMPLATE_CC
27 #define OOMPH_TRIANGLE_MESH_TEMPLATE_CC
32 #include "../generic/map_matrix.h"
33 #include "../generic/multi_domain.h"
34 #include "../generic/projection.h"
35 #include "../generic/face_element_as_geometric_object.h"
43 template<
class ELEMENT>
45 const bool& use_attributes)
48 MeshChecker::assert_geometric_element<TElementGeometricBase, ELEMENT>(2);
51 unsigned nelem = Tmp_mesh_pt->nelement();
52 Element_pt.resize(nelem);
55 unsigned nnode_scaffold = Tmp_mesh_pt->nnode();
59 std::map<Node*, unsigned> old_global_number;
62 for (
unsigned inod = 0; inod < nnode_scaffold; inod++)
64 Node* old_node_pt = Tmp_mesh_pt->node_pt(inod);
65 old_global_number[old_node_pt] = inod;
69 Oomph_vertex_nodes_id.resize(nnode_scaffold);
72 Node_pt.resize(nnode_scaffold, 0);
75 unsigned nbound = Tmp_mesh_pt->nboundary();
78 set_nboundary(nbound);
79 Boundary_element_pt.resize(nbound);
80 Face_index_at_boundary.resize(nbound);
86 Boundary_region_element_pt.resize(nbound);
87 Face_index_region_at_boundary.resize(nbound);
91 for (
unsigned e = 0; e < nelem; e++)
93 Element_pt[e] =
new ELEMENT;
97 unsigned nnod_el = Tmp_mesh_pt->finite_element_pt(0)->nnode();
102 std::map<Node*, unsigned> global_number;
103 unsigned global_count = 0;
106 std::map<double, Vector<FiniteElement*>> element_attribute_map;
113 element_attribute_map[0].resize(0);
117 for (
unsigned e = 0; e < nelem; e++)
120 for (
unsigned j = 0; j < nnod_el; j++)
123 Node* scaffold_node_pt = Tmp_mesh_pt->finite_element_pt(e)->node_pt(j);
127 unsigned j_global = global_number[scaffold_node_pt];
133 Oomph_vertex_nodes_id[global_count] =
134 old_global_number[scaffold_node_pt];
138 std::set<unsigned>* boundaries_pt;
139 scaffold_node_pt->get_boundaries_pt(boundaries_pt);
142 Node* new_node_pt = 0;
145 if (boundaries_pt != 0)
149 finite_element_pt(e)->construct_boundary_node(j, time_stepper_pt);
152 for (std::set<unsigned>::iterator it = boundaries_pt->begin();
153 it != boundaries_pt->end();
156 add_boundary_node(*it, new_node_pt);
164 finite_element_pt(e)->construct_node(j, time_stepper_pt);
171 global_number[scaffold_node_pt] = global_count;
177 Node_pt[global_count - 1] = new_node_pt;
180 for (
unsigned i = 0; i < finite_element_pt(e)->dim(); i++)
182 new_node_pt->x(i) = scaffold_node_pt->x(i);
188 finite_element_pt(e)->node_pt(j) = Node_pt[j_global - 1];
195 element_attribute_map[Tmp_mesh_pt->element_attribute(e)].push_back(
196 finite_element_pt(e));
204 unsigned n_attribute = element_attribute_map.size();
207 this->Region_attribute.resize(n_attribute);
211 for (std::map<
double, Vector<FiniteElement*>>::iterator it =
212 element_attribute_map.begin();
213 it != element_attribute_map.end();
216 this->Region_attribute[count] = it->first;
217 Region_element_pt[
static_cast<unsigned>(Region_attribute[count])] =
227 unsigned boundary_id = 0;
231 unsigned n_node_1d = finite_element_pt(0)->nnode_1d();
232 unsigned dim = finite_element_pt(0)->dim();
235 Vector<double> s(dim);
238 unsigned n_node = finite_element_pt(0)->nnode();
241 unsigned n_global_edge = Tmp_mesh_pt->nglobal_edge();
242 Vector<Vector<Node*>> nodes_on_global_edge(n_global_edge);
245 for (
unsigned e = 0; e < nelem; e++)
248 FiniteElement*
const elem_pt = finite_element_pt(e);
249 FiniteElement*
const tmp_elem_pt = Tmp_mesh_pt->finite_element_pt(e);
252 unsigned n_edge_node = 3 * (n_node_1d - 1);
256 for (
unsigned n = n_edge_node; n < n_node; ++n)
259 Node* new_node_pt = elem_pt->construct_node(n, time_stepper_pt);
262 elem_pt->local_coordinate_of_node(n, s);
266 for (
unsigned i = 0; i < dim; i++)
268 new_node_pt->x(i) = tmp_elem_pt->interpolated_x(s, i);
272 Node_pt.push_back(new_node_pt);
280 for (
unsigned j = 0; j < 3; j++)
283 boundary_id = Tmp_mesh_pt->edge_boundary(e, j);
286 unsigned edge_index = Tmp_mesh_pt->edge_index(e, j);
289 if (nodes_on_global_edge[edge_index].size() == 0)
292 for (
unsigned j2 = 0; j2 < n_node_1d - 2; ++j2)
295 Node* new_node_pt = 0;
301 elem_pt->construct_boundary_node(n, time_stepper_pt);
303 this->add_boundary_node(boundary_id - 1, new_node_pt);
308 new_node_pt = elem_pt->construct_node(n, time_stepper_pt);
312 elem_pt->local_coordinate_of_node(n, s);
316 for (
unsigned i = 0; i < dim; i++)
318 new_node_pt->x(i) = tmp_elem_pt->interpolated_x(s, i);
322 Node_pt.push_back(new_node_pt);
325 nodes_on_global_edge[edge_index].push_back(new_node_pt);
337 for (
unsigned j2 = 0; j2 < n_node_1d - 2; ++j2)
341 elem_pt->node_pt(n) =
342 nodes_on_global_edge[edge_index][n_node_1d - 3 - j2];
351 Boundary_element_pt[boundary_id - 1].push_back(elem_pt);
354 Face_index_at_boundary[boundary_id - 1].push_back((j + 2) % 3);
359 unsigned tmp_region =
360 static_cast<unsigned>(Tmp_mesh_pt->element_attribute(e));
362 Boundary_region_element_pt[boundary_id - 1][tmp_region].push_back(
366 Face_index_region_at_boundary[boundary_id - 1][tmp_region]
367 .push_back((j + 2) % 3);
376 Lookup_for_elements_next_boundary_is_setup =
true;
386 template<
class ELEMENT>
396 Vector<FiniteElement*> face_el_pt;
403 unsigned n_repeated_ele = 0;
405 const unsigned n_regions = this->nregion();
409 std::map<FiniteElement*, FiniteElement*> face_to_bulk_element_pt;
412 Vector<std::pair<Node*, Node*>> done_nodes_pt;
418 for (
unsigned rr = 0; rr < n_regions; rr++)
420 const unsigned region_id =
421 static_cast<unsigned>(this->Region_attribute[rr]);
424 const unsigned nel_in_region =
425 this->nboundary_element_in_region(b, region_id);
427 unsigned nel_repetead_in_region = 0;
431 if (nel_in_region > 0)
435 bool repeated =
false;
438 for (
unsigned e = 0; e < nel_in_region; e++)
441 FiniteElement* bulk_elem_pt =
442 this->boundary_element_in_region_pt(b, region_id, e);
446 if (this->is_mesh_distributed() && bulk_elem_pt->is_halo())
457 this->face_index_at_boundary_in_region(b, region_id, e);
462 FiniteElement* tmp_ele_pt =
463 new DummyFaceElement<ELEMENT>(bulk_elem_pt, face_index);
465 const unsigned n_nodes = tmp_ele_pt->nnode();
467 std::pair<Node*, Node*> tmp_pair = std::make_pair(
468 tmp_ele_pt->node_pt(0), tmp_ele_pt->node_pt(n_nodes - 1));
470 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
471 tmp_ele_pt->node_pt(n_nodes - 1), tmp_ele_pt->node_pt(0));
474 const unsigned n_done_nodes = done_nodes_pt.size();
475 for (
unsigned l = 0; l < n_done_nodes; l++)
477 if (tmp_pair == done_nodes_pt[l] ||
478 tmp_pair_inverse == done_nodes_pt[l])
480 nel_repetead_in_region++;
490 done_nodes_pt.push_back(tmp_pair);
492 face_el_pt.push_back(tmp_ele_pt);
494 face_to_bulk_element_pt[tmp_ele_pt] = bulk_elem_pt;
508 nele += nel_in_region;
510 n_repeated_ele += nel_repetead_in_region;
519 nele = this->nboundary_element(b);
526 bool repeated =
false;
529 for (
unsigned e = 0; e < nele; e++)
532 FiniteElement* bulk_elem_pt = this->boundary_element_pt(b, e);
536 if (this->is_mesh_distributed() && bulk_elem_pt->is_halo())
546 int face_index = this->face_index_at_boundary(b, e);
551 FiniteElement* tmp_ele_pt =
552 new DummyFaceElement<ELEMENT>(bulk_elem_pt, face_index);
554 const unsigned n_nodes = tmp_ele_pt->nnode();
556 std::pair<Node*, Node*> tmp_pair = std::make_pair(
557 tmp_ele_pt->node_pt(0), tmp_ele_pt->node_pt(n_nodes - 1));
559 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
560 tmp_ele_pt->node_pt(n_nodes - 1), tmp_ele_pt->node_pt(0));
563 const unsigned n_done_nodes = done_nodes_pt.size();
564 for (
unsigned l = 0; l < n_done_nodes; l++)
566 if (tmp_pair == done_nodes_pt[l] ||
567 tmp_pair_inverse == done_nodes_pt[l])
581 done_nodes_pt.push_back(tmp_pair);
583 face_el_pt.push_back(tmp_ele_pt);
585 face_to_bulk_element_pt[tmp_ele_pt] = bulk_elem_pt;
603 nele -= n_repeated_ele;
606 if (nele != face_el_pt.size())
608 std::ostringstream error_message;
610 <<
"The independent counting of face elements (" << nele <<
") for "
611 <<
"boundary (" << b <<
") is different\n"
612 <<
"from the real number of face elements in the container ("
613 << face_el_pt.size() <<
")\n";
614 throw OomphLibError(error_message.str(),
615 "TriangleMesh::identify_boundary_segments_and_assign_"
616 "initial_zeta_values()",
617 OOMPH_EXCEPTION_LOCATION);
630 std::vector<bool> is_halo_face_element(nele,
false);
633 unsigned nnon_halo_face_elements = 0;
636 for (
unsigned ie = 0; ie < nele; ie++)
639 FiniteElement* face_ele_pt = face_el_pt[ie];
641 FiniteElement* tmp_bulk_ele_pt = face_to_bulk_element_pt[face_ele_pt];
643 if (!tmp_bulk_ele_pt->is_halo())
645 is_halo_face_element[ie] =
false;
646 nnon_halo_face_elements++;
651 is_halo_face_element[ie] =
true;
657 const unsigned nhalo_face_element = nele - nnon_halo_face_elements;
658 if (nhalo_face_element > 0)
660 std::ostringstream error_message;
662 <<
"There should not be halo face elements since they were not "
663 <<
"considered when computing the face elements\n\n"
664 <<
"The number of found halo face elements is: " << nhalo_face_element
666 throw OomphLibError(error_message.str(),
667 "TriangleMesh::identify_boundary_segments_and_assign_"
668 "initial_zeta_values()",
669 OOMPH_EXCEPTION_LOCATION);
675 Vector<std::list<FiniteElement*>> segment_sorted_ele_pt;
679 unsigned nsorted_face_elements = 0;
683 std::map<FiniteElement*, bool> done_el;
687 std::map<FiniteElement*, bool> is_inverted;
690 while (nsorted_face_elements < nnon_halo_face_elements)
694 std::list<FiniteElement*> sorted_el_pt;
695 sorted_el_pt.clear();
699 bool found_initial_face_element =
false;
702 FiniteElement* ele_face_pt = 0;
705 for (iface = 0; iface < nele; iface++)
707 if (!is_halo_face_element[iface])
709 ele_face_pt = face_el_pt[iface];
711 if (!done_el[ele_face_pt])
714 found_initial_face_element =
true;
716 nsorted_face_elements++;
718 sorted_el_pt.push_back(ele_face_pt);
720 done_el[ele_face_pt] =
true;
727 if (!found_initial_face_element)
729 std::ostringstream error_message;
731 <<
"Could not find an initial face element for the current segment\n";
732 throw OomphLibError(error_message.str(),
733 "TriangleMesh::identify_boundary_segments_and_"
734 "assign_initial_zeta_values()",
735 OOMPH_EXCEPTION_LOCATION);
740 const unsigned nnod = ele_face_pt->nnode();
744 Node* left_node_pt = ele_face_pt->node_pt(0);
745 Node* right_node_pt = ele_face_pt->node_pt(nnod - 1);
749 bool face_element_added =
false;
758 for (
unsigned iiface = iface; iiface < nele; iiface++)
761 face_element_added =
false;
764 ele_face_pt = face_el_pt[iiface];
768 if (!(done_el[ele_face_pt] || is_halo_face_element[iiface]))
771 Node* local_left_node_pt = ele_face_pt->node_pt(0);
772 Node* local_right_node_pt = ele_face_pt->node_pt(nnod - 1);
774 if (left_node_pt == local_right_node_pt)
776 left_node_pt = local_left_node_pt;
777 sorted_el_pt.push_front(ele_face_pt);
778 is_inverted[ele_face_pt] =
false;
779 face_element_added =
true;
782 else if (left_node_pt == local_left_node_pt)
784 left_node_pt = local_right_node_pt;
785 sorted_el_pt.push_front(ele_face_pt);
786 is_inverted[ele_face_pt] =
true;
787 face_element_added =
true;
790 else if (right_node_pt == local_left_node_pt)
792 right_node_pt = local_right_node_pt;
793 sorted_el_pt.push_back(ele_face_pt);
794 is_inverted[ele_face_pt] =
false;
795 face_element_added =
true;
798 else if (right_node_pt == local_right_node_pt)
800 right_node_pt = local_left_node_pt;
801 sorted_el_pt.push_back(ele_face_pt);
802 is_inverted[ele_face_pt] =
true;
803 face_element_added =
true;
806 if (face_element_added)
808 done_el[ele_face_pt] =
true;
809 nsorted_face_elements++;
815 }
while (face_element_added &&
816 (nsorted_face_elements < nnon_halo_face_elements));
819 segment_sorted_ele_pt.push_back(sorted_el_pt);
824 const unsigned nsegments = segment_sorted_ele_pt.size();
840 Vector<std::set<Node*>> segment_all_nodes_pt;
843 Vector<double> segment_arclength(nsegments);
846 Vector<unsigned> nvertices_per_segment(nsegments);
849 Vector<double> initial_zeta_segment(nsegments);
852 Vector<double> final_zeta_segment(nsegments);
855 if (nnon_halo_face_elements > 0 && nsegments == 0)
857 std::ostringstream error_message;
859 <<
"The number of segments is zero, but the number of nonhalo\n"
860 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
861 throw OomphLibError(error_message.str(),
862 "TriangleMesh::identify_boundary_segments_and_assign_"
863 "initial_zeta_values()",
864 OOMPH_EXCEPTION_LOCATION);
870 for (
unsigned is = 0; is < nsegments; is++)
873 if (segment_sorted_ele_pt[is].size() == 0)
875 std::ostringstream error_message;
876 error_message <<
"The (" << is <<
")-th segment has no elements\n";
877 throw OomphLibError(error_message.str(),
878 "TriangleMesh::identify_boundary_segments_and_"
879 "assign_initial_zeta_values()",
880 OOMPH_EXCEPTION_LOCATION);
885 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
888 const unsigned nnod = first_ele_pt->nnode();
891 Node* first_node_pt = first_ele_pt->node_pt(0);
892 if (is_inverted[first_ele_pt])
894 first_node_pt = first_ele_pt->node_pt(nnod - 1);
898 FiniteElement* last_ele_pt = segment_sorted_ele_pt[is].back();
901 Node* last_node_pt = last_ele_pt->node_pt(nnod - 1);
902 if (is_inverted[last_ele_pt])
904 last_node_pt = last_ele_pt->node_pt(0);
908 double x_left = first_node_pt->x(0);
909 double y_left = first_node_pt->x(1);
913 Vector<double> zeta(1, 0.0);
918 if (this->boundary_geom_object_pt(b) != 0)
920 first_node_pt->get_coordinates_on_boundary(b, zeta);
921 initial_zeta_segment[is] = zeta[0];
922 last_node_pt->get_coordinates_on_boundary(b, zeta);
923 final_zeta_segment[is] = zeta[0];
927 std::set<Node*> local_nodes_pt;
928 local_nodes_pt.insert(first_node_pt);
931 for (std::list<FiniteElement*>::iterator it =
932 segment_sorted_ele_pt[is].begin();
933 it != segment_sorted_ele_pt[is].end();
937 FiniteElement* el_pt = *it;
942 if (is_inverted[el_pt])
949 for (
unsigned j = 1; j < nnod; j++)
951 Node* nod_pt = el_pt->node_pt(k_nod);
955 double x_right = nod_pt->x(0);
956 double y_right = nod_pt->x(1);
959 zeta[0] += sqrt((x_right - x_left) * (x_right - x_left) +
960 (y_right - y_left) * (y_right - y_left));
977 local_nodes_pt.insert(nod_pt);
983 segment_arclength[is] = zeta[0];
986 nvertices_per_segment[is] = local_nodes_pt.size();
989 segment_all_nodes_pt.push_back(local_nodes_pt);
995 if (segment_all_nodes_pt.size() != nsegments)
997 std::ostringstream error_message;
998 error_message <<
"The number of segments (" << nsegments
999 <<
") and the number of "
1000 <<
"sets of nodes (" << segment_all_nodes_pt.size()
1001 <<
") representing\n"
1002 <<
"the\nsegments is different!!!\n\n";
1003 throw OomphLibError(
1004 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
1011 Vector<double> initial_segment_arclength(nsegments, 0.0);
1015 Vector<unsigned> current_segment_to_original_segment_index(nsegments);
1019 Vector<unsigned> segment_inverted(nsegments);
1032 const unsigned nsegments_initial_coordinates =
1033 original_mesh_pt->boundary_segment_initial_coordinate(b).size();
1035 const unsigned nsegments_final_coordinates =
1036 original_mesh_pt->boundary_segment_final_coordinate(b).size();
1038 if (nsegments_initial_coordinates != nsegments_final_coordinates)
1040 std::stringstream error_message;
1042 <<
"The number of segments that present initial coordinates "
1043 << nsegments_initial_coordinates <<
" is different from "
1044 <<
"the\nnumber of segments that present final coordinates "
1045 << nsegments_final_coordinates <<
"\n\n";
1046 throw OomphLibError(error_message.str(),
1047 OOMPH_CURRENT_FUNCTION,
1048 OOMPH_EXCEPTION_LOCATION);
1053 if (nsegments_initial_coordinates != nsegments)
1055 std::stringstream error_message;
1056 error_message <<
"Working with boundary (" << b
1057 <<
").\n The number of initial and "
1058 <<
"final coordinates (" << nsegments_initial_coordinates
1059 <<
") is different from\n"
1060 <<
"the number of found segments (" << nsegments
1062 throw OomphLibError(error_message.str(),
1063 OOMPH_CURRENT_FUNCTION,
1064 OOMPH_EXCEPTION_LOCATION);
1070 Vector<Vector<double>> original_mesh_segment_initial_coordinate(
1072 Vector<Vector<double>> original_mesh_segment_final_coordinate(nsegments);
1074 Vector<double> original_mesh_segment_initial_zeta(nsegments);
1075 Vector<double> original_mesh_segment_final_zeta(nsegments);
1077 Vector<double> original_mesh_segment_initial_arclength(nsegments);
1078 Vector<double> original_mesh_segment_final_arclength(nsegments);
1080 for (
unsigned is = 0; is < nsegments; is++)
1082 original_mesh_segment_initial_coordinate[is].resize(2);
1083 original_mesh_segment_final_coordinate[is].resize(2);
1084 for (
unsigned k = 0; k < 2; k++)
1086 original_mesh_segment_initial_coordinate[is][k] =
1087 original_mesh_pt->boundary_segment_initial_coordinate(b)[is][k];
1088 original_mesh_segment_final_coordinate[is][k] =
1089 original_mesh_pt->boundary_segment_final_coordinate(b)[is][k];
1092 if (this->boundary_geom_object_pt(b) != 0)
1094 original_mesh_segment_initial_zeta[is] =
1095 original_mesh_pt->boundary_segment_initial_zeta(b)[is];
1096 original_mesh_segment_final_zeta[is] =
1097 original_mesh_pt->boundary_segment_final_zeta(b)[is];
1101 original_mesh_segment_initial_arclength[is] =
1102 original_mesh_pt->boundary_segment_initial_arclength(b)[is];
1103 original_mesh_segment_final_arclength[is] =
1104 original_mesh_pt->boundary_segment_final_arclength(b)[is];
1109 Boundary_segment_inverted[b].clear();
1110 Boundary_segment_initial_coordinate[b].clear();
1111 Boundary_segment_final_coordinate[b].clear();
1113 Boundary_segment_initial_zeta[b].clear();
1114 Boundary_segment_final_zeta[b].clear();
1116 Boundary_segment_initial_arclength[b].clear();
1117 Boundary_segment_final_arclength[b].clear();
1123 std::map<unsigned, bool> segment_done;
1124 for (
unsigned is = 0; is < nsegments; is++)
1128 bool found_original_segment =
false;
1132 Vector<double> current_seg_initial_coord(2);
1133 Vector<double> current_seg_final_coord(2);
1136 FiniteElement* current_seg_initial_ele_pt =
1137 segment_sorted_ele_pt[is].front();
1140 const unsigned nnod = current_seg_initial_ele_pt->nnode();
1143 Node* current_seg_first_node_pt =
1144 current_seg_initial_ele_pt->node_pt(0);
1145 if (is_inverted[current_seg_initial_ele_pt])
1147 current_seg_first_node_pt =
1148 current_seg_initial_ele_pt->node_pt(nnod - 1);
1152 FiniteElement* current_seg_last_ele_pt =
1153 segment_sorted_ele_pt[is].back();
1156 Node* current_seg_last_node_pt =
1157 current_seg_last_ele_pt->node_pt(nnod - 1);
1158 if (is_inverted[current_seg_last_ele_pt])
1160 current_seg_last_node_pt = current_seg_last_ele_pt->node_pt(0);
1164 for (
unsigned i = 0; i < 2; i++)
1166 current_seg_initial_coord[i] = current_seg_first_node_pt->x(i);
1167 current_seg_final_coord[i] = current_seg_last_node_pt->x(i);
1174 for (
unsigned orig_s = 0; orig_s < nsegments; orig_s++)
1176 if (!segment_done[orig_s])
1179 Vector<double> initial_coordinate =
1180 original_mesh_segment_initial_coordinate[orig_s];
1181 Vector<double> final_coordinate =
1182 original_mesh_segment_final_coordinate[orig_s];
1187 ((current_seg_initial_coord[0] - initial_coordinate[0]) *
1188 (current_seg_initial_coord[0] - initial_coordinate[0])) +
1189 ((current_seg_initial_coord[1] - initial_coordinate[1]) *
1190 (current_seg_initial_coord[1] - initial_coordinate[1]));
1194 if (dist < ToleranceForVertexMismatchInPolygons::Tolerable_error)
1198 dist = ((current_seg_final_coord[0] - final_coordinate[0]) *
1199 (current_seg_final_coord[0] - final_coordinate[0])) +
1200 ((current_seg_final_coord[1] - final_coordinate[1]) *
1201 (current_seg_final_coord[1] - final_coordinate[1]));
1206 if (dist < ToleranceForVertexMismatchInPolygons::Tolerable_error)
1210 current_segment_to_original_segment_index[is] = orig_s;
1213 Boundary_segment_inverted[b].push_back(0);
1216 Boundary_segment_initial_coordinate[b].push_back(
1217 initial_coordinate);
1218 Boundary_segment_final_coordinate[b].push_back(
1222 if (this->boundary_geom_object_pt(b) != 0)
1225 Boundary_segment_initial_zeta[b].push_back(
1226 original_mesh_segment_initial_zeta[orig_s]);
1227 Boundary_segment_final_zeta[b].push_back(
1228 original_mesh_segment_final_zeta[orig_s]);
1234 Boundary_segment_initial_arclength[b].push_back(
1235 original_mesh_segment_initial_arclength[orig_s]);
1236 Boundary_segment_final_arclength[b].push_back(
1237 original_mesh_segment_final_arclength[orig_s]);
1240 segment_done[orig_s] =
true;
1242 found_original_segment =
true;
1254 ((current_seg_initial_coord[0] - final_coordinate[0]) *
1255 (current_seg_initial_coord[0] - final_coordinate[0])) +
1256 ((current_seg_initial_coord[1] - final_coordinate[1]) *
1257 (current_seg_initial_coord[1] - final_coordinate[1]));
1258 dist_inv = sqrt(dist_inv);
1263 ToleranceForVertexMismatchInPolygons::Tolerable_error)
1268 ((current_seg_final_coord[0] - initial_coordinate[0]) *
1269 (current_seg_final_coord[0] - initial_coordinate[0])) +
1270 ((current_seg_final_coord[1] - initial_coordinate[1]) *
1271 (current_seg_final_coord[1] - initial_coordinate[1]));
1272 dist_inv = sqrt(dist_inv);
1277 ToleranceForVertexMismatchInPolygons::Tolerable_error)
1281 current_segment_to_original_segment_index[is] = orig_s;
1284 Boundary_segment_inverted[b].push_back(1);
1287 Boundary_segment_initial_coordinate[b].push_back(
1288 initial_coordinate);
1289 Boundary_segment_final_coordinate[b].push_back(
1293 if (this->boundary_geom_object_pt(b) != 0)
1296 Boundary_segment_initial_zeta[b].push_back(
1297 original_mesh_segment_initial_zeta[orig_s]);
1298 Boundary_segment_final_zeta[b].push_back(
1299 original_mesh_segment_final_zeta[orig_s]);
1304 Boundary_segment_initial_arclength[b].push_back(
1305 original_mesh_segment_initial_arclength[orig_s]);
1306 Boundary_segment_final_arclength[b].push_back(
1307 original_mesh_segment_final_arclength[orig_s]);
1310 segment_done[orig_s] =
true;
1312 found_original_segment =
true;
1327 if (!found_original_segment)
1329 std::stringstream error_message;
1331 <<
"The (" << is <<
")-th segment on the current segment was not\n"
1332 <<
"found when trying to identify it with the original mesh's\n"
1333 <<
"segment coordinates\n";
1334 throw OomphLibError(error_message.str(),
1335 OOMPH_CURRENT_FUNCTION,
1336 OOMPH_EXCEPTION_LOCATION);
1357 if (
this != original_mesh_pt)
1363 Vector<double> first_node_zeta_coordinate =
1364 original_mesh_pt->boundary_initial_zeta_coordinate(b);
1365 Vector<double> last_node_zeta_coordinate =
1366 original_mesh_pt->boundary_final_zeta_coordinate(b);
1370 const double boundary_arclength =
1371 std::max(first_node_zeta_coordinate[0], last_node_zeta_coordinate[0]);
1373 for (
unsigned is = 0; is < nsegments; is++)
1378 if (boundary_geom_object_pt(b) == 0)
1395 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
1398 const unsigned nnod = first_ele_pt->nnode();
1401 Node* first_node_pt = first_ele_pt->node_pt(0);
1402 if (is_inverted[first_ele_pt])
1404 first_node_pt = first_ele_pt->node_pt(nnod - 1);
1408 FiniteElement* last_ele_pt = segment_sorted_ele_pt[is].back();
1411 Node* last_node_pt = last_ele_pt->node_pt(nnod - 1);
1412 if (is_inverted[last_ele_pt])
1414 last_node_pt = last_ele_pt->node_pt(0);
1418 Vector<double> current_segment_initial_arclen(1);
1419 Vector<double> current_segment_final_arclen(1);
1421 if (!Boundary_segment_inverted[b][is])
1423 first_node_pt->get_coordinates_on_boundary(
1424 b, current_segment_initial_arclen);
1425 last_node_pt->get_coordinates_on_boundary(
1426 b, current_segment_final_arclen);
1430 first_node_pt->get_coordinates_on_boundary(
1431 b, current_segment_final_arclen);
1432 last_node_pt->get_coordinates_on_boundary(
1433 b, current_segment_initial_arclen);
1441 bool increasing_order =
false;
1445 if (current_segment_initial_arclen[0] <
1446 current_segment_final_arclen[0])
1448 increasing_order =
true;
1452 else if (current_segment_initial_arclen[0] >
1453 current_segment_final_arclen[0])
1455 increasing_order =
false;
1460 std::stringstream error_message;
1462 <<
"It was not possible to identify if the zeta values on "
1463 <<
"boundary (" << b <<
")\nand segment (" << is
1464 <<
") should go in "
1465 <<
"increasing or decreasing order.\n--- New mesh ---\n"
1466 <<
"Current segment initial arclength: ("
1467 << current_segment_initial_arclen[0] <<
")\n"
1468 <<
"First node coordinates: (" << first_node_pt->x(0) <<
", "
1469 << first_node_pt->x(1) <<
")\n"
1470 <<
"Current segment final arclength: ("
1471 << current_segment_final_arclen[0] <<
")\n"
1472 <<
"Last node coordinates: (" << last_node_pt->x(0) <<
", "
1473 << last_node_pt->x(1) <<
")\n"
1474 <<
"Current segment arclength: (" << segment_arclength[is]
1476 throw OomphLibError(error_message.str(),
1477 OOMPH_CURRENT_FUNCTION,
1478 OOMPH_EXCEPTION_LOCATION);
1484 const unsigned prev_s = current_segment_to_original_segment_index[is];
1485 const double original_segment_initial_arclength =
1486 original_mesh_pt->boundary_segment_initial_arclength(b)[prev_s];
1487 const double original_segment_final_arclength =
1488 original_mesh_pt->boundary_segment_final_arclength(b)[prev_s];
1492 bool original_increasing_order =
false;
1497 double starting_arclength = 0.0;
1498 if (original_segment_final_arclength >
1499 original_segment_initial_arclength)
1502 original_increasing_order =
true;
1504 starting_arclength = original_segment_initial_arclength;
1506 else if (original_segment_final_arclength <
1507 original_segment_initial_arclength)
1510 original_increasing_order =
false;
1512 starting_arclength = original_segment_final_arclength;
1517 std::stringstream error_message;
1519 <<
"It was not possible to identify if the zeta values on "
1520 <<
"boundary (" << b <<
")\nand segment (" << is
1521 <<
") should go in "
1522 <<
"increasing or decreasing order.\n--- Original mesh ---\n"
1523 <<
"Original segment initial arclength: ("
1524 << original_segment_initial_arclength <<
")\n"
1525 <<
"Original segment final arclength: ("
1526 << original_segment_final_arclength <<
")\n";
1527 throw OomphLibError(error_message.str(),
1528 OOMPH_CURRENT_FUNCTION,
1529 OOMPH_EXCEPTION_LOCATION);
1536 if (increasing_order && original_increasing_order)
1552 std::set<Node*> seg_nodes_pt = segment_all_nodes_pt[is];
1555 for (std::set<Node*>::iterator it = seg_nodes_pt.begin();
1556 it != seg_nodes_pt.end();
1560 Vector<double> zeta(1);
1562 Node* nod_pt = (*it);
1564 nod_pt->get_coordinates_on_boundary(b, zeta);
1567 starting_arclength + (zeta[0] * segment_arclength[is]);
1569 zeta[0] = temp / boundary_arclength;
1571 if (std::fabs(zeta[0] - 1.0) < 1.0e-14)
1575 else if (std::fabs(zeta[0]) < 1.0e-14)
1581 nod_pt->set_coordinates_on_boundary(b, zeta);
1584 else if (!increasing_order && original_increasing_order)
1600 std::set<Node*> seg_nodes_pt = segment_all_nodes_pt[is];
1603 for (std::set<Node*>::iterator it = seg_nodes_pt.begin();
1604 it != seg_nodes_pt.end();
1608 Vector<double> zeta(1);
1610 Node* nod_pt = (*it);
1612 nod_pt->get_coordinates_on_boundary(b, zeta);
1615 starting_arclength + ((1.0 - zeta[0]) * segment_arclength[is]);
1617 zeta[0] = temp / boundary_arclength;
1619 if (std::fabs(zeta[0] - 1.0) < 1.0e-14)
1623 else if (std::fabs(zeta[0]) < 1.0e-14)
1628 nod_pt->set_coordinates_on_boundary(b, zeta);
1631 else if (increasing_order && !original_increasing_order)
1647 std::set<Node*> seg_nodes_pt = segment_all_nodes_pt[is];
1650 for (std::set<Node*>::iterator it = seg_nodes_pt.begin();
1651 it != seg_nodes_pt.end();
1655 Vector<double> zeta(1);
1657 Node* nod_pt = (*it);
1659 nod_pt->get_coordinates_on_boundary(b, zeta);
1662 starting_arclength + ((1.0 - zeta[0]) * segment_arclength[is]);
1664 zeta[0] = temp / boundary_arclength;
1666 if (std::fabs(zeta[0] - 1.0) < 1.0e-14)
1670 else if (std::fabs(zeta[0]) < 1.0e-14)
1675 nod_pt->set_coordinates_on_boundary(b, zeta);
1678 else if (!increasing_order && !original_increasing_order)
1694 std::set<Node*> seg_nodes_pt = segment_all_nodes_pt[is];
1697 for (std::set<Node*>::iterator it = seg_nodes_pt.begin();
1698 it != seg_nodes_pt.end();
1702 Vector<double> zeta(1);
1704 Node* nod_pt = (*it);
1706 nod_pt->get_coordinates_on_boundary(b, zeta);
1709 starting_arclength + (zeta[0] * segment_arclength[is]);
1711 zeta[0] = temp / boundary_arclength;
1713 if (std::fabs(zeta[0] - 1.0) < 1.0e-14)
1717 else if (std::fabs(zeta[0]) < 1.0e-14)
1722 nod_pt->set_coordinates_on_boundary(b, zeta);
1729 for (std::list<FiniteElement*>::iterator it_list =
1730 segment_sorted_ele_pt[is].begin();
1731 it_list != segment_sorted_ele_pt[is].end();
1735 const unsigned nnod = (*it_list)->nnode();
1738 Node* first_node_pt = (*it_list)->node_pt(0);
1739 if (is_inverted[(*it_list)])
1741 first_node_pt = (*it_list)->node_pt(nnod - 1);
1745 Node* last_node_pt = (*it_list)->node_pt(nnod - 1);
1746 if (is_inverted[(*it_list)])
1748 last_node_pt = (*it_list)->node_pt(0);
1752 Vector<double> zeta(1);
1753 first_node_pt->get_coordinates_on_boundary(b, zeta);
1754 if (zeta[0] < 0.0 || zeta[0] > 1.0)
1756 std::ostringstream error_message;
1758 <<
"The boundary coordinate of the first node on boundary ("
1759 << b <<
")\nand segment (" << is <<
") is out of the "
1760 <<
"allowed values [0,1]\n"
1761 <<
"The node boundary coordinate: (" << zeta[0] <<
")\n"
1762 <<
"The vertex coordinates are: (" << first_node_pt->x(0)
1763 <<
", " << first_node_pt->x(1) <<
")\n";
1764 throw OomphLibError(error_message.str(),
1765 OOMPH_CURRENT_FUNCTION,
1766 OOMPH_EXCEPTION_LOCATION);
1770 last_node_pt->get_coordinates_on_boundary(b, zeta);
1771 if (zeta[0] < 0.0 || zeta[0] > 1.0)
1773 std::ostringstream error_message;
1775 <<
"The boundary coordinate of the last node on boundary (" << b
1776 <<
")\nand segment (" << is <<
") is out of the "
1777 <<
"allowed values [0,1]\n"
1778 <<
"The node boundary coordinate: (" << zeta[0] <<
")\n"
1779 <<
"The vertex coordinates are: (" << last_node_pt->x(0) <<
", "
1780 << last_node_pt->x(1) <<
")\n";
1781 throw OomphLibError(error_message.str(),
1782 OOMPH_CURRENT_FUNCTION,
1783 OOMPH_EXCEPTION_LOCATION);
1802 Boundary_initial_coordinate[b] =
1803 original_mesh_pt->boundary_initial_coordinate(b);
1805 Boundary_final_coordinate[b] =
1806 original_mesh_pt->boundary_final_coordinate(b);
1810 Boundary_initial_zeta_coordinate[b] =
1811 original_mesh_pt->boundary_initial_zeta_coordinate(b);
1813 Boundary_final_zeta_coordinate[b] =
1814 original_mesh_pt->boundary_final_zeta_coordinate(b);
1820 Assigned_segments_initial_zeta_values[b] =
true;
1823 for (
unsigned i = 0; i < nele; i++)
1825 delete face_el_pt[i];
1836 template<
class ELEMENT>
1846 OomphCommunicator* comm_pt = this->communicator_pt();
1849 const unsigned nproc = comm_pt->nproc();
1851 const unsigned my_rank = comm_pt->my_rank();
1854 Vector<FiniteElement*> all_face_ele_pt;
1859 bool is_internal_boundary =
false;
1863 std::map<FiniteElement*, FiniteElement*> face_to_bulk_element_pt;
1867 select_boundary_face_elements(
1868 all_face_ele_pt, b, is_internal_boundary, face_to_bulk_element_pt);
1871 const unsigned n_all_face_ele = all_face_ele_pt.size();
1879 std::vector<bool> is_halo_face_element(n_all_face_ele,
false);
1882 unsigned nnon_halo_face_elements = 0;
1886 for (
unsigned ie = 0; ie < n_all_face_ele; ie++)
1888 FiniteElement* face_ele_pt = all_face_ele_pt[ie];
1890 FiniteElement* tmp_bulk_ele_pt = face_to_bulk_element_pt[face_ele_pt];
1892 if (!tmp_bulk_ele_pt->is_halo())
1895 is_halo_face_element[ie] =
false;
1897 nnon_halo_face_elements++;
1902 is_halo_face_element[ie] =
true;
1908 const unsigned nhalo_face_element =
1909 n_all_face_ele - nnon_halo_face_elements;
1913 Vector<std::list<FiniteElement*>> segment_sorted_ele_pt;
1917 unsigned nsorted_face_elements = 0;
1921 std::map<FiniteElement*, bool> done_el;
1925 std::map<FiniteElement*, bool> is_inverted;
1928 while (nsorted_face_elements < nnon_halo_face_elements)
1932 std::list<FiniteElement*> sorted_el_pt;
1933 sorted_el_pt.clear();
1938 bool found_initial_face_element =
false;
1941 FiniteElement* ele_face_pt = 0;
1944 for (iface = 0; iface < n_all_face_ele; iface++)
1946 if (!is_halo_face_element[iface])
1948 ele_face_pt = all_face_ele_pt[iface];
1950 if (!done_el[ele_face_pt])
1953 found_initial_face_element =
true;
1955 nsorted_face_elements++;
1957 sorted_el_pt.push_back(ele_face_pt);
1959 done_el[ele_face_pt] =
true;
1966 if (!found_initial_face_element)
1968 std::ostringstream error_message;
1970 <<
"Could not find an initial face element for the current segment\n";
1972 throw OomphLibError(error_message.str(),
1973 OOMPH_CURRENT_FUNCTION,
1974 OOMPH_EXCEPTION_LOCATION);
1979 const unsigned nnod = ele_face_pt->nnode();
1983 Node* left_node_pt = ele_face_pt->node_pt(0);
1984 Node* right_node_pt = ele_face_pt->node_pt(nnod - 1);
1988 bool face_element_added =
false;
1997 for (
unsigned iiface = iface; iiface < n_all_face_ele; iiface++)
2000 face_element_added =
false;
2003 ele_face_pt = all_face_ele_pt[iiface];
2007 if (!(done_el[ele_face_pt] || is_halo_face_element[iiface]))
2010 Node* local_left_node_pt = ele_face_pt->node_pt(0);
2011 Node* local_right_node_pt = ele_face_pt->node_pt(nnod - 1);
2014 if (left_node_pt == local_right_node_pt)
2016 left_node_pt = local_left_node_pt;
2017 sorted_el_pt.push_front(ele_face_pt);
2018 is_inverted[ele_face_pt] =
false;
2019 face_element_added =
true;
2022 else if (left_node_pt == local_left_node_pt)
2024 left_node_pt = local_right_node_pt;
2025 sorted_el_pt.push_front(ele_face_pt);
2026 is_inverted[ele_face_pt] =
true;
2027 face_element_added =
true;
2030 else if (right_node_pt == local_left_node_pt)
2032 right_node_pt = local_right_node_pt;
2033 sorted_el_pt.push_back(ele_face_pt);
2034 is_inverted[ele_face_pt] =
false;
2035 face_element_added =
true;
2038 else if (right_node_pt == local_right_node_pt)
2040 right_node_pt = local_left_node_pt;
2041 sorted_el_pt.push_back(ele_face_pt);
2042 is_inverted[ele_face_pt] =
true;
2043 face_element_added =
true;
2046 if (face_element_added)
2048 done_el[ele_face_pt] =
true;
2049 nsorted_face_elements++;
2055 }
while (face_element_added &&
2056 (nsorted_face_elements < nnon_halo_face_elements));
2059 segment_sorted_ele_pt.push_back(sorted_el_pt);
2073 Vector<std::set<Node*>> segment_all_nodes_pt;
2076 const unsigned nsegments = segment_sorted_ele_pt.size();
2080 if (nnon_halo_face_elements > 0 && nsegments == 0)
2082 std::ostringstream error_message;
2084 <<
"The number of segments is zero, but the number of nonhalo\n"
2085 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
2086 throw OomphLibError(
2087 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
2092 Vector<double> segment_arclength(nsegments);
2095 Vector<unsigned> nvertices_per_segment(nsegments);
2098 Vector<double> initial_zeta_segment(nsegments);
2101 Vector<double> final_zeta_segment(nsegments);
2106 for (
unsigned is = 0; is < nsegments; is++)
2109 if (segment_sorted_ele_pt[is].size() == 0)
2111 std::ostringstream error_message;
2112 error_message <<
"The (" << is <<
")-th segment has no elements\n";
2113 throw OomphLibError(error_message.str(),
2114 OOMPH_CURRENT_FUNCTION,
2115 OOMPH_EXCEPTION_LOCATION);
2120 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
2123 const unsigned nnod = first_ele_pt->nnode();
2126 Node* first_node_pt = first_ele_pt->node_pt(0);
2127 if (is_inverted[first_ele_pt])
2129 first_node_pt = first_ele_pt->node_pt(nnod - 1);
2133 double x_left = first_node_pt->x(0);
2134 double y_left = first_node_pt->x(1);
2138 Vector<double> zeta(1, 0.0);
2143 if (this->boundary_geom_object_pt(b) != 0)
2146 first_node_pt->get_coordinates_on_boundary(b, zeta);
2148 initial_zeta_segment[is] = zeta[0];
2151 FiniteElement* last_ele_pt = segment_sorted_ele_pt[is].back();
2154 Node* last_node_pt = last_ele_pt->node_pt(nnod - 1);
2155 if (is_inverted[last_ele_pt])
2157 last_node_pt = last_ele_pt->node_pt(0);
2161 last_node_pt->get_coordinates_on_boundary(b, zeta);
2163 final_zeta_segment[is] = zeta[0];
2168 std::set<Node*> local_nodes_pt;
2170 local_nodes_pt.insert(first_node_pt);
2173 for (std::list<FiniteElement*>::iterator it =
2174 segment_sorted_ele_pt[is].begin();
2175 it != segment_sorted_ele_pt[is].end();
2179 FiniteElement* el_pt = (*it);
2185 if (is_inverted[el_pt])
2192 for (
unsigned j = 1; j < nnod; j++)
2194 Node* nod_pt = el_pt->node_pt(k_nod);
2198 double x_right = nod_pt->x(0);
2199 double y_right = nod_pt->x(1);
2202 zeta[0] += sqrt((x_right - x_left) * (x_right - x_left) +
2203 (y_right - y_left) * (y_right - y_left));
2220 local_nodes_pt.insert(nod_pt);
2229 segment_arclength[is] = zeta[0];
2234 nvertices_per_segment[is] = local_nodes_pt.size();
2237 segment_all_nodes_pt.push_back(local_nodes_pt);
2246 Vector<unsigned> nvertices_before_segment(nsegments, 0);
2251 Vector<double> initial_segment_arclength(nsegments, 0.0);
2259 unsigned proc_with_initial_seg = 0;
2260 unsigned proc_with_final_seg = 0;
2264 unsigned initial_segment = 0;
2265 unsigned final_segment = 0;
2269 Vector<unsigned> segment_inverted(nsegments);
2273 Vector<std::list<FiniteElement*>> segment_sorted_nonhalo_ele_pt(nsegments);
2274 for (
unsigned is = 0; is < nsegments; is++)
2276 for (std::list<FiniteElement*>::iterator it_seg =
2277 segment_sorted_ele_pt[is].begin();
2278 it_seg != segment_sorted_ele_pt[is].end();
2281 segment_sorted_nonhalo_ele_pt[is].push_back((*it_seg));
2288 for (
unsigned is = 0; is < nsegments; is++)
2291 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
2294 const unsigned nnod = first_ele_pt->nnode();
2297 Node* first_node_pt = first_ele_pt->node_pt(0);
2298 if (is_inverted[first_ele_pt])
2300 first_node_pt = first_ele_pt->node_pt(nnod - 1);
2304 FiniteElement* last_ele_pt = segment_sorted_ele_pt[is].back();
2307 Node* last_node_pt = last_ele_pt->node_pt(nnod - 1);
2308 if (is_inverted[last_ele_pt])
2310 last_node_pt = last_ele_pt->node_pt(0);
2317 bool attached_left_halo =
false;
2318 bool attached_right_halo =
false;
2319 if (nhalo_face_element > 0)
2321 for (
unsigned iiface = 0; iiface < n_all_face_ele; iiface++)
2324 FiniteElement* halo_face_ele_pt = all_face_ele_pt[iiface];
2337 if (is_halo_face_element[iiface])
2340 Node* left_node_pt = halo_face_ele_pt->node_pt(0);
2341 Node* right_node_pt = halo_face_ele_pt->node_pt(nnod - 1);
2343 if (!attached_left_halo && (first_node_pt == right_node_pt ||
2344 first_node_pt == left_node_pt))
2347 segment_sorted_ele_pt[is].push_front(halo_face_ele_pt);
2351 attached_left_halo =
true;
2354 else if (!attached_right_halo && (last_node_pt == left_node_pt ||
2355 last_node_pt == right_node_pt))
2358 segment_sorted_ele_pt[is].push_back(halo_face_ele_pt);
2361 attached_right_halo =
true;
2365 if (attached_left_halo && attached_right_halo)
2389 Vector<unsigned> left_processor_plus_one(nsegments);
2394 Vector<unsigned> right_processor_plus_one(nsegments);
2399 Vector<unsigned> left_halo_element(nsegments);
2404 Vector<unsigned> right_halo_element(nsegments);
2409 Vector<unsigned> left_haloed_element(nsegments);
2414 Vector<unsigned> right_haloed_element(nsegments);
2417 for (
unsigned is = 0; is < nsegments; is++)
2420 FiniteElement* left_face_ele_pt = segment_sorted_ele_pt[is].front();
2424 FiniteElement* tmp_left_bulk_ele_pt =
2425 face_to_bulk_element_pt[left_face_ele_pt];
2428 if (tmp_left_bulk_ele_pt->is_halo())
2431 int left_proc = tmp_left_bulk_ele_pt->non_halo_proc_ID();
2435 std::ostringstream error_message;
2437 <<
"The current bulk element (left) is marked as halo but "
2438 <<
"the processor holding\nthe non-halo counterpart is "
2440 throw OomphLibError(error_message.str(),
2441 OOMPH_CURRENT_FUNCTION,
2442 OOMPH_EXCEPTION_LOCATION);
2446 unsigned left_processor =
static_cast<unsigned>(left_proc);
2447 left_processor_plus_one[is] = left_processor + 1;
2450 GeneralisedElement* left_element_pt = tmp_left_bulk_ele_pt;
2453 Vector<GeneralisedElement*> left_halo_element_pt =
2454 this->halo_element_pt(left_processor);
2458 bool left_halo_element_found =
false;
2461 const unsigned n_halo_left = left_halo_element_pt.size();
2462 for (
unsigned lh = 0; lh < n_halo_left; lh++)
2464 if (left_element_pt == left_halo_element_pt[lh])
2466 left_halo_element[is] = lh;
2468 left_halo_element_found =
true;
2475 if (!left_halo_element_found)
2477 std::ostringstream error_message;
2479 <<
"The current bulk element (left) marked as halo was "
2480 <<
"not found in the vector of halo\nelements associated "
2481 <<
"with the (" << left_processor <<
") processor.\n\n";
2482 throw OomphLibError(error_message.str(),
2483 OOMPH_CURRENT_FUNCTION,
2484 OOMPH_EXCEPTION_LOCATION);
2490 left_face_ele_pt = segment_sorted_nonhalo_ele_pt[is].front();
2493 tmp_left_bulk_ele_pt = face_to_bulk_element_pt[left_face_ele_pt];
2497 if (tmp_left_bulk_ele_pt->is_halo())
2499 std::ostringstream error_message;
2501 <<
"The bulk element represetation of the left-most nonhalo face\n"
2502 <<
"element of the current segment (" << is
2503 <<
") is marked as halo,\n"
2504 <<
"but the face element created from it is nonhalo\n";
2505 throw OomphLibError(error_message.str(),
2506 OOMPH_CURRENT_FUNCTION,
2507 OOMPH_EXCEPTION_LOCATION);
2513 left_element_pt = tmp_left_bulk_ele_pt;
2517 bool left_haloed_element_found =
false;
2522 Vector<GeneralisedElement*> left_haloed_element_pt =
2523 this->haloed_element_pt(left_processor);
2525 const unsigned nhaloed_left = left_haloed_element_pt.size();
2526 for (
unsigned lhd = 0; lhd < nhaloed_left; lhd++)
2528 if (left_element_pt == left_haloed_element_pt[lhd])
2530 left_haloed_element[is] = lhd;
2532 left_haloed_element_found =
true;
2539 if (!left_haloed_element_found)
2541 std::ostringstream error_message;
2543 <<
"The current bulk element (left) marked as haloed was "
2544 <<
"not found in the vector of haloed\nelements associated "
2545 <<
"with processor (" << left_processor <<
").\n";
2546 throw OomphLibError(error_message.str(),
2547 OOMPH_CURRENT_FUNCTION,
2548 OOMPH_EXCEPTION_LOCATION);
2555 left_processor_plus_one[is] = 0;
2557 left_halo_element[is] = 0;
2559 left_haloed_element[is] = 0;
2563 FiniteElement* right_face_ele_pt = segment_sorted_ele_pt[is].back();
2567 FiniteElement* tmp_right_bulk_ele_pt =
2568 face_to_bulk_element_pt[right_face_ele_pt];
2571 if (tmp_right_bulk_ele_pt->is_halo())
2574 int right_proc = tmp_right_bulk_ele_pt->non_halo_proc_ID();
2578 std::ostringstream error_message;
2580 <<
"The current bulk element (right) is marked as halo but "
2581 <<
"the processor holding\nthe non-halo counterpart is "
2583 throw OomphLibError(error_message.str(),
2584 "TriangleMesh::compute_boundary_segments_"
2585 "connectivity_and_initial_zeta_values()",
2586 OOMPH_EXCEPTION_LOCATION);
2590 unsigned right_processor =
static_cast<unsigned>(right_proc);
2591 right_processor_plus_one[is] = right_processor + 1;
2594 GeneralisedElement* right_element_pt = tmp_right_bulk_ele_pt;
2597 Vector<GeneralisedElement*> right_halo_element_pt =
2598 this->halo_element_pt(right_processor);
2602 bool right_halo_element_found =
false;
2605 const unsigned nhalo_right = right_halo_element_pt.size();
2606 for (
unsigned rh = 0; rh < nhalo_right; rh++)
2608 if (right_element_pt == right_halo_element_pt[rh])
2610 right_halo_element[is] = rh;
2612 right_halo_element_found =
true;
2618 if (!right_halo_element_found)
2620 std::ostringstream error_message;
2622 <<
"The current bulk element (right) marked as halo was not "
2623 <<
"found in the vector of halo\nelements associated with "
2624 <<
"the (" << right_processor <<
") processor.\n\n";
2625 throw OomphLibError(error_message.str(),
2626 "TriangleMesh::compute_boundary_segments_"
2627 "connectivity_and_initial_zeta_values()",
2628 OOMPH_EXCEPTION_LOCATION);
2634 right_face_ele_pt = segment_sorted_nonhalo_ele_pt[is].back();
2637 tmp_right_bulk_ele_pt = face_to_bulk_element_pt[right_face_ele_pt];
2640 if (tmp_right_bulk_ele_pt->is_halo())
2642 std::ostringstream error_message;
2644 <<
"The bulk element represetation of the right-most nonhalo face\n"
2645 <<
"element of the current segment (" << is
2646 <<
") is marked as halo,\n"
2647 <<
"but the face element created from it is nonhalo\n";
2648 throw OomphLibError(error_message.str(),
2649 "TriangleMesh::compute_boundary_segments_"
2650 "connectivity_and_initial_zeta_values()",
2651 OOMPH_EXCEPTION_LOCATION);
2657 right_element_pt = tmp_right_bulk_ele_pt;
2661 bool right_haloed_element_found =
false;
2665 Vector<GeneralisedElement*> right_haloed_element_pt =
2666 this->haloed_element_pt(right_processor);
2668 const unsigned nhaloed_right = right_haloed_element_pt.size();
2669 for (
unsigned rhd = 0; rhd < nhaloed_right; rhd++)
2671 if (right_element_pt == right_haloed_element_pt[rhd])
2673 right_haloed_element[is] = rhd;
2675 right_haloed_element_found =
true;
2682 if (!right_haloed_element_found)
2684 std::ostringstream error_message;
2686 <<
"The current bulk element (right) marked as haloed was not "
2687 <<
"found in the vector of haloed\nelements associated with "
2688 <<
"the (" << right_processor <<
") processor.\n\n";
2689 throw OomphLibError(error_message.str(),
2690 "TriangleMesh::compute_boundary_segments_"
2691 "connectivity_and_initial_zeta_values()",
2692 OOMPH_EXCEPTION_LOCATION);
2700 right_processor_plus_one[is] = 0;
2702 right_halo_element[is] = 0;
2704 right_haloed_element[is] = 0;
2720 const unsigned root_processor = 0;
2726 Vector<unsigned> root_nsegments_per_processor(nproc);
2727 unsigned nsegments_mpi = nsegments;
2728 MPI_Gather(&nsegments_mpi,
2731 &root_nsegments_per_processor[0],
2735 comm_pt->mpi_comm());
2743 const unsigned spu = 7;
2744 Vector<unsigned> flat_packed_unsigned_send_data(nsegments * spu);
2745 for (
unsigned is = 0; is < nsegments; is++)
2747 flat_packed_unsigned_send_data[(spu * is) + 0] =
2748 left_processor_plus_one[is];
2749 flat_packed_unsigned_send_data[(spu * is) + 1] =
2750 right_processor_plus_one[is];
2751 flat_packed_unsigned_send_data[(spu * is) + 2] = left_halo_element[is];
2752 flat_packed_unsigned_send_data[(spu * is) + 3] = right_halo_element[is];
2753 flat_packed_unsigned_send_data[(spu * is) + 4] = left_haloed_element[is];
2754 flat_packed_unsigned_send_data[(spu * is) + 5] = right_haloed_element[is];
2755 flat_packed_unsigned_send_data[(spu * is) + 6] =
2756 nvertices_per_segment[is];
2760 const unsigned nudata_to_send = flat_packed_unsigned_send_data.size();
2764 Vector<int> root_nudata_to_receive(nproc, 0);
2766 unsigned root_nutotal_data_receive = 0;
2767 for (
unsigned ip = 0; ip < nproc; ip++)
2771 root_nudata_to_receive[ip] = root_nsegments_per_processor[ip] * spu;
2773 root_nutotal_data_receive += root_nudata_to_receive[ip];
2778 Vector<int> root_uoffsets_receive(nproc, 0);
2779 root_uoffsets_receive[0] = 0;
2780 for (
unsigned ip = 1; ip < nproc; ip++)
2783 root_uoffsets_receive[ip] =
2784 root_uoffsets_receive[ip - 1] + root_nudata_to_receive[ip - 1];
2788 if (flat_packed_unsigned_send_data.size() == 0)
2790 flat_packed_unsigned_send_data.resize(1);
2794 Vector<unsigned> flat_packed_unsigned_receive_data(
2795 root_nutotal_data_receive);
2796 if (my_rank != root_processor)
2799 if (flat_packed_unsigned_receive_data.size() == 0)
2801 flat_packed_unsigned_receive_data.resize(1);
2805 MPI_Gatherv(&flat_packed_unsigned_send_data[0],
2811 &flat_packed_unsigned_receive_data[0],
2816 &root_nudata_to_receive[0],
2818 &root_uoffsets_receive[0],
2823 comm_pt->mpi_comm());
2826 flat_packed_unsigned_send_data.clear();
2827 flat_packed_unsigned_send_data.resize(0);
2833 const unsigned spd = 1;
2834 Vector<double> flat_packed_double_send_data(nsegments * spd);
2835 for (
unsigned is = 0; is < nsegments; is++)
2837 flat_packed_double_send_data[(spd * is) + 0] = segment_arclength[is];
2841 const unsigned nddata_to_send = flat_packed_double_send_data.size();
2844 Vector<int> root_nddata_to_receive(nproc, 0);
2846 unsigned root_ndtotal_data_receive = 0;
2847 for (
unsigned ip = 0; ip < nproc; ip++)
2849 root_nddata_to_receive[ip] = root_nsegments_per_processor[ip] * spd;
2850 root_ndtotal_data_receive += root_nddata_to_receive[ip];
2855 Vector<int> root_doffsets_receive(nproc, 0);
2856 root_doffsets_receive[0] = 0;
2857 for (
unsigned ip = 1; ip < nproc; ip++)
2860 root_doffsets_receive[ip] =
2861 root_doffsets_receive[ip - 1] + root_nddata_to_receive[ip - 1];
2865 if (flat_packed_double_send_data.size() == 0)
2867 flat_packed_double_send_data.resize(1);
2871 Vector<double> flat_packed_double_receive_data(root_ndtotal_data_receive);
2872 if (my_rank != root_processor)
2875 if (flat_packed_double_receive_data.size() == 0)
2877 flat_packed_double_receive_data.resize(1);
2881 MPI_Gatherv(&flat_packed_double_send_data[0],
2887 &flat_packed_double_receive_data[0],
2891 &root_nddata_to_receive[0],
2893 &root_doffsets_receive[0],
2898 comm_pt->mpi_comm());
2901 flat_packed_double_send_data.clear();
2902 flat_packed_double_send_data.resize(0);
2910 Vector<Vector<double>> root_initial_segment_arclength(nproc);
2914 Vector<Vector<unsigned>> root_nvertices_before_segment(nproc);
2920 Vector<Vector<unsigned>> root_segment_inverted(nproc);
2924 double root_accumulated_arclength = 0.0;
2928 unsigned root_accumulated_vertices_before_segment = 0;
2932 if (my_rank == root_processor)
2942 Vector<Vector<unsigned>> root_left_processor_plus_one(nproc);
2947 Vector<Vector<unsigned>> root_right_processor_plus_one(nproc);
2952 Vector<Vector<unsigned>> root_left_halo_element(nproc);
2958 Vector<Vector<unsigned>> root_right_halo_element(nproc);
2964 Vector<Vector<unsigned>> root_left_haloed_element(nproc);
2970 Vector<Vector<unsigned>> root_right_haloed_element(nproc);
2973 Vector<Vector<unsigned>> root_nvertices_per_segment(nproc);
2976 Vector<Vector<double>> root_segment_arclength(nproc);
2978 unsigned ucounter = 0;
2979 unsigned dcounter = 0;
2980 for (
unsigned ip = 0; ip < nproc; ip++)
2983 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
2985 root_left_processor_plus_one[ip].resize(nsegs_iproc);
2986 root_right_processor_plus_one[ip].resize(nsegs_iproc);
2987 root_left_halo_element[ip].resize(nsegs_iproc);
2988 root_right_halo_element[ip].resize(nsegs_iproc);
2989 root_left_haloed_element[ip].resize(nsegs_iproc);
2990 root_right_haloed_element[ip].resize(nsegs_iproc);
2993 root_nvertices_per_segment[ip].resize(nsegs_iproc);
2994 root_segment_arclength[ip].resize(nsegs_iproc);
2995 root_segment_inverted[ip].resize(nsegs_iproc);
2999 for (
unsigned is = 0; is < nsegs_iproc; is++)
3002 root_left_processor_plus_one[ip][is] =
3003 flat_packed_unsigned_receive_data[ucounter++];
3004 root_right_processor_plus_one[ip][is] =
3005 flat_packed_unsigned_receive_data[ucounter++];
3006 root_left_halo_element[ip][is] =
3007 flat_packed_unsigned_receive_data[ucounter++];
3008 root_right_halo_element[ip][is] =
3009 flat_packed_unsigned_receive_data[ucounter++];
3010 root_left_haloed_element[ip][is] =
3011 flat_packed_unsigned_receive_data[ucounter++];
3012 root_right_haloed_element[ip][is] =
3013 flat_packed_unsigned_receive_data[ucounter++];
3014 root_nvertices_per_segment[ip][is] =
3015 flat_packed_unsigned_receive_data[ucounter++];
3018 root_segment_arclength[ip][is] =
3019 flat_packed_double_receive_data[dcounter++];
3028 Vector<Vector<int>> left_connected_segment_plus_one(nproc);
3029 Vector<Vector<int>> right_connected_segment_plus_one(nproc);
3030 for (
unsigned ip = 0; ip < nproc; ip++)
3032 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3033 left_connected_segment_plus_one[ip].resize(nsegs_iproc, -1);
3034 right_connected_segment_plus_one[ip].resize(nsegs_iproc, -1);
3039 std::list<std::pair<unsigned, unsigned>> proc_seg_connectivity;
3040 proc_seg_connectivity.clear();
3043 std::map<std::pair<unsigned, unsigned>,
bool> done_segment;
3047 unsigned left_proc = 0;
3048 unsigned right_proc = 0;
3049 unsigned left_seg = 0;
3050 unsigned right_seg = 0;
3051 for (
unsigned ip = 0; ip < nproc; ip++)
3053 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3054 if (nsegs_iproc > 0)
3056 right_proc = left_proc = ip;
3057 right_seg = left_seg = 0;
3064 std::pair<unsigned, unsigned> add_segment =
3065 std::make_pair(left_proc, left_seg);
3066 done_segment[add_segment] =
true;
3067 proc_seg_connectivity.push_back(add_segment);
3071 bool added_segment_to_the_left =
false;
3072 bool added_segment_to_the_right =
false;
3077 std::pair<unsigned, unsigned> left_pair = proc_seg_connectivity.front();
3078 left_proc = left_pair.first;
3079 left_seg = left_pair.second;
3083 const unsigned new_left_proc =
3084 root_left_processor_plus_one[left_proc][left_seg];
3086 if (new_left_proc != 0)
3089 added_segment_to_the_left =
false;
3091 const unsigned left_halo_id =
3092 root_left_halo_element[left_proc][left_seg];
3095 const unsigned left_haloed_id =
3096 root_left_haloed_element[left_proc][left_seg];
3100 const unsigned nsegs_new_left_proc =
3101 root_nsegments_per_processor[new_left_proc - 1];
3103 for (
unsigned ils = 0; ils < nsegs_new_left_proc; ils++)
3105 std::pair<unsigned, unsigned> candidate_seg =
3106 std::make_pair(new_left_proc - 1, ils);
3109 if (!done_segment[candidate_seg])
3113 const unsigned right_proc_of_new_left_proc =
3114 root_right_processor_plus_one[new_left_proc - 1][ils];
3117 const unsigned left_proc_of_new_left_proc =
3118 root_left_processor_plus_one[new_left_proc - 1][ils];
3121 if (right_proc_of_new_left_proc != 0 &&
3122 right_proc_of_new_left_proc - 1 == left_proc)
3127 const unsigned right_halo_id =
3128 root_right_halo_element[new_left_proc - 1][ils];
3129 const unsigned right_haloed_id =
3130 root_right_haloed_element[new_left_proc - 1][ils];
3131 if (left_halo_id == right_haloed_id &&
3132 left_haloed_id == right_halo_id)
3136 left_connected_segment_plus_one[left_proc][left_seg] =
3139 proc_seg_connectivity.push_front(candidate_seg);
3140 added_segment_to_the_left =
true;
3146 if (left_proc_of_new_left_proc != 0 &&
3147 left_proc_of_new_left_proc - 1 == left_proc)
3152 const unsigned inv_left_halo_id =
3153 root_left_halo_element[new_left_proc - 1][ils];
3154 const unsigned inv_left_haloed_id =
3155 root_left_haloed_element[new_left_proc - 1][ils];
3156 if (left_halo_id == inv_left_haloed_id &&
3157 left_haloed_id == inv_left_halo_id)
3161 left_connected_segment_plus_one[left_proc][left_seg] =
3164 proc_seg_connectivity.push_front(candidate_seg);
3168 const unsigned tmp_proc =
3169 root_left_processor_plus_one[new_left_proc - 1][ils];
3170 const unsigned tmp_halo =
3171 root_left_halo_element[new_left_proc - 1][ils];
3172 const unsigned tmp_haloed =
3173 root_left_haloed_element[new_left_proc - 1][ils];
3175 root_left_processor_plus_one[new_left_proc - 1][ils] =
3176 root_right_processor_plus_one[new_left_proc - 1][ils];
3177 root_left_halo_element[new_left_proc - 1][ils] =
3178 root_right_halo_element[new_left_proc - 1][ils];
3179 root_left_haloed_element[new_left_proc - 1][ils] =
3180 root_right_haloed_element[new_left_proc - 1][ils];
3182 root_right_processor_plus_one[new_left_proc - 1][ils] =
3184 root_right_halo_element[new_left_proc - 1][ils] = tmp_halo;
3185 root_right_haloed_element[new_left_proc - 1][ils] =
3190 root_segment_inverted[new_left_proc - 1][ils] = 1;
3192 added_segment_to_the_left =
true;
3200 if (!added_segment_to_the_left)
3202 std::ostringstream error_message;
3204 <<
"The corresponding processor and segment to the left of "
3205 <<
"the current left\nmost segment was not found\n";
3206 throw OomphLibError(error_message.str(),
3207 "TriangleMesh::compute_boundary_segments_"
3208 "connectivity_and_initial_zeta_values()",
3209 OOMPH_EXCEPTION_LOCATION);
3216 added_segment_to_the_left =
false;
3220 std::pair<unsigned, unsigned> right_pair = proc_seg_connectivity.back();
3221 right_proc = right_pair.first;
3222 right_seg = right_pair.second;
3226 const unsigned new_right_proc =
3227 root_right_processor_plus_one[right_proc][right_seg];
3229 if (new_right_proc != 0)
3232 added_segment_to_the_right =
false;
3234 const unsigned right_halo_id =
3235 root_right_halo_element[right_proc][right_seg];
3238 const unsigned right_haloed_id =
3239 root_right_haloed_element[right_proc][right_seg];
3243 const unsigned nsegs_new_right_proc =
3244 root_nsegments_per_processor[new_right_proc - 1];
3246 for (
unsigned irs = 0; irs < nsegs_new_right_proc; irs++)
3248 std::pair<unsigned, unsigned> candidate_seg =
3249 std::make_pair(new_right_proc - 1, irs);
3252 if (!done_segment[candidate_seg])
3256 const unsigned left_proc_of_new_right_proc =
3257 root_left_processor_plus_one[new_right_proc - 1][irs];
3260 const unsigned right_proc_of_new_right_proc =
3261 root_right_processor_plus_one[new_right_proc - 1][irs];
3264 if (left_proc_of_new_right_proc != 0 &&
3265 left_proc_of_new_right_proc - 1 == right_proc)
3270 const unsigned left_halo_id =
3271 root_left_halo_element[new_right_proc - 1][irs];
3272 const unsigned left_haloed_id =
3273 root_left_haloed_element[new_right_proc - 1][irs];
3275 if (right_halo_id == left_haloed_id &&
3276 right_haloed_id == left_halo_id)
3280 right_connected_segment_plus_one[right_proc][right_seg] =
3283 proc_seg_connectivity.push_back(candidate_seg);
3284 added_segment_to_the_right =
true;
3290 if (right_proc_of_new_right_proc != 0 &&
3291 right_proc_of_new_right_proc - 1 == right_proc)
3297 const unsigned inv_right_halo_id =
3298 root_right_halo_element[new_right_proc - 1][irs];
3299 const unsigned inv_right_haloed_id =
3300 root_right_haloed_element[new_right_proc - 1][irs];
3301 if (right_halo_id == inv_right_haloed_id &&
3302 right_haloed_id == inv_right_halo_id)
3306 right_connected_segment_plus_one[right_proc][right_seg] =
3309 proc_seg_connectivity.push_back(candidate_seg);
3312 const unsigned tmp_proc =
3313 root_left_processor_plus_one[new_right_proc - 1][irs];
3314 const unsigned tmp_halo =
3315 root_left_halo_element[new_right_proc - 1][irs];
3316 const unsigned tmp_haloed =
3317 root_left_haloed_element[new_right_proc - 1][irs];
3319 root_left_processor_plus_one[new_right_proc - 1][irs] =
3320 root_right_processor_plus_one[new_right_proc - 1][irs];
3321 root_left_halo_element[new_right_proc - 1][irs] =
3322 root_right_halo_element[new_right_proc - 1][irs];
3323 root_left_haloed_element[new_right_proc - 1][irs] =
3324 root_right_haloed_element[new_right_proc - 1][irs];
3326 root_right_processor_plus_one[new_right_proc - 1][irs] =
3328 root_right_halo_element[new_right_proc - 1][irs] = tmp_halo;
3329 root_right_haloed_element[new_right_proc - 1][irs] =
3334 root_segment_inverted[new_right_proc - 1][irs] = 1;
3336 added_segment_to_the_right =
true;
3344 if (!added_segment_to_the_right)
3346 std::ostringstream error_message;
3348 <<
"The corresponding processor and segment to the right of "
3349 <<
"the current right\nmost segment was not found\n";
3350 throw OomphLibError(error_message.str(),
3351 "TriangleMesh::compute_boundary_segments_"
3352 "connectivity_and_initial_zeta_values()",
3353 OOMPH_EXCEPTION_LOCATION);
3360 added_segment_to_the_right =
false;
3363 }
while (added_segment_to_the_left || added_segment_to_the_right);
3371 const unsigned ntotal_segments = proc_seg_connectivity.size();
3373 unsigned tmp_total_segments = 0;
3374 for (
unsigned ip = 0; ip < nproc; ip++)
3376 tmp_total_segments += root_nsegments_per_processor[ip];
3381 if (ntotal_segments != tmp_total_segments)
3383 std::ostringstream error_message;
3384 error_message <<
"The number of sorted segments (" << ntotal_segments
3386 <<
"boundary (" << b
3387 <<
")\nis different from the total number of "
3388 <<
"segments (" << tmp_total_segments
3389 <<
") in all\nprocessors.\n\n";
3390 throw OomphLibError(error_message.str(),
3391 OOMPH_CURRENT_FUNCTION,
3392 OOMPH_EXCEPTION_LOCATION);
3401 for (
unsigned ip = 0; ip < nproc; ip++)
3403 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3404 root_initial_segment_arclength[ip].resize(nsegs_iproc);
3405 root_nvertices_before_segment[ip].resize(nsegs_iproc);
3408 Vector<double> aux_initial_segment_arclength(ntotal_segments);
3409 Vector<unsigned> aux_nvertices_before_segment(ntotal_segments);
3412 for (std::list<std::pair<unsigned, unsigned>>::iterator it_list =
3413 proc_seg_connectivity.begin();
3414 it_list != proc_seg_connectivity.end();
3417 const unsigned iproc =
static_cast<unsigned>((*it_list).first);
3418 const unsigned iseg =
static_cast<unsigned>((*it_list).second);
3419 const double iseg_arclength = root_segment_arclength[iproc][iseg];
3420 const unsigned iseg_nvertices = root_nvertices_per_segment[iproc][iseg];
3422 aux_initial_segment_arclength[ucounter] = root_accumulated_arclength;
3423 aux_nvertices_before_segment[ucounter] =
3424 root_accumulated_vertices_before_segment;
3427 root_initial_segment_arclength[iproc][iseg] =
3428 root_accumulated_arclength;
3430 root_nvertices_before_segment[iproc][iseg] =
3431 root_accumulated_vertices_before_segment;
3434 root_accumulated_arclength += iseg_arclength;
3436 root_accumulated_vertices_before_segment += iseg_nvertices - 1;
3445 root_accumulated_vertices_before_segment++;
3448 proc_with_initial_seg = proc_seg_connectivity.front().first;
3449 proc_with_final_seg = proc_seg_connectivity.back().first;
3452 initial_segment = proc_seg_connectivity.front().second;
3453 final_segment = proc_seg_connectivity.back().second;
3458 unsigned root_ntotal_segments = 0;
3459 for (
unsigned ip = 0; ip < nproc; ip++)
3461 root_ntotal_segments += root_nsegments_per_processor[ip];
3468 const unsigned rspu = 2;
3469 flat_packed_unsigned_send_data.clear();
3470 flat_packed_unsigned_send_data.resize(root_ntotal_segments * rspu);
3471 unsigned ucounter = 0;
3473 for (
unsigned ip = 0; ip < nproc; ip++)
3475 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3476 for (
unsigned is = 0; is < nsegs_iproc; is++)
3478 flat_packed_unsigned_send_data[ucounter++] =
3479 root_nvertices_before_segment[ip][is];
3480 flat_packed_unsigned_send_data[ucounter++] =
3481 root_segment_inverted[ip][is];
3486 Vector<int> root_nudata_to_send(nproc, 0);
3487 for (
unsigned ip = 0; ip < nproc; ip++)
3490 root_nudata_to_send[ip] = root_nsegments_per_processor[ip] * rspu;
3494 Vector<int> root_uoffsets_send(nproc, 0);
3495 root_uoffsets_send[0] = 0;
3496 for (
unsigned ip = 1; ip < nproc; ip++)
3499 root_uoffsets_send[ip] =
3500 root_uoffsets_send[ip - 1] + root_nudata_to_send[ip - 1];
3504 unsigned nutotal_data_receive = nsegments * rspu;
3506 if (my_rank != root_processor)
3509 if (flat_packed_unsigned_send_data.size() == 0)
3511 flat_packed_unsigned_send_data.resize(1);
3516 flat_packed_unsigned_receive_data.clear();
3517 flat_packed_unsigned_receive_data.resize(nutotal_data_receive);
3519 if (flat_packed_unsigned_receive_data.size() == 0)
3521 flat_packed_unsigned_receive_data.resize(1);
3524 MPI_Scatterv(&flat_packed_unsigned_send_data[0],
3525 &root_nudata_to_send[0],
3526 &root_uoffsets_send[0],
3528 &flat_packed_unsigned_receive_data[0],
3529 nutotal_data_receive,
3532 comm_pt->mpi_comm());
3537 const unsigned rspd = 1;
3538 flat_packed_double_send_data.clear();
3539 flat_packed_double_send_data.resize(root_ntotal_segments * rspd);
3540 unsigned dcounter = 0;
3542 for (
unsigned ip = 0; ip < nproc; ip++)
3544 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3545 for (
unsigned is = 0; is < nsegs_iproc; is++)
3547 flat_packed_double_send_data[dcounter++] =
3548 root_initial_segment_arclength[ip][is];
3553 Vector<int> root_nddata_to_send(nproc, 0);
3554 for (
unsigned ip = 0; ip < nproc; ip++)
3557 root_nddata_to_send[ip] = root_nsegments_per_processor[ip] * rspd;
3561 Vector<int> root_doffsets_send(nproc, 0);
3562 root_doffsets_send[0] = 0;
3563 for (
unsigned ip = 1; ip < nproc; ip++)
3566 root_doffsets_send[ip] =
3567 root_doffsets_send[ip - 1] + root_nddata_to_send[ip - 1];
3571 unsigned ndtotal_data_receive = nsegments * rspd;
3573 if (my_rank != root_processor)
3576 if (flat_packed_double_send_data.size() == 0)
3578 flat_packed_double_send_data.resize(1);
3583 flat_packed_double_receive_data.clear();
3584 flat_packed_double_receive_data.resize(ndtotal_data_receive);
3586 if (flat_packed_double_receive_data.size() == 0)
3588 flat_packed_double_receive_data.resize(1);
3591 MPI_Scatterv(&flat_packed_double_send_data[0],
3592 &root_nddata_to_send[0],
3593 &root_doffsets_send[0],
3595 &flat_packed_double_receive_data[0],
3596 ndtotal_data_receive,
3599 comm_pt->mpi_comm());
3608 for (
unsigned is = 0; is < nsegments; is++)
3611 nvertices_before_segment[is] =
3612 flat_packed_unsigned_receive_data[ucounter++];
3614 segment_inverted[is] = flat_packed_unsigned_receive_data[ucounter++];
3616 initial_segment_arclength[is] =
3617 flat_packed_double_receive_data[dcounter++];
3623 const unsigned numore_info = 5;
3624 Vector<unsigned> flat_package_unsigned_more_info(numore_info);
3626 flat_package_unsigned_more_info[0] =
3627 root_accumulated_vertices_before_segment;
3628 flat_package_unsigned_more_info[1] = proc_with_initial_seg;
3629 flat_package_unsigned_more_info[2] = proc_with_final_seg;
3630 flat_package_unsigned_more_info[3] = initial_segment;
3631 flat_package_unsigned_more_info[4] = final_segment;
3634 MPI_Bcast(&flat_package_unsigned_more_info[0],
3638 comm_pt->mpi_comm());
3641 root_accumulated_vertices_before_segment =
3642 flat_package_unsigned_more_info[0];
3643 proc_with_initial_seg = flat_package_unsigned_more_info[1];
3644 proc_with_final_seg = flat_package_unsigned_more_info[2];
3645 initial_segment = flat_package_unsigned_more_info[3];
3646 final_segment = flat_package_unsigned_more_info[4];
3649 MPI_Bcast(&root_accumulated_arclength,
3653 comm_pt->mpi_comm());
3662 Boundary_initial_coordinate[b].clear();
3663 Boundary_final_coordinate[b].clear();
3665 Boundary_initial_zeta_coordinate[b].clear();
3666 Boundary_final_zeta_coordinate[b].clear();
3669 Boundary_segment_inverted[b].clear();
3670 Boundary_segment_initial_coordinate[b].clear();
3671 Boundary_segment_final_coordinate[b].clear();
3673 Boundary_segment_initial_zeta[b].clear();
3674 Boundary_segment_final_zeta[b].clear();
3676 Boundary_segment_initial_arclength[b].clear();
3677 Boundary_segment_final_arclength[b].clear();
3681 for (
unsigned is = 0; is < nsegments; is++)
3685 Vector<double> first_seg_coord(2);
3686 Vector<double> last_seg_coord(2);
3693 FiniteElement* first_seg_ele_pt =
3694 segment_sorted_nonhalo_ele_pt[is].front();
3699 if (first_seg_ele_pt->is_halo())
3701 std::ostringstream error_message;
3702 error_message <<
"The first face element in the (" << is
3703 <<
")-th segment is halo\n";
3704 throw OomphLibError(error_message.str(),
3705 "TriangleMesh::compute_boundary_segments_"
3706 "connectivity_and_initial_zeta_values()",
3707 OOMPH_EXCEPTION_LOCATION);
3712 const unsigned nnod = first_seg_ele_pt->nnode();
3715 Node* first_seg_node_pt = first_seg_ele_pt->node_pt(0);
3716 if (is_inverted[first_seg_ele_pt])
3718 first_seg_node_pt = first_seg_ele_pt->node_pt(nnod - 1);
3722 FiniteElement* last_seg_ele_pt = segment_sorted_nonhalo_ele_pt[is].back();
3727 if (last_seg_ele_pt->is_halo())
3729 std::ostringstream error_message;
3730 error_message <<
"The last face element in the (" << is
3731 <<
")-th segment is halo\n";
3732 throw OomphLibError(error_message.str(),
3733 "TriangleMesh::compute_boundary_segments_"
3734 "connectivity_and_initial_zeta_values()",
3735 OOMPH_EXCEPTION_LOCATION);
3740 Node* last_seg_node_pt = last_seg_ele_pt->node_pt(nnod - 1);
3741 if (is_inverted[last_seg_ele_pt])
3743 last_seg_node_pt = last_seg_ele_pt->node_pt(0);
3747 for (
unsigned i = 0; i < 2; i++)
3749 first_seg_coord[i] = first_seg_node_pt->x(i);
3750 last_seg_coord[i] = last_seg_node_pt->x(i);
3755 Boundary_segment_inverted[b].push_back(segment_inverted[is]);
3759 if (!segment_inverted[is])
3763 Boundary_segment_initial_coordinate[b].push_back(first_seg_coord);
3764 Boundary_segment_final_coordinate[b].push_back(last_seg_coord);
3771 Boundary_segment_initial_coordinate[b].push_back(last_seg_coord);
3772 Boundary_segment_final_coordinate[b].push_back(first_seg_coord);
3779 if (boundary_geom_object_pt(b) != 0)
3784 if (segment_inverted[is])
3786 Boundary_segment_initial_zeta[b].push_back(final_zeta_segment[is]);
3787 Boundary_segment_final_zeta[b].push_back(initial_zeta_segment[is]);
3791 Boundary_segment_initial_zeta[b].push_back(initial_zeta_segment[is]);
3792 Boundary_segment_final_zeta[b].push_back(final_zeta_segment[is]);
3799 Boundary_segment_initial_arclength[b].push_back(
3800 initial_segment_arclength[is]);
3802 Boundary_segment_final_arclength[b].push_back(
3803 initial_segment_arclength[is] + segment_arclength[is]);
3811 if (segment_all_nodes_pt.size() != nsegments)
3813 std::ostringstream error_message;
3814 error_message <<
"The number of segments (" << nsegments
3815 <<
") and the number of "
3816 <<
"set of nodes (" << segment_all_nodes_pt.size()
3817 <<
") representing\n"
3818 <<
"the\nsegments is different!!!\n\n";
3819 throw OomphLibError(error_message.str(),
3820 "TriangleMesh::compute_boundary_segments_"
3821 "connectivity_and_initial_zeta_values()",
3822 OOMPH_EXCEPTION_LOCATION);
3836 Vector<double> first_coordinate(2);
3837 Vector<double> last_coordinate(2);
3841 Vector<double> first_node_zeta_coordinate(1, 0.0);
3842 Vector<double> last_node_zeta_coordinate(1, 0.0);
3846 const unsigned ndtotal_data = 3;
3847 Vector<double> flat_packed_double_data_initial_seg(ndtotal_data);
3851 if (my_rank == proc_with_initial_seg)
3854 FiniteElement* first_ele_pt = 0;
3856 Node* first_node_pt = 0;
3858 if (!segment_inverted[initial_segment])
3862 first_ele_pt = segment_sorted_ele_pt[initial_segment].front();
3865 const unsigned nnod = first_ele_pt->nnode();
3868 first_node_pt = first_ele_pt->node_pt(0);
3869 if (is_inverted[first_ele_pt])
3871 first_node_pt = first_ele_pt->node_pt(nnod - 1);
3878 first_ele_pt = segment_sorted_ele_pt[initial_segment].back();
3881 const unsigned nnod = first_ele_pt->nnode();
3884 first_node_pt = first_ele_pt->node_pt(nnod - 1);
3885 if (is_inverted[first_ele_pt])
3887 first_node_pt = first_ele_pt->node_pt(0);
3892 for (
unsigned i = 0; i < 2; i++)
3894 flat_packed_double_data_initial_seg[i] = first_node_pt->x(i);
3898 Vector<double> tmp_zeta(1);
3899 first_node_pt->get_coordinates_on_boundary(b, tmp_zeta);
3903 if (this->boundary_geom_object_pt(b) != 0)
3911 if (tmp_zeta[0] >= 1.0e-14)
3918 flat_packed_double_data_initial_seg[2] = tmp_zeta[0];
3924 MPI_Bcast(&flat_packed_double_data_initial_seg[0],
3927 proc_with_initial_seg,
3928 comm_pt->mpi_comm());
3932 for (
unsigned i = 0; i < 2; i++)
3934 first_coordinate[i] = flat_packed_double_data_initial_seg[i];
3936 first_node_zeta_coordinate[0] = flat_packed_double_data_initial_seg[2];
3941 Vector<double> flat_packed_double_data_final_seg(ndtotal_data);
3945 if (my_rank == proc_with_final_seg)
3948 FiniteElement* last_ele_pt = 0;
3951 Node* last_node_pt = 0;
3954 if (!segment_inverted[final_segment])
3958 last_ele_pt = segment_sorted_ele_pt[final_segment].back();
3961 const unsigned nnod = last_ele_pt->nnode();
3964 last_node_pt = last_ele_pt->node_pt(nnod - 1);
3965 if (is_inverted[last_ele_pt])
3967 last_node_pt = last_ele_pt->node_pt(0);
3974 last_ele_pt = segment_sorted_ele_pt[final_segment].front();
3977 const unsigned nnod = last_ele_pt->nnode();
3980 last_node_pt = last_ele_pt->node_pt(0);
3981 if (is_inverted[last_ele_pt])
3983 last_node_pt = last_ele_pt->node_pt(nnod - 1);
3988 for (
unsigned i = 0; i < 2; i++)
3990 flat_packed_double_data_final_seg[i] = last_node_pt->x(i);
3994 Vector<double> tmp_zeta(1);
3995 last_node_pt->get_coordinates_on_boundary(b, tmp_zeta);
3999 if (this->boundary_geom_object_pt(b) != 0)
4008 if (std::fabs(tmp_zeta[0] - root_accumulated_arclength) >= 1.0e-14)
4010 tmp_zeta[0] = root_accumulated_arclength;
4015 flat_packed_double_data_final_seg[2] = tmp_zeta[0];
4021 MPI_Bcast(&flat_packed_double_data_final_seg[0],
4024 proc_with_final_seg,
4025 comm_pt->mpi_comm());
4029 for (
unsigned i = 0; i < 2; i++)
4031 last_coordinate[i] = flat_packed_double_data_final_seg[i];
4033 last_node_zeta_coordinate[0] = flat_packed_double_data_final_seg[2];
4037 Boundary_initial_coordinate[b] = first_coordinate;
4038 Boundary_final_coordinate[b] = last_coordinate;
4040 Boundary_initial_zeta_coordinate[b] = first_node_zeta_coordinate;
4041 Boundary_final_zeta_coordinate[b] = last_node_zeta_coordinate;
4045 if (is_internal_boundary)
4056 re_assign_initial_zeta_values_for_internal_boundary(
4057 b, segment_sorted_nonhalo_ele_pt, is_inverted);
4068 identify_boundary_segments_and_assign_initial_zeta_values(b,
this);
4072 for (
unsigned i = 0; i < n_all_face_ele; i++)
4074 delete all_face_ele_pt[i];
4075 all_face_ele_pt[i] = 0;
4087 template<
class ELEMENT>
4091 Vector<std::list<FiniteElement*>>& old_segment_sorted_ele_pt,
4092 std::map<FiniteElement*, bool>& old_is_inverted)
4099 Vector<FiniteElement*> face_el_pt;
4107 unsigned n_repeated_ele = 0;
4109 const unsigned n_regions = this->nregion();
4112 Vector<std::pair<Node*, Node*>> done_nodes_pt;
4118 for (
unsigned rr = 0; rr < n_regions; rr++)
4120 const unsigned region_id =
4121 static_cast<unsigned>(this->Region_attribute[rr]);
4124 const unsigned nel_in_region =
4125 this->nboundary_element_in_region(b, region_id);
4127 unsigned nel_repetead_in_region = 0;
4131 if (nel_in_region > 0)
4133 bool repeated =
false;
4136 for (
unsigned e = 0; e < nel_in_region; e++)
4140 FiniteElement* bulk_elem_pt =
4141 this->boundary_element_in_region_pt(b, region_id, e);
4144 if (bulk_elem_pt->is_halo())
4152 this->face_index_at_boundary_in_region(b, region_id, e);
4157 FiniteElement* tmp_ele_pt =
4158 new DummyFaceElement<ELEMENT>(bulk_elem_pt, face_index);
4160 const unsigned n_nodes = tmp_ele_pt->nnode();
4162 std::pair<Node*, Node*> tmp_pair = std::make_pair(
4163 tmp_ele_pt->node_pt(0), tmp_ele_pt->node_pt(n_nodes - 1));
4165 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
4166 tmp_ele_pt->node_pt(n_nodes - 1), tmp_ele_pt->node_pt(0));
4169 const unsigned repeated_nodes_size = done_nodes_pt.size();
4170 for (
unsigned l = 0; l < repeated_nodes_size; l++)
4172 if (tmp_pair == done_nodes_pt[l] ||
4173 tmp_pair_inverse == done_nodes_pt[l])
4175 nel_repetead_in_region++;
4185 done_nodes_pt.push_back(tmp_pair);
4187 face_el_pt.push_back(tmp_ele_pt);
4201 nele += nel_in_region;
4203 n_repeated_ele += nel_repetead_in_region;
4212 nele = this->nboundary_element(b);
4218 bool repeated =
false;
4221 for (
unsigned e = 0; e < nele; e++)
4225 FiniteElement* bulk_elem_pt = this->boundary_element_pt(b, e);
4228 if (bulk_elem_pt->is_halo())
4235 int face_index = this->face_index_at_boundary(b, e);
4240 FiniteElement* tmp_ele_pt =
4241 new DummyFaceElement<ELEMENT>(bulk_elem_pt, face_index);
4243 const unsigned n_nodes = tmp_ele_pt->nnode();
4245 std::pair<Node*, Node*> tmp_pair = std::make_pair(
4246 tmp_ele_pt->node_pt(0), tmp_ele_pt->node_pt(n_nodes - 1));
4248 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
4249 tmp_ele_pt->node_pt(n_nodes - 1), tmp_ele_pt->node_pt(0));
4252 const unsigned repeated_nodes_size = done_nodes_pt.size();
4253 for (
unsigned l = 0; l < repeated_nodes_size; l++)
4255 if (tmp_pair == done_nodes_pt[l] ||
4256 tmp_pair_inverse == done_nodes_pt[l])
4270 done_nodes_pt.push_back(tmp_pair);
4272 face_el_pt.push_back(tmp_ele_pt);
4290 nele -= n_repeated_ele;
4293 if (nele != face_el_pt.size())
4295 std::ostringstream error_message;
4297 <<
"The independet counting of face elements (" << nele <<
") for "
4298 <<
"boundary (" << b <<
") is different\n"
4299 <<
"from the real number of face elements in the container ("
4300 << face_el_pt.size() <<
")\n";
4302 throw OomphLibError(
4303 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
4312 const unsigned nnon_halo_face_elements = face_el_pt.size();
4316 Vector<std::list<FiniteElement*>> segment_sorted_ele_pt;
4319 unsigned nsorted_face_elements = 0;
4322 std::map<FiniteElement*, bool> done_el;
4325 std::map<FiniteElement*, bool> is_inverted;
4328 while (nsorted_face_elements < nnon_halo_face_elements)
4332 std::list<FiniteElement*> sorted_el_pt;
4336 bool found_initial_face_element =
false;
4339 FiniteElement* ele_face_pt = 0;
4342 for (iface = 0; iface < nele; iface++)
4344 ele_face_pt = face_el_pt[iface];
4346 if (!done_el[ele_face_pt])
4350 found_initial_face_element =
true;
4353 nsorted_face_elements++;
4358 sorted_el_pt.push_back(ele_face_pt);
4360 done_el[ele_face_pt] =
true;
4366 if (!found_initial_face_element)
4368 std::ostringstream error_message;
4370 <<
"Could not find an initial face element for the current segment\n";
4371 throw OomphLibError(
4372 error_message.str(),
4373 "TriangleMesh::re_assign_initial_zeta_values_for_internal_boundary()",
4374 OOMPH_EXCEPTION_LOCATION);
4379 const unsigned nnod = ele_face_pt->nnode();
4383 Node* left_node_pt = ele_face_pt->node_pt(0);
4384 Node* right_node_pt = ele_face_pt->node_pt(nnod - 1);
4388 bool face_element_added =
false;
4397 for (
unsigned iiface = iface; iiface < nele; iiface++)
4400 face_element_added =
false;
4403 ele_face_pt = face_el_pt[iiface];
4407 if (!(done_el[ele_face_pt]))
4410 Node* local_left_node_pt = ele_face_pt->node_pt(0);
4411 Node* local_right_node_pt = ele_face_pt->node_pt(nnod - 1);
4414 if (left_node_pt == local_right_node_pt)
4416 left_node_pt = local_left_node_pt;
4417 sorted_el_pt.push_front(ele_face_pt);
4418 is_inverted[ele_face_pt] =
false;
4419 face_element_added =
true;
4422 else if (left_node_pt == local_left_node_pt)
4424 left_node_pt = local_right_node_pt;
4425 sorted_el_pt.push_front(ele_face_pt);
4426 is_inverted[ele_face_pt] =
true;
4427 face_element_added =
true;
4430 else if (right_node_pt == local_left_node_pt)
4432 right_node_pt = local_right_node_pt;
4433 sorted_el_pt.push_back(ele_face_pt);
4434 is_inverted[ele_face_pt] =
false;
4435 face_element_added =
true;
4438 else if (right_node_pt == local_right_node_pt)
4440 right_node_pt = local_left_node_pt;
4441 sorted_el_pt.push_back(ele_face_pt);
4442 is_inverted[ele_face_pt] =
true;
4443 face_element_added =
true;
4446 if (face_element_added)
4448 done_el[ele_face_pt] =
true;
4449 nsorted_face_elements++;
4457 }
while (face_element_added &&
4458 (nsorted_face_elements < nnon_halo_face_elements));
4461 segment_sorted_ele_pt.push_back(sorted_el_pt);
4472 const unsigned nsegments = segment_sorted_ele_pt.size();
4475 if (nnon_halo_face_elements > 0 && nsegments == 0)
4477 std::ostringstream error_message;
4479 <<
"The number of segments is zero, but the number of nonhalo\n"
4480 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
4481 throw OomphLibError(
4482 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
4489 Vector<std::set<Node*>> segment_all_nodes_pt(nsegments);
4493 Vector<Vector<Node*>> sorted_segment_all_nodes_pt(nsegments);
4498 Vector<Vector<double>> sorted_segment_node_arclength(nsegments);
4501 Vector<double> segment_arclength(nsegments);
4504 Vector<unsigned> nvertices_per_segment(nsegments);
4507 Vector<double> initial_zeta_segment(nsegments);
4510 Vector<double> final_zeta_segment(nsegments);
4514 for (
unsigned is = 0; is < nsegments; is++)
4517 if (segment_sorted_ele_pt[is].size() == 0)
4519 std::ostringstream error_message;
4520 error_message <<
"The (" << is <<
")-th segment has no elements\n";
4521 throw OomphLibError(
4522 error_message.str(),
4523 "TriangleMesh::re_assign_initial_zeta_values_for_internal_boundary()",
4524 OOMPH_EXCEPTION_LOCATION);
4529 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
4532 const unsigned nnod = first_ele_pt->nnode();
4535 Node* first_node_pt = first_ele_pt->node_pt(0);
4536 if (is_inverted[first_ele_pt])
4538 first_node_pt = first_ele_pt->node_pt(nnod - 1);
4542 double x_left = first_node_pt->x(0);
4543 double y_left = first_node_pt->x(1);
4547 Vector<double> zeta(1, 0.0);
4552 if (this->boundary_geom_object_pt(b) != 0)
4554 first_node_pt->get_coordinates_on_boundary(b, zeta);
4555 initial_zeta_segment[is] = zeta[0];
4558 FiniteElement* last_ele_pt = segment_sorted_ele_pt[is].back();
4561 Node* last_node_pt = last_ele_pt->node_pt(nnod - 1);
4562 if (is_inverted[last_ele_pt])
4564 last_node_pt = last_ele_pt->node_pt(0);
4567 last_node_pt->get_coordinates_on_boundary(b, zeta);
4568 final_zeta_segment[is] = zeta[0];
4573 std::set<Node*> local_nodes_pt;
4574 local_nodes_pt.insert(first_node_pt);
4577 Vector<double> sorted_node_arclength;
4578 sorted_node_arclength.push_back(0.0);
4582 Vector<Node*> sorted_nodes_pt;
4583 sorted_nodes_pt.push_back(first_node_pt);
4586 for (std::list<FiniteElement*>::iterator it =
4587 segment_sorted_ele_pt[is].begin();
4588 it != segment_sorted_ele_pt[is].end();
4592 FiniteElement* el_pt = *it;
4597 if (is_inverted[el_pt])
4604 for (
unsigned j = 1; j < nnod; j++)
4606 Node* nod_pt = el_pt->node_pt(k_nod);
4610 double x_right = nod_pt->x(0);
4611 double y_right = nod_pt->x(1);
4614 zeta[0] += sqrt((x_right - x_left) * (x_right - x_left) +
4615 (y_right - y_left) * (y_right - y_left));
4620 if (this->boundary_geom_object_pt(b) == 0)
4632 local_nodes_pt.insert(nod_pt);
4635 sorted_node_arclength.push_back(zeta[0]);
4638 sorted_nodes_pt.push_back(nod_pt);
4647 segment_arclength[is] = zeta[0];
4652 nvertices_per_segment[is] = local_nodes_pt.size();
4655 segment_all_nodes_pt[is] = local_nodes_pt;
4658 sorted_segment_node_arclength[is] = sorted_node_arclength;
4661 sorted_segment_all_nodes_pt[is] = sorted_nodes_pt;
4676 const unsigned old_nsegments = old_segment_sorted_ele_pt.size();
4680 Vector<unsigned> old_boundary_segment_inverted(old_nsegments);
4682 Vector<Vector<double>> old_boundary_segment_initial_coordinate(
4684 Vector<Vector<double>> old_boundary_segment_final_coordinate(old_nsegments);
4686 Vector<double> old_boundary_segment_initial_zeta(old_nsegments);
4687 Vector<double> old_boundary_segment_final_zeta(old_nsegments);
4689 Vector<double> old_boundary_segment_initial_arclength(old_nsegments);
4690 Vector<double> old_boundary_segment_final_arclength(old_nsegments);
4693 for (
unsigned old_is = 0; old_is < old_nsegments; old_is++)
4695 old_boundary_segment_inverted[old_is] =
4696 boundary_segment_inverted(b)[old_is];
4698 old_boundary_segment_initial_coordinate[old_is].resize(2);
4699 old_boundary_segment_final_coordinate[old_is].resize(2);
4700 for (
unsigned i = 0; i < 2; i++)
4702 old_boundary_segment_initial_coordinate[old_is][i] =
4703 boundary_segment_initial_coordinate(b)[old_is][i];
4705 old_boundary_segment_final_coordinate[old_is][i] =
4706 boundary_segment_final_coordinate(b)[old_is][i];
4710 if (this->boundary_geom_object_pt(b) != 0)
4712 old_boundary_segment_initial_zeta[old_is] =
4713 boundary_segment_initial_zeta(b)[old_is];
4715 old_boundary_segment_final_zeta[old_is] =
4716 boundary_segment_final_zeta(b)[old_is];
4721 old_boundary_segment_initial_arclength[old_is] =
4722 boundary_segment_initial_arclength(b)[old_is];
4724 old_boundary_segment_final_arclength[old_is] =
4725 boundary_segment_final_arclength(b)[old_is];
4733 Boundary_segment_inverted[b].clear();
4734 Boundary_segment_initial_coordinate[b].clear();
4735 Boundary_segment_final_coordinate[b].clear();
4737 Boundary_segment_initial_zeta[b].clear();
4738 Boundary_segment_final_zeta[b].clear();
4740 Boundary_segment_initial_arclength[b].clear();
4741 Boundary_segment_final_arclength[b].clear();
4744 Boundary_segment_inverted[b].resize(nsegments);
4745 Boundary_segment_initial_coordinate[b].resize(nsegments);
4746 Boundary_segment_final_coordinate[b].resize(nsegments);
4749 if (this->boundary_geom_object_pt(b) != 0)
4751 Boundary_segment_initial_zeta[b].resize(nsegments);
4752 Boundary_segment_final_zeta[b].resize(nsegments);
4756 Boundary_segment_initial_arclength[b].resize(nsegments);
4757 Boundary_segment_final_arclength[b].resize(nsegments);
4761 std::map<unsigned, bool> done_segment;
4764 unsigned re_assigned_segments = 0;
4767 for (
unsigned old_is = 0; old_is < old_nsegments; old_is++)
4770 const double old_initial_arclength =
4771 old_boundary_segment_initial_arclength[old_is];
4772 const double old_final_arclength =
4773 old_boundary_segment_final_arclength[old_is];
4775 const unsigned old_inverted_segment =
4776 old_boundary_segment_inverted[old_is];
4780 bool old_increasing_order =
false;
4781 if (old_initial_arclength < old_final_arclength)
4783 old_increasing_order =
true;
4788 FiniteElement* first_old_seg_ele_pt =
4789 old_segment_sorted_ele_pt[old_is].front();
4792 const unsigned nnod = first_old_seg_ele_pt->nnode();
4795 Node* first_old_seg_node_pt = first_old_seg_ele_pt->node_pt(0);
4796 if (old_is_inverted[first_old_seg_ele_pt])
4798 first_old_seg_node_pt = first_old_seg_ele_pt->node_pt(nnod - 1);
4802 FiniteElement* last_old_seg_ele_pt =
4803 old_segment_sorted_ele_pt[old_is].back();
4806 Node* last_old_seg_node_pt = last_old_seg_ele_pt->node_pt(nnod - 1);
4807 if (old_is_inverted[last_old_seg_ele_pt])
4809 last_old_seg_node_pt = last_old_seg_ele_pt->node_pt(0);
4813 if (old_inverted_segment)
4815 Node* temp_node_pt = first_old_seg_node_pt;
4816 first_old_seg_node_pt = last_old_seg_node_pt;
4817 last_old_seg_node_pt = temp_node_pt;
4823 for (
unsigned is = 0; is < nsegments; is++)
4825 if (!done_segment[is])
4829 bool found_first_old_seg_node =
false;
4830 bool found_last_old_seg_node =
false;
4831 bool same_order =
false;
4834 FiniteElement* first_seg_ele_pt = segment_sorted_ele_pt[is].front();
4835 Node* first_seg_node_pt = first_seg_ele_pt->node_pt(0);
4836 if (is_inverted[first_seg_ele_pt])
4838 first_seg_node_pt = first_seg_ele_pt->node_pt(nnod - 1);
4842 const double segment_first_node_zeta =
4843 sorted_segment_node_arclength[is][0];
4846 Vector<double> first_node_coord(2);
4847 for (
unsigned i = 0; i < 2; i++)
4849 first_node_coord[i] = first_seg_node_pt->x(i);
4853 FiniteElement* last_seg_ele_pt = segment_sorted_ele_pt[is].back();
4854 Node* last_seg_node_pt = last_seg_ele_pt->node_pt(nnod - 1);
4855 if (is_inverted[last_seg_ele_pt])
4857 last_seg_node_pt = last_seg_ele_pt->node_pt(0);
4861 const double segment_final_node_zeta = segment_arclength[is];
4864 Vector<double> last_node_coord(2);
4865 for (
unsigned i = 0; i < 2; i++)
4867 last_node_coord[i] = last_seg_node_pt->x(i);
4871 Vector<Node*> segment_node_pt = sorted_segment_all_nodes_pt[is];
4873 const unsigned nsegment_node = segment_node_pt.size();
4874 for (
unsigned in = 0; in < nsegment_node; in++)
4876 Node* current_node_pt = segment_node_pt[in];
4877 if (!found_first_old_seg_node &&
4878 first_old_seg_node_pt == current_node_pt)
4882 const double current_node_zeta =
4883 sorted_segment_node_arclength[is][in];
4887 if (!found_last_old_seg_node)
4890 Boundary_segment_initial_coordinate[b][is] = first_node_coord;
4893 if (this->boundary_geom_object_pt(b) != 0)
4900 Boundary_segment_initial_zeta[b][is] =
4901 initial_zeta_segment[is];
4907 const double distance =
4908 std::fabs(current_node_zeta - segment_first_node_zeta);
4910 double new_initial_arclength = old_initial_arclength;
4913 if (old_increasing_order)
4916 new_initial_arclength -= distance;
4921 new_initial_arclength += distance;
4925 Boundary_segment_initial_arclength[b][is] =
4926 new_initial_arclength;
4933 Boundary_segment_initial_coordinate[b][is] = last_node_coord;
4936 if (this->boundary_geom_object_pt(b) != 0)
4944 Boundary_segment_initial_zeta[b][is] = final_zeta_segment[is];
4950 const double distance =
4951 std::fabs(current_node_zeta - segment_final_node_zeta);
4953 double new_initial_arclength = old_initial_arclength;
4956 if (old_increasing_order)
4959 new_initial_arclength -= distance;
4964 new_initial_arclength += distance;
4968 Boundary_segment_initial_arclength[b][is] =
4969 new_initial_arclength;
4975 found_first_old_seg_node =
true;
4982 if (found_first_old_seg_node && !found_last_old_seg_node)
4987 if (!found_last_old_seg_node &&
4988 last_old_seg_node_pt == current_node_pt)
4992 const double current_node_zeta =
4993 sorted_segment_node_arclength[is][in];
4997 if (found_first_old_seg_node)
5000 Boundary_segment_final_coordinate[b][is] = last_node_coord;
5003 if (this->boundary_geom_object_pt(b) != 0)
5010 Boundary_segment_final_zeta[b][is] = final_zeta_segment[is];
5016 const double distance =
5017 std::fabs(current_node_zeta - segment_final_node_zeta);
5019 double new_final_arclength = old_final_arclength;
5022 if (old_increasing_order)
5025 new_final_arclength += distance;
5030 new_final_arclength -= distance;
5034 Boundary_segment_final_arclength[b][is] = new_final_arclength;
5041 Boundary_segment_final_coordinate[b][is] = first_node_coord;
5044 if (this->boundary_geom_object_pt(b) != 0)
5052 Boundary_segment_final_zeta[b][is] = initial_zeta_segment[is];
5058 const double distance =
5059 std::fabs(current_node_zeta - segment_first_node_zeta);
5061 double new_final_arclength = old_final_arclength;
5064 if (old_increasing_order)
5067 new_final_arclength += distance;
5072 new_final_arclength -= distance;
5076 Boundary_segment_final_arclength[b][is] = new_final_arclength;
5082 found_last_old_seg_node =
true;
5089 if (!found_first_old_seg_node && found_last_old_seg_node)
5094 if (found_first_old_seg_node && found_last_old_seg_node)
5100 Boundary_segment_inverted[b][is] = old_inverted_segment;
5104 Boundary_segment_inverted[b][is] = !old_inverted_segment;
5108 done_segment[is] =
true;
5111 re_assigned_segments++;
5120 if ((found_first_old_seg_node && !found_last_old_seg_node) ||
5121 (!found_first_old_seg_node && found_last_old_seg_node))
5123 std::stringstream error_message;
5125 <<
"Working with boundary (" << b <<
").\nOnly the first node or "
5126 <<
"the last node of the old segment (" << old_is <<
") was\n"
5127 <<
"found. Both, first and last node should have been found in "
5128 <<
"the same segment!!!.\n"
5129 <<
"Found first seg node:" << found_first_old_seg_node <<
"\n"
5130 <<
"Found last seg node:" << found_last_old_seg_node <<
"\n\n";
5131 throw OomphLibError(error_message.str(),
5132 "TriangleMesh::re_assign_initial_zeta_values_"
5133 "for_internal_boundary()",
5134 OOMPH_EXCEPTION_LOCATION);
5147 for (
unsigned is = 0; is < nsegments; is++)
5150 if (!done_segment[is])
5153 FiniteElement* first_seg_ele_pt = segment_sorted_ele_pt[is].front();
5155 const unsigned nnod = first_seg_ele_pt->nnode();
5157 Node* first_seg_node_pt = first_seg_ele_pt->node_pt(0);
5158 if (is_inverted[first_seg_ele_pt])
5160 first_seg_node_pt = first_seg_ele_pt->node_pt(nnod - 1);
5164 const double segment_first_node_zeta =
5165 sorted_segment_node_arclength[is][0];
5168 Vector<double> first_node_coord(2);
5169 for (
unsigned i = 0; i < 2; i++)
5171 first_node_coord[i] = first_seg_node_pt->x(i);
5175 FiniteElement* last_seg_ele_pt = segment_sorted_ele_pt[is].back();
5176 Node* last_seg_node_pt = last_seg_ele_pt->node_pt(nnod - 1);
5177 if (is_inverted[last_seg_ele_pt])
5179 last_seg_node_pt = last_seg_ele_pt->node_pt(0);
5183 const double segment_final_node_zeta = segment_arclength[is];
5186 Vector<double> last_node_coord(2);
5187 for (
unsigned i = 0; i < 2; i++)
5189 last_node_coord[i] = last_seg_node_pt->x(i);
5193 Boundary_segment_initial_coordinate[b][is] = first_node_coord;
5196 if (this->boundary_geom_object_pt(b) != 0)
5203 Boundary_segment_initial_zeta[b][is] = initial_zeta_segment[is];
5209 Boundary_segment_initial_arclength[b][is] = segment_first_node_zeta;
5214 Boundary_segment_final_coordinate[b][is] = last_node_coord;
5217 if (this->boundary_geom_object_pt(b) != 0)
5224 Boundary_segment_final_zeta[b][is] = final_zeta_segment[is];
5230 Boundary_segment_final_arclength[b][is] = segment_final_node_zeta;
5234 Boundary_segment_inverted[b][is] = 0;
5237 done_segment[is] =
true;
5240 re_assigned_segments++;
5248 if (re_assigned_segments != nsegments)
5250 std::stringstream error_message;
5251 error_message <<
"Working with boundary (" << b
5252 <<
").\nThe number of re-assigned "
5253 <<
"segments (" << re_assigned_segments
5254 <<
") is different from the number\nof segments ("
5255 << nsegments <<
")\n\n";
5256 throw OomphLibError(
5257 error_message.str(),
5258 "TriangleMesh::re_assign_initial_zeta_values_for_internal_boundary()",
5259 OOMPH_EXCEPTION_LOCATION);
5264 for (
unsigned i = 0; i < nele; i++)
5266 delete face_el_pt[i];
5280 template<
class ELEMENT>
5282 Vector<FiniteElement*>& face_ele_pt,
5284 bool& is_internal_boundary,
5285 std::map<FiniteElement*, FiniteElement*>& face_to_bulk_element_pt)
5288 OomphCommunicator* comm_pt = this->communicator_pt();
5290 const unsigned my_rank = comm_pt->my_rank();
5298 Vector<FiniteElement*> tmp_face_ele_pt;
5300 const unsigned nregions = this->nregion();
5306 for (
unsigned ir = 0; ir < nregions; ir++)
5308 const unsigned region_id =
5309 static_cast<unsigned>(this->Region_attribute[ir]);
5312 const unsigned nele_in_region =
5313 this->nboundary_element_in_region(b, region_id);
5317 if (nele_in_region > 0)
5320 for (
unsigned e = 0; e < nele_in_region; e++)
5324 FiniteElement* bulk_ele_pt =
5325 this->boundary_element_in_region_pt(b, region_id, e);
5330 this->face_index_at_boundary_in_region(b, region_id, e);
5333 FiniteElement* tmp_face_el_pt =
5334 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
5337 face_to_bulk_element_pt[tmp_face_el_pt] = bulk_ele_pt;
5342 tmp_face_ele_pt.push_back(tmp_face_el_pt);
5356 const unsigned nbound_ele = this->nboundary_element(b);
5362 for (
unsigned e = 0; e < nbound_ele; e++)
5366 FiniteElement* bulk_ele_pt = this->boundary_element_pt(b, e);
5370 int face_index = this->face_index_at_boundary(b, e);
5373 FiniteElement* tmp_face_el_pt =
5374 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
5377 face_to_bulk_element_pt[tmp_face_el_pt] = bulk_ele_pt;
5382 tmp_face_ele_pt.push_back(tmp_face_el_pt);
5391 std::map<FiniteElement*, bool> done_face;
5395 is_internal_boundary =
false;
5399 Vector<FiniteElement*> free_memory_face_ele_pt;
5403 const unsigned n_tmp_face_ele = tmp_face_ele_pt.size();
5404 for (
unsigned ie = 0; ie < n_tmp_face_ele; ie++)
5407 FiniteElement* main_face_ele_pt = tmp_face_ele_pt[ie];
5408 if (!done_face[main_face_ele_pt])
5411 done_face[main_face_ele_pt] =
true;
5413 const unsigned nnodes = main_face_ele_pt->nnode();
5415 Node* main_first_node_pt = main_face_ele_pt->node_pt(0);
5416 Node* main_last_node_pt = main_face_ele_pt->node_pt(nnodes - 1);
5420 for (
unsigned iie = ie + 1; iie < n_tmp_face_ele; iie++)
5423 FiniteElement* dependant_face_ele_pt = tmp_face_ele_pt[iie];
5424 if (!done_face[dependant_face_ele_pt])
5428 Node* dependant_first_node_pt = dependant_face_ele_pt->node_pt(0);
5429 Node* dependant_last_node_pt =
5430 dependant_face_ele_pt->node_pt(nnodes - 1);
5433 if (((dependant_first_node_pt == main_first_node_pt) &&
5434 (dependant_last_node_pt == main_last_node_pt)) ||
5435 ((dependant_first_node_pt == main_last_node_pt) &&
5436 (dependant_last_node_pt == main_first_node_pt)))
5440 is_internal_boundary =
true;
5442 done_face[dependant_face_ele_pt] =
true;
5453 FiniteElement* main_bulk_ele_pt =
5454 face_to_bulk_element_pt[main_face_ele_pt];
5455 FiniteElement* dependant_bulk_ele_pt =
5456 face_to_bulk_element_pt[dependant_face_ele_pt];
5460 int processor_in_charge_main_bulk_ele =
5461 main_bulk_ele_pt->non_halo_proc_ID();
5462 int processor_in_charge_dependant_bulk_ele =
5463 dependant_bulk_ele_pt->non_halo_proc_ID();
5468 if (processor_in_charge_main_bulk_ele < 0)
5470 processor_in_charge_main_bulk_ele =
static_cast<int>(my_rank);
5472 if (processor_in_charge_dependant_bulk_ele < 0)
5474 processor_in_charge_dependant_bulk_ele =
5475 static_cast<int>(my_rank);
5480 bool add_main_face_element =
true;
5481 if (processor_in_charge_dependant_bulk_ele >
5482 processor_in_charge_main_bulk_ele)
5485 add_main_face_element =
false;
5487 else if (processor_in_charge_main_bulk_ele ==
5488 processor_in_charge_dependant_bulk_ele)
5494 Vector<double> main_ele_coordinates(2);
5495 Vector<double> dependant_ele_coordinates(2);
5498 const unsigned n_bulk_nodes = main_bulk_ele_pt->nnode();
5499 for (
unsigned inode = 0; inode < n_bulk_nodes; inode++)
5501 for (
unsigned idim = 0; idim < 2; idim++)
5503 main_ele_coordinates[idim] +=
5504 main_bulk_ele_pt->node_pt(inode)->x(idim);
5505 dependant_ele_coordinates[idim] +=
5506 dependant_bulk_ele_pt->node_pt(inode)->x(idim);
5512 for (
unsigned idim = 0; idim < 2; idim++)
5514 main_ele_coordinates[idim] /= (double)n_bulk_nodes;
5515 dependant_ele_coordinates[idim] /= (double)n_bulk_nodes;
5521 if (dependant_ele_coordinates[1] < main_ele_coordinates[1])
5523 add_main_face_element =
false;
5525 else if (dependant_ele_coordinates[1] ==
5526 main_ele_coordinates[1])
5529 if (dependant_ele_coordinates[0] < main_ele_coordinates[0])
5531 add_main_face_element =
false;
5537 if (add_main_face_element)
5542 face_ele_pt.push_back(main_face_ele_pt);
5545 free_memory_face_ele_pt.push_back(dependant_face_ele_pt);
5552 face_ele_pt.push_back(dependant_face_ele_pt);
5555 free_memory_face_ele_pt.push_back(main_face_ele_pt);
5574 const unsigned n_free_face_ele = free_memory_face_ele_pt.size();
5575 if (n_free_face_ele == 0)
5583 face_ele_pt.resize(n_tmp_face_ele);
5585 for (
unsigned i = 0; i < n_tmp_face_ele; i++)
5587 face_ele_pt[i] = tmp_face_ele_pt[i];
5595 for (
unsigned i = 0; i < n_free_face_ele; i++)
5597 delete free_memory_face_ele_pt[i];
5598 free_memory_face_ele_pt[i] = 0;
5609 template<
class ELEMENT>
5618 OomphCommunicator* comm_pt = this->communicator_pt();
5620 const unsigned nproc = comm_pt->nproc();
5621 const unsigned my_rank = comm_pt->my_rank();
5625 Vector<FiniteElement*> tmp_face_ele_pt;
5627 const unsigned nregions = this->nregion();
5631 std::map<FiniteElement*, FiniteElement*> face_to_bulk_element_pt;
5637 for (
unsigned ir = 0; ir < nregions; ir++)
5639 const unsigned region_id =
5640 static_cast<unsigned>(this->Region_attribute[ir]);
5643 const unsigned nele_in_region =
5644 this->nboundary_element_in_region(b, region_id);
5648 if (nele_in_region > 0)
5651 for (
unsigned e = 0; e < nele_in_region; e++)
5654 FiniteElement* bulk_ele_pt =
5655 this->boundary_element_in_region_pt(b, region_id, e);
5659 this->face_index_at_boundary_in_region(b, region_id, e);
5662 FiniteElement* tmp_face_el_pt =
5663 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
5668 tmp_face_ele_pt.push_back(tmp_face_el_pt);
5670 face_to_bulk_element_pt[tmp_face_el_pt] = bulk_ele_pt;
5684 const unsigned nbound_ele = this->nboundary_element(b);
5690 for (
unsigned e = 0; e < nbound_ele; e++)
5693 FiniteElement* bulk_ele_pt = this->boundary_element_pt(b, e);
5696 int face_index = this->face_index_at_boundary(b, e);
5699 FiniteElement* tmp_face_el_pt =
5700 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
5704 tmp_face_ele_pt.push_back(tmp_face_el_pt);
5706 face_to_bulk_element_pt[tmp_face_el_pt] = bulk_ele_pt;
5717 Vector<FiniteElement*> face_ele_pt;
5720 std::map<FiniteElement*, bool> done_face;
5723 bool is_internal_boundary =
false;
5727 bool is_internal_boundary_paranoid =
false;
5731 unsigned nfound_face_elements = 0;
5735 const unsigned nbound_ele = tmp_face_ele_pt.size();
5736 for (
unsigned ie = 0; ie < nbound_ele; ie++)
5739 FiniteElement* main_face_ele_pt = tmp_face_ele_pt[ie];
5740 if (!done_face[main_face_ele_pt])
5743 done_face[main_face_ele_pt] =
true;
5745 const unsigned nnodes = main_face_ele_pt->nnode();
5747 Node* main_first_node_pt = main_face_ele_pt->node_pt(0);
5748 Node* main_last_node_pt = main_face_ele_pt->node_pt(nnodes - 1);
5750 for (
unsigned iie = ie + 1; iie < nbound_ele; iie++)
5753 FiniteElement* dependant_face_ele_pt = tmp_face_ele_pt[iie];
5754 if (!done_face[dependant_face_ele_pt])
5757 Node* dependant_first_node_pt = dependant_face_ele_pt->node_pt(0);
5758 Node* dependant_last_node_pt =
5759 dependant_face_ele_pt->node_pt(nnodes - 1);
5762 if (((dependant_first_node_pt == main_first_node_pt) &&
5763 (dependant_last_node_pt == main_last_node_pt)) ||
5764 ((dependant_first_node_pt == main_last_node_pt) &&
5765 (dependant_last_node_pt == main_first_node_pt)))
5769 nfound_face_elements += 2;
5773 is_internal_boundary =
true;
5775 done_face[dependant_face_ele_pt] =
true;
5784 FiniteElement* main_bulk_ele_pt =
5785 face_to_bulk_element_pt[main_face_ele_pt];
5786 FiniteElement* dependant_bulk_ele_pt =
5787 face_to_bulk_element_pt[dependant_face_ele_pt];
5790 int processor_in_charge_main_bulk_ele =
5791 main_bulk_ele_pt->non_halo_proc_ID();
5792 int processor_in_charge_dependant_bulk_ele =
5793 dependant_bulk_ele_pt->non_halo_proc_ID();
5798 if (processor_in_charge_main_bulk_ele < 0)
5800 processor_in_charge_main_bulk_ele =
static_cast<int>(my_rank);
5802 if (processor_in_charge_dependant_bulk_ele < 0)
5804 processor_in_charge_dependant_bulk_ele =
5805 static_cast<int>(my_rank);
5809 bool add_main_face_element =
true;
5810 if (processor_in_charge_dependant_bulk_ele >
5811 processor_in_charge_main_bulk_ele)
5814 add_main_face_element =
false;
5816 else if (processor_in_charge_main_bulk_ele ==
5817 processor_in_charge_dependant_bulk_ele)
5822 Vector<double> main_ele_coordinates(2);
5823 Vector<double> dependant_ele_coordinates(2);
5825 const unsigned n_bulk_nodes = main_bulk_ele_pt->nnode();
5826 for (
unsigned inode = 0; inode < n_bulk_nodes; inode++)
5828 for (
unsigned idim = 0; idim < 2; idim++)
5830 main_ele_coordinates[idim] +=
5831 main_bulk_ele_pt->node_pt(inode)->x(idim);
5832 dependant_ele_coordinates[idim] +=
5833 dependant_bulk_ele_pt->node_pt(inode)->x(idim);
5838 for (
unsigned idim = 0; idim < 2; idim++)
5840 main_ele_coordinates[idim] /= (double)n_bulk_nodes;
5841 dependant_ele_coordinates[idim] /= (double)n_bulk_nodes;
5847 if (dependant_ele_coordinates[1] < main_ele_coordinates[1])
5849 add_main_face_element =
false;
5851 else if (dependant_ele_coordinates[1] ==
5852 main_ele_coordinates[1])
5855 if (dependant_ele_coordinates[0] < main_ele_coordinates[0])
5857 add_main_face_element =
false;
5863 if (add_main_face_element)
5867 face_ele_pt.push_back(main_face_ele_pt);
5873 face_ele_pt.push_back(dependant_face_ele_pt);
5886 const unsigned nface_ele = face_ele_pt.size();
5892 if (nbound_ele > 0 && nfound_face_elements == nbound_ele)
5894 is_internal_boundary_paranoid =
true;
5897 if (nbound_ele > 0 && is_internal_boundary_paranoid &&
5898 nbound_ele != nface_ele * 2)
5900 std::ostringstream error_message;
5902 <<
"The info. to perform the synchronisation of the boundary "
5903 <<
"coordinates was not completely established\n"
5904 <<
"In this case it was the number of non repeated boundary elements\n"
5905 <<
"Number of boundary elements: (" << nbound_ele <<
")\n"
5906 <<
"Number of nonrepeated boundary elements: (" << nface_ele <<
")\n";
5907 throw OomphLibError(error_message.str(),
5908 "TriangleMesh::synchronize_boundary_coordinates()",
5909 OOMPH_EXCEPTION_LOCATION);
5919 std::vector<bool> is_halo_face_element(nface_ele,
false);
5922 unsigned nnon_halo_face_elements = 0;
5924 for (
unsigned ie = 0; ie < nface_ele; ie++)
5926 FiniteElement* face_el_pt = face_ele_pt[ie];
5928 FiniteElement* tmp_bulk_ele_pt = face_to_bulk_element_pt[face_el_pt];
5930 if (!tmp_bulk_ele_pt->is_halo())
5932 is_halo_face_element[ie] =
false;
5933 nnon_halo_face_elements++;
5938 is_halo_face_element[ie] =
true;
5951 std::map<Node*, bool> done_node;
5955 Vector<Vector<Node*>> face_halo_node_pt(nproc);
5959 Vector<Vector<unsigned>> face_halo_node_id(nproc);
5963 Vector<Vector<Node*>> face_haloed_node_pt(nproc);
5967 Vector<Vector<unsigned>> face_haloed_node_id(nproc);
5971 std::map<Node*, bool> done_haloed_face_node;
5974 for (
unsigned iface = 0; iface < nface_ele; iface++)
5977 if (!is_halo_face_element[iface])
5980 FiniteElement* ele_face_pt = face_ele_pt[iface];
5982 const unsigned nnodes = ele_face_pt->nnode();
5984 for (
unsigned in = 0; in < nnodes; in++)
5986 Node* face_node_pt = ele_face_pt->node_pt(in);
5988 if (!done_node[face_node_pt])
5991 done_node[face_node_pt] =
true;
5993 if (face_node_pt->is_halo())
5996 int int_nonhalo_ID = face_node_pt->non_halo_proc_ID();
5998 if (int_nonhalo_ID < 0)
6000 std::ostringstream error_message;
6002 <<
"The node was marked to be halo but the processor in "
6003 <<
"charge was found to be -1\n\n";
6004 throw OomphLibError(
6005 error_message.str(),
6006 "TriangleMesh::synchronize_boundary_coordinates()",
6007 OOMPH_EXCEPTION_LOCATION);
6010 const unsigned ip =
static_cast<unsigned>(int_nonhalo_ID);
6014 face_halo_node_pt[ip].push_back(face_node_pt);
6018 bool found_halo_node =
false;
6020 const unsigned nhalo_iproc = this->nhalo_node(ip);
6021 for (
unsigned ihn = 0; ihn < nhalo_iproc; ihn++)
6023 Node* compare_face_node_pt = this->halo_node_pt(ip, ihn);
6024 if (compare_face_node_pt == face_node_pt)
6028 face_halo_node_id[ip].push_back(ihn);
6031 found_halo_node =
true;
6038 if (!found_halo_node)
6040 std::ostringstream error_message;
6042 <<
"The halo id of the current node: (" << face_node_pt->x(0)
6043 <<
", " << face_node_pt->x(1) <<
") with processor (" << ip
6044 <<
") was not found!!!\n\n";
6045 throw OomphLibError(
6046 error_message.str(),
6047 "TriangleMesh::synchronize_boundary_coordinates()",
6048 OOMPH_EXCEPTION_LOCATION);
6058 for (
unsigned ip = 0; ip < nproc; ip++)
6070 const unsigned nhaloed_iproc = this->nhaloed_node(ip);
6071 for (
unsigned ihdn = 0; ihdn < nhaloed_iproc; ihdn++)
6073 Node* compare_face_node_pt = this->haloed_node_pt(ip, ihdn);
6074 if (face_node_pt == compare_face_node_pt)
6078 face_haloed_node_pt[ip].push_back(face_node_pt);
6081 face_haloed_node_id[ip].push_back(ihdn);
6085 done_haloed_face_node[face_node_pt] =
true;
6111 for (
unsigned ip = 0; ip < nproc; ip++)
6116 const unsigned nhalo_face_nodes = face_halo_node_pt[ip].size();
6118 if (nhalo_face_nodes != face_halo_node_id[ip].size())
6120 std::ostringstream error_message;
6122 <<
"The number of found halo face nodes (" << nhalo_face_nodes
6123 <<
") is different from the number of\nfound halo face ids ("
6124 << face_halo_node_id[ip].size() <<
")!!!\n\n";
6125 throw OomphLibError(
6126 error_message.str(),
6127 "TriangleMesh::synchronize_boundary_coordinates()",
6128 OOMPH_EXCEPTION_LOCATION);
6134 Vector<unsigned> flat_unsigned_send_packed_data;
6135 Vector<double> flat_double_send_packed_data;
6138 for (
unsigned ihfn = 0; ihfn < nhalo_face_nodes; ihfn++)
6141 Node* halo_face_node_pt = face_halo_node_pt[ip][ihfn];
6143 const unsigned halo_id = face_halo_node_id[ip][ihfn];
6145 Vector<double> zeta(1);
6146 halo_face_node_pt->get_coordinates_on_boundary(b, zeta);
6148 flat_unsigned_send_packed_data.push_back(halo_id);
6149 flat_double_send_packed_data.push_back(zeta[0]);
6154 MPI_Request request;
6157 int send_proc =
static_cast<int>(ip);
6159 int receive_proc =
static_cast<int>(ip);
6162 Vector<unsigned> flat_unsigned_receive_packed_data;
6163 Vector<double> flat_double_receive_packed_data;
6167 unsigned nflat_unsigned_send = flat_unsigned_send_packed_data.size();
6168 MPI_Isend(&nflat_unsigned_send,
6173 comm_pt->mpi_comm(),
6176 unsigned nflat_unsigned_receive = 0;
6177 MPI_Recv(&nflat_unsigned_receive,
6182 comm_pt->mpi_comm(),
6185 MPI_Wait(&request, MPI_STATUS_IGNORE);
6187 if (nflat_unsigned_send != 0)
6189 MPI_Isend(&flat_unsigned_send_packed_data[0],
6190 nflat_unsigned_send,
6194 comm_pt->mpi_comm(),
6198 if (nflat_unsigned_receive != 0)
6200 flat_unsigned_receive_packed_data.resize(nflat_unsigned_receive);
6201 MPI_Recv(&flat_unsigned_receive_packed_data[0],
6202 nflat_unsigned_receive,
6206 comm_pt->mpi_comm(),
6210 if (nflat_unsigned_send != 0)
6212 MPI_Wait(&request, MPI_STATUS_IGNORE);
6219 MPI_Request my_request;
6222 unsigned nflat_double_send = flat_double_send_packed_data.size();
6223 MPI_Isend(&nflat_double_send,
6228 comm_pt->mpi_comm(),
6231 unsigned nflat_double_receive = 0;
6232 MPI_Recv(&nflat_double_receive,
6237 comm_pt->mpi_comm(),
6241 MPI_Wait(&my_request, MPI_STATUS_IGNORE);
6243 if (nflat_double_send != 0)
6245 MPI_Isend(&flat_double_send_packed_data[0],
6250 comm_pt->mpi_comm(),
6254 if (nflat_double_receive != 0)
6256 flat_double_receive_packed_data.resize(nflat_double_receive);
6257 MPI_Recv(&flat_double_receive_packed_data[0],
6258 nflat_double_receive,
6262 comm_pt->mpi_comm(),
6266 if (nflat_double_send != 0)
6268 MPI_Wait(&my_request, MPI_STATUS_IGNORE);
6273 if (nflat_unsigned_receive != nflat_double_receive)
6275 std::ostringstream error_message;
6276 error_message <<
"The number of unsigned received data ("
6277 << nflat_unsigned_receive <<
") is different from the "
6278 <<
"number\nof double received data ("
6279 << nflat_double_receive <<
")!!!\n\n";
6280 throw OomphLibError(
6281 error_message.str(),
6282 "TriangleMesh::synchronize_boundary_coordinates()",
6283 OOMPH_EXCEPTION_LOCATION);
6290 for (
unsigned iflat_packed = 0; iflat_packed < nflat_unsigned_receive;
6294 const unsigned haloed_id =
6295 flat_unsigned_receive_packed_data[iflat_packed];
6297 Vector<double> zeta(1);
6298 zeta[0] = flat_double_receive_packed_data[iflat_packed];
6301 Node* haloed_face_node_pt = this->haloed_node_pt(ip, haloed_id);
6315 if (!done_haloed_face_node[haloed_face_node_pt])
6318 haloed_face_node_pt->set_coordinates_on_boundary(b, zeta);
6321 for (
unsigned iiproc = 0; iiproc < nproc; iiproc++)
6324 if (iiproc != my_rank)
6327 const unsigned nhaloed_node_iiproc = this->nhaloed_node(iiproc);
6328 for (
unsigned ihdn = 0; ihdn < nhaloed_node_iiproc; ihdn++)
6330 Node* compare_haloed_node_pt =
6331 this->haloed_node_pt(iiproc, ihdn);
6332 if (haloed_face_node_pt == compare_haloed_node_pt)
6336 face_haloed_node_pt[iiproc].push_back(haloed_face_node_pt);
6339 face_haloed_node_id[iiproc].push_back(ihdn);
6360 for (
unsigned ip = 0; ip < nproc; ip++)
6367 Vector<unsigned> flat_unsigned_send_packed_data;
6368 Vector<double> flat_double_send_packed_data;
6372 const unsigned nhaloed_face_nodes = face_haloed_node_pt[ip].size();
6374 for (
unsigned ihdfn = 0; ihdfn < nhaloed_face_nodes; ihdfn++)
6377 Node* haloed_face_node_pt = face_haloed_node_pt[ip][ihdfn];
6379 const unsigned haloed_id = face_haloed_node_id[ip][ihdfn];
6381 Vector<double> zeta(1);
6382 haloed_face_node_pt->get_coordinates_on_boundary(b, zeta);
6384 flat_unsigned_send_packed_data.push_back(haloed_id);
6385 flat_double_send_packed_data.push_back(zeta[0]);
6390 MPI_Request request;
6393 int send_proc =
static_cast<int>(ip);
6395 int receive_proc =
static_cast<int>(ip);
6398 Vector<unsigned> flat_unsigned_receive_packed_data;
6399 Vector<double> flat_double_receive_packed_data;
6403 unsigned nflat_unsigned_send = flat_unsigned_send_packed_data.size();
6404 MPI_Isend(&nflat_unsigned_send,
6409 comm_pt->mpi_comm(),
6412 unsigned nflat_unsigned_receive = 0;
6413 MPI_Recv(&nflat_unsigned_receive,
6418 comm_pt->mpi_comm(),
6421 MPI_Wait(&request, MPI_STATUS_IGNORE);
6423 if (nflat_unsigned_send != 0)
6425 MPI_Isend(&flat_unsigned_send_packed_data[0],
6426 nflat_unsigned_send,
6430 comm_pt->mpi_comm(),
6434 if (nflat_unsigned_receive != 0)
6436 flat_unsigned_receive_packed_data.resize(nflat_unsigned_receive);
6437 MPI_Recv(&flat_unsigned_receive_packed_data[0],
6438 nflat_unsigned_receive,
6442 comm_pt->mpi_comm(),
6446 if (nflat_unsigned_send != 0)
6448 MPI_Wait(&request, MPI_STATUS_IGNORE);
6453 unsigned nflat_double_send = flat_double_send_packed_data.size();
6454 MPI_Isend(&nflat_double_send,
6459 comm_pt->mpi_comm(),
6462 unsigned nflat_double_receive = 0;
6463 MPI_Recv(&nflat_double_receive,
6468 comm_pt->mpi_comm(),
6471 MPI_Wait(&request, MPI_STATUS_IGNORE);
6473 if (nflat_double_send != 0)
6475 MPI_Isend(&flat_double_send_packed_data[0],
6480 comm_pt->mpi_comm(),
6484 if (nflat_double_receive != 0)
6486 flat_double_receive_packed_data.resize(nflat_double_receive);
6487 MPI_Recv(&flat_double_receive_packed_data[0],
6488 nflat_double_receive,
6492 comm_pt->mpi_comm(),
6496 if (nflat_double_send != 0)
6498 MPI_Wait(&request, MPI_STATUS_IGNORE);
6503 if (nflat_unsigned_receive != nflat_double_receive)
6505 std::ostringstream error_message;
6506 error_message <<
"The number of unsigned received data ("
6507 << nflat_unsigned_receive <<
") is different from the "
6508 <<
"number\nof double received data ("
6509 << nflat_double_receive <<
")!!!\n\n";
6510 throw OomphLibError(
6511 error_message.str(),
6512 "TriangleMesh::synchronize_boundary_coordinates()",
6513 OOMPH_EXCEPTION_LOCATION);
6520 for (
unsigned iflat_packed = 0; iflat_packed < nflat_unsigned_receive;
6524 const unsigned halo_id =
6525 flat_unsigned_receive_packed_data[iflat_packed];
6527 Vector<double> zeta(1);
6528 zeta[0] = flat_double_receive_packed_data[iflat_packed];
6531 Node* halo_face_node_pt = this->halo_node_pt(ip, halo_id);
6542 halo_face_node_pt->set_coordinates_on_boundary(b, zeta);
6548 for (
unsigned ie = 0; ie < nbound_ele; ie++)
6550 delete tmp_face_ele_pt[ie];
6551 tmp_face_ele_pt[ie] = 0;
6556 if (is_internal_boundary)
6558 re_scale_re_assigned_initial_zeta_values_for_internal_boundary(b);
6568 template<
class ELEMENT>
6578 Vector<FiniteElement*> face_el_pt;
6586 unsigned n_repeated_ele = 0;
6588 const unsigned n_regions = this->nregion();
6591 Vector<std::pair<Node*, Node*>> done_nodes_pt;
6597 for (
unsigned rr = 0; rr < n_regions; rr++)
6599 const unsigned region_id =
6600 static_cast<unsigned>(this->Region_attribute[rr]);
6603 const unsigned nel_in_region =
6604 this->nboundary_element_in_region(b, region_id);
6606 unsigned nel_repetead_in_region = 0;
6610 if (nel_in_region > 0)
6612 bool repeated =
false;
6615 for (
unsigned e = 0; e < nel_in_region; e++)
6619 FiniteElement* bulk_elem_pt =
6620 this->boundary_element_in_region_pt(b, region_id, e);
6623 if (bulk_elem_pt->is_halo())
6631 this->face_index_at_boundary_in_region(b, region_id, e);
6636 FiniteElement* tmp_ele_pt =
6637 new DummyFaceElement<ELEMENT>(bulk_elem_pt, face_index);
6639 const unsigned n_nodes = tmp_ele_pt->nnode();
6641 std::pair<Node*, Node*> tmp_pair = std::make_pair(
6642 tmp_ele_pt->node_pt(0), tmp_ele_pt->node_pt(n_nodes - 1));
6644 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
6645 tmp_ele_pt->node_pt(n_nodes - 1), tmp_ele_pt->node_pt(0));
6648 const unsigned n_done_nodes = done_nodes_pt.size();
6649 for (
unsigned l = 0; l < n_done_nodes; l++)
6651 if (tmp_pair == done_nodes_pt[l] ||
6652 tmp_pair_inverse == done_nodes_pt[l])
6654 nel_repetead_in_region++;
6664 done_nodes_pt.push_back(tmp_pair);
6666 face_el_pt.push_back(tmp_ele_pt);
6680 nele += nel_in_region;
6682 n_repeated_ele += nel_repetead_in_region;
6691 nele = this->nboundary_element(b);
6697 bool repeated =
false;
6700 for (
unsigned e = 0; e < nele; e++)
6704 FiniteElement* bulk_elem_pt = this->boundary_element_pt(b, e);
6707 if (bulk_elem_pt->is_halo())
6715 int face_index = this->face_index_at_boundary(b, e);
6720 FiniteElement* tmp_ele_pt =
6721 new DummyFaceElement<ELEMENT>(bulk_elem_pt, face_index);
6723 const unsigned n_nodes = tmp_ele_pt->nnode();
6725 std::pair<Node*, Node*> tmp_pair = std::make_pair(
6726 tmp_ele_pt->node_pt(0), tmp_ele_pt->node_pt(n_nodes - 1));
6728 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
6729 tmp_ele_pt->node_pt(n_nodes - 1), tmp_ele_pt->node_pt(0));
6732 const unsigned n_done_nodes = done_nodes_pt.size();
6733 for (
unsigned l = 0; l < n_done_nodes; l++)
6735 if (tmp_pair == done_nodes_pt[l] ||
6736 tmp_pair_inverse == done_nodes_pt[l])
6750 done_nodes_pt.push_back(tmp_pair);
6752 face_el_pt.push_back(tmp_ele_pt);
6770 nele -= n_repeated_ele;
6773 if (nele != face_el_pt.size())
6775 std::ostringstream error_message;
6777 <<
"The independet counting of face elements (" << nele <<
") for "
6778 <<
"boundary (" << b <<
") is different\n"
6779 <<
"from the real number of face elements in the container ("
6780 << face_el_pt.size() <<
")\n";
6782 throw OomphLibError(error_message.str(),
6783 "TriangleMesh::re_scale_re_assigned_initial_zeta_"
6784 "values_for_internal_boundary()",
6785 OOMPH_EXCEPTION_LOCATION);
6795 const unsigned nnon_halo_face_elements = face_el_pt.size();
6799 Vector<std::list<FiniteElement*>> segment_sorted_ele_pt;
6802 unsigned nsorted_face_elements = 0;
6805 std::map<FiniteElement*, bool> done_el;
6808 std::map<FiniteElement*, bool> is_inverted;
6811 while (nsorted_face_elements < nnon_halo_face_elements)
6815 std::list<FiniteElement*> sorted_el_pt;
6819 bool found_initial_face_element =
false;
6822 FiniteElement* ele_face_pt = 0;
6825 for (iface = 0; iface < nele; iface++)
6827 ele_face_pt = face_el_pt[iface];
6829 if (!done_el[ele_face_pt])
6832 found_initial_face_element =
true;
6834 nsorted_face_elements++;
6836 sorted_el_pt.push_back(ele_face_pt);
6838 done_el[ele_face_pt] =
true;
6844 if (!found_initial_face_element)
6846 std::ostringstream error_message;
6848 <<
"Could not find an initial face element for the current segment\n";
6850 throw OomphLibError(error_message.str(),
6851 "TriangleMesh::re_scale_re_assigned_initial_zeta_"
6852 "values_for_internal_boundary()",
6853 OOMPH_EXCEPTION_LOCATION);
6858 const unsigned nnod = ele_face_pt->nnode();
6862 Node* left_node_pt = ele_face_pt->node_pt(0);
6863 Node* right_node_pt = ele_face_pt->node_pt(nnod - 1);
6867 bool face_element_added =
false;
6876 for (
unsigned iiface = iface; iiface < nele; iiface++)
6879 face_element_added =
false;
6882 ele_face_pt = face_el_pt[iiface];
6885 if (!(done_el[ele_face_pt]))
6888 Node* local_left_node_pt = ele_face_pt->node_pt(0);
6889 Node* local_right_node_pt = ele_face_pt->node_pt(nnod - 1);
6892 if (left_node_pt == local_right_node_pt)
6894 left_node_pt = local_left_node_pt;
6895 sorted_el_pt.push_front(ele_face_pt);
6896 is_inverted[ele_face_pt] =
false;
6897 face_element_added =
true;
6900 else if (left_node_pt == local_left_node_pt)
6902 left_node_pt = local_right_node_pt;
6903 sorted_el_pt.push_front(ele_face_pt);
6904 is_inverted[ele_face_pt] =
true;
6905 face_element_added =
true;
6908 else if (right_node_pt == local_left_node_pt)
6910 right_node_pt = local_right_node_pt;
6911 sorted_el_pt.push_back(ele_face_pt);
6912 is_inverted[ele_face_pt] =
false;
6913 face_element_added =
true;
6916 else if (right_node_pt == local_right_node_pt)
6918 right_node_pt = local_left_node_pt;
6919 sorted_el_pt.push_back(ele_face_pt);
6920 is_inverted[ele_face_pt] =
true;
6921 face_element_added =
true;
6924 if (face_element_added)
6926 done_el[ele_face_pt] =
true;
6927 nsorted_face_elements++;
6933 }
while (face_element_added &&
6934 (nsorted_face_elements < nnon_halo_face_elements));
6937 segment_sorted_ele_pt.push_back(sorted_el_pt);
6950 Vector<std::set<Node*>> segment_all_nodes_pt;
6953 const unsigned nsegments = segment_sorted_ele_pt.size();
6956 if (nnon_halo_face_elements > 0 && nsegments == 0)
6958 std::ostringstream error_message;
6960 <<
"The number of segments is zero, but the number of nonhalo\n"
6961 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
6962 throw OomphLibError(error_message.str(),
6963 "TriangleMesh::re_scale_re_assigned_initial_zeta_"
6964 "values_for_internal_boundary()",
6965 OOMPH_EXCEPTION_LOCATION);
6970 Vector<double> segment_arclength(nsegments);
6973 Vector<double> initial_zeta_segment(nsegments);
6976 Vector<double> final_zeta_segment(nsegments);
6980 for (
unsigned is = 0; is < nsegments; is++)
6983 if (segment_sorted_ele_pt[is].size() == 0)
6985 std::ostringstream error_message;
6986 error_message <<
"The (" << is <<
")-th segment has no elements\n";
6987 throw OomphLibError(error_message.str(),
6988 "TriangleMesh::re_scale_re_assigned_initial_zeta_"
6989 "values_for_internal_boundary()",
6990 OOMPH_EXCEPTION_LOCATION);
6995 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
6998 const unsigned nnod = first_ele_pt->nnode();
7001 Node* first_node_pt = first_ele_pt->node_pt(0);
7002 if (is_inverted[first_ele_pt])
7004 first_node_pt = first_ele_pt->node_pt(nnod - 1);
7008 FiniteElement* last_ele_pt = segment_sorted_ele_pt[is].back();
7011 Node* last_node_pt = last_ele_pt->node_pt(nnod - 1);
7012 if (is_inverted[last_ele_pt])
7014 last_node_pt = last_ele_pt->node_pt(0);
7018 double x_left = first_node_pt->x(0);
7019 double y_left = first_node_pt->x(1);
7023 Vector<double> zeta(1, 0.0);
7028 if (this->boundary_geom_object_pt(b) != 0)
7030 first_node_pt->get_coordinates_on_boundary(b, zeta);
7031 initial_zeta_segment[is] = zeta[0];
7032 last_node_pt->get_coordinates_on_boundary(b, zeta);
7033 final_zeta_segment[is] = zeta[0];
7037 std::set<Node*> local_nodes_pt;
7038 local_nodes_pt.insert(first_node_pt);
7041 for (std::list<FiniteElement*>::iterator it =
7042 segment_sorted_ele_pt[is].begin();
7043 it != segment_sorted_ele_pt[is].end();
7047 FiniteElement* el_pt = *it;
7052 if (is_inverted[el_pt])
7059 for (
unsigned j = 1; j < nnod; j++)
7061 Node* nod_pt = el_pt->node_pt(k_nod);
7065 double x_right = nod_pt->x(0);
7066 double y_right = nod_pt->x(1);
7069 zeta[0] += sqrt((x_right - x_left) * (x_right - x_left) +
7070 (y_right - y_left) * (y_right - y_left));
7078 local_nodes_pt.insert(nod_pt);
7084 segment_arclength[is] = zeta[0];
7087 segment_all_nodes_pt.push_back(local_nodes_pt);
7099 Boundary_segment_inverted[b].clear();
7100 Boundary_segment_initial_coordinate[b].clear();
7101 Boundary_segment_final_coordinate[b].clear();
7103 Boundary_segment_initial_zeta[b].clear();
7104 Boundary_segment_final_zeta[b].clear();
7106 Boundary_segment_initial_arclength[b].clear();
7107 Boundary_segment_final_arclength[b].clear();
7110 Vector<double> first_node_zeta_coordinate(1, 0.0);
7111 Vector<double> last_node_zeta_coordinate(1, 0.0);
7112 first_node_zeta_coordinate = boundary_initial_zeta_coordinate(b);
7113 last_node_zeta_coordinate = boundary_final_zeta_coordinate(b);
7116 const double boundary_arclength =
7117 std::max(first_node_zeta_coordinate[0], last_node_zeta_coordinate[0]);
7121 for (
unsigned is = 0; is < nsegments; is++)
7124 FiniteElement* first_face_ele_pt = segment_sorted_ele_pt[is].front();
7127 const unsigned nnod = first_face_ele_pt->nnode();
7130 Node* first_node_pt = first_face_ele_pt->node_pt(0);
7131 if (is_inverted[first_face_ele_pt])
7133 first_node_pt = first_face_ele_pt->node_pt(nnod - 1);
7137 Vector<double> zeta_first(1);
7138 first_node_pt->get_coordinates_on_boundary(b, zeta_first);
7141 FiniteElement* last_face_ele_pt = segment_sorted_ele_pt[is].back();
7144 Node* last_node_pt = last_face_ele_pt->node_pt(nnod - 1);
7145 if (is_inverted[last_face_ele_pt])
7147 last_node_pt = last_face_ele_pt->node_pt(0);
7151 Vector<double> zeta_last(1);
7152 last_node_pt->get_coordinates_on_boundary(b, zeta_last);
7156 Vector<double> first_node_coord(2);
7157 Vector<double> last_node_coord(2);
7158 for (
unsigned i = 0; i < 2; i++)
7160 first_node_coord[i] = first_node_pt->x(i);
7161 last_node_coord[i] = last_node_pt->x(i);
7165 Boundary_segment_inverted[b].push_back(0);
7166 Boundary_segment_initial_coordinate[b].push_back(first_node_coord);
7167 Boundary_segment_final_coordinate[b].push_back(last_node_coord);
7170 if (this->boundary_geom_object_pt(b) != 0)
7172 Boundary_segment_initial_zeta[b].push_back(zeta_first[0]);
7173 Boundary_segment_final_zeta[b].push_back(zeta_last[0]);
7178 Boundary_segment_initial_arclength[b].push_back(zeta_first[0] *
7179 boundary_arclength);
7180 Boundary_segment_final_arclength[b].push_back(zeta_last[0] *
7181 boundary_arclength);
7187 for (
unsigned i = 0; i < nele; i++)
7189 delete face_el_pt[i];
7197 #ifdef OOMPH_HAS_TRIANGLE_LIB
7202 template<
class ELEMENT>
7204 const std::string& poly_file_name,
7205 TriangulateIO& triangulate_io,
7206 bool& use_attributes)
7210 std::ifstream poly_file(poly_file_name.c_str(), std::ios_base::in);
7213 throw OomphLibError(
"Error opening .poly file\n",
7214 OOMPH_CURRENT_FUNCTION,
7215 OOMPH_EXCEPTION_LOCATION);
7219 TriangleHelper::initialise_triangulateio(triangulate_io);
7222 poly_file.ignore(80,
'\n');
7225 unsigned invertices;
7226 poly_file >> invertices;
7227 triangulate_io.numberofpoints = invertices;
7230 triangulate_io.pointlist =
7231 (
double*)malloc(triangulate_io.numberofpoints * 2 *
sizeof(
double));
7235 poly_file >> mesh_dim;
7245 throw OomphLibError(
"The dimension must be 2\n",
7246 OOMPH_CURRENT_FUNCTION,
7247 OOMPH_EXCEPTION_LOCATION);
7253 poly_file >> nextras;
7255 triangulate_io.numberofpointattributes = 0;
7256 triangulate_io.pointattributelist = (
double*)NULL;
7259 unsigned nodemarkers;
7260 poly_file >> nodemarkers;
7261 triangulate_io.pointmarkerlist = (
int*)NULL;
7266 if (nextras != 0 || nodemarkers != 0)
7268 oomph_info <<
"===================================================="
7271 oomph_info <<
"Reading the .poly file via oomph_lib \n"
7272 <<
"point's attribute and point's markers \n"
7273 <<
"are automatically set to 0" << std::endl;
7274 oomph_info <<
"===================================================="
7280 unsigned dummy_value;
7281 unsigned count_point = 0;
7282 std::string test_string;
7285 getline(poly_file, test_string,
'#');
7286 poly_file.ignore(80,
'\n');
7290 for (
unsigned count = 0; count < invertices; count++)
7292 poly_file >> dummy_value;
7293 poly_file >> triangulate_io.pointlist[count_point];
7294 poly_file >> triangulate_io.pointlist[count_point + 1];
7295 if (nextras != 0 || nodemarkers != 0)
7297 for (
unsigned j = 0; j < nextras; j++)
7299 poly_file >> dummy_value;
7302 else if (nextras != 0 && nodemarkers != 0)
7304 for (
unsigned j = 0; j < nextras; j++)
7306 poly_file >> dummy_value;
7307 poly_file >> dummy_value;
7311 poly_file.ignore(80,
'\n');
7314 if (poly_file.get() ==
'#')
7316 poly_file.ignore(80,
'\n');
7332 unsigned inelements;
7333 poly_file >> inelements;
7335 unsigned segment_markers;
7336 poly_file >> segment_markers;
7341 if (segment_markers != 1)
7343 std::ostringstream error_stream;
7344 error_stream <<
"The segment marker should be provided \n"
7345 <<
"In order to assign each segment to a boundary \n "
7348 throw OomphLibError(
7349 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
7353 triangulate_io.numberofsegments = inelements;
7354 triangulate_io.segmentlist =
7355 (
int*)malloc(triangulate_io.numberofsegments * 2 *
sizeof(
int));
7356 triangulate_io.segmentmarkerlist =
7357 (
int*)malloc(triangulate_io.numberofsegments *
sizeof(
int));
7360 for (
unsigned i = 0; i < 2 * inelements; i += 2)
7362 poly_file >> dummy_seg;
7363 poly_file >> triangulate_io.segmentlist[i];
7364 poly_file >> triangulate_io.segmentlist[i + 1];
7365 if (segment_markers != 0)
7367 poly_file >> triangulate_io.segmentmarkerlist[i / 2];
7371 poly_file.ignore(80,
'\n');
7376 if (getline(poly_file, test_string,
'#'))
7378 poly_file.ignore(80,
'\n');
7380 unsigned dummy_hole;
7384 triangulate_io.numberofholes = nhole;
7385 triangulate_io.holelist =
7386 (
double*)malloc(triangulate_io.numberofholes * 2 *
sizeof(
double));
7390 for (
unsigned i = 0; i < 2 * nhole; i += 2)
7392 poly_file >> dummy_hole;
7393 poly_file >> triangulate_io.holelist[i];
7394 poly_file >> triangulate_io.holelist[i + 1];
7400 if (getline(poly_file, test_string,
'#'))
7402 poly_file.ignore(80,
'\n');
7404 unsigned dummy_region;
7406 poly_file >> nregion;
7407 std::cerr <<
"Regions: " << nregion << std::endl;
7410 triangulate_io.numberofregions = nregion;
7411 triangulate_io.regionlist =
7412 (
double*)malloc(triangulate_io.numberofregions * 4 *
sizeof(
double));
7417 use_attributes =
true;
7422 for (
unsigned i = 0; i < nregion; i++)
7424 poly_file >> dummy_region;
7425 poly_file >> triangulate_io.regionlist[4 * i];
7426 poly_file >> triangulate_io.regionlist[4 * i + 1];
7427 poly_file >> triangulate_io.regionlist[4 * i + 2];
7428 triangulate_io.regionlist[4 * i + 3] = 0.0;
7435 #ifdef OOMPH_HAS_TRIANGLE_LIB
7436 #ifdef OOMPH_HAS_MPI
7441 template<
class ELEMENT>
7443 std::ostream& dump_file)
7446 if (this->is_mesh_distributed())
7449 const unsigned nboundary = this->nboundary();
7450 dump_file << nboundary <<
" # number of original boundaries" << std::endl;
7453 const unsigned nshared_boundaries = this->nshared_boundaries();
7454 dump_file << nshared_boundaries <<
" # number of shared boundaries"
7458 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
7459 dump_file << init_shd_bnd_id <<
" # initial shared boundaries id"
7462 const unsigned final_shd_bnd_id = this->final_shared_boundary_id();
7463 dump_file << final_shd_bnd_id <<
" # final shared boundaries id"
7467 const unsigned nprocs = this->shared_boundaries_ids().size();
7468 dump_file << nprocs <<
" # number of processors" << std::endl;
7472 for (
unsigned ip = 0; ip < nprocs; ip++)
7474 for (
unsigned jp = 0; jp < nprocs; jp++)
7480 const unsigned nshared_boundaries_iproc_jproc =
7481 this->shared_boundaries_ids(ip, jp).size();
7485 dump_file << nshared_boundaries_iproc_jproc
7486 <<
" # number of shared boundaries with in two "
7487 <<
"processors" << std::endl;
7488 for (
unsigned is = 0; is < nshared_boundaries_iproc_jproc; is++)
7490 const unsigned shared_boundary_id =
7491 this->shared_boundaries_ids(ip, jp, is);
7492 dump_file << ip <<
" " << jp <<
" " << shared_boundary_id
7493 <<
" # ip jp shared_boundary of processors ip and jp"
7506 const unsigned nshared_boundaries_overlap_internal_boundaries =
7507 this->nshared_boundary_overlaps_internal_boundary();
7508 dump_file << nshared_boundaries_overlap_internal_boundaries
7509 <<
" # number of shared boundaries that overlap internal "
7510 <<
"boundaries" << std::endl;
7512 if (nshared_boundaries_overlap_internal_boundaries > 0)
7514 for (
unsigned isb = init_shd_bnd_id; isb < final_shd_bnd_id; isb++)
7518 if (this->shared_boundary_overlaps_internal_boundary(isb))
7522 const unsigned overlapped_internal_boundary =
7523 shared_boundary_overlapping_internal_boundary(isb);
7525 dump_file << isb <<
" " << overlapped_internal_boundary
7526 <<
" # the shared boundary overlaps the internal "
7527 <<
"boundary " << std::endl;
7538 for (
unsigned b = 0; b < nboundary; b++)
7543 if (Assigned_segments_initial_zeta_values[b])
7547 dump_file <<
"1 # assigned boundary coordinates initial zeta values"
7554 Vector<double> initial_coordinates =
7555 this->boundary_initial_coordinate(b);
7557 Vector<double> final_coordinates = this->boundary_final_coordinate(b);
7559 dump_file << std::setprecision(14) << initial_coordinates[0] <<
" "
7560 << initial_coordinates[1]
7561 <<
" # initial coordinates for the current boundary"
7564 dump_file << std::setprecision(14) << final_coordinates[0] <<
" "
7565 << final_coordinates[1]
7566 <<
" # final coordinates for the current boundary"
7573 const unsigned zeta_size =
7574 this->boundary_initial_zeta_coordinate(b).size();
7578 std::ostringstream error_message;
7580 <<
"The dimension for the zeta values container is different\n"
7581 <<
"from 1, the current implementation only supports\n"
7582 <<
"one-dimensioned zeta containers\n\n";
7583 throw OomphLibError(
7584 error_message.str(),
7585 "TriangleMesh::dump_distributed_info_for_restart()",
7586 OOMPH_EXCEPTION_LOCATION);
7590 Vector<double> zeta_initial =
7591 this->boundary_initial_zeta_coordinate(b);
7592 Vector<double> zeta_final = this->boundary_final_zeta_coordinate(b);
7594 dump_file << std::setprecision(14) << zeta_initial[0]
7595 <<
" # initial zeta value for the current boundary"
7598 dump_file << std::setprecision(14) << zeta_final[0]
7599 <<
" # final zeta value for the current boundary"
7603 const unsigned nsegments = this->nboundary_segment(b);
7605 dump_file << b <<
" " << nsegments
7606 <<
" # of segments for the current boundary" << std::endl;
7609 for (
unsigned is = 0; is < nsegments; is++)
7612 Vector<double> initial_segment_coordinates =
7613 this->boundary_segment_initial_coordinate(b)[is];
7614 Vector<double> final_segment_coordinates =
7615 this->boundary_segment_final_coordinate(b)[is];
7618 << std::setprecision(14) << initial_segment_coordinates[0] <<
" "
7619 << initial_segment_coordinates[1]
7620 <<
" # initial segment coordinates for the current boundary"
7623 dump_file << std::setprecision(14) << final_segment_coordinates[0]
7624 <<
" " << final_segment_coordinates[1]
7625 <<
" # final segment coordinates for the current boundary"
7630 if (this->boundary_geom_object_pt(b) != 0)
7632 const double zeta_segment_initial =
7633 this->boundary_segment_initial_zeta(b)[is];
7634 const double zeta_segment_final =
7635 this->boundary_segment_final_zeta(b)[is];
7638 << std::setprecision(14) << zeta_segment_initial
7639 <<
" # initial segment zeta value for the current boundary"
7643 << std::setprecision(14) << zeta_segment_final
7644 <<
" # final segment zeta value for the current boundary"
7649 const double arclength_segment_initial =
7650 this->boundary_segment_initial_arclength(b)[is];
7651 const double arclength_segment_final =
7652 this->boundary_segment_final_arclength(b)[is];
7655 << std::setprecision(14) << arclength_segment_initial
7656 <<
" # initial segment arclength for the current boundary"
7659 dump_file << std::setprecision(14) << arclength_segment_final
7660 <<
" # final segment arclength for the current boundary"
7672 dump_file <<
"0 # assigned boundary coordinates initial zeta values"
7684 template<
class ELEMENT>
7686 std::istream& restart_file)
7689 if (this->is_mesh_distributed())
7692 const unsigned n_boundary = read_unsigned_line_helper(restart_file);
7695 if (n_boundary != this->nboundary())
7697 std::ostringstream error_message;
7699 <<
"The number of boundaries (" << n_boundary <<
") on the "
7700 <<
"file used for restarting is different\nfrom the number of "
7701 <<
"boundaries (" << this->nboundary() <<
") on the current "
7703 throw OomphLibError(error_message.str(),
7704 "TriangleMesh::read_distributed_info_for_restart()",
7705 OOMPH_EXCEPTION_LOCATION);
7710 unsigned n_shared_boundaries = read_unsigned_line_helper(restart_file);
7713 n_shared_boundaries++;
7714 n_shared_boundaries--;
7717 unsigned init_shd_bnd_id = read_unsigned_line_helper(restart_file);
7723 unsigned final_shd_bnd_id = read_unsigned_line_helper(restart_file);
7731 const unsigned n_procs = read_unsigned_line_helper(restart_file);
7734 if (
static_cast<int>(n_procs) != this->communicator_pt()->nproc())
7736 std::ostringstream error_message;
7738 <<
"The number of previously used processors (" << n_procs
7739 <<
") (read from the restart file) is different\nfrom the "
7740 <<
"number of current used processors ("
7741 << this->communicator_pt()->nproc() <<
")\n\n";
7742 throw OomphLibError(error_message.str(),
7743 "TriangleMesh::read_distributed_info_for_restart()",
7744 OOMPH_EXCEPTION_LOCATION);
7749 this->shared_boundaries_ids().clear();
7750 this->shared_boundary_from_processors().clear();
7751 this->shared_boundary_overlaps_internal_boundary().clear();
7755 this->shared_boundaries_ids().resize(n_procs);
7759 for (
unsigned ip = 0; ip < n_procs; ip++)
7763 this->shared_boundaries_ids(ip).resize(n_procs);
7764 for (
unsigned jp = 0; jp < n_procs; jp++)
7770 const unsigned nshared_boundaries_iproc_jproc =
7771 read_unsigned_line_helper(restart_file);
7772 for (
unsigned is = 0; is < nshared_boundaries_iproc_jproc; is++)
7776 restart_file >> tmp_ip;
7778 restart_file >> tmp_jp;
7782 const unsigned shared_boundary_id =
7783 read_unsigned_line_helper(restart_file);
7787 this->shared_boundaries_ids(ip, jp).push_back(shared_boundary_id);
7791 Vector<unsigned> processors(2);
7794 this->shared_boundary_from_processors()[shared_boundary_id] =
7807 const unsigned nshared_boundaries_overlap_internal_boundaries =
7808 read_unsigned_line_helper(restart_file);
7810 for (
unsigned isb = 0;
7811 isb < nshared_boundaries_overlap_internal_boundaries;
7815 unsigned shared_boundary_overlapping;
7816 restart_file >> shared_boundary_overlapping;
7818 const unsigned overlapped_internal_boundary =
7819 read_unsigned_line_helper(restart_file);
7823 this->shared_boundary_overlaps_internal_boundary()
7824 [shared_boundary_overlapping] = overlapped_internal_boundary;
7832 for (
unsigned b = 0; b < n_boundary; b++)
7836 const unsigned boundary_coordinates_initial_zeta_values_assigned =
7837 read_unsigned_line_helper(restart_file);
7839 if (boundary_coordinates_initial_zeta_values_assigned)
7844 Boundary_initial_coordinate[b].clear();
7845 Boundary_final_coordinate[b].clear();
7847 Boundary_initial_zeta_coordinate[b].clear();
7848 Boundary_final_zeta_coordinate[b].clear();
7851 Boundary_segment_inverted[b].clear();
7852 Boundary_segment_initial_coordinate[b].clear();
7853 Boundary_segment_final_coordinate[b].clear();
7855 Boundary_segment_initial_zeta[b].clear();
7856 Boundary_segment_final_zeta[b].clear();
7858 Boundary_segment_initial_arclength[b].clear();
7859 Boundary_segment_final_arclength[b].clear();
7865 Vector<double> initial_coordinates(2);
7868 restart_file >> initial_coordinates[0] >> initial_coordinates[1];
7871 restart_file.ignore(80,
'\n');
7873 Vector<double> final_coordinates(2);
7876 restart_file >> final_coordinates[0] >> final_coordinates[1];
7879 restart_file.ignore(80,
'\n');
7884 this->boundary_initial_coordinate(b) = initial_coordinates;
7885 this->boundary_final_coordinate(b) = final_coordinates;
7888 Vector<double> zeta_initial(1);
7889 restart_file >> zeta_initial[0];
7892 restart_file.ignore(80,
'\n');
7894 Vector<double> zeta_final(1);
7895 restart_file >> zeta_final[0];
7898 restart_file.ignore(80,
'\n');
7901 this->boundary_initial_zeta_coordinate(b) = zeta_initial;
7902 this->boundary_final_zeta_coordinate(b) = zeta_final;
7905 unsigned current_boundary;
7906 restart_file >> current_boundary;
7909 if (current_boundary != b)
7911 std::ostringstream error_message;
7913 <<
"The current boundary id from the restart file ("
7914 << current_boundary <<
") is different from\nthe boundary id "
7915 << b <<
"currently used to re-establish the initial and\nfinal "
7916 <<
"segment's zeta values\n\n";
7917 throw OomphLibError(
7918 error_message.str(),
7919 "TriangleMesh::read_distributed_info_for_restart()",
7920 OOMPH_EXCEPTION_LOCATION);
7926 restart_file >> nsegments;
7929 restart_file.ignore(80,
'\n');
7934 for (
unsigned is = 0; is < nsegments; is++)
7937 Vector<double> initial_segment_coordinates(2);
7940 restart_file >> initial_segment_coordinates[0] >>
7941 initial_segment_coordinates[1];
7944 restart_file.ignore(80,
'\n');
7946 Vector<double> final_segment_coordinates(2);
7949 restart_file >> final_segment_coordinates[0] >>
7950 final_segment_coordinates[1];
7953 restart_file.ignore(80,
'\n');
7956 this->boundary_segment_initial_coordinate(b).push_back(
7957 initial_segment_coordinates);
7958 this->boundary_segment_final_coordinate(b).push_back(
7959 final_segment_coordinates);
7962 if (this->boundary_geom_object_pt(b) != 0)
7964 Vector<double> zeta_segment_initial(1);
7965 restart_file >> zeta_segment_initial[0];
7968 restart_file.ignore(80,
'\n');
7970 Vector<double> zeta_segment_final(1);
7971 restart_file >> zeta_segment_final[0];
7974 restart_file.ignore(80,
'\n');
7977 this->boundary_segment_initial_zeta(b).push_back(
7978 zeta_segment_initial[0]);
7979 this->boundary_segment_final_zeta(b).push_back(
7980 zeta_segment_final[0]);
7984 Vector<double> arclength_segment_initial(1);
7985 restart_file >> arclength_segment_initial[0];
7988 restart_file.ignore(80,
'\n');
7990 Vector<double> arclength_segment_final(1);
7991 restart_file >> arclength_segment_final[0];
7994 restart_file.ignore(80,
'\n');
7997 this->boundary_segment_initial_arclength(b).push_back(
7998 arclength_segment_initial[0]);
7999 this->boundary_segment_final_arclength(b).push_back(
8000 arclength_segment_final[0]);
8019 template<
class ELEMENT>
8021 std::ostream& outfile)
8030 std::set<Node*> boundary_nodes_pt;
8031 const unsigned n_boundary_ele = this->nboundary_element(b);
8032 for (
unsigned e = 0; e < n_boundary_ele; e++)
8035 FiniteElement* bulk_ele_pt = this->boundary_element_pt(b, e);
8036 #ifdef OOMPH_HAS_MPI
8038 if (!bulk_ele_pt->is_halo())
8042 int face_index = this->face_index_at_boundary(b, e);
8044 FiniteElement* face_ele_pt =
8045 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
8048 const unsigned n_nodes = face_ele_pt->nnode();
8049 for (
unsigned i = 0; i < n_nodes; i++)
8052 Node* tmp_node_pt = face_ele_pt->node_pt(i);
8054 boundary_nodes_pt.insert(tmp_node_pt);
8060 #ifdef OOMPH_HAS_MPI
8066 outfile <<
"ZONE T=\"Boundary nodes" << b <<
"\"\n";
8068 std::set<Vector<double>> set_node_coord;
8070 for (std::set<Node*>::iterator it = boundary_nodes_pt.begin();
8071 it != boundary_nodes_pt.end();
8074 Node* inode_pt = (*it);
8077 const unsigned n_dim = inode_pt->ndim();
8078 Vector<double> node_coord(n_dim + 1);
8081 Vector<double> zeta(1);
8082 inode_pt->get_coordinates_on_boundary(b, zeta);
8083 node_coord[0] = zeta[0];
8084 for (
unsigned j = 0; j < n_dim; j++)
8086 node_coord[j + 1] = inode_pt->x(j);
8088 set_node_coord.insert(node_coord);
8091 for (std::set<Vector<double>>::iterator it = set_node_coord.begin();
8092 it != set_node_coord.end();
8096 Vector<double> node_coord = (*it);
8099 const unsigned n_dim = node_coord.size() - 1;
8100 for (
unsigned j = 0; j < n_dim; j++)
8102 outfile << node_coord[j + 1] <<
" ";
8105 outfile <<
"0.0" << std::endl;
8109 outfile <<
"ZONE T=\"Boundary coordinates " << b <<
"\"\n";
8110 for (std::set<Vector<double>>::iterator it = set_node_coord.begin();
8111 it != set_node_coord.end();
8115 Vector<double> node_coord = (*it);
8118 const unsigned n_dim = node_coord.size() - 1;
8119 for (
unsigned j = 0; j < n_dim; j++)
8121 outfile << node_coord[j + 1] <<
" ";
8125 outfile << node_coord[0] << std::endl;
8129 #ifdef OOMPH_HAS_MPI
8136 template<
class ELEMENT>
8138 Vector<TriangleMeshPolygon*>& polygons_pt,
8139 Vector<TriangleMeshOpenCurve*>& open_curves_pt)
8147 const unsigned my_rank = this->communicator_pt()->my_rank();
8161 Vector<TriangleMeshPolyLine*> unsorted_outer_polyline_pt;
8166 Vector<Vector<TriangleMeshPolyLine*>> sorted_outer_curves_pt;
8169 const unsigned nouter = this->Outer_boundary_pt.size();
8170 for (
unsigned i = 0; i < nouter; i++)
8172 const unsigned npolylines = this->Outer_boundary_pt[i]->npolyline();
8173 for (
unsigned p = 0; p < npolylines; p++)
8176 TriangleMeshPolyLine* tmp_polyline_pt =
8177 this->Outer_boundary_pt[i]->polyline_pt(p);
8178 const unsigned nvertex = tmp_polyline_pt->nvertex();
8184 const unsigned bound_id = tmp_polyline_pt->boundary_id();
8185 if (!boundary_was_splitted(bound_id))
8187 unsorted_outer_polyline_pt.push_back(tmp_polyline_pt);
8192 Vector<TriangleMeshPolyLine*> tmp_vector_polylines =
8193 boundary_subpolylines(bound_id);
8194 const unsigned nsub_poly = tmp_vector_polylines.size();
8198 std::ostringstream error_message;
8199 error_message <<
"The boundary (" << bound_id
8200 <<
") was marked to be splitted but\n"
8201 <<
"there are only (" << nsub_poly
8202 <<
") polylines to represent it.\n";
8203 throw OomphLibError(error_message.str(),
8204 OOMPH_CURRENT_FUNCTION,
8205 OOMPH_EXCEPTION_LOCATION);
8210 for (
unsigned isub = 0; isub < nsub_poly; isub++)
8212 unsorted_outer_polyline_pt.push_back(tmp_vector_polylines[isub]);
8214 const unsigned nsvertex = tmp_vector_polylines[isub]->nvertex();
8217 std::ostringstream error_message;
8219 <<
"The current chunk (" << isub <<
") of the polyline with\n"
8220 <<
"boundary id (" << bound_id <<
") has no vertices\n";
8221 throw OomphLibError(error_message.str(),
8222 OOMPH_CURRENT_FUNCTION,
8223 OOMPH_EXCEPTION_LOCATION);
8233 unsigned nunsorted_outer_polyline = unsorted_outer_polyline_pt.size();
8234 if (nunsorted_outer_polyline > 0)
8238 sort_polylines_helper(unsorted_outer_polyline_pt, sorted_outer_curves_pt);
8249 Vector<TriangleMeshPolyLine*> unsorted_internal_closed_polyline_pt;
8254 Vector<Vector<TriangleMeshPolyLine*>> sorted_internal_closed_curves_pt;
8257 const unsigned ninternal_closed = this->Internal_polygon_pt.size();
8258 for (
unsigned i = 0; i < ninternal_closed; i++)
8260 const unsigned npolylines = this->Internal_polygon_pt[i]->npolyline();
8261 for (
unsigned p = 0; p < npolylines; p++)
8264 TriangleMeshPolyLine* tmp_polyline_pt =
8265 this->Internal_polygon_pt[i]->polyline_pt(p);
8266 const unsigned nvertex = tmp_polyline_pt->nvertex();
8272 const unsigned bound_id = tmp_polyline_pt->boundary_id();
8273 if (!boundary_was_splitted(bound_id))
8275 unsorted_internal_closed_polyline_pt.push_back(tmp_polyline_pt);
8280 Vector<TriangleMeshPolyLine*> tmp_vector_polylines =
8281 boundary_subpolylines(bound_id);
8282 const unsigned nsub_poly = tmp_vector_polylines.size();
8286 std::ostringstream error_message;
8287 error_message <<
"The boundary (" << bound_id
8288 <<
") was marked to be splitted but\n"
8289 <<
"there are only (" << nsub_poly
8290 <<
") polylines to represent it.\n";
8291 throw OomphLibError(error_message.str(),
8292 OOMPH_CURRENT_FUNCTION,
8293 OOMPH_EXCEPTION_LOCATION);
8298 for (
unsigned isub = 0; isub < nsub_poly; isub++)
8300 unsorted_internal_closed_polyline_pt.push_back(
8301 tmp_vector_polylines[isub]);
8303 const unsigned nsvertex = tmp_vector_polylines[isub]->nvertex();
8306 std::ostringstream error_message;
8308 <<
"The current chunk (" << isub <<
") of the polyline with\n"
8309 <<
"boundary id (" << bound_id <<
") has no vertices\n";
8310 throw OomphLibError(error_message.str(),
8311 OOMPH_CURRENT_FUNCTION,
8312 OOMPH_EXCEPTION_LOCATION);
8321 const unsigned nunsorted_internal_closed_polyline =
8322 unsorted_internal_closed_polyline_pt.size();
8324 if (nunsorted_internal_closed_polyline > 0)
8328 sort_polylines_helper(unsorted_internal_closed_polyline_pt,
8329 sorted_internal_closed_curves_pt);
8339 Vector<TriangleMeshPolyLine*> unsorted_internal_open_polyline_pt;
8344 Vector<Vector<TriangleMeshPolyLine*>> sorted_internal_open_curves_pt;
8347 const unsigned ninternal_open = this->Internal_open_curve_pt.size();
8348 for (
unsigned i = 0; i < ninternal_open; i++)
8350 const unsigned ncurve_section =
8351 this->Internal_open_curve_pt[i]->ncurve_section();
8352 for (
unsigned p = 0; p < ncurve_section; p++)
8355 TriangleMeshPolyLine* tmp_polyline_pt =
8356 this->Internal_open_curve_pt[i]->polyline_pt(p);
8357 const unsigned nvertex = tmp_polyline_pt->nvertex();
8363 const unsigned bound_id = tmp_polyline_pt->boundary_id();
8364 if (!boundary_was_splitted(bound_id))
8368 if (!boundary_marked_as_shared_boundary(bound_id, 0))
8370 unsorted_internal_open_polyline_pt.push_back(tmp_polyline_pt);
8376 Vector<TriangleMeshPolyLine*> tmp_vector_polylines =
8377 boundary_subpolylines(bound_id);
8378 const unsigned nsub_poly = tmp_vector_polylines.size();
8382 std::ostringstream error_message;
8383 error_message <<
"The boundary (" << bound_id
8384 <<
") was marked to be splitted but\n"
8385 <<
"there are only (" << nsub_poly
8386 <<
") polylines to represent it.\n";
8387 throw OomphLibError(error_message.str(),
8388 OOMPH_CURRENT_FUNCTION,
8389 OOMPH_EXCEPTION_LOCATION);
8394 for (
unsigned isub = 0; isub < nsub_poly; isub++)
8398 if (!boundary_marked_as_shared_boundary(bound_id, isub))
8400 unsorted_internal_open_polyline_pt.push_back(
8401 tmp_vector_polylines[isub]);
8404 const unsigned nsvertex = tmp_vector_polylines[isub]->nvertex();
8407 std::ostringstream error_message;
8409 <<
"The current chunk (" << isub <<
") of the polyline with\n"
8410 <<
"boundary id (" << bound_id <<
") has no vertices\n";
8411 throw OomphLibError(error_message.str(),
8412 OOMPH_CURRENT_FUNCTION,
8413 OOMPH_EXCEPTION_LOCATION);
8422 const unsigned nunsorted_internal_open_polyline =
8423 unsorted_internal_open_polyline_pt.size();
8425 if (nunsorted_internal_open_polyline > 0)
8429 sort_polylines_helper(unsorted_internal_open_polyline_pt,
8430 sorted_internal_open_curves_pt);
8438 Vector<TriangleMeshPolyLine*> unsorted_shared_polyline_pt;
8442 Vector<TriangleMeshPolyLine*> unsorted_shared_to_internal_polyline_pt;
8447 Vector<Vector<TriangleMeshPolyLine*>> sorted_shared_curves_pt;
8450 const unsigned ncurves = nshared_boundary_curves(my_rank);
8451 for (
unsigned i = 0; i < ncurves; i++)
8453 const unsigned npolylines = nshared_boundary_polyline(my_rank, i);
8454 for (
unsigned p = 0; p < npolylines; p++)
8456 const unsigned nvertex =
8457 shared_boundary_polyline_pt(my_rank, i, p)->nvertex();
8460 TriangleMeshPolyLine* tmp_shared_poly_pt =
8461 shared_boundary_polyline_pt(my_rank, i, p);
8465 if (this->nshared_boundary_overlaps_internal_boundary() > 0)
8468 const unsigned shd_bnd_id = tmp_shared_poly_pt->boundary_id();
8472 if (this->shared_boundary_overlaps_internal_boundary(shd_bnd_id))
8474 unsorted_shared_to_internal_polyline_pt.push_back(
8475 tmp_shared_poly_pt);
8478 unsorted_shared_polyline_pt.push_back(tmp_shared_poly_pt);
8484 const unsigned nunsorted_shared_polyline =
8485 unsorted_shared_polyline_pt.size();
8487 if (nunsorted_shared_polyline > 0)
8491 sort_polylines_helper(unsorted_shared_polyline_pt,
8492 sorted_shared_curves_pt);
8502 const unsigned nouter_curves = sorted_outer_curves_pt.size();
8503 const unsigned ninternal_closed_curves =
8504 sorted_internal_closed_curves_pt.size();
8505 const unsigned nshared_curves = sorted_shared_curves_pt.size();
8506 const unsigned ntotal_curves =
8507 nouter_curves + ninternal_closed_curves + nshared_curves;
8510 unsigned counter = 0;
8511 Vector<Vector<TriangleMeshPolyLine*>> all_curves_pt(ntotal_curves);
8515 for (
unsigned i = 0; i < nshared_curves; i++, counter++)
8517 all_curves_pt[counter] = sorted_shared_curves_pt[i];
8521 for (
unsigned i = 0; i < ninternal_closed_curves; i++, counter++)
8523 all_curves_pt[counter] = sorted_internal_closed_curves_pt[i];
8527 for (
unsigned i = 0; i < nouter_curves; i++, counter++)
8529 all_curves_pt[counter] = sorted_outer_curves_pt[i];
8534 this->create_tmp_polygons_helper(all_curves_pt, polygons_pt);
8536 this->create_tmp_open_curves_helper(sorted_internal_open_curves_pt,
8537 unsorted_shared_to_internal_polyline_pt,
8551 this->create_shared_polylines_connections();
8562 Vector<Vector<double>> new_holes_coordinates;
8568 const unsigned n_holes = this->Internal_polygon_pt.size();
8569 for (
unsigned h = 0; h < n_holes; h++)
8571 Vector<double> hole_coordinates =
8572 this->Internal_polygon_pt[h]->internal_point();
8574 if (!hole_coordinates.empty())
8576 new_holes_coordinates.push_back(hole_coordinates);
8582 if (First_time_compute_holes_left_by_halo_elements)
8585 const unsigned n_extra_holes = Extra_holes_coordinates.size();
8586 for (
unsigned h = 0; h < n_extra_holes; h++)
8588 Vector<double> hole_coordinates = Extra_holes_coordinates[h];
8589 new_holes_coordinates.push_back(hole_coordinates);
8593 Original_extra_holes_coordinates = Extra_holes_coordinates;
8596 First_time_compute_holes_left_by_halo_elements =
false;
8603 const unsigned n_original_extra_holes =
8604 Original_extra_holes_coordinates.size();
8605 for (
unsigned h = 0; h < n_original_extra_holes; h++)
8607 Vector<double> hole_coordinates = Original_extra_holes_coordinates[h];
8608 new_holes_coordinates.push_back(hole_coordinates);
8614 compute_holes_left_by_halo_elements_helper(new_holes_coordinates);
8618 update_holes_information_helper(polygons_pt, new_holes_coordinates);
8624 Extra_holes_coordinates = new_holes_coordinates;
8636 template<
class ELEMENT>
8638 Vector<Vector<TriangleMeshPolyLine*>>& polylines_pt,
8639 Vector<TriangleMeshPolygon*>& polygons_pt)
8651 const unsigned ncurves = polylines_pt.size();
8654 const unsigned nunsorted_curves = ncurves;
8656 unsigned nsorted_curves = 0;
8659 std::vector<bool> done_curve(ncurves);
8664 std::list<Vector<TriangleMeshPolyLine*>> list_building_polygon_pt;
8667 bool root_curve_found =
false;
8672 unsigned root_curve_idx = 0;
8675 for (
unsigned ic = 0; ic < ncurves; ic++)
8677 if (!done_curve[ic])
8679 root_curve_idx = ic;
8682 root_curve_found =
true;
8684 done_curve[ic] =
true;
8691 if (!root_curve_found)
8693 std::stringstream err;
8694 err <<
"The root curve to create a polygon from the shared and "
8695 <<
"original boundaries was not found!!!\n";
8696 throw OomphLibError(err.str(),
8697 "TriangleMesh::create_tmp_polygons_helper()",
8698 OOMPH_EXCEPTION_LOCATION);
8703 Vector<TriangleMeshPolyLine*> root_curve_pt =
8704 polylines_pt[root_curve_idx];
8707 list_building_polygon_pt.push_back(root_curve_pt);
8710 Vector<double> root_curve_initial_vertex(2);
8711 Vector<double> root_curve_final_vertex(2);
8714 const unsigned nroot_curve_polyline = root_curve_pt.size();
8716 root_curve_pt[0]->initial_vertex_coordinate(root_curve_initial_vertex);
8717 root_curve_pt[nroot_curve_polyline - 1]->final_vertex_coordinate(
8718 root_curve_final_vertex);
8722 ((root_curve_initial_vertex[0] - root_curve_final_vertex[0]) *
8723 (root_curve_initial_vertex[0] - root_curve_final_vertex[0])) +
8724 ((root_curve_initial_vertex[1] - root_curve_final_vertex[1]) *
8725 (root_curve_initial_vertex[1] - root_curve_final_vertex[1]));
8727 if (diff < ToleranceForVertexMismatchInPolygons::Tolerable_error)
8731 Vector<TriangleMeshCurveSection*> curve_section_pt(
8732 nroot_curve_polyline);
8735 for (
unsigned i = 0; i < nroot_curve_polyline; i++)
8737 curve_section_pt[i] = root_curve_pt[i];
8741 TriangleMeshPolygon* new_polygon_pt =
8742 new TriangleMeshPolygon(curve_section_pt);
8745 this->Free_polygon_pt.insert(new_polygon_pt);
8748 polygons_pt.push_back(new_polygon_pt);
8755 bool added_curve =
false;
8760 bool polygon_created =
false;
8764 added_curve =
false;
8767 for (
unsigned ic = root_curve_idx + 1; ic < ncurves; ic++)
8769 if (!done_curve[ic])
8772 Vector<TriangleMeshPolyLine*> current_curve_pt = polylines_pt[ic];
8776 const unsigned ncurrent_curve_polyline = current_curve_pt.size();
8780 Vector<double> current_curve_initial_vertex(2);
8781 Vector<double> current_curve_final_vertex(2);
8783 current_curve_pt[0]->initial_vertex_coordinate(
8784 current_curve_initial_vertex);
8785 current_curve_pt[ncurrent_curve_polyline - 1]
8786 ->final_vertex_coordinate(current_curve_final_vertex);
8791 diff = ((current_curve_final_vertex[0] -
8792 root_curve_initial_vertex[0]) *
8793 (current_curve_final_vertex[0] -
8794 root_curve_initial_vertex[0])) +
8795 ((current_curve_final_vertex[1] -
8796 root_curve_initial_vertex[1]) *
8797 (current_curve_final_vertex[1] -
8798 root_curve_initial_vertex[1]));
8801 if (diff < ToleranceForVertexMismatchInPolygons::Tolerable_error)
8804 list_building_polygon_pt.push_front(current_curve_pt);
8806 done_curve[ic] =
true;
8808 root_curve_initial_vertex[0] = current_curve_initial_vertex[0];
8809 root_curve_initial_vertex[1] = current_curve_initial_vertex[1];
8817 diff = ((current_curve_initial_vertex[0] -
8818 root_curve_initial_vertex[0]) *
8819 (current_curve_initial_vertex[0] -
8820 root_curve_initial_vertex[0])) +
8821 ((current_curve_initial_vertex[1] -
8822 root_curve_initial_vertex[1]) *
8823 (current_curve_initial_vertex[1] -
8824 root_curve_initial_vertex[1]));
8827 if (diff < ToleranceForVertexMismatchInPolygons::Tolerable_error)
8829 Vector<TriangleMeshPolyLine*> tmp_curve_pt(
8830 ncurrent_curve_polyline);
8832 for (
unsigned it = 0; it < ncurrent_curve_polyline; it++)
8834 current_curve_pt[it]->reverse();
8835 tmp_curve_pt[it] = current_curve_pt[it];
8839 for (
int i = ncurrent_curve_polyline - 1; i >= 0; i--, count++)
8841 current_curve_pt[count] = tmp_curve_pt[i];
8844 list_building_polygon_pt.push_front(current_curve_pt);
8846 done_curve[ic] =
true;
8848 root_curve_initial_vertex[0] = current_curve_final_vertex[0];
8849 root_curve_initial_vertex[1] = current_curve_final_vertex[1];
8857 diff = ((current_curve_initial_vertex[0] -
8858 root_curve_final_vertex[0]) *
8859 (current_curve_initial_vertex[0] -
8860 root_curve_final_vertex[0])) +
8861 ((current_curve_initial_vertex[1] -
8862 root_curve_final_vertex[1]) *
8863 (current_curve_initial_vertex[1] -
8864 root_curve_final_vertex[1]));
8867 if (diff < ToleranceForVertexMismatchInPolygons::Tolerable_error)
8870 list_building_polygon_pt.push_back(current_curve_pt);
8872 done_curve[ic] =
true;
8874 root_curve_final_vertex[0] = current_curve_final_vertex[0];
8875 root_curve_final_vertex[1] = current_curve_final_vertex[1];
8884 ((current_curve_final_vertex[0] - root_curve_final_vertex[0]) *
8885 (current_curve_final_vertex[0] - root_curve_final_vertex[0])) +
8886 ((current_curve_final_vertex[1] - root_curve_final_vertex[1]) *
8887 (current_curve_final_vertex[1] - root_curve_final_vertex[1]));
8890 if (diff < ToleranceForVertexMismatchInPolygons::Tolerable_error)
8892 Vector<TriangleMeshPolyLine*> tmp_curve_pt(
8893 ncurrent_curve_polyline);
8895 for (
unsigned it = 0; it < ncurrent_curve_polyline; it++)
8897 current_curve_pt[it]->reverse();
8898 tmp_curve_pt[it] = current_curve_pt[it];
8902 for (
int i = ncurrent_curve_polyline - 1; i >= 0; i--, count++)
8904 current_curve_pt[count] = tmp_curve_pt[i];
8907 list_building_polygon_pt.push_back(current_curve_pt);
8909 done_curve[ic] =
true;
8911 root_curve_final_vertex[0] = current_curve_initial_vertex[0];
8912 root_curve_final_vertex[1] = current_curve_initial_vertex[1];
8926 ((root_curve_initial_vertex[0] - root_curve_final_vertex[0]) *
8927 (root_curve_initial_vertex[0] - root_curve_final_vertex[0])) +
8928 ((root_curve_initial_vertex[1] - root_curve_final_vertex[1]) *
8929 (root_curve_initial_vertex[1] - root_curve_final_vertex[1]));
8931 if (diff < ToleranceForVertexMismatchInPolygons::Tolerable_error)
8935 added_curve =
false;
8938 polygon_created =
true;
8944 }
while (added_curve);
8947 if (!polygon_created)
8949 std::stringstream error_message;
8951 <<
"It was no possible to create a TriangleMeshPolygon with "
8952 <<
"the input set of curves\n"
8953 <<
"These are the initial and final vertices in the current "
8954 <<
"sorted list of\nTriangleMeshPolyLines\n\n";
8955 Vector<double> init_vertex(2);
8956 Vector<double> final_vertex(2);
8957 unsigned icurve = 0;
8958 for (std::list<Vector<TriangleMeshPolyLine*>>::iterator it =
8959 list_building_polygon_pt.begin();
8960 it != list_building_polygon_pt.end();
8963 const unsigned ncurrent_curve_polyline = (*it).size();
8964 error_message <<
"TriangleMeshCurve #" << icurve <<
"\n"
8965 <<
"-----------------------------------\n";
8966 for (
unsigned ip = 0; ip < ncurrent_curve_polyline; ip++)
8968 Vector<double> init_vertex(2);
8969 Vector<double> final_vertex(2);
8970 (*it)[ip]->initial_vertex_coordinate(init_vertex);
8971 (*it)[ip]->final_vertex_coordinate(final_vertex);
8972 error_message <<
"TriangleMeshPolyLine #" << ip <<
"\n"
8973 <<
"Initial vertex: (" << init_vertex[0] <<
","
8974 << init_vertex[1] <<
")\n"
8975 <<
"Final vertex: (" << final_vertex[0] <<
","
8976 << final_vertex[1] <<
")\n";
8980 throw OomphLibError(error_message.str(),
8981 "TriangleMesh::create_tmp_polygons_helper()",
8982 OOMPH_EXCEPTION_LOCATION);
8988 unsigned ntotal_polylines = 0;
8990 for (std::list<Vector<TriangleMeshPolyLine*>>::iterator it =
8991 list_building_polygon_pt.begin();
8992 it != list_building_polygon_pt.end();
8995 ntotal_polylines += (*it).size();
8999 Vector<TriangleMeshCurveSection*> curve_section_pt(ntotal_polylines);
9002 unsigned counter = 0;
9003 for (std::list<Vector<TriangleMeshPolyLine*>>::iterator it =
9004 list_building_polygon_pt.begin();
9005 it != list_building_polygon_pt.end();
9008 const unsigned ncurrent_curve_polyline = (*it).size();
9009 for (
unsigned ip = 0; ip < ncurrent_curve_polyline; ip++, counter++)
9011 curve_section_pt[counter] = (*it)[ip];
9016 TriangleMeshPolygon* new_polygon_pt =
9017 new TriangleMeshPolygon(curve_section_pt);
9020 this->Free_polygon_pt.insert(new_polygon_pt);
9023 polygons_pt.push_back(new_polygon_pt);
9028 }
while (nsorted_curves < nunsorted_curves);
9036 template<
class ELEMENT>
9038 Vector<Vector<TriangleMeshPolyLine*>>& sorted_open_curves_pt,
9039 Vector<TriangleMeshPolyLine*>& unsorted_shared_to_internal_poly_pt,
9040 Vector<TriangleMeshOpenCurve*>& open_curves_pt)
9044 const unsigned ninternal_open_curves = sorted_open_curves_pt.size();
9048 for (
unsigned i = 0; i < ninternal_open_curves; i++)
9051 const unsigned npoly = sorted_open_curves_pt[i].size();
9052 Vector<TriangleMeshCurveSection*> tmp_curve_section(npoly);
9053 for (
unsigned j = 0; j < npoly; j++)
9055 tmp_curve_section[j] = sorted_open_curves_pt[i][j];
9058 TriangleMeshOpenCurve* new_open_curve_pt =
9059 new TriangleMeshOpenCurve(tmp_curve_section);
9062 this->Free_open_curve_pt.insert(new_open_curve_pt);
9065 open_curves_pt.push_back(new_open_curve_pt);
9076 template<
class ELEMENT>
9078 std::set<FiniteElement*>& element_in_processor_pt,
9079 const int& root_edge_bnd_id,
9080 std::map<std::pair<Node*, Node*>,
bool>& overlapped_face,
9081 std::map<
unsigned, std::map<Node*, bool>>&
9082 node_on_bnd_not_overlapped_by_shd_bnd,
9083 std::list<Node*>& current_polyline_nodes,
9084 std::map<
unsigned, std::list<Node*>>& shared_bnd_id_to_sorted_list_node_pt,
9085 const unsigned& node_degree,
9087 const bool called_from_load_balance)
9090 int flag_to_return = -1;
9099 bool overlapping_internal_boundary =
false;
9101 unsigned internal_overlaping_bnd_id = 0;
9102 if (root_edge_bnd_id != -1)
9105 overlapping_internal_boundary =
true;
9107 internal_overlaping_bnd_id =
static_cast<unsigned>(root_edge_bnd_id);
9115 if (new_node_pt->is_on_boundary())
9118 bool is_node_living_in_non_overlapped_boundary =
false;
9122 const unsigned noriginal_bnd = this->initial_shared_boundary_id();
9123 for (
unsigned bb = 0; bb < noriginal_bnd; bb++)
9131 if (overlapping_internal_boundary)
9134 if (new_node_pt->is_on_boundary(bb))
9140 const bool on_bnd_edge_not_overlapped_by_shd_bnd =
9141 node_on_bnd_not_overlapped_by_shd_bnd[bb][new_node_pt];
9142 if (bb != internal_overlaping_bnd_id ||
9143 ((bb == internal_overlaping_bnd_id) &&
9144 (on_bnd_edge_not_overlapped_by_shd_bnd)))
9147 if (bb != internal_overlaping_bnd_id)
9149 is_node_living_in_non_overlapped_boundary =
true;
9159 const unsigned n_bound_ele = this->nboundary_element(bb);
9160 if (n_bound_ele > 0)
9164 for (
unsigned e = 0; e < n_bound_ele; e++)
9167 FiniteElement* bulk_ele_pt = this->boundary_element_pt(bb, e);
9170 std::set<FiniteElement*>::iterator it =
9171 element_in_processor_pt.find(bulk_ele_pt);
9173 if (it != element_in_processor_pt.end())
9176 bool found_node =
false;
9178 int face_index = this->face_index_at_boundary(bb, e);
9180 FiniteElement* face_ele_pt =
9181 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
9183 const unsigned n_node_face = face_ele_pt->nnode();
9185 Node* first_node_pt = face_ele_pt->node_pt(0);
9186 Node* last_node_pt = face_ele_pt->node_pt(n_node_face - 1);
9188 std::pair<Node*, Node*> tmp_edge =
9189 std::make_pair(first_node_pt, last_node_pt);
9193 if (!overlapped_face[tmp_edge])
9196 for (
unsigned n = 0; n < n_node_face; n++)
9199 if (face_ele_pt->node_pt(n) == new_node_pt)
9215 flag_to_return = bb;
9216 return flag_to_return;
9235 if (new_node_pt->is_on_boundary(bb))
9244 const unsigned n_bound_ele = this->nboundary_element(bb);
9245 if (n_bound_ele > 0)
9249 for (
unsigned e = 0; e < n_bound_ele; e++)
9252 FiniteElement* bulk_ele_pt = this->boundary_element_pt(bb, e);
9255 std::set<FiniteElement*>::iterator it =
9256 element_in_processor_pt.find(bulk_ele_pt);
9258 if (it != element_in_processor_pt.end())
9261 bool found_node =
false;
9263 int face_index = this->face_index_at_boundary(bb, e);
9265 FiniteElement* face_ele_pt =
9266 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
9268 const unsigned n_node_face = face_ele_pt->nnode();
9270 Node* first_node_pt = face_ele_pt->node_pt(0);
9271 Node* last_node_pt = face_ele_pt->node_pt(n_node_face - 1);
9273 std::pair<Node*, Node*> tmp_edge =
9274 std::make_pair(first_node_pt, last_node_pt);
9278 if (!overlapped_face[tmp_edge])
9281 for (
unsigned n = 0; n < n_node_face; n++)
9284 if (face_ele_pt->node_pt(n) == new_node_pt)
9300 flag_to_return = bb;
9301 return flag_to_return;
9326 if (!overlapping_internal_boundary)
9331 flag_to_return = -3;
9338 if (is_node_living_in_non_overlapped_boundary)
9340 flag_to_return = -3;
9349 if (flag_to_return >= 0)
9351 return flag_to_return;
9362 Vector<unsigned> candidate_shared_bnd_to_connect;
9364 for (std::map<
unsigned, std::list<Node*>>::iterator it =
9365 shared_bnd_id_to_sorted_list_node_pt.begin();
9366 it != shared_bnd_id_to_sorted_list_node_pt.end();
9372 const unsigned i_bnd_id = (*it).first;
9375 std::list<Node*>::iterator it_list = (*it).second.begin();
9377 const unsigned n_nodes = (*it).second.size();
9379 for (
unsigned i = 0; i < n_nodes; i++, it_list++)
9382 if ((*it_list) == new_node_pt)
9386 candidate_shared_bnd_to_connect.push_back(i_bnd_id);
9397 const unsigned n_candidate_shared_bnd_to_connect =
9398 candidate_shared_bnd_to_connect.size();
9401 if (n_candidate_shared_bnd_to_connect > 0)
9408 if (called_from_load_balance)
9410 return candidate_shared_bnd_to_connect[0];
9420 Vector<unsigned> shared_bound_in_this_proc;
9423 shared_boundaries_in_this_processor(shared_bound_in_this_proc);
9429 const unsigned n_shared_bound_in_this_proc =
9430 shared_bound_in_this_proc.size();
9433 for (
unsigned i = 0; i < n_candidate_shared_bnd_to_connect; i++)
9436 const unsigned i_candidate_shared_bnd =
9437 candidate_shared_bnd_to_connect[i];
9440 for (
unsigned j = 0; j < n_shared_bound_in_this_proc; j++)
9443 if (i_candidate_shared_bnd == shared_bound_in_this_proc[j])
9446 flag_to_return = i_candidate_shared_bnd;
9447 return flag_to_return;
9458 flag_to_return = -3;
9464 if (flag_to_return >= 0)
9466 return flag_to_return;
9475 unsigned nrepeated = 0;
9476 for (std::list<Node*>::iterator it_list = current_polyline_nodes.begin();
9477 it_list != current_polyline_nodes.end();
9482 if ((*it_list) == new_node_pt)
9494 flag_to_return = -2;
9500 if (node_degree > 2)
9502 flag_to_return = -3;
9506 return flag_to_return;
9516 template<
class ELEMENT>
9520 const unsigned my_rank = this->communicator_pt()->my_rank();
9523 Vector<Vector<TriangleMeshPolyLine*>> shared_curves_pt =
9524 this->Shared_boundary_polyline_pt[my_rank];
9528 const unsigned ncurves = shared_curves_pt.size();
9529 for (
unsigned icurve = 0; icurve < ncurves; icurve++)
9532 const unsigned npoly = shared_curves_pt[icurve].size();
9533 for (
unsigned ipoly = 0; ipoly < npoly; ipoly++)
9536 TriangleMeshPolyLine* shd_poly_pt = shared_curves_pt[icurve][ipoly];
9539 const unsigned bound_id = shd_poly_pt->boundary_id();
9542 const bool is_connected_to_the_left =
9543 shd_poly_pt->is_initial_vertex_connected();
9546 const bool is_connected_to_the_right =
9547 shd_poly_pt->is_final_vertex_connected();
9552 if (is_connected_to_the_left || is_connected_to_the_right)
9556 const unsigned n_vertex = shd_poly_pt->nvertex();
9563 if (is_connected_to_the_left)
9567 const unsigned uconnection_to_the_left =
9568 shd_poly_pt->initial_vertex_connected_bnd_id();
9571 TriangleMeshPolyLine* poly_to_connect_pt = 0;
9575 bool connecting_to_an_split_boundary =
false;
9579 bool connecting_to_an_overlaped_boundary =
false;
9582 if (uconnection_to_the_left == bound_id)
9585 poly_to_connect_pt = shd_poly_pt;
9590 const unsigned initial_shd_bnd_id = initial_shared_boundary_id();
9592 if (uconnection_to_the_left >= initial_shd_bnd_id)
9596 poly_to_connect_pt =
9597 boundary_polyline_pt(uconnection_to_the_left);
9605 if (boundary_was_splitted(uconnection_to_the_left))
9607 connecting_to_an_split_boundary =
true;
9617 if (connecting_to_an_split_boundary)
9621 const unsigned n_sub_poly =
9622 nboundary_subpolylines(uconnection_to_the_left);
9627 for (
unsigned ii = 0; ii < n_sub_poly; ii++)
9629 if (boundary_marked_as_shared_boundary(
9630 uconnection_to_the_left, ii))
9634 connecting_to_an_overlaped_boundary =
true;
9645 if (boundary_marked_as_shared_boundary(
9646 uconnection_to_the_left, 0))
9650 connecting_to_an_overlaped_boundary =
true;
9657 if (!(connecting_to_an_split_boundary ||
9658 connecting_to_an_overlaped_boundary))
9662 poly_to_connect_pt =
9663 boundary_polyline_pt(uconnection_to_the_left);
9674 if (!connecting_to_an_split_boundary)
9676 if (boundary_was_splitted(uconnection_to_the_left))
9678 std::stringstream error;
9680 <<
"The current shared boundary (" << bound_id <<
") was "
9681 <<
"marked to have a connection\nto the left with the "
9682 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9683 <<
"The problem is that the destination boundary (possibly\n"
9684 <<
"another shared boundary) is marked to be split\n"
9685 <<
"There should not be split shared boundaries\n\n";
9686 throw OomphLibError(
9688 "TriangleMesh::create_shared_polylines_connections()",
9689 OOMPH_EXCEPTION_LOCATION);
9702 Vector<double> shd_bnd_left_vertex =
9703 shd_poly_pt->vertex_coordinate(0);
9706 if (!connecting_to_an_split_boundary)
9710 if (!connecting_to_an_overlaped_boundary)
9714 unsigned vertex_index = 0;
9716 const bool found_vertex_index =
9717 get_connected_vertex_number_on_destination_polyline(
9718 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9722 if (!found_vertex_index)
9724 std::stringstream error;
9726 <<
"The current shared boundary (" << bound_id <<
") was "
9727 <<
"marked to have a connection\nto the left with the "
9728 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9729 <<
"The problem is that the left vertex of the current\n"
9730 <<
"shared boundary is not in the list of vertices of the\n"
9731 <<
"boundary to connect.\n\n"
9732 <<
"This is the left vertex of the current shared "
9734 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", "
9735 << shd_bnd_left_vertex[1] <<
")\n\n"
9736 <<
"This is the list of vertices on the destination "
9738 const unsigned n_v = poly_to_connect_pt->nvertex();
9739 for (
unsigned i = 0; i < n_v; i++)
9741 Vector<double> cvertex =
9742 poly_to_connect_pt->vertex_coordinate(i);
9743 error <<
"Vertex #" << i <<
": (" << cvertex[0] <<
", "
9744 << cvertex[1] <<
")\n";
9746 throw OomphLibError(
9748 "TriangleMesh::create_shared_polylines_connections()",
9749 OOMPH_EXCEPTION_LOCATION);
9755 shd_poly_pt->connect_initial_vertex_to_polyline(
9756 poly_to_connect_pt, vertex_index);
9766 unsigned vertex_index = 0;
9768 bool found_vertex_index =
false;
9772 Vector<unsigned> dst_shd_bnd_ids;
9773 get_shared_boundaries_overlapping_internal_boundary(
9774 uconnection_to_the_left, dst_shd_bnd_ids);
9778 const unsigned n_shd_bnd_overlap_int_bnd =
9779 dst_shd_bnd_ids.size();
9783 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
9786 const unsigned new_connection_to_the_left =
9787 dst_shd_bnd_ids[ss];
9791 poly_to_connect_pt =
9792 boundary_polyline_pt(new_connection_to_the_left);
9794 if (poly_to_connect_pt != 0)
9798 found_vertex_index =
9799 get_connected_vertex_number_on_destination_polyline(
9800 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9805 if (found_vertex_index)
9815 if (!found_vertex_index)
9817 std::stringstream error;
9819 <<
"The current shared boundary (" << bound_id <<
") was "
9820 <<
"marked to have a connection\nto the left with the "
9821 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9822 <<
"This last boundary is marked to be overlaped by "
9823 <<
"shared boundaries\n"
9824 <<
"The problem is that the left vertex of the current\n"
9825 <<
"shared boundary is not in the list of vertices of the\n"
9826 <<
"boundary to connect.\n\n"
9827 <<
"This is the left vertex of the current shared "
9829 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", "
9830 << shd_bnd_left_vertex[1] <<
")\n\n"
9831 <<
"This is the list of vertices on the destination "
9833 Vector<unsigned> dst_shd_bnd_ids;
9834 get_shared_boundaries_overlapping_internal_boundary(
9835 uconnection_to_the_left, dst_shd_bnd_ids);
9836 const unsigned n_shd_bnd_overlap_int_bnd =
9837 dst_shd_bnd_ids.size();
9838 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
9840 const unsigned new_connection_to_the_left =
9841 dst_shd_bnd_ids[ss];
9842 poly_to_connect_pt =
9843 boundary_polyline_pt(new_connection_to_the_left);
9844 if (poly_to_connect_pt != 0)
9846 const unsigned shd_bnd_id_overlap =
9847 poly_to_connect_pt->boundary_id();
9848 error <<
"Shared boundary id(" << shd_bnd_id_overlap
9850 const unsigned n_v = poly_to_connect_pt->nvertex();
9851 for (
unsigned i = 0; i < n_v; i++)
9853 Vector<double> cvertex =
9854 poly_to_connect_pt->vertex_coordinate(i);
9855 error <<
"Vertex #" << i <<
": (" << cvertex[0] <<
", "
9856 << cvertex[1] <<
")\n";
9861 throw OomphLibError(
9863 "TriangleMesh::create_shared_polylines_connections()",
9864 OOMPH_EXCEPTION_LOCATION);
9872 shd_poly_pt->connect_initial_vertex_to_polyline(
9873 poly_to_connect_pt, vertex_index);
9884 Vector<TriangleMeshPolyLine*> tmp_vector_subpolylines =
9885 boundary_subpolylines(uconnection_to_the_left);
9888 const unsigned nsub_poly = tmp_vector_subpolylines.size();
9892 std::ostringstream error_message;
9894 <<
"The boundary (" << uconnection_to_the_left <<
") was "
9895 <<
"marked to be splitted but\n"
9896 <<
"there are only (" << nsub_poly <<
") polylines to "
9897 <<
"represent it.\n";
9898 throw OomphLibError(
9899 error_message.str(),
9900 "TriangleMesh::create_shared_polylines_connections()",
9901 OOMPH_EXCEPTION_LOCATION);
9913 if (!connecting_to_an_overlaped_boundary)
9919 unsigned vertex_index = 0;
9921 unsigned sub_poly_to_connect = 0;
9923 bool found_vertex_index =
false;
9927 for (
unsigned isub = 0; isub < nsub_poly; isub++)
9930 poly_to_connect_pt = tmp_vector_subpolylines[isub];
9932 found_vertex_index =
9933 get_connected_vertex_number_on_destination_polyline(
9934 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9937 if (found_vertex_index)
9941 sub_poly_to_connect = isub;
9949 if (!found_vertex_index)
9951 std::stringstream error;
9953 <<
"The current shared boundary (" << bound_id <<
") was "
9954 <<
"marked to have a connection\nto the left with the "
9955 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9956 <<
"The problem is that the left vertex of the current\n"
9957 <<
"shared boundary is not in the list of vertices of any\n"
9958 <<
"of the sub polylines that represent the boundary to\n"
9960 <<
"This is the left vertex of the current shared "
9962 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", "
9963 << shd_bnd_left_vertex[1] <<
")\n\n"
9964 <<
"This is the list of vertices on the destination "
9966 for (
unsigned p = 0; p < nsub_poly; p++)
9968 error <<
"Subpolyline #(" << p <<
")\n";
9969 poly_to_connect_pt = tmp_vector_subpolylines[p];
9970 const unsigned n_v = poly_to_connect_pt->nvertex();
9971 for (
unsigned i = 0; i < n_v; i++)
9973 Vector<double> cvertex =
9974 poly_to_connect_pt->vertex_coordinate(i);
9975 error <<
"Vertex #" << i <<
": (" << cvertex[0] <<
", "
9976 << cvertex[1] <<
")\n";
9979 throw OomphLibError(
9981 "TriangleMesh::create_shared_polylines_connections()",
9982 OOMPH_EXCEPTION_LOCATION);
9990 shd_poly_pt->connect_initial_vertex_to_polyline(
9991 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
10002 unsigned vertex_index = 0;
10004 unsigned sub_poly_to_connect = 0;
10006 bool found_vertex_index =
false;
10010 Vector<unsigned> dst_shd_bnd_ids;
10011 get_shared_boundaries_overlapping_internal_boundary(
10012 uconnection_to_the_left, dst_shd_bnd_ids);
10016 const unsigned n_shd_bnd_overlap_int_bnd =
10017 dst_shd_bnd_ids.size();
10021 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10024 const unsigned new_connection_to_the_left =
10025 dst_shd_bnd_ids[ss];
10029 if (bound_id != new_connection_to_the_left)
10033 poly_to_connect_pt =
10034 boundary_polyline_pt(new_connection_to_the_left);
10036 if (poly_to_connect_pt != 0)
10040 found_vertex_index =
10041 get_connected_vertex_number_on_destination_polyline(
10042 poly_to_connect_pt,
10043 shd_bnd_left_vertex,
10049 if (found_vertex_index)
10061 if (!found_vertex_index)
10065 for (
unsigned isub = 0; isub < nsub_poly; isub++)
10069 if (!boundary_marked_as_shared_boundary(
10070 uconnection_to_the_left, isub))
10073 poly_to_connect_pt = tmp_vector_subpolylines[isub];
10075 found_vertex_index =
10076 get_connected_vertex_number_on_destination_polyline(
10077 poly_to_connect_pt,
10078 shd_bnd_left_vertex,
10082 if (found_vertex_index)
10086 sub_poly_to_connect = isub;
10099 if (!found_vertex_index)
10101 std::stringstream error;
10103 <<
"The current shared boundary (" << bound_id <<
") was "
10104 <<
"marked to have a connection\nto the left with the "
10105 <<
"boundary (" << uconnection_to_the_left <<
").\n"
10106 <<
"This last boundary is marked to be overlaped by "
10107 <<
"shared boundaries\n"
10108 <<
"The problem is that the left vertex of the current\n"
10109 <<
"shared boundary is not in the list of vertices of "
10110 <<
"the\nboundary to connect.\n\n"
10111 <<
"This is the left vertex of the current shared "
10113 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", "
10114 << shd_bnd_left_vertex[1] <<
")\n\n"
10115 <<
"This is the list of vertices on the destination "
10116 <<
"boundary (only those subpolylines not marked as "
10117 <<
"overlaped by\nshared boundaries)\n";
10118 for (
unsigned p = 0; p < nsub_poly; p++)
10120 if (!boundary_marked_as_shared_boundary(
10121 uconnection_to_the_left, p))
10123 error <<
"Subpolyline #(" << p <<
")\n";
10124 poly_to_connect_pt = tmp_vector_subpolylines[p];
10125 const unsigned n_v = poly_to_connect_pt->nvertex();
10126 for (
unsigned i = 0; i < n_v; i++)
10128 Vector<double> cvertex =
10129 poly_to_connect_pt->vertex_coordinate(i);
10130 error <<
"Vertex #" << i <<
": (" << cvertex[0] <<
", "
10131 << cvertex[1] <<
")\n";
10135 error <<
"\nThis is the list of vertices of the shared "
10136 <<
"polylines that overlap\nthe internal "
10138 Vector<unsigned> dst_shd_bnd_ids;
10139 get_shared_boundaries_overlapping_internal_boundary(
10140 uconnection_to_the_left, dst_shd_bnd_ids);
10141 const unsigned n_shd_bnd_overlap_int_bnd =
10142 dst_shd_bnd_ids.size();
10143 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10145 const unsigned new_connection_to_the_left =
10146 dst_shd_bnd_ids[ss];
10147 poly_to_connect_pt =
10148 boundary_polyline_pt(new_connection_to_the_left);
10149 if (poly_to_connect_pt != 0)
10151 const unsigned shd_bnd_id_overlap =
10152 poly_to_connect_pt->boundary_id();
10153 error <<
"Shared boundary id(" << shd_bnd_id_overlap
10155 const unsigned n_v = poly_to_connect_pt->nvertex();
10156 for (
unsigned i = 0; i < n_v; i++)
10158 Vector<double> cvertex =
10159 poly_to_connect_pt->vertex_coordinate(i);
10160 error <<
"Vertex #" << i <<
": (" << cvertex[0] <<
", "
10161 << cvertex[1] <<
")\n";
10166 throw OomphLibError(
10168 "TriangleMesh::create_shared_polylines_connections()",
10169 OOMPH_EXCEPTION_LOCATION);
10177 shd_poly_pt->connect_initial_vertex_to_polyline(
10178 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
10188 if (is_connected_to_the_right)
10192 const unsigned uconnection_to_the_right =
10193 shd_poly_pt->final_vertex_connected_bnd_id();
10196 TriangleMeshPolyLine* poly_to_connect_pt = 0;
10200 bool connecting_to_an_split_boundary =
false;
10204 bool connecting_to_an_overlaped_boundary =
false;
10207 if (uconnection_to_the_right == bound_id)
10210 poly_to_connect_pt = shd_poly_pt;
10215 const unsigned initial_shd_bnd_id = initial_shared_boundary_id();
10217 if (uconnection_to_the_right >= initial_shd_bnd_id)
10221 poly_to_connect_pt =
10222 boundary_polyline_pt(uconnection_to_the_right);
10230 if (boundary_was_splitted(uconnection_to_the_right))
10232 connecting_to_an_split_boundary =
true;
10242 if (connecting_to_an_split_boundary)
10246 const unsigned n_sub_poly =
10247 nboundary_subpolylines(uconnection_to_the_right);
10252 for (
unsigned ii = 0; ii < n_sub_poly; ii++)
10254 if (boundary_marked_as_shared_boundary(
10255 uconnection_to_the_right, ii))
10259 connecting_to_an_overlaped_boundary =
true;
10270 if (boundary_marked_as_shared_boundary(
10271 uconnection_to_the_right, 0))
10275 connecting_to_an_overlaped_boundary =
true;
10282 if (!(connecting_to_an_split_boundary ||
10283 connecting_to_an_overlaped_boundary))
10287 poly_to_connect_pt =
10288 boundary_polyline_pt(uconnection_to_the_right);
10299 if (!connecting_to_an_split_boundary)
10301 if (boundary_was_splitted(uconnection_to_the_right))
10303 std::stringstream error;
10305 <<
"The current shared boundary (" << bound_id <<
") was "
10306 <<
"marked to have a connection\nto the right with the "
10307 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10308 <<
"The problem is that the destination boundary (possibly\n"
10309 <<
"another shared boundary) is marked to be split\n"
10310 <<
"There should not be split shared boundaries\n\n";
10311 throw OomphLibError(
10313 "TriangleMesh::create_shared_polylines_connections()",
10314 OOMPH_EXCEPTION_LOCATION);
10327 Vector<double> shd_bnd_right_vertex =
10328 shd_poly_pt->vertex_coordinate(n_vertex - 1);
10332 if (!connecting_to_an_split_boundary)
10336 if (!connecting_to_an_overlaped_boundary)
10341 unsigned vertex_index = 0;
10342 const bool found_vertex_index =
10343 get_connected_vertex_number_on_destination_polyline(
10344 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10348 if (!found_vertex_index)
10350 std::stringstream error;
10352 <<
"The current shared boundary (" << bound_id <<
") was "
10353 <<
"marked to have a connection\nto the right with the "
10354 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10355 <<
"The problem is that the right vertex of the current\n"
10356 <<
"shared boundary is not in the list of vertices of the\n"
10357 <<
"boundary to connect.\n\n"
10358 <<
"This is the right vertex of the current shared "
10360 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", "
10361 << shd_bnd_right_vertex[1] <<
")\n\n"
10362 <<
"This is the list of vertices on the destination "
10364 const unsigned n_v = poly_to_connect_pt->nvertex();
10365 for (
unsigned i = 0; i < n_v; i++)
10367 Vector<double> cvertex =
10368 poly_to_connect_pt->vertex_coordinate(i);
10369 error <<
"Vertex #" << i <<
": (" << cvertex[0] <<
", "
10370 << cvertex[1] <<
")\n";
10372 throw OomphLibError(
10374 "TriangleMesh::create_shared_polylines_connections()",
10375 OOMPH_EXCEPTION_LOCATION);
10381 shd_poly_pt->connect_final_vertex_to_polyline(
10382 poly_to_connect_pt, vertex_index);
10392 unsigned vertex_index = 0;
10394 bool found_vertex_index =
false;
10398 Vector<unsigned> dst_shd_bnd_ids;
10399 get_shared_boundaries_overlapping_internal_boundary(
10400 uconnection_to_the_right, dst_shd_bnd_ids);
10404 const unsigned n_shd_bnd_overlap_int_bnd =
10405 dst_shd_bnd_ids.size();
10409 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10412 const unsigned new_connection_to_the_right =
10413 dst_shd_bnd_ids[ss];
10417 poly_to_connect_pt =
10418 boundary_polyline_pt(new_connection_to_the_right);
10420 if (poly_to_connect_pt != 0)
10424 found_vertex_index =
10425 get_connected_vertex_number_on_destination_polyline(
10426 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10431 if (found_vertex_index)
10441 if (!found_vertex_index)
10443 std::stringstream error;
10445 <<
"The current shared boundary (" << bound_id <<
") was "
10446 <<
"marked to have a connection\nto the right with the "
10447 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10448 <<
"This last boundary is marked to be overlaped by "
10449 <<
"shared boundaries\n"
10450 <<
"The problem is that the right vertex of the current\n"
10451 <<
"shared boundary is not in the list of vertices of the\n"
10452 <<
"boundary to connect.\n\n"
10453 <<
"This is the right vertex of the current shared "
10455 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", "
10456 << shd_bnd_right_vertex[1] <<
")\n\n"
10457 <<
"This is the list of vertices on the destination "
10459 Vector<unsigned> dst_shd_bnd_ids;
10460 get_shared_boundaries_overlapping_internal_boundary(
10461 uconnection_to_the_right, dst_shd_bnd_ids);
10462 const unsigned n_shd_bnd_overlap_int_bnd =
10463 dst_shd_bnd_ids.size();
10464 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10466 const unsigned new_connection_to_the_right =
10467 dst_shd_bnd_ids[ss];
10468 poly_to_connect_pt =
10469 boundary_polyline_pt(new_connection_to_the_right);
10470 if (poly_to_connect_pt != 0)
10472 const unsigned shd_bnd_id_overlap =
10473 poly_to_connect_pt->boundary_id();
10474 error <<
"Shared boundary id(" << shd_bnd_id_overlap
10476 const unsigned n_v = poly_to_connect_pt->nvertex();
10477 for (
unsigned i = 0; i < n_v; i++)
10479 Vector<double> cvertex =
10480 poly_to_connect_pt->vertex_coordinate(i);
10481 error <<
"Vertex #" << i <<
": (" << cvertex[0] <<
", "
10482 << cvertex[1] <<
")\n";
10487 throw OomphLibError(
10489 "TriangleMesh::create_shared_polylines_connections()",
10490 OOMPH_EXCEPTION_LOCATION);
10498 shd_poly_pt->connect_final_vertex_to_polyline(
10499 poly_to_connect_pt, vertex_index);
10510 Vector<TriangleMeshPolyLine*> tmp_vector_subpolylines =
10511 boundary_subpolylines(uconnection_to_the_right);
10514 const unsigned nsub_poly = tmp_vector_subpolylines.size();
10516 if (nsub_poly <= 1)
10518 std::ostringstream error_message;
10520 <<
"The boundary (" << uconnection_to_the_right <<
") was "
10521 <<
"marked to be splitted but\n"
10522 <<
"there are only (" << nsub_poly <<
") polylines to "
10523 <<
"represent it.\n";
10524 throw OomphLibError(
10525 error_message.str(),
10526 "TriangleMesh::create_shared_polylines_connections()",
10527 OOMPH_EXCEPTION_LOCATION);
10540 if (!connecting_to_an_overlaped_boundary)
10546 unsigned vertex_index = 0;
10548 unsigned sub_poly_to_connect = 0;
10550 bool found_vertex_index =
false;
10554 for (
unsigned isub = 0; isub < nsub_poly; isub++)
10557 poly_to_connect_pt = tmp_vector_subpolylines[isub];
10559 found_vertex_index =
10560 get_connected_vertex_number_on_destination_polyline(
10561 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10564 if (found_vertex_index)
10568 sub_poly_to_connect = isub;
10576 if (!found_vertex_index)
10578 std::stringstream error;
10580 <<
"The current shared boundary (" << bound_id <<
") was "
10581 <<
"marked to have a connection\nto the right with the "
10582 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10583 <<
"The problem is that the right vertex of the current\n"
10584 <<
"shared boundary is not in the list of vertices of any\n"
10585 <<
"of the sub polylines that represent the boundary to\n"
10587 <<
"This is the right vertex of the current shared "
10589 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", "
10590 << shd_bnd_right_vertex[1] <<
")\n\n"
10591 <<
"This is the list of vertices on the destination "
10593 for (
unsigned p = 0; p < nsub_poly; p++)
10595 error <<
"Subpolyline #(" << p <<
")\n";
10596 poly_to_connect_pt = tmp_vector_subpolylines[p];
10597 const unsigned n_v = poly_to_connect_pt->nvertex();
10598 for (
unsigned i = 0; i < n_v; i++)
10600 Vector<double> cvertex =
10601 poly_to_connect_pt->vertex_coordinate(i);
10602 error <<
"Vertex #" << i <<
": (" << cvertex[0] <<
", "
10603 << cvertex[1] <<
")\n";
10606 throw OomphLibError(
10608 "TriangleMesh::create_shared_polylines_connections()",
10609 OOMPH_EXCEPTION_LOCATION);
10617 shd_poly_pt->connect_final_vertex_to_polyline(
10618 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
10629 unsigned vertex_index = 0;
10631 unsigned sub_poly_to_connect = 0;
10633 bool found_vertex_index =
false;
10637 Vector<unsigned> dst_shd_bnd_ids;
10638 get_shared_boundaries_overlapping_internal_boundary(
10639 uconnection_to_the_right, dst_shd_bnd_ids);
10643 const unsigned n_shd_bnd_overlap_int_bnd =
10644 dst_shd_bnd_ids.size();
10648 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10651 const unsigned new_connection_to_the_right =
10652 dst_shd_bnd_ids[ss];
10656 if (bound_id != new_connection_to_the_right)
10660 poly_to_connect_pt =
10661 boundary_polyline_pt(new_connection_to_the_right);
10663 if (poly_to_connect_pt != 0)
10667 found_vertex_index =
10668 get_connected_vertex_number_on_destination_polyline(
10669 poly_to_connect_pt,
10670 shd_bnd_right_vertex,
10676 if (found_vertex_index)
10688 if (!found_vertex_index)
10692 for (
unsigned isub = 0; isub < nsub_poly; isub++)
10696 if (!boundary_marked_as_shared_boundary(
10697 uconnection_to_the_right, isub))
10700 poly_to_connect_pt = tmp_vector_subpolylines[isub];
10702 found_vertex_index =
10703 get_connected_vertex_number_on_destination_polyline(
10704 poly_to_connect_pt,
10705 shd_bnd_right_vertex,
10709 if (found_vertex_index)
10713 sub_poly_to_connect = isub;
10726 if (!found_vertex_index)
10728 std::stringstream error;
10730 <<
"The current shared boundary (" << bound_id <<
") was "
10731 <<
"marked to have a connection\nto the right with the "
10732 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10733 <<
"This last boundary is marked to be overlaped by "
10734 <<
"shared boundaries\n"
10735 <<
"The problem is that the right vertex of the current\n"
10736 <<
"shared boundary is not in the list of vertices of "
10737 <<
"the\nboundary to connect.\n\n"
10738 <<
"This is the right vertex of the current shared "
10740 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", "
10741 << shd_bnd_right_vertex[1] <<
")\n\n"
10742 <<
"This is the list of vertices on the destination "
10743 <<
"boundary (only those subpolylines not marked as "
10744 <<
"overlaped by\nshared boundaries)\n";
10745 for (
unsigned p = 0; p < nsub_poly; p++)
10747 if (!boundary_marked_as_shared_boundary(
10748 uconnection_to_the_right, p))
10750 error <<
"Subpolyline #(" << p <<
")\n";
10751 poly_to_connect_pt = tmp_vector_subpolylines[p];
10752 const unsigned n_v = poly_to_connect_pt->nvertex();
10753 for (
unsigned i = 0; i < n_v; i++)
10755 Vector<double> cvertex =
10756 poly_to_connect_pt->vertex_coordinate(i);
10757 error <<
"Vertex #" << i <<
": (" << cvertex[0] <<
", "
10758 << cvertex[1] <<
")\n";
10762 error <<
"\nThis is the list of vertices of the shared "
10763 <<
"polylines that overlap\nthe internal "
10765 Vector<unsigned> dst_shd_bnd_ids;
10766 get_shared_boundaries_overlapping_internal_boundary(
10767 uconnection_to_the_right, dst_shd_bnd_ids);
10768 const unsigned n_shd_bnd_overlap_int_bnd =
10769 dst_shd_bnd_ids.size();
10770 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10772 const unsigned new_connection_to_the_right =
10773 dst_shd_bnd_ids[ss];
10774 poly_to_connect_pt =
10775 boundary_polyline_pt(new_connection_to_the_right);
10776 if (poly_to_connect_pt != 0)
10778 const unsigned shd_bnd_id_overlap =
10779 poly_to_connect_pt->boundary_id();
10780 error <<
"Shared boundary id(" << shd_bnd_id_overlap
10782 const unsigned n_v = poly_to_connect_pt->nvertex();
10783 for (
unsigned i = 0; i < n_v; i++)
10785 Vector<double> cvertex =
10786 poly_to_connect_pt->vertex_coordinate(i);
10787 error <<
"Vertex #" << i <<
": (" << cvertex[0] <<
", "
10788 << cvertex[1] <<
")\n";
10793 throw OomphLibError(
10795 "TriangleMesh::create_shared_polylines_connections()",
10796 OOMPH_EXCEPTION_LOCATION);
10804 shd_poly_pt->connect_final_vertex_to_polyline(
10805 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
10824 template<
class ELEMENT>
10826 Vector<Vector<double>>& output_holes_coordinates)
10829 const unsigned n_proc = this->communicator_pt()->nproc();
10830 const unsigned my_rank = this->communicator_pt()->my_rank();
10834 std::map<FiniteElement*, bool> done_ele;
10838 for (
unsigned iproc = 0; iproc < n_proc; iproc++)
10841 if (iproc != my_rank)
10844 const unsigned n_shd_bnd_iproc = nshared_boundaries(my_rank, iproc);
10849 const unsigned n_shd_bnd_iproc_rev = nshared_boundaries(iproc, my_rank);
10850 if (n_shd_bnd_iproc != n_shd_bnd_iproc_rev)
10852 std::ostringstream error_stream;
10854 <<
"The number of shared boundaries of processor (" << my_rank
10855 <<
") with processor(" << iproc <<
"): (" << n_shd_bnd_iproc
10857 <<
"is different from the number of shared boundaries of "
10858 <<
"processor (" << iproc <<
")\nwith processor (" << my_rank
10859 <<
"): (" << n_shd_bnd_iproc <<
")\n\n";
10860 throw OomphLibError(error_stream.str(),
10861 OOMPH_CURRENT_FUNCTION,
10862 OOMPH_EXCEPTION_LOCATION);
10868 for (
unsigned i = 0; i < n_shd_bnd_iproc; i++)
10871 const unsigned shd_bnd_id = shared_boundaries_ids(my_rank, iproc, i);
10874 const unsigned n_shd_bnd_ele = nshared_boundary_element(shd_bnd_id);
10877 for (
unsigned e = 0; e < n_shd_bnd_ele; e++)
10880 FiniteElement* ele_pt = shared_boundary_element_pt(shd_bnd_id, e);
10883 if (ele_pt->is_halo())
10886 if (!done_ele[ele_pt])
10889 const unsigned n_nodes = ele_pt->nnode();
10892 Vector<double> element_centroid(2, 0.0);
10894 for (
unsigned k = 0; k < n_nodes; k++)
10896 Node* tmp_node_pt = ele_pt->node_pt(k);
10898 for (
unsigned d = 0; d < 2; d++)
10900 element_centroid[d] += tmp_node_pt->x(d);
10905 for (
unsigned d = 0; d < 2; d++)
10907 element_centroid[d] = element_centroid[d] / (double)n_nodes;
10911 output_holes_coordinates.push_back(element_centroid);
10933 template<
class ELEMENT>
10935 Vector<TriangleMeshPolygon*>& polygons_pt,
10936 Vector<Vector<double>>& output_holes_coordinates)
10954 const unsigned n_input_holes = output_holes_coordinates.size();
10957 if (n_input_holes == 0)
10963 const unsigned n_polygons = polygons_pt.size();
10969 Vector<Vector<Vector<double>>> vertices_polygons(n_polygons);
10972 for (
unsigned p = 0; p < n_polygons; p++)
10975 const unsigned n_polylines = polygons_pt[p]->npolyline();
10977 for (
unsigned pp = 0; pp < n_polylines; pp++)
10980 const TriangleMeshPolyLine* tmp_poly_pt =
10981 polygons_pt[p]->polyline_pt(pp);
10983 const unsigned n_vertices = tmp_poly_pt->nvertex();
10987 for (
unsigned v = 0; v < n_vertices - 1; v++)
10990 Vector<double> current_vertex = tmp_poly_pt->vertex_coordinate(v);
10991 vertices_polygons[p].push_back(current_vertex);
11003 std::vector<bool> is_outer_polygon(n_polygons,
true);
11007 if (n_polygons > 1)
11014 Vector<Vector<Vector<double>>> polygon_edge_middle_vertex(n_polygons);
11016 for (
unsigned p = 0; p < n_polygons; p++)
11019 Vector<Vector<double>> tmp_inner_polygon = vertices_polygons[p];
11022 const unsigned n_vertices = tmp_inner_polygon.size();
11025 polygon_edge_middle_vertex[p].resize(n_vertices - 1);
11029 for (
unsigned e = 0; e < n_vertices - 1; e++)
11032 const unsigned dim = 2;
11033 polygon_edge_middle_vertex[p][e].resize(dim);
11034 for (
unsigned d = 0; d < dim; d++)
11036 polygon_edge_middle_vertex[p][e][d] =
11037 (tmp_inner_polygon[e][d] + tmp_inner_polygon[e + 1][d]) / 2.0;
11046 for (
unsigned idx_inner = 0; idx_inner < n_polygons; idx_inner++)
11051 bool is_inner_polygon =
false;
11056 for (
unsigned i = 0; i < n_polygons; i++)
11059 if (i != idx_inner)
11062 const unsigned n_edges =
11063 polygon_edge_middle_vertex[idx_inner].size();
11066 for (
unsigned e = 0; e < n_edges; e++)
11069 Vector<double> current_vertex =
11070 polygon_edge_middle_vertex[idx_inner][e];
11073 const bool is_point_inside = is_point_inside_polygon_helper(
11074 vertices_polygons[i], current_vertex);
11078 if (is_point_inside)
11081 is_inner_polygon =
true;
11092 if (is_inner_polygon)
11102 if (is_inner_polygon)
11105 is_outer_polygon[idx_inner] =
false;
11111 is_outer_polygon[idx_inner] =
true;
11120 unsigned n_outer_polygons = 0;
11121 unsigned n_inner_polygons = 0;
11123 Vector<unsigned> index_inner_polygon;
11125 for (
unsigned i = 0; i < n_polygons; i++)
11127 if (is_outer_polygon[i])
11130 n_outer_polygons++;
11135 n_inner_polygons++;
11137 index_inner_polygon.push_back(i);
11156 std::vector<bool> is_inside_an_inner_polygon(n_input_holes,
false);
11160 std::vector<bool> is_outside_the_outer_polygons(n_input_holes,
true);
11164 std::vector<bool> is_inside_the_convex_hull(n_input_holes,
false);
11167 Vector<Vector<Vector<double>>> vertex_inside_inner_polygon(
11173 for (
unsigned i = 0; i < n_inner_polygons; i++)
11176 const unsigned ii = index_inner_polygon[i];
11179 for (
unsigned h = 0; h < n_input_holes; h++)
11183 if (!is_inside_an_inner_polygon[h])
11186 const bool is_inside_polygon = is_point_inside_polygon_helper(
11187 vertices_polygons[ii], output_holes_coordinates[h]);
11191 if (is_inside_polygon)
11194 is_inside_an_inner_polygon[h] =
true;
11196 vertex_inside_inner_polygon[i].push_back(
11197 output_holes_coordinates[h]);
11209 for (
unsigned h = 0; h < n_input_holes; h++)
11213 if (!is_inside_an_inner_polygon[h])
11217 for (
unsigned i = 0; i < n_polygons; i++)
11220 if (is_outer_polygon[i])
11223 const bool is_inside_polygon = is_point_inside_polygon_helper(
11224 vertices_polygons[i], output_holes_coordinates[h]);
11229 if (is_inside_polygon)
11232 is_outside_the_outer_polygons[h] =
false;
11246 is_outside_the_outer_polygons[h] =
false;
11253 std::vector<Point> input_vertices_convex_hull;
11256 for (
unsigned p = 0; p < n_polygons; p++)
11259 const unsigned n_vertices = vertices_polygons[p].size();
11261 for (
unsigned v = 0; v < n_vertices; v++)
11266 point.
x = vertices_polygons[p][v][0];
11267 point.
y = vertices_polygons[p][v][1];
11269 input_vertices_convex_hull.push_back(point);
11274 std::vector<Point> output_vertices_convex_hull =
11275 convex_hull(input_vertices_convex_hull);
11278 const unsigned n_vertices_convex_hull = output_vertices_convex_hull.size();
11281 Vector<Vector<double>> vertices_convex_hull(n_vertices_convex_hull);
11282 for (
unsigned i = 0; i < n_vertices_convex_hull; i++)
11285 vertices_convex_hull[i].resize(2);
11287 vertices_convex_hull[i][0] = output_vertices_convex_hull[i].x;
11288 vertices_convex_hull[i][1] = output_vertices_convex_hull[i].y;
11294 for (
unsigned h = 0; h < n_input_holes; h++)
11297 if (is_outside_the_outer_polygons[h])
11300 const bool is_inside_convex_hull = is_point_inside_polygon_helper(
11301 vertices_convex_hull, output_holes_coordinates[h]);
11304 if (is_inside_convex_hull)
11307 is_inside_the_convex_hull[h] =
true;
11314 is_inside_the_convex_hull[h] =
true;
11321 Vector<Vector<double>> hole_kept;
11322 for (
unsigned h = 0; h < n_input_holes; h++)
11325 if ((is_inside_an_inner_polygon[h]) ||
11326 (is_outside_the_outer_polygons[h] && is_inside_the_convex_hull[h]))
11329 hole_kept.push_back(output_holes_coordinates[h]);
11334 output_holes_coordinates.clear();
11336 output_holes_coordinates = hole_kept;
11343 template<
class ELEMENT>
11345 Vector<TriangleMeshPolyLine*>& unsorted_polylines_pt,
11346 Vector<Vector<TriangleMeshPolyLine*>>& sorted_polylines_pt)
11348 unsigned n_unsorted_polylines = unsorted_polylines_pt.size();
11349 unsigned n_sorted_polylines = 0;
11350 unsigned curves_index = 0;
11353 std::map<TriangleMeshPolyLine*, bool> done_polyline;
11359 std::list<TriangleMeshPolyLine*> sorted_polyline_list_pt;
11360 bool changes =
false;
11364 TriangleMeshPolyLine* left_pt = 0;
11365 TriangleMeshPolyLine* right_pt = 0;
11369 bool found_root_polyline =
false;
11370 while (pp < n_unsorted_polylines && !found_root_polyline)
11372 if (!done_polyline[unsorted_polylines_pt[pp]])
11374 found_root_polyline =
true;
11383 if (pp < n_unsorted_polylines)
11386 left_pt = right_pt = unsorted_polylines_pt[pp];
11387 done_polyline[left_pt] =
true;
11389 n_sorted_polylines++;
11393 sorted_polyline_list_pt.push_back(left_pt);
11399 Vector<double> left_vertex(2);
11400 Vector<double> right_vertex(2);
11402 left_pt->initial_vertex_coordinate(left_vertex);
11403 right_pt->final_vertex_coordinate(right_vertex);
11405 for (
unsigned i = pp + 1; i < n_unsorted_polylines; i++)
11407 TriangleMeshPolyLine* current_polyline_pt =
11408 unsorted_polylines_pt[i];
11409 if (!done_polyline[current_polyline_pt])
11411 Vector<double> initial_vertex(2);
11412 Vector<double> final_vertex(2);
11413 current_polyline_pt->initial_vertex_coordinate(initial_vertex);
11414 current_polyline_pt->final_vertex_coordinate(final_vertex);
11420 if (left_vertex == final_vertex)
11422 left_pt = current_polyline_pt;
11423 sorted_polyline_list_pt.push_front(left_pt);
11424 done_polyline[left_pt] =
true;
11425 n_sorted_polylines++;
11431 else if (right_vertex == initial_vertex)
11433 right_pt = current_polyline_pt;
11434 sorted_polyline_list_pt.push_back(right_pt);
11435 done_polyline[right_pt] =
true;
11436 n_sorted_polylines++;
11442 else if (left_vertex == initial_vertex)
11444 current_polyline_pt->reverse();
11445 left_pt = current_polyline_pt;
11446 sorted_polyline_list_pt.push_front(left_pt);
11447 done_polyline[left_pt] =
true;
11448 n_sorted_polylines++;
11454 else if (right_vertex == final_vertex)
11456 current_polyline_pt->reverse();
11457 right_pt = current_polyline_pt;
11458 sorted_polyline_list_pt.push_back(right_pt);
11459 done_polyline[right_pt] =
true;
11460 n_sorted_polylines++;
11481 if (!found_root_polyline)
11483 std::stringstream err;
11484 err <<
"It was not possible to find a root polyline to sort the "
11485 <<
"others around it.\nThe number of unsorted and sorted "
11486 <<
"polylines is different, it means that\nnot all the "
11487 <<
"polylines have been sorted.\n"
11488 <<
"Found root polyline: (" << found_root_polyline <<
")\n"
11489 <<
"Sorted polylines: (" << n_sorted_polylines <<
")\n"
11490 <<
"Unsorted polylines: (" << n_unsorted_polylines <<
")\n";
11491 throw OomphLibError(err.str(),
11492 "TriangleMesh::sort_polylines_helper()",
11493 OOMPH_EXCEPTION_LOCATION);
11500 unsigned n_sorted_polyline_on_list = sorted_polyline_list_pt.size();
11503 Vector<TriangleMeshPolyLine*> tmp_sorted_polylines(
11504 n_sorted_polyline_on_list);
11505 unsigned counter = 0;
11507 std::list<TriangleMeshPolyLine*>::iterator it_polyline;
11508 for (it_polyline = sorted_polyline_list_pt.begin();
11509 it_polyline != sorted_polyline_list_pt.end();
11512 tmp_sorted_polylines[counter] = *it_polyline;
11516 sorted_polylines_pt.push_back(tmp_sorted_polylines);
11520 }
while (n_sorted_polylines < n_unsorted_polylines);
11525 if (n_sorted_polylines != n_unsorted_polylines)
11527 std::stringstream err;
11528 err <<
"The number of polylines on the unsorted and sorted vectors"
11529 <<
" is different,\n"
11530 <<
"it means that not all the polylines have been sorted.\n"
11531 <<
"Sorted polylines: " << n_sorted_polylines
11532 <<
"\nUnsorted polylines: " << n_unsorted_polylines;
11533 throw OomphLibError(err.str(),
11534 "TriangleMesh::sort_polylines_helper()",
11535 OOMPH_EXCEPTION_LOCATION);
11543 template<
class ELEMENT>
11545 OomphCommunicator* comm_pt,
11546 const Vector<unsigned>& element_domain,
11547 const Vector<GeneralisedElement*>& backed_up_el_pt,
11548 const Vector<FiniteElement*>& backed_up_f_el_pt,
11549 std::map<Data*, std::set<unsigned>>& processors_associated_with_data,
11550 const bool& overrule_keep_as_halo_element_status)
11553 const unsigned nproc = comm_pt->nproc();
11554 const unsigned my_rank = comm_pt->my_rank();
11560 Vector<Vector<Vector<GeneralisedElement*>>> halo_element_pt(nproc);
11562 for (
unsigned iproc = 0; iproc < nproc; iproc++)
11564 halo_element_pt[iproc].resize(nproc);
11570 std::map<GeneralisedElement*, unsigned> element_to_global_index;
11573 this->get_halo_elements_on_all_procs(nproc,
11576 processors_associated_with_data,
11577 overrule_keep_as_halo_element_status,
11578 element_to_global_index,
11582 flush_shared_boundary_polyline_pt();
11583 Shared_boundary_polyline_pt.resize(nproc);
11589 std::set<FiniteElement*> element_in_processor_pt;
11590 const unsigned n_ele = backed_up_f_el_pt.size();
11591 for (
unsigned e = 0; e < n_ele; e++)
11593 if (element_domain[e] == my_rank)
11595 element_in_processor_pt.insert(backed_up_f_el_pt[e]);
11602 std::map<std::pair<Node*, Node*>,
unsigned> elements_edges_on_boundary;
11603 this->get_element_edges_on_boundary(elements_edges_on_boundary);
11607 this->create_polylines_from_halo_elements_helper(
11609 element_to_global_index,
11610 element_in_processor_pt,
11612 elements_edges_on_boundary,
11613 Shared_boundary_polyline_pt);
11621 template<
class ELEMENT>
11623 const unsigned& nproc,
11624 const Vector<unsigned>& element_domain,
11625 const Vector<GeneralisedElement*>& backed_up_el_pt,
11626 std::map<Data*, std::set<unsigned>>& processors_associated_with_data,
11627 const bool& overrule_keep_as_halo_element_status,
11628 std::map<GeneralisedElement*, unsigned>& element_to_global_index,
11629 Vector<Vector<Vector<GeneralisedElement*>>>& output_halo_elements_pt)
11631 const unsigned n_ele = backed_up_el_pt.size();
11634 for (
unsigned iproc = 0; iproc < nproc; iproc++)
11638 Vector<std::map<GeneralisedElement*, bool>> already_added(nproc);
11641 for (
unsigned e = 0; e < n_ele; e++)
11644 GeneralisedElement* el_pt = backed_up_el_pt[e];
11645 unsigned el_domain = element_domain[e];
11649 if (el_domain != iproc)
11654 if ((this->Keep_all_elements_as_halos) ||
11655 (el_pt->must_be_kept_as_halo()))
11657 if (!overrule_keep_as_halo_element_status)
11661 if (!already_added[el_domain][el_pt])
11663 output_halo_elements_pt[iproc][el_domain].push_back(el_pt);
11664 already_added[el_domain][el_pt] =
true;
11665 element_to_global_index[el_pt] = e;
11673 FiniteElement* finite_el_pt =
dynamic_cast<FiniteElement*
>(el_pt);
11674 if (finite_el_pt != 0)
11676 unsigned n_node = finite_el_pt->nnode();
11677 for (
unsigned n = 0; n < n_node; n++)
11679 Node* nod_pt = finite_el_pt->node_pt(n);
11682 std::set<unsigned>::iterator it =
11683 processors_associated_with_data[nod_pt].find(iproc);
11684 if (it != processors_associated_with_data[nod_pt].end())
11688 if (!already_added[el_domain][el_pt])
11690 output_halo_elements_pt[iproc][el_domain].push_back(el_pt);
11691 already_added[el_domain][el_pt] =
true;
11692 element_to_global_index[el_pt] = e;
11710 template<
class ELEMENT>
11712 std::map<std::pair<Node*, Node*>,
unsigned>& element_edges_on_boundary)
11715 const unsigned nbound = this->nboundary();
11717 for (
unsigned b = 0; b < nbound; b++)
11720 std::map<std::pair<Node*, Node*>,
bool> edge_done;
11722 const unsigned nbound_ele = this->nboundary_element(b);
11723 for (
unsigned e = 0; e < nbound_ele; e++)
11726 FiniteElement* bulk_ele_pt = this->boundary_element_pt(b, e);
11728 int face_index = this->face_index_at_boundary(b, e);
11730 FiniteElement* face_ele_pt =
11731 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
11733 const unsigned nnodes = face_ele_pt->nnode();
11735 Node* first_node_pt = face_ele_pt->node_pt(0);
11736 Node* last_node_pt = face_ele_pt->node_pt(nnodes - 1);
11739 std::pair<Node*, Node*> edge =
11740 std::make_pair(first_node_pt, last_node_pt);
11743 if (!edge_done[edge])
11746 edge_done[edge] =
true;
11749 std::pair<Node*, Node*> inv_edge =
11750 std::make_pair(last_node_pt, first_node_pt);
11753 edge_done[inv_edge] =
true;
11756 element_edges_on_boundary[edge] = b;
11760 delete face_ele_pt;
11775 template<
class ELEMENT>
11777 const Vector<unsigned>& element_domain,
11778 std::map<GeneralisedElement*, unsigned>& element_to_global_index,
11779 std::set<FiniteElement*>& element_in_processor_pt,
11780 Vector<Vector<Vector<GeneralisedElement*>>>& input_halo_elements,
11781 std::map<std::pair<Node*, Node*>,
unsigned>& elements_edges_on_boundary,
11782 Vector<Vector<Vector<TriangleMeshPolyLine*>>>& output_polylines_pt)
11784 const unsigned nproc = this->communicator_pt()->nproc();
11785 const unsigned my_rank = this->communicator_pt()->my_rank();
11793 Vector<Vector<Vector<std::pair<Node*, Node*>>>> edges(nproc);
11797 Vector<Vector<Vector<Vector<FiniteElement*>>>> edge_element_pt(nproc);
11802 Vector<Vector<Vector<Vector<int>>>> edge_element_face(nproc);
11807 Vector<Vector<Vector<int>>> edge_boundary(nproc);
11810 std::map<std::pair<Node*, Node*>,
bool> overlapped_edge;
11816 Shared_boundaries_ids.resize(nproc);
11817 for (
unsigned j = 0; j < nproc; j++)
11819 edges[j].resize(nproc);
11820 edge_element_pt[j].resize(nproc);
11821 edge_element_face[j].resize(nproc);
11822 edge_boundary[j].resize(nproc);
11825 Shared_boundaries_ids[j].resize(nproc);
11831 for (
unsigned iproc = 0; iproc < nproc; iproc++)
11838 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
11851 Vector<GeneralisedElement*> halo_elements_iproc_with_jproc;
11852 Vector<GeneralisedElement*> halo_elements_jproc_with_iproc;
11855 halo_elements_iproc_with_jproc = input_halo_elements[iproc][jproc];
11858 const unsigned nhalo_elements_iproc_with_jproc =
11859 halo_elements_iproc_with_jproc.size();
11861 if (nhalo_elements_iproc_with_jproc > 0)
11864 halo_elements_jproc_with_iproc = input_halo_elements[jproc][iproc];
11868 const unsigned nhalo_elements_jproc_with_iproc =
11869 halo_elements_jproc_with_iproc.size();
11872 if (nhalo_elements_jproc_with_iproc == 0)
11877 std::stringstream err;
11878 err <<
"There are no halo elements from processor (" << jproc
11880 <<
"with processor (" << iproc <<
").\n"
11881 <<
"This is strange since there are halo elements from "
11882 <<
"processor (" << iproc <<
") with processor (" << jproc
11884 <<
"Number of halo elements from (" << iproc <<
") to ("
11885 << jproc <<
") : (" << nhalo_elements_iproc_with_jproc <<
")\n"
11886 <<
"Number of halo elements from (" << jproc <<
") to ("
11887 << iproc <<
") : (" << nhalo_elements_jproc_with_iproc <<
")\n";
11888 throw OomphLibError(
11890 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11891 OOMPH_EXCEPTION_LOCATION);
11895 Vector<Node*> halo_edges_iproc;
11896 unsigned halo_edges_counter_iproc = 0;
11897 Vector<Node*> halo_edges_jproc;
11898 unsigned halo_edges_counter_jproc = 0;
11901 std::map<std::pair<Node*, Node*>, FiniteElement*>
11902 edgesi_to_element_pt;
11906 std::map<std::pair<std::pair<Node*, Node*>, FiniteElement*>,
int>
11907 edgesi_element_pt_to_face_index;
11910 std::map<std::pair<Node*, Node*>, FiniteElement*>
11911 edgesj_to_element_pt;
11915 std::map<std::pair<std::pair<Node*, Node*>, FiniteElement*>,
int>
11916 edgesj_element_pt_to_face_index;
11922 for (
unsigned ih = 0; ih < nhalo_elements_iproc_with_jproc; ih++)
11926 element_to_global_index[halo_elements_iproc_with_jproc[ih]];
11928 if (element_domain[e] != jproc)
11931 std::stringstream err;
11932 err <<
"There was a problem on the ihalo-jhalo classification.\n"
11933 <<
"One of the elements, (the one with the (" << e <<
")-th "
11934 <<
"index ) is not on the (" << jproc <<
")-th processor\n"
11935 <<
"but it was stored as a halo element of processor ("
11936 << iproc <<
") with processor (" << jproc <<
").\n";
11937 throw OomphLibError(
11939 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11940 OOMPH_EXCEPTION_LOCATION);
11944 FiniteElement* el_pt =
11945 dynamic_cast<FiniteElement*
>(halo_elements_iproc_with_jproc[ih]);
11949 std::stringstream err;
11950 err <<
"The halo element (" << ih
11951 <<
") could not be casted to the "
11952 <<
"FiniteElement type.\n";
11953 throw OomphLibError(
11955 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11956 OOMPH_EXCEPTION_LOCATION);
11961 const unsigned n_nodes = el_pt->nnode();
11968 std::stringstream err;
11969 err <<
"The number of nodes of the " << ih
11970 <<
"-th halo element is"
11971 <<
" (" << n_nodes <<
").\nWe can not work with triangle "
11972 <<
"elements with less than three nodes\n";
11973 throw OomphLibError(
11975 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11976 OOMPH_EXCEPTION_LOCATION);
11981 Node* first_node_pt = el_pt->node_pt(0);
11982 Node* second_node_pt = el_pt->node_pt(1);
11983 Node* third_node_pt = el_pt->node_pt(2);
11986 halo_edges_iproc.push_back(first_node_pt);
11987 halo_edges_iproc.push_back(second_node_pt);
11988 halo_edges_counter_jproc++;
11990 halo_edges_iproc.push_back(second_node_pt);
11991 halo_edges_iproc.push_back(third_node_pt);
11992 halo_edges_counter_jproc++;
11994 halo_edges_iproc.push_back(third_node_pt);
11995 halo_edges_iproc.push_back(first_node_pt);
11996 halo_edges_counter_jproc++;
11999 std::pair<Node*, Node*> edge1 =
12000 std::make_pair(first_node_pt, second_node_pt);
12001 edgesi_to_element_pt[edge1] = el_pt;
12003 std::pair<Node*, Node*> edge2 =
12004 std::make_pair(second_node_pt, third_node_pt);
12005 edgesi_to_element_pt[edge2] = el_pt;
12007 std::pair<Node*, Node*> edge3 =
12008 std::make_pair(third_node_pt, first_node_pt);
12009 edgesi_to_element_pt[edge3] = el_pt;
12012 std::pair<std::pair<Node*, Node*>, FiniteElement*> edge_ele1 =
12013 std::make_pair(edge1, el_pt);
12014 edgesi_element_pt_to_face_index[edge_ele1] = 2;
12016 std::pair<std::pair<Node*, Node*>, FiniteElement*> edge_ele2 =
12017 std::make_pair(edge2, el_pt);
12018 edgesi_element_pt_to_face_index[edge_ele2] = 0;
12020 std::pair<std::pair<Node*, Node*>, FiniteElement*> edge_ele3 =
12021 std::make_pair(edge3, el_pt);
12022 edgesi_element_pt_to_face_index[edge_ele3] = 1;
12030 for (
unsigned jh = 0; jh < nhalo_elements_jproc_with_iproc; jh++)
12034 element_to_global_index[halo_elements_jproc_with_iproc[jh]];
12036 if (element_domain[e] != iproc)
12039 std::stringstream err;
12040 err <<
"There was a problem on the jhalo-ihalo classification.\n"
12041 <<
"One of the elements, (the one with the (" << e <<
")-th "
12042 <<
"index ) is not on the (" << iproc <<
")-th processor\n"
12043 <<
"but it was stored as a halo element of processor ("
12044 << jproc <<
") with processor (" << iproc <<
").\n";
12045 throw OomphLibError(
12047 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12048 OOMPH_EXCEPTION_LOCATION);
12052 FiniteElement* el_pt =
12053 dynamic_cast<FiniteElement*
>(halo_elements_jproc_with_iproc[jh]);
12056 std::stringstream err;
12057 err <<
"The halo element (" << jh
12058 <<
") could not be casted to the "
12059 <<
"FiniteElement type.\n";
12060 throw OomphLibError(
12062 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12063 OOMPH_EXCEPTION_LOCATION);
12068 const unsigned n_nodes = el_pt->nnode();
12075 std::stringstream err;
12076 err <<
"The number of nodes of the " << jh
12077 <<
"-th halo element is"
12078 <<
" (" << n_nodes <<
").\nWe can not work with triangle "
12079 <<
"elements with less than three nodes\n";
12080 throw OomphLibError(
12082 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12083 OOMPH_EXCEPTION_LOCATION);
12088 Node* first_node_pt = el_pt->node_pt(0);
12089 Node* second_node_pt = el_pt->node_pt(1);
12090 Node* third_node_pt = el_pt->node_pt(2);
12093 halo_edges_jproc.push_back(first_node_pt);
12094 halo_edges_jproc.push_back(second_node_pt);
12095 halo_edges_counter_iproc++;
12097 halo_edges_jproc.push_back(second_node_pt);
12098 halo_edges_jproc.push_back(third_node_pt);
12099 halo_edges_counter_iproc++;
12101 halo_edges_jproc.push_back(third_node_pt);
12102 halo_edges_jproc.push_back(first_node_pt);
12103 halo_edges_counter_iproc++;
12106 std::pair<Node*, Node*> edge1 =
12107 std::make_pair(first_node_pt, second_node_pt);
12108 edgesj_to_element_pt[edge1] = el_pt;
12110 std::pair<Node*, Node*> edge2 =
12111 std::make_pair(second_node_pt, third_node_pt);
12112 edgesj_to_element_pt[edge2] = el_pt;
12114 std::pair<Node*, Node*> edge3 =
12115 std::make_pair(third_node_pt, first_node_pt);
12116 edgesj_to_element_pt[edge3] = el_pt;
12119 std::pair<std::pair<Node*, Node*>, FiniteElement*> edge_ele1 =
12120 std::make_pair(edge1, el_pt);
12121 edgesj_element_pt_to_face_index[edge_ele1] = 2;
12123 std::pair<std::pair<Node*, Node*>, FiniteElement*> edge_ele2 =
12124 std::make_pair(edge2, el_pt);
12125 edgesj_element_pt_to_face_index[edge_ele2] = 0;
12127 std::pair<std::pair<Node*, Node*>, FiniteElement*> edge_ele3 =
12128 std::make_pair(edge3, el_pt);
12129 edgesj_element_pt_to_face_index[edge_ele3] = 1;
12142 unsigned nhalo_iedges = halo_edges_iproc.size();
12143 unsigned nhalo_jedges = halo_edges_jproc.size();
12147 for (
unsigned ihe = 0; ihe < nhalo_iedges; ihe += 2)
12150 Vector<Node*> ihalo_edge(2);
12151 ihalo_edge[0] = halo_edges_iproc[ihe];
12152 ihalo_edge[1] = halo_edges_iproc[ihe + 1];
12155 std::pair<Node*, Node*> tmp_edge =
12156 std::make_pair(ihalo_edge[0], ihalo_edge[1]);
12160 int edge_boundary_id = -1;
12162 std::map<std::pair<Node*, Node*>,
unsigned>::iterator it;
12163 it = elements_edges_on_boundary.find(tmp_edge);
12166 if (it != elements_edges_on_boundary.end())
12170 edge_boundary_id = (*it).second;
12176 std::pair<Node*, Node*> rtmp_edge =
12177 std::make_pair(ihalo_edge[1], ihalo_edge[0]);
12178 it = elements_edges_on_boundary.find(rtmp_edge);
12179 if (it != elements_edges_on_boundary.end())
12183 edge_boundary_id = (*it).second;
12190 for (
unsigned jhe = 0; jhe < nhalo_jedges; jhe += 2)
12193 Vector<Node*> jhalo_edge(2);
12194 jhalo_edge[0] = halo_edges_jproc[jhe];
12195 jhalo_edge[1] = halo_edges_jproc[jhe + 1];
12198 if (ihalo_edge[0] == jhalo_edge[0] &&
12199 ihalo_edge[1] == jhalo_edge[1])
12202 std::pair<Node*, Node*> new_edge =
12203 std::make_pair(ihalo_edge[0], ihalo_edge[1]);
12208 FiniteElement* haloi_ele_pt = 0;
12209 haloi_ele_pt = edgesi_to_element_pt[new_edge];
12210 FiniteElement* haloj_ele_pt = 0;
12211 haloj_ele_pt = edgesj_to_element_pt[new_edge];
12214 if (haloi_ele_pt == 0 || haloj_ele_pt == 0)
12216 std::stringstream err;
12217 err <<
"There is no associated elements with the new "
12218 <<
"shared boundary. This is an storing problem,\n"
12219 <<
"possibly related with a memory leak problem!!!\n"
12220 <<
"The nodes that compound the edge are these:\n"
12221 <<
"On processor (" << iproc <<
"):\n"
12222 <<
"(" << ihalo_edge[0]->x(0) <<
", "
12223 << ihalo_edge[0]->x(1) <<
") and (" << ihalo_edge[1]->x(0)
12224 <<
", " << ihalo_edge[1]->x(1) <<
")\n\n"
12225 <<
"On processor (" << jproc <<
"):\n"
12226 <<
"(" << jhalo_edge[0]->x(0) <<
", "
12227 << jhalo_edge[0]->x(1) <<
") and (" << jhalo_edge[1]->x(0)
12228 <<
", " << jhalo_edge[1]->x(1) <<
")\n\n"
12229 <<
"The nodes coordinates should be the same!!!\n";
12230 throw OomphLibError(err.str(),
12231 "TriangleMesh::create_polylines_from_"
12232 "halo_elements_helper()",
12233 OOMPH_EXCEPTION_LOCATION);
12237 edges[iproc][jproc].push_back(new_edge);
12240 if (edge_boundary_id >= 0)
12243 overlapped_edge[new_edge] =
true;
12246 std::pair<Node*, Node*> rev_new_edge =
12247 std::make_pair(ihalo_edge[1], ihalo_edge[0]);
12250 overlapped_edge[rev_new_edge] =
true;
12256 edge_boundary[iproc][jproc].push_back(edge_boundary_id);
12259 Vector<FiniteElement*> tmp_elements_pt;
12260 tmp_elements_pt.push_back(haloi_ele_pt);
12261 tmp_elements_pt.push_back(haloj_ele_pt);
12264 edge_element_pt[iproc][jproc].push_back(tmp_elements_pt);
12270 std::pair<std::pair<Node*, Node*>, FiniteElement*>
12271 edge_elementi_pair = make_pair(new_edge, haloi_ele_pt);
12273 std::pair<std::pair<Node*, Node*>, FiniteElement*>
12274 edge_elementj_pair = make_pair(new_edge, haloj_ele_pt);
12278 int face_index_haloi_ele = -1;
12279 face_index_haloi_ele =
12280 edgesi_element_pt_to_face_index[edge_elementi_pair];
12281 int face_index_haloj_ele = -1;
12282 face_index_haloj_ele =
12283 edgesj_element_pt_to_face_index[edge_elementj_pair];
12285 if (face_index_haloi_ele == -1 || face_index_haloj_ele == -1)
12287 std::stringstream err;
12288 err <<
"There is no associated face indexes to the"
12289 <<
"elements that gave\nrise to the shared edge\n"
12290 <<
"The nodes that compound the edge are these:\n"
12291 <<
"On processor (" << iproc <<
"):\n"
12292 <<
"(" << ihalo_edge[0]->x(0) <<
", "
12293 << ihalo_edge[0]->x(1) <<
") and (" << ihalo_edge[1]->x(0)
12294 <<
", " << ihalo_edge[1]->x(1) <<
")\n\n"
12295 <<
"On processor (" << jproc <<
"):\n"
12296 <<
"(" << jhalo_edge[0]->x(0) <<
", "
12297 << jhalo_edge[0]->x(1) <<
") and (" << jhalo_edge[1]->x(0)
12298 <<
", " << jhalo_edge[1]->x(1) <<
")\n\n"
12299 <<
"The nodes coordinates should be the same!!!\n";
12300 throw OomphLibError(err.str(),
12301 "TriangleMesh::create_polylines_from_"
12302 "halo_elements_helper()",
12303 OOMPH_EXCEPTION_LOCATION);
12308 Vector<int> tmp_edge_element_face_index;
12309 tmp_edge_element_face_index.push_back(face_index_haloi_ele);
12310 tmp_edge_element_face_index.push_back(face_index_haloj_ele);
12312 edge_element_face[iproc][jproc].push_back(
12313 tmp_edge_element_face_index);
12321 else if (ihalo_edge[0] == jhalo_edge[1] &&
12322 ihalo_edge[1] == jhalo_edge[0])
12325 std::pair<Node*, Node*> new_edge =
12326 std::make_pair(ihalo_edge[0], ihalo_edge[1]);
12330 FiniteElement* haloi_ele_pt = 0;
12331 haloi_ele_pt = edgesi_to_element_pt[new_edge];
12333 FiniteElement* haloj_ele_pt = 0;
12336 std::pair<Node*, Node*> new_edge_reversed =
12337 std::make_pair(jhalo_edge[0], jhalo_edge[1]);
12338 haloj_ele_pt = edgesj_to_element_pt[new_edge_reversed];
12341 if (haloi_ele_pt == 0 || haloj_ele_pt == 0)
12343 std::stringstream err;
12344 err <<
"There is no associated elements with the new "
12345 <<
"shared boundary (reversed version). This is an "
12346 <<
"storing problem, possibly related with a memory "
12347 <<
"leak problem!!!\n"
12348 <<
"The nodes that compound the edge are these:\n"
12349 <<
"On processor (" << iproc <<
"):\n"
12350 <<
"(" << ihalo_edge[0]->x(0) <<
", "
12351 << ihalo_edge[0]->x(1) <<
") and (" << ihalo_edge[1]->x(0)
12352 <<
", " << ihalo_edge[1]->x(1) <<
")\n\n"
12353 <<
"On processor (" << jproc <<
"):\n"
12354 <<
"(" << jhalo_edge[0]->x(0) <<
", "
12355 << jhalo_edge[0]->x(1) <<
") and (" << jhalo_edge[1]->x(0)
12356 <<
", " << jhalo_edge[1]->x(1) <<
")\n\n"
12357 <<
"The nodes coordinates should be the same!!!\n";
12358 throw OomphLibError(err.str(),
12359 "TriangleMesh::create_polylines_from_"
12360 "halo_elements_helper()",
12361 OOMPH_EXCEPTION_LOCATION);
12365 edges[iproc][jproc].push_back(new_edge);
12368 if (edge_boundary_id >= 0)
12371 overlapped_edge[new_edge] =
true;
12374 std::pair<Node*, Node*> rev_new_edge =
12375 std::make_pair(ihalo_edge[1], ihalo_edge[0]);
12378 overlapped_edge[rev_new_edge] =
true;
12383 edge_boundary[iproc][jproc].push_back(edge_boundary_id);
12386 Vector<FiniteElement*> tmp_elements_pt;
12387 tmp_elements_pt.push_back(haloi_ele_pt);
12388 tmp_elements_pt.push_back(haloj_ele_pt);
12391 edge_element_pt[iproc][jproc].push_back(tmp_elements_pt);
12397 std::pair<std::pair<Node*, Node*>, FiniteElement*>
12398 edge_elementi_pair = make_pair(new_edge, haloi_ele_pt);
12400 std::pair<std::pair<Node*, Node*>, FiniteElement*>
12401 edge_elementj_pair =
12402 make_pair(new_edge_reversed, haloj_ele_pt);
12406 int face_index_haloi_ele = -1;
12407 face_index_haloi_ele =
12408 edgesi_element_pt_to_face_index[edge_elementi_pair];
12409 int face_index_haloj_ele = -1;
12410 face_index_haloj_ele =
12411 edgesj_element_pt_to_face_index[edge_elementj_pair];
12413 if (face_index_haloi_ele == -1 || face_index_haloj_ele == -1)
12415 std::stringstream err;
12416 err <<
"There is no associated face indexes to the"
12417 <<
"elements that gave\nrise to the shared edge\n"
12418 <<
"The nodes that compound the edge are these:\n"
12419 <<
"On processor (" << iproc <<
"):\n"
12420 <<
"(" << ihalo_edge[0]->x(0) <<
", "
12421 << ihalo_edge[0]->x(1) <<
") and (" << ihalo_edge[1]->x(0)
12422 <<
", " << ihalo_edge[1]->x(1) <<
")\n\n"
12423 <<
"On processor (" << jproc <<
"):\n"
12424 <<
"(" << jhalo_edge[0]->x(0) <<
", "
12425 << jhalo_edge[0]->x(1) <<
") and (" << jhalo_edge[1]->x(0)
12426 <<
", " << jhalo_edge[1]->x(1) <<
")\n\n"
12427 <<
"The nodes coordinates should be the same!!!\n";
12428 throw OomphLibError(err.str(),
12429 "TriangleMesh::create_polylines_from_"
12430 "halo_elements_helper()",
12431 OOMPH_EXCEPTION_LOCATION);
12436 Vector<int> tmp_edge_element_face_index;
12437 tmp_edge_element_face_index.push_back(face_index_haloi_ele);
12438 tmp_edge_element_face_index.push_back(face_index_haloj_ele);
12440 edge_element_face[iproc][jproc].push_back(
12441 tmp_edge_element_face_index);
12466 std::map<Node*, unsigned> global_shared_node_degree;
12470 std::map<std::pair<Node*, Node*>,
bool> edge_done;
12473 std::map<Node*, bool> node_done;
12477 for (
unsigned iproc = 0; iproc < nproc; iproc++)
12484 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
12487 const unsigned nshd_edges = edges[iproc][jproc].size();
12493 const unsigned nedge_element = edge_element_pt[iproc][jproc].size();
12494 if (nshd_edges != nedge_element)
12496 std::stringstream error_message;
12498 <<
"The number of shared edges between processor iproc and jproc\n"
12499 <<
"is different form the number of edge elements between the\n"
12500 <<
"pair of processors\n"
12501 <<
"iproc: (" << iproc <<
")\n"
12502 <<
"jproc: (" << jproc <<
")\n"
12503 <<
"# of shared edges: (" << nshd_edges <<
")\n"
12504 <<
"# of edge elements: (" << nedge_element <<
")\n\n";
12505 throw OomphLibError(
12506 error_message.str(),
12507 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12508 OOMPH_EXCEPTION_LOCATION);
12512 const unsigned nedge_element_face =
12513 edge_element_face[iproc][jproc].size();
12514 if (nshd_edges != nedge_element_face)
12516 std::stringstream error_message;
12518 <<
"The number of shared edges between processor iproc and jproc\n"
12519 <<
"is different form the number of edge element faces between "
12521 <<
"pair of processors\n"
12522 <<
"iproc: (" << iproc <<
")\n"
12523 <<
"jproc: (" << jproc <<
")\n"
12524 <<
"# of shared edges: (" << nshd_edges <<
")\n"
12525 <<
"# of edge element faces: (" << nedge_element_face <<
")\n\n";
12526 throw OomphLibError(
12527 error_message.str(),
12528 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12529 OOMPH_EXCEPTION_LOCATION);
12533 const unsigned nedge_boundary = edge_boundary[iproc][jproc].size();
12534 if (nshd_edges != nedge_boundary)
12536 std::stringstream error_message;
12538 <<
"The number of shared edges between processor iproc and jproc\n"
12539 <<
"is different form the number of edge boundaries ids between "
12541 <<
"pair of processors\n"
12542 <<
"iproc: (" << iproc <<
")\n"
12543 <<
"jproc: (" << jproc <<
")\n"
12544 <<
"# of shared edges: (" << nshd_edges <<
")\n"
12545 <<
"# of edge boundaries ids: (" << nedge_boundary <<
")\n\n";
12546 throw OomphLibError(
12547 error_message.str(),
12548 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12549 OOMPH_EXCEPTION_LOCATION);
12555 for (
unsigned se = 0; se < nshd_edges; se++)
12558 std::pair<Node*, Node*> edge = edges[iproc][jproc][se];
12561 if (edge_done[edge])
12563 std::stringstream error_message;
12565 <<
"The shared edge between processor iproc and processor\n"
12566 <<
"jproc has been already visited, this is weird since the\n"
12567 <<
"edge should not be shared by other pair of processors\n"
12568 <<
"iproc: (" << iproc <<
")\n"
12569 <<
"jproc: (" << jproc <<
")\n"
12570 <<
"First node of edge: (" << edge.first->x(0) <<
", "
12571 << edge.first->x(1) <<
")\n"
12572 <<
"Second node of edge: (" << edge.second->x(0) <<
", "
12573 << edge.second->x(1) <<
")\n"
12574 <<
"Associated edge boundary id: ("
12575 << edge_boundary[iproc][jproc][se] <<
")\n\n";
12576 throw OomphLibError(
12577 error_message.str(),
12578 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12579 OOMPH_EXCEPTION_LOCATION);
12583 edge_done[edge] =
true;
12585 std::pair<Node*, Node*> rev_edge =
12586 std::make_pair(edge.second, edge.first);
12588 edge_done[rev_edge] =
true;
12592 Node* left_node_pt = edge.first;
12593 Node* right_node_pt = edge.second;
12596 if (!node_done[left_node_pt])
12600 global_shared_node_degree[left_node_pt] = 1;
12606 global_shared_node_degree[left_node_pt]++;
12610 if (!node_done[right_node_pt])
12614 global_shared_node_degree[right_node_pt] = 1;
12619 global_shared_node_degree[right_node_pt]++;
12634 std::map<unsigned, std::map<Node*, bool>>
12635 node_on_bnd_not_overlapped_by_shd_bnd;
12638 for (std::map<std::pair<Node*, Node*>,
unsigned>::iterator it_map =
12639 elements_edges_on_boundary.begin();
12640 it_map != elements_edges_on_boundary.end();
12644 std::pair<Node*, Node*> edge_pair = (*it_map).first;
12647 if (!overlapped_edge[edge_pair])
12651 unsigned b = (*it_map).second;
12654 Node* left_node_pt = edge_pair.first;
12655 node_on_bnd_not_overlapped_by_shd_bnd[b][left_node_pt] =
true;
12658 Node* right_node_pt = edge_pair.second;
12659 node_on_bnd_not_overlapped_by_shd_bnd[b][right_node_pt] =
true;
12674 Vector<Vector<TriangleMeshPolyLine*>> unsorted_polylines_pt(nproc);
12679 std::map<unsigned, std::list<Node*>> shared_bnd_id_to_sorted_list_node_pt;
12683 unsigned shared_boundary_id_start = this->nboundary();
12684 Initial_shared_boundary_id = shared_boundary_id_start;
12690 for (
unsigned iproc = 0; iproc < nproc; iproc++)
12697 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
12705 unsigned npolylines_counter = 0;
12706 const unsigned nedges = edges[iproc][jproc].size();
12712 unsigned nsorted_edges = 0;
12715 std::map<std::pair<Node*, Node*>,
bool> edge_done;
12719 while (nsorted_edges < nedges)
12723 std::list<FiniteElement*> tmp_boundary_element_pt;
12726 std::list<int> tmp_face_index_element;
12728 std::pair<Node*, Node*> edge;
12730 bool found_initial_edge =
false;
12732 int root_edge_bound_id = -1;
12733 unsigned iedge = 0;
12734 for (iedge = 0; iedge < nedges; iedge++)
12736 edge = edges[iproc][jproc][iedge];
12738 if (!edge_done[edge])
12741 root_edge_bound_id = edge_boundary[iproc][jproc][iedge];
12743 found_initial_edge =
true;
12752 if (!found_initial_edge)
12754 std::ostringstream error_message;
12756 <<
"All the edge are already done, but the number of done\n"
12757 <<
"edges (" << nsorted_edges
12758 <<
") is still less than the total\n"
12759 <<
"number of edges (" << nedges <<
").\n";
12761 throw OomphLibError(
12762 error_message.str(),
12763 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12764 OOMPH_EXCEPTION_LOCATION);
12770 std::list<Node*> sorted_nodes;
12771 sorted_nodes.clear();
12774 Node* first_node_pt = edge.first;
12775 Node* last_node_pt = edge.second;
12778 sorted_nodes.push_back(first_node_pt);
12779 sorted_nodes.push_back(last_node_pt);
12783 tmp_boundary_element_pt.push_back(
12784 edge_element_pt[iproc][jproc][iedge - 1][0]);
12785 tmp_boundary_element_pt.push_back(
12786 edge_element_pt[iproc][jproc][iedge - 1][1]);
12790 tmp_face_index_element.push_back(
12791 edge_element_face[iproc][jproc][iedge - 1][0]);
12792 tmp_face_index_element.push_back(
12793 edge_element_face[iproc][jproc][iedge - 1][1]);
12796 edge_done[edge] =
true;
12801 bool node_added =
true;
12805 bool node_added_to_the_left =
true;
12806 bool node_added_to_the_right =
true;
12824 bool connection_to_the_left =
false;
12829 bool connection_to_the_right =
false;
12833 bool current_polyline_has_connections_at_both_ends =
false;
12840 int bound_id_connection_to_the_left = -1;
12841 int bound_id_connection_to_the_right = -1;
12844 const unsigned first_node_degree =
12845 global_shared_node_degree[first_node_pt];
12849 bound_id_connection_to_the_left = check_connections_of_polyline_nodes(
12850 element_in_processor_pt,
12851 root_edge_bound_id,
12853 node_on_bnd_not_overlapped_by_shd_bnd,
12855 shared_bnd_id_to_sorted_list_node_pt,
12865 if (bound_id_connection_to_the_left != -1)
12867 connection_to_the_left =
true;
12871 const unsigned last_node_degree =
12872 global_shared_node_degree[last_node_pt];
12876 bound_id_connection_to_the_right =
12877 check_connections_of_polyline_nodes(
12878 element_in_processor_pt,
12879 root_edge_bound_id,
12881 node_on_bnd_not_overlapped_by_shd_bnd,
12883 shared_bnd_id_to_sorted_list_node_pt,
12892 if (bound_id_connection_to_the_right != -1)
12894 connection_to_the_right =
true;
12899 if (connection_to_the_left && connection_to_the_right)
12901 current_polyline_has_connections_at_both_ends =
true;
12909 while (node_added && (nsorted_edges < nedges) &&
12910 !current_polyline_has_connections_at_both_ends)
12915 for (
unsigned iiedge = iedge; iiedge < nedges; iiedge++)
12918 node_added =
false;
12919 node_added_to_the_left =
false;
12920 node_added_to_the_right =
false;
12922 edge = edges[iproc][jproc][iiedge];
12923 const int edge_bound_id = edge_boundary[iproc][jproc][iiedge];
12929 if (!edge_done[edge] && (edge_bound_id == root_edge_bound_id))
12932 Node* left_node_pt = edge.first;
12933 Node* right_node_pt = edge.second;
12936 Node* new_added_node_pt = 0;
12939 if (left_node_pt == first_node_pt && !connection_to_the_left)
12942 sorted_nodes.push_front(right_node_pt);
12944 new_added_node_pt = first_node_pt = right_node_pt;
12948 node_added_to_the_left =
true;
12951 else if (left_node_pt == last_node_pt &&
12952 !connection_to_the_right)
12955 sorted_nodes.push_back(right_node_pt);
12957 new_added_node_pt = last_node_pt = right_node_pt;
12961 node_added_to_the_right =
true;
12964 else if (right_node_pt == first_node_pt &&
12965 !connection_to_the_left)
12968 sorted_nodes.push_front(left_node_pt);
12970 new_added_node_pt = first_node_pt = left_node_pt;
12974 node_added_to_the_left =
true;
12977 else if (right_node_pt == last_node_pt &&
12978 !connection_to_the_right)
12981 sorted_nodes.push_back(left_node_pt);
12983 new_added_node_pt = last_node_pt = left_node_pt;
12987 node_added_to_the_right =
true;
12997 edge_done[edge] =
true;
13001 const unsigned added_node_degree =
13002 global_shared_node_degree[new_added_node_pt];
13004 if (node_added_to_the_left)
13007 tmp_boundary_element_pt.push_front(
13008 edge_element_pt[iproc][jproc][iiedge][1]);
13009 tmp_boundary_element_pt.push_front(
13010 edge_element_pt[iproc][jproc][iiedge][0]);
13012 tmp_face_index_element.push_front(
13013 edge_element_face[iproc][jproc][iiedge][1]);
13014 tmp_face_index_element.push_front(
13015 edge_element_face[iproc][jproc][iiedge][0]);
13018 if (node_added_to_the_right)
13021 tmp_boundary_element_pt.push_back(
13022 edge_element_pt[iproc][jproc][iiedge][0]);
13023 tmp_boundary_element_pt.push_back(
13024 edge_element_pt[iproc][jproc][iiedge][1]);
13026 tmp_face_index_element.push_back(
13027 edge_element_face[iproc][jproc][iiedge][0]);
13028 tmp_face_index_element.push_back(
13029 edge_element_face[iproc][jproc][iiedge][1]);
13039 if (node_added_to_the_left && !connection_to_the_left)
13042 bound_id_connection_to_the_left =
13043 check_connections_of_polyline_nodes(
13044 element_in_processor_pt,
13045 root_edge_bound_id,
13047 node_on_bnd_not_overlapped_by_shd_bnd,
13049 shared_bnd_id_to_sorted_list_node_pt,
13051 new_added_node_pt);
13058 if (bound_id_connection_to_the_left != -1)
13060 connection_to_the_left =
true;
13070 if (node_added_to_the_right && !connection_to_the_right)
13073 bound_id_connection_to_the_right =
13074 check_connections_of_polyline_nodes(
13075 element_in_processor_pt,
13076 root_edge_bound_id,
13078 node_on_bnd_not_overlapped_by_shd_bnd,
13080 shared_bnd_id_to_sorted_list_node_pt,
13082 new_added_node_pt);
13089 if (bound_id_connection_to_the_right != -1)
13091 connection_to_the_right =
true;
13099 if (connection_to_the_left && connection_to_the_right)
13101 current_polyline_has_connections_at_both_ends =
true;
13125 const unsigned n_bnd_ele = tmp_boundary_element_pt.size();
13128 Vector<FiniteElement*> tmp_bnd_ele_pt(n_bnd_ele);
13129 Vector<int> tmp_face_idx_ele(n_bnd_ele);
13131 unsigned help_counter = 0;
13133 for (std::list<FiniteElement*>::iterator it_bnd_ele =
13134 tmp_boundary_element_pt.begin();
13135 it_bnd_ele != tmp_boundary_element_pt.end();
13138 tmp_bnd_ele_pt[help_counter++] = (*it_bnd_ele);
13143 for (std::list<int>::iterator it_face_idx =
13144 tmp_face_index_element.begin();
13145 it_face_idx != tmp_face_index_element.end();
13148 tmp_face_idx_ele[help_counter++] = (*it_face_idx);
13153 Vector<std::list<Node*>> final_sorted_nodes_pt;
13156 Vector<Vector<FiniteElement*>> final_boundary_element_pt;
13158 Vector<Vector<int>> final_face_index_element;
13161 Vector<int> final_bound_id_connection_to_the_left;
13164 Vector<int> final_bound_id_connection_to_the_right;
13167 break_loops_on_shared_polyline_helper(
13168 shared_boundary_id_start,
13172 bound_id_connection_to_the_left,
13173 bound_id_connection_to_the_right,
13174 final_sorted_nodes_pt,
13175 final_boundary_element_pt,
13176 final_face_index_element,
13177 final_bound_id_connection_to_the_left,
13178 final_bound_id_connection_to_the_right);
13181 const unsigned n_final_sorted_nodes = final_sorted_nodes_pt.size();
13184 for (
unsigned i = 0; i < n_final_sorted_nodes; i++)
13189 shared_bnd_id_to_sorted_list_node_pt[shared_boundary_id_start] =
13190 final_sorted_nodes_pt[i];
13194 create_shared_polyline(my_rank,
13195 shared_boundary_id_start,
13198 final_sorted_nodes_pt[i],
13199 root_edge_bound_id,
13200 final_boundary_element_pt[i],
13201 final_face_index_element[i],
13202 unsorted_polylines_pt,
13203 final_bound_id_connection_to_the_left[i],
13204 final_bound_id_connection_to_the_right[i]);
13208 npolylines_counter++;
13212 shared_boundary_id_start++;
13225 if (unsorted_polylines_pt[iproc].size() > 0)
13229 sort_polylines_helper(unsorted_polylines_pt[iproc],
13230 output_polylines_pt[iproc]);
13234 const unsigned nunsorted_polylines_iproc =
13235 unsorted_polylines_pt[iproc].size();
13238 unsigned tmp_ntotal_polylines = 0;
13240 for (
unsigned ii = 0; ii < output_polylines_pt[iproc].size(); ii++)
13242 tmp_ntotal_polylines += output_polylines_pt[iproc][ii].size();
13244 if (tmp_ntotal_polylines != nunsorted_polylines_iproc)
13246 std::ostringstream error_message;
13247 error_message <<
" The total number of unsorted polylines ("
13248 << nunsorted_polylines_iproc
13249 <<
") in common with\nprocessor (" << iproc
13250 <<
") is different from the total number of sorted "
13251 <<
"polylines (" << tmp_ntotal_polylines
13252 <<
") with\nthe same "
13254 throw OomphLibError(error_message.str(),
13255 OOMPH_CURRENT_FUNCTION,
13256 OOMPH_EXCEPTION_LOCATION);
13263 this->Final_shared_boundary_id = shared_boundary_id_start;
13270 template<
class ELEMENT>
13272 const unsigned& initial_shd_bnd_id,
13273 std::list<Node*>& input_nodes,
13274 Vector<FiniteElement*>& input_boundary_element_pt,
13275 Vector<int>& input_face_index_element,
13276 const int& input_connect_to_the_left,
13277 const int& input_connect_to_the_right,
13278 Vector<std::list<Node*>>& output_sorted_nodes_pt,
13279 Vector<Vector<FiniteElement*>>& output_boundary_element_pt,
13280 Vector<Vector<int>>& output_face_index_element,
13281 Vector<int>& output_connect_to_the_left,
13282 Vector<int>& output_connect_to_the_right)
13285 Node* left_node_pt = input_nodes.front();
13286 Node* right_node_pt = input_nodes.back();
13290 Vector<std::list<Node*>> tmp_sub_nodes;
13291 Vector<Vector<FiniteElement*>> tmp_sub_bnd_ele_pt;
13292 Vector<Vector<int>> tmp_sub_face_idx_ele;
13295 std::list<Node*>::iterator it = input_nodes.begin();
13298 unsigned counter = 0;
13301 while (it != input_nodes.end())
13306 if (it == input_nodes.end())
13318 std::list<Node*> sub_nodes;
13321 Vector<FiniteElement*> sub_bnd_ele_pt;
13324 Vector<int> sub_face_idx_ele;
13327 sub_nodes.push_back(*it);
13337 sub_nodes.push_back((*it));
13340 sub_bnd_ele_pt.push_back(input_boundary_element_pt[counter]);
13341 sub_bnd_ele_pt.push_back(input_boundary_element_pt[counter + 1]);
13344 sub_face_idx_ele.push_back(input_face_index_element[counter]);
13345 sub_face_idx_ele.push_back(input_face_index_element[counter + 1]);
13352 }
while ((*it) != left_node_pt && (*it) != right_node_pt &&
13353 it != input_nodes.end());
13356 tmp_sub_nodes.push_back(sub_nodes);
13358 tmp_sub_bnd_ele_pt.push_back(sub_bnd_ele_pt);
13360 tmp_sub_face_idx_ele.push_back(sub_face_idx_ele);
13368 const unsigned n_sub_list = tmp_sub_nodes.size();
13371 if (n_sub_list > 3)
13373 std::stringstream error_message;
13375 <<
"The number of sub-list of nodes created from the shared\n"
13376 <<
"polyline with loops was (" << n_sub_list <<
").\n"
13377 <<
"We can only handle up to three sub-list of nodes\n";
13378 throw OomphLibError(
13379 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
13385 if (n_sub_list == 1 && (left_node_pt != right_node_pt))
13393 output_sorted_nodes_pt = tmp_sub_nodes;
13395 output_boundary_element_pt = tmp_sub_bnd_ele_pt;
13397 output_face_index_element = tmp_sub_face_idx_ele;
13403 if (input_connect_to_the_left == -2)
13405 std::stringstream error_message;
13407 <<
"The connection flag to the left (" << input_connect_to_the_left
13408 <<
") indicates a connection\n"
13409 <<
"with the same polyline.\n However, only one sub-polyline was "
13410 <<
"found and no loop\nwas identified\n\n";
13411 throw OomphLibError(error_message.str(),
13412 OOMPH_CURRENT_FUNCTION,
13413 OOMPH_EXCEPTION_LOCATION);
13418 if (input_connect_to_the_left == -3)
13420 output_connect_to_the_left.push_back(-1);
13424 output_connect_to_the_left.push_back(input_connect_to_the_left);
13428 if (input_connect_to_the_right == -2)
13430 std::stringstream error_message;
13432 <<
"The connection flag to the right (" << input_connect_to_the_right
13433 <<
") indicates a connection\n"
13434 <<
"with the same polyline.\n However, only one sub-polyline was "
13435 <<
"found and no loop\nwas identified\n\n";
13436 throw OomphLibError(
13437 error_message.str(),
13438 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13439 OOMPH_EXCEPTION_LOCATION);
13444 if (input_connect_to_the_right == -3)
13446 output_connect_to_the_right.push_back(-1);
13450 output_connect_to_the_right.push_back(input_connect_to_the_right);
13458 unsigned tmp_shd_bnd_id = initial_shd_bnd_id;
13466 Node* left_sub_node_pt = tmp_sub_nodes[0].front();
13467 Node* right_sub_node_pt = tmp_sub_nodes[0].back();
13470 if (left_sub_node_pt == right_sub_node_pt)
13476 std::list<Node*> first_half_node_pt;
13477 std::list<Node*> second_half_node_pt;
13479 Vector<FiniteElement*> first_half_ele_pt;
13480 Vector<FiniteElement*> second_half_ele_pt;
13482 Vector<int> first_half_face_idx;
13483 Vector<int> second_half_face_idx;
13486 const unsigned n_sub_nodes = tmp_sub_nodes[0].size();
13490 const unsigned n_sub_nodes_half =
13491 static_cast<unsigned>(n_sub_nodes / 2.0);
13496 std::list<Node*>::iterator it_sub = tmp_sub_nodes[0].begin();
13499 first_half_node_pt.push_back(*it_sub);
13505 unsigned counter_nodes = 0;
13506 unsigned counter2 = 0;
13509 for (; it_sub != tmp_sub_nodes[0].end(); it_sub++)
13512 first_half_node_pt.push_back(*it_sub);
13515 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
13516 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2 + 1]);
13518 first_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
13519 first_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2 + 1]);
13527 if (counter_nodes == n_sub_nodes_half)
13538 second_half_node_pt.push_back(*it_sub);
13544 for (; it_sub != tmp_sub_nodes[0].end(); it_sub++)
13547 second_half_node_pt.push_back(*it_sub);
13550 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
13551 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2 + 1]);
13553 second_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
13554 second_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2 + 1]);
13562 output_sorted_nodes_pt.push_back(first_half_node_pt);
13563 output_sorted_nodes_pt.push_back(second_half_node_pt);
13566 output_boundary_element_pt.push_back(first_half_ele_pt);
13567 output_boundary_element_pt.push_back(second_half_ele_pt);
13570 output_face_index_element.push_back(first_half_face_idx);
13571 output_face_index_element.push_back(second_half_face_idx);
13582 if (input_connect_to_the_left == -3)
13585 output_connect_to_the_left.push_back(-1);
13588 else if (input_connect_to_the_left == -2)
13591 output_connect_to_the_left.push_back(-1);
13596 output_connect_to_the_left.push_back(input_connect_to_the_left);
13602 output_connect_to_the_right.push_back(-1);
13613 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
13619 if (n_sub_list == 1)
13621 if (input_connect_to_the_right == -3)
13624 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13626 else if (input_connect_to_the_right == -2)
13629 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13631 else if (input_connect_to_the_right == -1)
13634 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13639 output_connect_to_the_right.push_back(input_connect_to_the_right);
13645 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13658 output_sorted_nodes_pt.push_back(tmp_sub_nodes[0]);
13661 output_boundary_element_pt.push_back(tmp_sub_bnd_ele_pt[0]);
13664 output_face_index_element.push_back(tmp_sub_face_idx_ele[0]);
13672 if (input_connect_to_the_left == -3)
13675 output_connect_to_the_left.push_back(-1);
13678 else if (input_connect_to_the_left == -2)
13681 output_connect_to_the_left.push_back(tmp_shd_bnd_id + 1);
13686 output_connect_to_the_left.push_back(input_connect_to_the_left);
13692 output_connect_to_the_right.push_back(tmp_shd_bnd_id + 1);
13700 if (n_sub_list > 1)
13704 left_sub_node_pt = tmp_sub_nodes[1].front();
13705 right_sub_node_pt = tmp_sub_nodes[1].back();
13708 if (left_sub_node_pt == right_sub_node_pt)
13714 std::list<Node*> first_half_node_pt;
13715 std::list<Node*> second_half_node_pt;
13717 Vector<FiniteElement*> first_half_ele_pt;
13718 Vector<FiniteElement*> second_half_ele_pt;
13720 Vector<int> first_half_face_idx;
13721 Vector<int> second_half_face_idx;
13724 const unsigned n_sub_nodes = tmp_sub_nodes[1].size();
13728 const unsigned n_sub_nodes_half =
13729 static_cast<unsigned>(n_sub_nodes / 2.0);
13734 std::list<Node*>::iterator it_sub = tmp_sub_nodes[1].begin();
13737 first_half_node_pt.push_back(*it_sub);
13743 unsigned counter_nodes = 0;
13744 unsigned counter2 = 0;
13747 for (; it_sub != tmp_sub_nodes[1].end(); it_sub++)
13750 first_half_node_pt.push_back(*it_sub);
13752 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2]);
13753 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2 + 1]);
13755 first_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2]);
13756 first_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2 + 1]);
13764 if (counter_nodes == n_sub_nodes_half)
13775 second_half_node_pt.push_back(*it_sub);
13781 for (; it_sub != tmp_sub_nodes[1].end(); it_sub++)
13784 second_half_node_pt.push_back(*it_sub);
13786 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2]);
13787 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2 + 1]);
13789 second_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2]);
13790 second_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2 + 1]);
13798 output_sorted_nodes_pt.push_back(first_half_node_pt);
13799 output_sorted_nodes_pt.push_back(second_half_node_pt);
13802 output_boundary_element_pt.push_back(first_half_ele_pt);
13803 output_boundary_element_pt.push_back(second_half_ele_pt);
13806 output_face_index_element.push_back(first_half_face_idx);
13807 output_face_index_element.push_back(second_half_face_idx);
13818 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
13823 output_connect_to_the_right.push_back(-1);
13834 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
13840 if (n_sub_list == 2)
13843 if (input_connect_to_the_right == -1)
13846 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13849 else if (input_connect_to_the_right == -2)
13852 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13855 else if (input_connect_to_the_right == -3)
13858 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13863 output_connect_to_the_right.push_back(input_connect_to_the_right);
13873 std::stringstream error_message;
13875 <<
"The second sub-list of nodes creates a loop but this is not\n"
13876 <<
"the last list of sub-nodes.\n"
13877 <<
"This configuration is not supported\n";
13878 throw OomphLibError(
13879 error_message.str(),
13880 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13881 OOMPH_EXCEPTION_LOCATION);
13892 output_sorted_nodes_pt.push_back(tmp_sub_nodes[1]);
13895 output_boundary_element_pt.push_back(tmp_sub_bnd_ele_pt[1]);
13898 output_face_index_element.push_back(tmp_sub_face_idx_ele[1]);
13906 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
13912 if (n_sub_list == 2)
13915 if (input_connect_to_the_right == -3)
13918 output_connect_to_the_right.push_back(-1);
13922 else if (input_connect_to_the_right == -2)
13924 std::stringstream error_message;
13926 <<
"The connection flag to the right ("
13927 << input_connect_to_the_right <<
") indicates a connection\n"
13928 <<
"with the same polyline.\n However, the second sub-list of\n"
13929 <<
"nodes was found not making a loop so no connection with\n"
13930 <<
"itself should be marked\n\n";
13931 throw OomphLibError(
13932 error_message.str(),
13933 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13934 OOMPH_EXCEPTION_LOCATION);
13940 output_connect_to_the_right.push_back(input_connect_to_the_right);
13946 output_connect_to_the_right.push_back(tmp_shd_bnd_id + 1);
13957 if (n_sub_list > 2)
13961 left_sub_node_pt = tmp_sub_nodes[2].front();
13962 right_sub_node_pt = tmp_sub_nodes[2].back();
13965 if (left_sub_node_pt == right_sub_node_pt)
13971 std::list<Node*> first_half_node_pt;
13972 std::list<Node*> second_half_node_pt;
13974 Vector<FiniteElement*> first_half_ele_pt;
13975 Vector<FiniteElement*> second_half_ele_pt;
13977 Vector<int> first_half_face_idx;
13978 Vector<int> second_half_face_idx;
13981 const unsigned n_sub_nodes = tmp_sub_nodes[2].size();
13985 const unsigned n_sub_nodes_half =
13986 static_cast<unsigned>(n_sub_nodes / 2.0);
13991 std::list<Node*>::iterator it_sub = tmp_sub_nodes[2].begin();
13994 first_half_node_pt.push_back(*it_sub);
14000 unsigned counter_nodes = 0;
14001 unsigned counter2 = 0;
14004 for (; it_sub != tmp_sub_nodes[2].end(); it_sub++)
14007 first_half_node_pt.push_back(*it_sub);
14009 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2]);
14010 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2 + 1]);
14012 first_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2]);
14013 first_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2 + 1]);
14021 if (counter_nodes == n_sub_nodes_half)
14032 second_half_node_pt.push_back(*it_sub);
14038 for (; it_sub != tmp_sub_nodes[2].end(); it_sub++)
14041 second_half_node_pt.push_back(*it_sub);
14043 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2]);
14044 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2 + 1]);
14046 second_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2]);
14047 second_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2 + 1]);
14055 output_sorted_nodes_pt.push_back(first_half_node_pt);
14056 output_sorted_nodes_pt.push_back(second_half_node_pt);
14059 output_boundary_element_pt.push_back(first_half_ele_pt);
14060 output_boundary_element_pt.push_back(second_half_ele_pt);
14063 output_face_index_element.push_back(first_half_face_idx);
14064 output_face_index_element.push_back(second_half_face_idx);
14072 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
14077 output_connect_to_the_right.push_back(-1);
14088 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
14092 if (input_connect_to_the_right == -3)
14095 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14097 else if (input_connect_to_the_right == -2)
14100 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14102 else if (input_connect_to_the_right == -1)
14105 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14110 output_connect_to_the_right.push_back(input_connect_to_the_right);
14123 output_sorted_nodes_pt.push_back(tmp_sub_nodes[2]);
14126 output_boundary_element_pt.push_back(tmp_sub_bnd_ele_pt[2]);
14129 output_face_index_element.push_back(tmp_sub_face_idx_ele[2]);
14137 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
14142 if (input_connect_to_the_right == -3)
14144 std::stringstream error_message;
14146 <<
"The connection flag to the right ("
14147 << input_connect_to_the_right <<
") indicates 'no connection and\n"
14148 <<
"stop adding nodes'.\n However, the thrid sub-list of\n"
14149 <<
"nodes must have a connection to the right with the same\n"
14150 <<
"shared polyline or with any other polyline\n\n";
14151 throw OomphLibError(
14152 error_message.str(),
14153 "TriangleMesh::break_loops_on_shared_polyline_helper()",
14154 OOMPH_EXCEPTION_LOCATION);
14156 else if (input_connect_to_the_right == -1)
14158 std::stringstream error_message;
14160 <<
"The connection flag to the right ("
14161 << input_connect_to_the_right <<
") indicates 'no connection.\n"
14162 <<
"However, the thrid sub-list of nodes must have a connection\n"
14163 <<
"to the right with the same shared polyline or with any other\n"
14165 throw OomphLibError(
14166 error_message.str(),
14167 "TriangleMesh::break_loops_on_shared_polyline_helper()",
14168 OOMPH_EXCEPTION_LOCATION);
14171 else if (input_connect_to_the_right == -2)
14174 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14179 output_connect_to_the_right.push_back(input_connect_to_the_right);
14194 template<
class ELEMENT>
14197 const unsigned& initial_shd_bnd_id,
14198 std::list<Node*>& input_nodes,
14199 Vector<FiniteElement*>& input_boundary_element_pt,
14200 Vector<FiniteElement*>& input_boundary_face_element_pt,
14201 Vector<int>& input_face_index_element,
14202 const int& input_connect_to_the_left,
14203 const int& input_connect_to_the_right,
14204 Vector<std::list<Node*>>& output_sorted_nodes_pt,
14205 Vector<Vector<FiniteElement*>>& output_boundary_element_pt,
14206 Vector<Vector<FiniteElement*>>& output_boundary_face_element_pt,
14207 Vector<Vector<int>>& output_face_index_element,
14208 Vector<int>& output_connect_to_the_left,
14209 Vector<int>& output_connect_to_the_right)
14212 Node* left_node_pt = input_nodes.front();
14213 Node* right_node_pt = input_nodes.back();
14217 Vector<std::list<Node*>> tmp_sub_nodes;
14218 Vector<Vector<FiniteElement*>> tmp_sub_bnd_ele_pt;
14219 Vector<Vector<FiniteElement*>> tmp_sub_bnd_face_ele_pt;
14220 Vector<Vector<int>> tmp_sub_face_idx_ele;
14223 std::list<Node*>::iterator it = input_nodes.begin();
14226 unsigned counter = 0;
14229 while (it != input_nodes.end())
14234 if (it == input_nodes.end())
14246 std::list<Node*> sub_nodes;
14249 Vector<FiniteElement*> sub_bnd_ele_pt;
14252 Vector<FiniteElement*> sub_bnd_face_ele_pt;
14255 Vector<int> sub_face_idx_ele;
14258 sub_nodes.push_back(*it);
14268 sub_nodes.push_back((*it));
14271 sub_bnd_ele_pt.push_back(input_boundary_element_pt[counter]);
14274 sub_bnd_face_ele_pt.push_back(input_boundary_face_element_pt[counter]);
14277 sub_face_idx_ele.push_back(input_face_index_element[counter]);
14284 }
while ((*it) != left_node_pt && (*it) != right_node_pt &&
14285 it != input_nodes.end());
14288 tmp_sub_nodes.push_back(sub_nodes);
14291 tmp_sub_bnd_ele_pt.push_back(sub_bnd_ele_pt);
14293 tmp_sub_bnd_face_ele_pt.push_back(sub_bnd_face_ele_pt);
14295 tmp_sub_face_idx_ele.push_back(sub_face_idx_ele);
14303 const unsigned n_sub_list = tmp_sub_nodes.size();
14306 if (n_sub_list > 1)
14308 std::stringstream error_message;
14310 <<
"The number of sub-list of nodes created from the shared\n"
14311 <<
"polyline with loops was (" << n_sub_list <<
").\n"
14312 <<
"We can only handle one list which may still contain loops\n"
14313 <<
"(or repeated nodes)\n";
14314 throw OomphLibError(
14315 error_message.str(),
14316 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14317 OOMPH_EXCEPTION_LOCATION);
14323 if (n_sub_list == 1 && (left_node_pt != right_node_pt))
14331 output_sorted_nodes_pt = tmp_sub_nodes;
14333 output_boundary_element_pt = tmp_sub_bnd_ele_pt;
14335 output_boundary_face_element_pt = tmp_sub_bnd_face_ele_pt;
14337 output_face_index_element = tmp_sub_face_idx_ele;
14343 if (input_connect_to_the_left == -2)
14345 std::stringstream error_message;
14347 <<
"The connection flag to the left (" << input_connect_to_the_left
14348 <<
") indicates a connection\n"
14349 <<
"with the same polyline.\n However, only one sub-polyline was "
14350 <<
"found and no loops\nwere identified\n\n";
14351 throw OomphLibError(
14352 error_message.str(),
14353 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14354 OOMPH_EXCEPTION_LOCATION);
14359 if (input_connect_to_the_left == -3)
14361 output_connect_to_the_left.push_back(-1);
14365 output_connect_to_the_left.push_back(input_connect_to_the_left);
14369 if (input_connect_to_the_right == -2)
14371 std::stringstream error_message;
14373 <<
"The connection flag to the right (" << input_connect_to_the_right
14374 <<
") indicates a connection\n"
14375 <<
"with the same polyline.\n However, only one sub-polyline was "
14376 <<
"found and no loops\nwere identified\n\n";
14377 throw OomphLibError(
14378 error_message.str(),
14379 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14380 OOMPH_EXCEPTION_LOCATION);
14385 if (input_connect_to_the_right == -3)
14387 output_connect_to_the_right.push_back(-1);
14391 output_connect_to_the_right.push_back(input_connect_to_the_right);
14399 unsigned tmp_shd_bnd_id = initial_shd_bnd_id;
14407 Node* left_sub_node_pt = tmp_sub_nodes[0].front();
14408 Node* right_sub_node_pt = tmp_sub_nodes[0].back();
14411 if (left_sub_node_pt == right_sub_node_pt)
14417 std::list<Node*> first_half_node_pt;
14418 std::list<Node*> second_half_node_pt;
14420 Vector<FiniteElement*> first_half_ele_pt;
14421 Vector<FiniteElement*> second_half_ele_pt;
14423 Vector<FiniteElement*> first_half_ele_face_pt;
14424 Vector<FiniteElement*> second_half_ele_face_pt;
14426 Vector<int> first_half_face_idx;
14427 Vector<int> second_half_face_idx;
14430 const unsigned n_sub_nodes = tmp_sub_nodes[0].size();
14434 const unsigned n_sub_nodes_half =
14435 static_cast<unsigned>(n_sub_nodes / 2.0);
14440 std::list<Node*>::iterator it_sub = tmp_sub_nodes[0].begin();
14443 first_half_node_pt.push_back(*it_sub);
14449 unsigned counter_nodes = 0;
14450 unsigned counter2 = 0;
14453 for (; it_sub != tmp_sub_nodes[0].end(); it_sub++)
14456 first_half_node_pt.push_back(*it_sub);
14459 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
14461 first_half_ele_face_pt.push_back(tmp_sub_bnd_face_ele_pt[0][counter2]);
14463 first_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
14471 if (counter_nodes == n_sub_nodes_half)
14482 second_half_node_pt.push_back(*it_sub);
14488 for (; it_sub != tmp_sub_nodes[0].end(); it_sub++)
14491 second_half_node_pt.push_back(*it_sub);
14494 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
14496 second_half_ele_face_pt.push_back(tmp_sub_bnd_face_ele_pt[0][counter2]);
14498 second_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
14506 output_sorted_nodes_pt.push_back(first_half_node_pt);
14507 output_sorted_nodes_pt.push_back(second_half_node_pt);
14510 output_boundary_element_pt.push_back(first_half_ele_pt);
14511 output_boundary_element_pt.push_back(second_half_ele_pt);
14514 output_boundary_face_element_pt.push_back(first_half_ele_face_pt);
14515 output_boundary_face_element_pt.push_back(second_half_ele_face_pt);
14518 output_face_index_element.push_back(first_half_face_idx);
14519 output_face_index_element.push_back(second_half_face_idx);
14530 if (input_connect_to_the_left == -3)
14533 output_connect_to_the_left.push_back(-1);
14536 else if (input_connect_to_the_left == -2)
14539 output_connect_to_the_left.push_back(-1);
14544 output_connect_to_the_left.push_back(input_connect_to_the_left);
14550 output_connect_to_the_right.push_back(-1);
14561 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
14567 if (n_sub_list == 1)
14569 if (input_connect_to_the_right == -3)
14572 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14574 else if (input_connect_to_the_right == -2)
14577 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14579 else if (input_connect_to_the_right == -1)
14582 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14587 output_connect_to_the_right.push_back(input_connect_to_the_right);
14593 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14603 std::stringstream error_message;
14605 <<
"The initial and final node in the current shared polyline are not\n"
14606 <<
"the same and the number of sublists is (" << n_sub_list <<
").\n"
14607 <<
"We can not handle more than one sublist in the method to break\n"
14608 <<
"loops at the load balance stage\n\n";
14609 throw OomphLibError(
14610 error_message.str(),
14611 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14612 OOMPH_EXCEPTION_LOCATION);
14622 template<
class ELEMENT>
14624 const unsigned& my_rank,
14625 const unsigned& shd_bnd_id,
14626 const unsigned& iproc,
14627 const unsigned& jproc,
14628 std::list<Node*>& sorted_nodes,
14629 const int& root_edge_bnd_id,
14630 Vector<FiniteElement*>& bulk_bnd_ele_pt,
14631 Vector<int>& face_index_ele,
14632 Vector<Vector<TriangleMeshPolyLine*>>& unsorted_polylines_pt,
14633 const int& connect_to_the_left_flag,
14634 const int& connect_to_the_right_flag)
14645 Shared_boundaries_ids[iproc][jproc].push_back(shd_bnd_id);
14648 Shared_boundaries_ids[jproc][iproc].push_back(shd_bnd_id);
14652 Vector<unsigned> processors(2);
14653 processors[0] = iproc;
14654 processors[1] = jproc;
14655 Shared_boundary_from_processors[shd_bnd_id] = processors;
14661 if (iproc == my_rank || jproc == my_rank)
14668 const unsigned n_nodes = sorted_nodes.size();
14670 Vector<Vector<double>> vertices(n_nodes);
14673 unsigned counter = 0;
14675 for (std::list<Node*>::iterator it = sorted_nodes.begin();
14676 it != sorted_nodes.end();
14679 vertices[counter].resize(2);
14680 vertices[counter][0] = (*it)->x(0);
14681 vertices[counter][1] = (*it)->x(1);
14688 TriangleMeshPolyLine* polyline_pt =
14689 new TriangleMeshPolyLine(vertices, shd_bnd_id);
14697 if (root_edge_bnd_id != -1)
14701 Shared_boundary_overlaps_internal_boundary[shd_bnd_id] =
14702 static_cast<unsigned>(root_edge_bnd_id);
14710 const unsigned n_shared_boundary_elements = bulk_bnd_ele_pt.size();
14714 const unsigned n_face_index = face_index_ele.size();
14715 if (n_shared_boundary_elements != n_face_index)
14717 std::ostringstream error_message;
14719 <<
"The number of shared boundary elements is different from the\n"
14720 <<
"number of face indexes associated to the shared boundary\n"
14722 <<
"Number of shared boundary elements: ("
14723 << n_shared_boundary_elements <<
")\n"
14724 <<
"Number of face indexes: (" << n_face_index <<
")\n\n";
14725 throw OomphLibError(error_message.str(),
14726 "TriangleMesh::create_shared_polyline()",
14727 OOMPH_EXCEPTION_LOCATION);
14733 for (
unsigned i = 0; i < n_shared_boundary_elements; i++)
14735 add_shared_boundary_element(shd_bnd_id, bulk_bnd_ele_pt[i]);
14736 add_face_index_at_shared_boundary(shd_bnd_id, face_index_ele[i]);
14740 for (std::list<Node*>::iterator it = sorted_nodes.begin();
14741 it != sorted_nodes.end();
14744 add_shared_boundary_node(shd_bnd_id, (*it));
14752 this->Boundary_curve_section_pt[shd_bnd_id] = polyline_pt;
14757 const unsigned n_procs = unsorted_polylines_pt.size();
14762 unsorted_polylines_pt[iproc].push_back(polyline_pt);
14766 unsorted_polylines_pt[jproc].push_back(polyline_pt);
14772 unsorted_polylines_pt[0].push_back(polyline_pt);
14776 this->Free_curve_section_pt.insert(polyline_pt);
14786 if (connect_to_the_left_flag < 0)
14789 if (connect_to_the_left_flag != -1)
14791 std::ostringstream error_message;
14793 <<
"The only accepted values for the connection flags are:\n"
14794 <<
"POSITIVE values or -1, any other value is rejected, please\n"
14795 <<
"check that you previously called the methods to deal with\n"
14796 <<
"other flag values\n"
14797 <<
"The current flag value for connection to the left is: ("
14798 << connect_to_the_left_flag <<
")\n\n";
14799 throw OomphLibError(error_message.str(),
14800 "TriangleMesh::create_shared_polyline()",
14801 OOMPH_EXCEPTION_LOCATION);
14806 if (connect_to_the_right_flag < 0)
14809 if (connect_to_the_right_flag != -1)
14811 std::ostringstream error_message;
14813 <<
"The only accepted values for the connection flags are:\n"
14814 <<
"POSITIVE values or -1, any other value is rejected, please\n"
14815 <<
"check that you previously called the methods to deal with\n"
14816 <<
"other flag values\n"
14817 <<
"The current flag value for connection to the right is: ("
14818 << connect_to_the_right_flag <<
")\n\n";
14819 throw OomphLibError(error_message.str(),
14820 "TriangleMesh::create_shared_polyline()",
14821 OOMPH_EXCEPTION_LOCATION);
14827 if (connect_to_the_left_flag != -1)
14830 const unsigned bnd_id_connection_to_the_left =
14831 static_cast<unsigned>(connect_to_the_left_flag);
14833 polyline_pt->set_initial_vertex_connected();
14835 polyline_pt->initial_vertex_connected_bnd_id() =
14836 bnd_id_connection_to_the_left;
14838 polyline_pt->initial_vertex_connected_n_chunk() = 0;
14843 if (connect_to_the_right_flag != -1)
14846 const unsigned bnd_id_connection_to_the_right =
14847 static_cast<unsigned>(connect_to_the_right_flag);
14849 polyline_pt->set_final_vertex_connected();
14851 polyline_pt->final_vertex_connected_bnd_id() =
14852 bnd_id_connection_to_the_right;
14854 polyline_pt->final_vertex_connected_n_chunk() = 0;
14865 template<
class ELEMENT>
14867 Vector<unsigned>& ntmp_boundary_elements,
14868 Vector<Vector<unsigned>>& ntmp_boundary_elements_in_region,
14869 Vector<FiniteElement*>& deleted_elements)
14872 const unsigned nbound = this->nboundary();
14875 const unsigned n_regions = this->nregion();
14878 for (
unsigned b = 0; b < nbound; b++)
14883 const unsigned nbound_ele = this->nboundary_element(b);
14885 Vector<FiniteElement*> backed_up_boundary_element_pt(nbound_ele);
14886 Vector<int> backed_up_face_index_at_boundary(nbound_ele);
14887 for (
unsigned e = 0; e < nbound_ele; e++)
14890 backed_up_boundary_element_pt[e] = this->boundary_element_pt(b, e);
14892 backed_up_face_index_at_boundary[e] =
14893 this->face_index_at_boundary(b, e);
14897 Vector<Vector<FiniteElement*>> backed_up_boundary_region_element_pt(
14899 Vector<Vector<int>> backed_up_face_index_at_boundary_region(n_regions);
14903 for (
unsigned ir = 0; ir < n_regions; ir++)
14906 const unsigned region_id =
14907 static_cast<unsigned>(this->region_attribute(ir));
14909 const unsigned nbnd_region_ele =
14910 this->nboundary_element_in_region(b, region_id);
14913 for (
unsigned e = 0; e < nbnd_region_ele; e++)
14916 backed_up_boundary_region_element_pt[ir][e] =
14917 this->boundary_element_in_region_pt(b, region_id, e);
14920 backed_up_face_index_at_boundary_region[ir][e] =
14921 this->face_index_at_boundary_in_region(b, region_id, e);
14927 this->Boundary_element_pt[b].clear();
14928 this->Face_index_at_boundary[b].clear();
14931 this->Boundary_region_element_pt[b].clear();
14932 this->Face_index_region_at_boundary[b].clear();
14941 const unsigned nold_bnd_ele = ntmp_boundary_elements[b];
14943 for (
unsigned e = 0; e < nold_bnd_ele; e++)
14945 FiniteElement* tmp_ele_pt = backed_up_boundary_element_pt[e];
14947 Vector<FiniteElement*>::iterator it = std::find(
14948 deleted_elements.begin(), deleted_elements.end(), tmp_ele_pt);
14951 if (it == deleted_elements.end())
14953 FiniteElement* add_ele_pt = backed_up_boundary_element_pt[e];
14954 this->Boundary_element_pt[b].push_back(add_ele_pt);
14955 const int face_index = backed_up_face_index_at_boundary[e];
14956 this->Face_index_at_boundary[b].push_back(face_index);
14964 for (
unsigned ir = 0; ir < n_regions; ir++)
14967 const unsigned region_id =
14968 static_cast<unsigned>(this->region_attribute(ir));
14971 const unsigned nold_bnd_region_ele =
14972 ntmp_boundary_elements_in_region[b][ir];
14976 for (
unsigned e = 0; e < nold_bnd_region_ele; e++)
14979 FiniteElement* tmp_ele_pt =
14980 backed_up_boundary_region_element_pt[ir][e];
14982 Vector<FiniteElement*>::iterator it = std::find(
14983 deleted_elements.begin(), deleted_elements.end(), tmp_ele_pt);
14986 if (it == deleted_elements.end())
14988 FiniteElement* add_ele_pt =
14989 backed_up_boundary_region_element_pt[ir][e];
14990 this->Boundary_region_element_pt[b][region_id].push_back(
14992 const int face_index =
14993 backed_up_face_index_at_boundary_region[ir][e];
14994 this->Face_index_region_at_boundary[b][region_id].push_back(
15007 for (
unsigned e = nold_bnd_ele; e < nbound_ele; e++)
15009 FiniteElement* add_ele_pt = backed_up_boundary_element_pt[e];
15010 this->Boundary_element_pt[b].push_back(add_ele_pt);
15011 const int face_index = backed_up_face_index_at_boundary[e];
15012 this->Face_index_at_boundary[b].push_back(face_index);
15018 for (
unsigned ir = 0; ir < n_regions; ir++)
15021 const unsigned region_id =
15022 static_cast<unsigned>(this->region_attribute(ir));
15025 const unsigned nold_bnd_region_ele =
15026 ntmp_boundary_elements_in_region[b][ir];
15029 const unsigned nbnd_region_ele =
15030 this->nboundary_element_in_region(b, region_id);
15034 for (
unsigned e = nold_bnd_region_ele; e < nbnd_region_ele; e++)
15036 FiniteElement* add_ele_pt =
15037 backed_up_boundary_region_element_pt[ir][e];
15038 this->Boundary_region_element_pt[b][region_id].push_back(add_ele_pt);
15039 const int face_index = backed_up_face_index_at_boundary_region[ir][e];
15040 this->Face_index_region_at_boundary[b][region_id].push_back(
15049 Lookup_for_elements_next_boundary_is_setup =
true;
15054 #ifdef OOMPH_HAS_TRIANGLE_LIB
15059 template<
class ELEMENT>
15061 TriangulateIO& triangulate_io,
15062 const Vector<double>& target_area,
15063 struct TriangulateIO& triangle_refine)
15066 TriangleHelper::initialise_triangulateio(triangle_refine);
15070 unsigned n_points = triangulate_io.numberofpoints;
15071 triangle_refine.numberofpoints = n_points;
15073 unsigned n_segments = triangulate_io.numberofsegments;
15074 triangle_refine.numberofsegments = n_segments;
15077 triangle_refine.pointlist =
15078 (
double*)malloc(triangulate_io.numberofpoints * 2 *
sizeof(
double));
15079 triangle_refine.pointmarkerlist =
15080 (
int*)malloc(triangulate_io.numberofpoints *
sizeof(
int));
15081 triangle_refine.segmentlist =
15082 (
int*)malloc(triangulate_io.numberofsegments * 2 *
sizeof(
int));
15083 triangle_refine.segmentmarkerlist =
15084 (
int*)malloc(triangulate_io.numberofsegments *
sizeof(
int));
15088 Vector<double> x_coord(n_points);
15089 Vector<double> y_coord(n_points);
15091 for (
unsigned count_point = 0; count_point < n_points * 2; count_point++)
15093 triangle_refine.pointlist[count_point] =
15094 triangulate_io.pointlist[count_point];
15098 if (count_point % 2 == 0)
15100 x_coord[count_point / 2] = triangulate_io.pointlist[count_point];
15104 y_coord[(count_point - 1) / 2] = triangulate_io.pointlist[count_point];
15109 for (
unsigned count_marker = 0; count_marker < n_points; count_marker++)
15111 triangle_refine.pointmarkerlist[count_marker] =
15112 triangulate_io.pointmarkerlist[count_marker];
15116 for (
unsigned count_seg = 0; count_seg < n_segments * 2; count_seg++)
15118 triangle_refine.segmentlist[count_seg] =
15119 triangulate_io.segmentlist[count_seg];
15123 for (
unsigned count_markers = 0; count_markers < n_segments;
15126 triangle_refine.segmentmarkerlist[count_markers] =
15127 triangulate_io.segmentmarkerlist[count_markers];
15131 unsigned n_holes = triangulate_io.numberofholes;
15132 triangle_refine.numberofholes = n_holes;
15134 triangle_refine.holelist =
15135 (
double*)malloc(triangulate_io.numberofholes * 2 *
sizeof(
double));
15138 for (
unsigned count_hole = 0; count_hole < n_holes * 2; count_hole++)
15140 triangle_refine.holelist[count_hole] =
15141 triangulate_io.holelist[count_hole];
15145 unsigned n_triangles = triangulate_io.numberoftriangles;
15146 triangle_refine.numberoftriangles = n_triangles;
15149 if (n_triangles != target_area.size())
15151 std::stringstream err;
15152 err <<
"Number of triangles in triangulate_io=" << n_triangles
15153 <<
" doesn't match\n"
15154 <<
"size of target area vector (" << target_area.size() <<
")\n";
15155 throw OomphLibError(
15156 err.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
15160 unsigned n_corners = triangulate_io.numberofcorners;
15161 triangle_refine.numberofcorners = n_corners;
15163 triangle_refine.trianglelist =
15164 (
int*)malloc(triangulate_io.numberoftriangles * 3 *
sizeof(
int));
15167 for (
unsigned count_tri = 0; count_tri < n_triangles * 3; count_tri++)
15169 triangle_refine.trianglelist[count_tri] =
15170 triangulate_io.trianglelist[count_tri];
15174 triangle_refine.trianglearealist =
15175 (
double*)malloc(triangulate_io.numberoftriangles *
sizeof(
double));
15176 for (
unsigned count_area = 0; count_area < n_triangles; count_area++)
15178 triangle_refine.trianglearealist[count_area] = target_area[count_area];
15182 triangle_refine.numberoftriangleattributes =
15183 triangulate_io.numberoftriangleattributes;
15185 triangle_refine.triangleattributelist = (
double*)malloc(
15186 triangulate_io.numberoftriangles *
15187 triangulate_io.numberoftriangleattributes *
sizeof(
double));
15188 for (
unsigned count_attribute = 0;
15190 (n_triangles * triangulate_io.numberoftriangleattributes);
15193 triangle_refine.triangleattributelist[count_attribute] =
15194 triangulate_io.triangleattributelist[count_attribute];
15198 #ifdef OOMPH_HAS_MPI
15212 const std::pair<double, double>& rhs)
const
15214 double diff_y = lhs.second - rhs.second;
15225 double diff_x = lhs.first - rhs.first;
15226 if (fabs(diff_x) <
Tol)
15228 std::ostringstream warning_message;
15230 <<
"Dodgy \"lower left\" (lexicographic) comparison "
15231 <<
"of points with cooordinates: "
15232 <<
" lhs = ( " << lhs.first <<
" , " << lhs.second <<
" ) \n"
15233 <<
" rhs = ( " << rhs.first <<
" , " << rhs.second <<
" ) \n"
15234 <<
"x and y coordinates differ by less than tolerance!\n"
15235 <<
"diff_x = " << diff_x <<
"\n"
15236 <<
"diff_y = " << diff_y <<
"\n"
15237 <<
"Tol = " <<
Tol <<
"\n";
15238 OomphLibError(warning_message.str(),
15239 OOMPH_CURRENT_FUNCTION,
15240 OOMPH_EXCEPTION_LOCATION);
15243 if (lhs.first < rhs.first)
15297 template<
class ELEMENT>
15301 Vector<unsigned> my_rank_shared_boundaries_ids;
15302 this->shared_boundaries_in_this_processor(my_rank_shared_boundaries_ids);
15305 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
15308 for (
unsigned i = 0; i < nmy_rank_shd_bnd; i++)
15313 std::map<std::pair<double, double>, Node*,
classcomp> sorted_nodes_pt;
15320 double min_distance_squared = DBL_MAX;
15325 const unsigned b = my_rank_shared_boundaries_ids[i];
15328 const unsigned nbnd_node = this->nshared_boundary_node(b);
15332 for (
unsigned i_node = 0; i_node < nbnd_node; i_node++)
15334 Node* node_pt = this->shared_boundary_node_pt(b, i_node);
15335 std::pair<double, double> vertex =
15336 std::make_pair(node_pt->x(0), node_pt->x(1));
15337 sorted_nodes_pt[vertex] = node_pt;
15343 for (
unsigned j_node = 0; j_node < nbnd_node; j_node++)
15345 if (i_node != j_node)
15347 Node* node2_pt = this->shared_boundary_node_pt(b, j_node);
15350 double squared_distance = 0.0;
15351 for (
unsigned ii = 0; ii < 2; ii++)
15353 squared_distance += (node_pt->x(ii) - node2_pt->x(ii)) *
15354 (node_pt->x(ii) - node2_pt->x(ii));
15356 if (squared_distance < min_distance_squared)
15358 min_distance_squared = squared_distance;
15365 std::ostringstream warning_message;
15366 warning_message <<
"Minimum distance between nodes on boundary " << b
15368 <<
"is " << sqrt(min_distance_squared)
15369 <<
" which is less than "
15370 <<
"Bottom_left_sorter.Tol = "
15372 <<
"This may screw up the ordering of the nodes on "
15373 "shared boundaries\n";
15374 OomphLibWarning(warning_message.str(),
15375 OOMPH_CURRENT_FUNCTION,
15376 OOMPH_EXCEPTION_LOCATION);
15382 unsigned counter = 0;
15384 this->Sorted_shared_boundary_node_pt[b].resize(nbnd_node);
15390 for (std::map<std::pair<double, double>, Node*>::iterator it_map =
15391 sorted_nodes_pt.begin();
15392 it_map != sorted_nodes_pt.end();
15396 this->Sorted_shared_boundary_node_pt[b][counter++] = (*it_map).second;
15407 template<
class ELEMENT>
15410 const bool update_elements,
15411 const bool flush_nodes,
15412 const bool update_nodes)
15415 const unsigned my_rank = this->communicator_pt()->my_rank();
15421 const unsigned initial_id = this->initial_shared_boundary_id();
15424 const unsigned final_id = this->final_shared_boundary_id();
15426 if (flush_elements)
15429 this->flush_shared_boundary_element();
15431 this->flush_face_index_at_shared_boundary();
15437 this->flush_shared_boundary_node();
15440 for (
unsigned b = initial_id; b < final_id; b++)
15443 Vector<unsigned> procs_from_shrd_bnd;
15444 procs_from_shrd_bnd = this->shared_boundary_from_processors(b);
15445 bool current_processor_has_b_boundary =
false;
15446 const unsigned n_procs_from_shrd_bnd = procs_from_shrd_bnd.size();
15447 for (
unsigned p = 0; p < n_procs_from_shrd_bnd; p++)
15449 if (procs_from_shrd_bnd[p] == my_rank)
15451 current_processor_has_b_boundary =
true;
15456 if (current_processor_has_b_boundary)
15458 if (update_elements)
15460 const unsigned nboundary_ele = this->nboundary_element(b);
15461 for (
unsigned e = 0; e < nboundary_ele; e++)
15465 FiniteElement* bnd_ele_pt = this->boundary_element_pt(b, e);
15466 this->add_shared_boundary_element(b, bnd_ele_pt);
15468 int face_index = this->face_index_at_boundary(b, e);
15469 this->add_face_index_at_shared_boundary(b, face_index);
15475 const unsigned nboundary_node = this->nboundary_node(b);
15476 for (
unsigned n = 0; n < nboundary_node; n++)
15478 Node* bnd_node_pt = this->boundary_node_pt(b, n);
15479 this->add_shared_boundary_node(b, bnd_node_pt);
15491 template<
class ELEMENT>
15495 unsigned nproc = this->communicator_pt()->nproc();
15497 unsigned my_rank = this->communicator_pt()->my_rank();
15500 double tt_start = 0.0;
15501 double tt_end = 0.0;
15502 if (Global_timings::Doc_comprehensive_timings)
15504 tt_start = TimingHelpers::timer();
15514 Vector<Vector<Vector<std::map<unsigned, Node*>>>>
15515 other_proc_shd_bnd_node_pt(nproc);
15517 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15520 other_proc_shd_bnd_node_pt[iproc].resize(nproc);
15521 for (
unsigned jproc = 0; jproc < nproc; jproc++)
15524 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
15525 const unsigned final_shd_bnd_id = this->final_shared_boundary_id();
15526 const unsigned nshared_bound = final_shd_bnd_id - initial_shd_bnd_id;
15527 other_proc_shd_bnd_node_pt[iproc][jproc].resize(nshared_bound);
15536 Vector<Vector<Vector<unsigned>>> global_node_names;
15540 std::map<Vector<unsigned>,
unsigned> node_name_to_global_index;
15543 Vector<Node*> global_shared_node_pt;
15547 double t_start_global_node_names_and_shared_nodes = TimingHelpers::timer();
15552 compute_global_node_names_and_shared_nodes(other_proc_shd_bnd_node_pt,
15554 node_name_to_global_index,
15555 global_shared_node_pt);
15558 const unsigned n_ele = this->nelement();
15560 if (Print_timings_level_adaptation > 1)
15564 double t_final_global_node_names_and_shared_nodes =
15565 TimingHelpers::timer() - t_start_global_node_names_and_shared_nodes;
15566 oomph_info <<
"CPU for computing global node names and shared nodes "
15567 <<
"[n_ele=" << n_ele
15568 <<
"]: " << t_final_global_node_names_and_shared_nodes
15586 double t_start_send_info_shd_nodes_on_original_bnds =
15587 TimingHelpers::timer();
15591 send_boundary_node_info_of_shared_nodes(
15592 global_node_names, node_name_to_global_index, global_shared_node_pt);
15594 if (Print_timings_level_adaptation > 1)
15599 <<
"CPU for sending info. of shared nodes on original boundaries: "
15600 << TimingHelpers::timer() - t_start_send_info_shd_nodes_on_original_bnds
15623 Vector<Vector<Vector<FiniteElement*>>> ele_with_node_on_shd_bnd_pt(nproc);
15628 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15630 const unsigned n_shd_bnd_iproc = this->nshared_boundaries(my_rank, iproc);
15631 ele_with_node_on_shd_bnd_pt[iproc].resize(n_shd_bnd_iproc);
15638 for (
unsigned e = 0; e < n_ele; e++)
15641 FiniteElement* ele_pt = this->finite_element_pt(e);
15643 const unsigned n_nodes = ele_pt->nnode();
15646 for (
unsigned n = 0; n < n_nodes; n++)
15649 Node* node_pt = ele_pt->node_pt(n);
15655 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15660 const unsigned n_shd_bnd_iproc =
15661 this->nshared_boundaries(my_rank, iproc);
15664 if (iproc != my_rank && n_shd_bnd_iproc > 0)
15668 Vector<unsigned> shd_bnd_ids =
15669 this->shared_boundaries_ids(my_rank, iproc);
15672 for (
unsigned isb = 0; isb < n_shd_bnd_iproc; isb++)
15674 const unsigned shd_bnd_id = shd_bnd_ids[isb];
15675 const unsigned n_ele_shd_bnd =
15676 this->nshared_boundary_element(shd_bnd_id);
15680 if (n_ele_shd_bnd > 0 &&
15681 this->is_node_on_shared_boundary(shd_bnd_id, node_pt))
15685 ele_with_node_on_shd_bnd_pt[iproc][isb].push_back(ele_pt);
15725 Vector<Vector<Node*>> iproc_currently_created_nodes_pt(nproc);
15728 double t_start_regenerate_halo_ed_elements_nodes_first_stage =
15729 TimingHelpers::timer();
15732 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15735 if (iproc != my_rank)
15738 const unsigned nshared_boundaries_with_iproc =
15739 this->nshared_boundaries(my_rank, iproc);
15741 if (nshared_boundaries_with_iproc > 0)
15753 Flat_packed_unsigneds.clear();
15754 Flat_packed_doubles.clear();
15755 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15756 Flat_packed_unsigneds_string.clear();
15760 Vector<unsigned> bound_shared_with_iproc;
15761 bound_shared_with_iproc = this->shared_boundaries_ids(my_rank, iproc);
15764 for (
unsigned bs = 0; bs < nshared_boundaries_with_iproc; bs++)
15766 const unsigned bnd_id = bound_shared_with_iproc[bs];
15768 const unsigned nel_bnd = this->nshared_boundary_element(bnd_id);
15772 Vector<FiniteElement*> haloed_element;
15779 std::map<FiniteElement*, bool> already_added;
15782 for (
unsigned e = 0; e < nel_bnd; e++)
15785 FiniteElement* ele_pt =
15786 this->shared_boundary_element_pt(bnd_id, e);
15791 if (!already_added[ele_pt])
15794 haloed_element.push_back(ele_pt);
15796 already_added[ele_pt] =
true;
15807 const unsigned n_ele_with_node_on_shd_bnd =
15808 ele_with_node_on_shd_bnd_pt[iproc][bs].size();
15811 for (
unsigned iele = 0; iele < n_ele_with_node_on_shd_bnd; iele++)
15814 FiniteElement* ele_pt =
15815 ele_with_node_on_shd_bnd_pt[iproc][bs][iele];
15817 if (!already_added[ele_pt])
15820 haloed_element.push_back(ele_pt);
15822 already_added[ele_pt] =
true;
15830 const unsigned nhaloed_ele = haloed_element.size();
15837 Flat_packed_unsigneds.push_back(nhaloed_ele);
15838 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15839 std::stringstream junk;
15840 junk <<
"Number of haloed elements " << nhaloed_ele;
15841 Flat_packed_unsigneds_string.push_back(junk.str());
15845 for (
unsigned e = 0; e < nhaloed_ele; e++)
15848 FiniteElement* ele_pt = haloed_element[e];
15849 const unsigned nroot_haloed_ele =
15850 this->nroot_haloed_element(iproc);
15854 GeneralisedElement* gen_ele_pt = ele_pt;
15855 const unsigned haloed_ele_index =
15856 this->try_to_add_root_haloed_element_pt(iproc, gen_ele_pt);
15860 if (nroot_haloed_ele == haloed_ele_index)
15862 Flat_packed_unsigneds.push_back(1);
15863 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15864 Flat_packed_unsigneds_string.push_back(
15865 "Haloed element needs to be constructed");
15869 get_required_elemental_information_helper(iproc, ele_pt);
15872 const unsigned nnodes = ele_pt->nnode();
15873 for (
unsigned j = 0; j < nnodes; j++)
15875 Node* node_pt = ele_pt->node_pt(j);
15879 add_haloed_node_helper(iproc, node_pt);
15885 Flat_packed_unsigneds.push_back(0);
15886 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15887 Flat_packed_unsigneds_string.push_back(
15888 "Haloed element already exists");
15890 Flat_packed_unsigneds.push_back(haloed_ele_index);
15891 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15892 Flat_packed_unsigneds_string.push_back(
15893 "Index of existing haloed element");
15907 int send_proc =
static_cast<int>(iproc);
15909 int recv_proc =
static_cast<int>(iproc);
15910 send_and_receive_elements_nodes_info(send_proc, recv_proc);
15919 Counter_for_flat_packed_doubles = 0;
15920 Counter_for_flat_packed_unsigneds = 0;
15923 for (
unsigned bs = 0; bs < nshared_boundaries_with_iproc; bs++)
15926 const unsigned nhaloed_ele =
15927 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
15929 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15931 <<
"Rec:" << Counter_for_flat_packed_unsigneds
15932 <<
" Number of elements need to be constructed "
15933 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
15938 for (
unsigned e = 0; e < nhaloed_ele; e++)
15942 create_halo_element(iproc,
15943 iproc_currently_created_nodes_pt[iproc],
15944 other_proc_shd_bnd_node_pt,
15946 node_name_to_global_index,
15947 global_shared_node_pt);
15959 if (Print_timings_level_adaptation > 1)
15962 double t_final_regenerate_halo_ed_elements_nodes_first_stage =
15963 TimingHelpers::timer() -
15964 t_start_regenerate_halo_ed_elements_nodes_first_stage;
15966 oomph_info <<
"CPU for re-generating halo(ed) elements/nodes "
15967 <<
"(first stage) [n_ele=" << n_ele <<
"]: "
15968 << t_final_regenerate_halo_ed_elements_nodes_first_stage
15985 double t_start_regenerate_halo_ed_elements_nodes_second_stage =
15986 TimingHelpers::timer();
15990 reset_halo_haloed_scheme_helper(other_proc_shd_bnd_node_pt,
15991 iproc_currently_created_nodes_pt,
15993 node_name_to_global_index,
15994 global_shared_node_pt);
15996 if (Print_timings_level_adaptation > 1)
15999 double t_final_regenerate_halo_ed_elements_nodes_second_stage =
16000 TimingHelpers::timer() -
16001 t_start_regenerate_halo_ed_elements_nodes_second_stage;
16003 oomph_info <<
"CPU for re-generating halo(ed) elements/nodes "
16004 <<
"(second stage) [n_ele=" << n_ele <<
"]: "
16005 << t_final_regenerate_halo_ed_elements_nodes_second_stage
16015 Flat_packed_unsigneds.clear();
16016 Flat_packed_doubles.clear();
16017 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
16018 Flat_packed_unsigneds_string.clear();
16023 if (Print_timings_level_adaptation > 1)
16025 tt_end = TimingHelpers::timer();
16026 oomph_info <<
"CPU for resetting halo-haloed scheme (without "
16027 "classification of halo and haloed nodes): "
16028 << tt_end - tt_start << std::endl;
16034 const bool report_stats =
true;
16035 DocInfo tmp_doc_info;
16036 tmp_doc_info.disable_doc();
16039 this->classify_halo_and_haloed_nodes(tmp_doc_info, report_stats);
16043 if (Print_timings_level_adaptation > 1)
16045 tt_end = TimingHelpers::timer();
16046 oomph_info <<
"CPU for resetting halo-haloed scheme (with classification "
16047 "of halo and haloed nodes): "
16048 << tt_end - tt_start << std::endl;
16065 template<
class ELEMENT>
16068 Vector<Vector<Vector<std::map<unsigned, Node*>>>>&
16069 other_proc_shd_bnd_node_pt,
16070 Vector<Vector<Vector<unsigned>>>& global_node_names,
16071 std::map<Vector<unsigned>,
unsigned>& node_name_to_global_index,
16072 Vector<Node*>& global_shared_node_pt)
16075 const unsigned nproc = this->communicator_pt()->nproc();
16077 const unsigned my_rank = this->communicator_pt()->my_rank();
16079 OomphCommunicator* comm_pt = this->communicator_pt();
16089 unsigned counter_nodes = 0;
16091 std::map<Node*, bool> done_node;
16093 std::map<Node*, unsigned> local_node_number;
16095 Vector<Node*> local_node_pt;
16111 Vector<Vector<Vector<unsigned>>> local_node_names;
16114 for (
unsigned iproc = 0; iproc < nproc; iproc++)
16117 if (iproc != my_rank)
16120 const unsigned n_shd_bnds_with_iproc =
16121 this->nshared_boundaries(my_rank, iproc);
16124 Vector<unsigned> bnd_shd_with_iproc =
16125 this->shared_boundaries_ids(my_rank, iproc);
16128 for (
unsigned ishd = 0; ishd < n_shd_bnds_with_iproc; ishd++)
16131 std::map<Node*, bool> done_node_shd_bnd;
16133 unsigned shd_bnd_id = bnd_shd_with_iproc[ishd];
16135 const unsigned n_shd_bnd_ele =
16136 this->nshared_boundary_element(shd_bnd_id);
16139 for (
unsigned e = 0; e < n_shd_bnd_ele; e++)
16142 FiniteElement* ele_pt =
16143 this->shared_boundary_element_pt(shd_bnd_id, e);
16146 const unsigned n_nodes = ele_pt->nnode();
16149 for (
unsigned n = 0; n < n_nodes; n++)
16152 Node* node_pt = ele_pt->node_pt(n);
16157 if (!done_node_shd_bnd[node_pt] &&
16158 this->is_node_on_shared_boundary(shd_bnd_id, node_pt))
16161 done_node_shd_bnd[node_pt] =
true;
16166 const unsigned n_nodes_shd_bnd =
16167 nsorted_shared_boundary_node(shd_bnd_id);
16170 unsigned index = 0;
16174 bool found_node_on_shared_boundary =
false;
16178 for (
unsigned k = 0; k < n_nodes_shd_bnd; k++)
16181 Node* shd_bnd_node_pt =
16182 sorted_shared_boundary_node_pt(shd_bnd_id, k);
16185 if (shd_bnd_node_pt == node_pt)
16191 found_node_on_shared_boundary =
true;
16200 if (!found_node_on_shared_boundary)
16202 std::ostringstream error_message;
16203 error_message <<
"The index of the node on boundary ("
16204 << shd_bnd_id <<
") was not found.\n"
16205 <<
"These are the node coordinates\n"
16206 <<
"(" << node_pt->x(0) <<
"," << node_pt->x(1)
16208 throw OomphLibError(error_message.str(),
16209 OOMPH_CURRENT_FUNCTION,
16210 OOMPH_EXCEPTION_LOCATION);
16215 Vector<unsigned> node_name(5);
16216 node_name[0] = my_rank;
16217 node_name[1] = iproc;
16218 node_name[2] = shd_bnd_id;
16219 node_name[3] = index;
16224 if (!done_node[node_pt])
16229 local_node_pt.push_back(node_pt);
16232 local_node_number[node_pt] = counter_nodes;
16234 node_name[4] = counter_nodes;
16238 done_node[node_pt] =
true;
16242 Vector<Vector<unsigned>> first_node_name(1);
16243 first_node_name[0] = node_name;
16244 local_node_names.push_back(first_node_name);
16251 unsigned node_number = local_node_number[node_pt];
16254 node_name[4] = node_number;
16258 local_node_names[node_number].push_back(node_name);
16283 unsigned n_total_local_names = 0;
16285 const unsigned n_local_nodes = local_node_names.size();
16288 for (
unsigned i = 0; i < n_local_nodes; i++)
16291 const unsigned n_inode_names = local_node_names[i].size();
16293 n_total_local_names += n_inode_names;
16298 const unsigned n_info_per_node_name = 5;
16300 Vector<unsigned> flat_packed_send_udata(n_total_local_names *
16301 n_info_per_node_name);
16303 unsigned counter = 0;
16305 for (
unsigned i = 0; i < n_local_nodes; i++)
16308 const unsigned n_inode_names = local_node_names[i].size();
16310 for (
unsigned j = 0; j < n_inode_names; j++)
16313 flat_packed_send_udata[counter++] = local_node_names[i][j][0];
16315 flat_packed_send_udata[counter++] = local_node_names[i][j][1];
16317 flat_packed_send_udata[counter++] = local_node_names[i][j][2];
16319 flat_packed_send_udata[counter++] = local_node_names[i][j][3];
16321 flat_packed_send_udata[counter++] = local_node_names[i][j][4];
16331 const unsigned n_udata_send_to_root = flat_packed_send_udata.size();
16344 const unsigned root_processor = 0;
16348 Vector<unsigned> root_n_names_per_processor(nproc);
16352 MPI_Gather(&n_total_local_names,
16355 &root_n_names_per_processor[0],
16359 comm_pt->mpi_comm());
16363 unsigned root_n_total_udata_receive = 0;
16364 Vector<int> root_n_udata_to_receive(nproc, 0);
16365 for (
unsigned iproc = 0; iproc < nproc; iproc++)
16367 root_n_udata_to_receive[iproc] =
16368 root_n_names_per_processor[iproc] * n_info_per_node_name;
16369 root_n_total_udata_receive += root_n_udata_to_receive[iproc];
16374 Vector<int> root_uoffsets_receive(nproc, 0);
16375 root_uoffsets_receive[0] = 0;
16376 for (
unsigned iproc = 1; iproc < nproc; iproc++)
16379 root_uoffsets_receive[iproc] =
16380 root_uoffsets_receive[iproc - 1] + root_n_udata_to_receive[iproc - 1];
16384 if (flat_packed_send_udata.size() == 0)
16386 flat_packed_send_udata.resize(1);
16390 Vector<unsigned> root_flat_packed_receive_udata(root_n_total_udata_receive);
16393 if (my_rank != root_processor)
16396 if (root_flat_packed_receive_udata.size() == 0)
16398 root_flat_packed_receive_udata.resize(1);
16403 MPI_Gatherv(&flat_packed_send_udata[0],
16406 n_udata_send_to_root,
16409 &root_flat_packed_receive_udata[0],
16413 &root_n_udata_to_receive[0],
16416 &root_uoffsets_receive[0],
16422 comm_pt->mpi_comm());
16425 flat_packed_send_udata.clear();
16426 flat_packed_send_udata.resize(0);
16434 Vector<unsigned> flat_packed_root_send_receive_udata;
16440 if (my_rank == root_processor)
16446 Vector<Vector<Vector<unsigned>>> root_global_node_names;
16452 Vector<Vector<unsigned>> root_local_node_names;
16455 unsigned rcounter = 0;
16457 for (
unsigned iproc = 0; iproc < nproc; iproc++)
16460 const unsigned n_local_names_iproc = root_n_names_per_processor[iproc];
16461 for (
unsigned i = 0; i < n_local_names_iproc; i++)
16464 Vector<unsigned> node_name(n_info_per_node_name);
16465 for (
unsigned j = 0; j < n_info_per_node_name; j++)
16467 node_name[j] = root_flat_packed_receive_udata[rcounter++];
16471 root_local_node_names.push_back(node_name);
16478 const unsigned n_root_local_node_names = root_local_node_names.size();
16490 Vector<unsigned> node_name_counter_part(n_root_local_node_names);
16493 std::map<Vector<unsigned>,
bool> done_name;
16497 for (
unsigned i = 0; i < n_root_local_node_names; i++)
16500 Vector<unsigned> node_name = root_local_node_names[i];
16503 if (!done_name[node_name])
16506 done_name[node_name] =
true;
16510 bool found_both_names_node =
false;
16515 for (
unsigned j = i + 1; j < n_root_local_node_names; j++)
16517 Vector<unsigned> node_name_r = root_local_node_names[j];
16520 if (!done_name[node_name_r])
16524 if (node_name[0] == node_name_r[1] &&
16525 node_name[1] == node_name_r[0] &&
16526 node_name[2] == node_name_r[2] &&
16527 node_name[3] == node_name_r[3])
16530 done_name[node_name_r] =
true;
16533 node_name_counter_part[i] = j;
16536 node_name_counter_part[j] = i;
16539 found_both_names_node =
true;
16551 if (!found_both_names_node)
16553 std::ostringstream error_message;
16554 error_message <<
"The counter-part of the current name node was "
16555 <<
"not found,\nthe current node name is:\n"
16556 <<
"iproc:(" << node_name[0] <<
")\n"
16557 <<
"jproc:(" << node_name[1] <<
")\n"
16558 <<
"ishd_bnd:(" << node_name[2] <<
")\n"
16559 <<
"index:(" << node_name[3] <<
")\n";
16560 throw OomphLibError(error_message.str(),
16561 OOMPH_CURRENT_FUNCTION,
16562 OOMPH_EXCEPTION_LOCATION);
16578 for (
unsigned i = 0; i < n_root_local_node_names; i++)
16581 Vector<unsigned> node_name = root_local_node_names[i];
16584 if (!done_name[node_name])
16587 Vector<Vector<unsigned>> all_node_names;
16590 all_node_names.push_back(node_name);
16593 unsigned idx_c = node_name_counter_part[i];
16595 Vector<unsigned> node_name_r = root_local_node_names[idx_c];
16598 all_node_names.push_back(node_name_r);
16604 unsigned n_current_names = all_node_names.size();
16607 unsigned icounter = 0;
16610 while (icounter < n_current_names)
16613 Vector<unsigned> current_node_name = all_node_names[icounter];
16618 if (!done_name[current_node_name])
16621 done_name[current_node_name] =
true;
16626 for (
unsigned j = i + 1; j < n_root_local_node_names; j++)
16629 Vector<unsigned> other_node_name = root_local_node_names[j];
16632 if (!done_name[other_node_name])
16635 if ((current_node_name[0] == other_node_name[0]) &&
16636 (current_node_name[4] == other_node_name[4]))
16641 done_name[other_node_name] =
true;
16644 Vector<Vector<unsigned>>::iterator it =
16645 std::find(all_node_names.begin(),
16646 all_node_names.end(),
16648 if (it == all_node_names.end())
16650 all_node_names.push_back(other_node_name);
16652 unsigned k = node_name_counter_part[j];
16654 Vector<unsigned> other_node_name_r =
16655 root_local_node_names[k];
16659 if (!done_name[other_node_name_r])
16661 all_node_names.push_back(other_node_name_r);
16675 n_current_names = all_node_names.size();
16683 root_global_node_names.push_back(all_node_names);
16696 flat_packed_root_send_receive_udata.clear();
16698 const unsigned n_global_nodes = root_global_node_names.size();
16701 flat_packed_root_send_receive_udata.push_back(n_global_nodes);
16704 for (
unsigned i = 0; i < n_global_nodes; i++)
16707 Vector<Vector<unsigned>> global_inode_names = root_global_node_names[i];
16709 const unsigned n_names_global_inode = global_inode_names.size();
16712 flat_packed_root_send_receive_udata.push_back(n_names_global_inode);
16714 for (
unsigned j = 0; j < n_names_global_inode; j++)
16717 for (
unsigned k = 0; k < n_info_per_node_name; k++)
16721 flat_packed_root_send_receive_udata.push_back(
16722 global_inode_names[j][k]);
16743 unsigned root_n_udata_sent_to_all_proc =
16744 flat_packed_root_send_receive_udata.size();
16746 MPI_Bcast(&root_n_udata_sent_to_all_proc,
16751 comm_pt->mpi_comm());
16754 if (my_rank != root_processor)
16756 flat_packed_root_send_receive_udata.resize(root_n_udata_sent_to_all_proc);
16760 MPI_Bcast(&flat_packed_root_send_receive_udata[0],
16764 root_n_udata_sent_to_all_proc,
16769 comm_pt->mpi_comm());
16774 const unsigned n_global_nodes =
16775 flat_packed_root_send_receive_udata[counter++];
16782 global_node_names.resize(n_global_nodes);
16784 unsigned n_read_global_nodes = 0;
16785 while (n_read_global_nodes < n_global_nodes)
16788 const unsigned n_names_global_inode =
16789 flat_packed_root_send_receive_udata[counter++];
16791 const unsigned i = n_read_global_nodes;
16793 global_node_names[i].resize(n_names_global_inode);
16795 for (
unsigned j = 0; j < n_names_global_inode; j++)
16798 global_node_names[i][j].resize(n_info_per_node_name);
16801 for (
unsigned k = 0; k < n_info_per_node_name; k++)
16805 global_node_names[i][j][k] =
16806 flat_packed_root_send_receive_udata[counter++];
16812 Vector<unsigned> node_name(n_info_per_node_name - 1);
16813 node_name[0] = global_node_names[i][j][0];
16814 node_name[1] = global_node_names[i][j][1];
16815 node_name[2] = global_node_names[i][j][2];
16816 node_name[3] = global_node_names[i][j][3];
16821 node_name_to_global_index[node_name] = i;
16826 n_read_global_nodes++;
16832 if (counter != root_n_udata_sent_to_all_proc)
16834 std::ostringstream error_stream;
16836 <<
"The info. received from root regarding the global names of "
16837 <<
"the nodes\nwas not completely read.\n"
16838 <<
"The number of data sent/received from root is: ("
16839 << root_n_udata_sent_to_all_proc <<
")\n"
16840 <<
"The number of data read from the received info. is: (" << counter
16842 throw OomphLibError(
16843 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
16861 global_shared_node_pt.resize(n_global_nodes, 0);
16864 for (
unsigned i = 0; i < n_global_nodes; i++)
16868 bool is_this_a_local_node_name =
false;
16869 unsigned local_node_number;
16871 const unsigned n_names_global_inode = global_node_names[i].size();
16873 for (
unsigned j = 0; j < n_names_global_inode; j++)
16876 const unsigned iproc = global_node_names[i][j][0];
16877 local_node_number = global_node_names[i][j][4];
16880 if (my_rank == iproc)
16883 is_this_a_local_node_name =
true;
16892 if (is_this_a_local_node_name)
16897 const unsigned n_names_local_node =
16898 local_node_names[local_node_number].size();
16899 unsigned n_names_found_on_global_name_node = 0;
16904 global_shared_node_pt[i] = local_node_pt[local_node_number];
16910 for (
unsigned j = 0; j < n_names_global_inode; j++)
16913 const unsigned iproc = global_node_names[i][j][0];
16916 if (iproc != my_rank)
16919 local_node_names[local_node_number].push_back(
16920 global_node_names[i][j]);
16925 const unsigned jproc = global_node_names[i][j][1];
16926 const unsigned ishd_bnd = global_node_names[i][j][2];
16927 const unsigned idx = global_node_names[i][j][3];
16928 const unsigned n_local_node = global_node_names[i][j][4];
16930 for (
unsigned k = 0; k < n_names_local_node; k++)
16932 if ((local_node_names[local_node_number][k][0] == iproc) &&
16933 (local_node_names[local_node_number][k][1] == jproc) &&
16934 (local_node_names[local_node_number][k][2] == ishd_bnd) &&
16935 (local_node_names[local_node_number][k][3] == idx) &&
16936 (local_node_names[local_node_number][k][4] == n_local_node))
16940 n_names_found_on_global_name_node++;
16954 if (n_names_local_node != n_names_found_on_global_name_node)
16956 std::ostringstream error_stream;
16957 error_stream <<
"The local node names corresponding to the local "
16958 <<
"node (" << local_node_number <<
") were\n"
16959 <<
"not found on the global node names.\n\n"
16960 <<
"These are the names of the local node\n"
16961 <<
"Name k: iproc, jproc, ishd_bnd, idx. #node\n";
16962 for (
unsigned k = 0; k < n_names_local_node; k++)
16964 error_stream <<
"Name(" << k
16965 <<
"): " << local_node_names[local_node_number][k][0]
16966 <<
", " << local_node_names[local_node_number][k][1]
16967 <<
", " << local_node_names[local_node_number][k][2]
16968 <<
", " << local_node_names[local_node_number][k][3]
16969 <<
", " << local_node_names[local_node_number][k][4]
16973 error_stream <<
"\n\nThese are the names of the global node\n"
16974 <<
"Name k: iproc, jproc, ishd_bnd, idx. #node\n";
16975 for (
unsigned k = 0; k < n_names_global_inode; k++)
16977 error_stream <<
"Name(" << k <<
"): " << global_node_names[i][k][0]
16978 <<
", " << global_node_names[i][k][1] <<
", "
16979 << global_node_names[i][k][2] <<
", "
16980 << global_node_names[i][k][3] <<
", "
16981 << global_node_names[i][k][4] <<
"\n";
16984 throw OomphLibError(error_stream.str(),
16985 OOMPH_CURRENT_FUNCTION,
16986 OOMPH_EXCEPTION_LOCATION);
17012 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
17015 for (
unsigned i = 0; i < n_local_nodes; i++)
17018 const unsigned n_names = local_node_names[i].size();
17022 Node* node_pt = local_node_pt[i];
17025 for (
unsigned j = 0; j < n_names; j++)
17028 const unsigned iproc = local_node_names[i][j][0];
17029 const unsigned jproc = local_node_names[i][j][1];
17030 const unsigned ishd_bnd =
17031 local_node_names[i][j][2] - initial_shd_bnd_id;
17032 const unsigned index = local_node_names[i][j][3];
17039 other_proc_shd_bnd_node_pt[iproc][jproc][ishd_bnd][index] = node_pt;
17043 other_proc_shd_bnd_node_pt[jproc][iproc][ishd_bnd][index] = node_pt;
17061 template<
class ELEMENT>
17063 Vector<Vector<Vector<unsigned>>>& global_node_names,
17064 std::map<Vector<unsigned>,
unsigned>& node_name_to_global_index,
17065 Vector<Node*>& global_shared_node_pt)
17068 const unsigned nproc = this->communicator_pt()->nproc();
17069 const unsigned my_rank = this->communicator_pt()->my_rank();
17072 const unsigned n_nodes_on_shd_bnds = global_node_names.size();
17079 Vector<std::set<Node*>> node_on_shd_bnd_pt(nproc);
17083 std::map<Node*, unsigned> node_pt_to_global_shd_bnd_index;
17087 for (
unsigned i = 0; i < n_nodes_on_shd_bnds; i++)
17091 const unsigned n_names = global_node_names[i].size();
17093 for (
unsigned j = 0; j < n_names; j++)
17096 Vector<unsigned> node_name(4);
17097 node_name[0] = global_node_names[i][j][0];
17098 node_name[1] = global_node_names[i][j][1];
17099 node_name[2] = global_node_names[i][j][2];
17100 node_name[3] = global_node_names[i][j][3];
17103 if (node_name[0] == my_rank)
17106 const unsigned jproc = node_name[1];
17109 std::map<Vector<unsigned>,
unsigned>::iterator it =
17110 node_name_to_global_index.find(node_name);
17111 if (it != node_name_to_global_index.end())
17115 if (i != (*it).second)
17117 std::ostringstream error_message;
17119 <<
"The global node number " << (*it).second
17120 <<
") obtained from the current node\n"
17121 <<
"name is not the same as the current node number (" << i
17124 <<
"iproc:" << node_name[0] <<
"\n"
17125 <<
"jproc:" << node_name[1] <<
"\n"
17126 <<
"shd_bnd_id:" << node_name[2] <<
"\n"
17127 <<
"index:" << node_name[3] <<
"\n\n";
17128 throw OomphLibError(error_message.str(),
17129 OOMPH_CURRENT_FUNCTION,
17130 OOMPH_EXCEPTION_LOCATION);
17135 std::ostringstream error_message;
17137 <<
"The node name is not registerd as living in this processor.\n"
17139 <<
"iproc:" << node_name[0] <<
"\n"
17140 <<
"jproc:" << node_name[1] <<
"\n"
17141 <<
"shd_bnd_id:" << node_name[2] <<
"\n"
17142 <<
"index:" << node_name[3] <<
"\n\n";
17143 throw OomphLibError(error_message.str(),
17144 OOMPH_CURRENT_FUNCTION,
17145 OOMPH_EXCEPTION_LOCATION);
17151 Node* node_pt = global_shared_node_pt[i];
17156 std::ostringstream error_message;
17157 error_message <<
"There is not global shared node within this\n"
17158 <<
"global node number (" << i
17159 <<
"). The global shared\n"
17160 <<
"node pointer is null\n\n";
17161 throw OomphLibError(error_message.str(),
17162 OOMPH_CURRENT_FUNCTION,
17163 OOMPH_EXCEPTION_LOCATION);
17169 node_on_shd_bnd_pt[jproc].insert(node_pt);
17172 node_pt_to_global_shd_bnd_index[node_pt] = i;
17175 else if (node_name[1] == my_rank)
17178 const unsigned jproc = node_name[0];
17181 std::map<Vector<unsigned>,
unsigned>::iterator it =
17182 node_name_to_global_index.find(node_name);
17183 if (it != node_name_to_global_index.end())
17187 if (i != (*it).second)
17189 std::ostringstream error_message;
17191 <<
"The global node number " << (*it).second
17192 <<
") obtained from the current node\n"
17193 <<
"name is not the same as the current node number (" << i
17196 <<
"iproc:" << node_name[0] <<
"\n"
17197 <<
"jproc:" << node_name[1] <<
"\n"
17198 <<
"shd_bnd_id:" << node_name[2] <<
"\n"
17199 <<
"index:" << node_name[3] <<
"\n\n";
17200 throw OomphLibError(error_message.str(),
17201 OOMPH_CURRENT_FUNCTION,
17202 OOMPH_EXCEPTION_LOCATION);
17207 std::ostringstream error_message;
17209 <<
"The node name is not registerd as living in this processor.\n"
17211 <<
"iproc:" << node_name[0] <<
"\n"
17212 <<
"jproc:" << node_name[1] <<
"\n"
17213 <<
"shd_bnd_id:" << node_name[2] <<
"\n"
17214 <<
"index:" << node_name[3] <<
"\n\n";
17215 throw OomphLibError(error_message.str(),
17216 OOMPH_CURRENT_FUNCTION,
17217 OOMPH_EXCEPTION_LOCATION);
17223 Node* node_pt = global_shared_node_pt[i];
17228 std::ostringstream error_message;
17229 error_message <<
"There is not global shared node within this\n"
17230 <<
"global node number (" << i
17231 <<
"). The global shared\n"
17232 <<
"node pointer is null\n\n";
17233 throw OomphLibError(error_message.str(),
17234 OOMPH_CURRENT_FUNCTION,
17235 OOMPH_EXCEPTION_LOCATION);
17241 node_on_shd_bnd_pt[jproc].insert(node_pt);
17244 node_pt_to_global_shd_bnd_index[node_pt] = i;
17261 Vector<Vector<unsigned>> global_node_on_shared_bound(nproc);
17264 Vector<Vector<Vector<unsigned>>> global_node_original_boundaries(nproc);
17267 Vector<Vector<Vector<double>>> global_node_zeta_coordinate(nproc);
17270 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17273 std::set<Node*> nodes_shared_pt = node_on_shd_bnd_pt[iproc];
17276 for (std::set<Node*>::iterator it = nodes_shared_pt.begin();
17277 it != nodes_shared_pt.end();
17281 Node* node_pt = (*it);
17283 Vector<unsigned> on_original_boundaries;
17286 Vector<double> zeta_coordinate;
17288 const unsigned n_bnd = this->initial_shared_boundary_id();
17291 for (
unsigned bb = 0; bb < n_bnd; bb++)
17294 if (node_pt->is_on_boundary(bb))
17297 on_original_boundaries.push_back(bb);
17299 Vector<double> zeta(1);
17300 node_pt->get_coordinates_on_boundary(bb, zeta);
17302 zeta_coordinate.push_back(zeta[0]);
17308 if (on_original_boundaries.size() > 0)
17311 std::map<Node*, unsigned>::iterator it_index =
17312 node_pt_to_global_shd_bnd_index.find(node_pt);
17314 if (it_index == node_pt_to_global_shd_bnd_index.end())
17316 std::ostringstream error_message;
17318 <<
"We could not find the global shared node index associated\n"
17319 <<
"with the node pointer with vertices coordinates:\n"
17320 <<
"(" << node_pt->x(0) <<
", " << node_pt->x(1) <<
")\n\n";
17321 throw OomphLibError(error_message.str(),
17322 OOMPH_CURRENT_FUNCTION,
17323 OOMPH_EXCEPTION_LOCATION);
17327 const unsigned global_shared_node_number = (*it_index).second;
17329 global_node_on_shared_bound[iproc].push_back(
17330 global_shared_node_number);
17332 global_node_original_boundaries[iproc].push_back(
17333 on_original_boundaries);
17335 global_node_zeta_coordinate[iproc].push_back(zeta_coordinate);
17355 OomphCommunicator* comm_pt = this->communicator_pt();
17359 MPI_Request request;
17362 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17365 const unsigned n_shd_nodes_my_rank_iproc =
17366 node_on_shd_bnd_pt[iproc].size();
17370 if (n_shd_nodes_my_rank_iproc > 0 && iproc != my_rank)
17373 Vector<unsigned> flat_package_unsigned_send;
17376 flat_package_unsigned_send.push_back(n_shd_nodes_my_rank_iproc);
17379 const unsigned n_global_shared_node_on_original_boundary =
17380 global_node_on_shared_bound[iproc].size();
17384 flat_package_unsigned_send.push_back(
17385 n_global_shared_node_on_original_boundary);
17389 Vector<double> flat_package_double_send;
17392 for (
unsigned i = 0; i < n_global_shared_node_on_original_boundary; i++)
17395 const unsigned global_shared_node_index =
17396 global_node_on_shared_bound[iproc][i];
17400 flat_package_unsigned_send.push_back(global_shared_node_index);
17403 Vector<unsigned> on_original_boundaries =
17404 global_node_original_boundaries[iproc][i];
17407 Vector<double> zeta_coordinate =
17408 global_node_zeta_coordinate[iproc][i];
17412 const unsigned n_original_boundaries = on_original_boundaries.size();
17416 flat_package_unsigned_send.push_back(n_original_boundaries);
17420 for (
unsigned j = 0; j < n_original_boundaries; j++)
17424 flat_package_unsigned_send.push_back(on_original_boundaries[j]);
17426 flat_package_double_send.push_back(zeta_coordinate[j]);
17434 const unsigned n_udata_send = flat_package_unsigned_send.size();
17435 int n_udata_send_int = n_udata_send;
17438 MPI_Isend(&n_udata_send_int,
17443 comm_pt->mpi_comm(),
17446 int n_udata_received_int = 0;
17447 MPI_Recv(&n_udata_received_int,
17452 comm_pt->mpi_comm(),
17454 MPI_Wait(&request, MPI_STATUS_IGNORE);
17456 if (n_udata_send != 0)
17458 MPI_Isend(&flat_package_unsigned_send[0],
17463 comm_pt->mpi_comm(),
17467 const unsigned n_udata_received =
17468 static_cast<unsigned>(n_udata_received_int);
17471 Vector<unsigned> flat_package_unsigned_receive(n_udata_received);
17473 if (n_udata_received != 0)
17475 MPI_Recv(&flat_package_unsigned_receive[0],
17480 comm_pt->mpi_comm(),
17484 if (n_udata_send != 0)
17486 MPI_Wait(&request, MPI_STATUS_IGNORE);
17492 const unsigned n_ddata_send = flat_package_double_send.size();
17493 int n_ddata_send_int = n_ddata_send;
17496 MPI_Isend(&n_ddata_send_int,
17501 comm_pt->mpi_comm(),
17504 int n_ddata_received_int = 0;
17505 MPI_Recv(&n_ddata_received_int,
17510 comm_pt->mpi_comm(),
17512 MPI_Wait(&request, MPI_STATUS_IGNORE);
17514 if (n_ddata_send != 0)
17516 MPI_Isend(&flat_package_double_send[0],
17521 comm_pt->mpi_comm(),
17525 const unsigned n_ddata_received =
17526 static_cast<unsigned>(n_ddata_received_int);
17529 Vector<double> flat_package_double_receive(n_ddata_received);
17531 if (n_ddata_received != 0)
17533 MPI_Recv(&flat_package_double_receive[0],
17538 comm_pt->mpi_comm(),
17542 if (n_ddata_send != 0)
17544 MPI_Wait(&request, MPI_STATUS_IGNORE);
17552 unsigned n_shared_nodes_received = flat_package_unsigned_receive[0];
17556 n_shared_nodes_received++;
17557 n_shared_nodes_received--;
17560 if (n_shd_nodes_my_rank_iproc != n_shared_nodes_received)
17562 std::ostringstream error_message;
17564 <<
"The number of shared nodes between the pair of processors is\n"
17565 <<
"not the same\n"
17566 <<
"N.shared nodes proc (" << my_rank <<
") with proc (" << iproc
17567 <<
"): (" << n_shd_nodes_my_rank_iproc <<
"\n"
17568 <<
"N.shared nodes proc (" << iproc <<
") with proc (" << my_rank
17569 <<
"): (" << n_shared_nodes_received <<
"\n\n"
17570 <<
"You should have got the same error in proc: (" << iproc
17572 throw OomphLibError(error_message.str(),
17573 OOMPH_CURRENT_FUNCTION,
17574 OOMPH_EXCEPTION_LOCATION);
17587 unsigned current_index_data = 2;
17588 unsigned current_index_ddata = 0;
17589 while (current_index_data < n_udata_received)
17592 const unsigned global_shared_node_index =
17593 flat_package_unsigned_receive[current_index_data++];
17600 const unsigned n_original_boundaries =
17601 flat_package_unsigned_receive[current_index_data++];
17604 node_pt = global_shared_node_pt[global_shared_node_index];
17608 std::ostringstream error_message;
17610 <<
"The global shared node (" << global_shared_node_index <<
") "
17611 <<
"could not be found in this processor!!!\n"
17612 <<
"However, it was found in processor (" << iproc <<
"). The "
17613 <<
"data may be no synchronised,\ntherefore "
17614 <<
"we may be looking for a global shared node number that "
17615 <<
"do not\ncorrespond with the one that was sent by "
17616 <<
"processor (" << iproc <<
")\n\n";
17617 throw OomphLibError(error_message.str(),
17618 OOMPH_CURRENT_FUNCTION,
17619 OOMPH_EXCEPTION_LOCATION);
17625 for (
unsigned i = 0; i < n_original_boundaries; i++)
17629 const unsigned original_bound_id =
17630 flat_package_unsigned_receive[current_index_data++];
17633 this->add_boundary_node(original_bound_id, node_pt);
17636 Vector<double> zeta(1);
17637 zeta[0] = flat_package_double_receive[current_index_ddata++];
17638 node_pt->set_coordinates_on_boundary(original_bound_id, zeta);
17660 template<
class ELEMENT>
17662 Vector<Vector<Vector<std::map<unsigned, Node*>>>>&
17663 other_proc_shd_bnd_node_pt,
17664 Vector<Vector<Node*>>& iproc_currently_created_nodes_pt,
17665 Vector<Vector<Vector<unsigned>>>& global_node_names,
17666 std::map<Vector<unsigned>,
unsigned>& node_name_to_global_index,
17667 Vector<Node*>& global_shared_node_pt)
17670 const unsigned nproc = this->communicator_pt()->nproc();
17671 const unsigned my_rank = this->communicator_pt()->my_rank();
17679 std::map<Node*, bool> is_global_shared_node;
17680 std::map<Node*, unsigned> global_shared_node_index;
17683 const unsigned n_global_shared_nodes = global_shared_node_pt.size();
17685 for (
unsigned i = 0; i < n_global_shared_nodes; i++)
17688 Node* node_pt = global_shared_node_pt[i];
17690 is_global_shared_node[node_pt] =
true;
17692 global_shared_node_index[node_pt] = i;
17712 Vector<std::set<GeneralisedElement*>> additional_elements_pt(nproc);
17715 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17717 if (iproc != my_rank)
17720 Vector<GeneralisedElement*> haloed_ele_pt =
17721 this->root_haloed_element_pt(iproc);
17724 const unsigned n_haloed_ele = this->nroot_haloed_element(iproc);
17727 for (
unsigned ihd = 0; ihd < n_haloed_ele; ihd++)
17730 GeneralisedElement* gele_pt = haloed_ele_pt[ihd];
17732 FiniteElement* ele_pt =
dynamic_cast<FiniteElement*
>(gele_pt);
17734 const unsigned n_nodes = ele_pt->nnode();
17736 for (
unsigned n = 0; n < n_nodes; n++)
17739 Node* node_pt = ele_pt->node_pt(n);
17741 if (is_global_shared_node[node_pt])
17744 const unsigned global_index = global_shared_node_index[node_pt];
17746 Vector<Vector<unsigned>> iglobal_names =
17747 global_node_names[global_index];
17750 const unsigned n_names = iglobal_names.size();
17754 for (
unsigned j = 0; j < n_names; j++)
17758 const unsigned proc1 = iglobal_names[j][0];
17759 const unsigned proc2 = iglobal_names[j][1];
17762 additional_elements_pt[proc1].insert(gele_pt);
17763 additional_elements_pt[proc2].insert(gele_pt);
17783 Vector<Vector<FiniteElement*>> send_haloed_ele_pt(nproc);
17786 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17788 if (iproc != my_rank)
17792 std::set<GeneralisedElement*> iproc_ele_pt =
17793 additional_elements_pt[iproc];
17796 for (std::set<GeneralisedElement*>::iterator it = iproc_ele_pt.begin();
17797 it != iproc_ele_pt.end();
17801 GeneralisedElement* gele_pt = (*it);
17804 Vector<GeneralisedElement*> haloed_ele_pt =
17805 this->root_haloed_element_pt(iproc);
17808 const unsigned n_haloed_ele = this->nroot_haloed_element(iproc);
17812 bool send_ele_to_iproc_processor =
true;
17817 for (
unsigned ihd = 0; ihd < n_haloed_ele; ihd++)
17820 GeneralisedElement* ghd_ele_pt = haloed_ele_pt[ihd];
17821 if (gele_pt == ghd_ele_pt)
17824 send_ele_to_iproc_processor =
false;
17833 if (send_ele_to_iproc_processor)
17836 FiniteElement* ele_pt =
dynamic_cast<FiniteElement*
>(gele_pt);
17839 send_haloed_ele_pt[iproc].push_back(ele_pt);
17861 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17864 if (iproc != my_rank)
17867 const unsigned n_additional_haloed_ele =
17868 send_haloed_ele_pt[iproc].size();
17871 Flat_packed_unsigneds.clear();
17872 Flat_packed_doubles.clear();
17873 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17874 Flat_packed_unsigneds_string.clear();
17880 Flat_packed_unsigneds.push_back(n_additional_haloed_ele);
17881 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17882 std::stringstream junk;
17883 junk <<
"Number of haloed elements " << nhaloed_ele;
17884 Flat_packed_unsigneds_string.push_back(junk.str());
17888 for (
unsigned e = 0; e < n_additional_haloed_ele; e++)
17891 FiniteElement* ele_pt = send_haloed_ele_pt[iproc][e];
17892 const unsigned nroot_haloed_ele = this->nroot_haloed_element(iproc);
17898 GeneralisedElement* gen_ele_pt = ele_pt;
17900 const unsigned haloed_ele_index =
17901 this->try_to_add_root_haloed_element_pt(iproc, gen_ele_pt);
17905 if (nroot_haloed_ele == haloed_ele_index)
17907 Flat_packed_unsigneds.push_back(1);
17908 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17909 Flat_packed_unsigneds_string.push_back(
17910 "Haloed element needs to be constructed");
17914 get_required_elemental_information_helper(iproc, ele_pt);
17917 const unsigned nnodes = ele_pt->nnode();
17918 for (
unsigned j = 0; j < nnodes; j++)
17920 Node* node_pt = ele_pt->node_pt(j);
17924 add_haloed_node_helper(iproc, node_pt);
17931 Flat_packed_unsigneds.push_back(0);
17932 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17933 Flat_packed_unsigneds_string.push_back(
17934 "Haloed element already exists");
17936 Flat_packed_unsigneds.push_back(haloed_ele_index);
17937 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17938 Flat_packed_unsigneds_string.push_back(
17939 "Index of existing haloed element");
17949 int send_proc =
static_cast<int>(iproc);
17951 int recv_proc =
static_cast<int>(iproc);
17952 send_and_receive_elements_nodes_info(send_proc, recv_proc);
17955 Counter_for_flat_packed_doubles = 0;
17956 Counter_for_flat_packed_unsigneds = 0;
17959 const unsigned n_additional_halo_ele =
17960 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
17962 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17963 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
17964 <<
" Number of elements need to be constructed "
17965 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
17970 for (
unsigned e = 0; e < n_additional_halo_ele; e++)
17974 create_halo_element(iproc,
17975 iproc_currently_created_nodes_pt[iproc],
17976 other_proc_shd_bnd_node_pt,
17978 node_name_to_global_index,
17979 global_shared_node_pt);
17997 template<
class ELEMENT>
17999 ELEMENT>::get_required_elemental_information_helper(
unsigned& iproc,
18000 FiniteElement* ele_pt)
18003 const unsigned nbound = this->initial_shared_boundary_id();
18008 Vector<unsigned> associated_boundaries;
18009 Vector<unsigned> face_index_on_boundary;
18011 unsigned counter_face_indexes = 0;
18013 for (
unsigned b = 0; b < nbound; b++)
18016 const unsigned nboundary_ele = nboundary_element(b);
18017 for (
unsigned e = 0; e < nboundary_ele; e++)
18019 if (ele_pt == this->boundary_element_pt(b, e))
18022 associated_boundaries.push_back(b);
18024 face_index_on_boundary.push_back(face_index_at_boundary(b, e));
18025 counter_face_indexes++;
18027 if (counter_face_indexes > 2)
18029 std::stringstream error_message;
18031 <<
"A triangular element can not have more than two of its faces "
18032 <<
"on a boundary!!!\n\n";
18033 throw OomphLibError(error_message.str(),
18034 OOMPH_CURRENT_FUNCTION,
18035 OOMPH_EXCEPTION_LOCATION);
18039 if (counter_face_indexes == 2)
18053 const unsigned nassociated_boundaries = associated_boundaries.size();
18054 if (nassociated_boundaries > 0)
18056 Flat_packed_unsigneds.push_back(1);
18057 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18058 Flat_packed_unsigneds_string.push_back(
18059 "The element is a boundary element");
18061 Flat_packed_unsigneds.push_back(nassociated_boundaries);
18062 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18063 std::stringstream junk;
18064 junk <<
"The elements is associated to " << nassociated_boundaries
18066 Flat_packed_unsigneds_string.push_back(junk.str());
18073 for (
unsigned i = 0; i < nassociated_boundaries; i++)
18075 unsigned b = associated_boundaries[i];
18076 Flat_packed_unsigneds.push_back(b);
18077 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18078 std::stringstream junk;
18079 junk <<
"Element associated to boundary " << b <<
" of "
18080 << nassociated_boundaries <<
" total associated boundaries";
18081 Flat_packed_unsigneds_string.push_back(junk.str());
18083 unsigned f = face_index_on_boundary[i];
18084 Flat_packed_unsigneds.push_back(f);
18085 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18086 std::stringstream junk2;
18087 junk2 <<
"Face index " << f <<
" for associated boundary " << b;
18088 Flat_packed_unsigneds_string.push_back(junk2.str());
18098 Vector<Vector<unsigned>> associated_boundaries_and_regions;
18099 Vector<unsigned> face_index_on_boundary_and_region;
18102 const unsigned n_regions = this->nregion();
18107 unsigned counter_face_indexes_in_regions = 0;
18109 for (
unsigned b = 0; b < nbound; b++)
18112 for (
unsigned i_reg = 0; i_reg < n_regions; i_reg++)
18115 const unsigned region_id =
18116 static_cast<unsigned>(this->Region_attribute[i_reg]);
18121 const unsigned nele_in_region =
18122 this->nboundary_element_in_region(b, region_id);
18123 for (
unsigned ee = 0; ee < nele_in_region; ee++)
18128 this->boundary_element_in_region_pt(b, region_id, ee))
18132 Vector<unsigned> bound_and_region(2);
18135 bound_and_region[0] = b;
18137 bound_and_region[1] = region_id;
18140 associated_boundaries_and_regions.push_back(bound_and_region);
18142 face_index_on_boundary_and_region.push_back(
18143 this->face_index_at_boundary_in_region(b, region_id, ee));
18147 counter_face_indexes_in_regions++;
18150 if (counter_face_indexes_in_regions > 2)
18152 std::stringstream error_message;
18153 error_message <<
"A triangular element can not have more "
18154 "than two of its\n"
18155 <<
"faces on a boundary!!!\n\n";
18156 throw OomphLibError(error_message.str(),
18157 OOMPH_CURRENT_FUNCTION,
18158 OOMPH_EXCEPTION_LOCATION);
18173 const unsigned nassociated_boundaries_and_regions =
18174 associated_boundaries_and_regions.size();
18175 if (nassociated_boundaries_and_regions > 0)
18177 Flat_packed_unsigneds.push_back(1);
18178 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18179 Flat_packed_unsigneds_string.push_back(
18180 "The element is associated to boundaries and regions");
18183 Flat_packed_unsigneds.push_back(nassociated_boundaries_and_regions);
18184 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18185 std::stringstream junk;
18186 junk <<
"The element is associated to "
18187 << nassociated_boundaries_and_regions <<
" boundaries-regions";
18188 Flat_packed_unsigneds_string.push_back(junk.str());
18195 for (
unsigned i = 0; i < nassociated_boundaries_and_regions; i++)
18197 const unsigned b = associated_boundaries_and_regions[i][0];
18198 Flat_packed_unsigneds.push_back(b);
18199 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18200 std::stringstream junk;
18201 junk <<
"Element associated to boundary " << b <<
" of "
18202 << nassociated_boundaries_and_regions
18203 <<
" total associated boundaries-regions";
18204 Flat_packed_unsigneds_string.push_back(junk.str());
18207 const unsigned r = associated_boundaries_and_regions[i][1];
18208 Flat_packed_unsigneds.push_back(r);
18209 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18210 std::stringstream junk2;
18211 junk2 <<
"Element associated to region " << r <<
" of "
18212 << nassociated_boundaries_and_regions
18213 <<
" total associated boundaries-regions";
18214 Flat_packed_unsigneds_string.push_back(junk2.str());
18217 const unsigned f = face_index_on_boundary_and_region[i];
18218 Flat_packed_unsigneds.push_back(f);
18219 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18220 std::stringstream junk3;
18221 junk3 <<
"Face index " << f <<
" for associated boundary-region ("
18222 << b <<
"-" << r <<
")";
18223 Flat_packed_unsigneds_string.push_back(junk3.str());
18229 Flat_packed_unsigneds.push_back(0);
18230 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18231 Flat_packed_unsigneds_string.push_back(
18232 "The element is NOT associated to boundaries and regions");
18238 Flat_packed_unsigneds.push_back(0);
18239 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18240 Flat_packed_unsigneds_string.push_back(
18241 "The element is not associated to any original boundary");
18250 Vector<unsigned> associated_shared_boundaries;
18251 Vector<unsigned> face_index_on_shared_boundary;
18254 Vector<unsigned> my_rank_shared_boundaries_ids;
18255 this->shared_boundaries_in_this_processor(my_rank_shared_boundaries_ids);
18258 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
18260 for (
unsigned i = 0; i < nmy_rank_shd_bnd; i++)
18263 const unsigned sb = my_rank_shared_boundaries_ids[i];
18266 const unsigned nboundary_ele = this->nshared_boundary_element(sb);
18267 for (
unsigned e = 0; e < nboundary_ele; e++)
18269 if (ele_pt == this->shared_boundary_element_pt(sb, e))
18272 associated_shared_boundaries.push_back(sb);
18274 face_index_on_shared_boundary.push_back(
18275 this->face_index_at_shared_boundary(sb, e));
18282 const unsigned nassociated_shared_boundaries =
18283 associated_shared_boundaries.size();
18284 if (nassociated_shared_boundaries > 0)
18286 Flat_packed_unsigneds.push_back(3);
18287 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18288 Flat_packed_unsigneds_string.push_back(
18289 "The element is a shared boundary element");
18291 Flat_packed_unsigneds.push_back(nassociated_shared_boundaries);
18292 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18293 std::stringstream junk;
18294 junk <<
"The elements is associated to " << nassociated_shared_boundaries
18295 <<
"shared boundaries";
18296 Flat_packed_unsigneds_string.push_back(junk.str());
18300 for (
unsigned i = 0; i < nassociated_shared_boundaries; i++)
18302 const unsigned b = associated_shared_boundaries[i];
18303 Flat_packed_unsigneds.push_back(b);
18304 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18305 std::stringstream junk;
18306 junk <<
"Element associated to shared boundary " << b <<
" of "
18307 << nassociated_shared_boundaries <<
" total associated boundaries";
18308 Flat_packed_unsigneds_string.push_back(junk.str());
18311 const unsigned f = face_index_on_shared_boundary[i];
18312 Flat_packed_unsigneds.push_back(f);
18313 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18314 std::stringstream junk2;
18315 junk2 <<
"Face index " << f <<
" for associated shared boundary " << b;
18316 Flat_packed_unsigneds_string.push_back(junk2.str());
18322 Flat_packed_unsigneds.push_back(0);
18323 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18324 Flat_packed_unsigneds_string.push_back(
18325 "The element is not associated to any shared boundary");
18335 template<
class ELEMENT>
18337 unsigned& iproc, Node* nod_pt)
18339 unsigned my_rank = this->communicator_pt()->my_rank();
18340 const unsigned nproc = this->communicator_pt()->nproc();
18345 unsigned n_val = nod_pt->nvalue();
18346 Flat_packed_unsigneds.push_back(n_val);
18347 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18348 Flat_packed_unsigneds_string.push_back(
"Number of values");
18351 unsigned n_dim = nod_pt->ndim();
18354 unsigned n_prev = 1;
18355 if (this->Time_stepper_pt != 0)
18358 n_prev = this->Time_stepper_pt->ntstorage();
18364 Vector<unsigned> original_boundaries;
18367 const unsigned n_bnd = this->initial_shared_boundary_id();
18368 for (
unsigned bb = 0; bb < n_bnd; bb++)
18371 if (nod_pt->is_on_boundary(bb))
18373 original_boundaries.push_back(bb);
18377 const unsigned n_original_boundaries = original_boundaries.size();
18379 if (n_original_boundaries > 0)
18382 Flat_packed_unsigneds.push_back(2);
18383 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18384 Flat_packed_unsigneds_string.push_back(
18385 "Node is on the original boundaries");
18388 Flat_packed_unsigneds.push_back(n_original_boundaries);
18389 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18390 std::stringstream junk;
18391 junk <<
"Node is on " << n_original_boundaries <<
" original boundaries";
18392 Flat_packed_unsigneds_string.push_back(junk.str());
18396 for (
unsigned i = 0; i < n_original_boundaries; i++)
18398 Flat_packed_unsigneds.push_back(original_boundaries[i]);
18399 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18400 std::stringstream junk;
18401 junk <<
"Node is on boundary " << original_boundaries[i] <<
" of "
18403 Flat_packed_unsigneds_string.push_back(junk.str());
18406 Vector<double> zeta(1);
18407 nod_pt->get_coordinates_on_boundary(original_boundaries[i], zeta);
18408 Flat_packed_doubles.push_back(zeta[0]);
18414 Flat_packed_unsigneds.push_back(0);
18415 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18416 Flat_packed_unsigneds_string.push_back(
18417 "Node is on any original boundary");
18423 bool node_on_shared_boundary =
false;
18426 const unsigned n_shd_bnd = this->nshared_boundaries(my_rank, iproc);
18427 for (
unsigned bb = 0; bb < n_shd_bnd; bb++)
18430 unsigned i_bnd = this->shared_boundaries_ids(my_rank, iproc, bb);
18432 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
18434 node_on_shared_boundary =
true;
18442 if (node_on_shared_boundary)
18444 Flat_packed_unsigneds.push_back(1);
18445 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18446 Flat_packed_unsigneds_string.push_back(
"Node is on shared boundary");
18450 Vector<unsigned> shd_boundaries;
18452 for (
unsigned bb = 0; bb < n_shd_bnd; bb++)
18455 const unsigned i_bnd = this->shared_boundaries_ids(my_rank, iproc, bb);
18457 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
18459 shd_boundaries.push_back(i_bnd);
18464 const unsigned n_shd_bnd_is_on = shd_boundaries.size();
18466 Flat_packed_unsigneds.push_back(n_shd_bnd_is_on);
18467 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18468 std::stringstream junk;
18469 junk <<
"Node is on " << n_shd_bnd_is_on <<
" shared boundaries";
18470 Flat_packed_unsigneds_string.push_back(junk.str());
18474 for (
unsigned i = 0; i < n_shd_bnd_is_on; i++)
18476 Flat_packed_unsigneds.push_back(shd_boundaries[i]);
18477 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18478 std::stringstream junk;
18479 junk <<
"Node is on boundary " << shd_boundaries[i] <<
" of " << nb;
18480 Flat_packed_unsigneds_string.push_back(junk.str());
18486 unsigned shared_boundary_id = shd_boundaries[0];
18488 const unsigned n_nodes_on_shared_boundary =
18489 nsorted_shared_boundary_node(shared_boundary_id);
18491 unsigned index_node_on_shared_boundary;
18494 bool found_index_node_on_shared_boundary =
false;
18497 for (
unsigned i = 0; i < n_nodes_on_shared_boundary; i++)
18500 Node* shared_node_pt =
18501 sorted_shared_boundary_node_pt(shared_boundary_id, i);
18503 if (shared_node_pt == nod_pt)
18506 index_node_on_shared_boundary = i;
18509 found_index_node_on_shared_boundary =
true;
18517 if (!found_index_node_on_shared_boundary)
18519 std::ostringstream error_message;
18520 error_message <<
"The index of the node on boundary ("
18521 << shared_boundary_id <<
") was not found.\n"
18522 <<
"The node coordinates are (" << nod_pt->x(0) <<
","
18523 << nod_pt->x(1) <<
").\n";
18524 throw OomphLibError(
18525 error_message.str(),
18526 "RefineableTriangleMesh::get_required_nodal_information_helper()",
18527 OOMPH_EXCEPTION_LOCATION);
18531 Flat_packed_unsigneds.push_back(index_node_on_shared_boundary);
18532 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18533 std::stringstream junk2;
18534 junk2 <<
"Node index on boundary " << boundaries[0] <<
" is "
18535 << index_node_on_shared_boundary;
18536 Flat_packed_unsigneds_string.push_back(junk2.str());
18543 Flat_packed_unsigneds.push_back(0);
18544 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18545 Flat_packed_unsigneds_string.push_back(
18546 "Node is not on a shared boundary");
18561 bool node_on_shared_boundary_with_other_processors =
false;
18563 unsigned nshared_boundaries_with_other_processors_have_node = 0;
18567 for (
unsigned jproc = 0; jproc < nproc; jproc++)
18571 if (jproc != iproc)
18574 const unsigned n_jshd_bnd = this->nshared_boundaries(my_rank, jproc);
18576 for (
unsigned bb = 0; bb < n_jshd_bnd; bb++)
18579 const unsigned j_shd_bnd =
18580 this->shared_boundaries_ids(my_rank, jproc, bb);
18582 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
18590 node_on_shared_boundary_with_other_processors =
true;
18593 nshared_boundaries_with_other_processors_have_node++;
18604 if (node_on_shared_boundary_with_other_processors)
18606 Flat_packed_unsigneds.push_back(4);
18607 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18608 Flat_packed_unsigneds_string.push_back(
18609 "Node is on shared boundary no related with the received processor: 4");
18615 Flat_packed_unsigneds.push_back(
18616 nshared_boundaries_with_other_processors_have_node);
18617 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18618 std::stringstream junk;
18619 junk <<
"Number of other shared boundaries that the node is on: "
18620 << nshared_boundaries_with_other_processors_have_node;
18621 Flat_packed_unsigneds_string.push_back(junk.str());
18625 unsigned counter_shd_bnd_with_other_procs_have_node = 0;
18630 Vector<unsigned> other_processor_1;
18631 Vector<unsigned> other_processor_2;
18632 Vector<unsigned> shd_bnd_ids;
18633 Vector<unsigned> indexes;
18635 for (
unsigned jproc = 0; jproc < nproc; jproc++)
18639 if (jproc != iproc)
18643 const unsigned n_jshd_bnd = this->nshared_boundaries(my_rank, jproc);
18644 for (
unsigned bb = 0; bb < n_jshd_bnd; bb++)
18647 const unsigned j_shd_bnd =
18648 this->shared_boundaries_ids(my_rank, jproc, bb);
18650 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
18653 other_processor_1.push_back(my_rank);
18655 other_processor_2.push_back(jproc);
18657 shd_bnd_ids.push_back(j_shd_bnd);
18660 counter_shd_bnd_with_other_procs_have_node++;
18671 const unsigned n_other_processors = other_processor_1.size();
18673 for (
unsigned i = 0; i < n_other_processors; i++)
18676 unsigned shd_bnd_id = shd_bnd_ids[i];
18678 const unsigned n_nodes_on_shd_bnd =
18679 nsorted_shared_boundary_node(shd_bnd_id);
18682 bool found_index_node_on_shared_boundary =
false;
18684 for (
unsigned i = 0; i < n_nodes_on_shd_bnd; i++)
18687 Node* shared_node_pt = sorted_shared_boundary_node_pt(shd_bnd_id, i);
18689 if (shared_node_pt == nod_pt)
18695 indexes.push_back(i);
18698 found_index_node_on_shared_boundary =
true;
18706 if (!found_index_node_on_shared_boundary)
18708 std::ostringstream error_message;
18709 error_message <<
"The index of the node on boundary (" << shd_bnd_id
18710 <<
"), shared by other processors\nwas not found.\n"
18711 <<
"The node coordinates are (" << nod_pt->x(0) <<
","
18712 << nod_pt->x(1) <<
").\n";
18713 throw OomphLibError(
18714 error_message.str(),
18715 "RefineableTriangleMesh::get_required_nodal_information_helper()",
18716 OOMPH_EXCEPTION_LOCATION);
18725 if (counter_shd_bnd_with_other_procs_have_node !=
18726 nshared_boundaries_with_other_processors_have_node)
18728 std::ostringstream error_message;
18729 error_message <<
"The number of shared boundaries where the node is on "
18730 <<
"is different:\n"
18731 <<
"nshared_boundaries_with_other_processors_have_node: ("
18732 << nshared_boundaries_with_other_processors_have_node
18734 <<
"counter_shd_bnd_with_other_procs_have_node: ("
18735 << counter_shd_bnd_with_other_procs_have_node <<
")\n";
18736 throw OomphLibError(
18737 error_message.str(),
18738 "RefineableTriangleMesh::get_required_nodal_information_helper()",
18739 OOMPH_EXCEPTION_LOCATION);
18745 for (
unsigned i = 0; i < n_other_processors; i++)
18747 Flat_packed_unsigneds.push_back(other_processor_1[i]);
18748 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18749 std::stringstream junk1;
18750 junk1 <<
"Processor where the other shared boundary "
18751 <<
"has the node: " << other_processor_1[i];
18752 Flat_packed_unsigneds_string.push_back(junk1.str());
18755 Flat_packed_unsigneds.push_back(other_processor_2[i]);
18756 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18757 std::stringstream junk2;
18758 junk2 <<
"Processor where the other shared boundary "
18759 <<
"has the node: " << other_processor_2[i];
18760 Flat_packed_unsigneds_string.push_back(junk2.str());
18763 Flat_packed_unsigneds.push_back(shd_bnd_ids[i]);
18764 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18765 std::stringstream junk3;
18766 junk3 <<
"Other shared boundary id where the node is on"
18768 Flat_packed_unsigneds_string.push_back(junk3.str());
18771 Flat_packed_unsigneds.push_back(indexes[i]);
18772 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18773 std::stringstream junk4;
18774 junk4 <<
"Node index on other shared boundary " << boundaries[i]
18775 <<
" is " << indexes[i];
18776 Flat_packed_unsigneds_string.push_back(junk4.str());
18784 Flat_packed_unsigneds.push_back(0);
18785 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18786 Flat_packed_unsigneds_string.push_back(
18787 "Node is on any shared boundary with other processors");
18795 if (!node_on_shared_boundary)
18802 AlgebraicNode* alg_nod_pt =
dynamic_cast<AlgebraicNode*
>(nod_pt);
18803 if (alg_nod_pt != 0)
18806 AlgebraicMesh* alg_mesh_pt =
dynamic_cast<AlgebraicMesh*
>(
this);
18809 unsigned update_id = alg_nod_pt->node_update_fct_id();
18810 Flat_packed_unsigneds.push_back(update_id);
18811 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18812 Flat_packed_unsigneds_string.push_back(
"Alg Node update id");
18816 unsigned n_ref_val = alg_nod_pt->nref_value();
18817 Flat_packed_unsigneds.push_back(n_ref_val);
18818 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18819 Flat_packed_unsigneds_string.push_back(
"Alg Node n ref values");
18821 for (
unsigned i_ref_val = 0; i_ref_val < n_ref_val; i_ref_val++)
18823 Flat_packed_doubles.push_back(alg_nod_pt->ref_value(i_ref_val));
18827 unsigned n_geom_obj = alg_nod_pt->ngeom_object();
18828 Flat_packed_unsigneds.push_back(n_geom_obj);
18829 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18830 Flat_packed_unsigneds_string.push_back(
"Alg Node n geom objects");
18832 for (
unsigned i_geom = 0; i_geom < n_geom_obj; i_geom++)
18834 GeomObject* geom_obj_pt = alg_nod_pt->geom_object_pt(i_geom);
18837 unsigned n_geom_list = alg_mesh_pt->ngeom_object_list_pt();
18840 unsigned found_geom_object = 0;
18841 for (
unsigned i_list = 0; i_list < n_geom_list; i_list++)
18843 if (geom_obj_pt == alg_mesh_pt->geom_object_list_pt(i_list))
18845 found_geom_object = i_list;
18848 Flat_packed_unsigneds.push_back(found_geom_object);
18849 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18850 Flat_packed_unsigneds_string.push_back(
"Found geom object");
18856 SolidNode* solid_nod_pt =
dynamic_cast<SolidNode*
>(nod_pt);
18857 if (solid_nod_pt != 0)
18859 unsigned n_solid_val = solid_nod_pt->variable_position_pt()->nvalue();
18860 for (
unsigned i_val = 0; i_val < n_solid_val; i_val++)
18862 for (
unsigned t = 0; t < n_prev; t++)
18864 Flat_packed_doubles.push_back(
18865 solid_nod_pt->variable_position_pt()->value(t, i_val));
18869 Vector<double> values_solid_node;
18870 solid_nod_pt->add_values_to_vector(values_solid_node);
18871 const unsigned nvalues_solid_node = values_solid_node.size();
18872 Flat_packed_unsigneds.push_back(nvalues_solid_node);
18873 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18874 std::stringstream junk;
18875 junk <<
"Number of values solid node: " << nvalues_solid_node;
18876 Flat_packed_unsigneds_string.push_back(junk.str());
18878 for (
unsigned i = 0; i < nvalues_solid_node; i++)
18880 Flat_packed_doubles.push_back(values_solid_node[i]);
18885 for (
unsigned i_val = 0; i_val < n_val; i_val++)
18887 for (
unsigned t = 0; t < n_prev; t++)
18889 Flat_packed_doubles.push_back(nod_pt->value(t, i_val));
18894 for (
unsigned idim = 0; idim < n_dim; idim++)
18896 for (
unsigned t = 0; t < n_prev; t++)
18898 Flat_packed_doubles.push_back(nod_pt->x(t, idim));
18908 template<
class ELEMENT>
18913 const unsigned n_haloed_nod = this->nhaloed_node(iproc);
18914 const unsigned haloed_node_index =
18915 this->try_to_add_haloed_node_pt(iproc, nod_pt);
18918 if (haloed_node_index == n_haloed_nod)
18920 Flat_packed_unsigneds.push_back(1);
18922 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18923 std::stringstream junk;
18924 junk <<
"Node needs to be constructed [size="
18925 << Flat_packed_unsigneds.size() <<
"]; last entry: "
18926 << Flat_packed_unsigneds[Flat_packed_unsigneds.size() - 1];
18927 Flat_packed_unsigneds_string.push_back(junk.str());
18933 get_required_nodal_information_helper(iproc, nod_pt);
18937 Flat_packed_unsigneds.push_back(0);
18938 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18939 std::stringstream junk;
18940 junk <<
"Node was already added [size=" << Flat_packed_unsigneds.size()
18941 <<
"]; last entry: "
18942 << Flat_packed_unsigneds[Flat_packed_unsigneds.size() - 1];
18944 Flat_packed_unsigneds_string.push_back(junk.str());
18949 Flat_packed_unsigneds.push_back(haloed_node_index);
18950 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18951 Flat_packed_unsigneds_string.push_back(
"haloed node index");
18960 template<
class ELEMENT>
18962 int& send_proc,
int& recv_proc)
18965 OomphCommunicator* comm_pt = this->communicator_pt();
18969 MPI_Request request;
18972 Vector<double> received_double_values;
18973 Vector<unsigned> received_unsigned_values;
18977 unsigned send_count_double_values = Flat_packed_doubles.size();
18978 MPI_Isend(&send_count_double_values,
18983 comm_pt->mpi_comm(),
18986 int receive_count_double_values = 0;
18987 MPI_Recv(&receive_count_double_values,
18992 comm_pt->mpi_comm(),
18994 MPI_Wait(&request, MPI_STATUS_IGNORE);
18996 if (send_count_double_values != 0)
18998 MPI_Isend(&Flat_packed_doubles[0],
18999 send_count_double_values,
19003 comm_pt->mpi_comm(),
19006 if (receive_count_double_values != 0)
19008 received_double_values.resize(receive_count_double_values);
19009 MPI_Recv(&received_double_values[0],
19010 receive_count_double_values,
19014 comm_pt->mpi_comm(),
19017 if (send_count_double_values != 0)
19019 MPI_Wait(&request, MPI_STATUS_IGNORE);
19024 unsigned send_count_unsigned_values = Flat_packed_unsigneds.size();
19025 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19026 unsigned send_count_unsigned_string = Flat_packed_unsigneds_string.size();
19028 if (send_count_unsigned_string != send_count_unsigned_values)
19030 std::ostringstream error_message;
19031 error_message <<
"The number of unsigned values to send to processor ("
19033 <<
") is different from the\nnumber of annotated strings "
19034 <<
"for the communication\n\n";
19035 throw OomphLibError(
19036 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
19040 MPI_Isend(&send_count_unsigned_values,
19045 comm_pt->mpi_comm(),
19048 int receive_count_unsigned_values = 0;
19049 MPI_Recv(&receive_count_unsigned_values,
19054 comm_pt->mpi_comm(),
19057 MPI_Wait(&request, MPI_STATUS_IGNORE);
19059 if (send_count_unsigned_values != 0)
19061 MPI_Isend(&Flat_packed_unsigneds[0],
19062 send_count_unsigned_values,
19066 comm_pt->mpi_comm(),
19068 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19069 for (
unsigned i = 0; i < send_count_unsigned_values; i++)
19071 oomph_info <<
"Sent:" << i <<
" to orig_proc:" << send_proc <<
" "
19072 << Flat_packed_unsigneds_string[i] <<
": "
19073 << Flat_packed_unsigneds[i] << std::endl;
19077 if (receive_count_unsigned_values != 0)
19079 received_unsigned_values.resize(receive_count_unsigned_values);
19080 MPI_Recv(&received_unsigned_values[0],
19081 receive_count_unsigned_values,
19085 comm_pt->mpi_comm(),
19089 if (send_count_unsigned_values != 0)
19091 MPI_Wait(&request, MPI_STATUS_IGNORE);
19100 Flat_packed_doubles.resize(receive_count_double_values);
19101 for (
int ii = 0; ii < receive_count_double_values; ii++)
19103 Flat_packed_doubles[ii] = received_double_values[ii];
19105 Flat_packed_unsigneds.resize(receive_count_unsigned_values);
19106 for (
int ii = 0; ii < receive_count_unsigned_values; ii++)
19108 Flat_packed_unsigneds[ii] = received_unsigned_values[ii];
19116 template<
class ELEMENT>
19119 Vector<Node*>& new_nodes_on_domain,
19120 Vector<Vector<Vector<std::map<unsigned, Node*>>>>&
19121 other_proc_shd_bnd_node_pt,
19122 Vector<Vector<Vector<unsigned>>>& global_node_names,
19123 std::map<Vector<unsigned>,
unsigned>& node_name_to_global_index,
19124 Vector<Node*>& global_shared_node_pt)
19126 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19127 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19128 <<
" Bool: New element needs to be constructed "
19129 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19133 if (Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++] == 1)
19137 GeneralisedElement* new_el_pt =
new ELEMENT;
19140 this->add_element_pt(new_el_pt);
19143 this->add_root_halo_element_pt(iproc, new_el_pt);
19146 FiniteElement* f_el_pt =
dynamic_cast<FiniteElement*
>(new_el_pt);
19149 this->add_halo_element_helper(iproc, f_el_pt);
19152 unsigned n_node = f_el_pt->nnode();
19154 for (
unsigned j = 0; j < n_node; j++)
19156 Node* new_nod_pt = 0;
19159 add_halo_node_helper(new_nod_pt,
19160 new_nodes_on_domain,
19161 other_proc_shd_bnd_node_pt,
19166 node_name_to_global_index,
19167 global_shared_node_pt);
19173 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19174 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19175 <<
" Index of existing halo element "
19176 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19180 unsigned halo_ele_index =
19181 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19184 FiniteElement* f_el_pt =
dynamic_cast<FiniteElement*
>(
19185 this->root_halo_element_pt(iproc, halo_ele_index));
19190 throw OomphLibError(
"Halo element is not a FiniteElement\n",
19191 OOMPH_CURRENT_FUNCTION,
19192 OOMPH_EXCEPTION_LOCATION);
19204 template<
class ELEMENT>
19206 unsigned& iproc, FiniteElement* ele_pt)
19208 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19209 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19210 <<
" Bool: Element is associated to an original boundary "
19211 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19215 if (Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++] == 1)
19217 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19218 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19219 <<
" How many boundaries are associated with the element "
19220 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19223 const unsigned nassociated_boundaries =
19224 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19226 for (
unsigned b = 0; b < nassociated_boundaries; b++)
19228 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19229 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19230 <<
" Boundary associated to the element "
19231 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19234 const unsigned bnd =
19235 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19237 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19238 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19239 <<
" Face index of the element "
19240 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19243 const unsigned face_index =
19244 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19248 this->Boundary_element_pt[bnd].push_back(ele_pt);
19249 this->Face_index_at_boundary[bnd].push_back(face_index);
19254 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19255 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19256 <<
" Bool: Element is associated to a boundary-region "
19257 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19261 if (Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++] == 1)
19263 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19265 <<
"Rec:" << Counter_for_flat_packed_unsigneds
19266 <<
" How many boundaries-regions are associated with the element "
19267 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19270 const unsigned nassociated_boundaries_and_regions =
19271 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19273 for (
unsigned br = 0; br < nassociated_boundaries_and_regions; br++)
19275 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19276 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19277 <<
" Boundary associated to the element "
19278 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19281 const unsigned bnd =
19282 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19284 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19285 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19286 <<
" Region associated to the element "
19287 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19290 const unsigned region =
19291 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19293 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19294 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19295 <<
" Face index of the element in boundary-region "
19296 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19299 const unsigned face_index =
19300 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19304 this->Boundary_region_element_pt[bnd][region].push_back(ele_pt);
19305 this->Face_index_region_at_boundary[bnd][region].push_back(
19314 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19315 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19316 <<
" Bool: Element is associated to a shared boundary "
19317 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19320 if (Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++] == 3)
19322 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19324 <<
"Rec:" << Counter_for_flat_packed_unsigneds
19325 <<
" How many shared boundaries are associated with the element "
19326 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19329 const unsigned nassociated_shared_boundaries =
19330 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19332 for (
unsigned b = 0; b < nassociated_shared_boundaries; b++)
19334 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19335 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19336 <<
" Shared boundary associated to the element "
19337 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19340 const unsigned bnd =
19341 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19343 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19345 <<
"Rec:" << Counter_for_flat_packed_unsigneds
19346 <<
" Face index of the element associated to the shared boundary "
19347 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19351 const unsigned face_index =
19352 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19354 this->add_shared_boundary_element(bnd, ele_pt);
19355 this->add_face_index_at_shared_boundary(bnd, face_index);
19365 template<
class ELEMENT>
19368 Vector<Node*>& new_nodes_on_domain,
19369 Vector<Vector<Vector<std::map<unsigned, Node*>>>>&
19370 other_proc_shd_bnd_node_pt,
19372 unsigned& node_index,
19373 FiniteElement*
const& new_el_pt,
19374 Vector<Vector<Vector<unsigned>>>& global_node_names,
19375 std::map<Vector<unsigned>,
unsigned>& node_name_to_global_index,
19376 Vector<Node*>& global_shared_node_pt)
19380 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19381 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19382 <<
" Bool: New node needs to be constructed "
19383 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19386 if (Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++] == 1)
19390 construct_new_halo_node_helper(new_nod_pt,
19391 new_nodes_on_domain,
19392 other_proc_shd_bnd_node_pt,
19397 node_name_to_global_index,
19398 global_shared_node_pt);
19402 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19403 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19404 <<
" Index of existing halo node "
19405 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19410 new_nod_pt = new_nodes_on_domain
19411 [Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++]];
19413 new_el_pt->node_pt(node_index) = new_nod_pt;
19421 template<
class ELEMENT>
19424 Vector<Node*>& new_nodes_on_domain,
19425 Vector<Vector<Vector<std::map<unsigned, Node*>>>>&
19426 other_proc_shd_bnd_node_pt,
19428 unsigned& node_index,
19429 FiniteElement*
const& new_el_pt,
19430 Vector<Vector<Vector<unsigned>>>& global_node_names,
19431 std::map<Vector<unsigned>,
unsigned>& node_name_to_global_index,
19432 Vector<Node*>& global_shared_node_pt)
19436 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19437 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19438 <<
" Number of values of external halo node "
19439 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19442 unsigned n_val = Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19445 TimeStepper* time_stepper_pt = this->Time_stepper_pt;
19447 unsigned n_prev = time_stepper_pt->ntstorage();
19451 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19452 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19453 <<
" Is the node on an original boundary "
19454 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19459 const unsigned node_on_original_boundaries =
19460 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19463 Vector<unsigned> original_boundaries_node_is_on;
19465 Vector<double> zeta_coordinates;
19467 unsigned n_original_boundaries_node_is_on = 0;
19469 if (node_on_original_boundaries == 2)
19472 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19473 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19474 <<
" Number of boundaries the node is on: "
19475 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19478 n_original_boundaries_node_is_on =
19479 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19482 original_boundaries_node_is_on.resize(n_original_boundaries_node_is_on);
19483 zeta_coordinates.resize(n_original_boundaries_node_is_on);
19485 for (
unsigned i = 0; i < n_original_boundaries_node_is_on; i++)
19488 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19489 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19490 <<
" Node is on boundary "
19491 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19494 original_boundaries_node_is_on[i] =
19495 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19496 zeta_coordinates[i] =
19497 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
19504 if (node_on_original_boundaries != 0)
19506 std::ostringstream error_message;
19508 <<
"The current node is not on an original boundary, this should\n"
19509 <<
"be indicated by a zero flag. However, the read value for\n"
19510 <<
"that flag is (" << node_on_original_boundaries <<
").\n\n";
19511 throw OomphLibError(
19512 error_message.str(),
19513 "RefineableTriangleMesh::construct_new_halo_node_helper()",
19514 OOMPH_EXCEPTION_LOCATION);
19522 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19523 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19524 <<
" Is node on shared boundary? "
19525 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19528 const unsigned is_node_on_shared_boundary =
19529 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19530 if (is_node_on_shared_boundary == 1)
19533 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19534 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19535 <<
" Number of boundaries the node is on: "
19536 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19539 const unsigned n_shd_bnd_node_is_on =
19540 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19541 Vector<unsigned> shd_bnds_node_is_on(n_shd_bnd_node_is_on);
19542 for (
unsigned i = 0; i < n_shd_bnd_node_is_on; i++)
19545 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19546 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19547 <<
" Node is on boundary "
19548 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19551 shd_bnds_node_is_on[i] =
19552 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19556 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19557 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19558 <<
" Index of node on boundary "
19559 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19563 unsigned node_index_on_shared_boundary =
19564 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19567 new_nod_pt = this->sorted_shared_boundary_node_pt(
19568 shd_bnds_node_is_on[0], node_index_on_shared_boundary);
19574 if (is_node_on_shared_boundary != 0)
19576 std::ostringstream error_message;
19578 <<
"The current node is not on a shared boundary, this should\n"
19579 <<
"be indicated by a zero flag. However, the read value for\n"
19580 <<
"that flag is (" << is_node_on_shared_boundary <<
").\n\n";
19581 throw OomphLibError(
19582 error_message.str(),
19583 "RefineableTriangleMesh::construct_new_halo_node_helper()",
19584 OOMPH_EXCEPTION_LOCATION);
19591 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19592 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19593 <<
" Is the node on shared boundaries with other processors "
19594 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19600 const unsigned is_the_node_in_shared_boundaries_with_other_processors =
19601 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19604 Vector<unsigned> other_processor_1;
19605 Vector<unsigned> other_processor_2;
19606 Vector<unsigned> other_shared_boundaries;
19607 Vector<unsigned> other_indexes;
19610 unsigned n_shd_bnd_with_other_procs_have_node = 0;
19613 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
19615 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19616 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19617 <<
" In how many shared boundaries with other "
19618 <<
"processors is the node "
19619 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19624 n_shd_bnd_with_other_procs_have_node =
19625 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19628 other_processor_1.resize(n_shd_bnd_with_other_procs_have_node);
19629 other_processor_2.resize(n_shd_bnd_with_other_procs_have_node);
19630 other_shared_boundaries.resize(n_shd_bnd_with_other_procs_have_node);
19631 other_indexes.resize(n_shd_bnd_with_other_procs_have_node);
19633 for (
unsigned i = 0; i < n_shd_bnd_with_other_procs_have_node; i++)
19635 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19636 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19637 <<
" Processor where the other shared boundary"
19639 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19643 other_processor_1[i] =
19644 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19646 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19647 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19648 <<
" Processor where the other shared boundary"
19650 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19654 other_processor_2[i] =
19655 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19657 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19658 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19659 <<
" Other shared boundary id where the node is on: "
19660 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19665 other_shared_boundaries[i] =
19666 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19668 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19669 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19670 <<
" Node index on the other shared boundary "
19671 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19677 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19685 if (is_the_node_in_shared_boundaries_with_other_processors != 0)
19687 std::ostringstream error_message;
19689 <<
"The current node is not on a shared boundary with\n"
19690 <<
"other processors, this should be indicated by a zero flag.\n"
19691 <<
"However, the read value for that flag is ("
19692 << is_the_node_in_shared_boundaries_with_other_processors <<
").\n\n";
19693 throw OomphLibError(
19694 error_message.str(),
19695 "RefineableTriangleMesh::construct_new_halo_node_helper()",
19696 OOMPH_EXCEPTION_LOCATION);
19705 if (is_node_on_shared_boundary == 1)
19710 if (node_on_original_boundaries == 2)
19716 for (
unsigned i = 0; i < n_original_boundaries_node_is_on; i++)
19718 add_boundary_node(original_boundaries_node_is_on[i], new_nod_pt);
19720 Vector<double> zeta(1);
19721 zeta[0] = zeta_coordinates[i];
19722 new_nod_pt->set_coordinates_on_boundary(
19723 original_boundaries_node_is_on[i], zeta);
19729 new_nodes_on_domain.push_back(new_nod_pt);
19732 new_el_pt->node_pt(node_index) = new_nod_pt;
19742 bool found_node_in_other_shared_boundaries =
false;
19751 bool build_node_as_boundary_node =
false;
19753 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
19756 build_node_as_boundary_node =
true;
19763 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
19766 Vector<Node*> found_node_pt;
19769 for (
unsigned i = 0; i < n_shd_bnd_with_other_procs_have_node; i++)
19780 unsigned oproc1 = other_processor_1[i];
19781 unsigned oproc2 = other_processor_2[i];
19782 if (other_processor_1[i] > other_processor_2[i])
19784 oproc1 = other_processor_2[i];
19785 oproc2 = other_processor_1[i];
19790 const unsigned shd_bnd_id =
19791 other_shared_boundaries[i] - initial_shd_bnd_id;
19794 const unsigned index = other_indexes[i];
19798 const unsigned n_nodes_on_other_processor =
19799 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].size();
19801 if (n_nodes_on_other_processor > 0)
19805 std::map<unsigned, Node*>::iterator it =
19806 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].find(index);
19810 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].end())
19813 found_node_in_other_shared_boundaries =
true;
19815 Node* tmp_node_pt = (*it).second;
19818 found_node_pt.push_back(tmp_node_pt);
19829 if (found_node_in_other_shared_boundaries)
19832 const unsigned n_times_node_found = found_node_pt.size();
19833 for (
unsigned j = 1; j < n_times_node_found; j++)
19835 if (found_node_pt[j - 1] != found_node_pt[j])
19837 std::ostringstream error_message;
19839 <<
"The instances of the node that was found on\n"
19840 <<
"shared boundaries with other processors (but not\n"
19841 <<
"on shared boundaries with this processor) are not\n"
19843 <<
"These are the coordinates of the instances of the\n"
19845 <<
"(" << found_node_pt[j - 1]->x(0) <<
", "
19846 << found_node_pt[j - 1]->x(1) <<
")\n"
19847 <<
"(" << found_node_pt[j]->x(0) <<
", " << found_node_pt[j]->x(1)
19849 <<
"Dont be surprised if they are the same since the "
19850 <<
"node is\nrepeated.\n";
19851 throw OomphLibError(error_message.str(),
19852 OOMPH_CURRENT_FUNCTION,
19853 OOMPH_EXCEPTION_LOCATION);
19864 if (is_node_on_shared_boundary == 1)
19873 if (found_node_pt[0] != new_nod_pt)
19875 std::ostringstream error_message;
19877 <<
"The pointer of the node that was found to be on a\n"
19878 <<
"shared boundary with other processor(s) and the pointer\n"
19879 <<
"of the node on shared boundary with the receiver\n"
19880 <<
"processor (iproc) are not the same. This means we have a\n"
19881 <<
"repeated node)\n"
19882 <<
"The coordinates for the nodes are:\n"
19883 <<
"(" << found_node_pt[0]->x(0) <<
", " << found_node_pt[0]->x(1)
19885 <<
"(" << new_nod_pt->x(0) <<
", " << new_nod_pt->x(1) <<
")\n"
19886 <<
"Dont be surprised if they are the same since the "
19887 <<
"node is\nrepeated.\n";
19888 throw OomphLibError(error_message.str(),
19889 OOMPH_CURRENT_FUNCTION,
19890 OOMPH_EXCEPTION_LOCATION);
19901 new_nod_pt = found_node_pt[0];
19911 if (is_node_on_shared_boundary != 1)
19925 if (node_on_original_boundaries == 2 || build_node_as_boundary_node)
19929 if (!found_node_in_other_shared_boundaries)
19932 if (time_stepper_pt != 0)
19935 new_el_pt->construct_boundary_node(node_index, time_stepper_pt);
19939 new_nod_pt = new_el_pt->construct_boundary_node(node_index);
19946 new_el_pt->node_pt(node_index) = new_nod_pt;
19951 for (
unsigned i = 0; i < n_original_boundaries_node_is_on; i++)
19953 add_boundary_node(original_boundaries_node_is_on[i], new_nod_pt);
19955 Vector<double> zeta(1);
19956 zeta[0] = zeta_coordinates[i];
19957 new_nod_pt->set_coordinates_on_boundary(
19958 original_boundaries_node_is_on[i], zeta);
19966 if (!found_node_in_other_shared_boundaries)
19969 if (time_stepper_pt != 0)
19971 new_nod_pt = new_el_pt->construct_node(node_index, time_stepper_pt);
19975 new_nod_pt = new_el_pt->construct_node(node_index);
19981 new_el_pt->node_pt(node_index) = new_nod_pt;
19992 new_nodes_on_domain.push_back(new_nod_pt);
19996 if (!found_node_in_other_shared_boundaries)
19999 this->add_node_pt(new_nod_pt);
20003 AlgebraicNode* new_alg_nod_pt =
dynamic_cast<AlgebraicNode*
>(new_nod_pt);
20007 if (new_alg_nod_pt != 0)
20010 AlgebraicMesh* alg_mesh_pt =
dynamic_cast<AlgebraicMesh*
>(
this);
20016 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
20017 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
20018 <<
" Alg node update id "
20019 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
20023 unsigned update_id =
20024 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
20026 Vector<double> ref_value;
20030 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
20031 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
20032 <<
" Alg node # of ref values "
20033 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
20036 unsigned n_ref_val =
20037 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
20041 ref_value.resize(n_ref_val);
20042 for (
unsigned i_ref = 0; i_ref < n_ref_val; i_ref++)
20045 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
20048 Vector<GeomObject*> geom_object_pt;
20055 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
20056 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
20057 <<
" Alg node # of geom objects "
20058 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
20061 unsigned n_geom_obj =
20062 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
20066 geom_object_pt.resize(n_geom_obj);
20067 for (
unsigned i_geom = 0; i_geom < n_geom_obj; i_geom++)
20069 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
20070 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
20071 <<
" Alg node: geom object index "
20072 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
20075 unsigned geom_index =
20076 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
20083 geom_object_pt[i_geom] = alg_mesh_pt->geom_object_list_pt(geom_index);
20088 if (!found_node_in_other_shared_boundaries)
20092 new_alg_nod_pt->add_node_update_info(
20093 update_id, alg_mesh_pt, geom_object_pt, ref_value);
20096 alg_mesh_pt->update_node_update(new_alg_nod_pt);
20104 if (!found_node_in_other_shared_boundaries)
20107 MacroElementNodeUpdateNode* macro_nod_pt =
20108 dynamic_cast<MacroElementNodeUpdateNode*
>(new_nod_pt);
20110 if (macro_nod_pt != 0)
20114 Vector<GeomObject*> geom_object_vector_pt;
20118 MacroElementNodeUpdateMesh* macro_mesh_pt =
20119 dynamic_cast<MacroElementNodeUpdateMesh*
>(
this);
20120 geom_object_vector_pt = macro_mesh_pt->geom_object_vector_pt();
20123 Vector<double> s_in_macro_node_update_element;
20124 new_el_pt->local_coordinate_of_node(node_index,
20125 s_in_macro_node_update_element);
20128 macro_nod_pt->set_node_update_info(
20129 new_el_pt, s_in_macro_node_update_element, geom_object_vector_pt);
20135 unsigned n_new_val = new_nod_pt->nvalue();
20139 if (!found_node_in_other_shared_boundaries)
20141 if (n_val > n_new_val)
20148 BoundaryNodeBase* bnod_pt =
20149 dynamic_cast<BoundaryNodeBase*
>(new_nod_pt);
20154 if (bnod_pt->index_of_first_value_assigned_by_face_element_pt() == 0)
20156 bnod_pt->index_of_first_value_assigned_by_face_element_pt() =
20157 new std::map<unsigned, unsigned>;
20161 std::map<unsigned, unsigned>* map_pt =
20162 bnod_pt->index_of_first_value_assigned_by_face_element_pt();
20166 const unsigned id_face = 0;
20168 std::map<unsigned, unsigned>::const_iterator p =
20169 map_pt->find(id_face);
20172 if (p == map_pt->end())
20176 (*map_pt)[id_face] = n_new_val;
20179 new_nod_pt->resize(n_val);
20187 SolidNode* solid_nod_pt =
dynamic_cast<SolidNode*
>(new_nod_pt);
20188 if (solid_nod_pt != 0)
20190 unsigned n_solid_val = solid_nod_pt->variable_position_pt()->nvalue();
20191 for (
unsigned i_val = 0; i_val < n_solid_val; i_val++)
20193 for (
unsigned t = 0; t < n_prev; t++)
20196 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
20200 if (!found_node_in_other_shared_boundaries)
20202 solid_nod_pt->variable_position_pt()->set_value(
20203 t, i_val, read_data);
20208 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
20209 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
20210 <<
" Number of values solid node: "
20211 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
20214 const unsigned nvalues_solid_node =
20215 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
20216 Vector<double> values_solid_node(nvalues_solid_node);
20217 for (
unsigned i = 0; i < nvalues_solid_node; i++)
20219 values_solid_node[i] =
20220 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
20225 if (!found_node_in_other_shared_boundaries)
20227 unsigned index = 0;
20228 solid_nod_pt->read_values_from_vector(values_solid_node, index);
20234 for (
unsigned i_val = 0; i_val < n_val; i_val++)
20236 for (
unsigned t = 0; t < n_prev; t++)
20239 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
20244 if (!found_node_in_other_shared_boundaries)
20246 new_nod_pt->set_value(t, i_val, read_data);
20252 unsigned n_dim = new_nod_pt->ndim();
20253 for (
unsigned idim = 0; idim < n_dim; idim++)
20255 for (
unsigned t = 0; t < n_prev; t++)
20258 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
20263 if (!found_node_in_other_shared_boundaries)
20266 new_nod_pt->x(t, idim) = read_data;
20278 if (n_shd_bnd_with_other_procs_have_node > 0 &&
20282 !found_node_in_other_shared_boundaries)
20290 this->update_other_proc_shd_bnd_node_helper(new_nod_pt,
20291 other_proc_shd_bnd_node_pt,
20294 other_shared_boundaries,
20297 node_name_to_global_index,
20298 global_shared_node_pt);
20307 template<
class ELEMENT>
20309 Node*& new_node_pt,
20310 Vector<Vector<Vector<std::map<unsigned, Node*>>>>&
20311 other_proc_shd_bnd_node_pt,
20312 Vector<unsigned>& other_processor_1,
20313 Vector<unsigned>& other_processor_2,
20314 Vector<unsigned>& other_shared_boundaries,
20315 Vector<unsigned>& other_indexes,
20316 Vector<Vector<Vector<unsigned>>>& global_node_names,
20317 std::map<Vector<unsigned>,
unsigned>& node_name_to_global_index,
20318 Vector<Node*>& global_shared_node_pt)
20322 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
20327 const unsigned n_data = other_processor_1.size();
20331 Vector<unsigned> node_name(4);
20332 node_name[0] = other_processor_1[0];
20333 node_name[1] = other_processor_2[0];
20334 node_name[2] = other_shared_boundaries[0];
20335 node_name[3] = other_indexes[0];
20339 std::map<Vector<unsigned>,
unsigned>::iterator it =
20340 node_name_to_global_index.find(node_name);
20341 if (it == node_name_to_global_index.end())
20343 std::ostringstream error_stream;
20344 error_stream <<
"The node name does not exist in the global node names\n"
20345 <<
"This is the name of the node\n"
20346 <<
"Name: iproc, jproc, ishd_bnd, idx\n"
20347 <<
"Name: " << node_name[0] <<
", " << node_name[1] <<
", "
20348 << node_name[2] <<
", " << node_name[3] <<
"\n";
20349 throw OomphLibError(
20350 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
20355 const unsigned iglobal_node = node_name_to_global_index[node_name];
20357 global_shared_node_pt[iglobal_node] = new_node_pt;
20359 Vector<Vector<unsigned>> inode_names = global_node_names[iglobal_node];
20361 const unsigned n_names = inode_names.size();
20366 unsigned n_found_node_names_on_global_node_name = 0;
20368 for (
unsigned j = 0; j < n_data; j++)
20371 for (
unsigned k = 0; k < n_names; k++)
20374 if (inode_names[k][0] == other_processor_1[j] &&
20375 inode_names[k][1] == other_processor_2[j] &&
20376 inode_names[k][2] == other_shared_boundaries[j] &&
20377 inode_names[k][3] == other_indexes[j])
20381 n_found_node_names_on_global_node_name++;
20389 if (n_found_node_names_on_global_node_name != n_data)
20391 std::ostringstream error_stream;
20393 <<
"Not all the node names of the current node were found on the\n"
20394 <<
"global node names. This happened when adding the node pointer\n"
20395 <<
"to the data structure that keeps tracks of nodes on shared\n"
20396 <<
"boundaries with other processors\n\n"
20397 <<
"These are the names of the current node\n"
20398 <<
"Name k: iproc, jproc, ishd_bnd, idx\n";
20399 for (
unsigned j = 0; j < n_data; j++)
20401 error_stream <<
"Name(" << j <<
"): " << other_processor_1[j] <<
", "
20402 << other_processor_2[j] <<
", "
20403 << other_shared_boundaries[j] <<
", " << other_indexes[j]
20407 error_stream <<
"\n\nThese are the names of the global node\n"
20408 <<
"Name k: iproc, jproc, ishd_bnd, idx\n";
20409 for (
unsigned k = 0; k < n_names; k++)
20411 error_stream <<
"Name(" << k <<
"): " << inode_names[k][0] <<
", "
20412 << inode_names[k][1] <<
", " << inode_names[k][2] <<
", "
20413 << inode_names[k][3] <<
"\n";
20416 throw OomphLibError(
20417 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
20422 for (
unsigned j = 0; j < n_names; j++)
20425 const unsigned iproc = inode_names[j][0];
20426 const unsigned jproc = inode_names[j][1];
20427 const unsigned ishd_bnd = inode_names[j][2] - initial_shd_bnd_id;
20428 const unsigned index = inode_names[j][3];
20434 other_proc_shd_bnd_node_pt[iproc][jproc][ishd_bnd][index] = new_node_pt;
20438 other_proc_shd_bnd_node_pt[jproc][iproc][ishd_bnd][index] = new_node_pt;
20456 template<
class ELEMENT>
20458 const Vector<unsigned>& target_domain_for_local_non_halo_element)
20460 oomph_info <<
"Load balance (unstructured mesh) [BEGIN]" << std::endl;
20464 if (!this->is_mesh_distributed())
20466 std::ostringstream warning_message;
20468 <<
"\n===============================================================\n"
20469 <<
"The load balancing can only be performed in distributed meshes,\n"
20470 <<
"your mesh has not been distributed.\n"
20471 <<
"==============================================================="
20473 OomphLibWarning(warning_message.str(),
20474 OOMPH_CURRENT_FUNCTION,
20475 OOMPH_EXCEPTION_LOCATION);
20481 const unsigned nproc = this->communicator_pt()->nproc();
20483 const unsigned my_rank = this->communicator_pt()->my_rank();
20488 std::ostringstream warning_message;
20490 <<
"\n===============================================================\n"
20491 <<
"The load balancing can only be performed when there are at least\n"
20492 <<
"two procesors, the current number of processors is one.\n"
20493 <<
"==============================================================="
20495 OomphLibWarning(warning_message.str(),
20496 OOMPH_CURRENT_FUNCTION,
20497 OOMPH_EXCEPTION_LOCATION);
20503 double t_start_overall_load_balance = 0.0;
20504 if (Print_timings_level_load_balance > 1)
20506 t_start_overall_load_balance = TimingHelpers::timer();
20510 const unsigned nelement_before_load_balance = this->nelement();
20515 if (nnon_halo_element() != target_domain_for_local_non_halo_element.size())
20517 std::ostringstream error_message;
20518 error_message <<
"The number of non halo elements in the current mesh ("
20519 << nnon_halo_element() <<
") and the number\n"
20520 <<
"of target areas for the local non halo elements ("
20521 << target_domain_for_local_non_halo_element.size()
20522 <<
") is different\n\n";
20523 throw OomphLibError(
20524 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
20529 Vector<FiniteElement*> backed_up_ele_pt(nelement_before_load_balance);
20530 for (
unsigned e = 0; e < nelement_before_load_balance; e++)
20532 backed_up_ele_pt[e] = this->finite_element_pt(e);
20540 double tt_start_get_domains_halo_elements = 0.0;
20541 if (Print_timings_level_load_balance > 1)
20543 tt_start_get_domains_halo_elements = TimingHelpers::timer();
20557 Vector<Vector<unsigned>> new_domains_haloed_elements(nproc);
20560 Vector<Vector<unsigned>> new_domains_halo_elements(nproc);
20564 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20568 if (iproc != my_rank)
20571 const unsigned n_halo_iproc = this->nroot_halo_element(iproc);
20573 new_domains_halo_elements[iproc].resize(n_halo_iproc);
20576 const unsigned n_haloed_iproc = this->nroot_haloed_element(iproc);
20578 new_domains_haloed_elements[iproc].resize(n_haloed_iproc);
20584 Vector<unsigned> counter_for_found_haloed_elements(nproc, 0);
20591 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20595 if (iproc != my_rank)
20598 const unsigned n_haloed_iproc = this->nroot_haloed_element(iproc);
20601 for (
unsigned ihd = 0; ihd < n_haloed_iproc; ihd++)
20604 GeneralisedElement* haloed_ele_pt =
20605 this->root_haloed_element_pt(iproc, ihd);
20608 unsigned nh_count4 = 0;
20610 for (
unsigned e = 0; e < nelement_before_load_balance; e++)
20613 GeneralisedElement* ele_pt = this->element_pt(e);
20615 if (!ele_pt->is_halo())
20622 if (ele_pt == haloed_ele_pt)
20625 const unsigned element_domain =
20626 target_domain_for_local_non_halo_element[nh_count4 - 1];
20631 new_domains_haloed_elements[iproc][ihd] = element_domain;
20634 counter_for_found_haloed_elements[iproc]++;
20655 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20659 if (iproc != my_rank)
20662 const unsigned n_haloed_iproc = this->nroot_haloed_element(iproc);
20666 if (n_haloed_iproc != counter_for_found_haloed_elements[iproc])
20668 std::ostringstream error_message;
20669 error_message <<
"The independent counting of found haloed elements ("
20670 << counter_for_found_haloed_elements[iproc]
20671 <<
") with processor (" << iproc
20672 <<
") is not equal to the number of haloed elements ("
20673 << n_haloed_iproc <<
") with processor (" << iproc
20675 throw OomphLibError(error_message.str(),
20676 OOMPH_CURRENT_FUNCTION,
20677 OOMPH_EXCEPTION_LOCATION);
20691 Vector<unsigned> new_domains_haloed_flat_unsigned;
20694 Vector<int> nhaloed_elements_with_iproc(nproc);
20695 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20699 if (iproc != my_rank)
20702 const unsigned n_haloed_ele_iproc = this->nroot_haloed_element(iproc);
20704 nhaloed_elements_with_iproc[iproc] = n_haloed_ele_iproc;
20707 for (
unsigned i = 0; i < n_haloed_ele_iproc; i++)
20709 new_domains_haloed_flat_unsigned.push_back(
20710 new_domains_haloed_elements[iproc][i]);
20718 Vector<int> offset_haloed_elements_with_iproc(nproc);
20719 offset_haloed_elements_with_iproc[0] = 0;
20720 for (
unsigned ip = 1; ip < nproc; ip++)
20723 offset_haloed_elements_with_iproc[ip] =
20724 offset_haloed_elements_with_iproc[ip - 1] +
20725 nhaloed_elements_with_iproc[ip - 1];
20734 unsigned counter_halo_ele_with_all_procs = 0;
20738 Vector<int> nhalo_elements_with_iproc(nproc);
20741 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20745 if (iproc != my_rank)
20748 const unsigned n_halo_ele_iproc = this->nroot_halo_element(iproc);
20750 nhalo_elements_with_iproc[iproc] = n_halo_ele_iproc;
20752 counter_halo_ele_with_all_procs += n_halo_ele_iproc;
20758 Vector<int> offset_halo_elements_with_iproc(nproc);
20759 offset_halo_elements_with_iproc[0] = 0;
20760 for (
unsigned ip = 1; ip < nproc; ip++)
20763 offset_halo_elements_with_iproc[ip] =
20764 offset_halo_elements_with_iproc[ip - 1] +
20765 nhalo_elements_with_iproc[ip - 1];
20773 Vector<unsigned> new_domains_halo_flat_unsigned(
20774 counter_halo_ele_with_all_procs);
20778 MPI_Alltoallv(&new_domains_haloed_flat_unsigned[0],
20779 &nhaloed_elements_with_iproc[0],
20780 &offset_haloed_elements_with_iproc[0],
20782 &new_domains_halo_flat_unsigned[0],
20783 &nhalo_elements_with_iproc[0],
20784 &offset_halo_elements_with_iproc[0],
20786 this->communicator_pt()->mpi_comm());
20792 unsigned counter_new_domains_halo_ele = 0;
20793 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20797 if (iproc != my_rank)
20800 const unsigned ntmp_halo_elements_with_iproc =
20801 nhalo_elements_with_iproc[iproc];
20804 for (
unsigned i = 0; i < ntmp_halo_elements_with_iproc; i++)
20808 new_domains_halo_elements[iproc][i] =
20809 new_domains_halo_flat_unsigned[counter_new_domains_halo_ele++];
20815 if (Print_timings_level_load_balance > 1)
20817 oomph_info <<
"CPU for getting domains halo elements (load balance) [1]: "
20818 << TimingHelpers::timer() - tt_start_get_domains_halo_elements
20833 double tt_start_get_fe_version_from_ge_halo_ed = 0.0;
20834 if (Print_timings_level_load_balance > 1)
20836 tt_start_get_fe_version_from_ge_halo_ed = TimingHelpers::timer();
20840 Vector<Vector<FiniteElement*>> f_halo_element_pt(nproc);
20842 Vector<Vector<FiniteElement*>> f_haloed_element_pt(nproc);
20844 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20847 if (iproc != my_rank)
20850 const unsigned nhalo_ele_iproc = this->nroot_halo_element(iproc);
20852 Vector<GeneralisedElement*> halo_element_pt_iproc =
20853 this->root_halo_element_pt(iproc);
20855 f_halo_element_pt[iproc].resize(nhalo_ele_iproc);
20857 for (
unsigned ih = 0; ih < nhalo_ele_iproc; ih++)
20860 FiniteElement* ele_pt =
20861 dynamic_cast<FiniteElement*
>(halo_element_pt_iproc[ih]);
20863 f_halo_element_pt[iproc][ih] = ele_pt;
20867 const unsigned nhaloed_ele_iproc = this->nroot_haloed_element(iproc);
20869 Vector<GeneralisedElement*> haloed_element_pt_iproc =
20870 this->root_haloed_element_pt(iproc);
20872 f_haloed_element_pt[iproc].resize(nhaloed_ele_iproc);
20874 for (
unsigned ihd = 0; ihd < nhaloed_ele_iproc; ihd++)
20877 FiniteElement* ele_pt =
20878 dynamic_cast<FiniteElement*
>(haloed_element_pt_iproc[ihd]);
20880 f_haloed_element_pt[iproc][ihd] = ele_pt;
20889 if (Print_timings_level_load_balance > 1)
20891 oomph_info <<
"CPU for getting finite element versions from generalised "
20892 "halo(ed) elements (load balance) [2]: "
20893 << TimingHelpers::timer() -
20894 tt_start_get_fe_version_from_ge_halo_ed
20911 double tt_start_prepare_element_to_send = 0.0;
20912 if (Print_timings_level_load_balance > 1)
20914 tt_start_prepare_element_to_send = TimingHelpers::timer();
20918 Vector<Vector<FiniteElement*>> elements_to_send_pt(nproc);
20922 std::map<Data*, std::set<unsigned>>
20923 processors_associated_with_data_before_load_balance;
20927 unsigned nh_count3 = 0;
20928 for (
unsigned e = 0; e < nelement_before_load_balance; e++)
20931 FiniteElement* ele_pt = this->finite_element_pt(e);
20933 if (!(ele_pt->is_halo()))
20936 const unsigned element_domain =
20937 target_domain_for_local_non_halo_element[nh_count3++];
20940 elements_to_send_pt[element_domain].push_back(ele_pt);
20943 const unsigned n_nodes = ele_pt->nnode();
20945 for (
unsigned j = 0; j < n_nodes; j++)
20948 Node* node_pt = ele_pt->node_pt(j);
20950 processors_associated_with_data_before_load_balance[node_pt].insert(
20963 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20966 if (iproc != my_rank)
20969 const unsigned n_halo_ele_iproc = this->nroot_halo_element(iproc);
20971 Vector<GeneralisedElement*> halo_element_pt_iproc =
20972 this->root_halo_element_pt(iproc);
20974 for (
unsigned ih = 0; ih < n_halo_ele_iproc; ih++)
20977 const unsigned element_domain = new_domains_halo_elements[iproc][ih];
20980 FiniteElement* ele_pt =
20981 dynamic_cast<FiniteElement*
>(halo_element_pt_iproc[ih]);
20984 const unsigned n_nodes = ele_pt->nnode();
20986 for (
unsigned j = 0; j < n_nodes; j++)
20989 Node* node_pt = ele_pt->node_pt(j);
20992 processors_associated_with_data_before_load_balance[node_pt].insert(
21004 if (Print_timings_level_load_balance > 1)
21006 oomph_info <<
"CPU for preparing elements to send to other processors "
21007 "(load balance) [3]: "
21008 << TimingHelpers::timer() - tt_start_prepare_element_to_send
21031 double tt_start_compute_new_local_halo_elements = 0.0;
21032 if (Print_timings_level_load_balance > 1)
21034 tt_start_compute_new_local_halo_elements = TimingHelpers::timer();
21064 Vector<Vector<Vector<FiniteElement*>>> new_local_halo_element_pt(nproc);
21067 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21070 new_local_halo_element_pt[iproc].resize(nproc);
21074 Vector<std::map<FiniteElement*, bool>> new_local_halo_already_added(
21079 unsigned nh_count5 = 0;
21080 for (
unsigned e = 0; e < nelement_before_load_balance; e++)
21083 FiniteElement* ele_pt = this->finite_element_pt(e);
21085 if (!(ele_pt->is_halo()))
21088 const unsigned ele_domain =
21089 target_domain_for_local_non_halo_element[nh_count5++];
21092 if (ele_domain != iproc)
21095 const unsigned nnodes = ele_pt->nnode();
21097 for (
unsigned j = 0; j < nnodes; j++)
21099 Node* node_pt = ele_pt->node_pt(j);
21102 std::set<unsigned>::iterator it =
21103 processors_associated_with_data_before_load_balance[node_pt]
21107 processors_associated_with_data_before_load_balance[node_pt]
21114 if (!new_local_halo_already_added[ele_domain][ele_pt])
21118 new_local_halo_element_pt[iproc][ele_domain].push_back(
21121 new_local_halo_already_added[ele_domain][ele_pt] =
true;
21159 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21163 if (jproc != my_rank)
21166 const unsigned n_halo_ele_jproc = this->nroot_halo_element(jproc);
21168 Vector<GeneralisedElement*> halo_element_pt_jproc =
21169 this->root_halo_element_pt(jproc);
21172 for (
unsigned jh = 0; jh < n_halo_ele_jproc; jh++)
21175 const unsigned ele_domain = new_domains_halo_elements[jproc][jh];
21206 if (ele_domain != iproc)
21209 FiniteElement* ele_pt =
21210 dynamic_cast<FiniteElement*
>(halo_element_pt_jproc[jh]);
21212 const unsigned nnodes = ele_pt->nnode();
21214 for (
unsigned j = 0; j < nnodes; j++)
21217 Node* node_pt = ele_pt->node_pt(j);
21221 std::set<unsigned>::iterator it =
21222 processors_associated_with_data_before_load_balance[node_pt]
21226 processors_associated_with_data_before_load_balance[node_pt]
21234 if (!new_local_halo_already_added[ele_domain][ele_pt])
21238 new_local_halo_element_pt[iproc][ele_domain].push_back(
21240 new_local_halo_already_added[ele_domain][ele_pt] =
true;
21269 if (Print_timings_level_load_balance > 1)
21272 <<
"CPU for computing new local halo elements (load balance) [4]: "
21273 << TimingHelpers::timer() - tt_start_compute_new_local_halo_elements
21292 double tt_start_compute_new_local_shd_bnd_ele = 0.0;
21293 if (Print_timings_level_load_balance > 1)
21295 tt_start_compute_new_local_shd_bnd_ele = TimingHelpers::timer();
21300 Vector<Vector<Vector<FiniteElement*>>>
21301 new_local_halo_shared_boundary_element_pt(nproc);
21302 Vector<Vector<Vector<unsigned>>>
21303 new_local_halo_shared_boundary_element_face_index(nproc);
21306 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21308 new_local_halo_shared_boundary_element_pt[iproc].resize(nproc);
21309 new_local_halo_shared_boundary_element_face_index[iproc].resize(nproc);
21317 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21323 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
21325 this->get_shared_boundary_elements_and_face_indexes(
21326 new_local_halo_element_pt[iproc][jproc],
21327 new_local_halo_element_pt[jproc][iproc],
21328 new_local_halo_shared_boundary_element_pt[iproc][jproc],
21329 new_local_halo_shared_boundary_element_face_index[iproc][jproc],
21330 new_local_halo_shared_boundary_element_pt[jproc][iproc],
21331 new_local_halo_shared_boundary_element_face_index[jproc][iproc]);
21336 if (Print_timings_level_load_balance > 1)
21338 oomph_info <<
"CPU for computing new local shared boundary elements "
21339 "(load balance) [5]: "
21340 << TimingHelpers::timer() -
21341 tt_start_compute_new_local_shd_bnd_ele
21360 double tt_start_send_elements_to_other_processors = 0.0;
21361 if (Print_timings_level_load_balance > 1)
21363 tt_start_send_elements_to_other_processors = TimingHelpers::timer();
21369 this->sort_nodes_on_shared_boundaries();
21372 Vector<Vector<FiniteElement*>> received_elements_pt(nproc);
21379 Vector<Vector<Vector<FiniteElement*>>>
21380 new_received_haloed_shared_boundary_element_pt(nproc);
21381 Vector<Vector<Vector<unsigned>>>
21382 new_received_haloed_shared_boundary_element_face_index(nproc);
21387 Vector<Vector<Vector<std::map<unsigned, Node*>>>>
21388 other_proc_shd_bnd_node_pt(nproc);
21390 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21393 other_proc_shd_bnd_node_pt[iproc].resize(nproc);
21394 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21397 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
21398 const unsigned final_shd_bnd_id = this->final_shared_boundary_id();
21399 const unsigned n_shared_bound = final_shd_bnd_id - initial_shd_bnd_id;
21400 other_proc_shd_bnd_node_pt[iproc][jproc].resize(n_shared_bound);
21409 Vector<Vector<Vector<unsigned>>> global_node_names;
21413 std::map<Vector<unsigned>,
unsigned> node_name_to_global_index;
21416 Vector<Node*> global_shared_node_pt;
21421 compute_global_node_names_and_shared_nodes(other_proc_shd_bnd_node_pt,
21423 node_name_to_global_index,
21424 global_shared_node_pt);
21429 Vector<Vector<std::map<unsigned, FiniteElement*>>>
21430 received_old_haloed_element_pt(nproc);
21437 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21439 received_old_haloed_element_pt[iproc].resize(nproc);
21444 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21446 if (iproc != my_rank)
21453 Vector<FiniteElement*> currently_sent_elements;
21455 Vector<Node*> currently_sent_nodes;
21458 Flat_packed_unsigneds.clear();
21459 Flat_packed_doubles.clear();
21460 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21461 Flat_packed_unsigneds_string.clear();
21465 const unsigned nelements_to_send = elements_to_send_pt[iproc].size();
21471 Flat_packed_unsigneds.push_back(nelements_to_send);
21472 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21473 std::stringstream junk;
21474 junk <<
"Number of elements to send from processor " << my_rank
21475 <<
" to processor " << iproc <<
": (" << nelements_to_send <<
")";
21476 Flat_packed_unsigneds_string.push_back(junk.str());
21480 for (
unsigned e = 0; e < nelements_to_send; e++)
21483 FiniteElement* send_ele_pt = elements_to_send_pt[iproc][e];
21486 const unsigned ncurrently_sent_elements =
21487 currently_sent_elements.size();
21490 const unsigned index_ele = try_to_add_element_pt_load_balance(
21491 currently_sent_elements, send_ele_pt);
21494 if (index_ele == ncurrently_sent_elements)
21496 Flat_packed_unsigneds.push_back(1);
21497 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21498 Flat_packed_unsigneds_string.push_back(
21499 "Element needs to be constructed");
21503 get_required_elemental_information_load_balance_helper(
21504 iproc, f_haloed_element_pt, send_ele_pt);
21507 const unsigned nnodes = send_ele_pt->nnode();
21510 for (
unsigned j = 0; j < nnodes; j++)
21512 Node* node_pt = send_ele_pt->node_pt(j);
21515 add_node_load_balance_helper(iproc,
21517 currently_sent_nodes,
21525 Flat_packed_unsigneds.push_back(0);
21526 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21527 Flat_packed_unsigneds_string.push_back(
"Element already exists");
21529 Flat_packed_unsigneds.push_back(index_ele);
21530 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21531 Flat_packed_unsigneds_string.push_back(
"Index of existing element");
21550 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21556 const unsigned njproc_iproc_new_local_halo_shared_boundary_ele =
21557 new_local_halo_shared_boundary_element_pt[jproc][iproc].size();
21560 Vector<unsigned> new_local_halo_shared_boundary_ele_index;
21564 unsigned nfound_new_local_halo_shared_bound_ele_index = 0;
21567 unsigned nnon_halo_new_local_halo_shared_bound_ele = 0;
21571 for (
unsigned e = 0;
21572 e < njproc_iproc_new_local_halo_shared_boundary_ele;
21576 FiniteElement* shared_ele_pt =
21577 new_local_halo_shared_boundary_element_pt[jproc][iproc][e];
21581 if (!shared_ele_pt->is_halo())
21583 nnon_halo_new_local_halo_shared_bound_ele++;
21588 const unsigned ncurrently_sent_elements =
21589 currently_sent_elements.size();
21591 for (
unsigned ics = 0; ics < ncurrently_sent_elements; ics++)
21593 FiniteElement* currently_sent_ele_pt =
21594 currently_sent_elements[ics];
21597 if (currently_sent_ele_pt == shared_ele_pt)
21601 new_local_halo_shared_boundary_ele_index.push_back(ics);
21604 nfound_new_local_halo_shared_bound_ele_index++;
21616 if (nfound_new_local_halo_shared_bound_ele_index !=
21617 nnon_halo_new_local_halo_shared_bound_ele)
21619 std::ostringstream error_message;
21620 error_message <<
"Was only possible to identify ("
21621 << nfound_new_local_halo_shared_bound_ele_index
21623 << nnon_halo_new_local_halo_shared_bound_ele
21625 <<
"elements between\nprocessor (" << iproc
21626 <<
") and (" << jproc <<
") "
21627 <<
"when sending elements to processor (" << iproc
21629 throw OomphLibError(error_message.str(),
21630 OOMPH_CURRENT_FUNCTION,
21631 OOMPH_EXCEPTION_LOCATION);
21636 Flat_packed_unsigneds.push_back(9999);
21637 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21638 std::stringstream junk;
21639 junk <<
"Flag for synchronisation 9999";
21640 Flat_packed_unsigneds_string.push_back(junk.str());
21645 Flat_packed_unsigneds.push_back(
21646 nnon_halo_new_local_halo_shared_bound_ele);
21647 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21648 std::stringstream junk2;
21649 junk2 <<
"Number of new local halo shared boundary elements "
21650 << nnon_halo_new_local_halo_shared_bound_ele;
21651 Flat_packed_unsigneds_string.push_back(junk2.str());
21656 unsigned counter_nonhalo_sent = 0;
21659 for (
unsigned e = 0;
21660 e < njproc_iproc_new_local_halo_shared_boundary_ele;
21664 FiniteElement* shared_ele_pt =
21665 new_local_halo_shared_boundary_element_pt[jproc][iproc][e];
21669 if (!shared_ele_pt->is_halo())
21673 const unsigned ele_index =
21674 new_local_halo_shared_boundary_ele_index
21675 [counter_nonhalo_sent++];
21677 const unsigned face_index =
21678 new_local_halo_shared_boundary_element_face_index[jproc][iproc]
21683 Flat_packed_unsigneds.push_back(ele_index);
21684 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21685 std::stringstream junk;
21686 junk <<
"The index of the halo shared boundary element "
21688 Flat_packed_unsigneds_string.push_back(junk.str());
21693 Flat_packed_unsigneds.push_back(face_index);
21694 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21695 std::stringstream junk2;
21696 junk2 <<
"The face index of the halo shared boundary element "
21698 Flat_packed_unsigneds_string.push_back(junk2.str());
21711 int send_proc =
static_cast<int>(iproc);
21713 int recv_proc =
static_cast<int>(iproc);
21714 send_and_receive_elements_nodes_info(send_proc, recv_proc);
21721 Vector<FiniteElement*> currently_created_elements;
21723 Vector<Node*> currently_created_nodes;
21726 Counter_for_flat_packed_doubles = 0;
21727 Counter_for_flat_packed_unsigneds = 0;
21729 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21730 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
21731 <<
" Number of elements need to be constructed "
21732 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
21737 const unsigned nelements_to_create =
21738 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
21740 for (
unsigned e = 0; e < nelements_to_create; e++)
21744 create_element_load_balance_helper(iproc,
21745 f_haloed_element_pt,
21746 received_old_haloed_element_pt,
21747 currently_created_elements,
21748 currently_created_nodes,
21749 other_proc_shd_bnd_node_pt,
21751 node_name_to_global_index,
21752 global_shared_node_pt);
21758 const unsigned nreceived_elements = currently_created_elements.size();
21759 received_elements_pt[iproc].resize(nreceived_elements);
21760 for (
unsigned e = 0; e < nreceived_elements; e++)
21762 received_elements_pt[iproc][e] = currently_created_elements[e];
21769 new_received_haloed_shared_boundary_element_pt[iproc].resize(nproc);
21770 new_received_haloed_shared_boundary_element_face_index[iproc].resize(
21774 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21777 const unsigned synchronisation_flag =
21778 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
21780 if (synchronisation_flag != 9999)
21782 std::ostringstream error_message;
21783 error_message <<
"The synchronisation flag was not read, the\n"
21784 <<
"information sent between processor (" << my_rank
21786 <<
"and (" << iproc
21787 <<
")\nis no longer synchronised\n\n";
21788 throw OomphLibError(error_message.str(),
21789 OOMPH_CURRENT_FUNCTION,
21790 OOMPH_EXCEPTION_LOCATION);
21796 const unsigned niproc_jproc_new_received_haloed_shared_boundary_ele =
21797 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
21800 for (
unsigned e = 0;
21801 e < niproc_jproc_new_received_haloed_shared_boundary_ele;
21806 const unsigned ele_index =
21807 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
21810 const unsigned face_index =
21811 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
21814 FiniteElement* shared_ele_pt =
21815 currently_created_elements[ele_index];
21820 new_received_haloed_shared_boundary_element_pt[iproc][jproc]
21821 .push_back(shared_ele_pt);
21823 new_received_haloed_shared_boundary_element_face_index[iproc][jproc]
21824 .push_back(face_index);
21835 if (Print_timings_level_load_balance > 1)
21837 oomph_info <<
"CPU for sending elements to their new processors (load "
21839 << TimingHelpers::timer() -
21840 tt_start_send_elements_to_other_processors
21859 double tt_start_compute_additional_shared_boundaries = 0.0;
21860 if (Print_timings_level_load_balance > 1)
21862 tt_start_compute_additional_shared_boundaries = TimingHelpers::timer();
21868 Vector<Vector<FiniteElement*>> tmp_group1_shared_boundary_element_pt(nproc);
21869 Vector<Vector<unsigned>> tmp_group1_shared_boundary_element_face_index(
21871 Vector<Vector<FiniteElement*>> tmp_group2_shared_boundary_element_pt(nproc);
21872 Vector<Vector<unsigned>> tmp_group2_shared_boundary_element_face_index(
21897 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21899 if (my_rank < iproc)
21902 this->get_shared_boundary_elements_and_face_indexes(
21903 received_elements_pt[iproc],
21904 elements_to_send_pt[iproc],
21905 tmp_group1_shared_boundary_element_pt[iproc],
21906 tmp_group1_shared_boundary_element_face_index[iproc],
21907 tmp_group2_shared_boundary_element_pt[iproc],
21908 tmp_group2_shared_boundary_element_face_index[iproc]);
21911 else if (my_rank > iproc)
21914 this->get_shared_boundary_elements_and_face_indexes(
21915 elements_to_send_pt[iproc],
21916 received_elements_pt[iproc],
21917 tmp_group1_shared_boundary_element_pt[iproc],
21918 tmp_group1_shared_boundary_element_face_index[iproc],
21919 tmp_group2_shared_boundary_element_pt[iproc],
21920 tmp_group2_shared_boundary_element_face_index[iproc]);
21927 if (Print_timings_level_load_balance > 1)
21930 <<
"CPU for computing additional shared boundaries (load balance) [7]: "
21931 << TimingHelpers::timer() -
21932 tt_start_compute_additional_shared_boundaries
21951 double tt_start_sort_shared_boundaries = 0.0;
21952 if (Print_timings_level_load_balance > 1)
21954 tt_start_sort_shared_boundaries = TimingHelpers::timer();
21975 Vector<Vector<FiniteElement*>> new_shared_boundary_element_pt(nproc);
21976 Vector<Vector<unsigned>> new_shared_boundary_element_face_index(nproc);
21977 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21980 if (my_rank < iproc)
21984 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21987 if (jproc != my_rank)
21990 const unsigned nrecvd_haloed_shared_bound_ele_jproc_iproc =
21991 new_received_haloed_shared_boundary_element_pt[jproc][iproc]
21993 for (
unsigned e = 0; e < nrecvd_haloed_shared_bound_ele_jproc_iproc;
21997 FiniteElement* ele_pt =
21998 new_received_haloed_shared_boundary_element_pt[jproc][iproc][e];
22000 const unsigned face_index =
22001 new_received_haloed_shared_boundary_element_face_index[jproc]
22006 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
22007 new_shared_boundary_element_face_index[iproc].push_back(
22018 const unsigned nlocal_haloed_shared_bound_ele_iproc_my_rank =
22019 new_local_halo_shared_boundary_element_pt[iproc][my_rank].size();
22020 for (
unsigned e = 0; e < nlocal_haloed_shared_bound_ele_iproc_my_rank;
22024 FiniteElement* ele_pt =
22025 new_local_halo_shared_boundary_element_pt[iproc][my_rank][e];
22027 const unsigned face_index =
22028 new_local_halo_shared_boundary_element_face_index[iproc][my_rank]
22034 if (!ele_pt->is_halo())
22037 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
22038 new_shared_boundary_element_face_index[iproc].push_back(face_index);
22045 const unsigned ntmp_group1_shared_bound_ele_iproc =
22046 tmp_group1_shared_boundary_element_pt[iproc].size();
22047 for (
unsigned e = 0; e < ntmp_group1_shared_bound_ele_iproc; e++)
22050 FiniteElement* ele_pt =
22051 tmp_group1_shared_boundary_element_pt[iproc][e];
22053 const unsigned face_index =
22054 tmp_group1_shared_boundary_element_face_index[iproc][e];
22057 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
22058 new_shared_boundary_element_face_index[iproc].push_back(face_index);
22064 else if (my_rank > iproc)
22072 const unsigned nlocal_haloed_shared_bound_ele_iproc_my_rank =
22073 new_local_halo_shared_boundary_element_pt[iproc][my_rank].size();
22074 for (
unsigned e = 0; e < nlocal_haloed_shared_bound_ele_iproc_my_rank;
22078 FiniteElement* ele_pt =
22079 new_local_halo_shared_boundary_element_pt[iproc][my_rank][e];
22081 const unsigned face_index =
22082 new_local_halo_shared_boundary_element_face_index[iproc][my_rank]
22088 if (!ele_pt->is_halo())
22091 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
22092 new_shared_boundary_element_face_index[iproc].push_back(face_index);
22097 for (
unsigned jproc = 0; jproc < nproc; jproc++)
22100 if (jproc != my_rank)
22104 const unsigned nrecvd_haloed_shared_bound_ele_jproc_iproc =
22105 new_received_haloed_shared_boundary_element_pt[jproc][iproc]
22107 for (
unsigned e = 0; e < nrecvd_haloed_shared_bound_ele_jproc_iproc;
22111 FiniteElement* ele_pt =
22112 new_received_haloed_shared_boundary_element_pt[jproc][iproc][e];
22114 const unsigned face_index =
22115 new_received_haloed_shared_boundary_element_face_index[jproc]
22120 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
22121 new_shared_boundary_element_face_index[iproc].push_back(
22132 const unsigned ntmp_group2_shared_bound_ele_iproc =
22133 tmp_group2_shared_boundary_element_pt[iproc].size();
22134 for (
unsigned e = 0; e < ntmp_group2_shared_bound_ele_iproc; e++)
22137 FiniteElement* ele_pt =
22138 tmp_group2_shared_boundary_element_pt[iproc][e];
22140 const unsigned face_index =
22141 tmp_group2_shared_boundary_element_face_index[iproc][e];
22144 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
22145 new_shared_boundary_element_face_index[iproc].push_back(face_index);
22154 if (Print_timings_level_load_balance > 1)
22156 oomph_info <<
"CPU for sorting shared boundaries (load balance) [8]: "
22157 << TimingHelpers::timer() - tt_start_sort_shared_boundaries
22178 double tt_start_create_new_shared_boundaries = 0.0;
22179 if (Print_timings_level_load_balance > 1)
22181 tt_start_create_new_shared_boundaries = TimingHelpers::timer();
22192 std::set<FiniteElement*> element_in_processor_pt;
22196 unsigned nh_count6 = 0;
22197 for (
unsigned e = 0; e < nelement_before_load_balance; e++)
22200 FiniteElement* ele_pt = backed_up_ele_pt[e];
22202 if (!(ele_pt->is_halo()))
22205 if (target_domain_for_local_non_halo_element[nh_count6++] == my_rank)
22208 element_in_processor_pt.insert(ele_pt);
22217 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22220 if (iproc != my_rank)
22224 const unsigned n_received_ele = received_elements_pt[iproc].size();
22225 for (
unsigned ie = 0; ie < n_received_ele; ie++)
22228 FiniteElement* ele_pt = received_elements_pt[iproc][ie];
22231 element_in_processor_pt.insert(ele_pt);
22240 create_new_shared_boundaries(element_in_processor_pt,
22241 new_shared_boundary_element_pt,
22242 new_shared_boundary_element_face_index);
22245 if (Print_timings_level_load_balance > 1)
22248 <<
"CPU for creating new shared boundaries (load balance) [9]: "
22249 << TimingHelpers::timer() - tt_start_create_new_shared_boundaries
22271 double tt_start_delete_elements = 0.0;
22272 if (Print_timings_level_load_balance > 1)
22274 tt_start_delete_elements = TimingHelpers::timer();
22285 this->Halo_node_pt.clear();
22286 this->Root_halo_element_pt.clear();
22288 this->Haloed_node_pt.clear();
22289 this->Root_haloed_element_pt.clear();
22292 const unsigned nnodes = this->nnode();
22293 for (
unsigned j = 0; j < nnodes; j++)
22295 this->node_pt(j)->set_obsolete();
22299 this->flush_element_storage();
22302 this->delete_all_external_storage();
22305 this->External_halo_node_pt.clear();
22306 this->External_halo_element_pt.clear();
22308 this->External_haloed_node_pt.clear();
22309 this->External_haloed_element_pt.clear();
22312 Vector<FiniteElement*> deleted_elements;
22315 unsigned nh_count7 = 0;
22316 for (
unsigned e = 0; e < nelement_before_load_balance; e++)
22318 FiniteElement* ele_pt = backed_up_ele_pt[e];
22320 if (!(ele_pt->is_halo()))
22322 if (target_domain_for_local_non_halo_element[nh_count7++] == my_rank)
22325 this->add_element_pt(ele_pt);
22327 const unsigned nele_nodes = ele_pt->nnode();
22329 for (
unsigned j = 0; j < nele_nodes; j++)
22332 ele_pt->node_pt(j)->set_non_obsolete();
22339 deleted_elements.push_back(ele_pt);
22349 deleted_elements.push_back(ele_pt);
22358 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22360 if (iproc != my_rank)
22364 const unsigned nreceived_ele = received_elements_pt[iproc].size();
22365 for (
unsigned ie = 0; ie < nreceived_ele; ie++)
22368 FiniteElement* ele_pt = received_elements_pt[iproc][ie];
22370 this->add_element_pt(ele_pt);
22372 const unsigned nele_nodes = ele_pt->nnode();
22374 for (
unsigned j = 0; j < nele_nodes; j++)
22377 ele_pt->node_pt(j)->set_non_obsolete();
22387 this->prune_dead_nodes();
22390 if (Print_timings_level_load_balance > 1)
22392 oomph_info <<
"CPU for deleting elements no longer belonging to this "
22393 "processor (load balance) [10]: "
22394 << TimingHelpers::timer() - tt_start_delete_elements
22412 double tt_start_re_etablish_halo_ed_info = 0.0;
22413 if (Print_timings_level_load_balance > 1)
22415 tt_start_re_etablish_halo_ed_info = TimingHelpers::timer();
22422 this->sort_nodes_on_shared_boundaries();
22429 const unsigned tmp_nboundary = this->nboundary();
22430 Vector<unsigned> ntmp_boundary_elements(tmp_nboundary);
22433 Vector<Vector<unsigned>> ntmp_boundary_elements_in_region(tmp_nboundary);
22435 const unsigned n_regions = this->nregion();
22438 for (
unsigned ib = 0; ib < tmp_nboundary; ib++)
22441 ntmp_boundary_elements[ib] = this->nboundary_element(ib);
22444 ntmp_boundary_elements_in_region[ib].resize(n_regions);
22447 for (
unsigned rr = 0; rr < n_regions; rr++)
22450 const unsigned region_id =
22451 static_cast<unsigned>(this->region_attribute(rr));
22456 ntmp_boundary_elements_in_region[ib][rr] =
22457 this->nboundary_element_in_region(ib, region_id);
22464 this->reset_halo_haloed_scheme();
22467 const unsigned nelement_after_load_balance = this->nelement();
22471 this->reset_boundary_element_info(ntmp_boundary_elements,
22472 ntmp_boundary_elements_in_region,
22498 for (
unsigned b = 0; b < tmp_nboundary; b++)
22500 if (this->boundary_geom_object_pt(b) != 0)
22503 this->flush_boundary_segment_node(b);
22506 Vector<Vector<Node*>> dummy_segment_node_pt;
22509 get_boundary_segment_nodes_helper(b, dummy_segment_node_pt);
22512 const unsigned nsegments = dummy_segment_node_pt.size();
22516 this->set_nboundary_segment_node(b, nsegments);
22522 if (Print_timings_level_load_balance > 1)
22525 <<
"CPU for re-establishing halo(ed) information (load balance) [11]: "
22526 << TimingHelpers::timer() - tt_start_re_etablish_halo_ed_info
22537 if (Print_timings_level_load_balance > 1)
22539 oomph_info <<
"CPU for load balance [n_ele_before="
22540 << nelement_before_load_balance
22541 <<
", n_ele_after=" << nelement_after_load_balance <<
"]: "
22542 << TimingHelpers::timer() - t_start_overall_load_balance
22546 oomph_info <<
"Load balance (unstructured mesh) [END]" << std::endl;
22554 template<
class ELEMENT>
22557 const Vector<FiniteElement*>& first_element_pt,
22558 const Vector<FiniteElement*>& second_element_pt,
22559 Vector<FiniteElement*>& first_shared_boundary_element_pt,
22560 Vector<unsigned>& first_shared_boundary_element_face_index,
22561 Vector<FiniteElement*>& second_shared_boundary_element_pt,
22562 Vector<unsigned>& second_shared_boundary_element_face_index)
22570 const unsigned nfirst_element = first_element_pt.size();
22572 for (
unsigned ef = 0; ef < nfirst_element; ef++)
22575 FiniteElement* fele_pt = first_element_pt[ef];
22577 bool first_ele_is_halo =
false;
22578 if (fele_pt->is_halo())
22580 first_ele_is_halo =
true;
22583 for (
unsigned ifface = 0; ifface < 3; ifface++)
22585 Vector<Node*> first_face(2);
22588 first_face[0] = fele_pt->node_pt(1);
22589 first_face[1] = fele_pt->node_pt(2);
22591 else if (ifface == 1)
22593 first_face[0] = fele_pt->node_pt(2);
22594 first_face[1] = fele_pt->node_pt(0);
22596 else if (ifface == 2)
22598 first_face[0] = fele_pt->node_pt(0);
22599 first_face[1] = fele_pt->node_pt(1);
22606 const unsigned nsecond_element = second_element_pt.size();
22608 for (
unsigned es = 0; es < nsecond_element; es++)
22611 FiniteElement* sele_pt = second_element_pt[es];
22613 bool second_ele_is_halo =
false;
22614 if (sele_pt->is_halo())
22616 second_ele_is_halo =
true;
22623 if (!(first_ele_is_halo && second_ele_is_halo))
22626 for (
unsigned isface = 0; isface < 3; isface++)
22628 Vector<Node*> second_face(2);
22631 second_face[0] = sele_pt->node_pt(1);
22632 second_face[1] = sele_pt->node_pt(2);
22634 else if (isface == 1)
22636 second_face[0] = sele_pt->node_pt(2);
22637 second_face[1] = sele_pt->node_pt(0);
22639 else if (isface == 2)
22641 second_face[0] = sele_pt->node_pt(0);
22642 second_face[1] = sele_pt->node_pt(1);
22647 if (first_face[0] == second_face[0] &&
22648 first_face[1] == second_face[1])
22651 first_shared_boundary_element_pt.push_back(fele_pt);
22653 first_shared_boundary_element_face_index.push_back(ifface);
22656 second_shared_boundary_element_pt.push_back(sele_pt);
22658 second_shared_boundary_element_face_index.push_back(isface);
22666 es = nsecond_element;
22669 else if (first_face[0] == second_face[1] &&
22670 first_face[1] == second_face[0])
22673 first_shared_boundary_element_pt.push_back(fele_pt);
22675 first_shared_boundary_element_face_index.push_back(ifface);
22678 second_shared_boundary_element_pt.push_back(sele_pt);
22680 second_shared_boundary_element_face_index.push_back(isface);
22688 es = nsecond_element;
22707 template<
class ELEMENT>
22709 std::set<FiniteElement*>& element_in_processor_pt,
22710 Vector<Vector<FiniteElement*>>& new_shared_boundary_element_pt,
22711 Vector<Vector<unsigned>>& new_shared_boundary_element_face_index)
22714 const unsigned nproc = this->communicator_pt()->nproc();
22716 const unsigned my_rank = this->communicator_pt()->my_rank();
22726 double tt_start_get_edges_from_shd_bnd_face_ele = 0.0;
22727 if (Print_timings_level_load_balance > 2)
22729 tt_start_get_edges_from_shd_bnd_face_ele = TimingHelpers::timer();
22733 Vector<Vector<FiniteElement*>> tmp_unsorted_face_ele_pt(nproc);
22735 Vector<Vector<FiniteElement*>> tmp_unsorted_ele_pt(nproc);
22738 Vector<Vector<int>> tmp_unsorted_face_index_ele(nproc);
22742 std::map<std::pair<Node*, Node*>,
unsigned> elements_edges_on_boundary;
22745 this->get_element_edges_on_boundary(elements_edges_on_boundary);
22748 std::map<std::pair<Node*, Node*>,
bool> overlapped_edge;
22754 Vector<Vector<int>> tmp_edge_boundary(nproc);
22758 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22761 if (iproc != my_rank)
22765 const unsigned n_shared_bound_ele =
22766 new_shared_boundary_element_pt[iproc].size();
22770 Vector<std::pair<Node*, Node*>> done_faces;
22773 unsigned nrepeated_faces = 0;
22777 for (
unsigned iele = 0; iele < n_shared_bound_ele; iele++)
22780 FiniteElement* bulk_ele_pt =
22781 new_shared_boundary_element_pt[iproc][iele];
22784 int face_index =
static_cast<int>(
22785 new_shared_boundary_element_face_index[iproc][iele]);
22788 FiniteElement* tmp_ele_pt =
22789 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
22793 bool done_face =
false;
22797 const unsigned nnode_face_ele = tmp_ele_pt->nnode();
22798 Node* first_face_node_pt = tmp_ele_pt->node_pt(0);
22799 Node* last_face_node_pt = tmp_ele_pt->node_pt(nnode_face_ele - 1);
22802 const unsigned ndone_faces = done_faces.size();
22804 for (
unsigned n = 0; n < ndone_faces; n++)
22806 Node* first_done_face_node_pt = done_faces[n].first;
22807 Node* second_done_face_node_pt = done_faces[n].second;
22808 if (first_face_node_pt == first_done_face_node_pt &&
22809 last_face_node_pt == second_done_face_node_pt)
22816 else if (first_face_node_pt == second_done_face_node_pt &&
22817 last_face_node_pt == first_done_face_node_pt)
22830 tmp_unsorted_face_ele_pt[iproc].push_back(tmp_ele_pt);
22832 tmp_unsorted_ele_pt[iproc].push_back(bulk_ele_pt);
22834 tmp_unsorted_face_index_ele[iproc].push_back(face_index);
22836 std::pair<Node*, Node*> tmp_edge =
22837 std::make_pair(first_face_node_pt, last_face_node_pt);
22839 done_faces.push_back(tmp_edge);
22843 int edge_boundary_id = -1;
22844 std::map<std::pair<Node*, Node*>,
unsigned>::iterator it;
22845 it = elements_edges_on_boundary.find(tmp_edge);
22848 if (it != elements_edges_on_boundary.end())
22852 edge_boundary_id = (*it).second;
22854 overlapped_edge[tmp_edge] =
true;
22856 std::pair<Node*, Node*> rev_tmp_edge =
22857 std::make_pair(last_face_node_pt, first_face_node_pt);
22859 overlapped_edge[rev_tmp_edge] =
true;
22864 std::pair<Node*, Node*> rtmp_edge =
22865 std::make_pair(last_face_node_pt, first_face_node_pt);
22866 it = elements_edges_on_boundary.find(rtmp_edge);
22867 if (it != elements_edges_on_boundary.end())
22871 edge_boundary_id = (*it).second;
22873 overlapped_edge[rtmp_edge] =
true;
22876 overlapped_edge[tmp_edge] =
true;
22880 tmp_edge_boundary[iproc].push_back(edge_boundary_id);
22896 if (Print_timings_level_load_balance > 2)
22898 oomph_info <<
"CPU for getting edges from shared boundary face elements "
22899 "(load balance) [9.1]: "
22900 << TimingHelpers::timer() -
22901 tt_start_get_edges_from_shd_bnd_face_ele
22922 double tt_start_sort_shared_face_elements = 0.0;
22923 if (Print_timings_level_load_balance > 2)
22925 tt_start_sort_shared_face_elements = TimingHelpers::timer();
22934 Vector<Vector<FiniteElement*>> unsorted_face_ele_pt(nproc);
22936 Vector<Vector<FiniteElement*>> unsorted_ele_pt(nproc);
22939 Vector<Vector<int>> unsorted_face_index_ele(nproc);
22943 Vector<Vector<int>> edge_boundary(nproc);
22949 std::vector<std::vector<bool>> tmp_treat_as_inverted(nproc);
22952 std::vector<std::vector<bool>> treat_as_inverted(nproc);
22958 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22961 if (iproc != my_rank)
22964 const unsigned n_face_ele = tmp_unsorted_face_ele_pt[iproc].size();
22967 Vector<Vector<double>> centroid_vertices(n_face_ele);
22971 tmp_treat_as_inverted[iproc].resize(n_face_ele);
22975 for (
unsigned e = 0; e < n_face_ele; e++)
22978 FiniteElement* face_ele_pt = tmp_unsorted_face_ele_pt[iproc][e];
22980 const unsigned n_node = face_ele_pt->nnode();
22981 Vector<double> bottom_left(2);
22984 Node* node_pt = face_ele_pt->node_pt(0);
22985 bottom_left[0] = node_pt->x(0);
22986 bottom_left[1] = node_pt->x(1);
22988 tmp_treat_as_inverted[iproc][e] =
false;
22991 for (
unsigned n = 1; n < n_node; n++)
22994 Node* node_pt = face_ele_pt->node_pt(n);
22995 if (node_pt->x(1) < bottom_left[1])
22997 bottom_left[0] = node_pt->x(0);
22998 bottom_left[1] = node_pt->x(1);
23001 tmp_treat_as_inverted[iproc][e] =
true;
23003 else if (node_pt->x(1) == bottom_left[1])
23005 if (node_pt->x(0) < bottom_left[0])
23007 bottom_left[0] = node_pt->x(0);
23008 bottom_left[1] = node_pt->x(1);
23011 tmp_treat_as_inverted[iproc][e] =
true;
23018 centroid_vertices[e].resize(2);
23020 centroid_vertices[e][0] = (face_ele_pt->node_pt(0)->x(0) +
23021 face_ele_pt->node_pt(n_node - 1)->x(0)) *
23023 centroid_vertices[e][1] = (face_ele_pt->node_pt(0)->x(1) +
23024 face_ele_pt->node_pt(n_node - 1)->x(1)) *
23030 unsigned n_sorted_bottom_left = 0;
23032 std::vector<bool> done_face(n_face_ele,
false);
23035 while (n_sorted_bottom_left < n_face_ele)
23038 unsigned index = 0;
23039 Vector<double> current_bottom_left(2);
23040 for (
unsigned e = 0; e < n_face_ele; e++)
23046 current_bottom_left[0] = centroid_vertices[e][0];
23047 current_bottom_left[1] = centroid_vertices[e][1];
23057 for (
unsigned e = index + 1; e < n_face_ele; e++)
23062 if (centroid_vertices[e][1] < current_bottom_left[1])
23065 current_bottom_left[0] = centroid_vertices[e][0];
23066 current_bottom_left[1] = centroid_vertices[e][1];
23070 else if (centroid_vertices[e][1] == current_bottom_left[1])
23072 if (centroid_vertices[e][0] < current_bottom_left[0])
23075 current_bottom_left[0] = centroid_vertices[e][0];
23076 current_bottom_left[1] = centroid_vertices[e][1];
23088 unsorted_face_ele_pt[iproc].push_back(
23089 tmp_unsorted_face_ele_pt[iproc][index]);
23091 unsorted_ele_pt[iproc].push_back(tmp_unsorted_ele_pt[iproc][index]);
23093 unsorted_face_index_ele[iproc].push_back(
23094 tmp_unsorted_face_index_ele[iproc][index]);
23096 edge_boundary[iproc].push_back(tmp_edge_boundary[iproc][index]);
23098 treat_as_inverted[iproc].push_back(
23099 tmp_treat_as_inverted[iproc][index]);
23102 done_face[index] =
true;
23105 n_sorted_bottom_left++;
23112 const unsigned tmp_n_face_ele = unsorted_face_ele_pt[iproc].size();
23114 if (tmp_n_face_ele != n_face_ele)
23116 std::ostringstream error_stream;
23118 <<
"The number of face elements before sorting them starting\n"
23119 <<
"from their bottom-left vertex is different from the number\n"
23120 <<
"of face elements after the sorting\n"
23121 <<
"N. ele before sorting: (" << n_face_ele <<
")\n"
23122 <<
"N. ele after sorting: (" << tmp_n_face_ele <<
")\n";
23123 throw OomphLibError(
23124 error_stream.str(),
23125 "RefineableTriangleMesh::create_new_shared_boundaries()",
23126 OOMPH_EXCEPTION_LOCATION);
23135 if (Print_timings_level_load_balance > 2)
23137 oomph_info <<
"CPU for sorting shared boundary face elements (load "
23139 << TimingHelpers::timer() - tt_start_sort_shared_face_elements
23161 double tt_start_compute_valency_of_nodes = 0.0;
23162 if (Print_timings_level_load_balance > 2)
23164 tt_start_compute_valency_of_nodes = TimingHelpers::timer();
23168 std::map<Node*, unsigned> global_node_degree;
23171 compute_shared_node_degree_helper(unsorted_face_ele_pt, global_node_degree);
23174 if (Print_timings_level_load_balance > 2)
23177 <<
"CPU for computing the valency of nodes (load balance) [9.3]: "
23178 << TimingHelpers::timer() - tt_start_compute_valency_of_nodes
23196 double tt_start_nodes_on_non_overlapped_shd_bnd = 0.0;
23197 if (Print_timings_level_load_balance > 2)
23199 tt_start_nodes_on_non_overlapped_shd_bnd = TimingHelpers::timer();
23204 std::map<unsigned, std::map<Node*, bool>>
23205 node_on_bnd_not_overlapped_by_shd_bnd;
23208 for (std::map<std::pair<Node*, Node*>,
unsigned>::iterator it_map =
23209 elements_edges_on_boundary.begin();
23210 it_map != elements_edges_on_boundary.end();
23214 std::pair<Node*, Node*> edge_pair = (*it_map).first;
23216 if (!overlapped_edge[edge_pair])
23220 unsigned b = (*it_map).second;
23223 Node* left_node_pt = edge_pair.first;
23224 node_on_bnd_not_overlapped_by_shd_bnd[b][left_node_pt] =
true;
23227 Node* right_node_pt = edge_pair.second;
23228 node_on_bnd_not_overlapped_by_shd_bnd[b][right_node_pt] =
true;
23236 if (Print_timings_level_load_balance > 2)
23238 oomph_info <<
"CPU for computing nodes on non overlapped shared "
23239 "boundaries (load balance) [9.4]: "
23240 << TimingHelpers::timer() -
23241 tt_start_nodes_on_non_overlapped_shd_bnd
23264 double tt_start_join_shd_bnd_face_ele = 0.0;
23265 if (Print_timings_level_load_balance > 2)
23267 tt_start_join_shd_bnd_face_ele = TimingHelpers::timer();
23271 Vector<Vector<Vector<FiniteElement*>>> sorted_face_ele_pt(nproc);
23274 Vector<Vector<Vector<FiniteElement*>>> sorted_ele_pt(nproc);
23278 Vector<Vector<Vector<int>>> sorted_face_index_ele(nproc);
23284 Vector<Vector<int>> edge_boundary_id(nproc);
23288 Vector<Vector<Vector<int>>> sorted_connection_info(nproc);
23293 Vector<Vector<unsigned>> proc_local_shared_boundary_id(nproc);
23297 std::map<unsigned, std::list<Node*>>
23298 local_shd_bnd_id_to_sorted_list_node_pt;
23303 unsigned local_shd_bnd_id = this->Initial_shared_boundary_id;
23308 std::map<FiniteElement*, bool> done_ele;
23311 std::map<FiniteElement*, bool> is_inverted;
23315 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23318 if (iproc != my_rank)
23322 const unsigned nunsorted_face_ele = unsorted_face_ele_pt[iproc].size();
23324 unsigned nsorted_face_ele = 0;
23327 while (nsorted_face_ele < nunsorted_face_ele)
23336 bool found_root_element =
false;
23340 unsigned root_index = 0;
23343 std::list<FiniteElement*> tmp_sorted_face_ele_pt;
23346 std::list<FiniteElement*> tmp_sorted_ele_pt;
23350 std::list<int> tmp_sorted_face_index_ele;
23355 std::list<Node*> tmp_sorted_nodes_pt;
23357 tmp_sorted_nodes_pt.clear();
23360 Node* initial_node_pt = 0;
23361 Node* final_node_pt = 0;
23365 int root_edge_bound_id = -1;
23369 for (
unsigned e = 0; e < nunsorted_face_ele; e++)
23372 FiniteElement* root_ele_pt = unsorted_face_ele_pt[iproc][e];
23374 if (!done_ele[root_ele_pt])
23378 root_edge_bound_id = edge_boundary[iproc][e];
23381 tmp_sorted_face_ele_pt.push_back(root_ele_pt);
23383 tmp_sorted_ele_pt.push_back(unsorted_ele_pt[iproc][e]);
23386 tmp_sorted_face_index_ele.push_back(
23387 unsorted_face_index_ele[iproc][e]);
23390 const unsigned nnodes = root_ele_pt->nnode();
23392 if (!treat_as_inverted[iproc][e])
23394 initial_node_pt = root_ele_pt->node_pt(0);
23395 final_node_pt = root_ele_pt->node_pt(nnodes - 1);
23399 initial_node_pt = root_ele_pt->node_pt(nnodes - 1);
23400 final_node_pt = root_ele_pt->node_pt(0);
23403 tmp_sorted_nodes_pt.push_back(initial_node_pt);
23404 tmp_sorted_nodes_pt.push_back(final_node_pt);
23407 done_ele[root_ele_pt] =
true;
23409 if (!treat_as_inverted[iproc][e])
23412 is_inverted[root_ele_pt] =
false;
23417 is_inverted[root_ele_pt] =
true;
23420 nsorted_face_ele++;
23425 found_root_element =
true;
23435 if (!found_root_element)
23437 std::ostringstream error_stream;
23439 <<
"It was not possible the found the root element\n\n";
23440 throw OomphLibError(error_stream.str(),
23441 OOMPH_CURRENT_FUNCTION,
23442 OOMPH_EXCEPTION_LOCATION);
23450 bool new_element_added =
true;
23460 bool element_added_to_the_left =
false;
23461 bool element_added_to_the_right =
false;
23465 bool connection_to_the_left =
false;
23469 bool connection_to_the_right =
false;
23474 bool current_polyline_has_connections_at_both_ends =
false;
23486 int bound_id_connection_to_the_left = -1;
23487 int bound_id_connection_to_the_right = -1;
23491 const unsigned initial_node_degree =
23492 global_node_degree[initial_node_pt];
23496 const bool called_for_load_balance =
true;
23500 bound_id_connection_to_the_left =
23501 this->check_connections_of_polyline_nodes(
23502 element_in_processor_pt,
23503 root_edge_bound_id,
23505 node_on_bnd_not_overlapped_by_shd_bnd,
23506 tmp_sorted_nodes_pt,
23507 local_shd_bnd_id_to_sorted_list_node_pt,
23508 initial_node_degree,
23510 called_for_load_balance);
23514 if (bound_id_connection_to_the_left != -1)
23516 connection_to_the_left =
true;
23521 const unsigned final_node_degree = global_node_degree[final_node_pt];
23524 bound_id_connection_to_the_right =
23525 this->check_connections_of_polyline_nodes(
23526 element_in_processor_pt,
23527 root_edge_bound_id,
23529 node_on_bnd_not_overlapped_by_shd_bnd,
23530 tmp_sorted_nodes_pt,
23531 local_shd_bnd_id_to_sorted_list_node_pt,
23534 called_for_load_balance);
23538 if (bound_id_connection_to_the_right != -1)
23540 connection_to_the_right =
true;
23545 if (connection_to_the_left && connection_to_the_right)
23547 current_polyline_has_connections_at_both_ends =
true;
23556 while (new_element_added && (nsorted_face_ele < nunsorted_face_ele) &&
23557 !current_polyline_has_connections_at_both_ends)
23563 for (
unsigned e = root_index; e < nunsorted_face_ele; e++)
23566 new_element_added =
false;
23567 element_added_to_the_left =
false;
23568 element_added_to_the_right =
false;
23571 FiniteElement* tmp_ele_pt = unsorted_face_ele_pt[iproc][e];
23573 const int edge_bound_id = edge_boundary[iproc][e];
23577 if (!done_ele[tmp_ele_pt] &&
23578 (edge_bound_id == root_edge_bound_id))
23581 const unsigned nnodes = tmp_ele_pt->nnode();
23584 Node* first_node_pt = 0;
23585 Node* last_node_pt = 0;
23586 if (!treat_as_inverted[iproc][e])
23588 first_node_pt = tmp_ele_pt->node_pt(0);
23589 last_node_pt = tmp_ele_pt->node_pt(nnodes - 1);
23593 first_node_pt = tmp_ele_pt->node_pt(nnodes - 1);
23594 last_node_pt = tmp_ele_pt->node_pt(0);
23600 Node* new_added_node_pt = 0;
23603 if (initial_node_pt == last_node_pt && !connection_to_the_left)
23606 new_added_node_pt = initial_node_pt = first_node_pt;
23608 tmp_sorted_nodes_pt.push_front(first_node_pt);
23611 tmp_sorted_face_ele_pt.push_front(tmp_ele_pt);
23613 tmp_sorted_ele_pt.push_front(unsorted_ele_pt[iproc][e]);
23616 tmp_sorted_face_index_ele.push_front(
23617 unsorted_face_index_ele[iproc][e]);
23618 if (!treat_as_inverted[iproc][e])
23621 is_inverted[tmp_ele_pt] =
false;
23626 is_inverted[tmp_ele_pt] =
true;
23629 new_element_added =
true;
23632 element_added_to_the_left =
true;
23635 else if (initial_node_pt == first_node_pt &&
23636 !connection_to_the_left)
23639 new_added_node_pt = initial_node_pt = last_node_pt;
23641 tmp_sorted_nodes_pt.push_front(last_node_pt);
23644 tmp_sorted_face_ele_pt.push_front(tmp_ele_pt);
23646 tmp_sorted_ele_pt.push_front(unsorted_ele_pt[iproc][e]);
23649 tmp_sorted_face_index_ele.push_front(
23650 unsorted_face_index_ele[iproc][e]);
23651 if (!treat_as_inverted[iproc][e])
23654 is_inverted[tmp_ele_pt] =
true;
23659 is_inverted[tmp_ele_pt] =
false;
23662 new_element_added =
true;
23665 element_added_to_the_left =
true;
23668 else if (final_node_pt == first_node_pt &&
23669 !connection_to_the_right)
23672 new_added_node_pt = final_node_pt = last_node_pt;
23674 tmp_sorted_nodes_pt.push_back(last_node_pt);
23677 tmp_sorted_face_ele_pt.push_back(tmp_ele_pt);
23679 tmp_sorted_ele_pt.push_back(unsorted_ele_pt[iproc][e]);
23682 tmp_sorted_face_index_ele.push_back(
23683 unsorted_face_index_ele[iproc][e]);
23684 if (!treat_as_inverted[iproc][e])
23687 is_inverted[tmp_ele_pt] =
false;
23692 is_inverted[tmp_ele_pt] =
true;
23695 new_element_added =
true;
23698 element_added_to_the_right =
true;
23701 else if (final_node_pt == last_node_pt &&
23702 !connection_to_the_right)
23705 new_added_node_pt = final_node_pt = first_node_pt;
23707 tmp_sorted_nodes_pt.push_back(first_node_pt);
23710 tmp_sorted_face_ele_pt.push_back(tmp_ele_pt);
23712 tmp_sorted_ele_pt.push_back(unsorted_ele_pt[iproc][e]);
23715 tmp_sorted_face_index_ele.push_back(
23716 unsorted_face_index_ele[iproc][e]);
23717 if (!treat_as_inverted[iproc][e])
23720 is_inverted[tmp_ele_pt] =
true;
23725 is_inverted[tmp_ele_pt] =
false;
23728 new_element_added =
true;
23731 element_added_to_the_right =
true;
23735 if (new_element_added)
23738 done_ele[tmp_ele_pt] =
true;
23740 nsorted_face_ele++;
23744 const unsigned new_added_node_degree =
23745 global_node_degree[new_added_node_pt];
23754 if (element_added_to_the_left && !connection_to_the_left)
23757 bound_id_connection_to_the_left =
23758 this->check_connections_of_polyline_nodes(
23759 element_in_processor_pt,
23760 root_edge_bound_id,
23762 node_on_bnd_not_overlapped_by_shd_bnd,
23763 tmp_sorted_nodes_pt,
23764 local_shd_bnd_id_to_sorted_list_node_pt,
23765 new_added_node_degree,
23767 called_for_load_balance);
23771 if (bound_id_connection_to_the_left != -1)
23773 connection_to_the_left =
true;
23783 if (element_added_to_the_right && !connection_to_the_right)
23786 bound_id_connection_to_the_right =
23787 this->check_connections_of_polyline_nodes(
23788 element_in_processor_pt,
23789 root_edge_bound_id,
23791 node_on_bnd_not_overlapped_by_shd_bnd,
23792 tmp_sorted_nodes_pt,
23793 local_shd_bnd_id_to_sorted_list_node_pt,
23794 new_added_node_degree,
23796 called_for_load_balance);
23800 if (bound_id_connection_to_the_right != -1)
23802 connection_to_the_right =
true;
23811 if (connection_to_the_left && connection_to_the_right)
23813 current_polyline_has_connections_at_both_ends =
true;
23837 Vector<FiniteElement*> tmp_vector_sorted_ele_pt;
23839 for (std::list<FiniteElement*>::iterator it =
23840 tmp_sorted_ele_pt.begin();
23841 it != tmp_sorted_ele_pt.end();
23844 tmp_vector_sorted_ele_pt.push_back((*it));
23848 Vector<FiniteElement*> tmp_vector_sorted_face_ele_pt;
23851 for (std::list<FiniteElement*>::iterator it =
23852 tmp_sorted_face_ele_pt.begin();
23853 it != tmp_sorted_face_ele_pt.end();
23856 tmp_vector_sorted_face_ele_pt.push_back((*it));
23860 Vector<int> tmp_vector_sorted_face_index_ele;
23862 for (std::list<int>::iterator it = tmp_sorted_face_index_ele.begin();
23863 it != tmp_sorted_face_index_ele.end();
23866 tmp_vector_sorted_face_index_ele.push_back((*it));
23870 Vector<std::list<Node*>> final_sorted_nodes_pt;
23873 Vector<Vector<FiniteElement*>> final_boundary_element_pt;
23876 Vector<Vector<FiniteElement*>> final_boundary_face_element_pt;
23878 Vector<Vector<int>> final_face_index_element;
23881 Vector<int> final_bound_id_connection_to_the_left;
23884 Vector<int> final_bound_id_connection_to_the_right;
23887 this->break_loops_on_shared_polyline_load_balance_helper(
23889 tmp_sorted_nodes_pt,
23890 tmp_vector_sorted_ele_pt,
23891 tmp_vector_sorted_face_ele_pt,
23892 tmp_vector_sorted_face_index_ele,
23893 bound_id_connection_to_the_left,
23894 bound_id_connection_to_the_right,
23895 final_sorted_nodes_pt,
23896 final_boundary_element_pt,
23897 final_boundary_face_element_pt,
23898 final_face_index_element,
23899 final_bound_id_connection_to_the_left,
23900 final_bound_id_connection_to_the_right);
23903 const unsigned n_final_sorted_nodes = final_sorted_nodes_pt.size();
23906 for (
unsigned i = 0; i < n_final_sorted_nodes; i++)
23910 local_shd_bnd_id_to_sorted_list_node_pt[local_shd_bnd_id] =
23911 final_sorted_nodes_pt[i];
23915 proc_local_shared_boundary_id[iproc].push_back(local_shd_bnd_id);
23920 local_shd_bnd_id++;
23923 sorted_ele_pt[iproc].push_back(final_boundary_element_pt[i]);
23926 sorted_face_ele_pt[iproc].push_back(
23927 final_boundary_face_element_pt[i]);
23930 sorted_face_index_ele[iproc].push_back(final_face_index_element[i]);
23933 edge_boundary_id[iproc].push_back(root_edge_bound_id);
23939 Vector<int> bnd_connections_ids(2);
23940 bnd_connections_ids[0] = final_bound_id_connection_to_the_left[i];
23941 bnd_connections_ids[1] = final_bound_id_connection_to_the_right[i];
23942 sorted_connection_info[iproc].push_back(bnd_connections_ids);
23954 if (Print_timings_level_load_balance > 2)
23956 oomph_info <<
"CPU for joining shared boundary face elements (load "
23958 << TimingHelpers::timer() - tt_start_join_shd_bnd_face_ele
23986 double tt_start_get_new_shared_boundaries_ids = 0.0;
23987 if (Print_timings_level_load_balance > 2)
23989 tt_start_get_new_shared_boundaries_ids = TimingHelpers::timer();
23993 Vector<unsigned> nshared_boundaries_with_processor(nproc);
23995 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23998 if (iproc != my_rank)
24002 nshared_boundaries_with_processor[iproc] =
24003 sorted_face_ele_pt[iproc].size();
24013 const unsigned root_processor = 0;
24016 OomphCommunicator* comm_pt = this->communicator_pt();
24021 Vector<unsigned> flat_unsigned_root_received_data(nproc * nproc);
24024 MPI_Gather(&nshared_boundaries_with_processor[0],
24029 &flat_unsigned_root_received_data[0],
24037 comm_pt->mpi_comm());
24042 Vector<unsigned> flat_unsigned_root_send_receive_data;
24046 unsigned new_initial_shared_boundary_id = 0;
24047 unsigned new_final_shared_boundary_id = 0;
24050 if (my_rank == root_processor)
24054 Vector<Vector<unsigned>> root_nshared_bound_proc_with_proc(nproc);
24057 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24060 root_nshared_bound_proc_with_proc[iproc].resize(nproc);
24063 for (
unsigned jproc = 0; jproc < nproc; jproc++)
24065 root_nshared_bound_proc_with_proc[iproc][jproc] =
24066 flat_unsigned_root_received_data[(iproc * nproc) + jproc];
24075 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24077 for (
unsigned jproc = 0; jproc < iproc; jproc++)
24079 if (root_nshared_bound_proc_with_proc[iproc][jproc] !=
24080 root_nshared_bound_proc_with_proc[jproc][iproc])
24082 std::ostringstream error_stream;
24084 <<
"ROOT PROCESSOR ERROR\n\n"
24085 <<
"The number of shared boundaries between processor (" << iproc
24086 <<
") and (" << jproc <<
") is not the same:\n"
24087 <<
"Shared boundaries of processor (" << iproc
24088 <<
") with processor (" << jproc <<
"): ("
24089 << root_nshared_bound_proc_with_proc[iproc][jproc] <<
")\n"
24090 <<
"Shared boundaries of processor (" << jproc
24091 <<
") with processor (" << iproc <<
"): ("
24092 << root_nshared_bound_proc_with_proc[jproc][iproc] <<
")\n\n";
24093 throw OomphLibError(error_stream.str(),
24094 OOMPH_CURRENT_FUNCTION,
24095 OOMPH_EXCEPTION_LOCATION);
24111 Vector<Vector<unsigned>> start_shared_bound_id_proc_with_proc(nproc);
24114 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24116 start_shared_bound_id_proc_with_proc[iproc].resize(nproc);
24121 unsigned shared_bound_id = this->nboundary();
24124 new_initial_shared_boundary_id = shared_bound_id;
24127 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24129 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
24132 if (root_nshared_bound_proc_with_proc[iproc][jproc] > 0)
24136 start_shared_bound_id_proc_with_proc[iproc][jproc] =
24138 start_shared_bound_id_proc_with_proc[jproc][iproc] =
24143 shared_bound_id += root_nshared_bound_proc_with_proc[iproc][jproc];
24151 new_final_shared_boundary_id = shared_bound_id;
24154 Vector<unsigned> send_start_shared_bound_id_proc_with_proc(nproc * nproc);
24158 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24160 for (
unsigned jproc = 0; jproc < nproc; jproc++)
24164 const unsigned initial_shd_bnd_id =
24165 start_shared_bound_id_proc_with_proc[iproc][jproc];
24166 flat_unsigned_root_send_receive_data.push_back(initial_shd_bnd_id);
24170 const unsigned nshared_bnd_iproc_jproc =
24171 root_nshared_bound_proc_with_proc[iproc][jproc];
24172 flat_unsigned_root_send_receive_data.push_back(
24173 nshared_bnd_iproc_jproc);
24181 flat_unsigned_root_send_receive_data.push_back(
24182 new_initial_shared_boundary_id);
24185 flat_unsigned_root_send_receive_data.push_back(
24186 new_final_shared_boundary_id);
24197 unsigned root_ndata_sent_to_all_proc =
24198 flat_unsigned_root_send_receive_data.size();
24200 MPI_Bcast(&root_ndata_sent_to_all_proc,
24204 comm_pt->mpi_comm());
24207 if (my_rank != root_processor)
24209 flat_unsigned_root_send_receive_data.resize(root_ndata_sent_to_all_proc);
24214 MPI_Bcast(&flat_unsigned_root_send_receive_data[0],
24217 root_ndata_sent_to_all_proc,
24221 comm_pt->mpi_comm());
24225 Vector<Vector<unsigned>> initial_shared_bound_id_proc_with_proc(nproc);
24231 Vector<Vector<unsigned>> nshared_bound_proc_with_proc(nproc);
24233 unsigned iflat_counter = 0;
24235 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24238 initial_shared_bound_id_proc_with_proc[iproc].resize(nproc);
24239 nshared_bound_proc_with_proc[iproc].resize(nproc);
24242 for (
unsigned jproc = 0; jproc < nproc; jproc++)
24246 initial_shared_bound_id_proc_with_proc[iproc][jproc] =
24247 flat_unsigned_root_send_receive_data[iflat_counter++];
24251 nshared_bound_proc_with_proc[iproc][jproc] =
24252 flat_unsigned_root_send_receive_data[iflat_counter++];
24259 new_initial_shared_boundary_id =
24260 flat_unsigned_root_send_receive_data[root_ndata_sent_to_all_proc - 2];
24263 new_final_shared_boundary_id =
24264 flat_unsigned_root_send_receive_data[root_ndata_sent_to_all_proc - 1];
24267 if (Print_timings_level_load_balance > 2)
24270 <<
"CPU for computing new shared boundaries ids (load balance) [9.6]: "
24271 << TimingHelpers::timer() - tt_start_get_new_shared_boundaries_ids
24292 double tt_start_create_new_shared_boundaries_polylines = 0.0;
24293 if (Print_timings_level_load_balance > 2)
24295 tt_start_create_new_shared_boundaries_polylines = TimingHelpers::timer();
24305 this->flush_shared_boundary_polyline_pt();
24306 this->Shared_boundary_polyline_pt.resize(nproc);
24309 this->Shared_boundaries_ids.clear();
24310 this->Shared_boundaries_ids.resize(nproc);
24311 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24313 this->Shared_boundaries_ids[iproc].clear();
24314 this->Shared_boundaries_ids[iproc].resize(nproc);
24318 this->Shared_boundary_from_processors.clear();
24319 this->Shared_boundary_overlaps_internal_boundary.clear();
24320 this->Boundary_was_splitted.clear();
24321 this->Boundary_subpolylines.clear();
24322 this->Boundary_marked_as_shared_boundary.clear();
24325 this->flush_shared_boundary_element();
24326 this->flush_face_index_at_shared_boundary();
24327 this->flush_shared_boundary_node();
24328 this->flush_sorted_shared_boundary_node();
24332 const unsigned old_local_shd_bnd_id = this->Initial_shared_boundary_id;
24335 this->Initial_shared_boundary_id = new_initial_shared_boundary_id;
24336 this->Final_shared_boundary_id = new_final_shared_boundary_id;
24340 Vector<TriangleMeshPolyLine*> unsorted_polylines_pt;
24346 std::map<unsigned, unsigned> local_to_global_shd_bnd_id;
24353 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24359 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
24364 if (iproc == my_rank || jproc == my_rank)
24367 unsigned ref_proc = 0;
24368 if (iproc == my_rank)
24372 else if (jproc == my_rank)
24379 const unsigned nshared_bound_iproc_jproc =
24380 nshared_bound_proc_with_proc[iproc][jproc];
24383 for (
unsigned counter = 0; counter < nshared_bound_iproc_jproc;
24387 const unsigned shd_bnd_id =
24388 initial_shared_bound_id_proc_with_proc[iproc][jproc] + counter;
24391 this->Shared_boundaries_ids[iproc][jproc].push_back(shd_bnd_id);
24392 this->Shared_boundaries_ids[jproc][iproc].push_back(shd_bnd_id);
24396 Vector<unsigned> processors(2);
24397 processors[0] = iproc;
24398 processors[1] = jproc;
24399 this->Shared_boundary_from_processors[shd_bnd_id] = processors;
24404 int root_edge_bound_id = edge_boundary_id[ref_proc][counter];
24407 if (root_edge_bound_id != -1)
24411 this->Shared_boundary_overlaps_internal_boundary[shd_bnd_id] =
24412 static_cast<unsigned>(root_edge_bound_id);
24419 Vector<Node*> node_pt_to_create_shared_polyline;
24424 FiniteElement* first_face_ele_pt =
24425 sorted_face_ele_pt[ref_proc][counter][0];
24428 const unsigned first_face_ele_nnodes = first_face_ele_pt->nnode();
24429 if (!is_inverted[first_face_ele_pt])
24432 Node* first_node_pt = first_face_ele_pt->node_pt(0);
24434 node_pt_to_create_shared_polyline.push_back(first_node_pt);
24436 this->add_shared_boundary_node(shd_bnd_id, first_node_pt);
24441 Node* first_node_pt =
24442 first_face_ele_pt->node_pt(first_face_ele_nnodes - 1);
24444 node_pt_to_create_shared_polyline.push_back(first_node_pt);
24446 this->add_shared_boundary_node(shd_bnd_id, first_node_pt);
24454 const unsigned nshared_boundary_elements =
24455 sorted_face_ele_pt[ref_proc][counter].size();
24459 for (
unsigned ie = 0; ie < nshared_boundary_elements; ie++)
24462 FiniteElement* bulk_ele_pt = sorted_ele_pt[ref_proc][counter][ie];
24466 this->add_shared_boundary_element(shd_bnd_id, bulk_ele_pt);
24470 const int face_index =
24471 sorted_face_index_ele[ref_proc][counter][ie];
24475 this->add_face_index_at_shared_boundary(shd_bnd_id, face_index);
24478 FiniteElement* face_ele_pt =
24479 sorted_face_ele_pt[ref_proc][counter][ie];
24482 const unsigned nnodes = face_ele_pt->nnode();
24483 if (!is_inverted[face_ele_pt])
24487 for (
unsigned n = 1; n < nnodes; n++)
24490 Node* node_pt = face_ele_pt->node_pt(n);
24492 this->add_shared_boundary_node(shd_bnd_id, node_pt);
24498 Node* last_node_pt = face_ele_pt->node_pt(nnodes - 1);
24499 node_pt_to_create_shared_polyline.push_back(last_node_pt);
24505 for (
int n = nnodes - 2; n >= 0; n--)
24508 Node* node_pt = face_ele_pt->node_pt(n);
24510 this->add_shared_boundary_node(shd_bnd_id, node_pt);
24516 Node* last_node_pt = face_ele_pt->node_pt(0);
24517 node_pt_to_create_shared_polyline.push_back(last_node_pt);
24524 const unsigned nnodes_to_create_shared_boundary =
24525 node_pt_to_create_shared_polyline.size();
24528 Vector<Vector<double>> vertices(nnodes_to_create_shared_boundary);
24529 for (
unsigned n = 0; n < nnodes_to_create_shared_boundary; n++)
24531 vertices[n].resize(2);
24533 Node* tmp_node_pt = node_pt_to_create_shared_polyline[n];
24535 vertices[n][0] = tmp_node_pt->x(0);
24536 vertices[n][1] = tmp_node_pt->x(1);
24540 TriangleMeshPolyLine* polyline_pt =
24541 new TriangleMeshPolyLine(vertices, shd_bnd_id);
24544 this->Boundary_curve_section_pt[shd_bnd_id] = polyline_pt;
24548 unsorted_polylines_pt.push_back(polyline_pt);
24551 this->Free_curve_section_pt.insert(polyline_pt);
24557 const unsigned local_shd_bnd_id =
24558 proc_local_shared_boundary_id[ref_proc][counter];
24562 local_to_global_shd_bnd_id[local_shd_bnd_id] = shd_bnd_id;
24569 int tmp_bnd_id_connection_to_the_left =
24570 sorted_connection_info[ref_proc][counter][0];
24572 int tmp_bnd_id_connection_to_the_right =
24573 sorted_connection_info[ref_proc][counter][1];
24577 int bnd_id_connection_to_the_left = -1;
24578 int bnd_id_connection_to_the_right = -1;
24585 if (tmp_bnd_id_connection_to_the_left == -2)
24588 bnd_id_connection_to_the_left = shd_bnd_id;
24592 if (tmp_bnd_id_connection_to_the_left == -3)
24595 bnd_id_connection_to_the_left = -1;
24600 if (tmp_bnd_id_connection_to_the_left >=
24601 static_cast<int>(old_local_shd_bnd_id))
24606 std::map<unsigned, unsigned>::iterator it =
24607 local_to_global_shd_bnd_id.find(
24608 static_cast<unsigned>(tmp_bnd_id_connection_to_the_left));
24611 if (it == local_to_global_shd_bnd_id.end())
24613 std::stringstream error_message;
24615 <<
"The global shared boundary id was not found for\n"
24616 <<
"the local shared boundary shared with processor ("
24617 << ref_proc <<
").\n"
24618 <<
"This processor: (" << my_rank <<
")\n"
24619 <<
"Boundary shared with processor: (" << ref_proc <<
")\n"
24620 <<
"Local shared boundary: ("
24621 << tmp_bnd_id_connection_to_the_left <<
")\n";
24622 throw OomphLibError(error_message.str(),
24623 OOMPH_CURRENT_FUNCTION,
24624 OOMPH_EXCEPTION_LOCATION);
24629 bnd_id_connection_to_the_left =
24630 local_to_global_shd_bnd_id[
static_cast<unsigned>(
24631 tmp_bnd_id_connection_to_the_left)];
24637 bnd_id_connection_to_the_left = tmp_bnd_id_connection_to_the_left;
24646 if (tmp_bnd_id_connection_to_the_right == -2)
24649 bnd_id_connection_to_the_right = shd_bnd_id;
24653 if (tmp_bnd_id_connection_to_the_right == -3)
24656 bnd_id_connection_to_the_right = -1;
24661 if (tmp_bnd_id_connection_to_the_right >=
24662 static_cast<int>(old_local_shd_bnd_id))
24667 std::map<unsigned, unsigned>::iterator it =
24668 local_to_global_shd_bnd_id.find(
24669 static_cast<unsigned>(tmp_bnd_id_connection_to_the_right));
24672 if (it == local_to_global_shd_bnd_id.end())
24674 std::stringstream error_message;
24676 <<
"The global shared boundary id was not found for\n"
24677 <<
"the local shared boundary shared with processor ("
24678 << ref_proc <<
").\n"
24679 <<
"This processor: (" << my_rank <<
")\n"
24680 <<
"Boundary shared with processor: (" << ref_proc <<
")\n"
24681 <<
"Local shared boundary: ("
24682 << tmp_bnd_id_connection_to_the_right <<
")\n";
24683 throw OomphLibError(error_message.str(),
24684 OOMPH_CURRENT_FUNCTION,
24685 OOMPH_EXCEPTION_LOCATION);
24689 bnd_id_connection_to_the_right =
24690 local_to_global_shd_bnd_id[
static_cast<unsigned>(
24691 tmp_bnd_id_connection_to_the_right)];
24697 bnd_id_connection_to_the_right =
24698 tmp_bnd_id_connection_to_the_right;
24704 if (bnd_id_connection_to_the_left != -1)
24707 const unsigned ubnd_id_connection_to_the_left =
24708 static_cast<unsigned>(bnd_id_connection_to_the_left);
24710 polyline_pt->set_initial_vertex_connected();
24712 polyline_pt->initial_vertex_connected_bnd_id() =
24713 ubnd_id_connection_to_the_left;
24715 polyline_pt->initial_vertex_connected_n_chunk() = 0;
24721 if (bnd_id_connection_to_the_right != -1)
24725 const unsigned ubnd_id_connection_to_the_right =
24726 static_cast<unsigned>(bnd_id_connection_to_the_right);
24728 polyline_pt->set_final_vertex_connected();
24730 polyline_pt->final_vertex_connected_bnd_id() =
24731 ubnd_id_connection_to_the_right;
24733 polyline_pt->final_vertex_connected_n_chunk() = 0;
24747 const unsigned nshared_bound_iproc_jproc =
24748 nshared_bound_proc_with_proc[iproc][jproc];
24750 for (
unsigned counter = 0; counter < nshared_bound_iproc_jproc;
24754 const unsigned shd_bnd_id =
24755 initial_shared_bound_id_proc_with_proc[iproc][jproc] + counter;
24758 this->Shared_boundaries_ids[iproc][jproc].push_back(shd_bnd_id);
24759 this->Shared_boundaries_ids[jproc][iproc].push_back(shd_bnd_id);
24763 Vector<unsigned> processors(2);
24764 processors[0] = iproc;
24765 processors[1] = jproc;
24766 this->Shared_boundary_from_processors[shd_bnd_id] = processors;
24777 if (Print_timings_level_load_balance > 2)
24779 oomph_info <<
"CPU for creating new shared boundaries representations "
24780 "(load balance) [9.7]: "
24781 << TimingHelpers::timer() -
24782 tt_start_create_new_shared_boundaries_polylines
24800 double tt_start_create_new_shared_curves = 0.0;
24801 if (Print_timings_level_load_balance > 2)
24803 tt_start_create_new_shared_curves = TimingHelpers::timer();
24808 if (unsorted_polylines_pt.size() > 0)
24812 this->sort_polylines_helper(unsorted_polylines_pt,
24813 this->Shared_boundary_polyline_pt[my_rank]);
24817 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24819 const unsigned nface_ele = unsorted_face_ele_pt[iproc].size();
24820 for (
unsigned e = 0; e < nface_ele; e++)
24822 delete unsorted_face_ele_pt[iproc][e];
24823 unsorted_face_ele_pt[iproc][e] = 0;
24829 if (Print_timings_level_load_balance > 2)
24832 <<
"CPU for creating the new shared curves (load balance) [9.8]: "
24833 << TimingHelpers::timer() - tt_start_create_new_shared_curves
24850 template<
class ELEMENT>
24852 Vector<Vector<FiniteElement*>>& unsorted_face_ele_pt,
24853 std::map<Node*, unsigned>& global_node_degree)
24856 const unsigned nproc = this->communicator_pt()->nproc();
24857 const unsigned my_rank = this->communicator_pt()->my_rank();
24861 Vector<Vector<Node*>> tmp_sorted_shared_node_pt(nproc);
24868 std::map<Node*, Vector<Vector<unsigned>>> node_alias;
24872 Vector<Vector<Vector<unsigned>>> local_adjacency_matrix(nproc);
24876 create_adjacency_matrix_new_shared_edges_helper(unsorted_face_ele_pt,
24877 tmp_sorted_shared_node_pt,
24879 local_adjacency_matrix);
24886 Vector<unsigned> package_unsigned_send_data_to_root;
24892 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24895 package_unsigned_send_data_to_root.push_back(iproc);
24898 const unsigned n_nodes = tmp_sorted_shared_node_pt[iproc].size();
24901 package_unsigned_send_data_to_root.push_back(n_nodes);
24904 for (
unsigned ishd = 0; ishd < n_nodes; ishd++)
24907 Node* shd_node_pt = tmp_sorted_shared_node_pt[iproc][ishd];
24910 Vector<Vector<unsigned>> alias_node_info = node_alias[shd_node_pt];
24913 const unsigned n_alias = alias_node_info.size();
24916 package_unsigned_send_data_to_root.push_back(n_alias);
24919 for (
unsigned i = 0; i < n_alias; i++)
24923 package_unsigned_send_data_to_root.push_back(alias_node_info[i][0]);
24925 package_unsigned_send_data_to_root.push_back(alias_node_info[i][1]);
24927 package_unsigned_send_data_to_root.push_back(alias_node_info[i][2]);
24933 for (
unsigned i = 0; i < n_nodes; i++)
24935 for (
unsigned j = 0; j < n_nodes; j++)
24938 package_unsigned_send_data_to_root.push_back(
24939 local_adjacency_matrix[iproc][i][j]);
24948 const unsigned root_processor = 0;
24951 OomphCommunicator* comm_pt = this->communicator_pt();
24954 unsigned n_unsigned_data_send_to_root =
24955 package_unsigned_send_data_to_root.size();
24958 Vector<int> n_unsigned_data_received_in_root(nproc, 0);
24962 MPI_Gather(&n_unsigned_data_send_to_root,
24966 &n_unsigned_data_received_in_root[0],
24974 comm_pt->mpi_comm());
24977 unsigned n_unsigned_total_data_receive_in_root = 0;
24978 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24981 n_unsigned_total_data_receive_in_root +=
24982 n_unsigned_data_received_in_root[iproc];
24986 Vector<int> root_unsigned_offsets_receive(nproc, 0);
24987 root_unsigned_offsets_receive[0] = 0;
24988 for (
unsigned iproc = 1; iproc < nproc; iproc++)
24992 root_unsigned_offsets_receive[iproc] =
24993 root_unsigned_offsets_receive[iproc - 1] +
24994 n_unsigned_data_received_in_root[iproc - 1];
24998 if (package_unsigned_send_data_to_root.size() == 0)
25000 package_unsigned_send_data_to_root.resize(1);
25004 Vector<unsigned> package_unsigned_data_received_root(
25005 n_unsigned_total_data_receive_in_root);
25006 if (my_rank != root_processor)
25009 if (package_unsigned_data_received_root.size() == 0)
25011 package_unsigned_data_received_root.resize(1);
25016 MPI_Gatherv(&package_unsigned_send_data_to_root[0],
25021 n_unsigned_data_send_to_root,
25025 &package_unsigned_data_received_root[0],
25031 &n_unsigned_data_received_in_root[0],
25034 &root_unsigned_offsets_receive[0],
25041 comm_pt->mpi_comm());
25044 Vector<unsigned> package_unsigned_data_sent_from_root;
25046 Vector<int> n_unsigned_data_sent_from_root(nproc, 0);
25050 if (my_rank == root_processor)
25054 unsigned decode_counter = 0;
25062 Vector<Vector<Vector<Vector<Vector<unsigned>>>>> local_node_alias(nproc);
25064 Vector<Vector<Vector<Vector<unsigned>>>> local_adjacency_matrix(nproc);
25067 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25069 local_node_alias[iproc].resize(nproc);
25073 local_adjacency_matrix[iproc].resize(nproc);
25075 if (n_unsigned_data_received_in_root[iproc] > 0)
25079 for (
unsigned jproc = 0; jproc < nproc; jproc++)
25082 const unsigned read_jproc =
25083 package_unsigned_data_received_root[decode_counter++];
25087 if (read_jproc != jproc)
25089 std::ostringstream error_stream;
25091 <<
"The read processor is different from the jproc, this is\n"
25092 <<
"a synchronisation issue. The data are not read in the\n"
25093 <<
"sameorder as the were packaged\n"
25094 <<
"Read processor: (" << read_jproc <<
")\n"
25095 <<
"Current jproc: (" << jproc <<
")\n\n";
25096 throw OomphLibError(
25097 error_stream.str(),
25098 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25099 OOMPH_EXCEPTION_LOCATION);
25104 const unsigned read_n_shd_nodes_iproc_jproc =
25105 package_unsigned_data_received_root[decode_counter++];
25108 local_node_alias[iproc][jproc].resize(read_n_shd_nodes_iproc_jproc);
25112 for (
unsigned ishd = 0; ishd < read_n_shd_nodes_iproc_jproc; ishd++)
25115 const unsigned read_n_alias_node_iproc_jproc =
25116 package_unsigned_data_received_root[decode_counter++];
25119 local_node_alias[iproc][jproc][ishd].resize(
25120 read_n_alias_node_iproc_jproc);
25122 for (
unsigned ialias = 0; ialias < read_n_alias_node_iproc_jproc;
25127 local_node_alias[iproc][jproc][ishd][ialias].resize(3);
25130 local_node_alias[iproc][jproc][ishd][ialias][0] =
25131 package_unsigned_data_received_root[decode_counter++];
25134 local_node_alias[iproc][jproc][ishd][ialias][1] =
25135 package_unsigned_data_received_root[decode_counter++];
25138 local_node_alias[iproc][jproc][ishd][ialias][2] =
25139 package_unsigned_data_received_root[decode_counter++];
25146 local_adjacency_matrix[iproc][jproc].resize(
25147 read_n_shd_nodes_iproc_jproc);
25149 for (
unsigned i = 0; i < read_n_shd_nodes_iproc_jproc; i++)
25152 local_adjacency_matrix[iproc][jproc][i].resize(
25153 read_n_shd_nodes_iproc_jproc);
25154 for (
unsigned j = 0; j < read_n_shd_nodes_iproc_jproc; j++)
25157 local_adjacency_matrix[iproc][jproc][i][j] =
25158 package_unsigned_data_received_root[decode_counter++];
25170 if (decode_counter != n_unsigned_total_data_receive_in_root)
25172 std::ostringstream error_stream;
25174 <<
"The number of data decoded in root received from others\n"
25175 <<
"processors is different from the total number of data received\n"
25176 <<
"Data decoded: (" << decode_counter <<
")\n"
25177 <<
"Data received: (" << n_unsigned_total_data_receive_in_root
25179 <<
"This is a synchronisation issue so you are probably sending\n"
25180 <<
"more or less info. than the one that is being decoded\n\n";
25181 throw OomphLibError(
25182 error_stream.str(),
25183 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25184 OOMPH_EXCEPTION_LOCATION);
25194 std::map<Vector<unsigned>,
bool> alias_done;
25197 Vector<Vector<Vector<unsigned>>> global_node_alias;
25200 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25202 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25205 const unsigned n_shd_nodes_iproc_jproc =
25206 local_node_alias[iproc][jproc].size();
25209 const unsigned n_shd_nodes_jproc_iproc =
25210 local_node_alias[jproc][iproc].size();
25212 if (n_shd_nodes_iproc_jproc != n_shd_nodes_jproc_iproc)
25214 std::ostringstream error_stream;
25216 <<
"The number of nodes shared between iproc and jproc is\n"
25217 <<
"different from the number of nodes shared between jproc\n"
25219 <<
"Nodes shared between processor (" << iproc <<
") and "
25220 <<
"processor (" << jproc <<
"): (" << n_shd_nodes_iproc_jproc
25222 <<
"Nodes shared between processor (" << jproc <<
") and "
25223 <<
"processor (" << iproc <<
"): (" << n_shd_nodes_jproc_iproc
25225 throw OomphLibError(
25226 error_stream.str(),
25227 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25228 OOMPH_EXCEPTION_LOCATION);
25233 for (
unsigned ishd = 0; ishd < n_shd_nodes_iproc_jproc; ishd++)
25237 const unsigned n_alias_iproc_jproc =
25238 local_node_alias[iproc][jproc][ishd].size();
25239 const unsigned n_alias_jproc_iproc =
25240 local_node_alias[jproc][iproc][ishd].size();
25243 Vector<Vector<unsigned>> node_alias;
25246 bool new_alias_added =
false;
25249 for (
unsigned ialias = 0; ialias < n_alias_iproc_jproc; ialias++)
25252 Vector<unsigned> current_alias =
25253 local_node_alias[iproc][jproc][ishd][ialias];
25255 if (!alias_done[current_alias])
25258 node_alias.push_back(current_alias);
25260 new_alias_added =
true;
25262 alias_done[current_alias] =
true;
25268 for (
unsigned ialias = 0; ialias < n_alias_jproc_iproc; ialias++)
25271 Vector<unsigned> current_alias =
25272 local_node_alias[jproc][iproc][ishd][ialias];
25275 if (!alias_done[current_alias])
25278 node_alias.push_back(current_alias);
25280 new_alias_added =
true;
25282 alias_done[current_alias] =
true;
25287 unsigned counter_alias = 0;
25291 unsigned n_current_alias = node_alias.size();
25292 while (new_alias_added || counter_alias < n_current_alias)
25296 new_alias_added =
false;
25298 Vector<unsigned> current_alias = node_alias[counter_alias];
25301 Vector<Vector<unsigned>> alias_of_current_alias =
25302 local_node_alias[current_alias[0]][current_alias[1]]
25303 [current_alias[2]];
25307 const unsigned n_alias = alias_of_current_alias.size();
25311 for (
unsigned k = 0; k < n_alias; k++)
25314 Vector<unsigned> add_alias = alias_of_current_alias[k];
25317 if (!alias_done[add_alias])
25320 node_alias.push_back(add_alias);
25323 new_alias_added =
true;
25325 alias_done[add_alias] =
true;
25332 Vector<Vector<unsigned>> alias_of_current_alias2 =
25333 local_node_alias[current_alias[1]][current_alias[0]]
25334 [current_alias[2]];
25338 const unsigned n_alias2 = alias_of_current_alias2.size();
25342 for (
unsigned k = 0; k < n_alias2; k++)
25345 Vector<unsigned> add_alias = alias_of_current_alias2[k];
25348 if (!alias_done[add_alias])
25351 node_alias.push_back(add_alias);
25354 new_alias_added =
true;
25356 alias_done[add_alias] =
true;
25367 n_current_alias = node_alias.size();
25373 if (node_alias.size() > 0)
25377 global_node_alias.push_back(node_alias);
25390 const unsigned n_global_shared_nodes = global_node_alias.size();
25393 Vector<Vector<Vector<int>>> local_to_global_shared_node(nproc);
25396 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25399 local_to_global_shared_node[iproc].resize(nproc);
25404 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25407 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25410 const unsigned n_shd_nodes = local_node_alias[iproc][jproc].size();
25413 local_to_global_shared_node[iproc][jproc].resize(n_shd_nodes, -1);
25416 local_to_global_shared_node[jproc][iproc].resize(n_shd_nodes, -1);
25426 for (
unsigned k = 0; k < n_global_shared_nodes; k++)
25429 const unsigned n_alias_global_node = global_node_alias[k].size();
25431 for (
unsigned l = 0; l < n_alias_global_node; l++)
25434 const unsigned iproc = global_node_alias[k][l][0];
25436 const unsigned jproc = global_node_alias[k][l][1];
25438 const unsigned ishd = global_node_alias[k][l][2];
25440 local_to_global_shared_node[iproc][jproc][ishd] = k;
25447 Vector<Vector<unsigned>> global_adjacency_matrix(n_global_shared_nodes);
25449 for (
unsigned k = 0; k < n_global_shared_nodes; k++)
25452 global_adjacency_matrix[k].resize(n_global_shared_nodes, 0);
25459 Vector<unsigned> global_node_degree(n_global_shared_nodes, 0);
25462 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25465 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25468 const unsigned n_shd_nodes = local_node_alias[iproc][jproc].size();
25475 for (
unsigned ishd = 0; ishd < n_shd_nodes; ishd++)
25477 for (
unsigned jshd = ishd + 1; jshd < n_shd_nodes; jshd++)
25480 if (local_adjacency_matrix[iproc][jproc][ishd][jshd] > 0)
25485 const int global_shd_node_left =
25486 local_to_global_shared_node[iproc][jproc][ishd];
25489 const int global_shd_node_right =
25490 local_to_global_shared_node[iproc][jproc][jshd];
25495 if (global_shd_node_left == -1)
25497 std::ostringstream error_stream;
25499 <<
"The local node in processors iproc and jproc has no\n"
25500 <<
"global node assigned\n"
25501 <<
"iproc processor: (" << iproc <<
")\n"
25502 <<
"jproc processor: (" << jproc <<
")\n"
25503 <<
"Local node: (" << ishd <<
")\n\n";
25504 throw OomphLibError(error_stream.str(),
25505 "RefineableTriangleMesh::compute_shared_"
25506 "node_degree_helper()",
25507 OOMPH_EXCEPTION_LOCATION);
25512 if (global_shd_node_right == -1)
25514 std::ostringstream error_stream;
25516 <<
"The local node in processors iproc and jproc has no\n"
25517 <<
"global node assigned\n"
25518 <<
"iproc processor: (" << iproc <<
")\n"
25519 <<
"jproc processor: (" << jproc <<
")\n"
25520 <<
"Local node: (" << jshd <<
")\n\n";
25521 throw OomphLibError(error_stream.str(),
25522 "RefineableTriangleMesh::compute_shared_"
25523 "node_degree_helper()",
25524 OOMPH_EXCEPTION_LOCATION);
25528 const unsigned uleft =
25529 static_cast<unsigned>(global_shd_node_left);
25530 const unsigned uright =
25531 static_cast<unsigned>(global_shd_node_right);
25534 global_adjacency_matrix[uleft][uright]++;
25537 global_adjacency_matrix[uright][uleft]++;
25540 global_node_degree[uleft]++;
25543 global_node_degree[uright]++;
25557 Vector<Vector<Vector<unsigned>>> root_local_node_degree(nproc);
25559 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25561 root_local_node_degree[iproc].resize(nproc);
25565 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25568 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25572 const unsigned n_shd_nodes = local_node_alias[iproc][jproc].size();
25575 root_local_node_degree[iproc][jproc].resize(n_shd_nodes);
25577 root_local_node_degree[jproc][iproc].resize(n_shd_nodes);
25581 for (
unsigned ishd = 0; ishd < n_shd_nodes; ishd++)
25584 const int global_shd_node_id =
25585 local_to_global_shared_node[iproc][jproc][ishd];
25589 if (global_shd_node_id == -1)
25591 std::ostringstream error_stream;
25593 <<
"The local node in processors iproc and jproc has no\n"
25594 <<
"global node assigned\n"
25595 <<
"iproc processor: (" << iproc <<
")\n"
25596 <<
"jproc processor: (" << jproc <<
")\n"
25597 <<
"Local node: (" << ishd <<
")\n\n";
25598 throw OomphLibError(
25599 error_stream.str(),
25600 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25601 OOMPH_EXCEPTION_LOCATION);
25606 const unsigned uglobal_shd_node_id =
25607 static_cast<unsigned>(global_shd_node_id);
25610 const unsigned node_degree =
25611 global_node_degree[uglobal_shd_node_id];
25615 root_local_node_degree[iproc][jproc][ishd] = node_degree;
25617 root_local_node_degree[jproc][iproc][ishd] = node_degree;
25627 package_unsigned_data_sent_from_root.clear();
25631 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25634 unsigned count_n_data_sent_to_iproc = 0;
25635 for (
unsigned jproc = 0; jproc < nproc; jproc++)
25638 if (iproc != jproc)
25641 const unsigned n_shd_nodes =
25642 root_local_node_degree[iproc][jproc].size();
25645 count_n_data_sent_to_iproc += n_shd_nodes;
25648 for (
unsigned ishd = 0; ishd < n_shd_nodes; ishd++)
25650 package_unsigned_data_sent_from_root.push_back(
25651 root_local_node_degree[iproc][jproc][ishd]);
25659 n_unsigned_data_sent_from_root[iproc] = count_n_data_sent_to_iproc;
25666 int n_unsigned_data_received_from_root = 0;
25669 MPI_Scatter(&n_unsigned_data_sent_from_root[0],
25675 &n_unsigned_data_received_from_root,
25682 comm_pt->mpi_comm());
25685 Vector<unsigned> package_unsigned_data_received_from_root(
25686 n_unsigned_data_received_from_root);
25689 Vector<int> root_unsigned_offsets_sent(nproc, 0);
25690 root_unsigned_offsets_sent[0] = 0;
25691 for (
unsigned iproc = 1; iproc < nproc; iproc++)
25694 root_unsigned_offsets_sent[iproc] =
25695 root_unsigned_offsets_sent[iproc - 1] +
25696 n_unsigned_data_sent_from_root[iproc - 1];
25699 if (my_rank != root_processor)
25702 if (package_unsigned_data_sent_from_root.size() == 0)
25704 package_unsigned_data_sent_from_root.resize(1);
25709 if (package_unsigned_data_received_from_root.size() == 0)
25711 package_unsigned_data_received_from_root.resize(1);
25715 MPI_Scatterv(&package_unsigned_data_sent_from_root[0],
25720 &n_unsigned_data_sent_from_root[0],
25724 &root_unsigned_offsets_sent[0],
25727 &package_unsigned_data_received_from_root[0],
25735 n_unsigned_data_received_from_root,
25743 comm_pt->mpi_comm());
25748 std::map<Node*, bool> node_done;
25752 int decode_counter = 0;
25754 Vector<Vector<unsigned>> local_node_degree(nproc);
25756 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25759 if (iproc != my_rank)
25762 const unsigned n_nodes = tmp_sorted_shared_node_pt[iproc].size();
25765 package_unsigned_send_data_to_root.push_back(n_nodes);
25768 for (
unsigned ishd = 0; ishd < n_nodes; ishd++)
25772 const unsigned node_degree =
25773 package_unsigned_data_received_from_root[decode_counter++];
25776 Node* shd_node_pt = tmp_sorted_shared_node_pt[iproc][ishd];
25779 if (!node_done[shd_node_pt])
25782 global_node_degree[shd_node_pt] = node_degree;
25784 node_done[shd_node_pt] =
true;
25791 if (global_node_degree[shd_node_pt] != node_degree)
25793 std::ostringstream error_stream;
25795 <<
"The local node has already assigned a global degree,\n"
25796 <<
"however, a different degree for the same node has been\n"
25797 <<
"read from the data sent from root processor\n"
25798 <<
"iproc processor: (" << iproc <<
")\n"
25799 <<
"Local node: (" << ishd <<
")\n"
25800 <<
"---------------------------------------------------------\n"
25801 <<
"Already assigned degree: ("
25802 << global_node_degree[shd_node_pt] <<
")\n"
25803 <<
"New found degree: (" << node_degree <<
")\n"
25804 <<
"---------------------------------------------------------\n"
25805 <<
"Node coordinates: (" << shd_node_pt->x(0) <<
", "
25806 << shd_node_pt->x(1) <<
")\n\n";
25807 throw OomphLibError(
25808 error_stream.str(),
25809 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25810 OOMPH_EXCEPTION_LOCATION);
25824 if (decode_counter != n_unsigned_data_received_from_root)
25826 std::ostringstream error_stream;
25828 <<
"The number of data decoded received from root processor is\n"
25829 <<
"different from the total number of data received from the root\n"
25831 <<
"Data decoded: (" << decode_counter <<
")\n"
25832 <<
"Data received: (" << n_unsigned_data_received_from_root <<
")\n\n"
25833 <<
"This is a synchronisation issue so you are probably sending\n"
25834 <<
"more or less info. than the one that is being decoded\n\n";
25835 throw OomphLibError(
25836 error_stream.str(),
25837 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25838 OOMPH_EXCEPTION_LOCATION);
25849 template<
class ELEMENT>
25852 Vector<Vector<FiniteElement*>>& unsorted_face_ele_pt,
25853 Vector<Vector<Node*>>& tmp_sorted_shared_node_pt,
25854 std::map<Node*, Vector<Vector<unsigned>>>& node_alias,
25855 Vector<Vector<Vector<unsigned>>>& adjacency_matrix)
25858 const unsigned nproc = this->communicator_pt()->nproc();
25859 const unsigned my_rank = this->communicator_pt()->my_rank();
25868 node_alias.clear();
25871 Vector<std::map<Node*, unsigned>> tmp_node_index(nproc);
25874 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25877 if (iproc != my_rank)
25880 std::map<Node*, bool> done_node;
25885 std::map<std::pair<double, double>, Node*,
classcomp> sorted_nodes_pt;
25888 const unsigned n_unsorted_face_ele = unsorted_face_ele_pt[iproc].size();
25891 for (
unsigned e = 0; e < n_unsorted_face_ele; e++)
25894 FiniteElement* face_ele_pt = unsorted_face_ele_pt[iproc][e];
25896 Node* left_node_pt = face_ele_pt->node_pt(0);
25901 if (!done_node[left_node_pt])
25903 std::pair<double, double> vertex =
25904 std::make_pair(left_node_pt->x(0), left_node_pt->x(1));
25905 sorted_nodes_pt[vertex] = left_node_pt;
25907 done_node[left_node_pt] =
true;
25911 const unsigned n_nodes = face_ele_pt->nnode();
25913 Node* right_node_pt = face_ele_pt->node_pt(n_nodes - 1);
25918 if (!done_node[right_node_pt])
25920 std::pair<double, double> vertex =
25921 std::make_pair(right_node_pt->x(0), right_node_pt->x(1));
25922 sorted_nodes_pt[vertex] = right_node_pt;
25924 done_node[right_node_pt] =
true;
25933 unsigned counter = 0;
25937 for (std::map<std::pair<double, double>, Node*>::iterator it =
25938 sorted_nodes_pt.begin();
25939 it != sorted_nodes_pt.end();
25943 Node* node_pt = (*it).second;
25945 tmp_sorted_shared_node_pt[iproc].push_back(node_pt);
25948 tmp_node_index[iproc][node_pt] = counter;
25951 Vector<unsigned> alias(3);
25953 alias[0] = my_rank;
25957 alias[2] = counter++;
25960 node_alias[node_pt].push_back(alias);
25970 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25973 const unsigned n_shd_nodes = tmp_sorted_shared_node_pt[iproc].size();
25975 adjacency_matrix[iproc].resize(n_shd_nodes);
25976 for (
unsigned i = 0; i < n_shd_nodes; i++)
25979 adjacency_matrix[iproc][i].resize(n_shd_nodes);
25982 for (
unsigned j = 0; j < n_shd_nodes; j++)
25984 adjacency_matrix[iproc][i][j] = 0;
25992 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25995 if (iproc != my_rank)
25998 const unsigned n_unsorted_face_ele = unsorted_face_ele_pt[iproc].size();
26001 for (
unsigned e = 0; e < n_unsorted_face_ele; e++)
26004 FiniteElement* face_ele_pt = unsorted_face_ele_pt[iproc][e];
26006 Node* left_node_pt = face_ele_pt->node_pt(0);
26009 const unsigned n_nodes = face_ele_pt->nnode();
26011 Node* right_node_pt = face_ele_pt->node_pt(n_nodes - 1);
26014 const unsigned left_node_index = tmp_node_index[iproc][left_node_pt];
26015 const unsigned right_node_index =
26016 tmp_node_index[iproc][right_node_pt];
26020 adjacency_matrix[iproc][left_node_index][right_node_index]++;
26022 adjacency_matrix[iproc][right_node_index][left_node_index]++;
26035 template<
class ELEMENT>
26038 const unsigned& shd_bnd_id, Vector<Vector<Node*>>& tmp_segment_nodes)
26041 tmp_segment_nodes.clear();
26048 Vector<FiniteElement*> halo_shared_face_ele_pt;
26051 Vector<FiniteElement*> nonhalo_shared_face_ele_pt;
26055 const unsigned nshared_bound_ele =
26056 this->nshared_boundary_element(shd_bnd_id);
26060 for (
unsigned e = 0; e < nshared_bound_ele; e++)
26063 FiniteElement* bulk_ele_pt =
26064 this->shared_boundary_element_pt(shd_bnd_id, e);
26067 int face_index = this->face_index_at_shared_boundary(shd_bnd_id, e);
26071 FiniteElement* face_ele_pt =
26072 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
26075 if (!bulk_ele_pt->is_halo())
26078 nonhalo_shared_face_ele_pt.push_back(face_ele_pt);
26084 halo_shared_face_ele_pt.push_back(face_ele_pt);
26091 std::map<FiniteElement*, bool> shared_face_done;
26094 const unsigned nnonhalo_face_shared_ele = nonhalo_shared_face_ele_pt.size();
26100 const unsigned nhalo_face_shared_ele = halo_shared_face_ele_pt.size();
26104 if (nshared_bound_ele / 2 != nnonhalo_face_shared_ele)
26106 std::ostringstream error_message;
26108 <<
"The number of shared boundary elements (" << nshared_bound_ele
26109 <<
") is not the double\nof the number of unsorted nonhalo shared "
26110 <<
"face boundary elements (" << nnonhalo_face_shared_ele
26111 <<
")\n for the current boundary (" << shd_bnd_id <<
")\n\n";
26112 throw OomphLibError(
26113 error_message.str(),
26114 "RefineableTriangleMesh::get_shared_boundary_segment_nodes_helper()",
26115 OOMPH_EXCEPTION_LOCATION);
26120 if (nshared_bound_ele / 2 != nhalo_face_shared_ele)
26122 std::ostringstream error_message;
26124 <<
"The number of shared boundary elements (" << nshared_bound_ele
26125 <<
") is not the double\nof the number of unsorted halo shared "
26126 <<
"face boundary elements (" << nhalo_face_shared_ele
26127 <<
")\n for the current boundary (" << shd_bnd_id <<
")\n\n";
26128 throw OomphLibError(
26129 error_message.str(),
26130 "RefineableTriangleMesh::get_shared_boundary_segment_nodes_helper()",
26131 OOMPH_EXCEPTION_LOCATION);
26137 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
26140 FiniteElement* nonhalo_face_ele_pt = nonhalo_shared_face_ele_pt[inh];
26143 const unsigned nnodes_nh = nonhalo_face_ele_pt->nnode();
26145 Node* nh_first_node_pt = nonhalo_face_ele_pt->node_pt(0);
26146 Node* nh_last_node_pt = nonhalo_face_ele_pt->node_pt(nnodes_nh - 1);
26150 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
26153 FiniteElement* halo_face_ele_pt = halo_shared_face_ele_pt[ih];
26156 if (!shared_face_done[halo_face_ele_pt])
26159 const unsigned nnodes_h = halo_face_ele_pt->nnode();
26161 Node* h_first_node_pt = halo_face_ele_pt->node_pt(0);
26162 Node* h_last_node_pt = halo_face_ele_pt->node_pt(nnodes_h - 1);
26166 if (nh_first_node_pt == h_first_node_pt &&
26167 nh_last_node_pt == h_last_node_pt)
26170 shared_face_done[nonhalo_face_ele_pt] =
true;
26171 shared_face_done[halo_face_ele_pt] =
true;
26177 else if (nh_first_node_pt == h_last_node_pt &&
26178 nh_last_node_pt == h_first_node_pt)
26181 shared_face_done[nonhalo_face_ele_pt] =
true;
26182 shared_face_done[halo_face_ele_pt] =
true;
26197 if ((nnonhalo_face_shared_ele + nhalo_face_shared_ele) !=
26198 shared_face_done.size())
26200 std::ostringstream error_message;
26201 error_message <<
"The number of DONE shared boundary face elements ("
26202 << shared_face_done.size()
26203 <<
") is not the same\n as the sum of"
26204 <<
"the nonhalo face shared boundary elements ("
26205 << nnonhalo_face_shared_ele
26206 <<
")\nand the halo face shared "
26207 <<
"boundary elements (" << nhalo_face_shared_ele
26209 <<
"current boundary (" << shd_bnd_id <<
")\n\n";
26210 throw OomphLibError(
26211 error_message.str(),
26212 "RefineableTriangleMesh::get_shared_boundary_segment_nodes_helper()",
26213 OOMPH_EXCEPTION_LOCATION);
26225 shared_face_done.clear();
26227 unsigned nsorted_face_ele = 0;
26230 std::list<Node*> sorted_nodes;
26233 FiniteElement* root_face_ele_pt = nonhalo_shared_face_ele_pt[0];
26234 nsorted_face_ele++;
26237 shared_face_done[root_face_ele_pt] =
true;
26240 const unsigned nnodes_root = root_face_ele_pt->nnode();
26241 Node* first_node_pt = root_face_ele_pt->node_pt(0);
26242 Node* last_node_pt = root_face_ele_pt->node_pt(nnodes_root - 1);
26245 sorted_nodes.push_back(first_node_pt);
26246 sorted_nodes.push_back(last_node_pt);
26249 while (nsorted_face_ele < nnonhalo_face_shared_ele)
26252 bool node_added =
false;
26256 for (
unsigned iface = 1; iface < nnonhalo_face_shared_ele; iface++)
26258 FiniteElement* tmp_shared_face_ele_pt =
26259 nonhalo_shared_face_ele_pt[iface];
26262 if (!shared_face_done[tmp_shared_face_ele_pt])
26265 const unsigned tmp_nnodes = tmp_shared_face_ele_pt->nnode();
26268 Node* left_node_pt = tmp_shared_face_ele_pt->node_pt(0);
26269 Node* right_node_pt = tmp_shared_face_ele_pt->node_pt(tmp_nnodes - 1);
26271 if (left_node_pt == first_node_pt)
26274 sorted_nodes.push_front(right_node_pt);
26275 first_node_pt = right_node_pt;
26278 else if (left_node_pt == last_node_pt)
26281 sorted_nodes.push_back(right_node_pt);
26282 last_node_pt = right_node_pt;
26285 else if (right_node_pt == first_node_pt)
26288 sorted_nodes.push_front(left_node_pt);
26289 first_node_pt = left_node_pt;
26292 else if (right_node_pt == last_node_pt)
26295 sorted_nodes.push_back(left_node_pt);
26296 last_node_pt = left_node_pt;
26304 shared_face_done[tmp_shared_face_ele_pt] =
true;
26305 nsorted_face_ele++;
26321 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
26323 delete nonhalo_shared_face_ele_pt[inh];
26324 nonhalo_shared_face_ele_pt[inh] = 0;
26329 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
26331 delete halo_shared_face_ele_pt[ih];
26332 halo_shared_face_ele_pt[ih] = 0;
26340 const unsigned n_nodes = sorted_nodes.size();
26343 tmp_segment_nodes.resize(1);
26344 tmp_segment_nodes[0].resize(n_nodes);
26347 unsigned counter = 0;
26350 for (std::list<Node*>::iterator it = sorted_nodes.begin();
26351 it != sorted_nodes.end();
26354 tmp_segment_nodes[0][counter] = (*it);
26365 template<
class ELEMENT>
26369 Vector<Vector<FiniteElement*>>& f_haloed_ele_pt,
26370 FiniteElement* ele_pt)
26373 const unsigned nbound = this->initial_shared_boundary_id();
26376 const unsigned nproc = this->communicator_pt()->nproc();
26381 Vector<unsigned> associated_boundaries;
26382 Vector<unsigned> face_index_on_boundary;
26384 unsigned counter_face_indexes = 0;
26386 for (
unsigned b = 0; b < nbound; b++)
26389 const unsigned nboundary_ele = nboundary_element(b);
26390 for (
unsigned e = 0; e < nboundary_ele; e++)
26392 if (ele_pt == this->boundary_element_pt(b, e))
26395 associated_boundaries.push_back(b);
26397 face_index_on_boundary.push_back(face_index_at_boundary(b, e));
26398 counter_face_indexes++;
26400 if (counter_face_indexes > 2)
26402 std::stringstream error_message;
26404 <<
"A triangular element can not have more than two of its faces "
26405 <<
"on a boundary!!!\n\n";
26406 throw OomphLibError(error_message.str(),
26407 "RefineableTriangleMesh::get_required_"
26408 "elemental_information_helper()",
26409 OOMPH_EXCEPTION_LOCATION);
26413 if (counter_face_indexes == 2)
26427 const unsigned nassociated_boundaries = associated_boundaries.size();
26428 if (nassociated_boundaries > 0)
26430 Flat_packed_unsigneds.push_back(1);
26431 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26432 Flat_packed_unsigneds_string.push_back(
26433 "The element is a boundary element");
26435 Flat_packed_unsigneds.push_back(nassociated_boundaries);
26436 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26437 std::stringstream junk;
26438 junk <<
"The elements is associated to " << nassociated_boundaries
26440 Flat_packed_unsigneds_string.push_back(junk.str());
26447 for (
unsigned i = 0; i < nassociated_boundaries; i++)
26449 unsigned b = associated_boundaries[i];
26450 Flat_packed_unsigneds.push_back(b);
26451 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26452 std::stringstream junk;
26453 junk <<
"Element associated to boundary " << b <<
" of "
26454 << nassociated_boundaries <<
" total associated boundaries";
26455 Flat_packed_unsigneds_string.push_back(junk.str());
26457 unsigned f = face_index_on_boundary[i];
26458 Flat_packed_unsigneds.push_back(f);
26459 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26460 std::stringstream junk2;
26461 junk2 <<
"Face index " << f <<
" for associated boundary " << b;
26462 Flat_packed_unsigneds_string.push_back(junk2.str());
26472 Vector<Vector<unsigned>> associated_boundaries_and_regions;
26473 Vector<unsigned> face_index_on_boundary_and_region;
26476 const unsigned n_regions = this->nregion();
26481 unsigned counter_face_indexes_in_regions = 0;
26483 for (
unsigned b = 0; b < nbound; b++)
26486 for (
unsigned i_reg = 0; i_reg < n_regions; i_reg++)
26489 const unsigned region_id =
26490 static_cast<unsigned>(this->Region_attribute[i_reg]);
26495 const unsigned nele_in_region =
26496 this->nboundary_element_in_region(b, region_id);
26497 for (
unsigned ee = 0; ee < nele_in_region; ee++)
26502 this->boundary_element_in_region_pt(b, region_id, ee))
26506 Vector<unsigned> bound_and_region(2);
26509 bound_and_region[0] = b;
26511 bound_and_region[1] = region_id;
26514 associated_boundaries_and_regions.push_back(bound_and_region);
26516 face_index_on_boundary_and_region.push_back(
26517 this->face_index_at_boundary_in_region(b, region_id, ee));
26521 counter_face_indexes_in_regions++;
26524 if (counter_face_indexes_in_regions > 2)
26526 std::stringstream error_message;
26527 error_message <<
"A triangular element can not have more "
26528 "than two of its\n"
26529 <<
"faces on a boundary!!!\n\n";
26530 throw OomphLibError(error_message.str(),
26531 "RefineableTriangleMesh::get_required_"
26532 "elemental_information_helper()",
26533 OOMPH_EXCEPTION_LOCATION);
26548 const unsigned nassociated_boundaries_and_regions =
26549 associated_boundaries_and_regions.size();
26550 if (nassociated_boundaries_and_regions > 0)
26552 Flat_packed_unsigneds.push_back(1);
26553 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26554 Flat_packed_unsigneds_string.push_back(
26555 "The element is associated to boundaries and regions");
26558 Flat_packed_unsigneds.push_back(nassociated_boundaries_and_regions);
26559 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26560 std::stringstream junk;
26561 junk <<
"The element is associated to "
26562 << nassociated_boundaries_and_regions <<
" boundaries-regions";
26563 Flat_packed_unsigneds_string.push_back(junk.str());
26570 for (
unsigned i = 0; i < nassociated_boundaries_and_regions; i++)
26572 const unsigned b = associated_boundaries_and_regions[i][0];
26573 Flat_packed_unsigneds.push_back(b);
26574 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26575 std::stringstream junk;
26576 junk <<
"Element associated to boundary " << b <<
" of "
26577 << nassociated_boundaries_and_regions
26578 <<
" total associated boundaries-regions";
26579 Flat_packed_unsigneds_string.push_back(junk.str());
26582 const unsigned r = associated_boundaries_and_regions[i][1];
26583 Flat_packed_unsigneds.push_back(r);
26584 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26585 std::stringstream junk2;
26586 junk2 <<
"Element associated to region " << r <<
" of "
26587 << nassociated_boundaries_and_regions
26588 <<
" total associated boundaries-regions";
26589 Flat_packed_unsigneds_string.push_back(junk2.str());
26592 const unsigned f = face_index_on_boundary_and_region[i];
26593 Flat_packed_unsigneds.push_back(f);
26594 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26595 std::stringstream junk3;
26596 junk3 <<
"Face index " << f <<
" for associated boundary-region ("
26597 << b <<
"-" << r <<
")";
26598 Flat_packed_unsigneds_string.push_back(junk3.str());
26604 Flat_packed_unsigneds.push_back(0);
26605 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26606 Flat_packed_unsigneds_string.push_back(
26607 "The element is NOT associated to boundaries and regions");
26613 Flat_packed_unsigneds.push_back(0);
26614 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26615 Flat_packed_unsigneds_string.push_back(
26616 "The element is not associated to any original boundary");
26625 Vector<unsigned> associated_shared_boundaries;
26626 Vector<unsigned> face_index_on_shared_boundary;
26629 Vector<unsigned> my_rank_shared_boundaries_ids;
26630 this->shared_boundaries_in_this_processor(my_rank_shared_boundaries_ids);
26633 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
26635 for (
unsigned i = 0; i < nmy_rank_shd_bnd; i++)
26638 const unsigned sb = my_rank_shared_boundaries_ids[i];
26641 const unsigned nboundary_ele = this->nshared_boundary_element(sb);
26642 for (
unsigned e = 0; e < nboundary_ele; e++)
26644 if (ele_pt == this->shared_boundary_element_pt(sb, e))
26647 associated_shared_boundaries.push_back(sb);
26649 face_index_on_shared_boundary.push_back(
26650 this->face_index_at_shared_boundary(sb, e));
26657 const unsigned nassociated_shared_boundaries =
26658 associated_shared_boundaries.size();
26659 if (nassociated_shared_boundaries > 0)
26661 Flat_packed_unsigneds.push_back(3);
26662 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26663 Flat_packed_unsigneds_string.push_back(
26664 "The element is a shared boundary element");
26666 Flat_packed_unsigneds.push_back(nassociated_shared_boundaries);
26667 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26668 std::stringstream junk;
26669 junk <<
"The elements is associated to " << nassociated_shared_boundaries
26670 <<
"shared boundaries";
26671 Flat_packed_unsigneds_string.push_back(junk.str());
26675 for (
unsigned i = 0; i < nassociated_shared_boundaries; i++)
26677 const unsigned b = associated_shared_boundaries[i];
26678 Flat_packed_unsigneds.push_back(b);
26679 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26680 std::stringstream junk;
26681 junk <<
"Element associated to shared boundary " << b <<
" of "
26682 << nassociated_shared_boundaries <<
" total associated boundaries";
26683 Flat_packed_unsigneds_string.push_back(junk.str());
26686 const unsigned f = face_index_on_shared_boundary[i];
26687 Flat_packed_unsigneds.push_back(f);
26688 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26689 std::stringstream junk2;
26690 junk2 <<
"Face index " << f <<
" for associated shared boundary " << b;
26691 Flat_packed_unsigneds_string.push_back(junk2.str());
26697 Flat_packed_unsigneds.push_back(0);
26698 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26699 Flat_packed_unsigneds_string.push_back(
26700 "The element is not associated to any shared boundary");
26707 Vector<Vector<unsigned>> index_haloed(nproc);
26710 for (
unsigned jproc = 0; jproc < nproc; jproc++)
26713 const unsigned n_haloed_jproc = f_haloed_ele_pt[jproc].size();
26715 for (
unsigned ihd = 0; ihd < n_haloed_jproc; ihd++)
26718 if (ele_pt == f_haloed_ele_pt[jproc][ihd])
26721 index_haloed[jproc].push_back(ihd);
26732 for (
unsigned jproc = 0; jproc < nproc; jproc++)
26735 const unsigned n_index_haloed_jproc = index_haloed[jproc].size();
26736 Flat_packed_unsigneds.push_back(n_index_haloed_jproc);
26737 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26738 Flat_packed_unsigneds_string.push_back(
26739 "The number of haloed indexes the element is with processor jproc");
26741 for (
unsigned ihd = 0; ihd < n_index_haloed_jproc; ihd++)
26743 Flat_packed_unsigneds.push_back(index_haloed[jproc][ihd]);
26744 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26745 Flat_packed_unsigneds_string.push_back(
26746 "The haloed index of the element with jproc");
26757 template<
class ELEMENT>
26760 Vector<Vector<FiniteElement*>>& f_halo_ele_pt,
26761 Vector<Node*>& new_nodes_on_domain,
26765 const unsigned nnew_nodes_on_domain = new_nodes_on_domain.size();
26766 const unsigned new_added_node_index =
26767 this->try_to_add_node_pt_load_balance(new_nodes_on_domain, nod_pt);
26770 if (new_added_node_index == nnew_nodes_on_domain)
26772 Flat_packed_unsigneds.push_back(1);
26774 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26775 std::stringstream junk;
26776 junk <<
"Node needs to be constructed [size="
26777 << Flat_packed_unsigneds.size() <<
"]; last entry: "
26778 << Flat_packed_unsigneds[Flat_packed_unsigneds.size() - 1];
26779 Flat_packed_unsigneds_string.push_back(junk.str());
26785 get_required_nodal_information_load_balance_helper(
26786 f_halo_ele_pt, iproc, nod_pt);
26790 Flat_packed_unsigneds.push_back(0);
26791 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26792 std::stringstream junk;
26793 junk <<
"Node was already added [size=" << Flat_packed_unsigneds.size()
26794 <<
"]; last entry: "
26795 << Flat_packed_unsigneds[Flat_packed_unsigneds.size() - 1];
26797 Flat_packed_unsigneds_string.push_back(junk.str());
26802 Flat_packed_unsigneds.push_back(new_added_node_index);
26803 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26804 Flat_packed_unsigneds_string.push_back(
"new added node index");
26814 template<
class ELEMENT>
26817 Vector<Vector<FiniteElement*>>& f_halo_ele_pt,
26821 unsigned my_rank = this->communicator_pt()->my_rank();
26822 const unsigned nproc = this->communicator_pt()->nproc();
26827 unsigned n_val = nod_pt->nvalue();
26828 Flat_packed_unsigneds.push_back(n_val);
26829 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26830 Flat_packed_unsigneds_string.push_back(
"Number of values");
26833 unsigned n_dim = nod_pt->ndim();
26836 unsigned n_prev = 1;
26837 if (this->Time_stepper_pt != 0)
26840 n_prev = this->Time_stepper_pt->ntstorage();
26846 Vector<unsigned> original_boundaries;
26849 const unsigned n_bnd = this->initial_shared_boundary_id();
26850 for (
unsigned bb = 0; bb < n_bnd; bb++)
26853 if (nod_pt->is_on_boundary(bb))
26855 original_boundaries.push_back(bb);
26859 const unsigned n_original_boundaries = original_boundaries.size();
26861 if (n_original_boundaries > 0)
26864 Flat_packed_unsigneds.push_back(2);
26865 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26866 Flat_packed_unsigneds_string.push_back(
26867 "Node is on the original boundaries");
26870 Flat_packed_unsigneds.push_back(n_original_boundaries);
26871 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26872 std::stringstream junk;
26873 junk <<
"Node is on " << n_original_boundaries <<
" original boundaries";
26874 Flat_packed_unsigneds_string.push_back(junk.str());
26878 for (
unsigned i = 0; i < n_original_boundaries; i++)
26880 Flat_packed_unsigneds.push_back(original_boundaries[i]);
26881 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26882 std::stringstream junk;
26883 junk <<
"Node is on boundary " << original_boundaries[i] <<
" of "
26885 Flat_packed_unsigneds_string.push_back(junk.str());
26888 Vector<double> zeta(1);
26889 nod_pt->get_coordinates_on_boundary(original_boundaries[i], zeta);
26890 Flat_packed_doubles.push_back(zeta[0]);
26896 Flat_packed_unsigneds.push_back(0);
26897 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26898 Flat_packed_unsigneds_string.push_back(
26899 "Node is on any original boundary");
26905 bool node_on_shared_boundary =
false;
26908 const unsigned n_shd_bnd = this->nshared_boundaries(my_rank, iproc);
26909 for (
unsigned bb = 0; bb < n_shd_bnd; bb++)
26912 unsigned i_bnd = this->shared_boundaries_ids(my_rank, iproc, bb);
26914 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
26916 node_on_shared_boundary =
true;
26924 if (node_on_shared_boundary)
26926 Flat_packed_unsigneds.push_back(1);
26927 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26928 Flat_packed_unsigneds_string.push_back(
"Node is on shared boundary");
26932 Vector<unsigned> shd_boundaries;
26934 for (
unsigned bb = 0; bb < n_shd_bnd; bb++)
26937 const unsigned i_bnd = this->shared_boundaries_ids(my_rank, iproc, bb);
26939 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
26941 shd_boundaries.push_back(i_bnd);
26946 const unsigned n_shd_bnd_is_on = shd_boundaries.size();
26948 Flat_packed_unsigneds.push_back(n_shd_bnd_is_on);
26949 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26950 std::stringstream junk;
26951 junk <<
"Node is on " << n_shd_bnd_is_on <<
" shared boundaries";
26952 Flat_packed_unsigneds_string.push_back(junk.str());
26956 for (
unsigned i = 0; i < n_shd_bnd_is_on; i++)
26958 Flat_packed_unsigneds.push_back(shd_boundaries[i]);
26959 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26960 std::stringstream junk;
26961 junk <<
"Node is on boundary " << shd_boundaries[i] <<
" of " << nb;
26962 Flat_packed_unsigneds_string.push_back(junk.str());
26968 unsigned shared_boundary_id = shd_boundaries[0];
26970 const unsigned n_nodes_on_shared_boundary =
26971 nsorted_shared_boundary_node(shared_boundary_id);
26973 unsigned index_node_on_shared_boundary;
26976 bool found_index_node_on_shared_boundary =
false;
26979 for (
unsigned i = 0; i < n_nodes_on_shared_boundary; i++)
26982 Node* shared_node_pt =
26983 sorted_shared_boundary_node_pt(shared_boundary_id, i);
26985 if (shared_node_pt == nod_pt)
26988 index_node_on_shared_boundary = i;
26991 found_index_node_on_shared_boundary =
true;
26999 if (!found_index_node_on_shared_boundary)
27001 std::ostringstream error_message;
27002 error_message <<
"The index of the node on boundary ("
27003 << shared_boundary_id <<
") was not found.\n"
27004 <<
"The node coordinates are (" << nod_pt->x(0) <<
","
27005 << nod_pt->x(1) <<
").\n";
27006 throw OomphLibError(
27007 error_message.str(),
27008 "RefineableTriangleMesh::get_required_nodal_information_helper()",
27009 OOMPH_EXCEPTION_LOCATION);
27013 Flat_packed_unsigneds.push_back(index_node_on_shared_boundary);
27014 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27015 std::stringstream junk2;
27016 junk2 <<
"Node index on boundary " << boundaries[0] <<
" is "
27017 << index_node_on_shared_boundary;
27018 Flat_packed_unsigneds_string.push_back(junk2.str());
27025 Flat_packed_unsigneds.push_back(0);
27026 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27027 Flat_packed_unsigneds_string.push_back(
27028 "Node is not on a shared boundary");
27043 bool node_on_shared_boundary_with_other_processors =
false;
27045 unsigned nshared_boundaries_with_other_processors_have_node = 0;
27049 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27053 if (jproc != iproc)
27056 const unsigned n_jshd_bnd = this->nshared_boundaries(my_rank, jproc);
27058 for (
unsigned bb = 0; bb < n_jshd_bnd; bb++)
27061 const unsigned j_shd_bnd =
27062 this->shared_boundaries_ids(my_rank, jproc, bb);
27064 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
27072 node_on_shared_boundary_with_other_processors =
true;
27075 nshared_boundaries_with_other_processors_have_node++;
27086 if (node_on_shared_boundary_with_other_processors)
27088 Flat_packed_unsigneds.push_back(4);
27089 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27090 Flat_packed_unsigneds_string.push_back(
27091 "Node is on shared boundary no related with the received processor: 4");
27097 Flat_packed_unsigneds.push_back(
27098 nshared_boundaries_with_other_processors_have_node);
27099 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27100 std::stringstream junk;
27101 junk <<
"Number of other shared boundaries that the node is on: "
27102 << nshared_boundaries_with_other_processors_have_node;
27103 Flat_packed_unsigneds_string.push_back(junk.str());
27107 unsigned counter_shd_bnd_with_other_procs_have_node = 0;
27112 Vector<unsigned> other_processor_1;
27113 Vector<unsigned> other_processor_2;
27114 Vector<unsigned> shd_bnd_ids;
27115 Vector<unsigned> indexes;
27117 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27121 if (jproc != iproc)
27125 const unsigned n_jshd_bnd = this->nshared_boundaries(my_rank, jproc);
27126 for (
unsigned bb = 0; bb < n_jshd_bnd; bb++)
27129 const unsigned j_shd_bnd =
27130 this->shared_boundaries_ids(my_rank, jproc, bb);
27132 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
27135 other_processor_1.push_back(my_rank);
27137 other_processor_2.push_back(jproc);
27139 shd_bnd_ids.push_back(j_shd_bnd);
27142 counter_shd_bnd_with_other_procs_have_node++;
27153 const unsigned n_other_processors = other_processor_1.size();
27155 for (
unsigned i = 0; i < n_other_processors; i++)
27158 unsigned shd_bnd_id = shd_bnd_ids[i];
27160 const unsigned n_nodes_on_shd_bnd =
27161 nsorted_shared_boundary_node(shd_bnd_id);
27164 bool found_index_node_on_shared_boundary =
false;
27166 for (
unsigned i = 0; i < n_nodes_on_shd_bnd; i++)
27169 Node* shared_node_pt = sorted_shared_boundary_node_pt(shd_bnd_id, i);
27171 if (shared_node_pt == nod_pt)
27177 indexes.push_back(i);
27180 found_index_node_on_shared_boundary =
true;
27188 if (!found_index_node_on_shared_boundary)
27190 std::ostringstream error_message;
27191 error_message <<
"The index of the node on boundary (" << shd_bnd_id
27192 <<
"), shared by other processors\nwas not found.\n"
27193 <<
"The node coordinates are (" << nod_pt->x(0) <<
","
27194 << nod_pt->x(1) <<
").\n";
27195 throw OomphLibError(
27196 error_message.str(),
27197 "RefineableTriangleMesh::get_required_nodal_information_helper()",
27198 OOMPH_EXCEPTION_LOCATION);
27207 if (counter_shd_bnd_with_other_procs_have_node !=
27208 nshared_boundaries_with_other_processors_have_node)
27210 std::ostringstream error_message;
27211 error_message <<
"The number of shared boundaries where the node is on "
27212 <<
"is different:\n"
27213 <<
"nshared_boundaries_with_other_processors_have_node: ("
27214 << nshared_boundaries_with_other_processors_have_node
27216 <<
"counter_shd_bnd_with_other_procs_have_node: ("
27217 << counter_shd_bnd_with_other_procs_have_node <<
")\n";
27218 throw OomphLibError(
27219 error_message.str(),
27220 "RefineableTriangleMesh::get_required_nodal_information_helper()",
27221 OOMPH_EXCEPTION_LOCATION);
27227 for (
unsigned i = 0; i < n_other_processors; i++)
27229 Flat_packed_unsigneds.push_back(other_processor_1[i]);
27230 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27231 std::stringstream junk1;
27232 junk1 <<
"Processor where the other shared boundary "
27233 <<
"has the node: " << other_processor_1[i];
27234 Flat_packed_unsigneds_string.push_back(junk1.str());
27237 Flat_packed_unsigneds.push_back(other_processor_2[i]);
27238 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27239 std::stringstream junk2;
27240 junk2 <<
"Processor where the other shared boundary "
27241 <<
"has the node: " << other_processor_2[i];
27242 Flat_packed_unsigneds_string.push_back(junk2.str());
27245 Flat_packed_unsigneds.push_back(shd_bnd_ids[i]);
27246 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27247 std::stringstream junk3;
27248 junk3 <<
"Other shared boundary id where the node is on"
27250 Flat_packed_unsigneds_string.push_back(junk3.str());
27253 Flat_packed_unsigneds.push_back(indexes[i]);
27254 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27255 std::stringstream junk4;
27256 junk4 <<
"Node index on other shared boundary " << boundaries[i]
27257 <<
" is " << indexes[i];
27258 Flat_packed_unsigneds_string.push_back(junk4.str());
27266 Flat_packed_unsigneds.push_back(0);
27267 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27268 Flat_packed_unsigneds_string.push_back(
27269 "Node is on any shared boundary with other processors");
27296 Vector<Vector<unsigned>> halo_element_number(nproc);
27298 Vector<Vector<unsigned>> halo_node_number_in_halo_element(nproc);
27301 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27304 const unsigned n_halo_jproc = f_halo_ele_pt[jproc].size();
27306 for (
unsigned jh = 0; jh < n_halo_jproc; jh++)
27308 FiniteElement* halo_ele_pt = f_halo_ele_pt[jproc][jh];
27310 const unsigned n_node = halo_ele_pt->nnode();
27312 for (
unsigned n = 0; n < n_node; n++)
27315 if (nod_pt == halo_ele_pt->node_pt(n))
27317 halo_element_number[jproc].push_back(jh);
27318 halo_node_number_in_halo_element[jproc].push_back(n);
27334 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27338 const unsigned n_jproc_halo_ele_node_is_on =
27339 halo_element_number[jproc].size();
27341 Flat_packed_unsigneds.push_back(n_jproc_halo_ele_node_is_on);
27342 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27343 std::stringstream junk5;
27344 junk5 <<
"Node is on " << n_jproc_halo_ele_node_is_on <<
" halo "
27345 <<
"elements with " << jproc <<
"-th processor";
27346 Flat_packed_unsigneds_string.push_back(junk5.str());
27351 for (
unsigned i = 0; i < n_jproc_halo_ele_node_is_on; i++)
27354 const unsigned halo_element_index = halo_element_number[jproc][i];
27355 Flat_packed_unsigneds.push_back(halo_element_index);
27356 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27357 std::stringstream junk6;
27358 junk6 <<
"Halo element index is (" << halo_element_index
27359 <<
") with processor (" << jproc <<
")";
27360 Flat_packed_unsigneds_string.push_back(junk6.str());
27363 const unsigned node_index = halo_node_number_in_halo_element[jproc][i];
27364 Flat_packed_unsigneds.push_back(node_index);
27365 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27366 std::stringstream junk7;
27367 junk7 <<
"The node index on the halo element index is (" << node_index;
27368 Flat_packed_unsigneds_string.push_back(junk7.str());
27383 bool on_halo_element_with_iproc_processor =
false;
27384 if (halo_element_number[iproc].size() > 0)
27386 on_halo_element_with_iproc_processor =
true;
27390 if (!node_on_shared_boundary && !on_halo_element_with_iproc_processor)
27397 AlgebraicNode* alg_nod_pt =
dynamic_cast<AlgebraicNode*
>(nod_pt);
27398 if (alg_nod_pt != 0)
27401 AlgebraicMesh* alg_mesh_pt =
dynamic_cast<AlgebraicMesh*
>(
this);
27404 unsigned update_id = alg_nod_pt->node_update_fct_id();
27405 Flat_packed_unsigneds.push_back(update_id);
27406 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27407 Flat_packed_unsigneds_string.push_back(
"Alg Node update id");
27411 unsigned n_ref_val = alg_nod_pt->nref_value();
27412 Flat_packed_unsigneds.push_back(n_ref_val);
27413 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27414 Flat_packed_unsigneds_string.push_back(
"Alg Node n ref values");
27416 for (
unsigned i_ref_val = 0; i_ref_val < n_ref_val; i_ref_val++)
27418 Flat_packed_doubles.push_back(alg_nod_pt->ref_value(i_ref_val));
27422 unsigned n_geom_obj = alg_nod_pt->ngeom_object();
27423 Flat_packed_unsigneds.push_back(n_geom_obj);
27424 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27425 Flat_packed_unsigneds_string.push_back(
"Alg Node n geom objects");
27427 for (
unsigned i_geom = 0; i_geom < n_geom_obj; i_geom++)
27429 GeomObject* geom_obj_pt = alg_nod_pt->geom_object_pt(i_geom);
27432 unsigned n_geom_list = alg_mesh_pt->ngeom_object_list_pt();
27435 unsigned found_geom_object = 0;
27436 for (
unsigned i_list = 0; i_list < n_geom_list; i_list++)
27438 if (geom_obj_pt == alg_mesh_pt->geom_object_list_pt(i_list))
27440 found_geom_object = i_list;
27443 Flat_packed_unsigneds.push_back(found_geom_object);
27444 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27445 Flat_packed_unsigneds_string.push_back(
"Found geom object");
27451 SolidNode* solid_nod_pt =
dynamic_cast<SolidNode*
>(nod_pt);
27452 if (solid_nod_pt != 0)
27454 unsigned n_solid_val = solid_nod_pt->variable_position_pt()->nvalue();
27455 for (
unsigned i_val = 0; i_val < n_solid_val; i_val++)
27457 for (
unsigned t = 0; t < n_prev; t++)
27459 Flat_packed_doubles.push_back(
27460 solid_nod_pt->variable_position_pt()->value(t, i_val));
27464 Vector<double> values_solid_node;
27465 solid_nod_pt->add_values_to_vector(values_solid_node);
27466 const unsigned nvalues_solid_node = values_solid_node.size();
27467 Flat_packed_unsigneds.push_back(nvalues_solid_node);
27468 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27469 std::stringstream junk;
27470 junk <<
"Number of values solid node: " << nvalues_solid_node;
27471 Flat_packed_unsigneds_string.push_back(junk.str());
27473 for (
unsigned i = 0; i < nvalues_solid_node; i++)
27475 Flat_packed_doubles.push_back(values_solid_node[i]);
27480 for (
unsigned i_val = 0; i_val < n_val; i_val++)
27482 for (
unsigned t = 0; t < n_prev; t++)
27484 Flat_packed_doubles.push_back(nod_pt->value(t, i_val));
27489 for (
unsigned idim = 0; idim < n_dim; idim++)
27491 for (
unsigned t = 0; t < n_prev; t++)
27493 Flat_packed_doubles.push_back(nod_pt->x(t, idim));
27506 template<
class ELEMENT>
27509 Vector<Vector<FiniteElement*>>& f_haloed_ele_pt,
27510 Vector<Vector<std::map<unsigned, FiniteElement*>>>&
27511 received_old_haloed_element_pt,
27512 Vector<FiniteElement*>& new_elements_on_domain,
27513 Vector<Node*>& new_nodes_on_domain,
27514 Vector<Vector<Vector<std::map<unsigned, Node*>>>>&
27515 other_proc_shd_bnd_node_pt,
27516 Vector<Vector<Vector<unsigned>>>& global_node_names,
27517 std::map<Vector<unsigned>,
unsigned>& node_name_to_global_index,
27518 Vector<Node*>& global_shared_node_pt)
27520 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27521 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27522 <<
" Bool: New element needs to be constructed "
27523 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27527 if (Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++] == 1)
27531 GeneralisedElement* new_el_pt =
new ELEMENT;
27538 FiniteElement* f_el_pt =
dynamic_cast<FiniteElement*
>(new_el_pt);
27541 new_elements_on_domain.push_back(f_el_pt);
27544 this->add_element_load_balance_helper(
27545 iproc, received_old_haloed_element_pt, f_el_pt);
27548 unsigned n_node = f_el_pt->nnode();
27549 for (
unsigned j = 0; j < n_node; j++)
27551 Node* new_nod_pt = 0;
27554 add_received_node_load_balance_helper(new_nod_pt,
27556 received_old_haloed_element_pt,
27557 new_nodes_on_domain,
27558 other_proc_shd_bnd_node_pt,
27563 node_name_to_global_index,
27564 global_shared_node_pt);
27569 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27570 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27571 <<
" Index of existing element "
27572 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27577 Counter_for_flat_packed_unsigneds++;
27589 template<
class ELEMENT>
27591 const unsigned& iproc,
27592 Vector<Vector<std::map<unsigned, FiniteElement*>>>&
27593 received_old_haloed_element_pt,
27594 FiniteElement* ele_pt)
27597 const unsigned nproc = this->communicator_pt()->nproc();
27599 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27600 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27601 <<
" Bool: Element is associated to a boundary "
27602 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27607 const unsigned is_on_original_boundary =
27608 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27609 if (is_on_original_boundary == 1)
27611 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27612 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27613 <<
" How many boundaries are associated with the element "
27614 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27618 const unsigned nassociated_boundaries =
27619 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27622 for (
unsigned b = 0; b < nassociated_boundaries; b++)
27624 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27625 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27626 <<
" Boundary associated to the element "
27627 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27632 const unsigned bnd =
27633 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27635 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27636 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27637 <<
" Face index of the element "
27638 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27643 const unsigned face_index =
27644 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27648 this->Boundary_element_pt[bnd].push_back(ele_pt);
27649 this->Face_index_at_boundary[bnd].push_back(face_index);
27654 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27655 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27656 <<
" Bool: Element is associated to a boundary-region "
27657 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27662 if (Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++] == 1)
27664 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27666 <<
"Rec:" << Counter_for_flat_packed_unsigneds
27667 <<
" How many boundaries-regions are associated with the element "
27668 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27672 const unsigned nassociated_boundaries_and_regions =
27673 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27675 for (
unsigned br = 0; br < nassociated_boundaries_and_regions; br++)
27677 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27678 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27679 <<
" Boundary associated to the element "
27680 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27684 const unsigned bnd =
27685 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27687 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27688 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27689 <<
" Region associated to the element "
27690 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27694 const unsigned region =
27695 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27697 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27698 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27699 <<
" Face index of the element in boundary-region "
27700 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27703 const unsigned face_index =
27704 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27708 this->Boundary_region_element_pt[bnd][region].push_back(ele_pt);
27709 this->Face_index_region_at_boundary[bnd][region].push_back(
27720 if (is_on_original_boundary != 0)
27722 std::ostringstream error_message;
27724 <<
"The current element is not on an original boundary, this should\n"
27725 <<
"be indicated by a zero flag. However, the read value for\n"
27726 <<
"that flag is (" << is_on_original_boundary <<
").\n\n";
27727 throw OomphLibError(
27728 error_message.str(),
27729 "RefineableTriangleMesh::add_element_load_balance_helper()",
27730 OOMPH_EXCEPTION_LOCATION);
27735 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27736 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27737 <<
" Bool: Element is associated to a shared boundary "
27738 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27743 const unsigned is_on_shared_boundary =
27744 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27745 if (is_on_shared_boundary == 3)
27747 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27749 <<
"Rec:" << Counter_for_flat_packed_unsigneds
27750 <<
" How many shared boundaries are associated with the element "
27751 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27756 const unsigned nassociated_shared_boundaries =
27757 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27760 for (
unsigned b = 0; b < nassociated_shared_boundaries; b++)
27762 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27763 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27764 <<
" Shared boundary associated to the element "
27765 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27768 const unsigned bnd =
27769 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27771 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27773 <<
"Rec:" << Counter_for_flat_packed_unsigneds
27774 <<
" Face index of the element associated to the shared boundary "
27775 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27779 const unsigned face_index =
27780 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27782 this->add_shared_boundary_element(bnd, ele_pt);
27783 this->add_face_index_at_shared_boundary(bnd, face_index);
27791 if (is_on_shared_boundary != 0)
27793 std::ostringstream error_message;
27795 <<
"The current element is not on a shared boundary, this should\n"
27796 <<
"be indicated by a zero flag. However, the read value for\n"
27797 <<
"that flag is (" << is_on_shared_boundary <<
").\n\n";
27798 throw OomphLibError(
27799 error_message.str(),
27800 "RefineableTriangleMesh::add_element_load_balance_helper()",
27801 OOMPH_EXCEPTION_LOCATION);
27810 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27812 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27813 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27814 <<
" Bool: Number of haloed indexes of the element with the "
27815 << jproc <<
" processor: "
27816 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27820 const unsigned n_index_haloed_jproc =
27821 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27823 for (
unsigned ihd = 0; ihd < n_index_haloed_jproc; ihd++)
27825 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27826 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27827 <<
" Bool: The haloed element index with the " << jproc
27829 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27832 const unsigned haloed_index =
27833 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27836 received_old_haloed_element_pt[iproc][jproc][haloed_index] = ele_pt;
27846 template<
class ELEMENT>
27849 Vector<Vector<FiniteElement*>>& f_haloed_ele_pt,
27850 Vector<Vector<std::map<unsigned, FiniteElement*>>>&
27851 received_old_haloed_element_pt,
27852 Vector<Node*>& new_nodes_on_domain,
27853 Vector<Vector<Vector<std::map<unsigned, Node*>>>>&
27854 other_proc_shd_bnd_node_pt,
27856 unsigned& node_index,
27857 FiniteElement*
const& new_el_pt,
27858 Vector<Vector<Vector<unsigned>>>& global_node_names,
27859 std::map<Vector<unsigned>,
unsigned>& node_name_to_global_index,
27860 Vector<Node*>& global_shared_node_pt)
27864 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27865 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27866 <<
" Bool: New node needs to be constructed "
27867 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27870 if (Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++] == 1)
27874 construct_new_node_load_balance_helper(new_nod_pt,
27876 received_old_haloed_element_pt,
27877 new_nodes_on_domain,
27878 other_proc_shd_bnd_node_pt,
27883 node_name_to_global_index,
27884 global_shared_node_pt);
27888 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27889 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27890 <<
" Index of existing halo node "
27891 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27897 new_nod_pt = new_nodes_on_domain
27898 [Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++]];
27901 new_el_pt->node_pt(node_index) = new_nod_pt;
27910 template<
class ELEMENT>
27913 Vector<Vector<FiniteElement*>>& f_haloed_ele_pt,
27914 Vector<Vector<std::map<unsigned, FiniteElement*>>>&
27915 received_old_haloed_element_pt,
27916 Vector<Node*>& new_nodes_on_domain,
27917 Vector<Vector<Vector<std::map<unsigned, Node*>>>>&
27918 other_proc_shd_bnd_node_pt,
27920 unsigned& node_index,
27921 FiniteElement*
const& new_el_pt,
27922 Vector<Vector<Vector<unsigned>>>& global_node_names,
27923 std::map<Vector<unsigned>,
unsigned>& node_name_to_global_index,
27924 Vector<Node*>& global_shared_node_pt)
27927 const unsigned nproc = this->communicator_pt()->nproc();
27929 const unsigned my_rank = this->communicator_pt()->my_rank();
27933 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27934 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27935 <<
" Number of values of external halo node "
27936 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27939 unsigned n_val = Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27942 TimeStepper* time_stepper_pt = this->Time_stepper_pt;
27944 unsigned n_prev = time_stepper_pt->ntstorage();
27948 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27949 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27950 <<
" Is the node on an original boundary "
27951 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27956 const unsigned node_on_original_boundaries =
27957 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27960 Vector<unsigned> original_boundaries_node_is_on;
27962 Vector<double> zeta_coordinates;
27964 unsigned n_original_boundaries_node_is_on = 0;
27966 if (node_on_original_boundaries == 2)
27969 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27970 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27971 <<
" Number of boundaries the node is on: "
27972 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27975 n_original_boundaries_node_is_on =
27976 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27979 original_boundaries_node_is_on.resize(n_original_boundaries_node_is_on);
27980 zeta_coordinates.resize(n_original_boundaries_node_is_on);
27982 for (
unsigned i = 0; i < n_original_boundaries_node_is_on; i++)
27985 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27986 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27987 <<
" Node is on boundary "
27988 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27991 original_boundaries_node_is_on[i] =
27992 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27993 zeta_coordinates[i] =
27994 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
28001 if (node_on_original_boundaries != 0)
28003 std::ostringstream error_message;
28005 <<
"The current node is not on an original boundary, this should\n"
28006 <<
"be indicated by a zero flag. However, the read value for\n"
28007 <<
"that flag is (" << node_on_original_boundaries <<
").\n\n";
28008 throw OomphLibError(
28009 error_message.str(),
28010 "RefineableTriangleMesh::construct_new_halo_node_helper()",
28011 OOMPH_EXCEPTION_LOCATION);
28019 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28020 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28021 <<
" Is node on shared boundary? "
28022 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28025 const unsigned is_node_on_shared_boundary =
28026 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28027 if (is_node_on_shared_boundary == 1)
28030 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28031 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28032 <<
" Number of boundaries the node is on: "
28033 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28036 const unsigned n_shd_bnd_node_is_on =
28037 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28038 Vector<unsigned> shd_bnds_node_is_on(n_shd_bnd_node_is_on);
28039 for (
unsigned i = 0; i < n_shd_bnd_node_is_on; i++)
28042 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28043 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28044 <<
" Node is on boundary "
28045 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28048 shd_bnds_node_is_on[i] =
28049 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28053 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28054 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28055 <<
" Index of node on boundary "
28056 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28060 unsigned node_index_on_shared_boundary =
28061 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28064 new_nod_pt = this->sorted_shared_boundary_node_pt(
28065 shd_bnds_node_is_on[0], node_index_on_shared_boundary);
28071 if (is_node_on_shared_boundary != 0)
28073 std::ostringstream error_message;
28075 <<
"The current node is not on a shared boundary, this should\n"
28076 <<
"be indicated by a zero flag. However, the read value for\n"
28077 <<
"that flag is (" << is_node_on_shared_boundary <<
").\n\n";
28078 throw OomphLibError(
28079 error_message.str(),
28080 "RefineableTriangleMesh::construct_new_halo_node_helper()",
28081 OOMPH_EXCEPTION_LOCATION);
28088 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28089 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28090 <<
" Is the node on shared boundaries with other processors "
28091 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28097 const unsigned is_the_node_in_shared_boundaries_with_other_processors =
28098 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28101 Vector<unsigned> other_processor_1;
28102 Vector<unsigned> other_processor_2;
28103 Vector<unsigned> other_shared_boundaries;
28104 Vector<unsigned> other_indexes;
28107 unsigned n_shd_bnd_with_other_procs_have_node = 0;
28110 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
28112 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28113 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28114 <<
" In how many shared boundaries with other "
28115 <<
"processors is the node "
28116 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28121 n_shd_bnd_with_other_procs_have_node =
28122 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28125 other_processor_1.resize(n_shd_bnd_with_other_procs_have_node);
28126 other_processor_2.resize(n_shd_bnd_with_other_procs_have_node);
28127 other_shared_boundaries.resize(n_shd_bnd_with_other_procs_have_node);
28128 other_indexes.resize(n_shd_bnd_with_other_procs_have_node);
28130 for (
unsigned i = 0; i < n_shd_bnd_with_other_procs_have_node; i++)
28132 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28133 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28134 <<
" Processor where the other shared boundary"
28136 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28140 other_processor_1[i] =
28141 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28143 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28144 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28145 <<
" Processor where the other shared boundary"
28147 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28151 other_processor_2[i] =
28152 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28154 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28155 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28156 <<
" Other shared boundary id where the node is on: "
28157 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28162 other_shared_boundaries[i] =
28163 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28165 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28166 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28167 <<
" Node index on the other shared boundary "
28168 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28174 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28182 if (is_the_node_in_shared_boundaries_with_other_processors != 0)
28184 std::ostringstream error_message;
28186 <<
"The current node is not on a shared boundary with\n"
28187 <<
"other processors, this should be indicated by a zero flag.\n"
28188 <<
"However, the read value for that flag is ("
28189 << is_the_node_in_shared_boundaries_with_other_processors <<
").\n\n";
28190 throw OomphLibError(
28191 error_message.str(),
28192 "RefineableTriangleMesh::construct_new_node_load_balance_helper()",
28193 OOMPH_EXCEPTION_LOCATION);
28203 Vector<Vector<unsigned>> halo_element_number(nproc);
28205 Vector<Vector<unsigned>> halo_node_number_in_halo_element(nproc);
28208 for (
unsigned jproc = 0; jproc < nproc; jproc++)
28210 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28211 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28212 <<
" The node is on "
28213 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28214 <<
" halo elements with " << jproc <<
" processor"
28219 const unsigned n_jproc_halo_ele_node_is_on =
28220 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28223 halo_element_number[jproc].resize(n_jproc_halo_ele_node_is_on);
28224 halo_node_number_in_halo_element[jproc].resize(
28225 n_jproc_halo_ele_node_is_on);
28230 for (
unsigned i = 0; i < n_jproc_halo_ele_node_is_on; i++)
28233 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28234 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28235 <<
" The halo element index where the node is on "
28236 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28240 const unsigned halo_ele_index =
28241 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28242 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28243 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28244 <<
" The node index on the halo element where the node "
28246 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28249 const unsigned node_index_on_halo_ele =
28250 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28253 halo_element_number[jproc][i] = halo_ele_index;
28255 halo_node_number_in_halo_element[jproc][i] = node_index_on_halo_ele;
28264 std::set<Node*> set_haloed_node_pt;
28267 Node* haloed_node_pt = 0;
28273 bool on_haloed_element_with_iproc_processor =
false;
28274 if (halo_element_number[my_rank].size() > 0)
28278 on_haloed_element_with_iproc_processor =
true;
28281 const unsigned n_haloed_indexes = halo_element_number[my_rank].size();
28285 for (
unsigned i = 0; i < n_haloed_indexes; i++)
28288 const unsigned haloed_index = halo_element_number[my_rank][i];
28290 const unsigned haloed_node_index =
28291 halo_node_number_in_halo_element[my_rank][i];
28294 FiniteElement* tmp_haloed_ele_pt = f_haloed_ele_pt[iproc][haloed_index];
28296 Node* tmp_haloed_node_pt =
28297 tmp_haloed_ele_pt->node_pt(haloed_node_index);
28300 haloed_node_pt = tmp_haloed_node_pt;
28303 set_haloed_node_pt.insert(tmp_haloed_node_pt);
28306 if (set_haloed_node_pt.size() > 1)
28308 std::ostringstream error_message;
28310 <<
"When adding the " << haloed_node_index <<
" node of the "
28311 << haloed_index <<
"-th haloed element\n"
28312 <<
"in the currrent processor with the " << iproc <<
" processor"
28313 <<
"it was found that\nthe node pointer is different from the other"
28314 <<
"instances of the node.\nIt means we have a repeated node."
28315 <<
"This are the node coordinates of the previous node instances\n"
28316 <<
"The last entry is for the just added node with a different "
28319 for (std::set<Node*>::iterator it = set_haloed_node_pt.begin();
28320 it != set_haloed_node_pt.end();
28323 error_message <<
"Node: (" << (*it)->x(0) <<
", " << (*it)->x(1)
28326 error_message <<
"\n";
28327 throw OomphLibError(
28328 error_message.str(),
28329 "RefineableTriangleMesh::construct_new_node_load_balance_helper()",
28330 OOMPH_EXCEPTION_LOCATION);
28340 bool found_on_haloed_element_with_other_processor =
false;
28343 for (
unsigned jproc = 0; jproc < iproc; jproc++)
28346 if (halo_element_number[jproc].size() > 0)
28349 const unsigned n_halo_indexes = halo_element_number[jproc].size();
28353 for (
unsigned i = 0; i < n_halo_indexes; i++)
28356 const unsigned haloed_index = halo_element_number[jproc][i];
28358 const unsigned haloed_node_index =
28359 halo_node_number_in_halo_element[jproc][i];
28363 std::map<unsigned, FiniteElement*>::iterator it_map =
28364 received_old_haloed_element_pt[jproc][iproc].find(haloed_index);
28366 if (it_map != received_old_haloed_element_pt[jproc][iproc].end())
28371 found_on_haloed_element_with_other_processor =
true;
28374 FiniteElement* tmp_haloed_ele_pt = (*it_map).second;
28376 Node* tmp_haloed_node_pt =
28377 tmp_haloed_ele_pt->node_pt(haloed_node_index);
28380 haloed_node_pt = tmp_haloed_node_pt;
28383 set_haloed_node_pt.insert(tmp_haloed_node_pt);
28386 if (set_haloed_node_pt.size() > 1)
28388 std::ostringstream error_message;
28390 <<
"When adding the " << haloed_node_index <<
" node of the "
28391 << haloed_index <<
"-th haloed element "
28392 <<
"of the " << jproc <<
" processor\nwith the " << iproc
28393 <<
" processor, it was found that\n"
28394 <<
"the node pointer is different from the other\n"
28395 <<
"instances of the node.\nThis means we have a repeated "
28397 <<
"These are the node coordinates of the previous node "
28399 <<
"The last entry is for the just added node with a "
28401 <<
"node pointer\n";
28402 for (std::set<Node*>::iterator it = set_haloed_node_pt.begin();
28403 it != set_haloed_node_pt.end();
28406 error_message <<
"Node: (" << (*it)->x(0) <<
", " << (*it)->x(1)
28409 error_message <<
"\n";
28410 throw OomphLibError(error_message.str(),
28411 "RefineableTriangleMesh::construct_new_node_"
28412 "load_balance_helper()",
28413 OOMPH_EXCEPTION_LOCATION);
28431 if (on_haloed_element_with_iproc_processor ||
28432 found_on_haloed_element_with_other_processor)
28435 new_nod_pt = haloed_node_pt;
28443 if (is_node_on_shared_boundary == 1 ||
28444 (on_haloed_element_with_iproc_processor))
28449 if (node_on_original_boundaries == 2)
28455 for (
unsigned i = 0; i < n_original_boundaries_node_is_on; i++)
28457 add_boundary_node(original_boundaries_node_is_on[i], new_nod_pt);
28459 Vector<double> zeta(1);
28460 zeta[0] = zeta_coordinates[i];
28461 new_nod_pt->set_coordinates_on_boundary(
28462 original_boundaries_node_is_on[i], zeta);
28468 new_nodes_on_domain.push_back(new_nod_pt);
28471 new_el_pt->node_pt(node_index) = new_nod_pt;
28481 bool found_node_in_other_shared_boundaries =
false;
28490 bool build_node_as_boundary_node =
false;
28492 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
28495 build_node_as_boundary_node =
true;
28502 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
28506 Vector<Node*> found_node_pt;
28509 for (
unsigned i = 0; i < n_shd_bnd_with_other_procs_have_node; i++)
28511 unsigned oproc1 = other_processor_1[i];
28512 unsigned oproc2 = other_processor_2[i];
28516 if (oproc1 > oproc2)
28519 oproc1 = other_processor_2[i];
28524 const unsigned shd_bnd_id =
28525 other_shared_boundaries[i] - initial_shd_bnd_id;
28527 const unsigned index = other_indexes[i];
28531 const unsigned n_nodes_on_other_processor =
28532 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].size();
28534 if (n_nodes_on_other_processor > 0)
28538 std::map<unsigned, Node*>::iterator it =
28539 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].find(index);
28543 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].end())
28546 found_node_in_other_shared_boundaries =
true;
28548 Node* tmp_node_pt =
28549 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id][index];
28550 found_node_pt.push_back(tmp_node_pt);
28560 if (found_node_in_other_shared_boundaries)
28563 const unsigned ntimes_node_found = found_node_pt.size();
28564 for (
unsigned j = 1; j < ntimes_node_found; j++)
28566 if (found_node_pt[j - 1] != found_node_pt[j])
28568 std::ostringstream error_message;
28570 <<
"The instances of the node that was found to be on a\n"
28571 <<
"shared boundary with other processors are not the same,\n"
28572 <<
"the coordinates for the nodes are these:\n"
28573 <<
"(" << found_node_pt[j - 1]->x(0) <<
", "
28574 << found_node_pt[j - 1]->x(1) <<
")\n"
28575 <<
"(" << found_node_pt[j]->x(0) <<
", " << found_node_pt[j]->x(1)
28577 <<
"Not be surprised if they are the same since the node is\n"
28578 <<
"repeated!!!\n";
28579 throw OomphLibError(
28580 error_message.str(),
28581 "RefineableTriangleMesh::construct_new_halo_node_helper()",
28582 OOMPH_EXCEPTION_LOCATION);
28593 if (is_node_on_shared_boundary == 1)
28598 if (found_node_pt[0] != new_nod_pt)
28600 std::ostringstream error_message;
28602 <<
"The pointer of the node that was found to be on a\n"
28603 <<
"shared boundary with other processor(s) and the pointer\n"
28604 <<
"of the node on shared boundary with the receiver\n"
28605 <<
"processor (iproc) are not the same. This means we have a\n"
28606 <<
"repeated node)\n"
28607 <<
"The coordinates for the nodes are:\n"
28608 <<
"(" << found_node_pt[0]->x(0) <<
", " << found_node_pt[0]->x(1)
28610 <<
"(" << new_nod_pt->x(0) <<
", " << new_nod_pt->x(1) <<
")\n"
28611 <<
"Not to be surprised if they are the same since the node is\n"
28612 <<
"repeated!!!\n";
28613 throw OomphLibError(
28614 error_message.str(),
28615 "RefineableTriangleMesh::construct_new_halo_node_helper()",
28616 OOMPH_EXCEPTION_LOCATION);
28625 new_nod_pt = found_node_pt[0];
28637 if (is_node_on_shared_boundary != 1 &&
28638 !on_haloed_element_with_iproc_processor)
28652 if (node_on_original_boundaries == 2 || build_node_as_boundary_node)
28658 if (!found_node_in_other_shared_boundaries ||
28659 !found_on_haloed_element_with_other_processor)
28662 if (time_stepper_pt != 0)
28665 new_el_pt->construct_boundary_node(node_index, time_stepper_pt);
28669 new_nod_pt = new_el_pt->construct_boundary_node(node_index);
28677 new_el_pt->node_pt(node_index) = new_nod_pt;
28682 for (
unsigned i = 0; i < n_original_boundaries_node_is_on; i++)
28684 add_boundary_node(original_boundaries_node_is_on[i], new_nod_pt);
28686 Vector<double> zeta(1);
28687 zeta[0] = zeta_coordinates[i];
28688 new_nod_pt->set_coordinates_on_boundary(
28689 original_boundaries_node_is_on[i], zeta);
28699 if (!found_node_in_other_shared_boundaries ||
28700 !found_on_haloed_element_with_other_processor)
28703 if (time_stepper_pt != 0)
28705 new_nod_pt = new_el_pt->construct_node(node_index, time_stepper_pt);
28709 new_nod_pt = new_el_pt->construct_node(node_index);
28716 new_el_pt->node_pt(node_index) = new_nod_pt;
28728 new_nodes_on_domain.push_back(new_nod_pt);
28734 if (!found_node_in_other_shared_boundaries ||
28735 !found_on_haloed_element_with_other_processor)
28738 this->add_node_pt(new_nod_pt);
28743 AlgebraicNode* new_alg_nod_pt =
dynamic_cast<AlgebraicNode*
>(new_nod_pt);
28747 if (new_alg_nod_pt != 0)
28750 AlgebraicMesh* alg_mesh_pt =
dynamic_cast<AlgebraicMesh*
>(
this);
28756 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28757 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28758 <<
" Alg node update id "
28759 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28763 unsigned update_id =
28764 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28766 Vector<double> ref_value;
28770 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28771 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28772 <<
" Alg node # of ref values "
28773 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28776 unsigned n_ref_val =
28777 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28781 ref_value.resize(n_ref_val);
28782 for (
unsigned i_ref = 0; i_ref < n_ref_val; i_ref++)
28785 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
28788 Vector<GeomObject*> geom_object_pt;
28795 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28796 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28797 <<
" Alg node # of geom objects "
28798 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28801 unsigned n_geom_obj =
28802 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28806 geom_object_pt.resize(n_geom_obj);
28807 for (
unsigned i_geom = 0; i_geom < n_geom_obj; i_geom++)
28809 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28810 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28811 <<
" Alg node: geom object index "
28812 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28815 unsigned geom_index =
28816 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28823 geom_object_pt[i_geom] = alg_mesh_pt->geom_object_list_pt(geom_index);
28830 if (!found_node_in_other_shared_boundaries ||
28831 !found_on_haloed_element_with_other_processor)
28835 new_alg_nod_pt->add_node_update_info(
28836 update_id, alg_mesh_pt, geom_object_pt, ref_value);
28839 alg_mesh_pt->update_node_update(new_alg_nod_pt);
28850 if (!found_node_in_other_shared_boundaries ||
28851 !found_on_haloed_element_with_other_processor)
28854 MacroElementNodeUpdateNode* macro_nod_pt =
28855 dynamic_cast<MacroElementNodeUpdateNode*
>(new_nod_pt);
28857 if (macro_nod_pt != 0)
28861 Vector<GeomObject*> geom_object_vector_pt;
28865 MacroElementNodeUpdateMesh* macro_mesh_pt =
28866 dynamic_cast<MacroElementNodeUpdateMesh*
>(
this);
28867 geom_object_vector_pt = macro_mesh_pt->geom_object_vector_pt();
28870 Vector<double> s_in_macro_node_update_element;
28871 new_el_pt->local_coordinate_of_node(node_index,
28872 s_in_macro_node_update_element);
28875 macro_nod_pt->set_node_update_info(
28876 new_el_pt, s_in_macro_node_update_element, geom_object_vector_pt);
28883 unsigned n_new_val = new_nod_pt->nvalue();
28889 if (!found_node_in_other_shared_boundaries ||
28890 !found_on_haloed_element_with_other_processor)
28892 if (n_val > n_new_val)
28899 BoundaryNodeBase* bnod_pt =
28900 dynamic_cast<BoundaryNodeBase*
>(new_nod_pt);
28905 if (bnod_pt->index_of_first_value_assigned_by_face_element_pt() == 0)
28907 bnod_pt->index_of_first_value_assigned_by_face_element_pt() =
28908 new std::map<unsigned, unsigned>;
28912 std::map<unsigned, unsigned>* map_pt =
28913 bnod_pt->index_of_first_value_assigned_by_face_element_pt();
28917 const unsigned id_face = 0;
28919 std::map<unsigned, unsigned>::const_iterator p =
28920 map_pt->find(id_face);
28923 if (p == map_pt->end())
28927 (*map_pt)[id_face] = n_new_val;
28930 new_nod_pt->resize(n_val);
28939 SolidNode* solid_nod_pt =
dynamic_cast<SolidNode*
>(new_nod_pt);
28940 if (solid_nod_pt != 0)
28942 unsigned n_solid_val = solid_nod_pt->variable_position_pt()->nvalue();
28943 for (
unsigned i_val = 0; i_val < n_solid_val; i_val++)
28945 for (
unsigned t = 0; t < n_prev; t++)
28948 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
28954 if (!found_node_in_other_shared_boundaries ||
28955 !found_on_haloed_element_with_other_processor)
28957 solid_nod_pt->variable_position_pt()->set_value(
28958 t, i_val, read_data);
28964 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28965 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28966 <<
" Number of values solid node: "
28967 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28970 const unsigned nvalues_solid_node =
28971 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28972 Vector<double> values_solid_node(nvalues_solid_node);
28973 for (
unsigned i = 0; i < nvalues_solid_node; i++)
28975 values_solid_node[i] =
28976 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
28983 if (!found_node_in_other_shared_boundaries ||
28984 !found_on_haloed_element_with_other_processor)
28986 unsigned index = 0;
28987 solid_nod_pt->read_values_from_vector(values_solid_node, index);
28994 for (
unsigned i_val = 0; i_val < n_val; i_val++)
28996 for (
unsigned t = 0; t < n_prev; t++)
28999 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
29005 if (!found_node_in_other_shared_boundaries ||
29006 !found_on_haloed_element_with_other_processor)
29008 new_nod_pt->set_value(t, i_val, read_data);
29015 unsigned n_dim = new_nod_pt->ndim();
29016 for (
unsigned idim = 0; idim < n_dim; idim++)
29018 for (
unsigned t = 0; t < n_prev; t++)
29021 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
29027 if (!found_node_in_other_shared_boundaries ||
29028 !found_on_haloed_element_with_other_processor)
29031 new_nod_pt->x(t, idim) = read_data;
29044 if (n_shd_bnd_with_other_procs_have_node > 0 &&
29048 !found_node_in_other_shared_boundaries)
29056 this->update_other_proc_shd_bnd_node_helper(new_nod_pt,
29057 other_proc_shd_bnd_node_pt,
29060 other_shared_boundaries,
29063 node_name_to_global_index,
29064 global_shared_node_pt);
29077 template<
class ELEMENT>
29079 const unsigned& b, Vector<Vector<Node*>>& tmp_segment_nodes)
29082 tmp_segment_nodes.clear();
29085 Vector<FiniteElement*> face_el_pt;
29092 unsigned n_repeated_ele = 0;
29095 const unsigned n_regions = this->nregion();
29098 Vector<std::pair<Node*, Node*>> done_nodes_pt;
29103 for (
unsigned rr = 0; rr < n_regions; rr++)
29105 const unsigned region_id =
29106 static_cast<unsigned>(this->Region_attribute[rr]);
29109 const unsigned nel_in_region =
29110 this->nboundary_element_in_region(b, region_id);
29113 unsigned nel_repeated_in_region = 0;
29117 if (nel_in_region > 0)
29121 bool repeated =
false;
29124 for (
unsigned e = 0; e < nel_in_region; e++)
29127 FiniteElement* bulk_elem_pt =
29128 this->boundary_element_in_region_pt(b, region_id, e);
29130 #ifdef OOMPH_HAS_MPI
29132 if (this->is_mesh_distributed() && bulk_elem_pt->is_halo())
29143 this->face_index_at_boundary_in_region(b, region_id, e);
29148 FiniteElement* tmp_ele_pt =
29149 new DummyFaceElement<ELEMENT>(bulk_elem_pt, face_index);
29152 const unsigned n_nodes = tmp_ele_pt->nnode();
29154 std::pair<Node*, Node*> tmp_pair = std::make_pair(
29155 tmp_ele_pt->node_pt(0), tmp_ele_pt->node_pt(n_nodes - 1));
29157 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
29158 tmp_ele_pt->node_pt(n_nodes - 1), tmp_ele_pt->node_pt(0));
29161 unsigned n_done_nodes = done_nodes_pt.size();
29162 for (
unsigned l = 0; l < n_done_nodes; l++)
29164 if (tmp_pair == done_nodes_pt[l] ||
29165 tmp_pair_inverse == done_nodes_pt[l])
29167 nel_repeated_in_region++;
29178 done_nodes_pt.push_back(tmp_pair);
29180 face_el_pt.push_back(tmp_ele_pt);
29196 nel += nel_in_region;
29199 n_repeated_ele += nel_repeated_in_region;
29210 nel = this->nboundary_element(b);
29217 bool repeated =
false;
29220 for (
unsigned e = 0; e < nel; e++)
29223 FiniteElement* bulk_elem_pt = this->boundary_element_pt(b, e);
29225 #ifdef OOMPH_HAS_MPI
29227 if (this->is_mesh_distributed() && bulk_elem_pt->is_halo())
29237 int face_index = this->face_index_at_boundary(b, e);
29241 FiniteElement* tmp_ele_pt =
29242 new DummyFaceElement<ELEMENT>(bulk_elem_pt, face_index);
29245 const unsigned n_nodes = tmp_ele_pt->nnode();
29247 std::pair<Node*, Node*> tmp_pair = std::make_pair(
29248 tmp_ele_pt->node_pt(0), tmp_ele_pt->node_pt(n_nodes - 1));
29250 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
29251 tmp_ele_pt->node_pt(n_nodes - 1), tmp_ele_pt->node_pt(0));
29254 unsigned n_done_nodes = done_nodes_pt.size();
29255 for (
unsigned l = 0; l < n_done_nodes; l++)
29257 if (tmp_pair == done_nodes_pt[l] ||
29258 tmp_pair_inverse == done_nodes_pt[l])
29271 done_nodes_pt.push_back(tmp_pair);
29273 face_el_pt.push_back(tmp_ele_pt);
29292 nel -= n_repeated_ele;
29295 if (nel != face_el_pt.size())
29297 std::ostringstream error_message;
29299 <<
"The independet counting of face elements (" << nel <<
") for "
29300 <<
"boundary (" << b <<
") is different\n"
29301 <<
"from the real number of face elements in the container ("
29302 << face_el_pt.size() <<
")\n";
29303 throw OomphLibError(
29304 error_message.str(),
29305 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29306 OOMPH_EXCEPTION_LOCATION);
29314 const unsigned nnon_halo_face_elements = nel;
29318 Vector<std::list<FiniteElement*>> segment_sorted_ele_pt;
29322 unsigned nsorted_face_elements = 0;
29326 std::map<FiniteElement*, bool> done_ele;
29331 std::map<FiniteElement*, bool> is_inverted;
29336 while (nsorted_face_elements < nnon_halo_face_elements)
29340 std::list<FiniteElement*> sorted_el_pt;
29344 bool found_initial_face_element =
false;
29347 FiniteElement* ele_face_pt = 0;
29349 unsigned iface = 0;
29350 #ifdef OOMPH_HAS_MPI
29351 if (this->is_mesh_distributed())
29353 for (iface = 0; iface < nel; iface++)
29355 ele_face_pt = face_el_pt[iface];
29357 if (!done_ele[ele_face_pt])
29362 found_initial_face_element =
true;
29365 nsorted_face_elements++;
29369 sorted_el_pt.push_back(ele_face_pt);
29371 done_ele[ele_face_pt] =
true;
29382 ele_face_pt = face_el_pt[0];
29385 found_initial_face_element =
true;
29388 nsorted_face_elements++;
29392 sorted_el_pt.push_back(ele_face_pt);
29394 done_ele[ele_face_pt] =
true;
29395 #ifdef OOMPH_HAS_MPI
29400 if (!found_initial_face_element)
29402 std::ostringstream error_message;
29403 error_message <<
"Could not find an initial face element for the "
29404 "current segment\n";
29405 throw OomphLibError(
29406 error_message.str(),
29407 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29408 OOMPH_EXCEPTION_LOCATION);
29413 const unsigned nnod = ele_face_pt->nnode();
29417 Node* left_node_pt = ele_face_pt->node_pt(0);
29418 Node* right_node_pt = ele_face_pt->node_pt(nnod - 1);
29422 bool face_element_added =
false;
29432 for (
unsigned iiface = iface; iiface < nel; iiface++)
29435 face_element_added =
false;
29438 ele_face_pt = face_el_pt[iiface];
29442 if (!done_ele[ele_face_pt])
29445 Node* local_left_node_pt = ele_face_pt->node_pt(0);
29446 Node* local_right_node_pt = ele_face_pt->node_pt(nnod - 1);
29449 if (left_node_pt == local_right_node_pt)
29451 left_node_pt = local_left_node_pt;
29452 sorted_el_pt.push_front(ele_face_pt);
29453 is_inverted[ele_face_pt] =
false;
29454 face_element_added =
true;
29457 else if (left_node_pt == local_left_node_pt)
29459 left_node_pt = local_right_node_pt;
29460 sorted_el_pt.push_front(ele_face_pt);
29461 is_inverted[ele_face_pt] =
true;
29462 face_element_added =
true;
29465 else if (right_node_pt == local_left_node_pt)
29467 right_node_pt = local_right_node_pt;
29468 sorted_el_pt.push_back(ele_face_pt);
29469 is_inverted[ele_face_pt] =
false;
29470 face_element_added =
true;
29473 else if (right_node_pt == local_right_node_pt)
29475 right_node_pt = local_left_node_pt;
29476 sorted_el_pt.push_back(ele_face_pt);
29477 is_inverted[ele_face_pt] =
true;
29478 face_element_added =
true;
29481 if (face_element_added)
29484 done_ele[ele_face_pt] =
true;
29485 nsorted_face_elements++;
29493 }
while (face_element_added &&
29494 (nsorted_face_elements < nnon_halo_face_elements));
29497 segment_sorted_ele_pt.push_back(sorted_el_pt);
29502 const unsigned nsegments = segment_sorted_ele_pt.size();
29505 if (nnon_halo_face_elements > 0 && nsegments == 0)
29507 std::ostringstream error_message;
29509 <<
"The number of segments is zero, but the number of nonhalo\n"
29510 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
29511 throw OomphLibError(
29512 error_message.str(),
29513 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29514 OOMPH_EXCEPTION_LOCATION);
29523 tmp_segment_nodes.resize(nsegments);
29525 for (
unsigned is = 0; is < nsegments; is++)
29528 if (segment_sorted_ele_pt[is].size() == 0)
29530 std::ostringstream error_message;
29531 error_message <<
"The (" << is <<
")-th segment has no elements\n";
29532 throw OomphLibError(
29533 error_message.str(),
29534 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29535 OOMPH_EXCEPTION_LOCATION);
29540 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
29543 const unsigned nnod = first_ele_pt->nnode();
29546 Node* first_node_pt = first_ele_pt->node_pt(0);
29547 if (is_inverted[first_ele_pt])
29549 first_node_pt = first_ele_pt->node_pt(nnod - 1);
29553 tmp_segment_nodes[is].push_back(first_node_pt);
29556 for (std::list<FiniteElement*>::iterator it =
29557 segment_sorted_ele_pt[is].begin();
29558 it != segment_sorted_ele_pt[is].end();
29562 FiniteElement* ele_pt = *it;
29565 Node* last_node_pt = 0;
29568 if (!is_inverted[ele_pt])
29570 last_node_pt = ele_pt->node_pt(nnod - 1);
29574 last_node_pt = ele_pt->node_pt(0);
29578 tmp_segment_nodes[is].push_back(last_node_pt);
29587 for (
unsigned e = 0; e < nel; e++)
29589 delete face_el_pt[e];
29600 template<
class ELEMENT>
29603 double t_start_overall = TimingHelpers::timer();
29610 Vector<double> target_area(elem_error.size());
29611 double min_angle = compute_area_target(elem_error, target_area);
29616 bool quantised_areas =
true;
29617 if (quantised_areas)
29619 unsigned n = target_area.size();
29620 double total_area = 0;
29626 #ifdef OOMPH_HAS_MPI
29627 if (this->is_mesh_distributed())
29631 double sub_area = 0.0;
29634 for (
unsigned e = 0; e < n; e++)
29637 FiniteElement* ele_pt = this->finite_element_pt(e);
29638 if (!ele_pt->is_halo())
29640 sub_area += ele_pt->size();
29645 OomphCommunicator* comm_pt = this->communicator_pt();
29649 &sub_area, &total_area, 1, MPI_DOUBLE, MPI_SUM, comm_pt->mpi_comm());
29653 for (
unsigned e = 0; e < n; e++)
29655 total_area += this->finite_element_pt(e)->size();
29662 for (
unsigned e = 0; e < n; e++)
29664 total_area += this->finite_element_pt(e)->size();
29668 for (
unsigned e = 0; e < n; e++)
29671 unsigned(ceil(log(target_area[e] / total_area) / log(1.0 / 3.0))) - 1;
29672 double new_target_area = total_area * pow(1.0 / 3.0,
int(level));
29673 target_area[e] = new_target_area;
29683 unsigned n = target_area.size();
29684 double max_area = 0.0;
29685 double min_area = DBL_MAX;
29686 for (
unsigned e = 0; e < n; e++)
29688 if (target_area[e] > max_area) max_area = target_area[e];
29689 if (target_area[e] < min_area) min_area = target_area[e];
29704 oomph_info <<
"Maximum target area: " << max_area << std::endl;
29705 oomph_info <<
"Minimum target area: " << min_area << std::endl;
29706 oomph_info <<
"Number of elements to be refined: " << this->Nrefined
29708 oomph_info <<
"Number of elements to be unrefined: " << this->Nunrefined
29710 oomph_info <<
"Min. angle: " << min_angle << std::endl;
29712 double orig_max_area, orig_min_area;
29713 this->max_and_min_element_size(orig_max_area, orig_min_area);
29714 oomph_info <<
"Max./min. element size in original mesh: " << orig_max_area
29715 <<
" " << orig_min_area << std::endl;
29723 bool check_only =
true;
29724 bool outer_boundary_update_necessary =
false;
29725 bool inner_boundary_update_necessary =
false;
29726 bool inner_open_boundary_update_necessary =
false;
29730 const unsigned nouter = this->Outer_boundary_pt.size();
29732 if (this->is_automatic_creation_of_vertices_on_boundaries_allowed())
29735 for (
unsigned i_outer = 0; i_outer < nouter; i_outer++)
29737 outer_boundary_update_necessary = this->update_polygon_using_face_mesh(
29738 this->Outer_boundary_pt[i_outer], check_only);
29740 if (outer_boundary_update_necessary)
break;
29745 if (!outer_boundary_update_necessary)
29749 const unsigned nhole = this->Internal_polygon_pt.size();
29750 Vector<Vector<double>> internal_point_coord(nhole);
29751 inner_boundary_update_necessary =
29752 this->surface_remesh_for_inner_hole_boundaries(internal_point_coord,
29757 if (!inner_boundary_update_necessary)
29759 const unsigned n_open_polyline = this->Internal_open_curve_pt.size();
29761 for (
unsigned i = 0; i < n_open_polyline; i++)
29763 inner_open_boundary_update_necessary =
29764 this->update_open_curve_using_face_mesh(
29765 this->Internal_open_curve_pt[i], check_only);
29767 if (inner_open_boundary_update_necessary)
break;
29779 #ifdef OOMPH_HAS_MPI
29784 int adapt_this_processor = 0;
29785 if (this->is_mesh_distributed())
29788 if ((Nrefined > 0) || (Nunrefined > max_keep_unrefined()) ||
29789 (min_angle < min_permitted_angle()) ||
29790 (outer_boundary_update_necessary) ||
29791 (inner_boundary_update_necessary) ||
29792 (inner_open_boundary_update_necessary))
29794 adapt_this_processor = 1;
29798 OomphCommunicator* comm_pt = this->communicator_pt();
29801 MPI_Allreduce(&adapt_this_processor,
29806 comm_pt->mpi_comm());
29814 if ((Nrefined > 0) || (Nunrefined > max_keep_unrefined()) ||
29815 (min_angle < min_permitted_angle()) ||
29816 (outer_boundary_update_necessary) ||
29817 (inner_boundary_update_necessary) ||
29818 (inner_open_boundary_update_necessary) || (adapt_all))
29820 if (!((Nrefined > 0) || (Nunrefined > max_keep_unrefined())))
29822 if ((outer_boundary_update_necessary) ||
29823 (inner_boundary_update_necessary) ||
29824 (inner_open_boundary_update_necessary))
29827 <<
"Mesh regeneration triggered by inaccurate interface/surface\n"
29828 <<
"representation; setting Nrefined to number of elements.\n"
29829 <<
"outer_boundary_update_necessary : "
29830 << outer_boundary_update_necessary <<
"\n"
29831 <<
"inner_boundary_update_necessary : "
29832 << inner_boundary_update_necessary <<
"\n"
29833 <<
"inner_open_boundary_update_necessary: "
29834 << inner_open_boundary_update_necessary <<
"\n";
29835 Nrefined = nelement();
29839 oomph_info <<
"Mesh regeneration triggered by min angle criterion;\n"
29840 <<
"setting Nrefined to number of elements.\n";
29841 Nrefined = nelement();
29848 #ifdef OOMPH_HAS_MPI
29849 else if (this->is_mesh_distributed() && adapt_this_processor == 0 &&
29852 oomph_info <<
"Mesh regeneration triggered by (" << adapt_all
29853 <<
") processor(s) "
29854 <<
"that require(s)\n adaptation\n";
29869 add_vertices_for_non_deletion();
29874 #ifdef OOMPH_HAS_MPI
29879 if (this->is_mesh_distributed())
29881 synchronize_shared_boundary_connections();
29894 if (this->is_automatic_creation_of_vertices_on_boundaries_allowed())
29897 unsigned nhole = this->Internal_polygon_pt.size();
29898 Vector<Vector<double>> internal_point_coord(nhole);
29899 this->surface_remesh_for_inner_hole_boundaries(internal_point_coord);
29902 for (
unsigned i_outer = 0; i_outer < nouter; i_outer++)
29904 this->update_polygon_using_face_mesh(
29905 this->Outer_boundary_pt[i_outer]);
29910 unsigned n_open_polyline = this->Internal_open_curve_pt.size();
29911 for (
unsigned i = 0; i < n_open_polyline; i++)
29913 this->update_open_curve_using_face_mesh(
29914 this->Internal_open_curve_pt[i]);
29923 const unsigned ninternal = this->Internal_polygon_pt.size();
29924 for (
unsigned i_internal = 0; i_internal < ninternal; i_internal++)
29926 this->update_polygon_using_elements_area(
29927 this->Internal_polygon_pt[i_internal], target_area);
29932 for (
unsigned i_outer = 0; i_outer < nouter; i_outer++)
29934 this->update_polygon_using_elements_area(
29935 this->Outer_boundary_pt[i_outer], target_area);
29940 const unsigned n_open_polyline = this->Internal_open_curve_pt.size();
29941 for (
unsigned i = 0; i < n_open_polyline; i++)
29943 this->update_open_curve_using_elements_area(
29944 this->Internal_open_curve_pt[i], target_area);
29955 #ifdef OOMPH_HAS_MPI
29957 if (this->is_mesh_distributed())
29960 const unsigned my_rank = this->communicator_pt()->my_rank();
29963 const unsigned n_curves = this->nshared_boundary_curves(my_rank);
29965 for (
unsigned nc = 0; nc < n_curves; nc++)
29968 this->update_shared_curve_using_elements_area(
29969 this->Shared_boundary_polyline_pt[my_rank][nc],
29996 const unsigned n_boundary = this->nboundary();
29998 const double t_start_first_stage_segments_connectivity =
29999 TimingHelpers::timer();
30004 #ifdef OOMPH_HAS_MPI
30007 if (this->is_mesh_distributed())
30009 this->Assigned_segments_initial_zeta_values.clear();
30017 for (
unsigned b = 0; b < n_boundary; ++b)
30022 #ifdef OOMPH_HAS_MPI
30023 if (this->is_mesh_distributed())
30029 this->compute_boundary_segments_connectivity_and_initial_zeta_values(
30038 if (this->boundary_geom_object_pt(b) == 0)
30040 this->
template setup_boundary_coordinates<ELEMENT>(b);
30046 #ifdef OOMPH_HAS_MPI
30047 if (this->is_mesh_distributed())
30052 this->synchronize_boundary_coordinates(b);
30061 const double t_total_first_stage_segments_connectivity =
30062 TimingHelpers::timer() - t_start_first_stage_segments_connectivity;
30072 #ifdef OOMPH_HAS_MPI
30080 Vector<TriangleMeshPolygon*> tmp_outer_polygons_pt;
30085 Vector<TriangleMeshOpenCurve*> tmp_open_curves_pt;
30087 if (this->is_mesh_distributed())
30091 this->create_distributed_domain_representation(tmp_outer_polygons_pt,
30092 tmp_open_curves_pt);
30095 this->create_temporary_boundary_connections(tmp_outer_polygons_pt,
30096 tmp_open_curves_pt);
30110 Vector<TriangleMeshPolyLine*> resume_initial_connection_polyline_pt;
30111 Vector<TriangleMeshPolyLine*> resume_final_connection_polyline_pt;
30112 restore_boundary_connections(resume_initial_connection_polyline_pt,
30113 resume_final_connection_polyline_pt);
30119 unsigned n_region = this->nregion();
30122 for (std::map<
unsigned, Vector<double>>::iterator it =
30123 this->Regions_coordinates.begin();
30124 it != this->Regions_coordinates.end();
30128 Vector<double> centroid(2, 0.0);
30131 unsigned region_id = it->first;
30134 oomph_info <<
"Region " << region_id <<
": " << it->second[0] <<
" "
30135 << it->second[1] <<
" ";
30138 unsigned n_region_element = this->nregion_element(region_id);
30139 if (n_region_element > 0)
30142 FiniteElement*
const elem_pt =
30143 this->region_element_pt(region_id, 0);
30146 for (
unsigned n = 0; n < 3; n++)
30148 Node*
const nod_pt = elem_pt->node_pt(n);
30149 for (
unsigned i = 0; i < 2; i++)
30151 centroid[i] += nod_pt->x(i);
30154 for (
unsigned i = 0; i < 2; i++)
30159 it->second = centroid;
30161 oomph_info <<
" , " << it->second[0] <<
" " << it->second[1]
30176 SolidMesh* solid_mesh_pt =
dynamic_cast<SolidMesh*
>(
this);
30186 Vector<TriangleMeshClosedCurve*> closed_curve_pt;
30187 Vector<TriangleMeshClosedCurve*> hole_pt;
30188 Vector<TriangleMeshOpenCurve*> open_curves_pt;
30190 #ifdef OOMPH_HAS_MPI
30191 if (!this->is_mesh_distributed())
30195 closed_curve_pt.resize(nouter);
30196 for (
unsigned i = 0; i < nouter; i++)
30198 closed_curve_pt[i] = this->Outer_boundary_pt[i];
30202 const unsigned n_holes = this->Internal_polygon_pt.size();
30203 hole_pt.resize(n_holes);
30204 for (
unsigned i = 0; i < n_holes; i++)
30206 hole_pt[i] = this->Internal_polygon_pt[i];
30210 const unsigned n_open_curves = this->Internal_open_curve_pt.size();
30211 open_curves_pt.resize(n_open_curves);
30212 for (
unsigned i = 0; i < n_open_curves; i++)
30214 open_curves_pt[i] = this->Internal_open_curve_pt[i];
30220 #ifdef OOMPH_HAS_MPI
30225 const unsigned n_tmp_outer = tmp_outer_polygons_pt.size();
30226 closed_curve_pt.resize(n_tmp_outer);
30227 for (
unsigned i = 0; i < n_tmp_outer; i++)
30229 closed_curve_pt[i] = tmp_outer_polygons_pt[i];
30233 const unsigned n_open_curves = tmp_open_curves_pt.size();
30234 open_curves_pt.resize(n_open_curves);
30235 for (
unsigned i = 0; i < n_open_curves; i++)
30237 open_curves_pt[i] = tmp_open_curves_pt[i];
30266 this->Extra_holes_coordinates;
30270 this->Regions_coordinates;
30273 if (this->Use_attributes)
30279 if (!this->is_automatic_creation_of_vertices_on_boundaries_allowed())
30281 triangle_mesh_parameters
30287 #ifdef OOMPH_HAS_MPI
30288 if (this->is_mesh_distributed())
30299 const double t_start_building_background_mesh = TimingHelpers::timer();
30301 if (solid_mesh_pt != 0)
30304 triangle_mesh_parameters, this->Time_stepper_pt);
30309 triangle_mesh_parameters, this->Time_stepper_pt);
30312 if (Print_timings_level_adaptation > 2)
30314 oomph_info <<
"CPU for building background mesh: "
30315 << TimingHelpers::timer() - t_start_building_background_mesh
30321 const double this_max_element_size = this->max_element_size();
30322 const double this_min_element_size = this->min_element_size();
30327 const double this_min_permitted_angle = this->min_permitted_angle();
30333 #ifdef OOMPH_HAS_MPI
30337 if (this->is_mesh_distributed())
30341 if (this->nshared_boundary_overlaps_internal_boundary() > 0)
30346 this->shared_boundary_overlaps_internal_boundary();
30351 this->shared_boundaries_ids();
30371 tmp_new_mesh_pt->boundary_geom_object_pt() =
30372 this->boundary_geom_object_pt();
30376 tmp_new_mesh_pt->boundary_coordinate_limits() =
30377 this->boundary_coordinate_limits();
30379 const double t_start_second_stage_segments_connectivity =
30380 TimingHelpers::timer();
30382 for (
unsigned b = 0; b < n_boundary; b++)
30387 #ifdef OOMPH_HAS_MPI
30388 if (this->is_mesh_distributed())
30403 if (tmp_new_mesh_pt->boundary_geom_object_pt(b) != 0)
30405 tmp_new_mesh_pt->template setup_boundary_coordinates<ELEMENT>(b);
30409 const double t_total_second_stage_segments_connectivity =
30410 TimingHelpers::timer() - t_start_second_stage_segments_connectivity;
30412 const double t_start_snap_nodes_bg_mesh = TimingHelpers::timer();
30416 for (
unsigned b = 0; b < n_boundary; b++)
30418 this->snap_nodes_onto_boundary(tmp_new_mesh_pt, b);
30421 const double t_total_snap_nodes_bg_mesh =
30422 TimingHelpers::timer() - t_start_snap_nodes_bg_mesh;
30424 if (Print_timings_level_adaptation > 2)
30426 oomph_info <<
"CPU for snapping nodes onto boundaries "
30427 <<
"(background mesh): " << t_total_snap_nodes_bg_mesh
30432 if (Mesh_update_fct_pt != 0)
30434 Mesh_update_fct_pt(tmp_new_mesh_pt);
30461 TriangulateIO tmp_new_triangulateio =
30462 tmp_new_mesh_pt->triangulateio_representation();
30467 bool use_eulerian_coords =
false;
30468 if (solid_mesh_pt != 0)
30470 use_eulerian_coords =
true;
30474 #ifdef OOMPH_HAS_CGAL
30477 CGALSamplePointContainerParameters cgal_params(
this);
30478 if (use_eulerian_coords)
30480 cgal_params.enable_use_eulerian_coordinates_during_setup();
30482 MeshAsGeomObject* mesh_geom_obj_pt =
new MeshAsGeomObject(&cgal_params);
30487 NonRefineableBinArrayParameters params(
this);
30488 if (use_eulerian_coords)
30490 params.enable_use_eulerian_coordinates_during_setup();
30492 Vector<unsigned> bin_dim(2);
30493 bin_dim[0] = Nbin_x_for_area_transfer;
30494 bin_dim[1] = Nbin_y_for_area_transfer;
30495 params.dimensions_of_bin_array() = bin_dim;
30496 MeshAsGeomObject* mesh_geom_obj_pt =
new MeshAsGeomObject(¶ms);
30502 std::map<GeneralisedElement*, unsigned> element_number;
30503 unsigned nelem = this->nelement();
30504 for (
unsigned e = 0; e < nelem; e++)
30506 element_number[this->element_pt(e)] = e;
30509 #ifndef OOMPH_HAS_CGAL
30514 Vector<double> bin_min_target_area;
30517 NonRefineableBinArray* bin_array_pt =
30518 dynamic_cast<NonRefineableBinArray*
>(
30519 mesh_geom_obj_pt->sample_point_container_pt());
30520 if (bin_array_pt == 0)
30522 throw OomphLibError(
30523 "Sample point container has to be NonRefineableBinArray",
30524 OOMPH_CURRENT_FUNCTION,
30525 OOMPH_EXCEPTION_LOCATION);
30529 unsigned n_bin = 0;
30530 unsigned max_n_entry = 0;
30531 unsigned min_n_entry = UINT_MAX;
30532 unsigned tot_n_entry = 0;
30533 unsigned n_empty = 0;
30534 bin_array_pt->get_fill_stats(
30535 n_bin, max_n_entry, min_n_entry, tot_n_entry, n_empty);
30537 oomph_info <<
"Before bin diffusion:"
30538 <<
" nbin:(" << n_bin <<
")"
30539 <<
" nempty:(" << n_empty <<
")"
30540 <<
" min:(" << min_n_entry <<
")"
30541 <<
" max:(" << max_n_entry <<
")"
30542 <<
" average entries:("
30543 << double(tot_n_entry) / double(n_bin) <<
")" << std::endl;
30547 double t0_bin_diff = TimingHelpers::timer();
30548 oomph_info <<
"Going into diffusion bit...\n";
30549 bin_array_pt->fill_bin_by_diffusion();
30550 oomph_info <<
"Back from diffusion bit...\n";
30551 oomph_info <<
"Time for bin diffusion: "
30552 << TimingHelpers::timer() - t0_bin_diff << std::endl;
30556 unsigned n_bin = 0;
30557 unsigned max_n_entry = 0;
30558 unsigned min_n_entry = UINT_MAX;
30559 unsigned tot_n_entry = 0;
30560 unsigned n_empty = 0;
30561 bin_array_pt->get_fill_stats(
30562 n_bin, max_n_entry, min_n_entry, tot_n_entry, n_empty);
30564 oomph_info <<
"After bin diffusion:"
30565 <<
" nbin:(" << n_bin <<
")"
30566 <<
" nempty:(" << n_empty <<
")"
30567 <<
" min:(" << min_n_entry <<
")"
30568 <<
" max:(" << max_n_entry <<
")"
30569 <<
" average entries:("
30570 << double(tot_n_entry) / double(n_bin) <<
")" << std::endl;
30577 double t_total_map = 0.0;
30580 unsigned counter_map = 0;
30585 const std::map<unsigned,
30586 Vector<std::pair<FiniteElement*, Vector<double>>>>*
30587 bins_pt = bin_array_pt->get_all_bins_content();
30590 const unsigned n_bin = bins_pt->size();
30595 bin_min_target_area.resize(n_bin);
30596 for (
unsigned u = 0; u < n_bin; u++)
30598 bin_min_target_area[u] = 0.0;
30604 Vector<std::pair<FiniteElement*, Vector<double>>>>::const_iterator IT;
30605 for (IT it = bins_pt->begin(); it != bins_pt->end(); it++)
30608 unsigned ib = (*it).first;
30611 const unsigned n_ele_bin = (*it).second.size();
30614 for (
unsigned ee = 0; ee < n_ele_bin; ee++)
30617 GeneralisedElement* ele_pt = (*it).second[ee].first;
30618 double t_map = TimingHelpers::timer();
30619 const unsigned ele_number = element_number[ele_pt];
30620 t_total_map += TimingHelpers::timer() - t_map;
30628 if (bin_min_target_area[ib] != 0)
30630 bin_min_target_area[ib] =
30631 std::min(bin_min_target_area[ib], target_area[ele_number]);
30635 bin_min_target_area[ib] = target_area[ele_number];
30642 oomph_info <<
"CPU for map[counter=" << counter_map
30643 <<
"]: " << t_total_map << std::endl;
30647 const bool output_bins =
false;
30650 unsigned length = bin_min_target_area.size();
30651 for (
unsigned u = 0; u < length; u++)
30653 oomph_info <<
"Bin n" << u
30654 <<
",target area: " << bin_min_target_area[u] << std::endl;
30665 #ifdef OOMPH_HAS_MPI
30667 unsigned n_ele_need_refinement = 0;
30671 double t_total_third_stage_segments_connectivity = 0.0;
30674 double t_total_transfer_target_areas = 0.0;
30677 double t_total_limit_target_areas = 0.0;
30680 double t_total_create_new_adapted_mesh = 0.0;
30683 double t_total_snap_nodes = 0.0;
30686 double t_total_wait_other_processors = 0.0;
30687 double t_iter = TimingHelpers::timer();
30693 double t_start_transfer_target_areas = TimingHelpers::timer();
30694 double t0_loop_int_pts = TimingHelpers::timer();
30700 nelem = tmp_new_mesh_pt->nelement();
30704 Vector<double> new_transferred_target_area(nelem, 0.0);
30705 for (
unsigned e = 0; e < nelem; e++)
30708 dynamic_cast<ELEMENT*
>(tmp_new_mesh_pt->element_pt(e));
30709 unsigned nint = el_pt->integral_pt()->nweight();
30710 for (
unsigned ipt = 0; ipt < nint; ipt++)
30713 Vector<double> s(2);
30714 for (
unsigned i = 0; i < 2; i++)
30716 s[i] = el_pt->integral_pt()->knot(ipt, i);
30719 Vector<double> x(2);
30720 el_pt->interpolated_x(s, x);
30726 GeomObject* geom_obj_pt = 0;
30727 unsigned max_sample_points =
30728 Max_sample_points_for_limited_locate_zeta_during_target_area_transfer;
30729 dynamic_cast<CGALSamplePointContainer*
>(
30730 mesh_geom_obj_pt->sample_point_container_pt())
30731 ->limited_locate_zeta(x, max_sample_points, geom_obj_pt, s);
30733 if (geom_obj_pt == 0)
30735 std::stringstream error_message;
30736 error_message <<
"Limited locate zeta failed for zeta = [ "
30737 << x[0] <<
" " << x[1] <<
" ]. Makes no sense!\n";
30738 throw OomphLibError(error_message.str(),
30739 OOMPH_CURRENT_FUNCTION,
30740 OOMPH_EXCEPTION_LOCATION);
30745 FiniteElement* fe_pt =
dynamic_cast<FiniteElement*
>(geom_obj_pt);
30749 std::stringstream error_message;
30750 error_message <<
"Cast to FE for GeomObject returned by "
30751 "limited locate zeta failed for zeta = [ "
30752 << x[0] <<
" " << x[1] <<
" ]. Makes no sense!\n";
30753 throw OomphLibError(error_message.str(),
30754 OOMPH_CURRENT_FUNCTION,
30755 OOMPH_EXCEPTION_LOCATION);
30762 double tg_area = target_area[element_number[fe_pt]];
30769 if (new_transferred_target_area[e] != 0)
30771 new_transferred_target_area[e] =
30772 std::min(new_transferred_target_area[e], tg_area);
30776 new_transferred_target_area[e] = tg_area;
30786 int bin_number = 0;
30787 bin_array_pt->get_bin(x, bin_number);
30790 if (bin_number < 0)
30793 std::stringstream error_message;
30794 error_message <<
"Very odd -- we're looking for a point[ " << x[0]
30795 <<
" " << x[1] <<
" ] that's not even \n"
30796 <<
"located within the bin boundaries.\n";
30797 throw OomphLibError(error_message.str(),
30798 "RefineableTriangleMesh::adapt()",
30799 OOMPH_EXCEPTION_LOCATION);
30807 if (new_transferred_target_area[e] != 0)
30809 new_transferred_target_area[e] =
30810 std::min(new_transferred_target_area[e],
30811 bin_min_target_area[bin_number]);
30815 new_transferred_target_area[e] =
30816 bin_min_target_area[bin_number];
30828 const bool output_target_areas =
false;
30829 if (output_target_areas)
30831 unsigned length = new_transferred_target_area.size();
30832 for (
unsigned u = 0; u < length; u++)
30834 oomph_info <<
"Element" << u
30835 <<
",target area: " << new_transferred_target_area[u]
30839 oomph_info <<
"Time for loop over integration points in new mesh: "
30840 << TimingHelpers::timer() - t0_loop_int_pts << std::endl;
30872 const double t_sub_total_transfer_target_areas =
30873 TimingHelpers::timer() - t_start_transfer_target_areas;
30875 if (Print_timings_level_adaptation > 2)
30878 const unsigned n_element = this->nelement();
30880 const unsigned n_element_background = tmp_new_mesh_pt->nelement();
30882 oomph_info <<
"CPU for transfer of target areas "
30883 <<
"[n_ele_old_mesh=" << n_element
30884 <<
", n_ele_background_mesh=" << n_element_background
30885 <<
"] (iter " << iter
30886 <<
"): " << t_sub_total_transfer_target_areas << std::endl;
30890 t_total_transfer_target_areas += t_sub_total_transfer_target_areas;
30901 const double t_start_limit_target_areas = TimingHelpers::timer();
30905 #ifdef OOMPH_HAS_MPI
30906 unsigned n_ele_need_refinement_iter = 0;
30918 const unsigned nel_new = tmp_new_mesh_pt->nelement();
30919 Vector<double> new_target_area(nel_new);
30920 for (
unsigned e = 0; e < nel_new; e++)
30923 FiniteElement* f_ele_pt = tmp_new_mesh_pt->finite_element_pt(e);
30926 const double new_area = new_transferred_target_area[e];
30927 if (new_area <= 0.0)
30929 std::ostringstream error_stream;
30931 <<
"This shouldn't happen! Element whose centroid is at "
30932 << (f_ele_pt->node_pt(0)->x(0) + f_ele_pt->node_pt(1)->x(0) +
30933 f_ele_pt->node_pt(2)->x(0)) /
30936 << (f_ele_pt->node_pt(0)->x(1) + f_ele_pt->node_pt(1)->x(1) +
30937 f_ele_pt->node_pt(2)->x(1)) /
30940 <<
" has no target area assigned\n";
30941 throw OomphLibError(error_stream.str(),
30942 OOMPH_CURRENT_FUNCTION,
30943 OOMPH_EXCEPTION_LOCATION);
30949 new_target_area[e] = new_area;
30950 if (new_target_area[e] < f_ele_pt->size() / 3.0)
30952 new_target_area[e] = f_ele_pt->size() / 3.0;
30970 #ifdef OOMPH_HAS_MPI
30972 n_ele_need_refinement_iter++;
30983 const double t_sub_total_limit_target_areas =
30984 TimingHelpers::timer() - t_start_limit_target_areas;
30987 t_total_limit_target_areas += t_sub_total_limit_target_areas;
30989 if (Print_timings_level_adaptation > 2)
30992 const unsigned n_element = this->nelement();
30994 const unsigned n_element_background = tmp_new_mesh_pt->nelement();
30996 oomph_info <<
"CPU for limiting target areas "
30997 <<
"[n_ele_old_mesh=" << n_element
30998 <<
", n_ele_background_mesh=" << n_element_background
30999 <<
"] (iter " << iter
31000 <<
"): " << t_sub_total_limit_target_areas << std::endl;
31006 <<
"All area adjustments accommodated by max. permitted area"
31007 <<
" reduction \n";
31011 oomph_info <<
"NOT all area adjustments accommodated by max. "
31012 <<
"permitted area reduction \n";
31025 const double t_start_create_new_adapted_mesh = TimingHelpers::timer();
31028 if (solid_mesh_pt != 0)
31032 tmp_new_triangulateio,
31033 this->Time_stepper_pt,
31034 this->Use_attributes,
31035 this->Allow_automatic_creation_of_vertices_on_boundaries,
31036 this->communicator_pt());
31043 tmp_new_triangulateio,
31044 this->Time_stepper_pt,
31045 this->Use_attributes,
31046 this->Allow_automatic_creation_of_vertices_on_boundaries,
31047 this->communicator_pt());
31051 const double t_sub_total_create_new_adapted_mesh =
31052 TimingHelpers::timer() - t_start_create_new_adapted_mesh;
31055 t_total_create_new_adapted_mesh += t_sub_total_create_new_adapted_mesh;
31057 if (Print_timings_level_adaptation > 2)
31060 const unsigned n_element_new_adapted_mesh = new_mesh_pt->nelement();
31062 oomph_info <<
"CPU for creation of new adapted mesh "
31063 << t_sub_total_create_new_adapted_mesh
31064 <<
"[nele=" << n_element_new_adapted_mesh <<
"] (iter "
31065 << iter <<
"): " << t_sub_total_create_new_adapted_mesh
31069 #ifdef OOMPH_HAS_MPI
31080 if (this->nshared_boundary_overlaps_internal_boundary() > 0)
31085 this->shared_boundary_overlaps_internal_boundary();
31106 new_mesh_pt->boundary_geom_object_pt() =
31107 this->boundary_geom_object_pt();
31111 new_mesh_pt->boundary_coordinate_limits() =
31112 this->boundary_coordinate_limits();
31114 const double t_start_third_stage_segments_connectivity =
31115 TimingHelpers::timer();
31117 for (
unsigned b = 0; b < n_boundary; b++)
31126 #ifdef OOMPH_HAS_MPI
31127 if (this->is_mesh_distributed())
31142 if (new_mesh_pt->boundary_geom_object_pt(b) != 0)
31144 new_mesh_pt->template setup_boundary_coordinates<ELEMENT>(b);
31148 t_total_third_stage_segments_connectivity +=
31149 TimingHelpers::timer() - t_start_third_stage_segments_connectivity;
31151 const double t_start_snap_nodes_new_mesh = TimingHelpers::timer();
31155 for (
unsigned b = 0; b < n_boundary; b++)
31157 this->snap_nodes_onto_boundary(new_mesh_pt, b);
31160 const double t_sub_total_snap_nodes_new_mesh =
31161 TimingHelpers::timer() - t_start_snap_nodes_new_mesh;
31164 t_total_snap_nodes += t_sub_total_snap_nodes_new_mesh;
31166 if (Print_timings_level_adaptation > 2)
31168 oomph_info <<
"CPU for snapping nodes onto boundaries (new mesh) "
31169 <<
"(iter " << iter
31170 <<
"): " << t_sub_total_snap_nodes_new_mesh << std::endl;
31174 if (Mesh_update_fct_pt != 0)
31176 Mesh_update_fct_pt(new_mesh_pt);
31183 if (
dynamic_cast<GeneralisedTimeStepper*
>(this->Time_stepper_pt))
31185 new_mesh_pt->set_nodal_and_elemental_time_stepper(
31186 this->Time_stepper_pt,
false);
31193 delete tmp_new_mesh_pt;
31195 #ifdef OOMPH_HAS_MPI
31199 if (n_ele_need_refinement_iter == n_ele_need_refinement)
31205 n_ele_need_refinement = n_ele_need_refinement_iter;
31215 #ifdef OOMPH_HAS_MPI
31216 if (this->is_mesh_distributed())
31219 const double t_start_wait_other_processors = TimingHelpers::timer();
31226 unsigned this_processor_requires_another_iteration = 1;
31231 this_processor_requires_another_iteration = 0;
31233 int nproc_not_done = this_processor_requires_another_iteration;
31235 OomphCommunicator* comm_pt = this->communicator_pt();
31238 MPI_Allreduce(&this_processor_requires_another_iteration,
31243 comm_pt->mpi_comm());
31245 if (nproc_not_done > 0)
31248 <<
"At least one processors requires further refinement. "
31249 <<
"Go for another iteration." << std::endl;
31255 const double t_sub_total_wait_other_processors =
31256 TimingHelpers::timer() - t_start_wait_other_processors;
31260 t_total_wait_other_processors += t_sub_total_wait_other_processors;
31262 if (Print_timings_level_adaptation > 2)
31264 oomph_info <<
"CPU for waiting other processors "
31265 <<
"(iter " << iter
31266 <<
"): " << t_sub_total_wait_other_processors
31278 oomph_info <<
"Going for another iteration. Current iteration ("
31279 << iter <<
")" << std::endl;
31282 tmp_new_mesh_pt = new_mesh_pt;
31283 tmp_new_triangulateio = new_mesh_pt->triangulateio_representation();
31290 delete mesh_geom_obj_pt;
31292 oomph_info <<
"CPU for iterative generation of new mesh (TOTAL): "
31293 << TimingHelpers::timer() - t_iter << std::endl;
31295 if (Print_timings_level_adaptation > 1)
31297 oomph_info <<
"-- CPU for creating new adapted meshes (TOTAL): "
31298 << t_total_create_new_adapted_mesh << std::endl;
31300 oomph_info <<
"-- CPU for limiting target areas (TOTAL): "
31301 << t_total_limit_target_areas << std::endl;
31303 oomph_info <<
"-- CPU for transferring target areas (TOTAL): "
31304 << t_total_transfer_target_areas << std::endl;
31306 oomph_info <<
"-- CPU for waiting other processors (TOTAL): "
31307 << t_total_wait_other_processors << std::endl;
31319 if (!Disable_projection)
31322 double tt_start_projection = TimingHelpers::timer();
31325 if (Print_timings_projection)
31328 Multi_domain_functions::Doc_timings =
true;
31329 Multi_domain_functions::Doc_stats =
true;
31330 Multi_domain_functions::Doc_full_stats =
true;
31333 double t_proj = TimingHelpers::timer();
31334 oomph_info <<
"About to begin projection.\n";
31338 ProjectionProblem<ELEMENT>* project_problem_pt =
31339 new ProjectionProblem<ELEMENT>;
31343 #ifdef OOMPH_HAS_MPI
31344 if (this->is_mesh_distributed())
31352 Time* backed_up_time_pt = this->Time_stepper_pt->time_pt();
31355 project_problem_pt->enable_problem_distributed();
31359 project_problem_pt->add_time_stepper_pt(this->Time_stepper_pt);
31362 project_problem_pt->mesh_pt() = new_mesh_pt;
31367 if (!this->use_iterative_solver_for_projection())
31369 project_problem_pt->disable_use_iterative_solver_for_projection();
31373 project_problem_pt->project(
this);
31376 this->Time_stepper_pt->time_pt() = backed_up_time_pt;
31387 project_problem_pt->mesh_pt() = new_mesh_pt;
31393 if (!this->use_iterative_solver_for_projection())
31395 project_problem_pt->disable_use_iterative_solver_for_projection();
31399 project_problem_pt->project(
this);
31403 if (Print_timings_projection)
31406 Multi_domain_functions::Doc_timings =
false;
31407 Multi_domain_functions::Doc_stats =
false;
31408 Multi_domain_functions::Doc_full_stats =
false;
31412 const double tt_projection =
31413 TimingHelpers::timer() - tt_start_projection;
31415 if (Print_timings_level_adaptation > 1)
31418 const unsigned n_element = this->nelement();
31420 const unsigned n_element_new = new_mesh_pt->nelement();
31421 oomph_info <<
"CPU for projection (in mesh adaptation) "
31422 <<
"[n_ele_old_mesh=" << n_element
31423 <<
", n_ele_new_mesh=" << n_element_new
31424 <<
"]: " << tt_projection << std::endl;
31429 #ifdef OOMPH_HAS_MPI
31430 if (this->is_mesh_distributed())
31434 unsigned n_this_element_new = n_element_new;
31435 unsigned n_max_element_new_global = 0;
31437 MPI_Reduce(&n_this_element_new,
31438 &n_max_element_new_global,
31443 this->communicator_pt()->mpi_comm());
31446 double tt_this_projection = tt_projection;
31447 double tt_global_min_projection = 0.0;
31448 double tt_global_max_projection = 0.0;
31451 MPI_Reduce(&tt_this_projection,
31452 &tt_global_min_projection,
31457 this->communicator_pt()->mpi_comm());
31458 MPI_Reduce(&tt_this_projection,
31459 &tt_global_max_projection,
31464 this->communicator_pt()->mpi_comm());
31466 if (this->communicator_pt()->my_rank() == 0)
31468 oomph_info <<
"CPU for projection global (MIN): "
31469 << tt_global_min_projection << std::endl;
31470 oomph_info <<
"CPU for projection global (MAX) "
31471 <<
"[n_max_ele_new_global=" << n_max_element_new_global
31472 <<
"]: " << tt_global_max_projection << std::endl;
31474 std::cerr <<
"CPU for projection global (MIN): "
31475 << tt_global_min_projection << std::endl;
31476 std::cerr <<
"CPU for projection global (MAX): "
31477 <<
"[n_max_ele_new_global=" << n_max_element_new_global
31478 <<
"]: " << tt_global_max_projection << std::endl;
31488 oomph_info <<
"CPU for projection of solution onto new mesh: "
31489 << TimingHelpers::timer() - t_proj << std::endl;
31492 delete project_problem_pt;
31497 oomph_info <<
"Projection disabled! The new mesh will contain zeros"
31505 double t_rest = TimingHelpers::timer();
31508 unsigned nnod = nnode();
31509 for (
unsigned j = nnod; j > 0; j--)
31511 delete Node_pt[j - 1];
31512 Node_pt[j - 1] = 0;
31514 unsigned nel = nelement();
31515 for (
unsigned e = nel; e > 0; e--)
31517 delete Element_pt[e - 1];
31518 Element_pt[e - 1] = 0;
31523 nnod = new_mesh_pt->nnode();
31524 Node_pt.resize(nnod);
31525 nel = new_mesh_pt->nelement();
31526 Element_pt.resize(nel);
31527 for (
unsigned j = 0; j < nnod; j++)
31529 Node_pt[j] = new_mesh_pt->node_pt(j);
31531 for (
unsigned e = 0; e < nel; e++)
31533 Element_pt[e] = new_mesh_pt->element_pt(e);
31538 unsigned nbound = 0;
31540 #ifdef OOMPH_HAS_MPI
31544 if (this->is_mesh_distributed())
31549 nbound = new_mesh_pt->nboundary();
31558 nbound = n_boundary;
31561 Boundary_element_pt.resize(nbound);
31562 Face_index_at_boundary.resize(nbound);
31563 Boundary_node_pt.resize(nbound);
31564 for (
unsigned b = 0; b < nbound; b++)
31566 unsigned nel = new_mesh_pt->nboundary_element(b);
31567 Boundary_element_pt[b].resize(nel);
31568 Face_index_at_boundary[b].resize(nel);
31569 for (
unsigned e = 0; e < nel; e++)
31571 Boundary_element_pt[b][e] = new_mesh_pt->boundary_element_pt(b, e);
31572 Face_index_at_boundary[b][e] =
31573 new_mesh_pt->face_index_at_boundary(b, e);
31575 unsigned nnod = new_mesh_pt->nboundary_node(b);
31576 Boundary_node_pt[b].resize(nnod);
31577 for (
unsigned j = 0; j < nnod; j++)
31579 Boundary_node_pt[b][j] = new_mesh_pt->boundary_node_pt(b, j);
31584 unsigned n_region = new_mesh_pt->nregion();
31589 this->Region_attribute.resize(n_region);
31590 for (
unsigned r = 0; r < n_region; r++)
31592 this->Region_attribute[r] = new_mesh_pt->region_attribute(r);
31594 unsigned r_id =
static_cast<unsigned>(this->Region_attribute[r]);
31596 unsigned n_region_element = new_mesh_pt->nregion_element(r_id);
31597 this->Region_element_pt[r_id].resize(n_region_element);
31598 for (
unsigned e = 0; e < n_region_element; e++)
31600 this->Region_element_pt[r_id][e] =
31601 new_mesh_pt->region_element_pt(r_id, e);
31606 this->Boundary_region_element_pt.resize(nbound);
31607 this->Face_index_region_at_boundary.resize(nbound);
31610 for (
unsigned b = 0; b < nbound; ++b)
31612 for (
unsigned rr = 0; rr < n_region; rr++)
31615 unsigned r =
static_cast<unsigned>(this->Region_attribute[rr]);
31617 unsigned n_boundary_el_in_region =
31618 new_mesh_pt->nboundary_element_in_region(b, r);
31620 if (n_boundary_el_in_region > 0)
31623 this->Boundary_region_element_pt[b][r].resize(
31624 n_boundary_el_in_region);
31625 this->Face_index_region_at_boundary[b][r].resize(
31626 n_boundary_el_in_region);
31629 for (
unsigned e = 0; e < n_boundary_el_in_region; ++e)
31631 this->Boundary_region_element_pt[b][r][e] =
31632 new_mesh_pt->boundary_element_in_region_pt(b, r, e);
31633 this->Face_index_region_at_boundary[b][r][e] =
31634 new_mesh_pt->face_index_at_boundary_in_region(b, r, e);
31647 #ifdef OOMPH_HAS_MPI
31648 if (this->is_mesh_distributed())
31653 if (this->is_mesh_distributed())
31655 this->Halo_node_pt.clear();
31656 this->Root_halo_element_pt.clear();
31658 this->Haloed_node_pt.clear();
31659 this->Root_haloed_element_pt.clear();
31661 this->External_halo_node_pt.clear();
31662 this->External_halo_element_pt.clear();
31664 this->External_haloed_node_pt.clear();
31665 this->External_haloed_element_pt.clear();
31670 this->reset_shared_boundary_elements_and_nodes();
31680 Vector<unsigned> my_rank_shared_boundaries_ids;
31681 this->shared_boundaries_in_this_processor(
31682 my_rank_shared_boundaries_ids);
31685 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
31688 for (
unsigned i = 0; i < nmy_rank_shd_bnd; i++)
31691 const unsigned shd_bnd_id = my_rank_shared_boundaries_ids[i];
31694 this->Boundary_element_pt[shd_bnd_id].clear();
31698 const unsigned tmp_nnodes = this->nshared_boundary_node(shd_bnd_id);
31699 for (
unsigned n = 0; n < tmp_nnodes; n++)
31701 Node* tmp_node_pt = this->boundary_node_pt(shd_bnd_id, n);
31702 tmp_node_pt->remove_from_boundary(shd_bnd_id);
31708 this->set_nboundary(n_boundary);
31712 this->sort_nodes_on_shared_boundaries();
31715 this->reset_halo_haloed_scheme();
31719 for (
unsigned b = 0; b < n_boundary; b++)
31721 if (this->boundary_geom_object_pt(b) != 0)
31723 const unsigned nsegments = new_mesh_pt->nboundary_segment(b);
31724 this->set_nboundary_segment_node(b, nsegments);
31729 resume_boundary_connections(resume_initial_connection_polyline_pt,
31730 resume_final_connection_polyline_pt);
31741 this->snap_nodes_onto_geometric_objects();
31747 TriangleHelper::clear_triangulateio(this->Triangulateio);
31749 this->Triangulateio =
31750 TriangleHelper::deep_copy_of_triangulateio_representation(
31751 new_mesh_pt->triangulateio_representation(), quiet);
31754 new_mesh_pt->flush_element_and_node_storage();
31757 delete new_mesh_pt;
31760 if (Print_timings_level_adaptation > 2)
31764 oomph_info <<
"CPU for segments connectivity (first stage) [sec]: "
31765 << t_total_first_stage_segments_connectivity << std::endl;
31766 oomph_info <<
"CPU for segments connectivity (second stage) [sec]: "
31767 << t_total_second_stage_segments_connectivity << std::endl;
31768 oomph_info <<
"CPU for segments connectivity (third stage) [sec]: "
31769 << t_total_third_stage_segments_connectivity << std::endl;
31772 if (Print_timings_level_adaptation > 1)
31774 const double t_total_segments_connectivity =
31775 t_total_first_stage_segments_connectivity +
31776 t_total_second_stage_segments_connectivity +
31777 t_total_third_stage_segments_connectivity;
31779 oomph_info <<
"CPU for segments connectivity (TOTAL) [sec]: "
31780 << t_total_segments_connectivity << std::endl;
31782 if (Print_timings_level_adaptation > 2)
31785 oomph_info <<
"CPU for snapping nodes onto boundaries "
31786 <<
"(new mesh): " << t_total_snap_nodes << std::endl;
31789 t_total_snap_nodes += t_total_snap_nodes_bg_mesh;
31790 oomph_info <<
"CPU for snapping nodes onto boundaries (TOTAL): "
31791 << t_total_snap_nodes << std::endl;
31794 double max_area = 0.0;
31795 double min_area = 0.0;
31797 this->max_and_min_element_size(max_area, min_area);
31798 oomph_info <<
"Max/min element size in adapted mesh: " << max_area <<
" "
31799 << min_area << std::endl;
31801 oomph_info <<
"CPU time for final bits [sec]: "
31802 << TimingHelpers::timer() - t_rest << std::endl;
31806 oomph_info <<
"Not enough benefit in adaptation.\n";
31811 double CPU_for_adaptation = TimingHelpers::timer() - t_start_overall;
31812 oomph_info <<
"CPU time for adaptation [sec]: " << CPU_for_adaptation
31818 #ifdef OOMPH_HAS_MPI
31819 if (this->is_mesh_distributed())
31822 OomphCommunicator* comm_pt = this->communicator_pt();
31824 const unsigned n_proc = comm_pt->nproc();
31825 if (Print_timings_level_adaptation > 1 && n_proc > 1)
31827 double global_min_CPU_for_adaptation = 0.0;
31828 double global_max_CPU_for_adaptation = 0.0;
31829 double global_average_CPU_for_adaptation = 0.0;
31832 MPI_Reduce(&CPU_for_adaptation,
31833 &global_min_CPU_for_adaptation,
31838 comm_pt->mpi_comm());
31839 MPI_Reduce(&CPU_for_adaptation,
31840 &global_max_CPU_for_adaptation,
31845 comm_pt->mpi_comm());
31846 MPI_Reduce(&CPU_for_adaptation,
31847 &global_average_CPU_for_adaptation,
31852 comm_pt->mpi_comm());
31855 const unsigned my_rank = comm_pt->my_rank();
31858 oomph_info <<
"CPU for adaptation (MIN): "
31859 << global_min_CPU_for_adaptation << std::endl;
31860 oomph_info <<
"CPU for adaptation (MAX): "
31861 << global_max_CPU_for_adaptation << std::endl;
31862 oomph_info <<
"CPU for adaptation (AVERAGE): "
31863 << global_average_CPU_for_adaptation / n_proc << std::endl;
31882 template<
class ELEMENT>
31887 Boundary_connections_pt.clear();
31894 std::set<unsigned> boundary_id_with_connections;
31901 const unsigned n_outer_boundaries = this->Outer_boundary_pt.size();
31904 for (
unsigned i = 0; i < n_outer_boundaries; i++)
31907 TriangleMeshPolygon* tmp_polygon_pt = this->Outer_boundary_pt[i];
31910 const unsigned n_polyline = tmp_polygon_pt->npolyline();
31912 for (
unsigned p = 0; p < n_polyline; p++)
31915 TriangleMeshPolyLine* tmp_polyline_pt = tmp_polygon_pt->polyline_pt(p);
31918 if (tmp_polyline_pt->is_initial_vertex_connected())
31921 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
31925 boundary_id_with_connections.insert(bnd_id);
31928 const unsigned dst_bnd_id =
31929 tmp_polyline_pt->initial_vertex_connected_bnd_id();
31933 boundary_id_with_connections.insert(dst_bnd_id);
31938 if (tmp_polyline_pt->is_final_vertex_connected())
31941 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
31945 boundary_id_with_connections.insert(bnd_id);
31948 const unsigned dst_bnd_id =
31949 tmp_polyline_pt->final_vertex_connected_bnd_id();
31953 boundary_id_with_connections.insert(dst_bnd_id);
31966 const unsigned n_internal_boundaries = this->Internal_polygon_pt.size();
31969 for (
unsigned i = 0; i < n_internal_boundaries; i++)
31972 TriangleMeshPolygon* tmp_polygon_pt = this->Internal_polygon_pt[i];
31975 const unsigned n_polyline = tmp_polygon_pt->npolyline();
31977 for (
unsigned p = 0; p < n_polyline; p++)
31980 TriangleMeshPolyLine* tmp_polyline_pt = tmp_polygon_pt->polyline_pt(p);
31983 if (tmp_polyline_pt->is_initial_vertex_connected())
31986 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
31990 boundary_id_with_connections.insert(bnd_id);
31993 const unsigned dst_bnd_id =
31994 tmp_polyline_pt->initial_vertex_connected_bnd_id();
31998 boundary_id_with_connections.insert(dst_bnd_id);
32003 if (tmp_polyline_pt->is_final_vertex_connected())
32006 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32010 boundary_id_with_connections.insert(bnd_id);
32013 const unsigned dst_bnd_id =
32014 tmp_polyline_pt->final_vertex_connected_bnd_id();
32018 boundary_id_with_connections.insert(dst_bnd_id);
32031 const unsigned n_open_boundaries = this->Internal_open_curve_pt.size();
32034 for (
unsigned i = 0; i < n_open_boundaries; i++)
32037 TriangleMeshOpenCurve* tmp_open_curve_pt =
32038 this->Internal_open_curve_pt[i];
32042 const unsigned n_curve_section = tmp_open_curve_pt->ncurve_section();
32045 for (
unsigned p = 0; p < n_curve_section; p++)
32049 TriangleMeshPolyLine* tmp_polyline_pt =
32050 tmp_open_curve_pt->polyline_pt(p);
32053 if (tmp_polyline_pt->is_initial_vertex_connected())
32056 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32060 boundary_id_with_connections.insert(bnd_id);
32063 const unsigned dst_bnd_id =
32064 tmp_polyline_pt->initial_vertex_connected_bnd_id();
32068 boundary_id_with_connections.insert(dst_bnd_id);
32073 if (tmp_polyline_pt->is_final_vertex_connected())
32076 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32080 boundary_id_with_connections.insert(bnd_id);
32083 const unsigned dst_bnd_id =
32084 tmp_polyline_pt->final_vertex_connected_bnd_id();
32088 boundary_id_with_connections.insert(dst_bnd_id);
32096 #ifdef OOMPH_HAS_MPI
32103 if (this->is_mesh_distributed())
32106 const unsigned my_rank = this->communicator_pt()->my_rank();
32109 const unsigned n_shared_curves = this->nshared_boundary_curves(my_rank);
32112 for (
unsigned i = 0; i < n_shared_curves; i++)
32116 const unsigned n_polyline = this->nshared_boundary_polyline(my_rank, i);
32120 for (
unsigned p = 0; p < n_polyline; p++)
32123 TriangleMeshPolyLine* tmp_polyline_pt =
32124 this->shared_boundary_polyline_pt(my_rank, i, p);
32127 if (tmp_polyline_pt->is_initial_vertex_connected())
32130 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32134 boundary_id_with_connections.insert(bnd_id);
32137 const unsigned dst_bnd_id =
32138 tmp_polyline_pt->initial_vertex_connected_bnd_id();
32142 boundary_id_with_connections.insert(dst_bnd_id);
32147 if (tmp_polyline_pt->is_final_vertex_connected())
32150 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32154 boundary_id_with_connections.insert(bnd_id);
32157 const unsigned dst_bnd_id =
32158 tmp_polyline_pt->final_vertex_connected_bnd_id();
32162 boundary_id_with_connections.insert(dst_bnd_id);
32180 std::map<unsigned, Vector<Vector<Node*>>> bnd_sorted_segment_node_pt;
32183 for (std::set<unsigned>::iterator it = boundary_id_with_connections.begin();
32184 it != boundary_id_with_connections.end();
32188 const unsigned bnd_id = (*it);
32189 #ifdef OOMPH_HAS_MPI
32191 if (this->is_mesh_distributed())
32194 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
32196 if (bnd_id >= init_shd_bnd_id)
32201 Vector<Vector<Node*>> tmp_shared_nodes_pt;
32204 get_shared_boundary_segment_nodes_helper(bnd_id, tmp_shared_nodes_pt);
32207 bnd_sorted_segment_node_pt[bnd_id] = tmp_shared_nodes_pt;
32215 Vector<Vector<Node*>> tmp_boundary_nodes_pt;
32218 get_boundary_segment_nodes_helper(bnd_id, tmp_boundary_nodes_pt);
32221 bnd_sorted_segment_node_pt[bnd_id] = tmp_boundary_nodes_pt;
32232 Vector<Vector<Node*>> tmp_boundary_nodes_pt;
32235 get_boundary_segment_nodes_helper(bnd_id, tmp_boundary_nodes_pt);
32238 bnd_sorted_segment_node_pt[bnd_id] = tmp_boundary_nodes_pt;
32252 for (
unsigned i = 0; i < n_outer_boundaries; i++)
32255 TriangleMeshPolygon* tmp_polygon_pt = this->Outer_boundary_pt[i];
32258 const unsigned n_polyline = tmp_polygon_pt->npolyline();
32260 for (
unsigned p = 0; p < n_polyline; p++)
32263 TriangleMeshPolyLine* tmp_polyline_pt = tmp_polygon_pt->polyline_pt(p);
32266 if (tmp_polyline_pt->is_initial_vertex_connected())
32269 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32272 const unsigned dst_bnd_id =
32273 tmp_polyline_pt->initial_vertex_connected_bnd_id();
32276 const unsigned dst_chunk =
32277 tmp_polyline_pt->initial_vertex_connected_n_chunk();
32280 Vector<Vector<Node*>> src_bnd_node_pt =
32281 bnd_sorted_segment_node_pt[bnd_id];
32284 Vector<Vector<Node*>> dst_bnd_node_pt =
32285 bnd_sorted_segment_node_pt[dst_bnd_id];
32289 add_non_delete_vertices_from_boundary_helper(
32290 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32295 if (tmp_polyline_pt->is_final_vertex_connected())
32298 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32301 const unsigned dst_bnd_id =
32302 tmp_polyline_pt->final_vertex_connected_bnd_id();
32305 const unsigned dst_chunk =
32306 tmp_polyline_pt->final_vertex_connected_n_chunk();
32309 Vector<Vector<Node*>> src_bnd_node_pt =
32310 bnd_sorted_segment_node_pt[bnd_id];
32313 Vector<Vector<Node*>> dst_bnd_node_pt =
32314 bnd_sorted_segment_node_pt[dst_bnd_id];
32318 add_non_delete_vertices_from_boundary_helper(
32319 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32331 for (
unsigned i = 0; i < n_internal_boundaries; i++)
32334 TriangleMeshPolygon* tmp_polygon_pt = this->Internal_polygon_pt[i];
32337 const unsigned n_polyline = tmp_polygon_pt->npolyline();
32339 for (
unsigned p = 0; p < n_polyline; p++)
32342 TriangleMeshPolyLine* tmp_polyline_pt = tmp_polygon_pt->polyline_pt(p);
32345 if (tmp_polyline_pt->is_initial_vertex_connected())
32348 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32351 const unsigned dst_bnd_id =
32352 tmp_polyline_pt->initial_vertex_connected_bnd_id();
32355 const unsigned dst_chunk =
32356 tmp_polyline_pt->initial_vertex_connected_n_chunk();
32359 Vector<Vector<Node*>> src_bnd_node_pt =
32360 bnd_sorted_segment_node_pt[bnd_id];
32363 Vector<Vector<Node*>> dst_bnd_node_pt =
32364 bnd_sorted_segment_node_pt[dst_bnd_id];
32368 add_non_delete_vertices_from_boundary_helper(
32369 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32374 if (tmp_polyline_pt->is_final_vertex_connected())
32377 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32380 const unsigned dst_bnd_id =
32381 tmp_polyline_pt->final_vertex_connected_bnd_id();
32384 const unsigned dst_chunk =
32385 tmp_polyline_pt->final_vertex_connected_n_chunk();
32388 Vector<Vector<Node*>> src_bnd_node_pt =
32389 bnd_sorted_segment_node_pt[bnd_id];
32392 Vector<Vector<Node*>> dst_bnd_node_pt =
32393 bnd_sorted_segment_node_pt[dst_bnd_id];
32397 add_non_delete_vertices_from_boundary_helper(
32398 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32410 for (
unsigned i = 0; i < n_open_boundaries; i++)
32413 TriangleMeshOpenCurve* tmp_open_curve_pt =
32414 this->Internal_open_curve_pt[i];
32418 const unsigned n_curve_section = tmp_open_curve_pt->ncurve_section();
32421 for (
unsigned p = 0; p < n_curve_section; p++)
32425 TriangleMeshPolyLine* tmp_polyline_pt =
32426 tmp_open_curve_pt->polyline_pt(p);
32429 if (tmp_polyline_pt->is_initial_vertex_connected())
32432 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32435 const unsigned dst_bnd_id =
32436 tmp_polyline_pt->initial_vertex_connected_bnd_id();
32439 const unsigned dst_chunk =
32440 tmp_polyline_pt->initial_vertex_connected_n_chunk();
32443 Vector<Vector<Node*>> src_bnd_node_pt =
32444 bnd_sorted_segment_node_pt[bnd_id];
32447 Vector<Vector<Node*>> dst_bnd_node_pt =
32448 bnd_sorted_segment_node_pt[dst_bnd_id];
32452 add_non_delete_vertices_from_boundary_helper(
32453 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32458 if (tmp_polyline_pt->is_final_vertex_connected())
32461 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32464 const unsigned dst_bnd_id =
32465 tmp_polyline_pt->final_vertex_connected_bnd_id();
32468 const unsigned dst_chunk =
32469 tmp_polyline_pt->final_vertex_connected_n_chunk();
32472 Vector<Vector<Node*>> src_bnd_node_pt =
32473 bnd_sorted_segment_node_pt[bnd_id];
32476 Vector<Vector<Node*>> dst_bnd_node_pt =
32477 bnd_sorted_segment_node_pt[dst_bnd_id];
32481 add_non_delete_vertices_from_boundary_helper(
32482 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32490 #ifdef OOMPH_HAS_MPI
32497 if (this->is_mesh_distributed())
32500 const unsigned my_rank = this->communicator_pt()->my_rank();
32503 const unsigned n_shared_curves = this->nshared_boundary_curves(my_rank);
32506 for (
unsigned i = 0; i < n_shared_curves; i++)
32510 const unsigned n_polyline = this->nshared_boundary_polyline(my_rank, i);
32514 for (
unsigned p = 0; p < n_polyline; p++)
32517 TriangleMeshPolyLine* tmp_polyline_pt =
32518 this->shared_boundary_polyline_pt(my_rank, i, p);
32521 if (tmp_polyline_pt->is_initial_vertex_connected())
32524 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32527 const unsigned dst_bnd_id =
32528 tmp_polyline_pt->initial_vertex_connected_bnd_id();
32531 const unsigned dst_chunk =
32532 tmp_polyline_pt->initial_vertex_connected_n_chunk();
32535 Vector<Vector<Node*>> src_bnd_node_pt =
32536 bnd_sorted_segment_node_pt[bnd_id];
32539 Vector<Vector<Node*>> dst_bnd_node_pt =
32540 bnd_sorted_segment_node_pt[dst_bnd_id];
32544 add_non_delete_vertices_from_boundary_helper(
32545 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32550 if (tmp_polyline_pt->is_final_vertex_connected())
32553 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32556 const unsigned dst_bnd_id =
32557 tmp_polyline_pt->final_vertex_connected_bnd_id();
32560 const unsigned dst_chunk =
32561 tmp_polyline_pt->final_vertex_connected_n_chunk();
32564 Vector<Vector<Node*>> src_bnd_node_pt =
32565 bnd_sorted_segment_node_pt[bnd_id];
32568 Vector<Vector<Node*>> dst_bnd_node_pt =
32569 bnd_sorted_segment_node_pt[dst_bnd_id];
32573 add_non_delete_vertices_from_boundary_helper(
32574 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32592 template<
class ELEMENT>
32595 Vector<Vector<Node*>> src_bound_segment_node_pt,
32596 Vector<Vector<Node*>> dst_bound_segment_node_pt,
32597 const unsigned& dst_bnd_id,
32598 const unsigned& dst_bnd_chunk)
32601 const unsigned n_seg = src_bound_segment_node_pt.size();
32603 for (
unsigned iseg = 0; iseg < n_seg; iseg++)
32606 const unsigned nnode = src_bound_segment_node_pt[iseg].size();
32608 Node* left_node_pt = src_bound_segment_node_pt[iseg][0];
32609 Node* right_node_pt = src_bound_segment_node_pt[iseg][nnode - 1];
32612 const unsigned n_dst_seg = dst_bound_segment_node_pt.size();
32614 for (
unsigned jseg = 0; jseg < n_dst_seg; jseg++)
32617 const unsigned n_dst_node = dst_bound_segment_node_pt[jseg].size();
32620 for (
unsigned jnode = 0; jnode < n_dst_node; jnode++)
32624 Node* tmp_node_pt = dst_bound_segment_node_pt[jseg][jnode];
32627 if (tmp_node_pt == left_node_pt)
32630 Vector<double> vertex(2);
32631 vertex[0] = tmp_node_pt->x(0);
32632 vertex[1] = tmp_node_pt->x(1);
32638 Boundary_connections_pt[dst_bnd_id].insert(vertex);
32646 else if (tmp_node_pt == right_node_pt)
32649 Vector<double> vertex(2);
32650 vertex[0] = tmp_node_pt->x(0);
32651 vertex[1] = tmp_node_pt->x(1);
32659 Boundary_connections_pt[dst_bnd_id].insert(vertex);
32673 #ifdef OOMPH_HAS_MPI
32679 template<
class ELEMENT>
32681 ELEMENT>::synchronize_shared_boundary_connections()
32684 const unsigned nproc = this->communicator_pt()->nproc();
32686 const unsigned my_rank = this->communicator_pt()->my_rank();
32689 for (
unsigned jproc = 0; jproc < nproc; jproc++)
32694 const unsigned n_shd_bnd_jproc = this->nshared_boundaries(my_rank, jproc);
32698 if (jproc != my_rank && n_shd_bnd_jproc > 0)
32702 Vector<unsigned> shd_bnd_id_for_non_deletion;
32706 Vector<unsigned> chunk_for_non_deletion;
32710 Vector<unsigned> number_vertices_non_deletion;
32713 Vector<Vector<Vector<double>>> vertices_for_non_deletion;
32717 Vector<unsigned> shd_bnd_ids =
32718 this->shared_boundaries_ids(my_rank, jproc);
32721 const unsigned n_shd_bnd_jproc = shd_bnd_ids.size();
32723 for (
unsigned ishd_bnd = 0; ishd_bnd < n_shd_bnd_jproc; ishd_bnd++)
32726 const unsigned shd_bnd_id = shd_bnd_ids[ishd_bnd];
32728 TriangleMeshPolyLine* shd_polyline_pt =
32729 this->boundary_polyline_pt(shd_bnd_id);
32731 const unsigned chunk = shd_polyline_pt->boundary_chunk();
32734 std::set<Vector<double>> no_delete_vertex;
32737 const bool boundary_receive_connections =
32738 this->boundary_connections(shd_bnd_id, chunk, no_delete_vertex);
32741 const unsigned n_non_delete_vertex = no_delete_vertex.size();
32744 if (boundary_receive_connections && n_non_delete_vertex > 0)
32747 shd_bnd_id_for_non_deletion.push_back(shd_bnd_id);
32749 chunk_for_non_deletion.push_back(chunk);
32751 number_vertices_non_deletion.push_back(n_non_delete_vertex);
32754 Vector<Vector<double>> tmp_vertices;
32757 for (std::set<Vector<double>>::iterator it =
32758 no_delete_vertex.begin();
32759 it != no_delete_vertex.end();
32763 Vector<double> vertex = (*it);
32764 tmp_vertices.push_back(vertex);
32768 vertices_for_non_deletion.push_back(tmp_vertices);
32782 OomphCommunicator* comm_pt = this->communicator_pt();
32786 MPI_Request request;
32792 const unsigned n_shd_bnd_with_non_delete_vertices =
32793 shd_bnd_id_for_non_deletion.size();
32796 const unsigned size_package = 3;
32798 const unsigned n_unsigned_data_to_send =
32799 n_shd_bnd_with_non_delete_vertices * size_package;
32801 Vector<unsigned> flat_package_unsigned_send(n_unsigned_data_to_send);
32802 Vector<double> flat_package_double_send;
32804 Vector<unsigned> flat_package_unsigned_recv;
32805 Vector<double> flat_package_double_recv;
32809 for (
unsigned i = 0; i < n_shd_bnd_with_non_delete_vertices; i++)
32812 flat_package_unsigned_send[j++] = shd_bnd_id_for_non_deletion[i];
32814 flat_package_unsigned_send[j++] = chunk_for_non_deletion[i];
32816 flat_package_unsigned_send[j++] = number_vertices_non_deletion[i];
32818 const unsigned n_vertices_non_deletion =
32819 number_vertices_non_deletion[i];
32822 for (
unsigned h = 0; h < n_vertices_non_deletion; h++)
32824 flat_package_double_send.push_back(
32825 vertices_for_non_deletion[i][h][0]);
32826 flat_package_double_send.push_back(
32827 vertices_for_non_deletion[i][h][1]);
32833 int send_proc = jproc;
32834 int recv_proc = jproc;
32835 unsigned send_count_unsigned_values = n_unsigned_data_to_send;
32836 unsigned send_count_double_values = flat_package_double_send.size();
32841 MPI_Isend(&send_count_unsigned_values,
32846 comm_pt->mpi_comm(),
32849 unsigned receive_count_unsigned_values = 0;
32850 MPI_Recv(&receive_count_unsigned_values,
32855 comm_pt->mpi_comm(),
32858 MPI_Wait(&request, MPI_STATUS_IGNORE);
32861 if (send_count_unsigned_values != 0)
32863 MPI_Isend(&flat_package_unsigned_send[0],
32864 send_count_unsigned_values,
32868 comm_pt->mpi_comm(),
32873 if (receive_count_unsigned_values != 0)
32875 flat_package_unsigned_recv.resize(receive_count_unsigned_values);
32876 MPI_Recv(&flat_package_unsigned_recv[0],
32877 receive_count_unsigned_values,
32881 comm_pt->mpi_comm(),
32887 if (send_count_unsigned_values != 0)
32889 MPI_Wait(&request, MPI_STATUS_IGNORE);
32894 MPI_Isend(&send_count_double_values,
32899 comm_pt->mpi_comm(),
32902 unsigned receive_count_double_values = 0;
32903 MPI_Recv(&receive_count_double_values,
32908 comm_pt->mpi_comm(),
32911 MPI_Wait(&request, MPI_STATUS_IGNORE);
32914 if (send_count_double_values != 0)
32916 MPI_Isend(&flat_package_double_send[0],
32917 send_count_double_values,
32921 comm_pt->mpi_comm(),
32926 if (receive_count_double_values != 0)
32928 flat_package_double_recv.resize(receive_count_double_values);
32929 MPI_Recv(&flat_package_double_recv[0],
32930 receive_count_double_values,
32934 comm_pt->mpi_comm(),
32940 if (send_count_double_values != 0)
32942 MPI_Wait(&request, MPI_STATUS_IGNORE);
32955 Vector<unsigned> recv_shd_bnd_id_for_non_deletion;
32959 Vector<unsigned> recv_chunk_for_non_deletion;
32963 Vector<unsigned> recv_number_vertices_non_deletion;
32966 Vector<Vector<Vector<double>>> recv_vertices_for_non_deletion;
32970 for (
unsigned i = 0; i < receive_count_unsigned_values; i += 3)
32973 const unsigned recv_shd_bnd_id = flat_package_unsigned_recv[i];
32974 recv_shd_bnd_id_for_non_deletion.push_back(recv_shd_bnd_id);
32976 const unsigned recv_chunk = flat_package_unsigned_recv[i + 1];
32977 recv_chunk_for_non_deletion.push_back(recv_chunk);
32979 const unsigned recv_num_vertices = flat_package_unsigned_recv[i + 2];
32980 recv_number_vertices_non_deletion.push_back(recv_num_vertices);
32983 Vector<Vector<double>> temp_recv_vertices;
32985 for (
unsigned h = 0; h < recv_num_vertices; h++)
32987 Vector<double> tmp_vertex(2);
32988 tmp_vertex[0] = flat_package_double_recv[j++];
32989 tmp_vertex[1] = flat_package_double_recv[j++];
32991 temp_recv_vertices.push_back(tmp_vertex);
32995 recv_vertices_for_non_deletion.push_back(temp_recv_vertices);
33010 const unsigned n_recv_shd_bnd_id_for_non_deletion =
33011 recv_shd_bnd_id_for_non_deletion.size();
33014 for (
unsigned i = 0; i < n_recv_shd_bnd_id_for_non_deletion; i++)
33017 const unsigned shd_bnd_id = recv_shd_bnd_id_for_non_deletion[i];
33019 unsigned chunk = recv_chunk_for_non_deletion[i];
33026 const unsigned n_vertices = recv_number_vertices_non_deletion[i];
33028 for (
unsigned h = 0; h < n_vertices; h++)
33031 Vector<double> vertex(2);
33032 vertex[0] = recv_vertices_for_non_deletion[i][h][0];
33033 vertex[1] = recv_vertices_for_non_deletion[i][h][1];
33038 Boundary_connections_pt[shd_bnd_id].insert(vertex);
33055 template<
class ELEMENT>
33057 Vector<TriangleMeshPolygon*>& tmp_outer_polygons_pt,
33058 Vector<TriangleMeshOpenCurve*>& tmp_open_curves_pt)
33061 Vector<TriangleMeshPolyLine*> dummy_resume_initial_connection_polyline_pt;
33062 Vector<TriangleMeshPolyLine*> dummy_resume_final_connection_polyline_pt;
33065 dummy_resume_initial_connection_polyline_pt.clear();
33066 dummy_resume_final_connection_polyline_pt.clear();
33070 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
33088 const unsigned n_outer_boundaries = tmp_outer_polygons_pt.size();
33091 for (
unsigned i = 0; i < n_outer_boundaries; i++)
33094 TriangleMeshPolygon* tmp_polygon_pt = tmp_outer_polygons_pt[i];
33097 const unsigned n_polyline = tmp_polygon_pt->npolyline();
33099 for (
unsigned p = 0; p < n_polyline; p++)
33102 TriangleMeshPolyLine* tmp_polyline_pt = tmp_polygon_pt->polyline_pt(p);
33105 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
33108 if (bnd_id < init_shd_bnd_id)
33111 restore_polyline_connections_helper(
33113 dummy_resume_initial_connection_polyline_pt,
33114 dummy_resume_final_connection_polyline_pt);
33131 const unsigned n_open_boundaries = tmp_open_curves_pt.size();
33134 for (
unsigned i = 0; i < n_open_boundaries; i++)
33137 TriangleMeshOpenCurve* tmp_open_curve_pt = tmp_open_curves_pt[i];
33141 const unsigned n_curve_section = tmp_open_curve_pt->ncurve_section();
33144 for (
unsigned p = 0; p < n_curve_section; p++)
33148 TriangleMeshPolyLine* tmp_polyline_pt =
33149 tmp_open_curve_pt->polyline_pt(p);
33152 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
33155 if (bnd_id < init_shd_bnd_id)
33158 restore_polyline_connections_helper(
33160 dummy_resume_initial_connection_polyline_pt,
33161 dummy_resume_final_connection_polyline_pt);
33180 template<
class ELEMENT>
33182 Vector<TriangleMeshPolyLine*>& resume_initial_connection_polyline_pt,
33183 Vector<TriangleMeshPolyLine*>& resume_final_connection_polyline_pt)
33186 resume_initial_connection_polyline_pt.clear();
33187 resume_final_connection_polyline_pt.clear();
33198 const unsigned n_outer_boundaries = this->Outer_boundary_pt.size();
33201 for (
unsigned i = 0; i < n_outer_boundaries; i++)
33204 TriangleMeshPolygon* tmp_polygon_pt = this->Outer_boundary_pt[i];
33207 const unsigned n_polyline = tmp_polygon_pt->npolyline();
33209 for (
unsigned p = 0; p < n_polyline; p++)
33212 TriangleMeshPolyLine* tmp_polyline_pt = tmp_polygon_pt->polyline_pt(p);
33215 restore_polyline_connections_helper(
33217 resume_initial_connection_polyline_pt,
33218 resume_final_connection_polyline_pt);
33229 const unsigned n_internal_boundaries = this->Internal_polygon_pt.size();
33232 for (
unsigned i = 0; i < n_internal_boundaries; i++)
33235 TriangleMeshPolygon* tmp_polygon_pt = this->Internal_polygon_pt[i];
33238 const unsigned n_polyline = tmp_polygon_pt->npolyline();
33240 for (
unsigned p = 0; p < n_polyline; p++)
33243 TriangleMeshPolyLine* tmp_polyline_pt = tmp_polygon_pt->polyline_pt(p);
33246 restore_polyline_connections_helper(
33248 resume_initial_connection_polyline_pt,
33249 resume_final_connection_polyline_pt);
33260 const unsigned n_open_boundaries = this->Internal_open_curve_pt.size();
33263 for (
unsigned i = 0; i < n_open_boundaries; i++)
33266 TriangleMeshOpenCurve* tmp_open_curve_pt =
33267 this->Internal_open_curve_pt[i];
33271 const unsigned n_curve_section = tmp_open_curve_pt->ncurve_section();
33274 for (
unsigned p = 0; p < n_curve_section; p++)
33278 TriangleMeshPolyLine* tmp_polyline_pt =
33279 tmp_open_curve_pt->polyline_pt(p);
33282 restore_polyline_connections_helper(
33284 resume_initial_connection_polyline_pt,
33285 resume_final_connection_polyline_pt);
33300 template<
class ELEMENT>
33302 TriangleMeshPolyLine* polyline_pt,
33303 Vector<TriangleMeshPolyLine*>& resume_initial_connection_polyline_pt,
33304 Vector<TriangleMeshPolyLine*>& resume_final_connection_polyline_pt)
33311 if (polyline_pt->is_initial_vertex_connected())
33314 TriangleMeshPolyLine* poly_to_connect_pt = 0;
33317 const unsigned dst_bnd_id_initial =
33318 polyline_pt->initial_vertex_connected_bnd_id();
33321 Vector<double> src_vertex_coordinates_initial =
33322 polyline_pt->vertex_coordinate(0);
33326 #ifdef OOMPH_HAS_MPI
33327 if (this->is_mesh_distributed())
33330 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
33332 if (dst_bnd_id_initial >= init_shd_bnd_id)
33335 const unsigned bnd_id = polyline_pt->boundary_id();
33336 std::ostringstream error_message;
33338 <<
"INITIAL VERTEX CONNECTION\n"
33339 <<
"The current original boundary is trying to connect to a\n"
33340 <<
"shared boundary, this is not allowed. In this case the\n"
33341 <<
"shared boundary should be the one that connects with the\n"
33342 <<
"original boundary\n"
33343 <<
"The current original boundary (" << bnd_id <<
") is marked\n"
33344 <<
"to have a connection at the\nINITIAL vertex ("
33345 << src_vertex_coordinates_initial[0] <<
","
33346 << src_vertex_coordinates_initial[1] <<
")\n"
33347 <<
"with the shared boundary (" << dst_bnd_id_initial <<
")\n"
33348 <<
"This is the list of vertices on the shared destination "
33352 TriangleMeshPolyLine* dst_polyline =
33353 this->boundary_polyline_pt(dst_bnd_id_initial);
33355 const unsigned n_vertex_dst_boundary = dst_polyline->nvertex();
33357 for (
unsigned i = 0; i < n_vertex_dst_boundary; i++)
33359 Vector<double> current_vertex = dst_polyline->vertex_coordinate(i);
33360 error_message <<
"Vertex#(i): (" << current_vertex[0] <<
", "
33361 << current_vertex[1] <<
")\n";
33363 throw OomphLibError(
33364 error_message.str(),
33365 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33366 OOMPH_EXCEPTION_LOCATION);
33376 bool found_vertex_on_dst_boundary_initial =
false;
33380 unsigned sub_poly_to_connect = 0;
33383 unsigned n_vertex_connection_initial = 0;
33388 bool connecting_to_an_split_boundary =
false;
33392 bool connecting_to_an_overlaped_boundary =
false;
33394 #ifdef OOMPH_HAS_MPI
33395 if (this->is_mesh_distributed())
33400 if (this->boundary_was_splitted(dst_bnd_id_initial))
33402 connecting_to_an_split_boundary =
true;
33411 if (connecting_to_an_split_boundary)
33415 const unsigned n_sub_poly =
33416 this->nboundary_subpolylines(dst_bnd_id_initial);
33420 for (
unsigned ii = 0; ii < n_sub_poly; ii++)
33422 if (this->boundary_marked_as_shared_boundary(dst_bnd_id_initial,
33427 connecting_to_an_overlaped_boundary =
true;
33438 if (this->boundary_marked_as_shared_boundary(dst_bnd_id_initial, 0))
33441 connecting_to_an_overlaped_boundary =
true;
33452 if (!(connecting_to_an_split_boundary ||
33453 connecting_to_an_overlaped_boundary))
33457 poly_to_connect_pt = this->boundary_polyline_pt(dst_bnd_id_initial);
33467 if (!connecting_to_an_split_boundary)
33471 if (!connecting_to_an_overlaped_boundary)
33475 found_vertex_on_dst_boundary_initial =
33476 this->get_connected_vertex_number_on_destination_polyline(
33477 poly_to_connect_pt,
33478 src_vertex_coordinates_initial,
33479 n_vertex_connection_initial);
33492 #ifdef OOMPH_HAS_MPI
33499 Vector<TriangleMeshPolyLine*> tmp_vector_subpolylines =
33500 this->boundary_subpolylines(dst_bnd_id_initial);
33503 const unsigned nsub_poly = tmp_vector_subpolylines.size();
33505 if (nsub_poly <= 1)
33507 std::ostringstream error_message;
33508 error_message <<
"The boundary (" << dst_bnd_id_initial <<
") was "
33509 <<
"marked to be splitted but\n"
33510 <<
"there are only (" << nsub_poly <<
") polylines to "
33511 <<
"represent it.\n";
33512 throw OomphLibError(
33513 error_message.str(),
33514 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33515 OOMPH_EXCEPTION_LOCATION);
33526 if (!connecting_to_an_overlaped_boundary)
33534 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33537 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33539 found_vertex_on_dst_boundary_initial =
33540 this->get_connected_vertex_number_on_destination_polyline(
33541 poly_to_connect_pt,
33542 src_vertex_coordinates_initial,
33543 n_vertex_connection_initial);
33547 if (found_vertex_on_dst_boundary_initial)
33551 sub_poly_to_connect = isub;
33567 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33571 if (!this->boundary_marked_as_shared_boundary(dst_bnd_id_initial,
33575 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33578 found_vertex_on_dst_boundary_initial =
33579 this->get_connected_vertex_number_on_destination_polyline(
33580 poly_to_connect_pt,
33581 src_vertex_coordinates_initial,
33582 n_vertex_connection_initial);
33585 if (found_vertex_on_dst_boundary_initial)
33589 sub_poly_to_connect = isub;
33604 if (!found_vertex_on_dst_boundary_initial)
33607 #ifdef OOMPH_HAS_MPI
33608 if (this->is_mesh_distributed())
33614 polyline_pt->suspend_initial_vertex_connected();
33618 resume_initial_connection_polyline_pt.push_back(polyline_pt);
33630 const unsigned bnd_id = polyline_pt->boundary_id();
33631 std::ostringstream error_message;
33633 <<
"INITIAL VERTEX CONNECTION\n"
33634 <<
"It was not possible to find the associated "
33635 <<
"vertex number on the destination boundary\n"
33636 <<
"The current boundary (" << bnd_id <<
") is marked to have"
33637 <<
"a connection at the\nINITIAL vertex ("
33638 << src_vertex_coordinates_initial[0] <<
","
33639 << src_vertex_coordinates_initial[1] <<
")\n"
33640 <<
"with boundary (" << dst_bnd_id_initial <<
")\n"
33641 <<
"This is the list of vertices on the destination boundary\n";
33644 TriangleMeshPolyLine* dst_polyline =
33645 this->boundary_polyline_pt(dst_bnd_id_initial);
33647 const unsigned n_vertex_dst_boundary = dst_polyline->nvertex();
33649 for (
unsigned i = 0; i < n_vertex_dst_boundary; i++)
33651 Vector<double> current_vertex = dst_polyline->vertex_coordinate(i);
33652 error_message <<
"Vertex#(i): (" << current_vertex[0] <<
", "
33653 << current_vertex[1] <<
")\n";
33655 throw OomphLibError(
33656 error_message.str(),
33657 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33658 OOMPH_EXCEPTION_LOCATION);
33667 polyline_pt->initial_vertex_connected_n_vertex() =
33668 n_vertex_connection_initial;
33671 polyline_pt->initial_vertex_connected_n_chunk() = sub_poly_to_connect;
33679 if (polyline_pt->is_final_vertex_connected())
33682 TriangleMeshPolyLine* poly_to_connect_pt = 0;
33685 const unsigned dst_bnd_id_final =
33686 polyline_pt->final_vertex_connected_bnd_id();
33689 const unsigned tmp_n_vertices = polyline_pt->nvertex();
33690 Vector<double> src_vertex_coordinates_final =
33691 polyline_pt->vertex_coordinate(tmp_n_vertices - 1);
33696 #ifdef OOMPH_HAS_MPI
33697 if (this->is_mesh_distributed())
33700 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
33702 if (dst_bnd_id_final >= init_shd_bnd_id)
33705 const unsigned bnd_id = polyline_pt->boundary_id();
33706 std::ostringstream error_message;
33708 <<
"FINAL VERTEX CONNECTION\n"
33709 <<
"The current original boundary is trying to connect to a\n"
33710 <<
"shared boundary, this is not allowed. In this case the\n"
33711 <<
"shared boundary should be the one that connects with the\n"
33712 <<
"original boundary\n"
33713 <<
"The current boundary (" << bnd_id <<
") is marked to have "
33714 <<
"a connection at the\nFINAL vertex ("
33715 << src_vertex_coordinates_final[0] <<
","
33716 << src_vertex_coordinates_final[1] <<
")\n"
33717 <<
"with boundary (" << dst_bnd_id_final <<
")\n"
33718 <<
"This is the list of vertices on the destination boundary\n";
33721 TriangleMeshPolyLine* dst_polyline =
33722 this->boundary_polyline_pt(dst_bnd_id_final);
33724 const unsigned n_vertex_dst_boundary = dst_polyline->nvertex();
33726 for (
unsigned i = 0; i < n_vertex_dst_boundary; i++)
33728 Vector<double> current_vertex = dst_polyline->vertex_coordinate(i);
33729 error_message <<
"Vertex#(" << i <<
"): (" << current_vertex[0]
33730 <<
", " << current_vertex[1] <<
")\n";
33732 throw OomphLibError(
33733 error_message.str(),
33734 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33735 OOMPH_EXCEPTION_LOCATION);
33745 bool found_vertex_on_dst_boundary_final =
false;
33749 unsigned sub_poly_to_connect = 0;
33752 unsigned n_vertex_connection_final = 0;
33757 bool connecting_to_an_split_boundary =
false;
33761 bool connecting_to_an_overlaped_boundary =
false;
33763 #ifdef OOMPH_HAS_MPI
33764 if (this->is_mesh_distributed())
33769 if (this->boundary_was_splitted(dst_bnd_id_final))
33771 connecting_to_an_split_boundary =
true;
33780 if (connecting_to_an_split_boundary)
33784 const unsigned n_sub_poly =
33785 this->nboundary_subpolylines(dst_bnd_id_final);
33789 for (
unsigned ii = 0; ii < n_sub_poly; ii++)
33791 if (this->boundary_marked_as_shared_boundary(dst_bnd_id_final, ii))
33795 connecting_to_an_overlaped_boundary =
true;
33806 if (this->boundary_marked_as_shared_boundary(dst_bnd_id_final, 0))
33809 connecting_to_an_overlaped_boundary =
true;
33820 if (!(connecting_to_an_split_boundary ||
33821 connecting_to_an_overlaped_boundary))
33825 poly_to_connect_pt = this->boundary_polyline_pt(dst_bnd_id_final);
33835 if (!connecting_to_an_split_boundary)
33839 if (!connecting_to_an_overlaped_boundary)
33843 found_vertex_on_dst_boundary_final =
33844 this->get_connected_vertex_number_on_destination_polyline(
33845 poly_to_connect_pt,
33846 src_vertex_coordinates_final,
33847 n_vertex_connection_final);
33860 #ifdef OOMPH_HAS_MPI
33867 Vector<TriangleMeshPolyLine*> tmp_vector_subpolylines =
33868 this->boundary_subpolylines(dst_bnd_id_final);
33871 const unsigned nsub_poly = tmp_vector_subpolylines.size();
33873 if (nsub_poly <= 1)
33875 std::ostringstream error_message;
33876 error_message <<
"The boundary (" << dst_bnd_id_final <<
") was "
33877 <<
"marked to be splitted but\n"
33878 <<
"there are only (" << nsub_poly <<
") polylines to "
33879 <<
"represent it.\n";
33880 throw OomphLibError(
33881 error_message.str(),
33882 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33883 OOMPH_EXCEPTION_LOCATION);
33894 if (!connecting_to_an_overlaped_boundary)
33902 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33905 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33907 found_vertex_on_dst_boundary_final =
33908 this->get_connected_vertex_number_on_destination_polyline(
33909 poly_to_connect_pt,
33910 src_vertex_coordinates_final,
33911 n_vertex_connection_final);
33915 if (found_vertex_on_dst_boundary_final)
33919 sub_poly_to_connect = isub;
33935 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33939 if (!this->boundary_marked_as_shared_boundary(dst_bnd_id_final,
33943 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33946 found_vertex_on_dst_boundary_final =
33947 this->get_connected_vertex_number_on_destination_polyline(
33948 poly_to_connect_pt,
33949 src_vertex_coordinates_final,
33950 n_vertex_connection_final);
33953 if (found_vertex_on_dst_boundary_final)
33957 sub_poly_to_connect = isub;
33972 if (!found_vertex_on_dst_boundary_final)
33975 #ifdef OOMPH_HAS_MPI
33976 if (this->is_mesh_distributed())
33982 polyline_pt->suspend_final_vertex_connected();
33986 resume_final_connection_polyline_pt.push_back(polyline_pt);
33998 const unsigned bnd_id = polyline_pt->boundary_id();
33999 std::ostringstream error_message;
34001 <<
"FINAL VERTEX CONNECTION\n"
34002 <<
"It was not possible to find the associated "
34003 <<
"vertex number on the destination boundary\n"
34004 <<
"The current boundary (" << bnd_id <<
") is marked to have "
34005 <<
"a connection at the\nFINAL vertex ("
34006 << src_vertex_coordinates_final[0] <<
","
34007 << src_vertex_coordinates_final[1] <<
")\n"
34008 <<
"with boundary (" << dst_bnd_id_final <<
")\n"
34009 <<
"This is the list of vertices on the destination boundary\n";
34012 TriangleMeshPolyLine* dst_polyline =
34013 this->boundary_polyline_pt(dst_bnd_id_final);
34015 const unsigned n_vertex_dst_boundary = dst_polyline->nvertex();
34017 for (
unsigned i = 0; i < n_vertex_dst_boundary; i++)
34019 Vector<double> current_vertex = dst_polyline->vertex_coordinate(i);
34020 error_message <<
"Vertex#(" << i <<
"): (" << current_vertex[0]
34021 <<
", " << current_vertex[1] <<
")\n";
34023 throw OomphLibError(
34024 error_message.str(),
34025 "RefineableTriangleMesh::restore_polyline_connections_helper()",
34026 OOMPH_EXCEPTION_LOCATION);
34034 polyline_pt->final_vertex_connected_n_vertex() =
34035 n_vertex_connection_final;
34038 polyline_pt->final_vertex_connected_n_chunk() = sub_poly_to_connect;
34053 template<
class ELEMENT>
34055 Vector<TriangleMeshPolyLine*>& resume_initial_connection_polyline_pt,
34056 Vector<TriangleMeshPolyLine*>& resume_final_connection_polyline_pt)
34060 const unsigned n_initial_poly =
34061 resume_initial_connection_polyline_pt.size();
34064 for (
unsigned p = 0; p < n_initial_poly; p++)
34067 TriangleMeshPolyLine* tmp_poly_pt =
34068 resume_initial_connection_polyline_pt[p];
34070 tmp_poly_pt->resume_initial_vertex_connected();
34075 const unsigned n_final_poly = resume_final_connection_polyline_pt.size();
34078 for (
unsigned p = 0; p < n_final_poly; p++)
34081 TriangleMeshPolyLine* tmp_poly_pt =
34082 resume_final_connection_polyline_pt[p];
34084 tmp_poly_pt->resume_final_vertex_connected();
34088 resume_initial_connection_polyline_pt.clear();
34089 resume_final_connection_polyline_pt.clear();
34096 template<
class ELEMENT>
34099 Vector<double>& vertex_coordinates,
34100 const unsigned& dst_bnd_id,
34101 unsigned& vertex_number)
34103 bool found_associated_vertex_number =
false;
34106 TriangleMeshPolyLine* dst_polyline = this->boundary_polyline_pt(dst_bnd_id);
34108 const unsigned n_vertices = dst_polyline->nvertex();
34112 for (
unsigned i = 0; i < n_vertices; i++)
34114 Vector<double> current_vertex = dst_polyline->vertex_coordinate(i);
34116 double error = (vertex_coordinates[0] - current_vertex[0]) *
34117 (vertex_coordinates[0] - current_vertex[0]) +
34118 (vertex_coordinates[1] - current_vertex[1]) *
34119 (vertex_coordinates[1] - current_vertex[1]);
34121 error = sqrt(error);
34123 if (error < ToleranceForVertexMismatchInPolygons::Tolerable_error)
34126 found_associated_vertex_number =
true;
34131 return found_associated_vertex_number;
34143 template<
class ELEMENT>
34145 TriangleMeshPolygon* polygon_pt,
const bool& check_only)
34153 if (this->is_mesh_distributed() && !check_only)
34155 std::stringstream error_message;
34157 <<
"The updating of polygons of a distributed mesh can ONLY be\n"
34158 <<
"performed using the element's area associated to the halo(ed)\n"
34160 <<
"1) Make sure you have enabled the parallel mesh adaptation\n"
34161 <<
"option if you are working with a distributed mesh, OR\n"
34162 <<
"2) Make sure to call the update_..._using_elements_area() methods\n"
34163 <<
"if the mesh is marked as distributed\n\n";
34164 throw OomphLibError(
34165 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
34171 bool unrefinement_was_performed =
false;
34172 bool refinement_was_performed =
false;
34173 bool max_length_applied =
false;
34176 const unsigned n_polyline = polygon_pt->npolyline();
34181 Vector<Mesh*> face_mesh_pt;
34182 get_face_mesh_representation(polygon_pt, face_mesh_pt);
34186 Vector<double> vertex_coord(3);
34187 Vector<double> bound_left(1);
34188 Vector<double> bound_right(1);
34190 for (
unsigned p = 0; p < n_polyline; p++)
34195 std::set<Vector<double>> vertex_nodes;
34198 const unsigned bound = polygon_pt->curve_section_pt(p)->boundary_id();
34201 const unsigned chunk = polygon_pt->curve_section_pt(p)->boundary_chunk();
34204 unsigned n_face_element = face_mesh_pt[p]->nelement();
34205 for (
unsigned e = 0; e < n_face_element; ++e)
34207 FiniteElement* el_pt = face_mesh_pt[p]->finite_element_pt(e);
34209 #ifdef OOMPH_HAS_MPI
34211 if (this->is_mesh_distributed() && el_pt->is_halo())
34217 unsigned n_node = el_pt->nnode();
34222 el_pt->node_pt(0)->get_coordinates_on_boundary(bound, bound_left);
34223 vertex_coord[0] = bound_left[0];
34226 for (
unsigned i = 0; i < 2; i++)
34228 vertex_coord[i + 1] = el_pt->node_pt(0)->x(i);
34230 vertex_nodes.insert(vertex_coord);
34235 el_pt->node_pt(n_node - 1)
34236 ->get_coordinates_on_boundary(bound, bound_right);
34237 vertex_coord[0] = bound_right[0];
34240 for (
unsigned i = 0; i < 2; i++)
34242 vertex_coord[i + 1] = el_pt->node_pt(n_node - 1)->x(i);
34244 vertex_nodes.insert(vertex_coord);
34248 unsigned n_poly_vertex = vertex_nodes.size();
34249 Vector<Vector<double>> tmp_vector_vertex_node(n_poly_vertex);
34250 unsigned count = 0;
34251 for (std::set<Vector<double>>::iterator it = vertex_nodes.begin();
34252 it != vertex_nodes.end();
34255 tmp_vector_vertex_node[count].resize(3);
34256 tmp_vector_vertex_node[count][0] = (*it)[0];
34257 tmp_vector_vertex_node[count][1] = (*it)[1];
34258 tmp_vector_vertex_node[count][2] = (*it)[2];
34263 unsigned n_vertex = tmp_vector_vertex_node.size();
34267 double unrefinement_tolerance =
34268 polygon_pt->polyline_pt(p)->unrefinement_tolerance();
34273 if (unrefinement_tolerance > 0.0 && n_vertex >= 3)
34275 unrefinement_was_performed = unrefine_boundary(bound,
34277 tmp_vector_vertex_node,
34278 unrefinement_tolerance,
34284 if (check_only && unrefinement_was_performed)
34288 for (
unsigned p = 0; p < n_polyline; p++)
34290 face_mesh_pt[p]->flush_node_storage();
34291 delete face_mesh_pt[p];
34300 n_vertex = tmp_vector_vertex_node.size();
34305 double refinement_tolerance =
34306 polygon_pt->polyline_pt(p)->refinement_tolerance();
34307 if (refinement_tolerance > 0.0 && n_vertex >= 2)
34309 refinement_was_performed = refine_boundary(face_mesh_pt[p],
34310 tmp_vector_vertex_node,
34311 refinement_tolerance,
34317 if (check_only && refinement_was_performed)
34321 for (
unsigned p = 0; p < n_polyline; p++)
34323 face_mesh_pt[p]->flush_node_storage();
34324 delete face_mesh_pt[p];
34334 n_vertex = tmp_vector_vertex_node.size();
34339 double maximum_length = polygon_pt->polyline_pt(p)->maximum_length();
34340 if (maximum_length > 0.0 && n_vertex >= 2)
34342 max_length_applied = apply_max_length_constraint(
34343 face_mesh_pt[p], tmp_vector_vertex_node, maximum_length);
34347 if (check_only && max_length_applied)
34351 for (
unsigned p = 0; p < n_polyline; p++)
34353 face_mesh_pt[p]->flush_node_storage();
34354 delete face_mesh_pt[p];
34362 n_vertex = tmp_vector_vertex_node.size();
34363 Vector<Vector<double>> vector_vertex_node(n_vertex);
34365 for (
unsigned i = 0; i < n_vertex; i++)
34367 vector_vertex_node[i].resize(2);
34368 vector_vertex_node[i][0] = tmp_vector_vertex_node[i][1];
34369 vector_vertex_node[i][1] = tmp_vector_vertex_node[i][2];
34372 #ifdef OOMPH_HAS_MPI
34376 if (!this->is_mesh_distributed())
34379 if ((p > 0) && !check_only)
34382 Vector<double> final_vertex_of_previous_segment;
34383 unsigned n_prev_vertex =
34384 polygon_pt->curve_section_pt(p - 1)->nvertex();
34385 final_vertex_of_previous_segment =
34386 polygon_pt->polyline_pt(p - 1)->vertex_coordinate(n_prev_vertex -
34389 unsigned prev_seg_boundary_id =
34390 polygon_pt->curve_section_pt(p - 1)->boundary_id();
34394 double error = 0.0;
34395 for (
unsigned i = 0; i < 2; i++)
34397 const double dist = final_vertex_of_previous_segment[i] -
34398 (*vector_vertex_node.begin())[i];
34399 error += dist * dist;
34401 error = sqrt(error);
34405 if (error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
34409 double rev_error = 0.0;
34410 for (
unsigned i = 0; i < 2; i++)
34412 const double dist = final_vertex_of_previous_segment[i] -
34413 (*--vector_vertex_node.end())[i];
34414 rev_error += dist * dist;
34416 rev_error = sqrt(rev_error);
34419 ToleranceForVertexMismatchInPolygons::Tolerable_error)
34428 Vector<double> initial_vertex_of_previous_segment;
34430 initial_vertex_of_previous_segment =
34431 polygon_pt->polyline_pt(p - 1)->vertex_coordinate(0);
34433 unsigned prev_seg_boundary_id =
34434 polygon_pt->curve_section_pt(p - 1)->boundary_id();
34438 double error = 0.0;
34439 for (
unsigned i = 0; i < 2; i++)
34441 const double dist = initial_vertex_of_previous_segment[i] -
34442 (*vector_vertex_node.begin())[i];
34443 error += dist * dist;
34445 error = sqrt(error);
34450 ToleranceForVertexMismatchInPolygons::Tolerable_error)
34454 double rev_error = 0.0;
34455 for (
unsigned i = 0; i < 2; i++)
34457 const double dist = initial_vertex_of_previous_segment[i] -
34458 (*--vector_vertex_node.end())[i];
34459 rev_error += dist * dist;
34466 ToleranceForVertexMismatchInPolygons::Tolerable_error)
34468 std::ostringstream error_stream;
34470 <<
"The distance between the first node of the current\n"
34471 <<
"line segment (boundary " << bound
34472 <<
") and either end of "
34473 <<
"the previous line segment\n"
34474 <<
"(boundary " << prev_seg_boundary_id
34475 <<
") is bigger than "
34476 <<
"the desired tolerance "
34477 << ToleranceForVertexMismatchInPolygons::Tolerable_error
34479 <<
"This suggests that the polylines defining the "
34481 <<
"representation are not properly ordered.\n"
34482 <<
"Fail on last vertex of polyline: ("
34483 << prev_seg_boundary_id
34484 <<
") and\nfirst vertex of polyline (" << bound
34485 <<
").\nThis should have failed when first trying to "
34486 <<
"construct the\npolygon.\n";
34487 throw OomphLibError(error_stream.str(),
34488 OOMPH_CURRENT_FUNCTION,
34489 OOMPH_EXCEPTION_LOCATION);
34496 std::reverse(vector_vertex_node.begin(),
34497 vector_vertex_node.end());
34499 polygon_pt->polyline_pt(p - 1)->reverse();
34505 polygon_pt->polyline_pt(p - 1)->reverse();
34511 std::ostringstream error_stream;
34513 <<
"The distance between the first node of the current\n"
34514 <<
"line segment (boundary " << bound
34515 <<
") and either end of "
34516 <<
"the previous line segment\n"
34517 <<
"(boundary " << prev_seg_boundary_id
34518 <<
") is bigger than the "
34519 <<
"desired tolerance "
34520 << ToleranceForVertexMismatchInPolygons::Tolerable_error
34522 <<
"This suggests that the polylines defining the polygonal\n"
34523 <<
"representation are not properly ordered.\n"
34524 <<
"Fail on last vertex of polyline: ("
34525 << prev_seg_boundary_id <<
") and\nfirst vertex of polyline ("
34527 <<
"This should have failed when first trying to construct "
34530 throw OomphLibError(error_stream.str(),
34531 OOMPH_CURRENT_FUNCTION,
34532 OOMPH_EXCEPTION_LOCATION);
34538 std::reverse(vector_vertex_node.begin(),
34539 vector_vertex_node.end());
34550 TriangleMeshPolyLine* tmp_polyline_pt =
34551 new TriangleMeshPolyLine(vector_vertex_node, bound);
34555 TriangleMeshCurveSection* tmp_curve_section_pt = tmp_polyline_pt;
34558 tmp_polyline_pt->set_unrefinement_tolerance(unrefinement_tolerance);
34559 tmp_polyline_pt->set_refinement_tolerance(refinement_tolerance);
34562 tmp_polyline_pt->set_maximum_length(maximum_length);
34566 this->copy_connection_information(polygon_pt->polyline_pt(p),
34567 tmp_curve_section_pt);
34570 std::set<TriangleMeshCurveSection*>::iterator it =
34571 this->Free_curve_section_pt.find(polygon_pt->curve_section_pt(p));
34573 if (it != this->Free_curve_section_pt.end())
34575 this->Free_curve_section_pt.erase(it);
34576 delete polygon_pt->curve_section_pt(p);
34581 polygon_pt->curve_section_pt(p) = tmp_polyline_pt;
34584 this->Boundary_curve_section_pt[bound] =
34585 polygon_pt->curve_section_pt(p);
34589 this->Free_curve_section_pt.insert(polygon_pt->curve_section_pt(p));
34597 for (
unsigned p = 0; p < n_polyline; p++)
34599 face_mesh_pt[p]->flush_node_storage();
34600 delete face_mesh_pt[p];
34614 return (unrefinement_was_performed || refinement_was_performed ||
34615 max_length_applied);
34628 template<
class ELEMENT>
34630 TriangleMeshOpenCurve* open_polyline_pt,
const bool& check_only)
34638 if (this->is_mesh_distributed() && !check_only)
34640 std::stringstream error_message;
34642 <<
"The updating of open curves of a distributed mesh can ONLY be\n"
34643 <<
"performed using the element's area associated to the halo(ed)\n"
34645 <<
"1) Make sure you have enabled the parallel mesh adaptation\n"
34646 <<
"option if you are working with a distributed mesh, OR\n"
34647 <<
"2) Make sure to call the update_..._using_elements_area() methods\n"
34648 <<
"if the mesh is marked as distributed\n\n";
34649 throw OomphLibError(
34650 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
34656 bool unrefinement_was_performed =
false;
34657 bool refinement_was_performed =
false;
34658 bool max_length_applied =
false;
34661 const unsigned n_polyline = open_polyline_pt->ncurve_section();
34666 Vector<Mesh*> face_mesh_pt;
34667 get_face_mesh_representation(open_polyline_pt, face_mesh_pt);
34671 Vector<double> vertex_coord(3);
34672 Vector<double> bound_left(1);
34673 Vector<double> bound_right(1);
34675 for (
unsigned p = 0; p < n_polyline; p++)
34680 std::set<Vector<double>> vertex_nodes;
34683 const unsigned bound =
34684 open_polyline_pt->curve_section_pt(p)->boundary_id();
34687 const unsigned chunk =
34688 open_polyline_pt->curve_section_pt(p)->boundary_chunk();
34691 unsigned n_face_element = face_mesh_pt[p]->nelement();
34694 for (
unsigned e = 0; e < n_face_element; ++e)
34696 FiniteElement* el_pt = face_mesh_pt[p]->finite_element_pt(e);
34697 unsigned n_node = el_pt->nnode();
34702 el_pt->node_pt(0)->get_coordinates_on_boundary(bound, bound_left);
34703 vertex_coord[0] = bound_left[0];
34706 for (
unsigned i = 0; i < 2; i++)
34708 vertex_coord[i + 1] = el_pt->node_pt(0)->x(i);
34710 vertex_nodes.insert(vertex_coord);
34715 el_pt->node_pt(n_node - 1)
34716 ->get_coordinates_on_boundary(bound, bound_right);
34717 vertex_coord[0] = bound_right[0];
34720 for (
unsigned i = 0; i < 2; i++)
34722 vertex_coord[i + 1] = el_pt->node_pt(n_node - 1)->x(i);
34724 vertex_nodes.insert(vertex_coord);
34728 unsigned n_poly_vertex = vertex_nodes.size();
34729 Vector<Vector<double>> tmp_vector_vertex_node(n_poly_vertex);
34730 unsigned count = 0;
34731 for (std::set<Vector<double>>::iterator it = vertex_nodes.begin();
34732 it != vertex_nodes.end();
34735 tmp_vector_vertex_node[count].resize(3);
34736 tmp_vector_vertex_node[count][0] = (*it)[0];
34737 tmp_vector_vertex_node[count][1] = (*it)[1];
34738 tmp_vector_vertex_node[count][2] = (*it)[2];
34743 unsigned n_vertex = tmp_vector_vertex_node.size();
34747 double unrefinement_tolerance =
34748 open_polyline_pt->polyline_pt(p)->unrefinement_tolerance();
34753 if (unrefinement_tolerance > 0.0 && n_vertex >= 3)
34755 unrefinement_was_performed = unrefine_boundary(bound,
34757 tmp_vector_vertex_node,
34758 unrefinement_tolerance,
34764 if (check_only && unrefinement_was_performed)
34768 for (
unsigned p = 0; p < n_polyline; p++)
34770 face_mesh_pt[p]->flush_node_storage();
34771 delete face_mesh_pt[p];
34781 n_vertex = tmp_vector_vertex_node.size();
34786 double refinement_tolerance =
34787 open_polyline_pt->polyline_pt(p)->refinement_tolerance();
34788 if (refinement_tolerance > 0.0 && n_vertex >= 2)
34790 refinement_was_performed = refine_boundary(face_mesh_pt[p],
34791 tmp_vector_vertex_node,
34792 refinement_tolerance,
34798 if (check_only && refinement_was_performed)
34802 for (
unsigned p = 0; p < n_polyline; p++)
34804 face_mesh_pt[p]->flush_node_storage();
34805 delete face_mesh_pt[p];
34815 n_vertex = tmp_vector_vertex_node.size();
34820 double maximum_length =
34821 open_polyline_pt->polyline_pt(p)->maximum_length();
34822 if (maximum_length > 0.0 && n_vertex >= 2)
34824 bool max_length_applied =
false;
34825 max_length_applied = apply_max_length_constraint(
34826 face_mesh_pt[p], tmp_vector_vertex_node, maximum_length);
34830 if (check_only && max_length_applied)
34834 for (
unsigned p = 0; p < n_polyline; p++)
34836 face_mesh_pt[p]->flush_node_storage();
34837 delete face_mesh_pt[p];
34845 n_vertex = tmp_vector_vertex_node.size();
34846 Vector<Vector<double>> vector_vertex_node(n_vertex);
34848 for (
unsigned i = 0; i < n_vertex; i++)
34850 vector_vertex_node[i].resize(2);
34851 vector_vertex_node[i][0] = tmp_vector_vertex_node[i][1];
34852 vector_vertex_node[i][1] = tmp_vector_vertex_node[i][2];
34855 #ifdef OOMPH_HAS_MPI
34859 if (!this->is_mesh_distributed())
34868 if ((p > 0) && !check_only)
34871 Vector<double> final_vertex_of_previous_segment;
34872 open_polyline_pt->polyline_pt(p - 1)->final_vertex_coordinate(
34873 final_vertex_of_previous_segment);
34875 unsigned prev_seg_boundary_id =
34876 open_polyline_pt->curve_section_pt(p - 1)->boundary_id();
34880 double error = 0.0;
34881 for (
unsigned i = 0; i < 2; i++)
34883 const double dist = final_vertex_of_previous_segment[i] -
34884 (*vector_vertex_node.begin())[i];
34885 error += dist * dist;
34887 error = sqrt(error);
34891 if (error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
34896 for (
unsigned i = 0; i < 2; i++)
34898 const double dist = final_vertex_of_previous_segment[i] -
34899 (*--vector_vertex_node.end())[i];
34900 error += dist * dist;
34902 error = sqrt(error);
34904 if (error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
34915 Vector<double> initial_vertex_of_previous_segment;
34916 open_polyline_pt->polyline_pt(p - 1)->initial_vertex_coordinate(
34917 initial_vertex_of_previous_segment);
34922 for (
unsigned i = 0; i < 2; i++)
34924 const double dist = initial_vertex_of_previous_segment[i] -
34925 (*vector_vertex_node.begin())[i];
34926 error += dist * dist;
34928 error = sqrt(error);
34933 ToleranceForVertexMismatchInPolygons::Tolerable_error)
34938 for (
unsigned i = 0; i < 2; i++)
34940 const double dist = initial_vertex_of_previous_segment[i] -
34941 (*--vector_vertex_node.end())[i];
34942 error += dist * dist;
34944 error = sqrt(error);
34947 ToleranceForVertexMismatchInPolygons::Tolerable_error)
34949 std::ostringstream error_stream;
34951 <<
"The distance between the first node of the current\n"
34952 <<
"line segment (boundary " << bound
34953 <<
") and either end of the previous line segment\n"
34954 <<
"(boundary " << prev_seg_boundary_id
34955 <<
") is bigger than "
34956 <<
"the desired tolerance "
34957 << ToleranceForVertexMismatchInPolygons::Tolerable_error
34959 <<
"This suggests that the polylines defining the open "
34961 <<
"representation are not properly ordered.\n"
34962 <<
"Fail on last vertex of polyline: ("
34963 << prev_seg_boundary_id
34964 <<
") and\nfirst vertex of polyline (" << bound <<
").\n"
34965 <<
"This should have failed when first trying to "
34967 <<
"the open curve.\n";
34968 throw OomphLibError(error_stream.str(),
34969 OOMPH_CURRENT_FUNCTION,
34970 OOMPH_EXCEPTION_LOCATION);
34975 open_polyline_pt->polyline_pt(p - 1)->reverse();
34977 std::reverse(vector_vertex_node.begin(),
34978 vector_vertex_node.end());
34984 open_polyline_pt->polyline_pt(p - 1)->reverse();
34989 std::ostringstream error_stream;
34991 <<
"The distance between the first node of the current\n"
34992 <<
"line segment (boundary " << bound
34993 <<
") and either end of "
34994 <<
"the previous line segment\n"
34995 <<
"(boundary " << prev_seg_boundary_id
34996 <<
") is bigger than the "
34997 <<
"desired tolerance "
34998 << ToleranceForVertexMismatchInPolygons::Tolerable_error
35000 <<
"This suggests that the polylines defining the polygonal\n"
35001 <<
"representation are not properly ordered.\n"
35002 <<
"Fail on last vertex of polyline: ("
35003 << prev_seg_boundary_id <<
") and\nfirst vertex of polyline ("
35005 <<
"This should have failed when first trying to construct "
35008 throw OomphLibError(error_stream.str(),
35009 OOMPH_CURRENT_FUNCTION,
35010 OOMPH_EXCEPTION_LOCATION);
35016 std::reverse(vector_vertex_node.begin(),
35017 vector_vertex_node.end());
35029 TriangleMeshPolyLine* tmp_polyline =
35030 new TriangleMeshPolyLine(vector_vertex_node, bound);
35034 TriangleMeshCurveSection* tmp_curve_section = tmp_polyline;
35037 tmp_polyline->set_unrefinement_tolerance(unrefinement_tolerance);
35038 tmp_polyline->set_refinement_tolerance(refinement_tolerance);
35041 tmp_polyline->set_maximum_length(maximum_length);
35045 this->copy_connection_information(open_polyline_pt->polyline_pt(p),
35046 tmp_curve_section);
35048 std::set<TriangleMeshCurveSection*>::iterator it =
35049 this->Free_curve_section_pt.find(
35050 open_polyline_pt->curve_section_pt(p));
35052 bool delete_it_on_destructor =
false;
35054 if (it != this->Free_curve_section_pt.end())
35057 this->Free_curve_section_pt.erase(it);
35058 delete open_polyline_pt->curve_section_pt(p);
35059 delete_it_on_destructor =
true;
35064 open_polyline_pt->curve_section_pt(p) = tmp_polyline;
35067 this->Boundary_curve_section_pt[bound] =
35068 open_polyline_pt->curve_section_pt(p);
35070 if (delete_it_on_destructor)
35072 this->Free_curve_section_pt.insert(
35073 open_polyline_pt->curve_section_pt(p));
35082 for (
unsigned p = 0; p < n_polyline; p++)
35084 face_mesh_pt[p]->flush_node_storage();
35085 delete face_mesh_pt[p];
35099 return (unrefinement_was_performed || refinement_was_performed ||
35100 max_length_applied);
35112 template<
class ELEMENT>
35116 Vector<Vector<double>>& vector_bnd_vertices,
35117 double& unrefinement_tolerance,
35118 const bool& check_only)
35121 std::set<Vector<double>> no_delete_vertex;
35124 const bool boundary_receive_connections =
35125 this->boundary_connections(b, c, no_delete_vertex);
35129 bool unrefinement_was_performed =
false;
35131 unsigned n_vertex = vector_bnd_vertices.size();
35135 unsigned counter = 1;
35141 for (
unsigned i = 1; i <= n_vertex - 2; i += 2)
35144 double a_x = vector_bnd_vertices[i - 1][1];
35145 double a_y = vector_bnd_vertices[i - 1][2];
35146 double b_x = vector_bnd_vertices[i][1];
35147 double b_y = vector_bnd_vertices[i][2];
35148 double c_x = vector_bnd_vertices[i + 1][1];
35149 double c_y = vector_bnd_vertices[i + 1][2];
35151 double a = b_x - a_x;
35152 double b = b_y - a_y;
35153 double c = c_x - a_x;
35154 double d = c_y - a_y;
35156 double e = a * (a_x + b_x) + b * (a_y + b_y);
35157 double f = c * (a_x + c_x) + d * (a_y + c_y);
35159 double g = 2.0 * (a * (c_y - b_y) - b * (c_x - b_x));
35161 bool do_it =
false;
35162 if (std::fabs(g) < 1.0e-14)
35172 double p_x = (d * e - b * f) / g;
35173 double p_y = (a * f - c * e) / g;
35175 double r = sqrt(pow((a_x - p_x), 2) + pow((a_y - p_y), 2));
35177 double rhalfca_x = 0.5 * (a_x - c_x);
35178 double rhalfca_y = 0.5 * (a_y - c_y);
35180 double halfca_squared = pow(rhalfca_x, 2) + pow(rhalfca_y, 2);
35182 double sticky_out_bit = r - sqrt(std::fabs((r * r) - halfca_squared));
35187 if ((sticky_out_bit / (2.0 * sqrt(halfca_squared))) <
35188 unrefinement_tolerance)
35200 if (do_it && boundary_receive_connections)
35203 for (std::set<Vector<double>>::iterator it = no_delete_vertex.begin();
35204 it != no_delete_vertex.end();
35209 const double x = (*it)[0];
35210 const double y = (*it)[1];
35211 double error = (b_x - x) * (b_x - x) + (b_y - y) * (b_y - y);
35212 error = sqrt(error);
35214 if (error < ToleranceForVertexMismatchInPolygons::Tolerable_error)
35227 vector_bnd_vertices[i].resize(0);
35246 if ((counter) == (n_vertex - 1))
35249 unsigned i = vector_bnd_vertices.size() - 2;
35255 if (vector_bnd_vertices[counter - 2].size() != 0)
35274 double a_x = vector_bnd_vertices[n][1];
35275 double a_y = vector_bnd_vertices[n][2];
35276 double b_x = vector_bnd_vertices[i][1];
35277 double b_y = vector_bnd_vertices[i][2];
35278 double c_x = vector_bnd_vertices[i + 1][1];
35279 double c_y = vector_bnd_vertices[i + 1][2];
35281 double a = b_x - a_x;
35282 double b = b_y - a_y;
35283 double c = c_x - a_x;
35284 double d = c_y - a_y;
35286 double e = a * (a_x + b_x) + b * (a_y + b_y);
35287 double f = c * (a_x + c_x) + d * (a_y + c_y);
35289 double g = 2.0 * (a * (c_y - b_y) - b * (c_x - b_x));
35291 bool do_it =
false;
35292 if (std::fabs(g) < 1.0e-14)
35302 double p_x = (d * e - b * f) / g;
35303 double p_y = (a * f - c * e) / g;
35305 double r = sqrt(pow((a_x - p_x), 2) + pow((a_y - p_y), 2));
35307 double rhalfca_x = 0.5 * (a_x - c_x);
35308 double rhalfca_y = 0.5 * (a_y - c_y);
35310 double halfca_squared = pow(rhalfca_x, 2) + pow(rhalfca_y, 2);
35312 double sticky_out_bit = r - sqrt(std::fabs((r * r) - halfca_squared));
35317 if ((sticky_out_bit / (2.0 * sqrt(halfca_squared))) <
35318 unrefinement_tolerance)
35330 if (do_it && boundary_receive_connections)
35333 for (std::set<Vector<double>>::iterator it = no_delete_vertex.begin();
35334 it != no_delete_vertex.end();
35339 const double x = (*it)[0];
35340 const double y = (*it)[1];
35341 double error = (b_x - x) * (b_x - x) + (b_y - y) * (b_y - y);
35342 error = sqrt(error);
35344 if (error < ToleranceForVertexMismatchInPolygons::Tolerable_error)
35357 vector_bnd_vertices[i].resize(0);
35363 Vector<Vector<double>> compact_vector;
35364 compact_vector.reserve(n_vertex);
35365 for (
unsigned i = 0; i < n_vertex; i++)
35368 if (vector_bnd_vertices[i].size() != 0)
35370 compact_vector.push_back(vector_bnd_vertices[i]);
35375 n_vertex = compact_vector.size();
35381 if (n_vertex != vector_bnd_vertices.size())
35383 unrefinement_was_performed =
true;
35387 vector_bnd_vertices.resize(n_vertex);
35388 for (
unsigned i = 0; i < n_vertex; i++)
35390 vector_bnd_vertices[i].resize(3);
35391 vector_bnd_vertices[i][0] = compact_vector[i][0];
35392 vector_bnd_vertices[i][1] = compact_vector[i][1];
35393 vector_bnd_vertices[i][2] = compact_vector[i][2];
35396 return unrefinement_was_performed;
35407 template<
class ELEMENT>
35409 Mesh* face_mesh_pt,
35410 Vector<Vector<double>>& vector_bnd_vertices,
35411 double& refinement_tolerance,
35412 const bool& check_only)
35416 bool refinement_was_performed =
false;
35420 MeshAsGeomObject* mesh_geom_obj_pt =
new MeshAsGeomObject(face_mesh_pt);
35423 unsigned n_vertex = vector_bnd_vertices.size();
35427 Vector<Vector<double>> extended_vector;
35431 extended_vector.reserve(2 * n_vertex);
35434 for (
unsigned inod = 0; inod < n_vertex - 1; inod++)
35437 double zeta_left = vector_bnd_vertices[inod][0];
35440 Vector<double> R_left(2);
35441 for (
unsigned i = 0; i < 2; i++)
35443 R_left[i] = vector_bnd_vertices[inod][i + 1];
35447 double zeta_right = vector_bnd_vertices[inod + 1][0];
35450 Vector<double> R_right(2);
35451 for (
unsigned i = 0; i < 2; i++)
35453 R_right[i] = vector_bnd_vertices[inod + 1][i + 1];
35457 Vector<double> zeta_mid(1);
35458 zeta_mid[0] = 0.5 * (zeta_left + zeta_right);
35462 Vector<double> R_mid(2);
35463 mesh_geom_obj_pt->position(zeta_mid, R_mid);
35467 Vector<double> R_mid_polygon(2);
35468 for (
unsigned i = 0; i < 2; i++)
35470 R_mid_polygon[i] = 0.5 * (R_right[i] + R_left[i]);
35476 sqrt((R_mid[0] - R_mid_polygon[0]) * (R_mid[0] - R_mid_polygon[0]) +
35477 (R_mid[1] - R_mid_polygon[1]) * (R_mid[1] - R_mid_polygon[1]));
35480 double length = sqrt((R_right[0] - R_left[0]) * (R_right[0] - R_left[0]) +
35481 (R_right[1] - R_left[1]) * (R_right[1] - R_left[1]));
35487 if ((distance / length) > refinement_tolerance)
35493 delete mesh_geom_obj_pt;
35497 Vector<double> new_node(3);
35498 new_node[0] = zeta_mid[0];
35499 new_node[1] = R_mid[0];
35500 new_node[2] = R_mid[1];
35503 extended_vector.push_back(vector_bnd_vertices[inod]);
35506 extended_vector.push_back(new_node);
35512 extended_vector.push_back(vector_bnd_vertices[inod]);
35517 extended_vector.push_back(vector_bnd_vertices[n_vertex - 1]);
35520 n_vertex = extended_vector.size();
35525 if (n_vertex != vector_bnd_vertices.size())
35527 refinement_was_performed =
true;
35531 vector_bnd_vertices.resize(n_vertex);
35532 for (
unsigned i = 0; i < n_vertex; i++)
35534 vector_bnd_vertices[i].resize(3);
35535 vector_bnd_vertices[i][0] = extended_vector[i][0];
35536 vector_bnd_vertices[i][1] = extended_vector[i][1];
35537 vector_bnd_vertices[i][2] = extended_vector[i][2];
35542 delete mesh_geom_obj_pt;
35544 return refinement_was_performed;
35553 template<
class ELEMENT>
35555 Mesh* face_mesh_pt,
35556 Vector<Vector<double>>& vector_bnd_vertices,
35557 double& max_length_constraint)
35561 bool max_length_applied =
false;
35565 MeshAsGeomObject* mesh_geom_obj_pt =
new MeshAsGeomObject(face_mesh_pt);
35568 unsigned n_vertex = vector_bnd_vertices.size();
35572 Vector<Vector<double>> extended_vector;
35575 for (
unsigned inod = 0; inod < n_vertex - 1; inod++)
35578 double zeta_left = vector_bnd_vertices[inod][0];
35581 Vector<double> R_left(2);
35582 for (
unsigned i = 0; i < 2; i++)
35584 R_left[i] = vector_bnd_vertices[inod][i + 1];
35588 double zeta_right = vector_bnd_vertices[inod + 1][0];
35591 Vector<double> R_right(2);
35592 for (
unsigned i = 0; i < 2; i++)
35594 R_right[i] = vector_bnd_vertices[inod + 1][i + 1];
35598 extended_vector.push_back(vector_bnd_vertices[inod]);
35602 double length = std::fabs(zeta_right - zeta_left);
35605 if (length > max_length_constraint)
35607 double n_pts = length / max_length_constraint;
35609 unsigned n_points =
static_cast<unsigned>(n_pts);
35610 double zeta_increment =
35611 (zeta_right - zeta_left) / ((
double)n_points + 1);
35613 Vector<double> zeta(1);
35615 for (
unsigned s = 1; s < n_points + 1; s++)
35618 zeta[0] = zeta_left + zeta_increment * double(s);
35619 Vector<double> vertex(2);
35620 mesh_geom_obj_pt->position(zeta, vertex);
35623 Vector<double> new_node(3);
35624 new_node[0] = zeta[0];
35625 new_node[1] = vertex[0];
35626 new_node[2] = vertex[1];
35629 extended_vector.push_back(new_node);
35635 extended_vector.push_back(vector_bnd_vertices[n_vertex - 1]);
35638 n_vertex = extended_vector.size();
35643 if (n_vertex != vector_bnd_vertices.size())
35645 max_length_applied =
true;
35649 vector_bnd_vertices.resize(n_vertex);
35650 for (
unsigned i = 0; i < n_vertex; i++)
35652 vector_bnd_vertices[i].resize(3);
35653 vector_bnd_vertices[i][0] = extended_vector[i][0];
35654 vector_bnd_vertices[i][1] = extended_vector[i][1];
35655 vector_bnd_vertices[i][2] = extended_vector[i][2];
35660 delete mesh_geom_obj_pt;
35662 return max_length_applied;
35671 template<
class ELEMENT>
35674 Mesh* face_mesh_pt)
35681 this->
template build_face_mesh<ELEMENT, FaceElementAsGeomObject>(
35682 boundary_id, face_mesh_pt);
35685 unsigned n_element = face_mesh_pt->nelement();
35687 for (
unsigned e = 0; e < n_element; e++)
35690 FaceElementAsGeomObject<ELEMENT>* el_pt =
35691 dynamic_cast<FaceElementAsGeomObject<ELEMENT>*
>(
35692 face_mesh_pt->element_pt(e));
35695 el_pt->set_boundary_number_in_bulk_mesh(boundary_id);
35704 template<
class ELEMENT>
35706 const unsigned& boundary_id,
35707 Mesh* face_mesh_pt,
35708 std::map<FiniteElement*, bool>& is_inverted,
35709 bool& inverted_face_mesh)
35711 Mesh* tmp_unsorted_face_mesh_pt =
new Mesh();
35714 create_unsorted_face_mesh_representation(boundary_id,
35715 tmp_unsorted_face_mesh_pt);
35725 std::list<FiniteElement*> sorted_el_pt;
35726 FiniteElement* el_pt = tmp_unsorted_face_mesh_pt->finite_element_pt(0);
35727 sorted_el_pt.push_back(el_pt);
35730 unsigned nnod = el_pt->nnode();
35733 unsigned count_done = 0;
35736 unsigned n_face_element = tmp_unsorted_face_mesh_pt->nelement();
35739 std::map<FiniteElement*, bool> done_el;
35741 is_inverted.clear();
35744 for (
unsigned ee = 1; ee < n_face_element; ee++)
35748 for (
unsigned e = 1; e < n_face_element; e++)
35751 el_pt = tmp_unsorted_face_mesh_pt->finite_element_pt(e);
35754 if (!done_el[el_pt])
35757 FiniteElement* first_el_pt = (*sorted_el_pt.begin());
35758 std::list<FiniteElement*>::iterator it = sorted_el_pt.end();
35760 FiniteElement* last_el_pt = *it;
35763 Node* left_node_pt = first_el_pt->node_pt(0);
35764 if (is_inverted[first_el_pt])
35766 left_node_pt = first_el_pt->node_pt(nnod - 1);
35768 Node* right_node_pt = last_el_pt->node_pt(nnod - 1);
35769 if (is_inverted[last_el_pt])
35771 right_node_pt = last_el_pt->node_pt(0);
35775 if (left_node_pt == el_pt->node_pt(nnod - 1))
35777 sorted_el_pt.push_front(el_pt);
35778 done_el[el_pt] =
true;
35780 is_inverted[el_pt] =
false;
35784 else if (left_node_pt == el_pt->node_pt(0))
35786 sorted_el_pt.push_front(el_pt);
35787 done_el[el_pt] =
true;
35789 is_inverted[el_pt] =
true;
35793 else if (right_node_pt == el_pt->node_pt(0))
35795 sorted_el_pt.push_back(el_pt);
35796 done_el[el_pt] =
true;
35798 is_inverted[el_pt] =
false;
35802 else if (right_node_pt == el_pt->node_pt(nnod - 1))
35804 sorted_el_pt.push_back(el_pt);
35805 done_el[el_pt] =
true;
35807 is_inverted[el_pt] =
true;
35810 if (done_el[el_pt])
35819 if (count_done != (n_face_element - 1))
35821 std::ostringstream error_message;
35822 error_message <<
"When ordering FaceElements on "
35823 <<
"boundary " << boundary_id <<
" only managed to order \n"
35824 << count_done <<
" of " << n_face_element
35825 <<
" face elements.\n"
35827 throw OomphLibError(
35828 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
35835 for (std::list<FiniteElement*>::iterator it = sorted_el_pt.begin();
35836 it != sorted_el_pt.end();
35840 FiniteElement* el_pt = *it;
35843 face_mesh_pt->add_element_pt(el_pt);
35853 TriangleMeshPolyLine* bnd_polyline =
35854 this->Boundary_curve_section_pt[boundary_id];
35857 Vector<double> first_vertex = bnd_polyline->vertex_coordinate(0);
35861 FiniteElement* first_el_pt = face_mesh_pt->finite_element_pt(0);
35864 unsigned n_node = first_el_pt->nnode();
35867 Node* first_node_pt = first_el_pt->node_pt(0);
35868 if (is_inverted[first_el_pt])
35870 first_node_pt = first_el_pt->node_pt(n_node - 1);
35873 double error = (first_node_pt->x(0) - first_vertex[0]) *
35874 (first_node_pt->x(0) - first_vertex[0]) +
35875 (first_node_pt->x(1) - first_vertex[1]) *
35876 (first_node_pt->x(1) - first_vertex[1]);
35878 error = sqrt(error);
35880 if (error < ToleranceForVertexMismatchInPolygons::Tolerable_error)
35882 inverted_face_mesh =
false;
35886 inverted_face_mesh =
true;
35895 template<
class ELEMENT>
35897 TriangleMeshPolygon* polygon_pt, Vector<Mesh*>& face_mesh_pt)
35900 unsigned n_polyline = polygon_pt->npolyline();
35901 face_mesh_pt.resize(n_polyline);
35907 bool eligible_for_segment_redistribution =
true;
35910 for (
unsigned p = 0; p < n_polyline; p++)
35913 unsigned bound = polygon_pt->polyline_pt(p)->boundary_id();
35917 GeomObject*
const geom_object_pt = this->boundary_geom_object_pt(bound);
35918 if (geom_object_pt != 0)
35920 eligible_for_segment_redistribution =
false;
35923 face_mesh_pt[p] =
new Mesh();
35924 create_unsorted_face_mesh_representation(bound, face_mesh_pt[p]);
35927 if (!polygon_pt->is_redistribution_of_segments_between_polylines_enabled())
35933 if (this->nregion() > 1)
35935 std::ostringstream warn_message;
35937 <<
"Can't currently re-distribute segments between polylines if there\n"
35938 <<
"are multiple regions; returning..." << std::endl;
35939 OomphLibWarning(warn_message.str(),
35940 "RefineableTriangleMesh::get_face_mesh_representation()",
35941 OOMPH_EXCEPTION_LOCATION);
35946 if (!eligible_for_segment_redistribution)
35948 std::ostringstream warn_message;
35950 <<
"Over-ruling re-distribution of segments between polylines\n"
35951 <<
"because at least one boundary is associated with a GeomObject."
35952 <<
"Returning..." << std::endl;
35953 OomphLibWarning(warn_message.str(),
35954 "RefineableTriangleMesh::get_face_mesh_representation()",
35955 OOMPH_EXCEPTION_LOCATION);
35960 Vector<Mesh*> ordered_face_mesh_pt(n_polyline);
35963 double s_total = 0.0;
35967 Vector<Node*> first_polyline_node_pt(n_polyline);
35968 Vector<Node*> last_polyline_node_pt(n_polyline);
35969 std::vector<bool> is_reversed(n_polyline,
false);
35972 for (
unsigned p = 0; p < n_polyline; p++)
35978 std::list<FiniteElement*> ordered_el_pt;
35979 FiniteElement* el_pt = face_mesh_pt[p]->finite_element_pt(0);
35980 ordered_el_pt.push_back(el_pt);
35983 unsigned nnod = el_pt->nnode();
35986 first_polyline_node_pt[p] = el_pt->node_pt(0);
35987 last_polyline_node_pt[p] = el_pt->node_pt(nnod - 1);
35990 unsigned count_done = 0;
35993 unsigned n_face_element = face_mesh_pt[p]->nelement();
35996 unsigned bound = polygon_pt->polyline_pt(p)->boundary_id();
35999 std::map<FiniteElement*, bool> done_el;
36002 std::map<FiniteElement*, bool> is_inverted;
36005 for (
unsigned ee = 1; ee < n_face_element; ee++)
36009 for (
unsigned e = 1; e < n_face_element; e++)
36012 el_pt = face_mesh_pt[p]->finite_element_pt(e);
36015 if (!done_el[el_pt])
36018 FiniteElement* first_el_pt = (*ordered_el_pt.begin());
36019 std::list<FiniteElement*>::iterator it = ordered_el_pt.end();
36021 FiniteElement* last_el_pt = *it;
36024 Node* left_node_pt = first_el_pt->node_pt(0);
36025 if (is_inverted[first_el_pt])
36027 left_node_pt = first_el_pt->node_pt(nnod - 1);
36029 Node* right_node_pt = last_el_pt->node_pt(nnod - 1);
36030 if (is_inverted[last_el_pt])
36032 right_node_pt = last_el_pt->node_pt(0);
36036 if (left_node_pt == el_pt->node_pt(nnod - 1))
36038 ordered_el_pt.push_front(el_pt);
36039 done_el[el_pt] =
true;
36041 is_inverted[el_pt] =
false;
36042 first_polyline_node_pt[p] = el_pt->node_pt(0);
36046 else if (left_node_pt == el_pt->node_pt(0))
36048 ordered_el_pt.push_front(el_pt);
36049 done_el[el_pt] =
true;
36051 is_inverted[el_pt] =
true;
36052 first_polyline_node_pt[p] = el_pt->node_pt(nnod - 1);
36056 else if (right_node_pt == el_pt->node_pt(0))
36058 ordered_el_pt.push_back(el_pt);
36059 done_el[el_pt] =
true;
36061 is_inverted[el_pt] =
false;
36062 last_polyline_node_pt[p] = el_pt->node_pt(nnod - 1);
36066 else if (right_node_pt == el_pt->node_pt(nnod - 1))
36068 ordered_el_pt.push_back(el_pt);
36069 done_el[el_pt] =
true;
36071 is_inverted[el_pt] =
true;
36072 last_polyline_node_pt[p] = el_pt->node_pt(0);
36075 if (done_el[el_pt])
36084 if (count_done != (n_face_element - 1))
36086 std::ostringstream error_message;
36087 error_message <<
"When ordering FaceElements on "
36088 <<
"boundary " << bound <<
" only managed to order \n"
36089 << count_done <<
" of " << n_face_element
36090 <<
" face elements.\n"
36092 throw OomphLibError(error_message.str(),
36093 OOMPH_CURRENT_FUNCTION,
36094 OOMPH_EXCEPTION_LOCATION);
36098 ordered_face_mesh_pt[p] =
new Mesh;
36101 for (std::list<FiniteElement*>::iterator it = ordered_el_pt.begin();
36102 it != ordered_el_pt.end();
36106 FiniteElement* el_pt = *it;
36109 ordered_face_mesh_pt[p]->add_element_pt(el_pt);
36113 for (
unsigned e = 0; e < n_face_element; ++e)
36115 FiniteElement* el_pt = ordered_face_mesh_pt[p]->finite_element_pt(e);
36116 unsigned n_node = el_pt->nnode();
36117 double element_length_squared = 0.0;
36118 for (
unsigned i = 0; i < 2; i++)
36120 element_length_squared +=
36121 pow(el_pt->node_pt(n_node - 1)->x(i) - el_pt->node_pt(0)->x(i), 2);
36125 double element_length = sqrt(element_length_squared);
36128 s_total += element_length;
36132 face_mesh_pt[p]->flush_element_and_node_storage();
36136 if ((last_polyline_node_pt[0] == first_polyline_node_pt[1]) ||
36137 (last_polyline_node_pt[0] == last_polyline_node_pt[1]))
36139 is_reversed[0] =
false;
36141 else if ((first_polyline_node_pt[0] == first_polyline_node_pt[1]) ||
36142 (first_polyline_node_pt[0] == last_polyline_node_pt[1]))
36144 is_reversed[0] =
true;
36148 Vector<Mesh*> tmp_face_mesh_pt(n_polyline);
36149 std::vector<bool> mesh_done(n_polyline,
false);
36150 Vector<unsigned> old_polyline_number(n_polyline);
36153 tmp_face_mesh_pt[0] = ordered_face_mesh_pt[0];
36154 unsigned current = 0;
36155 old_polyline_number[0] = 0;
36156 unsigned count_found = 0;
36159 for (
unsigned p = 1; p < n_polyline; p++)
36161 Node* end_node_pt = last_polyline_node_pt[current];
36162 if (is_reversed[current])
36164 end_node_pt = first_polyline_node_pt[current];
36168 for (
unsigned pp = 1; pp < n_polyline; pp++)
36170 if (!mesh_done[pp])
36173 if ((!is_reversed[current]) &&
36174 (end_node_pt == first_polyline_node_pt[pp]))
36176 tmp_face_mesh_pt[p] = ordered_face_mesh_pt[pp];
36177 mesh_done[pp] =
true;
36178 is_reversed[pp] =
false;
36179 old_polyline_number[p] = pp;
36186 else if ((!is_reversed[current]) &&
36187 (end_node_pt == last_polyline_node_pt[pp]))
36189 tmp_face_mesh_pt[p] = ordered_face_mesh_pt[pp];
36190 mesh_done[pp] =
true;
36191 is_reversed[pp] =
true;
36192 old_polyline_number[p] = pp;
36199 else if ((is_reversed[current]) &&
36200 (end_node_pt == first_polyline_node_pt[pp]))
36202 tmp_face_mesh_pt[p] = ordered_face_mesh_pt[pp];
36203 mesh_done[pp] =
true;
36204 is_reversed[pp] =
false;
36205 old_polyline_number[p] = pp;
36212 else if ((is_reversed[current]) &&
36213 (end_node_pt == last_polyline_node_pt[pp]))
36215 tmp_face_mesh_pt[p] = ordered_face_mesh_pt[pp];
36216 mesh_done[pp] =
true;
36217 is_reversed[pp] =
true;
36218 old_polyline_number[p] = pp;
36228 if (count_found != n_polyline - 1)
36230 std::ostringstream error_message;
36231 error_message <<
"Only found " << count_found <<
" out of "
36232 << n_polyline - 1 <<
" polylines to be fitted in.\n";
36233 throw OomphLibError(
36234 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
36239 for (
unsigned i = 0; i < n_polyline; i++)
36241 ordered_face_mesh_pt[i] = tmp_face_mesh_pt[i];
36247 unsigned new_face_id = 0;
36251 std::map<Node*, std::map<unsigned, unsigned>>
36252 node_must_not_be_removed_from_boundary_flag;
36255 for (
unsigned p = 0; p < n_polyline; p++)
36258 unsigned n_face_element = ordered_face_mesh_pt[p]->nelement();
36259 for (
unsigned e = 0; e < n_face_element; e++)
36261 unsigned el_number = e;
36262 if (is_reversed[p])
36264 el_number = n_face_element - e - 1;
36267 FiniteElement* el_pt =
36268 ordered_face_mesh_pt[p]->finite_element_pt(el_number);
36269 unsigned n_node = el_pt->nnode();
36272 double element_length_squared = 0.0;
36273 for (
unsigned i = 0; i < 2; i++)
36275 element_length_squared +=
36276 pow(el_pt->node_pt(n_node - 1)->x(i) - el_pt->node_pt(0)->x(i), 2);
36278 double element_length = sqrt(element_length_squared);
36281 s += element_length;
36285 if (s < s_total /
double(n_polyline) + 1e-6)
36288 face_mesh_pt[new_face_id]->add_element_pt(el_pt);
36290 unsigned bound_old =
36291 polygon_pt->polyline_pt(old_polyline_number[p])->boundary_id();
36293 unsigned bound_new =
36294 polygon_pt->polyline_pt(new_face_id)->boundary_id();
36297 for (
unsigned i = 0; i < n_node; i++)
36300 Node* nod_pt = el_pt->node_pt(i);
36304 if (bound_new != bound_old)
36307 add_boundary_node(bound_new, nod_pt);
36311 node_must_not_be_removed_from_boundary_flag[nod_pt][bound_old] +=
36321 node_must_not_be_removed_from_boundary_flag[nod_pt][bound_old] +=
36334 if (new_face_id != n_polyline - 1)
36352 unsigned move_count = 0;
36353 for (std::map<Node*, std::map<unsigned, unsigned>>::iterator it =
36354 node_must_not_be_removed_from_boundary_flag.begin();
36355 it != node_must_not_be_removed_from_boundary_flag.end();
36359 Node* nod_pt = (*it).first;
36362 for (std::map<unsigned, unsigned>::iterator it_2 = (*it).second.begin();
36363 it_2 != (*it).second.end();
36367 unsigned bound = (*it_2).first;
36370 if ((*it_2).second == 0)
36372 remove_boundary_node(bound, nod_pt);
36379 for (
unsigned p = 0; p < n_polyline; p++)
36382 unsigned bound = polygon_pt->polyline_pt(p)->boundary_id();
36385 unsigned n_face_element = face_mesh_pt[p]->nelement();
36386 for (
unsigned e = 0; e < n_face_element; e++)
36389 FaceElementAsGeomObject<ELEMENT>* el_pt =
36390 dynamic_cast<FaceElementAsGeomObject<ELEMENT>*
>(
36391 face_mesh_pt[p]->element_pt(e));
36394 el_pt->set_boundary_number_in_bulk_mesh(bound);
36399 setup_boundary_element_info();
36402 for (
unsigned p = 0; p < n_polyline; p++)
36405 unsigned bound = polygon_pt->polyline_pt(p)->boundary_id();
36408 this->
template setup_boundary_coordinates<ELEMENT>(bound);
36412 for (
unsigned p = 0; p < n_polyline; p++)
36417 ordered_face_mesh_pt[p]->flush_element_and_node_storage();
36418 delete ordered_face_mesh_pt[p];
36425 template<
class ELEMENT>
36427 TriangleMeshOpenCurve* open_polyline_pt, Vector<Mesh*>& face_mesh_pt)
36430 unsigned n_polyline = open_polyline_pt->ncurve_section();
36431 face_mesh_pt.resize(n_polyline);
36434 for (
unsigned p = 0; p < n_polyline; p++)
36437 unsigned bound = open_polyline_pt->curve_section_pt(p)->boundary_id();
36439 face_mesh_pt[p] =
new Mesh();
36440 create_unsorted_face_mesh_representation(bound, face_mesh_pt[p]);
36451 template<
class ELEMENT>
36453 ELEMENT>::surface_remesh_for_inner_hole_boundaries(Vector<Vector<double>>&
36454 internal_point_coord,
36455 const bool& check_only)
36459 bool update_was_performed =
false;
36461 unsigned n_hole = internal_point_coord.size();
36462 for (
unsigned ihole = 0; ihole < n_hole; ihole++)
36465 TriangleMeshPolygon*
const poly_pt = this->Internal_polygon_pt[ihole];
36470 if (poly_pt->can_update_reference_configuration())
36472 poly_pt->reset_reference_configuration();
36475 internal_point_coord[ihole].resize(2);
36478 internal_point_coord[ihole] = poly_pt->internal_point();
36489 bool update_necessary =
36490 this->update_polygon_using_face_mesh(poly_pt, check_only);
36493 if (update_necessary)
36503 update_was_performed = this->update_polygon_using_face_mesh(poly_pt);
36507 if (!poly_pt->internal_point().empty())
36511 if (poly_pt->is_internal_point_fixed())
36514 internal_point_coord[ihole] = poly_pt->internal_point();
36521 if (this->Internal_hole_point_update_fct_pt != 0)
36523 this->Internal_hole_point_update_fct_pt(ihole, poly_pt);
36529 Vector<double> vertex_coord;
36530 unsigned n_polyline = poly_pt->npolyline();
36533 vertex_coord.resize(2);
36534 internal_point_coord[ihole].resize(2);
36538 internal_point_coord[ihole][0] = 0.0;
36539 internal_point_coord[ihole][1] = 0.0;
36541 for (
unsigned p = 0; p < n_polyline; p++)
36543 Vector<double> poly_ave(2, 0.0);
36545 unsigned n_vertex = poly_pt->polyline_pt(p)->nvertex();
36546 for (
unsigned v = 0; v < n_vertex; v++)
36548 vertex_coord = poly_pt->polyline_pt(p)->vertex_coordinate(v);
36549 for (
unsigned i = 0; i < 2; i++)
36551 poly_ave[i] += vertex_coord[i];
36556 for (
unsigned i = 0; i < 2; i++)
36558 internal_point_coord[ihole][i] += poly_ave[i] / n_vertex;
36563 for (
unsigned i = 0; i < 2; i++)
36565 internal_point_coord[ihole][i] /= n_polyline;
36614 poly_pt->internal_point() = internal_point_coord[ihole];
36632 return update_was_performed;
36641 template<
class ELEMENT>
36643 const std::string& node_file_name,
const std::string& poly_file_name)
36649 std::ifstream node_file(node_file_name.c_str(), std::ios_base::in);
36652 if (!node_file.is_open())
36654 std::string error_msg(
"Failed to open node file: ");
36655 error_msg +=
"\"" + node_file_name +
"\".";
36656 throw OomphLibError(
36657 error_msg, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
36662 node_file >> nnodes;
36665 unsigned dimension;
36666 node_file >> dimension;
36669 if (dimension != 2)
36671 throw OomphLibError(
"The dimension must be 2\n",
36672 OOMPH_CURRENT_FUNCTION,
36673 OOMPH_EXCEPTION_LOCATION);
36678 Vector<double> x_node(nnodes);
36679 Vector<double> y_node(nnodes);
36682 unsigned npoint_attributes;
36683 node_file >> npoint_attributes;
36687 unsigned boundary_markers_flag = 0;
36688 node_file >> boundary_markers_flag;
36691 unsigned dummy_node_number;
36693 unsigned dummy_node_attribute;
36695 unsigned dummy_node_boundary;
36699 for (
unsigned i = 0; i < nnodes; i++)
36701 node_file >> dummy_node_number;
36702 node_file >> x_node[i];
36703 node_file >> y_node[i];
36704 for (
unsigned j = 0; j < npoint_attributes; ++j)
36706 node_file >> dummy_node_attribute;
36708 if (boundary_markers_flag)
36710 node_file >> dummy_node_boundary;
36719 std::map<unsigned, Vector<std::pair<unsigned, unsigned>>>
36720 unsorted_boundary_segments;
36725 Vector<unsigned> sorted_boundaries_ids;
36731 std::ifstream poly_file(poly_file_name.c_str(), std::ios_base::in);
36734 if (!poly_file.is_open())
36736 std::string error_msg(
"Failed to open poly file: ");
36737 error_msg +=
"\"" + poly_file_name +
"\".";
36738 throw OomphLibError(
36739 error_msg, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
36743 unsigned n_node_poly;
36744 poly_file >> n_node_poly;
36747 poly_file >> dimension;
36750 unsigned attribute_flag;
36751 poly_file >> attribute_flag;
36754 poly_file >> boundary_markers_flag;
36759 for (
unsigned i = 0; i < n_node_poly; i++)
36762 poly_file >> dummy;
36763 poly_file >> dummy;
36764 poly_file >> dummy;
36766 for (
unsigned j = 0; j < attribute_flag; ++j)
36768 poly_file >> dummy;
36771 if (boundary_markers_flag == 1)
36773 poly_file >> dummy;
36778 unsigned read_value;
36781 poly_file >> read_value;
36782 const unsigned nglobal_segments = read_value;
36785 poly_file >> boundary_markers_flag;
36788 unsigned global_segment_number;
36791 std::set<unsigned> nodes_ids;
36794 for (
unsigned i = 0; i < nglobal_segments; i++)
36797 unsigned lnode_id = 0;
36798 unsigned rnode_id = 0;
36799 unsigned bnd_id = 0;
36800 poly_file >> global_segment_number;
36801 poly_file >> lnode_id;
36802 poly_file >> rnode_id;
36803 nodes_ids.insert(lnode_id);
36804 nodes_ids.insert(rnode_id);
36805 if (boundary_markers_flag)
36807 poly_file >> bnd_id;
36813 unsorted_boundary_segments[bnd_id - 1].push_back(
36814 std::make_pair(lnode_id, rnode_id));
36821 const unsigned nsorted_boundaries_ids = sorted_boundaries_ids.size();
36823 bool boundary_id_found =
false;
36824 for (
unsigned ib = 0; ib < nsorted_boundaries_ids; ib++)
36826 if (sorted_boundaries_ids[ib] == bnd_id - 1)
36828 boundary_id_found =
true;
36834 if (!boundary_id_found)
36836 sorted_boundaries_ids.push_back(bnd_id - 1);
36845 if (nglobal_segments != nodes_ids.size())
36847 std::ostringstream error_message;
36849 <<
"The number of nodes (" << nodes_ids.size() <<
") and segments ("
36850 << nglobal_segments <<
") is different.\nThis may mean that there "
36851 <<
"are internal non-closed boundaries defined in\nthe polyfile. "
36852 <<
"If you need this feature please use the TriangleMeshPoyLine\n"
36853 <<
"and TriangleMeshCurviLine objects to define your domain.\n\n";
36854 throw OomphLibError(
36855 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
36862 const unsigned nboundary = unsorted_boundary_segments.size();
36865 if (nboundary != this->nboundary())
36867 std::ostringstream error_message;
36869 <<
"The number of boundaries on the mesh (" << this->nboundary()
36870 <<
") is different from the number of\nboundaries read from the "
36871 <<
"polyfiles (" << unsorted_boundary_segments.size() <<
")!!!\n\n\n";
36872 throw OomphLibError(
36873 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
36879 const unsigned nsorted_boundaries_ids = sorted_boundaries_ids.size();
36881 if (nsorted_boundaries_ids != this->nboundary())
36883 std::ostringstream error_message;
36885 <<
"The number of boundaries on the mesh (" << this->nboundary()
36886 <<
") is different from the number of\nsorted boundaries ids read "
36887 <<
"from the polyfiles (" << nsorted_boundaries_ids <<
")!!!\n\n\n";
36888 throw OomphLibError(
36889 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
36894 std::map<unsigned, std::list<unsigned>> sorted_boundary_segments;
36897 std::map<unsigned, Vector<std::pair<unsigned, unsigned>>>::iterator it;
36899 for (it = unsorted_boundary_segments.begin();
36900 it != unsorted_boundary_segments.end();
36905 const unsigned bnd_id = (*it).first;
36906 Vector<std::pair<unsigned, unsigned>> segments_edges = (*it).second;
36909 std::map<std::pair<unsigned, unsigned>,
bool> segment_done;
36910 const unsigned nsegments = segments_edges.size();
36913 std::list<unsigned> sorted_segments;
36916 unsigned left_node_id = segments_edges[0].first;
36917 unsigned right_node_id = segments_edges[0].second;
36920 sorted_segments.push_back(left_node_id);
36921 sorted_segments.push_back(right_node_id);
36924 segment_done[segments_edges[0]] =
true;
36927 unsigned nsorted_segments = 1;
36929 while (nsorted_segments < nsegments)
36931 for (
unsigned i = 1; i < nsegments; i++)
36934 if (!segment_done[segments_edges[i]])
36937 unsigned current_left_node_id = segments_edges[i].first;
36938 unsigned current_right_node_id = segments_edges[i].second;
36942 if (current_left_node_id == right_node_id)
36946 sorted_segments.push_back(current_right_node_id);
36948 nsorted_segments++;
36950 segment_done[segments_edges[i]] =
true;
36952 right_node_id = current_right_node_id;
36956 else if (current_right_node_id == left_node_id)
36960 sorted_segments.push_front(current_left_node_id);
36962 nsorted_segments++;
36964 segment_done[segments_edges[i]] =
true;
36966 left_node_id = current_left_node_id;
36970 else if (current_left_node_id == left_node_id)
36974 sorted_segments.push_front(current_right_node_id);
36976 nsorted_segments++;
36978 segment_done[segments_edges[i]] =
true;
36980 left_node_id = current_right_node_id;
36984 else if (current_right_node_id == right_node_id)
36988 sorted_segments.push_back(current_left_node_id);
36990 nsorted_segments++;
36992 segment_done[segments_edges[i]] =
true;
36994 right_node_id = current_left_node_id;
37002 sorted_boundary_segments[bnd_id] = sorted_segments;
37008 if (sorted_boundary_segments.size() != this->nboundary())
37010 std::ostringstream error_message;
37012 <<
"The number of boundaries on the mesh (" << this->nboundary()
37013 <<
") is different from the number\nof sorted boundaries to create the "
37014 <<
"polylines (" << sorted_boundary_segments.size() <<
")\n\n";
37015 throw OomphLibError(
37016 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
37022 Vector<TriangleMeshPolyLine*> polylines_pt(nboundary);
37023 unsigned current_polyline = 0;
37026 for (
unsigned ib = 0; ib < nsorted_boundaries_ids; ib++)
37029 const unsigned bnd_id = sorted_boundaries_ids[ib];
37033 Vector<unsigned> nodes_ids;
37034 for (std::list<unsigned>::iterator it_list =
37035 sorted_boundary_segments[bnd_id].begin();
37036 it_list != sorted_boundary_segments[bnd_id].end();
37039 nodes_ids.push_back((*it_list));
37043 const unsigned nvertices = nodes_ids.size();
37046 Vector<Vector<double>> vertices(nvertices);
37049 for (
unsigned i = 0; i < nvertices; i++)
37052 vertices[i].resize(2);
37053 vertices[i][0] = x_node[nodes_ids[i] - 1];
37054 vertices[i][1] = y_node[nodes_ids[i] - 1];
37062 polylines_pt[current_polyline] =
37063 new TriangleMeshPolyLine(vertices, bnd_id);
37066 this->Boundary_curve_section_pt[bnd_id] =
37067 dynamic_cast<TriangleMeshCurveSection*
>(polylines_pt[current_polyline]);
37070 current_polyline++;
37077 unsigned nsorted_polylines = 0;
37080 unsigned npolygons = 0;
37083 Vector<TriangleMeshPolygon*> polygons_pt;
37086 std::map<unsigned, bool> polyline_done;
37087 while (nsorted_polylines < nboundary)
37090 std::list<TriangleMeshCurveSection*> sorted_curve_sections_pt;
37092 unsigned init_poly = 0;
37094 bool found_root_polyline =
false;
37097 for (
unsigned i = 0; i < nboundary; i++)
37099 if (!polyline_done[i])
37103 nsorted_polylines++;
37106 found_root_polyline =
true;
37109 polyline_done[i] =
true;
37111 sorted_curve_sections_pt.push_back(polylines_pt[i]);
37118 if (!found_root_polyline)
37120 std::ostringstream error_message;
37121 error_message <<
"Was not possible to found the root polyline to "
37122 "create polygons\n\n";
37123 throw OomphLibError(error_message.str(),
37124 OOMPH_CURRENT_FUNCTION,
37125 OOMPH_EXCEPTION_LOCATION);
37130 const unsigned bnd_id = polylines_pt[init_poly]->boundary_id();
37132 unsigned left_node_id = sorted_boundary_segments[bnd_id].front();
37133 unsigned right_node_id = sorted_boundary_segments[bnd_id].back();
37136 bool closed_polygon =
false;
37141 for (
unsigned i = init_poly; i < nboundary; i++)
37144 if (!polyline_done[i])
37149 const unsigned cbnd_id = polylines_pt[i]->boundary_id();
37151 unsigned cleft_node_id = sorted_boundary_segments[cbnd_id].front();
37152 unsigned cright_node_id = sorted_boundary_segments[cbnd_id].back();
37156 if (cleft_node_id == right_node_id)
37159 sorted_curve_sections_pt.push_back(polylines_pt[i]);
37161 polyline_done[i] =
true;
37163 right_node_id = cright_node_id;
37165 nsorted_polylines++;
37169 else if (cright_node_id == left_node_id)
37172 sorted_curve_sections_pt.push_front(polylines_pt[i]);
37174 polyline_done[i] =
true;
37176 left_node_id = cleft_node_id;
37178 nsorted_polylines++;
37182 else if (cleft_node_id == left_node_id)
37185 polylines_pt[i]->reverse();
37187 sorted_curve_sections_pt.push_front(polylines_pt[i]);
37189 polyline_done[i] =
true;
37191 left_node_id = cright_node_id;
37193 nsorted_polylines++;
37197 else if (cright_node_id == right_node_id)
37200 polylines_pt[i]->reverse();
37202 sorted_curve_sections_pt.push_back(polylines_pt[i]);
37204 polyline_done[i] =
true;
37206 right_node_id = cleft_node_id;
37208 nsorted_polylines++;
37217 if (left_node_id == right_node_id)
37220 closed_polygon =
true;
37223 }
while (nsorted_polylines < nboundary && !closed_polygon);
37226 if (!closed_polygon)
37228 std::ostringstream error_message;
37230 <<
"It was not possible to create a closed curve, these are the "
37231 <<
"vertices of the already sorted polylines\n\n";
37232 unsigned cpolyline = 0;
37233 for (std::list<TriangleMeshCurveSection*>::iterator it_list =
37234 sorted_curve_sections_pt.begin();
37235 it_list != sorted_curve_sections_pt.end();
37238 error_message <<
"Polyline (" << cpolyline <<
")\n";
37239 TriangleMeshPolyLine* tmp_poly_pt =
37240 dynamic_cast<TriangleMeshPolyLine*
>((*it_list));
37241 const unsigned nvertex = tmp_poly_pt->nvertex();
37242 for (
unsigned v = 0; v < nvertex; v++)
37244 error_message <<
"(" << tmp_poly_pt->vertex_coordinate(v)[0] <<
", "
37245 << tmp_poly_pt->vertex_coordinate(v)[1] <<
")\n";
37247 error_message <<
"\n";
37250 throw OomphLibError(error_message.str(),
37251 OOMPH_CURRENT_FUNCTION,
37252 OOMPH_EXCEPTION_LOCATION);
37258 Vector<TriangleMeshCurveSection*> tmp_sorted_curve_sections_pt;
37259 for (std::list<TriangleMeshCurveSection*>::iterator it_list =
37260 sorted_curve_sections_pt.begin();
37261 it_list != sorted_curve_sections_pt.end();
37264 tmp_sorted_curve_sections_pt.push_back((*it_list));
37268 TriangleMeshPolygon* polygon_pt =
37269 new TriangleMeshPolygon(tmp_sorted_curve_sections_pt);
37272 this->Free_polygon_pt.insert(polygon_pt);
37275 polygons_pt.push_back(polygon_pt);
37288 unsigned index_outer = 0;
37290 for (
unsigned idx_outer = 0; idx_outer < npolygons; idx_outer++)
37293 Vector<Vector<double>> outer_vertex_coordinates;
37297 bool all_inner_inside =
true;
37300 const unsigned nouter_polylines = polygons_pt[idx_outer]->npolyline();
37301 for (
unsigned p = 0; p < nouter_polylines; p++)
37303 TriangleMeshPolyLine* tmp_poly_pt =
37304 polygons_pt[idx_outer]->polyline_pt(p);
37305 const unsigned nvertex = tmp_poly_pt->nvertex();
37306 for (
unsigned v = 0; v < nvertex; v++)
37308 Vector<double> current_vertex = tmp_poly_pt->vertex_coordinate(v);
37309 outer_vertex_coordinates.push_back(current_vertex);
37318 const unsigned ninner_polygons = polygons_pt.size() - 1;
37321 Vector<Vector<Vector<double>>> inner_vertex_coordinates(ninner_polygons);
37323 for (
unsigned i = 0; i <= ninner_polygons; i++)
37325 if (i != idx_outer)
37328 const unsigned ninner_polylines = polygons_pt[i]->npolyline();
37329 for (
unsigned p = 0; p < ninner_polylines; p++)
37331 TriangleMeshPolyLine* tmp_poly_pt = polygons_pt[i]->polyline_pt(p);
37332 const unsigned nvertex = tmp_poly_pt->nvertex();
37333 for (
unsigned v = 0; v < nvertex; v++)
37335 Vector<double> current_vertex = tmp_poly_pt->vertex_coordinate(v);
37338 inner_vertex_coordinates[i].push_back(current_vertex);
37340 else if (i > idx_outer)
37342 inner_vertex_coordinates[i - 1].push_back(current_vertex);
37354 for (
unsigned i = 0; i < ninner_polygons; i++)
37358 const unsigned nvertex_internal = inner_vertex_coordinates[i].size();
37359 for (
unsigned v = 0; v < nvertex_internal; v++)
37362 Vector<double> current_point = inner_vertex_coordinates[i][v];
37363 all_inner_inside &= this->is_point_inside_polygon_helper(
37364 outer_vertex_coordinates, current_point);
37368 if (!all_inner_inside)
37378 if (!all_inner_inside)
37388 if (all_inner_inside)
37390 index_outer = idx_outer;
37400 if (index_outer != 0)
37402 std::ostringstream warning_message;
37404 <<
"The first set of nodes listed in the input polyfiles does not\n"
37405 <<
"correspond to the outer closed boundary. This may lead to\n"
37406 <<
"problems at the adaptation stage if the holes coordinates\n"
37407 <<
"are no correctly associated to the inner closed boundaries.\n"
37408 <<
"You can check the generated mesh by calling the output() method\n"
37409 <<
"from the mesh object '(problem.mesh_pt()->output(string))'\n\n";
37410 OomphLibWarning(warning_message.str(),
37411 OOMPH_CURRENT_FUNCTION,
37412 OOMPH_EXCEPTION_LOCATION);
37421 this->Outer_boundary_pt.resize(1);
37422 this->Outer_boundary_pt[0] = polygons_pt[index_outer];
37424 this->Internal_polygon_pt.resize(npolygons - 1);
37425 for (
unsigned i = 0; i < npolygons; i++)
37427 if (i != index_outer)
37429 if (i < index_outer)
37432 this->Internal_polygon_pt[i] = polygons_pt[i];
37434 else if (i > index_outer)
37437 this->Internal_polygon_pt[i - 1] = polygons_pt[i];
37448 Vector<Vector<Vector<double>>> inner_vertex_coordinates(npolygons - 1);
37450 for (
unsigned i = 0; i < npolygons - 1; i++)
37453 const unsigned ninner_polylines =
37454 this->Internal_polygon_pt[i]->npolyline();
37455 for (
unsigned p = 0; p < ninner_polylines; p++)
37457 TriangleMeshPolyLine* tmp_poly_pt =
37458 this->Internal_polygon_pt[i]->polyline_pt(p);
37461 const unsigned nvertex = tmp_poly_pt->nvertex();
37462 for (
unsigned v = 0; v < nvertex; v++)
37464 Vector<double> current_vertex = tmp_poly_pt->vertex_coordinate(v);
37465 inner_vertex_coordinates[i].push_back(current_vertex);
37474 poly_file >> nholes;
37477 if (npolygons > 1 && (npolygons - 1) != nholes)
37479 std::ostringstream error_message;
37481 <<
"The number of holes (" << nholes <<
") does not correspond "
37482 <<
"with the number\nof internal polygons (" << npolygons - 1 <<
")\n\n"
37483 <<
"Using polyfiles as input does not currently allows the\n"
37484 <<
"definition of more than one outer polygon\n\n";
37485 throw OomphLibError(
37486 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
37491 Vector<Vector<double>> hole_coordinates(nholes);
37494 unsigned dummy_hole;
37496 for (
unsigned ihole = 0; ihole < nholes; ihole++)
37498 hole_coordinates[ihole].resize(2);
37500 poly_file >> dummy_hole;
37501 poly_file >> hole_coordinates[ihole][0];
37502 poly_file >> hole_coordinates[ihole][1];
37507 Vector<unsigned> index_hole_of_internal_polygon(npolygons - 1);
37508 std::map<unsigned, bool> hole_done;
37512 for (
unsigned i = 0; i < npolygons - 1; i++)
37515 for (
unsigned h = 0; h < nholes; h++)
37521 Vector<double> current_point = hole_coordinates[h];
37523 const bool hole_in_polygon = this->is_point_inside_polygon_helper(
37524 inner_vertex_coordinates[i], current_point);
37527 if (hole_in_polygon)
37530 hole_done[h] =
true;
37533 index_hole_of_internal_polygon[i] = h;
37545 if (hole_done.size() != npolygons - 1)
37547 std::ostringstream error_message;
37549 <<
"Not all the holes were associated to an internal closed boundary\n"
37550 <<
"Only (" << hole_done.size()
37551 <<
") holes were assigned for a total of\n"
37552 <<
"(" << npolygons - 1 <<
") internal closed boundaries.\n"
37553 <<
"You can check the generated mesh by calling the output() method\n"
37554 <<
"from the mesh object '(problem.mesh_pt()->output(string))'\n\n";
37555 throw OomphLibError(
37556 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
37561 for (
unsigned ihole = 0; ihole < nholes; ihole++)
37564 const unsigned index_hole = index_hole_of_internal_polygon[ihole];
37569 if (index_hole != ihole)
37571 std::ostringstream error_message;
37573 <<
"The hole vertices coordinates are not listed in the same order\n"
37574 <<
"as the nodes that define the internal closed boundaries.\n"
37575 <<
"This may lead to problems in case that the holes coordinates\n"
37576 <<
"were no properly assigned to the internal closed boundaries.\n"
37577 <<
"You can check the generated mesh by calling the output() method\n"
37578 <<
"from the mesh object '(problem.mesh_pt()->output(string))'\n\n";
37579 throw OomphLibError(error_message.str(),
37580 OOMPH_CURRENT_FUNCTION,
37581 OOMPH_EXCEPTION_LOCATION);
37586 this->Internal_polygon_pt[ihole]->internal_point() =
37587 hole_coordinates[index_hole];
37591 poly_file.ignore(80,
'\n');
37598 std::string regions_info_string;
37601 getline(poly_file, regions_info_string);
37605 if (isdigit(regions_info_string.c_str()[0]))
37607 nregions = std::atoi(regions_info_string.c_str());
37615 std::map<unsigned, Vector<double>> regions_coordinates;
37618 unsigned dummy_region;
37620 unsigned region_id;
37623 for (
unsigned iregion = 0; iregion < nregions; iregion++)
37625 Vector<double> tmp_region_coordinates(2);
37627 poly_file >> dummy_region;
37628 poly_file >> tmp_region_coordinates[0];
37629 poly_file >> tmp_region_coordinates[1];
37630 poly_file >> region_id;
37631 regions_coordinates[region_id].resize(2);
37632 regions_coordinates[region_id][0] = tmp_region_coordinates[0];
37633 regions_coordinates[region_id][1] = tmp_region_coordinates[1];
37636 poly_file.ignore(80,
'\n');
37639 if (region_id == 0)
37641 std::ostringstream error_message;
37643 <<
"Please use another region id different from zero.\n"
37644 <<
"It is internally used as the default region number.\n";
37645 throw OomphLibError(error_message.str(),
37646 OOMPH_CURRENT_FUNCTION,
37647 OOMPH_EXCEPTION_LOCATION);
37652 this->Regions_coordinates = regions_coordinates;
37661 template<
class ELEMENT>
37663 TriangleMeshPolygon*& polygon_pt,
const Vector<double>& target_area)
37666 unsigned update_was_performed =
false;
37668 const unsigned nele = this->nelement();
37678 Vector<Mesh*> face_mesh_pt;
37679 get_face_mesh_representation(polygon_pt, face_mesh_pt);
37683 Vector<double> vertex_coord(3);
37684 Vector<double> bound_left(1);
37685 Vector<double> bound_right(1);
37687 unsigned n_polyline = polygon_pt->npolyline();
37690 for (
unsigned p = 0; p < n_polyline; p++)
37698 MeshAsGeomObject* mesh_geom_obj_pt =
37699 new MeshAsGeomObject(face_mesh_pt[p]);
37704 std::set<Vector<double>> vertex_nodes;
37708 Vector<Vector<double>> tmp_vector_vertex_node;
37713 Vector<Vector<double>> vector_vertex_node;
37715 #ifdef OOMPH_HAS_MPI
37721 Vector<std::set<Vector<double>>> sub_vertex_nodes;
37725 Vector<Vector<Vector<double>>> sub_tmp_vector_vertex_node;
37730 Vector<Vector<Vector<double>>> sub_vector_vertex_node;
37735 const unsigned bound = polygon_pt->curve_section_pt(p)->boundary_id();
37738 const unsigned chunk = polygon_pt->curve_section_pt(p)->boundary_chunk();
37745 const unsigned nface_element = face_mesh_pt[p]->nelement();
37749 Vector<FiniteElement*> non_halo_face_element_pt;
37752 std::map<FiniteElement*, unsigned> face_element_index_on_boundary;
37754 for (
unsigned ef = 0; ef < nface_element; ++ef)
37756 FiniteElement* ele_face_pt = face_mesh_pt[p]->finite_element_pt(ef);
37757 #ifdef OOMPH_HAS_MPI
37759 if (this->is_mesh_distributed() && ele_face_pt->is_halo())
37765 non_halo_face_element_pt.push_back(ele_face_pt);
37766 face_element_index_on_boundary[ele_face_pt] = ef;
37770 const unsigned nnon_halo_face_element = non_halo_face_element_pt.size();
37773 std::map<FiniteElement*, bool> face_element_done;
37776 unsigned nsorted_face_elements = 0;
37778 #ifdef OOMPH_HAS_MPI
37780 unsigned nsub_boundaries = 0;
37785 while (nsorted_face_elements < nnon_halo_face_element)
37788 FiniteElement* ele_face_pt = 0;
37790 bool found_initial_face_element =
false;
37793 unsigned iface = 0;
37794 for (iface = 0; iface < nnon_halo_face_element; iface++)
37796 ele_face_pt = non_halo_face_element_pt[iface];
37798 if (!face_element_done[ele_face_pt])
37801 found_initial_face_element =
true;
37803 nsorted_face_elements++;
37810 if (!found_initial_face_element)
37812 std::ostringstream error_message;
37813 error_message <<
"Could not find an initial face element for the "
37814 "current segment\n";
37816 throw OomphLibError(
37817 error_message.str(),
37818 "RefineableTriangleMesh::update_polygon_using_elements_area()",
37819 OOMPH_EXCEPTION_LOCATION);
37826 std::set<Vector<double>> local_vertex_nodes;
37830 Vector<Vector<double>> local_tmp_vector_vertex_node;
37834 std::set<Vector<double>> sorted_target_areas;
37838 Vector<double> tmp_sorted_target_areas;
37844 unsigned nnode = ele_face_pt->nnode();
37847 ele_face_pt->node_pt(0)->get_coordinates_on_boundary(bound, bound_left);
37848 vertex_coord[0] = bound_left[0];
37851 for (
unsigned i = 0; i < 2; i++)
37853 vertex_coord[i + 1] = ele_face_pt->node_pt(0)->x(i);
37855 local_vertex_nodes.insert(vertex_coord);
37859 ele_face_pt->node_pt(nnode - 1)->get_coordinates_on_boundary(
37860 bound, bound_right);
37861 vertex_coord[0] = bound_right[0];
37864 for (
unsigned i = 0; i < 2; i++)
37866 vertex_coord[i + 1] = ele_face_pt->node_pt(nnode - 1)->x(i);
37868 local_vertex_nodes.insert(vertex_coord);
37871 Node* first_node_pt = ele_face_pt->node_pt(0);
37872 Node* last_node_pt = ele_face_pt->node_pt(nnode - 1);
37875 face_element_done[ele_face_pt] =
true;
37883 Vector<double> zeta_target_area_values(2);
37887 zeta_target_area_values[0] = std::min(bound_left[0], bound_right[0]);
37890 unsigned ef = face_element_index_on_boundary[ele_face_pt];
37892 FiniteElement* el_pt = this->boundary_element_pt(bound, ef);
37895 bool found_global_element_index =
false;
37897 for (
unsigned eg = 0; eg < nele; eg++)
37900 FiniteElement* el_compare_pt = this->finite_element_pt(eg);
37904 if (el_pt == el_compare_pt)
37906 zeta_target_area_values[1] = target_area[eg];
37908 found_global_element_index =
true;
37915 if (!found_global_element_index)
37917 std::ostringstream error_message;
37918 error_message <<
"The global index for the (" << ef
37919 <<
")-th face element "
37920 <<
"on\nthe (" << bound
37921 <<
")-th boundary was not found!!!";
37922 throw OomphLibError(
37923 error_message.str(),
37924 "RefineableTriangleMesh::update_polygon_using_elements_area()",
37925 OOMPH_EXCEPTION_LOCATION);
37930 sorted_target_areas.insert(zeta_target_area_values);
37935 bool face_element_added =
false;
37945 for (
unsigned iiface = iface; iiface < nnon_halo_face_element;
37948 face_element_added =
false;
37949 ele_face_pt = non_halo_face_element_pt[iiface];
37950 if (!face_element_done[ele_face_pt])
37953 nnode = ele_face_pt->nnode();
37954 Node* left_node_pt = ele_face_pt->node_pt(0);
37955 Node* right_node_pt = ele_face_pt->node_pt(nnode - 1);
37957 if (left_node_pt == first_node_pt)
37959 first_node_pt = right_node_pt;
37960 face_element_added =
true;
37962 else if (left_node_pt == last_node_pt)
37964 last_node_pt = right_node_pt;
37965 face_element_added =
true;
37967 else if (right_node_pt == first_node_pt)
37969 first_node_pt = left_node_pt;
37970 face_element_added =
true;
37972 else if (right_node_pt == last_node_pt)
37974 last_node_pt = left_node_pt;
37975 face_element_added =
true;
37978 if (face_element_added)
37982 left_node_pt->get_coordinates_on_boundary(bound, bound_left);
37983 vertex_coord[0] = bound_left[0];
37986 for (
unsigned i = 0; i < 2; i++)
37988 vertex_coord[i + 1] = left_node_pt->x(i);
37990 local_vertex_nodes.insert(vertex_coord);
37994 right_node_pt->get_coordinates_on_boundary(bound, bound_right);
37995 vertex_coord[0] = bound_right[0];
37998 for (
unsigned i = 0; i < 2; i++)
38000 vertex_coord[i + 1] = right_node_pt->x(i);
38002 local_vertex_nodes.insert(vertex_coord);
38006 face_element_done[ele_face_pt] =
true;
38007 nsorted_face_elements++;
38015 zeta_target_area_values[0] =
38016 std::min(bound_left[0], bound_right[0]);
38019 ef = face_element_index_on_boundary[ele_face_pt];
38020 FiniteElement* lel_pt = this->boundary_element_pt(bound, ef);
38023 found_global_element_index =
false;
38025 for (
unsigned eg = 0; eg < nele; eg++)
38028 FiniteElement* lel_compare_pt = this->finite_element_pt(eg);
38032 if (lel_pt == lel_compare_pt)
38034 zeta_target_area_values[1] = target_area[eg];
38036 found_global_element_index =
true;
38043 if (!found_global_element_index)
38045 std::ostringstream error_message;
38046 error_message <<
"The global index for the (" << ef
38047 <<
")-th face element "
38048 <<
"on\nthe (" << bound
38049 <<
")-th boundary was not found!!!";
38050 throw OomphLibError(error_message.str(),
38051 "RefineableTriangleMesh::update_polygon_"
38052 "using_elements_area()",
38053 OOMPH_EXCEPTION_LOCATION);
38058 sorted_target_areas.insert(zeta_target_area_values);
38065 }
while (face_element_added &&
38066 (nsorted_face_elements < nnon_halo_face_element));
38074 const unsigned nlocal_nodes = local_vertex_nodes.size();
38076 local_tmp_vector_vertex_node.resize(nlocal_nodes);
38079 unsigned counter = 0;
38080 std::set<Vector<double>>::iterator it_vertex;
38081 for (it_vertex = local_vertex_nodes.begin();
38082 it_vertex != local_vertex_nodes.end();
38085 local_tmp_vector_vertex_node[counter].resize(3);
38086 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
38087 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
38088 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
38094 const unsigned ntarget_areas = sorted_target_areas.size();
38095 tmp_sorted_target_areas.resize(ntarget_areas);
38097 std::set<Vector<double>>::iterator it_area;
38098 for (it_area = sorted_target_areas.begin();
38099 it_area != sorted_target_areas.end();
38102 tmp_sorted_target_areas[counter] = (*it_area)[1];
38107 if (nlocal_nodes > 0 && (ntarget_areas != nlocal_nodes - 1))
38109 std::ostringstream error_message;
38111 <<
"The boundary (" << bound <<
") was split during the "
38112 <<
"distribution process.\n"
38113 <<
"The problem is in the association of the target areas with "
38115 <<
"elements that gave rise to the vertex coordinates.\n"
38116 <<
"The number of local nodes (" << nlocal_nodes
38117 <<
"), on the 'sub-polyline', is not\n"
38118 <<
"according with the number of target "
38119 <<
"areas (" << ntarget_areas <<
")\nfor that number of nodes.\n"
38120 <<
"The target areas number MUST be equal to the number of\n"
38121 <<
"local nodes minus one\n\n";
38122 throw OomphLibError(error_message.str(),
38123 OOMPH_CURRENT_FUNCTION,
38124 OOMPH_EXCEPTION_LOCATION);
38135 double unrefinement_tolerance =
38136 polygon_pt->polyline_pt(p)->unrefinement_tolerance();
38139 bool unrefinement_applied =
38140 unrefine_boundary_constrained_by_target_area(
38143 local_tmp_vector_vertex_node,
38144 unrefinement_tolerance,
38145 tmp_sorted_target_areas);
38148 double refinement_tolerance =
38149 polygon_pt->polyline_pt(p)->refinement_tolerance();
38152 bool refinement_applied = refine_boundary_constrained_by_target_area(
38154 local_tmp_vector_vertex_node,
38155 refinement_tolerance,
38156 tmp_sorted_target_areas);
38160 local_vertex_nodes.clear();
38165 unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
38166 for (
unsigned i = 0; i < nnew_nodes; i++)
38168 vertex_coord[0] = local_tmp_vector_vertex_node[i][0];
38169 vertex_coord[1] = local_tmp_vector_vertex_node[i][1];
38170 vertex_coord[2] = local_tmp_vector_vertex_node[i][2];
38171 vertex_nodes.insert(vertex_coord);
38172 local_vertex_nodes.insert(vertex_coord);
38177 update_was_performed = (unrefinement_applied || refinement_applied);
38179 #ifdef OOMPH_HAS_MPI
38180 if (this->is_mesh_distributed())
38184 sub_vertex_nodes.push_back(local_vertex_nodes);
38193 unsigned npoly_vertex = vertex_nodes.size();
38196 tmp_vector_vertex_node.resize(npoly_vertex);
38197 unsigned count = 0;
38198 for (std::set<Vector<double>>::iterator it = vertex_nodes.begin();
38199 it != vertex_nodes.end();
38202 tmp_vector_vertex_node[count].resize(3);
38203 tmp_vector_vertex_node[count][0] = (*it)[0];
38204 tmp_vector_vertex_node[count][1] = (*it)[1];
38205 tmp_vector_vertex_node[count][2] = (*it)[2];
38209 #ifdef OOMPH_HAS_MPI
38212 unsigned nsub_boundaries_set = sub_vertex_nodes.size();
38213 if (nsub_boundaries_set != nsub_boundaries)
38215 std::ostringstream error_message;
38217 <<
"The number of found sub-boundaries and the number of counted\n"
38218 <<
"sub-boundaries are different:\n"
38219 <<
"Number of found sub-boundaries: (" << nsub_boundaries_set <<
")\n"
38220 <<
"Number of counted sub-boundaries: (" << nsub_boundaries <<
")\n";
38221 throw OomphLibError(error_message.str(),
38222 OOMPH_CURRENT_FUNCTION,
38223 OOMPH_EXCEPTION_LOCATION);
38228 if (this->is_mesh_distributed() && nsub_boundaries > 1)
38231 this->Boundary_was_splitted[bound] =
true;
38233 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
38234 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
38237 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
38238 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
38239 unsigned subcount = 0;
38240 std::set<Vector<double>>::iterator subit;
38241 for (subit = sub_vertex_nodes[isub].begin();
38242 subit != sub_vertex_nodes[isub].end();
38245 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
38246 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
38247 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
38248 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
38258 unsigned n_vertex = tmp_vector_vertex_node.size();
38261 vector_vertex_node.resize(n_vertex);
38262 for (
unsigned i = 0; i < n_vertex; i++)
38264 vector_vertex_node[i].resize(2);
38265 vector_vertex_node[i][0] = tmp_vector_vertex_node[i][1];
38266 vector_vertex_node[i][1] = tmp_vector_vertex_node[i][2];
38269 #ifdef OOMPH_HAS_MPI
38272 if (this->is_mesh_distributed() && nsub_boundaries > 1)
38277 sub_vector_vertex_node.resize(nsub_boundaries);
38278 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
38280 const unsigned subn_vertex = sub_tmp_vector_vertex_node[isub].size();
38282 sub_vector_vertex_node[isub].resize(subn_vertex);
38283 for (
unsigned i = 0; i < subn_vertex; i++)
38285 sub_vector_vertex_node[isub][i].resize(2);
38286 sub_vector_vertex_node[isub][i][0] =
38287 sub_tmp_vector_vertex_node[isub][i][1];
38288 sub_vector_vertex_node[isub][i][1] =
38289 sub_tmp_vector_vertex_node[isub][i][2];
38304 #ifdef OOMPH_HAS_MPI
38308 if (!this->is_mesh_distributed())
38314 Vector<double> final_vertex_of_previous_segment;
38315 unsigned n_prev_vertex =
38316 polygon_pt->curve_section_pt(p - 1)->nvertex();
38317 final_vertex_of_previous_segment =
38318 polygon_pt->polyline_pt(p - 1)->vertex_coordinate(n_prev_vertex -
38321 unsigned prev_seg_boundary_id =
38322 polygon_pt->curve_section_pt(p - 1)->boundary_id();
38326 double error = 0.0;
38327 for (
unsigned i = 0; i < 2; i++)
38329 const double dist = final_vertex_of_previous_segment[i] -
38330 (*vector_vertex_node.begin())[i];
38331 error += dist * dist;
38333 error = sqrt(error);
38337 if (error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
38341 double rev_error = 0.0;
38342 for (
unsigned i = 0; i < 2; i++)
38344 const double dist = final_vertex_of_previous_segment[i] -
38345 (*--vector_vertex_node.end())[i];
38346 rev_error += dist * dist;
38348 rev_error = sqrt(rev_error);
38351 ToleranceForVertexMismatchInPolygons::Tolerable_error)
38360 Vector<double> initial_vertex_of_previous_segment;
38362 initial_vertex_of_previous_segment =
38363 polygon_pt->polyline_pt(p - 1)->vertex_coordinate(0);
38365 unsigned prev_seg_boundary_id =
38366 polygon_pt->curve_section_pt(p - 1)->boundary_id();
38370 double error = 0.0;
38371 for (
unsigned i = 0; i < 2; i++)
38373 const double dist = initial_vertex_of_previous_segment[i] -
38374 (*vector_vertex_node.begin())[i];
38375 error += dist * dist;
38377 error = sqrt(error);
38382 ToleranceForVertexMismatchInPolygons::Tolerable_error)
38386 double rev_error = 0.0;
38387 for (
unsigned i = 0; i < 2; i++)
38389 const double dist = initial_vertex_of_previous_segment[i] -
38390 (*--vector_vertex_node.end())[i];
38391 rev_error += dist * dist;
38398 ToleranceForVertexMismatchInPolygons::Tolerable_error)
38400 std::ostringstream error_stream;
38402 <<
"The distance between the first node of the current\n"
38403 <<
"line segment (boundary " << bound
38404 <<
") and either end of "
38405 <<
"the previous line segment\n"
38406 <<
"(boundary " << prev_seg_boundary_id
38407 <<
") is bigger than "
38408 <<
"the desired tolerance "
38409 << ToleranceForVertexMismatchInPolygons::Tolerable_error
38411 <<
"This suggests that the polylines defining the "
38413 <<
"representation are not properly ordered.\n"
38414 <<
"Fail on last vertex of polyline: ("
38415 << prev_seg_boundary_id <<
") and\n"
38416 <<
"first vertex of polyline (" << bound <<
").\n"
38417 <<
"This should have failed when first trying to "
38418 <<
"construct the\npolygon.\n";
38419 throw OomphLibError(error_stream.str(),
38420 OOMPH_CURRENT_FUNCTION,
38421 OOMPH_EXCEPTION_LOCATION);
38428 std::reverse(vector_vertex_node.begin(),
38429 vector_vertex_node.end());
38431 polygon_pt->polyline_pt(p - 1)->reverse();
38437 polygon_pt->polyline_pt(p - 1)->reverse();
38443 std::ostringstream error_stream;
38445 <<
"The distance between the first node of the current\n"
38446 <<
"line segment (boundary " << bound
38447 <<
") and either end of "
38448 <<
"the previous line segment\n"
38449 <<
"(boundary " << prev_seg_boundary_id
38450 <<
") is bigger than the "
38451 <<
"desired tolerance "
38452 << ToleranceForVertexMismatchInPolygons::Tolerable_error
38454 <<
"This suggests that the polylines defining the polygonal\n"
38455 <<
"representation are not properly ordered.\n"
38456 <<
"Fail on last vertex of polyline: ("
38457 << prev_seg_boundary_id <<
") and\nfirst vertex of polyline ("
38459 <<
"This should have failed when first trying to construct"
38460 <<
" the polygon.\n";
38461 throw OomphLibError(error_stream.str(),
38462 OOMPH_CURRENT_FUNCTION,
38463 OOMPH_EXCEPTION_LOCATION);
38469 std::reverse(vector_vertex_node.begin(),
38470 vector_vertex_node.end());
38488 n_vertex = vector_vertex_node.size();
38491 TriangleMeshPolyLine* tmp_polyline_pt =
38492 new TriangleMeshPolyLine(vector_vertex_node, bound);
38496 TriangleMeshCurveSection* tmp_curve_section_pt = tmp_polyline_pt;
38500 double unrefinement_tolerance =
38501 polygon_pt->polyline_pt(p)->unrefinement_tolerance();
38504 double refinement_tolerance =
38505 polygon_pt->polyline_pt(p)->refinement_tolerance();
38508 tmp_polyline_pt->set_unrefinement_tolerance(unrefinement_tolerance);
38509 tmp_polyline_pt->set_refinement_tolerance(refinement_tolerance);
38512 double maximum_length = polygon_pt->polyline_pt(p)->maximum_length();
38513 tmp_polyline_pt->set_maximum_length(maximum_length);
38515 #ifdef OOMPH_HAS_MPI
38518 if (this->is_mesh_distributed())
38524 this->copy_connection_information(polygon_pt->polyline_pt(p),
38525 tmp_curve_section_pt);
38533 this->copy_connection_information(polygon_pt->polyline_pt(p),
38534 tmp_curve_section_pt);
38540 bool delete_it_on_destructor =
false;
38542 std::set<TriangleMeshCurveSection*>::iterator it =
38543 this->Free_curve_section_pt.find(polygon_pt->curve_section_pt(p));
38545 if (it != this->Free_curve_section_pt.end())
38547 this->Free_curve_section_pt.erase(it);
38548 delete polygon_pt->curve_section_pt(p);
38549 delete_it_on_destructor =
true;
38554 polygon_pt->curve_section_pt(p) = tmp_polyline_pt;
38557 this->Boundary_curve_section_pt[bound] = polygon_pt->curve_section_pt(p);
38559 if (delete_it_on_destructor)
38561 this->Free_curve_section_pt.insert(polygon_pt->curve_section_pt(p));
38564 #ifdef OOMPH_HAS_MPI
38567 if (this->is_mesh_distributed() && nsub_boundaries > 1)
38573 this->Boundary_subpolylines[bound].clear();
38576 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
38577 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
38580 TriangleMeshPolyLine* sub_tmp_polyline_pt =
38581 new TriangleMeshPolyLine(sub_vector_vertex_node[isub], bound, isub);
38585 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
38601 delete mesh_geom_obj_pt;
38606 for (
unsigned p = 0; p < n_polyline; p++)
38608 face_mesh_pt[p]->flush_node_storage();
38609 delete face_mesh_pt[p];
38612 return update_was_performed;
38619 template<
class ELEMENT>
38621 TriangleMeshOpenCurve*& open_curve_pt,
const Vector<double>& target_area)
38624 unsigned update_was_performed =
false;
38626 const unsigned nele = this->nelement();
38636 Vector<Mesh*> face_mesh_pt;
38637 get_face_mesh_representation(open_curve_pt, face_mesh_pt);
38641 Vector<double> vertex_coord(3);
38642 Vector<double> bound_left(1);
38643 Vector<double> bound_right(1);
38645 const unsigned ncurve_section = open_curve_pt->ncurve_section();
38648 for (
unsigned cs = 0; cs < ncurve_section; cs++)
38656 MeshAsGeomObject* mesh_geom_obj_pt =
38657 new MeshAsGeomObject(face_mesh_pt[cs]);
38660 const unsigned bound = open_curve_pt->curve_section_pt(cs)->boundary_id();
38663 const unsigned chunk =
38664 open_curve_pt->curve_section_pt(cs)->boundary_chunk();
38673 const unsigned nface_element = face_mesh_pt[cs]->nelement();
38678 Vector<FiniteElement*> non_halo_doubled_face_element_pt;
38681 std::map<FiniteElement*, unsigned> face_element_index_on_boundary;
38684 std::map<FiniteElement*, bool> face_element_done;
38686 for (
unsigned ef = 0; ef < nface_element; ++ef)
38688 FiniteElement* ele_face_pt = face_mesh_pt[cs]->finite_element_pt(ef);
38693 #ifdef OOMPH_HAS_MPI
38694 if (this->is_mesh_distributed())
38697 if (ele_face_pt->is_halo())
38705 if (!face_element_done[ele_face_pt])
38710 non_halo_doubled_face_element_pt.push_back(ele_face_pt);
38712 face_element_index_on_boundary[ele_face_pt] = ef;
38714 face_element_done[ele_face_pt] =
true;
38716 const unsigned nnodes = ele_face_pt->nnode();
38719 Node* left_node_pt = ele_face_pt->node_pt(0);
38720 Node* right_node_pt = ele_face_pt->node_pt(nnodes - 1);
38724 bool found_other_side_face_ele =
false;
38726 for (
unsigned iface = 0; iface < nface_element; iface++)
38729 FiniteElement* cele_face_pt =
38730 face_mesh_pt[cs]->finite_element_pt(iface);
38732 if (!face_element_done[cele_face_pt])
38734 Node* cleft_node_pt = cele_face_pt->node_pt(0);
38735 Node* cright_node_pt = cele_face_pt->node_pt(nnodes - 1);
38737 if ((left_node_pt == cleft_node_pt &&
38738 right_node_pt == cright_node_pt) ||
38739 (left_node_pt == cright_node_pt &&
38740 right_node_pt == cleft_node_pt))
38743 non_halo_doubled_face_element_pt.push_back(cele_face_pt);
38745 face_element_done[cele_face_pt] =
true;
38747 face_element_index_on_boundary[cele_face_pt] = iface;
38750 found_other_side_face_ele =
true;
38758 if (!found_other_side_face_ele)
38760 std::ostringstream error_message;
38762 <<
"The face element at the other side of the boundary (" << bound
38763 <<
") was not found!!\n"
38764 <<
"These are the nodes of the face element:\n"
38765 <<
"(" << left_node_pt->x(0) <<
", " << left_node_pt->x(1) <<
") "
38766 <<
"and (" << right_node_pt->x(0) <<
"," << right_node_pt->x(1)
38768 throw OomphLibError(
38769 error_message.str(),
38770 "RefineableTriangleMesh::update_open_curve_using_elements_area()",
38771 OOMPH_EXCEPTION_LOCATION);
38780 face_element_done.clear();
38785 std::set<Vector<double>> vertex_nodes;
38789 Vector<Vector<double>> tmp_vector_vertex_node;
38794 Vector<Vector<double>> vector_vertex_node;
38796 #ifdef OOMPH_HAS_MPI
38801 std::vector<bool> internal_to_shared_boundary;
38808 Vector<std::set<Vector<double>>> sub_vertex_nodes;
38812 Vector<Vector<Vector<double>>> sub_tmp_vector_vertex_node;
38817 Vector<Vector<Vector<double>>> sub_vector_vertex_node;
38828 unsigned nsorted_face_elements = 0;
38830 #ifdef OOMPH_HAS_MPI
38832 unsigned nsub_boundaries = 0;
38836 const unsigned nnon_halo_doubled_face_ele =
38837 non_halo_doubled_face_element_pt.size();
38841 while (nsorted_face_elements < nnon_halo_doubled_face_ele)
38844 FiniteElement* ele_face_pt = 0;
38845 FiniteElement* repeated_ele_face_pt = 0;
38847 bool found_initial_face_element =
false;
38853 bool both_root_face_elements_are_nonhalo =
false;
38855 unsigned iface = 0;
38856 for (iface = 0; iface < nnon_halo_doubled_face_ele; iface += 2)
38858 ele_face_pt = non_halo_doubled_face_element_pt[iface];
38860 if (!face_element_done[ele_face_pt])
38863 face_element_done[ele_face_pt] =
true;
38865 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iface + 1];
38867 face_element_done[repeated_ele_face_pt] =
true;
38869 #ifdef OOMPH_HAS_MPI
38870 if (!repeated_ele_face_pt->is_halo())
38872 both_root_face_elements_are_nonhalo =
true;
38878 nsorted_face_elements += 2;
38882 found_initial_face_element =
true;
38889 if (!found_initial_face_element)
38891 std::ostringstream error_message;
38892 error_message <<
"Could not find an initial face element for the "
38893 "current segment\n";
38894 throw OomphLibError(error_message.str(),
38895 OOMPH_CURRENT_FUNCTION,
38896 OOMPH_EXCEPTION_LOCATION);
38903 std::set<Vector<double>> local_vertex_nodes;
38907 Vector<Vector<double>> local_tmp_vector_vertex_node;
38911 std::set<Vector<double>> sorted_target_areas;
38915 Vector<double> tmp_sorted_target_areas;
38921 const unsigned nnode = ele_face_pt->nnode();
38924 ele_face_pt->node_pt(0)->get_coordinates_on_boundary(bound, bound_left);
38925 vertex_coord[0] = bound_left[0];
38928 for (
unsigned i = 0; i < 2; i++)
38930 vertex_coord[i + 1] = ele_face_pt->node_pt(0)->x(i);
38932 local_vertex_nodes.insert(vertex_coord);
38936 ele_face_pt->node_pt(nnode - 1)->get_coordinates_on_boundary(
38937 bound, bound_right);
38938 vertex_coord[0] = bound_right[0];
38941 for (
unsigned i = 0; i < 2; i++)
38943 vertex_coord[i + 1] = ele_face_pt->node_pt(nnode - 1)->x(i);
38945 local_vertex_nodes.insert(vertex_coord);
38948 Node* first_node_pt = ele_face_pt->node_pt(0);
38949 Node* last_node_pt = ele_face_pt->node_pt(nnode - 1);
38957 Vector<double> zeta_target_area_values(2);
38961 zeta_target_area_values[0] = std::min(bound_left[0], bound_right[0]);
38964 const unsigned ef = face_element_index_on_boundary[ele_face_pt];
38966 FiniteElement* el_pt = this->boundary_element_pt(bound, ef);
38967 double target_area_face_element = 0.0;
38970 bool found_global_element_index =
false;
38972 for (
unsigned eg = 0; eg < nele; eg++)
38975 FiniteElement* el_compare_pt = this->finite_element_pt(eg);
38979 if (el_pt == el_compare_pt)
38981 target_area_face_element = target_area[eg];
38983 found_global_element_index =
true;
38990 if (!found_global_element_index)
38992 std::ostringstream error_message;
38993 error_message <<
"The global index for the (" << ef
38994 <<
")-th face element "
38995 <<
"on\nthe (" << bound
38996 <<
")-th boundary was not found!!!";
38997 throw OomphLibError(error_message.str(),
38998 OOMPH_CURRENT_FUNCTION,
38999 OOMPH_EXCEPTION_LOCATION);
39004 const unsigned ref =
39005 face_element_index_on_boundary[repeated_ele_face_pt];
39006 FiniteElement* rel_pt = this->boundary_element_pt(bound, ref);
39007 double target_area_repeated_face_element = 0.0;
39010 bool found_global_repeated_element_index =
false;
39012 for (
unsigned eg = 0; eg < nele; eg++)
39015 FiniteElement* el_compare_pt = this->finite_element_pt(eg);
39019 if (rel_pt == el_compare_pt)
39021 target_area_repeated_face_element = target_area[eg];
39023 found_global_repeated_element_index =
true;
39030 if (!found_global_repeated_element_index)
39032 std::ostringstream error_message;
39033 error_message <<
"The global index for the (" << ref
39034 <<
")-th face element "
39035 <<
"on\nthe (" << bound
39036 <<
")-th boundary was not found (repeated "
39037 <<
"face element)!!!";
39038 throw OomphLibError(error_message.str(),
39039 OOMPH_CURRENT_FUNCTION,
39040 OOMPH_EXCEPTION_LOCATION);
39046 zeta_target_area_values[1] =
39047 std::min(target_area_face_element, target_area_repeated_face_element);
39050 sorted_target_areas.insert(zeta_target_area_values);
39055 bool face_element_added =
false;
39065 for (
unsigned iiface = iface; iiface < nnon_halo_doubled_face_ele;
39068 face_element_added =
false;
39069 ele_face_pt = non_halo_doubled_face_element_pt[iiface];
39076 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iiface + 1];
39077 bool both_face_elements_are_nonhalo =
false;
39079 #ifdef OOMPH_HAS_MPI
39080 if (!repeated_ele_face_pt->is_halo())
39082 both_face_elements_are_nonhalo =
true;
39086 if (!face_element_done[ele_face_pt] &&
39087 (both_face_elements_are_nonhalo ==
39088 both_root_face_elements_are_nonhalo))
39091 const unsigned nlnode = ele_face_pt->nnode();
39092 Node* left_node_pt = ele_face_pt->node_pt(0);
39093 Node* right_node_pt = ele_face_pt->node_pt(nlnode - 1);
39095 if (left_node_pt == first_node_pt)
39097 first_node_pt = right_node_pt;
39098 face_element_added =
true;
39100 else if (left_node_pt == last_node_pt)
39102 last_node_pt = right_node_pt;
39103 face_element_added =
true;
39105 else if (right_node_pt == first_node_pt)
39107 first_node_pt = left_node_pt;
39108 face_element_added =
true;
39110 else if (right_node_pt == last_node_pt)
39112 last_node_pt = left_node_pt;
39113 face_element_added =
true;
39116 if (face_element_added)
39120 left_node_pt->get_coordinates_on_boundary(bound, bound_left);
39121 vertex_coord[0] = bound_left[0];
39124 for (
unsigned i = 0; i < 2; i++)
39126 vertex_coord[i + 1] = left_node_pt->x(i);
39128 local_vertex_nodes.insert(vertex_coord);
39132 right_node_pt->get_coordinates_on_boundary(bound, bound_right);
39133 vertex_coord[0] = bound_right[0];
39136 for (
unsigned i = 0; i < 2; i++)
39138 vertex_coord[i + 1] = right_node_pt->x(i);
39140 local_vertex_nodes.insert(vertex_coord);
39144 face_element_done[ele_face_pt] =
true;
39147 repeated_ele_face_pt =
39148 non_halo_doubled_face_element_pt[iiface + 1];
39149 face_element_done[repeated_ele_face_pt] =
true;
39151 nsorted_face_elements += 2;
39159 zeta_target_area_values[0] =
39160 std::min(bound_left[0], bound_right[0]);
39163 const unsigned lef =
39164 face_element_index_on_boundary[ele_face_pt];
39165 FiniteElement* lel_pt = this->boundary_element_pt(bound, lef);
39168 found_global_element_index =
false;
39170 for (
unsigned eg = 0; eg < nele; eg++)
39173 FiniteElement* lel_compare_pt = this->finite_element_pt(eg);
39177 if (lel_pt == lel_compare_pt)
39179 target_area_face_element = target_area[eg];
39181 found_global_element_index =
true;
39188 if (!found_global_element_index)
39190 std::ostringstream error_message;
39191 error_message <<
"The global index for the (" << lef
39192 <<
")-th face element "
39193 <<
"on\nthe (" << bound
39194 <<
")-th boundary was not found!!!";
39195 throw OomphLibError(error_message.str(),
39196 OOMPH_CURRENT_FUNCTION,
39197 OOMPH_EXCEPTION_LOCATION);
39202 const unsigned rlef =
39203 face_element_index_on_boundary[repeated_ele_face_pt];
39204 FiniteElement* rlel_pt = this->boundary_element_pt(bound, rlef);
39207 found_global_repeated_element_index =
false;
39209 for (
unsigned eg = 0; eg < nele; eg++)
39212 FiniteElement* lel_compare_pt = this->finite_element_pt(eg);
39216 if (rlel_pt == lel_compare_pt)
39218 target_area_repeated_face_element = target_area[eg];
39220 found_global_repeated_element_index =
true;
39227 if (!found_global_repeated_element_index)
39229 std::ostringstream error_message;
39230 error_message <<
"The global index for the (" << rlef
39231 <<
")-th face element "
39232 <<
"on\nthe (" << bound
39233 <<
")-th boundary was not found "
39234 <<
"(repeated face element)!!!";
39235 throw OomphLibError(error_message.str(),
39236 OOMPH_CURRENT_FUNCTION,
39237 OOMPH_EXCEPTION_LOCATION);
39243 zeta_target_area_values[1] = std::min(
39244 target_area_face_element, target_area_repeated_face_element);
39247 sorted_target_areas.insert(zeta_target_area_values);
39254 }
while (face_element_added &&
39255 (nsorted_face_elements < nnon_halo_doubled_face_ele));
39263 const unsigned nlocal_nodes = local_vertex_nodes.size();
39265 local_tmp_vector_vertex_node.resize(nlocal_nodes);
39268 unsigned counter = 0;
39269 std::set<Vector<double>>::iterator it_vertex;
39270 for (it_vertex = local_vertex_nodes.begin();
39271 it_vertex != local_vertex_nodes.end();
39274 local_tmp_vector_vertex_node[counter].resize(3);
39275 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
39276 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
39277 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
39283 const unsigned ntarget_areas = sorted_target_areas.size();
39284 tmp_sorted_target_areas.resize(ntarget_areas);
39286 std::set<Vector<double>>::iterator it_area;
39287 for (it_area = sorted_target_areas.begin();
39288 it_area != sorted_target_areas.end();
39291 tmp_sorted_target_areas[counter] = (*it_area)[1];
39296 if (nlocal_nodes > 0 && (ntarget_areas != nlocal_nodes - 1))
39298 std::ostringstream error_message;
39300 <<
"The boundary (" << bound <<
") was split during the "
39301 <<
"distribution process.\n"
39302 <<
"The problem comes when associating the target areas with the "
39303 <<
"elements that gave\nrise to the vertex coordinates.\n"
39304 <<
"The number of local nodes on the 'sub-polyline' ("
39305 << nlocal_nodes <<
") is not according with the number of target\n"
39306 <<
"areas (" << ntarget_areas <<
") for that number of nodes.\n"
39307 <<
"The target areas number must be equal to the number of "
39309 throw OomphLibError(error_message.str(),
39310 OOMPH_CURRENT_FUNCTION,
39311 OOMPH_EXCEPTION_LOCATION);
39318 if (local_tmp_vector_vertex_node[nlocal_nodes - 1][2] <
39319 local_tmp_vector_vertex_node[0][2])
39321 std::reverse(local_tmp_vector_vertex_node.begin(),
39322 local_tmp_vector_vertex_node.end());
39323 std::reverse(tmp_sorted_target_areas.begin(),
39324 tmp_sorted_target_areas.end());
39326 else if (local_tmp_vector_vertex_node[nlocal_nodes - 1][2] ==
39327 local_tmp_vector_vertex_node[0][2])
39329 if (local_tmp_vector_vertex_node[nlocal_nodes - 1][1] <
39330 local_tmp_vector_vertex_node[0][1])
39332 std::reverse(local_tmp_vector_vertex_node.begin(),
39333 local_tmp_vector_vertex_node.end());
39334 std::reverse(tmp_sorted_target_areas.begin(),
39335 tmp_sorted_target_areas.end());
39346 double unrefinement_tolerance =
39347 open_curve_pt->polyline_pt(cs)->unrefinement_tolerance();
39350 bool unrefinement_applied =
39351 unrefine_boundary_constrained_by_target_area(
39354 local_tmp_vector_vertex_node,
39355 unrefinement_tolerance,
39356 tmp_sorted_target_areas);
39359 double refinement_tolerance =
39360 open_curve_pt->polyline_pt(cs)->refinement_tolerance();
39363 bool refinement_applied = refine_boundary_constrained_by_target_area(
39365 local_tmp_vector_vertex_node,
39366 refinement_tolerance,
39367 tmp_sorted_target_areas);
39371 local_vertex_nodes.clear();
39376 const unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
39377 for (
unsigned i = 0; i < nnew_nodes; i++)
39379 vertex_coord[0] = local_tmp_vector_vertex_node[i][0];
39380 vertex_coord[1] = local_tmp_vector_vertex_node[i][1];
39381 vertex_coord[2] = local_tmp_vector_vertex_node[i][2];
39382 vertex_nodes.insert(vertex_coord);
39383 local_vertex_nodes.insert(vertex_coord);
39388 update_was_performed = (unrefinement_applied || refinement_applied);
39390 #ifdef OOMPH_HAS_MPI
39391 if (this->is_mesh_distributed())
39396 sub_vertex_nodes.push_back(local_vertex_nodes);
39402 if (both_root_face_elements_are_nonhalo)
39404 internal_to_shared_boundary.push_back(
false);
39408 internal_to_shared_boundary.push_back(
true);
39419 const unsigned npoly_vertex = vertex_nodes.size();
39420 tmp_vector_vertex_node.resize(npoly_vertex);
39421 unsigned count = 0;
39422 for (std::set<Vector<double>>::iterator it = vertex_nodes.begin();
39423 it != vertex_nodes.end();
39426 tmp_vector_vertex_node[count].resize(3);
39427 tmp_vector_vertex_node[count][0] = (*it)[0];
39428 tmp_vector_vertex_node[count][1] = (*it)[1];
39429 tmp_vector_vertex_node[count][2] = (*it)[2];
39433 #ifdef OOMPH_HAS_MPI
39438 const unsigned nsub_boundaries_set = sub_vertex_nodes.size();
39439 const unsigned ninternal_to_shared_boundaries =
39440 internal_to_shared_boundary.size();
39441 if (nsub_boundaries_set != ninternal_to_shared_boundaries)
39443 std::ostringstream error_message;
39445 <<
"The number of found sub-boundaries and the number of marked "
39446 <<
"internal\nboundaries are different\n"
39447 <<
"Number of found sub-boundaries: (" << nsub_boundaries_set <<
")\n"
39448 <<
"Number of marked internal boundaries: ("
39449 << ninternal_to_shared_boundaries <<
")\n\n";
39450 throw OomphLibError(error_message.str(),
39451 OOMPH_CURRENT_FUNCTION,
39452 OOMPH_EXCEPTION_LOCATION);
39458 if (nsub_boundaries_set != nsub_boundaries)
39460 std::ostringstream error_message;
39462 <<
"The number of found sub-boundaries and the number of counted\n"
39463 <<
"sub-boundaries are different:\n"
39464 <<
"Number of found sub-boundaries: (" << nsub_boundaries_set <<
")\n"
39465 <<
"Number of counted sub-boundaries: (" << nsub_boundaries
39467 throw OomphLibError(error_message.str(),
39468 OOMPH_CURRENT_FUNCTION,
39469 OOMPH_EXCEPTION_LOCATION);
39474 if (this->is_mesh_distributed() && nsub_boundaries > 1)
39477 this->Boundary_was_splitted[bound] =
true;
39480 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
39482 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
39485 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
39486 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
39487 unsigned subcount = 0;
39488 std::set<Vector<double>>::iterator subit;
39489 for (subit = sub_vertex_nodes[isub].begin();
39490 subit != sub_vertex_nodes[isub].end();
39493 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
39494 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
39495 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
39496 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
39506 unsigned n_vertex = tmp_vector_vertex_node.size();
39509 vector_vertex_node.resize(n_vertex);
39510 for (
unsigned i = 0; i < n_vertex; i++)
39512 vector_vertex_node[i].resize(2);
39513 vector_vertex_node[i][0] = tmp_vector_vertex_node[i][1];
39514 vector_vertex_node[i][1] = tmp_vector_vertex_node[i][2];
39517 #ifdef OOMPH_HAS_MPI
39520 if (this->is_mesh_distributed() && nsub_boundaries > 1)
39525 sub_vector_vertex_node.resize(nsub_boundaries);
39526 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
39528 const unsigned subn_vertex = sub_tmp_vector_vertex_node[isub].size();
39530 sub_vector_vertex_node[isub].resize(subn_vertex);
39531 for (
unsigned i = 0; i < subn_vertex; i++)
39533 sub_vector_vertex_node[isub][i].resize(2);
39534 sub_vector_vertex_node[isub][i][0] =
39535 sub_tmp_vector_vertex_node[isub][i][1];
39536 sub_vector_vertex_node[isub][i][1] =
39537 sub_tmp_vector_vertex_node[isub][i][2];
39552 #ifdef OOMPH_HAS_MPI
39556 if (!this->is_mesh_distributed())
39562 Vector<double> final_vertex_of_previous_segment;
39563 unsigned n_prev_vertex =
39564 open_curve_pt->curve_section_pt(cs - 1)->nvertex();
39565 final_vertex_of_previous_segment =
39566 open_curve_pt->polyline_pt(cs - 1)->vertex_coordinate(
39567 n_prev_vertex - 1);
39569 unsigned prev_seg_boundary_id =
39570 open_curve_pt->curve_section_pt(cs - 1)->boundary_id();
39574 double error = 0.0;
39575 for (
unsigned i = 0; i < 2; i++)
39577 const double dist = final_vertex_of_previous_segment[i] -
39578 (*vector_vertex_node.begin())[i];
39579 error += dist * dist;
39581 error = sqrt(error);
39585 if (error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
39589 double rev_error = 0.0;
39590 for (
unsigned i = 0; i < 2; i++)
39592 const double dist = final_vertex_of_previous_segment[i] -
39593 (*--vector_vertex_node.end())[i];
39594 rev_error += dist * dist;
39596 rev_error = sqrt(rev_error);
39599 ToleranceForVertexMismatchInPolygons::Tolerable_error)
39608 Vector<double> initial_vertex_of_previous_segment;
39610 initial_vertex_of_previous_segment =
39611 open_curve_pt->polyline_pt(cs - 1)->vertex_coordinate(0);
39613 unsigned prev_seg_boundary_id =
39614 open_curve_pt->curve_section_pt(cs - 1)->boundary_id();
39618 double error = 0.0;
39619 for (
unsigned i = 0; i < 2; i++)
39621 const double dist = initial_vertex_of_previous_segment[i] -
39622 (*vector_vertex_node.begin())[i];
39623 error += dist * dist;
39625 error = sqrt(error);
39630 ToleranceForVertexMismatchInPolygons::Tolerable_error)
39634 double rev_error = 0.0;
39635 for (
unsigned i = 0; i < 2; i++)
39637 const double dist = initial_vertex_of_previous_segment[i] -
39638 (*--vector_vertex_node.end())[i];
39639 rev_error += dist * dist;
39641 rev_error = sqrt(rev_error);
39645 ToleranceForVertexMismatchInPolygons::Tolerable_error)
39647 std::ostringstream error_stream;
39649 <<
"The distance between the first node of the current\n"
39650 <<
"line segment (boundary " << bound
39651 <<
") and either end of "
39652 <<
"the previous line segment\n"
39653 <<
"(boundary " << prev_seg_boundary_id
39654 <<
") is bigger than"
39655 <<
" the desired tolerance "
39656 << ToleranceForVertexMismatchInPolygons::Tolerable_error
39658 <<
"This suggests that the polylines defining the "
39660 <<
"representation are not properly ordered.\n"
39661 <<
"Fail on last vertex of polyline: ("
39662 << prev_seg_boundary_id
39663 <<
") and\nfirst vertex of polyline (" << bound
39664 <<
").\nThis should have failed when first trying to "
39665 <<
"construct the\npolygon.\n";
39666 throw OomphLibError(error_stream.str(),
39667 OOMPH_CURRENT_FUNCTION,
39668 OOMPH_EXCEPTION_LOCATION);
39675 std::reverse(vector_vertex_node.begin(),
39676 vector_vertex_node.end());
39677 open_curve_pt->polyline_pt(cs - 1)->reverse();
39683 open_curve_pt->polyline_pt(cs - 1)->reverse();
39689 std::ostringstream error_stream;
39691 <<
"The distance between the first node of the current\n"
39692 <<
"line segment (boundary " << bound
39693 <<
") and either end of "
39694 <<
"the previous line segment\n"
39695 <<
"(boundary " << prev_seg_boundary_id
39696 <<
") is bigger than the "
39697 <<
"desired tolerance "
39698 << ToleranceForVertexMismatchInPolygons::Tolerable_error
39700 <<
"This suggests that the polylines defining the polygonal\n"
39701 <<
"representation are not properly ordered.\n"
39702 <<
"Fail on last vertex of polyline: ("
39703 << prev_seg_boundary_id <<
") and\nfirst vertex of polyline ("
39705 <<
"This should have failed when first trying to construct\n"
39706 <<
"the polygon.\n";
39707 throw OomphLibError(error_stream.str(),
39708 OOMPH_CURRENT_FUNCTION,
39709 OOMPH_EXCEPTION_LOCATION);
39715 std::reverse(vector_vertex_node.begin(),
39716 vector_vertex_node.end());
39733 n_vertex = vector_vertex_node.size();
39736 TriangleMeshPolyLine* tmp_polyline_pt =
39737 new TriangleMeshPolyLine(vector_vertex_node, bound);
39741 TriangleMeshCurveSection* tmp_curve_section_pt = tmp_polyline_pt;
39745 double unrefinement_tolerance =
39746 open_curve_pt->polyline_pt(cs)->unrefinement_tolerance();
39749 double refinement_tolerance =
39750 open_curve_pt->polyline_pt(cs)->refinement_tolerance();
39753 tmp_polyline_pt->set_unrefinement_tolerance(unrefinement_tolerance);
39754 tmp_polyline_pt->set_refinement_tolerance(refinement_tolerance);
39757 double maximum_length = open_curve_pt->polyline_pt(cs)->maximum_length();
39758 tmp_polyline_pt->set_maximum_length(maximum_length);
39760 #ifdef OOMPH_HAS_MPI
39763 if (this->is_mesh_distributed())
39769 this->copy_connection_information(open_curve_pt->polyline_pt(cs),
39770 tmp_curve_section_pt);
39778 this->copy_connection_information(open_curve_pt->polyline_pt(cs),
39779 tmp_curve_section_pt);
39785 bool delete_it_on_destructor =
false;
39787 std::set<TriangleMeshCurveSection*>::iterator it =
39788 this->Free_curve_section_pt.find(open_curve_pt->curve_section_pt(cs));
39790 if (it != this->Free_curve_section_pt.end())
39792 this->Free_curve_section_pt.erase(it);
39793 delete open_curve_pt->curve_section_pt(cs);
39794 delete_it_on_destructor =
true;
39799 open_curve_pt->curve_section_pt(cs) = tmp_polyline_pt;
39802 this->Boundary_curve_section_pt[bound] =
39803 open_curve_pt->curve_section_pt(cs);
39805 if (delete_it_on_destructor)
39807 this->Free_curve_section_pt.insert(open_curve_pt->curve_section_pt(cs));
39810 #ifdef OOMPH_HAS_MPI
39813 if (this->is_mesh_distributed() && nsub_boundaries == 1)
39816 this->Boundary_marked_as_shared_boundary[bound].clear();
39819 this->Boundary_marked_as_shared_boundary[bound].push_back(
39820 internal_to_shared_boundary[0]);
39824 else if (this->is_mesh_distributed() && nsub_boundaries > 1)
39830 this->Boundary_subpolylines[bound].clear();
39832 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
39835 this->Boundary_marked_as_shared_boundary[bound].clear();
39838 this->Boundary_marked_as_shared_boundary[bound].resize(nsub_boundaries);
39839 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
39843 TriangleMeshPolyLine* sub_tmp_polyline_pt =
39844 new TriangleMeshPolyLine(sub_vector_vertex_node[isub], bound, isub);
39848 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
39852 this->Boundary_marked_as_shared_boundary[bound][isub] =
39853 internal_to_shared_boundary[isub];
39862 TriangleMeshCurveSection* tmp_sub_curve_section_pt =
39863 sub_tmp_polyline_pt;
39864 this->copy_connection_information_to_sub_polylines(
39865 tmp_curve_section_pt, tmp_sub_curve_section_pt);
39875 delete mesh_geom_obj_pt;
39880 for (
unsigned p = 0; p < ncurve_section; p++)
39882 face_mesh_pt[p]->flush_node_storage();
39883 delete face_mesh_pt[p];
39886 return update_was_performed;
39889 #ifdef OOMPH_HAS_MPI
39894 template<
class ELEMENT>
39896 Vector<TriangleMeshPolyLine*>& vector_polyline_pt,
39897 const Vector<double>& target_areas)
39901 unsigned update_was_performed =
false;
39904 const unsigned n_polylines = vector_polyline_pt.size();
39905 for (
unsigned pp = 0; pp < n_polylines; pp++)
39908 const unsigned shd_bnd_id = vector_polyline_pt[pp]->boundary_id();
39911 const unsigned chunk = vector_polyline_pt[pp]->boundary_chunk();
39919 std::map<FiniteElement*, FiniteElement*> face_ele_pt_to_bulk_element_pt;
39922 Vector<FiniteElement*> halo_shared_face_ele_pt;
39924 Vector<FiniteElement*> nonhalo_shared_face_ele_pt;
39928 const unsigned nshared_bound_ele =
39929 this->nshared_boundary_element(shd_bnd_id);
39933 for (
unsigned e = 0; e < nshared_bound_ele; e++)
39936 FiniteElement* bulk_ele_pt =
39937 this->shared_boundary_element_pt(shd_bnd_id, e);
39940 int face_index = this->face_index_at_shared_boundary(shd_bnd_id, e);
39944 FiniteElement* face_ele_pt =
39945 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
39949 face_ele_pt_to_bulk_element_pt[face_ele_pt] = bulk_ele_pt;
39952 if (!bulk_ele_pt->is_halo())
39955 nonhalo_shared_face_ele_pt.push_back(face_ele_pt);
39960 halo_shared_face_ele_pt.push_back(face_ele_pt);
39967 Vector<Vector<FiniteElement*>> unsorted_shared_bulk_ele_pt;
39970 std::map<FiniteElement*, bool> shared_face_done;
39973 const unsigned nnonhalo_face_shared_ele =
39974 nonhalo_shared_face_ele_pt.size();
39977 const unsigned nhalo_face_shared_ele = halo_shared_face_ele_pt.size();
39982 if (nshared_bound_ele / 2 != nnonhalo_face_shared_ele)
39984 std::ostringstream error_message;
39986 <<
"The number of shared boundary elements (" << nshared_bound_ele
39987 <<
") is not the double\nof the number of unsorted NONHALO shared "
39988 <<
"face boundary elements (" << nnonhalo_face_shared_ele <<
")\n"
39989 <<
"for the current boundary (" << shd_bnd_id <<
")\n\n";
39990 throw OomphLibError(error_message.str(),
39991 OOMPH_CURRENT_FUNCTION,
39992 OOMPH_EXCEPTION_LOCATION);
39997 if (nshared_bound_ele / 2 != nhalo_face_shared_ele)
39999 std::ostringstream error_message;
40001 <<
"The number of shared boundary elements (" << nshared_bound_ele
40002 <<
") is not the double\nof the number of unsorted HALO shared "
40003 <<
"face boundary elements (" << nhalo_face_shared_ele <<
")\n"
40004 <<
"for the current boundary (" << shd_bnd_id <<
")\n\n";
40005 throw OomphLibError(error_message.str(),
40006 OOMPH_CURRENT_FUNCTION,
40007 OOMPH_EXCEPTION_LOCATION);
40014 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
40017 FiniteElement* nonhalo_face_ele_pt = nonhalo_shared_face_ele_pt[inh];
40020 const unsigned nnodes_nh = nonhalo_face_ele_pt->nnode();
40022 Node* nh_first_node_pt = nonhalo_face_ele_pt->node_pt(0);
40023 Node* nh_last_node_pt = nonhalo_face_ele_pt->node_pt(nnodes_nh - 1);
40027 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
40030 FiniteElement* halo_face_ele_pt = halo_shared_face_ele_pt[ih];
40033 if (!shared_face_done[halo_face_ele_pt])
40036 const unsigned nnodes_h = halo_face_ele_pt->nnode();
40038 Node* h_first_node_pt = halo_face_ele_pt->node_pt(0);
40039 Node* h_last_node_pt = halo_face_ele_pt->node_pt(nnodes_h - 1);
40043 if (nh_first_node_pt == h_first_node_pt &&
40044 nh_last_node_pt == h_last_node_pt)
40047 Vector<FiniteElement*> tmp_bulk_element_pt;
40050 FiniteElement* nonhalo_bulk_ele_pt =
40051 face_ele_pt_to_bulk_element_pt[nonhalo_face_ele_pt];
40052 FiniteElement* halo_bulk_ele_pt =
40053 face_ele_pt_to_bulk_element_pt[halo_face_ele_pt];
40056 tmp_bulk_element_pt.push_back(nonhalo_bulk_ele_pt);
40057 tmp_bulk_element_pt.push_back(halo_bulk_ele_pt);
40060 unsorted_shared_bulk_ele_pt.push_back(tmp_bulk_element_pt);
40063 shared_face_done[nonhalo_face_ele_pt] =
true;
40064 shared_face_done[halo_face_ele_pt] =
true;
40070 else if (nh_first_node_pt == h_last_node_pt &&
40071 nh_last_node_pt == h_first_node_pt)
40074 Vector<FiniteElement*> tmp_bulk_element_pt;
40077 FiniteElement* nonhalo_bulk_ele_pt =
40078 face_ele_pt_to_bulk_element_pt[nonhalo_face_ele_pt];
40079 FiniteElement* halo_bulk_ele_pt =
40080 face_ele_pt_to_bulk_element_pt[halo_face_ele_pt];
40083 tmp_bulk_element_pt.push_back(nonhalo_bulk_ele_pt);
40084 tmp_bulk_element_pt.push_back(halo_bulk_ele_pt);
40087 unsorted_shared_bulk_ele_pt.push_back(tmp_bulk_element_pt);
40090 shared_face_done[nonhalo_face_ele_pt] =
true;
40091 shared_face_done[halo_face_ele_pt] =
true;
40113 const unsigned nunsorted_shared_bulk_ele =
40114 unsorted_shared_bulk_ele_pt.size();
40118 if (nshared_bound_ele / 2 != nunsorted_shared_bulk_ele)
40120 std::ostringstream error_message;
40122 <<
"The number of shared boundary elements (" << nshared_bound_ele
40123 <<
") is not the double\nof the number of unsorted shared bulk "
40124 <<
"boundary elements (" << nunsorted_shared_bulk_ele <<
")\n"
40125 <<
"for the current boundary (" << shd_bnd_id <<
")\n\n";
40126 throw OomphLibError(error_message.str(),
40127 OOMPH_CURRENT_FUNCTION,
40128 OOMPH_EXCEPTION_LOCATION);
40133 if ((nnonhalo_face_shared_ele + nhalo_face_shared_ele) !=
40134 shared_face_done.size())
40136 std::ostringstream error_message;
40137 error_message <<
"The number of DONE shared boundary face elements ("
40138 << shared_face_done.size()
40139 <<
") is not the same\n as the sum of"
40140 <<
"the nonhalo face shared boundary elements ("
40141 << nnonhalo_face_shared_ele
40142 <<
")\nand the halo face shared "
40143 <<
"boundary elements (" << nhalo_face_shared_ele
40145 <<
"current boundary (" << shd_bnd_id <<
")\n\n";
40146 throw OomphLibError(error_message.str(),
40147 OOMPH_CURRENT_FUNCTION,
40148 OOMPH_EXCEPTION_LOCATION);
40153 shared_face_done.clear();
40156 unsigned nsorted_face_ele = 0;
40160 std::list<Node*> sorted_nodes;
40163 std::list<FiniteElement*> sorted_shared_bound_elements_pt;
40166 FiniteElement* root_face_ele_pt = nonhalo_shared_face_ele_pt[0];
40167 nsorted_face_ele++;
40170 shared_face_done[root_face_ele_pt] =
true;
40173 const unsigned nnodes_root = root_face_ele_pt->nnode();
40174 Node* first_node_pt = root_face_ele_pt->node_pt(0);
40175 Node* last_node_pt = root_face_ele_pt->node_pt(nnodes_root - 1);
40178 sorted_nodes.push_back(first_node_pt);
40179 sorted_nodes.push_back(last_node_pt);
40182 sorted_shared_bound_elements_pt.push_back(
40183 unsorted_shared_bulk_ele_pt[0][0]);
40184 sorted_shared_bound_elements_pt.push_back(
40185 unsorted_shared_bulk_ele_pt[0][1]);
40188 while (nsorted_face_ele < nnonhalo_face_shared_ele)
40191 bool node_added =
false;
40195 for (
unsigned iface = 1; iface < nnonhalo_face_shared_ele; iface++)
40197 FiniteElement* tmp_shared_face_ele_pt =
40198 nonhalo_shared_face_ele_pt[iface];
40201 if (!shared_face_done[tmp_shared_face_ele_pt])
40204 const unsigned tmp_nnodes = tmp_shared_face_ele_pt->nnode();
40207 Node* left_node_pt = tmp_shared_face_ele_pt->node_pt(0);
40208 Node* right_node_pt =
40209 tmp_shared_face_ele_pt->node_pt(tmp_nnodes - 1);
40211 if (left_node_pt == first_node_pt)
40214 sorted_nodes.push_front(right_node_pt);
40215 first_node_pt = right_node_pt;
40219 sorted_shared_bound_elements_pt.push_front(
40220 unsorted_shared_bulk_ele_pt[iface][1]);
40221 sorted_shared_bound_elements_pt.push_front(
40222 unsorted_shared_bulk_ele_pt[iface][0]);
40224 else if (left_node_pt == last_node_pt)
40227 sorted_nodes.push_back(right_node_pt);
40228 last_node_pt = right_node_pt;
40232 sorted_shared_bound_elements_pt.push_back(
40233 unsorted_shared_bulk_ele_pt[iface][0]);
40234 sorted_shared_bound_elements_pt.push_back(
40235 unsorted_shared_bulk_ele_pt[iface][1]);
40237 else if (right_node_pt == first_node_pt)
40240 sorted_nodes.push_front(left_node_pt);
40241 first_node_pt = left_node_pt;
40245 sorted_shared_bound_elements_pt.push_front(
40246 unsorted_shared_bulk_ele_pt[iface][1]);
40247 sorted_shared_bound_elements_pt.push_front(
40248 unsorted_shared_bulk_ele_pt[iface][0]);
40250 else if (right_node_pt == last_node_pt)
40253 sorted_nodes.push_back(left_node_pt);
40254 last_node_pt = left_node_pt;
40258 sorted_shared_bound_elements_pt.push_back(
40259 unsorted_shared_bulk_ele_pt[iface][0]);
40260 sorted_shared_bound_elements_pt.push_back(
40261 unsorted_shared_bulk_ele_pt[iface][1]);
40268 shared_face_done[tmp_shared_face_ele_pt] =
true;
40269 nsorted_face_ele++;
40286 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
40288 delete nonhalo_shared_face_ele_pt[inh];
40289 nonhalo_shared_face_ele_pt[inh] = 0;
40293 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
40295 delete halo_shared_face_ele_pt[ih];
40296 halo_shared_face_ele_pt[ih] = 0;
40304 const unsigned n_nodes = sorted_nodes.size();
40307 Vector<Vector<double>> polyline_vertices(n_nodes);
40310 unsigned counter = 0;
40311 for (std::list<Node*>::iterator it_nodes = sorted_nodes.begin();
40312 it_nodes != sorted_nodes.end();
40315 polyline_vertices[counter].resize(2);
40316 polyline_vertices[counter][0] = (*it_nodes)->x(0);
40317 polyline_vertices[counter][1] = (*it_nodes)->x(1);
40326 Vector<FiniteElement*> sorted_shared_ele_pt;
40327 for (std::list<FiniteElement*>::iterator it_ele =
40328 sorted_shared_bound_elements_pt.begin();
40329 it_ele != sorted_shared_bound_elements_pt.end();
40332 sorted_shared_ele_pt.push_back((*it_ele));
40336 const unsigned n_shared_target_areas = sorted_shared_ele_pt.size();
40337 Vector<double> sorted_shared_target_areas(n_shared_target_areas);
40340 std::map<std::pair<GeneralisedElement*, unsigned>,
bool> shared_ele_done;
40343 unsigned count_found_shared_element = 0;
40346 const unsigned nele = this->nelement();
40350 for (
unsigned e = 0; e < nele; e++)
40352 GeneralisedElement* current_ele_pt = this->element_pt(e);
40355 for (
unsigned s = 0; s < n_shared_target_areas; s++)
40358 GeneralisedElement* current_shared_ele_pt = sorted_shared_ele_pt[s];
40360 std::pair<GeneralisedElement*, unsigned> pair_gen_ele_idx =
40361 std::make_pair(current_shared_ele_pt, s);
40362 if (!shared_ele_done[pair_gen_ele_idx])
40365 if (current_ele_pt == current_shared_ele_pt)
40368 sorted_shared_target_areas[s] = target_areas[e];
40370 shared_ele_done[pair_gen_ele_idx] =
true;
40372 count_found_shared_element++;
40378 if (count_found_shared_element == n_shared_target_areas)
40388 if (count_found_shared_element != n_shared_target_areas)
40390 std::ostringstream error_message;
40391 error_message <<
"The number of found target areas ("
40392 << count_found_shared_element
40393 <<
") is different from the "
40394 <<
"total number\nof target areas ("
40395 << n_shared_target_areas <<
") in shared boundary ("
40396 << shd_bnd_id <<
")\n\n";
40397 throw OomphLibError(error_message.str(),
40398 OOMPH_CURRENT_FUNCTION,
40399 OOMPH_EXCEPTION_LOCATION);
40404 const unsigned n_vertices = n_nodes;
40407 const unsigned n_segments = vector_polyline_pt[pp]->nsegment();
40416 if (n_segments != n_vertices - 1)
40418 std::ostringstream error_message;
40420 <<
"The number of segments from the current shared polyline "
40421 <<
"(" << n_segments <<
") does not\ncorrespond with the number of "
40422 <<
"sorted vertices (" << n_vertices - 1
40423 <<
") of the current shared\n"
40425 throw OomphLibError(error_message.str(),
40426 OOMPH_CURRENT_FUNCTION,
40427 OOMPH_EXCEPTION_LOCATION);
40432 if (n_segments != n_shared_target_areas / 2)
40434 std::ostringstream error_message;
40436 <<
"The number of segments for the current sorting of edges "
40437 <<
"(" << n_segments <<
") is different\nfrom the number of "
40438 <<
"target areas (" << n_shared_target_areas / 2 <<
")\n\n";
40439 throw OomphLibError(error_message.str(),
40440 OOMPH_CURRENT_FUNCTION,
40441 OOMPH_EXCEPTION_LOCATION);
40453 Vector<double> polyline_target_area(n_segments);
40455 for (
unsigned s = 0; s < n_segments; s++)
40458 polyline_target_area[s] =
40459 std::min(sorted_shared_target_areas[s * 2],
40460 sorted_shared_target_areas[(s * 2) + 1]);
40467 if (polyline_vertices[n_vertices - 1][1] < polyline_vertices[0][1])
40469 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
40470 std::reverse(polyline_target_area.begin(), polyline_target_area.end());
40472 else if (polyline_vertices[n_vertices - 1][1] == polyline_vertices[0][1])
40474 if (polyline_vertices[n_vertices - 1][0] < polyline_vertices[0][0])
40476 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
40477 std::reverse(polyline_target_area.begin(),
40478 polyline_target_area.end());
40484 bool unrefinement_applied =
false;
40487 if (n_vertices > 3)
40489 unrefinement_applied =
40490 unrefine_shared_boundary_constrained_by_target_area(
40491 shd_bnd_id, chunk, polyline_vertices, polyline_target_area);
40495 bool refinement_applied =
40496 refine_shared_boundary_constrained_by_target_area(polyline_vertices,
40497 polyline_target_area);
40500 update_was_performed |= (unrefinement_applied || refinement_applied);
40506 TriangleMeshPolyLine* new_polyline_pt =
40507 new TriangleMeshPolyLine(polyline_vertices, shd_bnd_id);
40510 TriangleMeshCurveSection* curve_section_pt = vector_polyline_pt[pp];
40514 this->copy_connection_information(curve_section_pt, new_polyline_pt);
40519 bool delete_it_on_destructor =
false;
40523 std::set<TriangleMeshCurveSection*>::iterator it =
40524 this->Free_curve_section_pt.find(curve_section_pt);
40526 if (it != this->Free_curve_section_pt.end())
40528 this->Free_curve_section_pt.erase(it);
40529 delete curve_section_pt;
40530 delete_it_on_destructor =
true;
40534 vector_polyline_pt[pp] = new_polyline_pt;
40537 TriangleMeshCurveSection* new_curve_section_pt = vector_polyline_pt[pp];
40540 this->Boundary_curve_section_pt[shd_bnd_id] = new_curve_section_pt;
40542 if (delete_it_on_destructor)
40544 this->Free_curve_section_pt.insert(new_curve_section_pt);
40549 return update_was_performed;
40558 template<
class ELEMENT>
40563 Vector<Vector<double>>& vector_bnd_vertices,
40564 double& unrefinement_tolerance,
40565 Vector<double>& area_constraint)
40568 std::set<Vector<double>> no_delete_vertex;
40571 const bool boundary_receive_connections =
40572 this->boundary_connections(b, c, no_delete_vertex);
40576 bool unrefinement_applied =
false;
40579 if (!Do_boundary_unrefinement_constrained_by_target_areas)
40581 return unrefinement_applied;
40595 unsigned n_vertex = vector_bnd_vertices.size();
40598 const double constant_value = 4.0 / sqrt(3.0);
40604 for (
unsigned i = 1; i < n_vertex - 1; i += 2)
40606 if (area_constraint[i - 1] > 0 && area_constraint[i] > 0)
40608 const double local_zeta_first = vector_bnd_vertices[i - 1][0];
40609 const double local_zeta_last = vector_bnd_vertices[i + 1][0];
40610 const double local_length_zeta =
40611 std::fabs(local_zeta_last - local_zeta_first);
40613 const double x1 = vector_bnd_vertices[i - 1][1];
40614 const double y1 = vector_bnd_vertices[i - 1][2];
40615 const double x2 = vector_bnd_vertices[i + 1][1];
40616 const double y2 = vector_bnd_vertices[i + 1][2];
40617 const double local_length =
40618 sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
40620 const double x_m = vector_bnd_vertices[i][1];
40621 const double y_m = vector_bnd_vertices[i][2];
40623 const double average_area_constraint =
40624 (area_constraint[i - 1] + area_constraint[i]) / 2.0;
40628 const double length_side =
40629 sqrt(constant_value * average_area_constraint);
40631 const double length_side_zeta =
40632 (local_length_zeta * length_side) / local_length;
40635 if ((length_side_zeta / local_length_zeta) > 1.0)
40643 double a_x = vector_bnd_vertices[i - 1][1];
40644 double a_y = vector_bnd_vertices[i - 1][2];
40645 double b_x = vector_bnd_vertices[i][1];
40646 double b_y = vector_bnd_vertices[i][2];
40647 double c_x = vector_bnd_vertices[i + 1][1];
40648 double c_y = vector_bnd_vertices[i + 1][2];
40650 double a = b_x - a_x;
40651 double b = b_y - a_y;
40652 double c = c_x - a_x;
40653 double d = c_y - a_y;
40655 double e = a * (a_x + b_x) + b * (a_y + b_y);
40656 double f = c * (a_x + c_x) + d * (a_y + c_y);
40658 double g = 2.0 * (a * (c_y - b_y) - b * (c_x - b_x));
40660 bool do_it =
false;
40661 if (std::fabs(g) < 1.0e-14)
40667 double p_x = (d * e - b * f) / g;
40668 double p_y = (a * f - c * e) / g;
40670 double r = sqrt(pow((a_x - p_x), 2) + pow((a_y - p_y), 2));
40672 double rhalfca_x = 0.5 * (a_x - c_x);
40673 double rhalfca_y = 0.5 * (a_y - c_y);
40675 double halfca_squared = pow(rhalfca_x, 2) + pow(rhalfca_y, 2);
40677 double sticky_out_bit =
40678 r - sqrt(std::fabs((r * r) - halfca_squared));
40683 if ((sticky_out_bit / (2.0 * sqrt(halfca_squared))) <
40684 unrefinement_tolerance)
40692 if (do_it && boundary_receive_connections)
40695 for (std::set<Vector<double>>::iterator it =
40696 no_delete_vertex.begin();
40697 it != no_delete_vertex.end();
40702 const double x = (*it)[0];
40703 const double y = (*it)[1];
40704 double error = (x_m - x) * (x_m - x) + (y_m - y) * (y_m - y);
40705 error = sqrt(error);
40708 ToleranceForVertexMismatchInPolygons::Tolerable_error)
40721 vector_bnd_vertices[i].resize(0);
40729 Vector<Vector<double>> compact_vector;
40732 Vector<double> compact_area_constraint;
40735 for (
unsigned i = 0; i < n_vertex; i++)
40738 if (vector_bnd_vertices[i].size() != 0)
40740 compact_vector.push_back(vector_bnd_vertices[i]);
40746 unsigned nsize_target = area_constraint.size();
40747 if (nsize_target == 1)
40750 compact_area_constraint.push_back(area_constraint[0]);
40754 for (
unsigned i = 1; i < n_vertex; i += 2)
40758 if (vector_bnd_vertices[i].size() != 0)
40760 compact_area_constraint.push_back(area_constraint[i - 1]);
40762 if (i < nsize_target)
40764 compact_area_constraint.push_back(area_constraint[i]);
40771 double new_area_constraint =
40772 (area_constraint[i - 1] + area_constraint[i]) / 2.0;
40773 compact_area_constraint.push_back(new_area_constraint);
40780 if (n_vertex != compact_vector.size())
40782 unrefinement_applied =
true;
40786 n_vertex = compact_vector.size();
40787 vector_bnd_vertices.resize(n_vertex);
40788 for (
unsigned i = 0; i < n_vertex; i++)
40790 vector_bnd_vertices[i].resize(3);
40791 vector_bnd_vertices[i][0] = compact_vector[i][0];
40792 vector_bnd_vertices[i][1] = compact_vector[i][1];
40793 vector_bnd_vertices[i][2] = compact_vector[i][2];
40797 unsigned ntarget_areas = compact_area_constraint.size();
40798 area_constraint.resize(ntarget_areas);
40799 for (
unsigned i = 0; i < ntarget_areas; i++)
40801 area_constraint[i] = compact_area_constraint[i];
40806 return unrefinement_applied;
40814 template<
class ELEMENT>
40817 MeshAsGeomObject* mesh_geom_obj_pt,
40818 Vector<Vector<double>>& vector_bnd_vertices,
40819 double& refinement_tolerance,
40820 Vector<double>& area_constraint)
40824 bool refinement_applied =
false;
40827 if (!Do_boundary_refinement_constrained_by_target_areas)
40829 return refinement_applied;
40833 unsigned n_vertex = vector_bnd_vertices.size();
40836 const double constant_value = 4.0 / sqrt(3.0);
40842 Vector<Vector<double>> new_vector;
40846 for (
unsigned i = 0; i < n_vertex - 1; i++)
40849 new_vector.push_back(vector_bnd_vertices[i]);
40851 if (area_constraint[i] > 0)
40853 double local_zeta_first = vector_bnd_vertices[i][0];
40854 double local_zeta_last = vector_bnd_vertices[i + 1][0];
40855 const double local_length_zeta =
40856 std::fabs(local_zeta_last - local_zeta_first);
40861 if (local_zeta_first > local_zeta_last)
40863 const double tmp_zeta = local_zeta_first;
40864 local_zeta_first = local_zeta_last;
40865 local_zeta_last = tmp_zeta;
40868 const double x1 = vector_bnd_vertices[i][1];
40869 const double y1 = vector_bnd_vertices[i][2];
40870 const double x2 = vector_bnd_vertices[i + 1][1];
40871 const double y2 = vector_bnd_vertices[i + 1][2];
40872 const double local_length =
40873 sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
40876 const double length_side = sqrt(constant_value * area_constraint[i]);
40877 const double length_side_zeta =
40878 (local_length_zeta * length_side) / local_length;
40881 const double n_seg_double = length_side_zeta / local_length_zeta;
40884 unsigned n_seg = 1;
40887 n_seg +=
static_cast<unsigned>(std::floor(1.0 / n_seg_double));
40894 double zeta_increment = (local_length_zeta) / ((
double)n_seg);
40896 Vector<double> zeta(1);
40898 for (
unsigned s = 1; s < n_seg; s++)
40901 zeta[0] = local_zeta_first + zeta_increment * double(s);
40902 Vector<double> vertex(2);
40903 mesh_geom_obj_pt->position(zeta, vertex);
40906 Vector<double> new_node(3);
40907 new_node[0] = zeta[0];
40908 new_node[1] = vertex[0];
40909 new_node[2] = vertex[1];
40912 new_vector.push_back(new_node);
40923 new_vector.push_back(vector_bnd_vertices[n_vertex - 1]);
40928 n_vertex = new_vector.size();
40929 if (n_vertex != vector_bnd_vertices.size())
40931 refinement_applied =
true;
40935 vector_bnd_vertices.resize(n_vertex);
40936 for (
unsigned i = 0; i < n_vertex; i++)
40938 vector_bnd_vertices[i].resize(3);
40939 vector_bnd_vertices[i][0] = new_vector[i][0];
40940 vector_bnd_vertices[i][1] = new_vector[i][1];
40941 vector_bnd_vertices[i][2] = new_vector[i][2];
40946 return refinement_applied;
40956 template<
class ELEMENT>
40961 Vector<Vector<double>>& vector_bnd_vertices,
40962 Vector<double>& area_constraint)
40965 std::set<Vector<double>> no_delete_vertex;
40968 const bool boundary_receive_connections =
40969 this->boundary_connections(b, c, no_delete_vertex);
40973 bool unrefinement_applied =
false;
40976 if (!Do_shared_boundary_unrefinement_constrained_by_target_areas)
40978 return unrefinement_applied;
40994 unsigned n_vertex = vector_bnd_vertices.size();
40997 const double constant_value = 4.0 / sqrt(3.0);
41003 for (
unsigned i = 1; i < n_vertex - 1; i += 2)
41007 if (area_constraint[i - 1] > 0 && area_constraint[i] > 0)
41010 const double x1 = vector_bnd_vertices[i - 1][0];
41011 const double y1 = vector_bnd_vertices[i - 1][1];
41013 const double x2 = vector_bnd_vertices[i + 1][0];
41014 const double y2 = vector_bnd_vertices[i + 1][1];
41017 const double local_length =
41018 sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
41021 const double x_m = vector_bnd_vertices[i][0];
41022 const double y_m = vector_bnd_vertices[i][1];
41025 const double average_area_constraint =
41026 (area_constraint[i - 1] + area_constraint[i]) / 2.0;
41030 const double length_side =
41031 sqrt(constant_value * average_area_constraint);
41034 if ((length_side / local_length) > 1.0)
41040 if (do_it && boundary_receive_connections)
41043 for (std::set<Vector<double>>::iterator it =
41044 no_delete_vertex.begin();
41045 it != no_delete_vertex.end();
41050 const double x = (*it)[0];
41051 const double y = (*it)[1];
41052 double error = (x_m - x) * (x_m - x) + (y_m - y) * (y_m - y);
41053 error = sqrt(error);
41056 ToleranceForVertexMismatchInPolygons::Tolerable_error)
41069 vector_bnd_vertices[i].resize(0);
41079 Vector<Vector<double>> compact_vector;
41082 Vector<double> compact_area_constraint;
41085 for (
unsigned i = 0; i < n_vertex; i++)
41088 if (vector_bnd_vertices[i].size() != 0)
41090 compact_vector.push_back(vector_bnd_vertices[i]);
41096 unsigned n_area_constraint = area_constraint.size();
41097 if (n_area_constraint == 1)
41100 compact_area_constraint.push_back(area_constraint[0]);
41104 for (
unsigned i = 1; i < n_vertex; i += 2)
41108 if (vector_bnd_vertices[i].size() != 0)
41110 compact_area_constraint.push_back(area_constraint[i - 1]);
41112 if (i < n_area_constraint)
41114 compact_area_constraint.push_back(area_constraint[i]);
41121 const double new_area_constraint =
41122 (area_constraint[i - 1] + area_constraint[i]) / 2.0;
41123 compact_area_constraint.push_back(new_area_constraint);
41130 if (n_vertex != compact_vector.size())
41132 unrefinement_applied =
true;
41136 n_vertex = compact_vector.size();
41137 vector_bnd_vertices.resize(n_vertex);
41138 for (
unsigned i = 0; i < n_vertex; i++)
41140 vector_bnd_vertices[i].resize(2);
41141 vector_bnd_vertices[i][0] = compact_vector[i][0];
41142 vector_bnd_vertices[i][1] = compact_vector[i][1];
41146 unsigned ntarget_areas = compact_area_constraint.size();
41147 area_constraint.resize(ntarget_areas);
41148 for (
unsigned i = 0; i < ntarget_areas; i++)
41150 area_constraint[i] = compact_area_constraint[i];
41155 return unrefinement_applied;
41165 template<
class ELEMENT>
41168 Vector<Vector<double>>& vector_bnd_vertices,
41169 Vector<double>& area_constraint)
41173 bool refinement_applied =
false;
41176 if (!Do_shared_boundary_refinement_constrained_by_target_areas)
41178 return refinement_applied;
41182 unsigned nsegments = vector_bnd_vertices.size() - 1;
41186 Vector<Vector<double>> tmp_bnd_vertices;
41189 const double constant_value = 4.0 / sqrt(3.0);
41191 for (
unsigned s = 0; s < nsegments; s++)
41193 Vector<double> left_vertex = vector_bnd_vertices[s];
41194 Vector<double> right_vertex = vector_bnd_vertices[s + 1];
41197 const double x1 = left_vertex[0];
41198 const double y1 = left_vertex[1];
41199 const double x2 = right_vertex[0];
41200 const double y2 = right_vertex[1];
41203 const double segment_length =
41204 sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
41207 const double new_segment_length =
41208 sqrt(constant_value * area_constraint[s]);
41211 const double n_seg_double = new_segment_length / segment_length;
41216 nseg +=
static_cast<unsigned>(std::floor(1.0 / n_seg_double));
41220 tmp_bnd_vertices.push_back(left_vertex);
41227 double incrementx = (right_vertex[0] - left_vertex[0]) / (
double)(nseg);
41228 double incrementy = (right_vertex[1] - left_vertex[1]) / (
double)(nseg);
41229 for (
unsigned i = 1; i < nseg; i++)
41231 Vector<double> tmp_vertex(2);
41232 tmp_vertex[0] = left_vertex[0] + incrementx * i;
41233 tmp_vertex[1] = left_vertex[1] + incrementy * i;
41234 tmp_bnd_vertices.push_back(tmp_vertex);
41242 tmp_bnd_vertices.push_back(vector_bnd_vertices[nsegments]);
41247 nsegments = tmp_bnd_vertices.size() - 1;
41248 if (nsegments != vector_bnd_vertices.size() - 1)
41250 refinement_applied =
true;
41253 vector_bnd_vertices.resize(nsegments + 1);
41254 for (
unsigned i = 0; i < nsegments + 1; i++)
41256 vector_bnd_vertices[i].resize(2);
41257 vector_bnd_vertices[i][0] = tmp_bnd_vertices[i][0];
41258 vector_bnd_vertices[i][1] = tmp_bnd_vertices[i][1];
41262 return refinement_applied;
41268 template<
class ELEMENT>
41270 TriangleMeshPolygon*& polygon_pt)
41278 Vector<Mesh*> face_mesh_pt;
41279 get_face_mesh_representation(polygon_pt, face_mesh_pt);
41283 Vector<double> vertex_coord(3);
41284 Vector<double> bound_left(1);
41285 Vector<double> bound_right(1);
41287 const unsigned n_polyline = polygon_pt->npolyline();
41290 for (
unsigned p = 0; p < n_polyline; p++)
41298 MeshAsGeomObject* mesh_geom_obj_pt =
41299 new MeshAsGeomObject(face_mesh_pt[p]);
41304 std::set<Vector<double>> vertex_nodes;
41308 Vector<Vector<double>> tmp_vector_vertex_node;
41313 Vector<Vector<double>> vector_vertex_node;
41315 #ifdef OOMPH_HAS_MPI
41321 Vector<std::set<Vector<double>>> sub_vertex_nodes;
41325 Vector<Vector<Vector<double>>> sub_tmp_vector_vertex_node;
41330 Vector<Vector<Vector<double>>> sub_vector_vertex_node;
41335 unsigned bound = polygon_pt->curve_section_pt(p)->boundary_id();
41342 const unsigned nface_element = face_mesh_pt[p]->nelement();
41346 Vector<FiniteElement*> non_halo_face_element_pt;
41348 std::map<FiniteElement*, unsigned> face_element_index_on_boundary;
41350 for (
unsigned ef = 0; ef < nface_element; ++ef)
41352 FiniteElement* ele_face_pt = face_mesh_pt[p]->finite_element_pt(ef);
41354 #ifdef OOMPH_HAS_MPI
41355 if (this->is_mesh_distributed())
41358 if (ele_face_pt->is_halo())
41365 non_halo_face_element_pt.push_back(ele_face_pt);
41366 face_element_index_on_boundary[ele_face_pt] = ef;
41370 const unsigned nnon_halo_face_element = non_halo_face_element_pt.size();
41373 std::map<FiniteElement*, bool> face_element_done;
41376 unsigned nsorted_face_elements = 0;
41378 #ifdef OOMPH_HAS_MPI
41380 unsigned nsub_boundaries = 0;
41385 while (nsorted_face_elements < nnon_halo_face_element)
41388 FiniteElement* ele_face_pt = 0;
41390 bool found_initial_face_element =
false;
41393 unsigned iface = 0;
41394 for (iface = 0; iface < nnon_halo_face_element; iface++)
41396 ele_face_pt = non_halo_face_element_pt[iface];
41398 if (!face_element_done[ele_face_pt])
41401 found_initial_face_element =
true;
41403 nsorted_face_elements++;
41410 if (!found_initial_face_element)
41412 std::ostringstream error_message;
41413 error_message <<
"Could not find an initial face element for the "
41414 "current segment\n";
41416 throw OomphLibError(
41417 error_message.str(),
41418 "RefineableTriangleMesh::update_polygon_after_restart()",
41419 OOMPH_EXCEPTION_LOCATION);
41426 std::set<Vector<double>> local_vertex_nodes;
41430 Vector<Vector<double>> local_tmp_vector_vertex_node;
41438 unsigned nnode = ele_face_pt->nnode();
41441 ele_face_pt->node_pt(0)->get_coordinates_on_boundary(bound, bound_left);
41442 vertex_coord[0] = bound_left[0];
41445 for (
unsigned i = 0; i < 2; i++)
41447 vertex_coord[i + 1] = ele_face_pt->node_pt(0)->x(i);
41449 local_vertex_nodes.insert(vertex_coord);
41453 ele_face_pt->node_pt(nnode - 1)->get_coordinates_on_boundary(
41454 bound, bound_right);
41455 vertex_coord[0] = bound_right[0];
41458 for (
unsigned i = 0; i < 2; i++)
41460 vertex_coord[i + 1] = ele_face_pt->node_pt(nnode - 1)->x(i);
41462 local_vertex_nodes.insert(vertex_coord);
41465 Node* first_node_pt = ele_face_pt->node_pt(0);
41466 Node* last_node_pt = ele_face_pt->node_pt(nnode - 1);
41469 face_element_done[ele_face_pt] =
true;
41477 bool face_element_added =
false;
41486 for (
unsigned iiface = iface; iiface < nnon_halo_face_element;
41489 face_element_added =
false;
41490 ele_face_pt = non_halo_face_element_pt[iiface];
41491 if (!face_element_done[ele_face_pt])
41494 nnode = ele_face_pt->nnode();
41495 Node* left_node_pt = ele_face_pt->node_pt(0);
41496 Node* right_node_pt = ele_face_pt->node_pt(nnode - 1);
41498 if (left_node_pt == first_node_pt)
41500 first_node_pt = right_node_pt;
41501 face_element_added =
true;
41503 else if (left_node_pt == last_node_pt)
41505 last_node_pt = right_node_pt;
41506 face_element_added =
true;
41508 else if (right_node_pt == first_node_pt)
41510 first_node_pt = left_node_pt;
41511 face_element_added =
true;
41513 else if (right_node_pt == last_node_pt)
41515 last_node_pt = left_node_pt;
41516 face_element_added =
true;
41519 if (face_element_added)
41523 left_node_pt->get_coordinates_on_boundary(bound, bound_left);
41524 vertex_coord[0] = bound_left[0];
41527 for (
unsigned i = 0; i < 2; i++)
41529 vertex_coord[i + 1] = left_node_pt->x(i);
41531 local_vertex_nodes.insert(vertex_coord);
41535 right_node_pt->get_coordinates_on_boundary(bound, bound_right);
41536 vertex_coord[0] = bound_right[0];
41539 for (
unsigned i = 0; i < 2; i++)
41541 vertex_coord[i + 1] = right_node_pt->x(i);
41543 local_vertex_nodes.insert(vertex_coord);
41547 face_element_done[ele_face_pt] =
true;
41548 nsorted_face_elements++;
41555 }
while (face_element_added &&
41556 (nsorted_face_elements < nnon_halo_face_element));
41564 const unsigned nlocal_nodes = local_vertex_nodes.size();
41566 local_tmp_vector_vertex_node.resize(nlocal_nodes);
41569 unsigned counter = 0;
41570 std::set<Vector<double>>::iterator it_vertex;
41571 for (it_vertex = local_vertex_nodes.begin();
41572 it_vertex != local_vertex_nodes.end();
41575 local_tmp_vector_vertex_node[counter].resize(3);
41576 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
41577 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
41578 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
41589 local_vertex_nodes.clear();
41594 unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
41595 for (
unsigned i = 0; i < nnew_nodes; i++)
41597 vertex_coord[0] = local_tmp_vector_vertex_node[i][0];
41598 vertex_coord[1] = local_tmp_vector_vertex_node[i][1];
41599 vertex_coord[2] = local_tmp_vector_vertex_node[i][2];
41600 vertex_nodes.insert(vertex_coord);
41601 local_vertex_nodes.insert(vertex_coord);
41604 #ifdef OOMPH_HAS_MPI
41605 if (this->is_mesh_distributed())
41609 sub_vertex_nodes.push_back(local_vertex_nodes);
41618 unsigned npoly_vertex = vertex_nodes.size();
41619 tmp_vector_vertex_node.resize(npoly_vertex);
41620 unsigned count = 0;
41621 std::set<Vector<double>>::iterator it;
41622 for (it = vertex_nodes.begin(); it != vertex_nodes.end(); ++it)
41624 tmp_vector_vertex_node[count].resize(3);
41625 tmp_vector_vertex_node[count][0] = (*it)[0];
41626 tmp_vector_vertex_node[count][1] = (*it)[1];
41627 tmp_vector_vertex_node[count][2] = (*it)[2];
41631 #ifdef OOMPH_HAS_MPI
41634 unsigned nsub_boundaries_set = sub_vertex_nodes.size();
41635 if (nsub_boundaries_set != nsub_boundaries)
41637 std::ostringstream error_message;
41639 <<
"The number of found sub-boundaries and the number of counted\n"
41640 <<
"sub-boundaries are different:\n"
41641 <<
"Number of found sub-boundaries: (" << nsub_boundaries_set <<
")\n"
41642 <<
"Number of counted sub-boundaries: (" << nsub_boundaries <<
")\n";
41643 throw OomphLibError(
41644 error_message.str(),
41645 "RefineableTriangleMesh::update_polygon_after_restart()",
41646 OOMPH_EXCEPTION_LOCATION);
41651 if (this->is_mesh_distributed() && nsub_boundaries > 1)
41654 this->Boundary_was_splitted[bound] =
true;
41656 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
41657 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
41660 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
41661 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
41662 unsigned subcount = 0;
41663 std::set<Vector<double>>::iterator subit;
41664 for (subit = sub_vertex_nodes[isub].begin();
41665 subit != sub_vertex_nodes[isub].end();
41668 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
41669 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
41670 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
41671 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
41682 unsigned n_vertex = tmp_vector_vertex_node.size();
41685 vector_vertex_node.resize(n_vertex);
41686 for (
unsigned i = 0; i < n_vertex; i++)
41688 vector_vertex_node[i].resize(2);
41689 vector_vertex_node[i][0] = tmp_vector_vertex_node[i][1];
41690 vector_vertex_node[i][1] = tmp_vector_vertex_node[i][2];
41693 #ifdef OOMPH_HAS_MPI
41696 if (this->is_mesh_distributed() && nsub_boundaries > 1)
41701 sub_vector_vertex_node.resize(nsub_boundaries);
41702 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
41704 const unsigned subn_vertex = sub_tmp_vector_vertex_node[isub].size();
41706 sub_vector_vertex_node[isub].resize(subn_vertex);
41707 for (
unsigned i = 0; i < subn_vertex; i++)
41709 sub_vector_vertex_node[isub][i].resize(2);
41710 sub_vector_vertex_node[isub][i][0] =
41711 sub_tmp_vector_vertex_node[isub][i][1];
41712 sub_vector_vertex_node[isub][i][1] =
41713 sub_tmp_vector_vertex_node[isub][i][2];
41728 #ifdef OOMPH_HAS_MPI
41732 if (!this->is_mesh_distributed())
41738 Vector<double> final_vertex_of_previous_segment;
41739 unsigned n_prev_vertex =
41740 polygon_pt->curve_section_pt(p - 1)->nvertex();
41741 final_vertex_of_previous_segment =
41742 polygon_pt->polyline_pt(p - 1)->vertex_coordinate(n_prev_vertex -
41745 unsigned prev_seg_boundary_id =
41746 polygon_pt->curve_section_pt(p - 1)->boundary_id();
41750 double error = 0.0;
41751 for (
unsigned i = 0; i < 2; i++)
41753 const double dist = final_vertex_of_previous_segment[i] -
41754 (*vector_vertex_node.begin())[i];
41755 error += dist * dist;
41757 error = sqrt(error);
41761 if (error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
41765 double rev_error = 0.0;
41766 for (
unsigned i = 0; i < 2; i++)
41768 const double dist = final_vertex_of_previous_segment[i] -
41769 (*--vector_vertex_node.end())[i];
41770 rev_error += dist * dist;
41772 rev_error = sqrt(rev_error);
41775 ToleranceForVertexMismatchInPolygons::Tolerable_error)
41784 Vector<double> initial_vertex_of_previous_segment;
41786 initial_vertex_of_previous_segment =
41787 polygon_pt->polyline_pt(p - 1)->vertex_coordinate(0);
41789 unsigned prev_seg_boundary_id =
41790 polygon_pt->curve_section_pt(p - 1)->boundary_id();
41794 double error = 0.0;
41795 for (
unsigned i = 0; i < 2; i++)
41797 const double dist = initial_vertex_of_previous_segment[i] -
41798 (*vector_vertex_node.begin())[i];
41799 error += dist * dist;
41801 error = sqrt(error);
41806 ToleranceForVertexMismatchInPolygons::Tolerable_error)
41810 double rev_error = 0.0;
41811 for (
unsigned i = 0; i < 2; i++)
41813 const double dist = initial_vertex_of_previous_segment[i] -
41814 (*--vector_vertex_node.end())[i];
41815 rev_error += dist * dist;
41822 ToleranceForVertexMismatchInPolygons::Tolerable_error)
41824 std::ostringstream error_stream;
41826 <<
"The distance between the first node of the current\n"
41827 <<
"line segment (boundary " << bound
41828 <<
") and either end of "
41829 <<
"the previous line segment\n"
41830 <<
"(boundary " << prev_seg_boundary_id
41831 <<
") is bigger than "
41832 <<
"the desired tolerance "
41833 << ToleranceForVertexMismatchInPolygons::Tolerable_error
41835 <<
"This suggests that the polylines defining the "
41837 <<
"representation are not properly ordered.\n"
41838 <<
"Fail on last vertex of polyline: ("
41839 << prev_seg_boundary_id
41840 <<
") and\nfirst vertex of polyline (" << bound
41841 <<
").\nThis should have failed when first trying to"
41842 <<
" construct the\npolygon.\n";
41843 throw OomphLibError(
41844 error_stream.str(),
41845 "RefineableTriangleMesh::update_polygon_after_restart()",
41846 OOMPH_EXCEPTION_LOCATION);
41853 std::reverse(vector_vertex_node.begin(),
41854 vector_vertex_node.end());
41855 polygon_pt->polyline_pt(p - 1)->reverse();
41861 polygon_pt->polyline_pt(p - 1)->reverse();
41867 std::ostringstream error_stream;
41869 <<
"The distance between the first node of the current\n"
41870 <<
"line segment (boundary " << bound
41871 <<
") and either end of "
41872 <<
"the previous line segment\n"
41873 <<
"(boundary " << prev_seg_boundary_id
41874 <<
") is bigger than the "
41875 <<
"desired tolerance "
41876 << ToleranceForVertexMismatchInPolygons::Tolerable_error
41878 <<
"This suggests that the polylines defining the polygonal\n"
41879 <<
"representation are not properly ordered.\n"
41880 <<
"Fail on last vertex of polyline: ("
41881 << prev_seg_boundary_id <<
") and\nfirst vertex of polyline ("
41883 <<
"This should have failed when first trying to construct "
41886 throw OomphLibError(
41887 error_stream.str(),
41888 "RefineableTriangleMesh::update_polygon_after_restart()",
41889 OOMPH_EXCEPTION_LOCATION);
41895 std::reverse(vector_vertex_node.begin(),
41896 vector_vertex_node.end());
41911 n_vertex = vector_vertex_node.size();
41915 TriangleMeshPolyLine* tmp_polyline_pt =
41916 new TriangleMeshPolyLine(vector_vertex_node, bound);
41927 TriangleMeshCurveSection* tmp_curve_section_pt = tmp_polyline_pt;
41931 double unrefinement_tolerance =
41932 polygon_pt->polyline_pt(p)->unrefinement_tolerance();
41935 double refinement_tolerance =
41936 polygon_pt->polyline_pt(p)->refinement_tolerance();
41939 tmp_polyline_pt->set_unrefinement_tolerance(unrefinement_tolerance);
41940 tmp_polyline_pt->set_refinement_tolerance(refinement_tolerance);
41943 double maximum_length = polygon_pt->polyline_pt(p)->maximum_length();
41944 tmp_polyline_pt->set_maximum_length(maximum_length);
41950 this->copy_connection_information(polygon_pt->polyline_pt(p),
41951 tmp_curve_section_pt);
41957 bool delete_it_on_destructor =
false;
41959 std::set<TriangleMeshCurveSection*>::iterator it =
41960 this->Free_curve_section_pt.find(polygon_pt->curve_section_pt(p));
41962 if (it != this->Free_curve_section_pt.end())
41964 this->Free_curve_section_pt.erase(it);
41965 delete polygon_pt->curve_section_pt(p);
41966 delete_it_on_destructor =
true;
41971 polygon_pt->curve_section_pt(p) = tmp_polyline_pt;
41974 this->Boundary_curve_section_pt[bound] =
41975 polygon_pt->curve_section_pt(p);
41977 if (delete_it_on_destructor)
41979 this->Free_curve_section_pt.insert(polygon_pt->curve_section_pt(p));
41982 #ifdef OOMPH_HAS_MPI
41985 if (this->is_mesh_distributed() && nsub_boundaries > 1)
41990 this->Boundary_subpolylines[bound].clear();
41992 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
41993 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
41997 TriangleMeshPolyLine* sub_tmp_polyline_pt =
41998 new TriangleMeshPolyLine(
41999 sub_vector_vertex_node[isub], bound, isub);
42003 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
42021 delete mesh_geom_obj_pt;
42026 for (
unsigned p = 0; p < n_polyline; p++)
42028 face_mesh_pt[p]->flush_node_storage();
42029 delete face_mesh_pt[p];
42037 template<
class ELEMENT>
42039 TriangleMeshOpenCurve*& open_curve_pt)
42047 Vector<Mesh*> face_mesh_pt;
42048 get_face_mesh_representation(open_curve_pt, face_mesh_pt);
42052 Vector<double> vertex_coord(3);
42053 Vector<double> bound_left(1);
42054 Vector<double> bound_right(1);
42056 const unsigned ncurve_section = open_curve_pt->ncurve_section();
42058 for (
unsigned cs = 0; cs < ncurve_section; cs++)
42066 MeshAsGeomObject* mesh_geom_obj_pt =
42067 new MeshAsGeomObject(face_mesh_pt[cs]);
42070 const unsigned bound = open_curve_pt->curve_section_pt(cs)->boundary_id();
42079 const unsigned nface_element = face_mesh_pt[cs]->nelement();
42083 Vector<FiniteElement*> non_halo_doubled_face_element_pt;
42086 std::map<FiniteElement*, unsigned> face_element_index_on_boundary;
42089 std::map<FiniteElement*, bool> face_element_done;
42091 for (
unsigned ef = 0; ef < nface_element; ++ef)
42093 FiniteElement* ele_face_pt = face_mesh_pt[cs]->finite_element_pt(ef);
42098 #ifdef OOMPH_HAS_MPI
42099 if (this->is_mesh_distributed())
42102 if (ele_face_pt->is_halo())
42110 if (!face_element_done[ele_face_pt])
42115 non_halo_doubled_face_element_pt.push_back(ele_face_pt);
42117 face_element_index_on_boundary[ele_face_pt] = ef;
42119 face_element_done[ele_face_pt] =
true;
42121 const unsigned nnodes = ele_face_pt->nnode();
42124 Node* left_node_pt = ele_face_pt->node_pt(0);
42125 Node* right_node_pt = ele_face_pt->node_pt(nnodes - 1);
42130 bool found_other_side_face_ele =
false;
42132 for (
unsigned iface = 0; iface < nface_element; iface++)
42135 FiniteElement* cele_face_pt =
42136 face_mesh_pt[cs]->finite_element_pt(iface);
42138 if (!face_element_done[cele_face_pt])
42140 Node* cleft_node_pt = cele_face_pt->node_pt(0);
42141 Node* cright_node_pt = cele_face_pt->node_pt(nnodes - 1);
42144 if ((left_node_pt == cleft_node_pt &&
42145 right_node_pt == cright_node_pt) ||
42146 (left_node_pt == cright_node_pt &&
42147 right_node_pt == cleft_node_pt))
42150 non_halo_doubled_face_element_pt.push_back(cele_face_pt);
42152 face_element_done[cele_face_pt] =
true;
42154 face_element_index_on_boundary[cele_face_pt] = iface;
42157 found_other_side_face_ele =
true;
42165 if (!found_other_side_face_ele)
42167 std::ostringstream error_message;
42169 <<
"The face element at the other side of the boundary (" << bound
42170 <<
") was not found!!\n"
42171 <<
"These are the nodes of the face element:\n"
42172 <<
"(" << left_node_pt->x(0) <<
", " << left_node_pt->x(1) <<
") "
42173 <<
"and (" << right_node_pt->x(0) <<
"," << right_node_pt->x(1)
42175 throw OomphLibError(
42176 error_message.str(),
42177 "RefineableTriangleMesh::update_open_curve_after_restart()",
42178 OOMPH_EXCEPTION_LOCATION);
42187 face_element_done.clear();
42192 std::set<Vector<double>> vertex_nodes;
42196 Vector<Vector<double>> tmp_vector_vertex_node;
42201 Vector<Vector<double>> vector_vertex_node;
42203 #ifdef OOMPH_HAS_MPI
42208 std::vector<bool> internal_to_shared_boundary;
42215 Vector<std::set<Vector<double>>> sub_vertex_nodes;
42219 Vector<Vector<Vector<double>>> sub_tmp_vector_vertex_node;
42224 Vector<Vector<Vector<double>>> sub_vector_vertex_node;
42233 unsigned nsorted_face_elements = 0;
42235 #ifdef OOMPH_HAS_MPI
42237 unsigned nsub_boundaries = 0;
42241 const unsigned nnon_halo_doubled_face_ele =
42242 non_halo_doubled_face_element_pt.size();
42246 while (nsorted_face_elements < nnon_halo_doubled_face_ele)
42249 FiniteElement* ele_face_pt = 0;
42250 FiniteElement* repeated_ele_face_pt = 0;
42252 bool found_initial_face_element =
false;
42258 bool both_root_face_elements_are_nonhalo =
false;
42260 unsigned iface = 0;
42261 for (iface = 0; iface < nnon_halo_doubled_face_ele; iface += 2)
42263 ele_face_pt = non_halo_doubled_face_element_pt[iface];
42265 if (!face_element_done[ele_face_pt])
42268 face_element_done[ele_face_pt] =
true;
42270 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iface + 1];
42272 face_element_done[repeated_ele_face_pt] =
true;
42274 #ifdef OOMPH_HAS_MPI
42275 if (!repeated_ele_face_pt->is_halo())
42277 both_root_face_elements_are_nonhalo =
true;
42283 nsorted_face_elements += 2;
42287 found_initial_face_element =
true;
42294 if (!found_initial_face_element)
42296 std::ostringstream error_message;
42297 error_message <<
"Could not find an initial face element for the "
42298 "current segment\n";
42300 throw OomphLibError(error_message.str(),
42301 OOMPH_CURRENT_FUNCTION,
42302 OOMPH_EXCEPTION_LOCATION);
42309 std::set<Vector<double>> local_vertex_nodes;
42313 Vector<Vector<double>> local_tmp_vector_vertex_node;
42321 const unsigned nnode = ele_face_pt->nnode();
42324 ele_face_pt->node_pt(0)->get_coordinates_on_boundary(bound, bound_left);
42325 vertex_coord[0] = bound_left[0];
42328 for (
unsigned i = 0; i < 2; i++)
42330 vertex_coord[i + 1] = ele_face_pt->node_pt(0)->x(i);
42332 local_vertex_nodes.insert(vertex_coord);
42336 ele_face_pt->node_pt(nnode - 1)->get_coordinates_on_boundary(
42337 bound, bound_right);
42338 vertex_coord[0] = bound_right[0];
42341 for (
unsigned i = 0; i < 2; i++)
42343 vertex_coord[i + 1] = ele_face_pt->node_pt(nnode - 1)->x(i);
42345 local_vertex_nodes.insert(vertex_coord);
42348 Node* first_node_pt = ele_face_pt->node_pt(0);
42349 Node* last_node_pt = ele_face_pt->node_pt(nnode - 1);
42353 bool face_element_added =
false;
42363 for (
unsigned iiface = iface; iiface < nnon_halo_doubled_face_ele;
42366 face_element_added =
false;
42367 ele_face_pt = non_halo_doubled_face_element_pt[iiface];
42374 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iiface + 1];
42375 bool both_face_elements_are_nonhalo =
false;
42377 #ifdef OOMPH_HAS_MPI
42378 if (!repeated_ele_face_pt->is_halo())
42380 both_face_elements_are_nonhalo =
true;
42384 if (!face_element_done[ele_face_pt] &&
42385 (both_face_elements_are_nonhalo ==
42386 both_root_face_elements_are_nonhalo))
42389 const unsigned nlnode = ele_face_pt->nnode();
42390 Node* left_node_pt = ele_face_pt->node_pt(0);
42391 Node* right_node_pt = ele_face_pt->node_pt(nlnode - 1);
42393 if (left_node_pt == first_node_pt)
42395 first_node_pt = right_node_pt;
42396 face_element_added =
true;
42398 else if (left_node_pt == last_node_pt)
42400 last_node_pt = right_node_pt;
42401 face_element_added =
true;
42403 else if (right_node_pt == first_node_pt)
42405 first_node_pt = left_node_pt;
42406 face_element_added =
true;
42408 else if (right_node_pt == last_node_pt)
42410 last_node_pt = left_node_pt;
42411 face_element_added =
true;
42414 if (face_element_added)
42418 left_node_pt->get_coordinates_on_boundary(bound, bound_left);
42419 vertex_coord[0] = bound_left[0];
42422 for (
unsigned i = 0; i < 2; i++)
42424 vertex_coord[i + 1] = left_node_pt->x(i);
42426 local_vertex_nodes.insert(vertex_coord);
42430 right_node_pt->get_coordinates_on_boundary(bound, bound_right);
42431 vertex_coord[0] = bound_right[0];
42434 for (
unsigned i = 0; i < 2; i++)
42436 vertex_coord[i + 1] = right_node_pt->x(i);
42438 local_vertex_nodes.insert(vertex_coord);
42442 face_element_done[ele_face_pt] =
true;
42445 repeated_ele_face_pt =
42446 non_halo_doubled_face_element_pt[iiface + 1];
42447 face_element_done[repeated_ele_face_pt] =
true;
42449 nsorted_face_elements += 2;
42456 }
while (face_element_added &&
42457 (nsorted_face_elements < nnon_halo_doubled_face_ele));
42465 const unsigned nlocal_nodes = local_vertex_nodes.size();
42467 local_tmp_vector_vertex_node.resize(nlocal_nodes);
42470 unsigned counter = 0;
42471 std::set<Vector<double>>::iterator it_vertex;
42472 for (it_vertex = local_vertex_nodes.begin();
42473 it_vertex != local_vertex_nodes.end();
42476 local_tmp_vector_vertex_node[counter].resize(3);
42477 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
42478 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
42479 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
42486 if (local_tmp_vector_vertex_node[nlocal_nodes - 1][2] <
42487 local_tmp_vector_vertex_node[0][2])
42489 std::reverse(local_tmp_vector_vertex_node.begin(),
42490 local_tmp_vector_vertex_node.end());
42492 else if (local_tmp_vector_vertex_node[nlocal_nodes - 1][2] ==
42493 local_tmp_vector_vertex_node[0][2])
42495 if (local_tmp_vector_vertex_node[nlocal_nodes - 1][1] <
42496 local_tmp_vector_vertex_node[0][1])
42498 std::reverse(local_tmp_vector_vertex_node.begin(),
42499 local_tmp_vector_vertex_node.end());
42510 local_vertex_nodes.clear();
42515 const unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
42516 for (
unsigned i = 0; i < nnew_nodes; i++)
42518 vertex_coord[0] = local_tmp_vector_vertex_node[i][0];
42519 vertex_coord[1] = local_tmp_vector_vertex_node[i][1];
42520 vertex_coord[2] = local_tmp_vector_vertex_node[i][2];
42521 vertex_nodes.insert(vertex_coord);
42522 local_vertex_nodes.insert(vertex_coord);
42525 #ifdef OOMPH_HAS_MPI
42526 if (this->is_mesh_distributed())
42531 sub_vertex_nodes.push_back(local_vertex_nodes);
42537 if (both_root_face_elements_are_nonhalo)
42539 internal_to_shared_boundary.push_back(
false);
42543 internal_to_shared_boundary.push_back(
true);
42554 const unsigned npoly_vertex = vertex_nodes.size();
42555 tmp_vector_vertex_node.resize(npoly_vertex);
42556 unsigned count = 0;
42557 std::set<Vector<double>>::iterator it;
42558 for (it = vertex_nodes.begin(); it != vertex_nodes.end(); ++it)
42560 tmp_vector_vertex_node[count].resize(3);
42561 tmp_vector_vertex_node[count][0] = (*it)[0];
42562 tmp_vector_vertex_node[count][1] = (*it)[1];
42563 tmp_vector_vertex_node[count][2] = (*it)[2];
42567 #ifdef OOMPH_HAS_MPI
42572 const unsigned nsub_boundaries_set = sub_vertex_nodes.size();
42573 const unsigned ninternal_to_shared_boundaries =
42574 internal_to_shared_boundary.size();
42575 if (nsub_boundaries_set != ninternal_to_shared_boundaries)
42577 std::ostringstream error_message;
42579 <<
"The number of found sub-boundaries and the number of marked "
42580 <<
"internal\nboundaries are different\n"
42581 <<
"Number of found sub-boundaries: (" << nsub_boundaries_set <<
")\n"
42582 <<
"Number of marked internal boundaries: ("
42583 << ninternal_to_shared_boundaries <<
")\n\n";
42584 throw OomphLibError(
42585 error_message.str(),
42586 "RefineableTriangleMesh::update_open_curve_after_restart()",
42587 OOMPH_EXCEPTION_LOCATION);
42593 if (nsub_boundaries_set != nsub_boundaries)
42595 std::ostringstream error_message;
42597 <<
"The number of found sub-boundaries and the number of counted\n"
42598 <<
"sub-boundaries are different:\n"
42599 <<
"Number of found sub-boundaries: (" << nsub_boundaries_set <<
")\n"
42600 <<
"Number of counted sub-boundaries: (" << nsub_boundaries
42602 throw OomphLibError(
42603 error_message.str(),
42604 "RefineableTriangleMesh::update_open_curve_after_restart()",
42605 OOMPH_EXCEPTION_LOCATION);
42610 if (this->is_mesh_distributed() && nsub_boundaries > 1)
42613 this->Boundary_was_splitted[bound] =
true;
42615 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
42616 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
42619 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
42620 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
42621 unsigned subcount = 0;
42622 std::set<Vector<double>>::iterator subit;
42623 for (subit = sub_vertex_nodes[isub].begin();
42624 subit != sub_vertex_nodes[isub].end();
42627 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
42628 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
42629 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
42630 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
42640 unsigned n_vertex = tmp_vector_vertex_node.size();
42643 vector_vertex_node.resize(n_vertex);
42644 for (
unsigned i = 0; i < n_vertex; i++)
42646 vector_vertex_node[i].resize(2);
42647 vector_vertex_node[i][0] = tmp_vector_vertex_node[i][1];
42648 vector_vertex_node[i][1] = tmp_vector_vertex_node[i][2];
42651 #ifdef OOMPH_HAS_MPI
42654 if (this->is_mesh_distributed() && nsub_boundaries > 1)
42659 sub_vector_vertex_node.resize(nsub_boundaries);
42660 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
42662 const unsigned subn_vertex = sub_tmp_vector_vertex_node[isub].size();
42664 sub_vector_vertex_node[isub].resize(subn_vertex);
42665 for (
unsigned i = 0; i < subn_vertex; i++)
42667 sub_vector_vertex_node[isub][i].resize(2);
42668 sub_vector_vertex_node[isub][i][0] =
42669 sub_tmp_vector_vertex_node[isub][i][1];
42670 sub_vector_vertex_node[isub][i][1] =
42671 sub_tmp_vector_vertex_node[isub][i][2];
42686 #ifdef OOMPH_HAS_MPI
42690 if (!this->is_mesh_distributed())
42696 Vector<double> final_vertex_of_previous_segment;
42697 unsigned n_prev_vertex =
42698 open_curve_pt->curve_section_pt(cs - 1)->nvertex();
42699 final_vertex_of_previous_segment =
42700 open_curve_pt->polyline_pt(cs - 1)->vertex_coordinate(
42701 n_prev_vertex - 1);
42703 unsigned prev_seg_boundary_id =
42704 open_curve_pt->curve_section_pt(cs - 1)->boundary_id();
42708 double error = 0.0;
42709 for (
unsigned i = 0; i < 2; i++)
42711 const double dist = final_vertex_of_previous_segment[i] -
42712 (*vector_vertex_node.begin())[i];
42713 error += dist * dist;
42715 error = sqrt(error);
42719 if (error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
42723 double rev_error = 0.0;
42724 for (
unsigned i = 0; i < 2; i++)
42726 const double dist = final_vertex_of_previous_segment[i] -
42727 (*--vector_vertex_node.end())[i];
42728 rev_error += dist * dist;
42730 rev_error = sqrt(rev_error);
42733 ToleranceForVertexMismatchInPolygons::Tolerable_error)
42742 Vector<double> initial_vertex_of_previous_segment;
42744 initial_vertex_of_previous_segment =
42745 open_curve_pt->polyline_pt(cs - 1)->vertex_coordinate(0);
42747 unsigned prev_seg_boundary_id =
42748 open_curve_pt->curve_section_pt(cs - 1)->boundary_id();
42752 double error = 0.0;
42753 for (
unsigned i = 0; i < 2; i++)
42755 const double dist = initial_vertex_of_previous_segment[i] -
42756 (*vector_vertex_node.begin())[i];
42757 error += dist * dist;
42759 error = sqrt(error);
42764 ToleranceForVertexMismatchInPolygons::Tolerable_error)
42768 double rev_error = 0.0;
42769 for (
unsigned i = 0; i < 2; i++)
42771 const double dist = initial_vertex_of_previous_segment[i] -
42772 (*--vector_vertex_node.end())[i];
42773 rev_error += dist * dist;
42775 rev_error = sqrt(rev_error);
42779 ToleranceForVertexMismatchInPolygons::Tolerable_error)
42781 std::ostringstream error_stream;
42783 <<
"The distance between the first node of the current\n"
42784 <<
"line segment (boundary " << bound
42785 <<
") and either end of "
42786 <<
"the previous line segment\n"
42787 <<
"(boundary " << prev_seg_boundary_id
42788 <<
") is bigger than"
42789 <<
" the desired tolerance "
42790 << ToleranceForVertexMismatchInPolygons::Tolerable_error
42792 <<
"This suggests that the polylines defining the "
42794 <<
"representation are not properly ordered.\n"
42795 <<
"Fail on last vertex of polyline: ("
42796 << prev_seg_boundary_id
42797 <<
") and\nfirst vertex of polyline (" << bound
42798 <<
").\nThis should have failed when first trying to "
42799 <<
"construct the\npolygon.\n";
42800 throw OomphLibError(error_stream.str(),
42801 "RefineableTriangleMesh::update_open_"
42802 "curve_after_restart()",
42803 OOMPH_EXCEPTION_LOCATION);
42810 std::reverse(vector_vertex_node.begin(),
42811 vector_vertex_node.end());
42812 open_curve_pt->polyline_pt(cs - 1)->reverse();
42818 open_curve_pt->polyline_pt(cs - 1)->reverse();
42824 std::ostringstream error_stream;
42826 <<
"The distance between the first node of the current\n"
42827 <<
"line segment (boundary " << bound
42828 <<
") and either end of "
42829 <<
"the previous line segment\n"
42830 <<
"(boundary " << prev_seg_boundary_id
42831 <<
") is bigger than the "
42832 <<
"desired tolerance "
42833 << ToleranceForVertexMismatchInPolygons::Tolerable_error
42835 <<
"This suggests that the polylines defining the polygonal\n"
42836 <<
"representation are not properly ordered.\n"
42837 <<
"Fail on last vertex of polyline: ("
42838 << prev_seg_boundary_id <<
") and\nfirst vertex of polyline ("
42840 <<
"This should have failed when first trying to construct "
42843 throw OomphLibError(
42844 error_stream.str(),
42845 "RefineableTriangleMesh::update_open_curve_after_restart()",
42846 OOMPH_EXCEPTION_LOCATION);
42852 std::reverse(vector_vertex_node.begin(),
42853 vector_vertex_node.end());
42871 n_vertex = vector_vertex_node.size();
42875 TriangleMeshPolyLine* tmp_polyline_pt =
42876 new TriangleMeshPolyLine(vector_vertex_node, bound);
42880 TriangleMeshCurveSection* tmp_curve_section_pt = tmp_polyline_pt;
42884 double unrefinement_tolerance =
42885 open_curve_pt->polyline_pt(cs)->unrefinement_tolerance();
42888 double refinement_tolerance =
42889 open_curve_pt->polyline_pt(cs)->refinement_tolerance();
42892 tmp_polyline_pt->set_unrefinement_tolerance(unrefinement_tolerance);
42893 tmp_polyline_pt->set_refinement_tolerance(refinement_tolerance);
42896 double maximum_length =
42897 open_curve_pt->polyline_pt(cs)->maximum_length();
42898 tmp_polyline_pt->set_maximum_length(maximum_length);
42904 this->copy_connection_information(open_curve_pt->polyline_pt(cs),
42905 tmp_curve_section_pt);
42911 bool delete_it_on_destructor =
false;
42913 std::set<TriangleMeshCurveSection*>::iterator it =
42914 this->Free_curve_section_pt.find(open_curve_pt->curve_section_pt(cs));
42916 if (it != this->Free_curve_section_pt.end())
42918 this->Free_curve_section_pt.erase(it);
42919 delete open_curve_pt->curve_section_pt(cs);
42920 delete_it_on_destructor =
true;
42925 open_curve_pt->curve_section_pt(cs) = tmp_polyline_pt;
42928 this->Boundary_curve_section_pt[bound] =
42929 open_curve_pt->curve_section_pt(cs);
42931 if (delete_it_on_destructor)
42933 this->Free_curve_section_pt.insert(
42934 open_curve_pt->curve_section_pt(cs));
42937 #ifdef OOMPH_HAS_MPI
42941 if (this->is_mesh_distributed() && nsub_boundaries == 1)
42944 this->Boundary_marked_as_shared_boundary[bound].clear();
42947 this->Boundary_marked_as_shared_boundary[bound].push_back(
42948 internal_to_shared_boundary[0]);
42952 else if (this->is_mesh_distributed() && nsub_boundaries > 1)
42957 this->Boundary_subpolylines[bound].clear();
42959 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
42962 this->Boundary_marked_as_shared_boundary[bound].clear();
42965 this->Boundary_marked_as_shared_boundary[bound].resize(
42967 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
42971 TriangleMeshPolyLine* sub_tmp_polyline_pt =
42972 new TriangleMeshPolyLine(
42973 sub_vector_vertex_node[isub], bound, isub);
42977 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
42981 this->Boundary_marked_as_shared_boundary[bound][isub] =
42982 internal_to_shared_boundary[isub];
42997 delete mesh_geom_obj_pt;
43002 for (
unsigned p = 0; p < ncurve_section; p++)
43004 face_mesh_pt[p]->flush_node_storage();
43005 delete face_mesh_pt[p];
43009 #ifdef OOMPH_HAS_MPI
43013 template<
class ELEMENT>
43015 Vector<TriangleMeshPolyLine*>& vector_polyline_pt)
43018 const unsigned npolylines = vector_polyline_pt.size();
43019 for (
unsigned pp = 0; pp < npolylines; pp++)
43022 const unsigned b = vector_polyline_pt[pp]->boundary_id();
43027 std::map<std::pair<Node*, Node*>, FiniteElement*> halo_edge_element_pt;
43028 std::map<std::pair<Node*, Node*>, FiniteElement*> nonhalo_edge_element_pt;
43031 Vector<Node*> halo_edge_nodes_pt;
43032 Vector<Node*> nonhalo_edge_nodes_pt;
43035 const unsigned nshared_bound_ele = this->nshared_boundary_element(b);
43036 for (
unsigned e = 0; e < nshared_bound_ele; e++)
43039 FiniteElement* current_ele_pt = this->shared_boundary_element_pt(b, e);
43042 Node* first_node_pt = current_ele_pt->node_pt(0);
43043 Node* second_node_pt = current_ele_pt->node_pt(1);
43044 Node* third_node_pt = current_ele_pt->node_pt(2);
43047 if (!current_ele_pt->is_halo())
43050 nonhalo_edge_nodes_pt.push_back(first_node_pt);
43051 nonhalo_edge_nodes_pt.push_back(second_node_pt);
43053 nonhalo_edge_nodes_pt.push_back(second_node_pt);
43054 nonhalo_edge_nodes_pt.push_back(third_node_pt);
43056 nonhalo_edge_nodes_pt.push_back(third_node_pt);
43057 nonhalo_edge_nodes_pt.push_back(first_node_pt);
43060 std::pair<Node*, Node*> edge1 =
43061 std::make_pair(first_node_pt, second_node_pt);
43062 nonhalo_edge_element_pt[edge1] = current_ele_pt;
43064 std::pair<Node*, Node*> edge2 =
43065 std::make_pair(second_node_pt, third_node_pt);
43066 nonhalo_edge_element_pt[edge2] = current_ele_pt;
43068 std::pair<Node*, Node*> edge3 =
43069 std::make_pair(third_node_pt, first_node_pt);
43070 nonhalo_edge_element_pt[edge3] = current_ele_pt;
43075 halo_edge_nodes_pt.push_back(first_node_pt);
43076 halo_edge_nodes_pt.push_back(second_node_pt);
43078 halo_edge_nodes_pt.push_back(second_node_pt);
43079 halo_edge_nodes_pt.push_back(third_node_pt);
43081 halo_edge_nodes_pt.push_back(third_node_pt);
43082 halo_edge_nodes_pt.push_back(first_node_pt);
43085 std::pair<Node*, Node*> edge1 =
43086 std::make_pair(first_node_pt, second_node_pt);
43087 halo_edge_element_pt[edge1] = current_ele_pt;
43089 std::pair<Node*, Node*> edge2 =
43090 std::make_pair(second_node_pt, third_node_pt);
43091 halo_edge_element_pt[edge2] = current_ele_pt;
43093 std::pair<Node*, Node*> edge3 =
43094 std::make_pair(third_node_pt, first_node_pt);
43095 halo_edge_element_pt[edge3] = current_ele_pt;
43103 std::map<std::pair<Node*, Node*>,
bool> edge_done;
43106 Vector<std::pair<Node*, Node*>> unsorted_edges;
43110 Vector<Vector<FiniteElement*>> unsorted_edges_elements_pt;
43112 const unsigned nnonhalo_edge_nodes = nonhalo_edge_nodes_pt.size();
43113 for (
unsigned i = 0; i < nnonhalo_edge_nodes; i += 2)
43115 Vector<Node*> currenti_edge(2);
43116 currenti_edge[0] = nonhalo_edge_nodes_pt[i];
43117 currenti_edge[1] = nonhalo_edge_nodes_pt[i + 1];
43120 std::pair<Node*, Node*> new_edge =
43121 std::make_pair(currenti_edge[0], currenti_edge[1]);
43123 if (!edge_done[new_edge])
43125 const unsigned nhalo_edge_nodes = halo_edge_nodes_pt.size();
43126 for (
unsigned j = 0; j < nhalo_edge_nodes; j += 2)
43128 Vector<Node*> currentj_edge(2);
43129 currentj_edge[0] = halo_edge_nodes_pt[j];
43130 currentj_edge[1] = halo_edge_nodes_pt[j + 1];
43133 if (currenti_edge[0] == currentj_edge[0] &&
43134 currenti_edge[1] == currentj_edge[1])
43137 unsorted_edges.push_back(new_edge);
43140 Vector<FiniteElement*> tmp_edge_element_pt;
43142 FiniteElement* nonhalo_ele_pt = nonhalo_edge_element_pt[new_edge];
43143 FiniteElement* halo_ele_pt = halo_edge_element_pt[new_edge];
43145 tmp_edge_element_pt.push_back(nonhalo_ele_pt);
43146 tmp_edge_element_pt.push_back(halo_ele_pt);
43149 unsorted_edges_elements_pt.push_back(tmp_edge_element_pt);
43152 edge_done[new_edge] =
true;
43160 else if (currenti_edge[0] == currentj_edge[1] &&
43161 currenti_edge[1] == currentj_edge[0])
43164 std::pair<Node*, Node*> new_edge =
43165 std::make_pair(currenti_edge[0], currenti_edge[1]);
43168 unsorted_edges.push_back(new_edge);
43171 std::pair<Node*, Node*> rev_new_edge =
43172 std::make_pair(currentj_edge[0], currentj_edge[1]);
43175 Vector<FiniteElement*> tmp_edge_element_pt;
43177 FiniteElement* nonhalo_ele_pt = nonhalo_edge_element_pt[new_edge];
43178 FiniteElement* halo_ele_pt = halo_edge_element_pt[rev_new_edge];
43180 tmp_edge_element_pt.push_back(nonhalo_ele_pt);
43181 tmp_edge_element_pt.push_back(halo_ele_pt);
43184 unsorted_edges_elements_pt.push_back(tmp_edge_element_pt);
43187 edge_done[new_edge] =
true;
43205 std::map<std::pair<Node*, Node*>,
bool> edge_sorted;
43207 const unsigned nunsorted_edges = unsorted_edges.size();
43212 if (nshared_bound_ele / 2 != nunsorted_edges)
43214 std::ostringstream error_message;
43216 <<
"The number of shared boundary elements (" << nshared_bound_ele
43217 <<
") is not the double\nof the number of unsorted edges ("
43218 << nunsorted_edges <<
") for the current boundary (" << b <<
")\n\n";
43219 throw OomphLibError(
43220 error_message.str(),
43221 "RefineableTriangleMesh::update_shared_curve_after_restart()",
43222 OOMPH_EXCEPTION_LOCATION);
43226 unsigned nsorted_edges = 0;
43230 std::list<Node*> sorted_nodes;
43233 std::list<FiniteElement*> sorted_edges_elements_pt;
43236 std::pair<Node*, Node*> edge = unsorted_edges[0];
43240 edge_sorted[edge] =
true;
43243 Node* first_node_pt = edge.first;
43244 Node* last_node_pt = edge.second;
43247 sorted_nodes.push_back(first_node_pt);
43248 sorted_nodes.push_back(last_node_pt);
43251 sorted_edges_elements_pt.push_back(unsorted_edges_elements_pt[0][0]);
43252 sorted_edges_elements_pt.push_back(unsorted_edges_elements_pt[0][1]);
43256 while (nsorted_edges < nunsorted_edges)
43259 bool node_added =
false;
43263 for (
unsigned iedge = 1; iedge < nunsorted_edges; iedge++)
43265 edge = unsorted_edges[iedge];
43268 if (!edge_sorted[edge])
43271 Node* left_node_pt = edge.first;
43272 Node* right_node_pt = edge.second;
43274 if (left_node_pt == first_node_pt)
43277 sorted_nodes.push_front(right_node_pt);
43278 first_node_pt = right_node_pt;
43282 sorted_edges_elements_pt.push_front(
43283 unsorted_edges_elements_pt[iedge][1]);
43284 sorted_edges_elements_pt.push_front(
43285 unsorted_edges_elements_pt[iedge][0]);
43287 else if (left_node_pt == last_node_pt)
43290 sorted_nodes.push_back(right_node_pt);
43291 last_node_pt = right_node_pt;
43295 sorted_edges_elements_pt.push_back(
43296 unsorted_edges_elements_pt[iedge][0]);
43297 sorted_edges_elements_pt.push_back(
43298 unsorted_edges_elements_pt[iedge][1]);
43300 else if (right_node_pt == first_node_pt)
43303 sorted_nodes.push_front(left_node_pt);
43304 first_node_pt = left_node_pt;
43308 sorted_edges_elements_pt.push_front(
43309 unsorted_edges_elements_pt[iedge][1]);
43310 sorted_edges_elements_pt.push_front(
43311 unsorted_edges_elements_pt[iedge][0]);
43313 else if (right_node_pt == last_node_pt)
43316 sorted_nodes.push_back(left_node_pt);
43317 last_node_pt = left_node_pt;
43321 sorted_edges_elements_pt.push_back(
43322 unsorted_edges_elements_pt[iedge][0]);
43323 sorted_edges_elements_pt.push_back(
43324 unsorted_edges_elements_pt[iedge][1]);
43331 edge_sorted[edge] =
true;
43346 unsigned nvertex = sorted_nodes.size();
43348 Vector<Vector<double>> polyline_vertices(nvertex);
43351 unsigned counter = 0;
43352 for (std::list<Node*>::iterator it_nodes = sorted_nodes.begin();
43353 it_nodes != sorted_nodes.end();
43356 polyline_vertices[counter].resize(2);
43357 polyline_vertices[counter][0] = (*it_nodes)->x(0);
43358 polyline_vertices[counter][1] = (*it_nodes)->x(1);
43365 if (polyline_vertices[nvertex - 1][1] < polyline_vertices[0][1])
43367 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
43369 else if (polyline_vertices[nvertex - 1][1] == polyline_vertices[0][1])
43371 if (polyline_vertices[nvertex - 1][0] < polyline_vertices[0][0])
43373 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
43378 TriangleMeshPolyLine* new_polyline_pt =
43379 new TriangleMeshPolyLine(polyline_vertices, b);
43382 TriangleMeshCurveSection* curve_section_pt = vector_polyline_pt[pp];
43386 this->copy_connection_information(curve_section_pt, new_polyline_pt);
43391 bool delete_it_on_destructor =
false;
43395 std::set<TriangleMeshCurveSection*>::iterator it =
43396 this->Free_curve_section_pt.find(curve_section_pt);
43398 if (it != this->Free_curve_section_pt.end())
43400 this->Free_curve_section_pt.erase(it);
43401 delete curve_section_pt;
43402 delete_it_on_destructor =
true;
43406 vector_polyline_pt[pp] = new_polyline_pt;
43409 TriangleMeshCurveSection* new_curve_section_pt = vector_polyline_pt[pp];
43412 this->Boundary_curve_section_pt[b] = new_curve_section_pt;
43414 if (delete_it_on_destructor)
43416 this->Free_curve_section_pt.insert(new_curve_section_pt);
43428 template<
class ELEMENT>
43430 ELEMENT>::fill_boundary_elements_and_nodes_for_internal_boundaries()
43433 std::ofstream some_file;
43434 fill_boundary_elements_and_nodes_for_internal_boundaries(some_file);
43441 template<
class ELEMENT>
43444 std::ofstream& outfile)
43447 const unsigned nproc = this->communicator_pt()->nproc();
43449 unsigned my_rank = this->communicator_pt()->my_rank();
43452 std::map<unsigned, unsigned> shd_bnd_over_int_bnd =
43453 this->Shared_boundary_overlaps_internal_boundary;
43457 std::set<unsigned> internal_boundary_overlaped;
43461 if (outfile.is_open())
43463 const unsigned nbound = this->nboundary();
43464 outfile <<
"Number of boundaries: " << nbound <<
"\n\n";
43465 outfile <<
"Number of elements and nodes associated to each "
43466 <<
"boundary before\nfilling elements and nodes\n\n";
43467 for (
unsigned i = 0; i < nbound; i++)
43469 outfile <<
"Boundary (" << i <<
") Elements ("
43470 << this->nboundary_element(i) <<
") "
43471 <<
"Nodes (" << this->nboundary_node(i) <<
")\n";
43476 std::set<unsigned> shared_boundaries_in_this_processor;
43480 for (
unsigned iproc = 0; iproc < nproc; iproc++)
43483 if (iproc != my_rank)
43486 unsigned nshared_boundaries_with_iproc =
43487 this->nshared_boundaries(my_rank, iproc);
43489 if (nshared_boundaries_with_iproc > 0)
43492 Vector<unsigned> bound_shared_with_iproc;
43493 bound_shared_with_iproc = this->shared_boundaries_ids(my_rank, iproc);
43496 for (
unsigned bs = 0; bs < nshared_boundaries_with_iproc; bs++)
43498 unsigned bnd_id = bound_shared_with_iproc[bs];
43499 shared_boundaries_in_this_processor.insert(bnd_id);
43510 for (std::map<unsigned, unsigned>::iterator it =
43511 shd_bnd_over_int_bnd.begin();
43512 it != shd_bnd_over_int_bnd.end();
43516 const unsigned shd_bnd_id = (*it).first;
43518 const unsigned int_bnd_id = (*it).second;
43521 std::set<unsigned>::iterator it_set =
43522 shared_boundaries_in_this_processor.find(shd_bnd_id);
43523 if (it_set != shared_boundaries_in_this_processor.end())
43525 internal_boundary_overlaped.insert(int_bnd_id);
43530 const unsigned nbnd_node_shd_bnd = this->nboundary_node(shd_bnd_id);
43534 if (outfile.is_open())
43536 outfile <<
"\nPass info. from shared (" << shd_bnd_id
43537 <<
") to internal (" << int_bnd_id <<
")\n";
43538 outfile <<
"Number of shared boundary nodes: " << nbnd_node_shd_bnd
43542 for (
unsigned in = 0; in < nbnd_node_shd_bnd; in++)
43545 Node* bnd_node_pt = this->boundary_node_pt(shd_bnd_id, in);
43547 this->add_boundary_node(int_bnd_id, bnd_node_pt);
43554 const unsigned nbnd_ele_shd_bnd = this->nboundary_element(shd_bnd_id);
43558 if (outfile.is_open())
43560 outfile <<
"Number of shared boundary elements: " << nbnd_ele_shd_bnd
43566 for (
unsigned ie = 0; ie < nbnd_ele_shd_bnd; ie++)
43569 FiniteElement* bnd_ele_pt = this->boundary_element_pt(shd_bnd_id, ie);
43572 Boundary_element_pt[int_bnd_id].push_back(bnd_ele_pt);
43574 int face_index = this->face_index_at_boundary(shd_bnd_id, ie);
43576 Face_index_at_boundary[int_bnd_id].push_back(face_index);
43581 const unsigned nregions = this->nregion();
43584 for (
unsigned ir = 0; ir < nregions; ir++)
43587 const unsigned region_id =
43588 static_cast<unsigned>(this->Region_attribute[ir]);
43591 const unsigned nele_ir =
43592 this->nboundary_element_in_region(shd_bnd_id, region_id);
43593 for (
unsigned ier = 0; ier < nele_ir; ier++)
43596 FiniteElement* bnd_ele_pt =
43597 this->boundary_element_in_region_pt(shd_bnd_id, region_id, ier);
43600 this->Boundary_region_element_pt[int_bnd_id][region_id].push_back(
43604 int face_index = this->face_index_at_boundary_in_region(
43605 shd_bnd_id, region_id, ier);
43607 this->Face_index_region_at_boundary[int_bnd_id][region_id]
43608 .push_back(face_index);
43622 if (outfile.is_open())
43624 const unsigned nbound = this->nboundary();
43625 outfile <<
"Number of boundaries: " << nbound <<
"\n\n";
43626 outfile <<
"Number of elements and nodes associated to each "
43627 <<
"boundary after\nfilling elements and nodes\n\n";
43628 for (
unsigned i = 0; i < nbound; i++)
43630 outfile <<
"Boundary (" << i <<
") Elements ("
43631 << this->nboundary_element(i) <<
")"
43632 <<
" Nodes (" << this->nboundary_node(i) <<
")\n";
43640 for (std::set<unsigned>::iterator it = internal_boundary_overlaped.begin();
43641 it != internal_boundary_overlaped.end();
43644 const unsigned overlaped_internal_bnd_id = (*it);
43647 this->
template setup_boundary_coordinates<ELEMENT>(
43648 overlaped_internal_bnd_id);
43657 template<
class ELEMENT>
43662 if (!Boundary_coordinate_exists[b])
43679 std::set<Node*> tmp_boundary_node_pt;
43680 const unsigned nboundary_ele = this->nboundary_element(b);
43681 for (
unsigned e = 0; e < nboundary_ele; e++)
43684 FiniteElement* bulk_ele_pt = this->boundary_element_pt(b, e);
43685 #ifdef OOMPH_HAS_MPI
43687 if (!bulk_ele_pt->is_halo())
43691 int face_index = this->face_index_at_boundary(b, e);
43693 FiniteElement* face_ele_pt =
43694 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
43697 const unsigned nnodes = face_ele_pt->nnode();
43698 for (
unsigned i = 0; i < nnodes; i++)
43701 Node* tmp_node_pt = face_ele_pt->node_pt(i);
43703 tmp_boundary_node_pt.insert(tmp_node_pt);
43707 delete face_ele_pt;
43709 #ifdef OOMPH_HAS_MPI
43716 const unsigned long n_boundary_node = tmp_boundary_node_pt.size();
43719 if (n_boundary_node == 0)
43721 #ifdef OOMPH_HAS_MPI
43723 if (!this->is_mesh_distributed())
43727 #ifdef OOMPH_HAS_MPI
43732 Mesh* face_mesh_pt =
new Mesh();
43733 create_unsorted_face_mesh_representation(b, face_mesh_pt);
43734 MeshAsGeomObject* mesh_geom_obj_pt =
new MeshAsGeomObject(face_mesh_pt);
43737 delete mesh_geom_obj_pt;
43741 face_mesh_pt->flush_node_storage();
43742 delete face_mesh_pt;
43750 Vector<double> node_coord(3);
43751 Vector<double> b_coord(1);
43753 Vector<Vector<double>> old_boundary_node(n_boundary_node);
43754 unsigned tmp_counter = 0;
43755 for (std::set<Node*>::iterator it_node = tmp_boundary_node_pt.begin();
43756 it_node != tmp_boundary_node_pt.end();
43757 it_node++, tmp_counter++)
43759 Node* nod_pt = (*it_node);
43760 nod_pt->get_coordinates_on_boundary(b, b_coord);
43761 node_coord[0] = b_coord[0];
43762 node_coord[1] = nod_pt->x(0);
43763 node_coord[2] = nod_pt->x(1);
43764 old_boundary_node[tmp_counter] = node_coord;
43768 std::sort(old_boundary_node.begin(), old_boundary_node.end());
43777 Vector<Vector<Node*>> segment_nodes_pt;
43779 #ifdef OOMPH_HAS_MPI
43781 const unsigned nsegments = new_mesh_pt->nboundary_segment(b);
43785 const unsigned nsegments = 1;
43788 #ifdef OOMPH_HAS_MPI
43790 const unsigned n_new_boundary_node = new_mesh_pt->nboundary_segment_node(b);
43793 if (this->is_mesh_distributed())
43798 if (n_new_boundary_node == 0)
43801 Mesh* face_mesh_pt =
new Mesh();
43802 create_unsorted_face_mesh_representation(b, face_mesh_pt);
43803 MeshAsGeomObject* mesh_geom_obj_pt =
new MeshAsGeomObject(face_mesh_pt);
43806 delete mesh_geom_obj_pt;
43809 face_mesh_pt->flush_node_storage();
43810 delete face_mesh_pt;
43817 Vector<Vector<unsigned>> nodes_to_be_snapped(nsegments);
43821 for (
unsigned is = 0; is < nsegments; is++)
43823 #ifdef OOMPH_HAS_MPI
43824 const unsigned n_new_boundary_segment_node =
43825 new_mesh_pt->nboundary_segment_node(b, is);
43827 const unsigned n_new_boundary_segment_node =
43828 new_mesh_pt->nboundary_node(b);
43831 Vector<Vector<double>> new_boundary_node(n_new_boundary_segment_node);
43833 node_coord.resize(6, 0.0);
43834 for (
unsigned n = 0; n < n_new_boundary_segment_node; n++)
43836 #ifdef OOMPH_HAS_MPI
43839 Node* nod_pt = new_mesh_pt->boundary_node_pt(b, n);
43841 nod_pt->get_coordinates_on_boundary(b, b_coord);
43842 node_coord[0] = b_coord[0];
43843 node_coord[1] = nod_pt->x(0);
43844 node_coord[2] = nod_pt->x(1);
43846 new_boundary_node[n] = node_coord;
43850 std::sort(new_boundary_node.begin(), new_boundary_node.end());
43857 unsigned old_index = 0;
43858 for (
unsigned n = 0; n < n_new_boundary_segment_node; ++n)
43862 for (
unsigned m = old_index; m < n_boundary_node; ++m)
43864 if ((std::fabs(old_boundary_node[m][1] - new_boundary_node[n][1]) <
43866 (std::fabs(old_boundary_node[m][2] - new_boundary_node[n][2]) <
43870 new_boundary_node[n][4] = old_boundary_node[m][0];
43872 new_boundary_node[n][5] = 1.0;
43883 if ((new_boundary_node[0][5] == 0.0) ||
43884 (new_boundary_node[n_new_boundary_segment_node - 1][5] == 0.0))
43886 std::ostringstream error_stream;
43888 <<
"New boundary coordinates not found for the first and/or last "
43890 <<
"on the boundary " << b <<
". This should not happen because "
43891 <<
"these\nlimits should have been setup in the constructor\n";
43893 <<
"The distance between the new and old nodes is probably outside\n"
43894 <<
"our tolerance.\n";
43895 error_stream.precision(20);
43896 error_stream <<
"Old boundaries: \n";
43897 error_stream << old_boundary_node[0][1] <<
" "
43898 << old_boundary_node[0][2] <<
" : "
43899 << old_boundary_node[n_boundary_node - 1][1] <<
" "
43900 << old_boundary_node[n_boundary_node - 1][2] <<
"\n";
43901 error_stream <<
"New boundaries: \n"
43902 << new_boundary_node[0][1] <<
" "
43903 << new_boundary_node[0][2] <<
" : "
43904 << new_boundary_node[n_new_boundary_segment_node - 1][1]
43906 << new_boundary_node[n_new_boundary_segment_node - 1][2]
43908 OomphLibWarning(error_stream.str(),
43909 "RefineableTriangleMesh::snap_nodes_onto_boundary()",
43910 OOMPH_EXCEPTION_LOCATION);
43916 if (!this->is_mesh_distributed())
43920 new_boundary_node[0][4] = new_boundary_node[0][0];
43923 new_boundary_node[n_new_boundary_segment_node - 1][4] =
43924 new_boundary_node[0][5] = 1.0;
43926 new_boundary_node[n_new_boundary_segment_node - 1][4] =
43927 new_boundary_node[n_new_boundary_segment_node - 1][0];
43928 new_boundary_node[n_new_boundary_segment_node - 1][5] = 1.0;
43933 for (
unsigned n = 1; n < n_new_boundary_segment_node - 1; ++n)
43936 if (new_boundary_node[n][5] == 0.0)
43939 nodes_to_be_snapped[is].push_back(
43940 static_cast<unsigned>(new_boundary_node[n][3]));
43944 double zeta_old_low = new_boundary_node[n - 1][0];
43945 double zeta_new_low = new_boundary_node[n - 1][4];
43949 for (
unsigned m = n + 1; m < n_new_boundary_segment_node; ++m)
43951 if (new_boundary_node[m][5] == 1.0)
43954 double zeta_old_high = new_boundary_node[m][0];
43955 double zeta_new_high = new_boundary_node[m][4];
43957 double frac = (new_boundary_node[n][0] - zeta_old_low) /
43958 (zeta_old_high - zeta_old_low);
43959 new_boundary_node[n][4] =
43960 zeta_new_low + frac * (zeta_new_high - zeta_new_low);
43961 new_boundary_node[n][5] = 1.0;
43969 for (
unsigned n = 0; n < n_new_boundary_segment_node; ++n)
43971 if (new_boundary_node[n][5] == 0)
43973 throw OomphLibError(
43974 "New boundary coordinate not assigned\n",
43975 "RefineableTriangleMesh::snap_nodes_onto_boundary()",
43976 OOMPH_EXCEPTION_LOCATION);
43979 #ifdef OOMPH_HAS_MPI
43983 b, is,
static_cast<unsigned>(new_boundary_node[n][3]))
43984 ->get_coordinates_on_boundary(b, b_coord);
43986 b_coord[0] = new_boundary_node[n][4];
43989 b, is,
static_cast<unsigned>(new_boundary_node[n][3]))
43990 ->set_coordinates_on_boundary(b, b_coord);
43994 ->boundary_node_pt(b,
static_cast<unsigned>(new_boundary_node[n][3]))
43995 ->get_coordinates_on_boundary(b, b_coord);
43997 b_coord[0] = new_boundary_node[n][4];
43999 ->boundary_node_pt(b,
static_cast<unsigned>(new_boundary_node[n][3]))
44000 ->set_coordinates_on_boundary(b, b_coord);
44006 Mesh* face_mesh_pt =
new Mesh();
44007 create_unsorted_face_mesh_representation(b, face_mesh_pt);
44010 MeshAsGeomObject* mesh_geom_obj_pt =
new MeshAsGeomObject(face_mesh_pt);
44014 Vector<double> new_x(2);
44017 for (
unsigned is = 0; is < nsegments; is++)
44019 const unsigned nnodes_to_snap = nodes_to_be_snapped[is].size();
44021 for (
unsigned in = 0; in < nnodes_to_snap; in++)
44024 unsigned n = nodes_to_be_snapped[is][in];
44025 #ifdef OOMPH_HAS_MPI
44030 Node*
const nod_pt = new_mesh_pt->boundary_node_pt(b, n);
44033 nod_pt->get_coordinates_on_boundary(b, b_coord);
44035 mesh_geom_obj_pt->position(b_coord, new_x);
44038 for (
unsigned i = 0; i < 2; i++)
44040 nod_pt->x(i) = new_x[i];
44046 delete mesh_geom_obj_pt;
44049 face_mesh_pt->flush_node_storage();
44050 delete face_mesh_pt;
44056 TElement<2, 3> dummy_six_node_element;
44057 for (
unsigned j = 0; j < 6; j++)
44059 dummy_six_node_element.construct_node(j);
44064 unsigned n_bound_el = new_mesh_pt->nboundary_element(b);
44065 for (
unsigned e = 0; e < n_bound_el; e++)
44067 FiniteElement* el_pt = new_mesh_pt->boundary_element_pt(b, e);
44070 unsigned nnod = el_pt->nnode();
44082 TElement<2, 2>* t_el_pt =
dynamic_cast<TElement<2, 2>*
>(el_pt);
44085 throw OomphLibError(
44086 "Have a three-noded element that's not a TElement<2,2>",
44087 OOMPH_CURRENT_FUNCTION,
44088 OOMPH_EXCEPTION_LOCATION);
44096 else if ((nnod == 6) || (nnod == 7))
44100 TElement<2, 3>* t_el_pt =
dynamic_cast<TElement<2, 3>*
>(el_pt);
44105 throw OomphLibError(
44106 "Have a six-noded element that's not a TElement<2,3>",
44107 OOMPH_CURRENT_FUNCTION,
44108 OOMPH_EXCEPTION_LOCATION);
44112 throw OomphLibError(
44113 "Have a seven-noded element that's not a TElement<2,3>",
44114 OOMPH_CURRENT_FUNCTION,
44115 OOMPH_EXCEPTION_LOCATION);
44128 if (el_pt->node_pt(3)->is_on_boundary(b))
44132 if (!el_pt->node_pt(5)->is_on_boundary())
44135 for (
unsigned i = 0; i < 2; i++)
44137 el_pt->node_pt(5)->x(i) =
44138 0.5 * (el_pt->node_pt(0)->x(i) + el_pt->node_pt(2)->x(i));
44143 if (!el_pt->node_pt(4)->is_on_boundary())
44146 for (
unsigned i = 0; i < 2; i++)
44148 el_pt->node_pt(4)->x(i) =
44149 0.5 * (el_pt->node_pt(1)->x(i) + el_pt->node_pt(2)->x(i));
44155 if (el_pt->node_pt(4)->is_on_boundary(b))
44159 if (!el_pt->node_pt(5)->is_on_boundary())
44162 for (
unsigned i = 0; i < 2; i++)
44164 el_pt->node_pt(5)->x(i) =
44165 0.5 * (el_pt->node_pt(0)->x(i) + el_pt->node_pt(2)->x(i));
44170 if (!el_pt->node_pt(3)->is_on_boundary())
44173 for (
unsigned i = 0; i < 2; i++)
44175 el_pt->node_pt(3)->x(i) =
44176 0.5 * (el_pt->node_pt(0)->x(i) + el_pt->node_pt(1)->x(i));
44182 if (el_pt->node_pt(5)->is_on_boundary(b))
44186 if (!el_pt->node_pt(4)->is_on_boundary())
44189 for (
unsigned i = 0; i < 2; i++)
44191 el_pt->node_pt(4)->x(i) =
44192 0.5 * (el_pt->node_pt(1)->x(i) + el_pt->node_pt(2)->x(i));
44197 if (!el_pt->node_pt(3)->is_on_boundary())
44200 for (
unsigned i = 0; i < 2; i++)
44202 el_pt->node_pt(3)->x(i) =
44203 0.5 * (el_pt->node_pt(0)->x(i) + el_pt->node_pt(1)->x(i));
44213 TBubbleEnrichedElement<2, 3>* t_el_pt =
44214 dynamic_cast<TBubbleEnrichedElement<2, 3>*
>(el_pt);
44217 throw OomphLibError(
"Have seven-noded element that's not a "
44218 "TBubbleEnrichedElement<2,3>",
44219 OOMPH_CURRENT_FUNCTION,
44220 OOMPH_EXCEPTION_LOCATION);
44225 for (
unsigned j = 0; j < 6; j++)
44227 for (
unsigned i = 0; i < 2; i++)
44229 dummy_six_node_element.node_pt(j)->x(i) = el_pt->node_pt(j)->x(i);
44234 unsigned j_enriched = 6;
44235 Vector<double> s(2);
44236 el_pt->local_coordinate_of_node(j_enriched, s);
44239 Vector<double> x(2);
44240 dummy_six_node_element.interpolated_x(s, x);
44241 el_pt->node_pt(j_enriched)->x(0) = x[0];
44242 el_pt->node_pt(j_enriched)->x(1) = x[1];
44249 std::ostringstream error_stream;
44250 error_stream <<
"Cannot deal with this particular " << nnod
44251 <<
"-noded element yet.\n"
44252 <<
"Please implement this yourself.\n";
44253 throw OomphLibError(
44254 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
44259 for (
unsigned j = 0; j < 6; j++)
44261 delete dummy_six_node_element.node_pt(j);
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
/////////////////////////////////////////////////////////////////// /////////////////////////////////...
bool refine_boundary_constrained_by_target_area(MeshAsGeomObject *mesh_geom_obj_pt, Vector< Vector< double >> &vector_bnd_vertices, double &refinement_tolerance, Vector< double > &area_constraint)
Helper function that performs the refinement process on the specified boundary by using the provided ...
bool update_shared_curve_using_elements_area(Vector< TriangleMeshPolyLine * > &vector_polyline_pt, const Vector< double > &target_areas)
Updates the polylines using the elements area as constraint for the number of points along the bounda...
void compute_shared_node_degree_helper(Vector< Vector< FiniteElement * >> &unsorted_face_ele_pt, std::map< Node *, unsigned > &global_node_degree)
Computes the degree of the nodes on the shared boundaries, the degree of the node is computed from th...
void construct_new_halo_node_helper(Node *&new_nod_pt, Vector< Node * > &new_nodes_on_domain, Vector< Vector< Vector< std::map< unsigned, Node * >>>> &other_proc_shd_bnd_node_pt, unsigned &iproc, unsigned &node_index, FiniteElement *const &new_el_pt, Vector< Vector< Vector< unsigned >>> &global_node_names, std::map< Vector< unsigned >, unsigned > &node_name_to_global_index, Vector< Node * > &global_shared_node_pt)
Helper function which constructs a new halo node (on an element) with the information sent from the h...
bool get_connected_vertex_number_on_dst_boundary(Vector< double > &vertex_coordinates, const unsigned &dst_b_id, unsigned &vertex_number)
Computes the associated vertex number on the destination boundary.
void update_other_proc_shd_bnd_node_helper(Node *&new_nod_pt, Vector< Vector< Vector< std::map< unsigned, Node * >>>> &other_proc_shd_bnd_node_pt, Vector< unsigned > &other_processor_1, Vector< unsigned > &other_processor_2, Vector< unsigned > &other_shared_boundaries, Vector< unsigned > &other_indexes, Vector< Vector< Vector< unsigned >>> &global_node_names, std::map< Vector< unsigned >, unsigned > &node_name_to_global_index, Vector< Node * > &global_shared_node_pt)
Helper function that assigns/updates the references to the node so that it can be found with any othe...
void send_boundary_node_info_of_shared_nodes(Vector< Vector< Vector< unsigned >>> &global_node_names, std::map< Vector< unsigned >, unsigned > &node_name_to_global_index, Vector< Node * > &global_shared_node_pt)
Get the original boundaries to which is associated each shared node, and send the info....
void get_boundary_segment_nodes_helper(const unsigned &b, Vector< Vector< Node * >> &tmp_segment_nodes)
Get the nodes on the boundary (b), these are stored in the segment they belong (also used by the load...
void create_halo_element(unsigned &iproc, Vector< Node * > &new_nodes_on_domain, Vector< Vector< Vector< std::map< unsigned, Node * >>>> &other_proc_shd_bnd_node_pt, Vector< Vector< Vector< unsigned >>> &global_node_names, std::map< Vector< unsigned >, unsigned > &node_name_to_global_index, Vector< Node * > &global_shared_node_pt)
Helper function to create (halo) elements on the loop process based on the info received in send_and_...
void get_required_nodal_information_load_balance_helper(Vector< Vector< FiniteElement * >> &f_halo_ele_pt, unsigned &iproc, Node *nod_pt)
Helper function to get the required nodal information from an haloed node so that a fully-functional ...
void update_shared_curve_after_restart(Vector< TriangleMeshPolyLine * > &vector_polyline_pt)
Updates the shared polylines representation after restart.
void send_and_receive_elements_nodes_info(int &send_proc, int &recv_proc)
Helper function to send back halo and haloed information.
void compute_global_node_names_and_shared_nodes(Vector< Vector< Vector< std::map< unsigned, Node * >>>> &other_proc_shd_bnd_node_pt, Vector< Vector< Vector< unsigned >>> &global_node_names, std::map< Vector< unsigned >, unsigned > &node_name_to_global_index, Vector< Node * > &global_shared_node_pt)
Compute the names of the nodes on shared boundaries in this (my_rank) processor with other processors...
void create_element_load_balance_helper(unsigned &iproc, Vector< Vector< FiniteElement * >> &f_haloed_ele_pt, Vector< Vector< std::map< unsigned, FiniteElement * >>> &received_old_haloed_element_pt, Vector< FiniteElement * > &new_elements_on_domain, Vector< Node * > &new_nodes_on_domain, Vector< Vector< Vector< std::map< unsigned, Node * >>>> &other_proc_shd_bnd_node_pt, Vector< Vector< Vector< unsigned >>> &global_node_names, std::map< Vector< unsigned >, unsigned > &node_name_to_global_index, Vector< Node * > &global_shared_node_pt)
Helper function to create elements on the loop process based on the info received in send_and_receive...
void snap_nodes_onto_boundary(RefineableTriangleMesh< ELEMENT > *&new_mesh_pt, const unsigned &b)
Snap the boundary nodes onto any curvilinear boundaries.
void reset_shared_boundary_elements_and_nodes(const bool flush_elements=true, const bool update_elements=true, const bool flush_nodes=true, const bool update_nodes=true)
Re-establish the shared boundary elements after the adaptation process (the updating of shared nodes ...
void get_face_mesh_representation(TriangleMeshPolygon *polygon_pt, Vector< Mesh * > &face_mesh_pt)
Helper function to construct face mesh representation of all polylines, possibly with segments re-dis...
double & max_element_size()
Max element size allowed during adaptation.
bool unrefine_shared_boundary_constrained_by_target_area(const unsigned &b, const unsigned &c, Vector< Vector< double >> &vector_bnd_vertices, Vector< double > &area_constraint)
Helper function that performs the unrefinement process on the specified boundary by using the provide...
void resume_boundary_connections(Vector< TriangleMeshPolyLine * > &resume_initial_connection_polyline_pt, Vector< TriangleMeshPolyLine * > &resume_final_connection_polyline_pt)
Resume the boundary connections that may have been suspended because the destination boundary is no p...
void sort_nodes_on_shared_boundaries()
Sort the nodes on shared boundaries so that the processors that share a boundary agree with the order...
bool update_open_curve_using_elements_area(TriangleMeshOpenCurve *&open_curve_pt, const Vector< double > &target_area)
Updates the open curve but using the elements area instead of the default refinement and unrefinement...
bool unrefine_boundary_constrained_by_target_area(const unsigned &b, const unsigned &c, Vector< Vector< double >> &vector_bnd_vertices, double &unrefinement_tolerance, Vector< double > &area_constraint)
Helper function that performs the unrefinement process on the specified boundary by using the provide...
void add_node_load_balance_helper(unsigned &iproc, Vector< Vector< FiniteElement * >> &f_halo_ele_pt, Vector< Node * > &new_nodes_on_domain, Node *nod_pt)
Helper function to add haloed node.
void create_new_shared_boundaries(std::set< FiniteElement * > &element_in_processor_pt, Vector< Vector< FiniteElement * >> &new_shared_boundary_element_pt, Vector< Vector< unsigned >> &new_shared_boundary_element_face_index)
Creates the new shared boundaries, this method is also in charge of computing the shared boundaries i...
bool unrefine_boundary(const unsigned &b, const unsigned &c, Vector< Vector< double >> &vector_bnd_vertices, double &unrefinement_tolerance, const bool &check_only=false)
Helper function that performs the unrefinement process.
void reset_halo_haloed_scheme_helper(Vector< Vector< Vector< std::map< unsigned, Node * >>>> &other_proc_shd_bnd_node_pt, Vector< Vector< Node * >> &iproc_currently_created_nodes_pt, Vector< Vector< Vector< unsigned >>> &global_node_names, std::map< Vector< unsigned >, unsigned > &node_name_to_global_index, Vector< Node * > &global_shared_node_pt)
In charge of creating additional halo(ed) elements on those processors that have no shared boundaries...
void construct_new_node_load_balance_helper(Node *&new_nod_pt, Vector< Vector< FiniteElement * >> &f_haloed_ele_pt, Vector< Vector< std::map< unsigned, FiniteElement * >>> &received_old_haloed_element_pt, Vector< Node * > &new_nodes_on_domain, Vector< Vector< Vector< std::map< unsigned, Node * >>>> &other_proc_shd_bnd_node_pt, unsigned &iproc, unsigned &node_index, FiniteElement *const &new_el_pt, Vector< Vector< Vector< unsigned >>> &global_node_names, std::map< Vector< unsigned >, unsigned > &node_name_to_global_index, Vector< Node * > &global_shared_node_pt)
Helper function which constructs a new node (on an element) with the information sent from the load b...
void add_received_node_load_balance_helper(Node *&new_nod_pt, Vector< Vector< FiniteElement * >> &f_haloed_ele_pt, Vector< Vector< std::map< unsigned, FiniteElement * >>> &received_old_haloed_element_pt, Vector< Node * > &new_nodes_on_domain, Vector< Vector< Vector< std::map< unsigned, Node * >>>> &other_proc_shd_bnd_node_pt, unsigned &iproc, unsigned &node_index, FiniteElement *const &new_el_pt, Vector< Vector< Vector< unsigned >>> &global_node_names, std::map< Vector< unsigned >, unsigned > &node_name_to_global_index, Vector< Node * > &global_shared_node_pt)
Helper function to add a new node from load balance.
double & min_permitted_angle()
Min angle before remesh gets triggered.
bool refine_boundary(Mesh *face_mesh_pt, Vector< Vector< double >> &vector_bnd_vertices, double &refinement_tolerance, const bool &check_only=false)
Helper function that performs the refinement process on the specified boundary by using the provided ...
void get_shared_boundary_elements_and_face_indexes(const Vector< FiniteElement * > &first_element_pt, const Vector< FiniteElement * > &second_element_pt, Vector< FiniteElement * > &first_shared_boundary_element_pt, Vector< unsigned > &first_shared_boundary_element_face_index, Vector< FiniteElement * > &second_shared_boundary_element_pt, Vector< unsigned > &second_shared_boundary_element_face_index)
Use the first and second group of elements to find the intersection between them to get the shared bo...
void create_sorted_face_mesh_representation(const unsigned &boundary_id, Mesh *face_mesh_pt, std::map< FiniteElement *, bool > &is_inverted, bool &inverted_face_mesh)
Helper function Creates a sorted face mesh representation of the specified PolyLine It means that the...
void update_open_curve_after_restart(TriangleMeshOpenCurve *&open_curve_pt)
Updates the open curve representation after restart.
bool refine_shared_boundary_constrained_by_target_area(Vector< Vector< double >> &vector_bnd_vertices, Vector< double > &area_constraint)
Helper function that performs the refinement process on the specified boundary by using the provided ...
void reset_halo_haloed_scheme()
In charge of. re-establish the halo(ed) scheme on all processors. Sends info. to create halo elements...
void refine_triangulateio(TriangulateIO &triangulate_io, const Vector< double > &target_area, TriangulateIO &triangle_refine)
Build a new TriangulateIO object from previous TriangulateIO based on target area for each element.
void get_required_elemental_information_load_balance_helper(unsigned &iproc, Vector< Vector< FiniteElement * >> &f_haloed_ele_pt, FiniteElement *ele_pt)
Helper function to get the required elemental information from the element to be sent....
void load_balance(const Vector< unsigned > &input_target_domain_for_local_non_halo_element)
Performs the load balancing for unstructured meshes, the load balancing strategy is based on mesh mig...
void create_unsorted_face_mesh_representation(const unsigned &boundary_id, Mesh *face_mesh_pt)
Helper function Creates an unsorted face mesh representation from the specified boundary id....
void add_non_delete_vertices_from_boundary_helper(Vector< Vector< Node * >> src_bound_segment_node_pt, Vector< Vector< Node * >> dst_bound_segment_node_pt, const unsigned &dst_bnd_id, const unsigned &dst_bnd_chunk)
Adds the vertices from the sources boundary that are repeated in the destination boundary to the list...
void add_element_load_balance_helper(const unsigned &iproc, Vector< Vector< std::map< unsigned, FiniteElement * >>> &received_old_haloed_element_pt, FiniteElement *ele_pt)
Helper function to create elements on the loop process based on the info received in send_and_receive...
void restore_boundary_connections(Vector< TriangleMeshPolyLine * > &resume_initial_connection_polyline_pt, Vector< TriangleMeshPolyLine * > &resume_final_connection_polyline_pt)
After unrefinement and refinement has taken place compute the new vertices numbers of the boundaries ...
bool update_open_curve_using_face_mesh(TriangleMeshOpenCurve *open_polyline_pt, const bool &check_only=false)
Helper function that updates the input open curve by using end-points of elements from FaceMesh(es) t...
void create_temporary_boundary_connections(Vector< TriangleMeshPolygon * > &tmp_outer_polygons_pt, Vector< TriangleMeshOpenCurve * > &tmp_open_curves_pt)
After unrefinement and refinement has taken place compute the new vertices numbers of the temporary r...
void add_haloed_node_helper(unsigned &iproc, Node *nod_pt)
Helper function to add haloed node.
void get_required_nodal_information_helper(unsigned &iproc, Node *nod_pt)
Helper function to get the required nodal information from a haloed node so that a fully-functional h...
void add_halo_element_helper(unsigned &iproc, FiniteElement *ele_pt)
Helper function to create (halo) elements on the loop process based on the info received in send_and_...
double & min_element_size()
Min element size allowed during adaptation.
void create_adjacency_matrix_new_shared_edges_helper(Vector< Vector< FiniteElement * >> &unsorted_face_ele_pt, Vector< Vector< Node * >> &tmp_sorted_shared_node_pt, std::map< Node *, Vector< Vector< unsigned >>> &node_alias, Vector< Vector< Vector< unsigned >>> &adjacency_matrix)
Sort the nodes on the new shared boundaries (after load balancing), computes the alias of the nodes a...
void fill_boundary_elements_and_nodes_for_internal_boundaries()
bool update_polygon_using_face_mesh(TriangleMeshPolygon *polygon_pt, const bool &check_only=false)
Helper function that updates the input polygon's PSLG by using the end-points of elements from FaceMe...
void update_polygon_after_restart(TriangleMeshPolygon *&polygon_pt)
Updates the polylines representation after restart.
void add_vertices_for_non_deletion()
Mark the vertices that are not allowed for deletion by the unrefienment/refinement polyline methods....
void create_polylines_from_polyfiles(const std::string &node_file_name, const std::string &poly_file_name)
Helper function to create polylines and fill associate data.
bool update_polygon_using_elements_area(TriangleMeshPolygon *&polygon_pt, const Vector< double > &target_area)
Updates the polylines using the elements area as constraint for the number of points along the bounda...
bool apply_max_length_constraint(Mesh *face_mesh_pt, Vector< Vector< double >> &vector_bnd_vertices, double &max_length_constraint)
void add_halo_node_helper(Node *&new_nod_pt, Vector< Node * > &new_nodes_on_domain, Vector< Vector< Vector< std::map< unsigned, Node * >>>> &other_proc_shd_bnd_node_pt, unsigned &iproc, unsigned &node_index, FiniteElement *const &new_el_pt, Vector< Vector< Vector< unsigned >>> &global_node_names, std::map< Vector< unsigned >, unsigned > &node_name_to_global_index, Vector< Node * > &global_shared_node_pt)
Helper function to add halo node.
void restore_polyline_connections_helper(TriangleMeshPolyLine *polyline_pt, Vector< TriangleMeshPolyLine * > &resume_initial_connection_polyline_pt, Vector< TriangleMeshPolyLine * > &resume_final_connection_polyline_pt)
Restore the connections of the specific polyline The vertices numbering on the destination boundaries...
void get_shared_boundary_segment_nodes_helper(const unsigned &shd_bnd_id, Vector< Vector< Node * >> &tmp_segment_nodes)
Get the nodes on the shared boundary (b), these are stored in the segment they belong.
void adapt(const Vector< double > &elem_error)
Adapt mesh, based on elemental error provided.
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
Vector< TriangleMeshClosedCurve * > internal_closed_curve_pt() const
Helper function for getting the internal closed boundaries.
Vector< Vector< double > > extra_holes_coordinates() const
Helper function for getting the extra holes.
void enable_use_attributes()
Helper function for enabling the use of attributes.
double element_area() const
Helper function for getting the element area.
void disable_automatic_creation_of_vertices_on_boundaries()
Disables the creation of points (by Triangle) on the outer and internal boundaries.
void set_communicator_pt(OomphCommunicator *comm_pt)
Function to set communicator (mesh is then assumed to be distributed)
Vector< TriangleMeshOpenCurve * > internal_open_curves_pt() const
Helper function for getting the internal open boundaries.
std::map< unsigned, Vector< double > > & regions_coordinates()
Helper function for getting access to the regions coordinates.
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
void re_assign_initial_zeta_values_for_internal_boundary(const unsigned &b, Vector< std::list< FiniteElement * >> &old_segment_sorted_ele_pt, std::map< FiniteElement *, bool > &old_is_inverted)
Re-assign the boundary segments initial zeta (arclength) value for those internal boundaries that wer...
void compute_boundary_segments_connectivity_and_initial_zeta_values(const unsigned &b)
Compute the boundary segments connectivity for those boundaries that were splited during the distribu...
void build_triangulateio(const std::string &poly_file_name, TriangulateIO &triangulate_io, bool &use_attributes)
Helper function to create TriangulateIO object (return in triangulate_io) from the ....
void create_shared_polylines_connections()
Establish the connections of the polylines previously marked as having connections....
void break_loops_on_shared_polyline_load_balance_helper(const unsigned &initial_shd_bnd_id, std::list< Node * > &input_nodes, Vector< FiniteElement * > &input_boundary_element_pt, Vector< FiniteElement * > &input_boundary_face_element_pt, Vector< int > &input_face_index_element, const int &input_connect_to_the_left, const int &input_connect_to_the_right, Vector< std::list< Node * >> &output_sorted_nodes_pt, Vector< Vector< FiniteElement * >> &output_boundary_element_pt, Vector< Vector< FiniteElement * >> &output_boundary_face_element_pt, Vector< Vector< int >> &output_face_index_element, Vector< int > &output_connect_to_the_left, Vector< int > &output_connect_to_the_right)
Break any possible loop created by the sorted list of nodes that is used to create a new shared polyl...
void synchronize_boundary_coordinates(const unsigned &b)
In charge of sinchronize the boundary coordinates for internal boundaries that were split as part of ...
void compute_holes_left_by_halo_elements_helper(Vector< Vector< double >> &output_holes_coordinates)
Compute the holes left by the halo elements, those adjacent to the shared boundaries.
void identify_boundary_segments_and_assign_initial_zeta_values(const unsigned &b, Vector< FiniteElement * > &input_face_ele_pt, const bool &is_internal_boundary, std::map< FiniteElement *, FiniteElement * > &face_to_bulk_element_pt)
Identify the segments from the old mesh (original mesh) in the new mesh (this) and assign initial and...
const bool shared_boundary_overlaps_internal_boundary(const unsigned &shd_bnd_id)
Checks if the shared boundary overlaps an internal boundary.
virtual void reset_boundary_element_info(Vector< unsigned > &ntmp_boundary_elements, Vector< Vector< unsigned >> &ntmp_boundary_elements_in_region, Vector< FiniteElement * > &deleted_elements)
Virtual function to perform the reset boundary elements info routines. Generally used after load bala...
const int check_connections_of_polyline_nodes(std::set< FiniteElement * > &element_in_processor_pt, const int &root_edge_bnd_id, std::map< std::pair< Node *, Node * >, bool > &overlapped_face, std::map< unsigned, std::map< Node *, bool >> &node_on_bnd_not_overlapped_by_shd_bnd, std::list< Node * > ¤t_polyline_nodes, std::map< unsigned, std::list< Node * >> &shared_bnd_id_to_sorted_list_node_pt, const unsigned &node_degree, Node *&new_node_pt, const bool called_from_load_balance=false)
Check for any possible connections that the array of sorted nodes have with any previous boundaries o...
void break_loops_on_shared_polyline_helper(const unsigned &initial_shd_bnd_id, std::list< Node * > &input_nodes, Vector< FiniteElement * > &input_boundary_element_pt, Vector< int > &input_face_index_element, const int &input_connect_to_the_left, const int &input_connect_to_the_right, Vector< std::list< Node * >> &output_sorted_nodes_pt, Vector< Vector< FiniteElement * >> &output_boundary_element_pt, Vector< Vector< int >> &output_face_index_element, Vector< int > &output_connect_to_the_left, Vector< int > &output_connect_to_the_right)
Break any possible loop created by the sorted list of nodes that is used to create a new shared polyl...
void create_tmp_polygons_helper(Vector< Vector< TriangleMeshPolyLine * >> &polylines_pt, Vector< TriangleMeshPolygon * > &polygons_pt)
Take the polylines from the shared boundaries and create temporary polygon representations of the dom...
void re_scale_re_assigned_initial_zeta_values_for_internal_boundary(const unsigned &b)
Re-scale the re-assigned zeta values for the boundary nodes, apply only for internal boundaries.
void create_tmp_open_curves_helper(Vector< Vector< TriangleMeshPolyLine * >> &sorted_open_curves_pt, Vector< TriangleMeshPolyLine * > &unsorted_shared_to_internal_poly_pt, Vector< TriangleMeshOpenCurve * > &open_curves_pt)
Take the polylines from the original open curves and created new temporaly representations of open cu...
void sort_polylines_helper(Vector< TriangleMeshPolyLine * > &unsorted_polylines_pt, Vector< Vector< TriangleMeshPolyLine * >> &sorted_polylines_pt)
Sorts the polylines so they be continuous and then we can create a closed or open curve from them.
void create_distributed_domain_representation(Vector< TriangleMeshPolygon * > &polygons_pt, Vector< TriangleMeshOpenCurve * > &open_curves_pt)
Creates the distributed domain representation. Joins the original boundaires, shared boundaries and c...
Vector< Vector< Node * > > & boundary_segment_node_pt(const unsigned &b)
Return direct access to nodes associated with a boundary but sorted in segments.
void build_from_scaffold(TimeStepper *time_stepper_pt, const bool &use_attributes)
Build mesh from scaffold.
Vector< Vector< Vector< unsigned > > > shared_boundaries_ids() const
void create_shared_boundaries(OomphCommunicator *comm_pt, const Vector< unsigned > &element_domain, const Vector< GeneralisedElement * > &backed_up_el_pt, const Vector< FiniteElement * > &backed_up_f_el_pt, std::map< Data *, std::set< unsigned >> &processors_associated_with_data, const bool &overrule_keep_as_halo_element_status)
Creates the shared boundaries.
Vector< unsigned > oomph_vertex_nodes_id()
Return the vector that contains the oomph-lib node number for all vertex nodes in the TriangulateIO r...
void create_shared_polyline(const unsigned &my_rank, const unsigned &shd_bnd_id, const unsigned &iproc, const unsigned &jproc, std::list< Node * > &sorted_nodes, const int &root_edge_bnd_id, Vector< FiniteElement * > &bulk_bnd_ele_pt, Vector< int > &face_index_ele, Vector< Vector< TriangleMeshPolyLine * >> &unsorted_polylines_pt, const int &connect_to_the_left_flag, const int &connect_to_the_right_flag)
Create the shared polyline and fill the data structured that keep all the information associated with...
void dump_distributed_info_for_restart(std::ostream &dump_file)
Used to dump info. related with distributed triangle meshes.
void get_halo_elements_on_all_procs(const unsigned &nproc, const Vector< unsigned > &element_domain, const Vector< GeneralisedElement * > &backed_up_el_pt, std::map< Data *, std::set< unsigned >> &processors_associated_with_data, const bool &overrule_keep_as_halo_element_status, std::map< GeneralisedElement *, unsigned > &element_to_global_index, Vector< Vector< Vector< GeneralisedElement * >>> &output_halo_elements_pt)
Creates the halo elements on all processors Gets the halo elements on all processors,...
void set_mesh_level_time_stepper(TimeStepper *const &time_stepper_pt, const bool &preserve_existing_data)
Overload set_mesh_level_time_stepper so that the stored time stepper now corresponds to the new times...
void read_distributed_info_for_restart(std::istream &restart_file)
Used to read info. related with distributed triangle meshes.
void select_boundary_face_elements(Vector< FiniteElement * > &face_el_pt, const unsigned &b, bool &is_internal_boundary, std::map< FiniteElement *, FiniteElement * > &face_to_bulk_element_pt)
Select face element from boundary using the criteria to decide which of the two face elements should ...
void output_boundary_coordinates(const unsigned &b, std::ostream &outfile)
Output the nodes on the boundary and their respective boundary coordinates(into separate tecplot zone...
void get_element_edges_on_boundary(std::map< std::pair< Node *, Node * >, unsigned > &element_edges_on_boundary)
Get the element edges (pair of nodes, edges) that lie on a boundary (used to mark shared boundaries t...
void update_holes_information_helper(Vector< TriangleMeshPolygon * > &polygons_pt, Vector< Vector< double >> &output_holes_coordinates)
Keeps those vertices that define a hole, those that are inside closed internal boundaries in the new ...
void create_polylines_from_halo_elements_helper(const Vector< unsigned > &element_domain, std::map< GeneralisedElement *, unsigned > &element_to_global_index, std::set< FiniteElement * > &element_in_processor_pt, Vector< Vector< Vector< GeneralisedElement * >>> &input_halo_elements, std::map< std::pair< Node *, Node * >, unsigned > &elements_edges_on_boundary, Vector< Vector< Vector< TriangleMeshPolyLine * >>> &output_polylines_pt)
Creates polylines from the intersection of halo elements on all processors. The new polylines define ...
////////////////////////////////////////////////////////////////////// //////////////////////////////...
struct oomph::classcomp Bottom_left_sorter
bool operator()(const std::pair< double, double > &lhs, const std::pair< double, double > &rhs) const