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);
6217 unsigned nflat_double_send = flat_double_send_packed_data.size();
6218 MPI_Isend(&nflat_double_send,
6223 comm_pt->mpi_comm(),
6226 unsigned nflat_double_receive = 0;
6227 MPI_Recv(&nflat_double_receive,
6232 comm_pt->mpi_comm(),
6235 MPI_Wait(&request, MPI_STATUS_IGNORE);
6237 if (nflat_double_send != 0)
6239 MPI_Isend(&flat_double_send_packed_data[0],
6244 comm_pt->mpi_comm(),
6248 if (nflat_double_receive != 0)
6250 flat_double_receive_packed_data.resize(nflat_double_receive);
6251 MPI_Recv(&flat_double_receive_packed_data[0],
6252 nflat_double_receive,
6256 comm_pt->mpi_comm(),
6260 if (nflat_double_send != 0)
6262 MPI_Wait(&request, MPI_STATUS_IGNORE);
6267 if (nflat_unsigned_receive != nflat_double_receive)
6269 std::ostringstream error_message;
6270 error_message <<
"The number of unsigned received data ("
6271 << nflat_unsigned_receive <<
") is different from the "
6272 <<
"number\nof double received data ("
6273 << nflat_double_receive <<
")!!!\n\n";
6274 throw OomphLibError(
6275 error_message.str(),
6276 "TriangleMesh::synchronize_boundary_coordinates()",
6277 OOMPH_EXCEPTION_LOCATION);
6284 for (
unsigned iflat_packed = 0; iflat_packed < nflat_unsigned_receive;
6288 const unsigned haloed_id =
6289 flat_unsigned_receive_packed_data[iflat_packed];
6291 Vector<double> zeta(1);
6292 zeta[0] = flat_double_receive_packed_data[iflat_packed];
6295 Node* haloed_face_node_pt = this->haloed_node_pt(ip, haloed_id);
6309 if (!done_haloed_face_node[haloed_face_node_pt])
6312 haloed_face_node_pt->set_coordinates_on_boundary(b, zeta);
6315 for (
unsigned iiproc = 0; iiproc < nproc; iiproc++)
6318 if (iiproc != my_rank)
6321 const unsigned nhaloed_node_iiproc = this->nhaloed_node(iiproc);
6322 for (
unsigned ihdn = 0; ihdn < nhaloed_node_iiproc; ihdn++)
6324 Node* compare_haloed_node_pt =
6325 this->haloed_node_pt(iiproc, ihdn);
6326 if (haloed_face_node_pt == compare_haloed_node_pt)
6330 face_haloed_node_pt[iiproc].push_back(haloed_face_node_pt);
6333 face_haloed_node_id[iiproc].push_back(ihdn);
6354 for (
unsigned ip = 0; ip < nproc; ip++)
6361 Vector<unsigned> flat_unsigned_send_packed_data;
6362 Vector<double> flat_double_send_packed_data;
6366 const unsigned nhaloed_face_nodes = face_haloed_node_pt[ip].size();
6368 for (
unsigned ihdfn = 0; ihdfn < nhaloed_face_nodes; ihdfn++)
6371 Node* haloed_face_node_pt = face_haloed_node_pt[ip][ihdfn];
6373 const unsigned haloed_id = face_haloed_node_id[ip][ihdfn];
6375 Vector<double> zeta(1);
6376 haloed_face_node_pt->get_coordinates_on_boundary(b, zeta);
6378 flat_unsigned_send_packed_data.push_back(haloed_id);
6379 flat_double_send_packed_data.push_back(zeta[0]);
6384 MPI_Request request;
6387 int send_proc =
static_cast<int>(ip);
6389 int receive_proc =
static_cast<int>(ip);
6392 Vector<unsigned> flat_unsigned_receive_packed_data;
6393 Vector<double> flat_double_receive_packed_data;
6397 unsigned nflat_unsigned_send = flat_unsigned_send_packed_data.size();
6398 MPI_Isend(&nflat_unsigned_send,
6403 comm_pt->mpi_comm(),
6406 unsigned nflat_unsigned_receive = 0;
6407 MPI_Recv(&nflat_unsigned_receive,
6412 comm_pt->mpi_comm(),
6415 MPI_Wait(&request, MPI_STATUS_IGNORE);
6417 if (nflat_unsigned_send != 0)
6419 MPI_Isend(&flat_unsigned_send_packed_data[0],
6420 nflat_unsigned_send,
6424 comm_pt->mpi_comm(),
6428 if (nflat_unsigned_receive != 0)
6430 flat_unsigned_receive_packed_data.resize(nflat_unsigned_receive);
6431 MPI_Recv(&flat_unsigned_receive_packed_data[0],
6432 nflat_unsigned_receive,
6436 comm_pt->mpi_comm(),
6440 if (nflat_unsigned_send != 0)
6442 MPI_Wait(&request, MPI_STATUS_IGNORE);
6447 unsigned nflat_double_send = flat_double_send_packed_data.size();
6448 MPI_Isend(&nflat_double_send,
6453 comm_pt->mpi_comm(),
6456 unsigned nflat_double_receive = 0;
6457 MPI_Recv(&nflat_double_receive,
6462 comm_pt->mpi_comm(),
6465 MPI_Wait(&request, MPI_STATUS_IGNORE);
6467 if (nflat_double_send != 0)
6469 MPI_Isend(&flat_double_send_packed_data[0],
6474 comm_pt->mpi_comm(),
6478 if (nflat_double_receive != 0)
6480 flat_double_receive_packed_data.resize(nflat_double_receive);
6481 MPI_Recv(&flat_double_receive_packed_data[0],
6482 nflat_double_receive,
6486 comm_pt->mpi_comm(),
6490 if (nflat_double_send != 0)
6492 MPI_Wait(&request, MPI_STATUS_IGNORE);
6497 if (nflat_unsigned_receive != nflat_double_receive)
6499 std::ostringstream error_message;
6500 error_message <<
"The number of unsigned received data ("
6501 << nflat_unsigned_receive <<
") is different from the "
6502 <<
"number\nof double received data ("
6503 << nflat_double_receive <<
")!!!\n\n";
6504 throw OomphLibError(
6505 error_message.str(),
6506 "TriangleMesh::synchronize_boundary_coordinates()",
6507 OOMPH_EXCEPTION_LOCATION);
6514 for (
unsigned iflat_packed = 0; iflat_packed < nflat_unsigned_receive;
6518 const unsigned halo_id =
6519 flat_unsigned_receive_packed_data[iflat_packed];
6521 Vector<double> zeta(1);
6522 zeta[0] = flat_double_receive_packed_data[iflat_packed];
6525 Node* halo_face_node_pt = this->halo_node_pt(ip, halo_id);
6536 halo_face_node_pt->set_coordinates_on_boundary(b, zeta);
6542 for (
unsigned ie = 0; ie < nbound_ele; ie++)
6544 delete tmp_face_ele_pt[ie];
6545 tmp_face_ele_pt[ie] = 0;
6550 if (is_internal_boundary)
6552 re_scale_re_assigned_initial_zeta_values_for_internal_boundary(b);
6562 template<
class ELEMENT>
6572 Vector<FiniteElement*> face_el_pt;
6580 unsigned n_repeated_ele = 0;
6582 const unsigned n_regions = this->nregion();
6585 Vector<std::pair<Node*, Node*>> done_nodes_pt;
6591 for (
unsigned rr = 0; rr < n_regions; rr++)
6593 const unsigned region_id =
6594 static_cast<unsigned>(this->Region_attribute[rr]);
6597 const unsigned nel_in_region =
6598 this->nboundary_element_in_region(b, region_id);
6600 unsigned nel_repetead_in_region = 0;
6604 if (nel_in_region > 0)
6606 bool repeated =
false;
6609 for (
unsigned e = 0; e < nel_in_region; e++)
6613 FiniteElement* bulk_elem_pt =
6614 this->boundary_element_in_region_pt(b, region_id, e);
6617 if (bulk_elem_pt->is_halo())
6625 this->face_index_at_boundary_in_region(b, region_id, e);
6630 FiniteElement* tmp_ele_pt =
6631 new DummyFaceElement<ELEMENT>(bulk_elem_pt, face_index);
6633 const unsigned n_nodes = tmp_ele_pt->nnode();
6635 std::pair<Node*, Node*> tmp_pair = std::make_pair(
6636 tmp_ele_pt->node_pt(0), tmp_ele_pt->node_pt(n_nodes - 1));
6638 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
6639 tmp_ele_pt->node_pt(n_nodes - 1), tmp_ele_pt->node_pt(0));
6642 const unsigned n_done_nodes = done_nodes_pt.size();
6643 for (
unsigned l = 0; l < n_done_nodes; l++)
6645 if (tmp_pair == done_nodes_pt[l] ||
6646 tmp_pair_inverse == done_nodes_pt[l])
6648 nel_repetead_in_region++;
6658 done_nodes_pt.push_back(tmp_pair);
6660 face_el_pt.push_back(tmp_ele_pt);
6674 nele += nel_in_region;
6676 n_repeated_ele += nel_repetead_in_region;
6685 nele = this->nboundary_element(b);
6691 bool repeated =
false;
6694 for (
unsigned e = 0; e < nele; e++)
6698 FiniteElement* bulk_elem_pt = this->boundary_element_pt(b, e);
6701 if (bulk_elem_pt->is_halo())
6709 int face_index = this->face_index_at_boundary(b, e);
6714 FiniteElement* tmp_ele_pt =
6715 new DummyFaceElement<ELEMENT>(bulk_elem_pt, face_index);
6717 const unsigned n_nodes = tmp_ele_pt->nnode();
6719 std::pair<Node*, Node*> tmp_pair = std::make_pair(
6720 tmp_ele_pt->node_pt(0), tmp_ele_pt->node_pt(n_nodes - 1));
6722 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
6723 tmp_ele_pt->node_pt(n_nodes - 1), tmp_ele_pt->node_pt(0));
6726 const unsigned n_done_nodes = done_nodes_pt.size();
6727 for (
unsigned l = 0; l < n_done_nodes; l++)
6729 if (tmp_pair == done_nodes_pt[l] ||
6730 tmp_pair_inverse == done_nodes_pt[l])
6744 done_nodes_pt.push_back(tmp_pair);
6746 face_el_pt.push_back(tmp_ele_pt);
6764 nele -= n_repeated_ele;
6767 if (nele != face_el_pt.size())
6769 std::ostringstream error_message;
6771 <<
"The independet counting of face elements (" << nele <<
") for "
6772 <<
"boundary (" << b <<
") is different\n"
6773 <<
"from the real number of face elements in the container ("
6774 << face_el_pt.size() <<
")\n";
6776 throw OomphLibError(error_message.str(),
6777 "TriangleMesh::re_scale_re_assigned_initial_zeta_"
6778 "values_for_internal_boundary()",
6779 OOMPH_EXCEPTION_LOCATION);
6789 const unsigned nnon_halo_face_elements = face_el_pt.size();
6793 Vector<std::list<FiniteElement*>> segment_sorted_ele_pt;
6796 unsigned nsorted_face_elements = 0;
6799 std::map<FiniteElement*, bool> done_el;
6802 std::map<FiniteElement*, bool> is_inverted;
6805 while (nsorted_face_elements < nnon_halo_face_elements)
6809 std::list<FiniteElement*> sorted_el_pt;
6813 bool found_initial_face_element =
false;
6816 FiniteElement* ele_face_pt = 0;
6819 for (iface = 0; iface < nele; iface++)
6821 ele_face_pt = face_el_pt[iface];
6823 if (!done_el[ele_face_pt])
6826 found_initial_face_element =
true;
6828 nsorted_face_elements++;
6830 sorted_el_pt.push_back(ele_face_pt);
6832 done_el[ele_face_pt] =
true;
6838 if (!found_initial_face_element)
6840 std::ostringstream error_message;
6842 <<
"Could not find an initial face element for the current segment\n";
6844 throw OomphLibError(error_message.str(),
6845 "TriangleMesh::re_scale_re_assigned_initial_zeta_"
6846 "values_for_internal_boundary()",
6847 OOMPH_EXCEPTION_LOCATION);
6852 const unsigned nnod = ele_face_pt->nnode();
6856 Node* left_node_pt = ele_face_pt->node_pt(0);
6857 Node* right_node_pt = ele_face_pt->node_pt(nnod - 1);
6861 bool face_element_added =
false;
6870 for (
unsigned iiface = iface; iiface < nele; iiface++)
6873 face_element_added =
false;
6876 ele_face_pt = face_el_pt[iiface];
6879 if (!(done_el[ele_face_pt]))
6882 Node* local_left_node_pt = ele_face_pt->node_pt(0);
6883 Node* local_right_node_pt = ele_face_pt->node_pt(nnod - 1);
6886 if (left_node_pt == local_right_node_pt)
6888 left_node_pt = local_left_node_pt;
6889 sorted_el_pt.push_front(ele_face_pt);
6890 is_inverted[ele_face_pt] =
false;
6891 face_element_added =
true;
6894 else if (left_node_pt == local_left_node_pt)
6896 left_node_pt = local_right_node_pt;
6897 sorted_el_pt.push_front(ele_face_pt);
6898 is_inverted[ele_face_pt] =
true;
6899 face_element_added =
true;
6902 else if (right_node_pt == local_left_node_pt)
6904 right_node_pt = local_right_node_pt;
6905 sorted_el_pt.push_back(ele_face_pt);
6906 is_inverted[ele_face_pt] =
false;
6907 face_element_added =
true;
6910 else if (right_node_pt == local_right_node_pt)
6912 right_node_pt = local_left_node_pt;
6913 sorted_el_pt.push_back(ele_face_pt);
6914 is_inverted[ele_face_pt] =
true;
6915 face_element_added =
true;
6918 if (face_element_added)
6920 done_el[ele_face_pt] =
true;
6921 nsorted_face_elements++;
6927 }
while (face_element_added &&
6928 (nsorted_face_elements < nnon_halo_face_elements));
6931 segment_sorted_ele_pt.push_back(sorted_el_pt);
6944 Vector<std::set<Node*>> segment_all_nodes_pt;
6947 const unsigned nsegments = segment_sorted_ele_pt.size();
6950 if (nnon_halo_face_elements > 0 && nsegments == 0)
6952 std::ostringstream error_message;
6954 <<
"The number of segments is zero, but the number of nonhalo\n"
6955 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
6956 throw OomphLibError(error_message.str(),
6957 "TriangleMesh::re_scale_re_assigned_initial_zeta_"
6958 "values_for_internal_boundary()",
6959 OOMPH_EXCEPTION_LOCATION);
6964 Vector<double> segment_arclength(nsegments);
6967 Vector<double> initial_zeta_segment(nsegments);
6970 Vector<double> final_zeta_segment(nsegments);
6974 for (
unsigned is = 0; is < nsegments; is++)
6977 if (segment_sorted_ele_pt[is].size() == 0)
6979 std::ostringstream error_message;
6980 error_message <<
"The (" << is <<
")-th segment has no elements\n";
6981 throw OomphLibError(error_message.str(),
6982 "TriangleMesh::re_scale_re_assigned_initial_zeta_"
6983 "values_for_internal_boundary()",
6984 OOMPH_EXCEPTION_LOCATION);
6989 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
6992 const unsigned nnod = first_ele_pt->nnode();
6995 Node* first_node_pt = first_ele_pt->node_pt(0);
6996 if (is_inverted[first_ele_pt])
6998 first_node_pt = first_ele_pt->node_pt(nnod - 1);
7002 FiniteElement* last_ele_pt = segment_sorted_ele_pt[is].back();
7005 Node* last_node_pt = last_ele_pt->node_pt(nnod - 1);
7006 if (is_inverted[last_ele_pt])
7008 last_node_pt = last_ele_pt->node_pt(0);
7012 double x_left = first_node_pt->x(0);
7013 double y_left = first_node_pt->x(1);
7017 Vector<double> zeta(1, 0.0);
7022 if (this->boundary_geom_object_pt(b) != 0)
7024 first_node_pt->get_coordinates_on_boundary(b, zeta);
7025 initial_zeta_segment[is] = zeta[0];
7026 last_node_pt->get_coordinates_on_boundary(b, zeta);
7027 final_zeta_segment[is] = zeta[0];
7031 std::set<Node*> local_nodes_pt;
7032 local_nodes_pt.insert(first_node_pt);
7035 for (std::list<FiniteElement*>::iterator it =
7036 segment_sorted_ele_pt[is].begin();
7037 it != segment_sorted_ele_pt[is].end();
7041 FiniteElement* el_pt = *it;
7046 if (is_inverted[el_pt])
7053 for (
unsigned j = 1; j < nnod; j++)
7055 Node* nod_pt = el_pt->node_pt(k_nod);
7059 double x_right = nod_pt->x(0);
7060 double y_right = nod_pt->x(1);
7063 zeta[0] += sqrt((x_right - x_left) * (x_right - x_left) +
7064 (y_right - y_left) * (y_right - y_left));
7072 local_nodes_pt.insert(nod_pt);
7078 segment_arclength[is] = zeta[0];
7081 segment_all_nodes_pt.push_back(local_nodes_pt);
7093 Boundary_segment_inverted[b].clear();
7094 Boundary_segment_initial_coordinate[b].clear();
7095 Boundary_segment_final_coordinate[b].clear();
7097 Boundary_segment_initial_zeta[b].clear();
7098 Boundary_segment_final_zeta[b].clear();
7100 Boundary_segment_initial_arclength[b].clear();
7101 Boundary_segment_final_arclength[b].clear();
7104 Vector<double> first_node_zeta_coordinate(1, 0.0);
7105 Vector<double> last_node_zeta_coordinate(1, 0.0);
7106 first_node_zeta_coordinate = boundary_initial_zeta_coordinate(b);
7107 last_node_zeta_coordinate = boundary_final_zeta_coordinate(b);
7110 const double boundary_arclength =
7111 std::max(first_node_zeta_coordinate[0], last_node_zeta_coordinate[0]);
7115 for (
unsigned is = 0; is < nsegments; is++)
7118 FiniteElement* first_face_ele_pt = segment_sorted_ele_pt[is].front();
7121 const unsigned nnod = first_face_ele_pt->nnode();
7124 Node* first_node_pt = first_face_ele_pt->node_pt(0);
7125 if (is_inverted[first_face_ele_pt])
7127 first_node_pt = first_face_ele_pt->node_pt(nnod - 1);
7131 Vector<double> zeta_first(1);
7132 first_node_pt->get_coordinates_on_boundary(b, zeta_first);
7135 FiniteElement* last_face_ele_pt = segment_sorted_ele_pt[is].back();
7138 Node* last_node_pt = last_face_ele_pt->node_pt(nnod - 1);
7139 if (is_inverted[last_face_ele_pt])
7141 last_node_pt = last_face_ele_pt->node_pt(0);
7145 Vector<double> zeta_last(1);
7146 last_node_pt->get_coordinates_on_boundary(b, zeta_last);
7150 Vector<double> first_node_coord(2);
7151 Vector<double> last_node_coord(2);
7152 for (
unsigned i = 0; i < 2; i++)
7154 first_node_coord[i] = first_node_pt->x(i);
7155 last_node_coord[i] = last_node_pt->x(i);
7159 Boundary_segment_inverted[b].push_back(0);
7160 Boundary_segment_initial_coordinate[b].push_back(first_node_coord);
7161 Boundary_segment_final_coordinate[b].push_back(last_node_coord);
7164 if (this->boundary_geom_object_pt(b) != 0)
7166 Boundary_segment_initial_zeta[b].push_back(zeta_first[0]);
7167 Boundary_segment_final_zeta[b].push_back(zeta_last[0]);
7172 Boundary_segment_initial_arclength[b].push_back(zeta_first[0] *
7173 boundary_arclength);
7174 Boundary_segment_final_arclength[b].push_back(zeta_last[0] *
7175 boundary_arclength);
7181 for (
unsigned i = 0; i < nele; i++)
7183 delete face_el_pt[i];
7191 #ifdef OOMPH_HAS_TRIANGLE_LIB
7196 template<
class ELEMENT>
7198 const std::string& poly_file_name,
7199 TriangulateIO& triangulate_io,
7200 bool& use_attributes)
7204 std::ifstream poly_file(poly_file_name.c_str(), std::ios_base::in);
7207 throw OomphLibError(
"Error opening .poly file\n",
7208 OOMPH_CURRENT_FUNCTION,
7209 OOMPH_EXCEPTION_LOCATION);
7213 TriangleHelper::initialise_triangulateio(triangulate_io);
7216 poly_file.ignore(80,
'\n');
7219 unsigned invertices;
7220 poly_file >> invertices;
7221 triangulate_io.numberofpoints = invertices;
7224 triangulate_io.pointlist =
7225 (
double*)malloc(triangulate_io.numberofpoints * 2 *
sizeof(
double));
7229 poly_file >> mesh_dim;
7239 throw OomphLibError(
"The dimension must be 2\n",
7240 OOMPH_CURRENT_FUNCTION,
7241 OOMPH_EXCEPTION_LOCATION);
7247 poly_file >> nextras;
7249 triangulate_io.numberofpointattributes = 0;
7250 triangulate_io.pointattributelist = (
double*)NULL;
7253 unsigned nodemarkers;
7254 poly_file >> nodemarkers;
7255 triangulate_io.pointmarkerlist = (
int*)NULL;
7260 if (nextras != 0 || nodemarkers != 0)
7262 oomph_info <<
"===================================================="
7265 oomph_info <<
"Reading the .poly file via oomph_lib \n"
7266 <<
"point's attribute and point's markers \n"
7267 <<
"are automatically set to 0" << std::endl;
7268 oomph_info <<
"===================================================="
7274 unsigned dummy_value;
7275 unsigned count_point = 0;
7276 std::string test_string;
7279 getline(poly_file, test_string,
'#');
7280 poly_file.ignore(80,
'\n');
7284 for (
unsigned count = 0; count < invertices; count++)
7286 poly_file >> dummy_value;
7287 poly_file >> triangulate_io.pointlist[count_point];
7288 poly_file >> triangulate_io.pointlist[count_point + 1];
7289 if (nextras != 0 || nodemarkers != 0)
7291 for (
unsigned j = 0; j < nextras; j++)
7293 poly_file >> dummy_value;
7296 else if (nextras != 0 && nodemarkers != 0)
7298 for (
unsigned j = 0; j < nextras; j++)
7300 poly_file >> dummy_value;
7301 poly_file >> dummy_value;
7305 poly_file.ignore(80,
'\n');
7308 if (poly_file.get() ==
'#')
7310 poly_file.ignore(80,
'\n');
7326 unsigned inelements;
7327 poly_file >> inelements;
7329 unsigned segment_markers;
7330 poly_file >> segment_markers;
7335 if (segment_markers != 1)
7337 std::ostringstream error_stream;
7338 error_stream <<
"The segment marker should be provided \n"
7339 <<
"In order to assign each segment to a boundary \n "
7342 throw OomphLibError(
7343 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
7347 triangulate_io.numberofsegments = inelements;
7348 triangulate_io.segmentlist =
7349 (
int*)malloc(triangulate_io.numberofsegments * 2 *
sizeof(
int));
7350 triangulate_io.segmentmarkerlist =
7351 (
int*)malloc(triangulate_io.numberofsegments *
sizeof(
int));
7354 for (
unsigned i = 0; i < 2 * inelements; i += 2)
7356 poly_file >> dummy_seg;
7357 poly_file >> triangulate_io.segmentlist[i];
7358 poly_file >> triangulate_io.segmentlist[i + 1];
7359 if (segment_markers != 0)
7361 poly_file >> triangulate_io.segmentmarkerlist[i / 2];
7365 poly_file.ignore(80,
'\n');
7370 if (getline(poly_file, test_string,
'#'))
7372 poly_file.ignore(80,
'\n');
7374 unsigned dummy_hole;
7378 triangulate_io.numberofholes = nhole;
7379 triangulate_io.holelist =
7380 (
double*)malloc(triangulate_io.numberofholes * 2 *
sizeof(
double));
7384 for (
unsigned i = 0; i < 2 * nhole; i += 2)
7386 poly_file >> dummy_hole;
7387 poly_file >> triangulate_io.holelist[i];
7388 poly_file >> triangulate_io.holelist[i + 1];
7394 if (getline(poly_file, test_string,
'#'))
7396 poly_file.ignore(80,
'\n');
7398 unsigned dummy_region;
7400 poly_file >> nregion;
7401 std::cerr <<
"Regions: " << nregion << std::endl;
7404 triangulate_io.numberofregions = nregion;
7405 triangulate_io.regionlist =
7406 (
double*)malloc(triangulate_io.numberofregions * 4 *
sizeof(
double));
7411 use_attributes =
true;
7416 for (
unsigned i = 0; i < nregion; i++)
7418 poly_file >> dummy_region;
7419 poly_file >> triangulate_io.regionlist[4 * i];
7420 poly_file >> triangulate_io.regionlist[4 * i + 1];
7421 poly_file >> triangulate_io.regionlist[4 * i + 2];
7422 triangulate_io.regionlist[4 * i + 3] = 0.0;
7429 #ifdef OOMPH_HAS_TRIANGLE_LIB
7430 #ifdef OOMPH_HAS_MPI
7435 template<
class ELEMENT>
7437 std::ostream& dump_file)
7440 if (this->is_mesh_distributed())
7443 const unsigned nboundary = this->nboundary();
7444 dump_file << nboundary <<
" # number of original boundaries" << std::endl;
7447 const unsigned nshared_boundaries = this->nshared_boundaries();
7448 dump_file << nshared_boundaries <<
" # number of shared boundaries"
7452 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
7453 dump_file << init_shd_bnd_id <<
" # initial shared boundaries id"
7456 const unsigned final_shd_bnd_id = this->final_shared_boundary_id();
7457 dump_file << final_shd_bnd_id <<
" # final shared boundaries id"
7461 const unsigned nprocs = this->shared_boundaries_ids().size();
7462 dump_file << nprocs <<
" # number of processors" << std::endl;
7466 for (
unsigned ip = 0; ip < nprocs; ip++)
7468 for (
unsigned jp = 0; jp < nprocs; jp++)
7474 const unsigned nshared_boundaries_iproc_jproc =
7475 this->shared_boundaries_ids(ip, jp).size();
7479 dump_file << nshared_boundaries_iproc_jproc
7480 <<
" # number of shared boundaries with in two "
7481 <<
"processors" << std::endl;
7482 for (
unsigned is = 0; is < nshared_boundaries_iproc_jproc; is++)
7484 const unsigned shared_boundary_id =
7485 this->shared_boundaries_ids(ip, jp, is);
7486 dump_file << ip <<
" " << jp <<
" " << shared_boundary_id
7487 <<
" # ip jp shared_boundary of processors ip and jp"
7500 const unsigned nshared_boundaries_overlap_internal_boundaries =
7501 this->nshared_boundary_overlaps_internal_boundary();
7502 dump_file << nshared_boundaries_overlap_internal_boundaries
7503 <<
" # number of shared boundaries that overlap internal "
7504 <<
"boundaries" << std::endl;
7506 if (nshared_boundaries_overlap_internal_boundaries > 0)
7508 for (
unsigned isb = init_shd_bnd_id; isb < final_shd_bnd_id; isb++)
7512 if (this->shared_boundary_overlaps_internal_boundary(isb))
7516 const unsigned overlapped_internal_boundary =
7517 shared_boundary_overlapping_internal_boundary(isb);
7519 dump_file << isb <<
" " << overlapped_internal_boundary
7520 <<
" # the shared boundary overlaps the internal "
7521 <<
"boundary " << std::endl;
7532 for (
unsigned b = 0; b < nboundary; b++)
7537 if (Assigned_segments_initial_zeta_values[b])
7541 dump_file <<
"1 # assigned boundary coordinates initial zeta values"
7548 Vector<double> initial_coordinates =
7549 this->boundary_initial_coordinate(b);
7551 Vector<double> final_coordinates = this->boundary_final_coordinate(b);
7553 dump_file << std::setprecision(14) << initial_coordinates[0] <<
" "
7554 << initial_coordinates[1]
7555 <<
" # initial coordinates for the current boundary"
7558 dump_file << std::setprecision(14) << final_coordinates[0] <<
" "
7559 << final_coordinates[1]
7560 <<
" # final coordinates for the current boundary"
7567 const unsigned zeta_size =
7568 this->boundary_initial_zeta_coordinate(b).size();
7572 std::ostringstream error_message;
7574 <<
"The dimension for the zeta values container is different\n"
7575 <<
"from 1, the current implementation only supports\n"
7576 <<
"one-dimensioned zeta containers\n\n";
7577 throw OomphLibError(
7578 error_message.str(),
7579 "TriangleMesh::dump_distributed_info_for_restart()",
7580 OOMPH_EXCEPTION_LOCATION);
7584 Vector<double> zeta_initial =
7585 this->boundary_initial_zeta_coordinate(b);
7586 Vector<double> zeta_final = this->boundary_final_zeta_coordinate(b);
7588 dump_file << std::setprecision(14) << zeta_initial[0]
7589 <<
" # initial zeta value for the current boundary"
7592 dump_file << std::setprecision(14) << zeta_final[0]
7593 <<
" # final zeta value for the current boundary"
7597 const unsigned nsegments = this->nboundary_segment(b);
7599 dump_file << b <<
" " << nsegments
7600 <<
" # of segments for the current boundary" << std::endl;
7603 for (
unsigned is = 0; is < nsegments; is++)
7606 Vector<double> initial_segment_coordinates =
7607 this->boundary_segment_initial_coordinate(b)[is];
7608 Vector<double> final_segment_coordinates =
7609 this->boundary_segment_final_coordinate(b)[is];
7612 << std::setprecision(14) << initial_segment_coordinates[0] <<
" "
7613 << initial_segment_coordinates[1]
7614 <<
" # initial segment coordinates for the current boundary"
7617 dump_file << std::setprecision(14) << final_segment_coordinates[0]
7618 <<
" " << final_segment_coordinates[1]
7619 <<
" # final segment coordinates for the current boundary"
7624 if (this->boundary_geom_object_pt(b) != 0)
7626 const double zeta_segment_initial =
7627 this->boundary_segment_initial_zeta(b)[is];
7628 const double zeta_segment_final =
7629 this->boundary_segment_final_zeta(b)[is];
7632 << std::setprecision(14) << zeta_segment_initial
7633 <<
" # initial segment zeta value for the current boundary"
7637 << std::setprecision(14) << zeta_segment_final
7638 <<
" # final segment zeta value for the current boundary"
7643 const double arclength_segment_initial =
7644 this->boundary_segment_initial_arclength(b)[is];
7645 const double arclength_segment_final =
7646 this->boundary_segment_final_arclength(b)[is];
7649 << std::setprecision(14) << arclength_segment_initial
7650 <<
" # initial segment arclength for the current boundary"
7653 dump_file << std::setprecision(14) << arclength_segment_final
7654 <<
" # final segment arclength for the current boundary"
7666 dump_file <<
"0 # assigned boundary coordinates initial zeta values"
7678 template<
class ELEMENT>
7680 std::istream& restart_file)
7683 if (this->is_mesh_distributed())
7686 const unsigned n_boundary = read_unsigned_line_helper(restart_file);
7689 if (n_boundary != this->nboundary())
7691 std::ostringstream error_message;
7693 <<
"The number of boundaries (" << n_boundary <<
") on the "
7694 <<
"file used for restarting is different\nfrom the number of "
7695 <<
"boundaries (" << this->nboundary() <<
") on the current "
7697 throw OomphLibError(error_message.str(),
7698 "TriangleMesh::read_distributed_info_for_restart()",
7699 OOMPH_EXCEPTION_LOCATION);
7704 unsigned n_shared_boundaries = read_unsigned_line_helper(restart_file);
7707 n_shared_boundaries++;
7708 n_shared_boundaries--;
7711 unsigned init_shd_bnd_id = read_unsigned_line_helper(restart_file);
7717 unsigned final_shd_bnd_id = read_unsigned_line_helper(restart_file);
7725 const unsigned n_procs = read_unsigned_line_helper(restart_file);
7728 if (
static_cast<int>(n_procs) != this->communicator_pt()->nproc())
7730 std::ostringstream error_message;
7732 <<
"The number of previously used processors (" << n_procs
7733 <<
") (read from the restart file) is different\nfrom the "
7734 <<
"number of current used processors ("
7735 << this->communicator_pt()->nproc() <<
")\n\n";
7736 throw OomphLibError(error_message.str(),
7737 "TriangleMesh::read_distributed_info_for_restart()",
7738 OOMPH_EXCEPTION_LOCATION);
7743 this->shared_boundaries_ids().clear();
7744 this->shared_boundary_from_processors().clear();
7745 this->shared_boundary_overlaps_internal_boundary().clear();
7749 this->shared_boundaries_ids().resize(n_procs);
7753 for (
unsigned ip = 0; ip < n_procs; ip++)
7757 this->shared_boundaries_ids(ip).resize(n_procs);
7758 for (
unsigned jp = 0; jp < n_procs; jp++)
7764 const unsigned nshared_boundaries_iproc_jproc =
7765 read_unsigned_line_helper(restart_file);
7766 for (
unsigned is = 0; is < nshared_boundaries_iproc_jproc; is++)
7770 restart_file >> tmp_ip;
7772 restart_file >> tmp_jp;
7776 const unsigned shared_boundary_id =
7777 read_unsigned_line_helper(restart_file);
7781 this->shared_boundaries_ids(ip, jp).push_back(shared_boundary_id);
7785 Vector<unsigned> processors(2);
7788 this->shared_boundary_from_processors()[shared_boundary_id] =
7801 const unsigned nshared_boundaries_overlap_internal_boundaries =
7802 read_unsigned_line_helper(restart_file);
7804 for (
unsigned isb = 0;
7805 isb < nshared_boundaries_overlap_internal_boundaries;
7809 unsigned shared_boundary_overlapping;
7810 restart_file >> shared_boundary_overlapping;
7812 const unsigned overlapped_internal_boundary =
7813 read_unsigned_line_helper(restart_file);
7817 this->shared_boundary_overlaps_internal_boundary()
7818 [shared_boundary_overlapping] = overlapped_internal_boundary;
7826 for (
unsigned b = 0; b < n_boundary; b++)
7830 const unsigned boundary_coordinates_initial_zeta_values_assigned =
7831 read_unsigned_line_helper(restart_file);
7833 if (boundary_coordinates_initial_zeta_values_assigned)
7838 Boundary_initial_coordinate[b].clear();
7839 Boundary_final_coordinate[b].clear();
7841 Boundary_initial_zeta_coordinate[b].clear();
7842 Boundary_final_zeta_coordinate[b].clear();
7845 Boundary_segment_inverted[b].clear();
7846 Boundary_segment_initial_coordinate[b].clear();
7847 Boundary_segment_final_coordinate[b].clear();
7849 Boundary_segment_initial_zeta[b].clear();
7850 Boundary_segment_final_zeta[b].clear();
7852 Boundary_segment_initial_arclength[b].clear();
7853 Boundary_segment_final_arclength[b].clear();
7859 Vector<double> initial_coordinates(2);
7862 restart_file >> initial_coordinates[0] >> initial_coordinates[1];
7865 restart_file.ignore(80,
'\n');
7867 Vector<double> final_coordinates(2);
7870 restart_file >> final_coordinates[0] >> final_coordinates[1];
7873 restart_file.ignore(80,
'\n');
7878 this->boundary_initial_coordinate(b) = initial_coordinates;
7879 this->boundary_final_coordinate(b) = final_coordinates;
7882 Vector<double> zeta_initial(1);
7883 restart_file >> zeta_initial[0];
7886 restart_file.ignore(80,
'\n');
7888 Vector<double> zeta_final(1);
7889 restart_file >> zeta_final[0];
7892 restart_file.ignore(80,
'\n');
7895 this->boundary_initial_zeta_coordinate(b) = zeta_initial;
7896 this->boundary_final_zeta_coordinate(b) = zeta_final;
7899 unsigned current_boundary;
7900 restart_file >> current_boundary;
7903 if (current_boundary != b)
7905 std::ostringstream error_message;
7907 <<
"The current boundary id from the restart file ("
7908 << current_boundary <<
") is different from\nthe boundary id "
7909 << b <<
"currently used to re-establish the initial and\nfinal "
7910 <<
"segment's zeta values\n\n";
7911 throw OomphLibError(
7912 error_message.str(),
7913 "TriangleMesh::read_distributed_info_for_restart()",
7914 OOMPH_EXCEPTION_LOCATION);
7920 restart_file >> nsegments;
7923 restart_file.ignore(80,
'\n');
7928 for (
unsigned is = 0; is < nsegments; is++)
7931 Vector<double> initial_segment_coordinates(2);
7934 restart_file >> initial_segment_coordinates[0] >>
7935 initial_segment_coordinates[1];
7938 restart_file.ignore(80,
'\n');
7940 Vector<double> final_segment_coordinates(2);
7943 restart_file >> final_segment_coordinates[0] >>
7944 final_segment_coordinates[1];
7947 restart_file.ignore(80,
'\n');
7950 this->boundary_segment_initial_coordinate(b).push_back(
7951 initial_segment_coordinates);
7952 this->boundary_segment_final_coordinate(b).push_back(
7953 final_segment_coordinates);
7956 if (this->boundary_geom_object_pt(b) != 0)
7958 Vector<double> zeta_segment_initial(1);
7959 restart_file >> zeta_segment_initial[0];
7962 restart_file.ignore(80,
'\n');
7964 Vector<double> zeta_segment_final(1);
7965 restart_file >> zeta_segment_final[0];
7968 restart_file.ignore(80,
'\n');
7971 this->boundary_segment_initial_zeta(b).push_back(
7972 zeta_segment_initial[0]);
7973 this->boundary_segment_final_zeta(b).push_back(
7974 zeta_segment_final[0]);
7978 Vector<double> arclength_segment_initial(1);
7979 restart_file >> arclength_segment_initial[0];
7982 restart_file.ignore(80,
'\n');
7984 Vector<double> arclength_segment_final(1);
7985 restart_file >> arclength_segment_final[0];
7988 restart_file.ignore(80,
'\n');
7991 this->boundary_segment_initial_arclength(b).push_back(
7992 arclength_segment_initial[0]);
7993 this->boundary_segment_final_arclength(b).push_back(
7994 arclength_segment_final[0]);
8013 template<
class ELEMENT>
8015 std::ostream& outfile)
8024 std::set<Node*> boundary_nodes_pt;
8025 const unsigned n_boundary_ele = this->nboundary_element(b);
8026 for (
unsigned e = 0; e < n_boundary_ele; e++)
8029 FiniteElement* bulk_ele_pt = this->boundary_element_pt(b, e);
8030 #ifdef OOMPH_HAS_MPI
8032 if (!bulk_ele_pt->is_halo())
8036 int face_index = this->face_index_at_boundary(b, e);
8038 FiniteElement* face_ele_pt =
8039 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
8042 const unsigned n_nodes = face_ele_pt->nnode();
8043 for (
unsigned i = 0; i < n_nodes; i++)
8046 Node* tmp_node_pt = face_ele_pt->node_pt(i);
8048 boundary_nodes_pt.insert(tmp_node_pt);
8054 #ifdef OOMPH_HAS_MPI
8060 outfile <<
"ZONE T=\"Boundary nodes" << b <<
"\"\n";
8062 std::set<Vector<double>> set_node_coord;
8064 for (std::set<Node*>::iterator it = boundary_nodes_pt.begin();
8065 it != boundary_nodes_pt.end();
8068 Node* inode_pt = (*it);
8071 const unsigned n_dim = inode_pt->ndim();
8072 Vector<double> node_coord(n_dim + 1);
8075 Vector<double> zeta(1);
8076 inode_pt->get_coordinates_on_boundary(b, zeta);
8077 node_coord[0] = zeta[0];
8078 for (
unsigned j = 0; j < n_dim; j++)
8080 node_coord[j + 1] = inode_pt->x(j);
8082 set_node_coord.insert(node_coord);
8085 for (std::set<Vector<double>>::iterator it = set_node_coord.begin();
8086 it != set_node_coord.end();
8090 Vector<double> node_coord = (*it);
8093 const unsigned n_dim = node_coord.size() - 1;
8094 for (
unsigned j = 0; j < n_dim; j++)
8096 outfile << node_coord[j + 1] <<
" ";
8099 outfile <<
"0.0" << std::endl;
8103 outfile <<
"ZONE T=\"Boundary coordinates " << b <<
"\"\n";
8104 for (std::set<Vector<double>>::iterator it = set_node_coord.begin();
8105 it != set_node_coord.end();
8109 Vector<double> node_coord = (*it);
8112 const unsigned n_dim = node_coord.size() - 1;
8113 for (
unsigned j = 0; j < n_dim; j++)
8115 outfile << node_coord[j + 1] <<
" ";
8119 outfile << node_coord[0] << std::endl;
8123 #ifdef OOMPH_HAS_MPI
8130 template<
class ELEMENT>
8132 Vector<TriangleMeshPolygon*>& polygons_pt,
8133 Vector<TriangleMeshOpenCurve*>& open_curves_pt)
8141 const unsigned my_rank = this->communicator_pt()->my_rank();
8155 Vector<TriangleMeshPolyLine*> unsorted_outer_polyline_pt;
8160 Vector<Vector<TriangleMeshPolyLine*>> sorted_outer_curves_pt;
8163 const unsigned nouter = this->Outer_boundary_pt.size();
8164 for (
unsigned i = 0; i < nouter; i++)
8166 const unsigned npolylines = this->Outer_boundary_pt[i]->npolyline();
8167 for (
unsigned p = 0; p < npolylines; p++)
8170 TriangleMeshPolyLine* tmp_polyline_pt =
8171 this->Outer_boundary_pt[i]->polyline_pt(p);
8172 const unsigned nvertex = tmp_polyline_pt->nvertex();
8178 const unsigned bound_id = tmp_polyline_pt->boundary_id();
8179 if (!boundary_was_splitted(bound_id))
8181 unsorted_outer_polyline_pt.push_back(tmp_polyline_pt);
8186 Vector<TriangleMeshPolyLine*> tmp_vector_polylines =
8187 boundary_subpolylines(bound_id);
8188 const unsigned nsub_poly = tmp_vector_polylines.size();
8192 std::ostringstream error_message;
8193 error_message <<
"The boundary (" << bound_id
8194 <<
") was marked to be splitted but\n"
8195 <<
"there are only (" << nsub_poly
8196 <<
") polylines to represent it.\n";
8197 throw OomphLibError(error_message.str(),
8198 OOMPH_CURRENT_FUNCTION,
8199 OOMPH_EXCEPTION_LOCATION);
8204 for (
unsigned isub = 0; isub < nsub_poly; isub++)
8206 unsorted_outer_polyline_pt.push_back(tmp_vector_polylines[isub]);
8208 const unsigned nsvertex = tmp_vector_polylines[isub]->nvertex();
8211 std::ostringstream error_message;
8213 <<
"The current chunk (" << isub <<
") of the polyline with\n"
8214 <<
"boundary id (" << bound_id <<
") has no vertices\n";
8215 throw OomphLibError(error_message.str(),
8216 OOMPH_CURRENT_FUNCTION,
8217 OOMPH_EXCEPTION_LOCATION);
8227 unsigned nunsorted_outer_polyline = unsorted_outer_polyline_pt.size();
8228 if (nunsorted_outer_polyline > 0)
8232 sort_polylines_helper(unsorted_outer_polyline_pt, sorted_outer_curves_pt);
8243 Vector<TriangleMeshPolyLine*> unsorted_internal_closed_polyline_pt;
8248 Vector<Vector<TriangleMeshPolyLine*>> sorted_internal_closed_curves_pt;
8251 const unsigned ninternal_closed = this->Internal_polygon_pt.size();
8252 for (
unsigned i = 0; i < ninternal_closed; i++)
8254 const unsigned npolylines = this->Internal_polygon_pt[i]->npolyline();
8255 for (
unsigned p = 0; p < npolylines; p++)
8258 TriangleMeshPolyLine* tmp_polyline_pt =
8259 this->Internal_polygon_pt[i]->polyline_pt(p);
8260 const unsigned nvertex = tmp_polyline_pt->nvertex();
8266 const unsigned bound_id = tmp_polyline_pt->boundary_id();
8267 if (!boundary_was_splitted(bound_id))
8269 unsorted_internal_closed_polyline_pt.push_back(tmp_polyline_pt);
8274 Vector<TriangleMeshPolyLine*> tmp_vector_polylines =
8275 boundary_subpolylines(bound_id);
8276 const unsigned nsub_poly = tmp_vector_polylines.size();
8280 std::ostringstream error_message;
8281 error_message <<
"The boundary (" << bound_id
8282 <<
") was marked to be splitted but\n"
8283 <<
"there are only (" << nsub_poly
8284 <<
") polylines to represent it.\n";
8285 throw OomphLibError(error_message.str(),
8286 OOMPH_CURRENT_FUNCTION,
8287 OOMPH_EXCEPTION_LOCATION);
8292 for (
unsigned isub = 0; isub < nsub_poly; isub++)
8294 unsorted_internal_closed_polyline_pt.push_back(
8295 tmp_vector_polylines[isub]);
8297 const unsigned nsvertex = tmp_vector_polylines[isub]->nvertex();
8300 std::ostringstream error_message;
8302 <<
"The current chunk (" << isub <<
") of the polyline with\n"
8303 <<
"boundary id (" << bound_id <<
") has no vertices\n";
8304 throw OomphLibError(error_message.str(),
8305 OOMPH_CURRENT_FUNCTION,
8306 OOMPH_EXCEPTION_LOCATION);
8315 const unsigned nunsorted_internal_closed_polyline =
8316 unsorted_internal_closed_polyline_pt.size();
8318 if (nunsorted_internal_closed_polyline > 0)
8322 sort_polylines_helper(unsorted_internal_closed_polyline_pt,
8323 sorted_internal_closed_curves_pt);
8333 Vector<TriangleMeshPolyLine*> unsorted_internal_open_polyline_pt;
8338 Vector<Vector<TriangleMeshPolyLine*>> sorted_internal_open_curves_pt;
8341 const unsigned ninternal_open = this->Internal_open_curve_pt.size();
8342 for (
unsigned i = 0; i < ninternal_open; i++)
8344 const unsigned ncurve_section =
8345 this->Internal_open_curve_pt[i]->ncurve_section();
8346 for (
unsigned p = 0; p < ncurve_section; p++)
8349 TriangleMeshPolyLine* tmp_polyline_pt =
8350 this->Internal_open_curve_pt[i]->polyline_pt(p);
8351 const unsigned nvertex = tmp_polyline_pt->nvertex();
8357 const unsigned bound_id = tmp_polyline_pt->boundary_id();
8358 if (!boundary_was_splitted(bound_id))
8362 if (!boundary_marked_as_shared_boundary(bound_id, 0))
8364 unsorted_internal_open_polyline_pt.push_back(tmp_polyline_pt);
8370 Vector<TriangleMeshPolyLine*> tmp_vector_polylines =
8371 boundary_subpolylines(bound_id);
8372 const unsigned nsub_poly = tmp_vector_polylines.size();
8376 std::ostringstream error_message;
8377 error_message <<
"The boundary (" << bound_id
8378 <<
") was marked to be splitted but\n"
8379 <<
"there are only (" << nsub_poly
8380 <<
") polylines to represent it.\n";
8381 throw OomphLibError(error_message.str(),
8382 OOMPH_CURRENT_FUNCTION,
8383 OOMPH_EXCEPTION_LOCATION);
8388 for (
unsigned isub = 0; isub < nsub_poly; isub++)
8392 if (!boundary_marked_as_shared_boundary(bound_id, isub))
8394 unsorted_internal_open_polyline_pt.push_back(
8395 tmp_vector_polylines[isub]);
8398 const unsigned nsvertex = tmp_vector_polylines[isub]->nvertex();
8401 std::ostringstream error_message;
8403 <<
"The current chunk (" << isub <<
") of the polyline with\n"
8404 <<
"boundary id (" << bound_id <<
") has no vertices\n";
8405 throw OomphLibError(error_message.str(),
8406 OOMPH_CURRENT_FUNCTION,
8407 OOMPH_EXCEPTION_LOCATION);
8416 const unsigned nunsorted_internal_open_polyline =
8417 unsorted_internal_open_polyline_pt.size();
8419 if (nunsorted_internal_open_polyline > 0)
8423 sort_polylines_helper(unsorted_internal_open_polyline_pt,
8424 sorted_internal_open_curves_pt);
8432 Vector<TriangleMeshPolyLine*> unsorted_shared_polyline_pt;
8436 Vector<TriangleMeshPolyLine*> unsorted_shared_to_internal_polyline_pt;
8441 Vector<Vector<TriangleMeshPolyLine*>> sorted_shared_curves_pt;
8444 const unsigned ncurves = nshared_boundary_curves(my_rank);
8445 for (
unsigned i = 0; i < ncurves; i++)
8447 const unsigned npolylines = nshared_boundary_polyline(my_rank, i);
8448 for (
unsigned p = 0; p < npolylines; p++)
8450 const unsigned nvertex =
8451 shared_boundary_polyline_pt(my_rank, i, p)->nvertex();
8454 TriangleMeshPolyLine* tmp_shared_poly_pt =
8455 shared_boundary_polyline_pt(my_rank, i, p);
8459 if (this->nshared_boundary_overlaps_internal_boundary() > 0)
8462 const unsigned shd_bnd_id = tmp_shared_poly_pt->boundary_id();
8466 if (this->shared_boundary_overlaps_internal_boundary(shd_bnd_id))
8468 unsorted_shared_to_internal_polyline_pt.push_back(
8469 tmp_shared_poly_pt);
8472 unsorted_shared_polyline_pt.push_back(tmp_shared_poly_pt);
8478 const unsigned nunsorted_shared_polyline =
8479 unsorted_shared_polyline_pt.size();
8481 if (nunsorted_shared_polyline > 0)
8485 sort_polylines_helper(unsorted_shared_polyline_pt,
8486 sorted_shared_curves_pt);
8496 const unsigned nouter_curves = sorted_outer_curves_pt.size();
8497 const unsigned ninternal_closed_curves =
8498 sorted_internal_closed_curves_pt.size();
8499 const unsigned nshared_curves = sorted_shared_curves_pt.size();
8500 const unsigned ntotal_curves =
8501 nouter_curves + ninternal_closed_curves + nshared_curves;
8504 unsigned counter = 0;
8505 Vector<Vector<TriangleMeshPolyLine*>> all_curves_pt(ntotal_curves);
8509 for (
unsigned i = 0; i < nshared_curves; i++, counter++)
8511 all_curves_pt[counter] = sorted_shared_curves_pt[i];
8515 for (
unsigned i = 0; i < ninternal_closed_curves; i++, counter++)
8517 all_curves_pt[counter] = sorted_internal_closed_curves_pt[i];
8521 for (
unsigned i = 0; i < nouter_curves; i++, counter++)
8523 all_curves_pt[counter] = sorted_outer_curves_pt[i];
8528 this->create_tmp_polygons_helper(all_curves_pt, polygons_pt);
8530 this->create_tmp_open_curves_helper(sorted_internal_open_curves_pt,
8531 unsorted_shared_to_internal_polyline_pt,
8545 this->create_shared_polylines_connections();
8556 Vector<Vector<double>> new_holes_coordinates;
8562 const unsigned n_holes = this->Internal_polygon_pt.size();
8563 for (
unsigned h = 0; h < n_holes; h++)
8565 Vector<double> hole_coordinates =
8566 this->Internal_polygon_pt[h]->internal_point();
8568 if (!hole_coordinates.empty())
8570 new_holes_coordinates.push_back(hole_coordinates);
8576 if (First_time_compute_holes_left_by_halo_elements)
8579 const unsigned n_extra_holes = Extra_holes_coordinates.size();
8580 for (
unsigned h = 0; h < n_extra_holes; h++)
8582 Vector<double> hole_coordinates = Extra_holes_coordinates[h];
8583 new_holes_coordinates.push_back(hole_coordinates);
8587 Original_extra_holes_coordinates = Extra_holes_coordinates;
8590 First_time_compute_holes_left_by_halo_elements =
false;
8597 const unsigned n_original_extra_holes =
8598 Original_extra_holes_coordinates.size();
8599 for (
unsigned h = 0; h < n_original_extra_holes; h++)
8601 Vector<double> hole_coordinates = Original_extra_holes_coordinates[h];
8602 new_holes_coordinates.push_back(hole_coordinates);
8608 compute_holes_left_by_halo_elements_helper(new_holes_coordinates);
8612 update_holes_information_helper(polygons_pt, new_holes_coordinates);
8618 Extra_holes_coordinates = new_holes_coordinates;
8630 template<
class ELEMENT>
8632 Vector<Vector<TriangleMeshPolyLine*>>& polylines_pt,
8633 Vector<TriangleMeshPolygon*>& polygons_pt)
8645 const unsigned ncurves = polylines_pt.size();
8648 const unsigned nunsorted_curves = ncurves;
8650 unsigned nsorted_curves = 0;
8653 std::vector<bool> done_curve(ncurves);
8658 std::list<Vector<TriangleMeshPolyLine*>> list_building_polygon_pt;
8661 bool root_curve_found =
false;
8666 unsigned root_curve_idx = 0;
8669 for (
unsigned ic = 0; ic < ncurves; ic++)
8671 if (!done_curve[ic])
8673 root_curve_idx = ic;
8676 root_curve_found =
true;
8678 done_curve[ic] =
true;
8685 if (!root_curve_found)
8687 std::stringstream err;
8688 err <<
"The root curve to create a polygon from the shared and "
8689 <<
"original boundaries was not found!!!\n";
8690 throw OomphLibError(err.str(),
8691 "TriangleMesh::create_tmp_polygons_helper()",
8692 OOMPH_EXCEPTION_LOCATION);
8697 Vector<TriangleMeshPolyLine*> root_curve_pt =
8698 polylines_pt[root_curve_idx];
8701 list_building_polygon_pt.push_back(root_curve_pt);
8704 Vector<double> root_curve_initial_vertex(2);
8705 Vector<double> root_curve_final_vertex(2);
8708 const unsigned nroot_curve_polyline = root_curve_pt.size();
8710 root_curve_pt[0]->initial_vertex_coordinate(root_curve_initial_vertex);
8711 root_curve_pt[nroot_curve_polyline - 1]->final_vertex_coordinate(
8712 root_curve_final_vertex);
8716 ((root_curve_initial_vertex[0] - root_curve_final_vertex[0]) *
8717 (root_curve_initial_vertex[0] - root_curve_final_vertex[0])) +
8718 ((root_curve_initial_vertex[1] - root_curve_final_vertex[1]) *
8719 (root_curve_initial_vertex[1] - root_curve_final_vertex[1]));
8721 if (diff < ToleranceForVertexMismatchInPolygons::Tolerable_error)
8725 Vector<TriangleMeshCurveSection*> curve_section_pt(
8726 nroot_curve_polyline);
8729 for (
unsigned i = 0; i < nroot_curve_polyline; i++)
8731 curve_section_pt[i] = root_curve_pt[i];
8735 TriangleMeshPolygon* new_polygon_pt =
8736 new TriangleMeshPolygon(curve_section_pt);
8739 this->Free_polygon_pt.insert(new_polygon_pt);
8742 polygons_pt.push_back(new_polygon_pt);
8749 bool added_curve =
false;
8754 bool polygon_created =
false;
8758 added_curve =
false;
8761 for (
unsigned ic = root_curve_idx + 1; ic < ncurves; ic++)
8763 if (!done_curve[ic])
8766 Vector<TriangleMeshPolyLine*> current_curve_pt = polylines_pt[ic];
8770 const unsigned ncurrent_curve_polyline = current_curve_pt.size();
8774 Vector<double> current_curve_initial_vertex(2);
8775 Vector<double> current_curve_final_vertex(2);
8777 current_curve_pt[0]->initial_vertex_coordinate(
8778 current_curve_initial_vertex);
8779 current_curve_pt[ncurrent_curve_polyline - 1]
8780 ->final_vertex_coordinate(current_curve_final_vertex);
8785 diff = ((current_curve_final_vertex[0] -
8786 root_curve_initial_vertex[0]) *
8787 (current_curve_final_vertex[0] -
8788 root_curve_initial_vertex[0])) +
8789 ((current_curve_final_vertex[1] -
8790 root_curve_initial_vertex[1]) *
8791 (current_curve_final_vertex[1] -
8792 root_curve_initial_vertex[1]));
8795 if (diff < ToleranceForVertexMismatchInPolygons::Tolerable_error)
8798 list_building_polygon_pt.push_front(current_curve_pt);
8800 done_curve[ic] =
true;
8802 root_curve_initial_vertex[0] = current_curve_initial_vertex[0];
8803 root_curve_initial_vertex[1] = current_curve_initial_vertex[1];
8811 diff = ((current_curve_initial_vertex[0] -
8812 root_curve_initial_vertex[0]) *
8813 (current_curve_initial_vertex[0] -
8814 root_curve_initial_vertex[0])) +
8815 ((current_curve_initial_vertex[1] -
8816 root_curve_initial_vertex[1]) *
8817 (current_curve_initial_vertex[1] -
8818 root_curve_initial_vertex[1]));
8821 if (diff < ToleranceForVertexMismatchInPolygons::Tolerable_error)
8823 Vector<TriangleMeshPolyLine*> tmp_curve_pt(
8824 ncurrent_curve_polyline);
8826 for (
unsigned it = 0; it < ncurrent_curve_polyline; it++)
8828 current_curve_pt[it]->reverse();
8829 tmp_curve_pt[it] = current_curve_pt[it];
8833 for (
int i = ncurrent_curve_polyline - 1; i >= 0; i--, count++)
8835 current_curve_pt[count] = tmp_curve_pt[i];
8838 list_building_polygon_pt.push_front(current_curve_pt);
8840 done_curve[ic] =
true;
8842 root_curve_initial_vertex[0] = current_curve_final_vertex[0];
8843 root_curve_initial_vertex[1] = current_curve_final_vertex[1];
8851 diff = ((current_curve_initial_vertex[0] -
8852 root_curve_final_vertex[0]) *
8853 (current_curve_initial_vertex[0] -
8854 root_curve_final_vertex[0])) +
8855 ((current_curve_initial_vertex[1] -
8856 root_curve_final_vertex[1]) *
8857 (current_curve_initial_vertex[1] -
8858 root_curve_final_vertex[1]));
8861 if (diff < ToleranceForVertexMismatchInPolygons::Tolerable_error)
8864 list_building_polygon_pt.push_back(current_curve_pt);
8866 done_curve[ic] =
true;
8868 root_curve_final_vertex[0] = current_curve_final_vertex[0];
8869 root_curve_final_vertex[1] = current_curve_final_vertex[1];
8878 ((current_curve_final_vertex[0] - root_curve_final_vertex[0]) *
8879 (current_curve_final_vertex[0] - root_curve_final_vertex[0])) +
8880 ((current_curve_final_vertex[1] - root_curve_final_vertex[1]) *
8881 (current_curve_final_vertex[1] - root_curve_final_vertex[1]));
8884 if (diff < ToleranceForVertexMismatchInPolygons::Tolerable_error)
8886 Vector<TriangleMeshPolyLine*> tmp_curve_pt(
8887 ncurrent_curve_polyline);
8889 for (
unsigned it = 0; it < ncurrent_curve_polyline; it++)
8891 current_curve_pt[it]->reverse();
8892 tmp_curve_pt[it] = current_curve_pt[it];
8896 for (
int i = ncurrent_curve_polyline - 1; i >= 0; i--, count++)
8898 current_curve_pt[count] = tmp_curve_pt[i];
8901 list_building_polygon_pt.push_back(current_curve_pt);
8903 done_curve[ic] =
true;
8905 root_curve_final_vertex[0] = current_curve_initial_vertex[0];
8906 root_curve_final_vertex[1] = current_curve_initial_vertex[1];
8920 ((root_curve_initial_vertex[0] - root_curve_final_vertex[0]) *
8921 (root_curve_initial_vertex[0] - root_curve_final_vertex[0])) +
8922 ((root_curve_initial_vertex[1] - root_curve_final_vertex[1]) *
8923 (root_curve_initial_vertex[1] - root_curve_final_vertex[1]));
8925 if (diff < ToleranceForVertexMismatchInPolygons::Tolerable_error)
8929 added_curve =
false;
8932 polygon_created =
true;
8938 }
while (added_curve);
8941 if (!polygon_created)
8943 std::stringstream error_message;
8945 <<
"It was no possible to create a TriangleMeshPolygon with "
8946 <<
"the input set of curves\n"
8947 <<
"These are the initial and final vertices in the current "
8948 <<
"sorted list of\nTriangleMeshPolyLines\n\n";
8949 Vector<double> init_vertex(2);
8950 Vector<double> final_vertex(2);
8951 unsigned icurve = 0;
8952 for (std::list<Vector<TriangleMeshPolyLine*>>::iterator it =
8953 list_building_polygon_pt.begin();
8954 it != list_building_polygon_pt.end();
8957 const unsigned ncurrent_curve_polyline = (*it).size();
8958 error_message <<
"TriangleMeshCurve #" << icurve <<
"\n"
8959 <<
"-----------------------------------\n";
8960 for (
unsigned ip = 0; ip < ncurrent_curve_polyline; ip++)
8962 Vector<double> init_vertex(2);
8963 Vector<double> final_vertex(2);
8964 (*it)[ip]->initial_vertex_coordinate(init_vertex);
8965 (*it)[ip]->final_vertex_coordinate(final_vertex);
8966 error_message <<
"TriangleMeshPolyLine #" << ip <<
"\n"
8967 <<
"Initial vertex: (" << init_vertex[0] <<
","
8968 << init_vertex[1] <<
")\n"
8969 <<
"Final vertex: (" << final_vertex[0] <<
","
8970 << final_vertex[1] <<
")\n";
8974 throw OomphLibError(error_message.str(),
8975 "TriangleMesh::create_tmp_polygons_helper()",
8976 OOMPH_EXCEPTION_LOCATION);
8982 unsigned ntotal_polylines = 0;
8984 for (std::list<Vector<TriangleMeshPolyLine*>>::iterator it =
8985 list_building_polygon_pt.begin();
8986 it != list_building_polygon_pt.end();
8989 ntotal_polylines += (*it).size();
8993 Vector<TriangleMeshCurveSection*> curve_section_pt(ntotal_polylines);
8996 unsigned counter = 0;
8997 for (std::list<Vector<TriangleMeshPolyLine*>>::iterator it =
8998 list_building_polygon_pt.begin();
8999 it != list_building_polygon_pt.end();
9002 const unsigned ncurrent_curve_polyline = (*it).size();
9003 for (
unsigned ip = 0; ip < ncurrent_curve_polyline; ip++, counter++)
9005 curve_section_pt[counter] = (*it)[ip];
9010 TriangleMeshPolygon* new_polygon_pt =
9011 new TriangleMeshPolygon(curve_section_pt);
9014 this->Free_polygon_pt.insert(new_polygon_pt);
9017 polygons_pt.push_back(new_polygon_pt);
9022 }
while (nsorted_curves < nunsorted_curves);
9030 template<
class ELEMENT>
9032 Vector<Vector<TriangleMeshPolyLine*>>& sorted_open_curves_pt,
9033 Vector<TriangleMeshPolyLine*>& unsorted_shared_to_internal_poly_pt,
9034 Vector<TriangleMeshOpenCurve*>& open_curves_pt)
9038 const unsigned ninternal_open_curves = sorted_open_curves_pt.size();
9042 for (
unsigned i = 0; i < ninternal_open_curves; i++)
9045 const unsigned npoly = sorted_open_curves_pt[i].size();
9046 Vector<TriangleMeshCurveSection*> tmp_curve_section(npoly);
9047 for (
unsigned j = 0; j < npoly; j++)
9049 tmp_curve_section[j] = sorted_open_curves_pt[i][j];
9052 TriangleMeshOpenCurve* new_open_curve_pt =
9053 new TriangleMeshOpenCurve(tmp_curve_section);
9056 this->Free_open_curve_pt.insert(new_open_curve_pt);
9059 open_curves_pt.push_back(new_open_curve_pt);
9070 template<
class ELEMENT>
9072 std::set<FiniteElement*>& element_in_processor_pt,
9073 const int& root_edge_bnd_id,
9074 std::map<std::pair<Node*, Node*>,
bool>& overlapped_face,
9075 std::map<
unsigned, std::map<Node*, bool>>&
9076 node_on_bnd_not_overlapped_by_shd_bnd,
9077 std::list<Node*>& current_polyline_nodes,
9078 std::map<
unsigned, std::list<Node*>>& shared_bnd_id_to_sorted_list_node_pt,
9079 const unsigned& node_degree,
9081 const bool called_from_load_balance)
9084 int flag_to_return = -1;
9093 bool overlapping_internal_boundary =
false;
9095 unsigned internal_overlaping_bnd_id = 0;
9096 if (root_edge_bnd_id != -1)
9099 overlapping_internal_boundary =
true;
9101 internal_overlaping_bnd_id =
static_cast<unsigned>(root_edge_bnd_id);
9109 if (new_node_pt->is_on_boundary())
9112 bool is_node_living_in_non_overlapped_boundary =
false;
9116 const unsigned noriginal_bnd = this->initial_shared_boundary_id();
9117 for (
unsigned bb = 0; bb < noriginal_bnd; bb++)
9125 if (overlapping_internal_boundary)
9128 if (new_node_pt->is_on_boundary(bb))
9134 const bool on_bnd_edge_not_overlapped_by_shd_bnd =
9135 node_on_bnd_not_overlapped_by_shd_bnd[bb][new_node_pt];
9136 if (bb != internal_overlaping_bnd_id ||
9137 ((bb == internal_overlaping_bnd_id) &&
9138 (on_bnd_edge_not_overlapped_by_shd_bnd)))
9141 if (bb != internal_overlaping_bnd_id)
9143 is_node_living_in_non_overlapped_boundary =
true;
9153 const unsigned n_bound_ele = this->nboundary_element(bb);
9154 if (n_bound_ele > 0)
9158 for (
unsigned e = 0; e < n_bound_ele; e++)
9161 FiniteElement* bulk_ele_pt = this->boundary_element_pt(bb, e);
9164 std::set<FiniteElement*>::iterator it =
9165 element_in_processor_pt.find(bulk_ele_pt);
9167 if (it != element_in_processor_pt.end())
9170 bool found_node =
false;
9172 int face_index = this->face_index_at_boundary(bb, e);
9174 FiniteElement* face_ele_pt =
9175 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
9177 const unsigned n_node_face = face_ele_pt->nnode();
9179 Node* first_node_pt = face_ele_pt->node_pt(0);
9180 Node* last_node_pt = face_ele_pt->node_pt(n_node_face - 1);
9182 std::pair<Node*, Node*> tmp_edge =
9183 std::make_pair(first_node_pt, last_node_pt);
9187 if (!overlapped_face[tmp_edge])
9190 for (
unsigned n = 0; n < n_node_face; n++)
9193 if (face_ele_pt->node_pt(n) == new_node_pt)
9209 flag_to_return = bb;
9210 return flag_to_return;
9229 if (new_node_pt->is_on_boundary(bb))
9238 const unsigned n_bound_ele = this->nboundary_element(bb);
9239 if (n_bound_ele > 0)
9243 for (
unsigned e = 0; e < n_bound_ele; e++)
9246 FiniteElement* bulk_ele_pt = this->boundary_element_pt(bb, e);
9249 std::set<FiniteElement*>::iterator it =
9250 element_in_processor_pt.find(bulk_ele_pt);
9252 if (it != element_in_processor_pt.end())
9255 bool found_node =
false;
9257 int face_index = this->face_index_at_boundary(bb, e);
9259 FiniteElement* face_ele_pt =
9260 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
9262 const unsigned n_node_face = face_ele_pt->nnode();
9264 Node* first_node_pt = face_ele_pt->node_pt(0);
9265 Node* last_node_pt = face_ele_pt->node_pt(n_node_face - 1);
9267 std::pair<Node*, Node*> tmp_edge =
9268 std::make_pair(first_node_pt, last_node_pt);
9272 if (!overlapped_face[tmp_edge])
9275 for (
unsigned n = 0; n < n_node_face; n++)
9278 if (face_ele_pt->node_pt(n) == new_node_pt)
9294 flag_to_return = bb;
9295 return flag_to_return;
9320 if (!overlapping_internal_boundary)
9325 flag_to_return = -3;
9332 if (is_node_living_in_non_overlapped_boundary)
9334 flag_to_return = -3;
9343 if (flag_to_return >= 0)
9345 return flag_to_return;
9356 Vector<unsigned> candidate_shared_bnd_to_connect;
9358 for (std::map<
unsigned, std::list<Node*>>::iterator it =
9359 shared_bnd_id_to_sorted_list_node_pt.begin();
9360 it != shared_bnd_id_to_sorted_list_node_pt.end();
9366 const unsigned i_bnd_id = (*it).first;
9369 std::list<Node*>::iterator it_list = (*it).second.begin();
9371 const unsigned n_nodes = (*it).second.size();
9373 for (
unsigned i = 0; i < n_nodes; i++, it_list++)
9376 if ((*it_list) == new_node_pt)
9380 candidate_shared_bnd_to_connect.push_back(i_bnd_id);
9391 const unsigned n_candidate_shared_bnd_to_connect =
9392 candidate_shared_bnd_to_connect.size();
9395 if (n_candidate_shared_bnd_to_connect > 0)
9402 if (called_from_load_balance)
9404 return candidate_shared_bnd_to_connect[0];
9414 Vector<unsigned> shared_bound_in_this_proc;
9417 shared_boundaries_in_this_processor(shared_bound_in_this_proc);
9423 const unsigned n_shared_bound_in_this_proc =
9424 shared_bound_in_this_proc.size();
9427 for (
unsigned i = 0; i < n_candidate_shared_bnd_to_connect; i++)
9430 const unsigned i_candidate_shared_bnd =
9431 candidate_shared_bnd_to_connect[i];
9434 for (
unsigned j = 0; j < n_shared_bound_in_this_proc; j++)
9437 if (i_candidate_shared_bnd == shared_bound_in_this_proc[j])
9440 flag_to_return = i_candidate_shared_bnd;
9441 return flag_to_return;
9452 flag_to_return = -3;
9458 if (flag_to_return >= 0)
9460 return flag_to_return;
9469 unsigned nrepeated = 0;
9470 for (std::list<Node*>::iterator it_list = current_polyline_nodes.begin();
9471 it_list != current_polyline_nodes.end();
9476 if ((*it_list) == new_node_pt)
9488 flag_to_return = -2;
9494 if (node_degree > 2)
9496 flag_to_return = -3;
9500 return flag_to_return;
9510 template<
class ELEMENT>
9514 const unsigned my_rank = this->communicator_pt()->my_rank();
9517 Vector<Vector<TriangleMeshPolyLine*>> shared_curves_pt =
9518 this->Shared_boundary_polyline_pt[my_rank];
9522 const unsigned ncurves = shared_curves_pt.size();
9523 for (
unsigned icurve = 0; icurve < ncurves; icurve++)
9526 const unsigned npoly = shared_curves_pt[icurve].size();
9527 for (
unsigned ipoly = 0; ipoly < npoly; ipoly++)
9530 TriangleMeshPolyLine* shd_poly_pt = shared_curves_pt[icurve][ipoly];
9533 const unsigned bound_id = shd_poly_pt->boundary_id();
9536 const bool is_connected_to_the_left =
9537 shd_poly_pt->is_initial_vertex_connected();
9540 const bool is_connected_to_the_right =
9541 shd_poly_pt->is_final_vertex_connected();
9546 if (is_connected_to_the_left || is_connected_to_the_right)
9550 const unsigned n_vertex = shd_poly_pt->nvertex();
9557 if (is_connected_to_the_left)
9561 const unsigned uconnection_to_the_left =
9562 shd_poly_pt->initial_vertex_connected_bnd_id();
9565 TriangleMeshPolyLine* poly_to_connect_pt = 0;
9569 bool connecting_to_an_split_boundary =
false;
9573 bool connecting_to_an_overlaped_boundary =
false;
9576 if (uconnection_to_the_left == bound_id)
9579 poly_to_connect_pt = shd_poly_pt;
9584 const unsigned initial_shd_bnd_id = initial_shared_boundary_id();
9586 if (uconnection_to_the_left >= initial_shd_bnd_id)
9590 poly_to_connect_pt =
9591 boundary_polyline_pt(uconnection_to_the_left);
9599 if (boundary_was_splitted(uconnection_to_the_left))
9601 connecting_to_an_split_boundary =
true;
9611 if (connecting_to_an_split_boundary)
9615 const unsigned n_sub_poly =
9616 nboundary_subpolylines(uconnection_to_the_left);
9621 for (
unsigned ii = 0; ii < n_sub_poly; ii++)
9623 if (boundary_marked_as_shared_boundary(
9624 uconnection_to_the_left, ii))
9628 connecting_to_an_overlaped_boundary =
true;
9639 if (boundary_marked_as_shared_boundary(
9640 uconnection_to_the_left, 0))
9644 connecting_to_an_overlaped_boundary =
true;
9651 if (!(connecting_to_an_split_boundary ||
9652 connecting_to_an_overlaped_boundary))
9656 poly_to_connect_pt =
9657 boundary_polyline_pt(uconnection_to_the_left);
9668 if (!connecting_to_an_split_boundary)
9670 if (boundary_was_splitted(uconnection_to_the_left))
9672 std::stringstream error;
9674 <<
"The current shared boundary (" << bound_id <<
") was "
9675 <<
"marked to have a connection\nto the left with the "
9676 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9677 <<
"The problem is that the destination boundary (possibly\n"
9678 <<
"another shared boundary) is marked to be split\n"
9679 <<
"There should not be split shared boundaries\n\n";
9680 throw OomphLibError(
9682 "TriangleMesh::create_shared_polylines_connections()",
9683 OOMPH_EXCEPTION_LOCATION);
9696 Vector<double> shd_bnd_left_vertex =
9697 shd_poly_pt->vertex_coordinate(0);
9700 if (!connecting_to_an_split_boundary)
9704 if (!connecting_to_an_overlaped_boundary)
9708 unsigned vertex_index = 0;
9710 const bool found_vertex_index =
9711 get_connected_vertex_number_on_destination_polyline(
9712 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9716 if (!found_vertex_index)
9718 std::stringstream error;
9720 <<
"The current shared boundary (" << bound_id <<
") was "
9721 <<
"marked to have a connection\nto the left with the "
9722 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9723 <<
"The problem is that the left vertex of the current\n"
9724 <<
"shared boundary is not in the list of vertices of the\n"
9725 <<
"boundary to connect.\n\n"
9726 <<
"This is the left vertex of the current shared "
9728 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", "
9729 << shd_bnd_left_vertex[1] <<
")\n\n"
9730 <<
"This is the list of vertices on the destination "
9732 const unsigned n_v = poly_to_connect_pt->nvertex();
9733 for (
unsigned i = 0; i < n_v; i++)
9735 Vector<double> cvertex =
9736 poly_to_connect_pt->vertex_coordinate(i);
9737 error <<
"Vertex #" << i <<
": (" << cvertex[0] <<
", "
9738 << cvertex[1] <<
")\n";
9740 throw OomphLibError(
9742 "TriangleMesh::create_shared_polylines_connections()",
9743 OOMPH_EXCEPTION_LOCATION);
9749 shd_poly_pt->connect_initial_vertex_to_polyline(
9750 poly_to_connect_pt, vertex_index);
9760 unsigned vertex_index = 0;
9762 bool found_vertex_index =
false;
9766 Vector<unsigned> dst_shd_bnd_ids;
9767 get_shared_boundaries_overlapping_internal_boundary(
9768 uconnection_to_the_left, dst_shd_bnd_ids);
9772 const unsigned n_shd_bnd_overlap_int_bnd =
9773 dst_shd_bnd_ids.size();
9777 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
9780 const unsigned new_connection_to_the_left =
9781 dst_shd_bnd_ids[ss];
9785 poly_to_connect_pt =
9786 boundary_polyline_pt(new_connection_to_the_left);
9788 if (poly_to_connect_pt != 0)
9792 found_vertex_index =
9793 get_connected_vertex_number_on_destination_polyline(
9794 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9799 if (found_vertex_index)
9809 if (!found_vertex_index)
9811 std::stringstream error;
9813 <<
"The current shared boundary (" << bound_id <<
") was "
9814 <<
"marked to have a connection\nto the left with the "
9815 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9816 <<
"This last boundary is marked to be overlaped by "
9817 <<
"shared boundaries\n"
9818 <<
"The problem is that the left vertex of the current\n"
9819 <<
"shared boundary is not in the list of vertices of the\n"
9820 <<
"boundary to connect.\n\n"
9821 <<
"This is the left vertex of the current shared "
9823 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", "
9824 << shd_bnd_left_vertex[1] <<
")\n\n"
9825 <<
"This is the list of vertices on the destination "
9827 Vector<unsigned> dst_shd_bnd_ids;
9828 get_shared_boundaries_overlapping_internal_boundary(
9829 uconnection_to_the_left, dst_shd_bnd_ids);
9830 const unsigned n_shd_bnd_overlap_int_bnd =
9831 dst_shd_bnd_ids.size();
9832 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
9834 const unsigned new_connection_to_the_left =
9835 dst_shd_bnd_ids[ss];
9836 poly_to_connect_pt =
9837 boundary_polyline_pt(new_connection_to_the_left);
9838 if (poly_to_connect_pt != 0)
9840 const unsigned shd_bnd_id_overlap =
9841 poly_to_connect_pt->boundary_id();
9842 error <<
"Shared boundary id(" << shd_bnd_id_overlap
9844 const unsigned n_v = poly_to_connect_pt->nvertex();
9845 for (
unsigned i = 0; i < n_v; i++)
9847 Vector<double> cvertex =
9848 poly_to_connect_pt->vertex_coordinate(i);
9849 error <<
"Vertex #" << i <<
": (" << cvertex[0] <<
", "
9850 << cvertex[1] <<
")\n";
9855 throw OomphLibError(
9857 "TriangleMesh::create_shared_polylines_connections()",
9858 OOMPH_EXCEPTION_LOCATION);
9866 shd_poly_pt->connect_initial_vertex_to_polyline(
9867 poly_to_connect_pt, vertex_index);
9878 Vector<TriangleMeshPolyLine*> tmp_vector_subpolylines =
9879 boundary_subpolylines(uconnection_to_the_left);
9882 const unsigned nsub_poly = tmp_vector_subpolylines.size();
9886 std::ostringstream error_message;
9888 <<
"The boundary (" << uconnection_to_the_left <<
") was "
9889 <<
"marked to be splitted but\n"
9890 <<
"there are only (" << nsub_poly <<
") polylines to "
9891 <<
"represent it.\n";
9892 throw OomphLibError(
9893 error_message.str(),
9894 "TriangleMesh::create_shared_polylines_connections()",
9895 OOMPH_EXCEPTION_LOCATION);
9907 if (!connecting_to_an_overlaped_boundary)
9913 unsigned vertex_index = 0;
9915 unsigned sub_poly_to_connect = 0;
9917 bool found_vertex_index =
false;
9921 for (
unsigned isub = 0; isub < nsub_poly; isub++)
9924 poly_to_connect_pt = tmp_vector_subpolylines[isub];
9926 found_vertex_index =
9927 get_connected_vertex_number_on_destination_polyline(
9928 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9931 if (found_vertex_index)
9935 sub_poly_to_connect = isub;
9943 if (!found_vertex_index)
9945 std::stringstream error;
9947 <<
"The current shared boundary (" << bound_id <<
") was "
9948 <<
"marked to have a connection\nto the left with the "
9949 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9950 <<
"The problem is that the left vertex of the current\n"
9951 <<
"shared boundary is not in the list of vertices of any\n"
9952 <<
"of the sub polylines that represent the boundary to\n"
9954 <<
"This is the left vertex of the current shared "
9956 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", "
9957 << shd_bnd_left_vertex[1] <<
")\n\n"
9958 <<
"This is the list of vertices on the destination "
9960 for (
unsigned p = 0; p < nsub_poly; p++)
9962 error <<
"Subpolyline #(" << p <<
")\n";
9963 poly_to_connect_pt = tmp_vector_subpolylines[p];
9964 const unsigned n_v = poly_to_connect_pt->nvertex();
9965 for (
unsigned i = 0; i < n_v; i++)
9967 Vector<double> cvertex =
9968 poly_to_connect_pt->vertex_coordinate(i);
9969 error <<
"Vertex #" << i <<
": (" << cvertex[0] <<
", "
9970 << cvertex[1] <<
")\n";
9973 throw OomphLibError(
9975 "TriangleMesh::create_shared_polylines_connections()",
9976 OOMPH_EXCEPTION_LOCATION);
9984 shd_poly_pt->connect_initial_vertex_to_polyline(
9985 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
9996 unsigned vertex_index = 0;
9998 unsigned sub_poly_to_connect = 0;
10000 bool found_vertex_index =
false;
10004 Vector<unsigned> dst_shd_bnd_ids;
10005 get_shared_boundaries_overlapping_internal_boundary(
10006 uconnection_to_the_left, dst_shd_bnd_ids);
10010 const unsigned n_shd_bnd_overlap_int_bnd =
10011 dst_shd_bnd_ids.size();
10015 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10018 const unsigned new_connection_to_the_left =
10019 dst_shd_bnd_ids[ss];
10023 if (bound_id != new_connection_to_the_left)
10027 poly_to_connect_pt =
10028 boundary_polyline_pt(new_connection_to_the_left);
10030 if (poly_to_connect_pt != 0)
10034 found_vertex_index =
10035 get_connected_vertex_number_on_destination_polyline(
10036 poly_to_connect_pt,
10037 shd_bnd_left_vertex,
10043 if (found_vertex_index)
10055 if (!found_vertex_index)
10059 for (
unsigned isub = 0; isub < nsub_poly; isub++)
10063 if (!boundary_marked_as_shared_boundary(
10064 uconnection_to_the_left, isub))
10067 poly_to_connect_pt = tmp_vector_subpolylines[isub];
10069 found_vertex_index =
10070 get_connected_vertex_number_on_destination_polyline(
10071 poly_to_connect_pt,
10072 shd_bnd_left_vertex,
10076 if (found_vertex_index)
10080 sub_poly_to_connect = isub;
10093 if (!found_vertex_index)
10095 std::stringstream error;
10097 <<
"The current shared boundary (" << bound_id <<
") was "
10098 <<
"marked to have a connection\nto the left with the "
10099 <<
"boundary (" << uconnection_to_the_left <<
").\n"
10100 <<
"This last boundary is marked to be overlaped by "
10101 <<
"shared boundaries\n"
10102 <<
"The problem is that the left vertex of the current\n"
10103 <<
"shared boundary is not in the list of vertices of "
10104 <<
"the\nboundary to connect.\n\n"
10105 <<
"This is the left vertex of the current shared "
10107 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", "
10108 << shd_bnd_left_vertex[1] <<
")\n\n"
10109 <<
"This is the list of vertices on the destination "
10110 <<
"boundary (only those subpolylines not marked as "
10111 <<
"overlaped by\nshared boundaries)\n";
10112 for (
unsigned p = 0; p < nsub_poly; p++)
10114 if (!boundary_marked_as_shared_boundary(
10115 uconnection_to_the_left, p))
10117 error <<
"Subpolyline #(" << p <<
")\n";
10118 poly_to_connect_pt = tmp_vector_subpolylines[p];
10119 const unsigned n_v = poly_to_connect_pt->nvertex();
10120 for (
unsigned i = 0; i < n_v; i++)
10122 Vector<double> cvertex =
10123 poly_to_connect_pt->vertex_coordinate(i);
10124 error <<
"Vertex #" << i <<
": (" << cvertex[0] <<
", "
10125 << cvertex[1] <<
")\n";
10129 error <<
"\nThis is the list of vertices of the shared "
10130 <<
"polylines that overlap\nthe internal "
10132 Vector<unsigned> dst_shd_bnd_ids;
10133 get_shared_boundaries_overlapping_internal_boundary(
10134 uconnection_to_the_left, dst_shd_bnd_ids);
10135 const unsigned n_shd_bnd_overlap_int_bnd =
10136 dst_shd_bnd_ids.size();
10137 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10139 const unsigned new_connection_to_the_left =
10140 dst_shd_bnd_ids[ss];
10141 poly_to_connect_pt =
10142 boundary_polyline_pt(new_connection_to_the_left);
10143 if (poly_to_connect_pt != 0)
10145 const unsigned shd_bnd_id_overlap =
10146 poly_to_connect_pt->boundary_id();
10147 error <<
"Shared boundary id(" << shd_bnd_id_overlap
10149 const unsigned n_v = poly_to_connect_pt->nvertex();
10150 for (
unsigned i = 0; i < n_v; i++)
10152 Vector<double> cvertex =
10153 poly_to_connect_pt->vertex_coordinate(i);
10154 error <<
"Vertex #" << i <<
": (" << cvertex[0] <<
", "
10155 << cvertex[1] <<
")\n";
10160 throw OomphLibError(
10162 "TriangleMesh::create_shared_polylines_connections()",
10163 OOMPH_EXCEPTION_LOCATION);
10171 shd_poly_pt->connect_initial_vertex_to_polyline(
10172 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
10182 if (is_connected_to_the_right)
10186 const unsigned uconnection_to_the_right =
10187 shd_poly_pt->final_vertex_connected_bnd_id();
10190 TriangleMeshPolyLine* poly_to_connect_pt = 0;
10194 bool connecting_to_an_split_boundary =
false;
10198 bool connecting_to_an_overlaped_boundary =
false;
10201 if (uconnection_to_the_right == bound_id)
10204 poly_to_connect_pt = shd_poly_pt;
10209 const unsigned initial_shd_bnd_id = initial_shared_boundary_id();
10211 if (uconnection_to_the_right >= initial_shd_bnd_id)
10215 poly_to_connect_pt =
10216 boundary_polyline_pt(uconnection_to_the_right);
10224 if (boundary_was_splitted(uconnection_to_the_right))
10226 connecting_to_an_split_boundary =
true;
10236 if (connecting_to_an_split_boundary)
10240 const unsigned n_sub_poly =
10241 nboundary_subpolylines(uconnection_to_the_right);
10246 for (
unsigned ii = 0; ii < n_sub_poly; ii++)
10248 if (boundary_marked_as_shared_boundary(
10249 uconnection_to_the_right, ii))
10253 connecting_to_an_overlaped_boundary =
true;
10264 if (boundary_marked_as_shared_boundary(
10265 uconnection_to_the_right, 0))
10269 connecting_to_an_overlaped_boundary =
true;
10276 if (!(connecting_to_an_split_boundary ||
10277 connecting_to_an_overlaped_boundary))
10281 poly_to_connect_pt =
10282 boundary_polyline_pt(uconnection_to_the_right);
10293 if (!connecting_to_an_split_boundary)
10295 if (boundary_was_splitted(uconnection_to_the_right))
10297 std::stringstream error;
10299 <<
"The current shared boundary (" << bound_id <<
") was "
10300 <<
"marked to have a connection\nto the right with the "
10301 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10302 <<
"The problem is that the destination boundary (possibly\n"
10303 <<
"another shared boundary) is marked to be split\n"
10304 <<
"There should not be split shared boundaries\n\n";
10305 throw OomphLibError(
10307 "TriangleMesh::create_shared_polylines_connections()",
10308 OOMPH_EXCEPTION_LOCATION);
10321 Vector<double> shd_bnd_right_vertex =
10322 shd_poly_pt->vertex_coordinate(n_vertex - 1);
10326 if (!connecting_to_an_split_boundary)
10330 if (!connecting_to_an_overlaped_boundary)
10335 unsigned vertex_index = 0;
10336 const bool found_vertex_index =
10337 get_connected_vertex_number_on_destination_polyline(
10338 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10342 if (!found_vertex_index)
10344 std::stringstream error;
10346 <<
"The current shared boundary (" << bound_id <<
") was "
10347 <<
"marked to have a connection\nto the right with the "
10348 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10349 <<
"The problem is that the right vertex of the current\n"
10350 <<
"shared boundary is not in the list of vertices of the\n"
10351 <<
"boundary to connect.\n\n"
10352 <<
"This is the right vertex of the current shared "
10354 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", "
10355 << shd_bnd_right_vertex[1] <<
")\n\n"
10356 <<
"This is the list of vertices on the destination "
10358 const unsigned n_v = poly_to_connect_pt->nvertex();
10359 for (
unsigned i = 0; i < n_v; i++)
10361 Vector<double> cvertex =
10362 poly_to_connect_pt->vertex_coordinate(i);
10363 error <<
"Vertex #" << i <<
": (" << cvertex[0] <<
", "
10364 << cvertex[1] <<
")\n";
10366 throw OomphLibError(
10368 "TriangleMesh::create_shared_polylines_connections()",
10369 OOMPH_EXCEPTION_LOCATION);
10375 shd_poly_pt->connect_final_vertex_to_polyline(
10376 poly_to_connect_pt, vertex_index);
10386 unsigned vertex_index = 0;
10388 bool found_vertex_index =
false;
10392 Vector<unsigned> dst_shd_bnd_ids;
10393 get_shared_boundaries_overlapping_internal_boundary(
10394 uconnection_to_the_right, dst_shd_bnd_ids);
10398 const unsigned n_shd_bnd_overlap_int_bnd =
10399 dst_shd_bnd_ids.size();
10403 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10406 const unsigned new_connection_to_the_right =
10407 dst_shd_bnd_ids[ss];
10411 poly_to_connect_pt =
10412 boundary_polyline_pt(new_connection_to_the_right);
10414 if (poly_to_connect_pt != 0)
10418 found_vertex_index =
10419 get_connected_vertex_number_on_destination_polyline(
10420 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10425 if (found_vertex_index)
10435 if (!found_vertex_index)
10437 std::stringstream error;
10439 <<
"The current shared boundary (" << bound_id <<
") was "
10440 <<
"marked to have a connection\nto the right with the "
10441 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10442 <<
"This last boundary is marked to be overlaped by "
10443 <<
"shared boundaries\n"
10444 <<
"The problem is that the right vertex of the current\n"
10445 <<
"shared boundary is not in the list of vertices of the\n"
10446 <<
"boundary to connect.\n\n"
10447 <<
"This is the right vertex of the current shared "
10449 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", "
10450 << shd_bnd_right_vertex[1] <<
")\n\n"
10451 <<
"This is the list of vertices on the destination "
10453 Vector<unsigned> dst_shd_bnd_ids;
10454 get_shared_boundaries_overlapping_internal_boundary(
10455 uconnection_to_the_right, dst_shd_bnd_ids);
10456 const unsigned n_shd_bnd_overlap_int_bnd =
10457 dst_shd_bnd_ids.size();
10458 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10460 const unsigned new_connection_to_the_right =
10461 dst_shd_bnd_ids[ss];
10462 poly_to_connect_pt =
10463 boundary_polyline_pt(new_connection_to_the_right);
10464 if (poly_to_connect_pt != 0)
10466 const unsigned shd_bnd_id_overlap =
10467 poly_to_connect_pt->boundary_id();
10468 error <<
"Shared boundary id(" << shd_bnd_id_overlap
10470 const unsigned n_v = poly_to_connect_pt->nvertex();
10471 for (
unsigned i = 0; i < n_v; i++)
10473 Vector<double> cvertex =
10474 poly_to_connect_pt->vertex_coordinate(i);
10475 error <<
"Vertex #" << i <<
": (" << cvertex[0] <<
", "
10476 << cvertex[1] <<
")\n";
10481 throw OomphLibError(
10483 "TriangleMesh::create_shared_polylines_connections()",
10484 OOMPH_EXCEPTION_LOCATION);
10492 shd_poly_pt->connect_final_vertex_to_polyline(
10493 poly_to_connect_pt, vertex_index);
10504 Vector<TriangleMeshPolyLine*> tmp_vector_subpolylines =
10505 boundary_subpolylines(uconnection_to_the_right);
10508 const unsigned nsub_poly = tmp_vector_subpolylines.size();
10510 if (nsub_poly <= 1)
10512 std::ostringstream error_message;
10514 <<
"The boundary (" << uconnection_to_the_right <<
") was "
10515 <<
"marked to be splitted but\n"
10516 <<
"there are only (" << nsub_poly <<
") polylines to "
10517 <<
"represent it.\n";
10518 throw OomphLibError(
10519 error_message.str(),
10520 "TriangleMesh::create_shared_polylines_connections()",
10521 OOMPH_EXCEPTION_LOCATION);
10534 if (!connecting_to_an_overlaped_boundary)
10540 unsigned vertex_index = 0;
10542 unsigned sub_poly_to_connect = 0;
10544 bool found_vertex_index =
false;
10548 for (
unsigned isub = 0; isub < nsub_poly; isub++)
10551 poly_to_connect_pt = tmp_vector_subpolylines[isub];
10553 found_vertex_index =
10554 get_connected_vertex_number_on_destination_polyline(
10555 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10558 if (found_vertex_index)
10562 sub_poly_to_connect = isub;
10570 if (!found_vertex_index)
10572 std::stringstream error;
10574 <<
"The current shared boundary (" << bound_id <<
") was "
10575 <<
"marked to have a connection\nto the right with the "
10576 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10577 <<
"The problem is that the right vertex of the current\n"
10578 <<
"shared boundary is not in the list of vertices of any\n"
10579 <<
"of the sub polylines that represent the boundary to\n"
10581 <<
"This is the right vertex of the current shared "
10583 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", "
10584 << shd_bnd_right_vertex[1] <<
")\n\n"
10585 <<
"This is the list of vertices on the destination "
10587 for (
unsigned p = 0; p < nsub_poly; p++)
10589 error <<
"Subpolyline #(" << p <<
")\n";
10590 poly_to_connect_pt = tmp_vector_subpolylines[p];
10591 const unsigned n_v = poly_to_connect_pt->nvertex();
10592 for (
unsigned i = 0; i < n_v; i++)
10594 Vector<double> cvertex =
10595 poly_to_connect_pt->vertex_coordinate(i);
10596 error <<
"Vertex #" << i <<
": (" << cvertex[0] <<
", "
10597 << cvertex[1] <<
")\n";
10600 throw OomphLibError(
10602 "TriangleMesh::create_shared_polylines_connections()",
10603 OOMPH_EXCEPTION_LOCATION);
10611 shd_poly_pt->connect_final_vertex_to_polyline(
10612 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
10623 unsigned vertex_index = 0;
10625 unsigned sub_poly_to_connect = 0;
10627 bool found_vertex_index =
false;
10631 Vector<unsigned> dst_shd_bnd_ids;
10632 get_shared_boundaries_overlapping_internal_boundary(
10633 uconnection_to_the_right, dst_shd_bnd_ids);
10637 const unsigned n_shd_bnd_overlap_int_bnd =
10638 dst_shd_bnd_ids.size();
10642 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10645 const unsigned new_connection_to_the_right =
10646 dst_shd_bnd_ids[ss];
10650 if (bound_id != new_connection_to_the_right)
10654 poly_to_connect_pt =
10655 boundary_polyline_pt(new_connection_to_the_right);
10657 if (poly_to_connect_pt != 0)
10661 found_vertex_index =
10662 get_connected_vertex_number_on_destination_polyline(
10663 poly_to_connect_pt,
10664 shd_bnd_right_vertex,
10670 if (found_vertex_index)
10682 if (!found_vertex_index)
10686 for (
unsigned isub = 0; isub < nsub_poly; isub++)
10690 if (!boundary_marked_as_shared_boundary(
10691 uconnection_to_the_right, isub))
10694 poly_to_connect_pt = tmp_vector_subpolylines[isub];
10696 found_vertex_index =
10697 get_connected_vertex_number_on_destination_polyline(
10698 poly_to_connect_pt,
10699 shd_bnd_right_vertex,
10703 if (found_vertex_index)
10707 sub_poly_to_connect = isub;
10720 if (!found_vertex_index)
10722 std::stringstream error;
10724 <<
"The current shared boundary (" << bound_id <<
") was "
10725 <<
"marked to have a connection\nto the right with the "
10726 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10727 <<
"This last boundary is marked to be overlaped by "
10728 <<
"shared boundaries\n"
10729 <<
"The problem is that the right vertex of the current\n"
10730 <<
"shared boundary is not in the list of vertices of "
10731 <<
"the\nboundary to connect.\n\n"
10732 <<
"This is the right vertex of the current shared "
10734 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", "
10735 << shd_bnd_right_vertex[1] <<
")\n\n"
10736 <<
"This is the list of vertices on the destination "
10737 <<
"boundary (only those subpolylines not marked as "
10738 <<
"overlaped by\nshared boundaries)\n";
10739 for (
unsigned p = 0; p < nsub_poly; p++)
10741 if (!boundary_marked_as_shared_boundary(
10742 uconnection_to_the_right, p))
10744 error <<
"Subpolyline #(" << p <<
")\n";
10745 poly_to_connect_pt = tmp_vector_subpolylines[p];
10746 const unsigned n_v = poly_to_connect_pt->nvertex();
10747 for (
unsigned i = 0; i < n_v; i++)
10749 Vector<double> cvertex =
10750 poly_to_connect_pt->vertex_coordinate(i);
10751 error <<
"Vertex #" << i <<
": (" << cvertex[0] <<
", "
10752 << cvertex[1] <<
")\n";
10756 error <<
"\nThis is the list of vertices of the shared "
10757 <<
"polylines that overlap\nthe internal "
10759 Vector<unsigned> dst_shd_bnd_ids;
10760 get_shared_boundaries_overlapping_internal_boundary(
10761 uconnection_to_the_right, dst_shd_bnd_ids);
10762 const unsigned n_shd_bnd_overlap_int_bnd =
10763 dst_shd_bnd_ids.size();
10764 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10766 const unsigned new_connection_to_the_right =
10767 dst_shd_bnd_ids[ss];
10768 poly_to_connect_pt =
10769 boundary_polyline_pt(new_connection_to_the_right);
10770 if (poly_to_connect_pt != 0)
10772 const unsigned shd_bnd_id_overlap =
10773 poly_to_connect_pt->boundary_id();
10774 error <<
"Shared boundary id(" << shd_bnd_id_overlap
10776 const unsigned n_v = poly_to_connect_pt->nvertex();
10777 for (
unsigned i = 0; i < n_v; i++)
10779 Vector<double> cvertex =
10780 poly_to_connect_pt->vertex_coordinate(i);
10781 error <<
"Vertex #" << i <<
": (" << cvertex[0] <<
", "
10782 << cvertex[1] <<
")\n";
10787 throw OomphLibError(
10789 "TriangleMesh::create_shared_polylines_connections()",
10790 OOMPH_EXCEPTION_LOCATION);
10798 shd_poly_pt->connect_final_vertex_to_polyline(
10799 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
10818 template<
class ELEMENT>
10820 Vector<Vector<double>>& output_holes_coordinates)
10823 const unsigned n_proc = this->communicator_pt()->nproc();
10824 const unsigned my_rank = this->communicator_pt()->my_rank();
10828 std::map<FiniteElement*, bool> done_ele;
10832 for (
unsigned iproc = 0; iproc < n_proc; iproc++)
10835 if (iproc != my_rank)
10838 const unsigned n_shd_bnd_iproc = nshared_boundaries(my_rank, iproc);
10843 const unsigned n_shd_bnd_iproc_rev = nshared_boundaries(iproc, my_rank);
10844 if (n_shd_bnd_iproc != n_shd_bnd_iproc_rev)
10846 std::ostringstream error_stream;
10848 <<
"The number of shared boundaries of processor (" << my_rank
10849 <<
") with processor(" << iproc <<
"): (" << n_shd_bnd_iproc
10851 <<
"is different from the number of shared boundaries of "
10852 <<
"processor (" << iproc <<
")\nwith processor (" << my_rank
10853 <<
"): (" << n_shd_bnd_iproc <<
")\n\n";
10854 throw OomphLibError(error_stream.str(),
10855 OOMPH_CURRENT_FUNCTION,
10856 OOMPH_EXCEPTION_LOCATION);
10862 for (
unsigned i = 0; i < n_shd_bnd_iproc; i++)
10865 const unsigned shd_bnd_id = shared_boundaries_ids(my_rank, iproc, i);
10868 const unsigned n_shd_bnd_ele = nshared_boundary_element(shd_bnd_id);
10871 for (
unsigned e = 0; e < n_shd_bnd_ele; e++)
10874 FiniteElement* ele_pt = shared_boundary_element_pt(shd_bnd_id, e);
10877 if (ele_pt->is_halo())
10880 if (!done_ele[ele_pt])
10883 const unsigned n_nodes = ele_pt->nnode();
10886 Vector<double> element_centroid(2, 0.0);
10888 for (
unsigned k = 0; k < n_nodes; k++)
10890 Node* tmp_node_pt = ele_pt->node_pt(k);
10892 for (
unsigned d = 0; d < 2; d++)
10894 element_centroid[d] += tmp_node_pt->x(d);
10899 for (
unsigned d = 0; d < 2; d++)
10901 element_centroid[d] = element_centroid[d] / (double)n_nodes;
10905 output_holes_coordinates.push_back(element_centroid);
10927 template<
class ELEMENT>
10929 Vector<TriangleMeshPolygon*>& polygons_pt,
10930 Vector<Vector<double>>& output_holes_coordinates)
10948 const unsigned n_input_holes = output_holes_coordinates.size();
10951 if (n_input_holes == 0)
10957 const unsigned n_polygons = polygons_pt.size();
10963 Vector<Vector<Vector<double>>> vertices_polygons(n_polygons);
10966 for (
unsigned p = 0; p < n_polygons; p++)
10969 const unsigned n_polylines = polygons_pt[p]->npolyline();
10971 for (
unsigned pp = 0; pp < n_polylines; pp++)
10974 const TriangleMeshPolyLine* tmp_poly_pt =
10975 polygons_pt[p]->polyline_pt(pp);
10977 const unsigned n_vertices = tmp_poly_pt->nvertex();
10981 for (
unsigned v = 0; v < n_vertices - 1; v++)
10984 Vector<double> current_vertex = tmp_poly_pt->vertex_coordinate(v);
10985 vertices_polygons[p].push_back(current_vertex);
10997 std::vector<bool> is_outer_polygon(n_polygons,
true);
11001 if (n_polygons > 1)
11008 Vector<Vector<Vector<double>>> polygon_edge_middle_vertex(n_polygons);
11010 for (
unsigned p = 0; p < n_polygons; p++)
11013 Vector<Vector<double>> tmp_inner_polygon = vertices_polygons[p];
11016 const unsigned n_vertices = tmp_inner_polygon.size();
11019 polygon_edge_middle_vertex[p].resize(n_vertices - 1);
11023 for (
unsigned e = 0; e < n_vertices - 1; e++)
11026 const unsigned dim = 2;
11027 polygon_edge_middle_vertex[p][e].resize(dim);
11028 for (
unsigned d = 0; d < dim; d++)
11030 polygon_edge_middle_vertex[p][e][d] =
11031 (tmp_inner_polygon[e][d] + tmp_inner_polygon[e + 1][d]) / 2.0;
11040 for (
unsigned idx_inner = 0; idx_inner < n_polygons; idx_inner++)
11045 bool is_inner_polygon =
false;
11050 for (
unsigned i = 0; i < n_polygons; i++)
11053 if (i != idx_inner)
11056 const unsigned n_edges =
11057 polygon_edge_middle_vertex[idx_inner].size();
11060 for (
unsigned e = 0; e < n_edges; e++)
11063 Vector<double> current_vertex =
11064 polygon_edge_middle_vertex[idx_inner][e];
11067 const bool is_point_inside = is_point_inside_polygon_helper(
11068 vertices_polygons[i], current_vertex);
11072 if (is_point_inside)
11075 is_inner_polygon =
true;
11086 if (is_inner_polygon)
11096 if (is_inner_polygon)
11099 is_outer_polygon[idx_inner] =
false;
11105 is_outer_polygon[idx_inner] =
true;
11114 unsigned n_outer_polygons = 0;
11115 unsigned n_inner_polygons = 0;
11117 Vector<unsigned> index_inner_polygon;
11119 for (
unsigned i = 0; i < n_polygons; i++)
11121 if (is_outer_polygon[i])
11124 n_outer_polygons++;
11129 n_inner_polygons++;
11131 index_inner_polygon.push_back(i);
11150 std::vector<bool> is_inside_an_inner_polygon(n_input_holes,
false);
11154 std::vector<bool> is_outside_the_outer_polygons(n_input_holes,
true);
11158 std::vector<bool> is_inside_the_convex_hull(n_input_holes,
false);
11161 Vector<Vector<Vector<double>>> vertex_inside_inner_polygon(
11167 for (
unsigned i = 0; i < n_inner_polygons; i++)
11170 const unsigned ii = index_inner_polygon[i];
11173 for (
unsigned h = 0; h < n_input_holes; h++)
11177 if (!is_inside_an_inner_polygon[h])
11180 const bool is_inside_polygon = is_point_inside_polygon_helper(
11181 vertices_polygons[ii], output_holes_coordinates[h]);
11185 if (is_inside_polygon)
11188 is_inside_an_inner_polygon[h] =
true;
11190 vertex_inside_inner_polygon[i].push_back(
11191 output_holes_coordinates[h]);
11203 for (
unsigned h = 0; h < n_input_holes; h++)
11207 if (!is_inside_an_inner_polygon[h])
11211 for (
unsigned i = 0; i < n_polygons; i++)
11214 if (is_outer_polygon[i])
11217 const bool is_inside_polygon = is_point_inside_polygon_helper(
11218 vertices_polygons[i], output_holes_coordinates[h]);
11223 if (is_inside_polygon)
11226 is_outside_the_outer_polygons[h] =
false;
11240 is_outside_the_outer_polygons[h] =
false;
11247 std::vector<Point> input_vertices_convex_hull;
11250 for (
unsigned p = 0; p < n_polygons; p++)
11253 const unsigned n_vertices = vertices_polygons[p].size();
11255 for (
unsigned v = 0; v < n_vertices; v++)
11260 point.
x = vertices_polygons[p][v][0];
11261 point.
y = vertices_polygons[p][v][1];
11263 input_vertices_convex_hull.push_back(point);
11268 std::vector<Point> output_vertices_convex_hull =
11269 convex_hull(input_vertices_convex_hull);
11272 const unsigned n_vertices_convex_hull = output_vertices_convex_hull.size();
11275 Vector<Vector<double>> vertices_convex_hull(n_vertices_convex_hull);
11276 for (
unsigned i = 0; i < n_vertices_convex_hull; i++)
11279 vertices_convex_hull[i].resize(2);
11281 vertices_convex_hull[i][0] = output_vertices_convex_hull[i].x;
11282 vertices_convex_hull[i][1] = output_vertices_convex_hull[i].y;
11288 for (
unsigned h = 0; h < n_input_holes; h++)
11291 if (is_outside_the_outer_polygons[h])
11294 const bool is_inside_convex_hull = is_point_inside_polygon_helper(
11295 vertices_convex_hull, output_holes_coordinates[h]);
11298 if (is_inside_convex_hull)
11301 is_inside_the_convex_hull[h] =
true;
11308 is_inside_the_convex_hull[h] =
true;
11315 Vector<Vector<double>> hole_kept;
11316 for (
unsigned h = 0; h < n_input_holes; h++)
11319 if ((is_inside_an_inner_polygon[h]) ||
11320 (is_outside_the_outer_polygons[h] && is_inside_the_convex_hull[h]))
11323 hole_kept.push_back(output_holes_coordinates[h]);
11328 output_holes_coordinates.clear();
11330 output_holes_coordinates = hole_kept;
11337 template<
class ELEMENT>
11339 Vector<TriangleMeshPolyLine*>& unsorted_polylines_pt,
11340 Vector<Vector<TriangleMeshPolyLine*>>& sorted_polylines_pt)
11342 unsigned n_unsorted_polylines = unsorted_polylines_pt.size();
11343 unsigned n_sorted_polylines = 0;
11344 unsigned curves_index = 0;
11347 std::map<TriangleMeshPolyLine*, bool> done_polyline;
11353 std::list<TriangleMeshPolyLine*> sorted_polyline_list_pt;
11354 bool changes =
false;
11358 TriangleMeshPolyLine* left_pt = 0;
11359 TriangleMeshPolyLine* right_pt = 0;
11363 bool found_root_polyline =
false;
11364 while (pp < n_unsorted_polylines && !found_root_polyline)
11366 if (!done_polyline[unsorted_polylines_pt[pp]])
11368 found_root_polyline =
true;
11377 if (pp < n_unsorted_polylines)
11380 left_pt = right_pt = unsorted_polylines_pt[pp];
11381 done_polyline[left_pt] =
true;
11383 n_sorted_polylines++;
11387 sorted_polyline_list_pt.push_back(left_pt);
11393 Vector<double> left_vertex(2);
11394 Vector<double> right_vertex(2);
11396 left_pt->initial_vertex_coordinate(left_vertex);
11397 right_pt->final_vertex_coordinate(right_vertex);
11399 for (
unsigned i = pp + 1; i < n_unsorted_polylines; i++)
11401 TriangleMeshPolyLine* current_polyline_pt =
11402 unsorted_polylines_pt[i];
11403 if (!done_polyline[current_polyline_pt])
11405 Vector<double> initial_vertex(2);
11406 Vector<double> final_vertex(2);
11407 current_polyline_pt->initial_vertex_coordinate(initial_vertex);
11408 current_polyline_pt->final_vertex_coordinate(final_vertex);
11414 if (left_vertex == final_vertex)
11416 left_pt = current_polyline_pt;
11417 sorted_polyline_list_pt.push_front(left_pt);
11418 done_polyline[left_pt] =
true;
11419 n_sorted_polylines++;
11425 else if (right_vertex == initial_vertex)
11427 right_pt = current_polyline_pt;
11428 sorted_polyline_list_pt.push_back(right_pt);
11429 done_polyline[right_pt] =
true;
11430 n_sorted_polylines++;
11436 else if (left_vertex == initial_vertex)
11438 current_polyline_pt->reverse();
11439 left_pt = current_polyline_pt;
11440 sorted_polyline_list_pt.push_front(left_pt);
11441 done_polyline[left_pt] =
true;
11442 n_sorted_polylines++;
11448 else if (right_vertex == final_vertex)
11450 current_polyline_pt->reverse();
11451 right_pt = current_polyline_pt;
11452 sorted_polyline_list_pt.push_back(right_pt);
11453 done_polyline[right_pt] =
true;
11454 n_sorted_polylines++;
11475 if (!found_root_polyline)
11477 std::stringstream err;
11478 err <<
"It was not possible to find a root polyline to sort the "
11479 <<
"others around it.\nThe number of unsorted and sorted "
11480 <<
"polylines is different, it means that\nnot all the "
11481 <<
"polylines have been sorted.\n"
11482 <<
"Found root polyline: (" << found_root_polyline <<
")\n"
11483 <<
"Sorted polylines: (" << n_sorted_polylines <<
")\n"
11484 <<
"Unsorted polylines: (" << n_unsorted_polylines <<
")\n";
11485 throw OomphLibError(err.str(),
11486 "TriangleMesh::sort_polylines_helper()",
11487 OOMPH_EXCEPTION_LOCATION);
11494 unsigned n_sorted_polyline_on_list = sorted_polyline_list_pt.size();
11497 Vector<TriangleMeshPolyLine*> tmp_sorted_polylines(
11498 n_sorted_polyline_on_list);
11499 unsigned counter = 0;
11501 std::list<TriangleMeshPolyLine*>::iterator it_polyline;
11502 for (it_polyline = sorted_polyline_list_pt.begin();
11503 it_polyline != sorted_polyline_list_pt.end();
11506 tmp_sorted_polylines[counter] = *it_polyline;
11510 sorted_polylines_pt.push_back(tmp_sorted_polylines);
11514 }
while (n_sorted_polylines < n_unsorted_polylines);
11519 if (n_sorted_polylines != n_unsorted_polylines)
11521 std::stringstream err;
11522 err <<
"The number of polylines on the unsorted and sorted vectors"
11523 <<
" is different,\n"
11524 <<
"it means that not all the polylines have been sorted.\n"
11525 <<
"Sorted polylines: " << n_sorted_polylines
11526 <<
"\nUnsorted polylines: " << n_unsorted_polylines;
11527 throw OomphLibError(err.str(),
11528 "TriangleMesh::sort_polylines_helper()",
11529 OOMPH_EXCEPTION_LOCATION);
11537 template<
class ELEMENT>
11539 OomphCommunicator* comm_pt,
11540 const Vector<unsigned>& element_domain,
11541 const Vector<GeneralisedElement*>& backed_up_el_pt,
11542 const Vector<FiniteElement*>& backed_up_f_el_pt,
11543 std::map<Data*, std::set<unsigned>>& processors_associated_with_data,
11544 const bool& overrule_keep_as_halo_element_status)
11547 const unsigned nproc = comm_pt->nproc();
11548 const unsigned my_rank = comm_pt->my_rank();
11554 Vector<Vector<Vector<GeneralisedElement*>>> halo_element_pt(nproc);
11556 for (
unsigned iproc = 0; iproc < nproc; iproc++)
11558 halo_element_pt[iproc].resize(nproc);
11564 std::map<GeneralisedElement*, unsigned> element_to_global_index;
11567 this->get_halo_elements_on_all_procs(nproc,
11570 processors_associated_with_data,
11571 overrule_keep_as_halo_element_status,
11572 element_to_global_index,
11576 flush_shared_boundary_polyline_pt();
11577 Shared_boundary_polyline_pt.resize(nproc);
11583 std::set<FiniteElement*> element_in_processor_pt;
11584 const unsigned n_ele = backed_up_f_el_pt.size();
11585 for (
unsigned e = 0; e < n_ele; e++)
11587 if (element_domain[e] == my_rank)
11589 element_in_processor_pt.insert(backed_up_f_el_pt[e]);
11596 std::map<std::pair<Node*, Node*>,
unsigned> elements_edges_on_boundary;
11597 this->get_element_edges_on_boundary(elements_edges_on_boundary);
11601 this->create_polylines_from_halo_elements_helper(
11603 element_to_global_index,
11604 element_in_processor_pt,
11606 elements_edges_on_boundary,
11607 Shared_boundary_polyline_pt);
11615 template<
class ELEMENT>
11617 const unsigned& nproc,
11618 const Vector<unsigned>& element_domain,
11619 const Vector<GeneralisedElement*>& backed_up_el_pt,
11620 std::map<Data*, std::set<unsigned>>& processors_associated_with_data,
11621 const bool& overrule_keep_as_halo_element_status,
11622 std::map<GeneralisedElement*, unsigned>& element_to_global_index,
11623 Vector<Vector<Vector<GeneralisedElement*>>>& output_halo_elements_pt)
11625 const unsigned n_ele = backed_up_el_pt.size();
11628 for (
unsigned iproc = 0; iproc < nproc; iproc++)
11632 Vector<std::map<GeneralisedElement*, bool>> already_added(nproc);
11635 for (
unsigned e = 0; e < n_ele; e++)
11638 GeneralisedElement* el_pt = backed_up_el_pt[e];
11639 unsigned el_domain = element_domain[e];
11643 if (el_domain != iproc)
11648 if ((this->Keep_all_elements_as_halos) ||
11649 (el_pt->must_be_kept_as_halo()))
11651 if (!overrule_keep_as_halo_element_status)
11655 if (!already_added[el_domain][el_pt])
11657 output_halo_elements_pt[iproc][el_domain].push_back(el_pt);
11658 already_added[el_domain][el_pt] =
true;
11659 element_to_global_index[el_pt] = e;
11667 FiniteElement* finite_el_pt =
dynamic_cast<FiniteElement*
>(el_pt);
11668 if (finite_el_pt != 0)
11670 unsigned n_node = finite_el_pt->nnode();
11671 for (
unsigned n = 0; n < n_node; n++)
11673 Node* nod_pt = finite_el_pt->node_pt(n);
11676 std::set<unsigned>::iterator it =
11677 processors_associated_with_data[nod_pt].find(iproc);
11678 if (it != processors_associated_with_data[nod_pt].end())
11682 if (!already_added[el_domain][el_pt])
11684 output_halo_elements_pt[iproc][el_domain].push_back(el_pt);
11685 already_added[el_domain][el_pt] =
true;
11686 element_to_global_index[el_pt] = e;
11704 template<
class ELEMENT>
11706 std::map<std::pair<Node*, Node*>,
unsigned>& element_edges_on_boundary)
11709 const unsigned nbound = this->nboundary();
11711 for (
unsigned b = 0; b < nbound; b++)
11714 std::map<std::pair<Node*, Node*>,
bool> edge_done;
11716 const unsigned nbound_ele = this->nboundary_element(b);
11717 for (
unsigned e = 0; e < nbound_ele; e++)
11720 FiniteElement* bulk_ele_pt = this->boundary_element_pt(b, e);
11722 int face_index = this->face_index_at_boundary(b, e);
11724 FiniteElement* face_ele_pt =
11725 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
11727 const unsigned nnodes = face_ele_pt->nnode();
11729 Node* first_node_pt = face_ele_pt->node_pt(0);
11730 Node* last_node_pt = face_ele_pt->node_pt(nnodes - 1);
11733 std::pair<Node*, Node*> edge =
11734 std::make_pair(first_node_pt, last_node_pt);
11737 if (!edge_done[edge])
11740 edge_done[edge] =
true;
11743 std::pair<Node*, Node*> inv_edge =
11744 std::make_pair(last_node_pt, first_node_pt);
11747 edge_done[inv_edge] =
true;
11750 element_edges_on_boundary[edge] = b;
11754 delete face_ele_pt;
11769 template<
class ELEMENT>
11771 const Vector<unsigned>& element_domain,
11772 std::map<GeneralisedElement*, unsigned>& element_to_global_index,
11773 std::set<FiniteElement*>& element_in_processor_pt,
11774 Vector<Vector<Vector<GeneralisedElement*>>>& input_halo_elements,
11775 std::map<std::pair<Node*, Node*>,
unsigned>& elements_edges_on_boundary,
11776 Vector<Vector<Vector<TriangleMeshPolyLine*>>>& output_polylines_pt)
11778 const unsigned nproc = this->communicator_pt()->nproc();
11779 const unsigned my_rank = this->communicator_pt()->my_rank();
11787 Vector<Vector<Vector<std::pair<Node*, Node*>>>> edges(nproc);
11791 Vector<Vector<Vector<Vector<FiniteElement*>>>> edge_element_pt(nproc);
11796 Vector<Vector<Vector<Vector<int>>>> edge_element_face(nproc);
11801 Vector<Vector<Vector<int>>> edge_boundary(nproc);
11804 std::map<std::pair<Node*, Node*>,
bool> overlapped_edge;
11810 Shared_boundaries_ids.resize(nproc);
11811 for (
unsigned j = 0; j < nproc; j++)
11813 edges[j].resize(nproc);
11814 edge_element_pt[j].resize(nproc);
11815 edge_element_face[j].resize(nproc);
11816 edge_boundary[j].resize(nproc);
11819 Shared_boundaries_ids[j].resize(nproc);
11825 for (
unsigned iproc = 0; iproc < nproc; iproc++)
11832 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
11845 Vector<GeneralisedElement*> halo_elements_iproc_with_jproc;
11846 Vector<GeneralisedElement*> halo_elements_jproc_with_iproc;
11849 halo_elements_iproc_with_jproc = input_halo_elements[iproc][jproc];
11852 const unsigned nhalo_elements_iproc_with_jproc =
11853 halo_elements_iproc_with_jproc.size();
11855 if (nhalo_elements_iproc_with_jproc > 0)
11858 halo_elements_jproc_with_iproc = input_halo_elements[jproc][iproc];
11862 const unsigned nhalo_elements_jproc_with_iproc =
11863 halo_elements_jproc_with_iproc.size();
11866 if (nhalo_elements_jproc_with_iproc == 0)
11871 std::stringstream err;
11872 err <<
"There are no halo elements from processor (" << jproc
11874 <<
"with processor (" << iproc <<
").\n"
11875 <<
"This is strange since there are halo elements from "
11876 <<
"processor (" << iproc <<
") with processor (" << jproc
11878 <<
"Number of halo elements from (" << iproc <<
") to ("
11879 << jproc <<
") : (" << nhalo_elements_iproc_with_jproc <<
")\n"
11880 <<
"Number of halo elements from (" << jproc <<
") to ("
11881 << iproc <<
") : (" << nhalo_elements_jproc_with_iproc <<
")\n";
11882 throw OomphLibError(
11884 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11885 OOMPH_EXCEPTION_LOCATION);
11889 Vector<Node*> halo_edges_iproc;
11890 unsigned halo_edges_counter_iproc = 0;
11891 Vector<Node*> halo_edges_jproc;
11892 unsigned halo_edges_counter_jproc = 0;
11895 std::map<std::pair<Node*, Node*>, FiniteElement*>
11896 edgesi_to_element_pt;
11900 std::map<std::pair<std::pair<Node*, Node*>, FiniteElement*>,
int>
11901 edgesi_element_pt_to_face_index;
11904 std::map<std::pair<Node*, Node*>, FiniteElement*>
11905 edgesj_to_element_pt;
11909 std::map<std::pair<std::pair<Node*, Node*>, FiniteElement*>,
int>
11910 edgesj_element_pt_to_face_index;
11916 for (
unsigned ih = 0; ih < nhalo_elements_iproc_with_jproc; ih++)
11920 element_to_global_index[halo_elements_iproc_with_jproc[ih]];
11922 if (element_domain[e] != jproc)
11925 std::stringstream err;
11926 err <<
"There was a problem on the ihalo-jhalo classification.\n"
11927 <<
"One of the elements, (the one with the (" << e <<
")-th "
11928 <<
"index ) is not on the (" << jproc <<
")-th processor\n"
11929 <<
"but it was stored as a halo element of processor ("
11930 << iproc <<
") with processor (" << jproc <<
").\n";
11931 throw OomphLibError(
11933 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11934 OOMPH_EXCEPTION_LOCATION);
11938 FiniteElement* el_pt =
11939 dynamic_cast<FiniteElement*
>(halo_elements_iproc_with_jproc[ih]);
11943 std::stringstream err;
11944 err <<
"The halo element (" << ih
11945 <<
") could not be casted to the "
11946 <<
"FiniteElement type.\n";
11947 throw OomphLibError(
11949 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11950 OOMPH_EXCEPTION_LOCATION);
11955 const unsigned n_nodes = el_pt->nnode();
11962 std::stringstream err;
11963 err <<
"The number of nodes of the " << ih
11964 <<
"-th halo element is"
11965 <<
" (" << n_nodes <<
").\nWe can not work with triangle "
11966 <<
"elements with less than three nodes\n";
11967 throw OomphLibError(
11969 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11970 OOMPH_EXCEPTION_LOCATION);
11975 Node* first_node_pt = el_pt->node_pt(0);
11976 Node* second_node_pt = el_pt->node_pt(1);
11977 Node* third_node_pt = el_pt->node_pt(2);
11980 halo_edges_iproc.push_back(first_node_pt);
11981 halo_edges_iproc.push_back(second_node_pt);
11982 halo_edges_counter_jproc++;
11984 halo_edges_iproc.push_back(second_node_pt);
11985 halo_edges_iproc.push_back(third_node_pt);
11986 halo_edges_counter_jproc++;
11988 halo_edges_iproc.push_back(third_node_pt);
11989 halo_edges_iproc.push_back(first_node_pt);
11990 halo_edges_counter_jproc++;
11993 std::pair<Node*, Node*> edge1 =
11994 std::make_pair(first_node_pt, second_node_pt);
11995 edgesi_to_element_pt[edge1] = el_pt;
11997 std::pair<Node*, Node*> edge2 =
11998 std::make_pair(second_node_pt, third_node_pt);
11999 edgesi_to_element_pt[edge2] = el_pt;
12001 std::pair<Node*, Node*> edge3 =
12002 std::make_pair(third_node_pt, first_node_pt);
12003 edgesi_to_element_pt[edge3] = el_pt;
12006 std::pair<std::pair<Node*, Node*>, FiniteElement*> edge_ele1 =
12007 std::make_pair(edge1, el_pt);
12008 edgesi_element_pt_to_face_index[edge_ele1] = 2;
12010 std::pair<std::pair<Node*, Node*>, FiniteElement*> edge_ele2 =
12011 std::make_pair(edge2, el_pt);
12012 edgesi_element_pt_to_face_index[edge_ele2] = 0;
12014 std::pair<std::pair<Node*, Node*>, FiniteElement*> edge_ele3 =
12015 std::make_pair(edge3, el_pt);
12016 edgesi_element_pt_to_face_index[edge_ele3] = 1;
12024 for (
unsigned jh = 0; jh < nhalo_elements_jproc_with_iproc; jh++)
12028 element_to_global_index[halo_elements_jproc_with_iproc[jh]];
12030 if (element_domain[e] != iproc)
12033 std::stringstream err;
12034 err <<
"There was a problem on the jhalo-ihalo classification.\n"
12035 <<
"One of the elements, (the one with the (" << e <<
")-th "
12036 <<
"index ) is not on the (" << iproc <<
")-th processor\n"
12037 <<
"but it was stored as a halo element of processor ("
12038 << jproc <<
") with processor (" << iproc <<
").\n";
12039 throw OomphLibError(
12041 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12042 OOMPH_EXCEPTION_LOCATION);
12046 FiniteElement* el_pt =
12047 dynamic_cast<FiniteElement*
>(halo_elements_jproc_with_iproc[jh]);
12050 std::stringstream err;
12051 err <<
"The halo element (" << jh
12052 <<
") could not be casted to the "
12053 <<
"FiniteElement type.\n";
12054 throw OomphLibError(
12056 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12057 OOMPH_EXCEPTION_LOCATION);
12062 const unsigned n_nodes = el_pt->nnode();
12069 std::stringstream err;
12070 err <<
"The number of nodes of the " << jh
12071 <<
"-th halo element is"
12072 <<
" (" << n_nodes <<
").\nWe can not work with triangle "
12073 <<
"elements with less than three nodes\n";
12074 throw OomphLibError(
12076 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12077 OOMPH_EXCEPTION_LOCATION);
12082 Node* first_node_pt = el_pt->node_pt(0);
12083 Node* second_node_pt = el_pt->node_pt(1);
12084 Node* third_node_pt = el_pt->node_pt(2);
12087 halo_edges_jproc.push_back(first_node_pt);
12088 halo_edges_jproc.push_back(second_node_pt);
12089 halo_edges_counter_iproc++;
12091 halo_edges_jproc.push_back(second_node_pt);
12092 halo_edges_jproc.push_back(third_node_pt);
12093 halo_edges_counter_iproc++;
12095 halo_edges_jproc.push_back(third_node_pt);
12096 halo_edges_jproc.push_back(first_node_pt);
12097 halo_edges_counter_iproc++;
12100 std::pair<Node*, Node*> edge1 =
12101 std::make_pair(first_node_pt, second_node_pt);
12102 edgesj_to_element_pt[edge1] = el_pt;
12104 std::pair<Node*, Node*> edge2 =
12105 std::make_pair(second_node_pt, third_node_pt);
12106 edgesj_to_element_pt[edge2] = el_pt;
12108 std::pair<Node*, Node*> edge3 =
12109 std::make_pair(third_node_pt, first_node_pt);
12110 edgesj_to_element_pt[edge3] = el_pt;
12113 std::pair<std::pair<Node*, Node*>, FiniteElement*> edge_ele1 =
12114 std::make_pair(edge1, el_pt);
12115 edgesj_element_pt_to_face_index[edge_ele1] = 2;
12117 std::pair<std::pair<Node*, Node*>, FiniteElement*> edge_ele2 =
12118 std::make_pair(edge2, el_pt);
12119 edgesj_element_pt_to_face_index[edge_ele2] = 0;
12121 std::pair<std::pair<Node*, Node*>, FiniteElement*> edge_ele3 =
12122 std::make_pair(edge3, el_pt);
12123 edgesj_element_pt_to_face_index[edge_ele3] = 1;
12136 unsigned nhalo_iedges = halo_edges_iproc.size();
12137 unsigned nhalo_jedges = halo_edges_jproc.size();
12141 for (
unsigned ihe = 0; ihe < nhalo_iedges; ihe += 2)
12144 Vector<Node*> ihalo_edge(2);
12145 ihalo_edge[0] = halo_edges_iproc[ihe];
12146 ihalo_edge[1] = halo_edges_iproc[ihe + 1];
12149 std::pair<Node*, Node*> tmp_edge =
12150 std::make_pair(ihalo_edge[0], ihalo_edge[1]);
12154 int edge_boundary_id = -1;
12156 std::map<std::pair<Node*, Node*>,
unsigned>::iterator it;
12157 it = elements_edges_on_boundary.find(tmp_edge);
12160 if (it != elements_edges_on_boundary.end())
12164 edge_boundary_id = (*it).second;
12170 std::pair<Node*, Node*> rtmp_edge =
12171 std::make_pair(ihalo_edge[1], ihalo_edge[0]);
12172 it = elements_edges_on_boundary.find(rtmp_edge);
12173 if (it != elements_edges_on_boundary.end())
12177 edge_boundary_id = (*it).second;
12184 for (
unsigned jhe = 0; jhe < nhalo_jedges; jhe += 2)
12187 Vector<Node*> jhalo_edge(2);
12188 jhalo_edge[0] = halo_edges_jproc[jhe];
12189 jhalo_edge[1] = halo_edges_jproc[jhe + 1];
12192 if (ihalo_edge[0] == jhalo_edge[0] &&
12193 ihalo_edge[1] == jhalo_edge[1])
12196 std::pair<Node*, Node*> new_edge =
12197 std::make_pair(ihalo_edge[0], ihalo_edge[1]);
12202 FiniteElement* haloi_ele_pt = 0;
12203 haloi_ele_pt = edgesi_to_element_pt[new_edge];
12204 FiniteElement* haloj_ele_pt = 0;
12205 haloj_ele_pt = edgesj_to_element_pt[new_edge];
12208 if (haloi_ele_pt == 0 || haloj_ele_pt == 0)
12210 std::stringstream err;
12211 err <<
"There is no associated elements with the new "
12212 <<
"shared boundary. This is an storing problem,\n"
12213 <<
"possibly related with a memory leak problem!!!\n"
12214 <<
"The nodes that compound the edge are these:\n"
12215 <<
"On processor (" << iproc <<
"):\n"
12216 <<
"(" << ihalo_edge[0]->x(0) <<
", "
12217 << ihalo_edge[0]->x(1) <<
") and (" << ihalo_edge[1]->x(0)
12218 <<
", " << ihalo_edge[1]->x(1) <<
")\n\n"
12219 <<
"On processor (" << jproc <<
"):\n"
12220 <<
"(" << jhalo_edge[0]->x(0) <<
", "
12221 << jhalo_edge[0]->x(1) <<
") and (" << jhalo_edge[1]->x(0)
12222 <<
", " << jhalo_edge[1]->x(1) <<
")\n\n"
12223 <<
"The nodes coordinates should be the same!!!\n";
12224 throw OomphLibError(err.str(),
12225 "TriangleMesh::create_polylines_from_"
12226 "halo_elements_helper()",
12227 OOMPH_EXCEPTION_LOCATION);
12231 edges[iproc][jproc].push_back(new_edge);
12234 if (edge_boundary_id >= 0)
12237 overlapped_edge[new_edge] =
true;
12240 std::pair<Node*, Node*> rev_new_edge =
12241 std::make_pair(ihalo_edge[1], ihalo_edge[0]);
12244 overlapped_edge[rev_new_edge] =
true;
12250 edge_boundary[iproc][jproc].push_back(edge_boundary_id);
12253 Vector<FiniteElement*> tmp_elements_pt;
12254 tmp_elements_pt.push_back(haloi_ele_pt);
12255 tmp_elements_pt.push_back(haloj_ele_pt);
12258 edge_element_pt[iproc][jproc].push_back(tmp_elements_pt);
12264 std::pair<std::pair<Node*, Node*>, FiniteElement*>
12265 edge_elementi_pair = make_pair(new_edge, haloi_ele_pt);
12267 std::pair<std::pair<Node*, Node*>, FiniteElement*>
12268 edge_elementj_pair = make_pair(new_edge, haloj_ele_pt);
12272 int face_index_haloi_ele = -1;
12273 face_index_haloi_ele =
12274 edgesi_element_pt_to_face_index[edge_elementi_pair];
12275 int face_index_haloj_ele = -1;
12276 face_index_haloj_ele =
12277 edgesj_element_pt_to_face_index[edge_elementj_pair];
12279 if (face_index_haloi_ele == -1 || face_index_haloj_ele == -1)
12281 std::stringstream err;
12282 err <<
"There is no associated face indexes to the"
12283 <<
"elements that gave\nrise to the shared edge\n"
12284 <<
"The nodes that compound the edge are these:\n"
12285 <<
"On processor (" << iproc <<
"):\n"
12286 <<
"(" << ihalo_edge[0]->x(0) <<
", "
12287 << ihalo_edge[0]->x(1) <<
") and (" << ihalo_edge[1]->x(0)
12288 <<
", " << ihalo_edge[1]->x(1) <<
")\n\n"
12289 <<
"On processor (" << jproc <<
"):\n"
12290 <<
"(" << jhalo_edge[0]->x(0) <<
", "
12291 << jhalo_edge[0]->x(1) <<
") and (" << jhalo_edge[1]->x(0)
12292 <<
", " << jhalo_edge[1]->x(1) <<
")\n\n"
12293 <<
"The nodes coordinates should be the same!!!\n";
12294 throw OomphLibError(err.str(),
12295 "TriangleMesh::create_polylines_from_"
12296 "halo_elements_helper()",
12297 OOMPH_EXCEPTION_LOCATION);
12302 Vector<int> tmp_edge_element_face_index;
12303 tmp_edge_element_face_index.push_back(face_index_haloi_ele);
12304 tmp_edge_element_face_index.push_back(face_index_haloj_ele);
12306 edge_element_face[iproc][jproc].push_back(
12307 tmp_edge_element_face_index);
12315 else if (ihalo_edge[0] == jhalo_edge[1] &&
12316 ihalo_edge[1] == jhalo_edge[0])
12319 std::pair<Node*, Node*> new_edge =
12320 std::make_pair(ihalo_edge[0], ihalo_edge[1]);
12324 FiniteElement* haloi_ele_pt = 0;
12325 haloi_ele_pt = edgesi_to_element_pt[new_edge];
12327 FiniteElement* haloj_ele_pt = 0;
12330 std::pair<Node*, Node*> new_edge_reversed =
12331 std::make_pair(jhalo_edge[0], jhalo_edge[1]);
12332 haloj_ele_pt = edgesj_to_element_pt[new_edge_reversed];
12335 if (haloi_ele_pt == 0 || haloj_ele_pt == 0)
12337 std::stringstream err;
12338 err <<
"There is no associated elements with the new "
12339 <<
"shared boundary (reversed version). This is an "
12340 <<
"storing problem, possibly related with a memory "
12341 <<
"leak problem!!!\n"
12342 <<
"The nodes that compound the edge are these:\n"
12343 <<
"On processor (" << iproc <<
"):\n"
12344 <<
"(" << ihalo_edge[0]->x(0) <<
", "
12345 << ihalo_edge[0]->x(1) <<
") and (" << ihalo_edge[1]->x(0)
12346 <<
", " << ihalo_edge[1]->x(1) <<
")\n\n"
12347 <<
"On processor (" << jproc <<
"):\n"
12348 <<
"(" << jhalo_edge[0]->x(0) <<
", "
12349 << jhalo_edge[0]->x(1) <<
") and (" << jhalo_edge[1]->x(0)
12350 <<
", " << jhalo_edge[1]->x(1) <<
")\n\n"
12351 <<
"The nodes coordinates should be the same!!!\n";
12352 throw OomphLibError(err.str(),
12353 "TriangleMesh::create_polylines_from_"
12354 "halo_elements_helper()",
12355 OOMPH_EXCEPTION_LOCATION);
12359 edges[iproc][jproc].push_back(new_edge);
12362 if (edge_boundary_id >= 0)
12365 overlapped_edge[new_edge] =
true;
12368 std::pair<Node*, Node*> rev_new_edge =
12369 std::make_pair(ihalo_edge[1], ihalo_edge[0]);
12372 overlapped_edge[rev_new_edge] =
true;
12377 edge_boundary[iproc][jproc].push_back(edge_boundary_id);
12380 Vector<FiniteElement*> tmp_elements_pt;
12381 tmp_elements_pt.push_back(haloi_ele_pt);
12382 tmp_elements_pt.push_back(haloj_ele_pt);
12385 edge_element_pt[iproc][jproc].push_back(tmp_elements_pt);
12391 std::pair<std::pair<Node*, Node*>, FiniteElement*>
12392 edge_elementi_pair = make_pair(new_edge, haloi_ele_pt);
12394 std::pair<std::pair<Node*, Node*>, FiniteElement*>
12395 edge_elementj_pair =
12396 make_pair(new_edge_reversed, haloj_ele_pt);
12400 int face_index_haloi_ele = -1;
12401 face_index_haloi_ele =
12402 edgesi_element_pt_to_face_index[edge_elementi_pair];
12403 int face_index_haloj_ele = -1;
12404 face_index_haloj_ele =
12405 edgesj_element_pt_to_face_index[edge_elementj_pair];
12407 if (face_index_haloi_ele == -1 || face_index_haloj_ele == -1)
12409 std::stringstream err;
12410 err <<
"There is no associated face indexes to the"
12411 <<
"elements that gave\nrise to the shared edge\n"
12412 <<
"The nodes that compound the edge are these:\n"
12413 <<
"On processor (" << iproc <<
"):\n"
12414 <<
"(" << ihalo_edge[0]->x(0) <<
", "
12415 << ihalo_edge[0]->x(1) <<
") and (" << ihalo_edge[1]->x(0)
12416 <<
", " << ihalo_edge[1]->x(1) <<
")\n\n"
12417 <<
"On processor (" << jproc <<
"):\n"
12418 <<
"(" << jhalo_edge[0]->x(0) <<
", "
12419 << jhalo_edge[0]->x(1) <<
") and (" << jhalo_edge[1]->x(0)
12420 <<
", " << jhalo_edge[1]->x(1) <<
")\n\n"
12421 <<
"The nodes coordinates should be the same!!!\n";
12422 throw OomphLibError(err.str(),
12423 "TriangleMesh::create_polylines_from_"
12424 "halo_elements_helper()",
12425 OOMPH_EXCEPTION_LOCATION);
12430 Vector<int> tmp_edge_element_face_index;
12431 tmp_edge_element_face_index.push_back(face_index_haloi_ele);
12432 tmp_edge_element_face_index.push_back(face_index_haloj_ele);
12434 edge_element_face[iproc][jproc].push_back(
12435 tmp_edge_element_face_index);
12460 std::map<Node*, unsigned> global_shared_node_degree;
12464 std::map<std::pair<Node*, Node*>,
bool> edge_done;
12467 std::map<Node*, bool> node_done;
12471 for (
unsigned iproc = 0; iproc < nproc; iproc++)
12478 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
12481 const unsigned nshd_edges = edges[iproc][jproc].size();
12487 const unsigned nedge_element = edge_element_pt[iproc][jproc].size();
12488 if (nshd_edges != nedge_element)
12490 std::stringstream error_message;
12492 <<
"The number of shared edges between processor iproc and jproc\n"
12493 <<
"is different form the number of edge elements between the\n"
12494 <<
"pair of processors\n"
12495 <<
"iproc: (" << iproc <<
")\n"
12496 <<
"jproc: (" << jproc <<
")\n"
12497 <<
"# of shared edges: (" << nshd_edges <<
")\n"
12498 <<
"# of edge elements: (" << nedge_element <<
")\n\n";
12499 throw OomphLibError(
12500 error_message.str(),
12501 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12502 OOMPH_EXCEPTION_LOCATION);
12506 const unsigned nedge_element_face =
12507 edge_element_face[iproc][jproc].size();
12508 if (nshd_edges != nedge_element_face)
12510 std::stringstream error_message;
12512 <<
"The number of shared edges between processor iproc and jproc\n"
12513 <<
"is different form the number of edge element faces between "
12515 <<
"pair of processors\n"
12516 <<
"iproc: (" << iproc <<
")\n"
12517 <<
"jproc: (" << jproc <<
")\n"
12518 <<
"# of shared edges: (" << nshd_edges <<
")\n"
12519 <<
"# of edge element faces: (" << nedge_element_face <<
")\n\n";
12520 throw OomphLibError(
12521 error_message.str(),
12522 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12523 OOMPH_EXCEPTION_LOCATION);
12527 const unsigned nedge_boundary = edge_boundary[iproc][jproc].size();
12528 if (nshd_edges != nedge_boundary)
12530 std::stringstream error_message;
12532 <<
"The number of shared edges between processor iproc and jproc\n"
12533 <<
"is different form the number of edge boundaries ids between "
12535 <<
"pair of processors\n"
12536 <<
"iproc: (" << iproc <<
")\n"
12537 <<
"jproc: (" << jproc <<
")\n"
12538 <<
"# of shared edges: (" << nshd_edges <<
")\n"
12539 <<
"# of edge boundaries ids: (" << nedge_boundary <<
")\n\n";
12540 throw OomphLibError(
12541 error_message.str(),
12542 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12543 OOMPH_EXCEPTION_LOCATION);
12549 for (
unsigned se = 0; se < nshd_edges; se++)
12552 std::pair<Node*, Node*> edge = edges[iproc][jproc][se];
12555 if (edge_done[edge])
12557 std::stringstream error_message;
12559 <<
"The shared edge between processor iproc and processor\n"
12560 <<
"jproc has been already visited, this is weird since the\n"
12561 <<
"edge should not be shared by other pair of processors\n"
12562 <<
"iproc: (" << iproc <<
")\n"
12563 <<
"jproc: (" << jproc <<
")\n"
12564 <<
"First node of edge: (" << edge.first->x(0) <<
", "
12565 << edge.first->x(1) <<
")\n"
12566 <<
"Second node of edge: (" << edge.second->x(0) <<
", "
12567 << edge.second->x(1) <<
")\n"
12568 <<
"Associated edge boundary id: ("
12569 << edge_boundary[iproc][jproc][se] <<
")\n\n";
12570 throw OomphLibError(
12571 error_message.str(),
12572 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12573 OOMPH_EXCEPTION_LOCATION);
12577 edge_done[edge] =
true;
12579 std::pair<Node*, Node*> rev_edge =
12580 std::make_pair(edge.second, edge.first);
12582 edge_done[rev_edge] =
true;
12586 Node* left_node_pt = edge.first;
12587 Node* right_node_pt = edge.second;
12590 if (!node_done[left_node_pt])
12594 global_shared_node_degree[left_node_pt] = 1;
12600 global_shared_node_degree[left_node_pt]++;
12604 if (!node_done[right_node_pt])
12608 global_shared_node_degree[right_node_pt] = 1;
12613 global_shared_node_degree[right_node_pt]++;
12628 std::map<unsigned, std::map<Node*, bool>>
12629 node_on_bnd_not_overlapped_by_shd_bnd;
12632 for (std::map<std::pair<Node*, Node*>,
unsigned>::iterator it_map =
12633 elements_edges_on_boundary.begin();
12634 it_map != elements_edges_on_boundary.end();
12638 std::pair<Node*, Node*> edge_pair = (*it_map).first;
12641 if (!overlapped_edge[edge_pair])
12645 unsigned b = (*it_map).second;
12648 Node* left_node_pt = edge_pair.first;
12649 node_on_bnd_not_overlapped_by_shd_bnd[b][left_node_pt] =
true;
12652 Node* right_node_pt = edge_pair.second;
12653 node_on_bnd_not_overlapped_by_shd_bnd[b][right_node_pt] =
true;
12668 Vector<Vector<TriangleMeshPolyLine*>> unsorted_polylines_pt(nproc);
12673 std::map<unsigned, std::list<Node*>> shared_bnd_id_to_sorted_list_node_pt;
12677 unsigned shared_boundary_id_start = this->nboundary();
12678 Initial_shared_boundary_id = shared_boundary_id_start;
12684 for (
unsigned iproc = 0; iproc < nproc; iproc++)
12691 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
12699 unsigned npolylines_counter = 0;
12700 const unsigned nedges = edges[iproc][jproc].size();
12706 unsigned nsorted_edges = 0;
12709 std::map<std::pair<Node*, Node*>,
bool> edge_done;
12713 while (nsorted_edges < nedges)
12717 std::list<FiniteElement*> tmp_boundary_element_pt;
12720 std::list<int> tmp_face_index_element;
12722 std::pair<Node*, Node*> edge;
12724 bool found_initial_edge =
false;
12726 int root_edge_bound_id = -1;
12727 unsigned iedge = 0;
12728 for (iedge = 0; iedge < nedges; iedge++)
12730 edge = edges[iproc][jproc][iedge];
12732 if (!edge_done[edge])
12735 root_edge_bound_id = edge_boundary[iproc][jproc][iedge];
12737 found_initial_edge =
true;
12746 if (!found_initial_edge)
12748 std::ostringstream error_message;
12750 <<
"All the edge are already done, but the number of done\n"
12751 <<
"edges (" << nsorted_edges
12752 <<
") is still less than the total\n"
12753 <<
"number of edges (" << nedges <<
").\n";
12755 throw OomphLibError(
12756 error_message.str(),
12757 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12758 OOMPH_EXCEPTION_LOCATION);
12764 std::list<Node*> sorted_nodes;
12765 sorted_nodes.clear();
12768 Node* first_node_pt = edge.first;
12769 Node* last_node_pt = edge.second;
12772 sorted_nodes.push_back(first_node_pt);
12773 sorted_nodes.push_back(last_node_pt);
12777 tmp_boundary_element_pt.push_back(
12778 edge_element_pt[iproc][jproc][iedge - 1][0]);
12779 tmp_boundary_element_pt.push_back(
12780 edge_element_pt[iproc][jproc][iedge - 1][1]);
12784 tmp_face_index_element.push_back(
12785 edge_element_face[iproc][jproc][iedge - 1][0]);
12786 tmp_face_index_element.push_back(
12787 edge_element_face[iproc][jproc][iedge - 1][1]);
12790 edge_done[edge] =
true;
12795 bool node_added =
true;
12799 bool node_added_to_the_left =
true;
12800 bool node_added_to_the_right =
true;
12818 bool connection_to_the_left =
false;
12823 bool connection_to_the_right =
false;
12827 bool current_polyline_has_connections_at_both_ends =
false;
12834 int bound_id_connection_to_the_left = -1;
12835 int bound_id_connection_to_the_right = -1;
12838 const unsigned first_node_degree =
12839 global_shared_node_degree[first_node_pt];
12843 bound_id_connection_to_the_left = check_connections_of_polyline_nodes(
12844 element_in_processor_pt,
12845 root_edge_bound_id,
12847 node_on_bnd_not_overlapped_by_shd_bnd,
12849 shared_bnd_id_to_sorted_list_node_pt,
12859 if (bound_id_connection_to_the_left != -1)
12861 connection_to_the_left =
true;
12865 const unsigned last_node_degree =
12866 global_shared_node_degree[last_node_pt];
12870 bound_id_connection_to_the_right =
12871 check_connections_of_polyline_nodes(
12872 element_in_processor_pt,
12873 root_edge_bound_id,
12875 node_on_bnd_not_overlapped_by_shd_bnd,
12877 shared_bnd_id_to_sorted_list_node_pt,
12886 if (bound_id_connection_to_the_right != -1)
12888 connection_to_the_right =
true;
12893 if (connection_to_the_left && connection_to_the_right)
12895 current_polyline_has_connections_at_both_ends =
true;
12903 while (node_added && (nsorted_edges < nedges) &&
12904 !current_polyline_has_connections_at_both_ends)
12909 for (
unsigned iiedge = iedge; iiedge < nedges; iiedge++)
12912 node_added =
false;
12913 node_added_to_the_left =
false;
12914 node_added_to_the_right =
false;
12916 edge = edges[iproc][jproc][iiedge];
12917 const int edge_bound_id = edge_boundary[iproc][jproc][iiedge];
12923 if (!edge_done[edge] && (edge_bound_id == root_edge_bound_id))
12926 Node* left_node_pt = edge.first;
12927 Node* right_node_pt = edge.second;
12930 Node* new_added_node_pt = 0;
12933 if (left_node_pt == first_node_pt && !connection_to_the_left)
12936 sorted_nodes.push_front(right_node_pt);
12938 new_added_node_pt = first_node_pt = right_node_pt;
12942 node_added_to_the_left =
true;
12945 else if (left_node_pt == last_node_pt &&
12946 !connection_to_the_right)
12949 sorted_nodes.push_back(right_node_pt);
12951 new_added_node_pt = last_node_pt = right_node_pt;
12955 node_added_to_the_right =
true;
12958 else if (right_node_pt == first_node_pt &&
12959 !connection_to_the_left)
12962 sorted_nodes.push_front(left_node_pt);
12964 new_added_node_pt = first_node_pt = left_node_pt;
12968 node_added_to_the_left =
true;
12971 else if (right_node_pt == last_node_pt &&
12972 !connection_to_the_right)
12975 sorted_nodes.push_back(left_node_pt);
12977 new_added_node_pt = last_node_pt = left_node_pt;
12981 node_added_to_the_right =
true;
12991 edge_done[edge] =
true;
12995 const unsigned added_node_degree =
12996 global_shared_node_degree[new_added_node_pt];
12998 if (node_added_to_the_left)
13001 tmp_boundary_element_pt.push_front(
13002 edge_element_pt[iproc][jproc][iiedge][1]);
13003 tmp_boundary_element_pt.push_front(
13004 edge_element_pt[iproc][jproc][iiedge][0]);
13006 tmp_face_index_element.push_front(
13007 edge_element_face[iproc][jproc][iiedge][1]);
13008 tmp_face_index_element.push_front(
13009 edge_element_face[iproc][jproc][iiedge][0]);
13012 if (node_added_to_the_right)
13015 tmp_boundary_element_pt.push_back(
13016 edge_element_pt[iproc][jproc][iiedge][0]);
13017 tmp_boundary_element_pt.push_back(
13018 edge_element_pt[iproc][jproc][iiedge][1]);
13020 tmp_face_index_element.push_back(
13021 edge_element_face[iproc][jproc][iiedge][0]);
13022 tmp_face_index_element.push_back(
13023 edge_element_face[iproc][jproc][iiedge][1]);
13033 if (node_added_to_the_left && !connection_to_the_left)
13036 bound_id_connection_to_the_left =
13037 check_connections_of_polyline_nodes(
13038 element_in_processor_pt,
13039 root_edge_bound_id,
13041 node_on_bnd_not_overlapped_by_shd_bnd,
13043 shared_bnd_id_to_sorted_list_node_pt,
13045 new_added_node_pt);
13052 if (bound_id_connection_to_the_left != -1)
13054 connection_to_the_left =
true;
13064 if (node_added_to_the_right && !connection_to_the_right)
13067 bound_id_connection_to_the_right =
13068 check_connections_of_polyline_nodes(
13069 element_in_processor_pt,
13070 root_edge_bound_id,
13072 node_on_bnd_not_overlapped_by_shd_bnd,
13074 shared_bnd_id_to_sorted_list_node_pt,
13076 new_added_node_pt);
13083 if (bound_id_connection_to_the_right != -1)
13085 connection_to_the_right =
true;
13093 if (connection_to_the_left && connection_to_the_right)
13095 current_polyline_has_connections_at_both_ends =
true;
13119 const unsigned n_bnd_ele = tmp_boundary_element_pt.size();
13122 Vector<FiniteElement*> tmp_bnd_ele_pt(n_bnd_ele);
13123 Vector<int> tmp_face_idx_ele(n_bnd_ele);
13125 unsigned help_counter = 0;
13127 for (std::list<FiniteElement*>::iterator it_bnd_ele =
13128 tmp_boundary_element_pt.begin();
13129 it_bnd_ele != tmp_boundary_element_pt.end();
13132 tmp_bnd_ele_pt[help_counter++] = (*it_bnd_ele);
13137 for (std::list<int>::iterator it_face_idx =
13138 tmp_face_index_element.begin();
13139 it_face_idx != tmp_face_index_element.end();
13142 tmp_face_idx_ele[help_counter++] = (*it_face_idx);
13147 Vector<std::list<Node*>> final_sorted_nodes_pt;
13150 Vector<Vector<FiniteElement*>> final_boundary_element_pt;
13152 Vector<Vector<int>> final_face_index_element;
13155 Vector<int> final_bound_id_connection_to_the_left;
13158 Vector<int> final_bound_id_connection_to_the_right;
13161 break_loops_on_shared_polyline_helper(
13162 shared_boundary_id_start,
13166 bound_id_connection_to_the_left,
13167 bound_id_connection_to_the_right,
13168 final_sorted_nodes_pt,
13169 final_boundary_element_pt,
13170 final_face_index_element,
13171 final_bound_id_connection_to_the_left,
13172 final_bound_id_connection_to_the_right);
13175 const unsigned n_final_sorted_nodes = final_sorted_nodes_pt.size();
13178 for (
unsigned i = 0; i < n_final_sorted_nodes; i++)
13183 shared_bnd_id_to_sorted_list_node_pt[shared_boundary_id_start] =
13184 final_sorted_nodes_pt[i];
13188 create_shared_polyline(my_rank,
13189 shared_boundary_id_start,
13192 final_sorted_nodes_pt[i],
13193 root_edge_bound_id,
13194 final_boundary_element_pt[i],
13195 final_face_index_element[i],
13196 unsorted_polylines_pt,
13197 final_bound_id_connection_to_the_left[i],
13198 final_bound_id_connection_to_the_right[i]);
13202 npolylines_counter++;
13206 shared_boundary_id_start++;
13219 if (unsorted_polylines_pt[iproc].size() > 0)
13223 sort_polylines_helper(unsorted_polylines_pt[iproc],
13224 output_polylines_pt[iproc]);
13228 const unsigned nunsorted_polylines_iproc =
13229 unsorted_polylines_pt[iproc].size();
13232 unsigned tmp_ntotal_polylines = 0;
13234 for (
unsigned ii = 0; ii < output_polylines_pt[iproc].size(); ii++)
13236 tmp_ntotal_polylines += output_polylines_pt[iproc][ii].size();
13238 if (tmp_ntotal_polylines != nunsorted_polylines_iproc)
13240 std::ostringstream error_message;
13241 error_message <<
" The total number of unsorted polylines ("
13242 << nunsorted_polylines_iproc
13243 <<
") in common with\nprocessor (" << iproc
13244 <<
") is different from the total number of sorted "
13245 <<
"polylines (" << tmp_ntotal_polylines
13246 <<
") with\nthe same "
13248 throw OomphLibError(error_message.str(),
13249 OOMPH_CURRENT_FUNCTION,
13250 OOMPH_EXCEPTION_LOCATION);
13257 this->Final_shared_boundary_id = shared_boundary_id_start;
13264 template<
class ELEMENT>
13266 const unsigned& initial_shd_bnd_id,
13267 std::list<Node*>& input_nodes,
13268 Vector<FiniteElement*>& input_boundary_element_pt,
13269 Vector<int>& input_face_index_element,
13270 const int& input_connect_to_the_left,
13271 const int& input_connect_to_the_right,
13272 Vector<std::list<Node*>>& output_sorted_nodes_pt,
13273 Vector<Vector<FiniteElement*>>& output_boundary_element_pt,
13274 Vector<Vector<int>>& output_face_index_element,
13275 Vector<int>& output_connect_to_the_left,
13276 Vector<int>& output_connect_to_the_right)
13279 Node* left_node_pt = input_nodes.front();
13280 Node* right_node_pt = input_nodes.back();
13284 Vector<std::list<Node*>> tmp_sub_nodes;
13285 Vector<Vector<FiniteElement*>> tmp_sub_bnd_ele_pt;
13286 Vector<Vector<int>> tmp_sub_face_idx_ele;
13289 std::list<Node*>::iterator it = input_nodes.begin();
13292 unsigned counter = 0;
13295 while (it != input_nodes.end())
13300 if (it == input_nodes.end())
13312 std::list<Node*> sub_nodes;
13315 Vector<FiniteElement*> sub_bnd_ele_pt;
13318 Vector<int> sub_face_idx_ele;
13321 sub_nodes.push_back(*it);
13331 sub_nodes.push_back((*it));
13334 sub_bnd_ele_pt.push_back(input_boundary_element_pt[counter]);
13335 sub_bnd_ele_pt.push_back(input_boundary_element_pt[counter + 1]);
13338 sub_face_idx_ele.push_back(input_face_index_element[counter]);
13339 sub_face_idx_ele.push_back(input_face_index_element[counter + 1]);
13346 }
while ((*it) != left_node_pt && (*it) != right_node_pt &&
13347 it != input_nodes.end());
13350 tmp_sub_nodes.push_back(sub_nodes);
13352 tmp_sub_bnd_ele_pt.push_back(sub_bnd_ele_pt);
13354 tmp_sub_face_idx_ele.push_back(sub_face_idx_ele);
13362 const unsigned n_sub_list = tmp_sub_nodes.size();
13365 if (n_sub_list > 3)
13367 std::stringstream error_message;
13369 <<
"The number of sub-list of nodes created from the shared\n"
13370 <<
"polyline with loops was (" << n_sub_list <<
").\n"
13371 <<
"We can only handle up to three sub-list of nodes\n";
13372 throw OomphLibError(
13373 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
13379 if (n_sub_list == 1 && (left_node_pt != right_node_pt))
13387 output_sorted_nodes_pt = tmp_sub_nodes;
13389 output_boundary_element_pt = tmp_sub_bnd_ele_pt;
13391 output_face_index_element = tmp_sub_face_idx_ele;
13397 if (input_connect_to_the_left == -2)
13399 std::stringstream error_message;
13401 <<
"The connection flag to the left (" << input_connect_to_the_left
13402 <<
") indicates a connection\n"
13403 <<
"with the same polyline.\n However, only one sub-polyline was "
13404 <<
"found and no loop\nwas identified\n\n";
13405 throw OomphLibError(error_message.str(),
13406 OOMPH_CURRENT_FUNCTION,
13407 OOMPH_EXCEPTION_LOCATION);
13412 if (input_connect_to_the_left == -3)
13414 output_connect_to_the_left.push_back(-1);
13418 output_connect_to_the_left.push_back(input_connect_to_the_left);
13422 if (input_connect_to_the_right == -2)
13424 std::stringstream error_message;
13426 <<
"The connection flag to the right (" << input_connect_to_the_right
13427 <<
") indicates a connection\n"
13428 <<
"with the same polyline.\n However, only one sub-polyline was "
13429 <<
"found and no loop\nwas identified\n\n";
13430 throw OomphLibError(
13431 error_message.str(),
13432 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13433 OOMPH_EXCEPTION_LOCATION);
13438 if (input_connect_to_the_right == -3)
13440 output_connect_to_the_right.push_back(-1);
13444 output_connect_to_the_right.push_back(input_connect_to_the_right);
13452 unsigned tmp_shd_bnd_id = initial_shd_bnd_id;
13460 Node* left_sub_node_pt = tmp_sub_nodes[0].front();
13461 Node* right_sub_node_pt = tmp_sub_nodes[0].back();
13464 if (left_sub_node_pt == right_sub_node_pt)
13470 std::list<Node*> first_half_node_pt;
13471 std::list<Node*> second_half_node_pt;
13473 Vector<FiniteElement*> first_half_ele_pt;
13474 Vector<FiniteElement*> second_half_ele_pt;
13476 Vector<int> first_half_face_idx;
13477 Vector<int> second_half_face_idx;
13480 const unsigned n_sub_nodes = tmp_sub_nodes[0].size();
13484 const unsigned n_sub_nodes_half =
13485 static_cast<unsigned>(n_sub_nodes / 2.0);
13490 std::list<Node*>::iterator it_sub = tmp_sub_nodes[0].begin();
13493 first_half_node_pt.push_back(*it_sub);
13499 unsigned counter_nodes = 0;
13500 unsigned counter2 = 0;
13503 for (; it_sub != tmp_sub_nodes[0].end(); it_sub++)
13506 first_half_node_pt.push_back(*it_sub);
13509 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
13510 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2 + 1]);
13512 first_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
13513 first_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2 + 1]);
13521 if (counter_nodes == n_sub_nodes_half)
13532 second_half_node_pt.push_back(*it_sub);
13538 for (; it_sub != tmp_sub_nodes[0].end(); it_sub++)
13541 second_half_node_pt.push_back(*it_sub);
13544 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
13545 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2 + 1]);
13547 second_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
13548 second_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2 + 1]);
13556 output_sorted_nodes_pt.push_back(first_half_node_pt);
13557 output_sorted_nodes_pt.push_back(second_half_node_pt);
13560 output_boundary_element_pt.push_back(first_half_ele_pt);
13561 output_boundary_element_pt.push_back(second_half_ele_pt);
13564 output_face_index_element.push_back(first_half_face_idx);
13565 output_face_index_element.push_back(second_half_face_idx);
13576 if (input_connect_to_the_left == -3)
13579 output_connect_to_the_left.push_back(-1);
13582 else if (input_connect_to_the_left == -2)
13585 output_connect_to_the_left.push_back(-1);
13590 output_connect_to_the_left.push_back(input_connect_to_the_left);
13596 output_connect_to_the_right.push_back(-1);
13607 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
13613 if (n_sub_list == 1)
13615 if (input_connect_to_the_right == -3)
13618 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13620 else if (input_connect_to_the_right == -2)
13623 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13625 else if (input_connect_to_the_right == -1)
13628 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13633 output_connect_to_the_right.push_back(input_connect_to_the_right);
13639 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13652 output_sorted_nodes_pt.push_back(tmp_sub_nodes[0]);
13655 output_boundary_element_pt.push_back(tmp_sub_bnd_ele_pt[0]);
13658 output_face_index_element.push_back(tmp_sub_face_idx_ele[0]);
13666 if (input_connect_to_the_left == -3)
13669 output_connect_to_the_left.push_back(-1);
13672 else if (input_connect_to_the_left == -2)
13675 output_connect_to_the_left.push_back(tmp_shd_bnd_id + 1);
13680 output_connect_to_the_left.push_back(input_connect_to_the_left);
13686 output_connect_to_the_right.push_back(tmp_shd_bnd_id + 1);
13694 if (n_sub_list > 1)
13698 left_sub_node_pt = tmp_sub_nodes[1].front();
13699 right_sub_node_pt = tmp_sub_nodes[1].back();
13702 if (left_sub_node_pt == right_sub_node_pt)
13708 std::list<Node*> first_half_node_pt;
13709 std::list<Node*> second_half_node_pt;
13711 Vector<FiniteElement*> first_half_ele_pt;
13712 Vector<FiniteElement*> second_half_ele_pt;
13714 Vector<int> first_half_face_idx;
13715 Vector<int> second_half_face_idx;
13718 const unsigned n_sub_nodes = tmp_sub_nodes[1].size();
13722 const unsigned n_sub_nodes_half =
13723 static_cast<unsigned>(n_sub_nodes / 2.0);
13728 std::list<Node*>::iterator it_sub = tmp_sub_nodes[1].begin();
13731 first_half_node_pt.push_back(*it_sub);
13737 unsigned counter_nodes = 0;
13738 unsigned counter2 = 0;
13741 for (; it_sub != tmp_sub_nodes[1].end(); it_sub++)
13744 first_half_node_pt.push_back(*it_sub);
13746 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2]);
13747 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2 + 1]);
13749 first_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2]);
13750 first_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2 + 1]);
13758 if (counter_nodes == n_sub_nodes_half)
13769 second_half_node_pt.push_back(*it_sub);
13775 for (; it_sub != tmp_sub_nodes[1].end(); it_sub++)
13778 second_half_node_pt.push_back(*it_sub);
13780 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2]);
13781 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2 + 1]);
13783 second_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2]);
13784 second_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2 + 1]);
13792 output_sorted_nodes_pt.push_back(first_half_node_pt);
13793 output_sorted_nodes_pt.push_back(second_half_node_pt);
13796 output_boundary_element_pt.push_back(first_half_ele_pt);
13797 output_boundary_element_pt.push_back(second_half_ele_pt);
13800 output_face_index_element.push_back(first_half_face_idx);
13801 output_face_index_element.push_back(second_half_face_idx);
13812 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
13817 output_connect_to_the_right.push_back(-1);
13828 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
13834 if (n_sub_list == 2)
13837 if (input_connect_to_the_right == -1)
13840 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13843 else if (input_connect_to_the_right == -2)
13846 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13849 else if (input_connect_to_the_right == -3)
13852 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13857 output_connect_to_the_right.push_back(input_connect_to_the_right);
13867 std::stringstream error_message;
13869 <<
"The second sub-list of nodes creates a loop but this is not\n"
13870 <<
"the last list of sub-nodes.\n"
13871 <<
"This configuration is not supported\n";
13872 throw OomphLibError(
13873 error_message.str(),
13874 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13875 OOMPH_EXCEPTION_LOCATION);
13886 output_sorted_nodes_pt.push_back(tmp_sub_nodes[1]);
13889 output_boundary_element_pt.push_back(tmp_sub_bnd_ele_pt[1]);
13892 output_face_index_element.push_back(tmp_sub_face_idx_ele[1]);
13900 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
13906 if (n_sub_list == 2)
13909 if (input_connect_to_the_right == -3)
13912 output_connect_to_the_right.push_back(-1);
13916 else if (input_connect_to_the_right == -2)
13918 std::stringstream error_message;
13920 <<
"The connection flag to the right ("
13921 << input_connect_to_the_right <<
") indicates a connection\n"
13922 <<
"with the same polyline.\n However, the second sub-list of\n"
13923 <<
"nodes was found not making a loop so no connection with\n"
13924 <<
"itself should be marked\n\n";
13925 throw OomphLibError(
13926 error_message.str(),
13927 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13928 OOMPH_EXCEPTION_LOCATION);
13934 output_connect_to_the_right.push_back(input_connect_to_the_right);
13940 output_connect_to_the_right.push_back(tmp_shd_bnd_id + 1);
13951 if (n_sub_list > 2)
13955 left_sub_node_pt = tmp_sub_nodes[2].front();
13956 right_sub_node_pt = tmp_sub_nodes[2].back();
13959 if (left_sub_node_pt == right_sub_node_pt)
13965 std::list<Node*> first_half_node_pt;
13966 std::list<Node*> second_half_node_pt;
13968 Vector<FiniteElement*> first_half_ele_pt;
13969 Vector<FiniteElement*> second_half_ele_pt;
13971 Vector<int> first_half_face_idx;
13972 Vector<int> second_half_face_idx;
13975 const unsigned n_sub_nodes = tmp_sub_nodes[2].size();
13979 const unsigned n_sub_nodes_half =
13980 static_cast<unsigned>(n_sub_nodes / 2.0);
13985 std::list<Node*>::iterator it_sub = tmp_sub_nodes[2].begin();
13988 first_half_node_pt.push_back(*it_sub);
13994 unsigned counter_nodes = 0;
13995 unsigned counter2 = 0;
13998 for (; it_sub != tmp_sub_nodes[2].end(); it_sub++)
14001 first_half_node_pt.push_back(*it_sub);
14003 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2]);
14004 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2 + 1]);
14006 first_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2]);
14007 first_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2 + 1]);
14015 if (counter_nodes == n_sub_nodes_half)
14026 second_half_node_pt.push_back(*it_sub);
14032 for (; it_sub != tmp_sub_nodes[2].end(); it_sub++)
14035 second_half_node_pt.push_back(*it_sub);
14037 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2]);
14038 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2 + 1]);
14040 second_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2]);
14041 second_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2 + 1]);
14049 output_sorted_nodes_pt.push_back(first_half_node_pt);
14050 output_sorted_nodes_pt.push_back(second_half_node_pt);
14053 output_boundary_element_pt.push_back(first_half_ele_pt);
14054 output_boundary_element_pt.push_back(second_half_ele_pt);
14057 output_face_index_element.push_back(first_half_face_idx);
14058 output_face_index_element.push_back(second_half_face_idx);
14066 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
14071 output_connect_to_the_right.push_back(-1);
14082 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
14086 if (input_connect_to_the_right == -3)
14089 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14091 else if (input_connect_to_the_right == -2)
14094 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14096 else if (input_connect_to_the_right == -1)
14099 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14104 output_connect_to_the_right.push_back(input_connect_to_the_right);
14117 output_sorted_nodes_pt.push_back(tmp_sub_nodes[2]);
14120 output_boundary_element_pt.push_back(tmp_sub_bnd_ele_pt[2]);
14123 output_face_index_element.push_back(tmp_sub_face_idx_ele[2]);
14131 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
14136 if (input_connect_to_the_right == -3)
14138 std::stringstream error_message;
14140 <<
"The connection flag to the right ("
14141 << input_connect_to_the_right <<
") indicates 'no connection and\n"
14142 <<
"stop adding nodes'.\n However, the thrid sub-list of\n"
14143 <<
"nodes must have a connection to the right with the same\n"
14144 <<
"shared polyline or with any other polyline\n\n";
14145 throw OomphLibError(
14146 error_message.str(),
14147 "TriangleMesh::break_loops_on_shared_polyline_helper()",
14148 OOMPH_EXCEPTION_LOCATION);
14150 else if (input_connect_to_the_right == -1)
14152 std::stringstream error_message;
14154 <<
"The connection flag to the right ("
14155 << input_connect_to_the_right <<
") indicates 'no connection.\n"
14156 <<
"However, the thrid sub-list of nodes must have a connection\n"
14157 <<
"to the right with the same shared polyline or with any other\n"
14159 throw OomphLibError(
14160 error_message.str(),
14161 "TriangleMesh::break_loops_on_shared_polyline_helper()",
14162 OOMPH_EXCEPTION_LOCATION);
14165 else if (input_connect_to_the_right == -2)
14168 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14173 output_connect_to_the_right.push_back(input_connect_to_the_right);
14188 template<
class ELEMENT>
14191 const unsigned& initial_shd_bnd_id,
14192 std::list<Node*>& input_nodes,
14193 Vector<FiniteElement*>& input_boundary_element_pt,
14194 Vector<FiniteElement*>& input_boundary_face_element_pt,
14195 Vector<int>& input_face_index_element,
14196 const int& input_connect_to_the_left,
14197 const int& input_connect_to_the_right,
14198 Vector<std::list<Node*>>& output_sorted_nodes_pt,
14199 Vector<Vector<FiniteElement*>>& output_boundary_element_pt,
14200 Vector<Vector<FiniteElement*>>& output_boundary_face_element_pt,
14201 Vector<Vector<int>>& output_face_index_element,
14202 Vector<int>& output_connect_to_the_left,
14203 Vector<int>& output_connect_to_the_right)
14206 Node* left_node_pt = input_nodes.front();
14207 Node* right_node_pt = input_nodes.back();
14211 Vector<std::list<Node*>> tmp_sub_nodes;
14212 Vector<Vector<FiniteElement*>> tmp_sub_bnd_ele_pt;
14213 Vector<Vector<FiniteElement*>> tmp_sub_bnd_face_ele_pt;
14214 Vector<Vector<int>> tmp_sub_face_idx_ele;
14217 std::list<Node*>::iterator it = input_nodes.begin();
14220 unsigned counter = 0;
14223 while (it != input_nodes.end())
14228 if (it == input_nodes.end())
14240 std::list<Node*> sub_nodes;
14243 Vector<FiniteElement*> sub_bnd_ele_pt;
14246 Vector<FiniteElement*> sub_bnd_face_ele_pt;
14249 Vector<int> sub_face_idx_ele;
14252 sub_nodes.push_back(*it);
14262 sub_nodes.push_back((*it));
14265 sub_bnd_ele_pt.push_back(input_boundary_element_pt[counter]);
14268 sub_bnd_face_ele_pt.push_back(input_boundary_face_element_pt[counter]);
14271 sub_face_idx_ele.push_back(input_face_index_element[counter]);
14278 }
while ((*it) != left_node_pt && (*it) != right_node_pt &&
14279 it != input_nodes.end());
14282 tmp_sub_nodes.push_back(sub_nodes);
14285 tmp_sub_bnd_ele_pt.push_back(sub_bnd_ele_pt);
14287 tmp_sub_bnd_face_ele_pt.push_back(sub_bnd_face_ele_pt);
14289 tmp_sub_face_idx_ele.push_back(sub_face_idx_ele);
14297 const unsigned n_sub_list = tmp_sub_nodes.size();
14300 if (n_sub_list > 1)
14302 std::stringstream error_message;
14304 <<
"The number of sub-list of nodes created from the shared\n"
14305 <<
"polyline with loops was (" << n_sub_list <<
").\n"
14306 <<
"We can only handle one list which may still contain loops\n"
14307 <<
"(or repeated nodes)\n";
14308 throw OomphLibError(
14309 error_message.str(),
14310 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14311 OOMPH_EXCEPTION_LOCATION);
14317 if (n_sub_list == 1 && (left_node_pt != right_node_pt))
14325 output_sorted_nodes_pt = tmp_sub_nodes;
14327 output_boundary_element_pt = tmp_sub_bnd_ele_pt;
14329 output_boundary_face_element_pt = tmp_sub_bnd_face_ele_pt;
14331 output_face_index_element = tmp_sub_face_idx_ele;
14337 if (input_connect_to_the_left == -2)
14339 std::stringstream error_message;
14341 <<
"The connection flag to the left (" << input_connect_to_the_left
14342 <<
") indicates a connection\n"
14343 <<
"with the same polyline.\n However, only one sub-polyline was "
14344 <<
"found and no loops\nwere identified\n\n";
14345 throw OomphLibError(
14346 error_message.str(),
14347 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14348 OOMPH_EXCEPTION_LOCATION);
14353 if (input_connect_to_the_left == -3)
14355 output_connect_to_the_left.push_back(-1);
14359 output_connect_to_the_left.push_back(input_connect_to_the_left);
14363 if (input_connect_to_the_right == -2)
14365 std::stringstream error_message;
14367 <<
"The connection flag to the right (" << input_connect_to_the_right
14368 <<
") indicates a connection\n"
14369 <<
"with the same polyline.\n However, only one sub-polyline was "
14370 <<
"found and no loops\nwere identified\n\n";
14371 throw OomphLibError(
14372 error_message.str(),
14373 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14374 OOMPH_EXCEPTION_LOCATION);
14379 if (input_connect_to_the_right == -3)
14381 output_connect_to_the_right.push_back(-1);
14385 output_connect_to_the_right.push_back(input_connect_to_the_right);
14393 unsigned tmp_shd_bnd_id = initial_shd_bnd_id;
14401 Node* left_sub_node_pt = tmp_sub_nodes[0].front();
14402 Node* right_sub_node_pt = tmp_sub_nodes[0].back();
14405 if (left_sub_node_pt == right_sub_node_pt)
14411 std::list<Node*> first_half_node_pt;
14412 std::list<Node*> second_half_node_pt;
14414 Vector<FiniteElement*> first_half_ele_pt;
14415 Vector<FiniteElement*> second_half_ele_pt;
14417 Vector<FiniteElement*> first_half_ele_face_pt;
14418 Vector<FiniteElement*> second_half_ele_face_pt;
14420 Vector<int> first_half_face_idx;
14421 Vector<int> second_half_face_idx;
14424 const unsigned n_sub_nodes = tmp_sub_nodes[0].size();
14428 const unsigned n_sub_nodes_half =
14429 static_cast<unsigned>(n_sub_nodes / 2.0);
14434 std::list<Node*>::iterator it_sub = tmp_sub_nodes[0].begin();
14437 first_half_node_pt.push_back(*it_sub);
14443 unsigned counter_nodes = 0;
14444 unsigned counter2 = 0;
14447 for (; it_sub != tmp_sub_nodes[0].end(); it_sub++)
14450 first_half_node_pt.push_back(*it_sub);
14453 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
14455 first_half_ele_face_pt.push_back(tmp_sub_bnd_face_ele_pt[0][counter2]);
14457 first_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
14465 if (counter_nodes == n_sub_nodes_half)
14476 second_half_node_pt.push_back(*it_sub);
14482 for (; it_sub != tmp_sub_nodes[0].end(); it_sub++)
14485 second_half_node_pt.push_back(*it_sub);
14488 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
14490 second_half_ele_face_pt.push_back(tmp_sub_bnd_face_ele_pt[0][counter2]);
14492 second_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
14500 output_sorted_nodes_pt.push_back(first_half_node_pt);
14501 output_sorted_nodes_pt.push_back(second_half_node_pt);
14504 output_boundary_element_pt.push_back(first_half_ele_pt);
14505 output_boundary_element_pt.push_back(second_half_ele_pt);
14508 output_boundary_face_element_pt.push_back(first_half_ele_face_pt);
14509 output_boundary_face_element_pt.push_back(second_half_ele_face_pt);
14512 output_face_index_element.push_back(first_half_face_idx);
14513 output_face_index_element.push_back(second_half_face_idx);
14524 if (input_connect_to_the_left == -3)
14527 output_connect_to_the_left.push_back(-1);
14530 else if (input_connect_to_the_left == -2)
14533 output_connect_to_the_left.push_back(-1);
14538 output_connect_to_the_left.push_back(input_connect_to_the_left);
14544 output_connect_to_the_right.push_back(-1);
14555 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
14561 if (n_sub_list == 1)
14563 if (input_connect_to_the_right == -3)
14566 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14568 else if (input_connect_to_the_right == -2)
14571 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14573 else if (input_connect_to_the_right == -1)
14576 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14581 output_connect_to_the_right.push_back(input_connect_to_the_right);
14587 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14597 std::stringstream error_message;
14599 <<
"The initial and final node in the current shared polyline are not\n"
14600 <<
"the same and the number of sublists is (" << n_sub_list <<
").\n"
14601 <<
"We can not handle more than one sublist in the method to break\n"
14602 <<
"loops at the load balance stage\n\n";
14603 throw OomphLibError(
14604 error_message.str(),
14605 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14606 OOMPH_EXCEPTION_LOCATION);
14616 template<
class ELEMENT>
14618 const unsigned& my_rank,
14619 const unsigned& shd_bnd_id,
14620 const unsigned& iproc,
14621 const unsigned& jproc,
14622 std::list<Node*>& sorted_nodes,
14623 const int& root_edge_bnd_id,
14624 Vector<FiniteElement*>& bulk_bnd_ele_pt,
14625 Vector<int>& face_index_ele,
14626 Vector<Vector<TriangleMeshPolyLine*>>& unsorted_polylines_pt,
14627 const int& connect_to_the_left_flag,
14628 const int& connect_to_the_right_flag)
14639 Shared_boundaries_ids[iproc][jproc].push_back(shd_bnd_id);
14642 Shared_boundaries_ids[jproc][iproc].push_back(shd_bnd_id);
14646 Vector<unsigned> processors(2);
14647 processors[0] = iproc;
14648 processors[1] = jproc;
14649 Shared_boundary_from_processors[shd_bnd_id] = processors;
14655 if (iproc == my_rank || jproc == my_rank)
14662 const unsigned n_nodes = sorted_nodes.size();
14664 Vector<Vector<double>> vertices(n_nodes);
14667 unsigned counter = 0;
14669 for (std::list<Node*>::iterator it = sorted_nodes.begin();
14670 it != sorted_nodes.end();
14673 vertices[counter].resize(2);
14674 vertices[counter][0] = (*it)->x(0);
14675 vertices[counter][1] = (*it)->x(1);
14682 TriangleMeshPolyLine* polyline_pt =
14683 new TriangleMeshPolyLine(vertices, shd_bnd_id);
14691 if (root_edge_bnd_id != -1)
14695 Shared_boundary_overlaps_internal_boundary[shd_bnd_id] =
14696 static_cast<unsigned>(root_edge_bnd_id);
14704 const unsigned n_shared_boundary_elements = bulk_bnd_ele_pt.size();
14708 const unsigned n_face_index = face_index_ele.size();
14709 if (n_shared_boundary_elements != n_face_index)
14711 std::ostringstream error_message;
14713 <<
"The number of shared boundary elements is different from the\n"
14714 <<
"number of face indexes associated to the shared boundary\n"
14716 <<
"Number of shared boundary elements: ("
14717 << n_shared_boundary_elements <<
")\n"
14718 <<
"Number of face indexes: (" << n_face_index <<
")\n\n";
14719 throw OomphLibError(error_message.str(),
14720 "TriangleMesh::create_shared_polyline()",
14721 OOMPH_EXCEPTION_LOCATION);
14727 for (
unsigned i = 0; i < n_shared_boundary_elements; i++)
14729 add_shared_boundary_element(shd_bnd_id, bulk_bnd_ele_pt[i]);
14730 add_face_index_at_shared_boundary(shd_bnd_id, face_index_ele[i]);
14734 for (std::list<Node*>::iterator it = sorted_nodes.begin();
14735 it != sorted_nodes.end();
14738 add_shared_boundary_node(shd_bnd_id, (*it));
14746 this->Boundary_curve_section_pt[shd_bnd_id] = polyline_pt;
14751 const unsigned n_procs = unsorted_polylines_pt.size();
14756 unsorted_polylines_pt[iproc].push_back(polyline_pt);
14760 unsorted_polylines_pt[jproc].push_back(polyline_pt);
14766 unsorted_polylines_pt[0].push_back(polyline_pt);
14770 this->Free_curve_section_pt.insert(polyline_pt);
14780 if (connect_to_the_left_flag < 0)
14783 if (connect_to_the_left_flag != -1)
14785 std::ostringstream error_message;
14787 <<
"The only accepted values for the connection flags are:\n"
14788 <<
"POSITIVE values or -1, any other value is rejected, please\n"
14789 <<
"check that you previously called the methods to deal with\n"
14790 <<
"other flag values\n"
14791 <<
"The current flag value for connection to the left is: ("
14792 << connect_to_the_left_flag <<
")\n\n";
14793 throw OomphLibError(error_message.str(),
14794 "TriangleMesh::create_shared_polyline()",
14795 OOMPH_EXCEPTION_LOCATION);
14800 if (connect_to_the_right_flag < 0)
14803 if (connect_to_the_right_flag != -1)
14805 std::ostringstream error_message;
14807 <<
"The only accepted values for the connection flags are:\n"
14808 <<
"POSITIVE values or -1, any other value is rejected, please\n"
14809 <<
"check that you previously called the methods to deal with\n"
14810 <<
"other flag values\n"
14811 <<
"The current flag value for connection to the right is: ("
14812 << connect_to_the_right_flag <<
")\n\n";
14813 throw OomphLibError(error_message.str(),
14814 "TriangleMesh::create_shared_polyline()",
14815 OOMPH_EXCEPTION_LOCATION);
14821 if (connect_to_the_left_flag != -1)
14824 const unsigned bnd_id_connection_to_the_left =
14825 static_cast<unsigned>(connect_to_the_left_flag);
14827 polyline_pt->set_initial_vertex_connected();
14829 polyline_pt->initial_vertex_connected_bnd_id() =
14830 bnd_id_connection_to_the_left;
14832 polyline_pt->initial_vertex_connected_n_chunk() = 0;
14837 if (connect_to_the_right_flag != -1)
14840 const unsigned bnd_id_connection_to_the_right =
14841 static_cast<unsigned>(connect_to_the_right_flag);
14843 polyline_pt->set_final_vertex_connected();
14845 polyline_pt->final_vertex_connected_bnd_id() =
14846 bnd_id_connection_to_the_right;
14848 polyline_pt->final_vertex_connected_n_chunk() = 0;
14859 template<
class ELEMENT>
14861 Vector<unsigned>& ntmp_boundary_elements,
14862 Vector<Vector<unsigned>>& ntmp_boundary_elements_in_region,
14863 Vector<FiniteElement*>& deleted_elements)
14866 const unsigned nbound = this->nboundary();
14869 const unsigned n_regions = this->nregion();
14872 for (
unsigned b = 0; b < nbound; b++)
14877 const unsigned nbound_ele = this->nboundary_element(b);
14879 Vector<FiniteElement*> backed_up_boundary_element_pt(nbound_ele);
14880 Vector<int> backed_up_face_index_at_boundary(nbound_ele);
14881 for (
unsigned e = 0; e < nbound_ele; e++)
14884 backed_up_boundary_element_pt[e] = this->boundary_element_pt(b, e);
14886 backed_up_face_index_at_boundary[e] =
14887 this->face_index_at_boundary(b, e);
14891 Vector<Vector<FiniteElement*>> backed_up_boundary_region_element_pt(
14893 Vector<Vector<int>> backed_up_face_index_at_boundary_region(n_regions);
14897 for (
unsigned ir = 0; ir < n_regions; ir++)
14900 const unsigned region_id =
14901 static_cast<unsigned>(this->region_attribute(ir));
14903 const unsigned nbnd_region_ele =
14904 this->nboundary_element_in_region(b, region_id);
14907 for (
unsigned e = 0; e < nbnd_region_ele; e++)
14910 backed_up_boundary_region_element_pt[ir][e] =
14911 this->boundary_element_in_region_pt(b, region_id, e);
14914 backed_up_face_index_at_boundary_region[ir][e] =
14915 this->face_index_at_boundary_in_region(b, region_id, e);
14921 this->Boundary_element_pt[b].clear();
14922 this->Face_index_at_boundary[b].clear();
14925 this->Boundary_region_element_pt[b].clear();
14926 this->Face_index_region_at_boundary[b].clear();
14935 const unsigned nold_bnd_ele = ntmp_boundary_elements[b];
14937 for (
unsigned e = 0; e < nold_bnd_ele; e++)
14939 FiniteElement* tmp_ele_pt = backed_up_boundary_element_pt[e];
14941 Vector<FiniteElement*>::iterator it = std::find(
14942 deleted_elements.begin(), deleted_elements.end(), tmp_ele_pt);
14945 if (it == deleted_elements.end())
14947 FiniteElement* add_ele_pt = backed_up_boundary_element_pt[e];
14948 this->Boundary_element_pt[b].push_back(add_ele_pt);
14949 const int face_index = backed_up_face_index_at_boundary[e];
14950 this->Face_index_at_boundary[b].push_back(face_index);
14958 for (
unsigned ir = 0; ir < n_regions; ir++)
14961 const unsigned region_id =
14962 static_cast<unsigned>(this->region_attribute(ir));
14965 const unsigned nold_bnd_region_ele =
14966 ntmp_boundary_elements_in_region[b][ir];
14970 for (
unsigned e = 0; e < nold_bnd_region_ele; e++)
14973 FiniteElement* tmp_ele_pt =
14974 backed_up_boundary_region_element_pt[ir][e];
14976 Vector<FiniteElement*>::iterator it = std::find(
14977 deleted_elements.begin(), deleted_elements.end(), tmp_ele_pt);
14980 if (it == deleted_elements.end())
14982 FiniteElement* add_ele_pt =
14983 backed_up_boundary_region_element_pt[ir][e];
14984 this->Boundary_region_element_pt[b][region_id].push_back(
14986 const int face_index =
14987 backed_up_face_index_at_boundary_region[ir][e];
14988 this->Face_index_region_at_boundary[b][region_id].push_back(
15001 for (
unsigned e = nold_bnd_ele; e < nbound_ele; e++)
15003 FiniteElement* add_ele_pt = backed_up_boundary_element_pt[e];
15004 this->Boundary_element_pt[b].push_back(add_ele_pt);
15005 const int face_index = backed_up_face_index_at_boundary[e];
15006 this->Face_index_at_boundary[b].push_back(face_index);
15012 for (
unsigned ir = 0; ir < n_regions; ir++)
15015 const unsigned region_id =
15016 static_cast<unsigned>(this->region_attribute(ir));
15019 const unsigned nold_bnd_region_ele =
15020 ntmp_boundary_elements_in_region[b][ir];
15023 const unsigned nbnd_region_ele =
15024 this->nboundary_element_in_region(b, region_id);
15028 for (
unsigned e = nold_bnd_region_ele; e < nbnd_region_ele; e++)
15030 FiniteElement* add_ele_pt =
15031 backed_up_boundary_region_element_pt[ir][e];
15032 this->Boundary_region_element_pt[b][region_id].push_back(add_ele_pt);
15033 const int face_index = backed_up_face_index_at_boundary_region[ir][e];
15034 this->Face_index_region_at_boundary[b][region_id].push_back(
15043 Lookup_for_elements_next_boundary_is_setup =
true;
15048 #ifdef OOMPH_HAS_TRIANGLE_LIB
15053 template<
class ELEMENT>
15055 TriangulateIO& triangulate_io,
15056 const Vector<double>& target_area,
15057 struct TriangulateIO& triangle_refine)
15060 TriangleHelper::initialise_triangulateio(triangle_refine);
15064 unsigned n_points = triangulate_io.numberofpoints;
15065 triangle_refine.numberofpoints = n_points;
15067 unsigned n_segments = triangulate_io.numberofsegments;
15068 triangle_refine.numberofsegments = n_segments;
15071 triangle_refine.pointlist =
15072 (
double*)malloc(triangulate_io.numberofpoints * 2 *
sizeof(
double));
15073 triangle_refine.pointmarkerlist =
15074 (
int*)malloc(triangulate_io.numberofpoints *
sizeof(
int));
15075 triangle_refine.segmentlist =
15076 (
int*)malloc(triangulate_io.numberofsegments * 2 *
sizeof(
int));
15077 triangle_refine.segmentmarkerlist =
15078 (
int*)malloc(triangulate_io.numberofsegments *
sizeof(
int));
15082 Vector<double> x_coord(n_points);
15083 Vector<double> y_coord(n_points);
15085 for (
unsigned count_point = 0; count_point < n_points * 2; count_point++)
15087 triangle_refine.pointlist[count_point] =
15088 triangulate_io.pointlist[count_point];
15092 if (count_point % 2 == 0)
15094 x_coord[count_point / 2] = triangulate_io.pointlist[count_point];
15098 y_coord[(count_point - 1) / 2] = triangulate_io.pointlist[count_point];
15103 for (
unsigned count_marker = 0; count_marker < n_points; count_marker++)
15105 triangle_refine.pointmarkerlist[count_marker] =
15106 triangulate_io.pointmarkerlist[count_marker];
15110 for (
unsigned count_seg = 0; count_seg < n_segments * 2; count_seg++)
15112 triangle_refine.segmentlist[count_seg] =
15113 triangulate_io.segmentlist[count_seg];
15117 for (
unsigned count_markers = 0; count_markers < n_segments;
15120 triangle_refine.segmentmarkerlist[count_markers] =
15121 triangulate_io.segmentmarkerlist[count_markers];
15125 unsigned n_holes = triangulate_io.numberofholes;
15126 triangle_refine.numberofholes = n_holes;
15128 triangle_refine.holelist =
15129 (
double*)malloc(triangulate_io.numberofholes * 2 *
sizeof(
double));
15132 for (
unsigned count_hole = 0; count_hole < n_holes * 2; count_hole++)
15134 triangle_refine.holelist[count_hole] =
15135 triangulate_io.holelist[count_hole];
15139 unsigned n_triangles = triangulate_io.numberoftriangles;
15140 triangle_refine.numberoftriangles = n_triangles;
15143 if (n_triangles != target_area.size())
15145 std::stringstream err;
15146 err <<
"Number of triangles in triangulate_io=" << n_triangles
15147 <<
" doesn't match\n"
15148 <<
"size of target area vector (" << target_area.size() <<
")\n";
15149 throw OomphLibError(
15150 err.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
15154 unsigned n_corners = triangulate_io.numberofcorners;
15155 triangle_refine.numberofcorners = n_corners;
15157 triangle_refine.trianglelist =
15158 (
int*)malloc(triangulate_io.numberoftriangles * 3 *
sizeof(
int));
15161 for (
unsigned count_tri = 0; count_tri < n_triangles * 3; count_tri++)
15163 triangle_refine.trianglelist[count_tri] =
15164 triangulate_io.trianglelist[count_tri];
15168 triangle_refine.trianglearealist =
15169 (
double*)malloc(triangulate_io.numberoftriangles *
sizeof(
double));
15170 for (
unsigned count_area = 0; count_area < n_triangles; count_area++)
15172 triangle_refine.trianglearealist[count_area] = target_area[count_area];
15176 triangle_refine.numberoftriangleattributes =
15177 triangulate_io.numberoftriangleattributes;
15179 triangle_refine.triangleattributelist = (
double*)malloc(
15180 triangulate_io.numberoftriangles *
15181 triangulate_io.numberoftriangleattributes *
sizeof(
double));
15182 for (
unsigned count_attribute = 0;
15184 (n_triangles * triangulate_io.numberoftriangleattributes);
15187 triangle_refine.triangleattributelist[count_attribute] =
15188 triangulate_io.triangleattributelist[count_attribute];
15192 #ifdef OOMPH_HAS_MPI
15206 const std::pair<double, double>& rhs)
const
15208 double diff_y = lhs.second - rhs.second;
15219 double diff_x = lhs.first - rhs.first;
15220 if (fabs(diff_x) <
Tol)
15222 std::ostringstream warning_message;
15224 <<
"Dodgy \"lower left\" (lexicographic) comparison "
15225 <<
"of points with cooordinates: "
15226 <<
" lhs = ( " << lhs.first <<
" , " << lhs.second <<
" ) \n"
15227 <<
" rhs = ( " << rhs.first <<
" , " << rhs.second <<
" ) \n"
15228 <<
"x and y coordinates differ by less than tolerance!\n"
15229 <<
"diff_x = " << diff_x <<
"\n"
15230 <<
"diff_y = " << diff_y <<
"\n"
15231 <<
"Tol = " <<
Tol <<
"\n";
15232 OomphLibError(warning_message.str(),
15233 OOMPH_CURRENT_FUNCTION,
15234 OOMPH_EXCEPTION_LOCATION);
15237 if (lhs.first < rhs.first)
15291 template<
class ELEMENT>
15295 Vector<unsigned> my_rank_shared_boundaries_ids;
15296 this->shared_boundaries_in_this_processor(my_rank_shared_boundaries_ids);
15299 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
15302 for (
unsigned i = 0; i < nmy_rank_shd_bnd; i++)
15307 std::map<std::pair<double, double>, Node*,
classcomp> sorted_nodes_pt;
15314 double min_distance_squared = DBL_MAX;
15319 const unsigned b = my_rank_shared_boundaries_ids[i];
15322 const unsigned nbnd_node = this->nshared_boundary_node(b);
15326 for (
unsigned i_node = 0; i_node < nbnd_node; i_node++)
15328 Node* node_pt = this->shared_boundary_node_pt(b, i_node);
15329 std::pair<double, double> vertex =
15330 std::make_pair(node_pt->x(0), node_pt->x(1));
15331 sorted_nodes_pt[vertex] = node_pt;
15337 for (
unsigned j_node = 0; j_node < nbnd_node; j_node++)
15339 if (i_node != j_node)
15341 Node* node2_pt = this->shared_boundary_node_pt(b, j_node);
15344 double squared_distance = 0.0;
15345 for (
unsigned ii = 0; ii < 2; ii++)
15347 squared_distance += (node_pt->x(ii) - node2_pt->x(ii)) *
15348 (node_pt->x(ii) - node2_pt->x(ii));
15350 if (squared_distance < min_distance_squared)
15352 min_distance_squared = squared_distance;
15359 std::ostringstream warning_message;
15360 warning_message <<
"Minimum distance between nodes on boundary " << b
15362 <<
"is " << sqrt(min_distance_squared)
15363 <<
" which is less than "
15364 <<
"Bottom_left_sorter.Tol = "
15366 <<
"This may screw up the ordering of the nodes on "
15367 "shared boundaries\n";
15368 OomphLibWarning(warning_message.str(),
15369 OOMPH_CURRENT_FUNCTION,
15370 OOMPH_EXCEPTION_LOCATION);
15376 unsigned counter = 0;
15378 this->Sorted_shared_boundary_node_pt[b].resize(nbnd_node);
15384 for (std::map<std::pair<double, double>, Node*>::iterator it_map =
15385 sorted_nodes_pt.begin();
15386 it_map != sorted_nodes_pt.end();
15390 this->Sorted_shared_boundary_node_pt[b][counter++] = (*it_map).second;
15401 template<
class ELEMENT>
15404 const bool update_elements,
15405 const bool flush_nodes,
15406 const bool update_nodes)
15409 const unsigned my_rank = this->communicator_pt()->my_rank();
15415 const unsigned initial_id = this->initial_shared_boundary_id();
15418 const unsigned final_id = this->final_shared_boundary_id();
15420 if (flush_elements)
15423 this->flush_shared_boundary_element();
15425 this->flush_face_index_at_shared_boundary();
15431 this->flush_shared_boundary_node();
15434 for (
unsigned b = initial_id; b < final_id; b++)
15437 Vector<unsigned> procs_from_shrd_bnd;
15438 procs_from_shrd_bnd = this->shared_boundary_from_processors(b);
15439 bool current_processor_has_b_boundary =
false;
15440 const unsigned n_procs_from_shrd_bnd = procs_from_shrd_bnd.size();
15441 for (
unsigned p = 0; p < n_procs_from_shrd_bnd; p++)
15443 if (procs_from_shrd_bnd[p] == my_rank)
15445 current_processor_has_b_boundary =
true;
15450 if (current_processor_has_b_boundary)
15452 if (update_elements)
15454 const unsigned nboundary_ele = this->nboundary_element(b);
15455 for (
unsigned e = 0; e < nboundary_ele; e++)
15459 FiniteElement* bnd_ele_pt = this->boundary_element_pt(b, e);
15460 this->add_shared_boundary_element(b, bnd_ele_pt);
15462 int face_index = this->face_index_at_boundary(b, e);
15463 this->add_face_index_at_shared_boundary(b, face_index);
15469 const unsigned nboundary_node = this->nboundary_node(b);
15470 for (
unsigned n = 0; n < nboundary_node; n++)
15472 Node* bnd_node_pt = this->boundary_node_pt(b, n);
15473 this->add_shared_boundary_node(b, bnd_node_pt);
15485 template<
class ELEMENT>
15489 unsigned nproc = this->communicator_pt()->nproc();
15491 unsigned my_rank = this->communicator_pt()->my_rank();
15494 double tt_start = 0.0;
15495 double tt_end = 0.0;
15496 if (Global_timings::Doc_comprehensive_timings)
15498 tt_start = TimingHelpers::timer();
15508 Vector<Vector<Vector<std::map<unsigned, Node*>>>>
15509 other_proc_shd_bnd_node_pt(nproc);
15511 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15514 other_proc_shd_bnd_node_pt[iproc].resize(nproc);
15515 for (
unsigned jproc = 0; jproc < nproc; jproc++)
15518 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
15519 const unsigned final_shd_bnd_id = this->final_shared_boundary_id();
15520 const unsigned nshared_bound = final_shd_bnd_id - initial_shd_bnd_id;
15521 other_proc_shd_bnd_node_pt[iproc][jproc].resize(nshared_bound);
15530 Vector<Vector<Vector<unsigned>>> global_node_names;
15534 std::map<Vector<unsigned>,
unsigned> node_name_to_global_index;
15537 Vector<Node*> global_shared_node_pt;
15541 double t_start_global_node_names_and_shared_nodes = TimingHelpers::timer();
15546 compute_global_node_names_and_shared_nodes(other_proc_shd_bnd_node_pt,
15548 node_name_to_global_index,
15549 global_shared_node_pt);
15552 const unsigned n_ele = this->nelement();
15554 if (Print_timings_level_adaptation > 1)
15558 double t_final_global_node_names_and_shared_nodes =
15559 TimingHelpers::timer() - t_start_global_node_names_and_shared_nodes;
15560 oomph_info <<
"CPU for computing global node names and shared nodes "
15561 <<
"[n_ele=" << n_ele
15562 <<
"]: " << t_final_global_node_names_and_shared_nodes
15580 double t_start_send_info_shd_nodes_on_original_bnds =
15581 TimingHelpers::timer();
15585 send_boundary_node_info_of_shared_nodes(
15586 global_node_names, node_name_to_global_index, global_shared_node_pt);
15588 if (Print_timings_level_adaptation > 1)
15593 <<
"CPU for sending info. of shared nodes on original boundaries: "
15594 << TimingHelpers::timer() - t_start_send_info_shd_nodes_on_original_bnds
15617 Vector<Vector<Vector<FiniteElement*>>> ele_with_node_on_shd_bnd_pt(nproc);
15622 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15624 const unsigned n_shd_bnd_iproc = this->nshared_boundaries(my_rank, iproc);
15625 ele_with_node_on_shd_bnd_pt[iproc].resize(n_shd_bnd_iproc);
15632 for (
unsigned e = 0; e < n_ele; e++)
15635 FiniteElement* ele_pt = this->finite_element_pt(e);
15637 const unsigned n_nodes = ele_pt->nnode();
15640 for (
unsigned n = 0; n < n_nodes; n++)
15643 Node* node_pt = ele_pt->node_pt(n);
15649 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15654 const unsigned n_shd_bnd_iproc =
15655 this->nshared_boundaries(my_rank, iproc);
15658 if (iproc != my_rank && n_shd_bnd_iproc > 0)
15662 Vector<unsigned> shd_bnd_ids =
15663 this->shared_boundaries_ids(my_rank, iproc);
15666 for (
unsigned isb = 0; isb < n_shd_bnd_iproc; isb++)
15668 const unsigned shd_bnd_id = shd_bnd_ids[isb];
15669 const unsigned n_ele_shd_bnd =
15670 this->nshared_boundary_element(shd_bnd_id);
15674 if (n_ele_shd_bnd > 0 &&
15675 this->is_node_on_shared_boundary(shd_bnd_id, node_pt))
15679 ele_with_node_on_shd_bnd_pt[iproc][isb].push_back(ele_pt);
15719 Vector<Vector<Node*>> iproc_currently_created_nodes_pt(nproc);
15722 double t_start_regenerate_halo_ed_elements_nodes_first_stage =
15723 TimingHelpers::timer();
15726 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15729 if (iproc != my_rank)
15732 const unsigned nshared_boundaries_with_iproc =
15733 this->nshared_boundaries(my_rank, iproc);
15735 if (nshared_boundaries_with_iproc > 0)
15747 Flat_packed_unsigneds.clear();
15748 Flat_packed_doubles.clear();
15749 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15750 Flat_packed_unsigneds_string.clear();
15754 Vector<unsigned> bound_shared_with_iproc;
15755 bound_shared_with_iproc = this->shared_boundaries_ids(my_rank, iproc);
15758 for (
unsigned bs = 0; bs < nshared_boundaries_with_iproc; bs++)
15760 const unsigned bnd_id = bound_shared_with_iproc[bs];
15762 const unsigned nel_bnd = this->nshared_boundary_element(bnd_id);
15766 Vector<FiniteElement*> haloed_element;
15773 std::map<FiniteElement*, bool> already_added;
15776 for (
unsigned e = 0; e < nel_bnd; e++)
15779 FiniteElement* ele_pt =
15780 this->shared_boundary_element_pt(bnd_id, e);
15785 if (!already_added[ele_pt])
15788 haloed_element.push_back(ele_pt);
15790 already_added[ele_pt] =
true;
15801 const unsigned n_ele_with_node_on_shd_bnd =
15802 ele_with_node_on_shd_bnd_pt[iproc][bs].size();
15805 for (
unsigned iele = 0; iele < n_ele_with_node_on_shd_bnd; iele++)
15808 FiniteElement* ele_pt =
15809 ele_with_node_on_shd_bnd_pt[iproc][bs][iele];
15811 if (!already_added[ele_pt])
15814 haloed_element.push_back(ele_pt);
15816 already_added[ele_pt] =
true;
15824 const unsigned nhaloed_ele = haloed_element.size();
15831 Flat_packed_unsigneds.push_back(nhaloed_ele);
15832 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15833 std::stringstream junk;
15834 junk <<
"Number of haloed elements " << nhaloed_ele;
15835 Flat_packed_unsigneds_string.push_back(junk.str());
15839 for (
unsigned e = 0; e < nhaloed_ele; e++)
15842 FiniteElement* ele_pt = haloed_element[e];
15843 const unsigned nroot_haloed_ele =
15844 this->nroot_haloed_element(iproc);
15848 GeneralisedElement* gen_ele_pt = ele_pt;
15849 const unsigned haloed_ele_index =
15850 this->try_to_add_root_haloed_element_pt(iproc, gen_ele_pt);
15854 if (nroot_haloed_ele == haloed_ele_index)
15856 Flat_packed_unsigneds.push_back(1);
15857 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15858 Flat_packed_unsigneds_string.push_back(
15859 "Haloed element needs to be constructed");
15863 get_required_elemental_information_helper(iproc, ele_pt);
15866 const unsigned nnodes = ele_pt->nnode();
15867 for (
unsigned j = 0; j < nnodes; j++)
15869 Node* node_pt = ele_pt->node_pt(j);
15873 add_haloed_node_helper(iproc, node_pt);
15879 Flat_packed_unsigneds.push_back(0);
15880 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15881 Flat_packed_unsigneds_string.push_back(
15882 "Haloed element already exists");
15884 Flat_packed_unsigneds.push_back(haloed_ele_index);
15885 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15886 Flat_packed_unsigneds_string.push_back(
15887 "Index of existing haloed element");
15901 int send_proc =
static_cast<int>(iproc);
15903 int recv_proc =
static_cast<int>(iproc);
15904 send_and_receive_elements_nodes_info(send_proc, recv_proc);
15913 Counter_for_flat_packed_doubles = 0;
15914 Counter_for_flat_packed_unsigneds = 0;
15917 for (
unsigned bs = 0; bs < nshared_boundaries_with_iproc; bs++)
15920 const unsigned nhaloed_ele =
15921 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
15923 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15925 <<
"Rec:" << Counter_for_flat_packed_unsigneds
15926 <<
" Number of elements need to be constructed "
15927 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
15932 for (
unsigned e = 0; e < nhaloed_ele; e++)
15936 create_halo_element(iproc,
15937 iproc_currently_created_nodes_pt[iproc],
15938 other_proc_shd_bnd_node_pt,
15940 node_name_to_global_index,
15941 global_shared_node_pt);
15953 if (Print_timings_level_adaptation > 1)
15956 double t_final_regenerate_halo_ed_elements_nodes_first_stage =
15957 TimingHelpers::timer() -
15958 t_start_regenerate_halo_ed_elements_nodes_first_stage;
15960 oomph_info <<
"CPU for re-generating halo(ed) elements/nodes "
15961 <<
"(first stage) [n_ele=" << n_ele <<
"]: "
15962 << t_final_regenerate_halo_ed_elements_nodes_first_stage
15979 double t_start_regenerate_halo_ed_elements_nodes_second_stage =
15980 TimingHelpers::timer();
15984 reset_halo_haloed_scheme_helper(other_proc_shd_bnd_node_pt,
15985 iproc_currently_created_nodes_pt,
15987 node_name_to_global_index,
15988 global_shared_node_pt);
15990 if (Print_timings_level_adaptation > 1)
15993 double t_final_regenerate_halo_ed_elements_nodes_second_stage =
15994 TimingHelpers::timer() -
15995 t_start_regenerate_halo_ed_elements_nodes_second_stage;
15997 oomph_info <<
"CPU for re-generating halo(ed) elements/nodes "
15998 <<
"(second stage) [n_ele=" << n_ele <<
"]: "
15999 << t_final_regenerate_halo_ed_elements_nodes_second_stage
16009 Flat_packed_unsigneds.clear();
16010 Flat_packed_doubles.clear();
16011 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
16012 Flat_packed_unsigneds_string.clear();
16017 if (Print_timings_level_adaptation > 1)
16019 tt_end = TimingHelpers::timer();
16020 oomph_info <<
"CPU for resetting halo-haloed scheme (without "
16021 "classification of halo and haloed nodes): "
16022 << tt_end - tt_start << std::endl;
16028 const bool report_stats =
true;
16029 DocInfo tmp_doc_info;
16030 tmp_doc_info.disable_doc();
16033 this->classify_halo_and_haloed_nodes(tmp_doc_info, report_stats);
16037 if (Print_timings_level_adaptation > 1)
16039 tt_end = TimingHelpers::timer();
16040 oomph_info <<
"CPU for resetting halo-haloed scheme (with classification "
16041 "of halo and haloed nodes): "
16042 << tt_end - tt_start << std::endl;
16059 template<
class ELEMENT>
16062 Vector<Vector<Vector<std::map<unsigned, Node*>>>>&
16063 other_proc_shd_bnd_node_pt,
16064 Vector<Vector<Vector<unsigned>>>& global_node_names,
16065 std::map<Vector<unsigned>,
unsigned>& node_name_to_global_index,
16066 Vector<Node*>& global_shared_node_pt)
16069 const unsigned nproc = this->communicator_pt()->nproc();
16071 const unsigned my_rank = this->communicator_pt()->my_rank();
16073 OomphCommunicator* comm_pt = this->communicator_pt();
16083 unsigned counter_nodes = 0;
16085 std::map<Node*, bool> done_node;
16087 std::map<Node*, unsigned> local_node_number;
16089 Vector<Node*> local_node_pt;
16105 Vector<Vector<Vector<unsigned>>> local_node_names;
16108 for (
unsigned iproc = 0; iproc < nproc; iproc++)
16111 if (iproc != my_rank)
16114 const unsigned n_shd_bnds_with_iproc =
16115 this->nshared_boundaries(my_rank, iproc);
16118 Vector<unsigned> bnd_shd_with_iproc =
16119 this->shared_boundaries_ids(my_rank, iproc);
16122 for (
unsigned ishd = 0; ishd < n_shd_bnds_with_iproc; ishd++)
16125 std::map<Node*, bool> done_node_shd_bnd;
16127 unsigned shd_bnd_id = bnd_shd_with_iproc[ishd];
16129 const unsigned n_shd_bnd_ele =
16130 this->nshared_boundary_element(shd_bnd_id);
16133 for (
unsigned e = 0; e < n_shd_bnd_ele; e++)
16136 FiniteElement* ele_pt =
16137 this->shared_boundary_element_pt(shd_bnd_id, e);
16140 const unsigned n_nodes = ele_pt->nnode();
16143 for (
unsigned n = 0; n < n_nodes; n++)
16146 Node* node_pt = ele_pt->node_pt(n);
16151 if (!done_node_shd_bnd[node_pt] &&
16152 this->is_node_on_shared_boundary(shd_bnd_id, node_pt))
16155 done_node_shd_bnd[node_pt] =
true;
16160 const unsigned n_nodes_shd_bnd =
16161 nsorted_shared_boundary_node(shd_bnd_id);
16164 unsigned index = 0;
16168 bool found_node_on_shared_boundary =
false;
16172 for (
unsigned k = 0; k < n_nodes_shd_bnd; k++)
16175 Node* shd_bnd_node_pt =
16176 sorted_shared_boundary_node_pt(shd_bnd_id, k);
16179 if (shd_bnd_node_pt == node_pt)
16185 found_node_on_shared_boundary =
true;
16194 if (!found_node_on_shared_boundary)
16196 std::ostringstream error_message;
16197 error_message <<
"The index of the node on boundary ("
16198 << shd_bnd_id <<
") was not found.\n"
16199 <<
"These are the node coordinates\n"
16200 <<
"(" << node_pt->x(0) <<
"," << node_pt->x(1)
16202 throw OomphLibError(error_message.str(),
16203 OOMPH_CURRENT_FUNCTION,
16204 OOMPH_EXCEPTION_LOCATION);
16209 Vector<unsigned> node_name(5);
16210 node_name[0] = my_rank;
16211 node_name[1] = iproc;
16212 node_name[2] = shd_bnd_id;
16213 node_name[3] = index;
16218 if (!done_node[node_pt])
16223 local_node_pt.push_back(node_pt);
16226 local_node_number[node_pt] = counter_nodes;
16228 node_name[4] = counter_nodes;
16232 done_node[node_pt] =
true;
16236 Vector<Vector<unsigned>> first_node_name(1);
16237 first_node_name[0] = node_name;
16238 local_node_names.push_back(first_node_name);
16245 unsigned node_number = local_node_number[node_pt];
16248 node_name[4] = node_number;
16252 local_node_names[node_number].push_back(node_name);
16277 unsigned n_total_local_names = 0;
16279 const unsigned n_local_nodes = local_node_names.size();
16282 for (
unsigned i = 0; i < n_local_nodes; i++)
16285 const unsigned n_inode_names = local_node_names[i].size();
16287 n_total_local_names += n_inode_names;
16292 const unsigned n_info_per_node_name = 5;
16294 Vector<unsigned> flat_packed_send_udata(n_total_local_names *
16295 n_info_per_node_name);
16297 unsigned counter = 0;
16299 for (
unsigned i = 0; i < n_local_nodes; i++)
16302 const unsigned n_inode_names = local_node_names[i].size();
16304 for (
unsigned j = 0; j < n_inode_names; j++)
16307 flat_packed_send_udata[counter++] = local_node_names[i][j][0];
16309 flat_packed_send_udata[counter++] = local_node_names[i][j][1];
16311 flat_packed_send_udata[counter++] = local_node_names[i][j][2];
16313 flat_packed_send_udata[counter++] = local_node_names[i][j][3];
16315 flat_packed_send_udata[counter++] = local_node_names[i][j][4];
16325 const unsigned n_udata_send_to_root = flat_packed_send_udata.size();
16338 const unsigned root_processor = 0;
16342 Vector<unsigned> root_n_names_per_processor(nproc);
16346 MPI_Gather(&n_total_local_names,
16349 &root_n_names_per_processor[0],
16353 comm_pt->mpi_comm());
16357 unsigned root_n_total_udata_receive = 0;
16358 Vector<int> root_n_udata_to_receive(nproc, 0);
16359 for (
unsigned iproc = 0; iproc < nproc; iproc++)
16361 root_n_udata_to_receive[iproc] =
16362 root_n_names_per_processor[iproc] * n_info_per_node_name;
16363 root_n_total_udata_receive += root_n_udata_to_receive[iproc];
16368 Vector<int> root_uoffsets_receive(nproc, 0);
16369 root_uoffsets_receive[0] = 0;
16370 for (
unsigned iproc = 1; iproc < nproc; iproc++)
16373 root_uoffsets_receive[iproc] =
16374 root_uoffsets_receive[iproc - 1] + root_n_udata_to_receive[iproc - 1];
16378 if (flat_packed_send_udata.size() == 0)
16380 flat_packed_send_udata.resize(1);
16384 Vector<unsigned> root_flat_packed_receive_udata(root_n_total_udata_receive);
16387 if (my_rank != root_processor)
16390 if (root_flat_packed_receive_udata.size() == 0)
16392 root_flat_packed_receive_udata.resize(1);
16397 MPI_Gatherv(&flat_packed_send_udata[0],
16400 n_udata_send_to_root,
16403 &root_flat_packed_receive_udata[0],
16407 &root_n_udata_to_receive[0],
16410 &root_uoffsets_receive[0],
16416 comm_pt->mpi_comm());
16419 flat_packed_send_udata.clear();
16420 flat_packed_send_udata.resize(0);
16428 Vector<unsigned> flat_packed_root_send_receive_udata;
16434 if (my_rank == root_processor)
16440 Vector<Vector<Vector<unsigned>>> root_global_node_names;
16446 Vector<Vector<unsigned>> root_local_node_names;
16449 unsigned rcounter = 0;
16451 for (
unsigned iproc = 0; iproc < nproc; iproc++)
16454 const unsigned n_local_names_iproc = root_n_names_per_processor[iproc];
16455 for (
unsigned i = 0; i < n_local_names_iproc; i++)
16458 Vector<unsigned> node_name(n_info_per_node_name);
16459 for (
unsigned j = 0; j < n_info_per_node_name; j++)
16461 node_name[j] = root_flat_packed_receive_udata[rcounter++];
16465 root_local_node_names.push_back(node_name);
16472 const unsigned n_root_local_node_names = root_local_node_names.size();
16484 Vector<unsigned> node_name_counter_part(n_root_local_node_names);
16487 std::map<Vector<unsigned>,
bool> done_name;
16491 for (
unsigned i = 0; i < n_root_local_node_names; i++)
16494 Vector<unsigned> node_name = root_local_node_names[i];
16497 if (!done_name[node_name])
16500 done_name[node_name] =
true;
16504 bool found_both_names_node =
false;
16509 for (
unsigned j = i + 1; j < n_root_local_node_names; j++)
16511 Vector<unsigned> node_name_r = root_local_node_names[j];
16514 if (!done_name[node_name_r])
16518 if (node_name[0] == node_name_r[1] &&
16519 node_name[1] == node_name_r[0] &&
16520 node_name[2] == node_name_r[2] &&
16521 node_name[3] == node_name_r[3])
16524 done_name[node_name_r] =
true;
16527 node_name_counter_part[i] = j;
16530 node_name_counter_part[j] = i;
16533 found_both_names_node =
true;
16545 if (!found_both_names_node)
16547 std::ostringstream error_message;
16548 error_message <<
"The counter-part of the current name node was "
16549 <<
"not found,\nthe current node name is:\n"
16550 <<
"iproc:(" << node_name[0] <<
")\n"
16551 <<
"jproc:(" << node_name[1] <<
")\n"
16552 <<
"ishd_bnd:(" << node_name[2] <<
")\n"
16553 <<
"index:(" << node_name[3] <<
")\n";
16554 throw OomphLibError(error_message.str(),
16555 OOMPH_CURRENT_FUNCTION,
16556 OOMPH_EXCEPTION_LOCATION);
16572 for (
unsigned i = 0; i < n_root_local_node_names; i++)
16575 Vector<unsigned> node_name = root_local_node_names[i];
16578 if (!done_name[node_name])
16581 Vector<Vector<unsigned>> all_node_names;
16584 all_node_names.push_back(node_name);
16587 unsigned idx_c = node_name_counter_part[i];
16589 Vector<unsigned> node_name_r = root_local_node_names[idx_c];
16592 all_node_names.push_back(node_name_r);
16598 unsigned n_current_names = all_node_names.size();
16601 unsigned icounter = 0;
16604 while (icounter < n_current_names)
16607 Vector<unsigned> current_node_name = all_node_names[icounter];
16612 if (!done_name[current_node_name])
16615 done_name[current_node_name] =
true;
16620 for (
unsigned j = i + 1; j < n_root_local_node_names; j++)
16623 Vector<unsigned> other_node_name = root_local_node_names[j];
16626 if (!done_name[other_node_name])
16629 if ((current_node_name[0] == other_node_name[0]) &&
16630 (current_node_name[4] == other_node_name[4]))
16635 done_name[other_node_name] =
true;
16638 Vector<Vector<unsigned>>::iterator it =
16639 std::find(all_node_names.begin(),
16640 all_node_names.end(),
16642 if (it == all_node_names.end())
16644 all_node_names.push_back(other_node_name);
16646 unsigned k = node_name_counter_part[j];
16648 Vector<unsigned> other_node_name_r =
16649 root_local_node_names[k];
16653 if (!done_name[other_node_name_r])
16655 all_node_names.push_back(other_node_name_r);
16669 n_current_names = all_node_names.size();
16677 root_global_node_names.push_back(all_node_names);
16690 flat_packed_root_send_receive_udata.clear();
16692 const unsigned n_global_nodes = root_global_node_names.size();
16695 flat_packed_root_send_receive_udata.push_back(n_global_nodes);
16698 for (
unsigned i = 0; i < n_global_nodes; i++)
16701 Vector<Vector<unsigned>> global_inode_names = root_global_node_names[i];
16703 const unsigned n_names_global_inode = global_inode_names.size();
16706 flat_packed_root_send_receive_udata.push_back(n_names_global_inode);
16708 for (
unsigned j = 0; j < n_names_global_inode; j++)
16711 for (
unsigned k = 0; k < n_info_per_node_name; k++)
16715 flat_packed_root_send_receive_udata.push_back(
16716 global_inode_names[j][k]);
16737 unsigned root_n_udata_sent_to_all_proc =
16738 flat_packed_root_send_receive_udata.size();
16740 MPI_Bcast(&root_n_udata_sent_to_all_proc,
16745 comm_pt->mpi_comm());
16748 if (my_rank != root_processor)
16750 flat_packed_root_send_receive_udata.resize(root_n_udata_sent_to_all_proc);
16754 MPI_Bcast(&flat_packed_root_send_receive_udata[0],
16758 root_n_udata_sent_to_all_proc,
16763 comm_pt->mpi_comm());
16768 const unsigned n_global_nodes =
16769 flat_packed_root_send_receive_udata[counter++];
16776 global_node_names.resize(n_global_nodes);
16778 unsigned n_read_global_nodes = 0;
16779 while (n_read_global_nodes < n_global_nodes)
16782 const unsigned n_names_global_inode =
16783 flat_packed_root_send_receive_udata[counter++];
16785 const unsigned i = n_read_global_nodes;
16787 global_node_names[i].resize(n_names_global_inode);
16789 for (
unsigned j = 0; j < n_names_global_inode; j++)
16792 global_node_names[i][j].resize(n_info_per_node_name);
16795 for (
unsigned k = 0; k < n_info_per_node_name; k++)
16799 global_node_names[i][j][k] =
16800 flat_packed_root_send_receive_udata[counter++];
16806 Vector<unsigned> node_name(n_info_per_node_name - 1);
16807 node_name[0] = global_node_names[i][j][0];
16808 node_name[1] = global_node_names[i][j][1];
16809 node_name[2] = global_node_names[i][j][2];
16810 node_name[3] = global_node_names[i][j][3];
16815 node_name_to_global_index[node_name] = i;
16820 n_read_global_nodes++;
16826 if (counter != root_n_udata_sent_to_all_proc)
16828 std::ostringstream error_stream;
16830 <<
"The info. received from root regarding the global names of "
16831 <<
"the nodes\nwas not completely read.\n"
16832 <<
"The number of data sent/received from root is: ("
16833 << root_n_udata_sent_to_all_proc <<
")\n"
16834 <<
"The number of data read from the received info. is: (" << counter
16836 throw OomphLibError(
16837 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
16855 global_shared_node_pt.resize(n_global_nodes, 0);
16858 for (
unsigned i = 0; i < n_global_nodes; i++)
16862 bool is_this_a_local_node_name =
false;
16863 unsigned local_node_number;
16865 const unsigned n_names_global_inode = global_node_names[i].size();
16867 for (
unsigned j = 0; j < n_names_global_inode; j++)
16870 const unsigned iproc = global_node_names[i][j][0];
16871 local_node_number = global_node_names[i][j][4];
16874 if (my_rank == iproc)
16877 is_this_a_local_node_name =
true;
16886 if (is_this_a_local_node_name)
16891 const unsigned n_names_local_node =
16892 local_node_names[local_node_number].size();
16893 unsigned n_names_found_on_global_name_node = 0;
16898 global_shared_node_pt[i] = local_node_pt[local_node_number];
16904 for (
unsigned j = 0; j < n_names_global_inode; j++)
16907 const unsigned iproc = global_node_names[i][j][0];
16910 if (iproc != my_rank)
16913 local_node_names[local_node_number].push_back(
16914 global_node_names[i][j]);
16919 const unsigned jproc = global_node_names[i][j][1];
16920 const unsigned ishd_bnd = global_node_names[i][j][2];
16921 const unsigned idx = global_node_names[i][j][3];
16922 const unsigned n_local_node = global_node_names[i][j][4];
16924 for (
unsigned k = 0; k < n_names_local_node; k++)
16926 if ((local_node_names[local_node_number][k][0] == iproc) &&
16927 (local_node_names[local_node_number][k][1] == jproc) &&
16928 (local_node_names[local_node_number][k][2] == ishd_bnd) &&
16929 (local_node_names[local_node_number][k][3] == idx) &&
16930 (local_node_names[local_node_number][k][4] == n_local_node))
16934 n_names_found_on_global_name_node++;
16948 if (n_names_local_node != n_names_found_on_global_name_node)
16950 std::ostringstream error_stream;
16951 error_stream <<
"The local node names corresponding to the local "
16952 <<
"node (" << local_node_number <<
") were\n"
16953 <<
"not found on the global node names.\n\n"
16954 <<
"These are the names of the local node\n"
16955 <<
"Name k: iproc, jproc, ishd_bnd, idx. #node\n";
16956 for (
unsigned k = 0; k < n_names_local_node; k++)
16958 error_stream <<
"Name(" << k
16959 <<
"): " << local_node_names[local_node_number][k][0]
16960 <<
", " << local_node_names[local_node_number][k][1]
16961 <<
", " << local_node_names[local_node_number][k][2]
16962 <<
", " << local_node_names[local_node_number][k][3]
16963 <<
", " << local_node_names[local_node_number][k][4]
16967 error_stream <<
"\n\nThese are the names of the global node\n"
16968 <<
"Name k: iproc, jproc, ishd_bnd, idx. #node\n";
16969 for (
unsigned k = 0; k < n_names_global_inode; k++)
16971 error_stream <<
"Name(" << k <<
"): " << global_node_names[i][k][0]
16972 <<
", " << global_node_names[i][k][1] <<
", "
16973 << global_node_names[i][k][2] <<
", "
16974 << global_node_names[i][k][3] <<
", "
16975 << global_node_names[i][k][4] <<
"\n";
16978 throw OomphLibError(error_stream.str(),
16979 OOMPH_CURRENT_FUNCTION,
16980 OOMPH_EXCEPTION_LOCATION);
17006 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
17009 for (
unsigned i = 0; i < n_local_nodes; i++)
17012 const unsigned n_names = local_node_names[i].size();
17016 Node* node_pt = local_node_pt[i];
17019 for (
unsigned j = 0; j < n_names; j++)
17022 const unsigned iproc = local_node_names[i][j][0];
17023 const unsigned jproc = local_node_names[i][j][1];
17024 const unsigned ishd_bnd =
17025 local_node_names[i][j][2] - initial_shd_bnd_id;
17026 const unsigned index = local_node_names[i][j][3];
17033 other_proc_shd_bnd_node_pt[iproc][jproc][ishd_bnd][index] = node_pt;
17037 other_proc_shd_bnd_node_pt[jproc][iproc][ishd_bnd][index] = node_pt;
17055 template<
class ELEMENT>
17057 Vector<Vector<Vector<unsigned>>>& global_node_names,
17058 std::map<Vector<unsigned>,
unsigned>& node_name_to_global_index,
17059 Vector<Node*>& global_shared_node_pt)
17062 const unsigned nproc = this->communicator_pt()->nproc();
17063 const unsigned my_rank = this->communicator_pt()->my_rank();
17066 const unsigned n_nodes_on_shd_bnds = global_node_names.size();
17073 Vector<std::set<Node*>> node_on_shd_bnd_pt(nproc);
17077 std::map<Node*, unsigned> node_pt_to_global_shd_bnd_index;
17081 for (
unsigned i = 0; i < n_nodes_on_shd_bnds; i++)
17085 const unsigned n_names = global_node_names[i].size();
17087 for (
unsigned j = 0; j < n_names; j++)
17090 Vector<unsigned> node_name(4);
17091 node_name[0] = global_node_names[i][j][0];
17092 node_name[1] = global_node_names[i][j][1];
17093 node_name[2] = global_node_names[i][j][2];
17094 node_name[3] = global_node_names[i][j][3];
17097 if (node_name[0] == my_rank)
17100 const unsigned jproc = node_name[1];
17103 std::map<Vector<unsigned>,
unsigned>::iterator it =
17104 node_name_to_global_index.find(node_name);
17105 if (it != node_name_to_global_index.end())
17109 if (i != (*it).second)
17111 std::ostringstream error_message;
17113 <<
"The global node number " << (*it).second
17114 <<
") obtained from the current node\n"
17115 <<
"name is not the same as the current node number (" << i
17118 <<
"iproc:" << node_name[0] <<
"\n"
17119 <<
"jproc:" << node_name[1] <<
"\n"
17120 <<
"shd_bnd_id:" << node_name[2] <<
"\n"
17121 <<
"index:" << node_name[3] <<
"\n\n";
17122 throw OomphLibError(error_message.str(),
17123 OOMPH_CURRENT_FUNCTION,
17124 OOMPH_EXCEPTION_LOCATION);
17129 std::ostringstream error_message;
17131 <<
"The node name is not registerd as living in this processor.\n"
17133 <<
"iproc:" << node_name[0] <<
"\n"
17134 <<
"jproc:" << node_name[1] <<
"\n"
17135 <<
"shd_bnd_id:" << node_name[2] <<
"\n"
17136 <<
"index:" << node_name[3] <<
"\n\n";
17137 throw OomphLibError(error_message.str(),
17138 OOMPH_CURRENT_FUNCTION,
17139 OOMPH_EXCEPTION_LOCATION);
17145 Node* node_pt = global_shared_node_pt[i];
17150 std::ostringstream error_message;
17151 error_message <<
"There is not global shared node within this\n"
17152 <<
"global node number (" << i
17153 <<
"). The global shared\n"
17154 <<
"node pointer is null\n\n";
17155 throw OomphLibError(error_message.str(),
17156 OOMPH_CURRENT_FUNCTION,
17157 OOMPH_EXCEPTION_LOCATION);
17163 node_on_shd_bnd_pt[jproc].insert(node_pt);
17166 node_pt_to_global_shd_bnd_index[node_pt] = i;
17169 else if (node_name[1] == my_rank)
17172 const unsigned jproc = node_name[0];
17175 std::map<Vector<unsigned>,
unsigned>::iterator it =
17176 node_name_to_global_index.find(node_name);
17177 if (it != node_name_to_global_index.end())
17181 if (i != (*it).second)
17183 std::ostringstream error_message;
17185 <<
"The global node number " << (*it).second
17186 <<
") obtained from the current node\n"
17187 <<
"name is not the same as the current node number (" << i
17190 <<
"iproc:" << node_name[0] <<
"\n"
17191 <<
"jproc:" << node_name[1] <<
"\n"
17192 <<
"shd_bnd_id:" << node_name[2] <<
"\n"
17193 <<
"index:" << node_name[3] <<
"\n\n";
17194 throw OomphLibError(error_message.str(),
17195 OOMPH_CURRENT_FUNCTION,
17196 OOMPH_EXCEPTION_LOCATION);
17201 std::ostringstream error_message;
17203 <<
"The node name is not registerd as living in this processor.\n"
17205 <<
"iproc:" << node_name[0] <<
"\n"
17206 <<
"jproc:" << node_name[1] <<
"\n"
17207 <<
"shd_bnd_id:" << node_name[2] <<
"\n"
17208 <<
"index:" << node_name[3] <<
"\n\n";
17209 throw OomphLibError(error_message.str(),
17210 OOMPH_CURRENT_FUNCTION,
17211 OOMPH_EXCEPTION_LOCATION);
17217 Node* node_pt = global_shared_node_pt[i];
17222 std::ostringstream error_message;
17223 error_message <<
"There is not global shared node within this\n"
17224 <<
"global node number (" << i
17225 <<
"). The global shared\n"
17226 <<
"node pointer is null\n\n";
17227 throw OomphLibError(error_message.str(),
17228 OOMPH_CURRENT_FUNCTION,
17229 OOMPH_EXCEPTION_LOCATION);
17235 node_on_shd_bnd_pt[jproc].insert(node_pt);
17238 node_pt_to_global_shd_bnd_index[node_pt] = i;
17255 Vector<Vector<unsigned>> global_node_on_shared_bound(nproc);
17258 Vector<Vector<Vector<unsigned>>> global_node_original_boundaries(nproc);
17261 Vector<Vector<Vector<double>>> global_node_zeta_coordinate(nproc);
17264 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17267 std::set<Node*> nodes_shared_pt = node_on_shd_bnd_pt[iproc];
17270 for (std::set<Node*>::iterator it = nodes_shared_pt.begin();
17271 it != nodes_shared_pt.end();
17275 Node* node_pt = (*it);
17277 Vector<unsigned> on_original_boundaries;
17280 Vector<double> zeta_coordinate;
17282 const unsigned n_bnd = this->initial_shared_boundary_id();
17285 for (
unsigned bb = 0; bb < n_bnd; bb++)
17288 if (node_pt->is_on_boundary(bb))
17291 on_original_boundaries.push_back(bb);
17293 Vector<double> zeta(1);
17294 node_pt->get_coordinates_on_boundary(bb, zeta);
17296 zeta_coordinate.push_back(zeta[0]);
17302 if (on_original_boundaries.size() > 0)
17305 std::map<Node*, unsigned>::iterator it_index =
17306 node_pt_to_global_shd_bnd_index.find(node_pt);
17308 if (it_index == node_pt_to_global_shd_bnd_index.end())
17310 std::ostringstream error_message;
17312 <<
"We could not find the global shared node index associated\n"
17313 <<
"with the node pointer with vertices coordinates:\n"
17314 <<
"(" << node_pt->x(0) <<
", " << node_pt->x(1) <<
")\n\n";
17315 throw OomphLibError(error_message.str(),
17316 OOMPH_CURRENT_FUNCTION,
17317 OOMPH_EXCEPTION_LOCATION);
17321 const unsigned global_shared_node_number = (*it_index).second;
17323 global_node_on_shared_bound[iproc].push_back(
17324 global_shared_node_number);
17326 global_node_original_boundaries[iproc].push_back(
17327 on_original_boundaries);
17329 global_node_zeta_coordinate[iproc].push_back(zeta_coordinate);
17349 OomphCommunicator* comm_pt = this->communicator_pt();
17353 MPI_Request request;
17356 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17359 const unsigned n_shd_nodes_my_rank_iproc =
17360 node_on_shd_bnd_pt[iproc].size();
17364 if (n_shd_nodes_my_rank_iproc > 0 && iproc != my_rank)
17367 Vector<unsigned> flat_package_unsigned_send;
17370 flat_package_unsigned_send.push_back(n_shd_nodes_my_rank_iproc);
17373 const unsigned n_global_shared_node_on_original_boundary =
17374 global_node_on_shared_bound[iproc].size();
17378 flat_package_unsigned_send.push_back(
17379 n_global_shared_node_on_original_boundary);
17383 Vector<double> flat_package_double_send;
17386 for (
unsigned i = 0; i < n_global_shared_node_on_original_boundary; i++)
17389 const unsigned global_shared_node_index =
17390 global_node_on_shared_bound[iproc][i];
17394 flat_package_unsigned_send.push_back(global_shared_node_index);
17397 Vector<unsigned> on_original_boundaries =
17398 global_node_original_boundaries[iproc][i];
17401 Vector<double> zeta_coordinate =
17402 global_node_zeta_coordinate[iproc][i];
17406 const unsigned n_original_boundaries = on_original_boundaries.size();
17410 flat_package_unsigned_send.push_back(n_original_boundaries);
17414 for (
unsigned j = 0; j < n_original_boundaries; j++)
17418 flat_package_unsigned_send.push_back(on_original_boundaries[j]);
17420 flat_package_double_send.push_back(zeta_coordinate[j]);
17428 const unsigned n_udata_send = flat_package_unsigned_send.size();
17429 int n_udata_send_int = n_udata_send;
17432 MPI_Isend(&n_udata_send_int,
17437 comm_pt->mpi_comm(),
17440 int n_udata_received_int = 0;
17441 MPI_Recv(&n_udata_received_int,
17446 comm_pt->mpi_comm(),
17448 MPI_Wait(&request, MPI_STATUS_IGNORE);
17450 if (n_udata_send != 0)
17452 MPI_Isend(&flat_package_unsigned_send[0],
17457 comm_pt->mpi_comm(),
17461 const unsigned n_udata_received =
17462 static_cast<unsigned>(n_udata_received_int);
17465 Vector<unsigned> flat_package_unsigned_receive(n_udata_received);
17467 if (n_udata_received != 0)
17469 MPI_Recv(&flat_package_unsigned_receive[0],
17474 comm_pt->mpi_comm(),
17478 if (n_udata_send != 0)
17480 MPI_Wait(&request, MPI_STATUS_IGNORE);
17486 const unsigned n_ddata_send = flat_package_double_send.size();
17487 int n_ddata_send_int = n_ddata_send;
17490 MPI_Isend(&n_ddata_send_int,
17495 comm_pt->mpi_comm(),
17498 int n_ddata_received_int = 0;
17499 MPI_Recv(&n_ddata_received_int,
17504 comm_pt->mpi_comm(),
17506 MPI_Wait(&request, MPI_STATUS_IGNORE);
17508 if (n_ddata_send != 0)
17510 MPI_Isend(&flat_package_double_send[0],
17515 comm_pt->mpi_comm(),
17519 const unsigned n_ddata_received =
17520 static_cast<unsigned>(n_ddata_received_int);
17523 Vector<double> flat_package_double_receive(n_ddata_received);
17525 if (n_ddata_received != 0)
17527 MPI_Recv(&flat_package_double_receive[0],
17532 comm_pt->mpi_comm(),
17536 if (n_ddata_send != 0)
17538 MPI_Wait(&request, MPI_STATUS_IGNORE);
17546 unsigned n_shared_nodes_received = flat_package_unsigned_receive[0];
17550 n_shared_nodes_received++;
17551 n_shared_nodes_received--;
17554 if (n_shd_nodes_my_rank_iproc != n_shared_nodes_received)
17556 std::ostringstream error_message;
17558 <<
"The number of shared nodes between the pair of processors is\n"
17559 <<
"not the same\n"
17560 <<
"N.shared nodes proc (" << my_rank <<
") with proc (" << iproc
17561 <<
"): (" << n_shd_nodes_my_rank_iproc <<
"\n"
17562 <<
"N.shared nodes proc (" << iproc <<
") with proc (" << my_rank
17563 <<
"): (" << n_shared_nodes_received <<
"\n\n"
17564 <<
"You should have got the same error in proc: (" << iproc
17566 throw OomphLibError(error_message.str(),
17567 OOMPH_CURRENT_FUNCTION,
17568 OOMPH_EXCEPTION_LOCATION);
17581 unsigned current_index_data = 2;
17582 unsigned current_index_ddata = 0;
17583 while (current_index_data < n_udata_received)
17586 const unsigned global_shared_node_index =
17587 flat_package_unsigned_receive[current_index_data++];
17594 const unsigned n_original_boundaries =
17595 flat_package_unsigned_receive[current_index_data++];
17598 node_pt = global_shared_node_pt[global_shared_node_index];
17602 std::ostringstream error_message;
17604 <<
"The global shared node (" << global_shared_node_index <<
") "
17605 <<
"could not be found in this processor!!!\n"
17606 <<
"However, it was found in processor (" << iproc <<
"). The "
17607 <<
"data may be no synchronised,\ntherefore "
17608 <<
"we may be looking for a global shared node number that "
17609 <<
"do not\ncorrespond with the one that was sent by "
17610 <<
"processor (" << iproc <<
")\n\n";
17611 throw OomphLibError(error_message.str(),
17612 OOMPH_CURRENT_FUNCTION,
17613 OOMPH_EXCEPTION_LOCATION);
17619 for (
unsigned i = 0; i < n_original_boundaries; i++)
17623 const unsigned original_bound_id =
17624 flat_package_unsigned_receive[current_index_data++];
17627 this->add_boundary_node(original_bound_id, node_pt);
17630 Vector<double> zeta(1);
17631 zeta[0] = flat_package_double_receive[current_index_ddata++];
17632 node_pt->set_coordinates_on_boundary(original_bound_id, zeta);
17654 template<
class ELEMENT>
17656 Vector<Vector<Vector<std::map<unsigned, Node*>>>>&
17657 other_proc_shd_bnd_node_pt,
17658 Vector<Vector<Node*>>& iproc_currently_created_nodes_pt,
17659 Vector<Vector<Vector<unsigned>>>& global_node_names,
17660 std::map<Vector<unsigned>,
unsigned>& node_name_to_global_index,
17661 Vector<Node*>& global_shared_node_pt)
17664 const unsigned nproc = this->communicator_pt()->nproc();
17665 const unsigned my_rank = this->communicator_pt()->my_rank();
17673 std::map<Node*, bool> is_global_shared_node;
17674 std::map<Node*, unsigned> global_shared_node_index;
17677 const unsigned n_global_shared_nodes = global_shared_node_pt.size();
17679 for (
unsigned i = 0; i < n_global_shared_nodes; i++)
17682 Node* node_pt = global_shared_node_pt[i];
17684 is_global_shared_node[node_pt] =
true;
17686 global_shared_node_index[node_pt] = i;
17706 Vector<std::set<GeneralisedElement*>> additional_elements_pt(nproc);
17709 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17711 if (iproc != my_rank)
17714 Vector<GeneralisedElement*> haloed_ele_pt =
17715 this->root_haloed_element_pt(iproc);
17718 const unsigned n_haloed_ele = this->nroot_haloed_element(iproc);
17721 for (
unsigned ihd = 0; ihd < n_haloed_ele; ihd++)
17724 GeneralisedElement* gele_pt = haloed_ele_pt[ihd];
17726 FiniteElement* ele_pt =
dynamic_cast<FiniteElement*
>(gele_pt);
17728 const unsigned n_nodes = ele_pt->nnode();
17730 for (
unsigned n = 0; n < n_nodes; n++)
17733 Node* node_pt = ele_pt->node_pt(n);
17735 if (is_global_shared_node[node_pt])
17738 const unsigned global_index = global_shared_node_index[node_pt];
17740 Vector<Vector<unsigned>> iglobal_names =
17741 global_node_names[global_index];
17744 const unsigned n_names = iglobal_names.size();
17748 for (
unsigned j = 0; j < n_names; j++)
17752 const unsigned proc1 = iglobal_names[j][0];
17753 const unsigned proc2 = iglobal_names[j][1];
17756 additional_elements_pt[proc1].insert(gele_pt);
17757 additional_elements_pt[proc2].insert(gele_pt);
17777 Vector<Vector<FiniteElement*>> send_haloed_ele_pt(nproc);
17780 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17782 if (iproc != my_rank)
17786 std::set<GeneralisedElement*> iproc_ele_pt =
17787 additional_elements_pt[iproc];
17790 for (std::set<GeneralisedElement*>::iterator it = iproc_ele_pt.begin();
17791 it != iproc_ele_pt.end();
17795 GeneralisedElement* gele_pt = (*it);
17798 Vector<GeneralisedElement*> haloed_ele_pt =
17799 this->root_haloed_element_pt(iproc);
17802 const unsigned n_haloed_ele = this->nroot_haloed_element(iproc);
17806 bool send_ele_to_iproc_processor =
true;
17811 for (
unsigned ihd = 0; ihd < n_haloed_ele; ihd++)
17814 GeneralisedElement* ghd_ele_pt = haloed_ele_pt[ihd];
17815 if (gele_pt == ghd_ele_pt)
17818 send_ele_to_iproc_processor =
false;
17827 if (send_ele_to_iproc_processor)
17830 FiniteElement* ele_pt =
dynamic_cast<FiniteElement*
>(gele_pt);
17833 send_haloed_ele_pt[iproc].push_back(ele_pt);
17855 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17858 if (iproc != my_rank)
17861 const unsigned n_additional_haloed_ele =
17862 send_haloed_ele_pt[iproc].size();
17865 Flat_packed_unsigneds.clear();
17866 Flat_packed_doubles.clear();
17867 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17868 Flat_packed_unsigneds_string.clear();
17874 Flat_packed_unsigneds.push_back(n_additional_haloed_ele);
17875 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17876 std::stringstream junk;
17877 junk <<
"Number of haloed elements " << nhaloed_ele;
17878 Flat_packed_unsigneds_string.push_back(junk.str());
17882 for (
unsigned e = 0; e < n_additional_haloed_ele; e++)
17885 FiniteElement* ele_pt = send_haloed_ele_pt[iproc][e];
17886 const unsigned nroot_haloed_ele = this->nroot_haloed_element(iproc);
17892 GeneralisedElement* gen_ele_pt = ele_pt;
17894 const unsigned haloed_ele_index =
17895 this->try_to_add_root_haloed_element_pt(iproc, gen_ele_pt);
17899 if (nroot_haloed_ele == haloed_ele_index)
17901 Flat_packed_unsigneds.push_back(1);
17902 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17903 Flat_packed_unsigneds_string.push_back(
17904 "Haloed element needs to be constructed");
17908 get_required_elemental_information_helper(iproc, ele_pt);
17911 const unsigned nnodes = ele_pt->nnode();
17912 for (
unsigned j = 0; j < nnodes; j++)
17914 Node* node_pt = ele_pt->node_pt(j);
17918 add_haloed_node_helper(iproc, node_pt);
17925 Flat_packed_unsigneds.push_back(0);
17926 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17927 Flat_packed_unsigneds_string.push_back(
17928 "Haloed element already exists");
17930 Flat_packed_unsigneds.push_back(haloed_ele_index);
17931 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17932 Flat_packed_unsigneds_string.push_back(
17933 "Index of existing haloed element");
17943 int send_proc =
static_cast<int>(iproc);
17945 int recv_proc =
static_cast<int>(iproc);
17946 send_and_receive_elements_nodes_info(send_proc, recv_proc);
17949 Counter_for_flat_packed_doubles = 0;
17950 Counter_for_flat_packed_unsigneds = 0;
17953 const unsigned n_additional_halo_ele =
17954 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
17956 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17957 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
17958 <<
" Number of elements need to be constructed "
17959 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
17964 for (
unsigned e = 0; e < n_additional_halo_ele; e++)
17968 create_halo_element(iproc,
17969 iproc_currently_created_nodes_pt[iproc],
17970 other_proc_shd_bnd_node_pt,
17972 node_name_to_global_index,
17973 global_shared_node_pt);
17991 template<
class ELEMENT>
17993 ELEMENT>::get_required_elemental_information_helper(
unsigned& iproc,
17994 FiniteElement* ele_pt)
17997 const unsigned nbound = this->initial_shared_boundary_id();
18002 Vector<unsigned> associated_boundaries;
18003 Vector<unsigned> face_index_on_boundary;
18005 unsigned counter_face_indexes = 0;
18007 for (
unsigned b = 0; b < nbound; b++)
18010 const unsigned nboundary_ele = nboundary_element(b);
18011 for (
unsigned e = 0; e < nboundary_ele; e++)
18013 if (ele_pt == this->boundary_element_pt(b, e))
18016 associated_boundaries.push_back(b);
18018 face_index_on_boundary.push_back(face_index_at_boundary(b, e));
18019 counter_face_indexes++;
18021 if (counter_face_indexes > 2)
18023 std::stringstream error_message;
18025 <<
"A triangular element can not have more than two of its faces "
18026 <<
"on a boundary!!!\n\n";
18027 throw OomphLibError(error_message.str(),
18028 OOMPH_CURRENT_FUNCTION,
18029 OOMPH_EXCEPTION_LOCATION);
18033 if (counter_face_indexes == 2)
18047 const unsigned nassociated_boundaries = associated_boundaries.size();
18048 if (nassociated_boundaries > 0)
18050 Flat_packed_unsigneds.push_back(1);
18051 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18052 Flat_packed_unsigneds_string.push_back(
18053 "The element is a boundary element");
18055 Flat_packed_unsigneds.push_back(nassociated_boundaries);
18056 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18057 std::stringstream junk;
18058 junk <<
"The elements is associated to " << nassociated_boundaries
18060 Flat_packed_unsigneds_string.push_back(junk.str());
18067 for (
unsigned i = 0; i < nassociated_boundaries; i++)
18069 unsigned b = associated_boundaries[i];
18070 Flat_packed_unsigneds.push_back(b);
18071 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18072 std::stringstream junk;
18073 junk <<
"Element associated to boundary " << b <<
" of "
18074 << nassociated_boundaries <<
" total associated boundaries";
18075 Flat_packed_unsigneds_string.push_back(junk.str());
18077 unsigned f = face_index_on_boundary[i];
18078 Flat_packed_unsigneds.push_back(f);
18079 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18080 std::stringstream junk2;
18081 junk2 <<
"Face index " << f <<
" for associated boundary " << b;
18082 Flat_packed_unsigneds_string.push_back(junk2.str());
18092 Vector<Vector<unsigned>> associated_boundaries_and_regions;
18093 Vector<unsigned> face_index_on_boundary_and_region;
18096 const unsigned n_regions = this->nregion();
18101 unsigned counter_face_indexes_in_regions = 0;
18103 for (
unsigned b = 0; b < nbound; b++)
18106 for (
unsigned i_reg = 0; i_reg < n_regions; i_reg++)
18109 const unsigned region_id =
18110 static_cast<unsigned>(this->Region_attribute[i_reg]);
18115 const unsigned nele_in_region =
18116 this->nboundary_element_in_region(b, region_id);
18117 for (
unsigned ee = 0; ee < nele_in_region; ee++)
18122 this->boundary_element_in_region_pt(b, region_id, ee))
18126 Vector<unsigned> bound_and_region(2);
18129 bound_and_region[0] = b;
18131 bound_and_region[1] = region_id;
18134 associated_boundaries_and_regions.push_back(bound_and_region);
18136 face_index_on_boundary_and_region.push_back(
18137 this->face_index_at_boundary_in_region(b, region_id, ee));
18141 counter_face_indexes_in_regions++;
18144 if (counter_face_indexes_in_regions > 2)
18146 std::stringstream error_message;
18147 error_message <<
"A triangular element can not have more "
18148 "than two of its\n"
18149 <<
"faces on a boundary!!!\n\n";
18150 throw OomphLibError(error_message.str(),
18151 OOMPH_CURRENT_FUNCTION,
18152 OOMPH_EXCEPTION_LOCATION);
18167 const unsigned nassociated_boundaries_and_regions =
18168 associated_boundaries_and_regions.size();
18169 if (nassociated_boundaries_and_regions > 0)
18171 Flat_packed_unsigneds.push_back(1);
18172 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18173 Flat_packed_unsigneds_string.push_back(
18174 "The element is associated to boundaries and regions");
18177 Flat_packed_unsigneds.push_back(nassociated_boundaries_and_regions);
18178 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18179 std::stringstream junk;
18180 junk <<
"The element is associated to "
18181 << nassociated_boundaries_and_regions <<
" boundaries-regions";
18182 Flat_packed_unsigneds_string.push_back(junk.str());
18189 for (
unsigned i = 0; i < nassociated_boundaries_and_regions; i++)
18191 const unsigned b = associated_boundaries_and_regions[i][0];
18192 Flat_packed_unsigneds.push_back(b);
18193 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18194 std::stringstream junk;
18195 junk <<
"Element associated to boundary " << b <<
" of "
18196 << nassociated_boundaries_and_regions
18197 <<
" total associated boundaries-regions";
18198 Flat_packed_unsigneds_string.push_back(junk.str());
18201 const unsigned r = associated_boundaries_and_regions[i][1];
18202 Flat_packed_unsigneds.push_back(r);
18203 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18204 std::stringstream junk2;
18205 junk2 <<
"Element associated to region " << r <<
" of "
18206 << nassociated_boundaries_and_regions
18207 <<
" total associated boundaries-regions";
18208 Flat_packed_unsigneds_string.push_back(junk2.str());
18211 const unsigned f = face_index_on_boundary_and_region[i];
18212 Flat_packed_unsigneds.push_back(f);
18213 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18214 std::stringstream junk3;
18215 junk3 <<
"Face index " << f <<
" for associated boundary-region ("
18216 << b <<
"-" << r <<
")";
18217 Flat_packed_unsigneds_string.push_back(junk3.str());
18223 Flat_packed_unsigneds.push_back(0);
18224 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18225 Flat_packed_unsigneds_string.push_back(
18226 "The element is NOT associated to boundaries and regions");
18232 Flat_packed_unsigneds.push_back(0);
18233 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18234 Flat_packed_unsigneds_string.push_back(
18235 "The element is not associated to any original boundary");
18244 Vector<unsigned> associated_shared_boundaries;
18245 Vector<unsigned> face_index_on_shared_boundary;
18248 Vector<unsigned> my_rank_shared_boundaries_ids;
18249 this->shared_boundaries_in_this_processor(my_rank_shared_boundaries_ids);
18252 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
18254 for (
unsigned i = 0; i < nmy_rank_shd_bnd; i++)
18257 const unsigned sb = my_rank_shared_boundaries_ids[i];
18260 const unsigned nboundary_ele = this->nshared_boundary_element(sb);
18261 for (
unsigned e = 0; e < nboundary_ele; e++)
18263 if (ele_pt == this->shared_boundary_element_pt(sb, e))
18266 associated_shared_boundaries.push_back(sb);
18268 face_index_on_shared_boundary.push_back(
18269 this->face_index_at_shared_boundary(sb, e));
18276 const unsigned nassociated_shared_boundaries =
18277 associated_shared_boundaries.size();
18278 if (nassociated_shared_boundaries > 0)
18280 Flat_packed_unsigneds.push_back(3);
18281 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18282 Flat_packed_unsigneds_string.push_back(
18283 "The element is a shared boundary element");
18285 Flat_packed_unsigneds.push_back(nassociated_shared_boundaries);
18286 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18287 std::stringstream junk;
18288 junk <<
"The elements is associated to " << nassociated_shared_boundaries
18289 <<
"shared boundaries";
18290 Flat_packed_unsigneds_string.push_back(junk.str());
18294 for (
unsigned i = 0; i < nassociated_shared_boundaries; i++)
18296 const unsigned b = associated_shared_boundaries[i];
18297 Flat_packed_unsigneds.push_back(b);
18298 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18299 std::stringstream junk;
18300 junk <<
"Element associated to shared boundary " << b <<
" of "
18301 << nassociated_shared_boundaries <<
" total associated boundaries";
18302 Flat_packed_unsigneds_string.push_back(junk.str());
18305 const unsigned f = face_index_on_shared_boundary[i];
18306 Flat_packed_unsigneds.push_back(f);
18307 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18308 std::stringstream junk2;
18309 junk2 <<
"Face index " << f <<
" for associated shared boundary " << b;
18310 Flat_packed_unsigneds_string.push_back(junk2.str());
18316 Flat_packed_unsigneds.push_back(0);
18317 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18318 Flat_packed_unsigneds_string.push_back(
18319 "The element is not associated to any shared boundary");
18329 template<
class ELEMENT>
18331 unsigned& iproc, Node* nod_pt)
18333 unsigned my_rank = this->communicator_pt()->my_rank();
18334 const unsigned nproc = this->communicator_pt()->nproc();
18339 unsigned n_val = nod_pt->nvalue();
18340 Flat_packed_unsigneds.push_back(n_val);
18341 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18342 Flat_packed_unsigneds_string.push_back(
"Number of values");
18345 unsigned n_dim = nod_pt->ndim();
18348 unsigned n_prev = 1;
18349 if (this->Time_stepper_pt != 0)
18352 n_prev = this->Time_stepper_pt->ntstorage();
18358 Vector<unsigned> original_boundaries;
18361 const unsigned n_bnd = this->initial_shared_boundary_id();
18362 for (
unsigned bb = 0; bb < n_bnd; bb++)
18365 if (nod_pt->is_on_boundary(bb))
18367 original_boundaries.push_back(bb);
18371 const unsigned n_original_boundaries = original_boundaries.size();
18373 if (n_original_boundaries > 0)
18376 Flat_packed_unsigneds.push_back(2);
18377 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18378 Flat_packed_unsigneds_string.push_back(
18379 "Node is on the original boundaries");
18382 Flat_packed_unsigneds.push_back(n_original_boundaries);
18383 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18384 std::stringstream junk;
18385 junk <<
"Node is on " << n_original_boundaries <<
" original boundaries";
18386 Flat_packed_unsigneds_string.push_back(junk.str());
18390 for (
unsigned i = 0; i < n_original_boundaries; i++)
18392 Flat_packed_unsigneds.push_back(original_boundaries[i]);
18393 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18394 std::stringstream junk;
18395 junk <<
"Node is on boundary " << original_boundaries[i] <<
" of "
18397 Flat_packed_unsigneds_string.push_back(junk.str());
18400 Vector<double> zeta(1);
18401 nod_pt->get_coordinates_on_boundary(original_boundaries[i], zeta);
18402 Flat_packed_doubles.push_back(zeta[0]);
18408 Flat_packed_unsigneds.push_back(0);
18409 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18410 Flat_packed_unsigneds_string.push_back(
18411 "Node is on any original boundary");
18417 bool node_on_shared_boundary =
false;
18420 const unsigned n_shd_bnd = this->nshared_boundaries(my_rank, iproc);
18421 for (
unsigned bb = 0; bb < n_shd_bnd; bb++)
18424 unsigned i_bnd = this->shared_boundaries_ids(my_rank, iproc, bb);
18426 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
18428 node_on_shared_boundary =
true;
18436 if (node_on_shared_boundary)
18438 Flat_packed_unsigneds.push_back(1);
18439 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18440 Flat_packed_unsigneds_string.push_back(
"Node is on shared boundary");
18444 Vector<unsigned> shd_boundaries;
18446 for (
unsigned bb = 0; bb < n_shd_bnd; bb++)
18449 const unsigned i_bnd = this->shared_boundaries_ids(my_rank, iproc, bb);
18451 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
18453 shd_boundaries.push_back(i_bnd);
18458 const unsigned n_shd_bnd_is_on = shd_boundaries.size();
18460 Flat_packed_unsigneds.push_back(n_shd_bnd_is_on);
18461 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18462 std::stringstream junk;
18463 junk <<
"Node is on " << n_shd_bnd_is_on <<
" shared boundaries";
18464 Flat_packed_unsigneds_string.push_back(junk.str());
18468 for (
unsigned i = 0; i < n_shd_bnd_is_on; i++)
18470 Flat_packed_unsigneds.push_back(shd_boundaries[i]);
18471 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18472 std::stringstream junk;
18473 junk <<
"Node is on boundary " << shd_boundaries[i] <<
" of " << nb;
18474 Flat_packed_unsigneds_string.push_back(junk.str());
18480 unsigned shared_boundary_id = shd_boundaries[0];
18482 const unsigned n_nodes_on_shared_boundary =
18483 nsorted_shared_boundary_node(shared_boundary_id);
18485 unsigned index_node_on_shared_boundary;
18488 bool found_index_node_on_shared_boundary =
false;
18491 for (
unsigned i = 0; i < n_nodes_on_shared_boundary; i++)
18494 Node* shared_node_pt =
18495 sorted_shared_boundary_node_pt(shared_boundary_id, i);
18497 if (shared_node_pt == nod_pt)
18500 index_node_on_shared_boundary = i;
18503 found_index_node_on_shared_boundary =
true;
18511 if (!found_index_node_on_shared_boundary)
18513 std::ostringstream error_message;
18514 error_message <<
"The index of the node on boundary ("
18515 << shared_boundary_id <<
") was not found.\n"
18516 <<
"The node coordinates are (" << nod_pt->x(0) <<
","
18517 << nod_pt->x(1) <<
").\n";
18518 throw OomphLibError(
18519 error_message.str(),
18520 "RefineableTriangleMesh::get_required_nodal_information_helper()",
18521 OOMPH_EXCEPTION_LOCATION);
18525 Flat_packed_unsigneds.push_back(index_node_on_shared_boundary);
18526 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18527 std::stringstream junk2;
18528 junk2 <<
"Node index on boundary " << boundaries[0] <<
" is "
18529 << index_node_on_shared_boundary;
18530 Flat_packed_unsigneds_string.push_back(junk2.str());
18537 Flat_packed_unsigneds.push_back(0);
18538 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18539 Flat_packed_unsigneds_string.push_back(
18540 "Node is not on a shared boundary");
18555 bool node_on_shared_boundary_with_other_processors =
false;
18557 unsigned nshared_boundaries_with_other_processors_have_node = 0;
18561 for (
unsigned jproc = 0; jproc < nproc; jproc++)
18565 if (jproc != iproc)
18568 const unsigned n_jshd_bnd = this->nshared_boundaries(my_rank, jproc);
18570 for (
unsigned bb = 0; bb < n_jshd_bnd; bb++)
18573 const unsigned j_shd_bnd =
18574 this->shared_boundaries_ids(my_rank, jproc, bb);
18576 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
18584 node_on_shared_boundary_with_other_processors =
true;
18587 nshared_boundaries_with_other_processors_have_node++;
18598 if (node_on_shared_boundary_with_other_processors)
18600 Flat_packed_unsigneds.push_back(4);
18601 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18602 Flat_packed_unsigneds_string.push_back(
18603 "Node is on shared boundary no related with the received processor: 4");
18609 Flat_packed_unsigneds.push_back(
18610 nshared_boundaries_with_other_processors_have_node);
18611 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18612 std::stringstream junk;
18613 junk <<
"Number of other shared boundaries that the node is on: "
18614 << nshared_boundaries_with_other_processors_have_node;
18615 Flat_packed_unsigneds_string.push_back(junk.str());
18619 unsigned counter_shd_bnd_with_other_procs_have_node = 0;
18624 Vector<unsigned> other_processor_1;
18625 Vector<unsigned> other_processor_2;
18626 Vector<unsigned> shd_bnd_ids;
18627 Vector<unsigned> indexes;
18629 for (
unsigned jproc = 0; jproc < nproc; jproc++)
18633 if (jproc != iproc)
18637 const unsigned n_jshd_bnd = this->nshared_boundaries(my_rank, jproc);
18638 for (
unsigned bb = 0; bb < n_jshd_bnd; bb++)
18641 const unsigned j_shd_bnd =
18642 this->shared_boundaries_ids(my_rank, jproc, bb);
18644 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
18647 other_processor_1.push_back(my_rank);
18649 other_processor_2.push_back(jproc);
18651 shd_bnd_ids.push_back(j_shd_bnd);
18654 counter_shd_bnd_with_other_procs_have_node++;
18665 const unsigned n_other_processors = other_processor_1.size();
18667 for (
unsigned i = 0; i < n_other_processors; i++)
18670 unsigned shd_bnd_id = shd_bnd_ids[i];
18672 const unsigned n_nodes_on_shd_bnd =
18673 nsorted_shared_boundary_node(shd_bnd_id);
18676 bool found_index_node_on_shared_boundary =
false;
18678 for (
unsigned i = 0; i < n_nodes_on_shd_bnd; i++)
18681 Node* shared_node_pt = sorted_shared_boundary_node_pt(shd_bnd_id, i);
18683 if (shared_node_pt == nod_pt)
18689 indexes.push_back(i);
18692 found_index_node_on_shared_boundary =
true;
18700 if (!found_index_node_on_shared_boundary)
18702 std::ostringstream error_message;
18703 error_message <<
"The index of the node on boundary (" << shd_bnd_id
18704 <<
"), shared by other processors\nwas not found.\n"
18705 <<
"The node coordinates are (" << nod_pt->x(0) <<
","
18706 << nod_pt->x(1) <<
").\n";
18707 throw OomphLibError(
18708 error_message.str(),
18709 "RefineableTriangleMesh::get_required_nodal_information_helper()",
18710 OOMPH_EXCEPTION_LOCATION);
18719 if (counter_shd_bnd_with_other_procs_have_node !=
18720 nshared_boundaries_with_other_processors_have_node)
18722 std::ostringstream error_message;
18723 error_message <<
"The number of shared boundaries where the node is on "
18724 <<
"is different:\n"
18725 <<
"nshared_boundaries_with_other_processors_have_node: ("
18726 << nshared_boundaries_with_other_processors_have_node
18728 <<
"counter_shd_bnd_with_other_procs_have_node: ("
18729 << counter_shd_bnd_with_other_procs_have_node <<
")\n";
18730 throw OomphLibError(
18731 error_message.str(),
18732 "RefineableTriangleMesh::get_required_nodal_information_helper()",
18733 OOMPH_EXCEPTION_LOCATION);
18739 for (
unsigned i = 0; i < n_other_processors; i++)
18741 Flat_packed_unsigneds.push_back(other_processor_1[i]);
18742 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18743 std::stringstream junk1;
18744 junk1 <<
"Processor where the other shared boundary "
18745 <<
"has the node: " << other_processor_1[i];
18746 Flat_packed_unsigneds_string.push_back(junk1.str());
18749 Flat_packed_unsigneds.push_back(other_processor_2[i]);
18750 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18751 std::stringstream junk2;
18752 junk2 <<
"Processor where the other shared boundary "
18753 <<
"has the node: " << other_processor_2[i];
18754 Flat_packed_unsigneds_string.push_back(junk2.str());
18757 Flat_packed_unsigneds.push_back(shd_bnd_ids[i]);
18758 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18759 std::stringstream junk3;
18760 junk3 <<
"Other shared boundary id where the node is on"
18762 Flat_packed_unsigneds_string.push_back(junk3.str());
18765 Flat_packed_unsigneds.push_back(indexes[i]);
18766 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18767 std::stringstream junk4;
18768 junk4 <<
"Node index on other shared boundary " << boundaries[i]
18769 <<
" is " << indexes[i];
18770 Flat_packed_unsigneds_string.push_back(junk4.str());
18778 Flat_packed_unsigneds.push_back(0);
18779 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18780 Flat_packed_unsigneds_string.push_back(
18781 "Node is on any shared boundary with other processors");
18789 if (!node_on_shared_boundary)
18796 AlgebraicNode* alg_nod_pt =
dynamic_cast<AlgebraicNode*
>(nod_pt);
18797 if (alg_nod_pt != 0)
18800 AlgebraicMesh* alg_mesh_pt =
dynamic_cast<AlgebraicMesh*
>(
this);
18803 unsigned update_id = alg_nod_pt->node_update_fct_id();
18804 Flat_packed_unsigneds.push_back(update_id);
18805 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18806 Flat_packed_unsigneds_string.push_back(
"Alg Node update id");
18810 unsigned n_ref_val = alg_nod_pt->nref_value();
18811 Flat_packed_unsigneds.push_back(n_ref_val);
18812 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18813 Flat_packed_unsigneds_string.push_back(
"Alg Node n ref values");
18815 for (
unsigned i_ref_val = 0; i_ref_val < n_ref_val; i_ref_val++)
18817 Flat_packed_doubles.push_back(alg_nod_pt->ref_value(i_ref_val));
18821 unsigned n_geom_obj = alg_nod_pt->ngeom_object();
18822 Flat_packed_unsigneds.push_back(n_geom_obj);
18823 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18824 Flat_packed_unsigneds_string.push_back(
"Alg Node n geom objects");
18826 for (
unsigned i_geom = 0; i_geom < n_geom_obj; i_geom++)
18828 GeomObject* geom_obj_pt = alg_nod_pt->geom_object_pt(i_geom);
18831 unsigned n_geom_list = alg_mesh_pt->ngeom_object_list_pt();
18834 unsigned found_geom_object = 0;
18835 for (
unsigned i_list = 0; i_list < n_geom_list; i_list++)
18837 if (geom_obj_pt == alg_mesh_pt->geom_object_list_pt(i_list))
18839 found_geom_object = i_list;
18842 Flat_packed_unsigneds.push_back(found_geom_object);
18843 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18844 Flat_packed_unsigneds_string.push_back(
"Found geom object");
18850 SolidNode* solid_nod_pt =
dynamic_cast<SolidNode*
>(nod_pt);
18851 if (solid_nod_pt != 0)
18853 unsigned n_solid_val = solid_nod_pt->variable_position_pt()->nvalue();
18854 for (
unsigned i_val = 0; i_val < n_solid_val; i_val++)
18856 for (
unsigned t = 0; t < n_prev; t++)
18858 Flat_packed_doubles.push_back(
18859 solid_nod_pt->variable_position_pt()->value(t, i_val));
18863 Vector<double> values_solid_node;
18864 solid_nod_pt->add_values_to_vector(values_solid_node);
18865 const unsigned nvalues_solid_node = values_solid_node.size();
18866 Flat_packed_unsigneds.push_back(nvalues_solid_node);
18867 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18868 std::stringstream junk;
18869 junk <<
"Number of values solid node: " << nvalues_solid_node;
18870 Flat_packed_unsigneds_string.push_back(junk.str());
18872 for (
unsigned i = 0; i < nvalues_solid_node; i++)
18874 Flat_packed_doubles.push_back(values_solid_node[i]);
18879 for (
unsigned i_val = 0; i_val < n_val; i_val++)
18881 for (
unsigned t = 0; t < n_prev; t++)
18883 Flat_packed_doubles.push_back(nod_pt->value(t, i_val));
18888 for (
unsigned idim = 0; idim < n_dim; idim++)
18890 for (
unsigned t = 0; t < n_prev; t++)
18892 Flat_packed_doubles.push_back(nod_pt->x(t, idim));
18902 template<
class ELEMENT>
18907 const unsigned n_haloed_nod = this->nhaloed_node(iproc);
18908 const unsigned haloed_node_index =
18909 this->try_to_add_haloed_node_pt(iproc, nod_pt);
18912 if (haloed_node_index == n_haloed_nod)
18914 Flat_packed_unsigneds.push_back(1);
18916 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18917 std::stringstream junk;
18918 junk <<
"Node needs to be constructed [size="
18919 << Flat_packed_unsigneds.size() <<
"]; last entry: "
18920 << Flat_packed_unsigneds[Flat_packed_unsigneds.size() - 1];
18921 Flat_packed_unsigneds_string.push_back(junk.str());
18927 get_required_nodal_information_helper(iproc, nod_pt);
18931 Flat_packed_unsigneds.push_back(0);
18932 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18933 std::stringstream junk;
18934 junk <<
"Node was already added [size=" << Flat_packed_unsigneds.size()
18935 <<
"]; last entry: "
18936 << Flat_packed_unsigneds[Flat_packed_unsigneds.size() - 1];
18938 Flat_packed_unsigneds_string.push_back(junk.str());
18943 Flat_packed_unsigneds.push_back(haloed_node_index);
18944 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18945 Flat_packed_unsigneds_string.push_back(
"haloed node index");
18954 template<
class ELEMENT>
18956 int& send_proc,
int& recv_proc)
18959 OomphCommunicator* comm_pt = this->communicator_pt();
18963 MPI_Request request;
18966 Vector<double> received_double_values;
18967 Vector<unsigned> received_unsigned_values;
18971 unsigned send_count_double_values = Flat_packed_doubles.size();
18972 MPI_Isend(&send_count_double_values,
18977 comm_pt->mpi_comm(),
18980 int receive_count_double_values = 0;
18981 MPI_Recv(&receive_count_double_values,
18986 comm_pt->mpi_comm(),
18988 MPI_Wait(&request, MPI_STATUS_IGNORE);
18990 if (send_count_double_values != 0)
18992 MPI_Isend(&Flat_packed_doubles[0],
18993 send_count_double_values,
18997 comm_pt->mpi_comm(),
19000 if (receive_count_double_values != 0)
19002 received_double_values.resize(receive_count_double_values);
19003 MPI_Recv(&received_double_values[0],
19004 receive_count_double_values,
19008 comm_pt->mpi_comm(),
19011 if (send_count_double_values != 0)
19013 MPI_Wait(&request, MPI_STATUS_IGNORE);
19018 unsigned send_count_unsigned_values = Flat_packed_unsigneds.size();
19019 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19020 unsigned send_count_unsigned_string = Flat_packed_unsigneds_string.size();
19022 if (send_count_unsigned_string != send_count_unsigned_values)
19024 std::ostringstream error_message;
19025 error_message <<
"The number of unsigned values to send to processor ("
19027 <<
") is different from the\nnumber of annotated strings "
19028 <<
"for the communication\n\n";
19029 throw OomphLibError(
19030 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
19034 MPI_Isend(&send_count_unsigned_values,
19039 comm_pt->mpi_comm(),
19042 int receive_count_unsigned_values = 0;
19043 MPI_Recv(&receive_count_unsigned_values,
19048 comm_pt->mpi_comm(),
19051 MPI_Wait(&request, MPI_STATUS_IGNORE);
19053 if (send_count_unsigned_values != 0)
19055 MPI_Isend(&Flat_packed_unsigneds[0],
19056 send_count_unsigned_values,
19060 comm_pt->mpi_comm(),
19062 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19063 for (
unsigned i = 0; i < send_count_unsigned_values; i++)
19065 oomph_info <<
"Sent:" << i <<
" to orig_proc:" << send_proc <<
" "
19066 << Flat_packed_unsigneds_string[i] <<
": "
19067 << Flat_packed_unsigneds[i] << std::endl;
19071 if (receive_count_unsigned_values != 0)
19073 received_unsigned_values.resize(receive_count_unsigned_values);
19074 MPI_Recv(&received_unsigned_values[0],
19075 receive_count_unsigned_values,
19079 comm_pt->mpi_comm(),
19083 if (send_count_unsigned_values != 0)
19085 MPI_Wait(&request, MPI_STATUS_IGNORE);
19094 Flat_packed_doubles.resize(receive_count_double_values);
19095 for (
int ii = 0; ii < receive_count_double_values; ii++)
19097 Flat_packed_doubles[ii] = received_double_values[ii];
19099 Flat_packed_unsigneds.resize(receive_count_unsigned_values);
19100 for (
int ii = 0; ii < receive_count_unsigned_values; ii++)
19102 Flat_packed_unsigneds[ii] = received_unsigned_values[ii];
19110 template<
class ELEMENT>
19113 Vector<Node*>& new_nodes_on_domain,
19114 Vector<Vector<Vector<std::map<unsigned, Node*>>>>&
19115 other_proc_shd_bnd_node_pt,
19116 Vector<Vector<Vector<unsigned>>>& global_node_names,
19117 std::map<Vector<unsigned>,
unsigned>& node_name_to_global_index,
19118 Vector<Node*>& global_shared_node_pt)
19120 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19121 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19122 <<
" Bool: New element needs to be constructed "
19123 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19127 if (Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++] == 1)
19131 GeneralisedElement* new_el_pt =
new ELEMENT;
19134 this->add_element_pt(new_el_pt);
19137 this->add_root_halo_element_pt(iproc, new_el_pt);
19140 FiniteElement* f_el_pt =
dynamic_cast<FiniteElement*
>(new_el_pt);
19143 this->add_halo_element_helper(iproc, f_el_pt);
19146 unsigned n_node = f_el_pt->nnode();
19148 for (
unsigned j = 0; j < n_node; j++)
19150 Node* new_nod_pt = 0;
19153 add_halo_node_helper(new_nod_pt,
19154 new_nodes_on_domain,
19155 other_proc_shd_bnd_node_pt,
19160 node_name_to_global_index,
19161 global_shared_node_pt);
19167 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19168 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19169 <<
" Index of existing halo element "
19170 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19174 unsigned halo_ele_index =
19175 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19178 FiniteElement* f_el_pt =
dynamic_cast<FiniteElement*
>(
19179 this->root_halo_element_pt(iproc, halo_ele_index));
19184 throw OomphLibError(
"Halo element is not a FiniteElement\n",
19185 OOMPH_CURRENT_FUNCTION,
19186 OOMPH_EXCEPTION_LOCATION);
19198 template<
class ELEMENT>
19200 unsigned& iproc, FiniteElement* ele_pt)
19202 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19203 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19204 <<
" Bool: Element is associated to an original boundary "
19205 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19209 if (Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++] == 1)
19211 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19212 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19213 <<
" How many boundaries are associated with the element "
19214 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19217 const unsigned nassociated_boundaries =
19218 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19220 for (
unsigned b = 0; b < nassociated_boundaries; b++)
19222 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19223 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19224 <<
" Boundary associated to the element "
19225 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19228 const unsigned bnd =
19229 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19231 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19232 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19233 <<
" Face index of the element "
19234 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19237 const unsigned face_index =
19238 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19242 this->Boundary_element_pt[bnd].push_back(ele_pt);
19243 this->Face_index_at_boundary[bnd].push_back(face_index);
19248 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19249 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19250 <<
" Bool: Element is associated to a boundary-region "
19251 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19255 if (Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++] == 1)
19257 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19259 <<
"Rec:" << Counter_for_flat_packed_unsigneds
19260 <<
" How many boundaries-regions are associated with the element "
19261 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19264 const unsigned nassociated_boundaries_and_regions =
19265 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19267 for (
unsigned br = 0; br < nassociated_boundaries_and_regions; br++)
19269 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19270 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19271 <<
" Boundary associated to the element "
19272 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19275 const unsigned bnd =
19276 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19278 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19279 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19280 <<
" Region associated to the element "
19281 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19284 const unsigned region =
19285 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19287 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19288 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19289 <<
" Face index of the element in boundary-region "
19290 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19293 const unsigned face_index =
19294 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19298 this->Boundary_region_element_pt[bnd][region].push_back(ele_pt);
19299 this->Face_index_region_at_boundary[bnd][region].push_back(
19308 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19309 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19310 <<
" Bool: Element is associated to a shared boundary "
19311 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19314 if (Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++] == 3)
19316 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19318 <<
"Rec:" << Counter_for_flat_packed_unsigneds
19319 <<
" How many shared boundaries are associated with the element "
19320 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19323 const unsigned nassociated_shared_boundaries =
19324 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19326 for (
unsigned b = 0; b < nassociated_shared_boundaries; b++)
19328 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19329 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19330 <<
" Shared boundary associated to the element "
19331 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19334 const unsigned bnd =
19335 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19337 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19339 <<
"Rec:" << Counter_for_flat_packed_unsigneds
19340 <<
" Face index of the element associated to the shared boundary "
19341 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19345 const unsigned face_index =
19346 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19348 this->add_shared_boundary_element(bnd, ele_pt);
19349 this->add_face_index_at_shared_boundary(bnd, face_index);
19359 template<
class ELEMENT>
19362 Vector<Node*>& new_nodes_on_domain,
19363 Vector<Vector<Vector<std::map<unsigned, Node*>>>>&
19364 other_proc_shd_bnd_node_pt,
19366 unsigned& node_index,
19367 FiniteElement*
const& new_el_pt,
19368 Vector<Vector<Vector<unsigned>>>& global_node_names,
19369 std::map<Vector<unsigned>,
unsigned>& node_name_to_global_index,
19370 Vector<Node*>& global_shared_node_pt)
19374 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19375 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19376 <<
" Bool: New node needs to be constructed "
19377 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19380 if (Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++] == 1)
19384 construct_new_halo_node_helper(new_nod_pt,
19385 new_nodes_on_domain,
19386 other_proc_shd_bnd_node_pt,
19391 node_name_to_global_index,
19392 global_shared_node_pt);
19396 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19397 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19398 <<
" Index of existing halo node "
19399 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19404 new_nod_pt = new_nodes_on_domain
19405 [Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++]];
19407 new_el_pt->node_pt(node_index) = new_nod_pt;
19415 template<
class ELEMENT>
19418 Vector<Node*>& new_nodes_on_domain,
19419 Vector<Vector<Vector<std::map<unsigned, Node*>>>>&
19420 other_proc_shd_bnd_node_pt,
19422 unsigned& node_index,
19423 FiniteElement*
const& new_el_pt,
19424 Vector<Vector<Vector<unsigned>>>& global_node_names,
19425 std::map<Vector<unsigned>,
unsigned>& node_name_to_global_index,
19426 Vector<Node*>& global_shared_node_pt)
19430 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19431 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19432 <<
" Number of values of external halo node "
19433 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19436 unsigned n_val = Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19439 TimeStepper* time_stepper_pt = this->Time_stepper_pt;
19441 unsigned n_prev = time_stepper_pt->ntstorage();
19445 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19446 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19447 <<
" Is the node on an original boundary "
19448 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19453 const unsigned node_on_original_boundaries =
19454 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19457 Vector<unsigned> original_boundaries_node_is_on;
19459 Vector<double> zeta_coordinates;
19461 unsigned n_original_boundaries_node_is_on = 0;
19463 if (node_on_original_boundaries == 2)
19466 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19467 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19468 <<
" Number of boundaries the node is on: "
19469 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19472 n_original_boundaries_node_is_on =
19473 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19476 original_boundaries_node_is_on.resize(n_original_boundaries_node_is_on);
19477 zeta_coordinates.resize(n_original_boundaries_node_is_on);
19479 for (
unsigned i = 0; i < n_original_boundaries_node_is_on; i++)
19482 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19483 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19484 <<
" Node is on boundary "
19485 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19488 original_boundaries_node_is_on[i] =
19489 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19490 zeta_coordinates[i] =
19491 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
19498 if (node_on_original_boundaries != 0)
19500 std::ostringstream error_message;
19502 <<
"The current node is not on an original boundary, this should\n"
19503 <<
"be indicated by a zero flag. However, the read value for\n"
19504 <<
"that flag is (" << node_on_original_boundaries <<
").\n\n";
19505 throw OomphLibError(
19506 error_message.str(),
19507 "RefineableTriangleMesh::construct_new_halo_node_helper()",
19508 OOMPH_EXCEPTION_LOCATION);
19516 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19517 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19518 <<
" Is node on shared boundary? "
19519 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19522 const unsigned is_node_on_shared_boundary =
19523 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19524 if (is_node_on_shared_boundary == 1)
19527 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19528 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19529 <<
" Number of boundaries the node is on: "
19530 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19533 const unsigned n_shd_bnd_node_is_on =
19534 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19535 Vector<unsigned> shd_bnds_node_is_on(n_shd_bnd_node_is_on);
19536 for (
unsigned i = 0; i < n_shd_bnd_node_is_on; i++)
19539 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19540 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19541 <<
" Node is on boundary "
19542 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19545 shd_bnds_node_is_on[i] =
19546 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19550 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19551 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19552 <<
" Index of node on boundary "
19553 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19557 unsigned node_index_on_shared_boundary =
19558 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19561 new_nod_pt = this->sorted_shared_boundary_node_pt(
19562 shd_bnds_node_is_on[0], node_index_on_shared_boundary);
19568 if (is_node_on_shared_boundary != 0)
19570 std::ostringstream error_message;
19572 <<
"The current node is not on a shared boundary, this should\n"
19573 <<
"be indicated by a zero flag. However, the read value for\n"
19574 <<
"that flag is (" << is_node_on_shared_boundary <<
").\n\n";
19575 throw OomphLibError(
19576 error_message.str(),
19577 "RefineableTriangleMesh::construct_new_halo_node_helper()",
19578 OOMPH_EXCEPTION_LOCATION);
19585 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19586 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19587 <<
" Is the node on shared boundaries with other processors "
19588 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19594 const unsigned is_the_node_in_shared_boundaries_with_other_processors =
19595 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19598 Vector<unsigned> other_processor_1;
19599 Vector<unsigned> other_processor_2;
19600 Vector<unsigned> other_shared_boundaries;
19601 Vector<unsigned> other_indexes;
19604 unsigned n_shd_bnd_with_other_procs_have_node = 0;
19607 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
19609 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19610 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19611 <<
" In how many shared boundaries with other "
19612 <<
"processors is the node "
19613 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19618 n_shd_bnd_with_other_procs_have_node =
19619 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19622 other_processor_1.resize(n_shd_bnd_with_other_procs_have_node);
19623 other_processor_2.resize(n_shd_bnd_with_other_procs_have_node);
19624 other_shared_boundaries.resize(n_shd_bnd_with_other_procs_have_node);
19625 other_indexes.resize(n_shd_bnd_with_other_procs_have_node);
19627 for (
unsigned i = 0; i < n_shd_bnd_with_other_procs_have_node; i++)
19629 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19630 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19631 <<
" Processor where the other shared boundary"
19633 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19637 other_processor_1[i] =
19638 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19640 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19641 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19642 <<
" Processor where the other shared boundary"
19644 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19648 other_processor_2[i] =
19649 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19651 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19652 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19653 <<
" Other shared boundary id where the node is on: "
19654 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19659 other_shared_boundaries[i] =
19660 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19662 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19663 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19664 <<
" Node index on the other shared boundary "
19665 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19671 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19679 if (is_the_node_in_shared_boundaries_with_other_processors != 0)
19681 std::ostringstream error_message;
19683 <<
"The current node is not on a shared boundary with\n"
19684 <<
"other processors, this should be indicated by a zero flag.\n"
19685 <<
"However, the read value for that flag is ("
19686 << is_the_node_in_shared_boundaries_with_other_processors <<
").\n\n";
19687 throw OomphLibError(
19688 error_message.str(),
19689 "RefineableTriangleMesh::construct_new_halo_node_helper()",
19690 OOMPH_EXCEPTION_LOCATION);
19699 if (is_node_on_shared_boundary == 1)
19704 if (node_on_original_boundaries == 2)
19710 for (
unsigned i = 0; i < n_original_boundaries_node_is_on; i++)
19712 add_boundary_node(original_boundaries_node_is_on[i], new_nod_pt);
19714 Vector<double> zeta(1);
19715 zeta[0] = zeta_coordinates[i];
19716 new_nod_pt->set_coordinates_on_boundary(
19717 original_boundaries_node_is_on[i], zeta);
19723 new_nodes_on_domain.push_back(new_nod_pt);
19726 new_el_pt->node_pt(node_index) = new_nod_pt;
19736 bool found_node_in_other_shared_boundaries =
false;
19745 bool build_node_as_boundary_node =
false;
19747 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
19750 build_node_as_boundary_node =
true;
19757 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
19760 Vector<Node*> found_node_pt;
19763 for (
unsigned i = 0; i < n_shd_bnd_with_other_procs_have_node; i++)
19774 unsigned oproc1 = other_processor_1[i];
19775 unsigned oproc2 = other_processor_2[i];
19776 if (other_processor_1[i] > other_processor_2[i])
19778 oproc1 = other_processor_2[i];
19779 oproc2 = other_processor_1[i];
19784 const unsigned shd_bnd_id =
19785 other_shared_boundaries[i] - initial_shd_bnd_id;
19788 const unsigned index = other_indexes[i];
19792 const unsigned n_nodes_on_other_processor =
19793 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].size();
19795 if (n_nodes_on_other_processor > 0)
19799 std::map<unsigned, Node*>::iterator it =
19800 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].find(index);
19804 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].end())
19807 found_node_in_other_shared_boundaries =
true;
19809 Node* tmp_node_pt = (*it).second;
19812 found_node_pt.push_back(tmp_node_pt);
19823 if (found_node_in_other_shared_boundaries)
19826 const unsigned n_times_node_found = found_node_pt.size();
19827 for (
unsigned j = 1; j < n_times_node_found; j++)
19829 if (found_node_pt[j - 1] != found_node_pt[j])
19831 std::ostringstream error_message;
19833 <<
"The instances of the node that was found on\n"
19834 <<
"shared boundaries with other processors (but not\n"
19835 <<
"on shared boundaries with this processor) are not\n"
19837 <<
"These are the coordinates of the instances of the\n"
19839 <<
"(" << found_node_pt[j - 1]->x(0) <<
", "
19840 << found_node_pt[j - 1]->x(1) <<
")\n"
19841 <<
"(" << found_node_pt[j]->x(0) <<
", " << found_node_pt[j]->x(1)
19843 <<
"Dont be surprised if they are the same since the "
19844 <<
"node is\nrepeated.\n";
19845 throw OomphLibError(error_message.str(),
19846 OOMPH_CURRENT_FUNCTION,
19847 OOMPH_EXCEPTION_LOCATION);
19858 if (is_node_on_shared_boundary == 1)
19867 if (found_node_pt[0] != new_nod_pt)
19869 std::ostringstream error_message;
19871 <<
"The pointer of the node that was found to be on a\n"
19872 <<
"shared boundary with other processor(s) and the pointer\n"
19873 <<
"of the node on shared boundary with the receiver\n"
19874 <<
"processor (iproc) are not the same. This means we have a\n"
19875 <<
"repeated node)\n"
19876 <<
"The coordinates for the nodes are:\n"
19877 <<
"(" << found_node_pt[0]->x(0) <<
", " << found_node_pt[0]->x(1)
19879 <<
"(" << new_nod_pt->x(0) <<
", " << new_nod_pt->x(1) <<
")\n"
19880 <<
"Dont be surprised if they are the same since the "
19881 <<
"node is\nrepeated.\n";
19882 throw OomphLibError(error_message.str(),
19883 OOMPH_CURRENT_FUNCTION,
19884 OOMPH_EXCEPTION_LOCATION);
19895 new_nod_pt = found_node_pt[0];
19905 if (is_node_on_shared_boundary != 1)
19919 if (node_on_original_boundaries == 2 || build_node_as_boundary_node)
19923 if (!found_node_in_other_shared_boundaries)
19926 if (time_stepper_pt != 0)
19929 new_el_pt->construct_boundary_node(node_index, time_stepper_pt);
19933 new_nod_pt = new_el_pt->construct_boundary_node(node_index);
19940 new_el_pt->node_pt(node_index) = new_nod_pt;
19945 for (
unsigned i = 0; i < n_original_boundaries_node_is_on; i++)
19947 add_boundary_node(original_boundaries_node_is_on[i], new_nod_pt);
19949 Vector<double> zeta(1);
19950 zeta[0] = zeta_coordinates[i];
19951 new_nod_pt->set_coordinates_on_boundary(
19952 original_boundaries_node_is_on[i], zeta);
19960 if (!found_node_in_other_shared_boundaries)
19963 if (time_stepper_pt != 0)
19965 new_nod_pt = new_el_pt->construct_node(node_index, time_stepper_pt);
19969 new_nod_pt = new_el_pt->construct_node(node_index);
19975 new_el_pt->node_pt(node_index) = new_nod_pt;
19986 new_nodes_on_domain.push_back(new_nod_pt);
19990 if (!found_node_in_other_shared_boundaries)
19993 this->add_node_pt(new_nod_pt);
19997 AlgebraicNode* new_alg_nod_pt =
dynamic_cast<AlgebraicNode*
>(new_nod_pt);
20001 if (new_alg_nod_pt != 0)
20004 AlgebraicMesh* alg_mesh_pt =
dynamic_cast<AlgebraicMesh*
>(
this);
20010 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
20011 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
20012 <<
" Alg node update id "
20013 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
20017 unsigned update_id =
20018 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
20020 Vector<double> ref_value;
20024 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
20025 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
20026 <<
" Alg node # of ref values "
20027 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
20030 unsigned n_ref_val =
20031 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
20035 ref_value.resize(n_ref_val);
20036 for (
unsigned i_ref = 0; i_ref < n_ref_val; i_ref++)
20039 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
20042 Vector<GeomObject*> geom_object_pt;
20049 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
20050 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
20051 <<
" Alg node # of geom objects "
20052 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
20055 unsigned n_geom_obj =
20056 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
20060 geom_object_pt.resize(n_geom_obj);
20061 for (
unsigned i_geom = 0; i_geom < n_geom_obj; i_geom++)
20063 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
20064 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
20065 <<
" Alg node: geom object index "
20066 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
20069 unsigned geom_index =
20070 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
20077 geom_object_pt[i_geom] = alg_mesh_pt->geom_object_list_pt(geom_index);
20082 if (!found_node_in_other_shared_boundaries)
20086 new_alg_nod_pt->add_node_update_info(
20087 update_id, alg_mesh_pt, geom_object_pt, ref_value);
20090 alg_mesh_pt->update_node_update(new_alg_nod_pt);
20098 if (!found_node_in_other_shared_boundaries)
20101 MacroElementNodeUpdateNode* macro_nod_pt =
20102 dynamic_cast<MacroElementNodeUpdateNode*
>(new_nod_pt);
20104 if (macro_nod_pt != 0)
20108 Vector<GeomObject*> geom_object_vector_pt;
20112 MacroElementNodeUpdateMesh* macro_mesh_pt =
20113 dynamic_cast<MacroElementNodeUpdateMesh*
>(
this);
20114 geom_object_vector_pt = macro_mesh_pt->geom_object_vector_pt();
20117 Vector<double> s_in_macro_node_update_element;
20118 new_el_pt->local_coordinate_of_node(node_index,
20119 s_in_macro_node_update_element);
20122 macro_nod_pt->set_node_update_info(
20123 new_el_pt, s_in_macro_node_update_element, geom_object_vector_pt);
20129 unsigned n_new_val = new_nod_pt->nvalue();
20133 if (!found_node_in_other_shared_boundaries)
20135 if (n_val > n_new_val)
20142 BoundaryNodeBase* bnod_pt =
20143 dynamic_cast<BoundaryNodeBase*
>(new_nod_pt);
20148 if (bnod_pt->index_of_first_value_assigned_by_face_element_pt() == 0)
20150 bnod_pt->index_of_first_value_assigned_by_face_element_pt() =
20151 new std::map<unsigned, unsigned>;
20155 std::map<unsigned, unsigned>* map_pt =
20156 bnod_pt->index_of_first_value_assigned_by_face_element_pt();
20160 const unsigned id_face = 0;
20162 std::map<unsigned, unsigned>::const_iterator p =
20163 map_pt->find(id_face);
20166 if (p == map_pt->end())
20170 (*map_pt)[id_face] = n_new_val;
20173 new_nod_pt->resize(n_val);
20181 SolidNode* solid_nod_pt =
dynamic_cast<SolidNode*
>(new_nod_pt);
20182 if (solid_nod_pt != 0)
20184 unsigned n_solid_val = solid_nod_pt->variable_position_pt()->nvalue();
20185 for (
unsigned i_val = 0; i_val < n_solid_val; i_val++)
20187 for (
unsigned t = 0; t < n_prev; t++)
20190 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
20194 if (!found_node_in_other_shared_boundaries)
20196 solid_nod_pt->variable_position_pt()->set_value(
20197 t, i_val, read_data);
20202 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
20203 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
20204 <<
" Number of values solid node: "
20205 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
20208 const unsigned nvalues_solid_node =
20209 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
20210 Vector<double> values_solid_node(nvalues_solid_node);
20211 for (
unsigned i = 0; i < nvalues_solid_node; i++)
20213 values_solid_node[i] =
20214 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
20219 if (!found_node_in_other_shared_boundaries)
20221 unsigned index = 0;
20222 solid_nod_pt->read_values_from_vector(values_solid_node, index);
20228 for (
unsigned i_val = 0; i_val < n_val; i_val++)
20230 for (
unsigned t = 0; t < n_prev; t++)
20233 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
20238 if (!found_node_in_other_shared_boundaries)
20240 new_nod_pt->set_value(t, i_val, read_data);
20246 unsigned n_dim = new_nod_pt->ndim();
20247 for (
unsigned idim = 0; idim < n_dim; idim++)
20249 for (
unsigned t = 0; t < n_prev; t++)
20252 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
20257 if (!found_node_in_other_shared_boundaries)
20260 new_nod_pt->x(t, idim) = read_data;
20272 if (n_shd_bnd_with_other_procs_have_node > 0 &&
20276 !found_node_in_other_shared_boundaries)
20284 this->update_other_proc_shd_bnd_node_helper(new_nod_pt,
20285 other_proc_shd_bnd_node_pt,
20288 other_shared_boundaries,
20291 node_name_to_global_index,
20292 global_shared_node_pt);
20301 template<
class ELEMENT>
20303 Node*& new_node_pt,
20304 Vector<Vector<Vector<std::map<unsigned, Node*>>>>&
20305 other_proc_shd_bnd_node_pt,
20306 Vector<unsigned>& other_processor_1,
20307 Vector<unsigned>& other_processor_2,
20308 Vector<unsigned>& other_shared_boundaries,
20309 Vector<unsigned>& other_indexes,
20310 Vector<Vector<Vector<unsigned>>>& global_node_names,
20311 std::map<Vector<unsigned>,
unsigned>& node_name_to_global_index,
20312 Vector<Node*>& global_shared_node_pt)
20316 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
20321 const unsigned n_data = other_processor_1.size();
20325 Vector<unsigned> node_name(4);
20326 node_name[0] = other_processor_1[0];
20327 node_name[1] = other_processor_2[0];
20328 node_name[2] = other_shared_boundaries[0];
20329 node_name[3] = other_indexes[0];
20333 std::map<Vector<unsigned>,
unsigned>::iterator it =
20334 node_name_to_global_index.find(node_name);
20335 if (it == node_name_to_global_index.end())
20337 std::ostringstream error_stream;
20338 error_stream <<
"The node name does not exist in the global node names\n"
20339 <<
"This is the name of the node\n"
20340 <<
"Name: iproc, jproc, ishd_bnd, idx\n"
20341 <<
"Name: " << node_name[0] <<
", " << node_name[1] <<
", "
20342 << node_name[2] <<
", " << node_name[3] <<
"\n";
20343 throw OomphLibError(
20344 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
20349 const unsigned iglobal_node = node_name_to_global_index[node_name];
20351 global_shared_node_pt[iglobal_node] = new_node_pt;
20353 Vector<Vector<unsigned>> inode_names = global_node_names[iglobal_node];
20355 const unsigned n_names = inode_names.size();
20360 unsigned n_found_node_names_on_global_node_name = 0;
20362 for (
unsigned j = 0; j < n_data; j++)
20365 for (
unsigned k = 0; k < n_names; k++)
20368 if (inode_names[k][0] == other_processor_1[j] &&
20369 inode_names[k][1] == other_processor_2[j] &&
20370 inode_names[k][2] == other_shared_boundaries[j] &&
20371 inode_names[k][3] == other_indexes[j])
20375 n_found_node_names_on_global_node_name++;
20383 if (n_found_node_names_on_global_node_name != n_data)
20385 std::ostringstream error_stream;
20387 <<
"Not all the node names of the current node were found on the\n"
20388 <<
"global node names. This happened when adding the node pointer\n"
20389 <<
"to the data structure that keeps tracks of nodes on shared\n"
20390 <<
"boundaries with other processors\n\n"
20391 <<
"These are the names of the current node\n"
20392 <<
"Name k: iproc, jproc, ishd_bnd, idx\n";
20393 for (
unsigned j = 0; j < n_data; j++)
20395 error_stream <<
"Name(" << j <<
"): " << other_processor_1[j] <<
", "
20396 << other_processor_2[j] <<
", "
20397 << other_shared_boundaries[j] <<
", " << other_indexes[j]
20401 error_stream <<
"\n\nThese are the names of the global node\n"
20402 <<
"Name k: iproc, jproc, ishd_bnd, idx\n";
20403 for (
unsigned k = 0; k < n_names; k++)
20405 error_stream <<
"Name(" << k <<
"): " << inode_names[k][0] <<
", "
20406 << inode_names[k][1] <<
", " << inode_names[k][2] <<
", "
20407 << inode_names[k][3] <<
"\n";
20410 throw OomphLibError(
20411 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
20416 for (
unsigned j = 0; j < n_names; j++)
20419 const unsigned iproc = inode_names[j][0];
20420 const unsigned jproc = inode_names[j][1];
20421 const unsigned ishd_bnd = inode_names[j][2] - initial_shd_bnd_id;
20422 const unsigned index = inode_names[j][3];
20428 other_proc_shd_bnd_node_pt[iproc][jproc][ishd_bnd][index] = new_node_pt;
20432 other_proc_shd_bnd_node_pt[jproc][iproc][ishd_bnd][index] = new_node_pt;
20450 template<
class ELEMENT>
20452 const Vector<unsigned>& target_domain_for_local_non_halo_element)
20454 oomph_info <<
"Load balance (unstructured mesh) [BEGIN]" << std::endl;
20458 if (!this->is_mesh_distributed())
20460 std::ostringstream warning_message;
20462 <<
"\n===============================================================\n"
20463 <<
"The load balancing can only be performed in distributed meshes,\n"
20464 <<
"your mesh has not been distributed.\n"
20465 <<
"==============================================================="
20467 OomphLibWarning(warning_message.str(),
20468 OOMPH_CURRENT_FUNCTION,
20469 OOMPH_EXCEPTION_LOCATION);
20475 const unsigned nproc = this->communicator_pt()->nproc();
20477 const unsigned my_rank = this->communicator_pt()->my_rank();
20482 std::ostringstream warning_message;
20484 <<
"\n===============================================================\n"
20485 <<
"The load balancing can only be performed when there are at least\n"
20486 <<
"two procesors, the current number of processors is one.\n"
20487 <<
"==============================================================="
20489 OomphLibWarning(warning_message.str(),
20490 OOMPH_CURRENT_FUNCTION,
20491 OOMPH_EXCEPTION_LOCATION);
20497 double t_start_overall_load_balance = 0.0;
20498 if (Print_timings_level_load_balance > 1)
20500 t_start_overall_load_balance = TimingHelpers::timer();
20504 const unsigned nelement_before_load_balance = this->nelement();
20509 if (nnon_halo_element() != target_domain_for_local_non_halo_element.size())
20511 std::ostringstream error_message;
20512 error_message <<
"The number of non halo elements in the current mesh ("
20513 << nnon_halo_element() <<
") and the number\n"
20514 <<
"of target areas for the local non halo elements ("
20515 << target_domain_for_local_non_halo_element.size()
20516 <<
") is different\n\n";
20517 throw OomphLibError(
20518 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
20523 Vector<FiniteElement*> backed_up_ele_pt(nelement_before_load_balance);
20524 for (
unsigned e = 0; e < nelement_before_load_balance; e++)
20526 backed_up_ele_pt[e] = this->finite_element_pt(e);
20534 double tt_start_get_domains_halo_elements = 0.0;
20535 if (Print_timings_level_load_balance > 1)
20537 tt_start_get_domains_halo_elements = TimingHelpers::timer();
20551 Vector<Vector<unsigned>> new_domains_haloed_elements(nproc);
20554 Vector<Vector<unsigned>> new_domains_halo_elements(nproc);
20558 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20562 if (iproc != my_rank)
20565 const unsigned n_halo_iproc = this->nroot_halo_element(iproc);
20567 new_domains_halo_elements[iproc].resize(n_halo_iproc);
20570 const unsigned n_haloed_iproc = this->nroot_haloed_element(iproc);
20572 new_domains_haloed_elements[iproc].resize(n_haloed_iproc);
20578 Vector<unsigned> counter_for_found_haloed_elements(nproc, 0);
20585 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20589 if (iproc != my_rank)
20592 const unsigned n_haloed_iproc = this->nroot_haloed_element(iproc);
20595 for (
unsigned ihd = 0; ihd < n_haloed_iproc; ihd++)
20598 GeneralisedElement* haloed_ele_pt =
20599 this->root_haloed_element_pt(iproc, ihd);
20602 unsigned nh_count4 = 0;
20604 for (
unsigned e = 0; e < nelement_before_load_balance; e++)
20607 GeneralisedElement* ele_pt = this->element_pt(e);
20609 if (!ele_pt->is_halo())
20616 if (ele_pt == haloed_ele_pt)
20619 const unsigned element_domain =
20620 target_domain_for_local_non_halo_element[nh_count4 - 1];
20625 new_domains_haloed_elements[iproc][ihd] = element_domain;
20628 counter_for_found_haloed_elements[iproc]++;
20649 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20653 if (iproc != my_rank)
20656 const unsigned n_haloed_iproc = this->nroot_haloed_element(iproc);
20660 if (n_haloed_iproc != counter_for_found_haloed_elements[iproc])
20662 std::ostringstream error_message;
20663 error_message <<
"The independent counting of found haloed elements ("
20664 << counter_for_found_haloed_elements[iproc]
20665 <<
") with processor (" << iproc
20666 <<
") is not equal to the number of haloed elements ("
20667 << n_haloed_iproc <<
") with processor (" << iproc
20669 throw OomphLibError(error_message.str(),
20670 OOMPH_CURRENT_FUNCTION,
20671 OOMPH_EXCEPTION_LOCATION);
20685 Vector<unsigned> new_domains_haloed_flat_unsigned;
20688 Vector<int> nhaloed_elements_with_iproc(nproc);
20689 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20693 if (iproc != my_rank)
20696 const unsigned n_haloed_ele_iproc = this->nroot_haloed_element(iproc);
20698 nhaloed_elements_with_iproc[iproc] = n_haloed_ele_iproc;
20701 for (
unsigned i = 0; i < n_haloed_ele_iproc; i++)
20703 new_domains_haloed_flat_unsigned.push_back(
20704 new_domains_haloed_elements[iproc][i]);
20712 Vector<int> offset_haloed_elements_with_iproc(nproc);
20713 offset_haloed_elements_with_iproc[0] = 0;
20714 for (
unsigned ip = 1; ip < nproc; ip++)
20717 offset_haloed_elements_with_iproc[ip] =
20718 offset_haloed_elements_with_iproc[ip - 1] +
20719 nhaloed_elements_with_iproc[ip - 1];
20728 unsigned counter_halo_ele_with_all_procs = 0;
20732 Vector<int> nhalo_elements_with_iproc(nproc);
20735 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20739 if (iproc != my_rank)
20742 const unsigned n_halo_ele_iproc = this->nroot_halo_element(iproc);
20744 nhalo_elements_with_iproc[iproc] = n_halo_ele_iproc;
20746 counter_halo_ele_with_all_procs += n_halo_ele_iproc;
20752 Vector<int> offset_halo_elements_with_iproc(nproc);
20753 offset_halo_elements_with_iproc[0] = 0;
20754 for (
unsigned ip = 1; ip < nproc; ip++)
20757 offset_halo_elements_with_iproc[ip] =
20758 offset_halo_elements_with_iproc[ip - 1] +
20759 nhalo_elements_with_iproc[ip - 1];
20767 Vector<unsigned> new_domains_halo_flat_unsigned(
20768 counter_halo_ele_with_all_procs);
20772 MPI_Alltoallv(&new_domains_haloed_flat_unsigned[0],
20773 &nhaloed_elements_with_iproc[0],
20774 &offset_haloed_elements_with_iproc[0],
20776 &new_domains_halo_flat_unsigned[0],
20777 &nhalo_elements_with_iproc[0],
20778 &offset_halo_elements_with_iproc[0],
20780 this->communicator_pt()->mpi_comm());
20786 unsigned counter_new_domains_halo_ele = 0;
20787 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20791 if (iproc != my_rank)
20794 const unsigned ntmp_halo_elements_with_iproc =
20795 nhalo_elements_with_iproc[iproc];
20798 for (
unsigned i = 0; i < ntmp_halo_elements_with_iproc; i++)
20802 new_domains_halo_elements[iproc][i] =
20803 new_domains_halo_flat_unsigned[counter_new_domains_halo_ele++];
20809 if (Print_timings_level_load_balance > 1)
20811 oomph_info <<
"CPU for getting domains halo elements (load balance) [1]: "
20812 << TimingHelpers::timer() - tt_start_get_domains_halo_elements
20827 double tt_start_get_fe_version_from_ge_halo_ed = 0.0;
20828 if (Print_timings_level_load_balance > 1)
20830 tt_start_get_fe_version_from_ge_halo_ed = TimingHelpers::timer();
20834 Vector<Vector<FiniteElement*>> f_halo_element_pt(nproc);
20836 Vector<Vector<FiniteElement*>> f_haloed_element_pt(nproc);
20838 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20841 if (iproc != my_rank)
20844 const unsigned nhalo_ele_iproc = this->nroot_halo_element(iproc);
20846 Vector<GeneralisedElement*> halo_element_pt_iproc =
20847 this->root_halo_element_pt(iproc);
20849 f_halo_element_pt[iproc].resize(nhalo_ele_iproc);
20851 for (
unsigned ih = 0; ih < nhalo_ele_iproc; ih++)
20854 FiniteElement* ele_pt =
20855 dynamic_cast<FiniteElement*
>(halo_element_pt_iproc[ih]);
20857 f_halo_element_pt[iproc][ih] = ele_pt;
20861 const unsigned nhaloed_ele_iproc = this->nroot_haloed_element(iproc);
20863 Vector<GeneralisedElement*> haloed_element_pt_iproc =
20864 this->root_haloed_element_pt(iproc);
20866 f_haloed_element_pt[iproc].resize(nhaloed_ele_iproc);
20868 for (
unsigned ihd = 0; ihd < nhaloed_ele_iproc; ihd++)
20871 FiniteElement* ele_pt =
20872 dynamic_cast<FiniteElement*
>(haloed_element_pt_iproc[ihd]);
20874 f_haloed_element_pt[iproc][ihd] = ele_pt;
20883 if (Print_timings_level_load_balance > 1)
20885 oomph_info <<
"CPU for getting finite element versions from generalised "
20886 "halo(ed) elements (load balance) [2]: "
20887 << TimingHelpers::timer() -
20888 tt_start_get_fe_version_from_ge_halo_ed
20905 double tt_start_prepare_element_to_send = 0.0;
20906 if (Print_timings_level_load_balance > 1)
20908 tt_start_prepare_element_to_send = TimingHelpers::timer();
20912 Vector<Vector<FiniteElement*>> elements_to_send_pt(nproc);
20916 std::map<Data*, std::set<unsigned>>
20917 processors_associated_with_data_before_load_balance;
20921 unsigned nh_count3 = 0;
20922 for (
unsigned e = 0; e < nelement_before_load_balance; e++)
20925 FiniteElement* ele_pt = this->finite_element_pt(e);
20927 if (!(ele_pt->is_halo()))
20930 const unsigned element_domain =
20931 target_domain_for_local_non_halo_element[nh_count3++];
20934 elements_to_send_pt[element_domain].push_back(ele_pt);
20937 const unsigned n_nodes = ele_pt->nnode();
20939 for (
unsigned j = 0; j < n_nodes; j++)
20942 Node* node_pt = ele_pt->node_pt(j);
20944 processors_associated_with_data_before_load_balance[node_pt].insert(
20957 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20960 if (iproc != my_rank)
20963 const unsigned n_halo_ele_iproc = this->nroot_halo_element(iproc);
20965 Vector<GeneralisedElement*> halo_element_pt_iproc =
20966 this->root_halo_element_pt(iproc);
20968 for (
unsigned ih = 0; ih < n_halo_ele_iproc; ih++)
20971 const unsigned element_domain = new_domains_halo_elements[iproc][ih];
20974 FiniteElement* ele_pt =
20975 dynamic_cast<FiniteElement*
>(halo_element_pt_iproc[ih]);
20978 const unsigned n_nodes = ele_pt->nnode();
20980 for (
unsigned j = 0; j < n_nodes; j++)
20983 Node* node_pt = ele_pt->node_pt(j);
20986 processors_associated_with_data_before_load_balance[node_pt].insert(
20998 if (Print_timings_level_load_balance > 1)
21000 oomph_info <<
"CPU for preparing elements to send to other processors "
21001 "(load balance) [3]: "
21002 << TimingHelpers::timer() - tt_start_prepare_element_to_send
21025 double tt_start_compute_new_local_halo_elements = 0.0;
21026 if (Print_timings_level_load_balance > 1)
21028 tt_start_compute_new_local_halo_elements = TimingHelpers::timer();
21058 Vector<Vector<Vector<FiniteElement*>>> new_local_halo_element_pt(nproc);
21061 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21064 new_local_halo_element_pt[iproc].resize(nproc);
21068 Vector<std::map<FiniteElement*, bool>> new_local_halo_already_added(
21073 unsigned nh_count5 = 0;
21074 for (
unsigned e = 0; e < nelement_before_load_balance; e++)
21077 FiniteElement* ele_pt = this->finite_element_pt(e);
21079 if (!(ele_pt->is_halo()))
21082 const unsigned ele_domain =
21083 target_domain_for_local_non_halo_element[nh_count5++];
21086 if (ele_domain != iproc)
21089 const unsigned nnodes = ele_pt->nnode();
21091 for (
unsigned j = 0; j < nnodes; j++)
21093 Node* node_pt = ele_pt->node_pt(j);
21096 std::set<unsigned>::iterator it =
21097 processors_associated_with_data_before_load_balance[node_pt]
21101 processors_associated_with_data_before_load_balance[node_pt]
21108 if (!new_local_halo_already_added[ele_domain][ele_pt])
21112 new_local_halo_element_pt[iproc][ele_domain].push_back(
21115 new_local_halo_already_added[ele_domain][ele_pt] =
true;
21153 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21157 if (jproc != my_rank)
21160 const unsigned n_halo_ele_jproc = this->nroot_halo_element(jproc);
21162 Vector<GeneralisedElement*> halo_element_pt_jproc =
21163 this->root_halo_element_pt(jproc);
21166 for (
unsigned jh = 0; jh < n_halo_ele_jproc; jh++)
21169 const unsigned ele_domain = new_domains_halo_elements[jproc][jh];
21200 if (ele_domain != iproc)
21203 FiniteElement* ele_pt =
21204 dynamic_cast<FiniteElement*
>(halo_element_pt_jproc[jh]);
21206 const unsigned nnodes = ele_pt->nnode();
21208 for (
unsigned j = 0; j < nnodes; j++)
21211 Node* node_pt = ele_pt->node_pt(j);
21215 std::set<unsigned>::iterator it =
21216 processors_associated_with_data_before_load_balance[node_pt]
21220 processors_associated_with_data_before_load_balance[node_pt]
21228 if (!new_local_halo_already_added[ele_domain][ele_pt])
21232 new_local_halo_element_pt[iproc][ele_domain].push_back(
21234 new_local_halo_already_added[ele_domain][ele_pt] =
true;
21263 if (Print_timings_level_load_balance > 1)
21266 <<
"CPU for computing new local halo elements (load balance) [4]: "
21267 << TimingHelpers::timer() - tt_start_compute_new_local_halo_elements
21286 double tt_start_compute_new_local_shd_bnd_ele = 0.0;
21287 if (Print_timings_level_load_balance > 1)
21289 tt_start_compute_new_local_shd_bnd_ele = TimingHelpers::timer();
21294 Vector<Vector<Vector<FiniteElement*>>>
21295 new_local_halo_shared_boundary_element_pt(nproc);
21296 Vector<Vector<Vector<unsigned>>>
21297 new_local_halo_shared_boundary_element_face_index(nproc);
21300 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21302 new_local_halo_shared_boundary_element_pt[iproc].resize(nproc);
21303 new_local_halo_shared_boundary_element_face_index[iproc].resize(nproc);
21311 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21317 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
21319 this->get_shared_boundary_elements_and_face_indexes(
21320 new_local_halo_element_pt[iproc][jproc],
21321 new_local_halo_element_pt[jproc][iproc],
21322 new_local_halo_shared_boundary_element_pt[iproc][jproc],
21323 new_local_halo_shared_boundary_element_face_index[iproc][jproc],
21324 new_local_halo_shared_boundary_element_pt[jproc][iproc],
21325 new_local_halo_shared_boundary_element_face_index[jproc][iproc]);
21330 if (Print_timings_level_load_balance > 1)
21332 oomph_info <<
"CPU for computing new local shared boundary elements "
21333 "(load balance) [5]: "
21334 << TimingHelpers::timer() -
21335 tt_start_compute_new_local_shd_bnd_ele
21354 double tt_start_send_elements_to_other_processors = 0.0;
21355 if (Print_timings_level_load_balance > 1)
21357 tt_start_send_elements_to_other_processors = TimingHelpers::timer();
21363 this->sort_nodes_on_shared_boundaries();
21366 Vector<Vector<FiniteElement*>> received_elements_pt(nproc);
21373 Vector<Vector<Vector<FiniteElement*>>>
21374 new_received_haloed_shared_boundary_element_pt(nproc);
21375 Vector<Vector<Vector<unsigned>>>
21376 new_received_haloed_shared_boundary_element_face_index(nproc);
21381 Vector<Vector<Vector<std::map<unsigned, Node*>>>>
21382 other_proc_shd_bnd_node_pt(nproc);
21384 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21387 other_proc_shd_bnd_node_pt[iproc].resize(nproc);
21388 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21391 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
21392 const unsigned final_shd_bnd_id = this->final_shared_boundary_id();
21393 const unsigned n_shared_bound = final_shd_bnd_id - initial_shd_bnd_id;
21394 other_proc_shd_bnd_node_pt[iproc][jproc].resize(n_shared_bound);
21403 Vector<Vector<Vector<unsigned>>> global_node_names;
21407 std::map<Vector<unsigned>,
unsigned> node_name_to_global_index;
21410 Vector<Node*> global_shared_node_pt;
21415 compute_global_node_names_and_shared_nodes(other_proc_shd_bnd_node_pt,
21417 node_name_to_global_index,
21418 global_shared_node_pt);
21423 Vector<Vector<std::map<unsigned, FiniteElement*>>>
21424 received_old_haloed_element_pt(nproc);
21431 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21433 received_old_haloed_element_pt[iproc].resize(nproc);
21438 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21440 if (iproc != my_rank)
21447 Vector<FiniteElement*> currently_sent_elements;
21449 Vector<Node*> currently_sent_nodes;
21452 Flat_packed_unsigneds.clear();
21453 Flat_packed_doubles.clear();
21454 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21455 Flat_packed_unsigneds_string.clear();
21459 const unsigned nelements_to_send = elements_to_send_pt[iproc].size();
21465 Flat_packed_unsigneds.push_back(nelements_to_send);
21466 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21467 std::stringstream junk;
21468 junk <<
"Number of elements to send from processor " << my_rank
21469 <<
" to processor " << iproc <<
": (" << nelements_to_send <<
")";
21470 Flat_packed_unsigneds_string.push_back(junk.str());
21474 for (
unsigned e = 0; e < nelements_to_send; e++)
21477 FiniteElement* send_ele_pt = elements_to_send_pt[iproc][e];
21480 const unsigned ncurrently_sent_elements =
21481 currently_sent_elements.size();
21484 const unsigned index_ele = try_to_add_element_pt_load_balance(
21485 currently_sent_elements, send_ele_pt);
21488 if (index_ele == ncurrently_sent_elements)
21490 Flat_packed_unsigneds.push_back(1);
21491 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21492 Flat_packed_unsigneds_string.push_back(
21493 "Element needs to be constructed");
21497 get_required_elemental_information_load_balance_helper(
21498 iproc, f_haloed_element_pt, send_ele_pt);
21501 const unsigned nnodes = send_ele_pt->nnode();
21504 for (
unsigned j = 0; j < nnodes; j++)
21506 Node* node_pt = send_ele_pt->node_pt(j);
21509 add_node_load_balance_helper(iproc,
21511 currently_sent_nodes,
21519 Flat_packed_unsigneds.push_back(0);
21520 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21521 Flat_packed_unsigneds_string.push_back(
"Element already exists");
21523 Flat_packed_unsigneds.push_back(index_ele);
21524 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21525 Flat_packed_unsigneds_string.push_back(
"Index of existing element");
21544 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21550 const unsigned njproc_iproc_new_local_halo_shared_boundary_ele =
21551 new_local_halo_shared_boundary_element_pt[jproc][iproc].size();
21554 Vector<unsigned> new_local_halo_shared_boundary_ele_index;
21558 unsigned nfound_new_local_halo_shared_bound_ele_index = 0;
21561 unsigned nnon_halo_new_local_halo_shared_bound_ele = 0;
21565 for (
unsigned e = 0;
21566 e < njproc_iproc_new_local_halo_shared_boundary_ele;
21570 FiniteElement* shared_ele_pt =
21571 new_local_halo_shared_boundary_element_pt[jproc][iproc][e];
21575 if (!shared_ele_pt->is_halo())
21577 nnon_halo_new_local_halo_shared_bound_ele++;
21582 const unsigned ncurrently_sent_elements =
21583 currently_sent_elements.size();
21585 for (
unsigned ics = 0; ics < ncurrently_sent_elements; ics++)
21587 FiniteElement* currently_sent_ele_pt =
21588 currently_sent_elements[ics];
21591 if (currently_sent_ele_pt == shared_ele_pt)
21595 new_local_halo_shared_boundary_ele_index.push_back(ics);
21598 nfound_new_local_halo_shared_bound_ele_index++;
21610 if (nfound_new_local_halo_shared_bound_ele_index !=
21611 nnon_halo_new_local_halo_shared_bound_ele)
21613 std::ostringstream error_message;
21614 error_message <<
"Was only possible to identify ("
21615 << nfound_new_local_halo_shared_bound_ele_index
21617 << nnon_halo_new_local_halo_shared_bound_ele
21619 <<
"elements between\nprocessor (" << iproc
21620 <<
") and (" << jproc <<
") "
21621 <<
"when sending elements to processor (" << iproc
21623 throw OomphLibError(error_message.str(),
21624 OOMPH_CURRENT_FUNCTION,
21625 OOMPH_EXCEPTION_LOCATION);
21630 Flat_packed_unsigneds.push_back(9999);
21631 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21632 std::stringstream junk;
21633 junk <<
"Flag for synchronisation 9999";
21634 Flat_packed_unsigneds_string.push_back(junk.str());
21639 Flat_packed_unsigneds.push_back(
21640 nnon_halo_new_local_halo_shared_bound_ele);
21641 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21642 std::stringstream junk2;
21643 junk2 <<
"Number of new local halo shared boundary elements "
21644 << nnon_halo_new_local_halo_shared_bound_ele;
21645 Flat_packed_unsigneds_string.push_back(junk2.str());
21650 unsigned counter_nonhalo_sent = 0;
21653 for (
unsigned e = 0;
21654 e < njproc_iproc_new_local_halo_shared_boundary_ele;
21658 FiniteElement* shared_ele_pt =
21659 new_local_halo_shared_boundary_element_pt[jproc][iproc][e];
21663 if (!shared_ele_pt->is_halo())
21667 const unsigned ele_index =
21668 new_local_halo_shared_boundary_ele_index
21669 [counter_nonhalo_sent++];
21671 const unsigned face_index =
21672 new_local_halo_shared_boundary_element_face_index[jproc][iproc]
21677 Flat_packed_unsigneds.push_back(ele_index);
21678 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21679 std::stringstream junk;
21680 junk <<
"The index of the halo shared boundary element "
21682 Flat_packed_unsigneds_string.push_back(junk.str());
21687 Flat_packed_unsigneds.push_back(face_index);
21688 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21689 std::stringstream junk2;
21690 junk2 <<
"The face index of the halo shared boundary element "
21692 Flat_packed_unsigneds_string.push_back(junk2.str());
21705 int send_proc =
static_cast<int>(iproc);
21707 int recv_proc =
static_cast<int>(iproc);
21708 send_and_receive_elements_nodes_info(send_proc, recv_proc);
21715 Vector<FiniteElement*> currently_created_elements;
21717 Vector<Node*> currently_created_nodes;
21720 Counter_for_flat_packed_doubles = 0;
21721 Counter_for_flat_packed_unsigneds = 0;
21723 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21724 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
21725 <<
" Number of elements need to be constructed "
21726 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
21731 const unsigned nelements_to_create =
21732 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
21734 for (
unsigned e = 0; e < nelements_to_create; e++)
21738 create_element_load_balance_helper(iproc,
21739 f_haloed_element_pt,
21740 received_old_haloed_element_pt,
21741 currently_created_elements,
21742 currently_created_nodes,
21743 other_proc_shd_bnd_node_pt,
21745 node_name_to_global_index,
21746 global_shared_node_pt);
21752 const unsigned nreceived_elements = currently_created_elements.size();
21753 received_elements_pt[iproc].resize(nreceived_elements);
21754 for (
unsigned e = 0; e < nreceived_elements; e++)
21756 received_elements_pt[iproc][e] = currently_created_elements[e];
21763 new_received_haloed_shared_boundary_element_pt[iproc].resize(nproc);
21764 new_received_haloed_shared_boundary_element_face_index[iproc].resize(
21768 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21771 const unsigned synchronisation_flag =
21772 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
21774 if (synchronisation_flag != 9999)
21776 std::ostringstream error_message;
21777 error_message <<
"The synchronisation flag was not read, the\n"
21778 <<
"information sent between processor (" << my_rank
21780 <<
"and (" << iproc
21781 <<
")\nis no longer synchronised\n\n";
21782 throw OomphLibError(error_message.str(),
21783 OOMPH_CURRENT_FUNCTION,
21784 OOMPH_EXCEPTION_LOCATION);
21790 const unsigned niproc_jproc_new_received_haloed_shared_boundary_ele =
21791 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
21794 for (
unsigned e = 0;
21795 e < niproc_jproc_new_received_haloed_shared_boundary_ele;
21800 const unsigned ele_index =
21801 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
21804 const unsigned face_index =
21805 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
21808 FiniteElement* shared_ele_pt =
21809 currently_created_elements[ele_index];
21814 new_received_haloed_shared_boundary_element_pt[iproc][jproc]
21815 .push_back(shared_ele_pt);
21817 new_received_haloed_shared_boundary_element_face_index[iproc][jproc]
21818 .push_back(face_index);
21829 if (Print_timings_level_load_balance > 1)
21831 oomph_info <<
"CPU for sending elements to their new processors (load "
21833 << TimingHelpers::timer() -
21834 tt_start_send_elements_to_other_processors
21853 double tt_start_compute_additional_shared_boundaries = 0.0;
21854 if (Print_timings_level_load_balance > 1)
21856 tt_start_compute_additional_shared_boundaries = TimingHelpers::timer();
21862 Vector<Vector<FiniteElement*>> tmp_group1_shared_boundary_element_pt(nproc);
21863 Vector<Vector<unsigned>> tmp_group1_shared_boundary_element_face_index(
21865 Vector<Vector<FiniteElement*>> tmp_group2_shared_boundary_element_pt(nproc);
21866 Vector<Vector<unsigned>> tmp_group2_shared_boundary_element_face_index(
21891 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21893 if (my_rank < iproc)
21896 this->get_shared_boundary_elements_and_face_indexes(
21897 received_elements_pt[iproc],
21898 elements_to_send_pt[iproc],
21899 tmp_group1_shared_boundary_element_pt[iproc],
21900 tmp_group1_shared_boundary_element_face_index[iproc],
21901 tmp_group2_shared_boundary_element_pt[iproc],
21902 tmp_group2_shared_boundary_element_face_index[iproc]);
21905 else if (my_rank > iproc)
21908 this->get_shared_boundary_elements_and_face_indexes(
21909 elements_to_send_pt[iproc],
21910 received_elements_pt[iproc],
21911 tmp_group1_shared_boundary_element_pt[iproc],
21912 tmp_group1_shared_boundary_element_face_index[iproc],
21913 tmp_group2_shared_boundary_element_pt[iproc],
21914 tmp_group2_shared_boundary_element_face_index[iproc]);
21921 if (Print_timings_level_load_balance > 1)
21924 <<
"CPU for computing additional shared boundaries (load balance) [7]: "
21925 << TimingHelpers::timer() -
21926 tt_start_compute_additional_shared_boundaries
21945 double tt_start_sort_shared_boundaries = 0.0;
21946 if (Print_timings_level_load_balance > 1)
21948 tt_start_sort_shared_boundaries = TimingHelpers::timer();
21969 Vector<Vector<FiniteElement*>> new_shared_boundary_element_pt(nproc);
21970 Vector<Vector<unsigned>> new_shared_boundary_element_face_index(nproc);
21971 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21974 if (my_rank < iproc)
21978 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21981 if (jproc != my_rank)
21984 const unsigned nrecvd_haloed_shared_bound_ele_jproc_iproc =
21985 new_received_haloed_shared_boundary_element_pt[jproc][iproc]
21987 for (
unsigned e = 0; e < nrecvd_haloed_shared_bound_ele_jproc_iproc;
21991 FiniteElement* ele_pt =
21992 new_received_haloed_shared_boundary_element_pt[jproc][iproc][e];
21994 const unsigned face_index =
21995 new_received_haloed_shared_boundary_element_face_index[jproc]
22000 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
22001 new_shared_boundary_element_face_index[iproc].push_back(
22012 const unsigned nlocal_haloed_shared_bound_ele_iproc_my_rank =
22013 new_local_halo_shared_boundary_element_pt[iproc][my_rank].size();
22014 for (
unsigned e = 0; e < nlocal_haloed_shared_bound_ele_iproc_my_rank;
22018 FiniteElement* ele_pt =
22019 new_local_halo_shared_boundary_element_pt[iproc][my_rank][e];
22021 const unsigned face_index =
22022 new_local_halo_shared_boundary_element_face_index[iproc][my_rank]
22028 if (!ele_pt->is_halo())
22031 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
22032 new_shared_boundary_element_face_index[iproc].push_back(face_index);
22039 const unsigned ntmp_group1_shared_bound_ele_iproc =
22040 tmp_group1_shared_boundary_element_pt[iproc].size();
22041 for (
unsigned e = 0; e < ntmp_group1_shared_bound_ele_iproc; e++)
22044 FiniteElement* ele_pt =
22045 tmp_group1_shared_boundary_element_pt[iproc][e];
22047 const unsigned face_index =
22048 tmp_group1_shared_boundary_element_face_index[iproc][e];
22051 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
22052 new_shared_boundary_element_face_index[iproc].push_back(face_index);
22058 else if (my_rank > iproc)
22066 const unsigned nlocal_haloed_shared_bound_ele_iproc_my_rank =
22067 new_local_halo_shared_boundary_element_pt[iproc][my_rank].size();
22068 for (
unsigned e = 0; e < nlocal_haloed_shared_bound_ele_iproc_my_rank;
22072 FiniteElement* ele_pt =
22073 new_local_halo_shared_boundary_element_pt[iproc][my_rank][e];
22075 const unsigned face_index =
22076 new_local_halo_shared_boundary_element_face_index[iproc][my_rank]
22082 if (!ele_pt->is_halo())
22085 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
22086 new_shared_boundary_element_face_index[iproc].push_back(face_index);
22091 for (
unsigned jproc = 0; jproc < nproc; jproc++)
22094 if (jproc != my_rank)
22098 const unsigned nrecvd_haloed_shared_bound_ele_jproc_iproc =
22099 new_received_haloed_shared_boundary_element_pt[jproc][iproc]
22101 for (
unsigned e = 0; e < nrecvd_haloed_shared_bound_ele_jproc_iproc;
22105 FiniteElement* ele_pt =
22106 new_received_haloed_shared_boundary_element_pt[jproc][iproc][e];
22108 const unsigned face_index =
22109 new_received_haloed_shared_boundary_element_face_index[jproc]
22114 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
22115 new_shared_boundary_element_face_index[iproc].push_back(
22126 const unsigned ntmp_group2_shared_bound_ele_iproc =
22127 tmp_group2_shared_boundary_element_pt[iproc].size();
22128 for (
unsigned e = 0; e < ntmp_group2_shared_bound_ele_iproc; e++)
22131 FiniteElement* ele_pt =
22132 tmp_group2_shared_boundary_element_pt[iproc][e];
22134 const unsigned face_index =
22135 tmp_group2_shared_boundary_element_face_index[iproc][e];
22138 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
22139 new_shared_boundary_element_face_index[iproc].push_back(face_index);
22148 if (Print_timings_level_load_balance > 1)
22150 oomph_info <<
"CPU for sorting shared boundaries (load balance) [8]: "
22151 << TimingHelpers::timer() - tt_start_sort_shared_boundaries
22172 double tt_start_create_new_shared_boundaries = 0.0;
22173 if (Print_timings_level_load_balance > 1)
22175 tt_start_create_new_shared_boundaries = TimingHelpers::timer();
22186 std::set<FiniteElement*> element_in_processor_pt;
22190 unsigned nh_count6 = 0;
22191 for (
unsigned e = 0; e < nelement_before_load_balance; e++)
22194 FiniteElement* ele_pt = backed_up_ele_pt[e];
22196 if (!(ele_pt->is_halo()))
22199 if (target_domain_for_local_non_halo_element[nh_count6++] == my_rank)
22202 element_in_processor_pt.insert(ele_pt);
22211 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22214 if (iproc != my_rank)
22218 const unsigned n_received_ele = received_elements_pt[iproc].size();
22219 for (
unsigned ie = 0; ie < n_received_ele; ie++)
22222 FiniteElement* ele_pt = received_elements_pt[iproc][ie];
22225 element_in_processor_pt.insert(ele_pt);
22234 create_new_shared_boundaries(element_in_processor_pt,
22235 new_shared_boundary_element_pt,
22236 new_shared_boundary_element_face_index);
22239 if (Print_timings_level_load_balance > 1)
22242 <<
"CPU for creating new shared boundaries (load balance) [9]: "
22243 << TimingHelpers::timer() - tt_start_create_new_shared_boundaries
22265 double tt_start_delete_elements = 0.0;
22266 if (Print_timings_level_load_balance > 1)
22268 tt_start_delete_elements = TimingHelpers::timer();
22279 this->Halo_node_pt.clear();
22280 this->Root_halo_element_pt.clear();
22282 this->Haloed_node_pt.clear();
22283 this->Root_haloed_element_pt.clear();
22286 const unsigned nnodes = this->nnode();
22287 for (
unsigned j = 0; j < nnodes; j++)
22289 this->node_pt(j)->set_obsolete();
22293 this->flush_element_storage();
22296 this->delete_all_external_storage();
22299 this->External_halo_node_pt.clear();
22300 this->External_halo_element_pt.clear();
22302 this->External_haloed_node_pt.clear();
22303 this->External_haloed_element_pt.clear();
22306 Vector<FiniteElement*> deleted_elements;
22309 unsigned nh_count7 = 0;
22310 for (
unsigned e = 0; e < nelement_before_load_balance; e++)
22312 FiniteElement* ele_pt = backed_up_ele_pt[e];
22314 if (!(ele_pt->is_halo()))
22316 if (target_domain_for_local_non_halo_element[nh_count7++] == my_rank)
22319 this->add_element_pt(ele_pt);
22321 const unsigned nele_nodes = ele_pt->nnode();
22323 for (
unsigned j = 0; j < nele_nodes; j++)
22326 ele_pt->node_pt(j)->set_non_obsolete();
22333 deleted_elements.push_back(ele_pt);
22343 deleted_elements.push_back(ele_pt);
22352 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22354 if (iproc != my_rank)
22358 const unsigned nreceived_ele = received_elements_pt[iproc].size();
22359 for (
unsigned ie = 0; ie < nreceived_ele; ie++)
22362 FiniteElement* ele_pt = received_elements_pt[iproc][ie];
22364 this->add_element_pt(ele_pt);
22366 const unsigned nele_nodes = ele_pt->nnode();
22368 for (
unsigned j = 0; j < nele_nodes; j++)
22371 ele_pt->node_pt(j)->set_non_obsolete();
22381 this->prune_dead_nodes();
22384 if (Print_timings_level_load_balance > 1)
22386 oomph_info <<
"CPU for deleting elements no longer belonging to this "
22387 "processor (load balance) [10]: "
22388 << TimingHelpers::timer() - tt_start_delete_elements
22406 double tt_start_re_etablish_halo_ed_info = 0.0;
22407 if (Print_timings_level_load_balance > 1)
22409 tt_start_re_etablish_halo_ed_info = TimingHelpers::timer();
22416 this->sort_nodes_on_shared_boundaries();
22423 const unsigned tmp_nboundary = this->nboundary();
22424 Vector<unsigned> ntmp_boundary_elements(tmp_nboundary);
22427 Vector<Vector<unsigned>> ntmp_boundary_elements_in_region(tmp_nboundary);
22429 const unsigned n_regions = this->nregion();
22432 for (
unsigned ib = 0; ib < tmp_nboundary; ib++)
22435 ntmp_boundary_elements[ib] = this->nboundary_element(ib);
22438 ntmp_boundary_elements_in_region[ib].resize(n_regions);
22441 for (
unsigned rr = 0; rr < n_regions; rr++)
22444 const unsigned region_id =
22445 static_cast<unsigned>(this->region_attribute(rr));
22450 ntmp_boundary_elements_in_region[ib][rr] =
22451 this->nboundary_element_in_region(ib, region_id);
22458 this->reset_halo_haloed_scheme();
22461 const unsigned nelement_after_load_balance = this->nelement();
22465 this->reset_boundary_element_info(ntmp_boundary_elements,
22466 ntmp_boundary_elements_in_region,
22492 for (
unsigned b = 0; b < tmp_nboundary; b++)
22494 if (this->boundary_geom_object_pt(b) != 0)
22497 this->flush_boundary_segment_node(b);
22500 Vector<Vector<Node*>> dummy_segment_node_pt;
22503 get_boundary_segment_nodes_helper(b, dummy_segment_node_pt);
22506 const unsigned nsegments = dummy_segment_node_pt.size();
22510 this->set_nboundary_segment_node(b, nsegments);
22516 if (Print_timings_level_load_balance > 1)
22519 <<
"CPU for re-establishing halo(ed) information (load balance) [11]: "
22520 << TimingHelpers::timer() - tt_start_re_etablish_halo_ed_info
22531 if (Print_timings_level_load_balance > 1)
22533 oomph_info <<
"CPU for load balance [n_ele_before="
22534 << nelement_before_load_balance
22535 <<
", n_ele_after=" << nelement_after_load_balance <<
"]: "
22536 << TimingHelpers::timer() - t_start_overall_load_balance
22540 oomph_info <<
"Load balance (unstructured mesh) [END]" << std::endl;
22548 template<
class ELEMENT>
22551 const Vector<FiniteElement*>& first_element_pt,
22552 const Vector<FiniteElement*>& second_element_pt,
22553 Vector<FiniteElement*>& first_shared_boundary_element_pt,
22554 Vector<unsigned>& first_shared_boundary_element_face_index,
22555 Vector<FiniteElement*>& second_shared_boundary_element_pt,
22556 Vector<unsigned>& second_shared_boundary_element_face_index)
22564 const unsigned nfirst_element = first_element_pt.size();
22566 for (
unsigned ef = 0; ef < nfirst_element; ef++)
22569 FiniteElement* fele_pt = first_element_pt[ef];
22571 bool first_ele_is_halo =
false;
22572 if (fele_pt->is_halo())
22574 first_ele_is_halo =
true;
22577 for (
unsigned ifface = 0; ifface < 3; ifface++)
22579 Vector<Node*> first_face(2);
22582 first_face[0] = fele_pt->node_pt(1);
22583 first_face[1] = fele_pt->node_pt(2);
22585 else if (ifface == 1)
22587 first_face[0] = fele_pt->node_pt(2);
22588 first_face[1] = fele_pt->node_pt(0);
22590 else if (ifface == 2)
22592 first_face[0] = fele_pt->node_pt(0);
22593 first_face[1] = fele_pt->node_pt(1);
22600 const unsigned nsecond_element = second_element_pt.size();
22602 for (
unsigned es = 0; es < nsecond_element; es++)
22605 FiniteElement* sele_pt = second_element_pt[es];
22607 bool second_ele_is_halo =
false;
22608 if (sele_pt->is_halo())
22610 second_ele_is_halo =
true;
22617 if (!(first_ele_is_halo && second_ele_is_halo))
22620 for (
unsigned isface = 0; isface < 3; isface++)
22622 Vector<Node*> second_face(2);
22625 second_face[0] = sele_pt->node_pt(1);
22626 second_face[1] = sele_pt->node_pt(2);
22628 else if (isface == 1)
22630 second_face[0] = sele_pt->node_pt(2);
22631 second_face[1] = sele_pt->node_pt(0);
22633 else if (isface == 2)
22635 second_face[0] = sele_pt->node_pt(0);
22636 second_face[1] = sele_pt->node_pt(1);
22641 if (first_face[0] == second_face[0] &&
22642 first_face[1] == second_face[1])
22645 first_shared_boundary_element_pt.push_back(fele_pt);
22647 first_shared_boundary_element_face_index.push_back(ifface);
22650 second_shared_boundary_element_pt.push_back(sele_pt);
22652 second_shared_boundary_element_face_index.push_back(isface);
22660 es = nsecond_element;
22663 else if (first_face[0] == second_face[1] &&
22664 first_face[1] == second_face[0])
22667 first_shared_boundary_element_pt.push_back(fele_pt);
22669 first_shared_boundary_element_face_index.push_back(ifface);
22672 second_shared_boundary_element_pt.push_back(sele_pt);
22674 second_shared_boundary_element_face_index.push_back(isface);
22682 es = nsecond_element;
22701 template<
class ELEMENT>
22703 std::set<FiniteElement*>& element_in_processor_pt,
22704 Vector<Vector<FiniteElement*>>& new_shared_boundary_element_pt,
22705 Vector<Vector<unsigned>>& new_shared_boundary_element_face_index)
22708 const unsigned nproc = this->communicator_pt()->nproc();
22710 const unsigned my_rank = this->communicator_pt()->my_rank();
22720 double tt_start_get_edges_from_shd_bnd_face_ele = 0.0;
22721 if (Print_timings_level_load_balance > 2)
22723 tt_start_get_edges_from_shd_bnd_face_ele = TimingHelpers::timer();
22727 Vector<Vector<FiniteElement*>> tmp_unsorted_face_ele_pt(nproc);
22729 Vector<Vector<FiniteElement*>> tmp_unsorted_ele_pt(nproc);
22732 Vector<Vector<int>> tmp_unsorted_face_index_ele(nproc);
22736 std::map<std::pair<Node*, Node*>,
unsigned> elements_edges_on_boundary;
22739 this->get_element_edges_on_boundary(elements_edges_on_boundary);
22742 std::map<std::pair<Node*, Node*>,
bool> overlapped_edge;
22748 Vector<Vector<int>> tmp_edge_boundary(nproc);
22752 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22755 if (iproc != my_rank)
22759 const unsigned n_shared_bound_ele =
22760 new_shared_boundary_element_pt[iproc].size();
22764 Vector<std::pair<Node*, Node*>> done_faces;
22767 unsigned nrepeated_faces = 0;
22771 for (
unsigned iele = 0; iele < n_shared_bound_ele; iele++)
22774 FiniteElement* bulk_ele_pt =
22775 new_shared_boundary_element_pt[iproc][iele];
22778 int face_index =
static_cast<int>(
22779 new_shared_boundary_element_face_index[iproc][iele]);
22782 FiniteElement* tmp_ele_pt =
22783 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
22787 bool done_face =
false;
22791 const unsigned nnode_face_ele = tmp_ele_pt->nnode();
22792 Node* first_face_node_pt = tmp_ele_pt->node_pt(0);
22793 Node* last_face_node_pt = tmp_ele_pt->node_pt(nnode_face_ele - 1);
22796 const unsigned ndone_faces = done_faces.size();
22798 for (
unsigned n = 0; n < ndone_faces; n++)
22800 Node* first_done_face_node_pt = done_faces[n].first;
22801 Node* second_done_face_node_pt = done_faces[n].second;
22802 if (first_face_node_pt == first_done_face_node_pt &&
22803 last_face_node_pt == second_done_face_node_pt)
22810 else if (first_face_node_pt == second_done_face_node_pt &&
22811 last_face_node_pt == first_done_face_node_pt)
22824 tmp_unsorted_face_ele_pt[iproc].push_back(tmp_ele_pt);
22826 tmp_unsorted_ele_pt[iproc].push_back(bulk_ele_pt);
22828 tmp_unsorted_face_index_ele[iproc].push_back(face_index);
22830 std::pair<Node*, Node*> tmp_edge =
22831 std::make_pair(first_face_node_pt, last_face_node_pt);
22833 done_faces.push_back(tmp_edge);
22837 int edge_boundary_id = -1;
22838 std::map<std::pair<Node*, Node*>,
unsigned>::iterator it;
22839 it = elements_edges_on_boundary.find(tmp_edge);
22842 if (it != elements_edges_on_boundary.end())
22846 edge_boundary_id = (*it).second;
22848 overlapped_edge[tmp_edge] =
true;
22850 std::pair<Node*, Node*> rev_tmp_edge =
22851 std::make_pair(last_face_node_pt, first_face_node_pt);
22853 overlapped_edge[rev_tmp_edge] =
true;
22858 std::pair<Node*, Node*> rtmp_edge =
22859 std::make_pair(last_face_node_pt, first_face_node_pt);
22860 it = elements_edges_on_boundary.find(rtmp_edge);
22861 if (it != elements_edges_on_boundary.end())
22865 edge_boundary_id = (*it).second;
22867 overlapped_edge[rtmp_edge] =
true;
22870 overlapped_edge[tmp_edge] =
true;
22874 tmp_edge_boundary[iproc].push_back(edge_boundary_id);
22890 if (Print_timings_level_load_balance > 2)
22892 oomph_info <<
"CPU for getting edges from shared boundary face elements "
22893 "(load balance) [9.1]: "
22894 << TimingHelpers::timer() -
22895 tt_start_get_edges_from_shd_bnd_face_ele
22916 double tt_start_sort_shared_face_elements = 0.0;
22917 if (Print_timings_level_load_balance > 2)
22919 tt_start_sort_shared_face_elements = TimingHelpers::timer();
22928 Vector<Vector<FiniteElement*>> unsorted_face_ele_pt(nproc);
22930 Vector<Vector<FiniteElement*>> unsorted_ele_pt(nproc);
22933 Vector<Vector<int>> unsorted_face_index_ele(nproc);
22937 Vector<Vector<int>> edge_boundary(nproc);
22943 std::vector<std::vector<bool>> tmp_treat_as_inverted(nproc);
22946 std::vector<std::vector<bool>> treat_as_inverted(nproc);
22952 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22955 if (iproc != my_rank)
22958 const unsigned n_face_ele = tmp_unsorted_face_ele_pt[iproc].size();
22961 Vector<Vector<double>> centroid_vertices(n_face_ele);
22965 tmp_treat_as_inverted[iproc].resize(n_face_ele);
22969 for (
unsigned e = 0; e < n_face_ele; e++)
22972 FiniteElement* face_ele_pt = tmp_unsorted_face_ele_pt[iproc][e];
22974 const unsigned n_node = face_ele_pt->nnode();
22975 Vector<double> bottom_left(2);
22978 Node* node_pt = face_ele_pt->node_pt(0);
22979 bottom_left[0] = node_pt->x(0);
22980 bottom_left[1] = node_pt->x(1);
22982 tmp_treat_as_inverted[iproc][e] =
false;
22985 for (
unsigned n = 1; n < n_node; n++)
22988 Node* node_pt = face_ele_pt->node_pt(n);
22989 if (node_pt->x(1) < bottom_left[1])
22991 bottom_left[0] = node_pt->x(0);
22992 bottom_left[1] = node_pt->x(1);
22995 tmp_treat_as_inverted[iproc][e] =
true;
22997 else if (node_pt->x(1) == bottom_left[1])
22999 if (node_pt->x(0) < bottom_left[0])
23001 bottom_left[0] = node_pt->x(0);
23002 bottom_left[1] = node_pt->x(1);
23005 tmp_treat_as_inverted[iproc][e] =
true;
23012 centroid_vertices[e].resize(2);
23014 centroid_vertices[e][0] = (face_ele_pt->node_pt(0)->x(0) +
23015 face_ele_pt->node_pt(n_node - 1)->x(0)) *
23017 centroid_vertices[e][1] = (face_ele_pt->node_pt(0)->x(1) +
23018 face_ele_pt->node_pt(n_node - 1)->x(1)) *
23024 unsigned n_sorted_bottom_left = 0;
23026 std::vector<bool> done_face(n_face_ele,
false);
23029 while (n_sorted_bottom_left < n_face_ele)
23032 unsigned index = 0;
23033 Vector<double> current_bottom_left(2);
23034 for (
unsigned e = 0; e < n_face_ele; e++)
23040 current_bottom_left[0] = centroid_vertices[e][0];
23041 current_bottom_left[1] = centroid_vertices[e][1];
23051 for (
unsigned e = index + 1; e < n_face_ele; e++)
23056 if (centroid_vertices[e][1] < current_bottom_left[1])
23059 current_bottom_left[0] = centroid_vertices[e][0];
23060 current_bottom_left[1] = centroid_vertices[e][1];
23064 else if (centroid_vertices[e][1] == current_bottom_left[1])
23066 if (centroid_vertices[e][0] < current_bottom_left[0])
23069 current_bottom_left[0] = centroid_vertices[e][0];
23070 current_bottom_left[1] = centroid_vertices[e][1];
23082 unsorted_face_ele_pt[iproc].push_back(
23083 tmp_unsorted_face_ele_pt[iproc][index]);
23085 unsorted_ele_pt[iproc].push_back(tmp_unsorted_ele_pt[iproc][index]);
23087 unsorted_face_index_ele[iproc].push_back(
23088 tmp_unsorted_face_index_ele[iproc][index]);
23090 edge_boundary[iproc].push_back(tmp_edge_boundary[iproc][index]);
23092 treat_as_inverted[iproc].push_back(
23093 tmp_treat_as_inverted[iproc][index]);
23096 done_face[index] =
true;
23099 n_sorted_bottom_left++;
23106 const unsigned tmp_n_face_ele = unsorted_face_ele_pt[iproc].size();
23108 if (tmp_n_face_ele != n_face_ele)
23110 std::ostringstream error_stream;
23112 <<
"The number of face elements before sorting them starting\n"
23113 <<
"from their bottom-left vertex is different from the number\n"
23114 <<
"of face elements after the sorting\n"
23115 <<
"N. ele before sorting: (" << n_face_ele <<
")\n"
23116 <<
"N. ele after sorting: (" << tmp_n_face_ele <<
")\n";
23117 throw OomphLibError(
23118 error_stream.str(),
23119 "RefineableTriangleMesh::create_new_shared_boundaries()",
23120 OOMPH_EXCEPTION_LOCATION);
23129 if (Print_timings_level_load_balance > 2)
23131 oomph_info <<
"CPU for sorting shared boundary face elements (load "
23133 << TimingHelpers::timer() - tt_start_sort_shared_face_elements
23155 double tt_start_compute_valency_of_nodes = 0.0;
23156 if (Print_timings_level_load_balance > 2)
23158 tt_start_compute_valency_of_nodes = TimingHelpers::timer();
23162 std::map<Node*, unsigned> global_node_degree;
23165 compute_shared_node_degree_helper(unsorted_face_ele_pt, global_node_degree);
23168 if (Print_timings_level_load_balance > 2)
23171 <<
"CPU for computing the valency of nodes (load balance) [9.3]: "
23172 << TimingHelpers::timer() - tt_start_compute_valency_of_nodes
23190 double tt_start_nodes_on_non_overlapped_shd_bnd = 0.0;
23191 if (Print_timings_level_load_balance > 2)
23193 tt_start_nodes_on_non_overlapped_shd_bnd = TimingHelpers::timer();
23198 std::map<unsigned, std::map<Node*, bool>>
23199 node_on_bnd_not_overlapped_by_shd_bnd;
23202 for (std::map<std::pair<Node*, Node*>,
unsigned>::iterator it_map =
23203 elements_edges_on_boundary.begin();
23204 it_map != elements_edges_on_boundary.end();
23208 std::pair<Node*, Node*> edge_pair = (*it_map).first;
23210 if (!overlapped_edge[edge_pair])
23214 unsigned b = (*it_map).second;
23217 Node* left_node_pt = edge_pair.first;
23218 node_on_bnd_not_overlapped_by_shd_bnd[b][left_node_pt] =
true;
23221 Node* right_node_pt = edge_pair.second;
23222 node_on_bnd_not_overlapped_by_shd_bnd[b][right_node_pt] =
true;
23230 if (Print_timings_level_load_balance > 2)
23232 oomph_info <<
"CPU for computing nodes on non overlapped shared "
23233 "boundaries (load balance) [9.4]: "
23234 << TimingHelpers::timer() -
23235 tt_start_nodes_on_non_overlapped_shd_bnd
23258 double tt_start_join_shd_bnd_face_ele = 0.0;
23259 if (Print_timings_level_load_balance > 2)
23261 tt_start_join_shd_bnd_face_ele = TimingHelpers::timer();
23265 Vector<Vector<Vector<FiniteElement*>>> sorted_face_ele_pt(nproc);
23268 Vector<Vector<Vector<FiniteElement*>>> sorted_ele_pt(nproc);
23272 Vector<Vector<Vector<int>>> sorted_face_index_ele(nproc);
23278 Vector<Vector<int>> edge_boundary_id(nproc);
23282 Vector<Vector<Vector<int>>> sorted_connection_info(nproc);
23287 Vector<Vector<unsigned>> proc_local_shared_boundary_id(nproc);
23291 std::map<unsigned, std::list<Node*>>
23292 local_shd_bnd_id_to_sorted_list_node_pt;
23297 unsigned local_shd_bnd_id = this->Initial_shared_boundary_id;
23302 std::map<FiniteElement*, bool> done_ele;
23305 std::map<FiniteElement*, bool> is_inverted;
23309 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23312 if (iproc != my_rank)
23316 const unsigned nunsorted_face_ele = unsorted_face_ele_pt[iproc].size();
23318 unsigned nsorted_face_ele = 0;
23321 while (nsorted_face_ele < nunsorted_face_ele)
23330 bool found_root_element =
false;
23334 unsigned root_index = 0;
23337 std::list<FiniteElement*> tmp_sorted_face_ele_pt;
23340 std::list<FiniteElement*> tmp_sorted_ele_pt;
23344 std::list<int> tmp_sorted_face_index_ele;
23349 std::list<Node*> tmp_sorted_nodes_pt;
23351 tmp_sorted_nodes_pt.clear();
23354 Node* initial_node_pt = 0;
23355 Node* final_node_pt = 0;
23359 int root_edge_bound_id = -1;
23363 for (
unsigned e = 0; e < nunsorted_face_ele; e++)
23366 FiniteElement* root_ele_pt = unsorted_face_ele_pt[iproc][e];
23368 if (!done_ele[root_ele_pt])
23372 root_edge_bound_id = edge_boundary[iproc][e];
23375 tmp_sorted_face_ele_pt.push_back(root_ele_pt);
23377 tmp_sorted_ele_pt.push_back(unsorted_ele_pt[iproc][e]);
23380 tmp_sorted_face_index_ele.push_back(
23381 unsorted_face_index_ele[iproc][e]);
23384 const unsigned nnodes = root_ele_pt->nnode();
23386 if (!treat_as_inverted[iproc][e])
23388 initial_node_pt = root_ele_pt->node_pt(0);
23389 final_node_pt = root_ele_pt->node_pt(nnodes - 1);
23393 initial_node_pt = root_ele_pt->node_pt(nnodes - 1);
23394 final_node_pt = root_ele_pt->node_pt(0);
23397 tmp_sorted_nodes_pt.push_back(initial_node_pt);
23398 tmp_sorted_nodes_pt.push_back(final_node_pt);
23401 done_ele[root_ele_pt] =
true;
23403 if (!treat_as_inverted[iproc][e])
23406 is_inverted[root_ele_pt] =
false;
23411 is_inverted[root_ele_pt] =
true;
23414 nsorted_face_ele++;
23419 found_root_element =
true;
23429 if (!found_root_element)
23431 std::ostringstream error_stream;
23433 <<
"It was not possible the found the root element\n\n";
23434 throw OomphLibError(error_stream.str(),
23435 OOMPH_CURRENT_FUNCTION,
23436 OOMPH_EXCEPTION_LOCATION);
23444 bool new_element_added =
true;
23454 bool element_added_to_the_left =
false;
23455 bool element_added_to_the_right =
false;
23459 bool connection_to_the_left =
false;
23463 bool connection_to_the_right =
false;
23468 bool current_polyline_has_connections_at_both_ends =
false;
23480 int bound_id_connection_to_the_left = -1;
23481 int bound_id_connection_to_the_right = -1;
23485 const unsigned initial_node_degree =
23486 global_node_degree[initial_node_pt];
23490 const bool called_for_load_balance =
true;
23494 bound_id_connection_to_the_left =
23495 this->check_connections_of_polyline_nodes(
23496 element_in_processor_pt,
23497 root_edge_bound_id,
23499 node_on_bnd_not_overlapped_by_shd_bnd,
23500 tmp_sorted_nodes_pt,
23501 local_shd_bnd_id_to_sorted_list_node_pt,
23502 initial_node_degree,
23504 called_for_load_balance);
23508 if (bound_id_connection_to_the_left != -1)
23510 connection_to_the_left =
true;
23515 const unsigned final_node_degree = global_node_degree[final_node_pt];
23518 bound_id_connection_to_the_right =
23519 this->check_connections_of_polyline_nodes(
23520 element_in_processor_pt,
23521 root_edge_bound_id,
23523 node_on_bnd_not_overlapped_by_shd_bnd,
23524 tmp_sorted_nodes_pt,
23525 local_shd_bnd_id_to_sorted_list_node_pt,
23528 called_for_load_balance);
23532 if (bound_id_connection_to_the_right != -1)
23534 connection_to_the_right =
true;
23539 if (connection_to_the_left && connection_to_the_right)
23541 current_polyline_has_connections_at_both_ends =
true;
23550 while (new_element_added && (nsorted_face_ele < nunsorted_face_ele) &&
23551 !current_polyline_has_connections_at_both_ends)
23557 for (
unsigned e = root_index; e < nunsorted_face_ele; e++)
23560 new_element_added =
false;
23561 element_added_to_the_left =
false;
23562 element_added_to_the_right =
false;
23565 FiniteElement* tmp_ele_pt = unsorted_face_ele_pt[iproc][e];
23567 const int edge_bound_id = edge_boundary[iproc][e];
23571 if (!done_ele[tmp_ele_pt] &&
23572 (edge_bound_id == root_edge_bound_id))
23575 const unsigned nnodes = tmp_ele_pt->nnode();
23578 Node* first_node_pt = 0;
23579 Node* last_node_pt = 0;
23580 if (!treat_as_inverted[iproc][e])
23582 first_node_pt = tmp_ele_pt->node_pt(0);
23583 last_node_pt = tmp_ele_pt->node_pt(nnodes - 1);
23587 first_node_pt = tmp_ele_pt->node_pt(nnodes - 1);
23588 last_node_pt = tmp_ele_pt->node_pt(0);
23594 Node* new_added_node_pt = 0;
23597 if (initial_node_pt == last_node_pt && !connection_to_the_left)
23600 new_added_node_pt = initial_node_pt = first_node_pt;
23602 tmp_sorted_nodes_pt.push_front(first_node_pt);
23605 tmp_sorted_face_ele_pt.push_front(tmp_ele_pt);
23607 tmp_sorted_ele_pt.push_front(unsorted_ele_pt[iproc][e]);
23610 tmp_sorted_face_index_ele.push_front(
23611 unsorted_face_index_ele[iproc][e]);
23612 if (!treat_as_inverted[iproc][e])
23615 is_inverted[tmp_ele_pt] =
false;
23620 is_inverted[tmp_ele_pt] =
true;
23623 new_element_added =
true;
23626 element_added_to_the_left =
true;
23629 else if (initial_node_pt == first_node_pt &&
23630 !connection_to_the_left)
23633 new_added_node_pt = initial_node_pt = last_node_pt;
23635 tmp_sorted_nodes_pt.push_front(last_node_pt);
23638 tmp_sorted_face_ele_pt.push_front(tmp_ele_pt);
23640 tmp_sorted_ele_pt.push_front(unsorted_ele_pt[iproc][e]);
23643 tmp_sorted_face_index_ele.push_front(
23644 unsorted_face_index_ele[iproc][e]);
23645 if (!treat_as_inverted[iproc][e])
23648 is_inverted[tmp_ele_pt] =
true;
23653 is_inverted[tmp_ele_pt] =
false;
23656 new_element_added =
true;
23659 element_added_to_the_left =
true;
23662 else if (final_node_pt == first_node_pt &&
23663 !connection_to_the_right)
23666 new_added_node_pt = final_node_pt = last_node_pt;
23668 tmp_sorted_nodes_pt.push_back(last_node_pt);
23671 tmp_sorted_face_ele_pt.push_back(tmp_ele_pt);
23673 tmp_sorted_ele_pt.push_back(unsorted_ele_pt[iproc][e]);
23676 tmp_sorted_face_index_ele.push_back(
23677 unsorted_face_index_ele[iproc][e]);
23678 if (!treat_as_inverted[iproc][e])
23681 is_inverted[tmp_ele_pt] =
false;
23686 is_inverted[tmp_ele_pt] =
true;
23689 new_element_added =
true;
23692 element_added_to_the_right =
true;
23695 else if (final_node_pt == last_node_pt &&
23696 !connection_to_the_right)
23699 new_added_node_pt = final_node_pt = first_node_pt;
23701 tmp_sorted_nodes_pt.push_back(first_node_pt);
23704 tmp_sorted_face_ele_pt.push_back(tmp_ele_pt);
23706 tmp_sorted_ele_pt.push_back(unsorted_ele_pt[iproc][e]);
23709 tmp_sorted_face_index_ele.push_back(
23710 unsorted_face_index_ele[iproc][e]);
23711 if (!treat_as_inverted[iproc][e])
23714 is_inverted[tmp_ele_pt] =
true;
23719 is_inverted[tmp_ele_pt] =
false;
23722 new_element_added =
true;
23725 element_added_to_the_right =
true;
23729 if (new_element_added)
23732 done_ele[tmp_ele_pt] =
true;
23734 nsorted_face_ele++;
23738 const unsigned new_added_node_degree =
23739 global_node_degree[new_added_node_pt];
23748 if (element_added_to_the_left && !connection_to_the_left)
23751 bound_id_connection_to_the_left =
23752 this->check_connections_of_polyline_nodes(
23753 element_in_processor_pt,
23754 root_edge_bound_id,
23756 node_on_bnd_not_overlapped_by_shd_bnd,
23757 tmp_sorted_nodes_pt,
23758 local_shd_bnd_id_to_sorted_list_node_pt,
23759 new_added_node_degree,
23761 called_for_load_balance);
23765 if (bound_id_connection_to_the_left != -1)
23767 connection_to_the_left =
true;
23777 if (element_added_to_the_right && !connection_to_the_right)
23780 bound_id_connection_to_the_right =
23781 this->check_connections_of_polyline_nodes(
23782 element_in_processor_pt,
23783 root_edge_bound_id,
23785 node_on_bnd_not_overlapped_by_shd_bnd,
23786 tmp_sorted_nodes_pt,
23787 local_shd_bnd_id_to_sorted_list_node_pt,
23788 new_added_node_degree,
23790 called_for_load_balance);
23794 if (bound_id_connection_to_the_right != -1)
23796 connection_to_the_right =
true;
23805 if (connection_to_the_left && connection_to_the_right)
23807 current_polyline_has_connections_at_both_ends =
true;
23831 Vector<FiniteElement*> tmp_vector_sorted_ele_pt;
23833 for (std::list<FiniteElement*>::iterator it =
23834 tmp_sorted_ele_pt.begin();
23835 it != tmp_sorted_ele_pt.end();
23838 tmp_vector_sorted_ele_pt.push_back((*it));
23842 Vector<FiniteElement*> tmp_vector_sorted_face_ele_pt;
23845 for (std::list<FiniteElement*>::iterator it =
23846 tmp_sorted_face_ele_pt.begin();
23847 it != tmp_sorted_face_ele_pt.end();
23850 tmp_vector_sorted_face_ele_pt.push_back((*it));
23854 Vector<int> tmp_vector_sorted_face_index_ele;
23856 for (std::list<int>::iterator it = tmp_sorted_face_index_ele.begin();
23857 it != tmp_sorted_face_index_ele.end();
23860 tmp_vector_sorted_face_index_ele.push_back((*it));
23864 Vector<std::list<Node*>> final_sorted_nodes_pt;
23867 Vector<Vector<FiniteElement*>> final_boundary_element_pt;
23870 Vector<Vector<FiniteElement*>> final_boundary_face_element_pt;
23872 Vector<Vector<int>> final_face_index_element;
23875 Vector<int> final_bound_id_connection_to_the_left;
23878 Vector<int> final_bound_id_connection_to_the_right;
23881 this->break_loops_on_shared_polyline_load_balance_helper(
23883 tmp_sorted_nodes_pt,
23884 tmp_vector_sorted_ele_pt,
23885 tmp_vector_sorted_face_ele_pt,
23886 tmp_vector_sorted_face_index_ele,
23887 bound_id_connection_to_the_left,
23888 bound_id_connection_to_the_right,
23889 final_sorted_nodes_pt,
23890 final_boundary_element_pt,
23891 final_boundary_face_element_pt,
23892 final_face_index_element,
23893 final_bound_id_connection_to_the_left,
23894 final_bound_id_connection_to_the_right);
23897 const unsigned n_final_sorted_nodes = final_sorted_nodes_pt.size();
23900 for (
unsigned i = 0; i < n_final_sorted_nodes; i++)
23904 local_shd_bnd_id_to_sorted_list_node_pt[local_shd_bnd_id] =
23905 final_sorted_nodes_pt[i];
23909 proc_local_shared_boundary_id[iproc].push_back(local_shd_bnd_id);
23914 local_shd_bnd_id++;
23917 sorted_ele_pt[iproc].push_back(final_boundary_element_pt[i]);
23920 sorted_face_ele_pt[iproc].push_back(
23921 final_boundary_face_element_pt[i]);
23924 sorted_face_index_ele[iproc].push_back(final_face_index_element[i]);
23927 edge_boundary_id[iproc].push_back(root_edge_bound_id);
23933 Vector<int> bnd_connections_ids(2);
23934 bnd_connections_ids[0] = final_bound_id_connection_to_the_left[i];
23935 bnd_connections_ids[1] = final_bound_id_connection_to_the_right[i];
23936 sorted_connection_info[iproc].push_back(bnd_connections_ids);
23948 if (Print_timings_level_load_balance > 2)
23950 oomph_info <<
"CPU for joining shared boundary face elements (load "
23952 << TimingHelpers::timer() - tt_start_join_shd_bnd_face_ele
23980 double tt_start_get_new_shared_boundaries_ids = 0.0;
23981 if (Print_timings_level_load_balance > 2)
23983 tt_start_get_new_shared_boundaries_ids = TimingHelpers::timer();
23987 Vector<unsigned> nshared_boundaries_with_processor(nproc);
23989 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23992 if (iproc != my_rank)
23996 nshared_boundaries_with_processor[iproc] =
23997 sorted_face_ele_pt[iproc].size();
24007 const unsigned root_processor = 0;
24010 OomphCommunicator* comm_pt = this->communicator_pt();
24015 Vector<unsigned> flat_unsigned_root_received_data(nproc * nproc);
24018 MPI_Gather(&nshared_boundaries_with_processor[0],
24023 &flat_unsigned_root_received_data[0],
24031 comm_pt->mpi_comm());
24036 Vector<unsigned> flat_unsigned_root_send_receive_data;
24040 unsigned new_initial_shared_boundary_id = 0;
24041 unsigned new_final_shared_boundary_id = 0;
24044 if (my_rank == root_processor)
24048 Vector<Vector<unsigned>> root_nshared_bound_proc_with_proc(nproc);
24051 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24054 root_nshared_bound_proc_with_proc[iproc].resize(nproc);
24057 for (
unsigned jproc = 0; jproc < nproc; jproc++)
24059 root_nshared_bound_proc_with_proc[iproc][jproc] =
24060 flat_unsigned_root_received_data[(iproc * nproc) + jproc];
24069 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24071 for (
unsigned jproc = 0; jproc < iproc; jproc++)
24073 if (root_nshared_bound_proc_with_proc[iproc][jproc] !=
24074 root_nshared_bound_proc_with_proc[jproc][iproc])
24076 std::ostringstream error_stream;
24078 <<
"ROOT PROCESSOR ERROR\n\n"
24079 <<
"The number of shared boundaries between processor (" << iproc
24080 <<
") and (" << jproc <<
") is not the same:\n"
24081 <<
"Shared boundaries of processor (" << iproc
24082 <<
") with processor (" << jproc <<
"): ("
24083 << root_nshared_bound_proc_with_proc[iproc][jproc] <<
")\n"
24084 <<
"Shared boundaries of processor (" << jproc
24085 <<
") with processor (" << iproc <<
"): ("
24086 << root_nshared_bound_proc_with_proc[jproc][iproc] <<
")\n\n";
24087 throw OomphLibError(error_stream.str(),
24088 OOMPH_CURRENT_FUNCTION,
24089 OOMPH_EXCEPTION_LOCATION);
24105 Vector<Vector<unsigned>> start_shared_bound_id_proc_with_proc(nproc);
24108 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24110 start_shared_bound_id_proc_with_proc[iproc].resize(nproc);
24115 unsigned shared_bound_id = this->nboundary();
24118 new_initial_shared_boundary_id = shared_bound_id;
24121 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24123 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
24126 if (root_nshared_bound_proc_with_proc[iproc][jproc] > 0)
24130 start_shared_bound_id_proc_with_proc[iproc][jproc] =
24132 start_shared_bound_id_proc_with_proc[jproc][iproc] =
24137 shared_bound_id += root_nshared_bound_proc_with_proc[iproc][jproc];
24145 new_final_shared_boundary_id = shared_bound_id;
24148 Vector<unsigned> send_start_shared_bound_id_proc_with_proc(nproc * nproc);
24152 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24154 for (
unsigned jproc = 0; jproc < nproc; jproc++)
24158 const unsigned initial_shd_bnd_id =
24159 start_shared_bound_id_proc_with_proc[iproc][jproc];
24160 flat_unsigned_root_send_receive_data.push_back(initial_shd_bnd_id);
24164 const unsigned nshared_bnd_iproc_jproc =
24165 root_nshared_bound_proc_with_proc[iproc][jproc];
24166 flat_unsigned_root_send_receive_data.push_back(
24167 nshared_bnd_iproc_jproc);
24175 flat_unsigned_root_send_receive_data.push_back(
24176 new_initial_shared_boundary_id);
24179 flat_unsigned_root_send_receive_data.push_back(
24180 new_final_shared_boundary_id);
24191 unsigned root_ndata_sent_to_all_proc =
24192 flat_unsigned_root_send_receive_data.size();
24194 MPI_Bcast(&root_ndata_sent_to_all_proc,
24198 comm_pt->mpi_comm());
24201 if (my_rank != root_processor)
24203 flat_unsigned_root_send_receive_data.resize(root_ndata_sent_to_all_proc);
24208 MPI_Bcast(&flat_unsigned_root_send_receive_data[0],
24211 root_ndata_sent_to_all_proc,
24215 comm_pt->mpi_comm());
24219 Vector<Vector<unsigned>> initial_shared_bound_id_proc_with_proc(nproc);
24225 Vector<Vector<unsigned>> nshared_bound_proc_with_proc(nproc);
24227 unsigned iflat_counter = 0;
24229 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24232 initial_shared_bound_id_proc_with_proc[iproc].resize(nproc);
24233 nshared_bound_proc_with_proc[iproc].resize(nproc);
24236 for (
unsigned jproc = 0; jproc < nproc; jproc++)
24240 initial_shared_bound_id_proc_with_proc[iproc][jproc] =
24241 flat_unsigned_root_send_receive_data[iflat_counter++];
24245 nshared_bound_proc_with_proc[iproc][jproc] =
24246 flat_unsigned_root_send_receive_data[iflat_counter++];
24253 new_initial_shared_boundary_id =
24254 flat_unsigned_root_send_receive_data[root_ndata_sent_to_all_proc - 2];
24257 new_final_shared_boundary_id =
24258 flat_unsigned_root_send_receive_data[root_ndata_sent_to_all_proc - 1];
24261 if (Print_timings_level_load_balance > 2)
24264 <<
"CPU for computing new shared boundaries ids (load balance) [9.6]: "
24265 << TimingHelpers::timer() - tt_start_get_new_shared_boundaries_ids
24286 double tt_start_create_new_shared_boundaries_polylines = 0.0;
24287 if (Print_timings_level_load_balance > 2)
24289 tt_start_create_new_shared_boundaries_polylines = TimingHelpers::timer();
24299 this->flush_shared_boundary_polyline_pt();
24300 this->Shared_boundary_polyline_pt.resize(nproc);
24303 this->Shared_boundaries_ids.clear();
24304 this->Shared_boundaries_ids.resize(nproc);
24305 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24307 this->Shared_boundaries_ids[iproc].clear();
24308 this->Shared_boundaries_ids[iproc].resize(nproc);
24312 this->Shared_boundary_from_processors.clear();
24313 this->Shared_boundary_overlaps_internal_boundary.clear();
24314 this->Boundary_was_splitted.clear();
24315 this->Boundary_subpolylines.clear();
24316 this->Boundary_marked_as_shared_boundary.clear();
24319 this->flush_shared_boundary_element();
24320 this->flush_face_index_at_shared_boundary();
24321 this->flush_shared_boundary_node();
24322 this->flush_sorted_shared_boundary_node();
24326 const unsigned old_local_shd_bnd_id = this->Initial_shared_boundary_id;
24329 this->Initial_shared_boundary_id = new_initial_shared_boundary_id;
24330 this->Final_shared_boundary_id = new_final_shared_boundary_id;
24334 Vector<TriangleMeshPolyLine*> unsorted_polylines_pt;
24340 std::map<unsigned, unsigned> local_to_global_shd_bnd_id;
24347 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24353 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
24358 if (iproc == my_rank || jproc == my_rank)
24361 unsigned ref_proc = 0;
24362 if (iproc == my_rank)
24366 else if (jproc == my_rank)
24373 const unsigned nshared_bound_iproc_jproc =
24374 nshared_bound_proc_with_proc[iproc][jproc];
24377 for (
unsigned counter = 0; counter < nshared_bound_iproc_jproc;
24381 const unsigned shd_bnd_id =
24382 initial_shared_bound_id_proc_with_proc[iproc][jproc] + counter;
24385 this->Shared_boundaries_ids[iproc][jproc].push_back(shd_bnd_id);
24386 this->Shared_boundaries_ids[jproc][iproc].push_back(shd_bnd_id);
24390 Vector<unsigned> processors(2);
24391 processors[0] = iproc;
24392 processors[1] = jproc;
24393 this->Shared_boundary_from_processors[shd_bnd_id] = processors;
24398 int root_edge_bound_id = edge_boundary_id[ref_proc][counter];
24401 if (root_edge_bound_id != -1)
24405 this->Shared_boundary_overlaps_internal_boundary[shd_bnd_id] =
24406 static_cast<unsigned>(root_edge_bound_id);
24413 Vector<Node*> node_pt_to_create_shared_polyline;
24418 FiniteElement* first_face_ele_pt =
24419 sorted_face_ele_pt[ref_proc][counter][0];
24422 const unsigned first_face_ele_nnodes = first_face_ele_pt->nnode();
24423 if (!is_inverted[first_face_ele_pt])
24426 Node* first_node_pt = first_face_ele_pt->node_pt(0);
24428 node_pt_to_create_shared_polyline.push_back(first_node_pt);
24430 this->add_shared_boundary_node(shd_bnd_id, first_node_pt);
24435 Node* first_node_pt =
24436 first_face_ele_pt->node_pt(first_face_ele_nnodes - 1);
24438 node_pt_to_create_shared_polyline.push_back(first_node_pt);
24440 this->add_shared_boundary_node(shd_bnd_id, first_node_pt);
24448 const unsigned nshared_boundary_elements =
24449 sorted_face_ele_pt[ref_proc][counter].size();
24453 for (
unsigned ie = 0; ie < nshared_boundary_elements; ie++)
24456 FiniteElement* bulk_ele_pt = sorted_ele_pt[ref_proc][counter][ie];
24460 this->add_shared_boundary_element(shd_bnd_id, bulk_ele_pt);
24464 const int face_index =
24465 sorted_face_index_ele[ref_proc][counter][ie];
24469 this->add_face_index_at_shared_boundary(shd_bnd_id, face_index);
24472 FiniteElement* face_ele_pt =
24473 sorted_face_ele_pt[ref_proc][counter][ie];
24476 const unsigned nnodes = face_ele_pt->nnode();
24477 if (!is_inverted[face_ele_pt])
24481 for (
unsigned n = 1; n < nnodes; n++)
24484 Node* node_pt = face_ele_pt->node_pt(n);
24486 this->add_shared_boundary_node(shd_bnd_id, node_pt);
24492 Node* last_node_pt = face_ele_pt->node_pt(nnodes - 1);
24493 node_pt_to_create_shared_polyline.push_back(last_node_pt);
24499 for (
int n = nnodes - 2; n >= 0; n--)
24502 Node* node_pt = face_ele_pt->node_pt(n);
24504 this->add_shared_boundary_node(shd_bnd_id, node_pt);
24510 Node* last_node_pt = face_ele_pt->node_pt(0);
24511 node_pt_to_create_shared_polyline.push_back(last_node_pt);
24518 const unsigned nnodes_to_create_shared_boundary =
24519 node_pt_to_create_shared_polyline.size();
24522 Vector<Vector<double>> vertices(nnodes_to_create_shared_boundary);
24523 for (
unsigned n = 0; n < nnodes_to_create_shared_boundary; n++)
24525 vertices[n].resize(2);
24527 Node* tmp_node_pt = node_pt_to_create_shared_polyline[n];
24529 vertices[n][0] = tmp_node_pt->x(0);
24530 vertices[n][1] = tmp_node_pt->x(1);
24534 TriangleMeshPolyLine* polyline_pt =
24535 new TriangleMeshPolyLine(vertices, shd_bnd_id);
24538 this->Boundary_curve_section_pt[shd_bnd_id] = polyline_pt;
24542 unsorted_polylines_pt.push_back(polyline_pt);
24545 this->Free_curve_section_pt.insert(polyline_pt);
24551 const unsigned local_shd_bnd_id =
24552 proc_local_shared_boundary_id[ref_proc][counter];
24556 local_to_global_shd_bnd_id[local_shd_bnd_id] = shd_bnd_id;
24563 int tmp_bnd_id_connection_to_the_left =
24564 sorted_connection_info[ref_proc][counter][0];
24566 int tmp_bnd_id_connection_to_the_right =
24567 sorted_connection_info[ref_proc][counter][1];
24571 int bnd_id_connection_to_the_left = -1;
24572 int bnd_id_connection_to_the_right = -1;
24579 if (tmp_bnd_id_connection_to_the_left == -2)
24582 bnd_id_connection_to_the_left = shd_bnd_id;
24586 if (tmp_bnd_id_connection_to_the_left == -3)
24589 bnd_id_connection_to_the_left = -1;
24594 if (tmp_bnd_id_connection_to_the_left >=
24595 static_cast<int>(old_local_shd_bnd_id))
24600 std::map<unsigned, unsigned>::iterator it =
24601 local_to_global_shd_bnd_id.find(
24602 static_cast<unsigned>(tmp_bnd_id_connection_to_the_left));
24605 if (it == local_to_global_shd_bnd_id.end())
24607 std::stringstream error_message;
24609 <<
"The global shared boundary id was not found for\n"
24610 <<
"the local shared boundary shared with processor ("
24611 << ref_proc <<
").\n"
24612 <<
"This processor: (" << my_rank <<
")\n"
24613 <<
"Boundary shared with processor: (" << ref_proc <<
")\n"
24614 <<
"Local shared boundary: ("
24615 << tmp_bnd_id_connection_to_the_left <<
")\n";
24616 throw OomphLibError(error_message.str(),
24617 OOMPH_CURRENT_FUNCTION,
24618 OOMPH_EXCEPTION_LOCATION);
24623 bnd_id_connection_to_the_left =
24624 local_to_global_shd_bnd_id[
static_cast<unsigned>(
24625 tmp_bnd_id_connection_to_the_left)];
24631 bnd_id_connection_to_the_left = tmp_bnd_id_connection_to_the_left;
24640 if (tmp_bnd_id_connection_to_the_right == -2)
24643 bnd_id_connection_to_the_right = shd_bnd_id;
24647 if (tmp_bnd_id_connection_to_the_right == -3)
24650 bnd_id_connection_to_the_right = -1;
24655 if (tmp_bnd_id_connection_to_the_right >=
24656 static_cast<int>(old_local_shd_bnd_id))
24661 std::map<unsigned, unsigned>::iterator it =
24662 local_to_global_shd_bnd_id.find(
24663 static_cast<unsigned>(tmp_bnd_id_connection_to_the_right));
24666 if (it == local_to_global_shd_bnd_id.end())
24668 std::stringstream error_message;
24670 <<
"The global shared boundary id was not found for\n"
24671 <<
"the local shared boundary shared with processor ("
24672 << ref_proc <<
").\n"
24673 <<
"This processor: (" << my_rank <<
")\n"
24674 <<
"Boundary shared with processor: (" << ref_proc <<
")\n"
24675 <<
"Local shared boundary: ("
24676 << tmp_bnd_id_connection_to_the_right <<
")\n";
24677 throw OomphLibError(error_message.str(),
24678 OOMPH_CURRENT_FUNCTION,
24679 OOMPH_EXCEPTION_LOCATION);
24683 bnd_id_connection_to_the_right =
24684 local_to_global_shd_bnd_id[
static_cast<unsigned>(
24685 tmp_bnd_id_connection_to_the_right)];
24691 bnd_id_connection_to_the_right =
24692 tmp_bnd_id_connection_to_the_right;
24698 if (bnd_id_connection_to_the_left != -1)
24701 const unsigned ubnd_id_connection_to_the_left =
24702 static_cast<unsigned>(bnd_id_connection_to_the_left);
24704 polyline_pt->set_initial_vertex_connected();
24706 polyline_pt->initial_vertex_connected_bnd_id() =
24707 ubnd_id_connection_to_the_left;
24709 polyline_pt->initial_vertex_connected_n_chunk() = 0;
24715 if (bnd_id_connection_to_the_right != -1)
24719 const unsigned ubnd_id_connection_to_the_right =
24720 static_cast<unsigned>(bnd_id_connection_to_the_right);
24722 polyline_pt->set_final_vertex_connected();
24724 polyline_pt->final_vertex_connected_bnd_id() =
24725 ubnd_id_connection_to_the_right;
24727 polyline_pt->final_vertex_connected_n_chunk() = 0;
24741 const unsigned nshared_bound_iproc_jproc =
24742 nshared_bound_proc_with_proc[iproc][jproc];
24744 for (
unsigned counter = 0; counter < nshared_bound_iproc_jproc;
24748 const unsigned shd_bnd_id =
24749 initial_shared_bound_id_proc_with_proc[iproc][jproc] + counter;
24752 this->Shared_boundaries_ids[iproc][jproc].push_back(shd_bnd_id);
24753 this->Shared_boundaries_ids[jproc][iproc].push_back(shd_bnd_id);
24757 Vector<unsigned> processors(2);
24758 processors[0] = iproc;
24759 processors[1] = jproc;
24760 this->Shared_boundary_from_processors[shd_bnd_id] = processors;
24771 if (Print_timings_level_load_balance > 2)
24773 oomph_info <<
"CPU for creating new shared boundaries representations "
24774 "(load balance) [9.7]: "
24775 << TimingHelpers::timer() -
24776 tt_start_create_new_shared_boundaries_polylines
24794 double tt_start_create_new_shared_curves = 0.0;
24795 if (Print_timings_level_load_balance > 2)
24797 tt_start_create_new_shared_curves = TimingHelpers::timer();
24802 if (unsorted_polylines_pt.size() > 0)
24806 this->sort_polylines_helper(unsorted_polylines_pt,
24807 this->Shared_boundary_polyline_pt[my_rank]);
24811 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24813 const unsigned nface_ele = unsorted_face_ele_pt[iproc].size();
24814 for (
unsigned e = 0; e < nface_ele; e++)
24816 delete unsorted_face_ele_pt[iproc][e];
24817 unsorted_face_ele_pt[iproc][e] = 0;
24823 if (Print_timings_level_load_balance > 2)
24826 <<
"CPU for creating the new shared curves (load balance) [9.8]: "
24827 << TimingHelpers::timer() - tt_start_create_new_shared_curves
24844 template<
class ELEMENT>
24846 Vector<Vector<FiniteElement*>>& unsorted_face_ele_pt,
24847 std::map<Node*, unsigned>& global_node_degree)
24850 const unsigned nproc = this->communicator_pt()->nproc();
24851 const unsigned my_rank = this->communicator_pt()->my_rank();
24855 Vector<Vector<Node*>> tmp_sorted_shared_node_pt(nproc);
24862 std::map<Node*, Vector<Vector<unsigned>>> node_alias;
24866 Vector<Vector<Vector<unsigned>>> local_adjacency_matrix(nproc);
24870 create_adjacency_matrix_new_shared_edges_helper(unsorted_face_ele_pt,
24871 tmp_sorted_shared_node_pt,
24873 local_adjacency_matrix);
24880 Vector<unsigned> package_unsigned_send_data_to_root;
24886 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24889 package_unsigned_send_data_to_root.push_back(iproc);
24892 const unsigned n_nodes = tmp_sorted_shared_node_pt[iproc].size();
24895 package_unsigned_send_data_to_root.push_back(n_nodes);
24898 for (
unsigned ishd = 0; ishd < n_nodes; ishd++)
24901 Node* shd_node_pt = tmp_sorted_shared_node_pt[iproc][ishd];
24904 Vector<Vector<unsigned>> alias_node_info = node_alias[shd_node_pt];
24907 const unsigned n_alias = alias_node_info.size();
24910 package_unsigned_send_data_to_root.push_back(n_alias);
24913 for (
unsigned i = 0; i < n_alias; i++)
24917 package_unsigned_send_data_to_root.push_back(alias_node_info[i][0]);
24919 package_unsigned_send_data_to_root.push_back(alias_node_info[i][1]);
24921 package_unsigned_send_data_to_root.push_back(alias_node_info[i][2]);
24927 for (
unsigned i = 0; i < n_nodes; i++)
24929 for (
unsigned j = 0; j < n_nodes; j++)
24932 package_unsigned_send_data_to_root.push_back(
24933 local_adjacency_matrix[iproc][i][j]);
24942 const unsigned root_processor = 0;
24945 OomphCommunicator* comm_pt = this->communicator_pt();
24948 unsigned n_unsigned_data_send_to_root =
24949 package_unsigned_send_data_to_root.size();
24952 Vector<int> n_unsigned_data_received_in_root(nproc, 0);
24956 MPI_Gather(&n_unsigned_data_send_to_root,
24960 &n_unsigned_data_received_in_root[0],
24968 comm_pt->mpi_comm());
24971 unsigned n_unsigned_total_data_receive_in_root = 0;
24972 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24975 n_unsigned_total_data_receive_in_root +=
24976 n_unsigned_data_received_in_root[iproc];
24980 Vector<int> root_unsigned_offsets_receive(nproc, 0);
24981 root_unsigned_offsets_receive[0] = 0;
24982 for (
unsigned iproc = 1; iproc < nproc; iproc++)
24986 root_unsigned_offsets_receive[iproc] =
24987 root_unsigned_offsets_receive[iproc - 1] +
24988 n_unsigned_data_received_in_root[iproc - 1];
24992 if (package_unsigned_send_data_to_root.size() == 0)
24994 package_unsigned_send_data_to_root.resize(1);
24998 Vector<unsigned> package_unsigned_data_received_root(
24999 n_unsigned_total_data_receive_in_root);
25000 if (my_rank != root_processor)
25003 if (package_unsigned_data_received_root.size() == 0)
25005 package_unsigned_data_received_root.resize(1);
25010 MPI_Gatherv(&package_unsigned_send_data_to_root[0],
25015 n_unsigned_data_send_to_root,
25019 &package_unsigned_data_received_root[0],
25025 &n_unsigned_data_received_in_root[0],
25028 &root_unsigned_offsets_receive[0],
25035 comm_pt->mpi_comm());
25038 Vector<unsigned> package_unsigned_data_sent_from_root;
25040 Vector<int> n_unsigned_data_sent_from_root(nproc, 0);
25044 if (my_rank == root_processor)
25048 unsigned decode_counter = 0;
25056 Vector<Vector<Vector<Vector<Vector<unsigned>>>>> local_node_alias(nproc);
25058 Vector<Vector<Vector<Vector<unsigned>>>> local_adjacency_matrix(nproc);
25061 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25063 local_node_alias[iproc].resize(nproc);
25067 local_adjacency_matrix[iproc].resize(nproc);
25069 if (n_unsigned_data_received_in_root[iproc] > 0)
25073 for (
unsigned jproc = 0; jproc < nproc; jproc++)
25076 const unsigned read_jproc =
25077 package_unsigned_data_received_root[decode_counter++];
25081 if (read_jproc != jproc)
25083 std::ostringstream error_stream;
25085 <<
"The read processor is different from the jproc, this is\n"
25086 <<
"a synchronisation issue. The data are not read in the\n"
25087 <<
"sameorder as the were packaged\n"
25088 <<
"Read processor: (" << read_jproc <<
")\n"
25089 <<
"Current jproc: (" << jproc <<
")\n\n";
25090 throw OomphLibError(
25091 error_stream.str(),
25092 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25093 OOMPH_EXCEPTION_LOCATION);
25098 const unsigned read_n_shd_nodes_iproc_jproc =
25099 package_unsigned_data_received_root[decode_counter++];
25102 local_node_alias[iproc][jproc].resize(read_n_shd_nodes_iproc_jproc);
25106 for (
unsigned ishd = 0; ishd < read_n_shd_nodes_iproc_jproc; ishd++)
25109 const unsigned read_n_alias_node_iproc_jproc =
25110 package_unsigned_data_received_root[decode_counter++];
25113 local_node_alias[iproc][jproc][ishd].resize(
25114 read_n_alias_node_iproc_jproc);
25116 for (
unsigned ialias = 0; ialias < read_n_alias_node_iproc_jproc;
25121 local_node_alias[iproc][jproc][ishd][ialias].resize(3);
25124 local_node_alias[iproc][jproc][ishd][ialias][0] =
25125 package_unsigned_data_received_root[decode_counter++];
25128 local_node_alias[iproc][jproc][ishd][ialias][1] =
25129 package_unsigned_data_received_root[decode_counter++];
25132 local_node_alias[iproc][jproc][ishd][ialias][2] =
25133 package_unsigned_data_received_root[decode_counter++];
25140 local_adjacency_matrix[iproc][jproc].resize(
25141 read_n_shd_nodes_iproc_jproc);
25143 for (
unsigned i = 0; i < read_n_shd_nodes_iproc_jproc; i++)
25146 local_adjacency_matrix[iproc][jproc][i].resize(
25147 read_n_shd_nodes_iproc_jproc);
25148 for (
unsigned j = 0; j < read_n_shd_nodes_iproc_jproc; j++)
25151 local_adjacency_matrix[iproc][jproc][i][j] =
25152 package_unsigned_data_received_root[decode_counter++];
25164 if (decode_counter != n_unsigned_total_data_receive_in_root)
25166 std::ostringstream error_stream;
25168 <<
"The number of data decoded in root received from others\n"
25169 <<
"processors is different from the total number of data received\n"
25170 <<
"Data decoded: (" << decode_counter <<
")\n"
25171 <<
"Data received: (" << n_unsigned_total_data_receive_in_root
25173 <<
"This is a synchronisation issue so you are probably sending\n"
25174 <<
"more or less info. than the one that is being decoded\n\n";
25175 throw OomphLibError(
25176 error_stream.str(),
25177 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25178 OOMPH_EXCEPTION_LOCATION);
25188 std::map<Vector<unsigned>,
bool> alias_done;
25191 Vector<Vector<Vector<unsigned>>> global_node_alias;
25194 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25196 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25199 const unsigned n_shd_nodes_iproc_jproc =
25200 local_node_alias[iproc][jproc].size();
25203 const unsigned n_shd_nodes_jproc_iproc =
25204 local_node_alias[jproc][iproc].size();
25206 if (n_shd_nodes_iproc_jproc != n_shd_nodes_jproc_iproc)
25208 std::ostringstream error_stream;
25210 <<
"The number of nodes shared between iproc and jproc is\n"
25211 <<
"different from the number of nodes shared between jproc\n"
25213 <<
"Nodes shared between processor (" << iproc <<
") and "
25214 <<
"processor (" << jproc <<
"): (" << n_shd_nodes_iproc_jproc
25216 <<
"Nodes shared between processor (" << jproc <<
") and "
25217 <<
"processor (" << iproc <<
"): (" << n_shd_nodes_jproc_iproc
25219 throw OomphLibError(
25220 error_stream.str(),
25221 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25222 OOMPH_EXCEPTION_LOCATION);
25227 for (
unsigned ishd = 0; ishd < n_shd_nodes_iproc_jproc; ishd++)
25231 const unsigned n_alias_iproc_jproc =
25232 local_node_alias[iproc][jproc][ishd].size();
25233 const unsigned n_alias_jproc_iproc =
25234 local_node_alias[jproc][iproc][ishd].size();
25237 Vector<Vector<unsigned>> node_alias;
25240 bool new_alias_added =
false;
25243 for (
unsigned ialias = 0; ialias < n_alias_iproc_jproc; ialias++)
25246 Vector<unsigned> current_alias =
25247 local_node_alias[iproc][jproc][ishd][ialias];
25249 if (!alias_done[current_alias])
25252 node_alias.push_back(current_alias);
25254 new_alias_added =
true;
25256 alias_done[current_alias] =
true;
25262 for (
unsigned ialias = 0; ialias < n_alias_jproc_iproc; ialias++)
25265 Vector<unsigned> current_alias =
25266 local_node_alias[jproc][iproc][ishd][ialias];
25269 if (!alias_done[current_alias])
25272 node_alias.push_back(current_alias);
25274 new_alias_added =
true;
25276 alias_done[current_alias] =
true;
25281 unsigned counter_alias = 0;
25285 unsigned n_current_alias = node_alias.size();
25286 while (new_alias_added || counter_alias < n_current_alias)
25290 new_alias_added =
false;
25292 Vector<unsigned> current_alias = node_alias[counter_alias];
25295 Vector<Vector<unsigned>> alias_of_current_alias =
25296 local_node_alias[current_alias[0]][current_alias[1]]
25297 [current_alias[2]];
25301 const unsigned n_alias = alias_of_current_alias.size();
25305 for (
unsigned k = 0; k < n_alias; k++)
25308 Vector<unsigned> add_alias = alias_of_current_alias[k];
25311 if (!alias_done[add_alias])
25314 node_alias.push_back(add_alias);
25317 new_alias_added =
true;
25319 alias_done[add_alias] =
true;
25326 Vector<Vector<unsigned>> alias_of_current_alias2 =
25327 local_node_alias[current_alias[1]][current_alias[0]]
25328 [current_alias[2]];
25332 const unsigned n_alias2 = alias_of_current_alias2.size();
25336 for (
unsigned k = 0; k < n_alias2; k++)
25339 Vector<unsigned> add_alias = alias_of_current_alias2[k];
25342 if (!alias_done[add_alias])
25345 node_alias.push_back(add_alias);
25348 new_alias_added =
true;
25350 alias_done[add_alias] =
true;
25361 n_current_alias = node_alias.size();
25367 if (node_alias.size() > 0)
25371 global_node_alias.push_back(node_alias);
25384 const unsigned n_global_shared_nodes = global_node_alias.size();
25387 Vector<Vector<Vector<int>>> local_to_global_shared_node(nproc);
25390 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25393 local_to_global_shared_node[iproc].resize(nproc);
25398 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25401 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25404 const unsigned n_shd_nodes = local_node_alias[iproc][jproc].size();
25407 local_to_global_shared_node[iproc][jproc].resize(n_shd_nodes, -1);
25410 local_to_global_shared_node[jproc][iproc].resize(n_shd_nodes, -1);
25420 for (
unsigned k = 0; k < n_global_shared_nodes; k++)
25423 const unsigned n_alias_global_node = global_node_alias[k].size();
25425 for (
unsigned l = 0; l < n_alias_global_node; l++)
25428 const unsigned iproc = global_node_alias[k][l][0];
25430 const unsigned jproc = global_node_alias[k][l][1];
25432 const unsigned ishd = global_node_alias[k][l][2];
25434 local_to_global_shared_node[iproc][jproc][ishd] = k;
25441 Vector<Vector<unsigned>> global_adjacency_matrix(n_global_shared_nodes);
25443 for (
unsigned k = 0; k < n_global_shared_nodes; k++)
25446 global_adjacency_matrix[k].resize(n_global_shared_nodes, 0);
25453 Vector<unsigned> global_node_degree(n_global_shared_nodes, 0);
25456 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25459 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25462 const unsigned n_shd_nodes = local_node_alias[iproc][jproc].size();
25469 for (
unsigned ishd = 0; ishd < n_shd_nodes; ishd++)
25471 for (
unsigned jshd = ishd + 1; jshd < n_shd_nodes; jshd++)
25474 if (local_adjacency_matrix[iproc][jproc][ishd][jshd] > 0)
25479 const int global_shd_node_left =
25480 local_to_global_shared_node[iproc][jproc][ishd];
25483 const int global_shd_node_right =
25484 local_to_global_shared_node[iproc][jproc][jshd];
25489 if (global_shd_node_left == -1)
25491 std::ostringstream error_stream;
25493 <<
"The local node in processors iproc and jproc has no\n"
25494 <<
"global node assigned\n"
25495 <<
"iproc processor: (" << iproc <<
")\n"
25496 <<
"jproc processor: (" << jproc <<
")\n"
25497 <<
"Local node: (" << ishd <<
")\n\n";
25498 throw OomphLibError(error_stream.str(),
25499 "RefineableTriangleMesh::compute_shared_"
25500 "node_degree_helper()",
25501 OOMPH_EXCEPTION_LOCATION);
25506 if (global_shd_node_right == -1)
25508 std::ostringstream error_stream;
25510 <<
"The local node in processors iproc and jproc has no\n"
25511 <<
"global node assigned\n"
25512 <<
"iproc processor: (" << iproc <<
")\n"
25513 <<
"jproc processor: (" << jproc <<
")\n"
25514 <<
"Local node: (" << jshd <<
")\n\n";
25515 throw OomphLibError(error_stream.str(),
25516 "RefineableTriangleMesh::compute_shared_"
25517 "node_degree_helper()",
25518 OOMPH_EXCEPTION_LOCATION);
25522 const unsigned uleft =
25523 static_cast<unsigned>(global_shd_node_left);
25524 const unsigned uright =
25525 static_cast<unsigned>(global_shd_node_right);
25528 global_adjacency_matrix[uleft][uright]++;
25531 global_adjacency_matrix[uright][uleft]++;
25534 global_node_degree[uleft]++;
25537 global_node_degree[uright]++;
25551 Vector<Vector<Vector<unsigned>>> root_local_node_degree(nproc);
25553 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25555 root_local_node_degree[iproc].resize(nproc);
25559 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25562 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25566 const unsigned n_shd_nodes = local_node_alias[iproc][jproc].size();
25569 root_local_node_degree[iproc][jproc].resize(n_shd_nodes);
25571 root_local_node_degree[jproc][iproc].resize(n_shd_nodes);
25575 for (
unsigned ishd = 0; ishd < n_shd_nodes; ishd++)
25578 const int global_shd_node_id =
25579 local_to_global_shared_node[iproc][jproc][ishd];
25583 if (global_shd_node_id == -1)
25585 std::ostringstream error_stream;
25587 <<
"The local node in processors iproc and jproc has no\n"
25588 <<
"global node assigned\n"
25589 <<
"iproc processor: (" << iproc <<
")\n"
25590 <<
"jproc processor: (" << jproc <<
")\n"
25591 <<
"Local node: (" << ishd <<
")\n\n";
25592 throw OomphLibError(
25593 error_stream.str(),
25594 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25595 OOMPH_EXCEPTION_LOCATION);
25600 const unsigned uglobal_shd_node_id =
25601 static_cast<unsigned>(global_shd_node_id);
25604 const unsigned node_degree =
25605 global_node_degree[uglobal_shd_node_id];
25609 root_local_node_degree[iproc][jproc][ishd] = node_degree;
25611 root_local_node_degree[jproc][iproc][ishd] = node_degree;
25621 package_unsigned_data_sent_from_root.clear();
25625 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25628 unsigned count_n_data_sent_to_iproc = 0;
25629 for (
unsigned jproc = 0; jproc < nproc; jproc++)
25632 if (iproc != jproc)
25635 const unsigned n_shd_nodes =
25636 root_local_node_degree[iproc][jproc].size();
25639 count_n_data_sent_to_iproc += n_shd_nodes;
25642 for (
unsigned ishd = 0; ishd < n_shd_nodes; ishd++)
25644 package_unsigned_data_sent_from_root.push_back(
25645 root_local_node_degree[iproc][jproc][ishd]);
25653 n_unsigned_data_sent_from_root[iproc] = count_n_data_sent_to_iproc;
25660 int n_unsigned_data_received_from_root = 0;
25663 MPI_Scatter(&n_unsigned_data_sent_from_root[0],
25669 &n_unsigned_data_received_from_root,
25676 comm_pt->mpi_comm());
25679 Vector<unsigned> package_unsigned_data_received_from_root(
25680 n_unsigned_data_received_from_root);
25683 Vector<int> root_unsigned_offsets_sent(nproc, 0);
25684 root_unsigned_offsets_sent[0] = 0;
25685 for (
unsigned iproc = 1; iproc < nproc; iproc++)
25688 root_unsigned_offsets_sent[iproc] =
25689 root_unsigned_offsets_sent[iproc - 1] +
25690 n_unsigned_data_sent_from_root[iproc - 1];
25693 if (my_rank != root_processor)
25696 if (package_unsigned_data_sent_from_root.size() == 0)
25698 package_unsigned_data_sent_from_root.resize(1);
25703 if (package_unsigned_data_received_from_root.size() == 0)
25705 package_unsigned_data_received_from_root.resize(1);
25709 MPI_Scatterv(&package_unsigned_data_sent_from_root[0],
25714 &n_unsigned_data_sent_from_root[0],
25718 &root_unsigned_offsets_sent[0],
25721 &package_unsigned_data_received_from_root[0],
25729 n_unsigned_data_received_from_root,
25737 comm_pt->mpi_comm());
25742 std::map<Node*, bool> node_done;
25746 int decode_counter = 0;
25748 Vector<Vector<unsigned>> local_node_degree(nproc);
25750 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25753 if (iproc != my_rank)
25756 const unsigned n_nodes = tmp_sorted_shared_node_pt[iproc].size();
25759 package_unsigned_send_data_to_root.push_back(n_nodes);
25762 for (
unsigned ishd = 0; ishd < n_nodes; ishd++)
25766 const unsigned node_degree =
25767 package_unsigned_data_received_from_root[decode_counter++];
25770 Node* shd_node_pt = tmp_sorted_shared_node_pt[iproc][ishd];
25773 if (!node_done[shd_node_pt])
25776 global_node_degree[shd_node_pt] = node_degree;
25778 node_done[shd_node_pt] =
true;
25785 if (global_node_degree[shd_node_pt] != node_degree)
25787 std::ostringstream error_stream;
25789 <<
"The local node has already assigned a global degree,\n"
25790 <<
"however, a different degree for the same node has been\n"
25791 <<
"read from the data sent from root processor\n"
25792 <<
"iproc processor: (" << iproc <<
")\n"
25793 <<
"Local node: (" << ishd <<
")\n"
25794 <<
"---------------------------------------------------------\n"
25795 <<
"Already assigned degree: ("
25796 << global_node_degree[shd_node_pt] <<
")\n"
25797 <<
"New found degree: (" << node_degree <<
")\n"
25798 <<
"---------------------------------------------------------\n"
25799 <<
"Node coordinates: (" << shd_node_pt->x(0) <<
", "
25800 << shd_node_pt->x(1) <<
")\n\n";
25801 throw OomphLibError(
25802 error_stream.str(),
25803 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25804 OOMPH_EXCEPTION_LOCATION);
25818 if (decode_counter != n_unsigned_data_received_from_root)
25820 std::ostringstream error_stream;
25822 <<
"The number of data decoded received from root processor is\n"
25823 <<
"different from the total number of data received from the root\n"
25825 <<
"Data decoded: (" << decode_counter <<
")\n"
25826 <<
"Data received: (" << n_unsigned_data_received_from_root <<
")\n\n"
25827 <<
"This is a synchronisation issue so you are probably sending\n"
25828 <<
"more or less info. than the one that is being decoded\n\n";
25829 throw OomphLibError(
25830 error_stream.str(),
25831 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25832 OOMPH_EXCEPTION_LOCATION);
25843 template<
class ELEMENT>
25846 Vector<Vector<FiniteElement*>>& unsorted_face_ele_pt,
25847 Vector<Vector<Node*>>& tmp_sorted_shared_node_pt,
25848 std::map<Node*, Vector<Vector<unsigned>>>& node_alias,
25849 Vector<Vector<Vector<unsigned>>>& adjacency_matrix)
25852 const unsigned nproc = this->communicator_pt()->nproc();
25853 const unsigned my_rank = this->communicator_pt()->my_rank();
25862 node_alias.clear();
25865 Vector<std::map<Node*, unsigned>> tmp_node_index(nproc);
25868 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25871 if (iproc != my_rank)
25874 std::map<Node*, bool> done_node;
25879 std::map<std::pair<double, double>, Node*,
classcomp> sorted_nodes_pt;
25882 const unsigned n_unsorted_face_ele = unsorted_face_ele_pt[iproc].size();
25885 for (
unsigned e = 0; e < n_unsorted_face_ele; e++)
25888 FiniteElement* face_ele_pt = unsorted_face_ele_pt[iproc][e];
25890 Node* left_node_pt = face_ele_pt->node_pt(0);
25895 if (!done_node[left_node_pt])
25897 std::pair<double, double> vertex =
25898 std::make_pair(left_node_pt->x(0), left_node_pt->x(1));
25899 sorted_nodes_pt[vertex] = left_node_pt;
25901 done_node[left_node_pt] =
true;
25905 const unsigned n_nodes = face_ele_pt->nnode();
25907 Node* right_node_pt = face_ele_pt->node_pt(n_nodes - 1);
25912 if (!done_node[right_node_pt])
25914 std::pair<double, double> vertex =
25915 std::make_pair(right_node_pt->x(0), right_node_pt->x(1));
25916 sorted_nodes_pt[vertex] = right_node_pt;
25918 done_node[right_node_pt] =
true;
25927 unsigned counter = 0;
25931 for (std::map<std::pair<double, double>, Node*>::iterator it =
25932 sorted_nodes_pt.begin();
25933 it != sorted_nodes_pt.end();
25937 Node* node_pt = (*it).second;
25939 tmp_sorted_shared_node_pt[iproc].push_back(node_pt);
25942 tmp_node_index[iproc][node_pt] = counter;
25945 Vector<unsigned> alias(3);
25947 alias[0] = my_rank;
25951 alias[2] = counter++;
25954 node_alias[node_pt].push_back(alias);
25964 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25967 const unsigned n_shd_nodes = tmp_sorted_shared_node_pt[iproc].size();
25969 adjacency_matrix[iproc].resize(n_shd_nodes);
25970 for (
unsigned i = 0; i < n_shd_nodes; i++)
25973 adjacency_matrix[iproc][i].resize(n_shd_nodes);
25976 for (
unsigned j = 0; j < n_shd_nodes; j++)
25978 adjacency_matrix[iproc][i][j] = 0;
25986 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25989 if (iproc != my_rank)
25992 const unsigned n_unsorted_face_ele = unsorted_face_ele_pt[iproc].size();
25995 for (
unsigned e = 0; e < n_unsorted_face_ele; e++)
25998 FiniteElement* face_ele_pt = unsorted_face_ele_pt[iproc][e];
26000 Node* left_node_pt = face_ele_pt->node_pt(0);
26003 const unsigned n_nodes = face_ele_pt->nnode();
26005 Node* right_node_pt = face_ele_pt->node_pt(n_nodes - 1);
26008 const unsigned left_node_index = tmp_node_index[iproc][left_node_pt];
26009 const unsigned right_node_index =
26010 tmp_node_index[iproc][right_node_pt];
26014 adjacency_matrix[iproc][left_node_index][right_node_index]++;
26016 adjacency_matrix[iproc][right_node_index][left_node_index]++;
26029 template<
class ELEMENT>
26032 const unsigned& shd_bnd_id, Vector<Vector<Node*>>& tmp_segment_nodes)
26035 tmp_segment_nodes.clear();
26042 Vector<FiniteElement*> halo_shared_face_ele_pt;
26045 Vector<FiniteElement*> nonhalo_shared_face_ele_pt;
26049 const unsigned nshared_bound_ele =
26050 this->nshared_boundary_element(shd_bnd_id);
26054 for (
unsigned e = 0; e < nshared_bound_ele; e++)
26057 FiniteElement* bulk_ele_pt =
26058 this->shared_boundary_element_pt(shd_bnd_id, e);
26061 int face_index = this->face_index_at_shared_boundary(shd_bnd_id, e);
26065 FiniteElement* face_ele_pt =
26066 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
26069 if (!bulk_ele_pt->is_halo())
26072 nonhalo_shared_face_ele_pt.push_back(face_ele_pt);
26078 halo_shared_face_ele_pt.push_back(face_ele_pt);
26085 std::map<FiniteElement*, bool> shared_face_done;
26088 const unsigned nnonhalo_face_shared_ele = nonhalo_shared_face_ele_pt.size();
26094 const unsigned nhalo_face_shared_ele = halo_shared_face_ele_pt.size();
26098 if (nshared_bound_ele / 2 != nnonhalo_face_shared_ele)
26100 std::ostringstream error_message;
26102 <<
"The number of shared boundary elements (" << nshared_bound_ele
26103 <<
") is not the double\nof the number of unsorted nonhalo shared "
26104 <<
"face boundary elements (" << nnonhalo_face_shared_ele
26105 <<
")\n for the current boundary (" << shd_bnd_id <<
")\n\n";
26106 throw OomphLibError(
26107 error_message.str(),
26108 "RefineableTriangleMesh::get_shared_boundary_segment_nodes_helper()",
26109 OOMPH_EXCEPTION_LOCATION);
26114 if (nshared_bound_ele / 2 != nhalo_face_shared_ele)
26116 std::ostringstream error_message;
26118 <<
"The number of shared boundary elements (" << nshared_bound_ele
26119 <<
") is not the double\nof the number of unsorted halo shared "
26120 <<
"face boundary elements (" << nhalo_face_shared_ele
26121 <<
")\n for the current boundary (" << shd_bnd_id <<
")\n\n";
26122 throw OomphLibError(
26123 error_message.str(),
26124 "RefineableTriangleMesh::get_shared_boundary_segment_nodes_helper()",
26125 OOMPH_EXCEPTION_LOCATION);
26131 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
26134 FiniteElement* nonhalo_face_ele_pt = nonhalo_shared_face_ele_pt[inh];
26137 const unsigned nnodes_nh = nonhalo_face_ele_pt->nnode();
26139 Node* nh_first_node_pt = nonhalo_face_ele_pt->node_pt(0);
26140 Node* nh_last_node_pt = nonhalo_face_ele_pt->node_pt(nnodes_nh - 1);
26144 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
26147 FiniteElement* halo_face_ele_pt = halo_shared_face_ele_pt[ih];
26150 if (!shared_face_done[halo_face_ele_pt])
26153 const unsigned nnodes_h = halo_face_ele_pt->nnode();
26155 Node* h_first_node_pt = halo_face_ele_pt->node_pt(0);
26156 Node* h_last_node_pt = halo_face_ele_pt->node_pt(nnodes_h - 1);
26160 if (nh_first_node_pt == h_first_node_pt &&
26161 nh_last_node_pt == h_last_node_pt)
26164 shared_face_done[nonhalo_face_ele_pt] =
true;
26165 shared_face_done[halo_face_ele_pt] =
true;
26171 else if (nh_first_node_pt == h_last_node_pt &&
26172 nh_last_node_pt == h_first_node_pt)
26175 shared_face_done[nonhalo_face_ele_pt] =
true;
26176 shared_face_done[halo_face_ele_pt] =
true;
26191 if ((nnonhalo_face_shared_ele + nhalo_face_shared_ele) !=
26192 shared_face_done.size())
26194 std::ostringstream error_message;
26195 error_message <<
"The number of DONE shared boundary face elements ("
26196 << shared_face_done.size()
26197 <<
") is not the same\n as the sum of"
26198 <<
"the nonhalo face shared boundary elements ("
26199 << nnonhalo_face_shared_ele
26200 <<
")\nand the halo face shared "
26201 <<
"boundary elements (" << nhalo_face_shared_ele
26203 <<
"current boundary (" << shd_bnd_id <<
")\n\n";
26204 throw OomphLibError(
26205 error_message.str(),
26206 "RefineableTriangleMesh::get_shared_boundary_segment_nodes_helper()",
26207 OOMPH_EXCEPTION_LOCATION);
26219 shared_face_done.clear();
26221 unsigned nsorted_face_ele = 0;
26224 std::list<Node*> sorted_nodes;
26227 FiniteElement* root_face_ele_pt = nonhalo_shared_face_ele_pt[0];
26228 nsorted_face_ele++;
26231 shared_face_done[root_face_ele_pt] =
true;
26234 const unsigned nnodes_root = root_face_ele_pt->nnode();
26235 Node* first_node_pt = root_face_ele_pt->node_pt(0);
26236 Node* last_node_pt = root_face_ele_pt->node_pt(nnodes_root - 1);
26239 sorted_nodes.push_back(first_node_pt);
26240 sorted_nodes.push_back(last_node_pt);
26243 while (nsorted_face_ele < nnonhalo_face_shared_ele)
26246 bool node_added =
false;
26250 for (
unsigned iface = 1; iface < nnonhalo_face_shared_ele; iface++)
26252 FiniteElement* tmp_shared_face_ele_pt =
26253 nonhalo_shared_face_ele_pt[iface];
26256 if (!shared_face_done[tmp_shared_face_ele_pt])
26259 const unsigned tmp_nnodes = tmp_shared_face_ele_pt->nnode();
26262 Node* left_node_pt = tmp_shared_face_ele_pt->node_pt(0);
26263 Node* right_node_pt = tmp_shared_face_ele_pt->node_pt(tmp_nnodes - 1);
26265 if (left_node_pt == first_node_pt)
26268 sorted_nodes.push_front(right_node_pt);
26269 first_node_pt = right_node_pt;
26272 else if (left_node_pt == last_node_pt)
26275 sorted_nodes.push_back(right_node_pt);
26276 last_node_pt = right_node_pt;
26279 else if (right_node_pt == first_node_pt)
26282 sorted_nodes.push_front(left_node_pt);
26283 first_node_pt = left_node_pt;
26286 else if (right_node_pt == last_node_pt)
26289 sorted_nodes.push_back(left_node_pt);
26290 last_node_pt = left_node_pt;
26298 shared_face_done[tmp_shared_face_ele_pt] =
true;
26299 nsorted_face_ele++;
26315 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
26317 delete nonhalo_shared_face_ele_pt[inh];
26318 nonhalo_shared_face_ele_pt[inh] = 0;
26323 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
26325 delete halo_shared_face_ele_pt[ih];
26326 halo_shared_face_ele_pt[ih] = 0;
26334 const unsigned n_nodes = sorted_nodes.size();
26337 tmp_segment_nodes.resize(1);
26338 tmp_segment_nodes[0].resize(n_nodes);
26341 unsigned counter = 0;
26344 for (std::list<Node*>::iterator it = sorted_nodes.begin();
26345 it != sorted_nodes.end();
26348 tmp_segment_nodes[0][counter] = (*it);
26359 template<
class ELEMENT>
26363 Vector<Vector<FiniteElement*>>& f_haloed_ele_pt,
26364 FiniteElement* ele_pt)
26367 const unsigned nbound = this->initial_shared_boundary_id();
26370 const unsigned nproc = this->communicator_pt()->nproc();
26375 Vector<unsigned> associated_boundaries;
26376 Vector<unsigned> face_index_on_boundary;
26378 unsigned counter_face_indexes = 0;
26380 for (
unsigned b = 0; b < nbound; b++)
26383 const unsigned nboundary_ele = nboundary_element(b);
26384 for (
unsigned e = 0; e < nboundary_ele; e++)
26386 if (ele_pt == this->boundary_element_pt(b, e))
26389 associated_boundaries.push_back(b);
26391 face_index_on_boundary.push_back(face_index_at_boundary(b, e));
26392 counter_face_indexes++;
26394 if (counter_face_indexes > 2)
26396 std::stringstream error_message;
26398 <<
"A triangular element can not have more than two of its faces "
26399 <<
"on a boundary!!!\n\n";
26400 throw OomphLibError(error_message.str(),
26401 "RefineableTriangleMesh::get_required_"
26402 "elemental_information_helper()",
26403 OOMPH_EXCEPTION_LOCATION);
26407 if (counter_face_indexes == 2)
26421 const unsigned nassociated_boundaries = associated_boundaries.size();
26422 if (nassociated_boundaries > 0)
26424 Flat_packed_unsigneds.push_back(1);
26425 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26426 Flat_packed_unsigneds_string.push_back(
26427 "The element is a boundary element");
26429 Flat_packed_unsigneds.push_back(nassociated_boundaries);
26430 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26431 std::stringstream junk;
26432 junk <<
"The elements is associated to " << nassociated_boundaries
26434 Flat_packed_unsigneds_string.push_back(junk.str());
26441 for (
unsigned i = 0; i < nassociated_boundaries; i++)
26443 unsigned b = associated_boundaries[i];
26444 Flat_packed_unsigneds.push_back(b);
26445 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26446 std::stringstream junk;
26447 junk <<
"Element associated to boundary " << b <<
" of "
26448 << nassociated_boundaries <<
" total associated boundaries";
26449 Flat_packed_unsigneds_string.push_back(junk.str());
26451 unsigned f = face_index_on_boundary[i];
26452 Flat_packed_unsigneds.push_back(f);
26453 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26454 std::stringstream junk2;
26455 junk2 <<
"Face index " << f <<
" for associated boundary " << b;
26456 Flat_packed_unsigneds_string.push_back(junk2.str());
26466 Vector<Vector<unsigned>> associated_boundaries_and_regions;
26467 Vector<unsigned> face_index_on_boundary_and_region;
26470 const unsigned n_regions = this->nregion();
26475 unsigned counter_face_indexes_in_regions = 0;
26477 for (
unsigned b = 0; b < nbound; b++)
26480 for (
unsigned i_reg = 0; i_reg < n_regions; i_reg++)
26483 const unsigned region_id =
26484 static_cast<unsigned>(this->Region_attribute[i_reg]);
26489 const unsigned nele_in_region =
26490 this->nboundary_element_in_region(b, region_id);
26491 for (
unsigned ee = 0; ee < nele_in_region; ee++)
26496 this->boundary_element_in_region_pt(b, region_id, ee))
26500 Vector<unsigned> bound_and_region(2);
26503 bound_and_region[0] = b;
26505 bound_and_region[1] = region_id;
26508 associated_boundaries_and_regions.push_back(bound_and_region);
26510 face_index_on_boundary_and_region.push_back(
26511 this->face_index_at_boundary_in_region(b, region_id, ee));
26515 counter_face_indexes_in_regions++;
26518 if (counter_face_indexes_in_regions > 2)
26520 std::stringstream error_message;
26521 error_message <<
"A triangular element can not have more "
26522 "than two of its\n"
26523 <<
"faces on a boundary!!!\n\n";
26524 throw OomphLibError(error_message.str(),
26525 "RefineableTriangleMesh::get_required_"
26526 "elemental_information_helper()",
26527 OOMPH_EXCEPTION_LOCATION);
26542 const unsigned nassociated_boundaries_and_regions =
26543 associated_boundaries_and_regions.size();
26544 if (nassociated_boundaries_and_regions > 0)
26546 Flat_packed_unsigneds.push_back(1);
26547 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26548 Flat_packed_unsigneds_string.push_back(
26549 "The element is associated to boundaries and regions");
26552 Flat_packed_unsigneds.push_back(nassociated_boundaries_and_regions);
26553 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26554 std::stringstream junk;
26555 junk <<
"The element is associated to "
26556 << nassociated_boundaries_and_regions <<
" boundaries-regions";
26557 Flat_packed_unsigneds_string.push_back(junk.str());
26564 for (
unsigned i = 0; i < nassociated_boundaries_and_regions; i++)
26566 const unsigned b = associated_boundaries_and_regions[i][0];
26567 Flat_packed_unsigneds.push_back(b);
26568 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26569 std::stringstream junk;
26570 junk <<
"Element associated to boundary " << b <<
" of "
26571 << nassociated_boundaries_and_regions
26572 <<
" total associated boundaries-regions";
26573 Flat_packed_unsigneds_string.push_back(junk.str());
26576 const unsigned r = associated_boundaries_and_regions[i][1];
26577 Flat_packed_unsigneds.push_back(r);
26578 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26579 std::stringstream junk2;
26580 junk2 <<
"Element associated to region " << r <<
" of "
26581 << nassociated_boundaries_and_regions
26582 <<
" total associated boundaries-regions";
26583 Flat_packed_unsigneds_string.push_back(junk2.str());
26586 const unsigned f = face_index_on_boundary_and_region[i];
26587 Flat_packed_unsigneds.push_back(f);
26588 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26589 std::stringstream junk3;
26590 junk3 <<
"Face index " << f <<
" for associated boundary-region ("
26591 << b <<
"-" << r <<
")";
26592 Flat_packed_unsigneds_string.push_back(junk3.str());
26598 Flat_packed_unsigneds.push_back(0);
26599 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26600 Flat_packed_unsigneds_string.push_back(
26601 "The element is NOT associated to boundaries and regions");
26607 Flat_packed_unsigneds.push_back(0);
26608 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26609 Flat_packed_unsigneds_string.push_back(
26610 "The element is not associated to any original boundary");
26619 Vector<unsigned> associated_shared_boundaries;
26620 Vector<unsigned> face_index_on_shared_boundary;
26623 Vector<unsigned> my_rank_shared_boundaries_ids;
26624 this->shared_boundaries_in_this_processor(my_rank_shared_boundaries_ids);
26627 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
26629 for (
unsigned i = 0; i < nmy_rank_shd_bnd; i++)
26632 const unsigned sb = my_rank_shared_boundaries_ids[i];
26635 const unsigned nboundary_ele = this->nshared_boundary_element(sb);
26636 for (
unsigned e = 0; e < nboundary_ele; e++)
26638 if (ele_pt == this->shared_boundary_element_pt(sb, e))
26641 associated_shared_boundaries.push_back(sb);
26643 face_index_on_shared_boundary.push_back(
26644 this->face_index_at_shared_boundary(sb, e));
26651 const unsigned nassociated_shared_boundaries =
26652 associated_shared_boundaries.size();
26653 if (nassociated_shared_boundaries > 0)
26655 Flat_packed_unsigneds.push_back(3);
26656 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26657 Flat_packed_unsigneds_string.push_back(
26658 "The element is a shared boundary element");
26660 Flat_packed_unsigneds.push_back(nassociated_shared_boundaries);
26661 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26662 std::stringstream junk;
26663 junk <<
"The elements is associated to " << nassociated_shared_boundaries
26664 <<
"shared boundaries";
26665 Flat_packed_unsigneds_string.push_back(junk.str());
26669 for (
unsigned i = 0; i < nassociated_shared_boundaries; i++)
26671 const unsigned b = associated_shared_boundaries[i];
26672 Flat_packed_unsigneds.push_back(b);
26673 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26674 std::stringstream junk;
26675 junk <<
"Element associated to shared boundary " << b <<
" of "
26676 << nassociated_shared_boundaries <<
" total associated boundaries";
26677 Flat_packed_unsigneds_string.push_back(junk.str());
26680 const unsigned f = face_index_on_shared_boundary[i];
26681 Flat_packed_unsigneds.push_back(f);
26682 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26683 std::stringstream junk2;
26684 junk2 <<
"Face index " << f <<
" for associated shared boundary " << b;
26685 Flat_packed_unsigneds_string.push_back(junk2.str());
26691 Flat_packed_unsigneds.push_back(0);
26692 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26693 Flat_packed_unsigneds_string.push_back(
26694 "The element is not associated to any shared boundary");
26701 Vector<Vector<unsigned>> index_haloed(nproc);
26704 for (
unsigned jproc = 0; jproc < nproc; jproc++)
26707 const unsigned n_haloed_jproc = f_haloed_ele_pt[jproc].size();
26709 for (
unsigned ihd = 0; ihd < n_haloed_jproc; ihd++)
26712 if (ele_pt == f_haloed_ele_pt[jproc][ihd])
26715 index_haloed[jproc].push_back(ihd);
26726 for (
unsigned jproc = 0; jproc < nproc; jproc++)
26729 const unsigned n_index_haloed_jproc = index_haloed[jproc].size();
26730 Flat_packed_unsigneds.push_back(n_index_haloed_jproc);
26731 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26732 Flat_packed_unsigneds_string.push_back(
26733 "The number of haloed indexes the element is with processor jproc");
26735 for (
unsigned ihd = 0; ihd < n_index_haloed_jproc; ihd++)
26737 Flat_packed_unsigneds.push_back(index_haloed[jproc][ihd]);
26738 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26739 Flat_packed_unsigneds_string.push_back(
26740 "The haloed index of the element with jproc");
26751 template<
class ELEMENT>
26754 Vector<Vector<FiniteElement*>>& f_halo_ele_pt,
26755 Vector<Node*>& new_nodes_on_domain,
26759 const unsigned nnew_nodes_on_domain = new_nodes_on_domain.size();
26760 const unsigned new_added_node_index =
26761 this->try_to_add_node_pt_load_balance(new_nodes_on_domain, nod_pt);
26764 if (new_added_node_index == nnew_nodes_on_domain)
26766 Flat_packed_unsigneds.push_back(1);
26768 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26769 std::stringstream junk;
26770 junk <<
"Node needs to be constructed [size="
26771 << Flat_packed_unsigneds.size() <<
"]; last entry: "
26772 << Flat_packed_unsigneds[Flat_packed_unsigneds.size() - 1];
26773 Flat_packed_unsigneds_string.push_back(junk.str());
26779 get_required_nodal_information_load_balance_helper(
26780 f_halo_ele_pt, iproc, nod_pt);
26784 Flat_packed_unsigneds.push_back(0);
26785 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26786 std::stringstream junk;
26787 junk <<
"Node was already added [size=" << Flat_packed_unsigneds.size()
26788 <<
"]; last entry: "
26789 << Flat_packed_unsigneds[Flat_packed_unsigneds.size() - 1];
26791 Flat_packed_unsigneds_string.push_back(junk.str());
26796 Flat_packed_unsigneds.push_back(new_added_node_index);
26797 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26798 Flat_packed_unsigneds_string.push_back(
"new added node index");
26808 template<
class ELEMENT>
26811 Vector<Vector<FiniteElement*>>& f_halo_ele_pt,
26815 unsigned my_rank = this->communicator_pt()->my_rank();
26816 const unsigned nproc = this->communicator_pt()->nproc();
26821 unsigned n_val = nod_pt->nvalue();
26822 Flat_packed_unsigneds.push_back(n_val);
26823 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26824 Flat_packed_unsigneds_string.push_back(
"Number of values");
26827 unsigned n_dim = nod_pt->ndim();
26830 unsigned n_prev = 1;
26831 if (this->Time_stepper_pt != 0)
26834 n_prev = this->Time_stepper_pt->ntstorage();
26840 Vector<unsigned> original_boundaries;
26843 const unsigned n_bnd = this->initial_shared_boundary_id();
26844 for (
unsigned bb = 0; bb < n_bnd; bb++)
26847 if (nod_pt->is_on_boundary(bb))
26849 original_boundaries.push_back(bb);
26853 const unsigned n_original_boundaries = original_boundaries.size();
26855 if (n_original_boundaries > 0)
26858 Flat_packed_unsigneds.push_back(2);
26859 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26860 Flat_packed_unsigneds_string.push_back(
26861 "Node is on the original boundaries");
26864 Flat_packed_unsigneds.push_back(n_original_boundaries);
26865 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26866 std::stringstream junk;
26867 junk <<
"Node is on " << n_original_boundaries <<
" original boundaries";
26868 Flat_packed_unsigneds_string.push_back(junk.str());
26872 for (
unsigned i = 0; i < n_original_boundaries; i++)
26874 Flat_packed_unsigneds.push_back(original_boundaries[i]);
26875 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26876 std::stringstream junk;
26877 junk <<
"Node is on boundary " << original_boundaries[i] <<
" of "
26879 Flat_packed_unsigneds_string.push_back(junk.str());
26882 Vector<double> zeta(1);
26883 nod_pt->get_coordinates_on_boundary(original_boundaries[i], zeta);
26884 Flat_packed_doubles.push_back(zeta[0]);
26890 Flat_packed_unsigneds.push_back(0);
26891 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26892 Flat_packed_unsigneds_string.push_back(
26893 "Node is on any original boundary");
26899 bool node_on_shared_boundary =
false;
26902 const unsigned n_shd_bnd = this->nshared_boundaries(my_rank, iproc);
26903 for (
unsigned bb = 0; bb < n_shd_bnd; bb++)
26906 unsigned i_bnd = this->shared_boundaries_ids(my_rank, iproc, bb);
26908 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
26910 node_on_shared_boundary =
true;
26918 if (node_on_shared_boundary)
26920 Flat_packed_unsigneds.push_back(1);
26921 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26922 Flat_packed_unsigneds_string.push_back(
"Node is on shared boundary");
26926 Vector<unsigned> shd_boundaries;
26928 for (
unsigned bb = 0; bb < n_shd_bnd; bb++)
26931 const unsigned i_bnd = this->shared_boundaries_ids(my_rank, iproc, bb);
26933 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
26935 shd_boundaries.push_back(i_bnd);
26940 const unsigned n_shd_bnd_is_on = shd_boundaries.size();
26942 Flat_packed_unsigneds.push_back(n_shd_bnd_is_on);
26943 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26944 std::stringstream junk;
26945 junk <<
"Node is on " << n_shd_bnd_is_on <<
" shared boundaries";
26946 Flat_packed_unsigneds_string.push_back(junk.str());
26950 for (
unsigned i = 0; i < n_shd_bnd_is_on; i++)
26952 Flat_packed_unsigneds.push_back(shd_boundaries[i]);
26953 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26954 std::stringstream junk;
26955 junk <<
"Node is on boundary " << shd_boundaries[i] <<
" of " << nb;
26956 Flat_packed_unsigneds_string.push_back(junk.str());
26962 unsigned shared_boundary_id = shd_boundaries[0];
26964 const unsigned n_nodes_on_shared_boundary =
26965 nsorted_shared_boundary_node(shared_boundary_id);
26967 unsigned index_node_on_shared_boundary;
26970 bool found_index_node_on_shared_boundary =
false;
26973 for (
unsigned i = 0; i < n_nodes_on_shared_boundary; i++)
26976 Node* shared_node_pt =
26977 sorted_shared_boundary_node_pt(shared_boundary_id, i);
26979 if (shared_node_pt == nod_pt)
26982 index_node_on_shared_boundary = i;
26985 found_index_node_on_shared_boundary =
true;
26993 if (!found_index_node_on_shared_boundary)
26995 std::ostringstream error_message;
26996 error_message <<
"The index of the node on boundary ("
26997 << shared_boundary_id <<
") was not found.\n"
26998 <<
"The node coordinates are (" << nod_pt->x(0) <<
","
26999 << nod_pt->x(1) <<
").\n";
27000 throw OomphLibError(
27001 error_message.str(),
27002 "RefineableTriangleMesh::get_required_nodal_information_helper()",
27003 OOMPH_EXCEPTION_LOCATION);
27007 Flat_packed_unsigneds.push_back(index_node_on_shared_boundary);
27008 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27009 std::stringstream junk2;
27010 junk2 <<
"Node index on boundary " << boundaries[0] <<
" is "
27011 << index_node_on_shared_boundary;
27012 Flat_packed_unsigneds_string.push_back(junk2.str());
27019 Flat_packed_unsigneds.push_back(0);
27020 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27021 Flat_packed_unsigneds_string.push_back(
27022 "Node is not on a shared boundary");
27037 bool node_on_shared_boundary_with_other_processors =
false;
27039 unsigned nshared_boundaries_with_other_processors_have_node = 0;
27043 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27047 if (jproc != iproc)
27050 const unsigned n_jshd_bnd = this->nshared_boundaries(my_rank, jproc);
27052 for (
unsigned bb = 0; bb < n_jshd_bnd; bb++)
27055 const unsigned j_shd_bnd =
27056 this->shared_boundaries_ids(my_rank, jproc, bb);
27058 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
27066 node_on_shared_boundary_with_other_processors =
true;
27069 nshared_boundaries_with_other_processors_have_node++;
27080 if (node_on_shared_boundary_with_other_processors)
27082 Flat_packed_unsigneds.push_back(4);
27083 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27084 Flat_packed_unsigneds_string.push_back(
27085 "Node is on shared boundary no related with the received processor: 4");
27091 Flat_packed_unsigneds.push_back(
27092 nshared_boundaries_with_other_processors_have_node);
27093 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27094 std::stringstream junk;
27095 junk <<
"Number of other shared boundaries that the node is on: "
27096 << nshared_boundaries_with_other_processors_have_node;
27097 Flat_packed_unsigneds_string.push_back(junk.str());
27101 unsigned counter_shd_bnd_with_other_procs_have_node = 0;
27106 Vector<unsigned> other_processor_1;
27107 Vector<unsigned> other_processor_2;
27108 Vector<unsigned> shd_bnd_ids;
27109 Vector<unsigned> indexes;
27111 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27115 if (jproc != iproc)
27119 const unsigned n_jshd_bnd = this->nshared_boundaries(my_rank, jproc);
27120 for (
unsigned bb = 0; bb < n_jshd_bnd; bb++)
27123 const unsigned j_shd_bnd =
27124 this->shared_boundaries_ids(my_rank, jproc, bb);
27126 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
27129 other_processor_1.push_back(my_rank);
27131 other_processor_2.push_back(jproc);
27133 shd_bnd_ids.push_back(j_shd_bnd);
27136 counter_shd_bnd_with_other_procs_have_node++;
27147 const unsigned n_other_processors = other_processor_1.size();
27149 for (
unsigned i = 0; i < n_other_processors; i++)
27152 unsigned shd_bnd_id = shd_bnd_ids[i];
27154 const unsigned n_nodes_on_shd_bnd =
27155 nsorted_shared_boundary_node(shd_bnd_id);
27158 bool found_index_node_on_shared_boundary =
false;
27160 for (
unsigned i = 0; i < n_nodes_on_shd_bnd; i++)
27163 Node* shared_node_pt = sorted_shared_boundary_node_pt(shd_bnd_id, i);
27165 if (shared_node_pt == nod_pt)
27171 indexes.push_back(i);
27174 found_index_node_on_shared_boundary =
true;
27182 if (!found_index_node_on_shared_boundary)
27184 std::ostringstream error_message;
27185 error_message <<
"The index of the node on boundary (" << shd_bnd_id
27186 <<
"), shared by other processors\nwas not found.\n"
27187 <<
"The node coordinates are (" << nod_pt->x(0) <<
","
27188 << nod_pt->x(1) <<
").\n";
27189 throw OomphLibError(
27190 error_message.str(),
27191 "RefineableTriangleMesh::get_required_nodal_information_helper()",
27192 OOMPH_EXCEPTION_LOCATION);
27201 if (counter_shd_bnd_with_other_procs_have_node !=
27202 nshared_boundaries_with_other_processors_have_node)
27204 std::ostringstream error_message;
27205 error_message <<
"The number of shared boundaries where the node is on "
27206 <<
"is different:\n"
27207 <<
"nshared_boundaries_with_other_processors_have_node: ("
27208 << nshared_boundaries_with_other_processors_have_node
27210 <<
"counter_shd_bnd_with_other_procs_have_node: ("
27211 << counter_shd_bnd_with_other_procs_have_node <<
")\n";
27212 throw OomphLibError(
27213 error_message.str(),
27214 "RefineableTriangleMesh::get_required_nodal_information_helper()",
27215 OOMPH_EXCEPTION_LOCATION);
27221 for (
unsigned i = 0; i < n_other_processors; i++)
27223 Flat_packed_unsigneds.push_back(other_processor_1[i]);
27224 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27225 std::stringstream junk1;
27226 junk1 <<
"Processor where the other shared boundary "
27227 <<
"has the node: " << other_processor_1[i];
27228 Flat_packed_unsigneds_string.push_back(junk1.str());
27231 Flat_packed_unsigneds.push_back(other_processor_2[i]);
27232 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27233 std::stringstream junk2;
27234 junk2 <<
"Processor where the other shared boundary "
27235 <<
"has the node: " << other_processor_2[i];
27236 Flat_packed_unsigneds_string.push_back(junk2.str());
27239 Flat_packed_unsigneds.push_back(shd_bnd_ids[i]);
27240 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27241 std::stringstream junk3;
27242 junk3 <<
"Other shared boundary id where the node is on"
27244 Flat_packed_unsigneds_string.push_back(junk3.str());
27247 Flat_packed_unsigneds.push_back(indexes[i]);
27248 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27249 std::stringstream junk4;
27250 junk4 <<
"Node index on other shared boundary " << boundaries[i]
27251 <<
" is " << indexes[i];
27252 Flat_packed_unsigneds_string.push_back(junk4.str());
27260 Flat_packed_unsigneds.push_back(0);
27261 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27262 Flat_packed_unsigneds_string.push_back(
27263 "Node is on any shared boundary with other processors");
27290 Vector<Vector<unsigned>> halo_element_number(nproc);
27292 Vector<Vector<unsigned>> halo_node_number_in_halo_element(nproc);
27295 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27298 const unsigned n_halo_jproc = f_halo_ele_pt[jproc].size();
27300 for (
unsigned jh = 0; jh < n_halo_jproc; jh++)
27302 FiniteElement* halo_ele_pt = f_halo_ele_pt[jproc][jh];
27304 const unsigned n_node = halo_ele_pt->nnode();
27306 for (
unsigned n = 0; n < n_node; n++)
27309 if (nod_pt == halo_ele_pt->node_pt(n))
27311 halo_element_number[jproc].push_back(jh);
27312 halo_node_number_in_halo_element[jproc].push_back(n);
27328 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27332 const unsigned n_jproc_halo_ele_node_is_on =
27333 halo_element_number[jproc].size();
27335 Flat_packed_unsigneds.push_back(n_jproc_halo_ele_node_is_on);
27336 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27337 std::stringstream junk5;
27338 junk5 <<
"Node is on " << n_jproc_halo_ele_node_is_on <<
" halo "
27339 <<
"elements with " << jproc <<
"-th processor";
27340 Flat_packed_unsigneds_string.push_back(junk5.str());
27345 for (
unsigned i = 0; i < n_jproc_halo_ele_node_is_on; i++)
27348 const unsigned halo_element_index = halo_element_number[jproc][i];
27349 Flat_packed_unsigneds.push_back(halo_element_index);
27350 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27351 std::stringstream junk6;
27352 junk6 <<
"Halo element index is (" << halo_element_index
27353 <<
") with processor (" << jproc <<
")";
27354 Flat_packed_unsigneds_string.push_back(junk6.str());
27357 const unsigned node_index = halo_node_number_in_halo_element[jproc][i];
27358 Flat_packed_unsigneds.push_back(node_index);
27359 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27360 std::stringstream junk7;
27361 junk7 <<
"The node index on the halo element index is (" << node_index;
27362 Flat_packed_unsigneds_string.push_back(junk7.str());
27377 bool on_halo_element_with_iproc_processor =
false;
27378 if (halo_element_number[iproc].size() > 0)
27380 on_halo_element_with_iproc_processor =
true;
27384 if (!node_on_shared_boundary && !on_halo_element_with_iproc_processor)
27391 AlgebraicNode* alg_nod_pt =
dynamic_cast<AlgebraicNode*
>(nod_pt);
27392 if (alg_nod_pt != 0)
27395 AlgebraicMesh* alg_mesh_pt =
dynamic_cast<AlgebraicMesh*
>(
this);
27398 unsigned update_id = alg_nod_pt->node_update_fct_id();
27399 Flat_packed_unsigneds.push_back(update_id);
27400 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27401 Flat_packed_unsigneds_string.push_back(
"Alg Node update id");
27405 unsigned n_ref_val = alg_nod_pt->nref_value();
27406 Flat_packed_unsigneds.push_back(n_ref_val);
27407 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27408 Flat_packed_unsigneds_string.push_back(
"Alg Node n ref values");
27410 for (
unsigned i_ref_val = 0; i_ref_val < n_ref_val; i_ref_val++)
27412 Flat_packed_doubles.push_back(alg_nod_pt->ref_value(i_ref_val));
27416 unsigned n_geom_obj = alg_nod_pt->ngeom_object();
27417 Flat_packed_unsigneds.push_back(n_geom_obj);
27418 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27419 Flat_packed_unsigneds_string.push_back(
"Alg Node n geom objects");
27421 for (
unsigned i_geom = 0; i_geom < n_geom_obj; i_geom++)
27423 GeomObject* geom_obj_pt = alg_nod_pt->geom_object_pt(i_geom);
27426 unsigned n_geom_list = alg_mesh_pt->ngeom_object_list_pt();
27429 unsigned found_geom_object = 0;
27430 for (
unsigned i_list = 0; i_list < n_geom_list; i_list++)
27432 if (geom_obj_pt == alg_mesh_pt->geom_object_list_pt(i_list))
27434 found_geom_object = i_list;
27437 Flat_packed_unsigneds.push_back(found_geom_object);
27438 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27439 Flat_packed_unsigneds_string.push_back(
"Found geom object");
27445 SolidNode* solid_nod_pt =
dynamic_cast<SolidNode*
>(nod_pt);
27446 if (solid_nod_pt != 0)
27448 unsigned n_solid_val = solid_nod_pt->variable_position_pt()->nvalue();
27449 for (
unsigned i_val = 0; i_val < n_solid_val; i_val++)
27451 for (
unsigned t = 0; t < n_prev; t++)
27453 Flat_packed_doubles.push_back(
27454 solid_nod_pt->variable_position_pt()->value(t, i_val));
27458 Vector<double> values_solid_node;
27459 solid_nod_pt->add_values_to_vector(values_solid_node);
27460 const unsigned nvalues_solid_node = values_solid_node.size();
27461 Flat_packed_unsigneds.push_back(nvalues_solid_node);
27462 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27463 std::stringstream junk;
27464 junk <<
"Number of values solid node: " << nvalues_solid_node;
27465 Flat_packed_unsigneds_string.push_back(junk.str());
27467 for (
unsigned i = 0; i < nvalues_solid_node; i++)
27469 Flat_packed_doubles.push_back(values_solid_node[i]);
27474 for (
unsigned i_val = 0; i_val < n_val; i_val++)
27476 for (
unsigned t = 0; t < n_prev; t++)
27478 Flat_packed_doubles.push_back(nod_pt->value(t, i_val));
27483 for (
unsigned idim = 0; idim < n_dim; idim++)
27485 for (
unsigned t = 0; t < n_prev; t++)
27487 Flat_packed_doubles.push_back(nod_pt->x(t, idim));
27500 template<
class ELEMENT>
27503 Vector<Vector<FiniteElement*>>& f_haloed_ele_pt,
27504 Vector<Vector<std::map<unsigned, FiniteElement*>>>&
27505 received_old_haloed_element_pt,
27506 Vector<FiniteElement*>& new_elements_on_domain,
27507 Vector<Node*>& new_nodes_on_domain,
27508 Vector<Vector<Vector<std::map<unsigned, Node*>>>>&
27509 other_proc_shd_bnd_node_pt,
27510 Vector<Vector<Vector<unsigned>>>& global_node_names,
27511 std::map<Vector<unsigned>,
unsigned>& node_name_to_global_index,
27512 Vector<Node*>& global_shared_node_pt)
27514 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27515 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27516 <<
" Bool: New element needs to be constructed "
27517 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27521 if (Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++] == 1)
27525 GeneralisedElement* new_el_pt =
new ELEMENT;
27532 FiniteElement* f_el_pt =
dynamic_cast<FiniteElement*
>(new_el_pt);
27535 new_elements_on_domain.push_back(f_el_pt);
27538 this->add_element_load_balance_helper(
27539 iproc, received_old_haloed_element_pt, f_el_pt);
27542 unsigned n_node = f_el_pt->nnode();
27543 for (
unsigned j = 0; j < n_node; j++)
27545 Node* new_nod_pt = 0;
27548 add_received_node_load_balance_helper(new_nod_pt,
27550 received_old_haloed_element_pt,
27551 new_nodes_on_domain,
27552 other_proc_shd_bnd_node_pt,
27557 node_name_to_global_index,
27558 global_shared_node_pt);
27563 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27564 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27565 <<
" Index of existing element "
27566 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27571 Counter_for_flat_packed_unsigneds++;
27583 template<
class ELEMENT>
27585 const unsigned& iproc,
27586 Vector<Vector<std::map<unsigned, FiniteElement*>>>&
27587 received_old_haloed_element_pt,
27588 FiniteElement* ele_pt)
27591 const unsigned nproc = this->communicator_pt()->nproc();
27593 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27594 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27595 <<
" Bool: Element is associated to a boundary "
27596 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27601 const unsigned is_on_original_boundary =
27602 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27603 if (is_on_original_boundary == 1)
27605 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27606 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27607 <<
" How many boundaries are associated with the element "
27608 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27612 const unsigned nassociated_boundaries =
27613 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27616 for (
unsigned b = 0; b < nassociated_boundaries; b++)
27618 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27619 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27620 <<
" Boundary associated to the element "
27621 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27626 const unsigned bnd =
27627 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27629 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27630 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27631 <<
" Face index of the element "
27632 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27637 const unsigned face_index =
27638 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27642 this->Boundary_element_pt[bnd].push_back(ele_pt);
27643 this->Face_index_at_boundary[bnd].push_back(face_index);
27648 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27649 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27650 <<
" Bool: Element is associated to a boundary-region "
27651 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27656 if (Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++] == 1)
27658 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27660 <<
"Rec:" << Counter_for_flat_packed_unsigneds
27661 <<
" How many boundaries-regions are associated with the element "
27662 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27666 const unsigned nassociated_boundaries_and_regions =
27667 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27669 for (
unsigned br = 0; br < nassociated_boundaries_and_regions; br++)
27671 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27672 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27673 <<
" Boundary associated to the element "
27674 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27678 const unsigned bnd =
27679 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27681 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27682 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27683 <<
" Region associated to the element "
27684 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27688 const unsigned region =
27689 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27691 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27692 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27693 <<
" Face index of the element in boundary-region "
27694 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27697 const unsigned face_index =
27698 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27702 this->Boundary_region_element_pt[bnd][region].push_back(ele_pt);
27703 this->Face_index_region_at_boundary[bnd][region].push_back(
27714 if (is_on_original_boundary != 0)
27716 std::ostringstream error_message;
27718 <<
"The current element is not on an original boundary, this should\n"
27719 <<
"be indicated by a zero flag. However, the read value for\n"
27720 <<
"that flag is (" << is_on_original_boundary <<
").\n\n";
27721 throw OomphLibError(
27722 error_message.str(),
27723 "RefineableTriangleMesh::add_element_load_balance_helper()",
27724 OOMPH_EXCEPTION_LOCATION);
27729 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27730 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27731 <<
" Bool: Element is associated to a shared boundary "
27732 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27737 const unsigned is_on_shared_boundary =
27738 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27739 if (is_on_shared_boundary == 3)
27741 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27743 <<
"Rec:" << Counter_for_flat_packed_unsigneds
27744 <<
" How many shared boundaries are associated with the element "
27745 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27750 const unsigned nassociated_shared_boundaries =
27751 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27754 for (
unsigned b = 0; b < nassociated_shared_boundaries; b++)
27756 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27757 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27758 <<
" Shared boundary associated to the element "
27759 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27762 const unsigned bnd =
27763 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27765 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27767 <<
"Rec:" << Counter_for_flat_packed_unsigneds
27768 <<
" Face index of the element associated to the shared boundary "
27769 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27773 const unsigned face_index =
27774 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27776 this->add_shared_boundary_element(bnd, ele_pt);
27777 this->add_face_index_at_shared_boundary(bnd, face_index);
27785 if (is_on_shared_boundary != 0)
27787 std::ostringstream error_message;
27789 <<
"The current element is not on a shared boundary, this should\n"
27790 <<
"be indicated by a zero flag. However, the read value for\n"
27791 <<
"that flag is (" << is_on_shared_boundary <<
").\n\n";
27792 throw OomphLibError(
27793 error_message.str(),
27794 "RefineableTriangleMesh::add_element_load_balance_helper()",
27795 OOMPH_EXCEPTION_LOCATION);
27804 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27806 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27807 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27808 <<
" Bool: Number of haloed indexes of the element with the "
27809 << jproc <<
" processor: "
27810 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27814 const unsigned n_index_haloed_jproc =
27815 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27817 for (
unsigned ihd = 0; ihd < n_index_haloed_jproc; ihd++)
27819 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27820 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27821 <<
" Bool: The haloed element index with the " << jproc
27823 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27826 const unsigned haloed_index =
27827 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27830 received_old_haloed_element_pt[iproc][jproc][haloed_index] = ele_pt;
27840 template<
class ELEMENT>
27843 Vector<Vector<FiniteElement*>>& f_haloed_ele_pt,
27844 Vector<Vector<std::map<unsigned, FiniteElement*>>>&
27845 received_old_haloed_element_pt,
27846 Vector<Node*>& new_nodes_on_domain,
27847 Vector<Vector<Vector<std::map<unsigned, Node*>>>>&
27848 other_proc_shd_bnd_node_pt,
27850 unsigned& node_index,
27851 FiniteElement*
const& new_el_pt,
27852 Vector<Vector<Vector<unsigned>>>& global_node_names,
27853 std::map<Vector<unsigned>,
unsigned>& node_name_to_global_index,
27854 Vector<Node*>& global_shared_node_pt)
27858 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27859 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27860 <<
" Bool: New node needs to be constructed "
27861 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27864 if (Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++] == 1)
27868 construct_new_node_load_balance_helper(new_nod_pt,
27870 received_old_haloed_element_pt,
27871 new_nodes_on_domain,
27872 other_proc_shd_bnd_node_pt,
27877 node_name_to_global_index,
27878 global_shared_node_pt);
27882 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27883 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27884 <<
" Index of existing halo node "
27885 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27891 new_nod_pt = new_nodes_on_domain
27892 [Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++]];
27895 new_el_pt->node_pt(node_index) = new_nod_pt;
27904 template<
class ELEMENT>
27907 Vector<Vector<FiniteElement*>>& f_haloed_ele_pt,
27908 Vector<Vector<std::map<unsigned, FiniteElement*>>>&
27909 received_old_haloed_element_pt,
27910 Vector<Node*>& new_nodes_on_domain,
27911 Vector<Vector<Vector<std::map<unsigned, Node*>>>>&
27912 other_proc_shd_bnd_node_pt,
27914 unsigned& node_index,
27915 FiniteElement*
const& new_el_pt,
27916 Vector<Vector<Vector<unsigned>>>& global_node_names,
27917 std::map<Vector<unsigned>,
unsigned>& node_name_to_global_index,
27918 Vector<Node*>& global_shared_node_pt)
27921 const unsigned nproc = this->communicator_pt()->nproc();
27923 const unsigned my_rank = this->communicator_pt()->my_rank();
27927 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27928 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27929 <<
" Number of values of external halo node "
27930 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27933 unsigned n_val = Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27936 TimeStepper* time_stepper_pt = this->Time_stepper_pt;
27938 unsigned n_prev = time_stepper_pt->ntstorage();
27942 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27943 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27944 <<
" Is the node on an original boundary "
27945 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27950 const unsigned node_on_original_boundaries =
27951 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27954 Vector<unsigned> original_boundaries_node_is_on;
27956 Vector<double> zeta_coordinates;
27958 unsigned n_original_boundaries_node_is_on = 0;
27960 if (node_on_original_boundaries == 2)
27963 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27964 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27965 <<
" Number of boundaries the node is on: "
27966 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27969 n_original_boundaries_node_is_on =
27970 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27973 original_boundaries_node_is_on.resize(n_original_boundaries_node_is_on);
27974 zeta_coordinates.resize(n_original_boundaries_node_is_on);
27976 for (
unsigned i = 0; i < n_original_boundaries_node_is_on; i++)
27979 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27980 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27981 <<
" Node is on boundary "
27982 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27985 original_boundaries_node_is_on[i] =
27986 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27987 zeta_coordinates[i] =
27988 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
27995 if (node_on_original_boundaries != 0)
27997 std::ostringstream error_message;
27999 <<
"The current node is not on an original boundary, this should\n"
28000 <<
"be indicated by a zero flag. However, the read value for\n"
28001 <<
"that flag is (" << node_on_original_boundaries <<
").\n\n";
28002 throw OomphLibError(
28003 error_message.str(),
28004 "RefineableTriangleMesh::construct_new_halo_node_helper()",
28005 OOMPH_EXCEPTION_LOCATION);
28013 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28014 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28015 <<
" Is node on shared boundary? "
28016 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28019 const unsigned is_node_on_shared_boundary =
28020 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28021 if (is_node_on_shared_boundary == 1)
28024 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28025 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28026 <<
" Number of boundaries the node is on: "
28027 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28030 const unsigned n_shd_bnd_node_is_on =
28031 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28032 Vector<unsigned> shd_bnds_node_is_on(n_shd_bnd_node_is_on);
28033 for (
unsigned i = 0; i < n_shd_bnd_node_is_on; i++)
28036 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28037 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28038 <<
" Node is on boundary "
28039 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28042 shd_bnds_node_is_on[i] =
28043 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28047 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28048 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28049 <<
" Index of node on boundary "
28050 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28054 unsigned node_index_on_shared_boundary =
28055 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28058 new_nod_pt = this->sorted_shared_boundary_node_pt(
28059 shd_bnds_node_is_on[0], node_index_on_shared_boundary);
28065 if (is_node_on_shared_boundary != 0)
28067 std::ostringstream error_message;
28069 <<
"The current node is not on a shared boundary, this should\n"
28070 <<
"be indicated by a zero flag. However, the read value for\n"
28071 <<
"that flag is (" << is_node_on_shared_boundary <<
").\n\n";
28072 throw OomphLibError(
28073 error_message.str(),
28074 "RefineableTriangleMesh::construct_new_halo_node_helper()",
28075 OOMPH_EXCEPTION_LOCATION);
28082 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28083 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28084 <<
" Is the node on shared boundaries with other processors "
28085 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28091 const unsigned is_the_node_in_shared_boundaries_with_other_processors =
28092 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28095 Vector<unsigned> other_processor_1;
28096 Vector<unsigned> other_processor_2;
28097 Vector<unsigned> other_shared_boundaries;
28098 Vector<unsigned> other_indexes;
28101 unsigned n_shd_bnd_with_other_procs_have_node = 0;
28104 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
28106 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28107 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28108 <<
" In how many shared boundaries with other "
28109 <<
"processors is the node "
28110 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28115 n_shd_bnd_with_other_procs_have_node =
28116 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28119 other_processor_1.resize(n_shd_bnd_with_other_procs_have_node);
28120 other_processor_2.resize(n_shd_bnd_with_other_procs_have_node);
28121 other_shared_boundaries.resize(n_shd_bnd_with_other_procs_have_node);
28122 other_indexes.resize(n_shd_bnd_with_other_procs_have_node);
28124 for (
unsigned i = 0; i < n_shd_bnd_with_other_procs_have_node; i++)
28126 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28127 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28128 <<
" Processor where the other shared boundary"
28130 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28134 other_processor_1[i] =
28135 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28137 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28138 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28139 <<
" Processor where the other shared boundary"
28141 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28145 other_processor_2[i] =
28146 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28148 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28149 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28150 <<
" Other shared boundary id where the node is on: "
28151 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28156 other_shared_boundaries[i] =
28157 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28159 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28160 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28161 <<
" Node index on the other shared boundary "
28162 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28168 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28176 if (is_the_node_in_shared_boundaries_with_other_processors != 0)
28178 std::ostringstream error_message;
28180 <<
"The current node is not on a shared boundary with\n"
28181 <<
"other processors, this should be indicated by a zero flag.\n"
28182 <<
"However, the read value for that flag is ("
28183 << is_the_node_in_shared_boundaries_with_other_processors <<
").\n\n";
28184 throw OomphLibError(
28185 error_message.str(),
28186 "RefineableTriangleMesh::construct_new_node_load_balance_helper()",
28187 OOMPH_EXCEPTION_LOCATION);
28197 Vector<Vector<unsigned>> halo_element_number(nproc);
28199 Vector<Vector<unsigned>> halo_node_number_in_halo_element(nproc);
28202 for (
unsigned jproc = 0; jproc < nproc; jproc++)
28204 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28205 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28206 <<
" The node is on "
28207 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28208 <<
" halo elements with " << jproc <<
" processor"
28213 const unsigned n_jproc_halo_ele_node_is_on =
28214 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28217 halo_element_number[jproc].resize(n_jproc_halo_ele_node_is_on);
28218 halo_node_number_in_halo_element[jproc].resize(
28219 n_jproc_halo_ele_node_is_on);
28224 for (
unsigned i = 0; i < n_jproc_halo_ele_node_is_on; i++)
28227 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28228 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28229 <<
" The halo element index where the node is on "
28230 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28234 const unsigned halo_ele_index =
28235 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28236 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28237 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28238 <<
" The node index on the halo element where the node "
28240 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28243 const unsigned node_index_on_halo_ele =
28244 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28247 halo_element_number[jproc][i] = halo_ele_index;
28249 halo_node_number_in_halo_element[jproc][i] = node_index_on_halo_ele;
28258 std::set<Node*> set_haloed_node_pt;
28261 Node* haloed_node_pt = 0;
28267 bool on_haloed_element_with_iproc_processor =
false;
28268 if (halo_element_number[my_rank].size() > 0)
28272 on_haloed_element_with_iproc_processor =
true;
28275 const unsigned n_haloed_indexes = halo_element_number[my_rank].size();
28279 for (
unsigned i = 0; i < n_haloed_indexes; i++)
28282 const unsigned haloed_index = halo_element_number[my_rank][i];
28284 const unsigned haloed_node_index =
28285 halo_node_number_in_halo_element[my_rank][i];
28288 FiniteElement* tmp_haloed_ele_pt = f_haloed_ele_pt[iproc][haloed_index];
28290 Node* tmp_haloed_node_pt =
28291 tmp_haloed_ele_pt->node_pt(haloed_node_index);
28294 haloed_node_pt = tmp_haloed_node_pt;
28297 set_haloed_node_pt.insert(tmp_haloed_node_pt);
28300 if (set_haloed_node_pt.size() > 1)
28302 std::ostringstream error_message;
28304 <<
"When adding the " << haloed_node_index <<
" node of the "
28305 << haloed_index <<
"-th haloed element\n"
28306 <<
"in the currrent processor with the " << iproc <<
" processor"
28307 <<
"it was found that\nthe node pointer is different from the other"
28308 <<
"instances of the node.\nIt means we have a repeated node."
28309 <<
"This are the node coordinates of the previous node instances\n"
28310 <<
"The last entry is for the just added node with a different "
28313 for (std::set<Node*>::iterator it = set_haloed_node_pt.begin();
28314 it != set_haloed_node_pt.end();
28317 error_message <<
"Node: (" << (*it)->x(0) <<
", " << (*it)->x(1)
28320 error_message <<
"\n";
28321 throw OomphLibError(
28322 error_message.str(),
28323 "RefineableTriangleMesh::construct_new_node_load_balance_helper()",
28324 OOMPH_EXCEPTION_LOCATION);
28334 bool found_on_haloed_element_with_other_processor =
false;
28337 for (
unsigned jproc = 0; jproc < iproc; jproc++)
28340 if (halo_element_number[jproc].size() > 0)
28343 const unsigned n_halo_indexes = halo_element_number[jproc].size();
28347 for (
unsigned i = 0; i < n_halo_indexes; i++)
28350 const unsigned haloed_index = halo_element_number[jproc][i];
28352 const unsigned haloed_node_index =
28353 halo_node_number_in_halo_element[jproc][i];
28357 std::map<unsigned, FiniteElement*>::iterator it_map =
28358 received_old_haloed_element_pt[jproc][iproc].find(haloed_index);
28360 if (it_map != received_old_haloed_element_pt[jproc][iproc].end())
28365 found_on_haloed_element_with_other_processor =
true;
28368 FiniteElement* tmp_haloed_ele_pt = (*it_map).second;
28370 Node* tmp_haloed_node_pt =
28371 tmp_haloed_ele_pt->node_pt(haloed_node_index);
28374 haloed_node_pt = tmp_haloed_node_pt;
28377 set_haloed_node_pt.insert(tmp_haloed_node_pt);
28380 if (set_haloed_node_pt.size() > 1)
28382 std::ostringstream error_message;
28384 <<
"When adding the " << haloed_node_index <<
" node of the "
28385 << haloed_index <<
"-th haloed element "
28386 <<
"of the " << jproc <<
" processor\nwith the " << iproc
28387 <<
" processor, it was found that\n"
28388 <<
"the node pointer is different from the other\n"
28389 <<
"instances of the node.\nThis means we have a repeated "
28391 <<
"These are the node coordinates of the previous node "
28393 <<
"The last entry is for the just added node with a "
28395 <<
"node pointer\n";
28396 for (std::set<Node*>::iterator it = set_haloed_node_pt.begin();
28397 it != set_haloed_node_pt.end();
28400 error_message <<
"Node: (" << (*it)->x(0) <<
", " << (*it)->x(1)
28403 error_message <<
"\n";
28404 throw OomphLibError(error_message.str(),
28405 "RefineableTriangleMesh::construct_new_node_"
28406 "load_balance_helper()",
28407 OOMPH_EXCEPTION_LOCATION);
28425 if (on_haloed_element_with_iproc_processor ||
28426 found_on_haloed_element_with_other_processor)
28429 new_nod_pt = haloed_node_pt;
28437 if (is_node_on_shared_boundary == 1 ||
28438 (on_haloed_element_with_iproc_processor))
28443 if (node_on_original_boundaries == 2)
28449 for (
unsigned i = 0; i < n_original_boundaries_node_is_on; i++)
28451 add_boundary_node(original_boundaries_node_is_on[i], new_nod_pt);
28453 Vector<double> zeta(1);
28454 zeta[0] = zeta_coordinates[i];
28455 new_nod_pt->set_coordinates_on_boundary(
28456 original_boundaries_node_is_on[i], zeta);
28462 new_nodes_on_domain.push_back(new_nod_pt);
28465 new_el_pt->node_pt(node_index) = new_nod_pt;
28475 bool found_node_in_other_shared_boundaries =
false;
28484 bool build_node_as_boundary_node =
false;
28486 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
28489 build_node_as_boundary_node =
true;
28496 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
28500 Vector<Node*> found_node_pt;
28503 for (
unsigned i = 0; i < n_shd_bnd_with_other_procs_have_node; i++)
28505 unsigned oproc1 = other_processor_1[i];
28506 unsigned oproc2 = other_processor_2[i];
28510 if (oproc1 > oproc2)
28513 oproc1 = other_processor_2[i];
28518 const unsigned shd_bnd_id =
28519 other_shared_boundaries[i] - initial_shd_bnd_id;
28521 const unsigned index = other_indexes[i];
28525 const unsigned n_nodes_on_other_processor =
28526 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].size();
28528 if (n_nodes_on_other_processor > 0)
28532 std::map<unsigned, Node*>::iterator it =
28533 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].find(index);
28537 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].end())
28540 found_node_in_other_shared_boundaries =
true;
28542 Node* tmp_node_pt =
28543 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id][index];
28544 found_node_pt.push_back(tmp_node_pt);
28554 if (found_node_in_other_shared_boundaries)
28557 const unsigned ntimes_node_found = found_node_pt.size();
28558 for (
unsigned j = 1; j < ntimes_node_found; j++)
28560 if (found_node_pt[j - 1] != found_node_pt[j])
28562 std::ostringstream error_message;
28564 <<
"The instances of the node that was found to be on a\n"
28565 <<
"shared boundary with other processors are not the same,\n"
28566 <<
"the coordinates for the nodes are these:\n"
28567 <<
"(" << found_node_pt[j - 1]->x(0) <<
", "
28568 << found_node_pt[j - 1]->x(1) <<
")\n"
28569 <<
"(" << found_node_pt[j]->x(0) <<
", " << found_node_pt[j]->x(1)
28571 <<
"Not be surprised if they are the same since the node is\n"
28572 <<
"repeated!!!\n";
28573 throw OomphLibError(
28574 error_message.str(),
28575 "RefineableTriangleMesh::construct_new_halo_node_helper()",
28576 OOMPH_EXCEPTION_LOCATION);
28587 if (is_node_on_shared_boundary == 1)
28592 if (found_node_pt[0] != new_nod_pt)
28594 std::ostringstream error_message;
28596 <<
"The pointer of the node that was found to be on a\n"
28597 <<
"shared boundary with other processor(s) and the pointer\n"
28598 <<
"of the node on shared boundary with the receiver\n"
28599 <<
"processor (iproc) are not the same. This means we have a\n"
28600 <<
"repeated node)\n"
28601 <<
"The coordinates for the nodes are:\n"
28602 <<
"(" << found_node_pt[0]->x(0) <<
", " << found_node_pt[0]->x(1)
28604 <<
"(" << new_nod_pt->x(0) <<
", " << new_nod_pt->x(1) <<
")\n"
28605 <<
"Not to be surprised if they are the same since the node is\n"
28606 <<
"repeated!!!\n";
28607 throw OomphLibError(
28608 error_message.str(),
28609 "RefineableTriangleMesh::construct_new_halo_node_helper()",
28610 OOMPH_EXCEPTION_LOCATION);
28619 new_nod_pt = found_node_pt[0];
28631 if (is_node_on_shared_boundary != 1 &&
28632 !on_haloed_element_with_iproc_processor)
28646 if (node_on_original_boundaries == 2 || build_node_as_boundary_node)
28652 if (!found_node_in_other_shared_boundaries ||
28653 !found_on_haloed_element_with_other_processor)
28656 if (time_stepper_pt != 0)
28659 new_el_pt->construct_boundary_node(node_index, time_stepper_pt);
28663 new_nod_pt = new_el_pt->construct_boundary_node(node_index);
28671 new_el_pt->node_pt(node_index) = new_nod_pt;
28676 for (
unsigned i = 0; i < n_original_boundaries_node_is_on; i++)
28678 add_boundary_node(original_boundaries_node_is_on[i], new_nod_pt);
28680 Vector<double> zeta(1);
28681 zeta[0] = zeta_coordinates[i];
28682 new_nod_pt->set_coordinates_on_boundary(
28683 original_boundaries_node_is_on[i], zeta);
28693 if (!found_node_in_other_shared_boundaries ||
28694 !found_on_haloed_element_with_other_processor)
28697 if (time_stepper_pt != 0)
28699 new_nod_pt = new_el_pt->construct_node(node_index, time_stepper_pt);
28703 new_nod_pt = new_el_pt->construct_node(node_index);
28710 new_el_pt->node_pt(node_index) = new_nod_pt;
28722 new_nodes_on_domain.push_back(new_nod_pt);
28728 if (!found_node_in_other_shared_boundaries ||
28729 !found_on_haloed_element_with_other_processor)
28732 this->add_node_pt(new_nod_pt);
28737 AlgebraicNode* new_alg_nod_pt =
dynamic_cast<AlgebraicNode*
>(new_nod_pt);
28741 if (new_alg_nod_pt != 0)
28744 AlgebraicMesh* alg_mesh_pt =
dynamic_cast<AlgebraicMesh*
>(
this);
28750 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28751 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28752 <<
" Alg node update id "
28753 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28757 unsigned update_id =
28758 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28760 Vector<double> ref_value;
28764 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28765 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28766 <<
" Alg node # of ref values "
28767 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28770 unsigned n_ref_val =
28771 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28775 ref_value.resize(n_ref_val);
28776 for (
unsigned i_ref = 0; i_ref < n_ref_val; i_ref++)
28779 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
28782 Vector<GeomObject*> geom_object_pt;
28789 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28790 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28791 <<
" Alg node # of geom objects "
28792 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28795 unsigned n_geom_obj =
28796 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28800 geom_object_pt.resize(n_geom_obj);
28801 for (
unsigned i_geom = 0; i_geom < n_geom_obj; i_geom++)
28803 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28804 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28805 <<
" Alg node: geom object index "
28806 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28809 unsigned geom_index =
28810 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28817 geom_object_pt[i_geom] = alg_mesh_pt->geom_object_list_pt(geom_index);
28824 if (!found_node_in_other_shared_boundaries ||
28825 !found_on_haloed_element_with_other_processor)
28829 new_alg_nod_pt->add_node_update_info(
28830 update_id, alg_mesh_pt, geom_object_pt, ref_value);
28833 alg_mesh_pt->update_node_update(new_alg_nod_pt);
28844 if (!found_node_in_other_shared_boundaries ||
28845 !found_on_haloed_element_with_other_processor)
28848 MacroElementNodeUpdateNode* macro_nod_pt =
28849 dynamic_cast<MacroElementNodeUpdateNode*
>(new_nod_pt);
28851 if (macro_nod_pt != 0)
28855 Vector<GeomObject*> geom_object_vector_pt;
28859 MacroElementNodeUpdateMesh* macro_mesh_pt =
28860 dynamic_cast<MacroElementNodeUpdateMesh*
>(
this);
28861 geom_object_vector_pt = macro_mesh_pt->geom_object_vector_pt();
28864 Vector<double> s_in_macro_node_update_element;
28865 new_el_pt->local_coordinate_of_node(node_index,
28866 s_in_macro_node_update_element);
28869 macro_nod_pt->set_node_update_info(
28870 new_el_pt, s_in_macro_node_update_element, geom_object_vector_pt);
28877 unsigned n_new_val = new_nod_pt->nvalue();
28883 if (!found_node_in_other_shared_boundaries ||
28884 !found_on_haloed_element_with_other_processor)
28886 if (n_val > n_new_val)
28893 BoundaryNodeBase* bnod_pt =
28894 dynamic_cast<BoundaryNodeBase*
>(new_nod_pt);
28899 if (bnod_pt->index_of_first_value_assigned_by_face_element_pt() == 0)
28901 bnod_pt->index_of_first_value_assigned_by_face_element_pt() =
28902 new std::map<unsigned, unsigned>;
28906 std::map<unsigned, unsigned>* map_pt =
28907 bnod_pt->index_of_first_value_assigned_by_face_element_pt();
28911 const unsigned id_face = 0;
28913 std::map<unsigned, unsigned>::const_iterator p =
28914 map_pt->find(id_face);
28917 if (p == map_pt->end())
28921 (*map_pt)[id_face] = n_new_val;
28924 new_nod_pt->resize(n_val);
28933 SolidNode* solid_nod_pt =
dynamic_cast<SolidNode*
>(new_nod_pt);
28934 if (solid_nod_pt != 0)
28936 unsigned n_solid_val = solid_nod_pt->variable_position_pt()->nvalue();
28937 for (
unsigned i_val = 0; i_val < n_solid_val; i_val++)
28939 for (
unsigned t = 0; t < n_prev; t++)
28942 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
28948 if (!found_node_in_other_shared_boundaries ||
28949 !found_on_haloed_element_with_other_processor)
28951 solid_nod_pt->variable_position_pt()->set_value(
28952 t, i_val, read_data);
28958 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28959 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28960 <<
" Number of values solid node: "
28961 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28964 const unsigned nvalues_solid_node =
28965 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28966 Vector<double> values_solid_node(nvalues_solid_node);
28967 for (
unsigned i = 0; i < nvalues_solid_node; i++)
28969 values_solid_node[i] =
28970 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
28977 if (!found_node_in_other_shared_boundaries ||
28978 !found_on_haloed_element_with_other_processor)
28980 unsigned index = 0;
28981 solid_nod_pt->read_values_from_vector(values_solid_node, index);
28988 for (
unsigned i_val = 0; i_val < n_val; i_val++)
28990 for (
unsigned t = 0; t < n_prev; t++)
28993 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
28999 if (!found_node_in_other_shared_boundaries ||
29000 !found_on_haloed_element_with_other_processor)
29002 new_nod_pt->set_value(t, i_val, read_data);
29009 unsigned n_dim = new_nod_pt->ndim();
29010 for (
unsigned idim = 0; idim < n_dim; idim++)
29012 for (
unsigned t = 0; t < n_prev; t++)
29015 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
29021 if (!found_node_in_other_shared_boundaries ||
29022 !found_on_haloed_element_with_other_processor)
29025 new_nod_pt->x(t, idim) = read_data;
29038 if (n_shd_bnd_with_other_procs_have_node > 0 &&
29042 !found_node_in_other_shared_boundaries)
29050 this->update_other_proc_shd_bnd_node_helper(new_nod_pt,
29051 other_proc_shd_bnd_node_pt,
29054 other_shared_boundaries,
29057 node_name_to_global_index,
29058 global_shared_node_pt);
29071 template<
class ELEMENT>
29073 const unsigned& b, Vector<Vector<Node*>>& tmp_segment_nodes)
29076 tmp_segment_nodes.clear();
29079 Vector<FiniteElement*> face_el_pt;
29086 unsigned n_repeated_ele = 0;
29089 const unsigned n_regions = this->nregion();
29092 Vector<std::pair<Node*, Node*>> done_nodes_pt;
29097 for (
unsigned rr = 0; rr < n_regions; rr++)
29099 const unsigned region_id =
29100 static_cast<unsigned>(this->Region_attribute[rr]);
29103 const unsigned nel_in_region =
29104 this->nboundary_element_in_region(b, region_id);
29107 unsigned nel_repeated_in_region = 0;
29111 if (nel_in_region > 0)
29115 bool repeated =
false;
29118 for (
unsigned e = 0; e < nel_in_region; e++)
29121 FiniteElement* bulk_elem_pt =
29122 this->boundary_element_in_region_pt(b, region_id, e);
29124 #ifdef OOMPH_HAS_MPI
29126 if (this->is_mesh_distributed() && bulk_elem_pt->is_halo())
29137 this->face_index_at_boundary_in_region(b, region_id, e);
29142 FiniteElement* tmp_ele_pt =
29143 new DummyFaceElement<ELEMENT>(bulk_elem_pt, face_index);
29146 const unsigned n_nodes = tmp_ele_pt->nnode();
29148 std::pair<Node*, Node*> tmp_pair = std::make_pair(
29149 tmp_ele_pt->node_pt(0), tmp_ele_pt->node_pt(n_nodes - 1));
29151 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
29152 tmp_ele_pt->node_pt(n_nodes - 1), tmp_ele_pt->node_pt(0));
29155 unsigned n_done_nodes = done_nodes_pt.size();
29156 for (
unsigned l = 0; l < n_done_nodes; l++)
29158 if (tmp_pair == done_nodes_pt[l] ||
29159 tmp_pair_inverse == done_nodes_pt[l])
29161 nel_repeated_in_region++;
29172 done_nodes_pt.push_back(tmp_pair);
29174 face_el_pt.push_back(tmp_ele_pt);
29190 nel += nel_in_region;
29193 n_repeated_ele += nel_repeated_in_region;
29204 nel = this->nboundary_element(b);
29211 bool repeated =
false;
29214 for (
unsigned e = 0; e < nel; e++)
29217 FiniteElement* bulk_elem_pt = this->boundary_element_pt(b, e);
29219 #ifdef OOMPH_HAS_MPI
29221 if (this->is_mesh_distributed() && bulk_elem_pt->is_halo())
29231 int face_index = this->face_index_at_boundary(b, e);
29235 FiniteElement* tmp_ele_pt =
29236 new DummyFaceElement<ELEMENT>(bulk_elem_pt, face_index);
29239 const unsigned n_nodes = tmp_ele_pt->nnode();
29241 std::pair<Node*, Node*> tmp_pair = std::make_pair(
29242 tmp_ele_pt->node_pt(0), tmp_ele_pt->node_pt(n_nodes - 1));
29244 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
29245 tmp_ele_pt->node_pt(n_nodes - 1), tmp_ele_pt->node_pt(0));
29248 unsigned n_done_nodes = done_nodes_pt.size();
29249 for (
unsigned l = 0; l < n_done_nodes; l++)
29251 if (tmp_pair == done_nodes_pt[l] ||
29252 tmp_pair_inverse == done_nodes_pt[l])
29265 done_nodes_pt.push_back(tmp_pair);
29267 face_el_pt.push_back(tmp_ele_pt);
29286 nel -= n_repeated_ele;
29289 if (nel != face_el_pt.size())
29291 std::ostringstream error_message;
29293 <<
"The independet counting of face elements (" << nel <<
") for "
29294 <<
"boundary (" << b <<
") is different\n"
29295 <<
"from the real number of face elements in the container ("
29296 << face_el_pt.size() <<
")\n";
29297 throw OomphLibError(
29298 error_message.str(),
29299 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29300 OOMPH_EXCEPTION_LOCATION);
29308 const unsigned nnon_halo_face_elements = nel;
29312 Vector<std::list<FiniteElement*>> segment_sorted_ele_pt;
29316 unsigned nsorted_face_elements = 0;
29320 std::map<FiniteElement*, bool> done_ele;
29325 std::map<FiniteElement*, bool> is_inverted;
29330 while (nsorted_face_elements < nnon_halo_face_elements)
29334 std::list<FiniteElement*> sorted_el_pt;
29338 bool found_initial_face_element =
false;
29341 FiniteElement* ele_face_pt = 0;
29343 unsigned iface = 0;
29344 #ifdef OOMPH_HAS_MPI
29345 if (this->is_mesh_distributed())
29347 for (iface = 0; iface < nel; iface++)
29349 ele_face_pt = face_el_pt[iface];
29351 if (!done_ele[ele_face_pt])
29356 found_initial_face_element =
true;
29359 nsorted_face_elements++;
29363 sorted_el_pt.push_back(ele_face_pt);
29365 done_ele[ele_face_pt] =
true;
29376 ele_face_pt = face_el_pt[0];
29379 found_initial_face_element =
true;
29382 nsorted_face_elements++;
29386 sorted_el_pt.push_back(ele_face_pt);
29388 done_ele[ele_face_pt] =
true;
29389 #ifdef OOMPH_HAS_MPI
29394 if (!found_initial_face_element)
29396 std::ostringstream error_message;
29397 error_message <<
"Could not find an initial face element for the "
29398 "current segment\n";
29399 throw OomphLibError(
29400 error_message.str(),
29401 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29402 OOMPH_EXCEPTION_LOCATION);
29407 const unsigned nnod = ele_face_pt->nnode();
29411 Node* left_node_pt = ele_face_pt->node_pt(0);
29412 Node* right_node_pt = ele_face_pt->node_pt(nnod - 1);
29416 bool face_element_added =
false;
29426 for (
unsigned iiface = iface; iiface < nel; iiface++)
29429 face_element_added =
false;
29432 ele_face_pt = face_el_pt[iiface];
29436 if (!done_ele[ele_face_pt])
29439 Node* local_left_node_pt = ele_face_pt->node_pt(0);
29440 Node* local_right_node_pt = ele_face_pt->node_pt(nnod - 1);
29443 if (left_node_pt == local_right_node_pt)
29445 left_node_pt = local_left_node_pt;
29446 sorted_el_pt.push_front(ele_face_pt);
29447 is_inverted[ele_face_pt] =
false;
29448 face_element_added =
true;
29451 else if (left_node_pt == local_left_node_pt)
29453 left_node_pt = local_right_node_pt;
29454 sorted_el_pt.push_front(ele_face_pt);
29455 is_inverted[ele_face_pt] =
true;
29456 face_element_added =
true;
29459 else if (right_node_pt == local_left_node_pt)
29461 right_node_pt = local_right_node_pt;
29462 sorted_el_pt.push_back(ele_face_pt);
29463 is_inverted[ele_face_pt] =
false;
29464 face_element_added =
true;
29467 else if (right_node_pt == local_right_node_pt)
29469 right_node_pt = local_left_node_pt;
29470 sorted_el_pt.push_back(ele_face_pt);
29471 is_inverted[ele_face_pt] =
true;
29472 face_element_added =
true;
29475 if (face_element_added)
29478 done_ele[ele_face_pt] =
true;
29479 nsorted_face_elements++;
29487 }
while (face_element_added &&
29488 (nsorted_face_elements < nnon_halo_face_elements));
29491 segment_sorted_ele_pt.push_back(sorted_el_pt);
29496 const unsigned nsegments = segment_sorted_ele_pt.size();
29499 if (nnon_halo_face_elements > 0 && nsegments == 0)
29501 std::ostringstream error_message;
29503 <<
"The number of segments is zero, but the number of nonhalo\n"
29504 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
29505 throw OomphLibError(
29506 error_message.str(),
29507 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29508 OOMPH_EXCEPTION_LOCATION);
29517 tmp_segment_nodes.resize(nsegments);
29519 for (
unsigned is = 0; is < nsegments; is++)
29522 if (segment_sorted_ele_pt[is].size() == 0)
29524 std::ostringstream error_message;
29525 error_message <<
"The (" << is <<
")-th segment has no elements\n";
29526 throw OomphLibError(
29527 error_message.str(),
29528 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29529 OOMPH_EXCEPTION_LOCATION);
29534 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
29537 const unsigned nnod = first_ele_pt->nnode();
29540 Node* first_node_pt = first_ele_pt->node_pt(0);
29541 if (is_inverted[first_ele_pt])
29543 first_node_pt = first_ele_pt->node_pt(nnod - 1);
29547 tmp_segment_nodes[is].push_back(first_node_pt);
29550 for (std::list<FiniteElement*>::iterator it =
29551 segment_sorted_ele_pt[is].begin();
29552 it != segment_sorted_ele_pt[is].end();
29556 FiniteElement* ele_pt = *it;
29559 Node* last_node_pt = 0;
29562 if (!is_inverted[ele_pt])
29564 last_node_pt = ele_pt->node_pt(nnod - 1);
29568 last_node_pt = ele_pt->node_pt(0);
29572 tmp_segment_nodes[is].push_back(last_node_pt);
29581 for (
unsigned e = 0; e < nel; e++)
29583 delete face_el_pt[e];
29594 template<
class ELEMENT>
29597 double t_start_overall = TimingHelpers::timer();
29604 Vector<double> target_area(elem_error.size());
29605 double min_angle = compute_area_target(elem_error, target_area);
29610 bool quantised_areas =
true;
29611 if (quantised_areas)
29613 unsigned n = target_area.size();
29614 double total_area = 0;
29620 #ifdef OOMPH_HAS_MPI
29621 if (this->is_mesh_distributed())
29625 double sub_area = 0.0;
29628 for (
unsigned e = 0; e < n; e++)
29631 FiniteElement* ele_pt = this->finite_element_pt(e);
29632 if (!ele_pt->is_halo())
29634 sub_area += ele_pt->size();
29639 OomphCommunicator* comm_pt = this->communicator_pt();
29643 &sub_area, &total_area, 1, MPI_DOUBLE, MPI_SUM, comm_pt->mpi_comm());
29647 for (
unsigned e = 0; e < n; e++)
29649 total_area += this->finite_element_pt(e)->size();
29656 for (
unsigned e = 0; e < n; e++)
29658 total_area += this->finite_element_pt(e)->size();
29662 for (
unsigned e = 0; e < n; e++)
29665 unsigned(ceil(log(target_area[e] / total_area) / log(1.0 / 3.0))) - 1;
29666 double new_target_area = total_area * pow(1.0 / 3.0,
int(level));
29667 target_area[e] = new_target_area;
29677 unsigned n = target_area.size();
29678 double max_area = 0.0;
29679 double min_area = DBL_MAX;
29680 for (
unsigned e = 0; e < n; e++)
29682 if (target_area[e] > max_area) max_area = target_area[e];
29683 if (target_area[e] < min_area) min_area = target_area[e];
29698 oomph_info <<
"Maximum target area: " << max_area << std::endl;
29699 oomph_info <<
"Minimum target area: " << min_area << std::endl;
29700 oomph_info <<
"Number of elements to be refined: " << this->Nrefined
29702 oomph_info <<
"Number of elements to be unrefined: " << this->Nunrefined
29704 oomph_info <<
"Min. angle: " << min_angle << std::endl;
29706 double orig_max_area, orig_min_area;
29707 this->max_and_min_element_size(orig_max_area, orig_min_area);
29708 oomph_info <<
"Max./min. element size in original mesh: " << orig_max_area
29709 <<
" " << orig_min_area << std::endl;
29717 bool check_only =
true;
29718 bool outer_boundary_update_necessary =
false;
29719 bool inner_boundary_update_necessary =
false;
29720 bool inner_open_boundary_update_necessary =
false;
29724 const unsigned nouter = this->Outer_boundary_pt.size();
29726 if (this->is_automatic_creation_of_vertices_on_boundaries_allowed())
29729 for (
unsigned i_outer = 0; i_outer < nouter; i_outer++)
29731 outer_boundary_update_necessary = this->update_polygon_using_face_mesh(
29732 this->Outer_boundary_pt[i_outer], check_only);
29734 if (outer_boundary_update_necessary)
break;
29739 if (!outer_boundary_update_necessary)
29743 const unsigned nhole = this->Internal_polygon_pt.size();
29744 Vector<Vector<double>> internal_point_coord(nhole);
29745 inner_boundary_update_necessary =
29746 this->surface_remesh_for_inner_hole_boundaries(internal_point_coord,
29751 if (!inner_boundary_update_necessary)
29753 const unsigned n_open_polyline = this->Internal_open_curve_pt.size();
29755 for (
unsigned i = 0; i < n_open_polyline; i++)
29757 inner_open_boundary_update_necessary =
29758 this->update_open_curve_using_face_mesh(
29759 this->Internal_open_curve_pt[i], check_only);
29761 if (inner_open_boundary_update_necessary)
break;
29773 #ifdef OOMPH_HAS_MPI
29778 int adapt_this_processor = 0;
29779 if (this->is_mesh_distributed())
29782 if ((Nrefined > 0) || (Nunrefined > max_keep_unrefined()) ||
29783 (min_angle < min_permitted_angle()) ||
29784 (outer_boundary_update_necessary) ||
29785 (inner_boundary_update_necessary) ||
29786 (inner_open_boundary_update_necessary))
29788 adapt_this_processor = 1;
29792 OomphCommunicator* comm_pt = this->communicator_pt();
29795 MPI_Allreduce(&adapt_this_processor,
29800 comm_pt->mpi_comm());
29808 if ((Nrefined > 0) || (Nunrefined > max_keep_unrefined()) ||
29809 (min_angle < min_permitted_angle()) ||
29810 (outer_boundary_update_necessary) ||
29811 (inner_boundary_update_necessary) ||
29812 (inner_open_boundary_update_necessary) || (adapt_all))
29814 if (!((Nrefined > 0) || (Nunrefined > max_keep_unrefined())))
29816 if ((outer_boundary_update_necessary) ||
29817 (inner_boundary_update_necessary) ||
29818 (inner_open_boundary_update_necessary))
29821 <<
"Mesh regeneration triggered by inaccurate interface/surface\n"
29822 <<
"representation; setting Nrefined to number of elements.\n"
29823 <<
"outer_boundary_update_necessary : "
29824 << outer_boundary_update_necessary <<
"\n"
29825 <<
"inner_boundary_update_necessary : "
29826 << inner_boundary_update_necessary <<
"\n"
29827 <<
"inner_open_boundary_update_necessary: "
29828 << inner_open_boundary_update_necessary <<
"\n";
29829 Nrefined = nelement();
29833 oomph_info <<
"Mesh regeneration triggered by min angle criterion;\n"
29834 <<
"setting Nrefined to number of elements.\n";
29835 Nrefined = nelement();
29842 #ifdef OOMPH_HAS_MPI
29843 else if (this->is_mesh_distributed() && adapt_this_processor == 0 &&
29846 oomph_info <<
"Mesh regeneration triggered by (" << adapt_all
29847 <<
") processor(s) "
29848 <<
"that require(s)\n adaptation\n";
29863 add_vertices_for_non_deletion();
29868 #ifdef OOMPH_HAS_MPI
29873 if (this->is_mesh_distributed())
29875 synchronize_shared_boundary_connections();
29888 if (this->is_automatic_creation_of_vertices_on_boundaries_allowed())
29891 unsigned nhole = this->Internal_polygon_pt.size();
29892 Vector<Vector<double>> internal_point_coord(nhole);
29893 this->surface_remesh_for_inner_hole_boundaries(internal_point_coord);
29896 for (
unsigned i_outer = 0; i_outer < nouter; i_outer++)
29898 this->update_polygon_using_face_mesh(
29899 this->Outer_boundary_pt[i_outer]);
29904 unsigned n_open_polyline = this->Internal_open_curve_pt.size();
29905 for (
unsigned i = 0; i < n_open_polyline; i++)
29907 this->update_open_curve_using_face_mesh(
29908 this->Internal_open_curve_pt[i]);
29917 const unsigned ninternal = this->Internal_polygon_pt.size();
29918 for (
unsigned i_internal = 0; i_internal < ninternal; i_internal++)
29920 this->update_polygon_using_elements_area(
29921 this->Internal_polygon_pt[i_internal], target_area);
29926 for (
unsigned i_outer = 0; i_outer < nouter; i_outer++)
29928 this->update_polygon_using_elements_area(
29929 this->Outer_boundary_pt[i_outer], target_area);
29934 const unsigned n_open_polyline = this->Internal_open_curve_pt.size();
29935 for (
unsigned i = 0; i < n_open_polyline; i++)
29937 this->update_open_curve_using_elements_area(
29938 this->Internal_open_curve_pt[i], target_area);
29949 #ifdef OOMPH_HAS_MPI
29951 if (this->is_mesh_distributed())
29954 const unsigned my_rank = this->communicator_pt()->my_rank();
29957 const unsigned n_curves = this->nshared_boundary_curves(my_rank);
29959 for (
unsigned nc = 0; nc < n_curves; nc++)
29962 this->update_shared_curve_using_elements_area(
29963 this->Shared_boundary_polyline_pt[my_rank][nc],
29990 const unsigned n_boundary = this->nboundary();
29992 const double t_start_first_stage_segments_connectivity =
29993 TimingHelpers::timer();
29998 #ifdef OOMPH_HAS_MPI
30001 if (this->is_mesh_distributed())
30003 this->Assigned_segments_initial_zeta_values.clear();
30011 for (
unsigned b = 0; b < n_boundary; ++b)
30016 #ifdef OOMPH_HAS_MPI
30017 if (this->is_mesh_distributed())
30023 this->compute_boundary_segments_connectivity_and_initial_zeta_values(
30032 if (this->boundary_geom_object_pt(b) == 0)
30034 this->
template setup_boundary_coordinates<ELEMENT>(b);
30040 #ifdef OOMPH_HAS_MPI
30041 if (this->is_mesh_distributed())
30046 this->synchronize_boundary_coordinates(b);
30055 const double t_total_first_stage_segments_connectivity =
30056 TimingHelpers::timer() - t_start_first_stage_segments_connectivity;
30066 #ifdef OOMPH_HAS_MPI
30074 Vector<TriangleMeshPolygon*> tmp_outer_polygons_pt;
30079 Vector<TriangleMeshOpenCurve*> tmp_open_curves_pt;
30081 if (this->is_mesh_distributed())
30085 this->create_distributed_domain_representation(tmp_outer_polygons_pt,
30086 tmp_open_curves_pt);
30089 this->create_temporary_boundary_connections(tmp_outer_polygons_pt,
30090 tmp_open_curves_pt);
30104 Vector<TriangleMeshPolyLine*> resume_initial_connection_polyline_pt;
30105 Vector<TriangleMeshPolyLine*> resume_final_connection_polyline_pt;
30106 restore_boundary_connections(resume_initial_connection_polyline_pt,
30107 resume_final_connection_polyline_pt);
30113 unsigned n_region = this->nregion();
30116 for (std::map<
unsigned, Vector<double>>::iterator it =
30117 this->Regions_coordinates.begin();
30118 it != this->Regions_coordinates.end();
30122 Vector<double> centroid(2, 0.0);
30125 unsigned region_id = it->first;
30128 oomph_info <<
"Region " << region_id <<
": " << it->second[0] <<
" "
30129 << it->second[1] <<
" ";
30132 unsigned n_region_element = this->nregion_element(region_id);
30133 if (n_region_element > 0)
30136 FiniteElement*
const elem_pt =
30137 this->region_element_pt(region_id, 0);
30140 for (
unsigned n = 0; n < 3; n++)
30142 Node*
const nod_pt = elem_pt->node_pt(n);
30143 for (
unsigned i = 0; i < 2; i++)
30145 centroid[i] += nod_pt->x(i);
30148 for (
unsigned i = 0; i < 2; i++)
30153 it->second = centroid;
30155 oomph_info <<
" , " << it->second[0] <<
" " << it->second[1]
30170 SolidMesh* solid_mesh_pt =
dynamic_cast<SolidMesh*
>(
this);
30180 Vector<TriangleMeshClosedCurve*> closed_curve_pt;
30181 Vector<TriangleMeshClosedCurve*> hole_pt;
30182 Vector<TriangleMeshOpenCurve*> open_curves_pt;
30184 #ifdef OOMPH_HAS_MPI
30185 if (!this->is_mesh_distributed())
30189 closed_curve_pt.resize(nouter);
30190 for (
unsigned i = 0; i < nouter; i++)
30192 closed_curve_pt[i] = this->Outer_boundary_pt[i];
30196 const unsigned n_holes = this->Internal_polygon_pt.size();
30197 hole_pt.resize(n_holes);
30198 for (
unsigned i = 0; i < n_holes; i++)
30200 hole_pt[i] = this->Internal_polygon_pt[i];
30204 const unsigned n_open_curves = this->Internal_open_curve_pt.size();
30205 open_curves_pt.resize(n_open_curves);
30206 for (
unsigned i = 0; i < n_open_curves; i++)
30208 open_curves_pt[i] = this->Internal_open_curve_pt[i];
30214 #ifdef OOMPH_HAS_MPI
30219 const unsigned n_tmp_outer = tmp_outer_polygons_pt.size();
30220 closed_curve_pt.resize(n_tmp_outer);
30221 for (
unsigned i = 0; i < n_tmp_outer; i++)
30223 closed_curve_pt[i] = tmp_outer_polygons_pt[i];
30227 const unsigned n_open_curves = tmp_open_curves_pt.size();
30228 open_curves_pt.resize(n_open_curves);
30229 for (
unsigned i = 0; i < n_open_curves; i++)
30231 open_curves_pt[i] = tmp_open_curves_pt[i];
30260 this->Extra_holes_coordinates;
30264 this->Regions_coordinates;
30267 if (this->Use_attributes)
30273 if (!this->is_automatic_creation_of_vertices_on_boundaries_allowed())
30275 triangle_mesh_parameters
30281 #ifdef OOMPH_HAS_MPI
30282 if (this->is_mesh_distributed())
30293 const double t_start_building_background_mesh = TimingHelpers::timer();
30295 if (solid_mesh_pt != 0)
30298 triangle_mesh_parameters, this->Time_stepper_pt);
30303 triangle_mesh_parameters, this->Time_stepper_pt);
30306 if (Print_timings_level_adaptation > 2)
30308 oomph_info <<
"CPU for building background mesh: "
30309 << TimingHelpers::timer() - t_start_building_background_mesh
30315 const double this_max_element_size = this->max_element_size();
30316 const double this_min_element_size = this->min_element_size();
30321 const double this_min_permitted_angle = this->min_permitted_angle();
30327 #ifdef OOMPH_HAS_MPI
30331 if (this->is_mesh_distributed())
30335 if (this->nshared_boundary_overlaps_internal_boundary() > 0)
30340 this->shared_boundary_overlaps_internal_boundary();
30345 this->shared_boundaries_ids();
30365 tmp_new_mesh_pt->boundary_geom_object_pt() =
30366 this->boundary_geom_object_pt();
30370 tmp_new_mesh_pt->boundary_coordinate_limits() =
30371 this->boundary_coordinate_limits();
30373 const double t_start_second_stage_segments_connectivity =
30374 TimingHelpers::timer();
30376 for (
unsigned b = 0; b < n_boundary; b++)
30381 #ifdef OOMPH_HAS_MPI
30382 if (this->is_mesh_distributed())
30397 if (tmp_new_mesh_pt->boundary_geom_object_pt(b) != 0)
30399 tmp_new_mesh_pt->template setup_boundary_coordinates<ELEMENT>(b);
30403 const double t_total_second_stage_segments_connectivity =
30404 TimingHelpers::timer() - t_start_second_stage_segments_connectivity;
30406 const double t_start_snap_nodes_bg_mesh = TimingHelpers::timer();
30410 for (
unsigned b = 0; b < n_boundary; b++)
30412 this->snap_nodes_onto_boundary(tmp_new_mesh_pt, b);
30415 const double t_total_snap_nodes_bg_mesh =
30416 TimingHelpers::timer() - t_start_snap_nodes_bg_mesh;
30418 if (Print_timings_level_adaptation > 2)
30420 oomph_info <<
"CPU for snapping nodes onto boundaries "
30421 <<
"(background mesh): " << t_total_snap_nodes_bg_mesh
30426 if (Mesh_update_fct_pt != 0)
30428 Mesh_update_fct_pt(tmp_new_mesh_pt);
30455 TriangulateIO tmp_new_triangulateio =
30456 tmp_new_mesh_pt->triangulateio_representation();
30461 bool use_eulerian_coords =
false;
30462 if (solid_mesh_pt != 0)
30464 use_eulerian_coords =
true;
30468 #ifdef OOMPH_HAS_CGAL
30471 CGALSamplePointContainerParameters cgal_params(
this);
30472 if (use_eulerian_coords)
30474 cgal_params.enable_use_eulerian_coordinates_during_setup();
30476 MeshAsGeomObject* mesh_geom_obj_pt =
new MeshAsGeomObject(&cgal_params);
30481 NonRefineableBinArrayParameters params(
this);
30482 if (use_eulerian_coords)
30484 params.enable_use_eulerian_coordinates_during_setup();
30486 Vector<unsigned> bin_dim(2);
30487 bin_dim[0] = Nbin_x_for_area_transfer;
30488 bin_dim[1] = Nbin_y_for_area_transfer;
30489 params.dimensions_of_bin_array() = bin_dim;
30490 MeshAsGeomObject* mesh_geom_obj_pt =
new MeshAsGeomObject(¶ms);
30496 std::map<GeneralisedElement*, unsigned> element_number;
30497 unsigned nelem = this->nelement();
30498 for (
unsigned e = 0; e < nelem; e++)
30500 element_number[this->element_pt(e)] = e;
30503 #ifndef OOMPH_HAS_CGAL
30508 Vector<double> bin_min_target_area;
30511 NonRefineableBinArray* bin_array_pt =
30512 dynamic_cast<NonRefineableBinArray*
>(
30513 mesh_geom_obj_pt->sample_point_container_pt());
30514 if (bin_array_pt == 0)
30516 throw OomphLibError(
30517 "Sample point container has to be NonRefineableBinArray",
30518 OOMPH_CURRENT_FUNCTION,
30519 OOMPH_EXCEPTION_LOCATION);
30523 unsigned n_bin = 0;
30524 unsigned max_n_entry = 0;
30525 unsigned min_n_entry = UINT_MAX;
30526 unsigned tot_n_entry = 0;
30527 unsigned n_empty = 0;
30528 bin_array_pt->get_fill_stats(
30529 n_bin, max_n_entry, min_n_entry, tot_n_entry, n_empty);
30531 oomph_info <<
"Before bin diffusion:"
30532 <<
" nbin:(" << n_bin <<
")"
30533 <<
" nempty:(" << n_empty <<
")"
30534 <<
" min:(" << min_n_entry <<
")"
30535 <<
" max:(" << max_n_entry <<
")"
30536 <<
" average entries:("
30537 << double(tot_n_entry) / double(n_bin) <<
")" << std::endl;
30541 double t0_bin_diff = TimingHelpers::timer();
30542 oomph_info <<
"Going into diffusion bit...\n";
30543 bin_array_pt->fill_bin_by_diffusion();
30544 oomph_info <<
"Back from diffusion bit...\n";
30545 oomph_info <<
"Time for bin diffusion: "
30546 << TimingHelpers::timer() - t0_bin_diff << std::endl;
30550 unsigned n_bin = 0;
30551 unsigned max_n_entry = 0;
30552 unsigned min_n_entry = UINT_MAX;
30553 unsigned tot_n_entry = 0;
30554 unsigned n_empty = 0;
30555 bin_array_pt->get_fill_stats(
30556 n_bin, max_n_entry, min_n_entry, tot_n_entry, n_empty);
30558 oomph_info <<
"After bin diffusion:"
30559 <<
" nbin:(" << n_bin <<
")"
30560 <<
" nempty:(" << n_empty <<
")"
30561 <<
" min:(" << min_n_entry <<
")"
30562 <<
" max:(" << max_n_entry <<
")"
30563 <<
" average entries:("
30564 << double(tot_n_entry) / double(n_bin) <<
")" << std::endl;
30571 double t_total_map = 0.0;
30574 unsigned counter_map = 0;
30579 const std::map<unsigned,
30580 Vector<std::pair<FiniteElement*, Vector<double>>>>*
30581 bins_pt = bin_array_pt->get_all_bins_content();
30584 const unsigned n_bin = bins_pt->size();
30589 bin_min_target_area.resize(n_bin);
30590 for (
unsigned u = 0; u < n_bin; u++)
30592 bin_min_target_area[u] = 0.0;
30598 Vector<std::pair<FiniteElement*, Vector<double>>>>::const_iterator IT;
30599 for (IT it = bins_pt->begin(); it != bins_pt->end(); it++)
30602 unsigned ib = (*it).first;
30605 const unsigned n_ele_bin = (*it).second.size();
30608 for (
unsigned ee = 0; ee < n_ele_bin; ee++)
30611 GeneralisedElement* ele_pt = (*it).second[ee].first;
30612 double t_map = TimingHelpers::timer();
30613 const unsigned ele_number = element_number[ele_pt];
30614 t_total_map += TimingHelpers::timer() - t_map;
30622 if (bin_min_target_area[ib] != 0)
30624 bin_min_target_area[ib] =
30625 std::min(bin_min_target_area[ib], target_area[ele_number]);
30629 bin_min_target_area[ib] = target_area[ele_number];
30636 oomph_info <<
"CPU for map[counter=" << counter_map
30637 <<
"]: " << t_total_map << std::endl;
30641 const bool output_bins =
false;
30644 unsigned length = bin_min_target_area.size();
30645 for (
unsigned u = 0; u < length; u++)
30647 oomph_info <<
"Bin n" << u
30648 <<
",target area: " << bin_min_target_area[u] << std::endl;
30659 #ifdef OOMPH_HAS_MPI
30661 unsigned n_ele_need_refinement = 0;
30665 double t_total_third_stage_segments_connectivity = 0.0;
30668 double t_total_transfer_target_areas = 0.0;
30671 double t_total_limit_target_areas = 0.0;
30674 double t_total_create_new_adapted_mesh = 0.0;
30677 double t_total_snap_nodes = 0.0;
30680 double t_total_wait_other_processors = 0.0;
30681 double t_iter = TimingHelpers::timer();
30687 double t_start_transfer_target_areas = TimingHelpers::timer();
30688 double t0_loop_int_pts = TimingHelpers::timer();
30694 nelem = tmp_new_mesh_pt->nelement();
30698 Vector<double> new_transferred_target_area(nelem, 0.0);
30699 for (
unsigned e = 0; e < nelem; e++)
30702 dynamic_cast<ELEMENT*
>(tmp_new_mesh_pt->element_pt(e));
30703 unsigned nint = el_pt->integral_pt()->nweight();
30704 for (
unsigned ipt = 0; ipt < nint; ipt++)
30707 Vector<double> s(2);
30708 for (
unsigned i = 0; i < 2; i++)
30710 s[i] = el_pt->integral_pt()->knot(ipt, i);
30713 Vector<double> x(2);
30714 el_pt->interpolated_x(s, x);
30720 GeomObject* geom_obj_pt = 0;
30721 unsigned max_sample_points =
30722 Max_sample_points_for_limited_locate_zeta_during_target_area_transfer;
30723 dynamic_cast<CGALSamplePointContainer*
>(
30724 mesh_geom_obj_pt->sample_point_container_pt())
30725 ->limited_locate_zeta(x, max_sample_points, geom_obj_pt, s);
30727 if (geom_obj_pt == 0)
30729 std::stringstream error_message;
30730 error_message <<
"Limited locate zeta failed for zeta = [ "
30731 << x[0] <<
" " << x[1] <<
" ]. Makes no sense!\n";
30732 throw OomphLibError(error_message.str(),
30733 OOMPH_CURRENT_FUNCTION,
30734 OOMPH_EXCEPTION_LOCATION);
30739 FiniteElement* fe_pt =
dynamic_cast<FiniteElement*
>(geom_obj_pt);
30743 std::stringstream error_message;
30744 error_message <<
"Cast to FE for GeomObject returned by "
30745 "limited locate zeta failed for zeta = [ "
30746 << x[0] <<
" " << x[1] <<
" ]. Makes no sense!\n";
30747 throw OomphLibError(error_message.str(),
30748 OOMPH_CURRENT_FUNCTION,
30749 OOMPH_EXCEPTION_LOCATION);
30756 double tg_area = target_area[element_number[fe_pt]];
30763 if (new_transferred_target_area[e] != 0)
30765 new_transferred_target_area[e] =
30766 std::min(new_transferred_target_area[e], tg_area);
30770 new_transferred_target_area[e] = tg_area;
30780 int bin_number = 0;
30781 bin_array_pt->get_bin(x, bin_number);
30784 if (bin_number < 0)
30787 std::stringstream error_message;
30788 error_message <<
"Very odd -- we're looking for a point[ " << x[0]
30789 <<
" " << x[1] <<
" ] that's not even \n"
30790 <<
"located within the bin boundaries.\n";
30791 throw OomphLibError(error_message.str(),
30792 "RefineableTriangleMesh::adapt()",
30793 OOMPH_EXCEPTION_LOCATION);
30801 if (new_transferred_target_area[e] != 0)
30803 new_transferred_target_area[e] =
30804 std::min(new_transferred_target_area[e],
30805 bin_min_target_area[bin_number]);
30809 new_transferred_target_area[e] =
30810 bin_min_target_area[bin_number];
30822 const bool output_target_areas =
false;
30823 if (output_target_areas)
30825 unsigned length = new_transferred_target_area.size();
30826 for (
unsigned u = 0; u < length; u++)
30828 oomph_info <<
"Element" << u
30829 <<
",target area: " << new_transferred_target_area[u]
30833 oomph_info <<
"Time for loop over integration points in new mesh: "
30834 << TimingHelpers::timer() - t0_loop_int_pts << std::endl;
30866 const double t_sub_total_transfer_target_areas =
30867 TimingHelpers::timer() - t_start_transfer_target_areas;
30869 if (Print_timings_level_adaptation > 2)
30872 const unsigned n_element = this->nelement();
30874 const unsigned n_element_background = tmp_new_mesh_pt->nelement();
30876 oomph_info <<
"CPU for transfer of target areas "
30877 <<
"[n_ele_old_mesh=" << n_element
30878 <<
", n_ele_background_mesh=" << n_element_background
30879 <<
"] (iter " << iter
30880 <<
"): " << t_sub_total_transfer_target_areas << std::endl;
30884 t_total_transfer_target_areas += t_sub_total_transfer_target_areas;
30895 const double t_start_limit_target_areas = TimingHelpers::timer();
30899 #ifdef OOMPH_HAS_MPI
30900 unsigned n_ele_need_refinement_iter = 0;
30912 const unsigned nel_new = tmp_new_mesh_pt->nelement();
30913 Vector<double> new_target_area(nel_new);
30914 for (
unsigned e = 0; e < nel_new; e++)
30917 FiniteElement* f_ele_pt = tmp_new_mesh_pt->finite_element_pt(e);
30920 const double new_area = new_transferred_target_area[e];
30921 if (new_area <= 0.0)
30923 std::ostringstream error_stream;
30925 <<
"This shouldn't happen! Element whose centroid is at "
30926 << (f_ele_pt->node_pt(0)->x(0) + f_ele_pt->node_pt(1)->x(0) +
30927 f_ele_pt->node_pt(2)->x(0)) /
30930 << (f_ele_pt->node_pt(0)->x(1) + f_ele_pt->node_pt(1)->x(1) +
30931 f_ele_pt->node_pt(2)->x(1)) /
30934 <<
" has no target area assigned\n";
30935 throw OomphLibError(error_stream.str(),
30936 OOMPH_CURRENT_FUNCTION,
30937 OOMPH_EXCEPTION_LOCATION);
30943 new_target_area[e] = new_area;
30944 if (new_target_area[e] < f_ele_pt->size() / 3.0)
30946 new_target_area[e] = f_ele_pt->size() / 3.0;
30964 #ifdef OOMPH_HAS_MPI
30966 n_ele_need_refinement_iter++;
30977 const double t_sub_total_limit_target_areas =
30978 TimingHelpers::timer() - t_start_limit_target_areas;
30981 t_total_limit_target_areas += t_sub_total_limit_target_areas;
30983 if (Print_timings_level_adaptation > 2)
30986 const unsigned n_element = this->nelement();
30988 const unsigned n_element_background = tmp_new_mesh_pt->nelement();
30990 oomph_info <<
"CPU for limiting target areas "
30991 <<
"[n_ele_old_mesh=" << n_element
30992 <<
", n_ele_background_mesh=" << n_element_background
30993 <<
"] (iter " << iter
30994 <<
"): " << t_sub_total_limit_target_areas << std::endl;
31000 <<
"All area adjustments accommodated by max. permitted area"
31001 <<
" reduction \n";
31005 oomph_info <<
"NOT all area adjustments accommodated by max. "
31006 <<
"permitted area reduction \n";
31019 const double t_start_create_new_adapted_mesh = TimingHelpers::timer();
31022 if (solid_mesh_pt != 0)
31026 tmp_new_triangulateio,
31027 this->Time_stepper_pt,
31028 this->Use_attributes,
31029 this->Allow_automatic_creation_of_vertices_on_boundaries,
31030 this->communicator_pt());
31037 tmp_new_triangulateio,
31038 this->Time_stepper_pt,
31039 this->Use_attributes,
31040 this->Allow_automatic_creation_of_vertices_on_boundaries,
31041 this->communicator_pt());
31045 const double t_sub_total_create_new_adapted_mesh =
31046 TimingHelpers::timer() - t_start_create_new_adapted_mesh;
31049 t_total_create_new_adapted_mesh += t_sub_total_create_new_adapted_mesh;
31051 if (Print_timings_level_adaptation > 2)
31054 const unsigned n_element_new_adapted_mesh = new_mesh_pt->nelement();
31056 oomph_info <<
"CPU for creation of new adapted mesh "
31057 << t_sub_total_create_new_adapted_mesh
31058 <<
"[nele=" << n_element_new_adapted_mesh <<
"] (iter "
31059 << iter <<
"): " << t_sub_total_create_new_adapted_mesh
31063 #ifdef OOMPH_HAS_MPI
31074 if (this->nshared_boundary_overlaps_internal_boundary() > 0)
31079 this->shared_boundary_overlaps_internal_boundary();
31100 new_mesh_pt->boundary_geom_object_pt() =
31101 this->boundary_geom_object_pt();
31105 new_mesh_pt->boundary_coordinate_limits() =
31106 this->boundary_coordinate_limits();
31108 const double t_start_third_stage_segments_connectivity =
31109 TimingHelpers::timer();
31111 for (
unsigned b = 0; b < n_boundary; b++)
31120 #ifdef OOMPH_HAS_MPI
31121 if (this->is_mesh_distributed())
31136 if (new_mesh_pt->boundary_geom_object_pt(b) != 0)
31138 new_mesh_pt->template setup_boundary_coordinates<ELEMENT>(b);
31142 t_total_third_stage_segments_connectivity +=
31143 TimingHelpers::timer() - t_start_third_stage_segments_connectivity;
31145 const double t_start_snap_nodes_new_mesh = TimingHelpers::timer();
31149 for (
unsigned b = 0; b < n_boundary; b++)
31151 this->snap_nodes_onto_boundary(new_mesh_pt, b);
31154 const double t_sub_total_snap_nodes_new_mesh =
31155 TimingHelpers::timer() - t_start_snap_nodes_new_mesh;
31158 t_total_snap_nodes += t_sub_total_snap_nodes_new_mesh;
31160 if (Print_timings_level_adaptation > 2)
31162 oomph_info <<
"CPU for snapping nodes onto boundaries (new mesh) "
31163 <<
"(iter " << iter
31164 <<
"): " << t_sub_total_snap_nodes_new_mesh << std::endl;
31168 if (Mesh_update_fct_pt != 0)
31170 Mesh_update_fct_pt(new_mesh_pt);
31177 if (
dynamic_cast<GeneralisedTimeStepper*
>(this->Time_stepper_pt))
31179 new_mesh_pt->set_nodal_and_elemental_time_stepper(
31180 this->Time_stepper_pt,
false);
31187 delete tmp_new_mesh_pt;
31189 #ifdef OOMPH_HAS_MPI
31193 if (n_ele_need_refinement_iter == n_ele_need_refinement)
31199 n_ele_need_refinement = n_ele_need_refinement_iter;
31209 #ifdef OOMPH_HAS_MPI
31210 if (this->is_mesh_distributed())
31213 const double t_start_wait_other_processors = TimingHelpers::timer();
31220 unsigned this_processor_requires_another_iteration = 1;
31225 this_processor_requires_another_iteration = 0;
31227 int nproc_not_done = this_processor_requires_another_iteration;
31229 OomphCommunicator* comm_pt = this->communicator_pt();
31232 MPI_Allreduce(&this_processor_requires_another_iteration,
31237 comm_pt->mpi_comm());
31239 if (nproc_not_done > 0)
31242 <<
"At least one processors requires further refinement. "
31243 <<
"Go for another iteration." << std::endl;
31249 const double t_sub_total_wait_other_processors =
31250 TimingHelpers::timer() - t_start_wait_other_processors;
31254 t_total_wait_other_processors += t_sub_total_wait_other_processors;
31256 if (Print_timings_level_adaptation > 2)
31258 oomph_info <<
"CPU for waiting other processors "
31259 <<
"(iter " << iter
31260 <<
"): " << t_sub_total_wait_other_processors
31272 oomph_info <<
"Going for another iteration. Current iteration ("
31273 << iter <<
")" << std::endl;
31276 tmp_new_mesh_pt = new_mesh_pt;
31277 tmp_new_triangulateio = new_mesh_pt->triangulateio_representation();
31284 delete mesh_geom_obj_pt;
31286 oomph_info <<
"CPU for iterative generation of new mesh (TOTAL): "
31287 << TimingHelpers::timer() - t_iter << std::endl;
31289 if (Print_timings_level_adaptation > 1)
31291 oomph_info <<
"-- CPU for creating new adapted meshes (TOTAL): "
31292 << t_total_create_new_adapted_mesh << std::endl;
31294 oomph_info <<
"-- CPU for limiting target areas (TOTAL): "
31295 << t_total_limit_target_areas << std::endl;
31297 oomph_info <<
"-- CPU for transferring target areas (TOTAL): "
31298 << t_total_transfer_target_areas << std::endl;
31300 oomph_info <<
"-- CPU for waiting other processors (TOTAL): "
31301 << t_total_wait_other_processors << std::endl;
31313 if (!Disable_projection)
31316 double tt_start_projection = TimingHelpers::timer();
31319 if (Print_timings_projection)
31322 Multi_domain_functions::Doc_timings =
true;
31323 Multi_domain_functions::Doc_stats =
true;
31324 Multi_domain_functions::Doc_full_stats =
true;
31327 double t_proj = TimingHelpers::timer();
31328 oomph_info <<
"About to begin projection.\n";
31332 ProjectionProblem<ELEMENT>* project_problem_pt =
31333 new ProjectionProblem<ELEMENT>;
31337 #ifdef OOMPH_HAS_MPI
31338 if (this->is_mesh_distributed())
31346 Time* backed_up_time_pt = this->Time_stepper_pt->time_pt();
31349 project_problem_pt->enable_problem_distributed();
31353 project_problem_pt->add_time_stepper_pt(this->Time_stepper_pt);
31356 project_problem_pt->mesh_pt() = new_mesh_pt;
31361 if (!this->use_iterative_solver_for_projection())
31363 project_problem_pt->disable_use_iterative_solver_for_projection();
31367 project_problem_pt->project(
this);
31370 this->Time_stepper_pt->time_pt() = backed_up_time_pt;
31381 project_problem_pt->mesh_pt() = new_mesh_pt;
31387 if (!this->use_iterative_solver_for_projection())
31389 project_problem_pt->disable_use_iterative_solver_for_projection();
31393 project_problem_pt->project(
this);
31397 if (Print_timings_projection)
31400 Multi_domain_functions::Doc_timings =
false;
31401 Multi_domain_functions::Doc_stats =
false;
31402 Multi_domain_functions::Doc_full_stats =
false;
31406 const double tt_projection =
31407 TimingHelpers::timer() - tt_start_projection;
31409 if (Print_timings_level_adaptation > 1)
31412 const unsigned n_element = this->nelement();
31414 const unsigned n_element_new = new_mesh_pt->nelement();
31415 oomph_info <<
"CPU for projection (in mesh adaptation) "
31416 <<
"[n_ele_old_mesh=" << n_element
31417 <<
", n_ele_new_mesh=" << n_element_new
31418 <<
"]: " << tt_projection << std::endl;
31423 #ifdef OOMPH_HAS_MPI
31424 if (this->is_mesh_distributed())
31428 unsigned n_this_element_new = n_element_new;
31429 unsigned n_max_element_new_global = 0;
31431 MPI_Reduce(&n_this_element_new,
31432 &n_max_element_new_global,
31437 this->communicator_pt()->mpi_comm());
31440 double tt_this_projection = tt_projection;
31441 double tt_global_min_projection = 0.0;
31442 double tt_global_max_projection = 0.0;
31445 MPI_Reduce(&tt_this_projection,
31446 &tt_global_min_projection,
31451 this->communicator_pt()->mpi_comm());
31452 MPI_Reduce(&tt_this_projection,
31453 &tt_global_max_projection,
31458 this->communicator_pt()->mpi_comm());
31460 if (this->communicator_pt()->my_rank() == 0)
31462 oomph_info <<
"CPU for projection global (MIN): "
31463 << tt_global_min_projection << std::endl;
31464 oomph_info <<
"CPU for projection global (MAX) "
31465 <<
"[n_max_ele_new_global=" << n_max_element_new_global
31466 <<
"]: " << tt_global_max_projection << std::endl;
31468 std::cerr <<
"CPU for projection global (MIN): "
31469 << tt_global_min_projection << std::endl;
31470 std::cerr <<
"CPU for projection global (MAX): "
31471 <<
"[n_max_ele_new_global=" << n_max_element_new_global
31472 <<
"]: " << tt_global_max_projection << std::endl;
31482 oomph_info <<
"CPU for projection of solution onto new mesh: "
31483 << TimingHelpers::timer() - t_proj << std::endl;
31486 delete project_problem_pt;
31491 oomph_info <<
"Projection disabled! The new mesh will contain zeros"
31499 double t_rest = TimingHelpers::timer();
31502 unsigned nnod = nnode();
31503 for (
unsigned j = nnod; j > 0; j--)
31505 delete Node_pt[j - 1];
31506 Node_pt[j - 1] = 0;
31508 unsigned nel = nelement();
31509 for (
unsigned e = nel; e > 0; e--)
31511 delete Element_pt[e - 1];
31512 Element_pt[e - 1] = 0;
31517 nnod = new_mesh_pt->nnode();
31518 Node_pt.resize(nnod);
31519 nel = new_mesh_pt->nelement();
31520 Element_pt.resize(nel);
31521 for (
unsigned j = 0; j < nnod; j++)
31523 Node_pt[j] = new_mesh_pt->node_pt(j);
31525 for (
unsigned e = 0; e < nel; e++)
31527 Element_pt[e] = new_mesh_pt->element_pt(e);
31532 unsigned nbound = 0;
31534 #ifdef OOMPH_HAS_MPI
31538 if (this->is_mesh_distributed())
31543 nbound = new_mesh_pt->nboundary();
31552 nbound = n_boundary;
31555 Boundary_element_pt.resize(nbound);
31556 Face_index_at_boundary.resize(nbound);
31557 Boundary_node_pt.resize(nbound);
31558 for (
unsigned b = 0; b < nbound; b++)
31560 unsigned nel = new_mesh_pt->nboundary_element(b);
31561 Boundary_element_pt[b].resize(nel);
31562 Face_index_at_boundary[b].resize(nel);
31563 for (
unsigned e = 0; e < nel; e++)
31565 Boundary_element_pt[b][e] = new_mesh_pt->boundary_element_pt(b, e);
31566 Face_index_at_boundary[b][e] =
31567 new_mesh_pt->face_index_at_boundary(b, e);
31569 unsigned nnod = new_mesh_pt->nboundary_node(b);
31570 Boundary_node_pt[b].resize(nnod);
31571 for (
unsigned j = 0; j < nnod; j++)
31573 Boundary_node_pt[b][j] = new_mesh_pt->boundary_node_pt(b, j);
31578 unsigned n_region = new_mesh_pt->nregion();
31583 this->Region_attribute.resize(n_region);
31584 for (
unsigned r = 0; r < n_region; r++)
31586 this->Region_attribute[r] = new_mesh_pt->region_attribute(r);
31588 unsigned r_id =
static_cast<unsigned>(this->Region_attribute[r]);
31590 unsigned n_region_element = new_mesh_pt->nregion_element(r_id);
31591 this->Region_element_pt[r_id].resize(n_region_element);
31592 for (
unsigned e = 0; e < n_region_element; e++)
31594 this->Region_element_pt[r_id][e] =
31595 new_mesh_pt->region_element_pt(r_id, e);
31600 this->Boundary_region_element_pt.resize(nbound);
31601 this->Face_index_region_at_boundary.resize(nbound);
31604 for (
unsigned b = 0; b < nbound; ++b)
31606 for (
unsigned rr = 0; rr < n_region; rr++)
31609 unsigned r =
static_cast<unsigned>(this->Region_attribute[rr]);
31611 unsigned n_boundary_el_in_region =
31612 new_mesh_pt->nboundary_element_in_region(b, r);
31614 if (n_boundary_el_in_region > 0)
31617 this->Boundary_region_element_pt[b][r].resize(
31618 n_boundary_el_in_region);
31619 this->Face_index_region_at_boundary[b][r].resize(
31620 n_boundary_el_in_region);
31623 for (
unsigned e = 0; e < n_boundary_el_in_region; ++e)
31625 this->Boundary_region_element_pt[b][r][e] =
31626 new_mesh_pt->boundary_element_in_region_pt(b, r, e);
31627 this->Face_index_region_at_boundary[b][r][e] =
31628 new_mesh_pt->face_index_at_boundary_in_region(b, r, e);
31641 #ifdef OOMPH_HAS_MPI
31642 if (this->is_mesh_distributed())
31647 if (this->is_mesh_distributed())
31649 this->Halo_node_pt.clear();
31650 this->Root_halo_element_pt.clear();
31652 this->Haloed_node_pt.clear();
31653 this->Root_haloed_element_pt.clear();
31655 this->External_halo_node_pt.clear();
31656 this->External_halo_element_pt.clear();
31658 this->External_haloed_node_pt.clear();
31659 this->External_haloed_element_pt.clear();
31664 this->reset_shared_boundary_elements_and_nodes();
31674 Vector<unsigned> my_rank_shared_boundaries_ids;
31675 this->shared_boundaries_in_this_processor(
31676 my_rank_shared_boundaries_ids);
31679 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
31682 for (
unsigned i = 0; i < nmy_rank_shd_bnd; i++)
31685 const unsigned shd_bnd_id = my_rank_shared_boundaries_ids[i];
31688 this->Boundary_element_pt[shd_bnd_id].clear();
31692 const unsigned tmp_nnodes = this->nshared_boundary_node(shd_bnd_id);
31693 for (
unsigned n = 0; n < tmp_nnodes; n++)
31695 Node* tmp_node_pt = this->boundary_node_pt(shd_bnd_id, n);
31696 tmp_node_pt->remove_from_boundary(shd_bnd_id);
31702 this->set_nboundary(n_boundary);
31706 this->sort_nodes_on_shared_boundaries();
31709 this->reset_halo_haloed_scheme();
31713 for (
unsigned b = 0; b < n_boundary; b++)
31715 if (this->boundary_geom_object_pt(b) != 0)
31717 const unsigned nsegments = new_mesh_pt->nboundary_segment(b);
31718 this->set_nboundary_segment_node(b, nsegments);
31723 resume_boundary_connections(resume_initial_connection_polyline_pt,
31724 resume_final_connection_polyline_pt);
31735 this->snap_nodes_onto_geometric_objects();
31741 TriangleHelper::clear_triangulateio(this->Triangulateio);
31743 this->Triangulateio =
31744 TriangleHelper::deep_copy_of_triangulateio_representation(
31745 new_mesh_pt->triangulateio_representation(), quiet);
31748 new_mesh_pt->flush_element_and_node_storage();
31751 delete new_mesh_pt;
31754 if (Print_timings_level_adaptation > 2)
31758 oomph_info <<
"CPU for segments connectivity (first stage) [sec]: "
31759 << t_total_first_stage_segments_connectivity << std::endl;
31760 oomph_info <<
"CPU for segments connectivity (second stage) [sec]: "
31761 << t_total_second_stage_segments_connectivity << std::endl;
31762 oomph_info <<
"CPU for segments connectivity (third stage) [sec]: "
31763 << t_total_third_stage_segments_connectivity << std::endl;
31766 if (Print_timings_level_adaptation > 1)
31768 const double t_total_segments_connectivity =
31769 t_total_first_stage_segments_connectivity +
31770 t_total_second_stage_segments_connectivity +
31771 t_total_third_stage_segments_connectivity;
31773 oomph_info <<
"CPU for segments connectivity (TOTAL) [sec]: "
31774 << t_total_segments_connectivity << std::endl;
31776 if (Print_timings_level_adaptation > 2)
31779 oomph_info <<
"CPU for snapping nodes onto boundaries "
31780 <<
"(new mesh): " << t_total_snap_nodes << std::endl;
31783 t_total_snap_nodes += t_total_snap_nodes_bg_mesh;
31784 oomph_info <<
"CPU for snapping nodes onto boundaries (TOTAL): "
31785 << t_total_snap_nodes << std::endl;
31788 double max_area = 0.0;
31789 double min_area = 0.0;
31791 this->max_and_min_element_size(max_area, min_area);
31792 oomph_info <<
"Max/min element size in adapted mesh: " << max_area <<
" "
31793 << min_area << std::endl;
31795 oomph_info <<
"CPU time for final bits [sec]: "
31796 << TimingHelpers::timer() - t_rest << std::endl;
31800 oomph_info <<
"Not enough benefit in adaptation.\n";
31805 double CPU_for_adaptation = TimingHelpers::timer() - t_start_overall;
31806 oomph_info <<
"CPU time for adaptation [sec]: " << CPU_for_adaptation
31812 #ifdef OOMPH_HAS_MPI
31813 if (this->is_mesh_distributed())
31816 OomphCommunicator* comm_pt = this->communicator_pt();
31818 const unsigned n_proc = comm_pt->nproc();
31819 if (Print_timings_level_adaptation > 1 && n_proc > 1)
31821 double global_min_CPU_for_adaptation = 0.0;
31822 double global_max_CPU_for_adaptation = 0.0;
31823 double global_average_CPU_for_adaptation = 0.0;
31826 MPI_Reduce(&CPU_for_adaptation,
31827 &global_min_CPU_for_adaptation,
31832 comm_pt->mpi_comm());
31833 MPI_Reduce(&CPU_for_adaptation,
31834 &global_max_CPU_for_adaptation,
31839 comm_pt->mpi_comm());
31840 MPI_Reduce(&CPU_for_adaptation,
31841 &global_average_CPU_for_adaptation,
31846 comm_pt->mpi_comm());
31849 const unsigned my_rank = comm_pt->my_rank();
31852 oomph_info <<
"CPU for adaptation (MIN): "
31853 << global_min_CPU_for_adaptation << std::endl;
31854 oomph_info <<
"CPU for adaptation (MAX): "
31855 << global_max_CPU_for_adaptation << std::endl;
31856 oomph_info <<
"CPU for adaptation (AVERAGE): "
31857 << global_average_CPU_for_adaptation / n_proc << std::endl;
31876 template<
class ELEMENT>
31881 Boundary_connections_pt.clear();
31888 std::set<unsigned> boundary_id_with_connections;
31895 const unsigned n_outer_boundaries = this->Outer_boundary_pt.size();
31898 for (
unsigned i = 0; i < n_outer_boundaries; i++)
31901 TriangleMeshPolygon* tmp_polygon_pt = this->Outer_boundary_pt[i];
31904 const unsigned n_polyline = tmp_polygon_pt->npolyline();
31906 for (
unsigned p = 0; p < n_polyline; p++)
31909 TriangleMeshPolyLine* tmp_polyline_pt = tmp_polygon_pt->polyline_pt(p);
31912 if (tmp_polyline_pt->is_initial_vertex_connected())
31915 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
31919 boundary_id_with_connections.insert(bnd_id);
31922 const unsigned dst_bnd_id =
31923 tmp_polyline_pt->initial_vertex_connected_bnd_id();
31927 boundary_id_with_connections.insert(dst_bnd_id);
31932 if (tmp_polyline_pt->is_final_vertex_connected())
31935 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
31939 boundary_id_with_connections.insert(bnd_id);
31942 const unsigned dst_bnd_id =
31943 tmp_polyline_pt->final_vertex_connected_bnd_id();
31947 boundary_id_with_connections.insert(dst_bnd_id);
31960 const unsigned n_internal_boundaries = this->Internal_polygon_pt.size();
31963 for (
unsigned i = 0; i < n_internal_boundaries; i++)
31966 TriangleMeshPolygon* tmp_polygon_pt = this->Internal_polygon_pt[i];
31969 const unsigned n_polyline = tmp_polygon_pt->npolyline();
31971 for (
unsigned p = 0; p < n_polyline; p++)
31974 TriangleMeshPolyLine* tmp_polyline_pt = tmp_polygon_pt->polyline_pt(p);
31977 if (tmp_polyline_pt->is_initial_vertex_connected())
31980 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
31984 boundary_id_with_connections.insert(bnd_id);
31987 const unsigned dst_bnd_id =
31988 tmp_polyline_pt->initial_vertex_connected_bnd_id();
31992 boundary_id_with_connections.insert(dst_bnd_id);
31997 if (tmp_polyline_pt->is_final_vertex_connected())
32000 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32004 boundary_id_with_connections.insert(bnd_id);
32007 const unsigned dst_bnd_id =
32008 tmp_polyline_pt->final_vertex_connected_bnd_id();
32012 boundary_id_with_connections.insert(dst_bnd_id);
32025 const unsigned n_open_boundaries = this->Internal_open_curve_pt.size();
32028 for (
unsigned i = 0; i < n_open_boundaries; i++)
32031 TriangleMeshOpenCurve* tmp_open_curve_pt =
32032 this->Internal_open_curve_pt[i];
32036 const unsigned n_curve_section = tmp_open_curve_pt->ncurve_section();
32039 for (
unsigned p = 0; p < n_curve_section; p++)
32043 TriangleMeshPolyLine* tmp_polyline_pt =
32044 tmp_open_curve_pt->polyline_pt(p);
32047 if (tmp_polyline_pt->is_initial_vertex_connected())
32050 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32054 boundary_id_with_connections.insert(bnd_id);
32057 const unsigned dst_bnd_id =
32058 tmp_polyline_pt->initial_vertex_connected_bnd_id();
32062 boundary_id_with_connections.insert(dst_bnd_id);
32067 if (tmp_polyline_pt->is_final_vertex_connected())
32070 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32074 boundary_id_with_connections.insert(bnd_id);
32077 const unsigned dst_bnd_id =
32078 tmp_polyline_pt->final_vertex_connected_bnd_id();
32082 boundary_id_with_connections.insert(dst_bnd_id);
32090 #ifdef OOMPH_HAS_MPI
32097 if (this->is_mesh_distributed())
32100 const unsigned my_rank = this->communicator_pt()->my_rank();
32103 const unsigned n_shared_curves = this->nshared_boundary_curves(my_rank);
32106 for (
unsigned i = 0; i < n_shared_curves; i++)
32110 const unsigned n_polyline = this->nshared_boundary_polyline(my_rank, i);
32114 for (
unsigned p = 0; p < n_polyline; p++)
32117 TriangleMeshPolyLine* tmp_polyline_pt =
32118 this->shared_boundary_polyline_pt(my_rank, i, p);
32121 if (tmp_polyline_pt->is_initial_vertex_connected())
32124 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32128 boundary_id_with_connections.insert(bnd_id);
32131 const unsigned dst_bnd_id =
32132 tmp_polyline_pt->initial_vertex_connected_bnd_id();
32136 boundary_id_with_connections.insert(dst_bnd_id);
32141 if (tmp_polyline_pt->is_final_vertex_connected())
32144 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32148 boundary_id_with_connections.insert(bnd_id);
32151 const unsigned dst_bnd_id =
32152 tmp_polyline_pt->final_vertex_connected_bnd_id();
32156 boundary_id_with_connections.insert(dst_bnd_id);
32174 std::map<unsigned, Vector<Vector<Node*>>> bnd_sorted_segment_node_pt;
32177 for (std::set<unsigned>::iterator it = boundary_id_with_connections.begin();
32178 it != boundary_id_with_connections.end();
32182 const unsigned bnd_id = (*it);
32183 #ifdef OOMPH_HAS_MPI
32185 if (this->is_mesh_distributed())
32188 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
32190 if (bnd_id >= init_shd_bnd_id)
32195 Vector<Vector<Node*>> tmp_shared_nodes_pt;
32198 get_shared_boundary_segment_nodes_helper(bnd_id, tmp_shared_nodes_pt);
32201 bnd_sorted_segment_node_pt[bnd_id] = tmp_shared_nodes_pt;
32209 Vector<Vector<Node*>> tmp_boundary_nodes_pt;
32212 get_boundary_segment_nodes_helper(bnd_id, tmp_boundary_nodes_pt);
32215 bnd_sorted_segment_node_pt[bnd_id] = tmp_boundary_nodes_pt;
32226 Vector<Vector<Node*>> tmp_boundary_nodes_pt;
32229 get_boundary_segment_nodes_helper(bnd_id, tmp_boundary_nodes_pt);
32232 bnd_sorted_segment_node_pt[bnd_id] = tmp_boundary_nodes_pt;
32246 for (
unsigned i = 0; i < n_outer_boundaries; i++)
32249 TriangleMeshPolygon* tmp_polygon_pt = this->Outer_boundary_pt[i];
32252 const unsigned n_polyline = tmp_polygon_pt->npolyline();
32254 for (
unsigned p = 0; p < n_polyline; p++)
32257 TriangleMeshPolyLine* tmp_polyline_pt = tmp_polygon_pt->polyline_pt(p);
32260 if (tmp_polyline_pt->is_initial_vertex_connected())
32263 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32266 const unsigned dst_bnd_id =
32267 tmp_polyline_pt->initial_vertex_connected_bnd_id();
32270 const unsigned dst_chunk =
32271 tmp_polyline_pt->initial_vertex_connected_n_chunk();
32274 Vector<Vector<Node*>> src_bnd_node_pt =
32275 bnd_sorted_segment_node_pt[bnd_id];
32278 Vector<Vector<Node*>> dst_bnd_node_pt =
32279 bnd_sorted_segment_node_pt[dst_bnd_id];
32283 add_non_delete_vertices_from_boundary_helper(
32284 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32289 if (tmp_polyline_pt->is_final_vertex_connected())
32292 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32295 const unsigned dst_bnd_id =
32296 tmp_polyline_pt->final_vertex_connected_bnd_id();
32299 const unsigned dst_chunk =
32300 tmp_polyline_pt->final_vertex_connected_n_chunk();
32303 Vector<Vector<Node*>> src_bnd_node_pt =
32304 bnd_sorted_segment_node_pt[bnd_id];
32307 Vector<Vector<Node*>> dst_bnd_node_pt =
32308 bnd_sorted_segment_node_pt[dst_bnd_id];
32312 add_non_delete_vertices_from_boundary_helper(
32313 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32325 for (
unsigned i = 0; i < n_internal_boundaries; i++)
32328 TriangleMeshPolygon* tmp_polygon_pt = this->Internal_polygon_pt[i];
32331 const unsigned n_polyline = tmp_polygon_pt->npolyline();
32333 for (
unsigned p = 0; p < n_polyline; p++)
32336 TriangleMeshPolyLine* tmp_polyline_pt = tmp_polygon_pt->polyline_pt(p);
32339 if (tmp_polyline_pt->is_initial_vertex_connected())
32342 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32345 const unsigned dst_bnd_id =
32346 tmp_polyline_pt->initial_vertex_connected_bnd_id();
32349 const unsigned dst_chunk =
32350 tmp_polyline_pt->initial_vertex_connected_n_chunk();
32353 Vector<Vector<Node*>> src_bnd_node_pt =
32354 bnd_sorted_segment_node_pt[bnd_id];
32357 Vector<Vector<Node*>> dst_bnd_node_pt =
32358 bnd_sorted_segment_node_pt[dst_bnd_id];
32362 add_non_delete_vertices_from_boundary_helper(
32363 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32368 if (tmp_polyline_pt->is_final_vertex_connected())
32371 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32374 const unsigned dst_bnd_id =
32375 tmp_polyline_pt->final_vertex_connected_bnd_id();
32378 const unsigned dst_chunk =
32379 tmp_polyline_pt->final_vertex_connected_n_chunk();
32382 Vector<Vector<Node*>> src_bnd_node_pt =
32383 bnd_sorted_segment_node_pt[bnd_id];
32386 Vector<Vector<Node*>> dst_bnd_node_pt =
32387 bnd_sorted_segment_node_pt[dst_bnd_id];
32391 add_non_delete_vertices_from_boundary_helper(
32392 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32404 for (
unsigned i = 0; i < n_open_boundaries; i++)
32407 TriangleMeshOpenCurve* tmp_open_curve_pt =
32408 this->Internal_open_curve_pt[i];
32412 const unsigned n_curve_section = tmp_open_curve_pt->ncurve_section();
32415 for (
unsigned p = 0; p < n_curve_section; p++)
32419 TriangleMeshPolyLine* tmp_polyline_pt =
32420 tmp_open_curve_pt->polyline_pt(p);
32423 if (tmp_polyline_pt->is_initial_vertex_connected())
32426 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32429 const unsigned dst_bnd_id =
32430 tmp_polyline_pt->initial_vertex_connected_bnd_id();
32433 const unsigned dst_chunk =
32434 tmp_polyline_pt->initial_vertex_connected_n_chunk();
32437 Vector<Vector<Node*>> src_bnd_node_pt =
32438 bnd_sorted_segment_node_pt[bnd_id];
32441 Vector<Vector<Node*>> dst_bnd_node_pt =
32442 bnd_sorted_segment_node_pt[dst_bnd_id];
32446 add_non_delete_vertices_from_boundary_helper(
32447 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32452 if (tmp_polyline_pt->is_final_vertex_connected())
32455 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32458 const unsigned dst_bnd_id =
32459 tmp_polyline_pt->final_vertex_connected_bnd_id();
32462 const unsigned dst_chunk =
32463 tmp_polyline_pt->final_vertex_connected_n_chunk();
32466 Vector<Vector<Node*>> src_bnd_node_pt =
32467 bnd_sorted_segment_node_pt[bnd_id];
32470 Vector<Vector<Node*>> dst_bnd_node_pt =
32471 bnd_sorted_segment_node_pt[dst_bnd_id];
32475 add_non_delete_vertices_from_boundary_helper(
32476 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32484 #ifdef OOMPH_HAS_MPI
32491 if (this->is_mesh_distributed())
32494 const unsigned my_rank = this->communicator_pt()->my_rank();
32497 const unsigned n_shared_curves = this->nshared_boundary_curves(my_rank);
32500 for (
unsigned i = 0; i < n_shared_curves; i++)
32504 const unsigned n_polyline = this->nshared_boundary_polyline(my_rank, i);
32508 for (
unsigned p = 0; p < n_polyline; p++)
32511 TriangleMeshPolyLine* tmp_polyline_pt =
32512 this->shared_boundary_polyline_pt(my_rank, i, p);
32515 if (tmp_polyline_pt->is_initial_vertex_connected())
32518 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32521 const unsigned dst_bnd_id =
32522 tmp_polyline_pt->initial_vertex_connected_bnd_id();
32525 const unsigned dst_chunk =
32526 tmp_polyline_pt->initial_vertex_connected_n_chunk();
32529 Vector<Vector<Node*>> src_bnd_node_pt =
32530 bnd_sorted_segment_node_pt[bnd_id];
32533 Vector<Vector<Node*>> dst_bnd_node_pt =
32534 bnd_sorted_segment_node_pt[dst_bnd_id];
32538 add_non_delete_vertices_from_boundary_helper(
32539 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32544 if (tmp_polyline_pt->is_final_vertex_connected())
32547 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32550 const unsigned dst_bnd_id =
32551 tmp_polyline_pt->final_vertex_connected_bnd_id();
32554 const unsigned dst_chunk =
32555 tmp_polyline_pt->final_vertex_connected_n_chunk();
32558 Vector<Vector<Node*>> src_bnd_node_pt =
32559 bnd_sorted_segment_node_pt[bnd_id];
32562 Vector<Vector<Node*>> dst_bnd_node_pt =
32563 bnd_sorted_segment_node_pt[dst_bnd_id];
32567 add_non_delete_vertices_from_boundary_helper(
32568 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32586 template<
class ELEMENT>
32589 Vector<Vector<Node*>> src_bound_segment_node_pt,
32590 Vector<Vector<Node*>> dst_bound_segment_node_pt,
32591 const unsigned& dst_bnd_id,
32592 const unsigned& dst_bnd_chunk)
32595 const unsigned n_seg = src_bound_segment_node_pt.size();
32597 for (
unsigned iseg = 0; iseg < n_seg; iseg++)
32600 const unsigned nnode = src_bound_segment_node_pt[iseg].size();
32602 Node* left_node_pt = src_bound_segment_node_pt[iseg][0];
32603 Node* right_node_pt = src_bound_segment_node_pt[iseg][nnode - 1];
32606 const unsigned n_dst_seg = dst_bound_segment_node_pt.size();
32608 for (
unsigned jseg = 0; jseg < n_dst_seg; jseg++)
32611 const unsigned n_dst_node = dst_bound_segment_node_pt[jseg].size();
32614 for (
unsigned jnode = 0; jnode < n_dst_node; jnode++)
32618 Node* tmp_node_pt = dst_bound_segment_node_pt[jseg][jnode];
32621 if (tmp_node_pt == left_node_pt)
32624 Vector<double> vertex(2);
32625 vertex[0] = tmp_node_pt->x(0);
32626 vertex[1] = tmp_node_pt->x(1);
32632 Boundary_connections_pt[dst_bnd_id].insert(vertex);
32640 else if (tmp_node_pt == right_node_pt)
32643 Vector<double> vertex(2);
32644 vertex[0] = tmp_node_pt->x(0);
32645 vertex[1] = tmp_node_pt->x(1);
32653 Boundary_connections_pt[dst_bnd_id].insert(vertex);
32667 #ifdef OOMPH_HAS_MPI
32673 template<
class ELEMENT>
32675 ELEMENT>::synchronize_shared_boundary_connections()
32678 const unsigned nproc = this->communicator_pt()->nproc();
32680 const unsigned my_rank = this->communicator_pt()->my_rank();
32683 for (
unsigned jproc = 0; jproc < nproc; jproc++)
32688 const unsigned n_shd_bnd_jproc = this->nshared_boundaries(my_rank, jproc);
32692 if (jproc != my_rank && n_shd_bnd_jproc > 0)
32696 Vector<unsigned> shd_bnd_id_for_non_deletion;
32700 Vector<unsigned> chunk_for_non_deletion;
32704 Vector<unsigned> number_vertices_non_deletion;
32707 Vector<Vector<Vector<double>>> vertices_for_non_deletion;
32711 Vector<unsigned> shd_bnd_ids =
32712 this->shared_boundaries_ids(my_rank, jproc);
32715 const unsigned n_shd_bnd_jproc = shd_bnd_ids.size();
32717 for (
unsigned ishd_bnd = 0; ishd_bnd < n_shd_bnd_jproc; ishd_bnd++)
32720 const unsigned shd_bnd_id = shd_bnd_ids[ishd_bnd];
32722 TriangleMeshPolyLine* shd_polyline_pt =
32723 this->boundary_polyline_pt(shd_bnd_id);
32725 const unsigned chunk = shd_polyline_pt->boundary_chunk();
32728 std::set<Vector<double>> no_delete_vertex;
32731 const bool boundary_receive_connections =
32732 this->boundary_connections(shd_bnd_id, chunk, no_delete_vertex);
32735 const unsigned n_non_delete_vertex = no_delete_vertex.size();
32738 if (boundary_receive_connections && n_non_delete_vertex > 0)
32741 shd_bnd_id_for_non_deletion.push_back(shd_bnd_id);
32743 chunk_for_non_deletion.push_back(chunk);
32745 number_vertices_non_deletion.push_back(n_non_delete_vertex);
32748 Vector<Vector<double>> tmp_vertices;
32751 for (std::set<Vector<double>>::iterator it =
32752 no_delete_vertex.begin();
32753 it != no_delete_vertex.end();
32757 Vector<double> vertex = (*it);
32758 tmp_vertices.push_back(vertex);
32762 vertices_for_non_deletion.push_back(tmp_vertices);
32776 OomphCommunicator* comm_pt = this->communicator_pt();
32780 MPI_Request request;
32786 const unsigned n_shd_bnd_with_non_delete_vertices =
32787 shd_bnd_id_for_non_deletion.size();
32790 const unsigned size_package = 3;
32792 const unsigned n_unsigned_data_to_send =
32793 n_shd_bnd_with_non_delete_vertices * size_package;
32795 Vector<unsigned> flat_package_unsigned_send(n_unsigned_data_to_send);
32796 Vector<double> flat_package_double_send;
32798 Vector<unsigned> flat_package_unsigned_recv;
32799 Vector<double> flat_package_double_recv;
32803 for (
unsigned i = 0; i < n_shd_bnd_with_non_delete_vertices; i++)
32806 flat_package_unsigned_send[j++] = shd_bnd_id_for_non_deletion[i];
32808 flat_package_unsigned_send[j++] = chunk_for_non_deletion[i];
32810 flat_package_unsigned_send[j++] = number_vertices_non_deletion[i];
32812 const unsigned n_vertices_non_deletion =
32813 number_vertices_non_deletion[i];
32816 for (
unsigned h = 0; h < n_vertices_non_deletion; h++)
32818 flat_package_double_send.push_back(
32819 vertices_for_non_deletion[i][h][0]);
32820 flat_package_double_send.push_back(
32821 vertices_for_non_deletion[i][h][1]);
32827 int send_proc = jproc;
32828 int recv_proc = jproc;
32829 unsigned send_count_unsigned_values = n_unsigned_data_to_send;
32830 unsigned send_count_double_values = flat_package_double_send.size();
32835 MPI_Isend(&send_count_unsigned_values,
32840 comm_pt->mpi_comm(),
32843 unsigned receive_count_unsigned_values = 0;
32844 MPI_Recv(&receive_count_unsigned_values,
32849 comm_pt->mpi_comm(),
32852 MPI_Wait(&request, MPI_STATUS_IGNORE);
32855 if (send_count_unsigned_values != 0)
32857 MPI_Isend(&flat_package_unsigned_send[0],
32858 send_count_unsigned_values,
32862 comm_pt->mpi_comm(),
32867 if (receive_count_unsigned_values != 0)
32869 flat_package_unsigned_recv.resize(receive_count_unsigned_values);
32870 MPI_Recv(&flat_package_unsigned_recv[0],
32871 receive_count_unsigned_values,
32875 comm_pt->mpi_comm(),
32881 if (send_count_unsigned_values != 0)
32883 MPI_Wait(&request, MPI_STATUS_IGNORE);
32888 MPI_Isend(&send_count_double_values,
32893 comm_pt->mpi_comm(),
32896 unsigned receive_count_double_values = 0;
32897 MPI_Recv(&receive_count_double_values,
32902 comm_pt->mpi_comm(),
32905 MPI_Wait(&request, MPI_STATUS_IGNORE);
32908 if (send_count_double_values != 0)
32910 MPI_Isend(&flat_package_double_send[0],
32911 send_count_double_values,
32915 comm_pt->mpi_comm(),
32920 if (receive_count_double_values != 0)
32922 flat_package_double_recv.resize(receive_count_double_values);
32923 MPI_Recv(&flat_package_double_recv[0],
32924 receive_count_double_values,
32928 comm_pt->mpi_comm(),
32934 if (send_count_double_values != 0)
32936 MPI_Wait(&request, MPI_STATUS_IGNORE);
32949 Vector<unsigned> recv_shd_bnd_id_for_non_deletion;
32953 Vector<unsigned> recv_chunk_for_non_deletion;
32957 Vector<unsigned> recv_number_vertices_non_deletion;
32960 Vector<Vector<Vector<double>>> recv_vertices_for_non_deletion;
32964 for (
unsigned i = 0; i < receive_count_unsigned_values; i += 3)
32967 const unsigned recv_shd_bnd_id = flat_package_unsigned_recv[i];
32968 recv_shd_bnd_id_for_non_deletion.push_back(recv_shd_bnd_id);
32970 const unsigned recv_chunk = flat_package_unsigned_recv[i + 1];
32971 recv_chunk_for_non_deletion.push_back(recv_chunk);
32973 const unsigned recv_num_vertices = flat_package_unsigned_recv[i + 2];
32974 recv_number_vertices_non_deletion.push_back(recv_num_vertices);
32977 Vector<Vector<double>> temp_recv_vertices;
32979 for (
unsigned h = 0; h < recv_num_vertices; h++)
32981 Vector<double> tmp_vertex(2);
32982 tmp_vertex[0] = flat_package_double_recv[j++];
32983 tmp_vertex[1] = flat_package_double_recv[j++];
32985 temp_recv_vertices.push_back(tmp_vertex);
32989 recv_vertices_for_non_deletion.push_back(temp_recv_vertices);
33004 const unsigned n_recv_shd_bnd_id_for_non_deletion =
33005 recv_shd_bnd_id_for_non_deletion.size();
33008 for (
unsigned i = 0; i < n_recv_shd_bnd_id_for_non_deletion; i++)
33011 const unsigned shd_bnd_id = recv_shd_bnd_id_for_non_deletion[i];
33013 unsigned chunk = recv_chunk_for_non_deletion[i];
33020 const unsigned n_vertices = recv_number_vertices_non_deletion[i];
33022 for (
unsigned h = 0; h < n_vertices; h++)
33025 Vector<double> vertex(2);
33026 vertex[0] = recv_vertices_for_non_deletion[i][h][0];
33027 vertex[1] = recv_vertices_for_non_deletion[i][h][1];
33032 Boundary_connections_pt[shd_bnd_id].insert(vertex);
33049 template<
class ELEMENT>
33051 Vector<TriangleMeshPolygon*>& tmp_outer_polygons_pt,
33052 Vector<TriangleMeshOpenCurve*>& tmp_open_curves_pt)
33055 Vector<TriangleMeshPolyLine*> dummy_resume_initial_connection_polyline_pt;
33056 Vector<TriangleMeshPolyLine*> dummy_resume_final_connection_polyline_pt;
33059 dummy_resume_initial_connection_polyline_pt.clear();
33060 dummy_resume_final_connection_polyline_pt.clear();
33064 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
33082 const unsigned n_outer_boundaries = tmp_outer_polygons_pt.size();
33085 for (
unsigned i = 0; i < n_outer_boundaries; i++)
33088 TriangleMeshPolygon* tmp_polygon_pt = tmp_outer_polygons_pt[i];
33091 const unsigned n_polyline = tmp_polygon_pt->npolyline();
33093 for (
unsigned p = 0; p < n_polyline; p++)
33096 TriangleMeshPolyLine* tmp_polyline_pt = tmp_polygon_pt->polyline_pt(p);
33099 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
33102 if (bnd_id < init_shd_bnd_id)
33105 restore_polyline_connections_helper(
33107 dummy_resume_initial_connection_polyline_pt,
33108 dummy_resume_final_connection_polyline_pt);
33125 const unsigned n_open_boundaries = tmp_open_curves_pt.size();
33128 for (
unsigned i = 0; i < n_open_boundaries; i++)
33131 TriangleMeshOpenCurve* tmp_open_curve_pt = tmp_open_curves_pt[i];
33135 const unsigned n_curve_section = tmp_open_curve_pt->ncurve_section();
33138 for (
unsigned p = 0; p < n_curve_section; p++)
33142 TriangleMeshPolyLine* tmp_polyline_pt =
33143 tmp_open_curve_pt->polyline_pt(p);
33146 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
33149 if (bnd_id < init_shd_bnd_id)
33152 restore_polyline_connections_helper(
33154 dummy_resume_initial_connection_polyline_pt,
33155 dummy_resume_final_connection_polyline_pt);
33174 template<
class ELEMENT>
33176 Vector<TriangleMeshPolyLine*>& resume_initial_connection_polyline_pt,
33177 Vector<TriangleMeshPolyLine*>& resume_final_connection_polyline_pt)
33180 resume_initial_connection_polyline_pt.clear();
33181 resume_final_connection_polyline_pt.clear();
33192 const unsigned n_outer_boundaries = this->Outer_boundary_pt.size();
33195 for (
unsigned i = 0; i < n_outer_boundaries; i++)
33198 TriangleMeshPolygon* tmp_polygon_pt = this->Outer_boundary_pt[i];
33201 const unsigned n_polyline = tmp_polygon_pt->npolyline();
33203 for (
unsigned p = 0; p < n_polyline; p++)
33206 TriangleMeshPolyLine* tmp_polyline_pt = tmp_polygon_pt->polyline_pt(p);
33209 restore_polyline_connections_helper(
33211 resume_initial_connection_polyline_pt,
33212 resume_final_connection_polyline_pt);
33223 const unsigned n_internal_boundaries = this->Internal_polygon_pt.size();
33226 for (
unsigned i = 0; i < n_internal_boundaries; i++)
33229 TriangleMeshPolygon* tmp_polygon_pt = this->Internal_polygon_pt[i];
33232 const unsigned n_polyline = tmp_polygon_pt->npolyline();
33234 for (
unsigned p = 0; p < n_polyline; p++)
33237 TriangleMeshPolyLine* tmp_polyline_pt = tmp_polygon_pt->polyline_pt(p);
33240 restore_polyline_connections_helper(
33242 resume_initial_connection_polyline_pt,
33243 resume_final_connection_polyline_pt);
33254 const unsigned n_open_boundaries = this->Internal_open_curve_pt.size();
33257 for (
unsigned i = 0; i < n_open_boundaries; i++)
33260 TriangleMeshOpenCurve* tmp_open_curve_pt =
33261 this->Internal_open_curve_pt[i];
33265 const unsigned n_curve_section = tmp_open_curve_pt->ncurve_section();
33268 for (
unsigned p = 0; p < n_curve_section; p++)
33272 TriangleMeshPolyLine* tmp_polyline_pt =
33273 tmp_open_curve_pt->polyline_pt(p);
33276 restore_polyline_connections_helper(
33278 resume_initial_connection_polyline_pt,
33279 resume_final_connection_polyline_pt);
33294 template<
class ELEMENT>
33296 TriangleMeshPolyLine* polyline_pt,
33297 Vector<TriangleMeshPolyLine*>& resume_initial_connection_polyline_pt,
33298 Vector<TriangleMeshPolyLine*>& resume_final_connection_polyline_pt)
33305 if (polyline_pt->is_initial_vertex_connected())
33308 TriangleMeshPolyLine* poly_to_connect_pt = 0;
33311 const unsigned dst_bnd_id_initial =
33312 polyline_pt->initial_vertex_connected_bnd_id();
33315 Vector<double> src_vertex_coordinates_initial =
33316 polyline_pt->vertex_coordinate(0);
33320 #ifdef OOMPH_HAS_MPI
33321 if (this->is_mesh_distributed())
33324 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
33326 if (dst_bnd_id_initial >= init_shd_bnd_id)
33329 const unsigned bnd_id = polyline_pt->boundary_id();
33330 std::ostringstream error_message;
33332 <<
"INITIAL VERTEX CONNECTION\n"
33333 <<
"The current original boundary is trying to connect to a\n"
33334 <<
"shared boundary, this is not allowed. In this case the\n"
33335 <<
"shared boundary should be the one that connects with the\n"
33336 <<
"original boundary\n"
33337 <<
"The current original boundary (" << bnd_id <<
") is marked\n"
33338 <<
"to have a connection at the\nINITIAL vertex ("
33339 << src_vertex_coordinates_initial[0] <<
","
33340 << src_vertex_coordinates_initial[1] <<
")\n"
33341 <<
"with the shared boundary (" << dst_bnd_id_initial <<
")\n"
33342 <<
"This is the list of vertices on the shared destination "
33346 TriangleMeshPolyLine* dst_polyline =
33347 this->boundary_polyline_pt(dst_bnd_id_initial);
33349 const unsigned n_vertex_dst_boundary = dst_polyline->nvertex();
33351 for (
unsigned i = 0; i < n_vertex_dst_boundary; i++)
33353 Vector<double> current_vertex = dst_polyline->vertex_coordinate(i);
33354 error_message <<
"Vertex#(i): (" << current_vertex[0] <<
", "
33355 << current_vertex[1] <<
")\n";
33357 throw OomphLibError(
33358 error_message.str(),
33359 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33360 OOMPH_EXCEPTION_LOCATION);
33370 bool found_vertex_on_dst_boundary_initial =
false;
33374 unsigned sub_poly_to_connect = 0;
33377 unsigned n_vertex_connection_initial = 0;
33382 bool connecting_to_an_split_boundary =
false;
33386 bool connecting_to_an_overlaped_boundary =
false;
33388 #ifdef OOMPH_HAS_MPI
33389 if (this->is_mesh_distributed())
33394 if (this->boundary_was_splitted(dst_bnd_id_initial))
33396 connecting_to_an_split_boundary =
true;
33405 if (connecting_to_an_split_boundary)
33409 const unsigned n_sub_poly =
33410 this->nboundary_subpolylines(dst_bnd_id_initial);
33414 for (
unsigned ii = 0; ii < n_sub_poly; ii++)
33416 if (this->boundary_marked_as_shared_boundary(dst_bnd_id_initial,
33421 connecting_to_an_overlaped_boundary =
true;
33432 if (this->boundary_marked_as_shared_boundary(dst_bnd_id_initial, 0))
33435 connecting_to_an_overlaped_boundary =
true;
33446 if (!(connecting_to_an_split_boundary ||
33447 connecting_to_an_overlaped_boundary))
33451 poly_to_connect_pt = this->boundary_polyline_pt(dst_bnd_id_initial);
33461 if (!connecting_to_an_split_boundary)
33465 if (!connecting_to_an_overlaped_boundary)
33469 found_vertex_on_dst_boundary_initial =
33470 this->get_connected_vertex_number_on_destination_polyline(
33471 poly_to_connect_pt,
33472 src_vertex_coordinates_initial,
33473 n_vertex_connection_initial);
33486 #ifdef OOMPH_HAS_MPI
33493 Vector<TriangleMeshPolyLine*> tmp_vector_subpolylines =
33494 this->boundary_subpolylines(dst_bnd_id_initial);
33497 const unsigned nsub_poly = tmp_vector_subpolylines.size();
33499 if (nsub_poly <= 1)
33501 std::ostringstream error_message;
33502 error_message <<
"The boundary (" << dst_bnd_id_initial <<
") was "
33503 <<
"marked to be splitted but\n"
33504 <<
"there are only (" << nsub_poly <<
") polylines to "
33505 <<
"represent it.\n";
33506 throw OomphLibError(
33507 error_message.str(),
33508 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33509 OOMPH_EXCEPTION_LOCATION);
33520 if (!connecting_to_an_overlaped_boundary)
33528 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33531 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33533 found_vertex_on_dst_boundary_initial =
33534 this->get_connected_vertex_number_on_destination_polyline(
33535 poly_to_connect_pt,
33536 src_vertex_coordinates_initial,
33537 n_vertex_connection_initial);
33541 if (found_vertex_on_dst_boundary_initial)
33545 sub_poly_to_connect = isub;
33561 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33565 if (!this->boundary_marked_as_shared_boundary(dst_bnd_id_initial,
33569 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33572 found_vertex_on_dst_boundary_initial =
33573 this->get_connected_vertex_number_on_destination_polyline(
33574 poly_to_connect_pt,
33575 src_vertex_coordinates_initial,
33576 n_vertex_connection_initial);
33579 if (found_vertex_on_dst_boundary_initial)
33583 sub_poly_to_connect = isub;
33598 if (!found_vertex_on_dst_boundary_initial)
33601 #ifdef OOMPH_HAS_MPI
33602 if (this->is_mesh_distributed())
33608 polyline_pt->suspend_initial_vertex_connected();
33612 resume_initial_connection_polyline_pt.push_back(polyline_pt);
33624 const unsigned bnd_id = polyline_pt->boundary_id();
33625 std::ostringstream error_message;
33627 <<
"INITIAL VERTEX CONNECTION\n"
33628 <<
"It was not possible to find the associated "
33629 <<
"vertex number on the destination boundary\n"
33630 <<
"The current boundary (" << bnd_id <<
") is marked to have"
33631 <<
"a connection at the\nINITIAL vertex ("
33632 << src_vertex_coordinates_initial[0] <<
","
33633 << src_vertex_coordinates_initial[1] <<
")\n"
33634 <<
"with boundary (" << dst_bnd_id_initial <<
")\n"
33635 <<
"This is the list of vertices on the destination boundary\n";
33638 TriangleMeshPolyLine* dst_polyline =
33639 this->boundary_polyline_pt(dst_bnd_id_initial);
33641 const unsigned n_vertex_dst_boundary = dst_polyline->nvertex();
33643 for (
unsigned i = 0; i < n_vertex_dst_boundary; i++)
33645 Vector<double> current_vertex = dst_polyline->vertex_coordinate(i);
33646 error_message <<
"Vertex#(i): (" << current_vertex[0] <<
", "
33647 << current_vertex[1] <<
")\n";
33649 throw OomphLibError(
33650 error_message.str(),
33651 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33652 OOMPH_EXCEPTION_LOCATION);
33661 polyline_pt->initial_vertex_connected_n_vertex() =
33662 n_vertex_connection_initial;
33665 polyline_pt->initial_vertex_connected_n_chunk() = sub_poly_to_connect;
33673 if (polyline_pt->is_final_vertex_connected())
33676 TriangleMeshPolyLine* poly_to_connect_pt = 0;
33679 const unsigned dst_bnd_id_final =
33680 polyline_pt->final_vertex_connected_bnd_id();
33683 const unsigned tmp_n_vertices = polyline_pt->nvertex();
33684 Vector<double> src_vertex_coordinates_final =
33685 polyline_pt->vertex_coordinate(tmp_n_vertices - 1);
33690 #ifdef OOMPH_HAS_MPI
33691 if (this->is_mesh_distributed())
33694 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
33696 if (dst_bnd_id_final >= init_shd_bnd_id)
33699 const unsigned bnd_id = polyline_pt->boundary_id();
33700 std::ostringstream error_message;
33702 <<
"FINAL VERTEX CONNECTION\n"
33703 <<
"The current original boundary is trying to connect to a\n"
33704 <<
"shared boundary, this is not allowed. In this case the\n"
33705 <<
"shared boundary should be the one that connects with the\n"
33706 <<
"original boundary\n"
33707 <<
"The current boundary (" << bnd_id <<
") is marked to have "
33708 <<
"a connection at the\nFINAL vertex ("
33709 << src_vertex_coordinates_final[0] <<
","
33710 << src_vertex_coordinates_final[1] <<
")\n"
33711 <<
"with boundary (" << dst_bnd_id_final <<
")\n"
33712 <<
"This is the list of vertices on the destination boundary\n";
33715 TriangleMeshPolyLine* dst_polyline =
33716 this->boundary_polyline_pt(dst_bnd_id_final);
33718 const unsigned n_vertex_dst_boundary = dst_polyline->nvertex();
33720 for (
unsigned i = 0; i < n_vertex_dst_boundary; i++)
33722 Vector<double> current_vertex = dst_polyline->vertex_coordinate(i);
33723 error_message <<
"Vertex#(" << i <<
"): (" << current_vertex[0]
33724 <<
", " << current_vertex[1] <<
")\n";
33726 throw OomphLibError(
33727 error_message.str(),
33728 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33729 OOMPH_EXCEPTION_LOCATION);
33739 bool found_vertex_on_dst_boundary_final =
false;
33743 unsigned sub_poly_to_connect = 0;
33746 unsigned n_vertex_connection_final = 0;
33751 bool connecting_to_an_split_boundary =
false;
33755 bool connecting_to_an_overlaped_boundary =
false;
33757 #ifdef OOMPH_HAS_MPI
33758 if (this->is_mesh_distributed())
33763 if (this->boundary_was_splitted(dst_bnd_id_final))
33765 connecting_to_an_split_boundary =
true;
33774 if (connecting_to_an_split_boundary)
33778 const unsigned n_sub_poly =
33779 this->nboundary_subpolylines(dst_bnd_id_final);
33783 for (
unsigned ii = 0; ii < n_sub_poly; ii++)
33785 if (this->boundary_marked_as_shared_boundary(dst_bnd_id_final, ii))
33789 connecting_to_an_overlaped_boundary =
true;
33800 if (this->boundary_marked_as_shared_boundary(dst_bnd_id_final, 0))
33803 connecting_to_an_overlaped_boundary =
true;
33814 if (!(connecting_to_an_split_boundary ||
33815 connecting_to_an_overlaped_boundary))
33819 poly_to_connect_pt = this->boundary_polyline_pt(dst_bnd_id_final);
33829 if (!connecting_to_an_split_boundary)
33833 if (!connecting_to_an_overlaped_boundary)
33837 found_vertex_on_dst_boundary_final =
33838 this->get_connected_vertex_number_on_destination_polyline(
33839 poly_to_connect_pt,
33840 src_vertex_coordinates_final,
33841 n_vertex_connection_final);
33854 #ifdef OOMPH_HAS_MPI
33861 Vector<TriangleMeshPolyLine*> tmp_vector_subpolylines =
33862 this->boundary_subpolylines(dst_bnd_id_final);
33865 const unsigned nsub_poly = tmp_vector_subpolylines.size();
33867 if (nsub_poly <= 1)
33869 std::ostringstream error_message;
33870 error_message <<
"The boundary (" << dst_bnd_id_final <<
") was "
33871 <<
"marked to be splitted but\n"
33872 <<
"there are only (" << nsub_poly <<
") polylines to "
33873 <<
"represent it.\n";
33874 throw OomphLibError(
33875 error_message.str(),
33876 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33877 OOMPH_EXCEPTION_LOCATION);
33888 if (!connecting_to_an_overlaped_boundary)
33896 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33899 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33901 found_vertex_on_dst_boundary_final =
33902 this->get_connected_vertex_number_on_destination_polyline(
33903 poly_to_connect_pt,
33904 src_vertex_coordinates_final,
33905 n_vertex_connection_final);
33909 if (found_vertex_on_dst_boundary_final)
33913 sub_poly_to_connect = isub;
33929 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33933 if (!this->boundary_marked_as_shared_boundary(dst_bnd_id_final,
33937 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33940 found_vertex_on_dst_boundary_final =
33941 this->get_connected_vertex_number_on_destination_polyline(
33942 poly_to_connect_pt,
33943 src_vertex_coordinates_final,
33944 n_vertex_connection_final);
33947 if (found_vertex_on_dst_boundary_final)
33951 sub_poly_to_connect = isub;
33966 if (!found_vertex_on_dst_boundary_final)
33969 #ifdef OOMPH_HAS_MPI
33970 if (this->is_mesh_distributed())
33976 polyline_pt->suspend_final_vertex_connected();
33980 resume_final_connection_polyline_pt.push_back(polyline_pt);
33992 const unsigned bnd_id = polyline_pt->boundary_id();
33993 std::ostringstream error_message;
33995 <<
"FINAL VERTEX CONNECTION\n"
33996 <<
"It was not possible to find the associated "
33997 <<
"vertex number on the destination boundary\n"
33998 <<
"The current boundary (" << bnd_id <<
") is marked to have "
33999 <<
"a connection at the\nFINAL vertex ("
34000 << src_vertex_coordinates_final[0] <<
","
34001 << src_vertex_coordinates_final[1] <<
")\n"
34002 <<
"with boundary (" << dst_bnd_id_final <<
")\n"
34003 <<
"This is the list of vertices on the destination boundary\n";
34006 TriangleMeshPolyLine* dst_polyline =
34007 this->boundary_polyline_pt(dst_bnd_id_final);
34009 const unsigned n_vertex_dst_boundary = dst_polyline->nvertex();
34011 for (
unsigned i = 0; i < n_vertex_dst_boundary; i++)
34013 Vector<double> current_vertex = dst_polyline->vertex_coordinate(i);
34014 error_message <<
"Vertex#(" << i <<
"): (" << current_vertex[0]
34015 <<
", " << current_vertex[1] <<
")\n";
34017 throw OomphLibError(
34018 error_message.str(),
34019 "RefineableTriangleMesh::restore_polyline_connections_helper()",
34020 OOMPH_EXCEPTION_LOCATION);
34028 polyline_pt->final_vertex_connected_n_vertex() =
34029 n_vertex_connection_final;
34032 polyline_pt->final_vertex_connected_n_chunk() = sub_poly_to_connect;
34047 template<
class ELEMENT>
34049 Vector<TriangleMeshPolyLine*>& resume_initial_connection_polyline_pt,
34050 Vector<TriangleMeshPolyLine*>& resume_final_connection_polyline_pt)
34054 const unsigned n_initial_poly =
34055 resume_initial_connection_polyline_pt.size();
34058 for (
unsigned p = 0; p < n_initial_poly; p++)
34061 TriangleMeshPolyLine* tmp_poly_pt =
34062 resume_initial_connection_polyline_pt[p];
34064 tmp_poly_pt->resume_initial_vertex_connected();
34069 const unsigned n_final_poly = resume_final_connection_polyline_pt.size();
34072 for (
unsigned p = 0; p < n_final_poly; p++)
34075 TriangleMeshPolyLine* tmp_poly_pt =
34076 resume_final_connection_polyline_pt[p];
34078 tmp_poly_pt->resume_final_vertex_connected();
34082 resume_initial_connection_polyline_pt.clear();
34083 resume_final_connection_polyline_pt.clear();
34090 template<
class ELEMENT>
34093 Vector<double>& vertex_coordinates,
34094 const unsigned& dst_bnd_id,
34095 unsigned& vertex_number)
34097 bool found_associated_vertex_number =
false;
34100 TriangleMeshPolyLine* dst_polyline = this->boundary_polyline_pt(dst_bnd_id);
34102 const unsigned n_vertices = dst_polyline->nvertex();
34106 for (
unsigned i = 0; i < n_vertices; i++)
34108 Vector<double> current_vertex = dst_polyline->vertex_coordinate(i);
34110 double error = (vertex_coordinates[0] - current_vertex[0]) *
34111 (vertex_coordinates[0] - current_vertex[0]) +
34112 (vertex_coordinates[1] - current_vertex[1]) *
34113 (vertex_coordinates[1] - current_vertex[1]);
34115 error = sqrt(error);
34117 if (error < ToleranceForVertexMismatchInPolygons::Tolerable_error)
34120 found_associated_vertex_number =
true;
34125 return found_associated_vertex_number;
34137 template<
class ELEMENT>
34139 TriangleMeshPolygon* polygon_pt,
const bool& check_only)
34147 if (this->is_mesh_distributed() && !check_only)
34149 std::stringstream error_message;
34151 <<
"The updating of polygons of a distributed mesh can ONLY be\n"
34152 <<
"performed using the element's area associated to the halo(ed)\n"
34154 <<
"1) Make sure you have enabled the parallel mesh adaptation\n"
34155 <<
"option if you are working with a distributed mesh, OR\n"
34156 <<
"2) Make sure to call the update_..._using_elements_area() methods\n"
34157 <<
"if the mesh is marked as distributed\n\n";
34158 throw OomphLibError(
34159 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
34165 bool unrefinement_was_performed =
false;
34166 bool refinement_was_performed =
false;
34167 bool max_length_applied =
false;
34170 const unsigned n_polyline = polygon_pt->npolyline();
34175 Vector<Mesh*> face_mesh_pt;
34176 get_face_mesh_representation(polygon_pt, face_mesh_pt);
34180 Vector<double> vertex_coord(3);
34181 Vector<double> bound_left(1);
34182 Vector<double> bound_right(1);
34184 for (
unsigned p = 0; p < n_polyline; p++)
34189 std::set<Vector<double>> vertex_nodes;
34192 const unsigned bound = polygon_pt->curve_section_pt(p)->boundary_id();
34195 const unsigned chunk = polygon_pt->curve_section_pt(p)->boundary_chunk();
34198 unsigned n_face_element = face_mesh_pt[p]->nelement();
34199 for (
unsigned e = 0; e < n_face_element; ++e)
34201 FiniteElement* el_pt = face_mesh_pt[p]->finite_element_pt(e);
34203 #ifdef OOMPH_HAS_MPI
34205 if (this->is_mesh_distributed() && el_pt->is_halo())
34211 unsigned n_node = el_pt->nnode();
34216 el_pt->node_pt(0)->get_coordinates_on_boundary(bound, bound_left);
34217 vertex_coord[0] = bound_left[0];
34220 for (
unsigned i = 0; i < 2; i++)
34222 vertex_coord[i + 1] = el_pt->node_pt(0)->x(i);
34224 vertex_nodes.insert(vertex_coord);
34229 el_pt->node_pt(n_node - 1)
34230 ->get_coordinates_on_boundary(bound, bound_right);
34231 vertex_coord[0] = bound_right[0];
34234 for (
unsigned i = 0; i < 2; i++)
34236 vertex_coord[i + 1] = el_pt->node_pt(n_node - 1)->x(i);
34238 vertex_nodes.insert(vertex_coord);
34242 unsigned n_poly_vertex = vertex_nodes.size();
34243 Vector<Vector<double>> tmp_vector_vertex_node(n_poly_vertex);
34244 unsigned count = 0;
34245 for (std::set<Vector<double>>::iterator it = vertex_nodes.begin();
34246 it != vertex_nodes.end();
34249 tmp_vector_vertex_node[count].resize(3);
34250 tmp_vector_vertex_node[count][0] = (*it)[0];
34251 tmp_vector_vertex_node[count][1] = (*it)[1];
34252 tmp_vector_vertex_node[count][2] = (*it)[2];
34257 unsigned n_vertex = tmp_vector_vertex_node.size();
34261 double unrefinement_tolerance =
34262 polygon_pt->polyline_pt(p)->unrefinement_tolerance();
34267 if (unrefinement_tolerance > 0.0 && n_vertex >= 3)
34269 unrefinement_was_performed = unrefine_boundary(bound,
34271 tmp_vector_vertex_node,
34272 unrefinement_tolerance,
34278 if (check_only && unrefinement_was_performed)
34282 for (
unsigned p = 0; p < n_polyline; p++)
34284 face_mesh_pt[p]->flush_node_storage();
34285 delete face_mesh_pt[p];
34294 n_vertex = tmp_vector_vertex_node.size();
34299 double refinement_tolerance =
34300 polygon_pt->polyline_pt(p)->refinement_tolerance();
34301 if (refinement_tolerance > 0.0 && n_vertex >= 2)
34303 refinement_was_performed = refine_boundary(face_mesh_pt[p],
34304 tmp_vector_vertex_node,
34305 refinement_tolerance,
34311 if (check_only && refinement_was_performed)
34315 for (
unsigned p = 0; p < n_polyline; p++)
34317 face_mesh_pt[p]->flush_node_storage();
34318 delete face_mesh_pt[p];
34328 n_vertex = tmp_vector_vertex_node.size();
34333 double maximum_length = polygon_pt->polyline_pt(p)->maximum_length();
34334 if (maximum_length > 0.0 && n_vertex >= 2)
34336 max_length_applied = apply_max_length_constraint(
34337 face_mesh_pt[p], tmp_vector_vertex_node, maximum_length);
34341 if (check_only && max_length_applied)
34345 for (
unsigned p = 0; p < n_polyline; p++)
34347 face_mesh_pt[p]->flush_node_storage();
34348 delete face_mesh_pt[p];
34356 n_vertex = tmp_vector_vertex_node.size();
34357 Vector<Vector<double>> vector_vertex_node(n_vertex);
34359 for (
unsigned i = 0; i < n_vertex; i++)
34361 vector_vertex_node[i].resize(2);
34362 vector_vertex_node[i][0] = tmp_vector_vertex_node[i][1];
34363 vector_vertex_node[i][1] = tmp_vector_vertex_node[i][2];
34366 #ifdef OOMPH_HAS_MPI
34370 if (!this->is_mesh_distributed())
34373 if ((p > 0) && !check_only)
34376 Vector<double> final_vertex_of_previous_segment;
34377 unsigned n_prev_vertex =
34378 polygon_pt->curve_section_pt(p - 1)->nvertex();
34379 final_vertex_of_previous_segment =
34380 polygon_pt->polyline_pt(p - 1)->vertex_coordinate(n_prev_vertex -
34383 unsigned prev_seg_boundary_id =
34384 polygon_pt->curve_section_pt(p - 1)->boundary_id();
34388 double error = 0.0;
34389 for (
unsigned i = 0; i < 2; i++)
34391 const double dist = final_vertex_of_previous_segment[i] -
34392 (*vector_vertex_node.begin())[i];
34393 error += dist * dist;
34395 error = sqrt(error);
34399 if (error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
34403 double rev_error = 0.0;
34404 for (
unsigned i = 0; i < 2; i++)
34406 const double dist = final_vertex_of_previous_segment[i] -
34407 (*--vector_vertex_node.end())[i];
34408 rev_error += dist * dist;
34410 rev_error = sqrt(rev_error);
34413 ToleranceForVertexMismatchInPolygons::Tolerable_error)
34422 Vector<double> initial_vertex_of_previous_segment;
34424 initial_vertex_of_previous_segment =
34425 polygon_pt->polyline_pt(p - 1)->vertex_coordinate(0);
34427 unsigned prev_seg_boundary_id =
34428 polygon_pt->curve_section_pt(p - 1)->boundary_id();
34432 double error = 0.0;
34433 for (
unsigned i = 0; i < 2; i++)
34435 const double dist = initial_vertex_of_previous_segment[i] -
34436 (*vector_vertex_node.begin())[i];
34437 error += dist * dist;
34439 error = sqrt(error);
34444 ToleranceForVertexMismatchInPolygons::Tolerable_error)
34448 double rev_error = 0.0;
34449 for (
unsigned i = 0; i < 2; i++)
34451 const double dist = initial_vertex_of_previous_segment[i] -
34452 (*--vector_vertex_node.end())[i];
34453 rev_error += dist * dist;
34460 ToleranceForVertexMismatchInPolygons::Tolerable_error)
34462 std::ostringstream error_stream;
34464 <<
"The distance between the first node of the current\n"
34465 <<
"line segment (boundary " << bound
34466 <<
") and either end of "
34467 <<
"the previous line segment\n"
34468 <<
"(boundary " << prev_seg_boundary_id
34469 <<
") is bigger than "
34470 <<
"the desired tolerance "
34471 << ToleranceForVertexMismatchInPolygons::Tolerable_error
34473 <<
"This suggests that the polylines defining the "
34475 <<
"representation are not properly ordered.\n"
34476 <<
"Fail on last vertex of polyline: ("
34477 << prev_seg_boundary_id
34478 <<
") and\nfirst vertex of polyline (" << bound
34479 <<
").\nThis should have failed when first trying to "
34480 <<
"construct the\npolygon.\n";
34481 throw OomphLibError(error_stream.str(),
34482 OOMPH_CURRENT_FUNCTION,
34483 OOMPH_EXCEPTION_LOCATION);
34490 std::reverse(vector_vertex_node.begin(),
34491 vector_vertex_node.end());
34493 polygon_pt->polyline_pt(p - 1)->reverse();
34499 polygon_pt->polyline_pt(p - 1)->reverse();
34505 std::ostringstream error_stream;
34507 <<
"The distance between the first node of the current\n"
34508 <<
"line segment (boundary " << bound
34509 <<
") and either end of "
34510 <<
"the previous line segment\n"
34511 <<
"(boundary " << prev_seg_boundary_id
34512 <<
") is bigger than the "
34513 <<
"desired tolerance "
34514 << ToleranceForVertexMismatchInPolygons::Tolerable_error
34516 <<
"This suggests that the polylines defining the polygonal\n"
34517 <<
"representation are not properly ordered.\n"
34518 <<
"Fail on last vertex of polyline: ("
34519 << prev_seg_boundary_id <<
") and\nfirst vertex of polyline ("
34521 <<
"This should have failed when first trying to construct "
34524 throw OomphLibError(error_stream.str(),
34525 OOMPH_CURRENT_FUNCTION,
34526 OOMPH_EXCEPTION_LOCATION);
34532 std::reverse(vector_vertex_node.begin(),
34533 vector_vertex_node.end());
34544 TriangleMeshPolyLine* tmp_polyline_pt =
34545 new TriangleMeshPolyLine(vector_vertex_node, bound);
34549 TriangleMeshCurveSection* tmp_curve_section_pt = tmp_polyline_pt;
34552 tmp_polyline_pt->set_unrefinement_tolerance(unrefinement_tolerance);
34553 tmp_polyline_pt->set_refinement_tolerance(refinement_tolerance);
34556 tmp_polyline_pt->set_maximum_length(maximum_length);
34560 this->copy_connection_information(polygon_pt->polyline_pt(p),
34561 tmp_curve_section_pt);
34566 bool delete_it_on_destructor =
false;
34568 std::set<TriangleMeshCurveSection*>::iterator it =
34569 this->Free_curve_section_pt.find(polygon_pt->curve_section_pt(p));
34571 if (it != this->Free_curve_section_pt.end())
34573 this->Free_curve_section_pt.erase(it);
34574 delete polygon_pt->curve_section_pt(p);
34575 delete_it_on_destructor =
true;
34580 polygon_pt->curve_section_pt(p) = tmp_polyline_pt;
34583 this->Boundary_curve_section_pt[bound] =
34584 polygon_pt->curve_section_pt(p);
34588 this->Free_curve_section_pt.insert(polygon_pt->curve_section_pt(p));
34596 for (
unsigned p = 0; p < n_polyline; p++)
34598 face_mesh_pt[p]->flush_node_storage();
34599 delete face_mesh_pt[p];
34613 return (unrefinement_was_performed || refinement_was_performed ||
34614 max_length_applied);
34627 template<
class ELEMENT>
34629 TriangleMeshOpenCurve* open_polyline_pt,
const bool& check_only)
34637 if (this->is_mesh_distributed() && !check_only)
34639 std::stringstream error_message;
34641 <<
"The updating of open curves of a distributed mesh can ONLY be\n"
34642 <<
"performed using the element's area associated to the halo(ed)\n"
34644 <<
"1) Make sure you have enabled the parallel mesh adaptation\n"
34645 <<
"option if you are working with a distributed mesh, OR\n"
34646 <<
"2) Make sure to call the update_..._using_elements_area() methods\n"
34647 <<
"if the mesh is marked as distributed\n\n";
34648 throw OomphLibError(
34649 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
34655 bool unrefinement_was_performed =
false;
34656 bool refinement_was_performed =
false;
34657 bool max_length_applied =
false;
34660 const unsigned n_polyline = open_polyline_pt->ncurve_section();
34665 Vector<Mesh*> face_mesh_pt;
34666 get_face_mesh_representation(open_polyline_pt, face_mesh_pt);
34670 Vector<double> vertex_coord(3);
34671 Vector<double> bound_left(1);
34672 Vector<double> bound_right(1);
34674 for (
unsigned p = 0; p < n_polyline; p++)
34679 std::set<Vector<double>> vertex_nodes;
34682 const unsigned bound =
34683 open_polyline_pt->curve_section_pt(p)->boundary_id();
34686 const unsigned chunk =
34687 open_polyline_pt->curve_section_pt(p)->boundary_chunk();
34690 unsigned n_face_element = face_mesh_pt[p]->nelement();
34693 for (
unsigned e = 0; e < n_face_element; ++e)
34695 FiniteElement* el_pt = face_mesh_pt[p]->finite_element_pt(e);
34696 unsigned n_node = el_pt->nnode();
34701 el_pt->node_pt(0)->get_coordinates_on_boundary(bound, bound_left);
34702 vertex_coord[0] = bound_left[0];
34705 for (
unsigned i = 0; i < 2; i++)
34707 vertex_coord[i + 1] = el_pt->node_pt(0)->x(i);
34709 vertex_nodes.insert(vertex_coord);
34714 el_pt->node_pt(n_node - 1)
34715 ->get_coordinates_on_boundary(bound, bound_right);
34716 vertex_coord[0] = bound_right[0];
34719 for (
unsigned i = 0; i < 2; i++)
34721 vertex_coord[i + 1] = el_pt->node_pt(n_node - 1)->x(i);
34723 vertex_nodes.insert(vertex_coord);
34727 unsigned n_poly_vertex = vertex_nodes.size();
34728 Vector<Vector<double>> tmp_vector_vertex_node(n_poly_vertex);
34729 unsigned count = 0;
34730 for (std::set<Vector<double>>::iterator it = vertex_nodes.begin();
34731 it != vertex_nodes.end();
34734 tmp_vector_vertex_node[count].resize(3);
34735 tmp_vector_vertex_node[count][0] = (*it)[0];
34736 tmp_vector_vertex_node[count][1] = (*it)[1];
34737 tmp_vector_vertex_node[count][2] = (*it)[2];
34742 unsigned n_vertex = tmp_vector_vertex_node.size();
34746 double unrefinement_tolerance =
34747 open_polyline_pt->polyline_pt(p)->unrefinement_tolerance();
34752 if (unrefinement_tolerance > 0.0 && n_vertex >= 3)
34754 unrefinement_was_performed = unrefine_boundary(bound,
34756 tmp_vector_vertex_node,
34757 unrefinement_tolerance,
34763 if (check_only && unrefinement_was_performed)
34767 for (
unsigned p = 0; p < n_polyline; p++)
34769 face_mesh_pt[p]->flush_node_storage();
34770 delete face_mesh_pt[p];
34780 n_vertex = tmp_vector_vertex_node.size();
34785 double refinement_tolerance =
34786 open_polyline_pt->polyline_pt(p)->refinement_tolerance();
34787 if (refinement_tolerance > 0.0 && n_vertex >= 2)
34789 refinement_was_performed = refine_boundary(face_mesh_pt[p],
34790 tmp_vector_vertex_node,
34791 refinement_tolerance,
34797 if (check_only && refinement_was_performed)
34801 for (
unsigned p = 0; p < n_polyline; p++)
34803 face_mesh_pt[p]->flush_node_storage();
34804 delete face_mesh_pt[p];
34814 n_vertex = tmp_vector_vertex_node.size();
34819 double maximum_length =
34820 open_polyline_pt->polyline_pt(p)->maximum_length();
34821 if (maximum_length > 0.0 && n_vertex >= 2)
34823 bool max_length_applied =
false;
34824 max_length_applied = apply_max_length_constraint(
34825 face_mesh_pt[p], tmp_vector_vertex_node, maximum_length);
34829 if (check_only && max_length_applied)
34833 for (
unsigned p = 0; p < n_polyline; p++)
34835 face_mesh_pt[p]->flush_node_storage();
34836 delete face_mesh_pt[p];
34844 n_vertex = tmp_vector_vertex_node.size();
34845 Vector<Vector<double>> vector_vertex_node(n_vertex);
34847 for (
unsigned i = 0; i < n_vertex; i++)
34849 vector_vertex_node[i].resize(2);
34850 vector_vertex_node[i][0] = tmp_vector_vertex_node[i][1];
34851 vector_vertex_node[i][1] = tmp_vector_vertex_node[i][2];
34854 #ifdef OOMPH_HAS_MPI
34858 if (!this->is_mesh_distributed())
34867 if ((p > 0) && !check_only)
34870 Vector<double> final_vertex_of_previous_segment;
34871 open_polyline_pt->polyline_pt(p - 1)->final_vertex_coordinate(
34872 final_vertex_of_previous_segment);
34874 unsigned prev_seg_boundary_id =
34875 open_polyline_pt->curve_section_pt(p - 1)->boundary_id();
34879 double error = 0.0;
34880 for (
unsigned i = 0; i < 2; i++)
34882 const double dist = final_vertex_of_previous_segment[i] -
34883 (*vector_vertex_node.begin())[i];
34884 error += dist * dist;
34886 error = sqrt(error);
34890 if (error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
34895 for (
unsigned i = 0; i < 2; i++)
34897 const double dist = final_vertex_of_previous_segment[i] -
34898 (*--vector_vertex_node.end())[i];
34899 error += dist * dist;
34901 error = sqrt(error);
34903 if (error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
34914 Vector<double> initial_vertex_of_previous_segment;
34915 open_polyline_pt->polyline_pt(p - 1)->initial_vertex_coordinate(
34916 initial_vertex_of_previous_segment);
34921 for (
unsigned i = 0; i < 2; i++)
34923 const double dist = initial_vertex_of_previous_segment[i] -
34924 (*vector_vertex_node.begin())[i];
34925 error += dist * dist;
34927 error = sqrt(error);
34932 ToleranceForVertexMismatchInPolygons::Tolerable_error)
34937 for (
unsigned i = 0; i < 2; i++)
34939 const double dist = initial_vertex_of_previous_segment[i] -
34940 (*--vector_vertex_node.end())[i];
34941 error += dist * dist;
34943 error = sqrt(error);
34946 ToleranceForVertexMismatchInPolygons::Tolerable_error)
34948 std::ostringstream error_stream;
34950 <<
"The distance between the first node of the current\n"
34951 <<
"line segment (boundary " << bound
34952 <<
") and either end of the previous line segment\n"
34953 <<
"(boundary " << prev_seg_boundary_id
34954 <<
") is bigger than "
34955 <<
"the desired tolerance "
34956 << ToleranceForVertexMismatchInPolygons::Tolerable_error
34958 <<
"This suggests that the polylines defining the open "
34960 <<
"representation are not properly ordered.\n"
34961 <<
"Fail on last vertex of polyline: ("
34962 << prev_seg_boundary_id
34963 <<
") and\nfirst vertex of polyline (" << bound <<
").\n"
34964 <<
"This should have failed when first trying to "
34966 <<
"the open curve.\n";
34967 throw OomphLibError(error_stream.str(),
34968 OOMPH_CURRENT_FUNCTION,
34969 OOMPH_EXCEPTION_LOCATION);
34974 open_polyline_pt->polyline_pt(p - 1)->reverse();
34976 std::reverse(vector_vertex_node.begin(),
34977 vector_vertex_node.end());
34983 open_polyline_pt->polyline_pt(p - 1)->reverse();
34988 std::ostringstream error_stream;
34990 <<
"The distance between the first node of the current\n"
34991 <<
"line segment (boundary " << bound
34992 <<
") and either end of "
34993 <<
"the previous line segment\n"
34994 <<
"(boundary " << prev_seg_boundary_id
34995 <<
") is bigger than the "
34996 <<
"desired tolerance "
34997 << ToleranceForVertexMismatchInPolygons::Tolerable_error
34999 <<
"This suggests that the polylines defining the polygonal\n"
35000 <<
"representation are not properly ordered.\n"
35001 <<
"Fail on last vertex of polyline: ("
35002 << prev_seg_boundary_id <<
") and\nfirst vertex of polyline ("
35004 <<
"This should have failed when first trying to construct "
35007 throw OomphLibError(error_stream.str(),
35008 OOMPH_CURRENT_FUNCTION,
35009 OOMPH_EXCEPTION_LOCATION);
35015 std::reverse(vector_vertex_node.begin(),
35016 vector_vertex_node.end());
35028 TriangleMeshPolyLine* tmp_polyline =
35029 new TriangleMeshPolyLine(vector_vertex_node, bound);
35033 TriangleMeshCurveSection* tmp_curve_section = tmp_polyline;
35036 tmp_polyline->set_unrefinement_tolerance(unrefinement_tolerance);
35037 tmp_polyline->set_refinement_tolerance(refinement_tolerance);
35040 tmp_polyline->set_maximum_length(maximum_length);
35044 this->copy_connection_information(open_polyline_pt->polyline_pt(p),
35045 tmp_curve_section);
35047 std::set<TriangleMeshCurveSection*>::iterator it =
35048 this->Free_curve_section_pt.find(
35049 open_polyline_pt->curve_section_pt(p));
35051 bool delete_it_on_destructor =
false;
35053 if (it != this->Free_curve_section_pt.end())
35056 this->Free_curve_section_pt.erase(it);
35057 delete open_polyline_pt->curve_section_pt(p);
35058 delete_it_on_destructor =
true;
35063 open_polyline_pt->curve_section_pt(p) = tmp_polyline;
35066 this->Boundary_curve_section_pt[bound] =
35067 open_polyline_pt->curve_section_pt(p);
35069 if (delete_it_on_destructor)
35071 this->Free_curve_section_pt.insert(
35072 open_polyline_pt->curve_section_pt(p));
35081 for (
unsigned p = 0; p < n_polyline; p++)
35083 face_mesh_pt[p]->flush_node_storage();
35084 delete face_mesh_pt[p];
35098 return (unrefinement_was_performed || refinement_was_performed ||
35099 max_length_applied);
35111 template<
class ELEMENT>
35115 Vector<Vector<double>>& vector_bnd_vertices,
35116 double& unrefinement_tolerance,
35117 const bool& check_only)
35120 std::set<Vector<double>> no_delete_vertex;
35123 const bool boundary_receive_connections =
35124 this->boundary_connections(b, c, no_delete_vertex);
35128 bool unrefinement_was_performed =
false;
35130 unsigned n_vertex = vector_bnd_vertices.size();
35134 unsigned counter = 1;
35140 for (
unsigned i = 1; i <= n_vertex - 2; i += 2)
35143 double a_x = vector_bnd_vertices[i - 1][1];
35144 double a_y = vector_bnd_vertices[i - 1][2];
35145 double b_x = vector_bnd_vertices[i][1];
35146 double b_y = vector_bnd_vertices[i][2];
35147 double c_x = vector_bnd_vertices[i + 1][1];
35148 double c_y = vector_bnd_vertices[i + 1][2];
35150 double a = b_x - a_x;
35151 double b = b_y - a_y;
35152 double c = c_x - a_x;
35153 double d = c_y - a_y;
35155 double e = a * (a_x + b_x) + b * (a_y + b_y);
35156 double f = c * (a_x + c_x) + d * (a_y + c_y);
35158 double g = 2.0 * (a * (c_y - b_y) - b * (c_x - b_x));
35160 bool do_it =
false;
35161 if (std::fabs(g) < 1.0e-14)
35171 double p_x = (d * e - b * f) / g;
35172 double p_y = (a * f - c * e) / g;
35174 double r = sqrt(pow((a_x - p_x), 2) + pow((a_y - p_y), 2));
35176 double rhalfca_x = 0.5 * (a_x - c_x);
35177 double rhalfca_y = 0.5 * (a_y - c_y);
35179 double halfca_squared = pow(rhalfca_x, 2) + pow(rhalfca_y, 2);
35181 double sticky_out_bit = r - sqrt(std::fabs((r * r) - halfca_squared));
35186 if ((sticky_out_bit / (2.0 * sqrt(halfca_squared))) <
35187 unrefinement_tolerance)
35199 if (do_it && boundary_receive_connections)
35202 for (std::set<Vector<double>>::iterator it = no_delete_vertex.begin();
35203 it != no_delete_vertex.end();
35208 const double x = (*it)[0];
35209 const double y = (*it)[1];
35210 double error = (b_x - x) * (b_x - x) + (b_y - y) * (b_y - y);
35211 error = sqrt(error);
35213 if (error < ToleranceForVertexMismatchInPolygons::Tolerable_error)
35226 vector_bnd_vertices[i].resize(0);
35245 if ((counter) == (n_vertex - 1))
35248 unsigned i = vector_bnd_vertices.size() - 2;
35254 if (vector_bnd_vertices[counter - 2].size() != 0)
35273 double a_x = vector_bnd_vertices[n][1];
35274 double a_y = vector_bnd_vertices[n][2];
35275 double b_x = vector_bnd_vertices[i][1];
35276 double b_y = vector_bnd_vertices[i][2];
35277 double c_x = vector_bnd_vertices[i + 1][1];
35278 double c_y = vector_bnd_vertices[i + 1][2];
35280 double a = b_x - a_x;
35281 double b = b_y - a_y;
35282 double c = c_x - a_x;
35283 double d = c_y - a_y;
35285 double e = a * (a_x + b_x) + b * (a_y + b_y);
35286 double f = c * (a_x + c_x) + d * (a_y + c_y);
35288 double g = 2.0 * (a * (c_y - b_y) - b * (c_x - b_x));
35290 bool do_it =
false;
35291 if (std::fabs(g) < 1.0e-14)
35301 double p_x = (d * e - b * f) / g;
35302 double p_y = (a * f - c * e) / g;
35304 double r = sqrt(pow((a_x - p_x), 2) + pow((a_y - p_y), 2));
35306 double rhalfca_x = 0.5 * (a_x - c_x);
35307 double rhalfca_y = 0.5 * (a_y - c_y);
35309 double halfca_squared = pow(rhalfca_x, 2) + pow(rhalfca_y, 2);
35311 double sticky_out_bit = r - sqrt(std::fabs((r * r) - halfca_squared));
35316 if ((sticky_out_bit / (2.0 * sqrt(halfca_squared))) <
35317 unrefinement_tolerance)
35329 if (do_it && boundary_receive_connections)
35332 for (std::set<Vector<double>>::iterator it = no_delete_vertex.begin();
35333 it != no_delete_vertex.end();
35338 const double x = (*it)[0];
35339 const double y = (*it)[1];
35340 double error = (b_x - x) * (b_x - x) + (b_y - y) * (b_y - y);
35341 error = sqrt(error);
35343 if (error < ToleranceForVertexMismatchInPolygons::Tolerable_error)
35356 vector_bnd_vertices[i].resize(0);
35362 Vector<Vector<double>> compact_vector;
35363 compact_vector.reserve(n_vertex);
35364 for (
unsigned i = 0; i < n_vertex; i++)
35367 if (vector_bnd_vertices[i].size() != 0)
35369 compact_vector.push_back(vector_bnd_vertices[i]);
35374 n_vertex = compact_vector.size();
35380 if (n_vertex != vector_bnd_vertices.size())
35382 unrefinement_was_performed =
true;
35386 vector_bnd_vertices.resize(n_vertex);
35387 for (
unsigned i = 0; i < n_vertex; i++)
35389 vector_bnd_vertices[i].resize(3);
35390 vector_bnd_vertices[i][0] = compact_vector[i][0];
35391 vector_bnd_vertices[i][1] = compact_vector[i][1];
35392 vector_bnd_vertices[i][2] = compact_vector[i][2];
35395 return unrefinement_was_performed;
35406 template<
class ELEMENT>
35408 Mesh* face_mesh_pt,
35409 Vector<Vector<double>>& vector_bnd_vertices,
35410 double& refinement_tolerance,
35411 const bool& check_only)
35415 bool refinement_was_performed =
false;
35419 MeshAsGeomObject* mesh_geom_obj_pt =
new MeshAsGeomObject(face_mesh_pt);
35422 unsigned n_vertex = vector_bnd_vertices.size();
35426 Vector<Vector<double>> extended_vector;
35430 extended_vector.reserve(2 * n_vertex);
35433 for (
unsigned inod = 0; inod < n_vertex - 1; inod++)
35436 double zeta_left = vector_bnd_vertices[inod][0];
35439 Vector<double> R_left(2);
35440 for (
unsigned i = 0; i < 2; i++)
35442 R_left[i] = vector_bnd_vertices[inod][i + 1];
35446 double zeta_right = vector_bnd_vertices[inod + 1][0];
35449 Vector<double> R_right(2);
35450 for (
unsigned i = 0; i < 2; i++)
35452 R_right[i] = vector_bnd_vertices[inod + 1][i + 1];
35456 Vector<double> zeta_mid(1);
35457 zeta_mid[0] = 0.5 * (zeta_left + zeta_right);
35461 Vector<double> R_mid(2);
35462 mesh_geom_obj_pt->position(zeta_mid, R_mid);
35466 Vector<double> R_mid_polygon(2);
35467 for (
unsigned i = 0; i < 2; i++)
35469 R_mid_polygon[i] = 0.5 * (R_right[i] + R_left[i]);
35475 sqrt((R_mid[0] - R_mid_polygon[0]) * (R_mid[0] - R_mid_polygon[0]) +
35476 (R_mid[1] - R_mid_polygon[1]) * (R_mid[1] - R_mid_polygon[1]));
35479 double length = sqrt((R_right[0] - R_left[0]) * (R_right[0] - R_left[0]) +
35480 (R_right[1] - R_left[1]) * (R_right[1] - R_left[1]));
35486 if ((distance / length) > refinement_tolerance)
35492 delete mesh_geom_obj_pt;
35496 Vector<double> new_node(3);
35497 new_node[0] = zeta_mid[0];
35498 new_node[1] = R_mid[0];
35499 new_node[2] = R_mid[1];
35502 extended_vector.push_back(vector_bnd_vertices[inod]);
35505 extended_vector.push_back(new_node);
35511 extended_vector.push_back(vector_bnd_vertices[inod]);
35516 extended_vector.push_back(vector_bnd_vertices[n_vertex - 1]);
35519 n_vertex = extended_vector.size();
35524 if (n_vertex != vector_bnd_vertices.size())
35526 refinement_was_performed =
true;
35530 vector_bnd_vertices.resize(n_vertex);
35531 for (
unsigned i = 0; i < n_vertex; i++)
35533 vector_bnd_vertices[i].resize(3);
35534 vector_bnd_vertices[i][0] = extended_vector[i][0];
35535 vector_bnd_vertices[i][1] = extended_vector[i][1];
35536 vector_bnd_vertices[i][2] = extended_vector[i][2];
35541 delete mesh_geom_obj_pt;
35543 return refinement_was_performed;
35552 template<
class ELEMENT>
35554 Mesh* face_mesh_pt,
35555 Vector<Vector<double>>& vector_bnd_vertices,
35556 double& max_length_constraint)
35560 bool max_length_applied =
false;
35564 MeshAsGeomObject* mesh_geom_obj_pt =
new MeshAsGeomObject(face_mesh_pt);
35567 unsigned n_vertex = vector_bnd_vertices.size();
35571 Vector<Vector<double>> extended_vector;
35574 for (
unsigned inod = 0; inod < n_vertex - 1; inod++)
35577 double zeta_left = vector_bnd_vertices[inod][0];
35580 Vector<double> R_left(2);
35581 for (
unsigned i = 0; i < 2; i++)
35583 R_left[i] = vector_bnd_vertices[inod][i + 1];
35587 double zeta_right = vector_bnd_vertices[inod + 1][0];
35590 Vector<double> R_right(2);
35591 for (
unsigned i = 0; i < 2; i++)
35593 R_right[i] = vector_bnd_vertices[inod + 1][i + 1];
35597 extended_vector.push_back(vector_bnd_vertices[inod]);
35601 double length = std::fabs(zeta_right - zeta_left);
35604 if (length > max_length_constraint)
35606 double n_pts = length / max_length_constraint;
35608 unsigned n_points =
static_cast<unsigned>(n_pts);
35609 double zeta_increment =
35610 (zeta_right - zeta_left) / ((
double)n_points + 1);
35612 Vector<double> zeta(1);
35614 for (
unsigned s = 1; s < n_points + 1; s++)
35617 zeta[0] = zeta_left + zeta_increment * double(s);
35618 Vector<double> vertex(2);
35619 mesh_geom_obj_pt->position(zeta, vertex);
35622 Vector<double> new_node(3);
35623 new_node[0] = zeta[0];
35624 new_node[1] = vertex[0];
35625 new_node[2] = vertex[1];
35628 extended_vector.push_back(new_node);
35634 extended_vector.push_back(vector_bnd_vertices[n_vertex - 1]);
35637 n_vertex = extended_vector.size();
35642 if (n_vertex != vector_bnd_vertices.size())
35644 max_length_applied =
true;
35648 vector_bnd_vertices.resize(n_vertex);
35649 for (
unsigned i = 0; i < n_vertex; i++)
35651 vector_bnd_vertices[i].resize(3);
35652 vector_bnd_vertices[i][0] = extended_vector[i][0];
35653 vector_bnd_vertices[i][1] = extended_vector[i][1];
35654 vector_bnd_vertices[i][2] = extended_vector[i][2];
35659 delete mesh_geom_obj_pt;
35661 return max_length_applied;
35670 template<
class ELEMENT>
35673 Mesh* face_mesh_pt)
35680 this->
template build_face_mesh<ELEMENT, FaceElementAsGeomObject>(
35681 boundary_id, face_mesh_pt);
35684 unsigned n_element = face_mesh_pt->nelement();
35686 for (
unsigned e = 0; e < n_element; e++)
35689 FaceElementAsGeomObject<ELEMENT>* el_pt =
35690 dynamic_cast<FaceElementAsGeomObject<ELEMENT>*
>(
35691 face_mesh_pt->element_pt(e));
35694 el_pt->set_boundary_number_in_bulk_mesh(boundary_id);
35703 template<
class ELEMENT>
35705 const unsigned& boundary_id,
35706 Mesh* face_mesh_pt,
35707 std::map<FiniteElement*, bool>& is_inverted,
35708 bool& inverted_face_mesh)
35710 Mesh* tmp_unsorted_face_mesh_pt =
new Mesh();
35713 create_unsorted_face_mesh_representation(boundary_id,
35714 tmp_unsorted_face_mesh_pt);
35724 std::list<FiniteElement*> sorted_el_pt;
35725 FiniteElement* el_pt = tmp_unsorted_face_mesh_pt->finite_element_pt(0);
35726 sorted_el_pt.push_back(el_pt);
35729 unsigned nnod = el_pt->nnode();
35732 unsigned count_done = 0;
35735 unsigned n_face_element = tmp_unsorted_face_mesh_pt->nelement();
35738 std::map<FiniteElement*, bool> done_el;
35740 is_inverted.clear();
35743 for (
unsigned ee = 1; ee < n_face_element; ee++)
35747 for (
unsigned e = 1; e < n_face_element; e++)
35750 el_pt = tmp_unsorted_face_mesh_pt->finite_element_pt(e);
35753 if (!done_el[el_pt])
35756 FiniteElement* first_el_pt = (*sorted_el_pt.begin());
35757 std::list<FiniteElement*>::iterator it = sorted_el_pt.end();
35759 FiniteElement* last_el_pt = *it;
35762 Node* left_node_pt = first_el_pt->node_pt(0);
35763 if (is_inverted[first_el_pt])
35765 left_node_pt = first_el_pt->node_pt(nnod - 1);
35767 Node* right_node_pt = last_el_pt->node_pt(nnod - 1);
35768 if (is_inverted[last_el_pt])
35770 right_node_pt = last_el_pt->node_pt(0);
35774 if (left_node_pt == el_pt->node_pt(nnod - 1))
35776 sorted_el_pt.push_front(el_pt);
35777 done_el[el_pt] =
true;
35779 is_inverted[el_pt] =
false;
35783 else if (left_node_pt == el_pt->node_pt(0))
35785 sorted_el_pt.push_front(el_pt);
35786 done_el[el_pt] =
true;
35788 is_inverted[el_pt] =
true;
35792 else if (right_node_pt == el_pt->node_pt(0))
35794 sorted_el_pt.push_back(el_pt);
35795 done_el[el_pt] =
true;
35797 is_inverted[el_pt] =
false;
35801 else if (right_node_pt == el_pt->node_pt(nnod - 1))
35803 sorted_el_pt.push_back(el_pt);
35804 done_el[el_pt] =
true;
35806 is_inverted[el_pt] =
true;
35809 if (done_el[el_pt])
35818 if (count_done != (n_face_element - 1))
35820 std::ostringstream error_message;
35821 error_message <<
"When ordering FaceElements on "
35822 <<
"boundary " << boundary_id <<
" only managed to order \n"
35823 << count_done <<
" of " << n_face_element
35824 <<
" face elements.\n"
35826 throw OomphLibError(
35827 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
35834 for (std::list<FiniteElement*>::iterator it = sorted_el_pt.begin();
35835 it != sorted_el_pt.end();
35839 FiniteElement* el_pt = *it;
35842 face_mesh_pt->add_element_pt(el_pt);
35852 TriangleMeshPolyLine* bnd_polyline =
35853 this->Boundary_curve_section_pt[boundary_id];
35856 Vector<double> first_vertex = bnd_polyline->vertex_coordinate(0);
35860 FiniteElement* first_el_pt = face_mesh_pt->finite_element_pt(0);
35863 unsigned n_node = first_el_pt->nnode();
35866 Node* first_node_pt = first_el_pt->node_pt(0);
35867 if (is_inverted[first_el_pt])
35869 first_node_pt = first_el_pt->node_pt(n_node - 1);
35872 double error = (first_node_pt->x(0) - first_vertex[0]) *
35873 (first_node_pt->x(0) - first_vertex[0]) +
35874 (first_node_pt->x(1) - first_vertex[1]) *
35875 (first_node_pt->x(1) - first_vertex[1]);
35877 error = sqrt(error);
35879 if (error < ToleranceForVertexMismatchInPolygons::Tolerable_error)
35881 inverted_face_mesh =
false;
35885 inverted_face_mesh =
true;
35894 template<
class ELEMENT>
35896 TriangleMeshPolygon* polygon_pt, Vector<Mesh*>& face_mesh_pt)
35899 unsigned n_polyline = polygon_pt->npolyline();
35900 face_mesh_pt.resize(n_polyline);
35906 bool eligible_for_segment_redistribution =
true;
35909 for (
unsigned p = 0; p < n_polyline; p++)
35912 unsigned bound = polygon_pt->polyline_pt(p)->boundary_id();
35916 GeomObject*
const geom_object_pt = this->boundary_geom_object_pt(bound);
35917 if (geom_object_pt != 0)
35919 eligible_for_segment_redistribution =
false;
35922 face_mesh_pt[p] =
new Mesh();
35923 create_unsorted_face_mesh_representation(bound, face_mesh_pt[p]);
35926 if (!polygon_pt->is_redistribution_of_segments_between_polylines_enabled())
35932 if (this->nregion() > 1)
35934 std::ostringstream warn_message;
35936 <<
"Can't currently re-distribute segments between polylines if there\n"
35937 <<
"are multiple regions; returning..." << std::endl;
35938 OomphLibWarning(warn_message.str(),
35939 "RefineableTriangleMesh::get_face_mesh_representation()",
35940 OOMPH_EXCEPTION_LOCATION);
35945 if (!eligible_for_segment_redistribution)
35947 std::ostringstream warn_message;
35949 <<
"Over-ruling re-distribution of segments between polylines\n"
35950 <<
"because at least one boundary is associated with a GeomObject."
35951 <<
"Returning..." << std::endl;
35952 OomphLibWarning(warn_message.str(),
35953 "RefineableTriangleMesh::get_face_mesh_representation()",
35954 OOMPH_EXCEPTION_LOCATION);
35959 Vector<Mesh*> ordered_face_mesh_pt(n_polyline);
35962 double s_total = 0.0;
35966 Vector<Node*> first_polyline_node_pt(n_polyline);
35967 Vector<Node*> last_polyline_node_pt(n_polyline);
35968 std::vector<bool> is_reversed(n_polyline,
false);
35971 for (
unsigned p = 0; p < n_polyline; p++)
35977 std::list<FiniteElement*> ordered_el_pt;
35978 FiniteElement* el_pt = face_mesh_pt[p]->finite_element_pt(0);
35979 ordered_el_pt.push_back(el_pt);
35982 unsigned nnod = el_pt->nnode();
35985 first_polyline_node_pt[p] = el_pt->node_pt(0);
35986 last_polyline_node_pt[p] = el_pt->node_pt(nnod - 1);
35989 unsigned count_done = 0;
35992 unsigned n_face_element = face_mesh_pt[p]->nelement();
35995 unsigned bound = polygon_pt->polyline_pt(p)->boundary_id();
35998 std::map<FiniteElement*, bool> done_el;
36001 std::map<FiniteElement*, bool> is_inverted;
36004 for (
unsigned ee = 1; ee < n_face_element; ee++)
36008 for (
unsigned e = 1; e < n_face_element; e++)
36011 el_pt = face_mesh_pt[p]->finite_element_pt(e);
36014 if (!done_el[el_pt])
36017 FiniteElement* first_el_pt = (*ordered_el_pt.begin());
36018 std::list<FiniteElement*>::iterator it = ordered_el_pt.end();
36020 FiniteElement* last_el_pt = *it;
36023 Node* left_node_pt = first_el_pt->node_pt(0);
36024 if (is_inverted[first_el_pt])
36026 left_node_pt = first_el_pt->node_pt(nnod - 1);
36028 Node* right_node_pt = last_el_pt->node_pt(nnod - 1);
36029 if (is_inverted[last_el_pt])
36031 right_node_pt = last_el_pt->node_pt(0);
36035 if (left_node_pt == el_pt->node_pt(nnod - 1))
36037 ordered_el_pt.push_front(el_pt);
36038 done_el[el_pt] =
true;
36040 is_inverted[el_pt] =
false;
36041 first_polyline_node_pt[p] = el_pt->node_pt(0);
36045 else if (left_node_pt == el_pt->node_pt(0))
36047 ordered_el_pt.push_front(el_pt);
36048 done_el[el_pt] =
true;
36050 is_inverted[el_pt] =
true;
36051 first_polyline_node_pt[p] = el_pt->node_pt(nnod - 1);
36055 else if (right_node_pt == el_pt->node_pt(0))
36057 ordered_el_pt.push_back(el_pt);
36058 done_el[el_pt] =
true;
36060 is_inverted[el_pt] =
false;
36061 last_polyline_node_pt[p] = el_pt->node_pt(nnod - 1);
36065 else if (right_node_pt == el_pt->node_pt(nnod - 1))
36067 ordered_el_pt.push_back(el_pt);
36068 done_el[el_pt] =
true;
36070 is_inverted[el_pt] =
true;
36071 last_polyline_node_pt[p] = el_pt->node_pt(0);
36074 if (done_el[el_pt])
36083 if (count_done != (n_face_element - 1))
36085 std::ostringstream error_message;
36086 error_message <<
"When ordering FaceElements on "
36087 <<
"boundary " << bound <<
" only managed to order \n"
36088 << count_done <<
" of " << n_face_element
36089 <<
" face elements.\n"
36091 throw OomphLibError(error_message.str(),
36092 OOMPH_CURRENT_FUNCTION,
36093 OOMPH_EXCEPTION_LOCATION);
36097 ordered_face_mesh_pt[p] =
new Mesh;
36100 for (std::list<FiniteElement*>::iterator it = ordered_el_pt.begin();
36101 it != ordered_el_pt.end();
36105 FiniteElement* el_pt = *it;
36108 ordered_face_mesh_pt[p]->add_element_pt(el_pt);
36112 for (
unsigned e = 0; e < n_face_element; ++e)
36114 FiniteElement* el_pt = ordered_face_mesh_pt[p]->finite_element_pt(e);
36115 unsigned n_node = el_pt->nnode();
36116 double element_length_squared = 0.0;
36117 for (
unsigned i = 0; i < 2; i++)
36119 element_length_squared +=
36120 pow(el_pt->node_pt(n_node - 1)->x(i) - el_pt->node_pt(0)->x(i), 2);
36124 double element_length = sqrt(element_length_squared);
36127 s_total += element_length;
36131 face_mesh_pt[p]->flush_element_and_node_storage();
36135 if ((last_polyline_node_pt[0] == first_polyline_node_pt[1]) ||
36136 (last_polyline_node_pt[0] == last_polyline_node_pt[1]))
36138 is_reversed[0] =
false;
36140 else if ((first_polyline_node_pt[0] == first_polyline_node_pt[1]) ||
36141 (first_polyline_node_pt[0] == last_polyline_node_pt[1]))
36143 is_reversed[0] =
true;
36147 Vector<Mesh*> tmp_face_mesh_pt(n_polyline);
36148 std::vector<bool> mesh_done(n_polyline,
false);
36149 Vector<unsigned> old_polyline_number(n_polyline);
36152 tmp_face_mesh_pt[0] = ordered_face_mesh_pt[0];
36153 unsigned current = 0;
36154 old_polyline_number[0] = 0;
36155 unsigned count_found = 0;
36158 for (
unsigned p = 1; p < n_polyline; p++)
36160 Node* end_node_pt = last_polyline_node_pt[current];
36161 if (is_reversed[current])
36163 end_node_pt = first_polyline_node_pt[current];
36167 for (
unsigned pp = 1; pp < n_polyline; pp++)
36169 if (!mesh_done[pp])
36172 if ((!is_reversed[current]) &&
36173 (end_node_pt == first_polyline_node_pt[pp]))
36175 tmp_face_mesh_pt[p] = ordered_face_mesh_pt[pp];
36176 mesh_done[pp] =
true;
36177 is_reversed[pp] =
false;
36178 old_polyline_number[p] = pp;
36185 else if ((!is_reversed[current]) &&
36186 (end_node_pt == last_polyline_node_pt[pp]))
36188 tmp_face_mesh_pt[p] = ordered_face_mesh_pt[pp];
36189 mesh_done[pp] =
true;
36190 is_reversed[pp] =
true;
36191 old_polyline_number[p] = pp;
36198 else if ((is_reversed[current]) &&
36199 (end_node_pt == first_polyline_node_pt[pp]))
36201 tmp_face_mesh_pt[p] = ordered_face_mesh_pt[pp];
36202 mesh_done[pp] =
true;
36203 is_reversed[pp] =
false;
36204 old_polyline_number[p] = pp;
36211 else if ((is_reversed[current]) &&
36212 (end_node_pt == last_polyline_node_pt[pp]))
36214 tmp_face_mesh_pt[p] = ordered_face_mesh_pt[pp];
36215 mesh_done[pp] =
true;
36216 is_reversed[pp] =
true;
36217 old_polyline_number[p] = pp;
36227 if (count_found != n_polyline - 1)
36229 std::ostringstream error_message;
36230 error_message <<
"Only found " << count_found <<
" out of "
36231 << n_polyline - 1 <<
" polylines to be fitted in.\n";
36232 throw OomphLibError(
36233 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
36238 for (
unsigned i = 0; i < n_polyline; i++)
36240 ordered_face_mesh_pt[i] = tmp_face_mesh_pt[i];
36246 unsigned new_face_id = 0;
36250 std::map<Node*, std::map<unsigned, unsigned>>
36251 node_must_not_be_removed_from_boundary_flag;
36254 for (
unsigned p = 0; p < n_polyline; p++)
36257 unsigned n_face_element = ordered_face_mesh_pt[p]->nelement();
36258 for (
unsigned e = 0; e < n_face_element; e++)
36260 unsigned el_number = e;
36261 if (is_reversed[p])
36263 el_number = n_face_element - e - 1;
36266 FiniteElement* el_pt =
36267 ordered_face_mesh_pt[p]->finite_element_pt(el_number);
36268 unsigned n_node = el_pt->nnode();
36271 double element_length_squared = 0.0;
36272 for (
unsigned i = 0; i < 2; i++)
36274 element_length_squared +=
36275 pow(el_pt->node_pt(n_node - 1)->x(i) - el_pt->node_pt(0)->x(i), 2);
36277 double element_length = sqrt(element_length_squared);
36280 s += element_length;
36284 if (s < s_total /
double(n_polyline) + 1e-6)
36287 face_mesh_pt[new_face_id]->add_element_pt(el_pt);
36289 unsigned bound_old =
36290 polygon_pt->polyline_pt(old_polyline_number[p])->boundary_id();
36292 unsigned bound_new =
36293 polygon_pt->polyline_pt(new_face_id)->boundary_id();
36296 for (
unsigned i = 0; i < n_node; i++)
36299 Node* nod_pt = el_pt->node_pt(i);
36303 if (bound_new != bound_old)
36306 add_boundary_node(bound_new, nod_pt);
36310 node_must_not_be_removed_from_boundary_flag[nod_pt][bound_old] +=
36320 node_must_not_be_removed_from_boundary_flag[nod_pt][bound_old] +=
36333 if (new_face_id != n_polyline - 1)
36351 unsigned move_count = 0;
36352 for (std::map<Node*, std::map<unsigned, unsigned>>::iterator it =
36353 node_must_not_be_removed_from_boundary_flag.begin();
36354 it != node_must_not_be_removed_from_boundary_flag.end();
36358 Node* nod_pt = (*it).first;
36361 for (std::map<unsigned, unsigned>::iterator it_2 = (*it).second.begin();
36362 it_2 != (*it).second.end();
36366 unsigned bound = (*it_2).first;
36369 if ((*it_2).second == 0)
36371 remove_boundary_node(bound, nod_pt);
36378 for (
unsigned p = 0; p < n_polyline; p++)
36381 unsigned bound = polygon_pt->polyline_pt(p)->boundary_id();
36384 unsigned n_face_element = face_mesh_pt[p]->nelement();
36385 for (
unsigned e = 0; e < n_face_element; e++)
36388 FaceElementAsGeomObject<ELEMENT>* el_pt =
36389 dynamic_cast<FaceElementAsGeomObject<ELEMENT>*
>(
36390 face_mesh_pt[p]->element_pt(e));
36393 el_pt->set_boundary_number_in_bulk_mesh(bound);
36398 setup_boundary_element_info();
36401 for (
unsigned p = 0; p < n_polyline; p++)
36404 unsigned bound = polygon_pt->polyline_pt(p)->boundary_id();
36407 this->
template setup_boundary_coordinates<ELEMENT>(bound);
36411 for (
unsigned p = 0; p < n_polyline; p++)
36416 ordered_face_mesh_pt[p]->flush_element_and_node_storage();
36417 delete ordered_face_mesh_pt[p];
36424 template<
class ELEMENT>
36426 TriangleMeshOpenCurve* open_polyline_pt, Vector<Mesh*>& face_mesh_pt)
36429 unsigned n_polyline = open_polyline_pt->ncurve_section();
36430 face_mesh_pt.resize(n_polyline);
36433 for (
unsigned p = 0; p < n_polyline; p++)
36436 unsigned bound = open_polyline_pt->curve_section_pt(p)->boundary_id();
36438 face_mesh_pt[p] =
new Mesh();
36439 create_unsorted_face_mesh_representation(bound, face_mesh_pt[p]);
36450 template<
class ELEMENT>
36452 ELEMENT>::surface_remesh_for_inner_hole_boundaries(Vector<Vector<double>>&
36453 internal_point_coord,
36454 const bool& check_only)
36458 bool update_was_performed =
false;
36460 unsigned n_hole = internal_point_coord.size();
36461 for (
unsigned ihole = 0; ihole < n_hole; ihole++)
36464 TriangleMeshPolygon*
const poly_pt = this->Internal_polygon_pt[ihole];
36469 if (poly_pt->can_update_reference_configuration())
36471 poly_pt->reset_reference_configuration();
36474 internal_point_coord[ihole].resize(2);
36477 internal_point_coord[ihole] = poly_pt->internal_point();
36488 bool update_necessary =
36489 this->update_polygon_using_face_mesh(poly_pt, check_only);
36492 if (update_necessary)
36502 update_was_performed = this->update_polygon_using_face_mesh(poly_pt);
36506 if (!poly_pt->internal_point().empty())
36510 if (poly_pt->is_internal_point_fixed())
36513 internal_point_coord[ihole] = poly_pt->internal_point();
36520 if (this->Internal_hole_point_update_fct_pt != 0)
36522 this->Internal_hole_point_update_fct_pt(ihole, poly_pt);
36528 Vector<double> vertex_coord;
36529 unsigned n_polyline = poly_pt->npolyline();
36532 vertex_coord.resize(2);
36533 internal_point_coord[ihole].resize(2);
36537 internal_point_coord[ihole][0] = 0.0;
36538 internal_point_coord[ihole][1] = 0.0;
36540 for (
unsigned p = 0; p < n_polyline; p++)
36542 Vector<double> poly_ave(2, 0.0);
36544 unsigned n_vertex = poly_pt->polyline_pt(p)->nvertex();
36545 for (
unsigned v = 0; v < n_vertex; v++)
36547 vertex_coord = poly_pt->polyline_pt(p)->vertex_coordinate(v);
36548 for (
unsigned i = 0; i < 2; i++)
36550 poly_ave[i] += vertex_coord[i];
36555 for (
unsigned i = 0; i < 2; i++)
36557 internal_point_coord[ihole][i] += poly_ave[i] / n_vertex;
36562 for (
unsigned i = 0; i < 2; i++)
36564 internal_point_coord[ihole][i] /= n_polyline;
36613 poly_pt->internal_point() = internal_point_coord[ihole];
36631 return update_was_performed;
36640 template<
class ELEMENT>
36642 const std::string& node_file_name,
const std::string& poly_file_name)
36648 std::ifstream node_file(node_file_name.c_str(), std::ios_base::in);
36651 if (!node_file.is_open())
36653 std::string error_msg(
"Failed to open node file: ");
36654 error_msg +=
"\"" + node_file_name +
"\".";
36655 throw OomphLibError(
36656 error_msg, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
36661 node_file >> nnodes;
36664 unsigned dimension;
36665 node_file >> dimension;
36668 if (dimension != 2)
36670 throw OomphLibError(
"The dimension must be 2\n",
36671 OOMPH_CURRENT_FUNCTION,
36672 OOMPH_EXCEPTION_LOCATION);
36677 Vector<double> x_node(nnodes);
36678 Vector<double> y_node(nnodes);
36681 unsigned npoint_attributes;
36682 node_file >> npoint_attributes;
36686 unsigned boundary_markers_flag = 0;
36687 node_file >> boundary_markers_flag;
36690 unsigned dummy_node_number;
36692 unsigned dummy_node_attribute;
36694 unsigned dummy_node_boundary;
36698 for (
unsigned i = 0; i < nnodes; i++)
36700 node_file >> dummy_node_number;
36701 node_file >> x_node[i];
36702 node_file >> y_node[i];
36703 for (
unsigned j = 0; j < npoint_attributes; ++j)
36705 node_file >> dummy_node_attribute;
36707 if (boundary_markers_flag)
36709 node_file >> dummy_node_boundary;
36718 std::map<unsigned, Vector<std::pair<unsigned, unsigned>>>
36719 unsorted_boundary_segments;
36724 Vector<unsigned> sorted_boundaries_ids;
36730 std::ifstream poly_file(poly_file_name.c_str(), std::ios_base::in);
36733 if (!poly_file.is_open())
36735 std::string error_msg(
"Failed to open poly file: ");
36736 error_msg +=
"\"" + poly_file_name +
"\".";
36737 throw OomphLibError(
36738 error_msg, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
36742 unsigned n_node_poly;
36743 poly_file >> n_node_poly;
36746 poly_file >> dimension;
36749 unsigned attribute_flag;
36750 poly_file >> attribute_flag;
36753 poly_file >> boundary_markers_flag;
36758 for (
unsigned i = 0; i < n_node_poly; i++)
36761 poly_file >> dummy;
36762 poly_file >> dummy;
36763 poly_file >> dummy;
36765 for (
unsigned j = 0; j < attribute_flag; ++j)
36767 poly_file >> dummy;
36770 if (boundary_markers_flag == 1)
36772 poly_file >> dummy;
36777 unsigned read_value;
36780 poly_file >> read_value;
36781 const unsigned nglobal_segments = read_value;
36784 poly_file >> boundary_markers_flag;
36787 unsigned global_segment_number;
36790 std::set<unsigned> nodes_ids;
36793 for (
unsigned i = 0; i < nglobal_segments; i++)
36796 unsigned lnode_id = 0;
36797 unsigned rnode_id = 0;
36798 unsigned bnd_id = 0;
36799 poly_file >> global_segment_number;
36800 poly_file >> lnode_id;
36801 poly_file >> rnode_id;
36802 nodes_ids.insert(lnode_id);
36803 nodes_ids.insert(rnode_id);
36804 if (boundary_markers_flag)
36806 poly_file >> bnd_id;
36812 unsorted_boundary_segments[bnd_id - 1].push_back(
36813 std::make_pair(lnode_id, rnode_id));
36820 const unsigned nsorted_boundaries_ids = sorted_boundaries_ids.size();
36822 bool boundary_id_found =
false;
36823 for (
unsigned ib = 0; ib < nsorted_boundaries_ids; ib++)
36825 if (sorted_boundaries_ids[ib] == bnd_id - 1)
36827 boundary_id_found =
true;
36833 if (!boundary_id_found)
36835 sorted_boundaries_ids.push_back(bnd_id - 1);
36844 if (nglobal_segments != nodes_ids.size())
36846 std::ostringstream error_message;
36848 <<
"The number of nodes (" << nodes_ids.size() <<
") and segments ("
36849 << nglobal_segments <<
") is different.\nThis may mean that there "
36850 <<
"are internal non-closed boundaries defined in\nthe polyfile. "
36851 <<
"If you need this feature please use the TriangleMeshPoyLine\n"
36852 <<
"and TriangleMeshCurviLine objects to define your domain.\n\n";
36853 throw OomphLibError(
36854 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
36861 const unsigned nboundary = unsorted_boundary_segments.size();
36864 if (nboundary != this->nboundary())
36866 std::ostringstream error_message;
36868 <<
"The number of boundaries on the mesh (" << this->nboundary()
36869 <<
") is different from the number of\nboundaries read from the "
36870 <<
"polyfiles (" << unsorted_boundary_segments.size() <<
")!!!\n\n\n";
36871 throw OomphLibError(
36872 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
36878 const unsigned nsorted_boundaries_ids = sorted_boundaries_ids.size();
36880 if (nsorted_boundaries_ids != this->nboundary())
36882 std::ostringstream error_message;
36884 <<
"The number of boundaries on the mesh (" << this->nboundary()
36885 <<
") is different from the number of\nsorted boundaries ids read "
36886 <<
"from the polyfiles (" << nsorted_boundaries_ids <<
")!!!\n\n\n";
36887 throw OomphLibError(
36888 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
36893 std::map<unsigned, std::list<unsigned>> sorted_boundary_segments;
36896 std::map<unsigned, Vector<std::pair<unsigned, unsigned>>>::iterator it;
36898 for (it = unsorted_boundary_segments.begin();
36899 it != unsorted_boundary_segments.end();
36904 const unsigned bnd_id = (*it).first;
36905 Vector<std::pair<unsigned, unsigned>> segments_edges = (*it).second;
36908 std::map<std::pair<unsigned, unsigned>,
bool> segment_done;
36909 const unsigned nsegments = segments_edges.size();
36912 std::list<unsigned> sorted_segments;
36915 unsigned left_node_id = segments_edges[0].first;
36916 unsigned right_node_id = segments_edges[0].second;
36919 sorted_segments.push_back(left_node_id);
36920 sorted_segments.push_back(right_node_id);
36923 segment_done[segments_edges[0]] =
true;
36926 unsigned nsorted_segments = 1;
36928 while (nsorted_segments < nsegments)
36930 for (
unsigned i = 1; i < nsegments; i++)
36933 if (!segment_done[segments_edges[i]])
36936 unsigned current_left_node_id = segments_edges[i].first;
36937 unsigned current_right_node_id = segments_edges[i].second;
36941 if (current_left_node_id == right_node_id)
36945 sorted_segments.push_back(current_right_node_id);
36947 nsorted_segments++;
36949 segment_done[segments_edges[i]] =
true;
36951 right_node_id = current_right_node_id;
36955 else if (current_right_node_id == left_node_id)
36959 sorted_segments.push_front(current_left_node_id);
36961 nsorted_segments++;
36963 segment_done[segments_edges[i]] =
true;
36965 left_node_id = current_left_node_id;
36969 else if (current_left_node_id == left_node_id)
36973 sorted_segments.push_front(current_right_node_id);
36975 nsorted_segments++;
36977 segment_done[segments_edges[i]] =
true;
36979 left_node_id = current_right_node_id;
36983 else if (current_right_node_id == right_node_id)
36987 sorted_segments.push_back(current_left_node_id);
36989 nsorted_segments++;
36991 segment_done[segments_edges[i]] =
true;
36993 right_node_id = current_left_node_id;
37001 sorted_boundary_segments[bnd_id] = sorted_segments;
37007 if (sorted_boundary_segments.size() != this->nboundary())
37009 std::ostringstream error_message;
37011 <<
"The number of boundaries on the mesh (" << this->nboundary()
37012 <<
") is different from the number\nof sorted boundaries to create the "
37013 <<
"polylines (" << sorted_boundary_segments.size() <<
")\n\n";
37014 throw OomphLibError(
37015 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
37021 Vector<TriangleMeshPolyLine*> polylines_pt(nboundary);
37022 unsigned current_polyline = 0;
37025 for (
unsigned ib = 0; ib < nsorted_boundaries_ids; ib++)
37028 const unsigned bnd_id = sorted_boundaries_ids[ib];
37032 Vector<unsigned> nodes_ids;
37033 for (std::list<unsigned>::iterator it_list =
37034 sorted_boundary_segments[bnd_id].begin();
37035 it_list != sorted_boundary_segments[bnd_id].end();
37038 nodes_ids.push_back((*it_list));
37042 const unsigned nvertices = nodes_ids.size();
37045 Vector<Vector<double>> vertices(nvertices);
37048 for (
unsigned i = 0; i < nvertices; i++)
37051 vertices[i].resize(2);
37052 vertices[i][0] = x_node[nodes_ids[i] - 1];
37053 vertices[i][1] = y_node[nodes_ids[i] - 1];
37061 polylines_pt[current_polyline] =
37062 new TriangleMeshPolyLine(vertices, bnd_id);
37065 this->Boundary_curve_section_pt[bnd_id] =
37066 dynamic_cast<TriangleMeshCurveSection*
>(polylines_pt[current_polyline]);
37069 current_polyline++;
37076 unsigned nsorted_polylines = 0;
37079 unsigned npolygons = 0;
37082 Vector<TriangleMeshPolygon*> polygons_pt;
37085 std::map<unsigned, bool> polyline_done;
37086 while (nsorted_polylines < nboundary)
37089 std::list<TriangleMeshCurveSection*> sorted_curve_sections_pt;
37091 unsigned init_poly = 0;
37093 bool found_root_polyline =
false;
37096 for (
unsigned i = 0; i < nboundary; i++)
37098 if (!polyline_done[i])
37102 nsorted_polylines++;
37105 found_root_polyline =
true;
37108 polyline_done[i] =
true;
37110 sorted_curve_sections_pt.push_back(polylines_pt[i]);
37117 if (!found_root_polyline)
37119 std::ostringstream error_message;
37120 error_message <<
"Was not possible to found the root polyline to "
37121 "create polygons\n\n";
37122 throw OomphLibError(error_message.str(),
37123 OOMPH_CURRENT_FUNCTION,
37124 OOMPH_EXCEPTION_LOCATION);
37129 const unsigned bnd_id = polylines_pt[init_poly]->boundary_id();
37131 unsigned left_node_id = sorted_boundary_segments[bnd_id].front();
37132 unsigned right_node_id = sorted_boundary_segments[bnd_id].back();
37135 bool closed_polygon =
false;
37140 for (
unsigned i = init_poly; i < nboundary; i++)
37143 if (!polyline_done[i])
37148 const unsigned cbnd_id = polylines_pt[i]->boundary_id();
37150 unsigned cleft_node_id = sorted_boundary_segments[cbnd_id].front();
37151 unsigned cright_node_id = sorted_boundary_segments[cbnd_id].back();
37155 if (cleft_node_id == right_node_id)
37158 sorted_curve_sections_pt.push_back(polylines_pt[i]);
37160 polyline_done[i] =
true;
37162 right_node_id = cright_node_id;
37164 nsorted_polylines++;
37168 else if (cright_node_id == left_node_id)
37171 sorted_curve_sections_pt.push_front(polylines_pt[i]);
37173 polyline_done[i] =
true;
37175 left_node_id = cleft_node_id;
37177 nsorted_polylines++;
37181 else if (cleft_node_id == left_node_id)
37184 polylines_pt[i]->reverse();
37186 sorted_curve_sections_pt.push_front(polylines_pt[i]);
37188 polyline_done[i] =
true;
37190 left_node_id = cright_node_id;
37192 nsorted_polylines++;
37196 else if (cright_node_id == right_node_id)
37199 polylines_pt[i]->reverse();
37201 sorted_curve_sections_pt.push_back(polylines_pt[i]);
37203 polyline_done[i] =
true;
37205 right_node_id = cleft_node_id;
37207 nsorted_polylines++;
37216 if (left_node_id == right_node_id)
37219 closed_polygon =
true;
37222 }
while (nsorted_polylines < nboundary && !closed_polygon);
37225 if (!closed_polygon)
37227 std::ostringstream error_message;
37229 <<
"It was not possible to create a closed curve, these are the "
37230 <<
"vertices of the already sorted polylines\n\n";
37231 unsigned cpolyline = 0;
37232 for (std::list<TriangleMeshCurveSection*>::iterator it_list =
37233 sorted_curve_sections_pt.begin();
37234 it_list != sorted_curve_sections_pt.end();
37237 error_message <<
"Polyline (" << cpolyline <<
")\n";
37238 TriangleMeshPolyLine* tmp_poly_pt =
37239 dynamic_cast<TriangleMeshPolyLine*
>((*it_list));
37240 const unsigned nvertex = tmp_poly_pt->nvertex();
37241 for (
unsigned v = 0; v < nvertex; v++)
37243 error_message <<
"(" << tmp_poly_pt->vertex_coordinate(v)[0] <<
", "
37244 << tmp_poly_pt->vertex_coordinate(v)[1] <<
")\n";
37246 error_message <<
"\n";
37249 throw OomphLibError(error_message.str(),
37250 OOMPH_CURRENT_FUNCTION,
37251 OOMPH_EXCEPTION_LOCATION);
37257 Vector<TriangleMeshCurveSection*> tmp_sorted_curve_sections_pt;
37258 for (std::list<TriangleMeshCurveSection*>::iterator it_list =
37259 sorted_curve_sections_pt.begin();
37260 it_list != sorted_curve_sections_pt.end();
37263 tmp_sorted_curve_sections_pt.push_back((*it_list));
37267 TriangleMeshPolygon* polygon_pt =
37268 new TriangleMeshPolygon(tmp_sorted_curve_sections_pt);
37271 this->Free_polygon_pt.insert(polygon_pt);
37274 polygons_pt.push_back(polygon_pt);
37287 unsigned index_outer = 0;
37289 for (
unsigned idx_outer = 0; idx_outer < npolygons; idx_outer++)
37292 Vector<Vector<double>> outer_vertex_coordinates;
37296 bool all_inner_inside =
true;
37299 const unsigned nouter_polylines = polygons_pt[idx_outer]->npolyline();
37300 for (
unsigned p = 0; p < nouter_polylines; p++)
37302 TriangleMeshPolyLine* tmp_poly_pt =
37303 polygons_pt[idx_outer]->polyline_pt(p);
37304 const unsigned nvertex = tmp_poly_pt->nvertex();
37305 for (
unsigned v = 0; v < nvertex; v++)
37307 Vector<double> current_vertex = tmp_poly_pt->vertex_coordinate(v);
37308 outer_vertex_coordinates.push_back(current_vertex);
37317 const unsigned ninner_polygons = polygons_pt.size() - 1;
37320 Vector<Vector<Vector<double>>> inner_vertex_coordinates(ninner_polygons);
37322 for (
unsigned i = 0; i <= ninner_polygons; i++)
37324 if (i != idx_outer)
37327 const unsigned ninner_polylines = polygons_pt[i]->npolyline();
37328 for (
unsigned p = 0; p < ninner_polylines; p++)
37330 TriangleMeshPolyLine* tmp_poly_pt = polygons_pt[i]->polyline_pt(p);
37331 const unsigned nvertex = tmp_poly_pt->nvertex();
37332 for (
unsigned v = 0; v < nvertex; v++)
37334 Vector<double> current_vertex = tmp_poly_pt->vertex_coordinate(v);
37337 inner_vertex_coordinates[i].push_back(current_vertex);
37339 else if (i > idx_outer)
37341 inner_vertex_coordinates[i - 1].push_back(current_vertex);
37353 for (
unsigned i = 0; i < ninner_polygons; i++)
37357 const unsigned nvertex_internal = inner_vertex_coordinates[i].size();
37358 for (
unsigned v = 0; v < nvertex_internal; v++)
37361 Vector<double> current_point = inner_vertex_coordinates[i][v];
37362 all_inner_inside &= this->is_point_inside_polygon_helper(
37363 outer_vertex_coordinates, current_point);
37367 if (!all_inner_inside)
37377 if (!all_inner_inside)
37387 if (all_inner_inside)
37389 index_outer = idx_outer;
37399 if (index_outer != 0)
37401 std::ostringstream warning_message;
37403 <<
"The first set of nodes listed in the input polyfiles does not\n"
37404 <<
"correspond to the outer closed boundary. This may lead to\n"
37405 <<
"problems at the adaptation stage if the holes coordinates\n"
37406 <<
"are no correctly associated to the inner closed boundaries.\n"
37407 <<
"You can check the generated mesh by calling the output() method\n"
37408 <<
"from the mesh object '(problem.mesh_pt()->output(string))'\n\n";
37409 OomphLibWarning(warning_message.str(),
37410 OOMPH_CURRENT_FUNCTION,
37411 OOMPH_EXCEPTION_LOCATION);
37420 this->Outer_boundary_pt.resize(1);
37421 this->Outer_boundary_pt[0] = polygons_pt[index_outer];
37423 this->Internal_polygon_pt.resize(npolygons - 1);
37424 for (
unsigned i = 0; i < npolygons; i++)
37426 if (i != index_outer)
37428 if (i < index_outer)
37431 this->Internal_polygon_pt[i] = polygons_pt[i];
37433 else if (i > index_outer)
37436 this->Internal_polygon_pt[i - 1] = polygons_pt[i];
37447 Vector<Vector<Vector<double>>> inner_vertex_coordinates(npolygons - 1);
37449 for (
unsigned i = 0; i < npolygons - 1; i++)
37452 const unsigned ninner_polylines =
37453 this->Internal_polygon_pt[i]->npolyline();
37454 for (
unsigned p = 0; p < ninner_polylines; p++)
37456 TriangleMeshPolyLine* tmp_poly_pt =
37457 this->Internal_polygon_pt[i]->polyline_pt(p);
37460 const unsigned nvertex = tmp_poly_pt->nvertex();
37461 for (
unsigned v = 0; v < nvertex; v++)
37463 Vector<double> current_vertex = tmp_poly_pt->vertex_coordinate(v);
37464 inner_vertex_coordinates[i].push_back(current_vertex);
37473 poly_file >> nholes;
37476 if (npolygons > 1 && (npolygons - 1) != nholes)
37478 std::ostringstream error_message;
37480 <<
"The number of holes (" << nholes <<
") does not correspond "
37481 <<
"with the number\nof internal polygons (" << npolygons - 1 <<
")\n\n"
37482 <<
"Using polyfiles as input does not currently allows the\n"
37483 <<
"definition of more than one outer polygon\n\n";
37484 throw OomphLibError(
37485 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
37490 Vector<Vector<double>> hole_coordinates(nholes);
37493 unsigned dummy_hole;
37495 for (
unsigned ihole = 0; ihole < nholes; ihole++)
37497 hole_coordinates[ihole].resize(2);
37499 poly_file >> dummy_hole;
37500 poly_file >> hole_coordinates[ihole][0];
37501 poly_file >> hole_coordinates[ihole][1];
37506 Vector<unsigned> index_hole_of_internal_polygon(npolygons - 1);
37507 std::map<unsigned, bool> hole_done;
37511 for (
unsigned i = 0; i < npolygons - 1; i++)
37514 for (
unsigned h = 0; h < nholes; h++)
37520 Vector<double> current_point = hole_coordinates[h];
37522 const bool hole_in_polygon = this->is_point_inside_polygon_helper(
37523 inner_vertex_coordinates[i], current_point);
37526 if (hole_in_polygon)
37529 hole_done[h] =
true;
37532 index_hole_of_internal_polygon[i] = h;
37544 if (hole_done.size() != npolygons - 1)
37546 std::ostringstream error_message;
37548 <<
"Not all the holes were associated to an internal closed boundary\n"
37549 <<
"Only (" << hole_done.size()
37550 <<
") holes were assigned for a total of\n"
37551 <<
"(" << npolygons - 1 <<
") internal closed boundaries.\n"
37552 <<
"You can check the generated mesh by calling the output() method\n"
37553 <<
"from the mesh object '(problem.mesh_pt()->output(string))'\n\n";
37554 throw OomphLibError(
37555 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
37560 for (
unsigned ihole = 0; ihole < nholes; ihole++)
37563 const unsigned index_hole = index_hole_of_internal_polygon[ihole];
37568 if (index_hole != ihole)
37570 std::ostringstream error_message;
37572 <<
"The hole vertices coordinates are not listed in the same order\n"
37573 <<
"as the nodes that define the internal closed boundaries.\n"
37574 <<
"This may lead to problems in case that the holes coordinates\n"
37575 <<
"were no properly assigned to the internal closed boundaries.\n"
37576 <<
"You can check the generated mesh by calling the output() method\n"
37577 <<
"from the mesh object '(problem.mesh_pt()->output(string))'\n\n";
37578 throw OomphLibError(error_message.str(),
37579 OOMPH_CURRENT_FUNCTION,
37580 OOMPH_EXCEPTION_LOCATION);
37585 this->Internal_polygon_pt[ihole]->internal_point() =
37586 hole_coordinates[index_hole];
37590 poly_file.ignore(80,
'\n');
37597 std::string regions_info_string;
37600 getline(poly_file, regions_info_string);
37604 if (isdigit(regions_info_string.c_str()[0]))
37606 nregions = std::atoi(regions_info_string.c_str());
37614 std::map<unsigned, Vector<double>> regions_coordinates;
37617 unsigned dummy_region;
37619 unsigned region_id;
37622 for (
unsigned iregion = 0; iregion < nregions; iregion++)
37624 Vector<double> tmp_region_coordinates(2);
37626 poly_file >> dummy_region;
37627 poly_file >> tmp_region_coordinates[0];
37628 poly_file >> tmp_region_coordinates[1];
37629 poly_file >> region_id;
37630 regions_coordinates[region_id].resize(2);
37631 regions_coordinates[region_id][0] = tmp_region_coordinates[0];
37632 regions_coordinates[region_id][1] = tmp_region_coordinates[1];
37635 poly_file.ignore(80,
'\n');
37638 if (region_id == 0)
37640 std::ostringstream error_message;
37642 <<
"Please use another region id different from zero.\n"
37643 <<
"It is internally used as the default region number.\n";
37644 throw OomphLibError(error_message.str(),
37645 OOMPH_CURRENT_FUNCTION,
37646 OOMPH_EXCEPTION_LOCATION);
37651 this->Regions_coordinates = regions_coordinates;
37660 template<
class ELEMENT>
37662 TriangleMeshPolygon*& polygon_pt,
const Vector<double>& target_area)
37665 unsigned update_was_performed =
false;
37667 const unsigned nele = this->nelement();
37677 Vector<Mesh*> face_mesh_pt;
37678 get_face_mesh_representation(polygon_pt, face_mesh_pt);
37682 Vector<double> vertex_coord(3);
37683 Vector<double> bound_left(1);
37684 Vector<double> bound_right(1);
37686 unsigned n_polyline = polygon_pt->npolyline();
37689 for (
unsigned p = 0; p < n_polyline; p++)
37697 MeshAsGeomObject* mesh_geom_obj_pt =
37698 new MeshAsGeomObject(face_mesh_pt[p]);
37703 std::set<Vector<double>> vertex_nodes;
37707 Vector<Vector<double>> tmp_vector_vertex_node;
37712 Vector<Vector<double>> vector_vertex_node;
37714 #ifdef OOMPH_HAS_MPI
37720 Vector<std::set<Vector<double>>> sub_vertex_nodes;
37724 Vector<Vector<Vector<double>>> sub_tmp_vector_vertex_node;
37729 Vector<Vector<Vector<double>>> sub_vector_vertex_node;
37734 const unsigned bound = polygon_pt->curve_section_pt(p)->boundary_id();
37737 const unsigned chunk = polygon_pt->curve_section_pt(p)->boundary_chunk();
37744 const unsigned nface_element = face_mesh_pt[p]->nelement();
37748 Vector<FiniteElement*> non_halo_face_element_pt;
37751 std::map<FiniteElement*, unsigned> face_element_index_on_boundary;
37753 for (
unsigned ef = 0; ef < nface_element; ++ef)
37755 FiniteElement* ele_face_pt = face_mesh_pt[p]->finite_element_pt(ef);
37756 #ifdef OOMPH_HAS_MPI
37758 if (this->is_mesh_distributed() && ele_face_pt->is_halo())
37764 non_halo_face_element_pt.push_back(ele_face_pt);
37765 face_element_index_on_boundary[ele_face_pt] = ef;
37769 const unsigned nnon_halo_face_element = non_halo_face_element_pt.size();
37772 std::map<FiniteElement*, bool> face_element_done;
37775 unsigned nsorted_face_elements = 0;
37777 #ifdef OOMPH_HAS_MPI
37779 unsigned nsub_boundaries = 0;
37784 while (nsorted_face_elements < nnon_halo_face_element)
37787 FiniteElement* ele_face_pt = 0;
37789 bool found_initial_face_element =
false;
37792 unsigned iface = 0;
37793 for (iface = 0; iface < nnon_halo_face_element; iface++)
37795 ele_face_pt = non_halo_face_element_pt[iface];
37797 if (!face_element_done[ele_face_pt])
37800 found_initial_face_element =
true;
37802 nsorted_face_elements++;
37809 if (!found_initial_face_element)
37811 std::ostringstream error_message;
37812 error_message <<
"Could not find an initial face element for the "
37813 "current segment\n";
37815 throw OomphLibError(
37816 error_message.str(),
37817 "RefineableTriangleMesh::update_polygon_using_elements_area()",
37818 OOMPH_EXCEPTION_LOCATION);
37825 std::set<Vector<double>> local_vertex_nodes;
37829 Vector<Vector<double>> local_tmp_vector_vertex_node;
37833 std::set<Vector<double>> sorted_target_areas;
37837 Vector<double> tmp_sorted_target_areas;
37843 unsigned nnode = ele_face_pt->nnode();
37846 ele_face_pt->node_pt(0)->get_coordinates_on_boundary(bound, bound_left);
37847 vertex_coord[0] = bound_left[0];
37850 for (
unsigned i = 0; i < 2; i++)
37852 vertex_coord[i + 1] = ele_face_pt->node_pt(0)->x(i);
37854 local_vertex_nodes.insert(vertex_coord);
37858 ele_face_pt->node_pt(nnode - 1)->get_coordinates_on_boundary(
37859 bound, bound_right);
37860 vertex_coord[0] = bound_right[0];
37863 for (
unsigned i = 0; i < 2; i++)
37865 vertex_coord[i + 1] = ele_face_pt->node_pt(nnode - 1)->x(i);
37867 local_vertex_nodes.insert(vertex_coord);
37870 Node* first_node_pt = ele_face_pt->node_pt(0);
37871 Node* last_node_pt = ele_face_pt->node_pt(nnode - 1);
37874 face_element_done[ele_face_pt] =
true;
37882 Vector<double> zeta_target_area_values(2);
37886 zeta_target_area_values[0] = std::min(bound_left[0], bound_right[0]);
37889 unsigned ef = face_element_index_on_boundary[ele_face_pt];
37891 FiniteElement* el_pt = this->boundary_element_pt(bound, ef);
37894 bool found_global_element_index =
false;
37896 for (
unsigned eg = 0; eg < nele; eg++)
37899 FiniteElement* el_compare_pt = this->finite_element_pt(eg);
37903 if (el_pt == el_compare_pt)
37905 zeta_target_area_values[1] = target_area[eg];
37907 found_global_element_index =
true;
37914 if (!found_global_element_index)
37916 std::ostringstream error_message;
37917 error_message <<
"The global index for the (" << ef
37918 <<
")-th face element "
37919 <<
"on\nthe (" << bound
37920 <<
")-th boundary was not found!!!";
37921 throw OomphLibError(
37922 error_message.str(),
37923 "RefineableTriangleMesh::update_polygon_using_elements_area()",
37924 OOMPH_EXCEPTION_LOCATION);
37929 sorted_target_areas.insert(zeta_target_area_values);
37934 bool face_element_added =
false;
37944 for (
unsigned iiface = iface; iiface < nnon_halo_face_element;
37947 face_element_added =
false;
37948 ele_face_pt = non_halo_face_element_pt[iiface];
37949 if (!face_element_done[ele_face_pt])
37952 nnode = ele_face_pt->nnode();
37953 Node* left_node_pt = ele_face_pt->node_pt(0);
37954 Node* right_node_pt = ele_face_pt->node_pt(nnode - 1);
37956 if (left_node_pt == first_node_pt)
37958 first_node_pt = right_node_pt;
37959 face_element_added =
true;
37961 else if (left_node_pt == last_node_pt)
37963 last_node_pt = right_node_pt;
37964 face_element_added =
true;
37966 else if (right_node_pt == first_node_pt)
37968 first_node_pt = left_node_pt;
37969 face_element_added =
true;
37971 else if (right_node_pt == last_node_pt)
37973 last_node_pt = left_node_pt;
37974 face_element_added =
true;
37977 if (face_element_added)
37981 left_node_pt->get_coordinates_on_boundary(bound, bound_left);
37982 vertex_coord[0] = bound_left[0];
37985 for (
unsigned i = 0; i < 2; i++)
37987 vertex_coord[i + 1] = left_node_pt->x(i);
37989 local_vertex_nodes.insert(vertex_coord);
37993 right_node_pt->get_coordinates_on_boundary(bound, bound_right);
37994 vertex_coord[0] = bound_right[0];
37997 for (
unsigned i = 0; i < 2; i++)
37999 vertex_coord[i + 1] = right_node_pt->x(i);
38001 local_vertex_nodes.insert(vertex_coord);
38005 face_element_done[ele_face_pt] =
true;
38006 nsorted_face_elements++;
38014 zeta_target_area_values[0] =
38015 std::min(bound_left[0], bound_right[0]);
38018 ef = face_element_index_on_boundary[ele_face_pt];
38019 FiniteElement* lel_pt = this->boundary_element_pt(bound, ef);
38022 found_global_element_index =
false;
38024 for (
unsigned eg = 0; eg < nele; eg++)
38027 FiniteElement* lel_compare_pt = this->finite_element_pt(eg);
38031 if (lel_pt == lel_compare_pt)
38033 zeta_target_area_values[1] = target_area[eg];
38035 found_global_element_index =
true;
38042 if (!found_global_element_index)
38044 std::ostringstream error_message;
38045 error_message <<
"The global index for the (" << ef
38046 <<
")-th face element "
38047 <<
"on\nthe (" << bound
38048 <<
")-th boundary was not found!!!";
38049 throw OomphLibError(error_message.str(),
38050 "RefineableTriangleMesh::update_polygon_"
38051 "using_elements_area()",
38052 OOMPH_EXCEPTION_LOCATION);
38057 sorted_target_areas.insert(zeta_target_area_values);
38064 }
while (face_element_added &&
38065 (nsorted_face_elements < nnon_halo_face_element));
38073 const unsigned nlocal_nodes = local_vertex_nodes.size();
38075 local_tmp_vector_vertex_node.resize(nlocal_nodes);
38078 unsigned counter = 0;
38079 std::set<Vector<double>>::iterator it_vertex;
38080 for (it_vertex = local_vertex_nodes.begin();
38081 it_vertex != local_vertex_nodes.end();
38084 local_tmp_vector_vertex_node[counter].resize(3);
38085 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
38086 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
38087 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
38093 const unsigned ntarget_areas = sorted_target_areas.size();
38094 tmp_sorted_target_areas.resize(ntarget_areas);
38096 std::set<Vector<double>>::iterator it_area;
38097 for (it_area = sorted_target_areas.begin();
38098 it_area != sorted_target_areas.end();
38101 tmp_sorted_target_areas[counter] = (*it_area)[1];
38106 if (nlocal_nodes > 0 && (ntarget_areas != nlocal_nodes - 1))
38108 std::ostringstream error_message;
38110 <<
"The boundary (" << bound <<
") was split during the "
38111 <<
"distribution process.\n"
38112 <<
"The problem is in the association of the target areas with "
38114 <<
"elements that gave rise to the vertex coordinates.\n"
38115 <<
"The number of local nodes (" << nlocal_nodes
38116 <<
"), on the 'sub-polyline', is not\n"
38117 <<
"according with the number of target "
38118 <<
"areas (" << ntarget_areas <<
")\nfor that number of nodes.\n"
38119 <<
"The target areas number MUST be equal to the number of\n"
38120 <<
"local nodes minus one\n\n";
38121 throw OomphLibError(error_message.str(),
38122 OOMPH_CURRENT_FUNCTION,
38123 OOMPH_EXCEPTION_LOCATION);
38134 double unrefinement_tolerance =
38135 polygon_pt->polyline_pt(p)->unrefinement_tolerance();
38138 bool unrefinement_applied =
38139 unrefine_boundary_constrained_by_target_area(
38142 local_tmp_vector_vertex_node,
38143 unrefinement_tolerance,
38144 tmp_sorted_target_areas);
38147 double refinement_tolerance =
38148 polygon_pt->polyline_pt(p)->refinement_tolerance();
38151 bool refinement_applied = refine_boundary_constrained_by_target_area(
38153 local_tmp_vector_vertex_node,
38154 refinement_tolerance,
38155 tmp_sorted_target_areas);
38159 local_vertex_nodes.clear();
38164 unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
38165 for (
unsigned i = 0; i < nnew_nodes; i++)
38167 vertex_coord[0] = local_tmp_vector_vertex_node[i][0];
38168 vertex_coord[1] = local_tmp_vector_vertex_node[i][1];
38169 vertex_coord[2] = local_tmp_vector_vertex_node[i][2];
38170 vertex_nodes.insert(vertex_coord);
38171 local_vertex_nodes.insert(vertex_coord);
38176 update_was_performed = (unrefinement_applied || refinement_applied);
38178 #ifdef OOMPH_HAS_MPI
38179 if (this->is_mesh_distributed())
38183 sub_vertex_nodes.push_back(local_vertex_nodes);
38192 unsigned npoly_vertex = vertex_nodes.size();
38195 tmp_vector_vertex_node.resize(npoly_vertex);
38196 unsigned count = 0;
38197 for (std::set<Vector<double>>::iterator it = vertex_nodes.begin();
38198 it != vertex_nodes.end();
38201 tmp_vector_vertex_node[count].resize(3);
38202 tmp_vector_vertex_node[count][0] = (*it)[0];
38203 tmp_vector_vertex_node[count][1] = (*it)[1];
38204 tmp_vector_vertex_node[count][2] = (*it)[2];
38208 #ifdef OOMPH_HAS_MPI
38211 unsigned nsub_boundaries_set = sub_vertex_nodes.size();
38212 if (nsub_boundaries_set != nsub_boundaries)
38214 std::ostringstream error_message;
38216 <<
"The number of found sub-boundaries and the number of counted\n"
38217 <<
"sub-boundaries are different:\n"
38218 <<
"Number of found sub-boundaries: (" << nsub_boundaries_set <<
")\n"
38219 <<
"Number of counted sub-boundaries: (" << nsub_boundaries <<
")\n";
38220 throw OomphLibError(error_message.str(),
38221 OOMPH_CURRENT_FUNCTION,
38222 OOMPH_EXCEPTION_LOCATION);
38227 if (this->is_mesh_distributed() && nsub_boundaries > 1)
38230 this->Boundary_was_splitted[bound] =
true;
38232 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
38233 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
38236 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
38237 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
38238 unsigned subcount = 0;
38239 std::set<Vector<double>>::iterator subit;
38240 for (subit = sub_vertex_nodes[isub].begin();
38241 subit != sub_vertex_nodes[isub].end();
38244 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
38245 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
38246 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
38247 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
38257 unsigned n_vertex = tmp_vector_vertex_node.size();
38260 vector_vertex_node.resize(n_vertex);
38261 for (
unsigned i = 0; i < n_vertex; i++)
38263 vector_vertex_node[i].resize(2);
38264 vector_vertex_node[i][0] = tmp_vector_vertex_node[i][1];
38265 vector_vertex_node[i][1] = tmp_vector_vertex_node[i][2];
38268 #ifdef OOMPH_HAS_MPI
38271 if (this->is_mesh_distributed() && nsub_boundaries > 1)
38276 sub_vector_vertex_node.resize(nsub_boundaries);
38277 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
38279 const unsigned subn_vertex = sub_tmp_vector_vertex_node[isub].size();
38281 sub_vector_vertex_node[isub].resize(subn_vertex);
38282 for (
unsigned i = 0; i < subn_vertex; i++)
38284 sub_vector_vertex_node[isub][i].resize(2);
38285 sub_vector_vertex_node[isub][i][0] =
38286 sub_tmp_vector_vertex_node[isub][i][1];
38287 sub_vector_vertex_node[isub][i][1] =
38288 sub_tmp_vector_vertex_node[isub][i][2];
38303 #ifdef OOMPH_HAS_MPI
38307 if (!this->is_mesh_distributed())
38313 Vector<double> final_vertex_of_previous_segment;
38314 unsigned n_prev_vertex =
38315 polygon_pt->curve_section_pt(p - 1)->nvertex();
38316 final_vertex_of_previous_segment =
38317 polygon_pt->polyline_pt(p - 1)->vertex_coordinate(n_prev_vertex -
38320 unsigned prev_seg_boundary_id =
38321 polygon_pt->curve_section_pt(p - 1)->boundary_id();
38325 double error = 0.0;
38326 for (
unsigned i = 0; i < 2; i++)
38328 const double dist = final_vertex_of_previous_segment[i] -
38329 (*vector_vertex_node.begin())[i];
38330 error += dist * dist;
38332 error = sqrt(error);
38336 if (error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
38340 double rev_error = 0.0;
38341 for (
unsigned i = 0; i < 2; i++)
38343 const double dist = final_vertex_of_previous_segment[i] -
38344 (*--vector_vertex_node.end())[i];
38345 rev_error += dist * dist;
38347 rev_error = sqrt(rev_error);
38350 ToleranceForVertexMismatchInPolygons::Tolerable_error)
38359 Vector<double> initial_vertex_of_previous_segment;
38361 initial_vertex_of_previous_segment =
38362 polygon_pt->polyline_pt(p - 1)->vertex_coordinate(0);
38364 unsigned prev_seg_boundary_id =
38365 polygon_pt->curve_section_pt(p - 1)->boundary_id();
38369 double error = 0.0;
38370 for (
unsigned i = 0; i < 2; i++)
38372 const double dist = initial_vertex_of_previous_segment[i] -
38373 (*vector_vertex_node.begin())[i];
38374 error += dist * dist;
38376 error = sqrt(error);
38381 ToleranceForVertexMismatchInPolygons::Tolerable_error)
38385 double rev_error = 0.0;
38386 for (
unsigned i = 0; i < 2; i++)
38388 const double dist = initial_vertex_of_previous_segment[i] -
38389 (*--vector_vertex_node.end())[i];
38390 rev_error += dist * dist;
38397 ToleranceForVertexMismatchInPolygons::Tolerable_error)
38399 std::ostringstream error_stream;
38401 <<
"The distance between the first node of the current\n"
38402 <<
"line segment (boundary " << bound
38403 <<
") and either end of "
38404 <<
"the previous line segment\n"
38405 <<
"(boundary " << prev_seg_boundary_id
38406 <<
") is bigger than "
38407 <<
"the desired tolerance "
38408 << ToleranceForVertexMismatchInPolygons::Tolerable_error
38410 <<
"This suggests that the polylines defining the "
38412 <<
"representation are not properly ordered.\n"
38413 <<
"Fail on last vertex of polyline: ("
38414 << prev_seg_boundary_id <<
") and\n"
38415 <<
"first vertex of polyline (" << bound <<
").\n"
38416 <<
"This should have failed when first trying to "
38417 <<
"construct the\npolygon.\n";
38418 throw OomphLibError(error_stream.str(),
38419 OOMPH_CURRENT_FUNCTION,
38420 OOMPH_EXCEPTION_LOCATION);
38427 std::reverse(vector_vertex_node.begin(),
38428 vector_vertex_node.end());
38430 polygon_pt->polyline_pt(p - 1)->reverse();
38436 polygon_pt->polyline_pt(p - 1)->reverse();
38442 std::ostringstream error_stream;
38444 <<
"The distance between the first node of the current\n"
38445 <<
"line segment (boundary " << bound
38446 <<
") and either end of "
38447 <<
"the previous line segment\n"
38448 <<
"(boundary " << prev_seg_boundary_id
38449 <<
") is bigger than the "
38450 <<
"desired tolerance "
38451 << ToleranceForVertexMismatchInPolygons::Tolerable_error
38453 <<
"This suggests that the polylines defining the polygonal\n"
38454 <<
"representation are not properly ordered.\n"
38455 <<
"Fail on last vertex of polyline: ("
38456 << prev_seg_boundary_id <<
") and\nfirst vertex of polyline ("
38458 <<
"This should have failed when first trying to construct"
38459 <<
" the polygon.\n";
38460 throw OomphLibError(error_stream.str(),
38461 OOMPH_CURRENT_FUNCTION,
38462 OOMPH_EXCEPTION_LOCATION);
38468 std::reverse(vector_vertex_node.begin(),
38469 vector_vertex_node.end());
38487 n_vertex = vector_vertex_node.size();
38490 TriangleMeshPolyLine* tmp_polyline_pt =
38491 new TriangleMeshPolyLine(vector_vertex_node, bound);
38495 TriangleMeshCurveSection* tmp_curve_section_pt = tmp_polyline_pt;
38499 double unrefinement_tolerance =
38500 polygon_pt->polyline_pt(p)->unrefinement_tolerance();
38503 double refinement_tolerance =
38504 polygon_pt->polyline_pt(p)->refinement_tolerance();
38507 tmp_polyline_pt->set_unrefinement_tolerance(unrefinement_tolerance);
38508 tmp_polyline_pt->set_refinement_tolerance(refinement_tolerance);
38511 double maximum_length = polygon_pt->polyline_pt(p)->maximum_length();
38512 tmp_polyline_pt->set_maximum_length(maximum_length);
38514 #ifdef OOMPH_HAS_MPI
38517 if (this->is_mesh_distributed())
38523 this->copy_connection_information(polygon_pt->polyline_pt(p),
38524 tmp_curve_section_pt);
38532 this->copy_connection_information(polygon_pt->polyline_pt(p),
38533 tmp_curve_section_pt);
38539 bool delete_it_on_destructor =
false;
38541 std::set<TriangleMeshCurveSection*>::iterator it =
38542 this->Free_curve_section_pt.find(polygon_pt->curve_section_pt(p));
38544 if (it != this->Free_curve_section_pt.end())
38546 this->Free_curve_section_pt.erase(it);
38547 delete polygon_pt->curve_section_pt(p);
38548 delete_it_on_destructor =
true;
38553 polygon_pt->curve_section_pt(p) = tmp_polyline_pt;
38556 this->Boundary_curve_section_pt[bound] = polygon_pt->curve_section_pt(p);
38558 if (delete_it_on_destructor)
38560 this->Free_curve_section_pt.insert(polygon_pt->curve_section_pt(p));
38563 #ifdef OOMPH_HAS_MPI
38566 if (this->is_mesh_distributed() && nsub_boundaries > 1)
38572 this->Boundary_subpolylines[bound].clear();
38575 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
38576 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
38579 TriangleMeshPolyLine* sub_tmp_polyline_pt =
38580 new TriangleMeshPolyLine(sub_vector_vertex_node[isub], bound, isub);
38584 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
38600 delete mesh_geom_obj_pt;
38605 for (
unsigned p = 0; p < n_polyline; p++)
38607 face_mesh_pt[p]->flush_node_storage();
38608 delete face_mesh_pt[p];
38611 return update_was_performed;
38618 template<
class ELEMENT>
38620 TriangleMeshOpenCurve*& open_curve_pt,
const Vector<double>& target_area)
38623 unsigned update_was_performed =
false;
38625 const unsigned nele = this->nelement();
38635 Vector<Mesh*> face_mesh_pt;
38636 get_face_mesh_representation(open_curve_pt, face_mesh_pt);
38640 Vector<double> vertex_coord(3);
38641 Vector<double> bound_left(1);
38642 Vector<double> bound_right(1);
38644 const unsigned ncurve_section = open_curve_pt->ncurve_section();
38647 for (
unsigned cs = 0; cs < ncurve_section; cs++)
38655 MeshAsGeomObject* mesh_geom_obj_pt =
38656 new MeshAsGeomObject(face_mesh_pt[cs]);
38659 const unsigned bound = open_curve_pt->curve_section_pt(cs)->boundary_id();
38662 const unsigned chunk =
38663 open_curve_pt->curve_section_pt(cs)->boundary_chunk();
38672 const unsigned nface_element = face_mesh_pt[cs]->nelement();
38677 Vector<FiniteElement*> non_halo_doubled_face_element_pt;
38680 std::map<FiniteElement*, unsigned> face_element_index_on_boundary;
38683 std::map<FiniteElement*, bool> face_element_done;
38685 for (
unsigned ef = 0; ef < nface_element; ++ef)
38687 FiniteElement* ele_face_pt = face_mesh_pt[cs]->finite_element_pt(ef);
38692 #ifdef OOMPH_HAS_MPI
38693 if (this->is_mesh_distributed())
38696 if (ele_face_pt->is_halo())
38704 if (!face_element_done[ele_face_pt])
38709 non_halo_doubled_face_element_pt.push_back(ele_face_pt);
38711 face_element_index_on_boundary[ele_face_pt] = ef;
38713 face_element_done[ele_face_pt] =
true;
38715 const unsigned nnodes = ele_face_pt->nnode();
38718 Node* left_node_pt = ele_face_pt->node_pt(0);
38719 Node* right_node_pt = ele_face_pt->node_pt(nnodes - 1);
38723 bool found_other_side_face_ele =
false;
38725 for (
unsigned iface = 0; iface < nface_element; iface++)
38728 FiniteElement* cele_face_pt =
38729 face_mesh_pt[cs]->finite_element_pt(iface);
38731 if (!face_element_done[cele_face_pt])
38733 Node* cleft_node_pt = cele_face_pt->node_pt(0);
38734 Node* cright_node_pt = cele_face_pt->node_pt(nnodes - 1);
38736 if ((left_node_pt == cleft_node_pt &&
38737 right_node_pt == cright_node_pt) ||
38738 (left_node_pt == cright_node_pt &&
38739 right_node_pt == cleft_node_pt))
38742 non_halo_doubled_face_element_pt.push_back(cele_face_pt);
38744 face_element_done[cele_face_pt] =
true;
38746 face_element_index_on_boundary[cele_face_pt] = iface;
38749 found_other_side_face_ele =
true;
38757 if (!found_other_side_face_ele)
38759 std::ostringstream error_message;
38761 <<
"The face element at the other side of the boundary (" << bound
38762 <<
") was not found!!\n"
38763 <<
"These are the nodes of the face element:\n"
38764 <<
"(" << left_node_pt->x(0) <<
", " << left_node_pt->x(1) <<
") "
38765 <<
"and (" << right_node_pt->x(0) <<
"," << right_node_pt->x(1)
38767 throw OomphLibError(
38768 error_message.str(),
38769 "RefineableTriangleMesh::update_open_curve_using_elements_area()",
38770 OOMPH_EXCEPTION_LOCATION);
38779 face_element_done.clear();
38784 std::set<Vector<double>> vertex_nodes;
38788 Vector<Vector<double>> tmp_vector_vertex_node;
38793 Vector<Vector<double>> vector_vertex_node;
38795 #ifdef OOMPH_HAS_MPI
38800 std::vector<bool> internal_to_shared_boundary;
38807 Vector<std::set<Vector<double>>> sub_vertex_nodes;
38811 Vector<Vector<Vector<double>>> sub_tmp_vector_vertex_node;
38816 Vector<Vector<Vector<double>>> sub_vector_vertex_node;
38827 unsigned nsorted_face_elements = 0;
38829 #ifdef OOMPH_HAS_MPI
38831 unsigned nsub_boundaries = 0;
38835 const unsigned nnon_halo_doubled_face_ele =
38836 non_halo_doubled_face_element_pt.size();
38840 while (nsorted_face_elements < nnon_halo_doubled_face_ele)
38843 FiniteElement* ele_face_pt = 0;
38844 FiniteElement* repeated_ele_face_pt = 0;
38846 bool found_initial_face_element =
false;
38852 bool both_root_face_elements_are_nonhalo =
false;
38854 unsigned iface = 0;
38855 for (iface = 0; iface < nnon_halo_doubled_face_ele; iface += 2)
38857 ele_face_pt = non_halo_doubled_face_element_pt[iface];
38859 if (!face_element_done[ele_face_pt])
38862 face_element_done[ele_face_pt] =
true;
38864 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iface + 1];
38866 face_element_done[repeated_ele_face_pt] =
true;
38868 #ifdef OOMPH_HAS_MPI
38869 if (!repeated_ele_face_pt->is_halo())
38871 both_root_face_elements_are_nonhalo =
true;
38877 nsorted_face_elements += 2;
38881 found_initial_face_element =
true;
38888 if (!found_initial_face_element)
38890 std::ostringstream error_message;
38891 error_message <<
"Could not find an initial face element for the "
38892 "current segment\n";
38893 throw OomphLibError(error_message.str(),
38894 OOMPH_CURRENT_FUNCTION,
38895 OOMPH_EXCEPTION_LOCATION);
38902 std::set<Vector<double>> local_vertex_nodes;
38906 Vector<Vector<double>> local_tmp_vector_vertex_node;
38910 std::set<Vector<double>> sorted_target_areas;
38914 Vector<double> tmp_sorted_target_areas;
38920 const unsigned nnode = ele_face_pt->nnode();
38923 ele_face_pt->node_pt(0)->get_coordinates_on_boundary(bound, bound_left);
38924 vertex_coord[0] = bound_left[0];
38927 for (
unsigned i = 0; i < 2; i++)
38929 vertex_coord[i + 1] = ele_face_pt->node_pt(0)->x(i);
38931 local_vertex_nodes.insert(vertex_coord);
38935 ele_face_pt->node_pt(nnode - 1)->get_coordinates_on_boundary(
38936 bound, bound_right);
38937 vertex_coord[0] = bound_right[0];
38940 for (
unsigned i = 0; i < 2; i++)
38942 vertex_coord[i + 1] = ele_face_pt->node_pt(nnode - 1)->x(i);
38944 local_vertex_nodes.insert(vertex_coord);
38947 Node* first_node_pt = ele_face_pt->node_pt(0);
38948 Node* last_node_pt = ele_face_pt->node_pt(nnode - 1);
38956 Vector<double> zeta_target_area_values(2);
38960 zeta_target_area_values[0] = std::min(bound_left[0], bound_right[0]);
38963 const unsigned ef = face_element_index_on_boundary[ele_face_pt];
38965 FiniteElement* el_pt = this->boundary_element_pt(bound, ef);
38966 double target_area_face_element = 0.0;
38969 bool found_global_element_index =
false;
38971 for (
unsigned eg = 0; eg < nele; eg++)
38974 FiniteElement* el_compare_pt = this->finite_element_pt(eg);
38978 if (el_pt == el_compare_pt)
38980 target_area_face_element = target_area[eg];
38982 found_global_element_index =
true;
38989 if (!found_global_element_index)
38991 std::ostringstream error_message;
38992 error_message <<
"The global index for the (" << ef
38993 <<
")-th face element "
38994 <<
"on\nthe (" << bound
38995 <<
")-th boundary was not found!!!";
38996 throw OomphLibError(error_message.str(),
38997 OOMPH_CURRENT_FUNCTION,
38998 OOMPH_EXCEPTION_LOCATION);
39003 const unsigned ref =
39004 face_element_index_on_boundary[repeated_ele_face_pt];
39005 FiniteElement* rel_pt = this->boundary_element_pt(bound, ref);
39006 double target_area_repeated_face_element = 0.0;
39009 bool found_global_repeated_element_index =
false;
39011 for (
unsigned eg = 0; eg < nele; eg++)
39014 FiniteElement* el_compare_pt = this->finite_element_pt(eg);
39018 if (rel_pt == el_compare_pt)
39020 target_area_repeated_face_element = target_area[eg];
39022 found_global_repeated_element_index =
true;
39029 if (!found_global_repeated_element_index)
39031 std::ostringstream error_message;
39032 error_message <<
"The global index for the (" << ref
39033 <<
")-th face element "
39034 <<
"on\nthe (" << bound
39035 <<
")-th boundary was not found (repeated "
39036 <<
"face element)!!!";
39037 throw OomphLibError(error_message.str(),
39038 OOMPH_CURRENT_FUNCTION,
39039 OOMPH_EXCEPTION_LOCATION);
39045 zeta_target_area_values[1] =
39046 std::min(target_area_face_element, target_area_repeated_face_element);
39049 sorted_target_areas.insert(zeta_target_area_values);
39054 bool face_element_added =
false;
39064 for (
unsigned iiface = iface; iiface < nnon_halo_doubled_face_ele;
39067 face_element_added =
false;
39068 ele_face_pt = non_halo_doubled_face_element_pt[iiface];
39075 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iiface + 1];
39076 bool both_face_elements_are_nonhalo =
false;
39078 #ifdef OOMPH_HAS_MPI
39079 if (!repeated_ele_face_pt->is_halo())
39081 both_face_elements_are_nonhalo =
true;
39085 if (!face_element_done[ele_face_pt] &&
39086 (both_face_elements_are_nonhalo ==
39087 both_root_face_elements_are_nonhalo))
39090 const unsigned nlnode = ele_face_pt->nnode();
39091 Node* left_node_pt = ele_face_pt->node_pt(0);
39092 Node* right_node_pt = ele_face_pt->node_pt(nlnode - 1);
39094 if (left_node_pt == first_node_pt)
39096 first_node_pt = right_node_pt;
39097 face_element_added =
true;
39099 else if (left_node_pt == last_node_pt)
39101 last_node_pt = right_node_pt;
39102 face_element_added =
true;
39104 else if (right_node_pt == first_node_pt)
39106 first_node_pt = left_node_pt;
39107 face_element_added =
true;
39109 else if (right_node_pt == last_node_pt)
39111 last_node_pt = left_node_pt;
39112 face_element_added =
true;
39115 if (face_element_added)
39119 left_node_pt->get_coordinates_on_boundary(bound, bound_left);
39120 vertex_coord[0] = bound_left[0];
39123 for (
unsigned i = 0; i < 2; i++)
39125 vertex_coord[i + 1] = left_node_pt->x(i);
39127 local_vertex_nodes.insert(vertex_coord);
39131 right_node_pt->get_coordinates_on_boundary(bound, bound_right);
39132 vertex_coord[0] = bound_right[0];
39135 for (
unsigned i = 0; i < 2; i++)
39137 vertex_coord[i + 1] = right_node_pt->x(i);
39139 local_vertex_nodes.insert(vertex_coord);
39143 face_element_done[ele_face_pt] =
true;
39146 repeated_ele_face_pt =
39147 non_halo_doubled_face_element_pt[iiface + 1];
39148 face_element_done[repeated_ele_face_pt] =
true;
39150 nsorted_face_elements += 2;
39158 zeta_target_area_values[0] =
39159 std::min(bound_left[0], bound_right[0]);
39162 const unsigned lef =
39163 face_element_index_on_boundary[ele_face_pt];
39164 FiniteElement* lel_pt = this->boundary_element_pt(bound, lef);
39167 found_global_element_index =
false;
39169 for (
unsigned eg = 0; eg < nele; eg++)
39172 FiniteElement* lel_compare_pt = this->finite_element_pt(eg);
39176 if (lel_pt == lel_compare_pt)
39178 target_area_face_element = target_area[eg];
39180 found_global_element_index =
true;
39187 if (!found_global_element_index)
39189 std::ostringstream error_message;
39190 error_message <<
"The global index for the (" << lef
39191 <<
")-th face element "
39192 <<
"on\nthe (" << bound
39193 <<
")-th boundary was not found!!!";
39194 throw OomphLibError(error_message.str(),
39195 OOMPH_CURRENT_FUNCTION,
39196 OOMPH_EXCEPTION_LOCATION);
39201 const unsigned rlef =
39202 face_element_index_on_boundary[repeated_ele_face_pt];
39203 FiniteElement* rlel_pt = this->boundary_element_pt(bound, rlef);
39206 found_global_repeated_element_index =
false;
39208 for (
unsigned eg = 0; eg < nele; eg++)
39211 FiniteElement* lel_compare_pt = this->finite_element_pt(eg);
39215 if (rlel_pt == lel_compare_pt)
39217 target_area_repeated_face_element = target_area[eg];
39219 found_global_repeated_element_index =
true;
39226 if (!found_global_repeated_element_index)
39228 std::ostringstream error_message;
39229 error_message <<
"The global index for the (" << rlef
39230 <<
")-th face element "
39231 <<
"on\nthe (" << bound
39232 <<
")-th boundary was not found "
39233 <<
"(repeated face element)!!!";
39234 throw OomphLibError(error_message.str(),
39235 OOMPH_CURRENT_FUNCTION,
39236 OOMPH_EXCEPTION_LOCATION);
39242 zeta_target_area_values[1] = std::min(
39243 target_area_face_element, target_area_repeated_face_element);
39246 sorted_target_areas.insert(zeta_target_area_values);
39253 }
while (face_element_added &&
39254 (nsorted_face_elements < nnon_halo_doubled_face_ele));
39262 const unsigned nlocal_nodes = local_vertex_nodes.size();
39264 local_tmp_vector_vertex_node.resize(nlocal_nodes);
39267 unsigned counter = 0;
39268 std::set<Vector<double>>::iterator it_vertex;
39269 for (it_vertex = local_vertex_nodes.begin();
39270 it_vertex != local_vertex_nodes.end();
39273 local_tmp_vector_vertex_node[counter].resize(3);
39274 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
39275 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
39276 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
39282 const unsigned ntarget_areas = sorted_target_areas.size();
39283 tmp_sorted_target_areas.resize(ntarget_areas);
39285 std::set<Vector<double>>::iterator it_area;
39286 for (it_area = sorted_target_areas.begin();
39287 it_area != sorted_target_areas.end();
39290 tmp_sorted_target_areas[counter] = (*it_area)[1];
39295 if (nlocal_nodes > 0 && (ntarget_areas != nlocal_nodes - 1))
39297 std::ostringstream error_message;
39299 <<
"The boundary (" << bound <<
") was split during the "
39300 <<
"distribution process.\n"
39301 <<
"The problem comes when associating the target areas with the "
39302 <<
"elements that gave\nrise to the vertex coordinates.\n"
39303 <<
"The number of local nodes on the 'sub-polyline' ("
39304 << nlocal_nodes <<
") is not according with the number of target\n"
39305 <<
"areas (" << ntarget_areas <<
") for that number of nodes.\n"
39306 <<
"The target areas number must be equal to the number of "
39308 throw OomphLibError(error_message.str(),
39309 OOMPH_CURRENT_FUNCTION,
39310 OOMPH_EXCEPTION_LOCATION);
39317 if (local_tmp_vector_vertex_node[nlocal_nodes - 1][2] <
39318 local_tmp_vector_vertex_node[0][2])
39320 std::reverse(local_tmp_vector_vertex_node.begin(),
39321 local_tmp_vector_vertex_node.end());
39322 std::reverse(tmp_sorted_target_areas.begin(),
39323 tmp_sorted_target_areas.end());
39325 else if (local_tmp_vector_vertex_node[nlocal_nodes - 1][2] ==
39326 local_tmp_vector_vertex_node[0][2])
39328 if (local_tmp_vector_vertex_node[nlocal_nodes - 1][1] <
39329 local_tmp_vector_vertex_node[0][1])
39331 std::reverse(local_tmp_vector_vertex_node.begin(),
39332 local_tmp_vector_vertex_node.end());
39333 std::reverse(tmp_sorted_target_areas.begin(),
39334 tmp_sorted_target_areas.end());
39345 double unrefinement_tolerance =
39346 open_curve_pt->polyline_pt(cs)->unrefinement_tolerance();
39349 bool unrefinement_applied =
39350 unrefine_boundary_constrained_by_target_area(
39353 local_tmp_vector_vertex_node,
39354 unrefinement_tolerance,
39355 tmp_sorted_target_areas);
39358 double refinement_tolerance =
39359 open_curve_pt->polyline_pt(cs)->refinement_tolerance();
39362 bool refinement_applied = refine_boundary_constrained_by_target_area(
39364 local_tmp_vector_vertex_node,
39365 refinement_tolerance,
39366 tmp_sorted_target_areas);
39370 local_vertex_nodes.clear();
39375 const unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
39376 for (
unsigned i = 0; i < nnew_nodes; i++)
39378 vertex_coord[0] = local_tmp_vector_vertex_node[i][0];
39379 vertex_coord[1] = local_tmp_vector_vertex_node[i][1];
39380 vertex_coord[2] = local_tmp_vector_vertex_node[i][2];
39381 vertex_nodes.insert(vertex_coord);
39382 local_vertex_nodes.insert(vertex_coord);
39387 update_was_performed = (unrefinement_applied || refinement_applied);
39389 #ifdef OOMPH_HAS_MPI
39390 if (this->is_mesh_distributed())
39395 sub_vertex_nodes.push_back(local_vertex_nodes);
39401 if (both_root_face_elements_are_nonhalo)
39403 internal_to_shared_boundary.push_back(
false);
39407 internal_to_shared_boundary.push_back(
true);
39418 const unsigned npoly_vertex = vertex_nodes.size();
39419 tmp_vector_vertex_node.resize(npoly_vertex);
39420 unsigned count = 0;
39421 for (std::set<Vector<double>>::iterator it = vertex_nodes.begin();
39422 it != vertex_nodes.end();
39425 tmp_vector_vertex_node[count].resize(3);
39426 tmp_vector_vertex_node[count][0] = (*it)[0];
39427 tmp_vector_vertex_node[count][1] = (*it)[1];
39428 tmp_vector_vertex_node[count][2] = (*it)[2];
39432 #ifdef OOMPH_HAS_MPI
39437 const unsigned nsub_boundaries_set = sub_vertex_nodes.size();
39438 const unsigned ninternal_to_shared_boundaries =
39439 internal_to_shared_boundary.size();
39440 if (nsub_boundaries_set != ninternal_to_shared_boundaries)
39442 std::ostringstream error_message;
39444 <<
"The number of found sub-boundaries and the number of marked "
39445 <<
"internal\nboundaries are different\n"
39446 <<
"Number of found sub-boundaries: (" << nsub_boundaries_set <<
")\n"
39447 <<
"Number of marked internal boundaries: ("
39448 << ninternal_to_shared_boundaries <<
")\n\n";
39449 throw OomphLibError(error_message.str(),
39450 OOMPH_CURRENT_FUNCTION,
39451 OOMPH_EXCEPTION_LOCATION);
39457 if (nsub_boundaries_set != nsub_boundaries)
39459 std::ostringstream error_message;
39461 <<
"The number of found sub-boundaries and the number of counted\n"
39462 <<
"sub-boundaries are different:\n"
39463 <<
"Number of found sub-boundaries: (" << nsub_boundaries_set <<
")\n"
39464 <<
"Number of counted sub-boundaries: (" << nsub_boundaries
39466 throw OomphLibError(error_message.str(),
39467 OOMPH_CURRENT_FUNCTION,
39468 OOMPH_EXCEPTION_LOCATION);
39473 if (this->is_mesh_distributed() && nsub_boundaries > 1)
39476 this->Boundary_was_splitted[bound] =
true;
39479 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
39481 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
39484 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
39485 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
39486 unsigned subcount = 0;
39487 std::set<Vector<double>>::iterator subit;
39488 for (subit = sub_vertex_nodes[isub].begin();
39489 subit != sub_vertex_nodes[isub].end();
39492 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
39493 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
39494 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
39495 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
39505 unsigned n_vertex = tmp_vector_vertex_node.size();
39508 vector_vertex_node.resize(n_vertex);
39509 for (
unsigned i = 0; i < n_vertex; i++)
39511 vector_vertex_node[i].resize(2);
39512 vector_vertex_node[i][0] = tmp_vector_vertex_node[i][1];
39513 vector_vertex_node[i][1] = tmp_vector_vertex_node[i][2];
39516 #ifdef OOMPH_HAS_MPI
39519 if (this->is_mesh_distributed() && nsub_boundaries > 1)
39524 sub_vector_vertex_node.resize(nsub_boundaries);
39525 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
39527 const unsigned subn_vertex = sub_tmp_vector_vertex_node[isub].size();
39529 sub_vector_vertex_node[isub].resize(subn_vertex);
39530 for (
unsigned i = 0; i < subn_vertex; i++)
39532 sub_vector_vertex_node[isub][i].resize(2);
39533 sub_vector_vertex_node[isub][i][0] =
39534 sub_tmp_vector_vertex_node[isub][i][1];
39535 sub_vector_vertex_node[isub][i][1] =
39536 sub_tmp_vector_vertex_node[isub][i][2];
39551 #ifdef OOMPH_HAS_MPI
39555 if (!this->is_mesh_distributed())
39561 Vector<double> final_vertex_of_previous_segment;
39562 unsigned n_prev_vertex =
39563 open_curve_pt->curve_section_pt(cs - 1)->nvertex();
39564 final_vertex_of_previous_segment =
39565 open_curve_pt->polyline_pt(cs - 1)->vertex_coordinate(
39566 n_prev_vertex - 1);
39568 unsigned prev_seg_boundary_id =
39569 open_curve_pt->curve_section_pt(cs - 1)->boundary_id();
39573 double error = 0.0;
39574 for (
unsigned i = 0; i < 2; i++)
39576 const double dist = final_vertex_of_previous_segment[i] -
39577 (*vector_vertex_node.begin())[i];
39578 error += dist * dist;
39580 error = sqrt(error);
39584 if (error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
39588 double rev_error = 0.0;
39589 for (
unsigned i = 0; i < 2; i++)
39591 const double dist = final_vertex_of_previous_segment[i] -
39592 (*--vector_vertex_node.end())[i];
39593 rev_error += dist * dist;
39595 rev_error = sqrt(rev_error);
39598 ToleranceForVertexMismatchInPolygons::Tolerable_error)
39607 Vector<double> initial_vertex_of_previous_segment;
39609 initial_vertex_of_previous_segment =
39610 open_curve_pt->polyline_pt(cs - 1)->vertex_coordinate(0);
39612 unsigned prev_seg_boundary_id =
39613 open_curve_pt->curve_section_pt(cs - 1)->boundary_id();
39617 double error = 0.0;
39618 for (
unsigned i = 0; i < 2; i++)
39620 const double dist = initial_vertex_of_previous_segment[i] -
39621 (*vector_vertex_node.begin())[i];
39622 error += dist * dist;
39624 error = sqrt(error);
39629 ToleranceForVertexMismatchInPolygons::Tolerable_error)
39633 double rev_error = 0.0;
39634 for (
unsigned i = 0; i < 2; i++)
39636 const double dist = initial_vertex_of_previous_segment[i] -
39637 (*--vector_vertex_node.end())[i];
39638 rev_error += dist * dist;
39640 rev_error = sqrt(rev_error);
39644 ToleranceForVertexMismatchInPolygons::Tolerable_error)
39646 std::ostringstream error_stream;
39648 <<
"The distance between the first node of the current\n"
39649 <<
"line segment (boundary " << bound
39650 <<
") and either end of "
39651 <<
"the previous line segment\n"
39652 <<
"(boundary " << prev_seg_boundary_id
39653 <<
") is bigger than"
39654 <<
" the desired tolerance "
39655 << ToleranceForVertexMismatchInPolygons::Tolerable_error
39657 <<
"This suggests that the polylines defining the "
39659 <<
"representation are not properly ordered.\n"
39660 <<
"Fail on last vertex of polyline: ("
39661 << prev_seg_boundary_id
39662 <<
") and\nfirst vertex of polyline (" << bound
39663 <<
").\nThis should have failed when first trying to "
39664 <<
"construct the\npolygon.\n";
39665 throw OomphLibError(error_stream.str(),
39666 OOMPH_CURRENT_FUNCTION,
39667 OOMPH_EXCEPTION_LOCATION);
39674 std::reverse(vector_vertex_node.begin(),
39675 vector_vertex_node.end());
39676 open_curve_pt->polyline_pt(cs - 1)->reverse();
39682 open_curve_pt->polyline_pt(cs - 1)->reverse();
39688 std::ostringstream error_stream;
39690 <<
"The distance between the first node of the current\n"
39691 <<
"line segment (boundary " << bound
39692 <<
") and either end of "
39693 <<
"the previous line segment\n"
39694 <<
"(boundary " << prev_seg_boundary_id
39695 <<
") is bigger than the "
39696 <<
"desired tolerance "
39697 << ToleranceForVertexMismatchInPolygons::Tolerable_error
39699 <<
"This suggests that the polylines defining the polygonal\n"
39700 <<
"representation are not properly ordered.\n"
39701 <<
"Fail on last vertex of polyline: ("
39702 << prev_seg_boundary_id <<
") and\nfirst vertex of polyline ("
39704 <<
"This should have failed when first trying to construct\n"
39705 <<
"the polygon.\n";
39706 throw OomphLibError(error_stream.str(),
39707 OOMPH_CURRENT_FUNCTION,
39708 OOMPH_EXCEPTION_LOCATION);
39714 std::reverse(vector_vertex_node.begin(),
39715 vector_vertex_node.end());
39732 n_vertex = vector_vertex_node.size();
39735 TriangleMeshPolyLine* tmp_polyline_pt =
39736 new TriangleMeshPolyLine(vector_vertex_node, bound);
39740 TriangleMeshCurveSection* tmp_curve_section_pt = tmp_polyline_pt;
39744 double unrefinement_tolerance =
39745 open_curve_pt->polyline_pt(cs)->unrefinement_tolerance();
39748 double refinement_tolerance =
39749 open_curve_pt->polyline_pt(cs)->refinement_tolerance();
39752 tmp_polyline_pt->set_unrefinement_tolerance(unrefinement_tolerance);
39753 tmp_polyline_pt->set_refinement_tolerance(refinement_tolerance);
39756 double maximum_length = open_curve_pt->polyline_pt(cs)->maximum_length();
39757 tmp_polyline_pt->set_maximum_length(maximum_length);
39759 #ifdef OOMPH_HAS_MPI
39762 if (this->is_mesh_distributed())
39768 this->copy_connection_information(open_curve_pt->polyline_pt(cs),
39769 tmp_curve_section_pt);
39777 this->copy_connection_information(open_curve_pt->polyline_pt(cs),
39778 tmp_curve_section_pt);
39784 bool delete_it_on_destructor =
false;
39786 std::set<TriangleMeshCurveSection*>::iterator it =
39787 this->Free_curve_section_pt.find(open_curve_pt->curve_section_pt(cs));
39789 if (it != this->Free_curve_section_pt.end())
39791 this->Free_curve_section_pt.erase(it);
39792 delete open_curve_pt->curve_section_pt(cs);
39793 delete_it_on_destructor =
true;
39798 open_curve_pt->curve_section_pt(cs) = tmp_polyline_pt;
39801 this->Boundary_curve_section_pt[bound] =
39802 open_curve_pt->curve_section_pt(cs);
39804 if (delete_it_on_destructor)
39806 this->Free_curve_section_pt.insert(open_curve_pt->curve_section_pt(cs));
39809 #ifdef OOMPH_HAS_MPI
39812 if (this->is_mesh_distributed() && nsub_boundaries == 1)
39815 this->Boundary_marked_as_shared_boundary[bound].clear();
39818 this->Boundary_marked_as_shared_boundary[bound].push_back(
39819 internal_to_shared_boundary[0]);
39823 else if (this->is_mesh_distributed() && nsub_boundaries > 1)
39829 this->Boundary_subpolylines[bound].clear();
39831 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
39834 this->Boundary_marked_as_shared_boundary[bound].clear();
39837 this->Boundary_marked_as_shared_boundary[bound].resize(nsub_boundaries);
39838 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
39842 TriangleMeshPolyLine* sub_tmp_polyline_pt =
39843 new TriangleMeshPolyLine(sub_vector_vertex_node[isub], bound, isub);
39847 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
39851 this->Boundary_marked_as_shared_boundary[bound][isub] =
39852 internal_to_shared_boundary[isub];
39861 TriangleMeshCurveSection* tmp_sub_curve_section_pt =
39862 sub_tmp_polyline_pt;
39863 this->copy_connection_information_to_sub_polylines(
39864 tmp_curve_section_pt, tmp_sub_curve_section_pt);
39874 delete mesh_geom_obj_pt;
39879 for (
unsigned p = 0; p < ncurve_section; p++)
39881 face_mesh_pt[p]->flush_node_storage();
39882 delete face_mesh_pt[p];
39885 return update_was_performed;
39888 #ifdef OOMPH_HAS_MPI
39893 template<
class ELEMENT>
39895 Vector<TriangleMeshPolyLine*>& vector_polyline_pt,
39896 const Vector<double>& target_areas)
39900 unsigned update_was_performed =
false;
39903 const unsigned n_polylines = vector_polyline_pt.size();
39904 for (
unsigned pp = 0; pp < n_polylines; pp++)
39907 const unsigned shd_bnd_id = vector_polyline_pt[pp]->boundary_id();
39910 const unsigned chunk = vector_polyline_pt[pp]->boundary_chunk();
39918 std::map<FiniteElement*, FiniteElement*> face_ele_pt_to_bulk_element_pt;
39921 Vector<FiniteElement*> halo_shared_face_ele_pt;
39923 Vector<FiniteElement*> nonhalo_shared_face_ele_pt;
39927 const unsigned nshared_bound_ele =
39928 this->nshared_boundary_element(shd_bnd_id);
39932 for (
unsigned e = 0; e < nshared_bound_ele; e++)
39935 FiniteElement* bulk_ele_pt =
39936 this->shared_boundary_element_pt(shd_bnd_id, e);
39939 int face_index = this->face_index_at_shared_boundary(shd_bnd_id, e);
39943 FiniteElement* face_ele_pt =
39944 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
39948 face_ele_pt_to_bulk_element_pt[face_ele_pt] = bulk_ele_pt;
39951 if (!bulk_ele_pt->is_halo())
39954 nonhalo_shared_face_ele_pt.push_back(face_ele_pt);
39959 halo_shared_face_ele_pt.push_back(face_ele_pt);
39966 Vector<Vector<FiniteElement*>> unsorted_shared_bulk_ele_pt;
39969 std::map<FiniteElement*, bool> shared_face_done;
39972 const unsigned nnonhalo_face_shared_ele =
39973 nonhalo_shared_face_ele_pt.size();
39976 const unsigned nhalo_face_shared_ele = halo_shared_face_ele_pt.size();
39981 if (nshared_bound_ele / 2 != nnonhalo_face_shared_ele)
39983 std::ostringstream error_message;
39985 <<
"The number of shared boundary elements (" << nshared_bound_ele
39986 <<
") is not the double\nof the number of unsorted NONHALO shared "
39987 <<
"face boundary elements (" << nnonhalo_face_shared_ele <<
")\n"
39988 <<
"for the current boundary (" << shd_bnd_id <<
")\n\n";
39989 throw OomphLibError(error_message.str(),
39990 OOMPH_CURRENT_FUNCTION,
39991 OOMPH_EXCEPTION_LOCATION);
39996 if (nshared_bound_ele / 2 != nhalo_face_shared_ele)
39998 std::ostringstream error_message;
40000 <<
"The number of shared boundary elements (" << nshared_bound_ele
40001 <<
") is not the double\nof the number of unsorted HALO shared "
40002 <<
"face boundary elements (" << nhalo_face_shared_ele <<
")\n"
40003 <<
"for the current boundary (" << shd_bnd_id <<
")\n\n";
40004 throw OomphLibError(error_message.str(),
40005 OOMPH_CURRENT_FUNCTION,
40006 OOMPH_EXCEPTION_LOCATION);
40013 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
40016 FiniteElement* nonhalo_face_ele_pt = nonhalo_shared_face_ele_pt[inh];
40019 const unsigned nnodes_nh = nonhalo_face_ele_pt->nnode();
40021 Node* nh_first_node_pt = nonhalo_face_ele_pt->node_pt(0);
40022 Node* nh_last_node_pt = nonhalo_face_ele_pt->node_pt(nnodes_nh - 1);
40026 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
40029 FiniteElement* halo_face_ele_pt = halo_shared_face_ele_pt[ih];
40032 if (!shared_face_done[halo_face_ele_pt])
40035 const unsigned nnodes_h = halo_face_ele_pt->nnode();
40037 Node* h_first_node_pt = halo_face_ele_pt->node_pt(0);
40038 Node* h_last_node_pt = halo_face_ele_pt->node_pt(nnodes_h - 1);
40042 if (nh_first_node_pt == h_first_node_pt &&
40043 nh_last_node_pt == h_last_node_pt)
40046 Vector<FiniteElement*> tmp_bulk_element_pt;
40049 FiniteElement* nonhalo_bulk_ele_pt =
40050 face_ele_pt_to_bulk_element_pt[nonhalo_face_ele_pt];
40051 FiniteElement* halo_bulk_ele_pt =
40052 face_ele_pt_to_bulk_element_pt[halo_face_ele_pt];
40055 tmp_bulk_element_pt.push_back(nonhalo_bulk_ele_pt);
40056 tmp_bulk_element_pt.push_back(halo_bulk_ele_pt);
40059 unsorted_shared_bulk_ele_pt.push_back(tmp_bulk_element_pt);
40062 shared_face_done[nonhalo_face_ele_pt] =
true;
40063 shared_face_done[halo_face_ele_pt] =
true;
40069 else if (nh_first_node_pt == h_last_node_pt &&
40070 nh_last_node_pt == h_first_node_pt)
40073 Vector<FiniteElement*> tmp_bulk_element_pt;
40076 FiniteElement* nonhalo_bulk_ele_pt =
40077 face_ele_pt_to_bulk_element_pt[nonhalo_face_ele_pt];
40078 FiniteElement* halo_bulk_ele_pt =
40079 face_ele_pt_to_bulk_element_pt[halo_face_ele_pt];
40082 tmp_bulk_element_pt.push_back(nonhalo_bulk_ele_pt);
40083 tmp_bulk_element_pt.push_back(halo_bulk_ele_pt);
40086 unsorted_shared_bulk_ele_pt.push_back(tmp_bulk_element_pt);
40089 shared_face_done[nonhalo_face_ele_pt] =
true;
40090 shared_face_done[halo_face_ele_pt] =
true;
40112 const unsigned nunsorted_shared_bulk_ele =
40113 unsorted_shared_bulk_ele_pt.size();
40117 if (nshared_bound_ele / 2 != nunsorted_shared_bulk_ele)
40119 std::ostringstream error_message;
40121 <<
"The number of shared boundary elements (" << nshared_bound_ele
40122 <<
") is not the double\nof the number of unsorted shared bulk "
40123 <<
"boundary elements (" << nunsorted_shared_bulk_ele <<
")\n"
40124 <<
"for the current boundary (" << shd_bnd_id <<
")\n\n";
40125 throw OomphLibError(error_message.str(),
40126 OOMPH_CURRENT_FUNCTION,
40127 OOMPH_EXCEPTION_LOCATION);
40132 if ((nnonhalo_face_shared_ele + nhalo_face_shared_ele) !=
40133 shared_face_done.size())
40135 std::ostringstream error_message;
40136 error_message <<
"The number of DONE shared boundary face elements ("
40137 << shared_face_done.size()
40138 <<
") is not the same\n as the sum of"
40139 <<
"the nonhalo face shared boundary elements ("
40140 << nnonhalo_face_shared_ele
40141 <<
")\nand the halo face shared "
40142 <<
"boundary elements (" << nhalo_face_shared_ele
40144 <<
"current boundary (" << shd_bnd_id <<
")\n\n";
40145 throw OomphLibError(error_message.str(),
40146 OOMPH_CURRENT_FUNCTION,
40147 OOMPH_EXCEPTION_LOCATION);
40152 shared_face_done.clear();
40155 unsigned nsorted_face_ele = 0;
40159 std::list<Node*> sorted_nodes;
40162 std::list<FiniteElement*> sorted_shared_bound_elements_pt;
40165 FiniteElement* root_face_ele_pt = nonhalo_shared_face_ele_pt[0];
40166 nsorted_face_ele++;
40169 shared_face_done[root_face_ele_pt] =
true;
40172 const unsigned nnodes_root = root_face_ele_pt->nnode();
40173 Node* first_node_pt = root_face_ele_pt->node_pt(0);
40174 Node* last_node_pt = root_face_ele_pt->node_pt(nnodes_root - 1);
40177 sorted_nodes.push_back(first_node_pt);
40178 sorted_nodes.push_back(last_node_pt);
40181 sorted_shared_bound_elements_pt.push_back(
40182 unsorted_shared_bulk_ele_pt[0][0]);
40183 sorted_shared_bound_elements_pt.push_back(
40184 unsorted_shared_bulk_ele_pt[0][1]);
40187 while (nsorted_face_ele < nnonhalo_face_shared_ele)
40190 bool node_added =
false;
40194 for (
unsigned iface = 1; iface < nnonhalo_face_shared_ele; iface++)
40196 FiniteElement* tmp_shared_face_ele_pt =
40197 nonhalo_shared_face_ele_pt[iface];
40200 if (!shared_face_done[tmp_shared_face_ele_pt])
40203 const unsigned tmp_nnodes = tmp_shared_face_ele_pt->nnode();
40206 Node* left_node_pt = tmp_shared_face_ele_pt->node_pt(0);
40207 Node* right_node_pt =
40208 tmp_shared_face_ele_pt->node_pt(tmp_nnodes - 1);
40210 if (left_node_pt == first_node_pt)
40213 sorted_nodes.push_front(right_node_pt);
40214 first_node_pt = right_node_pt;
40218 sorted_shared_bound_elements_pt.push_front(
40219 unsorted_shared_bulk_ele_pt[iface][1]);
40220 sorted_shared_bound_elements_pt.push_front(
40221 unsorted_shared_bulk_ele_pt[iface][0]);
40223 else if (left_node_pt == last_node_pt)
40226 sorted_nodes.push_back(right_node_pt);
40227 last_node_pt = right_node_pt;
40231 sorted_shared_bound_elements_pt.push_back(
40232 unsorted_shared_bulk_ele_pt[iface][0]);
40233 sorted_shared_bound_elements_pt.push_back(
40234 unsorted_shared_bulk_ele_pt[iface][1]);
40236 else if (right_node_pt == first_node_pt)
40239 sorted_nodes.push_front(left_node_pt);
40240 first_node_pt = left_node_pt;
40244 sorted_shared_bound_elements_pt.push_front(
40245 unsorted_shared_bulk_ele_pt[iface][1]);
40246 sorted_shared_bound_elements_pt.push_front(
40247 unsorted_shared_bulk_ele_pt[iface][0]);
40249 else if (right_node_pt == last_node_pt)
40252 sorted_nodes.push_back(left_node_pt);
40253 last_node_pt = left_node_pt;
40257 sorted_shared_bound_elements_pt.push_back(
40258 unsorted_shared_bulk_ele_pt[iface][0]);
40259 sorted_shared_bound_elements_pt.push_back(
40260 unsorted_shared_bulk_ele_pt[iface][1]);
40267 shared_face_done[tmp_shared_face_ele_pt] =
true;
40268 nsorted_face_ele++;
40285 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
40287 delete nonhalo_shared_face_ele_pt[inh];
40288 nonhalo_shared_face_ele_pt[inh] = 0;
40292 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
40294 delete halo_shared_face_ele_pt[ih];
40295 halo_shared_face_ele_pt[ih] = 0;
40303 const unsigned n_nodes = sorted_nodes.size();
40306 Vector<Vector<double>> polyline_vertices(n_nodes);
40309 unsigned counter = 0;
40310 for (std::list<Node*>::iterator it_nodes = sorted_nodes.begin();
40311 it_nodes != sorted_nodes.end();
40314 polyline_vertices[counter].resize(2);
40315 polyline_vertices[counter][0] = (*it_nodes)->x(0);
40316 polyline_vertices[counter][1] = (*it_nodes)->x(1);
40325 Vector<FiniteElement*> sorted_shared_ele_pt;
40326 for (std::list<FiniteElement*>::iterator it_ele =
40327 sorted_shared_bound_elements_pt.begin();
40328 it_ele != sorted_shared_bound_elements_pt.end();
40331 sorted_shared_ele_pt.push_back((*it_ele));
40335 const unsigned n_shared_target_areas = sorted_shared_ele_pt.size();
40336 Vector<double> sorted_shared_target_areas(n_shared_target_areas);
40339 std::map<std::pair<GeneralisedElement*, unsigned>,
bool> shared_ele_done;
40342 unsigned count_found_shared_element = 0;
40345 const unsigned nele = this->nelement();
40349 for (
unsigned e = 0; e < nele; e++)
40351 GeneralisedElement* current_ele_pt = this->element_pt(e);
40354 for (
unsigned s = 0; s < n_shared_target_areas; s++)
40357 GeneralisedElement* current_shared_ele_pt = sorted_shared_ele_pt[s];
40359 std::pair<GeneralisedElement*, unsigned> pair_gen_ele_idx =
40360 std::make_pair(current_shared_ele_pt, s);
40361 if (!shared_ele_done[pair_gen_ele_idx])
40364 if (current_ele_pt == current_shared_ele_pt)
40367 sorted_shared_target_areas[s] = target_areas[e];
40369 shared_ele_done[pair_gen_ele_idx] =
true;
40371 count_found_shared_element++;
40377 if (count_found_shared_element == n_shared_target_areas)
40387 if (count_found_shared_element != n_shared_target_areas)
40389 std::ostringstream error_message;
40390 error_message <<
"The number of found target areas ("
40391 << count_found_shared_element
40392 <<
") is different from the "
40393 <<
"total number\nof target areas ("
40394 << n_shared_target_areas <<
") in shared boundary ("
40395 << shd_bnd_id <<
")\n\n";
40396 throw OomphLibError(error_message.str(),
40397 OOMPH_CURRENT_FUNCTION,
40398 OOMPH_EXCEPTION_LOCATION);
40403 const unsigned n_vertices = n_nodes;
40406 const unsigned n_segments = vector_polyline_pt[pp]->nsegment();
40415 if (n_segments != n_vertices - 1)
40417 std::ostringstream error_message;
40419 <<
"The number of segments from the current shared polyline "
40420 <<
"(" << n_segments <<
") does not\ncorrespond with the number of "
40421 <<
"sorted vertices (" << n_vertices - 1
40422 <<
") of the current shared\n"
40424 throw OomphLibError(error_message.str(),
40425 OOMPH_CURRENT_FUNCTION,
40426 OOMPH_EXCEPTION_LOCATION);
40431 if (n_segments != n_shared_target_areas / 2)
40433 std::ostringstream error_message;
40435 <<
"The number of segments for the current sorting of edges "
40436 <<
"(" << n_segments <<
") is different\nfrom the number of "
40437 <<
"target areas (" << n_shared_target_areas / 2 <<
")\n\n";
40438 throw OomphLibError(error_message.str(),
40439 OOMPH_CURRENT_FUNCTION,
40440 OOMPH_EXCEPTION_LOCATION);
40452 Vector<double> polyline_target_area(n_segments);
40454 for (
unsigned s = 0; s < n_segments; s++)
40457 polyline_target_area[s] =
40458 std::min(sorted_shared_target_areas[s * 2],
40459 sorted_shared_target_areas[(s * 2) + 1]);
40466 if (polyline_vertices[n_vertices - 1][1] < polyline_vertices[0][1])
40468 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
40469 std::reverse(polyline_target_area.begin(), polyline_target_area.end());
40471 else if (polyline_vertices[n_vertices - 1][1] == polyline_vertices[0][1])
40473 if (polyline_vertices[n_vertices - 1][0] < polyline_vertices[0][0])
40475 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
40476 std::reverse(polyline_target_area.begin(),
40477 polyline_target_area.end());
40483 bool unrefinement_applied =
false;
40486 if (n_vertices > 3)
40488 unrefinement_applied =
40489 unrefine_shared_boundary_constrained_by_target_area(
40490 shd_bnd_id, chunk, polyline_vertices, polyline_target_area);
40494 bool refinement_applied =
40495 refine_shared_boundary_constrained_by_target_area(polyline_vertices,
40496 polyline_target_area);
40499 update_was_performed |= (unrefinement_applied || refinement_applied);
40505 TriangleMeshPolyLine* new_polyline_pt =
40506 new TriangleMeshPolyLine(polyline_vertices, shd_bnd_id);
40509 TriangleMeshCurveSection* curve_section_pt = vector_polyline_pt[pp];
40513 this->copy_connection_information(curve_section_pt, new_polyline_pt);
40518 bool delete_it_on_destructor =
false;
40522 std::set<TriangleMeshCurveSection*>::iterator it =
40523 this->Free_curve_section_pt.find(curve_section_pt);
40525 if (it != this->Free_curve_section_pt.end())
40527 this->Free_curve_section_pt.erase(it);
40528 delete curve_section_pt;
40529 delete_it_on_destructor =
true;
40533 vector_polyline_pt[pp] = new_polyline_pt;
40536 TriangleMeshCurveSection* new_curve_section_pt = vector_polyline_pt[pp];
40539 this->Boundary_curve_section_pt[shd_bnd_id] = new_curve_section_pt;
40541 if (delete_it_on_destructor)
40543 this->Free_curve_section_pt.insert(new_curve_section_pt);
40548 return update_was_performed;
40557 template<
class ELEMENT>
40562 Vector<Vector<double>>& vector_bnd_vertices,
40563 double& unrefinement_tolerance,
40564 Vector<double>& area_constraint)
40567 std::set<Vector<double>> no_delete_vertex;
40570 const bool boundary_receive_connections =
40571 this->boundary_connections(b, c, no_delete_vertex);
40575 bool unrefinement_applied =
false;
40578 if (!Do_boundary_unrefinement_constrained_by_target_areas)
40580 return unrefinement_applied;
40594 unsigned n_vertex = vector_bnd_vertices.size();
40597 const double constant_value = 4.0 / sqrt(3.0);
40603 for (
unsigned i = 1; i < n_vertex - 1; i += 2)
40605 if (area_constraint[i - 1] > 0 && area_constraint[i] > 0)
40607 const double local_zeta_first = vector_bnd_vertices[i - 1][0];
40608 const double local_zeta_last = vector_bnd_vertices[i + 1][0];
40609 const double local_length_zeta =
40610 std::fabs(local_zeta_last - local_zeta_first);
40612 const double x1 = vector_bnd_vertices[i - 1][1];
40613 const double y1 = vector_bnd_vertices[i - 1][2];
40614 const double x2 = vector_bnd_vertices[i + 1][1];
40615 const double y2 = vector_bnd_vertices[i + 1][2];
40616 const double local_length =
40617 sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
40619 const double x_m = vector_bnd_vertices[i][1];
40620 const double y_m = vector_bnd_vertices[i][2];
40622 const double average_area_constraint =
40623 (area_constraint[i - 1] + area_constraint[i]) / 2.0;
40627 const double length_side =
40628 sqrt(constant_value * average_area_constraint);
40630 const double length_side_zeta =
40631 (local_length_zeta * length_side) / local_length;
40634 if ((length_side_zeta / local_length_zeta) > 1.0)
40642 double a_x = vector_bnd_vertices[i - 1][1];
40643 double a_y = vector_bnd_vertices[i - 1][2];
40644 double b_x = vector_bnd_vertices[i][1];
40645 double b_y = vector_bnd_vertices[i][2];
40646 double c_x = vector_bnd_vertices[i + 1][1];
40647 double c_y = vector_bnd_vertices[i + 1][2];
40649 double a = b_x - a_x;
40650 double b = b_y - a_y;
40651 double c = c_x - a_x;
40652 double d = c_y - a_y;
40654 double e = a * (a_x + b_x) + b * (a_y + b_y);
40655 double f = c * (a_x + c_x) + d * (a_y + c_y);
40657 double g = 2.0 * (a * (c_y - b_y) - b * (c_x - b_x));
40659 bool do_it =
false;
40660 if (std::fabs(g) < 1.0e-14)
40666 double p_x = (d * e - b * f) / g;
40667 double p_y = (a * f - c * e) / g;
40669 double r = sqrt(pow((a_x - p_x), 2) + pow((a_y - p_y), 2));
40671 double rhalfca_x = 0.5 * (a_x - c_x);
40672 double rhalfca_y = 0.5 * (a_y - c_y);
40674 double halfca_squared = pow(rhalfca_x, 2) + pow(rhalfca_y, 2);
40676 double sticky_out_bit =
40677 r - sqrt(std::fabs((r * r) - halfca_squared));
40682 if ((sticky_out_bit / (2.0 * sqrt(halfca_squared))) <
40683 unrefinement_tolerance)
40691 if (do_it && boundary_receive_connections)
40694 for (std::set<Vector<double>>::iterator it =
40695 no_delete_vertex.begin();
40696 it != no_delete_vertex.end();
40701 const double x = (*it)[0];
40702 const double y = (*it)[1];
40703 double error = (x_m - x) * (x_m - x) + (y_m - y) * (y_m - y);
40704 error = sqrt(error);
40707 ToleranceForVertexMismatchInPolygons::Tolerable_error)
40720 vector_bnd_vertices[i].resize(0);
40728 Vector<Vector<double>> compact_vector;
40731 Vector<double> compact_area_constraint;
40734 for (
unsigned i = 0; i < n_vertex; i++)
40737 if (vector_bnd_vertices[i].size() != 0)
40739 compact_vector.push_back(vector_bnd_vertices[i]);
40745 unsigned nsize_target = area_constraint.size();
40746 if (nsize_target == 1)
40749 compact_area_constraint.push_back(area_constraint[0]);
40753 for (
unsigned i = 1; i < n_vertex; i += 2)
40757 if (vector_bnd_vertices[i].size() != 0)
40759 compact_area_constraint.push_back(area_constraint[i - 1]);
40761 if (i < nsize_target)
40763 compact_area_constraint.push_back(area_constraint[i]);
40770 double new_area_constraint =
40771 (area_constraint[i - 1] + area_constraint[i]) / 2.0;
40772 compact_area_constraint.push_back(new_area_constraint);
40779 if (n_vertex != compact_vector.size())
40781 unrefinement_applied =
true;
40785 n_vertex = compact_vector.size();
40786 vector_bnd_vertices.resize(n_vertex);
40787 for (
unsigned i = 0; i < n_vertex; i++)
40789 vector_bnd_vertices[i].resize(3);
40790 vector_bnd_vertices[i][0] = compact_vector[i][0];
40791 vector_bnd_vertices[i][1] = compact_vector[i][1];
40792 vector_bnd_vertices[i][2] = compact_vector[i][2];
40796 unsigned ntarget_areas = compact_area_constraint.size();
40797 area_constraint.resize(ntarget_areas);
40798 for (
unsigned i = 0; i < ntarget_areas; i++)
40800 area_constraint[i] = compact_area_constraint[i];
40805 return unrefinement_applied;
40813 template<
class ELEMENT>
40816 MeshAsGeomObject* mesh_geom_obj_pt,
40817 Vector<Vector<double>>& vector_bnd_vertices,
40818 double& refinement_tolerance,
40819 Vector<double>& area_constraint)
40823 bool refinement_applied =
false;
40826 if (!Do_boundary_refinement_constrained_by_target_areas)
40828 return refinement_applied;
40832 unsigned n_vertex = vector_bnd_vertices.size();
40835 const double constant_value = 4.0 / sqrt(3.0);
40841 Vector<Vector<double>> new_vector;
40845 for (
unsigned i = 0; i < n_vertex - 1; i++)
40848 new_vector.push_back(vector_bnd_vertices[i]);
40850 if (area_constraint[i] > 0)
40852 double local_zeta_first = vector_bnd_vertices[i][0];
40853 double local_zeta_last = vector_bnd_vertices[i + 1][0];
40854 const double local_length_zeta =
40855 std::fabs(local_zeta_last - local_zeta_first);
40860 if (local_zeta_first > local_zeta_last)
40862 const double tmp_zeta = local_zeta_first;
40863 local_zeta_first = local_zeta_last;
40864 local_zeta_last = tmp_zeta;
40867 const double x1 = vector_bnd_vertices[i][1];
40868 const double y1 = vector_bnd_vertices[i][2];
40869 const double x2 = vector_bnd_vertices[i + 1][1];
40870 const double y2 = vector_bnd_vertices[i + 1][2];
40871 const double local_length =
40872 sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
40875 const double length_side = sqrt(constant_value * area_constraint[i]);
40876 const double length_side_zeta =
40877 (local_length_zeta * length_side) / local_length;
40880 const double n_seg_double = length_side_zeta / local_length_zeta;
40883 unsigned n_seg = 1;
40886 n_seg +=
static_cast<unsigned>(std::floor(1.0 / n_seg_double));
40893 double zeta_increment = (local_length_zeta) / ((
double)n_seg);
40895 Vector<double> zeta(1);
40897 for (
unsigned s = 1; s < n_seg; s++)
40900 zeta[0] = local_zeta_first + zeta_increment * double(s);
40901 Vector<double> vertex(2);
40902 mesh_geom_obj_pt->position(zeta, vertex);
40905 Vector<double> new_node(3);
40906 new_node[0] = zeta[0];
40907 new_node[1] = vertex[0];
40908 new_node[2] = vertex[1];
40911 new_vector.push_back(new_node);
40922 new_vector.push_back(vector_bnd_vertices[n_vertex - 1]);
40927 n_vertex = new_vector.size();
40928 if (n_vertex != vector_bnd_vertices.size())
40930 refinement_applied =
true;
40934 vector_bnd_vertices.resize(n_vertex);
40935 for (
unsigned i = 0; i < n_vertex; i++)
40937 vector_bnd_vertices[i].resize(3);
40938 vector_bnd_vertices[i][0] = new_vector[i][0];
40939 vector_bnd_vertices[i][1] = new_vector[i][1];
40940 vector_bnd_vertices[i][2] = new_vector[i][2];
40945 return refinement_applied;
40955 template<
class ELEMENT>
40960 Vector<Vector<double>>& vector_bnd_vertices,
40961 Vector<double>& area_constraint)
40964 std::set<Vector<double>> no_delete_vertex;
40967 const bool boundary_receive_connections =
40968 this->boundary_connections(b, c, no_delete_vertex);
40972 bool unrefinement_applied =
false;
40975 if (!Do_shared_boundary_unrefinement_constrained_by_target_areas)
40977 return unrefinement_applied;
40993 unsigned n_vertex = vector_bnd_vertices.size();
40996 const double constant_value = 4.0 / sqrt(3.0);
41002 for (
unsigned i = 1; i < n_vertex - 1; i += 2)
41006 if (area_constraint[i - 1] > 0 && area_constraint[i] > 0)
41009 const double x1 = vector_bnd_vertices[i - 1][0];
41010 const double y1 = vector_bnd_vertices[i - 1][1];
41012 const double x2 = vector_bnd_vertices[i + 1][0];
41013 const double y2 = vector_bnd_vertices[i + 1][1];
41016 const double local_length =
41017 sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
41020 const double x_m = vector_bnd_vertices[i][0];
41021 const double y_m = vector_bnd_vertices[i][1];
41024 const double average_area_constraint =
41025 (area_constraint[i - 1] + area_constraint[i]) / 2.0;
41029 const double length_side =
41030 sqrt(constant_value * average_area_constraint);
41033 if ((length_side / local_length) > 1.0)
41039 if (do_it && boundary_receive_connections)
41042 for (std::set<Vector<double>>::iterator it =
41043 no_delete_vertex.begin();
41044 it != no_delete_vertex.end();
41049 const double x = (*it)[0];
41050 const double y = (*it)[1];
41051 double error = (x_m - x) * (x_m - x) + (y_m - y) * (y_m - y);
41052 error = sqrt(error);
41055 ToleranceForVertexMismatchInPolygons::Tolerable_error)
41068 vector_bnd_vertices[i].resize(0);
41078 Vector<Vector<double>> compact_vector;
41081 Vector<double> compact_area_constraint;
41084 for (
unsigned i = 0; i < n_vertex; i++)
41087 if (vector_bnd_vertices[i].size() != 0)
41089 compact_vector.push_back(vector_bnd_vertices[i]);
41095 unsigned n_area_constraint = area_constraint.size();
41096 if (n_area_constraint == 1)
41099 compact_area_constraint.push_back(area_constraint[0]);
41103 for (
unsigned i = 1; i < n_vertex; i += 2)
41107 if (vector_bnd_vertices[i].size() != 0)
41109 compact_area_constraint.push_back(area_constraint[i - 1]);
41111 if (i < n_area_constraint)
41113 compact_area_constraint.push_back(area_constraint[i]);
41120 const double new_area_constraint =
41121 (area_constraint[i - 1] + area_constraint[i]) / 2.0;
41122 compact_area_constraint.push_back(new_area_constraint);
41129 if (n_vertex != compact_vector.size())
41131 unrefinement_applied =
true;
41135 n_vertex = compact_vector.size();
41136 vector_bnd_vertices.resize(n_vertex);
41137 for (
unsigned i = 0; i < n_vertex; i++)
41139 vector_bnd_vertices[i].resize(2);
41140 vector_bnd_vertices[i][0] = compact_vector[i][0];
41141 vector_bnd_vertices[i][1] = compact_vector[i][1];
41145 unsigned ntarget_areas = compact_area_constraint.size();
41146 area_constraint.resize(ntarget_areas);
41147 for (
unsigned i = 0; i < ntarget_areas; i++)
41149 area_constraint[i] = compact_area_constraint[i];
41154 return unrefinement_applied;
41164 template<
class ELEMENT>
41167 Vector<Vector<double>>& vector_bnd_vertices,
41168 Vector<double>& area_constraint)
41172 bool refinement_applied =
false;
41175 if (!Do_shared_boundary_refinement_constrained_by_target_areas)
41177 return refinement_applied;
41181 unsigned nsegments = vector_bnd_vertices.size() - 1;
41185 Vector<Vector<double>> tmp_bnd_vertices;
41188 const double constant_value = 4.0 / sqrt(3.0);
41190 for (
unsigned s = 0; s < nsegments; s++)
41192 Vector<double> left_vertex = vector_bnd_vertices[s];
41193 Vector<double> right_vertex = vector_bnd_vertices[s + 1];
41196 const double x1 = left_vertex[0];
41197 const double y1 = left_vertex[1];
41198 const double x2 = right_vertex[0];
41199 const double y2 = right_vertex[1];
41202 const double segment_length =
41203 sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
41206 const double new_segment_length =
41207 sqrt(constant_value * area_constraint[s]);
41210 const double n_seg_double = new_segment_length / segment_length;
41215 nseg +=
static_cast<unsigned>(std::floor(1.0 / n_seg_double));
41219 tmp_bnd_vertices.push_back(left_vertex);
41226 double incrementx = (right_vertex[0] - left_vertex[0]) / (
double)(nseg);
41227 double incrementy = (right_vertex[1] - left_vertex[1]) / (
double)(nseg);
41228 for (
unsigned i = 1; i < nseg; i++)
41230 Vector<double> tmp_vertex(2);
41231 tmp_vertex[0] = left_vertex[0] + incrementx * i;
41232 tmp_vertex[1] = left_vertex[1] + incrementy * i;
41233 tmp_bnd_vertices.push_back(tmp_vertex);
41241 tmp_bnd_vertices.push_back(vector_bnd_vertices[nsegments]);
41246 nsegments = tmp_bnd_vertices.size() - 1;
41247 if (nsegments != vector_bnd_vertices.size() - 1)
41249 refinement_applied =
true;
41252 vector_bnd_vertices.resize(nsegments + 1);
41253 for (
unsigned i = 0; i < nsegments + 1; i++)
41255 vector_bnd_vertices[i].resize(2);
41256 vector_bnd_vertices[i][0] = tmp_bnd_vertices[i][0];
41257 vector_bnd_vertices[i][1] = tmp_bnd_vertices[i][1];
41261 return refinement_applied;
41267 template<
class ELEMENT>
41269 TriangleMeshPolygon*& polygon_pt)
41277 Vector<Mesh*> face_mesh_pt;
41278 get_face_mesh_representation(polygon_pt, face_mesh_pt);
41282 Vector<double> vertex_coord(3);
41283 Vector<double> bound_left(1);
41284 Vector<double> bound_right(1);
41286 const unsigned n_polyline = polygon_pt->npolyline();
41289 for (
unsigned p = 0; p < n_polyline; p++)
41297 MeshAsGeomObject* mesh_geom_obj_pt =
41298 new MeshAsGeomObject(face_mesh_pt[p]);
41303 std::set<Vector<double>> vertex_nodes;
41307 Vector<Vector<double>> tmp_vector_vertex_node;
41312 Vector<Vector<double>> vector_vertex_node;
41314 #ifdef OOMPH_HAS_MPI
41320 Vector<std::set<Vector<double>>> sub_vertex_nodes;
41324 Vector<Vector<Vector<double>>> sub_tmp_vector_vertex_node;
41329 Vector<Vector<Vector<double>>> sub_vector_vertex_node;
41334 unsigned bound = polygon_pt->curve_section_pt(p)->boundary_id();
41341 const unsigned nface_element = face_mesh_pt[p]->nelement();
41345 Vector<FiniteElement*> non_halo_face_element_pt;
41347 std::map<FiniteElement*, unsigned> face_element_index_on_boundary;
41349 for (
unsigned ef = 0; ef < nface_element; ++ef)
41351 FiniteElement* ele_face_pt = face_mesh_pt[p]->finite_element_pt(ef);
41353 #ifdef OOMPH_HAS_MPI
41354 if (this->is_mesh_distributed())
41357 if (ele_face_pt->is_halo())
41364 non_halo_face_element_pt.push_back(ele_face_pt);
41365 face_element_index_on_boundary[ele_face_pt] = ef;
41369 const unsigned nnon_halo_face_element = non_halo_face_element_pt.size();
41372 std::map<FiniteElement*, bool> face_element_done;
41375 unsigned nsorted_face_elements = 0;
41377 #ifdef OOMPH_HAS_MPI
41379 unsigned nsub_boundaries = 0;
41384 while (nsorted_face_elements < nnon_halo_face_element)
41387 FiniteElement* ele_face_pt = 0;
41389 bool found_initial_face_element =
false;
41392 unsigned iface = 0;
41393 for (iface = 0; iface < nnon_halo_face_element; iface++)
41395 ele_face_pt = non_halo_face_element_pt[iface];
41397 if (!face_element_done[ele_face_pt])
41400 found_initial_face_element =
true;
41402 nsorted_face_elements++;
41409 if (!found_initial_face_element)
41411 std::ostringstream error_message;
41412 error_message <<
"Could not find an initial face element for the "
41413 "current segment\n";
41415 throw OomphLibError(
41416 error_message.str(),
41417 "RefineableTriangleMesh::update_polygon_after_restart()",
41418 OOMPH_EXCEPTION_LOCATION);
41425 std::set<Vector<double>> local_vertex_nodes;
41429 Vector<Vector<double>> local_tmp_vector_vertex_node;
41437 unsigned nnode = ele_face_pt->nnode();
41440 ele_face_pt->node_pt(0)->get_coordinates_on_boundary(bound, bound_left);
41441 vertex_coord[0] = bound_left[0];
41444 for (
unsigned i = 0; i < 2; i++)
41446 vertex_coord[i + 1] = ele_face_pt->node_pt(0)->x(i);
41448 local_vertex_nodes.insert(vertex_coord);
41452 ele_face_pt->node_pt(nnode - 1)->get_coordinates_on_boundary(
41453 bound, bound_right);
41454 vertex_coord[0] = bound_right[0];
41457 for (
unsigned i = 0; i < 2; i++)
41459 vertex_coord[i + 1] = ele_face_pt->node_pt(nnode - 1)->x(i);
41461 local_vertex_nodes.insert(vertex_coord);
41464 Node* first_node_pt = ele_face_pt->node_pt(0);
41465 Node* last_node_pt = ele_face_pt->node_pt(nnode - 1);
41468 face_element_done[ele_face_pt] =
true;
41476 bool face_element_added =
false;
41485 for (
unsigned iiface = iface; iiface < nnon_halo_face_element;
41488 face_element_added =
false;
41489 ele_face_pt = non_halo_face_element_pt[iiface];
41490 if (!face_element_done[ele_face_pt])
41493 nnode = ele_face_pt->nnode();
41494 Node* left_node_pt = ele_face_pt->node_pt(0);
41495 Node* right_node_pt = ele_face_pt->node_pt(nnode - 1);
41497 if (left_node_pt == first_node_pt)
41499 first_node_pt = right_node_pt;
41500 face_element_added =
true;
41502 else if (left_node_pt == last_node_pt)
41504 last_node_pt = right_node_pt;
41505 face_element_added =
true;
41507 else if (right_node_pt == first_node_pt)
41509 first_node_pt = left_node_pt;
41510 face_element_added =
true;
41512 else if (right_node_pt == last_node_pt)
41514 last_node_pt = left_node_pt;
41515 face_element_added =
true;
41518 if (face_element_added)
41522 left_node_pt->get_coordinates_on_boundary(bound, bound_left);
41523 vertex_coord[0] = bound_left[0];
41526 for (
unsigned i = 0; i < 2; i++)
41528 vertex_coord[i + 1] = left_node_pt->x(i);
41530 local_vertex_nodes.insert(vertex_coord);
41534 right_node_pt->get_coordinates_on_boundary(bound, bound_right);
41535 vertex_coord[0] = bound_right[0];
41538 for (
unsigned i = 0; i < 2; i++)
41540 vertex_coord[i + 1] = right_node_pt->x(i);
41542 local_vertex_nodes.insert(vertex_coord);
41546 face_element_done[ele_face_pt] =
true;
41547 nsorted_face_elements++;
41554 }
while (face_element_added &&
41555 (nsorted_face_elements < nnon_halo_face_element));
41563 const unsigned nlocal_nodes = local_vertex_nodes.size();
41565 local_tmp_vector_vertex_node.resize(nlocal_nodes);
41568 unsigned counter = 0;
41569 std::set<Vector<double>>::iterator it_vertex;
41570 for (it_vertex = local_vertex_nodes.begin();
41571 it_vertex != local_vertex_nodes.end();
41574 local_tmp_vector_vertex_node[counter].resize(3);
41575 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
41576 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
41577 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
41588 local_vertex_nodes.clear();
41593 unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
41594 for (
unsigned i = 0; i < nnew_nodes; i++)
41596 vertex_coord[0] = local_tmp_vector_vertex_node[i][0];
41597 vertex_coord[1] = local_tmp_vector_vertex_node[i][1];
41598 vertex_coord[2] = local_tmp_vector_vertex_node[i][2];
41599 vertex_nodes.insert(vertex_coord);
41600 local_vertex_nodes.insert(vertex_coord);
41603 #ifdef OOMPH_HAS_MPI
41604 if (this->is_mesh_distributed())
41608 sub_vertex_nodes.push_back(local_vertex_nodes);
41617 unsigned npoly_vertex = vertex_nodes.size();
41618 tmp_vector_vertex_node.resize(npoly_vertex);
41619 unsigned count = 0;
41620 std::set<Vector<double>>::iterator it;
41621 for (it = vertex_nodes.begin(); it != vertex_nodes.end(); ++it)
41623 tmp_vector_vertex_node[count].resize(3);
41624 tmp_vector_vertex_node[count][0] = (*it)[0];
41625 tmp_vector_vertex_node[count][1] = (*it)[1];
41626 tmp_vector_vertex_node[count][2] = (*it)[2];
41630 #ifdef OOMPH_HAS_MPI
41633 unsigned nsub_boundaries_set = sub_vertex_nodes.size();
41634 if (nsub_boundaries_set != nsub_boundaries)
41636 std::ostringstream error_message;
41638 <<
"The number of found sub-boundaries and the number of counted\n"
41639 <<
"sub-boundaries are different:\n"
41640 <<
"Number of found sub-boundaries: (" << nsub_boundaries_set <<
")\n"
41641 <<
"Number of counted sub-boundaries: (" << nsub_boundaries <<
")\n";
41642 throw OomphLibError(
41643 error_message.str(),
41644 "RefineableTriangleMesh::update_polygon_after_restart()",
41645 OOMPH_EXCEPTION_LOCATION);
41650 if (this->is_mesh_distributed() && nsub_boundaries > 1)
41653 this->Boundary_was_splitted[bound] =
true;
41655 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
41656 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
41659 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
41660 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
41661 unsigned subcount = 0;
41662 std::set<Vector<double>>::iterator subit;
41663 for (subit = sub_vertex_nodes[isub].begin();
41664 subit != sub_vertex_nodes[isub].end();
41667 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
41668 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
41669 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
41670 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
41681 unsigned n_vertex = tmp_vector_vertex_node.size();
41684 vector_vertex_node.resize(n_vertex);
41685 for (
unsigned i = 0; i < n_vertex; i++)
41687 vector_vertex_node[i].resize(2);
41688 vector_vertex_node[i][0] = tmp_vector_vertex_node[i][1];
41689 vector_vertex_node[i][1] = tmp_vector_vertex_node[i][2];
41692 #ifdef OOMPH_HAS_MPI
41695 if (this->is_mesh_distributed() && nsub_boundaries > 1)
41700 sub_vector_vertex_node.resize(nsub_boundaries);
41701 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
41703 const unsigned subn_vertex = sub_tmp_vector_vertex_node[isub].size();
41705 sub_vector_vertex_node[isub].resize(subn_vertex);
41706 for (
unsigned i = 0; i < subn_vertex; i++)
41708 sub_vector_vertex_node[isub][i].resize(2);
41709 sub_vector_vertex_node[isub][i][0] =
41710 sub_tmp_vector_vertex_node[isub][i][1];
41711 sub_vector_vertex_node[isub][i][1] =
41712 sub_tmp_vector_vertex_node[isub][i][2];
41727 #ifdef OOMPH_HAS_MPI
41731 if (!this->is_mesh_distributed())
41737 Vector<double> final_vertex_of_previous_segment;
41738 unsigned n_prev_vertex =
41739 polygon_pt->curve_section_pt(p - 1)->nvertex();
41740 final_vertex_of_previous_segment =
41741 polygon_pt->polyline_pt(p - 1)->vertex_coordinate(n_prev_vertex -
41744 unsigned prev_seg_boundary_id =
41745 polygon_pt->curve_section_pt(p - 1)->boundary_id();
41749 double error = 0.0;
41750 for (
unsigned i = 0; i < 2; i++)
41752 const double dist = final_vertex_of_previous_segment[i] -
41753 (*vector_vertex_node.begin())[i];
41754 error += dist * dist;
41756 error = sqrt(error);
41760 if (error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
41764 double rev_error = 0.0;
41765 for (
unsigned i = 0; i < 2; i++)
41767 const double dist = final_vertex_of_previous_segment[i] -
41768 (*--vector_vertex_node.end())[i];
41769 rev_error += dist * dist;
41771 rev_error = sqrt(rev_error);
41774 ToleranceForVertexMismatchInPolygons::Tolerable_error)
41783 Vector<double> initial_vertex_of_previous_segment;
41785 initial_vertex_of_previous_segment =
41786 polygon_pt->polyline_pt(p - 1)->vertex_coordinate(0);
41788 unsigned prev_seg_boundary_id =
41789 polygon_pt->curve_section_pt(p - 1)->boundary_id();
41793 double error = 0.0;
41794 for (
unsigned i = 0; i < 2; i++)
41796 const double dist = initial_vertex_of_previous_segment[i] -
41797 (*vector_vertex_node.begin())[i];
41798 error += dist * dist;
41800 error = sqrt(error);
41805 ToleranceForVertexMismatchInPolygons::Tolerable_error)
41809 double rev_error = 0.0;
41810 for (
unsigned i = 0; i < 2; i++)
41812 const double dist = initial_vertex_of_previous_segment[i] -
41813 (*--vector_vertex_node.end())[i];
41814 rev_error += dist * dist;
41821 ToleranceForVertexMismatchInPolygons::Tolerable_error)
41823 std::ostringstream error_stream;
41825 <<
"The distance between the first node of the current\n"
41826 <<
"line segment (boundary " << bound
41827 <<
") and either end of "
41828 <<
"the previous line segment\n"
41829 <<
"(boundary " << prev_seg_boundary_id
41830 <<
") is bigger than "
41831 <<
"the desired tolerance "
41832 << ToleranceForVertexMismatchInPolygons::Tolerable_error
41834 <<
"This suggests that the polylines defining the "
41836 <<
"representation are not properly ordered.\n"
41837 <<
"Fail on last vertex of polyline: ("
41838 << prev_seg_boundary_id
41839 <<
") and\nfirst vertex of polyline (" << bound
41840 <<
").\nThis should have failed when first trying to"
41841 <<
" construct the\npolygon.\n";
41842 throw OomphLibError(
41843 error_stream.str(),
41844 "RefineableTriangleMesh::update_polygon_after_restart()",
41845 OOMPH_EXCEPTION_LOCATION);
41852 std::reverse(vector_vertex_node.begin(),
41853 vector_vertex_node.end());
41854 polygon_pt->polyline_pt(p - 1)->reverse();
41860 polygon_pt->polyline_pt(p - 1)->reverse();
41866 std::ostringstream error_stream;
41868 <<
"The distance between the first node of the current\n"
41869 <<
"line segment (boundary " << bound
41870 <<
") and either end of "
41871 <<
"the previous line segment\n"
41872 <<
"(boundary " << prev_seg_boundary_id
41873 <<
") is bigger than the "
41874 <<
"desired tolerance "
41875 << ToleranceForVertexMismatchInPolygons::Tolerable_error
41877 <<
"This suggests that the polylines defining the polygonal\n"
41878 <<
"representation are not properly ordered.\n"
41879 <<
"Fail on last vertex of polyline: ("
41880 << prev_seg_boundary_id <<
") and\nfirst vertex of polyline ("
41882 <<
"This should have failed when first trying to construct "
41885 throw OomphLibError(
41886 error_stream.str(),
41887 "RefineableTriangleMesh::update_polygon_after_restart()",
41888 OOMPH_EXCEPTION_LOCATION);
41894 std::reverse(vector_vertex_node.begin(),
41895 vector_vertex_node.end());
41910 n_vertex = vector_vertex_node.size();
41914 TriangleMeshPolyLine* tmp_polyline_pt =
41915 new TriangleMeshPolyLine(vector_vertex_node, bound);
41926 TriangleMeshCurveSection* tmp_curve_section_pt = tmp_polyline_pt;
41930 double unrefinement_tolerance =
41931 polygon_pt->polyline_pt(p)->unrefinement_tolerance();
41934 double refinement_tolerance =
41935 polygon_pt->polyline_pt(p)->refinement_tolerance();
41938 tmp_polyline_pt->set_unrefinement_tolerance(unrefinement_tolerance);
41939 tmp_polyline_pt->set_refinement_tolerance(refinement_tolerance);
41942 double maximum_length = polygon_pt->polyline_pt(p)->maximum_length();
41943 tmp_polyline_pt->set_maximum_length(maximum_length);
41949 this->copy_connection_information(polygon_pt->polyline_pt(p),
41950 tmp_curve_section_pt);
41956 bool delete_it_on_destructor =
false;
41958 std::set<TriangleMeshCurveSection*>::iterator it =
41959 this->Free_curve_section_pt.find(polygon_pt->curve_section_pt(p));
41961 if (it != this->Free_curve_section_pt.end())
41963 this->Free_curve_section_pt.erase(it);
41964 delete polygon_pt->curve_section_pt(p);
41965 delete_it_on_destructor =
true;
41970 polygon_pt->curve_section_pt(p) = tmp_polyline_pt;
41973 this->Boundary_curve_section_pt[bound] =
41974 polygon_pt->curve_section_pt(p);
41976 if (delete_it_on_destructor)
41978 this->Free_curve_section_pt.insert(polygon_pt->curve_section_pt(p));
41981 #ifdef OOMPH_HAS_MPI
41984 if (this->is_mesh_distributed() && nsub_boundaries > 1)
41989 this->Boundary_subpolylines[bound].clear();
41991 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
41992 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
41996 TriangleMeshPolyLine* sub_tmp_polyline_pt =
41997 new TriangleMeshPolyLine(
41998 sub_vector_vertex_node[isub], bound, isub);
42002 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
42020 delete mesh_geom_obj_pt;
42025 for (
unsigned p = 0; p < n_polyline; p++)
42027 face_mesh_pt[p]->flush_node_storage();
42028 delete face_mesh_pt[p];
42036 template<
class ELEMENT>
42038 TriangleMeshOpenCurve*& open_curve_pt)
42046 Vector<Mesh*> face_mesh_pt;
42047 get_face_mesh_representation(open_curve_pt, face_mesh_pt);
42051 Vector<double> vertex_coord(3);
42052 Vector<double> bound_left(1);
42053 Vector<double> bound_right(1);
42055 const unsigned ncurve_section = open_curve_pt->ncurve_section();
42057 for (
unsigned cs = 0; cs < ncurve_section; cs++)
42065 MeshAsGeomObject* mesh_geom_obj_pt =
42066 new MeshAsGeomObject(face_mesh_pt[cs]);
42069 const unsigned bound = open_curve_pt->curve_section_pt(cs)->boundary_id();
42078 const unsigned nface_element = face_mesh_pt[cs]->nelement();
42082 Vector<FiniteElement*> non_halo_doubled_face_element_pt;
42085 std::map<FiniteElement*, unsigned> face_element_index_on_boundary;
42088 std::map<FiniteElement*, bool> face_element_done;
42090 for (
unsigned ef = 0; ef < nface_element; ++ef)
42092 FiniteElement* ele_face_pt = face_mesh_pt[cs]->finite_element_pt(ef);
42097 #ifdef OOMPH_HAS_MPI
42098 if (this->is_mesh_distributed())
42101 if (ele_face_pt->is_halo())
42109 if (!face_element_done[ele_face_pt])
42114 non_halo_doubled_face_element_pt.push_back(ele_face_pt);
42116 face_element_index_on_boundary[ele_face_pt] = ef;
42118 face_element_done[ele_face_pt] =
true;
42120 const unsigned nnodes = ele_face_pt->nnode();
42123 Node* left_node_pt = ele_face_pt->node_pt(0);
42124 Node* right_node_pt = ele_face_pt->node_pt(nnodes - 1);
42129 bool found_other_side_face_ele =
false;
42131 for (
unsigned iface = 0; iface < nface_element; iface++)
42134 FiniteElement* cele_face_pt =
42135 face_mesh_pt[cs]->finite_element_pt(iface);
42137 if (!face_element_done[cele_face_pt])
42139 Node* cleft_node_pt = cele_face_pt->node_pt(0);
42140 Node* cright_node_pt = cele_face_pt->node_pt(nnodes - 1);
42143 if ((left_node_pt == cleft_node_pt &&
42144 right_node_pt == cright_node_pt) ||
42145 (left_node_pt == cright_node_pt &&
42146 right_node_pt == cleft_node_pt))
42149 non_halo_doubled_face_element_pt.push_back(cele_face_pt);
42151 face_element_done[cele_face_pt] =
true;
42153 face_element_index_on_boundary[cele_face_pt] = iface;
42156 found_other_side_face_ele =
true;
42164 if (!found_other_side_face_ele)
42166 std::ostringstream error_message;
42168 <<
"The face element at the other side of the boundary (" << bound
42169 <<
") was not found!!\n"
42170 <<
"These are the nodes of the face element:\n"
42171 <<
"(" << left_node_pt->x(0) <<
", " << left_node_pt->x(1) <<
") "
42172 <<
"and (" << right_node_pt->x(0) <<
"," << right_node_pt->x(1)
42174 throw OomphLibError(
42175 error_message.str(),
42176 "RefineableTriangleMesh::update_open_curve_after_restart()",
42177 OOMPH_EXCEPTION_LOCATION);
42186 face_element_done.clear();
42191 std::set<Vector<double>> vertex_nodes;
42195 Vector<Vector<double>> tmp_vector_vertex_node;
42200 Vector<Vector<double>> vector_vertex_node;
42202 #ifdef OOMPH_HAS_MPI
42207 std::vector<bool> internal_to_shared_boundary;
42214 Vector<std::set<Vector<double>>> sub_vertex_nodes;
42218 Vector<Vector<Vector<double>>> sub_tmp_vector_vertex_node;
42223 Vector<Vector<Vector<double>>> sub_vector_vertex_node;
42232 unsigned nsorted_face_elements = 0;
42234 #ifdef OOMPH_HAS_MPI
42236 unsigned nsub_boundaries = 0;
42240 const unsigned nnon_halo_doubled_face_ele =
42241 non_halo_doubled_face_element_pt.size();
42245 while (nsorted_face_elements < nnon_halo_doubled_face_ele)
42248 FiniteElement* ele_face_pt = 0;
42249 FiniteElement* repeated_ele_face_pt = 0;
42251 bool found_initial_face_element =
false;
42257 bool both_root_face_elements_are_nonhalo =
false;
42259 unsigned iface = 0;
42260 for (iface = 0; iface < nnon_halo_doubled_face_ele; iface += 2)
42262 ele_face_pt = non_halo_doubled_face_element_pt[iface];
42264 if (!face_element_done[ele_face_pt])
42267 face_element_done[ele_face_pt] =
true;
42269 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iface + 1];
42271 face_element_done[repeated_ele_face_pt] =
true;
42273 #ifdef OOMPH_HAS_MPI
42274 if (!repeated_ele_face_pt->is_halo())
42276 both_root_face_elements_are_nonhalo =
true;
42282 nsorted_face_elements += 2;
42286 found_initial_face_element =
true;
42293 if (!found_initial_face_element)
42295 std::ostringstream error_message;
42296 error_message <<
"Could not find an initial face element for the "
42297 "current segment\n";
42299 throw OomphLibError(error_message.str(),
42300 OOMPH_CURRENT_FUNCTION,
42301 OOMPH_EXCEPTION_LOCATION);
42308 std::set<Vector<double>> local_vertex_nodes;
42312 Vector<Vector<double>> local_tmp_vector_vertex_node;
42320 const unsigned nnode = ele_face_pt->nnode();
42323 ele_face_pt->node_pt(0)->get_coordinates_on_boundary(bound, bound_left);
42324 vertex_coord[0] = bound_left[0];
42327 for (
unsigned i = 0; i < 2; i++)
42329 vertex_coord[i + 1] = ele_face_pt->node_pt(0)->x(i);
42331 local_vertex_nodes.insert(vertex_coord);
42335 ele_face_pt->node_pt(nnode - 1)->get_coordinates_on_boundary(
42336 bound, bound_right);
42337 vertex_coord[0] = bound_right[0];
42340 for (
unsigned i = 0; i < 2; i++)
42342 vertex_coord[i + 1] = ele_face_pt->node_pt(nnode - 1)->x(i);
42344 local_vertex_nodes.insert(vertex_coord);
42347 Node* first_node_pt = ele_face_pt->node_pt(0);
42348 Node* last_node_pt = ele_face_pt->node_pt(nnode - 1);
42352 bool face_element_added =
false;
42362 for (
unsigned iiface = iface; iiface < nnon_halo_doubled_face_ele;
42365 face_element_added =
false;
42366 ele_face_pt = non_halo_doubled_face_element_pt[iiface];
42373 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iiface + 1];
42374 bool both_face_elements_are_nonhalo =
false;
42376 #ifdef OOMPH_HAS_MPI
42377 if (!repeated_ele_face_pt->is_halo())
42379 both_face_elements_are_nonhalo =
true;
42383 if (!face_element_done[ele_face_pt] &&
42384 (both_face_elements_are_nonhalo ==
42385 both_root_face_elements_are_nonhalo))
42388 const unsigned nlnode = ele_face_pt->nnode();
42389 Node* left_node_pt = ele_face_pt->node_pt(0);
42390 Node* right_node_pt = ele_face_pt->node_pt(nlnode - 1);
42392 if (left_node_pt == first_node_pt)
42394 first_node_pt = right_node_pt;
42395 face_element_added =
true;
42397 else if (left_node_pt == last_node_pt)
42399 last_node_pt = right_node_pt;
42400 face_element_added =
true;
42402 else if (right_node_pt == first_node_pt)
42404 first_node_pt = left_node_pt;
42405 face_element_added =
true;
42407 else if (right_node_pt == last_node_pt)
42409 last_node_pt = left_node_pt;
42410 face_element_added =
true;
42413 if (face_element_added)
42417 left_node_pt->get_coordinates_on_boundary(bound, bound_left);
42418 vertex_coord[0] = bound_left[0];
42421 for (
unsigned i = 0; i < 2; i++)
42423 vertex_coord[i + 1] = left_node_pt->x(i);
42425 local_vertex_nodes.insert(vertex_coord);
42429 right_node_pt->get_coordinates_on_boundary(bound, bound_right);
42430 vertex_coord[0] = bound_right[0];
42433 for (
unsigned i = 0; i < 2; i++)
42435 vertex_coord[i + 1] = right_node_pt->x(i);
42437 local_vertex_nodes.insert(vertex_coord);
42441 face_element_done[ele_face_pt] =
true;
42444 repeated_ele_face_pt =
42445 non_halo_doubled_face_element_pt[iiface + 1];
42446 face_element_done[repeated_ele_face_pt] =
true;
42448 nsorted_face_elements += 2;
42455 }
while (face_element_added &&
42456 (nsorted_face_elements < nnon_halo_doubled_face_ele));
42464 const unsigned nlocal_nodes = local_vertex_nodes.size();
42466 local_tmp_vector_vertex_node.resize(nlocal_nodes);
42469 unsigned counter = 0;
42470 std::set<Vector<double>>::iterator it_vertex;
42471 for (it_vertex = local_vertex_nodes.begin();
42472 it_vertex != local_vertex_nodes.end();
42475 local_tmp_vector_vertex_node[counter].resize(3);
42476 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
42477 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
42478 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
42485 if (local_tmp_vector_vertex_node[nlocal_nodes - 1][2] <
42486 local_tmp_vector_vertex_node[0][2])
42488 std::reverse(local_tmp_vector_vertex_node.begin(),
42489 local_tmp_vector_vertex_node.end());
42491 else if (local_tmp_vector_vertex_node[nlocal_nodes - 1][2] ==
42492 local_tmp_vector_vertex_node[0][2])
42494 if (local_tmp_vector_vertex_node[nlocal_nodes - 1][1] <
42495 local_tmp_vector_vertex_node[0][1])
42497 std::reverse(local_tmp_vector_vertex_node.begin(),
42498 local_tmp_vector_vertex_node.end());
42509 local_vertex_nodes.clear();
42514 const unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
42515 for (
unsigned i = 0; i < nnew_nodes; i++)
42517 vertex_coord[0] = local_tmp_vector_vertex_node[i][0];
42518 vertex_coord[1] = local_tmp_vector_vertex_node[i][1];
42519 vertex_coord[2] = local_tmp_vector_vertex_node[i][2];
42520 vertex_nodes.insert(vertex_coord);
42521 local_vertex_nodes.insert(vertex_coord);
42524 #ifdef OOMPH_HAS_MPI
42525 if (this->is_mesh_distributed())
42530 sub_vertex_nodes.push_back(local_vertex_nodes);
42536 if (both_root_face_elements_are_nonhalo)
42538 internal_to_shared_boundary.push_back(
false);
42542 internal_to_shared_boundary.push_back(
true);
42553 const unsigned npoly_vertex = vertex_nodes.size();
42554 tmp_vector_vertex_node.resize(npoly_vertex);
42555 unsigned count = 0;
42556 std::set<Vector<double>>::iterator it;
42557 for (it = vertex_nodes.begin(); it != vertex_nodes.end(); ++it)
42559 tmp_vector_vertex_node[count].resize(3);
42560 tmp_vector_vertex_node[count][0] = (*it)[0];
42561 tmp_vector_vertex_node[count][1] = (*it)[1];
42562 tmp_vector_vertex_node[count][2] = (*it)[2];
42566 #ifdef OOMPH_HAS_MPI
42571 const unsigned nsub_boundaries_set = sub_vertex_nodes.size();
42572 const unsigned ninternal_to_shared_boundaries =
42573 internal_to_shared_boundary.size();
42574 if (nsub_boundaries_set != ninternal_to_shared_boundaries)
42576 std::ostringstream error_message;
42578 <<
"The number of found sub-boundaries and the number of marked "
42579 <<
"internal\nboundaries are different\n"
42580 <<
"Number of found sub-boundaries: (" << nsub_boundaries_set <<
")\n"
42581 <<
"Number of marked internal boundaries: ("
42582 << ninternal_to_shared_boundaries <<
")\n\n";
42583 throw OomphLibError(
42584 error_message.str(),
42585 "RefineableTriangleMesh::update_open_curve_after_restart()",
42586 OOMPH_EXCEPTION_LOCATION);
42592 if (nsub_boundaries_set != nsub_boundaries)
42594 std::ostringstream error_message;
42596 <<
"The number of found sub-boundaries and the number of counted\n"
42597 <<
"sub-boundaries are different:\n"
42598 <<
"Number of found sub-boundaries: (" << nsub_boundaries_set <<
")\n"
42599 <<
"Number of counted sub-boundaries: (" << nsub_boundaries
42601 throw OomphLibError(
42602 error_message.str(),
42603 "RefineableTriangleMesh::update_open_curve_after_restart()",
42604 OOMPH_EXCEPTION_LOCATION);
42609 if (this->is_mesh_distributed() && nsub_boundaries > 1)
42612 this->Boundary_was_splitted[bound] =
true;
42614 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
42615 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
42618 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
42619 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
42620 unsigned subcount = 0;
42621 std::set<Vector<double>>::iterator subit;
42622 for (subit = sub_vertex_nodes[isub].begin();
42623 subit != sub_vertex_nodes[isub].end();
42626 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
42627 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
42628 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
42629 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
42639 unsigned n_vertex = tmp_vector_vertex_node.size();
42642 vector_vertex_node.resize(n_vertex);
42643 for (
unsigned i = 0; i < n_vertex; i++)
42645 vector_vertex_node[i].resize(2);
42646 vector_vertex_node[i][0] = tmp_vector_vertex_node[i][1];
42647 vector_vertex_node[i][1] = tmp_vector_vertex_node[i][2];
42650 #ifdef OOMPH_HAS_MPI
42653 if (this->is_mesh_distributed() && nsub_boundaries > 1)
42658 sub_vector_vertex_node.resize(nsub_boundaries);
42659 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
42661 const unsigned subn_vertex = sub_tmp_vector_vertex_node[isub].size();
42663 sub_vector_vertex_node[isub].resize(subn_vertex);
42664 for (
unsigned i = 0; i < subn_vertex; i++)
42666 sub_vector_vertex_node[isub][i].resize(2);
42667 sub_vector_vertex_node[isub][i][0] =
42668 sub_tmp_vector_vertex_node[isub][i][1];
42669 sub_vector_vertex_node[isub][i][1] =
42670 sub_tmp_vector_vertex_node[isub][i][2];
42685 #ifdef OOMPH_HAS_MPI
42689 if (!this->is_mesh_distributed())
42695 Vector<double> final_vertex_of_previous_segment;
42696 unsigned n_prev_vertex =
42697 open_curve_pt->curve_section_pt(cs - 1)->nvertex();
42698 final_vertex_of_previous_segment =
42699 open_curve_pt->polyline_pt(cs - 1)->vertex_coordinate(
42700 n_prev_vertex - 1);
42702 unsigned prev_seg_boundary_id =
42703 open_curve_pt->curve_section_pt(cs - 1)->boundary_id();
42707 double error = 0.0;
42708 for (
unsigned i = 0; i < 2; i++)
42710 const double dist = final_vertex_of_previous_segment[i] -
42711 (*vector_vertex_node.begin())[i];
42712 error += dist * dist;
42714 error = sqrt(error);
42718 if (error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
42722 double rev_error = 0.0;
42723 for (
unsigned i = 0; i < 2; i++)
42725 const double dist = final_vertex_of_previous_segment[i] -
42726 (*--vector_vertex_node.end())[i];
42727 rev_error += dist * dist;
42729 rev_error = sqrt(rev_error);
42732 ToleranceForVertexMismatchInPolygons::Tolerable_error)
42741 Vector<double> initial_vertex_of_previous_segment;
42743 initial_vertex_of_previous_segment =
42744 open_curve_pt->polyline_pt(cs - 1)->vertex_coordinate(0);
42746 unsigned prev_seg_boundary_id =
42747 open_curve_pt->curve_section_pt(cs - 1)->boundary_id();
42751 double error = 0.0;
42752 for (
unsigned i = 0; i < 2; i++)
42754 const double dist = initial_vertex_of_previous_segment[i] -
42755 (*vector_vertex_node.begin())[i];
42756 error += dist * dist;
42758 error = sqrt(error);
42763 ToleranceForVertexMismatchInPolygons::Tolerable_error)
42767 double rev_error = 0.0;
42768 for (
unsigned i = 0; i < 2; i++)
42770 const double dist = initial_vertex_of_previous_segment[i] -
42771 (*--vector_vertex_node.end())[i];
42772 rev_error += dist * dist;
42774 rev_error = sqrt(rev_error);
42778 ToleranceForVertexMismatchInPolygons::Tolerable_error)
42780 std::ostringstream error_stream;
42782 <<
"The distance between the first node of the current\n"
42783 <<
"line segment (boundary " << bound
42784 <<
") and either end of "
42785 <<
"the previous line segment\n"
42786 <<
"(boundary " << prev_seg_boundary_id
42787 <<
") is bigger than"
42788 <<
" the desired tolerance "
42789 << ToleranceForVertexMismatchInPolygons::Tolerable_error
42791 <<
"This suggests that the polylines defining the "
42793 <<
"representation are not properly ordered.\n"
42794 <<
"Fail on last vertex of polyline: ("
42795 << prev_seg_boundary_id
42796 <<
") and\nfirst vertex of polyline (" << bound
42797 <<
").\nThis should have failed when first trying to "
42798 <<
"construct the\npolygon.\n";
42799 throw OomphLibError(error_stream.str(),
42800 "RefineableTriangleMesh::update_open_"
42801 "curve_after_restart()",
42802 OOMPH_EXCEPTION_LOCATION);
42809 std::reverse(vector_vertex_node.begin(),
42810 vector_vertex_node.end());
42811 open_curve_pt->polyline_pt(cs - 1)->reverse();
42817 open_curve_pt->polyline_pt(cs - 1)->reverse();
42823 std::ostringstream error_stream;
42825 <<
"The distance between the first node of the current\n"
42826 <<
"line segment (boundary " << bound
42827 <<
") and either end of "
42828 <<
"the previous line segment\n"
42829 <<
"(boundary " << prev_seg_boundary_id
42830 <<
") is bigger than the "
42831 <<
"desired tolerance "
42832 << ToleranceForVertexMismatchInPolygons::Tolerable_error
42834 <<
"This suggests that the polylines defining the polygonal\n"
42835 <<
"representation are not properly ordered.\n"
42836 <<
"Fail on last vertex of polyline: ("
42837 << prev_seg_boundary_id <<
") and\nfirst vertex of polyline ("
42839 <<
"This should have failed when first trying to construct "
42842 throw OomphLibError(
42843 error_stream.str(),
42844 "RefineableTriangleMesh::update_open_curve_after_restart()",
42845 OOMPH_EXCEPTION_LOCATION);
42851 std::reverse(vector_vertex_node.begin(),
42852 vector_vertex_node.end());
42870 n_vertex = vector_vertex_node.size();
42874 TriangleMeshPolyLine* tmp_polyline_pt =
42875 new TriangleMeshPolyLine(vector_vertex_node, bound);
42879 TriangleMeshCurveSection* tmp_curve_section_pt = tmp_polyline_pt;
42883 double unrefinement_tolerance =
42884 open_curve_pt->polyline_pt(cs)->unrefinement_tolerance();
42887 double refinement_tolerance =
42888 open_curve_pt->polyline_pt(cs)->refinement_tolerance();
42891 tmp_polyline_pt->set_unrefinement_tolerance(unrefinement_tolerance);
42892 tmp_polyline_pt->set_refinement_tolerance(refinement_tolerance);
42895 double maximum_length =
42896 open_curve_pt->polyline_pt(cs)->maximum_length();
42897 tmp_polyline_pt->set_maximum_length(maximum_length);
42903 this->copy_connection_information(open_curve_pt->polyline_pt(cs),
42904 tmp_curve_section_pt);
42910 bool delete_it_on_destructor =
false;
42912 std::set<TriangleMeshCurveSection*>::iterator it =
42913 this->Free_curve_section_pt.find(open_curve_pt->curve_section_pt(cs));
42915 if (it != this->Free_curve_section_pt.end())
42917 this->Free_curve_section_pt.erase(it);
42918 delete open_curve_pt->curve_section_pt(cs);
42919 delete_it_on_destructor =
true;
42924 open_curve_pt->curve_section_pt(cs) = tmp_polyline_pt;
42927 this->Boundary_curve_section_pt[bound] =
42928 open_curve_pt->curve_section_pt(cs);
42930 if (delete_it_on_destructor)
42932 this->Free_curve_section_pt.insert(
42933 open_curve_pt->curve_section_pt(cs));
42936 #ifdef OOMPH_HAS_MPI
42940 if (this->is_mesh_distributed() && nsub_boundaries == 1)
42943 this->Boundary_marked_as_shared_boundary[bound].clear();
42946 this->Boundary_marked_as_shared_boundary[bound].push_back(
42947 internal_to_shared_boundary[0]);
42951 else if (this->is_mesh_distributed() && nsub_boundaries > 1)
42956 this->Boundary_subpolylines[bound].clear();
42958 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
42961 this->Boundary_marked_as_shared_boundary[bound].clear();
42964 this->Boundary_marked_as_shared_boundary[bound].resize(
42966 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
42970 TriangleMeshPolyLine* sub_tmp_polyline_pt =
42971 new TriangleMeshPolyLine(
42972 sub_vector_vertex_node[isub], bound, isub);
42976 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
42980 this->Boundary_marked_as_shared_boundary[bound][isub] =
42981 internal_to_shared_boundary[isub];
42996 delete mesh_geom_obj_pt;
43001 for (
unsigned p = 0; p < ncurve_section; p++)
43003 face_mesh_pt[p]->flush_node_storage();
43004 delete face_mesh_pt[p];
43008 #ifdef OOMPH_HAS_MPI
43012 template<
class ELEMENT>
43014 Vector<TriangleMeshPolyLine*>& vector_polyline_pt)
43017 const unsigned npolylines = vector_polyline_pt.size();
43018 for (
unsigned pp = 0; pp < npolylines; pp++)
43021 const unsigned b = vector_polyline_pt[pp]->boundary_id();
43026 std::map<std::pair<Node*, Node*>, FiniteElement*> halo_edge_element_pt;
43027 std::map<std::pair<Node*, Node*>, FiniteElement*> nonhalo_edge_element_pt;
43030 Vector<Node*> halo_edge_nodes_pt;
43031 Vector<Node*> nonhalo_edge_nodes_pt;
43034 const unsigned nshared_bound_ele = this->nshared_boundary_element(b);
43035 for (
unsigned e = 0; e < nshared_bound_ele; e++)
43038 FiniteElement* current_ele_pt = this->shared_boundary_element_pt(b, e);
43041 Node* first_node_pt = current_ele_pt->node_pt(0);
43042 Node* second_node_pt = current_ele_pt->node_pt(1);
43043 Node* third_node_pt = current_ele_pt->node_pt(2);
43046 if (!current_ele_pt->is_halo())
43049 nonhalo_edge_nodes_pt.push_back(first_node_pt);
43050 nonhalo_edge_nodes_pt.push_back(second_node_pt);
43052 nonhalo_edge_nodes_pt.push_back(second_node_pt);
43053 nonhalo_edge_nodes_pt.push_back(third_node_pt);
43055 nonhalo_edge_nodes_pt.push_back(third_node_pt);
43056 nonhalo_edge_nodes_pt.push_back(first_node_pt);
43059 std::pair<Node*, Node*> edge1 =
43060 std::make_pair(first_node_pt, second_node_pt);
43061 nonhalo_edge_element_pt[edge1] = current_ele_pt;
43063 std::pair<Node*, Node*> edge2 =
43064 std::make_pair(second_node_pt, third_node_pt);
43065 nonhalo_edge_element_pt[edge2] = current_ele_pt;
43067 std::pair<Node*, Node*> edge3 =
43068 std::make_pair(third_node_pt, first_node_pt);
43069 nonhalo_edge_element_pt[edge3] = current_ele_pt;
43074 halo_edge_nodes_pt.push_back(first_node_pt);
43075 halo_edge_nodes_pt.push_back(second_node_pt);
43077 halo_edge_nodes_pt.push_back(second_node_pt);
43078 halo_edge_nodes_pt.push_back(third_node_pt);
43080 halo_edge_nodes_pt.push_back(third_node_pt);
43081 halo_edge_nodes_pt.push_back(first_node_pt);
43084 std::pair<Node*, Node*> edge1 =
43085 std::make_pair(first_node_pt, second_node_pt);
43086 halo_edge_element_pt[edge1] = current_ele_pt;
43088 std::pair<Node*, Node*> edge2 =
43089 std::make_pair(second_node_pt, third_node_pt);
43090 halo_edge_element_pt[edge2] = current_ele_pt;
43092 std::pair<Node*, Node*> edge3 =
43093 std::make_pair(third_node_pt, first_node_pt);
43094 halo_edge_element_pt[edge3] = current_ele_pt;
43102 std::map<std::pair<Node*, Node*>,
bool> edge_done;
43105 Vector<std::pair<Node*, Node*>> unsorted_edges;
43109 Vector<Vector<FiniteElement*>> unsorted_edges_elements_pt;
43111 const unsigned nnonhalo_edge_nodes = nonhalo_edge_nodes_pt.size();
43112 for (
unsigned i = 0; i < nnonhalo_edge_nodes; i += 2)
43114 Vector<Node*> currenti_edge(2);
43115 currenti_edge[0] = nonhalo_edge_nodes_pt[i];
43116 currenti_edge[1] = nonhalo_edge_nodes_pt[i + 1];
43119 std::pair<Node*, Node*> new_edge =
43120 std::make_pair(currenti_edge[0], currenti_edge[1]);
43122 if (!edge_done[new_edge])
43124 const unsigned nhalo_edge_nodes = halo_edge_nodes_pt.size();
43125 for (
unsigned j = 0; j < nhalo_edge_nodes; j += 2)
43127 Vector<Node*> currentj_edge(2);
43128 currentj_edge[0] = halo_edge_nodes_pt[j];
43129 currentj_edge[1] = halo_edge_nodes_pt[j + 1];
43132 if (currenti_edge[0] == currentj_edge[0] &&
43133 currenti_edge[1] == currentj_edge[1])
43136 unsorted_edges.push_back(new_edge);
43139 Vector<FiniteElement*> tmp_edge_element_pt;
43141 FiniteElement* nonhalo_ele_pt = nonhalo_edge_element_pt[new_edge];
43142 FiniteElement* halo_ele_pt = halo_edge_element_pt[new_edge];
43144 tmp_edge_element_pt.push_back(nonhalo_ele_pt);
43145 tmp_edge_element_pt.push_back(halo_ele_pt);
43148 unsorted_edges_elements_pt.push_back(tmp_edge_element_pt);
43151 edge_done[new_edge] =
true;
43159 else if (currenti_edge[0] == currentj_edge[1] &&
43160 currenti_edge[1] == currentj_edge[0])
43163 std::pair<Node*, Node*> new_edge =
43164 std::make_pair(currenti_edge[0], currenti_edge[1]);
43167 unsorted_edges.push_back(new_edge);
43170 std::pair<Node*, Node*> rev_new_edge =
43171 std::make_pair(currentj_edge[0], currentj_edge[1]);
43174 Vector<FiniteElement*> tmp_edge_element_pt;
43176 FiniteElement* nonhalo_ele_pt = nonhalo_edge_element_pt[new_edge];
43177 FiniteElement* halo_ele_pt = halo_edge_element_pt[rev_new_edge];
43179 tmp_edge_element_pt.push_back(nonhalo_ele_pt);
43180 tmp_edge_element_pt.push_back(halo_ele_pt);
43183 unsorted_edges_elements_pt.push_back(tmp_edge_element_pt);
43186 edge_done[new_edge] =
true;
43204 std::map<std::pair<Node*, Node*>,
bool> edge_sorted;
43206 const unsigned nunsorted_edges = unsorted_edges.size();
43211 if (nshared_bound_ele / 2 != nunsorted_edges)
43213 std::ostringstream error_message;
43215 <<
"The number of shared boundary elements (" << nshared_bound_ele
43216 <<
") is not the double\nof the number of unsorted edges ("
43217 << nunsorted_edges <<
") for the current boundary (" << b <<
")\n\n";
43218 throw OomphLibError(
43219 error_message.str(),
43220 "RefineableTriangleMesh::update_shared_curve_after_restart()",
43221 OOMPH_EXCEPTION_LOCATION);
43225 unsigned nsorted_edges = 0;
43229 std::list<Node*> sorted_nodes;
43232 std::list<FiniteElement*> sorted_edges_elements_pt;
43235 std::pair<Node*, Node*> edge = unsorted_edges[0];
43239 edge_sorted[edge] =
true;
43242 Node* first_node_pt = edge.first;
43243 Node* last_node_pt = edge.second;
43246 sorted_nodes.push_back(first_node_pt);
43247 sorted_nodes.push_back(last_node_pt);
43250 sorted_edges_elements_pt.push_back(unsorted_edges_elements_pt[0][0]);
43251 sorted_edges_elements_pt.push_back(unsorted_edges_elements_pt[0][1]);
43255 while (nsorted_edges < nunsorted_edges)
43258 bool node_added =
false;
43262 for (
unsigned iedge = 1; iedge < nunsorted_edges; iedge++)
43264 edge = unsorted_edges[iedge];
43267 if (!edge_sorted[edge])
43270 Node* left_node_pt = edge.first;
43271 Node* right_node_pt = edge.second;
43273 if (left_node_pt == first_node_pt)
43276 sorted_nodes.push_front(right_node_pt);
43277 first_node_pt = right_node_pt;
43281 sorted_edges_elements_pt.push_front(
43282 unsorted_edges_elements_pt[iedge][1]);
43283 sorted_edges_elements_pt.push_front(
43284 unsorted_edges_elements_pt[iedge][0]);
43286 else if (left_node_pt == last_node_pt)
43289 sorted_nodes.push_back(right_node_pt);
43290 last_node_pt = right_node_pt;
43294 sorted_edges_elements_pt.push_back(
43295 unsorted_edges_elements_pt[iedge][0]);
43296 sorted_edges_elements_pt.push_back(
43297 unsorted_edges_elements_pt[iedge][1]);
43299 else if (right_node_pt == first_node_pt)
43302 sorted_nodes.push_front(left_node_pt);
43303 first_node_pt = left_node_pt;
43307 sorted_edges_elements_pt.push_front(
43308 unsorted_edges_elements_pt[iedge][1]);
43309 sorted_edges_elements_pt.push_front(
43310 unsorted_edges_elements_pt[iedge][0]);
43312 else if (right_node_pt == last_node_pt)
43315 sorted_nodes.push_back(left_node_pt);
43316 last_node_pt = left_node_pt;
43320 sorted_edges_elements_pt.push_back(
43321 unsorted_edges_elements_pt[iedge][0]);
43322 sorted_edges_elements_pt.push_back(
43323 unsorted_edges_elements_pt[iedge][1]);
43330 edge_sorted[edge] =
true;
43345 unsigned nvertex = sorted_nodes.size();
43347 Vector<Vector<double>> polyline_vertices(nvertex);
43350 unsigned counter = 0;
43351 for (std::list<Node*>::iterator it_nodes = sorted_nodes.begin();
43352 it_nodes != sorted_nodes.end();
43355 polyline_vertices[counter].resize(2);
43356 polyline_vertices[counter][0] = (*it_nodes)->x(0);
43357 polyline_vertices[counter][1] = (*it_nodes)->x(1);
43364 if (polyline_vertices[nvertex - 1][1] < polyline_vertices[0][1])
43366 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
43368 else if (polyline_vertices[nvertex - 1][1] == polyline_vertices[0][1])
43370 if (polyline_vertices[nvertex - 1][0] < polyline_vertices[0][0])
43372 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
43377 TriangleMeshPolyLine* new_polyline_pt =
43378 new TriangleMeshPolyLine(polyline_vertices, b);
43381 TriangleMeshCurveSection* curve_section_pt = vector_polyline_pt[pp];
43385 this->copy_connection_information(curve_section_pt, new_polyline_pt);
43390 bool delete_it_on_destructor =
false;
43394 std::set<TriangleMeshCurveSection*>::iterator it =
43395 this->Free_curve_section_pt.find(curve_section_pt);
43397 if (it != this->Free_curve_section_pt.end())
43399 this->Free_curve_section_pt.erase(it);
43400 delete curve_section_pt;
43401 delete_it_on_destructor =
true;
43405 vector_polyline_pt[pp] = new_polyline_pt;
43408 TriangleMeshCurveSection* new_curve_section_pt = vector_polyline_pt[pp];
43411 this->Boundary_curve_section_pt[b] = new_curve_section_pt;
43413 if (delete_it_on_destructor)
43415 this->Free_curve_section_pt.insert(new_curve_section_pt);
43427 template<
class ELEMENT>
43429 ELEMENT>::fill_boundary_elements_and_nodes_for_internal_boundaries()
43432 std::ofstream some_file;
43433 fill_boundary_elements_and_nodes_for_internal_boundaries(some_file);
43440 template<
class ELEMENT>
43443 std::ofstream& outfile)
43446 const unsigned nproc = this->communicator_pt()->nproc();
43448 unsigned my_rank = this->communicator_pt()->my_rank();
43451 std::map<unsigned, unsigned> shd_bnd_over_int_bnd =
43452 this->Shared_boundary_overlaps_internal_boundary;
43456 std::set<unsigned> internal_boundary_overlaped;
43460 if (outfile.is_open())
43462 const unsigned nbound = this->nboundary();
43463 outfile <<
"Number of boundaries: " << nbound <<
"\n\n";
43464 outfile <<
"Number of elements and nodes associated to each "
43465 <<
"boundary before\nfilling elements and nodes\n\n";
43466 for (
unsigned i = 0; i < nbound; i++)
43468 outfile <<
"Boundary (" << i <<
") Elements ("
43469 << this->nboundary_element(i) <<
") "
43470 <<
"Nodes (" << this->nboundary_node(i) <<
")\n";
43475 std::set<unsigned> shared_boundaries_in_this_processor;
43479 for (
unsigned iproc = 0; iproc < nproc; iproc++)
43482 if (iproc != my_rank)
43485 unsigned nshared_boundaries_with_iproc =
43486 this->nshared_boundaries(my_rank, iproc);
43488 if (nshared_boundaries_with_iproc > 0)
43491 Vector<unsigned> bound_shared_with_iproc;
43492 bound_shared_with_iproc = this->shared_boundaries_ids(my_rank, iproc);
43495 for (
unsigned bs = 0; bs < nshared_boundaries_with_iproc; bs++)
43497 unsigned bnd_id = bound_shared_with_iproc[bs];
43498 shared_boundaries_in_this_processor.insert(bnd_id);
43509 for (std::map<unsigned, unsigned>::iterator it =
43510 shd_bnd_over_int_bnd.begin();
43511 it != shd_bnd_over_int_bnd.end();
43515 const unsigned shd_bnd_id = (*it).first;
43517 const unsigned int_bnd_id = (*it).second;
43520 std::set<unsigned>::iterator it_set =
43521 shared_boundaries_in_this_processor.find(shd_bnd_id);
43522 if (it_set != shared_boundaries_in_this_processor.end())
43524 internal_boundary_overlaped.insert(int_bnd_id);
43529 const unsigned nbnd_node_shd_bnd = this->nboundary_node(shd_bnd_id);
43533 if (outfile.is_open())
43535 outfile <<
"\nPass info. from shared (" << shd_bnd_id
43536 <<
") to internal (" << int_bnd_id <<
")\n";
43537 outfile <<
"Number of shared boundary nodes: " << nbnd_node_shd_bnd
43541 for (
unsigned in = 0; in < nbnd_node_shd_bnd; in++)
43544 Node* bnd_node_pt = this->boundary_node_pt(shd_bnd_id, in);
43546 this->add_boundary_node(int_bnd_id, bnd_node_pt);
43553 const unsigned nbnd_ele_shd_bnd = this->nboundary_element(shd_bnd_id);
43557 if (outfile.is_open())
43559 outfile <<
"Number of shared boundary elements: " << nbnd_ele_shd_bnd
43565 for (
unsigned ie = 0; ie < nbnd_ele_shd_bnd; ie++)
43568 FiniteElement* bnd_ele_pt = this->boundary_element_pt(shd_bnd_id, ie);
43571 Boundary_element_pt[int_bnd_id].push_back(bnd_ele_pt);
43573 int face_index = this->face_index_at_boundary(shd_bnd_id, ie);
43575 Face_index_at_boundary[int_bnd_id].push_back(face_index);
43580 const unsigned nregions = this->nregion();
43583 for (
unsigned ir = 0; ir < nregions; ir++)
43586 const unsigned region_id =
43587 static_cast<unsigned>(this->Region_attribute[ir]);
43590 const unsigned nele_ir =
43591 this->nboundary_element_in_region(shd_bnd_id, region_id);
43592 for (
unsigned ier = 0; ier < nele_ir; ier++)
43595 FiniteElement* bnd_ele_pt =
43596 this->boundary_element_in_region_pt(shd_bnd_id, region_id, ier);
43599 this->Boundary_region_element_pt[int_bnd_id][region_id].push_back(
43603 int face_index = this->face_index_at_boundary_in_region(
43604 shd_bnd_id, region_id, ier);
43606 this->Face_index_region_at_boundary[int_bnd_id][region_id]
43607 .push_back(face_index);
43621 if (outfile.is_open())
43623 const unsigned nbound = this->nboundary();
43624 outfile <<
"Number of boundaries: " << nbound <<
"\n\n";
43625 outfile <<
"Number of elements and nodes associated to each "
43626 <<
"boundary after\nfilling elements and nodes\n\n";
43627 for (
unsigned i = 0; i < nbound; i++)
43629 outfile <<
"Boundary (" << i <<
") Elements ("
43630 << this->nboundary_element(i) <<
")"
43631 <<
" Nodes (" << this->nboundary_node(i) <<
")\n";
43639 for (std::set<unsigned>::iterator it = internal_boundary_overlaped.begin();
43640 it != internal_boundary_overlaped.end();
43643 const unsigned overlaped_internal_bnd_id = (*it);
43646 this->
template setup_boundary_coordinates<ELEMENT>(
43647 overlaped_internal_bnd_id);
43656 template<
class ELEMENT>
43661 if (!Boundary_coordinate_exists[b])
43678 std::set<Node*> tmp_boundary_node_pt;
43679 const unsigned nboundary_ele = this->nboundary_element(b);
43680 for (
unsigned e = 0; e < nboundary_ele; e++)
43683 FiniteElement* bulk_ele_pt = this->boundary_element_pt(b, e);
43684 #ifdef OOMPH_HAS_MPI
43686 if (!bulk_ele_pt->is_halo())
43690 int face_index = this->face_index_at_boundary(b, e);
43692 FiniteElement* face_ele_pt =
43693 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
43696 const unsigned nnodes = face_ele_pt->nnode();
43697 for (
unsigned i = 0; i < nnodes; i++)
43700 Node* tmp_node_pt = face_ele_pt->node_pt(i);
43702 tmp_boundary_node_pt.insert(tmp_node_pt);
43706 delete face_ele_pt;
43708 #ifdef OOMPH_HAS_MPI
43715 const unsigned long n_boundary_node = tmp_boundary_node_pt.size();
43718 if (n_boundary_node == 0)
43720 #ifdef OOMPH_HAS_MPI
43722 if (!this->is_mesh_distributed())
43726 #ifdef OOMPH_HAS_MPI
43731 Mesh* face_mesh_pt =
new Mesh();
43732 create_unsorted_face_mesh_representation(b, face_mesh_pt);
43733 MeshAsGeomObject* mesh_geom_obj_pt =
new MeshAsGeomObject(face_mesh_pt);
43736 delete mesh_geom_obj_pt;
43740 face_mesh_pt->flush_node_storage();
43741 delete face_mesh_pt;
43749 Vector<double> node_coord(3);
43750 Vector<double> b_coord(1);
43752 Vector<Vector<double>> old_boundary_node(n_boundary_node);
43753 unsigned tmp_counter = 0;
43754 for (std::set<Node*>::iterator it_node = tmp_boundary_node_pt.begin();
43755 it_node != tmp_boundary_node_pt.end();
43756 it_node++, tmp_counter++)
43758 Node* nod_pt = (*it_node);
43759 nod_pt->get_coordinates_on_boundary(b, b_coord);
43760 node_coord[0] = b_coord[0];
43761 node_coord[1] = nod_pt->x(0);
43762 node_coord[2] = nod_pt->x(1);
43763 old_boundary_node[tmp_counter] = node_coord;
43767 std::sort(old_boundary_node.begin(), old_boundary_node.end());
43776 Vector<Vector<Node*>> segment_nodes_pt;
43778 #ifdef OOMPH_HAS_MPI
43780 const unsigned nsegments = new_mesh_pt->nboundary_segment(b);
43784 const unsigned nsegments = 1;
43787 #ifdef OOMPH_HAS_MPI
43789 const unsigned n_new_boundary_node = new_mesh_pt->nboundary_segment_node(b);
43792 if (this->is_mesh_distributed())
43797 if (n_new_boundary_node == 0)
43800 Mesh* face_mesh_pt =
new Mesh();
43801 create_unsorted_face_mesh_representation(b, face_mesh_pt);
43802 MeshAsGeomObject* mesh_geom_obj_pt =
new MeshAsGeomObject(face_mesh_pt);
43805 delete mesh_geom_obj_pt;
43808 face_mesh_pt->flush_node_storage();
43809 delete face_mesh_pt;
43816 Vector<Vector<unsigned>> nodes_to_be_snapped(nsegments);
43820 for (
unsigned is = 0; is < nsegments; is++)
43822 #ifdef OOMPH_HAS_MPI
43823 const unsigned n_new_boundary_segment_node =
43824 new_mesh_pt->nboundary_segment_node(b, is);
43826 const unsigned n_new_boundary_segment_node =
43827 new_mesh_pt->nboundary_node(b);
43830 Vector<Vector<double>> new_boundary_node(n_new_boundary_segment_node);
43832 node_coord.resize(6, 0.0);
43833 for (
unsigned n = 0; n < n_new_boundary_segment_node; n++)
43835 #ifdef OOMPH_HAS_MPI
43838 Node* nod_pt = new_mesh_pt->boundary_node_pt(b, n);
43840 nod_pt->get_coordinates_on_boundary(b, b_coord);
43841 node_coord[0] = b_coord[0];
43842 node_coord[1] = nod_pt->x(0);
43843 node_coord[2] = nod_pt->x(1);
43845 new_boundary_node[n] = node_coord;
43849 std::sort(new_boundary_node.begin(), new_boundary_node.end());
43856 unsigned old_index = 0;
43857 for (
unsigned n = 0; n < n_new_boundary_segment_node; ++n)
43861 for (
unsigned m = old_index; m < n_boundary_node; ++m)
43863 if ((std::fabs(old_boundary_node[m][1] - new_boundary_node[n][1]) <
43865 (std::fabs(old_boundary_node[m][2] - new_boundary_node[n][2]) <
43869 new_boundary_node[n][4] = old_boundary_node[m][0];
43871 new_boundary_node[n][5] = 1.0;
43882 if ((new_boundary_node[0][5] == 0.0) ||
43883 (new_boundary_node[n_new_boundary_segment_node - 1][5] == 0.0))
43885 std::ostringstream error_stream;
43887 <<
"New boundary coordinates not found for the first and/or last "
43889 <<
"on the boundary " << b <<
". This should not happen because "
43890 <<
"these\nlimits should have been setup in the constructor\n";
43892 <<
"The distance between the new and old nodes is probably outside\n"
43893 <<
"our tolerance.\n";
43894 error_stream.precision(20);
43895 error_stream <<
"Old boundaries: \n";
43896 error_stream << old_boundary_node[0][1] <<
" "
43897 << old_boundary_node[0][2] <<
" : "
43898 << old_boundary_node[n_boundary_node - 1][1] <<
" "
43899 << old_boundary_node[n_boundary_node - 1][2] <<
"\n";
43900 error_stream <<
"New boundaries: \n"
43901 << new_boundary_node[0][1] <<
" "
43902 << new_boundary_node[0][2] <<
" : "
43903 << new_boundary_node[n_new_boundary_segment_node - 1][1]
43905 << new_boundary_node[n_new_boundary_segment_node - 1][2]
43907 OomphLibWarning(error_stream.str(),
43908 "RefineableTriangleMesh::snap_nodes_onto_boundary()",
43909 OOMPH_EXCEPTION_LOCATION);
43915 if (!this->is_mesh_distributed())
43919 new_boundary_node[0][4] = new_boundary_node[0][0];
43922 new_boundary_node[n_new_boundary_segment_node - 1][4] =
43923 new_boundary_node[0][5] = 1.0;
43925 new_boundary_node[n_new_boundary_segment_node - 1][4] =
43926 new_boundary_node[n_new_boundary_segment_node - 1][0];
43927 new_boundary_node[n_new_boundary_segment_node - 1][5] = 1.0;
43932 for (
unsigned n = 1; n < n_new_boundary_segment_node - 1; ++n)
43935 if (new_boundary_node[n][5] == 0.0)
43938 nodes_to_be_snapped[is].push_back(
43939 static_cast<unsigned>(new_boundary_node[n][3]));
43943 double zeta_old_low = new_boundary_node[n - 1][0];
43944 double zeta_new_low = new_boundary_node[n - 1][4];
43948 for (
unsigned m = n + 1; m < n_new_boundary_segment_node; ++m)
43950 if (new_boundary_node[m][5] == 1.0)
43953 double zeta_old_high = new_boundary_node[m][0];
43954 double zeta_new_high = new_boundary_node[m][4];
43956 double frac = (new_boundary_node[n][0] - zeta_old_low) /
43957 (zeta_old_high - zeta_old_low);
43958 new_boundary_node[n][4] =
43959 zeta_new_low + frac * (zeta_new_high - zeta_new_low);
43960 new_boundary_node[n][5] = 1.0;
43968 for (
unsigned n = 0; n < n_new_boundary_segment_node; ++n)
43970 if (new_boundary_node[n][5] == 0)
43972 throw OomphLibError(
43973 "New boundary coordinate not assigned\n",
43974 "RefineableTriangleMesh::snap_nodes_onto_boundary()",
43975 OOMPH_EXCEPTION_LOCATION);
43978 #ifdef OOMPH_HAS_MPI
43982 b, is,
static_cast<unsigned>(new_boundary_node[n][3]))
43983 ->get_coordinates_on_boundary(b, b_coord);
43985 b_coord[0] = new_boundary_node[n][4];
43988 b, is,
static_cast<unsigned>(new_boundary_node[n][3]))
43989 ->set_coordinates_on_boundary(b, b_coord);
43993 ->boundary_node_pt(b,
static_cast<unsigned>(new_boundary_node[n][3]))
43994 ->get_coordinates_on_boundary(b, b_coord);
43996 b_coord[0] = new_boundary_node[n][4];
43998 ->boundary_node_pt(b,
static_cast<unsigned>(new_boundary_node[n][3]))
43999 ->set_coordinates_on_boundary(b, b_coord);
44005 Mesh* face_mesh_pt =
new Mesh();
44006 create_unsorted_face_mesh_representation(b, face_mesh_pt);
44009 MeshAsGeomObject* mesh_geom_obj_pt =
new MeshAsGeomObject(face_mesh_pt);
44013 Vector<double> new_x(2);
44016 for (
unsigned is = 0; is < nsegments; is++)
44018 const unsigned nnodes_to_snap = nodes_to_be_snapped[is].size();
44020 for (
unsigned in = 0; in < nnodes_to_snap; in++)
44023 unsigned n = nodes_to_be_snapped[is][in];
44024 #ifdef OOMPH_HAS_MPI
44029 Node*
const nod_pt = new_mesh_pt->boundary_node_pt(b, n);
44032 nod_pt->get_coordinates_on_boundary(b, b_coord);
44034 mesh_geom_obj_pt->position(b_coord, new_x);
44037 for (
unsigned i = 0; i < 2; i++)
44039 nod_pt->x(i) = new_x[i];
44045 delete mesh_geom_obj_pt;
44048 face_mesh_pt->flush_node_storage();
44049 delete face_mesh_pt;
44055 TElement<2, 3> dummy_six_node_element;
44056 for (
unsigned j = 0; j < 6; j++)
44058 dummy_six_node_element.construct_node(j);
44063 unsigned n_bound_el = new_mesh_pt->nboundary_element(b);
44064 for (
unsigned e = 0; e < n_bound_el; e++)
44066 FiniteElement* el_pt = new_mesh_pt->boundary_element_pt(b, e);
44069 unsigned nnod = el_pt->nnode();
44081 TElement<2, 2>* t_el_pt =
dynamic_cast<TElement<2, 2>*
>(el_pt);
44084 throw OomphLibError(
44085 "Have a three-noded element that's not a TElement<2,2>",
44086 OOMPH_CURRENT_FUNCTION,
44087 OOMPH_EXCEPTION_LOCATION);
44095 else if ((nnod == 6) || (nnod == 7))
44099 TElement<2, 3>* t_el_pt =
dynamic_cast<TElement<2, 3>*
>(el_pt);
44104 throw OomphLibError(
44105 "Have a six-noded element that's not a TElement<2,3>",
44106 OOMPH_CURRENT_FUNCTION,
44107 OOMPH_EXCEPTION_LOCATION);
44111 throw OomphLibError(
44112 "Have a seven-noded element that's not a TElement<2,3>",
44113 OOMPH_CURRENT_FUNCTION,
44114 OOMPH_EXCEPTION_LOCATION);
44127 if (el_pt->node_pt(3)->is_on_boundary(b))
44131 if (!el_pt->node_pt(5)->is_on_boundary())
44134 for (
unsigned i = 0; i < 2; i++)
44136 el_pt->node_pt(5)->x(i) =
44137 0.5 * (el_pt->node_pt(0)->x(i) + el_pt->node_pt(2)->x(i));
44142 if (!el_pt->node_pt(4)->is_on_boundary())
44145 for (
unsigned i = 0; i < 2; i++)
44147 el_pt->node_pt(4)->x(i) =
44148 0.5 * (el_pt->node_pt(1)->x(i) + el_pt->node_pt(2)->x(i));
44154 if (el_pt->node_pt(4)->is_on_boundary(b))
44158 if (!el_pt->node_pt(5)->is_on_boundary())
44161 for (
unsigned i = 0; i < 2; i++)
44163 el_pt->node_pt(5)->x(i) =
44164 0.5 * (el_pt->node_pt(0)->x(i) + el_pt->node_pt(2)->x(i));
44169 if (!el_pt->node_pt(3)->is_on_boundary())
44172 for (
unsigned i = 0; i < 2; i++)
44174 el_pt->node_pt(3)->x(i) =
44175 0.5 * (el_pt->node_pt(0)->x(i) + el_pt->node_pt(1)->x(i));
44181 if (el_pt->node_pt(5)->is_on_boundary(b))
44185 if (!el_pt->node_pt(4)->is_on_boundary())
44188 for (
unsigned i = 0; i < 2; i++)
44190 el_pt->node_pt(4)->x(i) =
44191 0.5 * (el_pt->node_pt(1)->x(i) + el_pt->node_pt(2)->x(i));
44196 if (!el_pt->node_pt(3)->is_on_boundary())
44199 for (
unsigned i = 0; i < 2; i++)
44201 el_pt->node_pt(3)->x(i) =
44202 0.5 * (el_pt->node_pt(0)->x(i) + el_pt->node_pt(1)->x(i));
44212 TBubbleEnrichedElement<2, 3>* t_el_pt =
44213 dynamic_cast<TBubbleEnrichedElement<2, 3>*
>(el_pt);
44216 throw OomphLibError(
"Have seven-noded element that's not a "
44217 "TBubbleEnrichedElement<2,3>",
44218 OOMPH_CURRENT_FUNCTION,
44219 OOMPH_EXCEPTION_LOCATION);
44224 for (
unsigned j = 0; j < 6; j++)
44226 for (
unsigned i = 0; i < 2; i++)
44228 dummy_six_node_element.node_pt(j)->x(i) = el_pt->node_pt(j)->x(i);
44233 unsigned j_enriched = 6;
44234 Vector<double> s(2);
44235 el_pt->local_coordinate_of_node(j_enriched, s);
44238 Vector<double> x(2);
44239 dummy_six_node_element.interpolated_x(s, x);
44240 el_pt->node_pt(j_enriched)->x(0) = x[0];
44241 el_pt->node_pt(j_enriched)->x(1) = x[1];
44248 std::ostringstream error_stream;
44249 error_stream <<
"Cannot deal with this particular " << nnod
44250 <<
"-noded element yet.\n"
44251 <<
"Please implement this yourself.\n";
44252 throw OomphLibError(
44253 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
44258 for (
unsigned j = 0; j < 6; j++)
44260 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