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;
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);
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();
238 unsigned n_node = finite_element_pt(0)->nnode();
241 unsigned n_global_edge = Tmp_mesh_pt->nglobal_edge();
245 for (
unsigned e = 0;
e < nelem;
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)
266 for (
unsigned i = 0;
i < dim;
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;
303 this->add_boundary_node(boundary_id - 1, new_node_pt);
316 for (
unsigned i = 0;
i < dim;
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)
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>
403 unsigned n_repeated_ele = 0;
405 const unsigned n_regions = this->nregion();
409 std::map<FiniteElement*, FiniteElement*> face_to_bulk_element_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++)
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);
465 const unsigned n_nodes = tmp_ele_pt->
nnode();
467 std::pair<Node*, Node*> tmp_pair = std::make_pair(
470 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
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++)
536 if (this->is_mesh_distributed() && bulk_elem_pt->
is_halo())
546 int face_index = this->face_index_at_boundary(b,
e);
554 const unsigned n_nodes = tmp_ele_pt->
nnode();
556 std::pair<Node*, Node*> tmp_pair = std::make_pair(
559 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
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";
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++)
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
667 "TriangleMesh::identify_boundary_segments_and_assign_"
668 "initial_zeta_values()",
669 OOMPH_EXCEPTION_LOCATION);
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;
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";
733 "TriangleMesh::identify_boundary_segments_and_"
734 "assign_initial_zeta_values()",
735 OOMPH_EXCEPTION_LOCATION);
740 const unsigned nnod = ele_face_pt->
nnode();
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();
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";
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";
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();
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);
918 if (this->boundary_geom_object_pt(b) != 0)
921 initial_zeta_segment[is] = zeta[0];
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();
942 if (is_inverted[el_pt])
949 for (
unsigned j = 1; j < nnod; j++)
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";
1004 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
1032 const unsigned nsegments_initial_coordinates =
1035 const unsigned nsegments_final_coordinates =
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";
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
1063 OOMPH_CURRENT_FUNCTION,
1064 OOMPH_EXCEPTION_LOCATION);
1077 Vector<double> original_mesh_segment_initial_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] =
1088 original_mesh_segment_final_coordinate[is][k] =
1092 if (this->boundary_geom_object_pt(b) != 0)
1094 original_mesh_segment_initial_zeta[is] =
1096 original_mesh_segment_final_zeta[is] =
1101 original_mesh_segment_initial_arclength[is] =
1103 original_mesh_segment_final_arclength[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;
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);
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])
1180 original_mesh_segment_initial_coordinate[orig_s];
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]));
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]));
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);
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);
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";
1335 OOMPH_CURRENT_FUNCTION,
1336 OOMPH_EXCEPTION_LOCATION);
1357 if (
this != original_mesh_pt)
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();
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);
1421 if (!Boundary_segment_inverted[b][is])
1424 b, current_segment_initial_arclen);
1426 b, current_segment_final_arclen);
1431 b, current_segment_final_arclen);
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]
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 =
1487 const double original_segment_final_arclength =
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";
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();
1562 Node* nod_pt = (*it);
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)
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();
1610 Node* nod_pt = (*it);
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)
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();
1657 Node* nod_pt = (*it);
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)
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();
1704 Node* nod_pt = (*it);
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)
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);
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";
1765 OOMPH_CURRENT_FUNCTION,
1766 OOMPH_EXCEPTION_LOCATION);
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";
1782 OOMPH_CURRENT_FUNCTION,
1783 OOMPH_EXCEPTION_LOCATION);
1802 Boundary_initial_coordinate[b] =
1805 Boundary_final_coordinate[b] =
1810 Boundary_initial_zeta_coordinate[b] =
1813 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>
1849 const unsigned nproc = comm_pt->nproc();
1851 const unsigned my_rank = comm_pt->my_rank();
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++)
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;
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;
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";
1973 OOMPH_CURRENT_FUNCTION,
1974 OOMPH_EXCEPTION_LOCATION);
1979 const unsigned nnod = ele_face_pt->
nnode();
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);
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";
2087 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
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";
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();
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);
2143 if (this->boundary_geom_object_pt(b) != 0)
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);
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();
2185 if (is_inverted[el_pt])
2192 for (
unsigned j = 1; j < nnod; j++)
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);
2259 unsigned proc_with_initial_seg = 0;
2260 unsigned proc_with_final_seg = 0;
2264 unsigned initial_segment = 0;
2265 unsigned final_segment = 0;
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();
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++)
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)
2417 for (
unsigned is = 0; is < nsegments; is++)
2420 FiniteElement* left_face_ele_pt = segment_sorted_ele_pt[is].front();
2425 face_to_bulk_element_pt[left_face_ele_pt];
2428 if (tmp_left_bulk_ele_pt->
is_halo())
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 "
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;
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";
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";
2506 OOMPH_CURRENT_FUNCTION,
2507 OOMPH_EXCEPTION_LOCATION);
2513 left_element_pt = tmp_left_bulk_ele_pt;
2517 bool left_haloed_element_found =
false;
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";
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();
2568 face_to_bulk_element_pt[right_face_ele_pt];
2571 if (tmp_right_bulk_ele_pt->
is_halo())
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 "
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;
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";
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";
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;
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";
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;
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;
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();
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];
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);
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;
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();
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];
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);
2924 double root_accumulated_arclength = 0.0;
2928 unsigned root_accumulated_vertices_before_segment = 0;
2932 if (my_rank == root_processor)
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++];
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";
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";
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";
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);
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];
3487 for (
unsigned ip = 0; ip < nproc; ip++)
3490 root_nudata_to_send[ip] = root_nsegments_per_processor[ip] * rspu;
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];
3554 for (
unsigned ip = 0; ip < nproc; ip++)
3557 root_nddata_to_send[ip] = root_nsegments_per_processor[ip] * rspd;
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;
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++)
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";
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";
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";
3820 "TriangleMesh::compute_boundary_segments_"
3821 "connectivity_and_initial_zeta_values()",
3822 OOMPH_EXCEPTION_LOCATION);
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)
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);
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];
3945 if (my_rank == proc_with_final_seg)
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);
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)
4107 unsigned n_repeated_ele = 0;
4109 const unsigned n_regions = this->nregion();
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++)
4141 this->boundary_element_in_region_pt(b, region_id,
e);
4152 this->face_index_at_boundary_in_region(b, region_id,
e);
4160 const unsigned n_nodes = tmp_ele_pt->
nnode();
4162 std::pair<Node*, Node*> tmp_pair = std::make_pair(
4165 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
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++)
4235 int face_index = this->face_index_at_boundary(b,
e);
4243 const unsigned n_nodes = tmp_ele_pt->
nnode();
4245 std::pair<Node*, Node*> tmp_pair = std::make_pair(
4248 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
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";
4303 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
4312 const unsigned nnon_halo_face_elements = face_el_pt.size();
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;
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";
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();
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";
4482 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
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";
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();
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);
4552 if (this->boundary_geom_object_pt(b) != 0)
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);
4568 final_zeta_segment[is] = zeta[0];
4573 std::set<Node*> local_nodes_pt;
4574 local_nodes_pt.insert(first_node_pt);
4578 sorted_node_arclength.push_back(0.0);
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();
4597 if (is_inverted[el_pt])
4604 for (
unsigned j = 1; j < nnod; j++)
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();
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;
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);
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];
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];
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";
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];
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];
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";
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>
5284 bool& is_internal_boundary,
5285 std::map<FiniteElement*, FiniteElement*>& face_to_bulk_element_pt)
5290 const unsigned my_rank = comm_pt->my_rank();
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++)
5325 this->boundary_element_in_region_pt(b, region_id,
e);
5330 this->face_index_at_boundary_in_region(b, region_id,
e);
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++)
5370 int face_index = this->face_index_at_boundary(b,
e);
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;
5403 const unsigned n_tmp_face_ele = tmp_face_ele_pt.size();
5404 for (
unsigned ie = 0; ie < n_tmp_face_ele; 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;
5454 face_to_bulk_element_pt[main_face_ele_pt];
5456 face_to_bulk_element_pt[dependant_face_ele_pt];
5460 int processor_in_charge_main_bulk_ele =
5462 int processor_in_charge_dependant_bulk_ele =
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)
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>
5620 const unsigned nproc = comm_pt->nproc();
5621 const unsigned my_rank = comm_pt->my_rank();
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++)
5655 this->boundary_element_in_region_pt(b, region_id,
e);
5659 this->face_index_at_boundary_in_region(b, region_id,
e);
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++)
5696 int face_index = this->face_index_at_boundary(b,
e);
5704 tmp_face_ele_pt.push_back(tmp_face_el_pt);
5706 face_to_bulk_element_pt[tmp_face_el_pt] = bulk_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++)
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;
5785 face_to_bulk_element_pt[main_face_ele_pt];
5787 face_to_bulk_element_pt[dependant_face_ele_pt];
5790 int processor_in_charge_main_bulk_ele =
5792 int processor_in_charge_dependant_bulk_ele =
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)
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";
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++)
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;
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])
5982 const unsigned nnodes = ele_face_pt->
nnode();
5984 for (
unsigned in = 0; in < nnodes; in++)
5988 if (!done_node[face_node_pt])
5991 done_node[face_node_pt] =
true;
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";
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";
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";
6126 error_message.str(),
6127 "TriangleMesh::synchronize_boundary_coordinates()",
6128 OOMPH_EXCEPTION_LOCATION);
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];
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);
6167 unsigned nflat_unsigned_send = flat_unsigned_send_packed_data.size();
6168 MPI_Isend(&nflat_unsigned_send,
6173 comm_pt->mpi_comm(),
6176 unsigned nflat_unsigned_receive = 0;
6177 MPI_Recv(&nflat_unsigned_receive,
6182 comm_pt->mpi_comm(),
6185 MPI_Wait(&request, MPI_STATUS_IGNORE);
6187 if (nflat_unsigned_send != 0)
6189 MPI_Isend(&flat_unsigned_send_packed_data[0],
6190 nflat_unsigned_send,
6194 comm_pt->mpi_comm(),
6198 if (nflat_unsigned_receive != 0)
6200 flat_unsigned_receive_packed_data.resize(nflat_unsigned_receive);
6201 MPI_Recv(&flat_unsigned_receive_packed_data[0],
6202 nflat_unsigned_receive,
6206 comm_pt->mpi_comm(),
6210 if (nflat_unsigned_send != 0)
6212 MPI_Wait(&request, MPI_STATUS_IGNORE);
6219 MPI_Request my_request;
6222 unsigned nflat_double_send = flat_double_send_packed_data.size();
6223 MPI_Isend(&nflat_double_send,
6228 comm_pt->mpi_comm(),
6231 unsigned nflat_double_receive = 0;
6232 MPI_Recv(&nflat_double_receive,
6237 comm_pt->mpi_comm(),
6241 MPI_Wait(&my_request, MPI_STATUS_IGNORE);
6243 if (nflat_double_send != 0)
6245 MPI_Isend(&flat_double_send_packed_data[0],
6250 comm_pt->mpi_comm(),
6254 if (nflat_double_receive != 0)
6256 flat_double_receive_packed_data.resize(nflat_double_receive);
6257 MPI_Recv(&flat_double_receive_packed_data[0],
6258 nflat_double_receive,
6262 comm_pt->mpi_comm(),
6266 if (nflat_double_send != 0)
6268 MPI_Wait(&my_request, MPI_STATUS_IGNORE);
6273 if (nflat_unsigned_receive != nflat_double_receive)
6275 std::ostringstream error_message;
6276 error_message <<
"The number of unsigned received data ("
6277 << nflat_unsigned_receive <<
") is different from the "
6278 <<
"number\nof double received data ("
6279 << nflat_double_receive <<
")!!!\n\n";
6281 error_message.str(),
6282 "TriangleMesh::synchronize_boundary_coordinates()",
6283 OOMPH_EXCEPTION_LOCATION);
6290 for (
unsigned iflat_packed = 0; iflat_packed < nflat_unsigned_receive;
6294 const unsigned haloed_id =
6295 flat_unsigned_receive_packed_data[iflat_packed];
6298 zeta[0] = flat_double_receive_packed_data[iflat_packed];
6301 Node* haloed_face_node_pt = this->haloed_node_pt(ip, haloed_id);
6315 if (!done_haloed_face_node[haloed_face_node_pt])
6321 for (
unsigned iiproc = 0; iiproc < nproc; iiproc++)
6324 if (iiproc != my_rank)
6327 const unsigned nhaloed_node_iiproc = this->nhaloed_node(iiproc);
6328 for (
unsigned ihdn = 0; ihdn < nhaloed_node_iiproc; ihdn++)
6330 Node* compare_haloed_node_pt =
6331 this->haloed_node_pt(iiproc, ihdn);
6332 if (haloed_face_node_pt == compare_haloed_node_pt)
6336 face_haloed_node_pt[iiproc].push_back(haloed_face_node_pt);
6339 face_haloed_node_id[iiproc].push_back(ihdn);
6360 for (
unsigned ip = 0; ip < nproc; ip++)
6372 const unsigned nhaloed_face_nodes = face_haloed_node_pt[ip].size();
6374 for (
unsigned ihdfn = 0; ihdfn < nhaloed_face_nodes; ihdfn++)
6377 Node* haloed_face_node_pt = face_haloed_node_pt[ip][ihdfn];
6379 const unsigned haloed_id = face_haloed_node_id[ip][ihdfn];
6384 flat_unsigned_send_packed_data.push_back(haloed_id);
6385 flat_double_send_packed_data.push_back(zeta[0]);
6390 MPI_Request request;
6393 int send_proc =
static_cast<int>(ip);
6395 int receive_proc =
static_cast<int>(ip);
6403 unsigned nflat_unsigned_send = flat_unsigned_send_packed_data.size();
6404 MPI_Isend(&nflat_unsigned_send,
6409 comm_pt->mpi_comm(),
6412 unsigned nflat_unsigned_receive = 0;
6413 MPI_Recv(&nflat_unsigned_receive,
6418 comm_pt->mpi_comm(),
6421 MPI_Wait(&request, MPI_STATUS_IGNORE);
6423 if (nflat_unsigned_send != 0)
6425 MPI_Isend(&flat_unsigned_send_packed_data[0],
6426 nflat_unsigned_send,
6430 comm_pt->mpi_comm(),
6434 if (nflat_unsigned_receive != 0)
6436 flat_unsigned_receive_packed_data.resize(nflat_unsigned_receive);
6437 MPI_Recv(&flat_unsigned_receive_packed_data[0],
6438 nflat_unsigned_receive,
6442 comm_pt->mpi_comm(),
6446 if (nflat_unsigned_send != 0)
6448 MPI_Wait(&request, MPI_STATUS_IGNORE);
6453 unsigned nflat_double_send = flat_double_send_packed_data.size();
6454 MPI_Isend(&nflat_double_send,
6459 comm_pt->mpi_comm(),
6462 unsigned nflat_double_receive = 0;
6463 MPI_Recv(&nflat_double_receive,
6468 comm_pt->mpi_comm(),
6471 MPI_Wait(&request, MPI_STATUS_IGNORE);
6473 if (nflat_double_send != 0)
6475 MPI_Isend(&flat_double_send_packed_data[0],
6480 comm_pt->mpi_comm(),
6484 if (nflat_double_receive != 0)
6486 flat_double_receive_packed_data.resize(nflat_double_receive);
6487 MPI_Recv(&flat_double_receive_packed_data[0],
6488 nflat_double_receive,
6492 comm_pt->mpi_comm(),
6496 if (nflat_double_send != 0)
6498 MPI_Wait(&request, MPI_STATUS_IGNORE);
6503 if (nflat_unsigned_receive != nflat_double_receive)
6505 std::ostringstream error_message;
6506 error_message <<
"The number of unsigned received data ("
6507 << nflat_unsigned_receive <<
") is different from the "
6508 <<
"number\nof double received data ("
6509 << nflat_double_receive <<
")!!!\n\n";
6511 error_message.str(),
6512 "TriangleMesh::synchronize_boundary_coordinates()",
6513 OOMPH_EXCEPTION_LOCATION);
6520 for (
unsigned iflat_packed = 0; iflat_packed < nflat_unsigned_receive;
6524 const unsigned halo_id =
6525 flat_unsigned_receive_packed_data[iflat_packed];
6528 zeta[0] = flat_double_receive_packed_data[iflat_packed];
6531 Node* halo_face_node_pt = this->halo_node_pt(ip, halo_id);
6548 for (
unsigned ie = 0; ie < nbound_ele; ie++)
6550 delete tmp_face_ele_pt[ie];
6551 tmp_face_ele_pt[ie] = 0;
6556 if (is_internal_boundary)
6558 re_scale_re_assigned_initial_zeta_values_for_internal_boundary(b);
6568 template<
class ELEMENT>
6586 unsigned n_repeated_ele = 0;
6588 const unsigned n_regions = this->nregion();
6597 for (
unsigned rr = 0; rr < n_regions; rr++)
6599 const unsigned region_id =
6600 static_cast<unsigned>(this->Region_attribute[rr]);
6603 const unsigned nel_in_region =
6604 this->nboundary_element_in_region(b, region_id);
6606 unsigned nel_repetead_in_region = 0;
6610 if (nel_in_region > 0)
6612 bool repeated =
false;
6615 for (
unsigned e = 0;
e < nel_in_region;
e++)
6620 this->boundary_element_in_region_pt(b, region_id,
e);
6631 this->face_index_at_boundary_in_region(b, region_id,
e);
6639 const unsigned n_nodes = tmp_ele_pt->
nnode();
6641 std::pair<Node*, Node*> tmp_pair = std::make_pair(
6644 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
6648 const unsigned n_done_nodes = done_nodes_pt.size();
6649 for (
unsigned l = 0; l < n_done_nodes; l++)
6651 if (tmp_pair == done_nodes_pt[l] ||
6652 tmp_pair_inverse == done_nodes_pt[l])
6654 nel_repetead_in_region++;
6664 done_nodes_pt.push_back(tmp_pair);
6666 face_el_pt.push_back(tmp_ele_pt);
6680 nele += nel_in_region;
6682 n_repeated_ele += nel_repetead_in_region;
6691 nele = this->nboundary_element(b);
6697 bool repeated =
false;
6700 for (
unsigned e = 0;
e < nele;
e++)
6715 int face_index = this->face_index_at_boundary(b,
e);
6723 const unsigned n_nodes = tmp_ele_pt->
nnode();
6725 std::pair<Node*, Node*> tmp_pair = std::make_pair(
6728 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
6732 const unsigned n_done_nodes = done_nodes_pt.size();
6733 for (
unsigned l = 0; l < n_done_nodes; l++)
6735 if (tmp_pair == done_nodes_pt[l] ||
6736 tmp_pair_inverse == done_nodes_pt[l])
6750 done_nodes_pt.push_back(tmp_pair);
6752 face_el_pt.push_back(tmp_ele_pt);
6770 nele -= n_repeated_ele;
6773 if (nele != face_el_pt.size())
6775 std::ostringstream error_message;
6777 <<
"The independet counting of face elements (" << nele <<
") for "
6778 <<
"boundary (" << b <<
") is different\n"
6779 <<
"from the real number of face elements in the container ("
6780 << face_el_pt.size() <<
")\n";
6783 "TriangleMesh::re_scale_re_assigned_initial_zeta_"
6784 "values_for_internal_boundary()",
6785 OOMPH_EXCEPTION_LOCATION);
6795 const unsigned nnon_halo_face_elements = face_el_pt.size();
6802 unsigned nsorted_face_elements = 0;
6805 std::map<FiniteElement*, bool> done_el;
6808 std::map<FiniteElement*, bool> is_inverted;
6811 while (nsorted_face_elements < nnon_halo_face_elements)
6815 std::list<FiniteElement*> sorted_el_pt;
6819 bool found_initial_face_element =
false;
6825 for (iface = 0; iface < nele; iface++)
6827 ele_face_pt = face_el_pt[iface];
6829 if (!done_el[ele_face_pt])
6832 found_initial_face_element =
true;
6834 nsorted_face_elements++;
6836 sorted_el_pt.push_back(ele_face_pt);
6838 done_el[ele_face_pt] =
true;
6844 if (!found_initial_face_element)
6846 std::ostringstream error_message;
6848 <<
"Could not find an initial face element for the current segment\n";
6851 "TriangleMesh::re_scale_re_assigned_initial_zeta_"
6852 "values_for_internal_boundary()",
6853 OOMPH_EXCEPTION_LOCATION);
6858 const unsigned nnod = ele_face_pt->
nnode();
6863 Node* right_node_pt = ele_face_pt->
node_pt(nnod - 1);
6867 bool face_element_added =
false;
6876 for (
unsigned iiface = iface; iiface < nele; iiface++)
6879 face_element_added =
false;
6882 ele_face_pt = face_el_pt[iiface];
6885 if (!(done_el[ele_face_pt]))
6888 Node* local_left_node_pt = ele_face_pt->node_pt(0);
6889 Node* local_right_node_pt = ele_face_pt->node_pt(nnod - 1);
6892 if (left_node_pt == local_right_node_pt)
6894 left_node_pt = local_left_node_pt;
6895 sorted_el_pt.push_front(ele_face_pt);
6896 is_inverted[ele_face_pt] =
false;
6897 face_element_added =
true;
6900 else if (left_node_pt == local_left_node_pt)
6902 left_node_pt = local_right_node_pt;
6903 sorted_el_pt.push_front(ele_face_pt);
6904 is_inverted[ele_face_pt] =
true;
6905 face_element_added =
true;
6908 else if (right_node_pt == local_left_node_pt)
6910 right_node_pt = local_right_node_pt;
6911 sorted_el_pt.push_back(ele_face_pt);
6912 is_inverted[ele_face_pt] =
false;
6913 face_element_added =
true;
6916 else if (right_node_pt == local_right_node_pt)
6918 right_node_pt = local_left_node_pt;
6919 sorted_el_pt.push_back(ele_face_pt);
6920 is_inverted[ele_face_pt] =
true;
6921 face_element_added =
true;
6924 if (face_element_added)
6926 done_el[ele_face_pt] =
true;
6927 nsorted_face_elements++;
6933 }
while (face_element_added &&
6934 (nsorted_face_elements < nnon_halo_face_elements));
6937 segment_sorted_ele_pt.push_back(sorted_el_pt);
6953 const unsigned nsegments = segment_sorted_ele_pt.size();
6956 if (nnon_halo_face_elements > 0 && nsegments == 0)
6958 std::ostringstream error_message;
6960 <<
"The number of segments is zero, but the number of nonhalo\n"
6961 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
6963 "TriangleMesh::re_scale_re_assigned_initial_zeta_"
6964 "values_for_internal_boundary()",
6965 OOMPH_EXCEPTION_LOCATION);
6980 for (
unsigned is = 0; is < nsegments; is++)
6983 if (segment_sorted_ele_pt[is].size() == 0)
6985 std::ostringstream error_message;
6986 error_message <<
"The (" << is <<
")-th segment has no elements\n";
6988 "TriangleMesh::re_scale_re_assigned_initial_zeta_"
6989 "values_for_internal_boundary()",
6990 OOMPH_EXCEPTION_LOCATION);
6995 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
6998 const unsigned nnod = first_ele_pt->
nnode();
7002 if (is_inverted[first_ele_pt])
7004 first_node_pt = first_ele_pt->
node_pt(nnod - 1);
7008 FiniteElement* last_ele_pt = segment_sorted_ele_pt[is].back();
7011 Node* last_node_pt = last_ele_pt->
node_pt(nnod - 1);
7012 if (is_inverted[last_ele_pt])
7014 last_node_pt = last_ele_pt->
node_pt(0);
7018 double x_left = first_node_pt->
x(0);
7019 double y_left = first_node_pt->
x(1);
7028 if (this->boundary_geom_object_pt(b) != 0)
7031 initial_zeta_segment[is] = zeta[0];
7033 final_zeta_segment[is] = zeta[0];
7037 std::set<Node*> local_nodes_pt;
7038 local_nodes_pt.insert(first_node_pt);
7041 for (std::list<FiniteElement*>::iterator it =
7042 segment_sorted_ele_pt[is].begin();
7043 it != segment_sorted_ele_pt[is].end();
7052 if (is_inverted[el_pt])
7059 for (
unsigned j = 1; j < nnod; j++)
7065 double x_right = nod_pt->
x(0);
7066 double y_right = nod_pt->
x(1);
7069 zeta[0] += sqrt((x_right - x_left) * (x_right - x_left) +
7070 (y_right - y_left) * (y_right - y_left));
7078 local_nodes_pt.insert(nod_pt);
7084 segment_arclength[is] = zeta[0];
7087 segment_all_nodes_pt.push_back(local_nodes_pt);
7099 Boundary_segment_inverted[b].clear();
7100 Boundary_segment_initial_coordinate[b].clear();
7101 Boundary_segment_final_coordinate[b].clear();
7103 Boundary_segment_initial_zeta[b].clear();
7104 Boundary_segment_final_zeta[b].clear();
7106 Boundary_segment_initial_arclength[b].clear();
7107 Boundary_segment_final_arclength[b].clear();
7112 first_node_zeta_coordinate = boundary_initial_zeta_coordinate(b);
7113 last_node_zeta_coordinate = boundary_final_zeta_coordinate(b);
7116 const double boundary_arclength =
7117 std::max(first_node_zeta_coordinate[0], last_node_zeta_coordinate[0]);
7121 for (
unsigned is = 0; is < nsegments; is++)
7124 FiniteElement* first_face_ele_pt = segment_sorted_ele_pt[is].front();
7127 const unsigned nnod = first_face_ele_pt->
nnode();
7130 Node* first_node_pt = first_face_ele_pt->
node_pt(0);
7131 if (is_inverted[first_face_ele_pt])
7133 first_node_pt = first_face_ele_pt->
node_pt(nnod - 1);
7141 FiniteElement* last_face_ele_pt = segment_sorted_ele_pt[is].back();
7144 Node* last_node_pt = last_face_ele_pt->
node_pt(nnod - 1);
7145 if (is_inverted[last_face_ele_pt])
7147 last_node_pt = last_face_ele_pt->
node_pt(0);
7158 for (
unsigned i = 0;
i < 2;
i++)
7160 first_node_coord[
i] = first_node_pt->
x(
i);
7161 last_node_coord[
i] = last_node_pt->
x(
i);
7165 Boundary_segment_inverted[b].push_back(0);
7166 Boundary_segment_initial_coordinate[b].push_back(first_node_coord);
7167 Boundary_segment_final_coordinate[b].push_back(last_node_coord);
7170 if (this->boundary_geom_object_pt(b) != 0)
7172 Boundary_segment_initial_zeta[b].push_back(zeta_first[0]);
7173 Boundary_segment_final_zeta[b].push_back(zeta_last[0]);
7178 Boundary_segment_initial_arclength[b].push_back(zeta_first[0] *
7179 boundary_arclength);
7180 Boundary_segment_final_arclength[b].push_back(zeta_last[0] *
7181 boundary_arclength);
7187 for (
unsigned i = 0;
i < nele;
i++)
7189 delete face_el_pt[
i];
7197 #ifdef OOMPH_HAS_TRIANGLE_LIB
7202 template<
class ELEMENT>
7206 bool& use_attributes)
7210 std::ifstream poly_file(poly_file_name.c_str(), std::ios_base::in);
7214 OOMPH_CURRENT_FUNCTION,
7215 OOMPH_EXCEPTION_LOCATION);
7222 poly_file.ignore(80,
'\n');
7225 unsigned invertices;
7226 poly_file >> invertices;
7231 (
double*)malloc(triangulate_io.
numberofpoints * 2 *
sizeof(
double));
7235 poly_file >> mesh_dim;
7246 OOMPH_CURRENT_FUNCTION,
7247 OOMPH_EXCEPTION_LOCATION);
7253 poly_file >> nextras;
7259 unsigned nodemarkers;
7260 poly_file >> nodemarkers;
7266 if (nextras != 0 || nodemarkers != 0)
7268 oomph_info <<
"===================================================="
7271 oomph_info <<
"Reading the .poly file via oomph_lib \n"
7272 <<
"point's attribute and point's markers \n"
7273 <<
"are automatically set to 0" << std::endl;
7274 oomph_info <<
"===================================================="
7280 unsigned dummy_value;
7281 unsigned count_point = 0;
7285 getline(poly_file, test_string,
'#');
7286 poly_file.ignore(80,
'\n');
7290 for (
unsigned count = 0; count < invertices; count++)
7292 poly_file >> dummy_value;
7293 poly_file >> triangulate_io.
pointlist[count_point];
7294 poly_file >> triangulate_io.
pointlist[count_point + 1];
7295 if (nextras != 0 || nodemarkers != 0)
7297 for (
unsigned j = 0; j < nextras; j++)
7299 poly_file >> dummy_value;
7302 else if (nextras != 0 && nodemarkers != 0)
7304 for (
unsigned j = 0; j < nextras; j++)
7306 poly_file >> dummy_value;
7307 poly_file >> dummy_value;
7311 poly_file.ignore(80,
'\n');
7314 if (poly_file.get() ==
'#')
7316 poly_file.ignore(80,
'\n');
7332 unsigned inelements;
7333 poly_file >> inelements;
7335 unsigned segment_markers;
7336 poly_file >> segment_markers;
7341 if (segment_markers != 1)
7343 std::ostringstream error_stream;
7344 error_stream <<
"The segment marker should be provided \n"
7345 <<
"In order to assign each segment to a boundary \n "
7349 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
7360 for (
unsigned i = 0;
i < 2 * inelements;
i += 2)
7362 poly_file >> dummy_seg;
7365 if (segment_markers != 0)
7371 poly_file.ignore(80,
'\n');
7376 if (getline(poly_file, test_string,
'#'))
7378 poly_file.ignore(80,
'\n');
7380 unsigned dummy_hole;
7386 (
double*)malloc(triangulate_io.
numberofholes * 2 *
sizeof(
double));
7390 for (
unsigned i = 0;
i < 2 * nhole;
i += 2)
7392 poly_file >> dummy_hole;
7393 poly_file >> triangulate_io.
holelist[
i];
7394 poly_file >> triangulate_io.
holelist[
i + 1];
7400 if (getline(poly_file, test_string,
'#'))
7402 poly_file.ignore(80,
'\n');
7404 unsigned dummy_region;
7406 poly_file >> nregion;
7407 std::cerr <<
"Regions: " << nregion << std::endl;
7417 use_attributes =
true;
7422 for (
unsigned i = 0;
i < nregion;
i++)
7424 poly_file >> dummy_region;
7426 poly_file >> triangulate_io.
regionlist[4 *
i + 1];
7427 poly_file >> triangulate_io.
regionlist[4 *
i + 2];
7435 #ifdef OOMPH_HAS_TRIANGLE_LIB
7436 #ifdef OOMPH_HAS_MPI
7441 template<
class ELEMENT>
7443 std::ostream& dump_file)
7446 if (this->is_mesh_distributed())
7449 const unsigned nboundary = this->nboundary();
7450 dump_file << nboundary <<
" # number of original boundaries" << std::endl;
7453 const unsigned nshared_boundaries = this->nshared_boundaries();
7454 dump_file << nshared_boundaries <<
" # number of shared boundaries"
7458 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
7459 dump_file << init_shd_bnd_id <<
" # initial shared boundaries id"
7462 const unsigned final_shd_bnd_id = this->final_shared_boundary_id();
7463 dump_file << final_shd_bnd_id <<
" # final shared boundaries id"
7467 const unsigned nprocs = this->shared_boundaries_ids().size();
7468 dump_file << nprocs <<
" # number of processors" << std::endl;
7472 for (
unsigned ip = 0; ip < nprocs; ip++)
7474 for (
unsigned jp = 0; jp < nprocs; jp++)
7480 const unsigned nshared_boundaries_iproc_jproc =
7481 this->shared_boundaries_ids(ip, jp).size();
7485 dump_file << nshared_boundaries_iproc_jproc
7486 <<
" # number of shared boundaries with in two "
7487 <<
"processors" << std::endl;
7488 for (
unsigned is = 0; is < nshared_boundaries_iproc_jproc; is++)
7490 const unsigned shared_boundary_id =
7491 this->shared_boundaries_ids(ip, jp, is);
7492 dump_file << ip <<
" " << jp <<
" " << shared_boundary_id
7493 <<
" # ip jp shared_boundary of processors ip and jp"
7506 const unsigned nshared_boundaries_overlap_internal_boundaries =
7507 this->nshared_boundary_overlaps_internal_boundary();
7508 dump_file << nshared_boundaries_overlap_internal_boundaries
7509 <<
" # number of shared boundaries that overlap internal "
7510 <<
"boundaries" << std::endl;
7512 if (nshared_boundaries_overlap_internal_boundaries > 0)
7514 for (
unsigned isb = init_shd_bnd_id; isb < final_shd_bnd_id; isb++)
7518 if (this->shared_boundary_overlaps_internal_boundary(isb))
7522 const unsigned overlapped_internal_boundary =
7523 shared_boundary_overlapping_internal_boundary(isb);
7525 dump_file << isb <<
" " << overlapped_internal_boundary
7526 <<
" # the shared boundary overlaps the internal "
7527 <<
"boundary " << std::endl;
7538 for (
unsigned b = 0; b < nboundary; b++)
7543 if (Assigned_segments_initial_zeta_values[b])
7547 dump_file <<
"1 # assigned boundary coordinates initial zeta values"
7555 this->boundary_initial_coordinate(b);
7557 Vector<double> final_coordinates = this->boundary_final_coordinate(b);
7559 dump_file << std::setprecision(14) << initial_coordinates[0] <<
" "
7560 << initial_coordinates[1]
7561 <<
" # initial coordinates for the current boundary"
7564 dump_file << std::setprecision(14) << final_coordinates[0] <<
" "
7565 << final_coordinates[1]
7566 <<
" # final coordinates for the current boundary"
7573 const unsigned zeta_size =
7574 this->boundary_initial_zeta_coordinate(b).size();
7578 std::ostringstream error_message;
7580 <<
"The dimension for the zeta values container is different\n"
7581 <<
"from 1, the current implementation only supports\n"
7582 <<
"one-dimensioned zeta containers\n\n";
7584 error_message.str(),
7585 "TriangleMesh::dump_distributed_info_for_restart()",
7586 OOMPH_EXCEPTION_LOCATION);
7591 this->boundary_initial_zeta_coordinate(b);
7592 Vector<double> zeta_final = this->boundary_final_zeta_coordinate(b);
7594 dump_file << std::setprecision(14) << zeta_initial[0]
7595 <<
" # initial zeta value for the current boundary"
7598 dump_file << std::setprecision(14) << zeta_final[0]
7599 <<
" # final zeta value for the current boundary"
7603 const unsigned nsegments = this->nboundary_segment(b);
7605 dump_file << b <<
" " << nsegments
7606 <<
" # of segments for the current boundary" << std::endl;
7609 for (
unsigned is = 0; is < nsegments; is++)
7613 this->boundary_segment_initial_coordinate(b)[is];
7615 this->boundary_segment_final_coordinate(b)[is];
7618 << std::setprecision(14) << initial_segment_coordinates[0] <<
" "
7619 << initial_segment_coordinates[1]
7620 <<
" # initial segment coordinates for the current boundary"
7623 dump_file << std::setprecision(14) << final_segment_coordinates[0]
7624 <<
" " << final_segment_coordinates[1]
7625 <<
" # final segment coordinates for the current boundary"
7630 if (this->boundary_geom_object_pt(b) != 0)
7632 const double zeta_segment_initial =
7633 this->boundary_segment_initial_zeta(b)[is];
7634 const double zeta_segment_final =
7635 this->boundary_segment_final_zeta(b)[is];
7638 << std::setprecision(14) << zeta_segment_initial
7639 <<
" # initial segment zeta value for the current boundary"
7643 << std::setprecision(14) << zeta_segment_final
7644 <<
" # final segment zeta value for the current boundary"
7649 const double arclength_segment_initial =
7650 this->boundary_segment_initial_arclength(b)[is];
7651 const double arclength_segment_final =
7652 this->boundary_segment_final_arclength(b)[is];
7655 << std::setprecision(14) << arclength_segment_initial
7656 <<
" # initial segment arclength for the current boundary"
7659 dump_file << std::setprecision(14) << arclength_segment_final
7660 <<
" # final segment arclength for the current boundary"
7672 dump_file <<
"0 # assigned boundary coordinates initial zeta values"
7684 template<
class ELEMENT>
7686 std::istream& restart_file)
7689 if (this->is_mesh_distributed())
7692 const unsigned n_boundary = read_unsigned_line_helper(restart_file);
7695 if (n_boundary != this->nboundary())
7697 std::ostringstream error_message;
7699 <<
"The number of boundaries (" << n_boundary <<
") on the "
7700 <<
"file used for restarting is different\nfrom the number of "
7701 <<
"boundaries (" << this->nboundary() <<
") on the current "
7704 "TriangleMesh::read_distributed_info_for_restart()",
7705 OOMPH_EXCEPTION_LOCATION);
7710 unsigned n_shared_boundaries = read_unsigned_line_helper(restart_file);
7713 n_shared_boundaries++;
7714 n_shared_boundaries--;
7717 unsigned init_shd_bnd_id = read_unsigned_line_helper(restart_file);
7723 unsigned final_shd_bnd_id = read_unsigned_line_helper(restart_file);
7731 const unsigned n_procs = read_unsigned_line_helper(restart_file);
7734 if (
static_cast<int>(n_procs) != this->communicator_pt()->nproc())
7736 std::ostringstream error_message;
7738 <<
"The number of previously used processors (" << n_procs
7739 <<
") (read from the restart file) is different\nfrom the "
7740 <<
"number of current used processors ("
7741 << this->communicator_pt()->nproc() <<
")\n\n";
7743 "TriangleMesh::read_distributed_info_for_restart()",
7744 OOMPH_EXCEPTION_LOCATION);
7749 this->shared_boundaries_ids().clear();
7750 this->shared_boundary_from_processors().clear();
7751 this->shared_boundary_overlaps_internal_boundary().clear();
7755 this->shared_boundaries_ids().resize(n_procs);
7759 for (
unsigned ip = 0; ip < n_procs; ip++)
7763 this->shared_boundaries_ids(ip).resize(n_procs);
7764 for (
unsigned jp = 0; jp < n_procs; jp++)
7770 const unsigned nshared_boundaries_iproc_jproc =
7771 read_unsigned_line_helper(restart_file);
7772 for (
unsigned is = 0; is < nshared_boundaries_iproc_jproc; is++)
7776 restart_file >> tmp_ip;
7778 restart_file >> tmp_jp;
7782 const unsigned shared_boundary_id =
7783 read_unsigned_line_helper(restart_file);
7787 this->shared_boundaries_ids(ip, jp).push_back(shared_boundary_id);
7794 this->shared_boundary_from_processors()[shared_boundary_id] =
7807 const unsigned nshared_boundaries_overlap_internal_boundaries =
7808 read_unsigned_line_helper(restart_file);
7810 for (
unsigned isb = 0;
7811 isb < nshared_boundaries_overlap_internal_boundaries;
7815 unsigned shared_boundary_overlapping;
7816 restart_file >> shared_boundary_overlapping;
7818 const unsigned overlapped_internal_boundary =
7819 read_unsigned_line_helper(restart_file);
7823 this->shared_boundary_overlaps_internal_boundary()
7824 [shared_boundary_overlapping] = overlapped_internal_boundary;
7832 for (
unsigned b = 0; b < n_boundary; b++)
7836 const unsigned boundary_coordinates_initial_zeta_values_assigned =
7837 read_unsigned_line_helper(restart_file);
7839 if (boundary_coordinates_initial_zeta_values_assigned)
7844 Boundary_initial_coordinate[b].clear();
7845 Boundary_final_coordinate[b].clear();
7847 Boundary_initial_zeta_coordinate[b].clear();
7848 Boundary_final_zeta_coordinate[b].clear();
7851 Boundary_segment_inverted[b].clear();
7852 Boundary_segment_initial_coordinate[b].clear();
7853 Boundary_segment_final_coordinate[b].clear();
7855 Boundary_segment_initial_zeta[b].clear();
7856 Boundary_segment_final_zeta[b].clear();
7858 Boundary_segment_initial_arclength[b].clear();
7859 Boundary_segment_final_arclength[b].clear();
7868 restart_file >> initial_coordinates[0] >> initial_coordinates[1];
7871 restart_file.ignore(80,
'\n');
7876 restart_file >> final_coordinates[0] >> final_coordinates[1];
7879 restart_file.ignore(80,
'\n');
7884 this->boundary_initial_coordinate(b) = initial_coordinates;
7885 this->boundary_final_coordinate(b) = final_coordinates;
7889 restart_file >> zeta_initial[0];
7892 restart_file.ignore(80,
'\n');
7895 restart_file >> zeta_final[0];
7898 restart_file.ignore(80,
'\n');
7901 this->boundary_initial_zeta_coordinate(b) = zeta_initial;
7902 this->boundary_final_zeta_coordinate(b) = zeta_final;
7905 unsigned current_boundary;
7906 restart_file >> current_boundary;
7909 if (current_boundary != b)
7911 std::ostringstream error_message;
7913 <<
"The current boundary id from the restart file ("
7914 << current_boundary <<
") is different from\nthe boundary id "
7915 << b <<
"currently used to re-establish the initial and\nfinal "
7916 <<
"segment's zeta values\n\n";
7918 error_message.str(),
7919 "TriangleMesh::read_distributed_info_for_restart()",
7920 OOMPH_EXCEPTION_LOCATION);
7926 restart_file >> nsegments;
7929 restart_file.ignore(80,
'\n');
7934 for (
unsigned is = 0; is < nsegments; is++)
7940 restart_file >> initial_segment_coordinates[0] >>
7941 initial_segment_coordinates[1];
7944 restart_file.ignore(80,
'\n');
7949 restart_file >> final_segment_coordinates[0] >>
7950 final_segment_coordinates[1];
7953 restart_file.ignore(80,
'\n');
7956 this->boundary_segment_initial_coordinate(b).push_back(
7957 initial_segment_coordinates);
7958 this->boundary_segment_final_coordinate(b).push_back(
7959 final_segment_coordinates);
7962 if (this->boundary_geom_object_pt(b) != 0)
7965 restart_file >> zeta_segment_initial[0];
7968 restart_file.ignore(80,
'\n');
7971 restart_file >> zeta_segment_final[0];
7974 restart_file.ignore(80,
'\n');
7977 this->boundary_segment_initial_zeta(b).push_back(
7978 zeta_segment_initial[0]);
7979 this->boundary_segment_final_zeta(b).push_back(
7980 zeta_segment_final[0]);
7985 restart_file >> arclength_segment_initial[0];
7988 restart_file.ignore(80,
'\n');
7991 restart_file >> arclength_segment_final[0];
7994 restart_file.ignore(80,
'\n');
7997 this->boundary_segment_initial_arclength(b).push_back(
7998 arclength_segment_initial[0]);
7999 this->boundary_segment_final_arclength(b).push_back(
8000 arclength_segment_final[0]);
8019 template<
class ELEMENT>
8021 std::ostream& outfile)
8030 std::set<Node*> boundary_nodes_pt;
8031 const unsigned n_boundary_ele = this->nboundary_element(b);
8032 for (
unsigned e = 0;
e < n_boundary_ele;
e++)
8036 #ifdef OOMPH_HAS_MPI
8042 int face_index = this->face_index_at_boundary(b,
e);
8048 const unsigned n_nodes = face_ele_pt->
nnode();
8049 for (
unsigned i = 0;
i < n_nodes;
i++)
8054 boundary_nodes_pt.insert(tmp_node_pt);
8060 #ifdef OOMPH_HAS_MPI
8066 outfile <<
"ZONE T=\"Boundary nodes" << b <<
"\"\n";
8068 std::set<Vector<double>> set_node_coord;
8070 for (std::set<Node*>::iterator it = boundary_nodes_pt.begin();
8071 it != boundary_nodes_pt.end();
8074 Node* inode_pt = (*it);
8077 const unsigned n_dim = inode_pt->
ndim();
8083 node_coord[0] = zeta[0];
8084 for (
unsigned j = 0; j < n_dim; j++)
8086 node_coord[j + 1] = inode_pt->
x(j);
8088 set_node_coord.insert(node_coord);
8091 for (std::set<
Vector<double>>::iterator it = set_node_coord.begin();
8092 it != set_node_coord.end();
8099 const unsigned n_dim = node_coord.size() - 1;
8100 for (
unsigned j = 0; j < n_dim; j++)
8102 outfile << node_coord[j + 1] <<
" ";
8105 outfile <<
"0.0" << std::endl;
8109 outfile <<
"ZONE T=\"Boundary coordinates " << b <<
"\"\n";
8110 for (std::set<
Vector<double>>::iterator it = set_node_coord.begin();
8111 it != set_node_coord.end();
8118 const unsigned n_dim = node_coord.size() - 1;
8119 for (
unsigned j = 0; j < n_dim; j++)
8121 outfile << node_coord[j + 1] <<
" ";
8125 outfile << node_coord[0] << std::endl;
8129 #ifdef OOMPH_HAS_MPI
8136 template<
class ELEMENT>
8147 const unsigned my_rank = this->communicator_pt()->my_rank();
8169 const unsigned nouter = this->Outer_boundary_pt.size();
8170 for (
unsigned i = 0;
i < nouter;
i++)
8172 const unsigned npolylines = this->Outer_boundary_pt[
i]->npolyline();
8173 for (
unsigned p = 0; p < npolylines; p++)
8177 this->Outer_boundary_pt[
i]->polyline_pt(p);
8178 const unsigned nvertex = tmp_polyline_pt->
nvertex();
8184 const unsigned bound_id = tmp_polyline_pt->
boundary_id();
8185 if (!boundary_was_splitted(bound_id))
8187 unsorted_outer_polyline_pt.push_back(tmp_polyline_pt);
8193 boundary_subpolylines(bound_id);
8194 const unsigned nsub_poly = tmp_vector_polylines.size();
8198 std::ostringstream error_message;
8199 error_message <<
"The boundary (" << bound_id
8200 <<
") was marked to be splitted but\n"
8201 <<
"there are only (" << nsub_poly
8202 <<
") polylines to represent it.\n";
8204 OOMPH_CURRENT_FUNCTION,
8205 OOMPH_EXCEPTION_LOCATION);
8210 for (
unsigned isub = 0; isub < nsub_poly; isub++)
8212 unsorted_outer_polyline_pt.push_back(tmp_vector_polylines[isub]);
8214 const unsigned nsvertex = tmp_vector_polylines[isub]->nvertex();
8217 std::ostringstream error_message;
8219 <<
"The current chunk (" << isub <<
") of the polyline with\n"
8220 <<
"boundary id (" << bound_id <<
") has no vertices\n";
8222 OOMPH_CURRENT_FUNCTION,
8223 OOMPH_EXCEPTION_LOCATION);
8233 unsigned nunsorted_outer_polyline = unsorted_outer_polyline_pt.size();
8234 if (nunsorted_outer_polyline > 0)
8238 sort_polylines_helper(unsorted_outer_polyline_pt, sorted_outer_curves_pt);
8257 const unsigned ninternal_closed = this->Internal_polygon_pt.size();
8258 for (
unsigned i = 0;
i < ninternal_closed;
i++)
8260 const unsigned npolylines = this->Internal_polygon_pt[
i]->npolyline();
8261 for (
unsigned p = 0; p < npolylines; p++)
8265 this->Internal_polygon_pt[
i]->polyline_pt(p);
8266 const unsigned nvertex = tmp_polyline_pt->
nvertex();
8272 const unsigned bound_id = tmp_polyline_pt->
boundary_id();
8273 if (!boundary_was_splitted(bound_id))
8275 unsorted_internal_closed_polyline_pt.push_back(tmp_polyline_pt);
8281 boundary_subpolylines(bound_id);
8282 const unsigned nsub_poly = tmp_vector_polylines.size();
8286 std::ostringstream error_message;
8287 error_message <<
"The boundary (" << bound_id
8288 <<
") was marked to be splitted but\n"
8289 <<
"there are only (" << nsub_poly
8290 <<
") polylines to represent it.\n";
8292 OOMPH_CURRENT_FUNCTION,
8293 OOMPH_EXCEPTION_LOCATION);
8298 for (
unsigned isub = 0; isub < nsub_poly; isub++)
8300 unsorted_internal_closed_polyline_pt.push_back(
8301 tmp_vector_polylines[isub]);
8303 const unsigned nsvertex = tmp_vector_polylines[isub]->nvertex();
8306 std::ostringstream error_message;
8308 <<
"The current chunk (" << isub <<
") of the polyline with\n"
8309 <<
"boundary id (" << bound_id <<
") has no vertices\n";
8311 OOMPH_CURRENT_FUNCTION,
8312 OOMPH_EXCEPTION_LOCATION);
8321 const unsigned nunsorted_internal_closed_polyline =
8322 unsorted_internal_closed_polyline_pt.size();
8324 if (nunsorted_internal_closed_polyline > 0)
8328 sort_polylines_helper(unsorted_internal_closed_polyline_pt,
8329 sorted_internal_closed_curves_pt);
8347 const unsigned ninternal_open = this->Internal_open_curve_pt.size();
8348 for (
unsigned i = 0;
i < ninternal_open;
i++)
8350 const unsigned ncurve_section =
8351 this->Internal_open_curve_pt[
i]->ncurve_section();
8352 for (
unsigned p = 0; p < ncurve_section; p++)
8356 this->Internal_open_curve_pt[
i]->polyline_pt(p);
8357 const unsigned nvertex = tmp_polyline_pt->
nvertex();
8363 const unsigned bound_id = tmp_polyline_pt->
boundary_id();
8364 if (!boundary_was_splitted(bound_id))
8368 if (!boundary_marked_as_shared_boundary(bound_id, 0))
8370 unsorted_internal_open_polyline_pt.push_back(tmp_polyline_pt);
8377 boundary_subpolylines(bound_id);
8378 const unsigned nsub_poly = tmp_vector_polylines.size();
8382 std::ostringstream error_message;
8383 error_message <<
"The boundary (" << bound_id
8384 <<
") was marked to be splitted but\n"
8385 <<
"there are only (" << nsub_poly
8386 <<
") polylines to represent it.\n";
8388 OOMPH_CURRENT_FUNCTION,
8389 OOMPH_EXCEPTION_LOCATION);
8394 for (
unsigned isub = 0; isub < nsub_poly; isub++)
8398 if (!boundary_marked_as_shared_boundary(bound_id, isub))
8400 unsorted_internal_open_polyline_pt.push_back(
8401 tmp_vector_polylines[isub]);
8404 const unsigned nsvertex = tmp_vector_polylines[isub]->nvertex();
8407 std::ostringstream error_message;
8409 <<
"The current chunk (" << isub <<
") of the polyline with\n"
8410 <<
"boundary id (" << bound_id <<
") has no vertices\n";
8412 OOMPH_CURRENT_FUNCTION,
8413 OOMPH_EXCEPTION_LOCATION);
8422 const unsigned nunsorted_internal_open_polyline =
8423 unsorted_internal_open_polyline_pt.size();
8425 if (nunsorted_internal_open_polyline > 0)
8429 sort_polylines_helper(unsorted_internal_open_polyline_pt,
8430 sorted_internal_open_curves_pt);
8450 const unsigned ncurves = nshared_boundary_curves(my_rank);
8451 for (
unsigned i = 0;
i < ncurves;
i++)
8453 const unsigned npolylines = nshared_boundary_polyline(my_rank,
i);
8454 for (
unsigned p = 0; p < npolylines; p++)
8456 const unsigned nvertex =
8457 shared_boundary_polyline_pt(my_rank,
i, p)->nvertex();
8461 shared_boundary_polyline_pt(my_rank,
i, p);
8465 if (this->nshared_boundary_overlaps_internal_boundary() > 0)
8468 const unsigned shd_bnd_id = tmp_shared_poly_pt->
boundary_id();
8472 if (this->shared_boundary_overlaps_internal_boundary(shd_bnd_id))
8474 unsorted_shared_to_internal_polyline_pt.push_back(
8475 tmp_shared_poly_pt);
8478 unsorted_shared_polyline_pt.push_back(tmp_shared_poly_pt);
8484 const unsigned nunsorted_shared_polyline =
8485 unsorted_shared_polyline_pt.size();
8487 if (nunsorted_shared_polyline > 0)
8491 sort_polylines_helper(unsorted_shared_polyline_pt,
8492 sorted_shared_curves_pt);
8502 const unsigned nouter_curves = sorted_outer_curves_pt.size();
8503 const unsigned ninternal_closed_curves =
8504 sorted_internal_closed_curves_pt.size();
8505 const unsigned nshared_curves = sorted_shared_curves_pt.size();
8506 const unsigned ntotal_curves =
8507 nouter_curves + ninternal_closed_curves + nshared_curves;
8510 unsigned counter = 0;
8515 for (
unsigned i = 0;
i < nshared_curves;
i++, counter++)
8517 all_curves_pt[counter] = sorted_shared_curves_pt[
i];
8521 for (
unsigned i = 0;
i < ninternal_closed_curves;
i++, counter++)
8523 all_curves_pt[counter] = sorted_internal_closed_curves_pt[
i];
8527 for (
unsigned i = 0;
i < nouter_curves;
i++, counter++)
8529 all_curves_pt[counter] = sorted_outer_curves_pt[
i];
8534 this->create_tmp_polygons_helper(all_curves_pt, polygons_pt);
8536 this->create_tmp_open_curves_helper(sorted_internal_open_curves_pt,
8537 unsorted_shared_to_internal_polyline_pt,
8551 this->create_shared_polylines_connections();
8568 const unsigned n_holes = this->Internal_polygon_pt.size();
8569 for (
unsigned h = 0; h < n_holes; h++)
8572 this->Internal_polygon_pt[h]->internal_point();
8574 if (!hole_coordinates.empty())
8576 new_holes_coordinates.push_back(hole_coordinates);
8582 if (First_time_compute_holes_left_by_halo_elements)
8585 const unsigned n_extra_holes = Extra_holes_coordinates.size();
8586 for (
unsigned h = 0; h < n_extra_holes; h++)
8589 new_holes_coordinates.push_back(hole_coordinates);
8593 Original_extra_holes_coordinates = Extra_holes_coordinates;
8596 First_time_compute_holes_left_by_halo_elements =
false;
8603 const unsigned n_original_extra_holes =
8604 Original_extra_holes_coordinates.size();
8605 for (
unsigned h = 0; h < n_original_extra_holes; h++)
8607 Vector<double> hole_coordinates = Original_extra_holes_coordinates[h];
8608 new_holes_coordinates.push_back(hole_coordinates);
8614 compute_holes_left_by_halo_elements_helper(new_holes_coordinates);
8618 update_holes_information_helper(polygons_pt, new_holes_coordinates);
8624 Extra_holes_coordinates = new_holes_coordinates;
8636 template<
class ELEMENT>
8651 const unsigned ncurves = polylines_pt.size();
8654 const unsigned nunsorted_curves = ncurves;
8656 unsigned nsorted_curves = 0;
8659 std::vector<bool> done_curve(ncurves);
8664 std::list<Vector<TriangleMeshPolyLine*>> list_building_polygon_pt;
8667 bool root_curve_found =
false;
8672 unsigned root_curve_idx = 0;
8675 for (
unsigned ic = 0; ic < ncurves; ic++)
8677 if (!done_curve[ic])
8679 root_curve_idx = ic;
8682 root_curve_found =
true;
8684 done_curve[ic] =
true;
8691 if (!root_curve_found)
8693 std::stringstream err;
8694 err <<
"The root curve to create a polygon from the shared and "
8695 <<
"original boundaries was not found!!!\n";
8697 "TriangleMesh::create_tmp_polygons_helper()",
8698 OOMPH_EXCEPTION_LOCATION);
8704 polylines_pt[root_curve_idx];
8707 list_building_polygon_pt.push_back(root_curve_pt);
8714 const unsigned nroot_curve_polyline = root_curve_pt.size();
8716 root_curve_pt[0]->initial_vertex_coordinate(root_curve_initial_vertex);
8717 root_curve_pt[nroot_curve_polyline - 1]->final_vertex_coordinate(
8718 root_curve_final_vertex);
8722 ((root_curve_initial_vertex[0] - root_curve_final_vertex[0]) *
8723 (root_curve_initial_vertex[0] - root_curve_final_vertex[0])) +
8724 ((root_curve_initial_vertex[1] - root_curve_final_vertex[1]) *
8725 (root_curve_initial_vertex[1] - root_curve_final_vertex[1]));
8732 nroot_curve_polyline);
8735 for (
unsigned i = 0;
i < nroot_curve_polyline;
i++)
8737 curve_section_pt[
i] = root_curve_pt[
i];
8745 this->Free_polygon_pt.insert(new_polygon_pt);
8748 polygons_pt.push_back(new_polygon_pt);
8755 bool added_curve =
false;
8760 bool polygon_created =
false;
8764 added_curve =
false;
8767 for (
unsigned ic = root_curve_idx + 1; ic < ncurves; ic++)
8769 if (!done_curve[ic])
8776 const unsigned ncurrent_curve_polyline = current_curve_pt.size();
8783 current_curve_pt[0]->initial_vertex_coordinate(
8784 current_curve_initial_vertex);
8785 current_curve_pt[ncurrent_curve_polyline - 1]
8786 ->final_vertex_coordinate(current_curve_final_vertex);
8791 diff = ((current_curve_final_vertex[0] -
8792 root_curve_initial_vertex[0]) *
8793 (current_curve_final_vertex[0] -
8794 root_curve_initial_vertex[0])) +
8795 ((current_curve_final_vertex[1] -
8796 root_curve_initial_vertex[1]) *
8797 (current_curve_final_vertex[1] -
8798 root_curve_initial_vertex[1]));
8804 list_building_polygon_pt.push_front(current_curve_pt);
8806 done_curve[ic] =
true;
8808 root_curve_initial_vertex[0] = current_curve_initial_vertex[0];
8809 root_curve_initial_vertex[1] = current_curve_initial_vertex[1];
8817 diff = ((current_curve_initial_vertex[0] -
8818 root_curve_initial_vertex[0]) *
8819 (current_curve_initial_vertex[0] -
8820 root_curve_initial_vertex[0])) +
8821 ((current_curve_initial_vertex[1] -
8822 root_curve_initial_vertex[1]) *
8823 (current_curve_initial_vertex[1] -
8824 root_curve_initial_vertex[1]));
8830 ncurrent_curve_polyline);
8832 for (
unsigned it = 0; it < ncurrent_curve_polyline; it++)
8834 current_curve_pt[it]->reverse();
8835 tmp_curve_pt[it] = current_curve_pt[it];
8839 for (
int i = ncurrent_curve_polyline - 1;
i >= 0;
i--, count++)
8841 current_curve_pt[count] = tmp_curve_pt[
i];
8844 list_building_polygon_pt.push_front(current_curve_pt);
8846 done_curve[ic] =
true;
8848 root_curve_initial_vertex[0] = current_curve_final_vertex[0];
8849 root_curve_initial_vertex[1] = current_curve_final_vertex[1];
8857 diff = ((current_curve_initial_vertex[0] -
8858 root_curve_final_vertex[0]) *
8859 (current_curve_initial_vertex[0] -
8860 root_curve_final_vertex[0])) +
8861 ((current_curve_initial_vertex[1] -
8862 root_curve_final_vertex[1]) *
8863 (current_curve_initial_vertex[1] -
8864 root_curve_final_vertex[1]));
8870 list_building_polygon_pt.push_back(current_curve_pt);
8872 done_curve[ic] =
true;
8874 root_curve_final_vertex[0] = current_curve_final_vertex[0];
8875 root_curve_final_vertex[1] = current_curve_final_vertex[1];
8884 ((current_curve_final_vertex[0] - root_curve_final_vertex[0]) *
8885 (current_curve_final_vertex[0] - root_curve_final_vertex[0])) +
8886 ((current_curve_final_vertex[1] - root_curve_final_vertex[1]) *
8887 (current_curve_final_vertex[1] - root_curve_final_vertex[1]));
8893 ncurrent_curve_polyline);
8895 for (
unsigned it = 0; it < ncurrent_curve_polyline; it++)
8897 current_curve_pt[it]->reverse();
8898 tmp_curve_pt[it] = current_curve_pt[it];
8902 for (
int i = ncurrent_curve_polyline - 1;
i >= 0;
i--, count++)
8904 current_curve_pt[count] = tmp_curve_pt[
i];
8907 list_building_polygon_pt.push_back(current_curve_pt);
8909 done_curve[ic] =
true;
8911 root_curve_final_vertex[0] = current_curve_initial_vertex[0];
8912 root_curve_final_vertex[1] = current_curve_initial_vertex[1];
8926 ((root_curve_initial_vertex[0] - root_curve_final_vertex[0]) *
8927 (root_curve_initial_vertex[0] - root_curve_final_vertex[0])) +
8928 ((root_curve_initial_vertex[1] - root_curve_final_vertex[1]) *
8929 (root_curve_initial_vertex[1] - root_curve_final_vertex[1]));
8935 added_curve =
false;
8938 polygon_created =
true;
8944 }
while (added_curve);
8947 if (!polygon_created)
8949 std::stringstream error_message;
8951 <<
"It was no possible to create a TriangleMeshPolygon with "
8952 <<
"the input set of curves\n"
8953 <<
"These are the initial and final vertices in the current "
8954 <<
"sorted list of\nTriangleMeshPolyLines\n\n";
8957 unsigned icurve = 0;
8959 list_building_polygon_pt.begin();
8960 it != list_building_polygon_pt.end();
8963 const unsigned ncurrent_curve_polyline = (*it).size();
8964 error_message <<
"TriangleMeshCurve #" << icurve <<
"\n"
8965 <<
"-----------------------------------\n";
8966 for (
unsigned ip = 0; ip < ncurrent_curve_polyline; ip++)
8970 (*it)[ip]->initial_vertex_coordinate(init_vertex);
8971 (*it)[ip]->final_vertex_coordinate(final_vertex);
8972 error_message <<
"TriangleMeshPolyLine #" << ip <<
"\n"
8973 <<
"Initial vertex: (" << init_vertex[0] <<
","
8974 << init_vertex[1] <<
")\n"
8975 <<
"Final vertex: (" << final_vertex[0] <<
","
8976 << final_vertex[1] <<
")\n";
8981 "TriangleMesh::create_tmp_polygons_helper()",
8982 OOMPH_EXCEPTION_LOCATION);
8988 unsigned ntotal_polylines = 0;
8991 list_building_polygon_pt.begin();
8992 it != list_building_polygon_pt.end();
8995 ntotal_polylines += (*it).size();
9002 unsigned counter = 0;
9004 list_building_polygon_pt.begin();
9005 it != list_building_polygon_pt.end();
9008 const unsigned ncurrent_curve_polyline = (*it).size();
9009 for (
unsigned ip = 0; ip < ncurrent_curve_polyline; ip++, counter++)
9011 curve_section_pt[counter] = (*it)[ip];
9020 this->Free_polygon_pt.insert(new_polygon_pt);
9023 polygons_pt.push_back(new_polygon_pt);
9028 }
while (nsorted_curves < nunsorted_curves);
9036 template<
class ELEMENT>
9044 const unsigned ninternal_open_curves = sorted_open_curves_pt.size();
9048 for (
unsigned i = 0;
i < ninternal_open_curves;
i++)
9051 const unsigned npoly = sorted_open_curves_pt[
i].size();
9053 for (
unsigned j = 0; j < npoly; j++)
9055 tmp_curve_section[j] = sorted_open_curves_pt[
i][j];
9062 this->Free_open_curve_pt.insert(new_open_curve_pt);
9065 open_curves_pt.push_back(new_open_curve_pt);
9076 template<
class ELEMENT>
9078 std::set<FiniteElement*>& element_in_processor_pt,
9079 const int& root_edge_bnd_id,
9080 std::map<std::pair<Node*, Node*>,
bool>& overlapped_face,
9081 std::map<
unsigned, std::map<Node*, bool>>&
9082 node_on_bnd_not_overlapped_by_shd_bnd,
9083 std::list<Node*>& current_polyline_nodes,
9084 std::map<
unsigned, std::list<Node*>>& shared_bnd_id_to_sorted_list_node_pt,
9085 const unsigned& node_degree,
9087 const bool called_from_load_balance)
9090 int flag_to_return = -1;
9099 bool overlapping_internal_boundary =
false;
9101 unsigned internal_overlaping_bnd_id = 0;
9102 if (root_edge_bnd_id != -1)
9105 overlapping_internal_boundary =
true;
9107 internal_overlaping_bnd_id =
static_cast<unsigned>(root_edge_bnd_id);
9118 bool is_node_living_in_non_overlapped_boundary =
false;
9122 const unsigned noriginal_bnd = this->initial_shared_boundary_id();
9123 for (
unsigned bb = 0; bb < noriginal_bnd; bb++)
9131 if (overlapping_internal_boundary)
9140 const bool on_bnd_edge_not_overlapped_by_shd_bnd =
9141 node_on_bnd_not_overlapped_by_shd_bnd[bb][new_node_pt];
9142 if (bb != internal_overlaping_bnd_id ||
9143 ((bb == internal_overlaping_bnd_id) &&
9144 (on_bnd_edge_not_overlapped_by_shd_bnd)))
9147 if (bb != internal_overlaping_bnd_id)
9149 is_node_living_in_non_overlapped_boundary =
true;
9159 const unsigned n_bound_ele = this->nboundary_element(bb);
9160 if (n_bound_ele > 0)
9164 for (
unsigned e = 0;
e < n_bound_ele;
e++)
9170 std::set<FiniteElement*>::iterator it =
9171 element_in_processor_pt.find(bulk_ele_pt);
9173 if (it != element_in_processor_pt.end())
9176 bool found_node =
false;
9178 int face_index = this->face_index_at_boundary(bb,
e);
9183 const unsigned n_node_face = face_ele_pt->
nnode();
9186 Node* last_node_pt = face_ele_pt->
node_pt(n_node_face - 1);
9188 std::pair<Node*, Node*> tmp_edge =
9189 std::make_pair(first_node_pt, last_node_pt);
9193 if (!overlapped_face[tmp_edge])
9196 for (
unsigned n = 0; n < n_node_face; n++)
9199 if (face_ele_pt->
node_pt(n) == new_node_pt)
9215 flag_to_return = bb;
9216 return flag_to_return;
9244 const unsigned n_bound_ele = this->nboundary_element(bb);
9245 if (n_bound_ele > 0)
9249 for (
unsigned e = 0;
e < n_bound_ele;
e++)
9255 std::set<FiniteElement*>::iterator it =
9256 element_in_processor_pt.find(bulk_ele_pt);
9258 if (it != element_in_processor_pt.end())
9261 bool found_node =
false;
9263 int face_index = this->face_index_at_boundary(bb,
e);
9268 const unsigned n_node_face = face_ele_pt->
nnode();
9271 Node* last_node_pt = face_ele_pt->
node_pt(n_node_face - 1);
9273 std::pair<Node*, Node*> tmp_edge =
9274 std::make_pair(first_node_pt, last_node_pt);
9278 if (!overlapped_face[tmp_edge])
9281 for (
unsigned n = 0; n < n_node_face; n++)
9284 if (face_ele_pt->
node_pt(n) == new_node_pt)
9300 flag_to_return = bb;
9301 return flag_to_return;
9326 if (!overlapping_internal_boundary)
9331 flag_to_return = -3;
9338 if (is_node_living_in_non_overlapped_boundary)
9340 flag_to_return = -3;
9349 if (flag_to_return >= 0)
9351 return flag_to_return;
9364 for (std::map<
unsigned, std::list<Node*>>::iterator it =
9365 shared_bnd_id_to_sorted_list_node_pt.begin();
9366 it != shared_bnd_id_to_sorted_list_node_pt.end();
9372 const unsigned i_bnd_id = (*it).first;
9375 std::list<Node*>::iterator it_list = (*it).second.begin();
9377 const unsigned n_nodes = (*it).second.size();
9379 for (
unsigned i = 0;
i < n_nodes;
i++, it_list++)
9382 if ((*it_list) == new_node_pt)
9386 candidate_shared_bnd_to_connect.push_back(i_bnd_id);
9397 const unsigned n_candidate_shared_bnd_to_connect =
9398 candidate_shared_bnd_to_connect.size();
9401 if (n_candidate_shared_bnd_to_connect > 0)
9408 if (called_from_load_balance)
9410 return candidate_shared_bnd_to_connect[0];
9423 shared_boundaries_in_this_processor(shared_bound_in_this_proc);
9429 const unsigned n_shared_bound_in_this_proc =
9430 shared_bound_in_this_proc.size();
9433 for (
unsigned i = 0;
i < n_candidate_shared_bnd_to_connect;
i++)
9436 const unsigned i_candidate_shared_bnd =
9437 candidate_shared_bnd_to_connect[
i];
9440 for (
unsigned j = 0; j < n_shared_bound_in_this_proc; j++)
9443 if (i_candidate_shared_bnd == shared_bound_in_this_proc[j])
9446 flag_to_return = i_candidate_shared_bnd;
9447 return flag_to_return;
9458 flag_to_return = -3;
9464 if (flag_to_return >= 0)
9466 return flag_to_return;
9475 unsigned nrepeated = 0;
9476 for (std::list<Node*>::iterator it_list = current_polyline_nodes.begin();
9477 it_list != current_polyline_nodes.end();
9482 if ((*it_list) == new_node_pt)
9494 flag_to_return = -2;
9500 if (node_degree > 2)
9502 flag_to_return = -3;
9506 return flag_to_return;
9516 template<
class ELEMENT>
9520 const unsigned my_rank = this->communicator_pt()->my_rank();
9524 this->Shared_boundary_polyline_pt[my_rank];
9528 const unsigned ncurves = shared_curves_pt.size();
9529 for (
unsigned icurve = 0; icurve < ncurves; icurve++)
9532 const unsigned npoly = shared_curves_pt[icurve].size();
9533 for (
unsigned ipoly = 0; ipoly < npoly; ipoly++)
9539 const unsigned bound_id = shd_poly_pt->
boundary_id();
9542 const bool is_connected_to_the_left =
9546 const bool is_connected_to_the_right =
9552 if (is_connected_to_the_left || is_connected_to_the_right)
9556 const unsigned n_vertex = shd_poly_pt->
nvertex();
9563 if (is_connected_to_the_left)
9567 const unsigned uconnection_to_the_left =
9575 bool connecting_to_an_split_boundary =
false;
9579 bool connecting_to_an_overlaped_boundary =
false;
9582 if (uconnection_to_the_left == bound_id)
9585 poly_to_connect_pt = shd_poly_pt;
9590 const unsigned initial_shd_bnd_id = initial_shared_boundary_id();
9592 if (uconnection_to_the_left >= initial_shd_bnd_id)
9596 poly_to_connect_pt =
9597 boundary_polyline_pt(uconnection_to_the_left);
9605 if (boundary_was_splitted(uconnection_to_the_left))
9607 connecting_to_an_split_boundary =
true;
9617 if (connecting_to_an_split_boundary)
9621 const unsigned n_sub_poly =
9622 nboundary_subpolylines(uconnection_to_the_left);
9627 for (
unsigned ii = 0; ii < n_sub_poly; ii++)
9629 if (boundary_marked_as_shared_boundary(
9630 uconnection_to_the_left, ii))
9634 connecting_to_an_overlaped_boundary =
true;
9645 if (boundary_marked_as_shared_boundary(
9646 uconnection_to_the_left, 0))
9650 connecting_to_an_overlaped_boundary =
true;
9657 if (!(connecting_to_an_split_boundary ||
9658 connecting_to_an_overlaped_boundary))
9662 poly_to_connect_pt =
9663 boundary_polyline_pt(uconnection_to_the_left);
9674 if (!connecting_to_an_split_boundary)
9676 if (boundary_was_splitted(uconnection_to_the_left))
9678 std::stringstream error;
9680 <<
"The current shared boundary (" << bound_id <<
") was "
9681 <<
"marked to have a connection\nto the left with the "
9682 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9683 <<
"The problem is that the destination boundary (possibly\n"
9684 <<
"another shared boundary) is marked to be split\n"
9685 <<
"There should not be split shared boundaries\n\n";
9688 "TriangleMesh::create_shared_polylines_connections()",
9689 OOMPH_EXCEPTION_LOCATION);
9706 if (!connecting_to_an_split_boundary)
9710 if (!connecting_to_an_overlaped_boundary)
9714 unsigned vertex_index = 0;
9716 const bool found_vertex_index =
9717 get_connected_vertex_number_on_destination_polyline(
9718 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9722 if (!found_vertex_index)
9724 std::stringstream error;
9726 <<
"The current shared boundary (" << bound_id <<
") was "
9727 <<
"marked to have a connection\nto the left with the "
9728 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9729 <<
"The problem is that the left vertex of the current\n"
9730 <<
"shared boundary is not in the list of vertices of the\n"
9731 <<
"boundary to connect.\n\n"
9732 <<
"This is the left vertex of the current shared "
9734 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", "
9735 << shd_bnd_left_vertex[1] <<
")\n\n"
9736 <<
"This is the list of vertices on the destination "
9738 const unsigned n_v = poly_to_connect_pt->
nvertex();
9739 for (
unsigned i = 0;
i < n_v;
i++)
9743 error <<
"Vertex #" <<
i <<
": (" << cvertex[0] <<
", "
9744 << cvertex[1] <<
")\n";
9748 "TriangleMesh::create_shared_polylines_connections()",
9749 OOMPH_EXCEPTION_LOCATION);
9756 poly_to_connect_pt, vertex_index);
9766 unsigned vertex_index = 0;
9768 bool found_vertex_index =
false;
9773 get_shared_boundaries_overlapping_internal_boundary(
9774 uconnection_to_the_left, dst_shd_bnd_ids);
9778 const unsigned n_shd_bnd_overlap_int_bnd =
9779 dst_shd_bnd_ids.size();
9783 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
9786 const unsigned new_connection_to_the_left =
9787 dst_shd_bnd_ids[ss];
9791 poly_to_connect_pt =
9792 boundary_polyline_pt(new_connection_to_the_left);
9794 if (poly_to_connect_pt != 0)
9798 found_vertex_index =
9799 get_connected_vertex_number_on_destination_polyline(
9800 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9805 if (found_vertex_index)
9815 if (!found_vertex_index)
9817 std::stringstream error;
9819 <<
"The current shared boundary (" << bound_id <<
") was "
9820 <<
"marked to have a connection\nto the left with the "
9821 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9822 <<
"This last boundary is marked to be overlaped by "
9823 <<
"shared boundaries\n"
9824 <<
"The problem is that the left vertex of the current\n"
9825 <<
"shared boundary is not in the list of vertices of the\n"
9826 <<
"boundary to connect.\n\n"
9827 <<
"This is the left vertex of the current shared "
9829 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", "
9830 << shd_bnd_left_vertex[1] <<
")\n\n"
9831 <<
"This is the list of vertices on the destination "
9834 get_shared_boundaries_overlapping_internal_boundary(
9835 uconnection_to_the_left, dst_shd_bnd_ids);
9836 const unsigned n_shd_bnd_overlap_int_bnd =
9837 dst_shd_bnd_ids.size();
9838 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
9840 const unsigned new_connection_to_the_left =
9841 dst_shd_bnd_ids[ss];
9842 poly_to_connect_pt =
9843 boundary_polyline_pt(new_connection_to_the_left);
9844 if (poly_to_connect_pt != 0)
9846 const unsigned shd_bnd_id_overlap =
9848 error <<
"Shared boundary id(" << shd_bnd_id_overlap
9850 const unsigned n_v = poly_to_connect_pt->
nvertex();
9851 for (
unsigned i = 0;
i < n_v;
i++)
9855 error <<
"Vertex #" <<
i <<
": (" << cvertex[0] <<
", "
9856 << cvertex[1] <<
")\n";
9863 "TriangleMesh::create_shared_polylines_connections()",
9864 OOMPH_EXCEPTION_LOCATION);
9873 poly_to_connect_pt, vertex_index);
9885 boundary_subpolylines(uconnection_to_the_left);
9888 const unsigned nsub_poly = tmp_vector_subpolylines.size();
9892 std::ostringstream error_message;
9894 <<
"The boundary (" << uconnection_to_the_left <<
") was "
9895 <<
"marked to be splitted but\n"
9896 <<
"there are only (" << nsub_poly <<
") polylines to "
9897 <<
"represent it.\n";
9899 error_message.str(),
9900 "TriangleMesh::create_shared_polylines_connections()",
9901 OOMPH_EXCEPTION_LOCATION);
9913 if (!connecting_to_an_overlaped_boundary)
9919 unsigned vertex_index = 0;
9921 unsigned sub_poly_to_connect = 0;
9923 bool found_vertex_index =
false;
9927 for (
unsigned isub = 0; isub < nsub_poly; isub++)
9930 poly_to_connect_pt = tmp_vector_subpolylines[isub];
9932 found_vertex_index =
9933 get_connected_vertex_number_on_destination_polyline(
9934 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9937 if (found_vertex_index)
9941 sub_poly_to_connect = isub;
9949 if (!found_vertex_index)
9951 std::stringstream error;
9953 <<
"The current shared boundary (" << bound_id <<
") was "
9954 <<
"marked to have a connection\nto the left with the "
9955 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9956 <<
"The problem is that the left vertex of the current\n"
9957 <<
"shared boundary is not in the list of vertices of any\n"
9958 <<
"of the sub polylines that represent the boundary to\n"
9960 <<
"This is the left vertex of the current shared "
9962 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", "
9963 << shd_bnd_left_vertex[1] <<
")\n\n"
9964 <<
"This is the list of vertices on the destination "
9966 for (
unsigned p = 0; p < nsub_poly; p++)
9968 error <<
"Subpolyline #(" << p <<
")\n";
9969 poly_to_connect_pt = tmp_vector_subpolylines[p];
9970 const unsigned n_v = poly_to_connect_pt->
nvertex();
9971 for (
unsigned i = 0;
i < n_v;
i++)
9975 error <<
"Vertex #" <<
i <<
": (" << cvertex[0] <<
", "
9976 << cvertex[1] <<
")\n";
9981 "TriangleMesh::create_shared_polylines_connections()",
9982 OOMPH_EXCEPTION_LOCATION);
9991 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
10002 unsigned vertex_index = 0;
10004 unsigned sub_poly_to_connect = 0;
10006 bool found_vertex_index =
false;
10011 get_shared_boundaries_overlapping_internal_boundary(
10012 uconnection_to_the_left, dst_shd_bnd_ids);
10016 const unsigned n_shd_bnd_overlap_int_bnd =
10017 dst_shd_bnd_ids.size();
10021 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10024 const unsigned new_connection_to_the_left =
10025 dst_shd_bnd_ids[ss];
10029 if (bound_id != new_connection_to_the_left)
10033 poly_to_connect_pt =
10034 boundary_polyline_pt(new_connection_to_the_left);
10036 if (poly_to_connect_pt != 0)
10040 found_vertex_index =
10041 get_connected_vertex_number_on_destination_polyline(
10042 poly_to_connect_pt,
10043 shd_bnd_left_vertex,
10049 if (found_vertex_index)
10061 if (!found_vertex_index)
10065 for (
unsigned isub = 0; isub < nsub_poly; isub++)
10069 if (!boundary_marked_as_shared_boundary(
10070 uconnection_to_the_left, isub))
10073 poly_to_connect_pt = tmp_vector_subpolylines[isub];
10075 found_vertex_index =
10076 get_connected_vertex_number_on_destination_polyline(
10077 poly_to_connect_pt,
10078 shd_bnd_left_vertex,
10082 if (found_vertex_index)
10086 sub_poly_to_connect = isub;
10099 if (!found_vertex_index)
10101 std::stringstream error;
10103 <<
"The current shared boundary (" << bound_id <<
") was "
10104 <<
"marked to have a connection\nto the left with the "
10105 <<
"boundary (" << uconnection_to_the_left <<
").\n"
10106 <<
"This last boundary is marked to be overlaped by "
10107 <<
"shared boundaries\n"
10108 <<
"The problem is that the left vertex of the current\n"
10109 <<
"shared boundary is not in the list of vertices of "
10110 <<
"the\nboundary to connect.\n\n"
10111 <<
"This is the left vertex of the current shared "
10113 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", "
10114 << shd_bnd_left_vertex[1] <<
")\n\n"
10115 <<
"This is the list of vertices on the destination "
10116 <<
"boundary (only those subpolylines not marked as "
10117 <<
"overlaped by\nshared boundaries)\n";
10118 for (
unsigned p = 0; p < nsub_poly; p++)
10120 if (!boundary_marked_as_shared_boundary(
10121 uconnection_to_the_left, p))
10123 error <<
"Subpolyline #(" << p <<
")\n";
10124 poly_to_connect_pt = tmp_vector_subpolylines[p];
10125 const unsigned n_v = poly_to_connect_pt->
nvertex();
10126 for (
unsigned i = 0;
i < n_v;
i++)
10130 error <<
"Vertex #" <<
i <<
": (" << cvertex[0] <<
", "
10131 << cvertex[1] <<
")\n";
10135 error <<
"\nThis is the list of vertices of the shared "
10136 <<
"polylines that overlap\nthe internal "
10139 get_shared_boundaries_overlapping_internal_boundary(
10140 uconnection_to_the_left, dst_shd_bnd_ids);
10141 const unsigned n_shd_bnd_overlap_int_bnd =
10142 dst_shd_bnd_ids.size();
10143 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10145 const unsigned new_connection_to_the_left =
10146 dst_shd_bnd_ids[ss];
10147 poly_to_connect_pt =
10148 boundary_polyline_pt(new_connection_to_the_left);
10149 if (poly_to_connect_pt != 0)
10151 const unsigned shd_bnd_id_overlap =
10153 error <<
"Shared boundary id(" << shd_bnd_id_overlap
10155 const unsigned n_v = poly_to_connect_pt->
nvertex();
10156 for (
unsigned i = 0;
i < n_v;
i++)
10160 error <<
"Vertex #" <<
i <<
": (" << cvertex[0] <<
", "
10161 << cvertex[1] <<
")\n";
10168 "TriangleMesh::create_shared_polylines_connections()",
10169 OOMPH_EXCEPTION_LOCATION);
10178 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
10188 if (is_connected_to_the_right)
10192 const unsigned uconnection_to_the_right =
10200 bool connecting_to_an_split_boundary =
false;
10204 bool connecting_to_an_overlaped_boundary =
false;
10207 if (uconnection_to_the_right == bound_id)
10210 poly_to_connect_pt = shd_poly_pt;
10215 const unsigned initial_shd_bnd_id = initial_shared_boundary_id();
10217 if (uconnection_to_the_right >= initial_shd_bnd_id)
10221 poly_to_connect_pt =
10222 boundary_polyline_pt(uconnection_to_the_right);
10230 if (boundary_was_splitted(uconnection_to_the_right))
10232 connecting_to_an_split_boundary =
true;
10242 if (connecting_to_an_split_boundary)
10246 const unsigned n_sub_poly =
10247 nboundary_subpolylines(uconnection_to_the_right);
10252 for (
unsigned ii = 0; ii < n_sub_poly; ii++)
10254 if (boundary_marked_as_shared_boundary(
10255 uconnection_to_the_right, ii))
10259 connecting_to_an_overlaped_boundary =
true;
10270 if (boundary_marked_as_shared_boundary(
10271 uconnection_to_the_right, 0))
10275 connecting_to_an_overlaped_boundary =
true;
10282 if (!(connecting_to_an_split_boundary ||
10283 connecting_to_an_overlaped_boundary))
10287 poly_to_connect_pt =
10288 boundary_polyline_pt(uconnection_to_the_right);
10299 if (!connecting_to_an_split_boundary)
10301 if (boundary_was_splitted(uconnection_to_the_right))
10303 std::stringstream error;
10305 <<
"The current shared boundary (" << bound_id <<
") was "
10306 <<
"marked to have a connection\nto the right with the "
10307 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10308 <<
"The problem is that the destination boundary (possibly\n"
10309 <<
"another shared boundary) is marked to be split\n"
10310 <<
"There should not be split shared boundaries\n\n";
10313 "TriangleMesh::create_shared_polylines_connections()",
10314 OOMPH_EXCEPTION_LOCATION);
10332 if (!connecting_to_an_split_boundary)
10336 if (!connecting_to_an_overlaped_boundary)
10341 unsigned vertex_index = 0;
10342 const bool found_vertex_index =
10343 get_connected_vertex_number_on_destination_polyline(
10344 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10348 if (!found_vertex_index)
10350 std::stringstream error;
10352 <<
"The current shared boundary (" << bound_id <<
") was "
10353 <<
"marked to have a connection\nto the right with the "
10354 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10355 <<
"The problem is that the right vertex of the current\n"
10356 <<
"shared boundary is not in the list of vertices of the\n"
10357 <<
"boundary to connect.\n\n"
10358 <<
"This is the right vertex of the current shared "
10360 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", "
10361 << shd_bnd_right_vertex[1] <<
")\n\n"
10362 <<
"This is the list of vertices on the destination "
10364 const unsigned n_v = poly_to_connect_pt->
nvertex();
10365 for (
unsigned i = 0;
i < n_v;
i++)
10369 error <<
"Vertex #" <<
i <<
": (" << cvertex[0] <<
", "
10370 << cvertex[1] <<
")\n";
10374 "TriangleMesh::create_shared_polylines_connections()",
10375 OOMPH_EXCEPTION_LOCATION);
10382 poly_to_connect_pt, vertex_index);
10392 unsigned vertex_index = 0;
10394 bool found_vertex_index =
false;
10399 get_shared_boundaries_overlapping_internal_boundary(
10400 uconnection_to_the_right, dst_shd_bnd_ids);
10404 const unsigned n_shd_bnd_overlap_int_bnd =
10405 dst_shd_bnd_ids.size();
10409 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10412 const unsigned new_connection_to_the_right =
10413 dst_shd_bnd_ids[ss];
10417 poly_to_connect_pt =
10418 boundary_polyline_pt(new_connection_to_the_right);
10420 if (poly_to_connect_pt != 0)
10424 found_vertex_index =
10425 get_connected_vertex_number_on_destination_polyline(
10426 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10431 if (found_vertex_index)
10441 if (!found_vertex_index)
10443 std::stringstream error;
10445 <<
"The current shared boundary (" << bound_id <<
") was "
10446 <<
"marked to have a connection\nto the right with the "
10447 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10448 <<
"This last boundary is marked to be overlaped by "
10449 <<
"shared boundaries\n"
10450 <<
"The problem is that the right vertex of the current\n"
10451 <<
"shared boundary is not in the list of vertices of the\n"
10452 <<
"boundary to connect.\n\n"
10453 <<
"This is the right vertex of the current shared "
10455 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", "
10456 << shd_bnd_right_vertex[1] <<
")\n\n"
10457 <<
"This is the list of vertices on the destination "
10460 get_shared_boundaries_overlapping_internal_boundary(
10461 uconnection_to_the_right, dst_shd_bnd_ids);
10462 const unsigned n_shd_bnd_overlap_int_bnd =
10463 dst_shd_bnd_ids.size();
10464 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10466 const unsigned new_connection_to_the_right =
10467 dst_shd_bnd_ids[ss];
10468 poly_to_connect_pt =
10469 boundary_polyline_pt(new_connection_to_the_right);
10470 if (poly_to_connect_pt != 0)
10472 const unsigned shd_bnd_id_overlap =
10474 error <<
"Shared boundary id(" << shd_bnd_id_overlap
10476 const unsigned n_v = poly_to_connect_pt->
nvertex();
10477 for (
unsigned i = 0;
i < n_v;
i++)
10481 error <<
"Vertex #" <<
i <<
": (" << cvertex[0] <<
", "
10482 << cvertex[1] <<
")\n";
10489 "TriangleMesh::create_shared_polylines_connections()",
10490 OOMPH_EXCEPTION_LOCATION);
10499 poly_to_connect_pt, vertex_index);
10511 boundary_subpolylines(uconnection_to_the_right);
10514 const unsigned nsub_poly = tmp_vector_subpolylines.size();
10516 if (nsub_poly <= 1)
10518 std::ostringstream error_message;
10520 <<
"The boundary (" << uconnection_to_the_right <<
") was "
10521 <<
"marked to be splitted but\n"
10522 <<
"there are only (" << nsub_poly <<
") polylines to "
10523 <<
"represent it.\n";
10525 error_message.str(),
10526 "TriangleMesh::create_shared_polylines_connections()",
10527 OOMPH_EXCEPTION_LOCATION);
10540 if (!connecting_to_an_overlaped_boundary)
10546 unsigned vertex_index = 0;
10548 unsigned sub_poly_to_connect = 0;
10550 bool found_vertex_index =
false;
10554 for (
unsigned isub = 0; isub < nsub_poly; isub++)
10557 poly_to_connect_pt = tmp_vector_subpolylines[isub];
10559 found_vertex_index =
10560 get_connected_vertex_number_on_destination_polyline(
10561 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10564 if (found_vertex_index)
10568 sub_poly_to_connect = isub;
10576 if (!found_vertex_index)
10578 std::stringstream error;
10580 <<
"The current shared boundary (" << bound_id <<
") was "
10581 <<
"marked to have a connection\nto the right with the "
10582 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10583 <<
"The problem is that the right vertex of the current\n"
10584 <<
"shared boundary is not in the list of vertices of any\n"
10585 <<
"of the sub polylines that represent the boundary to\n"
10587 <<
"This is the right vertex of the current shared "
10589 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", "
10590 << shd_bnd_right_vertex[1] <<
")\n\n"
10591 <<
"This is the list of vertices on the destination "
10593 for (
unsigned p = 0; p < nsub_poly; p++)
10595 error <<
"Subpolyline #(" << p <<
")\n";
10596 poly_to_connect_pt = tmp_vector_subpolylines[p];
10597 const unsigned n_v = poly_to_connect_pt->
nvertex();
10598 for (
unsigned i = 0;
i < n_v;
i++)
10602 error <<
"Vertex #" <<
i <<
": (" << cvertex[0] <<
", "
10603 << cvertex[1] <<
")\n";
10608 "TriangleMesh::create_shared_polylines_connections()",
10609 OOMPH_EXCEPTION_LOCATION);
10618 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
10629 unsigned vertex_index = 0;
10631 unsigned sub_poly_to_connect = 0;
10633 bool found_vertex_index =
false;
10638 get_shared_boundaries_overlapping_internal_boundary(
10639 uconnection_to_the_right, dst_shd_bnd_ids);
10643 const unsigned n_shd_bnd_overlap_int_bnd =
10644 dst_shd_bnd_ids.size();
10648 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10651 const unsigned new_connection_to_the_right =
10652 dst_shd_bnd_ids[ss];
10656 if (bound_id != new_connection_to_the_right)
10660 poly_to_connect_pt =
10661 boundary_polyline_pt(new_connection_to_the_right);
10663 if (poly_to_connect_pt != 0)
10667 found_vertex_index =
10668 get_connected_vertex_number_on_destination_polyline(
10669 poly_to_connect_pt,
10670 shd_bnd_right_vertex,
10676 if (found_vertex_index)
10688 if (!found_vertex_index)
10692 for (
unsigned isub = 0; isub < nsub_poly; isub++)
10696 if (!boundary_marked_as_shared_boundary(
10697 uconnection_to_the_right, isub))
10700 poly_to_connect_pt = tmp_vector_subpolylines[isub];
10702 found_vertex_index =
10703 get_connected_vertex_number_on_destination_polyline(
10704 poly_to_connect_pt,
10705 shd_bnd_right_vertex,
10709 if (found_vertex_index)
10713 sub_poly_to_connect = isub;
10726 if (!found_vertex_index)
10728 std::stringstream error;
10730 <<
"The current shared boundary (" << bound_id <<
") was "
10731 <<
"marked to have a connection\nto the right with the "
10732 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10733 <<
"This last boundary is marked to be overlaped by "
10734 <<
"shared boundaries\n"
10735 <<
"The problem is that the right vertex of the current\n"
10736 <<
"shared boundary is not in the list of vertices of "
10737 <<
"the\nboundary to connect.\n\n"
10738 <<
"This is the right vertex of the current shared "
10740 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", "
10741 << shd_bnd_right_vertex[1] <<
")\n\n"
10742 <<
"This is the list of vertices on the destination "
10743 <<
"boundary (only those subpolylines not marked as "
10744 <<
"overlaped by\nshared boundaries)\n";
10745 for (
unsigned p = 0; p < nsub_poly; p++)
10747 if (!boundary_marked_as_shared_boundary(
10748 uconnection_to_the_right, p))
10750 error <<
"Subpolyline #(" << p <<
")\n";
10751 poly_to_connect_pt = tmp_vector_subpolylines[p];
10752 const unsigned n_v = poly_to_connect_pt->
nvertex();
10753 for (
unsigned i = 0;
i < n_v;
i++)
10757 error <<
"Vertex #" <<
i <<
": (" << cvertex[0] <<
", "
10758 << cvertex[1] <<
")\n";
10762 error <<
"\nThis is the list of vertices of the shared "
10763 <<
"polylines that overlap\nthe internal "
10766 get_shared_boundaries_overlapping_internal_boundary(
10767 uconnection_to_the_right, dst_shd_bnd_ids);
10768 const unsigned n_shd_bnd_overlap_int_bnd =
10769 dst_shd_bnd_ids.size();
10770 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10772 const unsigned new_connection_to_the_right =
10773 dst_shd_bnd_ids[ss];
10774 poly_to_connect_pt =
10775 boundary_polyline_pt(new_connection_to_the_right);
10776 if (poly_to_connect_pt != 0)
10778 const unsigned shd_bnd_id_overlap =
10780 error <<
"Shared boundary id(" << shd_bnd_id_overlap
10782 const unsigned n_v = poly_to_connect_pt->
nvertex();
10783 for (
unsigned i = 0;
i < n_v;
i++)
10787 error <<
"Vertex #" <<
i <<
": (" << cvertex[0] <<
", "
10788 << cvertex[1] <<
")\n";
10795 "TriangleMesh::create_shared_polylines_connections()",
10796 OOMPH_EXCEPTION_LOCATION);
10805 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
10824 template<
class ELEMENT>
10829 const unsigned n_proc = this->communicator_pt()->nproc();
10830 const unsigned my_rank = this->communicator_pt()->my_rank();
10834 std::map<FiniteElement*, bool> done_ele;
10838 for (
unsigned iproc = 0; iproc < n_proc; iproc++)
10841 if (iproc != my_rank)
10844 const unsigned n_shd_bnd_iproc = nshared_boundaries(my_rank, iproc);
10849 const unsigned n_shd_bnd_iproc_rev = nshared_boundaries(iproc, my_rank);
10850 if (n_shd_bnd_iproc != n_shd_bnd_iproc_rev)
10852 std::ostringstream error_stream;
10854 <<
"The number of shared boundaries of processor (" << my_rank
10855 <<
") with processor(" << iproc <<
"): (" << n_shd_bnd_iproc
10857 <<
"is different from the number of shared boundaries of "
10858 <<
"processor (" << iproc <<
")\nwith processor (" << my_rank
10859 <<
"): (" << n_shd_bnd_iproc <<
")\n\n";
10861 OOMPH_CURRENT_FUNCTION,
10862 OOMPH_EXCEPTION_LOCATION);
10868 for (
unsigned i = 0;
i < n_shd_bnd_iproc;
i++)
10871 const unsigned shd_bnd_id = shared_boundaries_ids(my_rank, iproc,
i);
10874 const unsigned n_shd_bnd_ele = nshared_boundary_element(shd_bnd_id);
10877 for (
unsigned e = 0;
e < n_shd_bnd_ele;
e++)
10880 FiniteElement* ele_pt = shared_boundary_element_pt(shd_bnd_id,
e);
10886 if (!done_ele[ele_pt])
10889 const unsigned n_nodes = ele_pt->nnode();
10894 for (
unsigned k = 0; k < n_nodes; k++)
10896 Node* tmp_node_pt = ele_pt->node_pt(k);
10898 for (
unsigned d = 0; d < 2; d++)
10900 element_centroid[d] += tmp_node_pt->
x(d);
10905 for (
unsigned d = 0; d < 2; d++)
10907 element_centroid[d] = element_centroid[d] / (double)n_nodes;
10911 output_holes_coordinates.push_back(element_centroid);
10933 template<
class ELEMENT>
10954 const unsigned n_input_holes = output_holes_coordinates.size();
10957 if (n_input_holes == 0)
10963 const unsigned n_polygons = polygons_pt.size();
10972 for (
unsigned p = 0; p < n_polygons; p++)
10975 const unsigned n_polylines = polygons_pt[p]->npolyline();
10977 for (
unsigned pp = 0; pp < n_polylines; pp++)
10981 polygons_pt[p]->polyline_pt(pp);
10983 const unsigned n_vertices = tmp_poly_pt->
nvertex();
10987 for (
unsigned v = 0; v < n_vertices - 1; v++)
10991 vertices_polygons[p].push_back(current_vertex);
11003 std::vector<bool> is_outer_polygon(n_polygons,
true);
11007 if (n_polygons > 1)
11016 for (
unsigned p = 0; p < n_polygons; p++)
11022 const unsigned n_vertices = tmp_inner_polygon.size();
11025 polygon_edge_middle_vertex[p].resize(n_vertices - 1);
11029 for (
unsigned e = 0;
e < n_vertices - 1;
e++)
11032 const unsigned dim = 2;
11033 polygon_edge_middle_vertex[p][
e].resize(dim);
11034 for (
unsigned d = 0; d < dim; d++)
11036 polygon_edge_middle_vertex[p][
e][d] =
11037 (tmp_inner_polygon[
e][d] + tmp_inner_polygon[
e + 1][d]) / 2.0;
11046 for (
unsigned idx_inner = 0; idx_inner < n_polygons; idx_inner++)
11051 bool is_inner_polygon =
false;
11056 for (
unsigned i = 0;
i < n_polygons;
i++)
11059 if (
i != idx_inner)
11062 const unsigned n_edges =
11063 polygon_edge_middle_vertex[idx_inner].size();
11066 for (
unsigned e = 0;
e < n_edges;
e++)
11070 polygon_edge_middle_vertex[idx_inner][
e];
11073 const bool is_point_inside = is_point_inside_polygon_helper(
11074 vertices_polygons[
i], current_vertex);
11078 if (is_point_inside)
11081 is_inner_polygon =
true;
11092 if (is_inner_polygon)
11102 if (is_inner_polygon)
11105 is_outer_polygon[idx_inner] =
false;
11111 is_outer_polygon[idx_inner] =
true;
11120 unsigned n_outer_polygons = 0;
11121 unsigned n_inner_polygons = 0;
11125 for (
unsigned i = 0;
i < n_polygons;
i++)
11127 if (is_outer_polygon[
i])
11130 n_outer_polygons++;
11135 n_inner_polygons++;
11137 index_inner_polygon.push_back(
i);
11156 std::vector<bool> is_inside_an_inner_polygon(n_input_holes,
false);
11160 std::vector<bool> is_outside_the_outer_polygons(n_input_holes,
true);
11164 std::vector<bool> is_inside_the_convex_hull(n_input_holes,
false);
11173 for (
unsigned i = 0;
i < n_inner_polygons;
i++)
11176 const unsigned ii = index_inner_polygon[
i];
11179 for (
unsigned h = 0; h < n_input_holes; h++)
11183 if (!is_inside_an_inner_polygon[h])
11186 const bool is_inside_polygon = is_point_inside_polygon_helper(
11187 vertices_polygons[ii], output_holes_coordinates[h]);
11191 if (is_inside_polygon)
11194 is_inside_an_inner_polygon[h] =
true;
11196 vertex_inside_inner_polygon[
i].push_back(
11197 output_holes_coordinates[h]);
11209 for (
unsigned h = 0; h < n_input_holes; h++)
11213 if (!is_inside_an_inner_polygon[h])
11217 for (
unsigned i = 0;
i < n_polygons;
i++)
11220 if (is_outer_polygon[
i])
11223 const bool is_inside_polygon = is_point_inside_polygon_helper(
11224 vertices_polygons[
i], output_holes_coordinates[h]);
11229 if (is_inside_polygon)
11232 is_outside_the_outer_polygons[h] =
false;
11246 is_outside_the_outer_polygons[h] =
false;
11253 std::vector<Point> input_vertices_convex_hull;
11256 for (
unsigned p = 0; p < n_polygons; p++)
11259 const unsigned n_vertices = vertices_polygons[p].size();
11261 for (
unsigned v = 0; v < n_vertices; v++)
11266 point.
x = vertices_polygons[p][v][0];
11267 point.
y = vertices_polygons[p][v][1];
11269 input_vertices_convex_hull.push_back(point);
11274 std::vector<Point> output_vertices_convex_hull =
11275 convex_hull(input_vertices_convex_hull);
11278 const unsigned n_vertices_convex_hull = output_vertices_convex_hull.size();
11282 for (
unsigned i = 0;
i < n_vertices_convex_hull;
i++)
11285 vertices_convex_hull[
i].resize(2);
11287 vertices_convex_hull[
i][0] = output_vertices_convex_hull[
i].x;
11288 vertices_convex_hull[
i][1] = output_vertices_convex_hull[
i].y;
11294 for (
unsigned h = 0; h < n_input_holes; h++)
11297 if (is_outside_the_outer_polygons[h])
11300 const bool is_inside_convex_hull = is_point_inside_polygon_helper(
11301 vertices_convex_hull, output_holes_coordinates[h]);
11304 if (is_inside_convex_hull)
11307 is_inside_the_convex_hull[h] =
true;
11314 is_inside_the_convex_hull[h] =
true;
11322 for (
unsigned h = 0; h < n_input_holes; h++)
11325 if ((is_inside_an_inner_polygon[h]) ||
11326 (is_outside_the_outer_polygons[h] && is_inside_the_convex_hull[h]))
11329 hole_kept.push_back(output_holes_coordinates[h]);
11334 output_holes_coordinates.clear();
11336 output_holes_coordinates = hole_kept;
11343 template<
class ELEMENT>
11348 unsigned n_unsorted_polylines = unsorted_polylines_pt.size();
11349 unsigned n_sorted_polylines = 0;
11350 unsigned curves_index = 0;
11353 std::map<TriangleMeshPolyLine*, bool> done_polyline;
11359 std::list<TriangleMeshPolyLine*> sorted_polyline_list_pt;
11360 bool changes =
false;
11369 bool found_root_polyline =
false;
11370 while (pp < n_unsorted_polylines && !found_root_polyline)
11372 if (!done_polyline[unsorted_polylines_pt[pp]])
11374 found_root_polyline =
true;
11383 if (pp < n_unsorted_polylines)
11386 left_pt = right_pt = unsorted_polylines_pt[pp];
11387 done_polyline[left_pt] =
true;
11389 n_sorted_polylines++;
11393 sorted_polyline_list_pt.push_back(left_pt);
11405 for (
unsigned i = pp + 1;
i < n_unsorted_polylines;
i++)
11408 unsorted_polylines_pt[
i];
11409 if (!done_polyline[current_polyline_pt])
11420 if (left_vertex == final_vertex)
11422 left_pt = current_polyline_pt;
11423 sorted_polyline_list_pt.push_front(left_pt);
11424 done_polyline[left_pt] =
true;
11425 n_sorted_polylines++;
11431 else if (right_vertex == initial_vertex)
11433 right_pt = current_polyline_pt;
11434 sorted_polyline_list_pt.push_back(right_pt);
11435 done_polyline[right_pt] =
true;
11436 n_sorted_polylines++;
11442 else if (left_vertex == initial_vertex)
11444 current_polyline_pt->
reverse();
11445 left_pt = current_polyline_pt;
11446 sorted_polyline_list_pt.push_front(left_pt);
11447 done_polyline[left_pt] =
true;
11448 n_sorted_polylines++;
11454 else if (right_vertex == final_vertex)
11456 current_polyline_pt->
reverse();
11457 right_pt = current_polyline_pt;
11458 sorted_polyline_list_pt.push_back(right_pt);
11459 done_polyline[right_pt] =
true;
11460 n_sorted_polylines++;
11481 if (!found_root_polyline)
11483 std::stringstream err;
11484 err <<
"It was not possible to find a root polyline to sort the "
11485 <<
"others around it.\nThe number of unsorted and sorted "
11486 <<
"polylines is different, it means that\nnot all the "
11487 <<
"polylines have been sorted.\n"
11488 <<
"Found root polyline: (" << found_root_polyline <<
")\n"
11489 <<
"Sorted polylines: (" << n_sorted_polylines <<
")\n"
11490 <<
"Unsorted polylines: (" << n_unsorted_polylines <<
")\n";
11492 "TriangleMesh::sort_polylines_helper()",
11493 OOMPH_EXCEPTION_LOCATION);
11500 unsigned n_sorted_polyline_on_list = sorted_polyline_list_pt.size();
11504 n_sorted_polyline_on_list);
11505 unsigned counter = 0;
11507 std::list<TriangleMeshPolyLine*>::iterator it_polyline;
11508 for (it_polyline = sorted_polyline_list_pt.begin();
11509 it_polyline != sorted_polyline_list_pt.end();
11512 tmp_sorted_polylines[counter] = *it_polyline;
11516 sorted_polylines_pt.push_back(tmp_sorted_polylines);
11520 }
while (n_sorted_polylines < n_unsorted_polylines);
11525 if (n_sorted_polylines != n_unsorted_polylines)
11527 std::stringstream err;
11528 err <<
"The number of polylines on the unsorted and sorted vectors"
11529 <<
" is different,\n"
11530 <<
"it means that not all the polylines have been sorted.\n"
11531 <<
"Sorted polylines: " << n_sorted_polylines
11532 <<
"\nUnsorted polylines: " << n_unsorted_polylines;
11534 "TriangleMesh::sort_polylines_helper()",
11535 OOMPH_EXCEPTION_LOCATION);
11543 template<
class ELEMENT>
11549 std::map<
Data*, std::set<unsigned>>& processors_associated_with_data,
11550 const bool& overrule_keep_as_halo_element_status)
11553 const unsigned nproc = comm_pt->nproc();
11554 const unsigned my_rank = comm_pt->my_rank();
11562 for (
unsigned iproc = 0; iproc < nproc; iproc++)
11564 halo_element_pt[iproc].resize(nproc);
11570 std::map<GeneralisedElement*, unsigned> element_to_global_index;
11573 this->get_halo_elements_on_all_procs(nproc,
11576 processors_associated_with_data,
11577 overrule_keep_as_halo_element_status,
11578 element_to_global_index,
11582 flush_shared_boundary_polyline_pt();
11583 Shared_boundary_polyline_pt.resize(nproc);
11589 std::set<FiniteElement*> element_in_processor_pt;
11590 const unsigned n_ele = backed_up_f_el_pt.size();
11591 for (
unsigned e = 0;
e < n_ele;
e++)
11593 if (element_domain[
e] == my_rank)
11595 element_in_processor_pt.insert(backed_up_f_el_pt[
e]);
11602 std::map<std::pair<Node*, Node*>,
unsigned> elements_edges_on_boundary;
11603 this->get_element_edges_on_boundary(elements_edges_on_boundary);
11607 this->create_polylines_from_halo_elements_helper(
11609 element_to_global_index,
11610 element_in_processor_pt,
11612 elements_edges_on_boundary,
11613 Shared_boundary_polyline_pt);
11621 template<
class ELEMENT>
11623 const unsigned& nproc,
11626 std::map<
Data*, std::set<unsigned>>& processors_associated_with_data,
11627 const bool& overrule_keep_as_halo_element_status,
11628 std::map<GeneralisedElement*, unsigned>& element_to_global_index,
11631 const unsigned n_ele = backed_up_el_pt.size();
11634 for (
unsigned iproc = 0; iproc < nproc; iproc++)
11641 for (
unsigned e = 0;
e < n_ele;
e++)
11645 unsigned el_domain = element_domain[
e];
11649 if (el_domain != iproc)
11654 if ((this->Keep_all_elements_as_halos) ||
11657 if (!overrule_keep_as_halo_element_status)
11661 if (!already_added[el_domain][el_pt])
11663 output_halo_elements_pt[iproc][el_domain].push_back(el_pt);
11664 already_added[el_domain][el_pt] =
true;
11665 element_to_global_index[el_pt] =
e;
11674 if (finite_el_pt != 0)
11676 unsigned n_node = finite_el_pt->
nnode();
11677 for (
unsigned n = 0; n < n_node; n++)
11682 std::set<unsigned>::iterator it =
11683 processors_associated_with_data[nod_pt].find(iproc);
11684 if (it != processors_associated_with_data[nod_pt].end())
11688 if (!already_added[el_domain][el_pt])
11690 output_halo_elements_pt[iproc][el_domain].push_back(el_pt);
11691 already_added[el_domain][el_pt] =
true;
11692 element_to_global_index[el_pt] =
e;
11710 template<
class ELEMENT>
11712 std::map<std::pair<Node*, Node*>,
unsigned>& element_edges_on_boundary)
11715 const unsigned nbound = this->nboundary();
11717 for (
unsigned b = 0; b < nbound; b++)
11720 std::map<std::pair<Node*, Node*>,
bool> edge_done;
11722 const unsigned nbound_ele = this->nboundary_element(b);
11723 for (
unsigned e = 0;
e < nbound_ele;
e++)
11728 int face_index = this->face_index_at_boundary(b,
e);
11733 const unsigned nnodes = face_ele_pt->
nnode();
11736 Node* last_node_pt = face_ele_pt->
node_pt(nnodes - 1);
11739 std::pair<Node*, Node*> edge =
11740 std::make_pair(first_node_pt, last_node_pt);
11743 if (!edge_done[edge])
11746 edge_done[edge] =
true;
11749 std::pair<Node*, Node*> inv_edge =
11750 std::make_pair(last_node_pt, first_node_pt);
11753 edge_done[inv_edge] =
true;
11756 element_edges_on_boundary[edge] = b;
11760 delete face_ele_pt;
11775 template<
class ELEMENT>
11778 std::map<GeneralisedElement*, unsigned>& element_to_global_index,
11779 std::set<FiniteElement*>& element_in_processor_pt,
11781 std::map<std::pair<Node*, Node*>,
unsigned>& elements_edges_on_boundary,
11784 const unsigned nproc = this->communicator_pt()->nproc();
11785 const unsigned my_rank = this->communicator_pt()->my_rank();
11810 std::map<std::pair<Node*, Node*>,
bool> overlapped_edge;
11816 Shared_boundaries_ids.resize(nproc);
11817 for (
unsigned j = 0; j < nproc; j++)
11819 edges[j].resize(nproc);
11820 edge_element_pt[j].resize(nproc);
11821 edge_element_face[j].resize(nproc);
11822 edge_boundary[j].resize(nproc);
11825 Shared_boundaries_ids[j].resize(nproc);
11831 for (
unsigned iproc = 0; iproc < nproc; iproc++)
11838 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
11855 halo_elements_iproc_with_jproc = input_halo_elements[iproc][jproc];
11858 const unsigned nhalo_elements_iproc_with_jproc =
11859 halo_elements_iproc_with_jproc.size();
11861 if (nhalo_elements_iproc_with_jproc > 0)
11864 halo_elements_jproc_with_iproc = input_halo_elements[jproc][iproc];
11868 const unsigned nhalo_elements_jproc_with_iproc =
11869 halo_elements_jproc_with_iproc.size();
11872 if (nhalo_elements_jproc_with_iproc == 0)
11877 std::stringstream err;
11878 err <<
"There are no halo elements from processor (" << jproc
11880 <<
"with processor (" << iproc <<
").\n"
11881 <<
"This is strange since there are halo elements from "
11882 <<
"processor (" << iproc <<
") with processor (" << jproc
11884 <<
"Number of halo elements from (" << iproc <<
") to ("
11885 << jproc <<
") : (" << nhalo_elements_iproc_with_jproc <<
")\n"
11886 <<
"Number of halo elements from (" << jproc <<
") to ("
11887 << iproc <<
") : (" << nhalo_elements_jproc_with_iproc <<
")\n";
11890 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11891 OOMPH_EXCEPTION_LOCATION);
11896 unsigned halo_edges_counter_iproc = 0;
11898 unsigned halo_edges_counter_jproc = 0;
11902 edgesi_to_element_pt;
11906 std::map<std::pair<std::pair<Node*, Node*>,
FiniteElement*>,
int>
11907 edgesi_element_pt_to_face_index;
11911 edgesj_to_element_pt;
11915 std::map<std::pair<std::pair<Node*, Node*>,
FiniteElement*>,
int>
11916 edgesj_element_pt_to_face_index;
11922 for (
unsigned ih = 0; ih < nhalo_elements_iproc_with_jproc; ih++)
11926 element_to_global_index[halo_elements_iproc_with_jproc[ih]];
11928 if (element_domain[
e] != jproc)
11931 std::stringstream err;
11932 err <<
"There was a problem on the ihalo-jhalo classification.\n"
11933 <<
"One of the elements, (the one with the (" <<
e <<
")-th "
11934 <<
"index ) is not on the (" << jproc <<
")-th processor\n"
11935 <<
"but it was stored as a halo element of processor ("
11936 << iproc <<
") with processor (" << jproc <<
").\n";
11939 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11940 OOMPH_EXCEPTION_LOCATION);
11945 dynamic_cast<FiniteElement*
>(halo_elements_iproc_with_jproc[ih]);
11949 std::stringstream err;
11950 err <<
"The halo element (" << ih
11951 <<
") could not be casted to the "
11952 <<
"FiniteElement type.\n";
11955 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11956 OOMPH_EXCEPTION_LOCATION);
11961 const unsigned n_nodes = el_pt->
nnode();
11968 std::stringstream err;
11969 err <<
"The number of nodes of the " << ih
11970 <<
"-th halo element is"
11971 <<
" (" << n_nodes <<
").\nWe can not work with triangle "
11972 <<
"elements with less than three nodes\n";
11975 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11976 OOMPH_EXCEPTION_LOCATION);
11986 halo_edges_iproc.push_back(first_node_pt);
11987 halo_edges_iproc.push_back(second_node_pt);
11988 halo_edges_counter_jproc++;
11990 halo_edges_iproc.push_back(second_node_pt);
11991 halo_edges_iproc.push_back(third_node_pt);
11992 halo_edges_counter_jproc++;
11994 halo_edges_iproc.push_back(third_node_pt);
11995 halo_edges_iproc.push_back(first_node_pt);
11996 halo_edges_counter_jproc++;
11999 std::pair<Node*, Node*> edge1 =
12000 std::make_pair(first_node_pt, second_node_pt);
12001 edgesi_to_element_pt[edge1] = el_pt;
12003 std::pair<Node*, Node*> edge2 =
12004 std::make_pair(second_node_pt, third_node_pt);
12005 edgesi_to_element_pt[edge2] = el_pt;
12007 std::pair<Node*, Node*> edge3 =
12008 std::make_pair(third_node_pt, first_node_pt);
12009 edgesi_to_element_pt[edge3] = el_pt;
12012 std::pair<std::pair<Node*, Node*>,
FiniteElement*> edge_ele1 =
12013 std::make_pair(edge1, el_pt);
12014 edgesi_element_pt_to_face_index[edge_ele1] = 2;
12016 std::pair<std::pair<Node*, Node*>,
FiniteElement*> edge_ele2 =
12017 std::make_pair(edge2, el_pt);
12018 edgesi_element_pt_to_face_index[edge_ele2] = 0;
12020 std::pair<std::pair<Node*, Node*>,
FiniteElement*> edge_ele3 =
12021 std::make_pair(edge3, el_pt);
12022 edgesi_element_pt_to_face_index[edge_ele3] = 1;
12030 for (
unsigned jh = 0; jh < nhalo_elements_jproc_with_iproc; jh++)
12034 element_to_global_index[halo_elements_jproc_with_iproc[jh]];
12036 if (element_domain[
e] != iproc)
12039 std::stringstream err;
12040 err <<
"There was a problem on the jhalo-ihalo classification.\n"
12041 <<
"One of the elements, (the one with the (" <<
e <<
")-th "
12042 <<
"index ) is not on the (" << iproc <<
")-th processor\n"
12043 <<
"but it was stored as a halo element of processor ("
12044 << jproc <<
") with processor (" << iproc <<
").\n";
12047 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12048 OOMPH_EXCEPTION_LOCATION);
12053 dynamic_cast<FiniteElement*
>(halo_elements_jproc_with_iproc[jh]);
12056 std::stringstream err;
12057 err <<
"The halo element (" << jh
12058 <<
") could not be casted to the "
12059 <<
"FiniteElement type.\n";
12062 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12063 OOMPH_EXCEPTION_LOCATION);
12068 const unsigned n_nodes = el_pt->
nnode();
12075 std::stringstream err;
12076 err <<
"The number of nodes of the " << jh
12077 <<
"-th halo element is"
12078 <<
" (" << n_nodes <<
").\nWe can not work with triangle "
12079 <<
"elements with less than three nodes\n";
12082 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12083 OOMPH_EXCEPTION_LOCATION);
12093 halo_edges_jproc.push_back(first_node_pt);
12094 halo_edges_jproc.push_back(second_node_pt);
12095 halo_edges_counter_iproc++;
12097 halo_edges_jproc.push_back(second_node_pt);
12098 halo_edges_jproc.push_back(third_node_pt);
12099 halo_edges_counter_iproc++;
12101 halo_edges_jproc.push_back(third_node_pt);
12102 halo_edges_jproc.push_back(first_node_pt);
12103 halo_edges_counter_iproc++;
12106 std::pair<Node*, Node*> edge1 =
12107 std::make_pair(first_node_pt, second_node_pt);
12108 edgesj_to_element_pt[edge1] = el_pt;
12110 std::pair<Node*, Node*> edge2 =
12111 std::make_pair(second_node_pt, third_node_pt);
12112 edgesj_to_element_pt[edge2] = el_pt;
12114 std::pair<Node*, Node*> edge3 =
12115 std::make_pair(third_node_pt, first_node_pt);
12116 edgesj_to_element_pt[edge3] = el_pt;
12119 std::pair<std::pair<Node*, Node*>,
FiniteElement*> edge_ele1 =
12120 std::make_pair(edge1, el_pt);
12121 edgesj_element_pt_to_face_index[edge_ele1] = 2;
12123 std::pair<std::pair<Node*, Node*>,
FiniteElement*> edge_ele2 =
12124 std::make_pair(edge2, el_pt);
12125 edgesj_element_pt_to_face_index[edge_ele2] = 0;
12127 std::pair<std::pair<Node*, Node*>,
FiniteElement*> edge_ele3 =
12128 std::make_pair(edge3, el_pt);
12129 edgesj_element_pt_to_face_index[edge_ele3] = 1;
12142 unsigned nhalo_iedges = halo_edges_iproc.size();
12143 unsigned nhalo_jedges = halo_edges_jproc.size();
12147 for (
unsigned ihe = 0; ihe < nhalo_iedges; ihe += 2)
12151 ihalo_edge[0] = halo_edges_iproc[ihe];
12152 ihalo_edge[1] = halo_edges_iproc[ihe + 1];
12155 std::pair<Node*, Node*> tmp_edge =
12156 std::make_pair(ihalo_edge[0], ihalo_edge[1]);
12160 int edge_boundary_id = -1;
12162 std::map<std::pair<Node*, Node*>,
unsigned>::iterator it;
12163 it = elements_edges_on_boundary.find(tmp_edge);
12166 if (it != elements_edges_on_boundary.end())
12170 edge_boundary_id = (*it).second;
12176 std::pair<Node*, Node*> rtmp_edge =
12177 std::make_pair(ihalo_edge[1], ihalo_edge[0]);
12178 it = elements_edges_on_boundary.find(rtmp_edge);
12179 if (it != elements_edges_on_boundary.end())
12183 edge_boundary_id = (*it).second;
12190 for (
unsigned jhe = 0; jhe < nhalo_jedges; jhe += 2)
12194 jhalo_edge[0] = halo_edges_jproc[jhe];
12195 jhalo_edge[1] = halo_edges_jproc[jhe + 1];
12198 if (ihalo_edge[0] == jhalo_edge[0] &&
12199 ihalo_edge[1] == jhalo_edge[1])
12202 std::pair<Node*, Node*> new_edge =
12203 std::make_pair(ihalo_edge[0], ihalo_edge[1]);
12209 haloi_ele_pt = edgesi_to_element_pt[new_edge];
12211 haloj_ele_pt = edgesj_to_element_pt[new_edge];
12214 if (haloi_ele_pt == 0 || haloj_ele_pt == 0)
12216 std::stringstream err;
12217 err <<
"There is no associated elements with the new "
12218 <<
"shared boundary. This is an storing problem,\n"
12219 <<
"possibly related with a memory leak problem!!!\n"
12220 <<
"The nodes that compound the edge are these:\n"
12221 <<
"On processor (" << iproc <<
"):\n"
12222 <<
"(" << ihalo_edge[0]->x(0) <<
", "
12223 << ihalo_edge[0]->x(1) <<
") and (" << ihalo_edge[1]->x(0)
12224 <<
", " << ihalo_edge[1]->x(1) <<
")\n\n"
12225 <<
"On processor (" << jproc <<
"):\n"
12226 <<
"(" << jhalo_edge[0]->x(0) <<
", "
12227 << jhalo_edge[0]->x(1) <<
") and (" << jhalo_edge[1]->x(0)
12228 <<
", " << jhalo_edge[1]->x(1) <<
")\n\n"
12229 <<
"The nodes coordinates should be the same!!!\n";
12231 "TriangleMesh::create_polylines_from_"
12232 "halo_elements_helper()",
12233 OOMPH_EXCEPTION_LOCATION);
12237 edges[iproc][jproc].push_back(new_edge);
12240 if (edge_boundary_id >= 0)
12243 overlapped_edge[new_edge] =
true;
12246 std::pair<Node*, Node*> rev_new_edge =
12247 std::make_pair(ihalo_edge[1], ihalo_edge[0]);
12250 overlapped_edge[rev_new_edge] =
true;
12256 edge_boundary[iproc][jproc].push_back(edge_boundary_id);
12260 tmp_elements_pt.push_back(haloi_ele_pt);
12261 tmp_elements_pt.push_back(haloj_ele_pt);
12264 edge_element_pt[iproc][jproc].push_back(tmp_elements_pt);
12271 edge_elementi_pair = make_pair(new_edge, haloi_ele_pt);
12274 edge_elementj_pair = make_pair(new_edge, haloj_ele_pt);
12278 int face_index_haloi_ele = -1;
12279 face_index_haloi_ele =
12280 edgesi_element_pt_to_face_index[edge_elementi_pair];
12281 int face_index_haloj_ele = -1;
12282 face_index_haloj_ele =
12283 edgesj_element_pt_to_face_index[edge_elementj_pair];
12285 if (face_index_haloi_ele == -1 || face_index_haloj_ele == -1)
12287 std::stringstream err;
12288 err <<
"There is no associated face indexes to the"
12289 <<
"elements that gave\nrise to the shared edge\n"
12290 <<
"The nodes that compound the edge are these:\n"
12291 <<
"On processor (" << iproc <<
"):\n"
12292 <<
"(" << ihalo_edge[0]->x(0) <<
", "
12293 << ihalo_edge[0]->x(1) <<
") and (" << ihalo_edge[1]->x(0)
12294 <<
", " << ihalo_edge[1]->x(1) <<
")\n\n"
12295 <<
"On processor (" << jproc <<
"):\n"
12296 <<
"(" << jhalo_edge[0]->x(0) <<
", "
12297 << jhalo_edge[0]->x(1) <<
") and (" << jhalo_edge[1]->x(0)
12298 <<
", " << jhalo_edge[1]->x(1) <<
")\n\n"
12299 <<
"The nodes coordinates should be the same!!!\n";
12301 "TriangleMesh::create_polylines_from_"
12302 "halo_elements_helper()",
12303 OOMPH_EXCEPTION_LOCATION);
12309 tmp_edge_element_face_index.push_back(face_index_haloi_ele);
12310 tmp_edge_element_face_index.push_back(face_index_haloj_ele);
12312 edge_element_face[iproc][jproc].push_back(
12313 tmp_edge_element_face_index);
12321 else if (ihalo_edge[0] == jhalo_edge[1] &&
12322 ihalo_edge[1] == jhalo_edge[0])
12325 std::pair<Node*, Node*> new_edge =
12326 std::make_pair(ihalo_edge[0], ihalo_edge[1]);
12331 haloi_ele_pt = edgesi_to_element_pt[new_edge];
12336 std::pair<Node*, Node*> new_edge_reversed =
12337 std::make_pair(jhalo_edge[0], jhalo_edge[1]);
12338 haloj_ele_pt = edgesj_to_element_pt[new_edge_reversed];
12341 if (haloi_ele_pt == 0 || haloj_ele_pt == 0)
12343 std::stringstream err;
12344 err <<
"There is no associated elements with the new "
12345 <<
"shared boundary (reversed version). This is an "
12346 <<
"storing problem, possibly related with a memory "
12347 <<
"leak problem!!!\n"
12348 <<
"The nodes that compound the edge are these:\n"
12349 <<
"On processor (" << iproc <<
"):\n"
12350 <<
"(" << ihalo_edge[0]->x(0) <<
", "
12351 << ihalo_edge[0]->x(1) <<
") and (" << ihalo_edge[1]->x(0)
12352 <<
", " << ihalo_edge[1]->x(1) <<
")\n\n"
12353 <<
"On processor (" << jproc <<
"):\n"
12354 <<
"(" << jhalo_edge[0]->x(0) <<
", "
12355 << jhalo_edge[0]->x(1) <<
") and (" << jhalo_edge[1]->x(0)
12356 <<
", " << jhalo_edge[1]->x(1) <<
")\n\n"
12357 <<
"The nodes coordinates should be the same!!!\n";
12359 "TriangleMesh::create_polylines_from_"
12360 "halo_elements_helper()",
12361 OOMPH_EXCEPTION_LOCATION);
12365 edges[iproc][jproc].push_back(new_edge);
12368 if (edge_boundary_id >= 0)
12371 overlapped_edge[new_edge] =
true;
12374 std::pair<Node*, Node*> rev_new_edge =
12375 std::make_pair(ihalo_edge[1], ihalo_edge[0]);
12378 overlapped_edge[rev_new_edge] =
true;
12383 edge_boundary[iproc][jproc].push_back(edge_boundary_id);
12387 tmp_elements_pt.push_back(haloi_ele_pt);
12388 tmp_elements_pt.push_back(haloj_ele_pt);
12391 edge_element_pt[iproc][jproc].push_back(tmp_elements_pt);
12398 edge_elementi_pair = make_pair(new_edge, haloi_ele_pt);
12401 edge_elementj_pair =
12402 make_pair(new_edge_reversed, haloj_ele_pt);
12406 int face_index_haloi_ele = -1;
12407 face_index_haloi_ele =
12408 edgesi_element_pt_to_face_index[edge_elementi_pair];
12409 int face_index_haloj_ele = -1;
12410 face_index_haloj_ele =
12411 edgesj_element_pt_to_face_index[edge_elementj_pair];
12413 if (face_index_haloi_ele == -1 || face_index_haloj_ele == -1)
12415 std::stringstream err;
12416 err <<
"There is no associated face indexes to the"
12417 <<
"elements that gave\nrise to the shared edge\n"
12418 <<
"The nodes that compound the edge are these:\n"
12419 <<
"On processor (" << iproc <<
"):\n"
12420 <<
"(" << ihalo_edge[0]->x(0) <<
", "
12421 << ihalo_edge[0]->x(1) <<
") and (" << ihalo_edge[1]->x(0)
12422 <<
", " << ihalo_edge[1]->x(1) <<
")\n\n"
12423 <<
"On processor (" << jproc <<
"):\n"
12424 <<
"(" << jhalo_edge[0]->x(0) <<
", "
12425 << jhalo_edge[0]->x(1) <<
") and (" << jhalo_edge[1]->x(0)
12426 <<
", " << jhalo_edge[1]->x(1) <<
")\n\n"
12427 <<
"The nodes coordinates should be the same!!!\n";
12429 "TriangleMesh::create_polylines_from_"
12430 "halo_elements_helper()",
12431 OOMPH_EXCEPTION_LOCATION);
12437 tmp_edge_element_face_index.push_back(face_index_haloi_ele);
12438 tmp_edge_element_face_index.push_back(face_index_haloj_ele);
12440 edge_element_face[iproc][jproc].push_back(
12441 tmp_edge_element_face_index);
12466 std::map<Node*, unsigned> global_shared_node_degree;
12470 std::map<std::pair<Node*, Node*>,
bool> edge_done;
12473 std::map<Node*, bool> node_done;
12477 for (
unsigned iproc = 0; iproc < nproc; iproc++)
12484 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
12487 const unsigned nshd_edges = edges[iproc][jproc].size();
12493 const unsigned nedge_element = edge_element_pt[iproc][jproc].size();
12494 if (nshd_edges != nedge_element)
12496 std::stringstream error_message;
12498 <<
"The number of shared edges between processor iproc and jproc\n"
12499 <<
"is different form the number of edge elements between the\n"
12500 <<
"pair of processors\n"
12501 <<
"iproc: (" << iproc <<
")\n"
12502 <<
"jproc: (" << jproc <<
")\n"
12503 <<
"# of shared edges: (" << nshd_edges <<
")\n"
12504 <<
"# of edge elements: (" << nedge_element <<
")\n\n";
12506 error_message.str(),
12507 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12508 OOMPH_EXCEPTION_LOCATION);
12512 const unsigned nedge_element_face =
12513 edge_element_face[iproc][jproc].size();
12514 if (nshd_edges != nedge_element_face)
12516 std::stringstream error_message;
12518 <<
"The number of shared edges between processor iproc and jproc\n"
12519 <<
"is different form the number of edge element faces between "
12521 <<
"pair of processors\n"
12522 <<
"iproc: (" << iproc <<
")\n"
12523 <<
"jproc: (" << jproc <<
")\n"
12524 <<
"# of shared edges: (" << nshd_edges <<
")\n"
12525 <<
"# of edge element faces: (" << nedge_element_face <<
")\n\n";
12527 error_message.str(),
12528 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12529 OOMPH_EXCEPTION_LOCATION);
12533 const unsigned nedge_boundary = edge_boundary[iproc][jproc].size();
12534 if (nshd_edges != nedge_boundary)
12536 std::stringstream error_message;
12538 <<
"The number of shared edges between processor iproc and jproc\n"
12539 <<
"is different form the number of edge boundaries ids between "
12541 <<
"pair of processors\n"
12542 <<
"iproc: (" << iproc <<
")\n"
12543 <<
"jproc: (" << jproc <<
")\n"
12544 <<
"# of shared edges: (" << nshd_edges <<
")\n"
12545 <<
"# of edge boundaries ids: (" << nedge_boundary <<
")\n\n";
12547 error_message.str(),
12548 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12549 OOMPH_EXCEPTION_LOCATION);
12555 for (
unsigned se = 0; se < nshd_edges; se++)
12558 std::pair<Node*, Node*> edge = edges[iproc][jproc][se];
12561 if (edge_done[edge])
12563 std::stringstream error_message;
12565 <<
"The shared edge between processor iproc and processor\n"
12566 <<
"jproc has been already visited, this is weird since the\n"
12567 <<
"edge should not be shared by other pair of processors\n"
12568 <<
"iproc: (" << iproc <<
")\n"
12569 <<
"jproc: (" << jproc <<
")\n"
12570 <<
"First node of edge: (" << edge.first->x(0) <<
", "
12571 << edge.first->x(1) <<
")\n"
12572 <<
"Second node of edge: (" << edge.second->x(0) <<
", "
12573 << edge.second->x(1) <<
")\n"
12574 <<
"Associated edge boundary id: ("
12575 << edge_boundary[iproc][jproc][se] <<
")\n\n";
12577 error_message.str(),
12578 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12579 OOMPH_EXCEPTION_LOCATION);
12583 edge_done[edge] =
true;
12585 std::pair<Node*, Node*> rev_edge =
12586 std::make_pair(edge.second, edge.first);
12588 edge_done[rev_edge] =
true;
12592 Node* left_node_pt = edge.first;
12593 Node* right_node_pt = edge.second;
12596 if (!node_done[left_node_pt])
12600 global_shared_node_degree[left_node_pt] = 1;
12606 global_shared_node_degree[left_node_pt]++;
12610 if (!node_done[right_node_pt])
12614 global_shared_node_degree[right_node_pt] = 1;
12619 global_shared_node_degree[right_node_pt]++;
12634 std::map<unsigned, std::map<Node*, bool>>
12635 node_on_bnd_not_overlapped_by_shd_bnd;
12638 for (std::map<std::pair<Node*, Node*>,
unsigned>::iterator it_map =
12639 elements_edges_on_boundary.begin();
12640 it_map != elements_edges_on_boundary.end();
12644 std::pair<Node*, Node*> edge_pair = (*it_map).first;
12647 if (!overlapped_edge[edge_pair])
12651 unsigned b = (*it_map).second;
12654 Node* left_node_pt = edge_pair.first;
12655 node_on_bnd_not_overlapped_by_shd_bnd[b][left_node_pt] =
true;
12658 Node* right_node_pt = edge_pair.second;
12659 node_on_bnd_not_overlapped_by_shd_bnd[b][right_node_pt] =
true;
12679 std::map<unsigned, std::list<Node*>> shared_bnd_id_to_sorted_list_node_pt;
12683 unsigned shared_boundary_id_start = this->nboundary();
12684 Initial_shared_boundary_id = shared_boundary_id_start;
12690 for (
unsigned iproc = 0; iproc < nproc; iproc++)
12697 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
12705 unsigned npolylines_counter = 0;
12706 const unsigned nedges = edges[iproc][jproc].size();
12712 unsigned nsorted_edges = 0;
12715 std::map<std::pair<Node*, Node*>,
bool> edge_done;
12719 while (nsorted_edges < nedges)
12723 std::list<FiniteElement*> tmp_boundary_element_pt;
12726 std::list<int> tmp_face_index_element;
12728 std::pair<Node*, Node*> edge;
12730 bool found_initial_edge =
false;
12732 int root_edge_bound_id = -1;
12733 unsigned iedge = 0;
12734 for (iedge = 0; iedge < nedges; iedge++)
12736 edge = edges[iproc][jproc][iedge];
12738 if (!edge_done[edge])
12741 root_edge_bound_id = edge_boundary[iproc][jproc][iedge];
12743 found_initial_edge =
true;
12752 if (!found_initial_edge)
12754 std::ostringstream error_message;
12756 <<
"All the edge are already done, but the number of done\n"
12757 <<
"edges (" << nsorted_edges
12758 <<
") is still less than the total\n"
12759 <<
"number of edges (" << nedges <<
").\n";
12762 error_message.str(),
12763 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12764 OOMPH_EXCEPTION_LOCATION);
12770 std::list<Node*> sorted_nodes;
12771 sorted_nodes.clear();
12774 Node* first_node_pt = edge.first;
12775 Node* last_node_pt = edge.second;
12778 sorted_nodes.push_back(first_node_pt);
12779 sorted_nodes.push_back(last_node_pt);
12783 tmp_boundary_element_pt.push_back(
12784 edge_element_pt[iproc][jproc][iedge - 1][0]);
12785 tmp_boundary_element_pt.push_back(
12786 edge_element_pt[iproc][jproc][iedge - 1][1]);
12790 tmp_face_index_element.push_back(
12791 edge_element_face[iproc][jproc][iedge - 1][0]);
12792 tmp_face_index_element.push_back(
12793 edge_element_face[iproc][jproc][iedge - 1][1]);
12796 edge_done[edge] =
true;
12801 bool node_added =
true;
12805 bool node_added_to_the_left =
true;
12806 bool node_added_to_the_right =
true;
12824 bool connection_to_the_left =
false;
12829 bool connection_to_the_right =
false;
12833 bool current_polyline_has_connections_at_both_ends =
false;
12840 int bound_id_connection_to_the_left = -1;
12841 int bound_id_connection_to_the_right = -1;
12844 const unsigned first_node_degree =
12845 global_shared_node_degree[first_node_pt];
12849 bound_id_connection_to_the_left = check_connections_of_polyline_nodes(
12850 element_in_processor_pt,
12851 root_edge_bound_id,
12853 node_on_bnd_not_overlapped_by_shd_bnd,
12855 shared_bnd_id_to_sorted_list_node_pt,
12865 if (bound_id_connection_to_the_left != -1)
12867 connection_to_the_left =
true;
12871 const unsigned last_node_degree =
12872 global_shared_node_degree[last_node_pt];
12876 bound_id_connection_to_the_right =
12877 check_connections_of_polyline_nodes(
12878 element_in_processor_pt,
12879 root_edge_bound_id,
12881 node_on_bnd_not_overlapped_by_shd_bnd,
12883 shared_bnd_id_to_sorted_list_node_pt,
12892 if (bound_id_connection_to_the_right != -1)
12894 connection_to_the_right =
true;
12899 if (connection_to_the_left && connection_to_the_right)
12901 current_polyline_has_connections_at_both_ends =
true;
12909 while (node_added && (nsorted_edges < nedges) &&
12910 !current_polyline_has_connections_at_both_ends)
12915 for (
unsigned iiedge = iedge; iiedge < nedges; iiedge++)
12918 node_added =
false;
12919 node_added_to_the_left =
false;
12920 node_added_to_the_right =
false;
12922 edge = edges[iproc][jproc][iiedge];
12923 const int edge_bound_id = edge_boundary[iproc][jproc][iiedge];
12929 if (!edge_done[edge] && (edge_bound_id == root_edge_bound_id))
12932 Node* left_node_pt = edge.first;
12933 Node* right_node_pt = edge.second;
12936 Node* new_added_node_pt = 0;
12939 if (left_node_pt == first_node_pt && !connection_to_the_left)
12942 sorted_nodes.push_front(right_node_pt);
12944 new_added_node_pt = first_node_pt = right_node_pt;
12948 node_added_to_the_left =
true;
12951 else if (left_node_pt == last_node_pt &&
12952 !connection_to_the_right)
12955 sorted_nodes.push_back(right_node_pt);
12957 new_added_node_pt = last_node_pt = right_node_pt;
12961 node_added_to_the_right =
true;
12964 else if (right_node_pt == first_node_pt &&
12965 !connection_to_the_left)
12968 sorted_nodes.push_front(left_node_pt);
12970 new_added_node_pt = first_node_pt = left_node_pt;
12974 node_added_to_the_left =
true;
12977 else if (right_node_pt == last_node_pt &&
12978 !connection_to_the_right)
12981 sorted_nodes.push_back(left_node_pt);
12983 new_added_node_pt = last_node_pt = left_node_pt;
12987 node_added_to_the_right =
true;
12997 edge_done[edge] =
true;
13001 const unsigned added_node_degree =
13002 global_shared_node_degree[new_added_node_pt];
13004 if (node_added_to_the_left)
13007 tmp_boundary_element_pt.push_front(
13008 edge_element_pt[iproc][jproc][iiedge][1]);
13009 tmp_boundary_element_pt.push_front(
13010 edge_element_pt[iproc][jproc][iiedge][0]);
13012 tmp_face_index_element.push_front(
13013 edge_element_face[iproc][jproc][iiedge][1]);
13014 tmp_face_index_element.push_front(
13015 edge_element_face[iproc][jproc][iiedge][0]);
13018 if (node_added_to_the_right)
13021 tmp_boundary_element_pt.push_back(
13022 edge_element_pt[iproc][jproc][iiedge][0]);
13023 tmp_boundary_element_pt.push_back(
13024 edge_element_pt[iproc][jproc][iiedge][1]);
13026 tmp_face_index_element.push_back(
13027 edge_element_face[iproc][jproc][iiedge][0]);
13028 tmp_face_index_element.push_back(
13029 edge_element_face[iproc][jproc][iiedge][1]);
13039 if (node_added_to_the_left && !connection_to_the_left)
13042 bound_id_connection_to_the_left =
13043 check_connections_of_polyline_nodes(
13044 element_in_processor_pt,
13045 root_edge_bound_id,
13047 node_on_bnd_not_overlapped_by_shd_bnd,
13049 shared_bnd_id_to_sorted_list_node_pt,
13051 new_added_node_pt);
13058 if (bound_id_connection_to_the_left != -1)
13060 connection_to_the_left =
true;
13070 if (node_added_to_the_right && !connection_to_the_right)
13073 bound_id_connection_to_the_right =
13074 check_connections_of_polyline_nodes(
13075 element_in_processor_pt,
13076 root_edge_bound_id,
13078 node_on_bnd_not_overlapped_by_shd_bnd,
13080 shared_bnd_id_to_sorted_list_node_pt,
13082 new_added_node_pt);
13089 if (bound_id_connection_to_the_right != -1)
13091 connection_to_the_right =
true;
13099 if (connection_to_the_left && connection_to_the_right)
13101 current_polyline_has_connections_at_both_ends =
true;
13125 const unsigned n_bnd_ele = tmp_boundary_element_pt.size();
13131 unsigned help_counter = 0;
13133 for (std::list<FiniteElement*>::iterator it_bnd_ele =
13134 tmp_boundary_element_pt.begin();
13135 it_bnd_ele != tmp_boundary_element_pt.end();
13138 tmp_bnd_ele_pt[help_counter++] = (*it_bnd_ele);
13143 for (std::list<int>::iterator it_face_idx =
13144 tmp_face_index_element.begin();
13145 it_face_idx != tmp_face_index_element.end();
13148 tmp_face_idx_ele[help_counter++] = (*it_face_idx);
13161 Vector<int> final_bound_id_connection_to_the_left;
13164 Vector<int> final_bound_id_connection_to_the_right;
13167 break_loops_on_shared_polyline_helper(
13168 shared_boundary_id_start,
13172 bound_id_connection_to_the_left,
13173 bound_id_connection_to_the_right,
13174 final_sorted_nodes_pt,
13175 final_boundary_element_pt,
13176 final_face_index_element,
13177 final_bound_id_connection_to_the_left,
13178 final_bound_id_connection_to_the_right);
13181 const unsigned n_final_sorted_nodes = final_sorted_nodes_pt.size();
13184 for (
unsigned i = 0;
i < n_final_sorted_nodes;
i++)
13189 shared_bnd_id_to_sorted_list_node_pt[shared_boundary_id_start] =
13190 final_sorted_nodes_pt[
i];
13194 create_shared_polyline(my_rank,
13195 shared_boundary_id_start,
13198 final_sorted_nodes_pt[
i],
13199 root_edge_bound_id,
13200 final_boundary_element_pt[
i],
13201 final_face_index_element[
i],
13202 unsorted_polylines_pt,
13203 final_bound_id_connection_to_the_left[
i],
13204 final_bound_id_connection_to_the_right[
i]);
13208 npolylines_counter++;
13212 shared_boundary_id_start++;
13225 if (unsorted_polylines_pt[iproc].size() > 0)
13229 sort_polylines_helper(unsorted_polylines_pt[iproc],
13230 output_polylines_pt[iproc]);
13234 const unsigned nunsorted_polylines_iproc =
13235 unsorted_polylines_pt[iproc].size();
13238 unsigned tmp_ntotal_polylines = 0;
13240 for (
unsigned ii = 0; ii < output_polylines_pt[iproc].size(); ii++)
13242 tmp_ntotal_polylines += output_polylines_pt[iproc][ii].size();
13244 if (tmp_ntotal_polylines != nunsorted_polylines_iproc)
13246 std::ostringstream error_message;
13247 error_message <<
" The total number of unsorted polylines ("
13248 << nunsorted_polylines_iproc
13249 <<
") in common with\nprocessor (" << iproc
13250 <<
") is different from the total number of sorted "
13251 <<
"polylines (" << tmp_ntotal_polylines
13252 <<
") with\nthe same "
13255 OOMPH_CURRENT_FUNCTION,
13256 OOMPH_EXCEPTION_LOCATION);
13263 this->Final_shared_boundary_id = shared_boundary_id_start;
13270 template<
class ELEMENT>
13272 const unsigned& initial_shd_bnd_id,
13273 std::list<Node*>& input_nodes,
13276 const int& input_connect_to_the_left,
13277 const int& input_connect_to_the_right,
13278 Vector<std::list<Node*>>& output_sorted_nodes_pt,
13285 Node* left_node_pt = input_nodes.front();
13286 Node* right_node_pt = input_nodes.back();
13295 std::list<Node*>::iterator it = input_nodes.begin();
13298 unsigned counter = 0;
13301 while (it != input_nodes.end())
13306 if (it == input_nodes.end())
13318 std::list<Node*> sub_nodes;
13327 sub_nodes.push_back(*it);
13337 sub_nodes.push_back((*it));
13340 sub_bnd_ele_pt.push_back(input_boundary_element_pt[counter]);
13341 sub_bnd_ele_pt.push_back(input_boundary_element_pt[counter + 1]);
13344 sub_face_idx_ele.push_back(input_face_index_element[counter]);
13345 sub_face_idx_ele.push_back(input_face_index_element[counter + 1]);
13352 }
while ((*it) != left_node_pt && (*it) != right_node_pt &&
13353 it != input_nodes.end());
13356 tmp_sub_nodes.push_back(sub_nodes);
13358 tmp_sub_bnd_ele_pt.push_back(sub_bnd_ele_pt);
13360 tmp_sub_face_idx_ele.push_back(sub_face_idx_ele);
13368 const unsigned n_sub_list = tmp_sub_nodes.size();
13371 if (n_sub_list > 3)
13373 std::stringstream error_message;
13375 <<
"The number of sub-list of nodes created from the shared\n"
13376 <<
"polyline with loops was (" << n_sub_list <<
").\n"
13377 <<
"We can only handle up to three sub-list of nodes\n";
13379 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
13385 if (n_sub_list == 1 && (left_node_pt != right_node_pt))
13393 output_sorted_nodes_pt = tmp_sub_nodes;
13395 output_boundary_element_pt = tmp_sub_bnd_ele_pt;
13397 output_face_index_element = tmp_sub_face_idx_ele;
13403 if (input_connect_to_the_left == -2)
13405 std::stringstream error_message;
13407 <<
"The connection flag to the left (" << input_connect_to_the_left
13408 <<
") indicates a connection\n"
13409 <<
"with the same polyline.\n However, only one sub-polyline was "
13410 <<
"found and no loop\nwas identified\n\n";
13412 OOMPH_CURRENT_FUNCTION,
13413 OOMPH_EXCEPTION_LOCATION);
13418 if (input_connect_to_the_left == -3)
13420 output_connect_to_the_left.push_back(-1);
13424 output_connect_to_the_left.push_back(input_connect_to_the_left);
13428 if (input_connect_to_the_right == -2)
13430 std::stringstream error_message;
13432 <<
"The connection flag to the right (" << input_connect_to_the_right
13433 <<
") indicates a connection\n"
13434 <<
"with the same polyline.\n However, only one sub-polyline was "
13435 <<
"found and no loop\nwas identified\n\n";
13437 error_message.str(),
13438 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13439 OOMPH_EXCEPTION_LOCATION);
13444 if (input_connect_to_the_right == -3)
13446 output_connect_to_the_right.push_back(-1);
13450 output_connect_to_the_right.push_back(input_connect_to_the_right);
13458 unsigned tmp_shd_bnd_id = initial_shd_bnd_id;
13466 Node* left_sub_node_pt = tmp_sub_nodes[0].front();
13467 Node* right_sub_node_pt = tmp_sub_nodes[0].back();
13470 if (left_sub_node_pt == right_sub_node_pt)
13476 std::list<Node*> first_half_node_pt;
13477 std::list<Node*> second_half_node_pt;
13486 const unsigned n_sub_nodes = tmp_sub_nodes[0].size();
13490 const unsigned n_sub_nodes_half =
13491 static_cast<unsigned>(n_sub_nodes / 2.0);
13496 std::list<Node*>::iterator it_sub = tmp_sub_nodes[0].begin();
13499 first_half_node_pt.push_back(*it_sub);
13505 unsigned counter_nodes = 0;
13506 unsigned counter2 = 0;
13509 for (; it_sub != tmp_sub_nodes[0].end(); it_sub++)
13512 first_half_node_pt.push_back(*it_sub);
13515 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
13516 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2 + 1]);
13518 first_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
13519 first_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2 + 1]);
13527 if (counter_nodes == n_sub_nodes_half)
13538 second_half_node_pt.push_back(*it_sub);
13544 for (; it_sub != tmp_sub_nodes[0].end(); it_sub++)
13547 second_half_node_pt.push_back(*it_sub);
13550 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
13551 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2 + 1]);
13553 second_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
13554 second_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2 + 1]);
13562 output_sorted_nodes_pt.push_back(first_half_node_pt);
13563 output_sorted_nodes_pt.push_back(second_half_node_pt);
13566 output_boundary_element_pt.push_back(first_half_ele_pt);
13567 output_boundary_element_pt.push_back(second_half_ele_pt);
13570 output_face_index_element.push_back(first_half_face_idx);
13571 output_face_index_element.push_back(second_half_face_idx);
13582 if (input_connect_to_the_left == -3)
13585 output_connect_to_the_left.push_back(-1);
13588 else if (input_connect_to_the_left == -2)
13591 output_connect_to_the_left.push_back(-1);
13596 output_connect_to_the_left.push_back(input_connect_to_the_left);
13602 output_connect_to_the_right.push_back(-1);
13613 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
13619 if (n_sub_list == 1)
13621 if (input_connect_to_the_right == -3)
13624 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13626 else if (input_connect_to_the_right == -2)
13629 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13631 else if (input_connect_to_the_right == -1)
13634 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13639 output_connect_to_the_right.push_back(input_connect_to_the_right);
13645 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13658 output_sorted_nodes_pt.push_back(tmp_sub_nodes[0]);
13661 output_boundary_element_pt.push_back(tmp_sub_bnd_ele_pt[0]);
13664 output_face_index_element.push_back(tmp_sub_face_idx_ele[0]);
13672 if (input_connect_to_the_left == -3)
13675 output_connect_to_the_left.push_back(-1);
13678 else if (input_connect_to_the_left == -2)
13681 output_connect_to_the_left.push_back(tmp_shd_bnd_id + 1);
13686 output_connect_to_the_left.push_back(input_connect_to_the_left);
13692 output_connect_to_the_right.push_back(tmp_shd_bnd_id + 1);
13700 if (n_sub_list > 1)
13704 left_sub_node_pt = tmp_sub_nodes[1].front();
13705 right_sub_node_pt = tmp_sub_nodes[1].back();
13708 if (left_sub_node_pt == right_sub_node_pt)
13714 std::list<Node*> first_half_node_pt;
13715 std::list<Node*> second_half_node_pt;
13724 const unsigned n_sub_nodes = tmp_sub_nodes[1].size();
13728 const unsigned n_sub_nodes_half =
13729 static_cast<unsigned>(n_sub_nodes / 2.0);
13734 std::list<Node*>::iterator it_sub = tmp_sub_nodes[1].begin();
13737 first_half_node_pt.push_back(*it_sub);
13743 unsigned counter_nodes = 0;
13744 unsigned counter2 = 0;
13747 for (; it_sub != tmp_sub_nodes[1].end(); it_sub++)
13750 first_half_node_pt.push_back(*it_sub);
13752 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2]);
13753 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2 + 1]);
13755 first_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2]);
13756 first_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2 + 1]);
13764 if (counter_nodes == n_sub_nodes_half)
13775 second_half_node_pt.push_back(*it_sub);
13781 for (; it_sub != tmp_sub_nodes[1].end(); it_sub++)
13784 second_half_node_pt.push_back(*it_sub);
13786 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2]);
13787 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2 + 1]);
13789 second_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2]);
13790 second_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2 + 1]);
13798 output_sorted_nodes_pt.push_back(first_half_node_pt);
13799 output_sorted_nodes_pt.push_back(second_half_node_pt);
13802 output_boundary_element_pt.push_back(first_half_ele_pt);
13803 output_boundary_element_pt.push_back(second_half_ele_pt);
13806 output_face_index_element.push_back(first_half_face_idx);
13807 output_face_index_element.push_back(second_half_face_idx);
13818 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
13823 output_connect_to_the_right.push_back(-1);
13834 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
13840 if (n_sub_list == 2)
13843 if (input_connect_to_the_right == -1)
13846 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13849 else if (input_connect_to_the_right == -2)
13852 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13855 else if (input_connect_to_the_right == -3)
13858 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13863 output_connect_to_the_right.push_back(input_connect_to_the_right);
13873 std::stringstream error_message;
13875 <<
"The second sub-list of nodes creates a loop but this is not\n"
13876 <<
"the last list of sub-nodes.\n"
13877 <<
"This configuration is not supported\n";
13879 error_message.str(),
13880 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13881 OOMPH_EXCEPTION_LOCATION);
13892 output_sorted_nodes_pt.push_back(tmp_sub_nodes[1]);
13895 output_boundary_element_pt.push_back(tmp_sub_bnd_ele_pt[1]);
13898 output_face_index_element.push_back(tmp_sub_face_idx_ele[1]);
13906 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
13912 if (n_sub_list == 2)
13915 if (input_connect_to_the_right == -3)
13918 output_connect_to_the_right.push_back(-1);
13922 else if (input_connect_to_the_right == -2)
13924 std::stringstream error_message;
13926 <<
"The connection flag to the right ("
13927 << input_connect_to_the_right <<
") indicates a connection\n"
13928 <<
"with the same polyline.\n However, the second sub-list of\n"
13929 <<
"nodes was found not making a loop so no connection with\n"
13930 <<
"itself should be marked\n\n";
13932 error_message.str(),
13933 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13934 OOMPH_EXCEPTION_LOCATION);
13940 output_connect_to_the_right.push_back(input_connect_to_the_right);
13946 output_connect_to_the_right.push_back(tmp_shd_bnd_id + 1);
13957 if (n_sub_list > 2)
13961 left_sub_node_pt = tmp_sub_nodes[2].front();
13962 right_sub_node_pt = tmp_sub_nodes[2].back();
13965 if (left_sub_node_pt == right_sub_node_pt)
13971 std::list<Node*> first_half_node_pt;
13972 std::list<Node*> second_half_node_pt;
13981 const unsigned n_sub_nodes = tmp_sub_nodes[2].size();
13985 const unsigned n_sub_nodes_half =
13986 static_cast<unsigned>(n_sub_nodes / 2.0);
13991 std::list<Node*>::iterator it_sub = tmp_sub_nodes[2].begin();
13994 first_half_node_pt.push_back(*it_sub);
14000 unsigned counter_nodes = 0;
14001 unsigned counter2 = 0;
14004 for (; it_sub != tmp_sub_nodes[2].end(); it_sub++)
14007 first_half_node_pt.push_back(*it_sub);
14009 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2]);
14010 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2 + 1]);
14012 first_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2]);
14013 first_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2 + 1]);
14021 if (counter_nodes == n_sub_nodes_half)
14032 second_half_node_pt.push_back(*it_sub);
14038 for (; it_sub != tmp_sub_nodes[2].end(); it_sub++)
14041 second_half_node_pt.push_back(*it_sub);
14043 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2]);
14044 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2 + 1]);
14046 second_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2]);
14047 second_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2 + 1]);
14055 output_sorted_nodes_pt.push_back(first_half_node_pt);
14056 output_sorted_nodes_pt.push_back(second_half_node_pt);
14059 output_boundary_element_pt.push_back(first_half_ele_pt);
14060 output_boundary_element_pt.push_back(second_half_ele_pt);
14063 output_face_index_element.push_back(first_half_face_idx);
14064 output_face_index_element.push_back(second_half_face_idx);
14072 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
14077 output_connect_to_the_right.push_back(-1);
14088 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
14092 if (input_connect_to_the_right == -3)
14095 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14097 else if (input_connect_to_the_right == -2)
14100 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14102 else if (input_connect_to_the_right == -1)
14105 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14110 output_connect_to_the_right.push_back(input_connect_to_the_right);
14123 output_sorted_nodes_pt.push_back(tmp_sub_nodes[2]);
14126 output_boundary_element_pt.push_back(tmp_sub_bnd_ele_pt[2]);
14129 output_face_index_element.push_back(tmp_sub_face_idx_ele[2]);
14137 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
14142 if (input_connect_to_the_right == -3)
14144 std::stringstream error_message;
14146 <<
"The connection flag to the right ("
14147 << input_connect_to_the_right <<
") indicates 'no connection and\n"
14148 <<
"stop adding nodes'.\n However, the thrid sub-list of\n"
14149 <<
"nodes must have a connection to the right with the same\n"
14150 <<
"shared polyline or with any other polyline\n\n";
14152 error_message.str(),
14153 "TriangleMesh::break_loops_on_shared_polyline_helper()",
14154 OOMPH_EXCEPTION_LOCATION);
14156 else if (input_connect_to_the_right == -1)
14158 std::stringstream error_message;
14160 <<
"The connection flag to the right ("
14161 << input_connect_to_the_right <<
") indicates 'no connection.\n"
14162 <<
"However, the thrid sub-list of nodes must have a connection\n"
14163 <<
"to the right with the same shared polyline or with any other\n"
14166 error_message.str(),
14167 "TriangleMesh::break_loops_on_shared_polyline_helper()",
14168 OOMPH_EXCEPTION_LOCATION);
14171 else if (input_connect_to_the_right == -2)
14174 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14179 output_connect_to_the_right.push_back(input_connect_to_the_right);
14194 template<
class ELEMENT>
14197 const unsigned& initial_shd_bnd_id,
14198 std::list<Node*>& input_nodes,
14202 const int& input_connect_to_the_left,
14203 const int& input_connect_to_the_right,
14204 Vector<std::list<Node*>>& output_sorted_nodes_pt,
14212 Node* left_node_pt = input_nodes.front();
14213 Node* right_node_pt = input_nodes.back();
14223 std::list<Node*>::iterator it = input_nodes.begin();
14226 unsigned counter = 0;
14229 while (it != input_nodes.end())
14234 if (it == input_nodes.end())
14246 std::list<Node*> sub_nodes;
14258 sub_nodes.push_back(*it);
14268 sub_nodes.push_back((*it));
14271 sub_bnd_ele_pt.push_back(input_boundary_element_pt[counter]);
14274 sub_bnd_face_ele_pt.push_back(input_boundary_face_element_pt[counter]);
14277 sub_face_idx_ele.push_back(input_face_index_element[counter]);
14284 }
while ((*it) != left_node_pt && (*it) != right_node_pt &&
14285 it != input_nodes.end());
14288 tmp_sub_nodes.push_back(sub_nodes);
14291 tmp_sub_bnd_ele_pt.push_back(sub_bnd_ele_pt);
14293 tmp_sub_bnd_face_ele_pt.push_back(sub_bnd_face_ele_pt);
14295 tmp_sub_face_idx_ele.push_back(sub_face_idx_ele);
14303 const unsigned n_sub_list = tmp_sub_nodes.size();
14306 if (n_sub_list > 1)
14308 std::stringstream error_message;
14310 <<
"The number of sub-list of nodes created from the shared\n"
14311 <<
"polyline with loops was (" << n_sub_list <<
").\n"
14312 <<
"We can only handle one list which may still contain loops\n"
14313 <<
"(or repeated nodes)\n";
14315 error_message.str(),
14316 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14317 OOMPH_EXCEPTION_LOCATION);
14323 if (n_sub_list == 1 && (left_node_pt != right_node_pt))
14331 output_sorted_nodes_pt = tmp_sub_nodes;
14333 output_boundary_element_pt = tmp_sub_bnd_ele_pt;
14335 output_boundary_face_element_pt = tmp_sub_bnd_face_ele_pt;
14337 output_face_index_element = tmp_sub_face_idx_ele;
14343 if (input_connect_to_the_left == -2)
14345 std::stringstream error_message;
14347 <<
"The connection flag to the left (" << input_connect_to_the_left
14348 <<
") indicates a connection\n"
14349 <<
"with the same polyline.\n However, only one sub-polyline was "
14350 <<
"found and no loops\nwere identified\n\n";
14352 error_message.str(),
14353 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14354 OOMPH_EXCEPTION_LOCATION);
14359 if (input_connect_to_the_left == -3)
14361 output_connect_to_the_left.push_back(-1);
14365 output_connect_to_the_left.push_back(input_connect_to_the_left);
14369 if (input_connect_to_the_right == -2)
14371 std::stringstream error_message;
14373 <<
"The connection flag to the right (" << input_connect_to_the_right
14374 <<
") indicates a connection\n"
14375 <<
"with the same polyline.\n However, only one sub-polyline was "
14376 <<
"found and no loops\nwere identified\n\n";
14378 error_message.str(),
14379 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14380 OOMPH_EXCEPTION_LOCATION);
14385 if (input_connect_to_the_right == -3)
14387 output_connect_to_the_right.push_back(-1);
14391 output_connect_to_the_right.push_back(input_connect_to_the_right);
14399 unsigned tmp_shd_bnd_id = initial_shd_bnd_id;
14407 Node* left_sub_node_pt = tmp_sub_nodes[0].front();
14408 Node* right_sub_node_pt = tmp_sub_nodes[0].back();
14411 if (left_sub_node_pt == right_sub_node_pt)
14417 std::list<Node*> first_half_node_pt;
14418 std::list<Node*> second_half_node_pt;
14430 const unsigned n_sub_nodes = tmp_sub_nodes[0].size();
14434 const unsigned n_sub_nodes_half =
14435 static_cast<unsigned>(n_sub_nodes / 2.0);
14440 std::list<Node*>::iterator it_sub = tmp_sub_nodes[0].begin();
14443 first_half_node_pt.push_back(*it_sub);
14449 unsigned counter_nodes = 0;
14450 unsigned counter2 = 0;
14453 for (; it_sub != tmp_sub_nodes[0].end(); it_sub++)
14456 first_half_node_pt.push_back(*it_sub);
14459 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
14461 first_half_ele_face_pt.push_back(tmp_sub_bnd_face_ele_pt[0][counter2]);
14463 first_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
14471 if (counter_nodes == n_sub_nodes_half)
14482 second_half_node_pt.push_back(*it_sub);
14488 for (; it_sub != tmp_sub_nodes[0].end(); it_sub++)
14491 second_half_node_pt.push_back(*it_sub);
14494 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
14496 second_half_ele_face_pt.push_back(tmp_sub_bnd_face_ele_pt[0][counter2]);
14498 second_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
14506 output_sorted_nodes_pt.push_back(first_half_node_pt);
14507 output_sorted_nodes_pt.push_back(second_half_node_pt);
14510 output_boundary_element_pt.push_back(first_half_ele_pt);
14511 output_boundary_element_pt.push_back(second_half_ele_pt);
14514 output_boundary_face_element_pt.push_back(first_half_ele_face_pt);
14515 output_boundary_face_element_pt.push_back(second_half_ele_face_pt);
14518 output_face_index_element.push_back(first_half_face_idx);
14519 output_face_index_element.push_back(second_half_face_idx);
14530 if (input_connect_to_the_left == -3)
14533 output_connect_to_the_left.push_back(-1);
14536 else if (input_connect_to_the_left == -2)
14539 output_connect_to_the_left.push_back(-1);
14544 output_connect_to_the_left.push_back(input_connect_to_the_left);
14550 output_connect_to_the_right.push_back(-1);
14561 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
14567 if (n_sub_list == 1)
14569 if (input_connect_to_the_right == -3)
14572 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14574 else if (input_connect_to_the_right == -2)
14577 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14579 else if (input_connect_to_the_right == -1)
14582 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14587 output_connect_to_the_right.push_back(input_connect_to_the_right);
14593 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14603 std::stringstream error_message;
14605 <<
"The initial and final node in the current shared polyline are not\n"
14606 <<
"the same and the number of sublists is (" << n_sub_list <<
").\n"
14607 <<
"We can not handle more than one sublist in the method to break\n"
14608 <<
"loops at the load balance stage\n\n";
14610 error_message.str(),
14611 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14612 OOMPH_EXCEPTION_LOCATION);
14622 template<
class ELEMENT>
14624 const unsigned& my_rank,
14625 const unsigned& shd_bnd_id,
14626 const unsigned& iproc,
14627 const unsigned& jproc,
14628 std::list<Node*>& sorted_nodes,
14629 const int& root_edge_bnd_id,
14633 const int& connect_to_the_left_flag,
14634 const int& connect_to_the_right_flag)
14645 Shared_boundaries_ids[iproc][jproc].push_back(shd_bnd_id);
14648 Shared_boundaries_ids[jproc][iproc].push_back(shd_bnd_id);
14653 processors[0] = iproc;
14654 processors[1] = jproc;
14655 Shared_boundary_from_processors[shd_bnd_id] = processors;
14661 if (iproc == my_rank || jproc == my_rank)
14668 const unsigned n_nodes = sorted_nodes.size();
14673 unsigned counter = 0;
14675 for (std::list<Node*>::iterator it = sorted_nodes.begin();
14676 it != sorted_nodes.end();
14679 vertices[counter].resize(2);
14680 vertices[counter][0] = (*it)->x(0);
14681 vertices[counter][1] = (*it)->x(1);
14697 if (root_edge_bnd_id != -1)
14701 Shared_boundary_overlaps_internal_boundary[shd_bnd_id] =
14702 static_cast<unsigned>(root_edge_bnd_id);
14710 const unsigned n_shared_boundary_elements = bulk_bnd_ele_pt.size();
14714 const unsigned n_face_index = face_index_ele.size();
14715 if (n_shared_boundary_elements != n_face_index)
14717 std::ostringstream error_message;
14719 <<
"The number of shared boundary elements is different from the\n"
14720 <<
"number of face indexes associated to the shared boundary\n"
14722 <<
"Number of shared boundary elements: ("
14723 << n_shared_boundary_elements <<
")\n"
14724 <<
"Number of face indexes: (" << n_face_index <<
")\n\n";
14726 "TriangleMesh::create_shared_polyline()",
14727 OOMPH_EXCEPTION_LOCATION);
14733 for (
unsigned i = 0;
i < n_shared_boundary_elements;
i++)
14735 add_shared_boundary_element(shd_bnd_id, bulk_bnd_ele_pt[
i]);
14736 add_face_index_at_shared_boundary(shd_bnd_id, face_index_ele[
i]);
14740 for (std::list<Node*>::iterator it = sorted_nodes.begin();
14741 it != sorted_nodes.end();
14744 add_shared_boundary_node(shd_bnd_id, (*it));
14752 this->Boundary_curve_section_pt[shd_bnd_id] = polyline_pt;
14757 const unsigned n_procs = unsorted_polylines_pt.size();
14762 unsorted_polylines_pt[iproc].push_back(polyline_pt);
14766 unsorted_polylines_pt[jproc].push_back(polyline_pt);
14772 unsorted_polylines_pt[0].push_back(polyline_pt);
14776 this->Free_curve_section_pt.insert(polyline_pt);
14786 if (connect_to_the_left_flag < 0)
14789 if (connect_to_the_left_flag != -1)
14791 std::ostringstream error_message;
14793 <<
"The only accepted values for the connection flags are:\n"
14794 <<
"POSITIVE values or -1, any other value is rejected, please\n"
14795 <<
"check that you previously called the methods to deal with\n"
14796 <<
"other flag values\n"
14797 <<
"The current flag value for connection to the left is: ("
14798 << connect_to_the_left_flag <<
")\n\n";
14800 "TriangleMesh::create_shared_polyline()",
14801 OOMPH_EXCEPTION_LOCATION);
14806 if (connect_to_the_right_flag < 0)
14809 if (connect_to_the_right_flag != -1)
14811 std::ostringstream error_message;
14813 <<
"The only accepted values for the connection flags are:\n"
14814 <<
"POSITIVE values or -1, any other value is rejected, please\n"
14815 <<
"check that you previously called the methods to deal with\n"
14816 <<
"other flag values\n"
14817 <<
"The current flag value for connection to the right is: ("
14818 << connect_to_the_right_flag <<
")\n\n";
14820 "TriangleMesh::create_shared_polyline()",
14821 OOMPH_EXCEPTION_LOCATION);
14827 if (connect_to_the_left_flag != -1)
14830 const unsigned bnd_id_connection_to_the_left =
14831 static_cast<unsigned>(connect_to_the_left_flag);
14836 bnd_id_connection_to_the_left;
14843 if (connect_to_the_right_flag != -1)
14846 const unsigned bnd_id_connection_to_the_right =
14847 static_cast<unsigned>(connect_to_the_right_flag);
14852 bnd_id_connection_to_the_right;
14865 template<
class ELEMENT>
14872 const unsigned nbound = this->nboundary();
14875 const unsigned n_regions = this->nregion();
14878 for (
unsigned b = 0; b < nbound; b++)
14883 const unsigned nbound_ele = this->nboundary_element(b);
14886 Vector<int> backed_up_face_index_at_boundary(nbound_ele);
14887 for (
unsigned e = 0;
e < nbound_ele;
e++)
14890 backed_up_boundary_element_pt[
e] = this->boundary_element_pt(b,
e);
14892 backed_up_face_index_at_boundary[
e] =
14893 this->face_index_at_boundary(b,
e);
14903 for (
unsigned ir = 0; ir < n_regions; ir++)
14906 const unsigned region_id =
14907 static_cast<unsigned>(this->region_attribute(ir));
14909 const unsigned nbnd_region_ele =
14910 this->nboundary_element_in_region(b, region_id);
14913 for (
unsigned e = 0;
e < nbnd_region_ele;
e++)
14916 backed_up_boundary_region_element_pt[ir][
e] =
14917 this->boundary_element_in_region_pt(b, region_id,
e);
14920 backed_up_face_index_at_boundary_region[ir][
e] =
14921 this->face_index_at_boundary_in_region(b, region_id,
e);
14927 this->Boundary_element_pt[b].clear();
14928 this->Face_index_at_boundary[b].clear();
14931 this->Boundary_region_element_pt[b].clear();
14932 this->Face_index_region_at_boundary[b].clear();
14941 const unsigned nold_bnd_ele = ntmp_boundary_elements[b];
14943 for (
unsigned e = 0;
e < nold_bnd_ele;
e++)
14948 deleted_elements.begin(), deleted_elements.end(), tmp_ele_pt);
14951 if (it == deleted_elements.end())
14954 this->Boundary_element_pt[b].push_back(add_ele_pt);
14955 const int face_index = backed_up_face_index_at_boundary[
e];
14956 this->Face_index_at_boundary[b].push_back(face_index);
14964 for (
unsigned ir = 0; ir < n_regions; ir++)
14967 const unsigned region_id =
14968 static_cast<unsigned>(this->region_attribute(ir));
14971 const unsigned nold_bnd_region_ele =
14972 ntmp_boundary_elements_in_region[b][ir];
14976 for (
unsigned e = 0;
e < nold_bnd_region_ele;
e++)
14980 backed_up_boundary_region_element_pt[ir][
e];
14983 deleted_elements.begin(), deleted_elements.end(), tmp_ele_pt);
14986 if (it == deleted_elements.end())
14989 backed_up_boundary_region_element_pt[ir][
e];
14990 this->Boundary_region_element_pt[b][region_id].push_back(
14992 const int face_index =
14993 backed_up_face_index_at_boundary_region[ir][
e];
14994 this->Face_index_region_at_boundary[b][region_id].push_back(
15007 for (
unsigned e = nold_bnd_ele;
e < nbound_ele;
e++)
15010 this->Boundary_element_pt[b].push_back(add_ele_pt);
15011 const int face_index = backed_up_face_index_at_boundary[
e];
15012 this->Face_index_at_boundary[b].push_back(face_index);
15018 for (
unsigned ir = 0; ir < n_regions; ir++)
15021 const unsigned region_id =
15022 static_cast<unsigned>(this->region_attribute(ir));
15025 const unsigned nold_bnd_region_ele =
15026 ntmp_boundary_elements_in_region[b][ir];
15029 const unsigned nbnd_region_ele =
15030 this->nboundary_element_in_region(b, region_id);
15034 for (
unsigned e = nold_bnd_region_ele;
e < nbnd_region_ele;
e++)
15037 backed_up_boundary_region_element_pt[ir][
e];
15038 this->Boundary_region_element_pt[b][region_id].push_back(add_ele_pt);
15039 const int face_index = backed_up_face_index_at_boundary_region[ir][
e];
15040 this->Face_index_region_at_boundary[b][region_id].push_back(
15049 Lookup_for_elements_next_boundary_is_setup =
true;
15054 #ifdef OOMPH_HAS_TRIANGLE_LIB
15059 template<
class ELEMENT>
15078 (
double*)malloc(triangulate_io.
numberofpoints * 2 *
sizeof(
double));
15091 for (
unsigned count_point = 0; count_point < n_points * 2; count_point++)
15093 triangle_refine.
pointlist[count_point] =
15098 if (count_point % 2 == 0)
15100 x_coord[count_point / 2] = triangulate_io.
pointlist[count_point];
15104 y_coord[(count_point - 1) / 2] = triangulate_io.
pointlist[count_point];
15109 for (
unsigned count_marker = 0; count_marker < n_points; count_marker++)
15116 for (
unsigned count_seg = 0; count_seg < n_segments * 2; count_seg++)
15123 for (
unsigned count_markers = 0; count_markers < n_segments;
15135 (
double*)malloc(triangulate_io.
numberofholes * 2 *
sizeof(
double));
15138 for (
unsigned count_hole = 0; count_hole < n_holes * 2; count_hole++)
15140 triangle_refine.
holelist[count_hole] =
15141 triangulate_io.
holelist[count_hole];
15149 if (n_triangles != target_area.size())
15151 std::stringstream err;
15152 err <<
"Number of triangles in triangulate_io=" << n_triangles
15153 <<
" doesn't match\n"
15154 <<
"size of target area vector (" << target_area.size() <<
")\n";
15156 err.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
15167 for (
unsigned count_tri = 0; count_tri < n_triangles * 3; count_tri++)
15176 for (
unsigned count_area = 0; count_area < n_triangles; count_area++)
15188 for (
unsigned count_attribute = 0;
15198 #ifdef OOMPH_HAS_MPI
15212 const std::pair<double, double>& rhs)
const
15214 double diff_y = lhs.second - rhs.second;
15225 double diff_x = lhs.first - rhs.first;
15226 if (fabs(diff_x) <
Tol)
15228 std::ostringstream warning_message;
15230 <<
"Dodgy \"lower left\" (lexicographic) comparison "
15231 <<
"of points with cooordinates: "
15232 <<
" lhs = ( " << lhs.first <<
" , " << lhs.second <<
" ) \n"
15233 <<
" rhs = ( " << rhs.first <<
" , " << rhs.second <<
" ) \n"
15234 <<
"x and y coordinates differ by less than tolerance!\n"
15235 <<
"diff_x = " << diff_x <<
"\n"
15236 <<
"diff_y = " << diff_y <<
"\n"
15237 <<
"Tol = " <<
Tol <<
"\n";
15239 OOMPH_CURRENT_FUNCTION,
15240 OOMPH_EXCEPTION_LOCATION);
15243 if (lhs.first < rhs.first)
15297 template<
class ELEMENT>
15302 this->shared_boundaries_in_this_processor(my_rank_shared_boundaries_ids);
15305 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
15308 for (
unsigned i = 0;
i < nmy_rank_shd_bnd;
i++)
15313 std::map<std::pair<double, double>,
Node*,
classcomp> sorted_nodes_pt;
15320 double min_distance_squared = DBL_MAX;
15325 const unsigned b = my_rank_shared_boundaries_ids[
i];
15328 const unsigned nbnd_node = this->nshared_boundary_node(b);
15332 for (
unsigned i_node = 0; i_node < nbnd_node; i_node++)
15334 Node* node_pt = this->shared_boundary_node_pt(b, i_node);
15335 std::pair<double, double> vertex =
15336 std::make_pair(node_pt->
x(0), node_pt->
x(1));
15337 sorted_nodes_pt[vertex] = node_pt;
15343 for (
unsigned j_node = 0; j_node < nbnd_node; j_node++)
15345 if (i_node != j_node)
15347 Node* node2_pt = this->shared_boundary_node_pt(b, j_node);
15350 double squared_distance = 0.0;
15351 for (
unsigned ii = 0; ii < 2; ii++)
15353 squared_distance += (node_pt->
x(ii) - node2_pt->
x(ii)) *
15354 (node_pt->
x(ii) - node2_pt->
x(ii));
15356 if (squared_distance < min_distance_squared)
15358 min_distance_squared = squared_distance;
15365 std::ostringstream warning_message;
15366 warning_message <<
"Minimum distance between nodes on boundary " << b
15368 <<
"is " << sqrt(min_distance_squared)
15369 <<
" which is less than "
15370 <<
"Bottom_left_sorter.Tol = "
15372 <<
"This may screw up the ordering of the nodes on "
15373 "shared boundaries\n";
15375 OOMPH_CURRENT_FUNCTION,
15376 OOMPH_EXCEPTION_LOCATION);
15382 unsigned counter = 0;
15384 this->Sorted_shared_boundary_node_pt[b].resize(nbnd_node);
15390 for (std::map<std::pair<double, double>,
Node*>::iterator it_map =
15391 sorted_nodes_pt.begin();
15392 it_map != sorted_nodes_pt.end();
15396 this->Sorted_shared_boundary_node_pt[b][counter++] = (*it_map).second;
15407 template<
class ELEMENT>
15410 const bool update_elements,
15411 const bool flush_nodes,
15412 const bool update_nodes)
15415 const unsigned my_rank = this->communicator_pt()->my_rank();
15421 const unsigned initial_id = this->initial_shared_boundary_id();
15424 const unsigned final_id = this->final_shared_boundary_id();
15426 if (flush_elements)
15429 this->flush_shared_boundary_element();
15431 this->flush_face_index_at_shared_boundary();
15437 this->flush_shared_boundary_node();
15440 for (
unsigned b = initial_id; b < final_id; b++)
15444 procs_from_shrd_bnd = this->shared_boundary_from_processors(b);
15445 bool current_processor_has_b_boundary =
false;
15446 const unsigned n_procs_from_shrd_bnd = procs_from_shrd_bnd.size();
15447 for (
unsigned p = 0; p < n_procs_from_shrd_bnd; p++)
15449 if (procs_from_shrd_bnd[p] == my_rank)
15451 current_processor_has_b_boundary =
true;
15456 if (current_processor_has_b_boundary)
15458 if (update_elements)
15460 const unsigned nboundary_ele = this->nboundary_element(b);
15461 for (
unsigned e = 0;
e < nboundary_ele;
e++)
15466 this->add_shared_boundary_element(b, bnd_ele_pt);
15468 int face_index = this->face_index_at_boundary(b,
e);
15469 this->add_face_index_at_shared_boundary(b, face_index);
15475 const unsigned nboundary_node = this->nboundary_node(b);
15476 for (
unsigned n = 0; n < nboundary_node; n++)
15478 Node* bnd_node_pt = this->boundary_node_pt(b, n);
15479 this->add_shared_boundary_node(b, bnd_node_pt);
15491 template<
class ELEMENT>
15495 unsigned nproc = this->communicator_pt()->nproc();
15497 unsigned my_rank = this->communicator_pt()->my_rank();
15500 double tt_start = 0.0;
15501 double tt_end = 0.0;
15515 other_proc_shd_bnd_node_pt(nproc);
15517 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15520 other_proc_shd_bnd_node_pt[iproc].resize(nproc);
15521 for (
unsigned jproc = 0; jproc < nproc; jproc++)
15524 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
15525 const unsigned final_shd_bnd_id = this->final_shared_boundary_id();
15526 const unsigned nshared_bound = final_shd_bnd_id - initial_shd_bnd_id;
15527 other_proc_shd_bnd_node_pt[iproc][jproc].resize(nshared_bound);
15540 std::map<Vector<unsigned>,
unsigned> node_name_to_global_index;
15552 compute_global_node_names_and_shared_nodes(other_proc_shd_bnd_node_pt,
15554 node_name_to_global_index,
15555 global_shared_node_pt);
15558 const unsigned n_ele = this->nelement();
15560 if (Print_timings_level_adaptation > 1)
15564 double t_final_global_node_names_and_shared_nodes =
15566 oomph_info <<
"CPU for computing global node names and shared nodes "
15567 <<
"[n_ele=" << n_ele
15568 <<
"]: " << t_final_global_node_names_and_shared_nodes
15586 double t_start_send_info_shd_nodes_on_original_bnds =
15591 send_boundary_node_info_of_shared_nodes(
15592 global_node_names, node_name_to_global_index, global_shared_node_pt);
15594 if (Print_timings_level_adaptation > 1)
15599 <<
"CPU for sending info. of shared nodes on original boundaries: "
15628 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15630 const unsigned n_shd_bnd_iproc = this->nshared_boundaries(my_rank, iproc);
15631 ele_with_node_on_shd_bnd_pt[iproc].resize(n_shd_bnd_iproc);
15638 for (
unsigned e = 0;
e < n_ele;
e++)
15643 const unsigned n_nodes = ele_pt->
nnode();
15646 for (
unsigned n = 0; n < n_nodes; n++)
15655 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15660 const unsigned n_shd_bnd_iproc =
15661 this->nshared_boundaries(my_rank, iproc);
15664 if (iproc != my_rank && n_shd_bnd_iproc > 0)
15669 this->shared_boundaries_ids(my_rank, iproc);
15672 for (
unsigned isb = 0; isb < n_shd_bnd_iproc; isb++)
15674 const unsigned shd_bnd_id = shd_bnd_ids[isb];
15675 const unsigned n_ele_shd_bnd =
15676 this->nshared_boundary_element(shd_bnd_id);
15680 if (n_ele_shd_bnd > 0 &&
15681 this->is_node_on_shared_boundary(shd_bnd_id, node_pt))
15685 ele_with_node_on_shd_bnd_pt[iproc][isb].push_back(ele_pt);
15728 double t_start_regenerate_halo_ed_elements_nodes_first_stage =
15732 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15735 if (iproc != my_rank)
15738 const unsigned nshared_boundaries_with_iproc =
15739 this->nshared_boundaries(my_rank, iproc);
15741 if (nshared_boundaries_with_iproc > 0)
15755 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15761 bound_shared_with_iproc = this->shared_boundaries_ids(my_rank, iproc);
15764 for (
unsigned bs = 0; bs < nshared_boundaries_with_iproc; bs++)
15766 const unsigned bnd_id = bound_shared_with_iproc[bs];
15768 const unsigned nel_bnd = this->nshared_boundary_element(bnd_id);
15779 std::map<FiniteElement*, bool> already_added;
15782 for (
unsigned e = 0;
e < nel_bnd;
e++)
15786 this->shared_boundary_element_pt(bnd_id,
e);
15791 if (!already_added[ele_pt])
15794 haloed_element.push_back(ele_pt);
15796 already_added[ele_pt] =
true;
15807 const unsigned n_ele_with_node_on_shd_bnd =
15808 ele_with_node_on_shd_bnd_pt[iproc][bs].size();
15811 for (
unsigned iele = 0; iele < n_ele_with_node_on_shd_bnd; iele++)
15815 ele_with_node_on_shd_bnd_pt[iproc][bs][iele];
15817 if (!already_added[ele_pt])
15820 haloed_element.push_back(ele_pt);
15822 already_added[ele_pt] =
true;
15830 const unsigned nhaloed_ele = haloed_element.size();
15838 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15839 std::stringstream junk;
15840 junk <<
"Number of haloed elements " << nhaloed_ele;
15845 for (
unsigned e = 0;
e < nhaloed_ele;
e++)
15849 const unsigned nroot_haloed_ele =
15850 this->nroot_haloed_element(iproc);
15855 const unsigned haloed_ele_index =
15856 this->try_to_add_root_haloed_element_pt(iproc, gen_ele_pt);
15860 if (nroot_haloed_ele == haloed_ele_index)
15863 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15865 "Haloed element needs to be constructed");
15869 get_required_elemental_information_helper(iproc, ele_pt);
15872 const unsigned nnodes = ele_pt->
nnode();
15873 for (
unsigned j = 0; j < nnodes; j++)
15879 add_haloed_node_helper(iproc, node_pt);
15886 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15888 "Haloed element already exists");
15891 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15893 "Index of existing haloed element");
15907 int send_proc =
static_cast<int>(iproc);
15909 int recv_proc =
static_cast<int>(iproc);
15910 send_and_receive_elements_nodes_info(send_proc, recv_proc);
15923 for (
unsigned bs = 0; bs < nshared_boundaries_with_iproc; bs++)
15926 const unsigned nhaloed_ele =
15929 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15932 <<
" Number of elements need to be constructed "
15938 for (
unsigned e = 0;
e < nhaloed_ele;
e++)
15942 create_halo_element(iproc,
15943 iproc_currently_created_nodes_pt[iproc],
15944 other_proc_shd_bnd_node_pt,
15946 node_name_to_global_index,
15947 global_shared_node_pt);
15959 if (Print_timings_level_adaptation > 1)
15962 double t_final_regenerate_halo_ed_elements_nodes_first_stage =
15964 t_start_regenerate_halo_ed_elements_nodes_first_stage;
15966 oomph_info <<
"CPU for re-generating halo(ed) elements/nodes "
15967 <<
"(first stage) [n_ele=" << n_ele <<
"]: "
15968 << t_final_regenerate_halo_ed_elements_nodes_first_stage
15985 double t_start_regenerate_halo_ed_elements_nodes_second_stage =
15990 reset_halo_haloed_scheme_helper(other_proc_shd_bnd_node_pt,
15991 iproc_currently_created_nodes_pt,
15993 node_name_to_global_index,
15994 global_shared_node_pt);
15996 if (Print_timings_level_adaptation > 1)
15999 double t_final_regenerate_halo_ed_elements_nodes_second_stage =
16001 t_start_regenerate_halo_ed_elements_nodes_second_stage;
16003 oomph_info <<
"CPU for re-generating halo(ed) elements/nodes "
16004 <<
"(second stage) [n_ele=" << n_ele <<
"]: "
16005 << t_final_regenerate_halo_ed_elements_nodes_second_stage
16017 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
16023 if (Print_timings_level_adaptation > 1)
16026 oomph_info <<
"CPU for resetting halo-haloed scheme (without "
16027 "classification of halo and haloed nodes): "
16028 << tt_end - tt_start << std::endl;
16034 const bool report_stats =
true;
16039 this->classify_halo_and_haloed_nodes(tmp_doc_info, report_stats);
16043 if (Print_timings_level_adaptation > 1)
16046 oomph_info <<
"CPU for resetting halo-haloed scheme (with classification "
16047 "of halo and haloed nodes): "
16048 << tt_end - tt_start << std::endl;
16065 template<
class ELEMENT>
16069 other_proc_shd_bnd_node_pt,
16075 const unsigned nproc = this->communicator_pt()->nproc();
16077 const unsigned my_rank = this->communicator_pt()->my_rank();
16089 unsigned counter_nodes = 0;
16091 std::map<Node*, bool> done_node;
16093 std::map<Node*, unsigned> local_node_number;
16114 for (
unsigned iproc = 0; iproc < nproc; iproc++)
16117 if (iproc != my_rank)
16120 const unsigned n_shd_bnds_with_iproc =
16121 this->nshared_boundaries(my_rank, iproc);
16125 this->shared_boundaries_ids(my_rank, iproc);
16128 for (
unsigned ishd = 0; ishd < n_shd_bnds_with_iproc; ishd++)
16131 std::map<Node*, bool> done_node_shd_bnd;
16133 unsigned shd_bnd_id = bnd_shd_with_iproc[ishd];
16135 const unsigned n_shd_bnd_ele =
16136 this->nshared_boundary_element(shd_bnd_id);
16139 for (
unsigned e = 0;
e < n_shd_bnd_ele;
e++)
16143 this->shared_boundary_element_pt(shd_bnd_id,
e);
16146 const unsigned n_nodes = ele_pt->
nnode();
16149 for (
unsigned n = 0; n < n_nodes; n++)
16157 if (!done_node_shd_bnd[node_pt] &&
16158 this->is_node_on_shared_boundary(shd_bnd_id, node_pt))
16161 done_node_shd_bnd[node_pt] =
true;
16166 const unsigned n_nodes_shd_bnd =
16167 nsorted_shared_boundary_node(shd_bnd_id);
16170 unsigned index = 0;
16174 bool found_node_on_shared_boundary =
false;
16178 for (
unsigned k = 0; k < n_nodes_shd_bnd; k++)
16181 Node* shd_bnd_node_pt =
16182 sorted_shared_boundary_node_pt(shd_bnd_id, k);
16185 if (shd_bnd_node_pt == node_pt)
16191 found_node_on_shared_boundary =
true;
16200 if (!found_node_on_shared_boundary)
16202 std::ostringstream error_message;
16203 error_message <<
"The index of the node on boundary ("
16204 << shd_bnd_id <<
") was not found.\n"
16205 <<
"These are the node coordinates\n"
16206 <<
"(" << node_pt->
x(0) <<
"," << node_pt->
x(1)
16209 OOMPH_CURRENT_FUNCTION,
16210 OOMPH_EXCEPTION_LOCATION);
16216 node_name[0] = my_rank;
16217 node_name[1] = iproc;
16218 node_name[2] = shd_bnd_id;
16219 node_name[3] = index;
16224 if (!done_node[node_pt])
16229 local_node_pt.push_back(node_pt);
16232 local_node_number[node_pt] = counter_nodes;
16234 node_name[4] = counter_nodes;
16238 done_node[node_pt] =
true;
16243 first_node_name[0] = node_name;
16244 local_node_names.push_back(first_node_name);
16251 unsigned node_number = local_node_number[node_pt];
16254 node_name[4] = node_number;
16258 local_node_names[node_number].push_back(node_name);
16283 unsigned n_total_local_names = 0;
16285 const unsigned n_local_nodes = local_node_names.size();
16288 for (
unsigned i = 0;
i < n_local_nodes;
i++)
16291 const unsigned n_inode_names = local_node_names[
i].size();
16293 n_total_local_names += n_inode_names;
16298 const unsigned n_info_per_node_name = 5;
16301 n_info_per_node_name);
16303 unsigned counter = 0;
16305 for (
unsigned i = 0;
i < n_local_nodes;
i++)
16308 const unsigned n_inode_names = local_node_names[
i].size();
16310 for (
unsigned j = 0; j < n_inode_names; j++)
16313 flat_packed_send_udata[counter++] = local_node_names[
i][j][0];
16315 flat_packed_send_udata[counter++] = local_node_names[
i][j][1];
16317 flat_packed_send_udata[counter++] = local_node_names[
i][j][2];
16319 flat_packed_send_udata[counter++] = local_node_names[
i][j][3];
16321 flat_packed_send_udata[counter++] = local_node_names[
i][j][4];
16331 const unsigned n_udata_send_to_root = flat_packed_send_udata.size();
16344 const unsigned root_processor = 0;
16352 MPI_Gather(&n_total_local_names,
16355 &root_n_names_per_processor[0],
16359 comm_pt->mpi_comm());
16363 unsigned root_n_total_udata_receive = 0;
16365 for (
unsigned iproc = 0; iproc < nproc; iproc++)
16367 root_n_udata_to_receive[iproc] =
16368 root_n_names_per_processor[iproc] * n_info_per_node_name;
16369 root_n_total_udata_receive += root_n_udata_to_receive[iproc];
16375 root_uoffsets_receive[0] = 0;
16376 for (
unsigned iproc = 1; iproc < nproc; iproc++)
16379 root_uoffsets_receive[iproc] =
16380 root_uoffsets_receive[iproc - 1] + root_n_udata_to_receive[iproc - 1];
16384 if (flat_packed_send_udata.size() == 0)
16386 flat_packed_send_udata.resize(1);
16390 Vector<unsigned> root_flat_packed_receive_udata(root_n_total_udata_receive);
16393 if (my_rank != root_processor)
16396 if (root_flat_packed_receive_udata.size() == 0)
16398 root_flat_packed_receive_udata.resize(1);
16403 MPI_Gatherv(&flat_packed_send_udata[0],
16406 n_udata_send_to_root,
16409 &root_flat_packed_receive_udata[0],
16413 &root_n_udata_to_receive[0],
16416 &root_uoffsets_receive[0],
16422 comm_pt->mpi_comm());
16425 flat_packed_send_udata.clear();
16426 flat_packed_send_udata.resize(0);
16440 if (my_rank == root_processor)
16455 unsigned rcounter = 0;
16457 for (
unsigned iproc = 0; iproc < nproc; iproc++)
16460 const unsigned n_local_names_iproc = root_n_names_per_processor[iproc];
16461 for (
unsigned i = 0;
i < n_local_names_iproc;
i++)
16465 for (
unsigned j = 0; j < n_info_per_node_name; j++)
16467 node_name[j] = root_flat_packed_receive_udata[rcounter++];
16471 root_local_node_names.push_back(node_name);
16478 const unsigned n_root_local_node_names = root_local_node_names.size();
16493 std::map<Vector<unsigned>,
bool> done_name;
16497 for (
unsigned i = 0;
i < n_root_local_node_names;
i++)
16503 if (!done_name[node_name])
16506 done_name[node_name] =
true;
16510 bool found_both_names_node =
false;
16515 for (
unsigned j =
i + 1; j < n_root_local_node_names; j++)
16520 if (!done_name[node_name_r])
16524 if (node_name[0] == node_name_r[1] &&
16525 node_name[1] == node_name_r[0] &&
16526 node_name[2] == node_name_r[2] &&
16527 node_name[3] == node_name_r[3])
16530 done_name[node_name_r] =
true;
16533 node_name_counter_part[
i] = j;
16536 node_name_counter_part[j] =
i;
16539 found_both_names_node =
true;
16551 if (!found_both_names_node)
16553 std::ostringstream error_message;
16554 error_message <<
"The counter-part of the current name node was "
16555 <<
"not found,\nthe current node name is:\n"
16556 <<
"iproc:(" << node_name[0] <<
")\n"
16557 <<
"jproc:(" << node_name[1] <<
")\n"
16558 <<
"ishd_bnd:(" << node_name[2] <<
")\n"
16559 <<
"index:(" << node_name[3] <<
")\n";
16561 OOMPH_CURRENT_FUNCTION,
16562 OOMPH_EXCEPTION_LOCATION);
16578 for (
unsigned i = 0;
i < n_root_local_node_names;
i++)
16584 if (!done_name[node_name])
16590 all_node_names.push_back(node_name);
16593 unsigned idx_c = node_name_counter_part[
i];
16598 all_node_names.push_back(node_name_r);
16604 unsigned n_current_names = all_node_names.size();
16607 unsigned icounter = 0;
16610 while (icounter < n_current_names)
16618 if (!done_name[current_node_name])
16621 done_name[current_node_name] =
true;
16626 for (
unsigned j =
i + 1; j < n_root_local_node_names; j++)
16632 if (!done_name[other_node_name])
16635 if ((current_node_name[0] == other_node_name[0]) &&
16636 (current_node_name[4] == other_node_name[4]))
16641 done_name[other_node_name] =
true;
16645 std::find(all_node_names.begin(),
16646 all_node_names.end(),
16648 if (it == all_node_names.end())
16650 all_node_names.push_back(other_node_name);
16652 unsigned k = node_name_counter_part[j];
16655 root_local_node_names[k];
16659 if (!done_name[other_node_name_r])
16661 all_node_names.push_back(other_node_name_r);
16675 n_current_names = all_node_names.size();
16683 root_global_node_names.push_back(all_node_names);
16696 flat_packed_root_send_receive_udata.clear();
16698 const unsigned n_global_nodes = root_global_node_names.size();
16701 flat_packed_root_send_receive_udata.push_back(n_global_nodes);
16704 for (
unsigned i = 0;
i < n_global_nodes;
i++)
16709 const unsigned n_names_global_inode = global_inode_names.size();
16712 flat_packed_root_send_receive_udata.push_back(n_names_global_inode);
16714 for (
unsigned j = 0; j < n_names_global_inode; j++)
16717 for (
unsigned k = 0; k < n_info_per_node_name; k++)
16721 flat_packed_root_send_receive_udata.push_back(
16722 global_inode_names[j][k]);
16743 unsigned root_n_udata_sent_to_all_proc =
16744 flat_packed_root_send_receive_udata.size();
16746 MPI_Bcast(&root_n_udata_sent_to_all_proc,
16751 comm_pt->mpi_comm());
16754 if (my_rank != root_processor)
16756 flat_packed_root_send_receive_udata.resize(root_n_udata_sent_to_all_proc);
16760 MPI_Bcast(&flat_packed_root_send_receive_udata[0],
16764 root_n_udata_sent_to_all_proc,
16769 comm_pt->mpi_comm());
16774 const unsigned n_global_nodes =
16775 flat_packed_root_send_receive_udata[counter++];
16782 global_node_names.resize(n_global_nodes);
16784 unsigned n_read_global_nodes = 0;
16785 while (n_read_global_nodes < n_global_nodes)
16788 const unsigned n_names_global_inode =
16789 flat_packed_root_send_receive_udata[counter++];
16791 const unsigned i = n_read_global_nodes;
16793 global_node_names[
i].resize(n_names_global_inode);
16795 for (
unsigned j = 0; j < n_names_global_inode; j++)
16798 global_node_names[
i][j].resize(n_info_per_node_name);
16801 for (
unsigned k = 0; k < n_info_per_node_name; k++)
16805 global_node_names[
i][j][k] =
16806 flat_packed_root_send_receive_udata[counter++];
16813 node_name[0] = global_node_names[
i][j][0];
16814 node_name[1] = global_node_names[
i][j][1];
16815 node_name[2] = global_node_names[
i][j][2];
16816 node_name[3] = global_node_names[
i][j][3];
16821 node_name_to_global_index[node_name] =
i;
16826 n_read_global_nodes++;
16832 if (counter != root_n_udata_sent_to_all_proc)
16834 std::ostringstream error_stream;
16836 <<
"The info. received from root regarding the global names of "
16837 <<
"the nodes\nwas not completely read.\n"
16838 <<
"The number of data sent/received from root is: ("
16839 << root_n_udata_sent_to_all_proc <<
")\n"
16840 <<
"The number of data read from the received info. is: (" << counter
16843 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
16861 global_shared_node_pt.resize(n_global_nodes, 0);
16864 for (
unsigned i = 0;
i < n_global_nodes;
i++)
16868 bool is_this_a_local_node_name =
false;
16869 unsigned local_node_number;
16871 const unsigned n_names_global_inode = global_node_names[
i].size();
16873 for (
unsigned j = 0; j < n_names_global_inode; j++)
16876 const unsigned iproc = global_node_names[
i][j][0];
16877 local_node_number = global_node_names[
i][j][4];
16880 if (my_rank == iproc)
16883 is_this_a_local_node_name =
true;
16892 if (is_this_a_local_node_name)
16897 const unsigned n_names_local_node =
16898 local_node_names[local_node_number].size();
16899 unsigned n_names_found_on_global_name_node = 0;
16904 global_shared_node_pt[
i] = local_node_pt[local_node_number];
16910 for (
unsigned j = 0; j < n_names_global_inode; j++)
16913 const unsigned iproc = global_node_names[
i][j][0];
16916 if (iproc != my_rank)
16919 local_node_names[local_node_number].push_back(
16920 global_node_names[
i][j]);
16925 const unsigned jproc = global_node_names[
i][j][1];
16926 const unsigned ishd_bnd = global_node_names[
i][j][2];
16927 const unsigned idx = global_node_names[
i][j][3];
16928 const unsigned n_local_node = global_node_names[
i][j][4];
16930 for (
unsigned k = 0; k < n_names_local_node; k++)
16932 if ((local_node_names[local_node_number][k][0] == iproc) &&
16933 (local_node_names[local_node_number][k][1] == jproc) &&
16934 (local_node_names[local_node_number][k][2] == ishd_bnd) &&
16935 (local_node_names[local_node_number][k][3] == idx) &&
16936 (local_node_names[local_node_number][k][4] == n_local_node))
16940 n_names_found_on_global_name_node++;
16954 if (n_names_local_node != n_names_found_on_global_name_node)
16956 std::ostringstream error_stream;
16957 error_stream <<
"The local node names corresponding to the local "
16958 <<
"node (" << local_node_number <<
") were\n"
16959 <<
"not found on the global node names.\n\n"
16960 <<
"These are the names of the local node\n"
16961 <<
"Name k: iproc, jproc, ishd_bnd, idx. #node\n";
16962 for (
unsigned k = 0; k < n_names_local_node; k++)
16964 error_stream <<
"Name(" << k
16965 <<
"): " << local_node_names[local_node_number][k][0]
16966 <<
", " << local_node_names[local_node_number][k][1]
16967 <<
", " << local_node_names[local_node_number][k][2]
16968 <<
", " << local_node_names[local_node_number][k][3]
16969 <<
", " << local_node_names[local_node_number][k][4]
16973 error_stream <<
"\n\nThese are the names of the global node\n"
16974 <<
"Name k: iproc, jproc, ishd_bnd, idx. #node\n";
16975 for (
unsigned k = 0; k < n_names_global_inode; k++)
16977 error_stream <<
"Name(" << k <<
"): " << global_node_names[
i][k][0]
16978 <<
", " << global_node_names[
i][k][1] <<
", "
16979 << global_node_names[
i][k][2] <<
", "
16980 << global_node_names[
i][k][3] <<
", "
16981 << global_node_names[
i][k][4] <<
"\n";
16985 OOMPH_CURRENT_FUNCTION,
16986 OOMPH_EXCEPTION_LOCATION);
17012 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
17015 for (
unsigned i = 0;
i < n_local_nodes;
i++)
17018 const unsigned n_names = local_node_names[
i].size();
17022 Node* node_pt = local_node_pt[
i];
17025 for (
unsigned j = 0; j < n_names; j++)
17028 const unsigned iproc = local_node_names[
i][j][0];
17029 const unsigned jproc = local_node_names[
i][j][1];
17030 const unsigned ishd_bnd =
17031 local_node_names[
i][j][2] - initial_shd_bnd_id;
17032 const unsigned index = local_node_names[
i][j][3];
17039 other_proc_shd_bnd_node_pt[iproc][jproc][ishd_bnd][index] = node_pt;
17043 other_proc_shd_bnd_node_pt[jproc][iproc][ishd_bnd][index] = node_pt;
17061 template<
class ELEMENT>
17068 const unsigned nproc = this->communicator_pt()->nproc();
17069 const unsigned my_rank = this->communicator_pt()->my_rank();
17072 const unsigned n_nodes_on_shd_bnds = global_node_names.size();
17083 std::map<Node*, unsigned> node_pt_to_global_shd_bnd_index;
17087 for (
unsigned i = 0;
i < n_nodes_on_shd_bnds;
i++)
17091 const unsigned n_names = global_node_names[
i].size();
17093 for (
unsigned j = 0; j < n_names; j++)
17097 node_name[0] = global_node_names[
i][j][0];
17098 node_name[1] = global_node_names[
i][j][1];
17099 node_name[2] = global_node_names[
i][j][2];
17100 node_name[3] = global_node_names[
i][j][3];
17103 if (node_name[0] == my_rank)
17106 const unsigned jproc = node_name[1];
17109 std::map<Vector<unsigned>,
unsigned>::iterator it =
17110 node_name_to_global_index.find(node_name);
17111 if (it != node_name_to_global_index.end())
17115 if (
i != (*it).second)
17117 std::ostringstream error_message;
17119 <<
"The global node number " << (*it).second
17120 <<
") obtained from the current node\n"
17121 <<
"name is not the same as the current node number (" <<
i
17124 <<
"iproc:" << node_name[0] <<
"\n"
17125 <<
"jproc:" << node_name[1] <<
"\n"
17126 <<
"shd_bnd_id:" << node_name[2] <<
"\n"
17127 <<
"index:" << node_name[3] <<
"\n\n";
17129 OOMPH_CURRENT_FUNCTION,
17130 OOMPH_EXCEPTION_LOCATION);
17135 std::ostringstream error_message;
17137 <<
"The node name is not registerd as living in this processor.\n"
17139 <<
"iproc:" << node_name[0] <<
"\n"
17140 <<
"jproc:" << node_name[1] <<
"\n"
17141 <<
"shd_bnd_id:" << node_name[2] <<
"\n"
17142 <<
"index:" << node_name[3] <<
"\n\n";
17144 OOMPH_CURRENT_FUNCTION,
17145 OOMPH_EXCEPTION_LOCATION);
17151 Node* node_pt = global_shared_node_pt[
i];
17156 std::ostringstream error_message;
17157 error_message <<
"There is not global shared node within this\n"
17158 <<
"global node number (" <<
i
17159 <<
"). The global shared\n"
17160 <<
"node pointer is null\n\n";
17162 OOMPH_CURRENT_FUNCTION,
17163 OOMPH_EXCEPTION_LOCATION);
17169 node_on_shd_bnd_pt[jproc].insert(node_pt);
17172 node_pt_to_global_shd_bnd_index[node_pt] =
i;
17175 else if (node_name[1] == my_rank)
17178 const unsigned jproc = node_name[0];
17181 std::map<Vector<unsigned>,
unsigned>::iterator it =
17182 node_name_to_global_index.find(node_name);
17183 if (it != node_name_to_global_index.end())
17187 if (
i != (*it).second)
17189 std::ostringstream error_message;
17191 <<
"The global node number " << (*it).second
17192 <<
") obtained from the current node\n"
17193 <<
"name is not the same as the current node number (" <<
i
17196 <<
"iproc:" << node_name[0] <<
"\n"
17197 <<
"jproc:" << node_name[1] <<
"\n"
17198 <<
"shd_bnd_id:" << node_name[2] <<
"\n"
17199 <<
"index:" << node_name[3] <<
"\n\n";
17201 OOMPH_CURRENT_FUNCTION,
17202 OOMPH_EXCEPTION_LOCATION);
17207 std::ostringstream error_message;
17209 <<
"The node name is not registerd as living in this processor.\n"
17211 <<
"iproc:" << node_name[0] <<
"\n"
17212 <<
"jproc:" << node_name[1] <<
"\n"
17213 <<
"shd_bnd_id:" << node_name[2] <<
"\n"
17214 <<
"index:" << node_name[3] <<
"\n\n";
17216 OOMPH_CURRENT_FUNCTION,
17217 OOMPH_EXCEPTION_LOCATION);
17223 Node* node_pt = global_shared_node_pt[
i];
17228 std::ostringstream error_message;
17229 error_message <<
"There is not global shared node within this\n"
17230 <<
"global node number (" <<
i
17231 <<
"). The global shared\n"
17232 <<
"node pointer is null\n\n";
17234 OOMPH_CURRENT_FUNCTION,
17235 OOMPH_EXCEPTION_LOCATION);
17241 node_on_shd_bnd_pt[jproc].insert(node_pt);
17244 node_pt_to_global_shd_bnd_index[node_pt] =
i;
17270 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17273 std::set<Node*> nodes_shared_pt = node_on_shd_bnd_pt[iproc];
17276 for (std::set<Node*>::iterator it = nodes_shared_pt.begin();
17277 it != nodes_shared_pt.end();
17281 Node* node_pt = (*it);
17288 const unsigned n_bnd = this->initial_shared_boundary_id();
17291 for (
unsigned bb = 0; bb < n_bnd; bb++)
17297 on_original_boundaries.push_back(bb);
17302 zeta_coordinate.push_back(zeta[0]);
17308 if (on_original_boundaries.size() > 0)
17311 std::map<Node*, unsigned>::iterator it_index =
17312 node_pt_to_global_shd_bnd_index.find(node_pt);
17314 if (it_index == node_pt_to_global_shd_bnd_index.end())
17316 std::ostringstream error_message;
17318 <<
"We could not find the global shared node index associated\n"
17319 <<
"with the node pointer with vertices coordinates:\n"
17320 <<
"(" << node_pt->
x(0) <<
", " << node_pt->
x(1) <<
")\n\n";
17322 OOMPH_CURRENT_FUNCTION,
17323 OOMPH_EXCEPTION_LOCATION);
17327 const unsigned global_shared_node_number = (*it_index).second;
17329 global_node_on_shared_bound[iproc].push_back(
17330 global_shared_node_number);
17332 global_node_original_boundaries[iproc].push_back(
17333 on_original_boundaries);
17335 global_node_zeta_coordinate[iproc].push_back(zeta_coordinate);
17359 MPI_Request request;
17362 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17365 const unsigned n_shd_nodes_my_rank_iproc =
17366 node_on_shd_bnd_pt[iproc].size();
17370 if (n_shd_nodes_my_rank_iproc > 0 && iproc != my_rank)
17376 flat_package_unsigned_send.push_back(n_shd_nodes_my_rank_iproc);
17379 const unsigned n_global_shared_node_on_original_boundary =
17380 global_node_on_shared_bound[iproc].size();
17384 flat_package_unsigned_send.push_back(
17385 n_global_shared_node_on_original_boundary);
17392 for (
unsigned i = 0;
i < n_global_shared_node_on_original_boundary;
i++)
17395 const unsigned global_shared_node_index =
17396 global_node_on_shared_bound[iproc][
i];
17400 flat_package_unsigned_send.push_back(global_shared_node_index);
17404 global_node_original_boundaries[iproc][
i];
17408 global_node_zeta_coordinate[iproc][
i];
17412 const unsigned n_original_boundaries = on_original_boundaries.size();
17416 flat_package_unsigned_send.push_back(n_original_boundaries);
17420 for (
unsigned j = 0; j < n_original_boundaries; j++)
17424 flat_package_unsigned_send.push_back(on_original_boundaries[j]);
17426 flat_package_double_send.push_back(zeta_coordinate[j]);
17434 const unsigned n_udata_send = flat_package_unsigned_send.size();
17435 int n_udata_send_int = n_udata_send;
17438 MPI_Isend(&n_udata_send_int,
17443 comm_pt->mpi_comm(),
17446 int n_udata_received_int = 0;
17447 MPI_Recv(&n_udata_received_int,
17452 comm_pt->mpi_comm(),
17454 MPI_Wait(&request, MPI_STATUS_IGNORE);
17456 if (n_udata_send != 0)
17458 MPI_Isend(&flat_package_unsigned_send[0],
17463 comm_pt->mpi_comm(),
17467 const unsigned n_udata_received =
17468 static_cast<unsigned>(n_udata_received_int);
17473 if (n_udata_received != 0)
17475 MPI_Recv(&flat_package_unsigned_receive[0],
17480 comm_pt->mpi_comm(),
17484 if (n_udata_send != 0)
17486 MPI_Wait(&request, MPI_STATUS_IGNORE);
17492 const unsigned n_ddata_send = flat_package_double_send.size();
17493 int n_ddata_send_int = n_ddata_send;
17496 MPI_Isend(&n_ddata_send_int,
17501 comm_pt->mpi_comm(),
17504 int n_ddata_received_int = 0;
17505 MPI_Recv(&n_ddata_received_int,
17510 comm_pt->mpi_comm(),
17512 MPI_Wait(&request, MPI_STATUS_IGNORE);
17514 if (n_ddata_send != 0)
17516 MPI_Isend(&flat_package_double_send[0],
17521 comm_pt->mpi_comm(),
17525 const unsigned n_ddata_received =
17526 static_cast<unsigned>(n_ddata_received_int);
17531 if (n_ddata_received != 0)
17533 MPI_Recv(&flat_package_double_receive[0],
17538 comm_pt->mpi_comm(),
17542 if (n_ddata_send != 0)
17544 MPI_Wait(&request, MPI_STATUS_IGNORE);
17552 unsigned n_shared_nodes_received = flat_package_unsigned_receive[0];
17556 n_shared_nodes_received++;
17557 n_shared_nodes_received--;
17560 if (n_shd_nodes_my_rank_iproc != n_shared_nodes_received)
17562 std::ostringstream error_message;
17564 <<
"The number of shared nodes between the pair of processors is\n"
17565 <<
"not the same\n"
17566 <<
"N.shared nodes proc (" << my_rank <<
") with proc (" << iproc
17567 <<
"): (" << n_shd_nodes_my_rank_iproc <<
"\n"
17568 <<
"N.shared nodes proc (" << iproc <<
") with proc (" << my_rank
17569 <<
"): (" << n_shared_nodes_received <<
"\n\n"
17570 <<
"You should have got the same error in proc: (" << iproc
17573 OOMPH_CURRENT_FUNCTION,
17574 OOMPH_EXCEPTION_LOCATION);
17587 unsigned current_index_data = 2;
17588 unsigned current_index_ddata = 0;
17589 while (current_index_data < n_udata_received)
17592 const unsigned global_shared_node_index =
17593 flat_package_unsigned_receive[current_index_data++];
17600 const unsigned n_original_boundaries =
17601 flat_package_unsigned_receive[current_index_data++];
17604 node_pt = global_shared_node_pt[global_shared_node_index];
17608 std::ostringstream error_message;
17610 <<
"The global shared node (" << global_shared_node_index <<
") "
17611 <<
"could not be found in this processor!!!\n"
17612 <<
"However, it was found in processor (" << iproc <<
"). The "
17613 <<
"data may be no synchronised,\ntherefore "
17614 <<
"we may be looking for a global shared node number that "
17615 <<
"do not\ncorrespond with the one that was sent by "
17616 <<
"processor (" << iproc <<
")\n\n";
17618 OOMPH_CURRENT_FUNCTION,
17619 OOMPH_EXCEPTION_LOCATION);
17625 for (
unsigned i = 0;
i < n_original_boundaries;
i++)
17629 const unsigned original_bound_id =
17630 flat_package_unsigned_receive[current_index_data++];
17633 this->add_boundary_node(original_bound_id, node_pt);
17637 zeta[0] = flat_package_double_receive[current_index_ddata++];
17660 template<
class ELEMENT>
17663 other_proc_shd_bnd_node_pt,
17670 const unsigned nproc = this->communicator_pt()->nproc();
17671 const unsigned my_rank = this->communicator_pt()->my_rank();
17679 std::map<Node*, bool> is_global_shared_node;
17680 std::map<Node*, unsigned> global_shared_node_index;
17683 const unsigned n_global_shared_nodes = global_shared_node_pt.size();
17685 for (
unsigned i = 0;
i < n_global_shared_nodes;
i++)
17688 Node* node_pt = global_shared_node_pt[
i];
17690 is_global_shared_node[node_pt] =
true;
17692 global_shared_node_index[node_pt] =
i;
17715 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17717 if (iproc != my_rank)
17721 this->root_haloed_element_pt(iproc);
17724 const unsigned n_haloed_ele = this->nroot_haloed_element(iproc);
17727 for (
unsigned ihd = 0; ihd < n_haloed_ele; ihd++)
17734 const unsigned n_nodes = ele_pt->
nnode();
17736 for (
unsigned n = 0; n < n_nodes; n++)
17741 if (is_global_shared_node[node_pt])
17744 const unsigned global_index = global_shared_node_index[node_pt];
17747 global_node_names[global_index];
17750 const unsigned n_names = iglobal_names.size();
17754 for (
unsigned j = 0; j < n_names; j++)
17758 const unsigned proc1 = iglobal_names[j][0];
17759 const unsigned proc2 = iglobal_names[j][1];
17762 additional_elements_pt[proc1].insert(gele_pt);
17763 additional_elements_pt[proc2].insert(gele_pt);
17786 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17788 if (iproc != my_rank)
17792 std::set<GeneralisedElement*> iproc_ele_pt =
17793 additional_elements_pt[iproc];
17796 for (std::set<GeneralisedElement*>::iterator it = iproc_ele_pt.begin();
17797 it != iproc_ele_pt.end();
17805 this->root_haloed_element_pt(iproc);
17808 const unsigned n_haloed_ele = this->nroot_haloed_element(iproc);
17812 bool send_ele_to_iproc_processor =
true;
17817 for (
unsigned ihd = 0; ihd < n_haloed_ele; ihd++)
17821 if (gele_pt == ghd_ele_pt)
17824 send_ele_to_iproc_processor =
false;
17833 if (send_ele_to_iproc_processor)
17839 send_haloed_ele_pt[iproc].push_back(ele_pt);
17861 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17864 if (iproc != my_rank)
17867 const unsigned n_additional_haloed_ele =
17868 send_haloed_ele_pt[iproc].size();
17873 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17881 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17882 std::stringstream junk;
17883 junk <<
"Number of haloed elements " << nhaloed_ele;
17888 for (
unsigned e = 0;
e < n_additional_haloed_ele;
e++)
17892 const unsigned nroot_haloed_ele = this->nroot_haloed_element(iproc);
17900 const unsigned haloed_ele_index =
17901 this->try_to_add_root_haloed_element_pt(iproc, gen_ele_pt);
17905 if (nroot_haloed_ele == haloed_ele_index)
17908 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17910 "Haloed element needs to be constructed");
17914 get_required_elemental_information_helper(iproc, ele_pt);
17917 const unsigned nnodes = ele_pt->
nnode();
17918 for (
unsigned j = 0; j < nnodes; j++)
17924 add_haloed_node_helper(iproc, node_pt);
17932 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17934 "Haloed element already exists");
17937 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17939 "Index of existing haloed element");
17949 int send_proc =
static_cast<int>(iproc);
17951 int recv_proc =
static_cast<int>(iproc);
17952 send_and_receive_elements_nodes_info(send_proc, recv_proc);
17959 const unsigned n_additional_halo_ele =
17962 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17964 <<
" Number of elements need to be constructed "
17970 for (
unsigned e = 0;
e < n_additional_halo_ele;
e++)
17974 create_halo_element(iproc,
17975 iproc_currently_created_nodes_pt[iproc],
17976 other_proc_shd_bnd_node_pt,
17978 node_name_to_global_index,
17979 global_shared_node_pt);
17997 template<
class ELEMENT>
17999 ELEMENT>::get_required_elemental_information_helper(
unsigned& iproc,
18003 const unsigned nbound = this->initial_shared_boundary_id();
18011 unsigned counter_face_indexes = 0;
18013 for (
unsigned b = 0; b < nbound; b++)
18016 const unsigned nboundary_ele = nboundary_element(b);
18017 for (
unsigned e = 0;
e < nboundary_ele;
e++)
18019 if (ele_pt == this->boundary_element_pt(b,
e))
18022 associated_boundaries.push_back(b);
18024 face_index_on_boundary.push_back(face_index_at_boundary(b,
e));
18025 counter_face_indexes++;
18027 if (counter_face_indexes > 2)
18029 std::stringstream error_message;
18031 <<
"A triangular element can not have more than two of its faces "
18032 <<
"on a boundary!!!\n\n";
18034 OOMPH_CURRENT_FUNCTION,
18035 OOMPH_EXCEPTION_LOCATION);
18039 if (counter_face_indexes == 2)
18053 const unsigned nassociated_boundaries = associated_boundaries.size();
18054 if (nassociated_boundaries > 0)
18057 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18059 "The element is a boundary element");
18062 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18063 std::stringstream junk;
18064 junk <<
"The elements is associated to " << nassociated_boundaries
18073 for (
unsigned i = 0;
i < nassociated_boundaries;
i++)
18075 unsigned b = associated_boundaries[
i];
18077 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18078 std::stringstream junk;
18079 junk <<
"Element associated to boundary " << b <<
" of "
18080 << nassociated_boundaries <<
" total associated boundaries";
18083 unsigned f = face_index_on_boundary[
i];
18085 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18086 std::stringstream junk2;
18087 junk2 <<
"Face index " << f <<
" for associated boundary " << b;
18102 const unsigned n_regions = this->nregion();
18107 unsigned counter_face_indexes_in_regions = 0;
18109 for (
unsigned b = 0; b < nbound; b++)
18112 for (
unsigned i_reg = 0; i_reg < n_regions; i_reg++)
18115 const unsigned region_id =
18116 static_cast<unsigned>(this->Region_attribute[i_reg]);
18121 const unsigned nele_in_region =
18122 this->nboundary_element_in_region(b, region_id);
18123 for (
unsigned ee = 0; ee < nele_in_region; ee++)
18128 this->boundary_element_in_region_pt(b, region_id, ee))
18135 bound_and_region[0] = b;
18137 bound_and_region[1] = region_id;
18140 associated_boundaries_and_regions.push_back(bound_and_region);
18142 face_index_on_boundary_and_region.push_back(
18143 this->face_index_at_boundary_in_region(b, region_id, ee));
18147 counter_face_indexes_in_regions++;
18150 if (counter_face_indexes_in_regions > 2)
18152 std::stringstream error_message;
18153 error_message <<
"A triangular element can not have more "
18154 "than two of its\n"
18155 <<
"faces on a boundary!!!\n\n";
18157 OOMPH_CURRENT_FUNCTION,
18158 OOMPH_EXCEPTION_LOCATION);
18173 const unsigned nassociated_boundaries_and_regions =
18174 associated_boundaries_and_regions.size();
18175 if (nassociated_boundaries_and_regions > 0)
18178 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18180 "The element is associated to boundaries and regions");
18184 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18185 std::stringstream junk;
18186 junk <<
"The element is associated to "
18187 << nassociated_boundaries_and_regions <<
" boundaries-regions";
18195 for (
unsigned i = 0;
i < nassociated_boundaries_and_regions;
i++)
18197 const unsigned b = associated_boundaries_and_regions[
i][0];
18199 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18200 std::stringstream junk;
18201 junk <<
"Element associated to boundary " << b <<
" of "
18202 << nassociated_boundaries_and_regions
18203 <<
" total associated boundaries-regions";
18207 const unsigned r = associated_boundaries_and_regions[
i][1];
18209 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18210 std::stringstream junk2;
18211 junk2 <<
"Element associated to region " << r <<
" of "
18212 << nassociated_boundaries_and_regions
18213 <<
" total associated boundaries-regions";
18217 const unsigned f = face_index_on_boundary_and_region[
i];
18219 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18220 std::stringstream junk3;
18221 junk3 <<
"Face index " << f <<
" for associated boundary-region ("
18222 << b <<
"-" << r <<
")";
18230 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18232 "The element is NOT associated to boundaries and regions");
18239 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18241 "The element is not associated to any original boundary");
18255 this->shared_boundaries_in_this_processor(my_rank_shared_boundaries_ids);
18258 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
18260 for (
unsigned i = 0;
i < nmy_rank_shd_bnd;
i++)
18263 const unsigned sb = my_rank_shared_boundaries_ids[
i];
18266 const unsigned nboundary_ele = this->nshared_boundary_element(sb);
18267 for (
unsigned e = 0;
e < nboundary_ele;
e++)
18269 if (ele_pt == this->shared_boundary_element_pt(sb,
e))
18272 associated_shared_boundaries.push_back(sb);
18274 face_index_on_shared_boundary.push_back(
18275 this->face_index_at_shared_boundary(sb,
e));
18282 const unsigned nassociated_shared_boundaries =
18283 associated_shared_boundaries.size();
18284 if (nassociated_shared_boundaries > 0)
18287 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18289 "The element is a shared boundary element");
18292 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18293 std::stringstream junk;
18294 junk <<
"The elements is associated to " << nassociated_shared_boundaries
18295 <<
"shared boundaries";
18300 for (
unsigned i = 0;
i < nassociated_shared_boundaries;
i++)
18302 const unsigned b = associated_shared_boundaries[
i];
18304 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18305 std::stringstream junk;
18306 junk <<
"Element associated to shared boundary " << b <<
" of "
18307 << nassociated_shared_boundaries <<
" total associated boundaries";
18311 const unsigned f = face_index_on_shared_boundary[
i];
18313 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18314 std::stringstream junk2;
18315 junk2 <<
"Face index " << f <<
" for associated shared boundary " << b;
18323 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18325 "The element is not associated to any shared boundary");
18335 template<
class ELEMENT>
18337 unsigned& iproc,
Node* nod_pt)
18339 unsigned my_rank = this->communicator_pt()->my_rank();
18340 const unsigned nproc = this->communicator_pt()->nproc();
18345 unsigned n_val = nod_pt->
nvalue();
18347 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18351 unsigned n_dim = nod_pt->
ndim();
18354 unsigned n_prev = 1;
18355 if (this->Time_stepper_pt != 0)
18358 n_prev = this->Time_stepper_pt->ntstorage();
18367 const unsigned n_bnd = this->initial_shared_boundary_id();
18368 for (
unsigned bb = 0; bb < n_bnd; bb++)
18373 original_boundaries.push_back(bb);
18377 const unsigned n_original_boundaries = original_boundaries.size();
18379 if (n_original_boundaries > 0)
18383 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18385 "Node is on the original boundaries");
18389 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18390 std::stringstream junk;
18391 junk <<
"Node is on " << n_original_boundaries <<
" original boundaries";
18396 for (
unsigned i = 0;
i < n_original_boundaries;
i++)
18399 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18400 std::stringstream junk;
18401 junk <<
"Node is on boundary " << original_boundaries[
i] <<
" of "
18415 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18417 "Node is on any original boundary");
18423 bool node_on_shared_boundary =
false;
18426 const unsigned n_shd_bnd = this->nshared_boundaries(my_rank, iproc);
18427 for (
unsigned bb = 0; bb < n_shd_bnd; bb++)
18430 unsigned i_bnd = this->shared_boundaries_ids(my_rank, iproc, bb);
18432 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
18434 node_on_shared_boundary =
true;
18442 if (node_on_shared_boundary)
18445 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18452 for (
unsigned bb = 0; bb < n_shd_bnd; bb++)
18455 const unsigned i_bnd = this->shared_boundaries_ids(my_rank, iproc, bb);
18457 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
18459 shd_boundaries.push_back(i_bnd);
18464 const unsigned n_shd_bnd_is_on = shd_boundaries.size();
18467 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18468 std::stringstream junk;
18469 junk <<
"Node is on " << n_shd_bnd_is_on <<
" shared boundaries";
18474 for (
unsigned i = 0;
i < n_shd_bnd_is_on;
i++)
18477 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18478 std::stringstream junk;
18479 junk <<
"Node is on boundary " << shd_boundaries[
i] <<
" of " << nb;
18486 unsigned shared_boundary_id = shd_boundaries[0];
18488 const unsigned n_nodes_on_shared_boundary =
18489 nsorted_shared_boundary_node(shared_boundary_id);
18491 unsigned index_node_on_shared_boundary;
18494 bool found_index_node_on_shared_boundary =
false;
18497 for (
unsigned i = 0;
i < n_nodes_on_shared_boundary;
i++)
18500 Node* shared_node_pt =
18501 sorted_shared_boundary_node_pt(shared_boundary_id,
i);
18503 if (shared_node_pt == nod_pt)
18506 index_node_on_shared_boundary =
i;
18509 found_index_node_on_shared_boundary =
true;
18517 if (!found_index_node_on_shared_boundary)
18519 std::ostringstream error_message;
18520 error_message <<
"The index of the node on boundary ("
18521 << shared_boundary_id <<
") was not found.\n"
18522 <<
"The node coordinates are (" << nod_pt->
x(0) <<
","
18523 << nod_pt->
x(1) <<
").\n";
18525 error_message.str(),
18526 "RefineableTriangleMesh::get_required_nodal_information_helper()",
18527 OOMPH_EXCEPTION_LOCATION);
18532 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18533 std::stringstream junk2;
18534 junk2 <<
"Node index on boundary " << boundaries[0] <<
" is "
18535 << index_node_on_shared_boundary;
18544 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18546 "Node is not on a shared boundary");
18561 bool node_on_shared_boundary_with_other_processors =
false;
18563 unsigned nshared_boundaries_with_other_processors_have_node = 0;
18567 for (
unsigned jproc = 0; jproc < nproc; jproc++)
18571 if (jproc != iproc)
18574 const unsigned n_jshd_bnd = this->nshared_boundaries(my_rank, jproc);
18576 for (
unsigned bb = 0; bb < n_jshd_bnd; bb++)
18579 const unsigned j_shd_bnd =
18580 this->shared_boundaries_ids(my_rank, jproc, bb);
18582 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
18590 node_on_shared_boundary_with_other_processors =
true;
18593 nshared_boundaries_with_other_processors_have_node++;
18604 if (node_on_shared_boundary_with_other_processors)
18607 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18609 "Node is on shared boundary no related with the received processor: 4");
18616 nshared_boundaries_with_other_processors_have_node);
18617 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18618 std::stringstream junk;
18619 junk <<
"Number of other shared boundaries that the node is on: "
18620 << nshared_boundaries_with_other_processors_have_node;
18625 unsigned counter_shd_bnd_with_other_procs_have_node = 0;
18635 for (
unsigned jproc = 0; jproc < nproc; jproc++)
18639 if (jproc != iproc)
18643 const unsigned n_jshd_bnd = this->nshared_boundaries(my_rank, jproc);
18644 for (
unsigned bb = 0; bb < n_jshd_bnd; bb++)
18647 const unsigned j_shd_bnd =
18648 this->shared_boundaries_ids(my_rank, jproc, bb);
18650 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
18653 other_processor_1.push_back(my_rank);
18655 other_processor_2.push_back(jproc);
18657 shd_bnd_ids.push_back(j_shd_bnd);
18660 counter_shd_bnd_with_other_procs_have_node++;
18671 const unsigned n_other_processors = other_processor_1.size();
18673 for (
unsigned i = 0;
i < n_other_processors;
i++)
18676 unsigned shd_bnd_id = shd_bnd_ids[
i];
18678 const unsigned n_nodes_on_shd_bnd =
18679 nsorted_shared_boundary_node(shd_bnd_id);
18682 bool found_index_node_on_shared_boundary =
false;
18684 for (
unsigned i = 0;
i < n_nodes_on_shd_bnd;
i++)
18687 Node* shared_node_pt = sorted_shared_boundary_node_pt(shd_bnd_id,
i);
18689 if (shared_node_pt == nod_pt)
18695 indexes.push_back(
i);
18698 found_index_node_on_shared_boundary =
true;
18706 if (!found_index_node_on_shared_boundary)
18708 std::ostringstream error_message;
18709 error_message <<
"The index of the node on boundary (" << shd_bnd_id
18710 <<
"), shared by other processors\nwas not found.\n"
18711 <<
"The node coordinates are (" << nod_pt->
x(0) <<
","
18712 << nod_pt->
x(1) <<
").\n";
18714 error_message.str(),
18715 "RefineableTriangleMesh::get_required_nodal_information_helper()",
18716 OOMPH_EXCEPTION_LOCATION);
18725 if (counter_shd_bnd_with_other_procs_have_node !=
18726 nshared_boundaries_with_other_processors_have_node)
18728 std::ostringstream error_message;
18729 error_message <<
"The number of shared boundaries where the node is on "
18730 <<
"is different:\n"
18731 <<
"nshared_boundaries_with_other_processors_have_node: ("
18732 << nshared_boundaries_with_other_processors_have_node
18734 <<
"counter_shd_bnd_with_other_procs_have_node: ("
18735 << counter_shd_bnd_with_other_procs_have_node <<
")\n";
18737 error_message.str(),
18738 "RefineableTriangleMesh::get_required_nodal_information_helper()",
18739 OOMPH_EXCEPTION_LOCATION);
18745 for (
unsigned i = 0;
i < n_other_processors;
i++)
18748 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18749 std::stringstream junk1;
18750 junk1 <<
"Processor where the other shared boundary "
18751 <<
"has the node: " << other_processor_1[
i];
18756 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18757 std::stringstream junk2;
18758 junk2 <<
"Processor where the other shared boundary "
18759 <<
"has the node: " << other_processor_2[
i];
18764 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18765 std::stringstream junk3;
18766 junk3 <<
"Other shared boundary id where the node is on"
18772 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18773 std::stringstream junk4;
18774 junk4 <<
"Node index on other shared boundary " << boundaries[
i]
18775 <<
" is " << indexes[
i];
18785 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18787 "Node is on any shared boundary with other processors");
18795 if (!node_on_shared_boundary)
18803 if (alg_nod_pt != 0)
18811 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18816 unsigned n_ref_val = alg_nod_pt->
nref_value();
18818 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18821 for (
unsigned i_ref_val = 0; i_ref_val < n_ref_val; i_ref_val++)
18829 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18832 for (
unsigned i_geom = 0; i_geom < n_geom_obj; i_geom++)
18840 unsigned found_geom_object = 0;
18841 for (
unsigned i_list = 0; i_list < n_geom_list; i_list++)
18845 found_geom_object = i_list;
18849 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18857 if (solid_nod_pt != 0)
18860 for (
unsigned i_val = 0; i_val < n_solid_val; i_val++)
18862 for (
unsigned t = 0;
t < n_prev;
t++)
18871 const unsigned nvalues_solid_node = values_solid_node.size();
18873 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18874 std::stringstream junk;
18875 junk <<
"Number of values solid node: " << nvalues_solid_node;
18878 for (
unsigned i = 0;
i < nvalues_solid_node;
i++)
18885 for (
unsigned i_val = 0; i_val < n_val; i_val++)
18887 for (
unsigned t = 0;
t < n_prev;
t++)
18894 for (
unsigned idim = 0; idim < n_dim; idim++)
18896 for (
unsigned t = 0;
t < n_prev;
t++)
18908 template<
class ELEMENT>
18913 const unsigned n_haloed_nod = this->nhaloed_node(iproc);
18914 const unsigned haloed_node_index =
18915 this->try_to_add_haloed_node_pt(iproc, nod_pt);
18918 if (haloed_node_index == n_haloed_nod)
18922 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18923 std::stringstream junk;
18924 junk <<
"Node needs to be constructed [size="
18938 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18939 std::stringstream junk;
18941 <<
"]; last entry: "
18950 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18960 template<
class ELEMENT>
18962 int& send_proc,
int& recv_proc)
18969 MPI_Request request;
18978 MPI_Isend(&send_count_double_values,
18983 comm_pt->mpi_comm(),
18986 int receive_count_double_values = 0;
18987 MPI_Recv(&receive_count_double_values,
18992 comm_pt->mpi_comm(),
18994 MPI_Wait(&request, MPI_STATUS_IGNORE);
18996 if (send_count_double_values != 0)
18999 send_count_double_values,
19003 comm_pt->mpi_comm(),
19006 if (receive_count_double_values != 0)
19008 received_double_values.resize(receive_count_double_values);
19009 MPI_Recv(&received_double_values[0],
19010 receive_count_double_values,
19014 comm_pt->mpi_comm(),
19017 if (send_count_double_values != 0)
19019 MPI_Wait(&request, MPI_STATUS_IGNORE);
19025 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19028 if (send_count_unsigned_string != send_count_unsigned_values)
19030 std::ostringstream error_message;
19031 error_message <<
"The number of unsigned values to send to processor ("
19033 <<
") is different from the\nnumber of annotated strings "
19034 <<
"for the communication\n\n";
19036 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
19040 MPI_Isend(&send_count_unsigned_values,
19045 comm_pt->mpi_comm(),
19048 int receive_count_unsigned_values = 0;
19049 MPI_Recv(&receive_count_unsigned_values,
19054 comm_pt->mpi_comm(),
19057 MPI_Wait(&request, MPI_STATUS_IGNORE);
19059 if (send_count_unsigned_values != 0)
19062 send_count_unsigned_values,
19066 comm_pt->mpi_comm(),
19068 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19069 for (
unsigned i = 0;
i < send_count_unsigned_values;
i++)
19071 oomph_info <<
"Sent:" <<
i <<
" to orig_proc:" << send_proc <<
" "
19077 if (receive_count_unsigned_values != 0)
19079 received_unsigned_values.resize(receive_count_unsigned_values);
19080 MPI_Recv(&received_unsigned_values[0],
19081 receive_count_unsigned_values,
19085 comm_pt->mpi_comm(),
19089 if (send_count_unsigned_values != 0)
19091 MPI_Wait(&request, MPI_STATUS_IGNORE);
19101 for (
int ii = 0; ii < receive_count_double_values; ii++)
19106 for (
int ii = 0; ii < receive_count_unsigned_values; ii++)
19116 template<
class ELEMENT>
19121 other_proc_shd_bnd_node_pt,
19126 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19128 <<
" Bool: New element needs to be constructed "
19140 this->add_element_pt(new_el_pt);
19143 this->add_root_halo_element_pt(iproc, new_el_pt);
19149 this->add_halo_element_helper(iproc, f_el_pt);
19152 unsigned n_node = f_el_pt->
nnode();
19154 for (
unsigned j = 0; j < n_node; j++)
19156 Node* new_nod_pt = 0;
19159 add_halo_node_helper(new_nod_pt,
19160 new_nodes_on_domain,
19161 other_proc_shd_bnd_node_pt,
19166 node_name_to_global_index,
19167 global_shared_node_pt);
19173 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19175 <<
" Index of existing halo element "
19180 unsigned halo_ele_index =
19185 this->root_halo_element_pt(iproc, halo_ele_index));
19190 throw OomphLibError(
"Halo element is not a FiniteElement\n",
19191 OOMPH_CURRENT_FUNCTION,
19192 OOMPH_EXCEPTION_LOCATION);
19204 template<
class ELEMENT>
19208 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19210 <<
" Bool: Element is associated to an original boundary "
19217 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19219 <<
" How many boundaries are associated with the element "
19223 const unsigned nassociated_boundaries =
19226 for (
unsigned b = 0; b < nassociated_boundaries; b++)
19228 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19230 <<
" Boundary associated to the element "
19234 const unsigned bnd =
19237 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19239 <<
" Face index of the element "
19243 const unsigned face_index =
19248 this->Boundary_element_pt[bnd].push_back(ele_pt);
19249 this->Face_index_at_boundary[bnd].push_back(face_index);
19254 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19256 <<
" Bool: Element is associated to a boundary-region "
19263 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19266 <<
" How many boundaries-regions are associated with the element "
19270 const unsigned nassociated_boundaries_and_regions =
19273 for (
unsigned br = 0; br < nassociated_boundaries_and_regions; br++)
19275 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19277 <<
" Boundary associated to the element "
19281 const unsigned bnd =
19284 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19286 <<
" Region associated to the element "
19290 const unsigned region =
19293 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19295 <<
" Face index of the element in boundary-region "
19299 const unsigned face_index =
19304 this->Boundary_region_element_pt[bnd][region].push_back(ele_pt);
19305 this->Face_index_region_at_boundary[bnd][region].push_back(
19314 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19316 <<
" Bool: Element is associated to a shared boundary "
19322 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19325 <<
" How many shared boundaries are associated with the element "
19329 const unsigned nassociated_shared_boundaries =
19332 for (
unsigned b = 0; b < nassociated_shared_boundaries; b++)
19334 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19336 <<
" Shared boundary associated to the element "
19340 const unsigned bnd =
19343 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19346 <<
" Face index of the element associated to the shared boundary "
19351 const unsigned face_index =
19354 this->add_shared_boundary_element(bnd, ele_pt);
19355 this->add_face_index_at_shared_boundary(bnd, face_index);
19365 template<
class ELEMENT>
19370 other_proc_shd_bnd_node_pt,
19372 unsigned& node_index,
19380 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19382 <<
" Bool: New node needs to be constructed "
19390 construct_new_halo_node_helper(new_nod_pt,
19391 new_nodes_on_domain,
19392 other_proc_shd_bnd_node_pt,
19397 node_name_to_global_index,
19398 global_shared_node_pt);
19402 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19404 <<
" Index of existing halo node "
19410 new_nod_pt = new_nodes_on_domain
19413 new_el_pt->
node_pt(node_index) = new_nod_pt;
19421 template<
class ELEMENT>
19426 other_proc_shd_bnd_node_pt,
19428 unsigned& node_index,
19436 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19438 <<
" Number of values of external halo node "
19445 TimeStepper* time_stepper_pt = this->Time_stepper_pt;
19447 unsigned n_prev = time_stepper_pt->
ntstorage();
19451 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19453 <<
" Is the node on an original boundary "
19459 const unsigned node_on_original_boundaries =
19467 unsigned n_original_boundaries_node_is_on = 0;
19469 if (node_on_original_boundaries == 2)
19472 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19474 <<
" Number of boundaries the node is on: "
19478 n_original_boundaries_node_is_on =
19482 original_boundaries_node_is_on.resize(n_original_boundaries_node_is_on);
19483 zeta_coordinates.resize(n_original_boundaries_node_is_on);
19485 for (
unsigned i = 0;
i < n_original_boundaries_node_is_on;
i++)
19488 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19490 <<
" Node is on boundary "
19494 original_boundaries_node_is_on[
i] =
19496 zeta_coordinates[
i] =
19504 if (node_on_original_boundaries != 0)
19506 std::ostringstream error_message;
19508 <<
"The current node is not on an original boundary, this should\n"
19509 <<
"be indicated by a zero flag. However, the read value for\n"
19510 <<
"that flag is (" << node_on_original_boundaries <<
").\n\n";
19512 error_message.str(),
19513 "RefineableTriangleMesh::construct_new_halo_node_helper()",
19514 OOMPH_EXCEPTION_LOCATION);
19522 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19524 <<
" Is node on shared boundary? "
19528 const unsigned is_node_on_shared_boundary =
19530 if (is_node_on_shared_boundary == 1)
19533 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19535 <<
" Number of boundaries the node is on: "
19539 const unsigned n_shd_bnd_node_is_on =
19542 for (
unsigned i = 0;
i < n_shd_bnd_node_is_on;
i++)
19545 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19547 <<
" Node is on boundary "
19551 shd_bnds_node_is_on[
i] =
19556 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19558 <<
" Index of node on boundary "
19563 unsigned node_index_on_shared_boundary =
19567 new_nod_pt = this->sorted_shared_boundary_node_pt(
19568 shd_bnds_node_is_on[0], node_index_on_shared_boundary);
19574 if (is_node_on_shared_boundary != 0)
19576 std::ostringstream error_message;
19578 <<
"The current node is not on a shared boundary, this should\n"
19579 <<
"be indicated by a zero flag. However, the read value for\n"
19580 <<
"that flag is (" << is_node_on_shared_boundary <<
").\n\n";
19582 error_message.str(),
19583 "RefineableTriangleMesh::construct_new_halo_node_helper()",
19584 OOMPH_EXCEPTION_LOCATION);
19591 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19593 <<
" Is the node on shared boundaries with other processors "
19600 const unsigned is_the_node_in_shared_boundaries_with_other_processors =
19610 unsigned n_shd_bnd_with_other_procs_have_node = 0;
19613 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
19615 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19617 <<
" In how many shared boundaries with other "
19618 <<
"processors is the node "
19624 n_shd_bnd_with_other_procs_have_node =
19628 other_processor_1.resize(n_shd_bnd_with_other_procs_have_node);
19629 other_processor_2.resize(n_shd_bnd_with_other_procs_have_node);
19630 other_shared_boundaries.resize(n_shd_bnd_with_other_procs_have_node);
19631 other_indexes.resize(n_shd_bnd_with_other_procs_have_node);
19633 for (
unsigned i = 0;
i < n_shd_bnd_with_other_procs_have_node;
i++)
19635 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19637 <<
" Processor where the other shared boundary"
19643 other_processor_1[
i] =
19646 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19648 <<
" Processor where the other shared boundary"
19654 other_processor_2[
i] =
19657 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19659 <<
" Other shared boundary id where the node is on: "
19665 other_shared_boundaries[
i] =
19668 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19670 <<
" Node index on the other shared boundary "
19685 if (is_the_node_in_shared_boundaries_with_other_processors != 0)
19687 std::ostringstream error_message;
19689 <<
"The current node is not on a shared boundary with\n"
19690 <<
"other processors, this should be indicated by a zero flag.\n"
19691 <<
"However, the read value for that flag is ("
19692 << is_the_node_in_shared_boundaries_with_other_processors <<
").\n\n";
19694 error_message.str(),
19695 "RefineableTriangleMesh::construct_new_halo_node_helper()",
19696 OOMPH_EXCEPTION_LOCATION);
19705 if (is_node_on_shared_boundary == 1)
19710 if (node_on_original_boundaries == 2)
19716 for (
unsigned i = 0;
i < n_original_boundaries_node_is_on;
i++)
19718 add_boundary_node(original_boundaries_node_is_on[
i], new_nod_pt);
19721 zeta[0] = zeta_coordinates[
i];
19723 original_boundaries_node_is_on[
i], zeta);
19729 new_nodes_on_domain.push_back(new_nod_pt);
19732 new_el_pt->
node_pt(node_index) = new_nod_pt;
19742 bool found_node_in_other_shared_boundaries =
false;
19751 bool build_node_as_boundary_node =
false;
19753 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
19756 build_node_as_boundary_node =
true;
19763 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
19769 for (
unsigned i = 0;
i < n_shd_bnd_with_other_procs_have_node;
i++)
19780 unsigned oproc1 = other_processor_1[
i];
19781 unsigned oproc2 = other_processor_2[
i];
19782 if (other_processor_1[
i] > other_processor_2[
i])
19784 oproc1 = other_processor_2[
i];
19785 oproc2 = other_processor_1[
i];
19790 const unsigned shd_bnd_id =
19791 other_shared_boundaries[
i] - initial_shd_bnd_id;
19794 const unsigned index = other_indexes[
i];
19798 const unsigned n_nodes_on_other_processor =
19799 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].size();
19801 if (n_nodes_on_other_processor > 0)
19805 std::map<unsigned, Node*>::iterator it =
19806 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].find(index);
19810 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].end())
19813 found_node_in_other_shared_boundaries =
true;
19815 Node* tmp_node_pt = (*it).second;
19818 found_node_pt.push_back(tmp_node_pt);
19829 if (found_node_in_other_shared_boundaries)
19832 const unsigned n_times_node_found = found_node_pt.size();
19833 for (
unsigned j = 1; j < n_times_node_found; j++)
19835 if (found_node_pt[j - 1] != found_node_pt[j])
19837 std::ostringstream error_message;
19839 <<
"The instances of the node that was found on\n"
19840 <<
"shared boundaries with other processors (but not\n"
19841 <<
"on shared boundaries with this processor) are not\n"
19843 <<
"These are the coordinates of the instances of the\n"
19845 <<
"(" << found_node_pt[j - 1]->x(0) <<
", "
19846 << found_node_pt[j - 1]->x(1) <<
")\n"
19847 <<
"(" << found_node_pt[j]->x(0) <<
", " << found_node_pt[j]->x(1)
19849 <<
"Dont be surprised if they are the same since the "
19850 <<
"node is\nrepeated.\n";
19852 OOMPH_CURRENT_FUNCTION,
19853 OOMPH_EXCEPTION_LOCATION);
19864 if (is_node_on_shared_boundary == 1)
19873 if (found_node_pt[0] != new_nod_pt)
19875 std::ostringstream error_message;
19877 <<
"The pointer of the node that was found to be on a\n"
19878 <<
"shared boundary with other processor(s) and the pointer\n"
19879 <<
"of the node on shared boundary with the receiver\n"
19880 <<
"processor (iproc) are not the same. This means we have a\n"
19881 <<
"repeated node)\n"
19882 <<
"The coordinates for the nodes are:\n"
19883 <<
"(" << found_node_pt[0]->x(0) <<
", " << found_node_pt[0]->x(1)
19885 <<
"(" << new_nod_pt->
x(0) <<
", " << new_nod_pt->
x(1) <<
")\n"
19886 <<
"Dont be surprised if they are the same since the "
19887 <<
"node is\nrepeated.\n";
19889 OOMPH_CURRENT_FUNCTION,
19890 OOMPH_EXCEPTION_LOCATION);
19901 new_nod_pt = found_node_pt[0];
19911 if (is_node_on_shared_boundary != 1)
19925 if (node_on_original_boundaries == 2 || build_node_as_boundary_node)
19929 if (!found_node_in_other_shared_boundaries)
19932 if (time_stepper_pt != 0)
19946 new_el_pt->
node_pt(node_index) = new_nod_pt;
19951 for (
unsigned i = 0;
i < n_original_boundaries_node_is_on;
i++)
19953 add_boundary_node(original_boundaries_node_is_on[
i], new_nod_pt);
19956 zeta[0] = zeta_coordinates[
i];
19958 original_boundaries_node_is_on[
i], zeta);
19966 if (!found_node_in_other_shared_boundaries)
19969 if (time_stepper_pt != 0)
19971 new_nod_pt = new_el_pt->
construct_node(node_index, time_stepper_pt);
19981 new_el_pt->
node_pt(node_index) = new_nod_pt;
19992 new_nodes_on_domain.push_back(new_nod_pt);
19996 if (!found_node_in_other_shared_boundaries)
19999 this->add_node_pt(new_nod_pt);
20007 if (new_alg_nod_pt != 0)
20016 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
20018 <<
" Alg node update id "
20023 unsigned update_id =
20030 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
20032 <<
" Alg node # of ref values "
20036 unsigned n_ref_val =
20041 ref_value.resize(n_ref_val);
20042 for (
unsigned i_ref = 0; i_ref < n_ref_val; i_ref++)
20055 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
20057 <<
" Alg node # of geom objects "
20061 unsigned n_geom_obj =
20066 geom_object_pt.resize(n_geom_obj);
20067 for (
unsigned i_geom = 0; i_geom < n_geom_obj; i_geom++)
20069 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
20071 <<
" Alg node: geom object index "
20075 unsigned geom_index =
20088 if (!found_node_in_other_shared_boundaries)
20093 update_id, alg_mesh_pt, geom_object_pt, ref_value);
20104 if (!found_node_in_other_shared_boundaries)
20110 if (macro_nod_pt != 0)
20125 s_in_macro_node_update_element);
20129 new_el_pt, s_in_macro_node_update_element, geom_object_vector_pt);
20135 unsigned n_new_val = new_nod_pt->
nvalue();
20139 if (!found_node_in_other_shared_boundaries)
20141 if (n_val > n_new_val)
20157 new std::map<unsigned, unsigned>;
20161 std::map<unsigned, unsigned>* map_pt =
20166 const unsigned id_face = 0;
20168 std::map<unsigned, unsigned>::const_iterator p =
20169 map_pt->find(id_face);
20172 if (p == map_pt->end())
20176 (*map_pt)[id_face] = n_new_val;
20179 new_nod_pt->
resize(n_val);
20188 if (solid_nod_pt != 0)
20191 for (
unsigned i_val = 0; i_val < n_solid_val; i_val++)
20193 for (
unsigned t = 0;
t < n_prev;
t++)
20200 if (!found_node_in_other_shared_boundaries)
20203 t, i_val, read_data);
20208 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
20210 <<
" Number of values solid node: "
20214 const unsigned nvalues_solid_node =
20217 for (
unsigned i = 0;
i < nvalues_solid_node;
i++)
20219 values_solid_node[
i] =
20225 if (!found_node_in_other_shared_boundaries)
20227 unsigned index = 0;
20234 for (
unsigned i_val = 0; i_val < n_val; i_val++)
20236 for (
unsigned t = 0;
t < n_prev;
t++)
20244 if (!found_node_in_other_shared_boundaries)
20252 unsigned n_dim = new_nod_pt->
ndim();
20253 for (
unsigned idim = 0; idim < n_dim; idim++)
20255 for (
unsigned t = 0;
t < n_prev;
t++)
20263 if (!found_node_in_other_shared_boundaries)
20266 new_nod_pt->
x(
t, idim) = read_data;
20278 if (n_shd_bnd_with_other_procs_have_node > 0 &&
20282 !found_node_in_other_shared_boundaries)
20290 this->update_other_proc_shd_bnd_node_helper(new_nod_pt,
20291 other_proc_shd_bnd_node_pt,
20294 other_shared_boundaries,
20297 node_name_to_global_index,
20298 global_shared_node_pt);
20307 template<
class ELEMENT>
20309 Node*& new_node_pt,
20311 other_proc_shd_bnd_node_pt,
20322 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
20327 const unsigned n_data = other_processor_1.size();
20332 node_name[0] = other_processor_1[0];
20333 node_name[1] = other_processor_2[0];
20334 node_name[2] = other_shared_boundaries[0];
20335 node_name[3] = other_indexes[0];
20339 std::map<Vector<unsigned>,
unsigned>::iterator it =
20340 node_name_to_global_index.find(node_name);
20341 if (it == node_name_to_global_index.end())
20343 std::ostringstream error_stream;
20344 error_stream <<
"The node name does not exist in the global node names\n"
20345 <<
"This is the name of the node\n"
20346 <<
"Name: iproc, jproc, ishd_bnd, idx\n"
20347 <<
"Name: " << node_name[0] <<
", " << node_name[1] <<
", "
20348 << node_name[2] <<
", " << node_name[3] <<
"\n";
20350 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
20355 const unsigned iglobal_node = node_name_to_global_index[node_name];
20357 global_shared_node_pt[iglobal_node] = new_node_pt;
20361 const unsigned n_names = inode_names.size();
20366 unsigned n_found_node_names_on_global_node_name = 0;
20368 for (
unsigned j = 0; j < n_data; j++)
20371 for (
unsigned k = 0; k < n_names; k++)
20374 if (inode_names[k][0] == other_processor_1[j] &&
20375 inode_names[k][1] == other_processor_2[j] &&
20376 inode_names[k][2] == other_shared_boundaries[j] &&
20377 inode_names[k][3] == other_indexes[j])
20381 n_found_node_names_on_global_node_name++;
20389 if (n_found_node_names_on_global_node_name != n_data)
20391 std::ostringstream error_stream;
20393 <<
"Not all the node names of the current node were found on the\n"
20394 <<
"global node names. This happened when adding the node pointer\n"
20395 <<
"to the data structure that keeps tracks of nodes on shared\n"
20396 <<
"boundaries with other processors\n\n"
20397 <<
"These are the names of the current node\n"
20398 <<
"Name k: iproc, jproc, ishd_bnd, idx\n";
20399 for (
unsigned j = 0; j < n_data; j++)
20401 error_stream <<
"Name(" << j <<
"): " << other_processor_1[j] <<
", "
20402 << other_processor_2[j] <<
", "
20403 << other_shared_boundaries[j] <<
", " << other_indexes[j]
20407 error_stream <<
"\n\nThese are the names of the global node\n"
20408 <<
"Name k: iproc, jproc, ishd_bnd, idx\n";
20409 for (
unsigned k = 0; k < n_names; k++)
20411 error_stream <<
"Name(" << k <<
"): " << inode_names[k][0] <<
", "
20412 << inode_names[k][1] <<
", " << inode_names[k][2] <<
", "
20413 << inode_names[k][3] <<
"\n";
20417 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
20422 for (
unsigned j = 0; j < n_names; j++)
20425 const unsigned iproc = inode_names[j][0];
20426 const unsigned jproc = inode_names[j][1];
20427 const unsigned ishd_bnd = inode_names[j][2] - initial_shd_bnd_id;
20428 const unsigned index = inode_names[j][3];
20434 other_proc_shd_bnd_node_pt[iproc][jproc][ishd_bnd][index] = new_node_pt;
20438 other_proc_shd_bnd_node_pt[jproc][iproc][ishd_bnd][index] = new_node_pt;
20456 template<
class ELEMENT>
20460 oomph_info <<
"Load balance (unstructured mesh) [BEGIN]" << std::endl;
20464 if (!this->is_mesh_distributed())
20466 std::ostringstream warning_message;
20468 <<
"\n===============================================================\n"
20469 <<
"The load balancing can only be performed in distributed meshes,\n"
20470 <<
"your mesh has not been distributed.\n"
20471 <<
"==============================================================="
20474 OOMPH_CURRENT_FUNCTION,
20475 OOMPH_EXCEPTION_LOCATION);
20481 const unsigned nproc = this->communicator_pt()->nproc();
20483 const unsigned my_rank = this->communicator_pt()->my_rank();
20488 std::ostringstream warning_message;
20490 <<
"\n===============================================================\n"
20491 <<
"The load balancing can only be performed when there are at least\n"
20492 <<
"two procesors, the current number of processors is one.\n"
20493 <<
"==============================================================="
20496 OOMPH_CURRENT_FUNCTION,
20497 OOMPH_EXCEPTION_LOCATION);
20503 double t_start_overall_load_balance = 0.0;
20504 if (Print_timings_level_load_balance > 1)
20510 const unsigned nelement_before_load_balance = this->nelement();
20515 if (nnon_halo_element() != target_domain_for_local_non_halo_element.size())
20517 std::ostringstream error_message;
20518 error_message <<
"The number of non halo elements in the current mesh ("
20519 << nnon_halo_element() <<
") and the number\n"
20520 <<
"of target areas for the local non halo elements ("
20521 << target_domain_for_local_non_halo_element.size()
20522 <<
") is different\n\n";
20524 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
20530 for (
unsigned e = 0;
e < nelement_before_load_balance;
e++)
20532 backed_up_ele_pt[
e] = this->finite_element_pt(
e);
20540 double tt_start_get_domains_halo_elements = 0.0;
20541 if (Print_timings_level_load_balance > 1)
20564 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20568 if (iproc != my_rank)
20571 const unsigned n_halo_iproc = this->nroot_halo_element(iproc);
20573 new_domains_halo_elements[iproc].resize(n_halo_iproc);
20576 const unsigned n_haloed_iproc = this->nroot_haloed_element(iproc);
20578 new_domains_haloed_elements[iproc].resize(n_haloed_iproc);
20591 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20595 if (iproc != my_rank)
20598 const unsigned n_haloed_iproc = this->nroot_haloed_element(iproc);
20601 for (
unsigned ihd = 0; ihd < n_haloed_iproc; ihd++)
20605 this->root_haloed_element_pt(iproc, ihd);
20608 unsigned nh_count4 = 0;
20610 for (
unsigned e = 0;
e < nelement_before_load_balance;
e++)
20622 if (ele_pt == haloed_ele_pt)
20625 const unsigned element_domain =
20626 target_domain_for_local_non_halo_element[nh_count4 - 1];
20631 new_domains_haloed_elements[iproc][ihd] = element_domain;
20634 counter_for_found_haloed_elements[iproc]++;
20655 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20659 if (iproc != my_rank)
20662 const unsigned n_haloed_iproc = this->nroot_haloed_element(iproc);
20666 if (n_haloed_iproc != counter_for_found_haloed_elements[iproc])
20668 std::ostringstream error_message;
20669 error_message <<
"The independent counting of found haloed elements ("
20670 << counter_for_found_haloed_elements[iproc]
20671 <<
") with processor (" << iproc
20672 <<
") is not equal to the number of haloed elements ("
20673 << n_haloed_iproc <<
") with processor (" << iproc
20676 OOMPH_CURRENT_FUNCTION,
20677 OOMPH_EXCEPTION_LOCATION);
20695 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20699 if (iproc != my_rank)
20702 const unsigned n_haloed_ele_iproc = this->nroot_haloed_element(iproc);
20704 nhaloed_elements_with_iproc[iproc] = n_haloed_ele_iproc;
20707 for (
unsigned i = 0;
i < n_haloed_ele_iproc;
i++)
20709 new_domains_haloed_flat_unsigned.push_back(
20710 new_domains_haloed_elements[iproc][
i]);
20718 Vector<int> offset_haloed_elements_with_iproc(nproc);
20719 offset_haloed_elements_with_iproc[0] = 0;
20720 for (
unsigned ip = 1; ip < nproc; ip++)
20723 offset_haloed_elements_with_iproc[ip] =
20724 offset_haloed_elements_with_iproc[ip - 1] +
20725 nhaloed_elements_with_iproc[ip - 1];
20734 unsigned counter_halo_ele_with_all_procs = 0;
20741 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20745 if (iproc != my_rank)
20748 const unsigned n_halo_ele_iproc = this->nroot_halo_element(iproc);
20750 nhalo_elements_with_iproc[iproc] = n_halo_ele_iproc;
20752 counter_halo_ele_with_all_procs += n_halo_ele_iproc;
20758 Vector<int> offset_halo_elements_with_iproc(nproc);
20759 offset_halo_elements_with_iproc[0] = 0;
20760 for (
unsigned ip = 1; ip < nproc; ip++)
20763 offset_halo_elements_with_iproc[ip] =
20764 offset_halo_elements_with_iproc[ip - 1] +
20765 nhalo_elements_with_iproc[ip - 1];
20774 counter_halo_ele_with_all_procs);
20778 MPI_Alltoallv(&new_domains_haloed_flat_unsigned[0],
20779 &nhaloed_elements_with_iproc[0],
20780 &offset_haloed_elements_with_iproc[0],
20782 &new_domains_halo_flat_unsigned[0],
20783 &nhalo_elements_with_iproc[0],
20784 &offset_halo_elements_with_iproc[0],
20786 this->communicator_pt()->mpi_comm());
20792 unsigned counter_new_domains_halo_ele = 0;
20793 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20797 if (iproc != my_rank)
20800 const unsigned ntmp_halo_elements_with_iproc =
20801 nhalo_elements_with_iproc[iproc];
20804 for (
unsigned i = 0;
i < ntmp_halo_elements_with_iproc;
i++)
20808 new_domains_halo_elements[iproc][
i] =
20809 new_domains_halo_flat_unsigned[counter_new_domains_halo_ele++];
20815 if (Print_timings_level_load_balance > 1)
20817 oomph_info <<
"CPU for getting domains halo elements (load balance) [1]: "
20833 double tt_start_get_fe_version_from_ge_halo_ed = 0.0;
20834 if (Print_timings_level_load_balance > 1)
20844 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20847 if (iproc != my_rank)
20850 const unsigned nhalo_ele_iproc = this->nroot_halo_element(iproc);
20853 this->root_halo_element_pt(iproc);
20855 f_halo_element_pt[iproc].resize(nhalo_ele_iproc);
20857 for (
unsigned ih = 0; ih < nhalo_ele_iproc; ih++)
20863 f_halo_element_pt[iproc][ih] = ele_pt;
20867 const unsigned nhaloed_ele_iproc = this->nroot_haloed_element(iproc);
20870 this->root_haloed_element_pt(iproc);
20872 f_haloed_element_pt[iproc].resize(nhaloed_ele_iproc);
20874 for (
unsigned ihd = 0; ihd < nhaloed_ele_iproc; ihd++)
20878 dynamic_cast<FiniteElement*
>(haloed_element_pt_iproc[ihd]);
20880 f_haloed_element_pt[iproc][ihd] = ele_pt;
20889 if (Print_timings_level_load_balance > 1)
20891 oomph_info <<
"CPU for getting finite element versions from generalised "
20892 "halo(ed) elements (load balance) [2]: "
20894 tt_start_get_fe_version_from_ge_halo_ed
20911 double tt_start_prepare_element_to_send = 0.0;
20912 if (Print_timings_level_load_balance > 1)
20922 std::map<Data*, std::set<unsigned>>
20923 processors_associated_with_data_before_load_balance;
20927 unsigned nh_count3 = 0;
20928 for (
unsigned e = 0;
e < nelement_before_load_balance;
e++)
20936 const unsigned element_domain =
20937 target_domain_for_local_non_halo_element[nh_count3++];
20940 elements_to_send_pt[element_domain].push_back(ele_pt);
20943 const unsigned n_nodes = ele_pt->
nnode();
20945 for (
unsigned j = 0; j < n_nodes; j++)
20950 processors_associated_with_data_before_load_balance[node_pt].insert(
20963 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20966 if (iproc != my_rank)
20969 const unsigned n_halo_ele_iproc = this->nroot_halo_element(iproc);
20972 this->root_halo_element_pt(iproc);
20974 for (
unsigned ih = 0; ih < n_halo_ele_iproc; ih++)
20977 const unsigned element_domain = new_domains_halo_elements[iproc][ih];
20984 const unsigned n_nodes = ele_pt->
nnode();
20986 for (
unsigned j = 0; j < n_nodes; j++)
20992 processors_associated_with_data_before_load_balance[node_pt].insert(
21004 if (Print_timings_level_load_balance > 1)
21006 oomph_info <<
"CPU for preparing elements to send to other processors "
21007 "(load balance) [3]: "
21031 double tt_start_compute_new_local_halo_elements = 0.0;
21032 if (Print_timings_level_load_balance > 1)
21067 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21070 new_local_halo_element_pt[iproc].resize(nproc);
21079 unsigned nh_count5 = 0;
21080 for (
unsigned e = 0;
e < nelement_before_load_balance;
e++)
21088 const unsigned ele_domain =
21089 target_domain_for_local_non_halo_element[nh_count5++];
21092 if (ele_domain != iproc)
21095 const unsigned nnodes = ele_pt->
nnode();
21097 for (
unsigned j = 0; j < nnodes; j++)
21102 std::set<unsigned>::iterator it =
21103 processors_associated_with_data_before_load_balance[node_pt]
21107 processors_associated_with_data_before_load_balance[node_pt]
21114 if (!new_local_halo_already_added[ele_domain][ele_pt])
21118 new_local_halo_element_pt[iproc][ele_domain].push_back(
21121 new_local_halo_already_added[ele_domain][ele_pt] =
true;
21159 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21163 if (jproc != my_rank)
21166 const unsigned n_halo_ele_jproc = this->nroot_halo_element(jproc);
21169 this->root_halo_element_pt(jproc);
21172 for (
unsigned jh = 0; jh < n_halo_ele_jproc; jh++)
21175 const unsigned ele_domain = new_domains_halo_elements[jproc][jh];
21206 if (ele_domain != iproc)
21212 const unsigned nnodes = ele_pt->
nnode();
21214 for (
unsigned j = 0; j < nnodes; j++)
21221 std::set<unsigned>::iterator it =
21222 processors_associated_with_data_before_load_balance[node_pt]
21226 processors_associated_with_data_before_load_balance[node_pt]
21234 if (!new_local_halo_already_added[ele_domain][ele_pt])
21238 new_local_halo_element_pt[iproc][ele_domain].push_back(
21240 new_local_halo_already_added[ele_domain][ele_pt] =
true;
21269 if (Print_timings_level_load_balance > 1)
21272 <<
"CPU for computing new local halo elements (load balance) [4]: "
21292 double tt_start_compute_new_local_shd_bnd_ele = 0.0;
21293 if (Print_timings_level_load_balance > 1)
21301 new_local_halo_shared_boundary_element_pt(nproc);
21303 new_local_halo_shared_boundary_element_face_index(nproc);
21306 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21308 new_local_halo_shared_boundary_element_pt[iproc].resize(nproc);
21309 new_local_halo_shared_boundary_element_face_index[iproc].resize(nproc);
21317 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21323 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
21325 this->get_shared_boundary_elements_and_face_indexes(
21326 new_local_halo_element_pt[iproc][jproc],
21327 new_local_halo_element_pt[jproc][iproc],
21328 new_local_halo_shared_boundary_element_pt[iproc][jproc],
21329 new_local_halo_shared_boundary_element_face_index[iproc][jproc],
21330 new_local_halo_shared_boundary_element_pt[jproc][iproc],
21331 new_local_halo_shared_boundary_element_face_index[jproc][iproc]);
21336 if (Print_timings_level_load_balance > 1)
21338 oomph_info <<
"CPU for computing new local shared boundary elements "
21339 "(load balance) [5]: "
21341 tt_start_compute_new_local_shd_bnd_ele
21360 double tt_start_send_elements_to_other_processors = 0.0;
21361 if (Print_timings_level_load_balance > 1)
21369 this->sort_nodes_on_shared_boundaries();
21380 new_received_haloed_shared_boundary_element_pt(nproc);
21382 new_received_haloed_shared_boundary_element_face_index(nproc);
21388 other_proc_shd_bnd_node_pt(nproc);
21390 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21393 other_proc_shd_bnd_node_pt[iproc].resize(nproc);
21394 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21397 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
21398 const unsigned final_shd_bnd_id = this->final_shared_boundary_id();
21399 const unsigned n_shared_bound = final_shd_bnd_id - initial_shd_bnd_id;
21400 other_proc_shd_bnd_node_pt[iproc][jproc].resize(n_shared_bound);
21413 std::map<Vector<unsigned>,
unsigned> node_name_to_global_index;
21421 compute_global_node_names_and_shared_nodes(other_proc_shd_bnd_node_pt,
21423 node_name_to_global_index,
21424 global_shared_node_pt);
21430 received_old_haloed_element_pt(nproc);
21437 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21439 received_old_haloed_element_pt[iproc].resize(nproc);
21444 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21446 if (iproc != my_rank)
21460 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21465 const unsigned nelements_to_send = elements_to_send_pt[iproc].size();
21472 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21473 std::stringstream junk;
21474 junk <<
"Number of elements to send from processor " << my_rank
21475 <<
" to processor " << iproc <<
": (" << nelements_to_send <<
")";
21480 for (
unsigned e = 0;
e < nelements_to_send;
e++)
21486 const unsigned ncurrently_sent_elements =
21487 currently_sent_elements.size();
21490 const unsigned index_ele = try_to_add_element_pt_load_balance(
21491 currently_sent_elements, send_ele_pt);
21494 if (index_ele == ncurrently_sent_elements)
21497 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21499 "Element needs to be constructed");
21503 get_required_elemental_information_load_balance_helper(
21504 iproc, f_haloed_element_pt, send_ele_pt);
21507 const unsigned nnodes = send_ele_pt->
nnode();
21510 for (
unsigned j = 0; j < nnodes; j++)
21515 add_node_load_balance_helper(iproc,
21517 currently_sent_nodes,
21526 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21530 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21550 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21556 const unsigned njproc_iproc_new_local_halo_shared_boundary_ele =
21557 new_local_halo_shared_boundary_element_pt[jproc][iproc].size();
21564 unsigned nfound_new_local_halo_shared_bound_ele_index = 0;
21567 unsigned nnon_halo_new_local_halo_shared_bound_ele = 0;
21571 for (
unsigned e = 0;
21572 e < njproc_iproc_new_local_halo_shared_boundary_ele;
21577 new_local_halo_shared_boundary_element_pt[jproc][iproc][
e];
21581 if (!shared_ele_pt->
is_halo())
21583 nnon_halo_new_local_halo_shared_bound_ele++;
21588 const unsigned ncurrently_sent_elements =
21589 currently_sent_elements.size();
21591 for (
unsigned ics = 0; ics < ncurrently_sent_elements; ics++)
21594 currently_sent_elements[ics];
21597 if (currently_sent_ele_pt == shared_ele_pt)
21601 new_local_halo_shared_boundary_ele_index.push_back(ics);
21604 nfound_new_local_halo_shared_bound_ele_index++;
21616 if (nfound_new_local_halo_shared_bound_ele_index !=
21617 nnon_halo_new_local_halo_shared_bound_ele)
21619 std::ostringstream error_message;
21620 error_message <<
"Was only possible to identify ("
21621 << nfound_new_local_halo_shared_bound_ele_index
21623 << nnon_halo_new_local_halo_shared_bound_ele
21625 <<
"elements between\nprocessor (" << iproc
21626 <<
") and (" << jproc <<
") "
21627 <<
"when sending elements to processor (" << iproc
21630 OOMPH_CURRENT_FUNCTION,
21631 OOMPH_EXCEPTION_LOCATION);
21637 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21638 std::stringstream junk;
21639 junk <<
"Flag for synchronisation 9999";
21646 nnon_halo_new_local_halo_shared_bound_ele);
21647 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21648 std::stringstream junk2;
21649 junk2 <<
"Number of new local halo shared boundary elements "
21650 << nnon_halo_new_local_halo_shared_bound_ele;
21656 unsigned counter_nonhalo_sent = 0;
21659 for (
unsigned e = 0;
21660 e < njproc_iproc_new_local_halo_shared_boundary_ele;
21665 new_local_halo_shared_boundary_element_pt[jproc][iproc][
e];
21669 if (!shared_ele_pt->
is_halo())
21673 const unsigned ele_index =
21674 new_local_halo_shared_boundary_ele_index
21675 [counter_nonhalo_sent++];
21677 const unsigned face_index =
21678 new_local_halo_shared_boundary_element_face_index[jproc][iproc]
21684 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21685 std::stringstream junk;
21686 junk <<
"The index of the halo shared boundary element "
21694 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21695 std::stringstream junk2;
21696 junk2 <<
"The face index of the halo shared boundary element "
21711 int send_proc =
static_cast<int>(iproc);
21713 int recv_proc =
static_cast<int>(iproc);
21714 send_and_receive_elements_nodes_info(send_proc, recv_proc);
21729 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21731 <<
" Number of elements need to be constructed "
21737 const unsigned nelements_to_create =
21740 for (
unsigned e = 0;
e < nelements_to_create;
e++)
21744 create_element_load_balance_helper(iproc,
21745 f_haloed_element_pt,
21746 received_old_haloed_element_pt,
21747 currently_created_elements,
21748 currently_created_nodes,
21749 other_proc_shd_bnd_node_pt,
21751 node_name_to_global_index,
21752 global_shared_node_pt);
21758 const unsigned nreceived_elements = currently_created_elements.size();
21759 received_elements_pt[iproc].resize(nreceived_elements);
21760 for (
unsigned e = 0;
e < nreceived_elements;
e++)
21762 received_elements_pt[iproc][
e] = currently_created_elements[
e];
21769 new_received_haloed_shared_boundary_element_pt[iproc].resize(nproc);
21770 new_received_haloed_shared_boundary_element_face_index[iproc].resize(
21774 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21777 const unsigned synchronisation_flag =
21780 if (synchronisation_flag != 9999)
21782 std::ostringstream error_message;
21783 error_message <<
"The synchronisation flag was not read, the\n"
21784 <<
"information sent between processor (" << my_rank
21786 <<
"and (" << iproc
21787 <<
")\nis no longer synchronised\n\n";
21789 OOMPH_CURRENT_FUNCTION,
21790 OOMPH_EXCEPTION_LOCATION);
21796 const unsigned niproc_jproc_new_received_haloed_shared_boundary_ele =
21800 for (
unsigned e = 0;
21801 e < niproc_jproc_new_received_haloed_shared_boundary_ele;
21806 const unsigned ele_index =
21810 const unsigned face_index =
21815 currently_created_elements[ele_index];
21820 new_received_haloed_shared_boundary_element_pt[iproc][jproc]
21821 .push_back(shared_ele_pt);
21823 new_received_haloed_shared_boundary_element_face_index[iproc][jproc]
21824 .push_back(face_index);
21835 if (Print_timings_level_load_balance > 1)
21837 oomph_info <<
"CPU for sending elements to their new processors (load "
21840 tt_start_send_elements_to_other_processors
21859 double tt_start_compute_additional_shared_boundaries = 0.0;
21860 if (Print_timings_level_load_balance > 1)
21897 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21899 if (my_rank < iproc)
21902 this->get_shared_boundary_elements_and_face_indexes(
21903 received_elements_pt[iproc],
21904 elements_to_send_pt[iproc],
21905 tmp_group1_shared_boundary_element_pt[iproc],
21906 tmp_group1_shared_boundary_element_face_index[iproc],
21907 tmp_group2_shared_boundary_element_pt[iproc],
21908 tmp_group2_shared_boundary_element_face_index[iproc]);
21911 else if (my_rank > iproc)
21914 this->get_shared_boundary_elements_and_face_indexes(
21915 elements_to_send_pt[iproc],
21916 received_elements_pt[iproc],
21917 tmp_group1_shared_boundary_element_pt[iproc],
21918 tmp_group1_shared_boundary_element_face_index[iproc],
21919 tmp_group2_shared_boundary_element_pt[iproc],
21920 tmp_group2_shared_boundary_element_face_index[iproc]);
21927 if (Print_timings_level_load_balance > 1)
21930 <<
"CPU for computing additional shared boundaries (load balance) [7]: "
21932 tt_start_compute_additional_shared_boundaries
21951 double tt_start_sort_shared_boundaries = 0.0;
21952 if (Print_timings_level_load_balance > 1)
21977 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21980 if (my_rank < iproc)
21984 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21987 if (jproc != my_rank)
21990 const unsigned nrecvd_haloed_shared_bound_ele_jproc_iproc =
21991 new_received_haloed_shared_boundary_element_pt[jproc][iproc]
21993 for (
unsigned e = 0;
e < nrecvd_haloed_shared_bound_ele_jproc_iproc;
21998 new_received_haloed_shared_boundary_element_pt[jproc][iproc][
e];
22000 const unsigned face_index =
22001 new_received_haloed_shared_boundary_element_face_index[jproc]
22006 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
22007 new_shared_boundary_element_face_index[iproc].push_back(
22018 const unsigned nlocal_haloed_shared_bound_ele_iproc_my_rank =
22019 new_local_halo_shared_boundary_element_pt[iproc][my_rank].size();
22020 for (
unsigned e = 0;
e < nlocal_haloed_shared_bound_ele_iproc_my_rank;
22025 new_local_halo_shared_boundary_element_pt[iproc][my_rank][
e];
22027 const unsigned face_index =
22028 new_local_halo_shared_boundary_element_face_index[iproc][my_rank]
22037 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
22038 new_shared_boundary_element_face_index[iproc].push_back(face_index);
22045 const unsigned ntmp_group1_shared_bound_ele_iproc =
22046 tmp_group1_shared_boundary_element_pt[iproc].size();
22047 for (
unsigned e = 0;
e < ntmp_group1_shared_bound_ele_iproc;
e++)
22051 tmp_group1_shared_boundary_element_pt[iproc][
e];
22053 const unsigned face_index =
22054 tmp_group1_shared_boundary_element_face_index[iproc][
e];
22057 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
22058 new_shared_boundary_element_face_index[iproc].push_back(face_index);
22064 else if (my_rank > iproc)
22072 const unsigned nlocal_haloed_shared_bound_ele_iproc_my_rank =
22073 new_local_halo_shared_boundary_element_pt[iproc][my_rank].size();
22074 for (
unsigned e = 0;
e < nlocal_haloed_shared_bound_ele_iproc_my_rank;
22079 new_local_halo_shared_boundary_element_pt[iproc][my_rank][
e];
22081 const unsigned face_index =
22082 new_local_halo_shared_boundary_element_face_index[iproc][my_rank]
22091 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
22092 new_shared_boundary_element_face_index[iproc].push_back(face_index);
22097 for (
unsigned jproc = 0; jproc < nproc; jproc++)
22100 if (jproc != my_rank)
22104 const unsigned nrecvd_haloed_shared_bound_ele_jproc_iproc =
22105 new_received_haloed_shared_boundary_element_pt[jproc][iproc]
22107 for (
unsigned e = 0;
e < nrecvd_haloed_shared_bound_ele_jproc_iproc;
22112 new_received_haloed_shared_boundary_element_pt[jproc][iproc][
e];
22114 const unsigned face_index =
22115 new_received_haloed_shared_boundary_element_face_index[jproc]
22120 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
22121 new_shared_boundary_element_face_index[iproc].push_back(
22132 const unsigned ntmp_group2_shared_bound_ele_iproc =
22133 tmp_group2_shared_boundary_element_pt[iproc].size();
22134 for (
unsigned e = 0;
e < ntmp_group2_shared_bound_ele_iproc;
e++)
22138 tmp_group2_shared_boundary_element_pt[iproc][
e];
22140 const unsigned face_index =
22141 tmp_group2_shared_boundary_element_face_index[iproc][
e];
22144 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
22145 new_shared_boundary_element_face_index[iproc].push_back(face_index);
22154 if (Print_timings_level_load_balance > 1)
22156 oomph_info <<
"CPU for sorting shared boundaries (load balance) [8]: "
22178 double tt_start_create_new_shared_boundaries = 0.0;
22179 if (Print_timings_level_load_balance > 1)
22192 std::set<FiniteElement*> element_in_processor_pt;
22196 unsigned nh_count6 = 0;
22197 for (
unsigned e = 0;
e < nelement_before_load_balance;
e++)
22205 if (target_domain_for_local_non_halo_element[nh_count6++] == my_rank)
22208 element_in_processor_pt.insert(ele_pt);
22217 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22220 if (iproc != my_rank)
22224 const unsigned n_received_ele = received_elements_pt[iproc].size();
22225 for (
unsigned ie = 0; ie < n_received_ele; ie++)
22231 element_in_processor_pt.insert(ele_pt);
22240 create_new_shared_boundaries(element_in_processor_pt,
22241 new_shared_boundary_element_pt,
22242 new_shared_boundary_element_face_index);
22245 if (Print_timings_level_load_balance > 1)
22248 <<
"CPU for creating new shared boundaries (load balance) [9]: "
22271 double tt_start_delete_elements = 0.0;
22272 if (Print_timings_level_load_balance > 1)
22285 this->Halo_node_pt.clear();
22286 this->Root_halo_element_pt.clear();
22288 this->Haloed_node_pt.clear();
22289 this->Root_haloed_element_pt.clear();
22292 const unsigned nnodes = this->nnode();
22293 for (
unsigned j = 0; j < nnodes; j++)
22295 this->node_pt(j)->set_obsolete();
22299 this->flush_element_storage();
22302 this->delete_all_external_storage();
22305 this->External_halo_node_pt.clear();
22306 this->External_halo_element_pt.clear();
22308 this->External_haloed_node_pt.clear();
22309 this->External_haloed_element_pt.clear();
22315 unsigned nh_count7 = 0;
22316 for (
unsigned e = 0;
e < nelement_before_load_balance;
e++)
22322 if (target_domain_for_local_non_halo_element[nh_count7++] == my_rank)
22325 this->add_element_pt(ele_pt);
22327 const unsigned nele_nodes = ele_pt->
nnode();
22329 for (
unsigned j = 0; j < nele_nodes; j++)
22339 deleted_elements.push_back(ele_pt);
22349 deleted_elements.push_back(ele_pt);
22358 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22360 if (iproc != my_rank)
22364 const unsigned nreceived_ele = received_elements_pt[iproc].size();
22365 for (
unsigned ie = 0; ie < nreceived_ele; ie++)
22370 this->add_element_pt(ele_pt);
22372 const unsigned nele_nodes = ele_pt->
nnode();
22374 for (
unsigned j = 0; j < nele_nodes; j++)
22387 this->prune_dead_nodes();
22390 if (Print_timings_level_load_balance > 1)
22392 oomph_info <<
"CPU for deleting elements no longer belonging to this "
22393 "processor (load balance) [10]: "
22412 double tt_start_re_etablish_halo_ed_info = 0.0;
22413 if (Print_timings_level_load_balance > 1)
22422 this->sort_nodes_on_shared_boundaries();
22429 const unsigned tmp_nboundary = this->nboundary();
22435 const unsigned n_regions = this->nregion();
22438 for (
unsigned ib = 0; ib < tmp_nboundary; ib++)
22441 ntmp_boundary_elements[ib] = this->nboundary_element(ib);
22444 ntmp_boundary_elements_in_region[ib].resize(n_regions);
22447 for (
unsigned rr = 0; rr < n_regions; rr++)
22450 const unsigned region_id =
22451 static_cast<unsigned>(this->region_attribute(rr));
22456 ntmp_boundary_elements_in_region[ib][rr] =
22457 this->nboundary_element_in_region(ib, region_id);
22464 this->reset_halo_haloed_scheme();
22467 const unsigned nelement_after_load_balance = this->nelement();
22471 this->reset_boundary_element_info(ntmp_boundary_elements,
22472 ntmp_boundary_elements_in_region,
22498 for (
unsigned b = 0; b < tmp_nboundary; b++)
22500 if (this->boundary_geom_object_pt(b) != 0)
22503 this->flush_boundary_segment_node(b);
22509 get_boundary_segment_nodes_helper(b, dummy_segment_node_pt);
22512 const unsigned nsegments = dummy_segment_node_pt.size();
22516 this->set_nboundary_segment_node(b, nsegments);
22522 if (Print_timings_level_load_balance > 1)
22525 <<
"CPU for re-establishing halo(ed) information (load balance) [11]: "
22537 if (Print_timings_level_load_balance > 1)
22539 oomph_info <<
"CPU for load balance [n_ele_before="
22540 << nelement_before_load_balance
22541 <<
", n_ele_after=" << nelement_after_load_balance <<
"]: "
22546 oomph_info <<
"Load balance (unstructured mesh) [END]" << std::endl;
22554 template<
class ELEMENT>
22570 const unsigned nfirst_element = first_element_pt.size();
22572 for (
unsigned ef = 0; ef < nfirst_element; ef++)
22577 bool first_ele_is_halo =
false;
22580 first_ele_is_halo =
true;
22583 for (
unsigned ifface = 0; ifface < 3; ifface++)
22588 first_face[0] = fele_pt->
node_pt(1);
22589 first_face[1] = fele_pt->
node_pt(2);
22591 else if (ifface == 1)
22593 first_face[0] = fele_pt->
node_pt(2);
22594 first_face[1] = fele_pt->
node_pt(0);
22596 else if (ifface == 2)
22598 first_face[0] = fele_pt->
node_pt(0);
22599 first_face[1] = fele_pt->
node_pt(1);
22606 const unsigned nsecond_element = second_element_pt.size();
22608 for (
unsigned es = 0; es < nsecond_element; es++)
22613 bool second_ele_is_halo =
false;
22616 second_ele_is_halo =
true;
22623 if (!(first_ele_is_halo && second_ele_is_halo))
22626 for (
unsigned isface = 0; isface < 3; isface++)
22631 second_face[0] = sele_pt->
node_pt(1);
22632 second_face[1] = sele_pt->
node_pt(2);
22634 else if (isface == 1)
22636 second_face[0] = sele_pt->
node_pt(2);
22637 second_face[1] = sele_pt->
node_pt(0);
22639 else if (isface == 2)
22641 second_face[0] = sele_pt->
node_pt(0);
22642 second_face[1] = sele_pt->
node_pt(1);
22647 if (first_face[0] == second_face[0] &&
22648 first_face[1] == second_face[1])
22651 first_shared_boundary_element_pt.push_back(fele_pt);
22653 first_shared_boundary_element_face_index.push_back(ifface);
22656 second_shared_boundary_element_pt.push_back(sele_pt);
22658 second_shared_boundary_element_face_index.push_back(isface);
22666 es = nsecond_element;
22669 else if (first_face[0] == second_face[1] &&
22670 first_face[1] == second_face[0])
22673 first_shared_boundary_element_pt.push_back(fele_pt);
22675 first_shared_boundary_element_face_index.push_back(ifface);
22678 second_shared_boundary_element_pt.push_back(sele_pt);
22680 second_shared_boundary_element_face_index.push_back(isface);
22688 es = nsecond_element;
22707 template<
class ELEMENT>
22709 std::set<FiniteElement*>& element_in_processor_pt,
22714 const unsigned nproc = this->communicator_pt()->nproc();
22716 const unsigned my_rank = this->communicator_pt()->my_rank();
22726 double tt_start_get_edges_from_shd_bnd_face_ele = 0.0;
22727 if (Print_timings_level_load_balance > 2)
22742 std::map<std::pair<Node*, Node*>,
unsigned> elements_edges_on_boundary;
22745 this->get_element_edges_on_boundary(elements_edges_on_boundary);
22748 std::map<std::pair<Node*, Node*>,
bool> overlapped_edge;
22758 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22761 if (iproc != my_rank)
22765 const unsigned n_shared_bound_ele =
22766 new_shared_boundary_element_pt[iproc].size();
22773 unsigned nrepeated_faces = 0;
22777 for (
unsigned iele = 0; iele < n_shared_bound_ele; iele++)
22781 new_shared_boundary_element_pt[iproc][iele];
22784 int face_index =
static_cast<int>(
22785 new_shared_boundary_element_face_index[iproc][iele]);
22793 bool done_face =
false;
22797 const unsigned nnode_face_ele = tmp_ele_pt->
nnode();
22798 Node* first_face_node_pt = tmp_ele_pt->
node_pt(0);
22799 Node* last_face_node_pt = tmp_ele_pt->
node_pt(nnode_face_ele - 1);
22802 const unsigned ndone_faces = done_faces.size();
22804 for (
unsigned n = 0; n < ndone_faces; n++)
22806 Node* first_done_face_node_pt = done_faces[n].first;
22807 Node* second_done_face_node_pt = done_faces[n].second;
22808 if (first_face_node_pt == first_done_face_node_pt &&
22809 last_face_node_pt == second_done_face_node_pt)
22816 else if (first_face_node_pt == second_done_face_node_pt &&
22817 last_face_node_pt == first_done_face_node_pt)
22830 tmp_unsorted_face_ele_pt[iproc].push_back(tmp_ele_pt);
22832 tmp_unsorted_ele_pt[iproc].push_back(bulk_ele_pt);
22834 tmp_unsorted_face_index_ele[iproc].push_back(face_index);
22836 std::pair<Node*, Node*> tmp_edge =
22837 std::make_pair(first_face_node_pt, last_face_node_pt);
22839 done_faces.push_back(tmp_edge);
22843 int edge_boundary_id = -1;
22844 std::map<std::pair<Node*, Node*>,
unsigned>::iterator it;
22845 it = elements_edges_on_boundary.find(tmp_edge);
22848 if (it != elements_edges_on_boundary.end())
22852 edge_boundary_id = (*it).second;
22854 overlapped_edge[tmp_edge] =
true;
22856 std::pair<Node*, Node*> rev_tmp_edge =
22857 std::make_pair(last_face_node_pt, first_face_node_pt);
22859 overlapped_edge[rev_tmp_edge] =
true;
22864 std::pair<Node*, Node*> rtmp_edge =
22865 std::make_pair(last_face_node_pt, first_face_node_pt);
22866 it = elements_edges_on_boundary.find(rtmp_edge);
22867 if (it != elements_edges_on_boundary.end())
22871 edge_boundary_id = (*it).second;
22873 overlapped_edge[rtmp_edge] =
true;
22876 overlapped_edge[tmp_edge] =
true;
22880 tmp_edge_boundary[iproc].push_back(edge_boundary_id);
22896 if (Print_timings_level_load_balance > 2)
22898 oomph_info <<
"CPU for getting edges from shared boundary face elements "
22899 "(load balance) [9.1]: "
22901 tt_start_get_edges_from_shd_bnd_face_ele
22922 double tt_start_sort_shared_face_elements = 0.0;
22923 if (Print_timings_level_load_balance > 2)
22949 std::vector<std::vector<bool>> tmp_treat_as_inverted(nproc);
22952 std::vector<std::vector<bool>> treat_as_inverted(nproc);
22958 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22961 if (iproc != my_rank)
22964 const unsigned n_face_ele = tmp_unsorted_face_ele_pt[iproc].size();
22971 tmp_treat_as_inverted[iproc].resize(n_face_ele);
22975 for (
unsigned e = 0;
e < n_face_ele;
e++)
22978 FiniteElement* face_ele_pt = tmp_unsorted_face_ele_pt[iproc][
e];
22980 const unsigned n_node = face_ele_pt->
nnode();
22985 bottom_left[0] = node_pt->
x(0);
22986 bottom_left[1] = node_pt->
x(1);
22988 tmp_treat_as_inverted[iproc][
e] =
false;
22991 for (
unsigned n = 1; n < n_node; n++)
22995 if (node_pt->
x(1) < bottom_left[1])
22997 bottom_left[0] = node_pt->
x(0);
22998 bottom_left[1] = node_pt->
x(1);
23001 tmp_treat_as_inverted[iproc][
e] =
true;
23003 else if (node_pt->
x(1) == bottom_left[1])
23005 if (node_pt->
x(0) < bottom_left[0])
23007 bottom_left[0] = node_pt->
x(0);
23008 bottom_left[1] = node_pt->
x(1);
23011 tmp_treat_as_inverted[iproc][
e] =
true;
23018 centroid_vertices[
e].resize(2);
23020 centroid_vertices[
e][0] = (face_ele_pt->
node_pt(0)->
x(0) +
23021 face_ele_pt->
node_pt(n_node - 1)->
x(0)) *
23023 centroid_vertices[
e][1] = (face_ele_pt->
node_pt(0)->
x(1) +
23024 face_ele_pt->
node_pt(n_node - 1)->
x(1)) *
23030 unsigned n_sorted_bottom_left = 0;
23032 std::vector<bool> done_face(n_face_ele,
false);
23035 while (n_sorted_bottom_left < n_face_ele)
23038 unsigned index = 0;
23040 for (
unsigned e = 0;
e < n_face_ele;
e++)
23046 current_bottom_left[0] = centroid_vertices[
e][0];
23047 current_bottom_left[1] = centroid_vertices[
e][1];
23057 for (
unsigned e = index + 1;
e < n_face_ele;
e++)
23062 if (centroid_vertices[
e][1] < current_bottom_left[1])
23065 current_bottom_left[0] = centroid_vertices[
e][0];
23066 current_bottom_left[1] = centroid_vertices[
e][1];
23070 else if (centroid_vertices[
e][1] == current_bottom_left[1])
23072 if (centroid_vertices[
e][0] < current_bottom_left[0])
23075 current_bottom_left[0] = centroid_vertices[
e][0];
23076 current_bottom_left[1] = centroid_vertices[
e][1];
23088 unsorted_face_ele_pt[iproc].push_back(
23089 tmp_unsorted_face_ele_pt[iproc][index]);
23091 unsorted_ele_pt[iproc].push_back(tmp_unsorted_ele_pt[iproc][index]);
23093 unsorted_face_index_ele[iproc].push_back(
23094 tmp_unsorted_face_index_ele[iproc][index]);
23096 edge_boundary[iproc].push_back(tmp_edge_boundary[iproc][index]);
23098 treat_as_inverted[iproc].push_back(
23099 tmp_treat_as_inverted[iproc][index]);
23102 done_face[index] =
true;
23105 n_sorted_bottom_left++;
23112 const unsigned tmp_n_face_ele = unsorted_face_ele_pt[iproc].size();
23114 if (tmp_n_face_ele != n_face_ele)
23116 std::ostringstream error_stream;
23118 <<
"The number of face elements before sorting them starting\n"
23119 <<
"from their bottom-left vertex is different from the number\n"
23120 <<
"of face elements after the sorting\n"
23121 <<
"N. ele before sorting: (" << n_face_ele <<
")\n"
23122 <<
"N. ele after sorting: (" << tmp_n_face_ele <<
")\n";
23124 error_stream.str(),
23125 "RefineableTriangleMesh::create_new_shared_boundaries()",
23126 OOMPH_EXCEPTION_LOCATION);
23135 if (Print_timings_level_load_balance > 2)
23137 oomph_info <<
"CPU for sorting shared boundary face elements (load "
23161 double tt_start_compute_valency_of_nodes = 0.0;
23162 if (Print_timings_level_load_balance > 2)
23168 std::map<Node*, unsigned> global_node_degree;
23171 compute_shared_node_degree_helper(unsorted_face_ele_pt, global_node_degree);
23174 if (Print_timings_level_load_balance > 2)
23177 <<
"CPU for computing the valency of nodes (load balance) [9.3]: "
23196 double tt_start_nodes_on_non_overlapped_shd_bnd = 0.0;
23197 if (Print_timings_level_load_balance > 2)
23204 std::map<unsigned, std::map<Node*, bool>>
23205 node_on_bnd_not_overlapped_by_shd_bnd;
23208 for (std::map<std::pair<Node*, Node*>,
unsigned>::iterator it_map =
23209 elements_edges_on_boundary.begin();
23210 it_map != elements_edges_on_boundary.end();
23214 std::pair<Node*, Node*> edge_pair = (*it_map).first;
23216 if (!overlapped_edge[edge_pair])
23220 unsigned b = (*it_map).second;
23223 Node* left_node_pt = edge_pair.first;
23224 node_on_bnd_not_overlapped_by_shd_bnd[b][left_node_pt] =
true;
23227 Node* right_node_pt = edge_pair.second;
23228 node_on_bnd_not_overlapped_by_shd_bnd[b][right_node_pt] =
true;
23236 if (Print_timings_level_load_balance > 2)
23238 oomph_info <<
"CPU for computing nodes on non overlapped shared "
23239 "boundaries (load balance) [9.4]: "
23241 tt_start_nodes_on_non_overlapped_shd_bnd
23264 double tt_start_join_shd_bnd_face_ele = 0.0;
23265 if (Print_timings_level_load_balance > 2)
23297 std::map<unsigned, std::list<Node*>>
23298 local_shd_bnd_id_to_sorted_list_node_pt;
23303 unsigned local_shd_bnd_id = this->Initial_shared_boundary_id;
23308 std::map<FiniteElement*, bool> done_ele;
23311 std::map<FiniteElement*, bool> is_inverted;
23315 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23318 if (iproc != my_rank)
23322 const unsigned nunsorted_face_ele = unsorted_face_ele_pt[iproc].size();
23324 unsigned nsorted_face_ele = 0;
23327 while (nsorted_face_ele < nunsorted_face_ele)
23336 bool found_root_element =
false;
23340 unsigned root_index = 0;
23343 std::list<FiniteElement*> tmp_sorted_face_ele_pt;
23346 std::list<FiniteElement*> tmp_sorted_ele_pt;
23350 std::list<int> tmp_sorted_face_index_ele;
23355 std::list<Node*> tmp_sorted_nodes_pt;
23357 tmp_sorted_nodes_pt.clear();
23360 Node* initial_node_pt = 0;
23361 Node* final_node_pt = 0;
23365 int root_edge_bound_id = -1;
23369 for (
unsigned e = 0;
e < nunsorted_face_ele;
e++)
23374 if (!done_ele[root_ele_pt])
23378 root_edge_bound_id = edge_boundary[iproc][
e];
23381 tmp_sorted_face_ele_pt.push_back(root_ele_pt);
23383 tmp_sorted_ele_pt.push_back(unsorted_ele_pt[iproc][
e]);
23386 tmp_sorted_face_index_ele.push_back(
23387 unsorted_face_index_ele[iproc][
e]);
23390 const unsigned nnodes = root_ele_pt->
nnode();
23392 if (!treat_as_inverted[iproc][
e])
23394 initial_node_pt = root_ele_pt->
node_pt(0);
23395 final_node_pt = root_ele_pt->
node_pt(nnodes - 1);
23399 initial_node_pt = root_ele_pt->
node_pt(nnodes - 1);
23400 final_node_pt = root_ele_pt->
node_pt(0);
23403 tmp_sorted_nodes_pt.push_back(initial_node_pt);
23404 tmp_sorted_nodes_pt.push_back(final_node_pt);
23407 done_ele[root_ele_pt] =
true;
23409 if (!treat_as_inverted[iproc][
e])
23412 is_inverted[root_ele_pt] =
false;
23417 is_inverted[root_ele_pt] =
true;
23420 nsorted_face_ele++;
23425 found_root_element =
true;
23435 if (!found_root_element)
23437 std::ostringstream error_stream;
23439 <<
"It was not possible the found the root element\n\n";
23441 OOMPH_CURRENT_FUNCTION,
23442 OOMPH_EXCEPTION_LOCATION);
23450 bool new_element_added =
true;
23460 bool element_added_to_the_left =
false;
23461 bool element_added_to_the_right =
false;
23465 bool connection_to_the_left =
false;
23469 bool connection_to_the_right =
false;
23474 bool current_polyline_has_connections_at_both_ends =
false;
23486 int bound_id_connection_to_the_left = -1;
23487 int bound_id_connection_to_the_right = -1;
23491 const unsigned initial_node_degree =
23492 global_node_degree[initial_node_pt];
23496 const bool called_for_load_balance =
true;
23500 bound_id_connection_to_the_left =
23501 this->check_connections_of_polyline_nodes(
23502 element_in_processor_pt,
23503 root_edge_bound_id,
23505 node_on_bnd_not_overlapped_by_shd_bnd,
23506 tmp_sorted_nodes_pt,
23507 local_shd_bnd_id_to_sorted_list_node_pt,
23508 initial_node_degree,
23510 called_for_load_balance);
23514 if (bound_id_connection_to_the_left != -1)
23516 connection_to_the_left =
true;
23521 const unsigned final_node_degree = global_node_degree[final_node_pt];
23524 bound_id_connection_to_the_right =
23525 this->check_connections_of_polyline_nodes(
23526 element_in_processor_pt,
23527 root_edge_bound_id,
23529 node_on_bnd_not_overlapped_by_shd_bnd,
23530 tmp_sorted_nodes_pt,
23531 local_shd_bnd_id_to_sorted_list_node_pt,
23534 called_for_load_balance);
23538 if (bound_id_connection_to_the_right != -1)
23540 connection_to_the_right =
true;
23545 if (connection_to_the_left && connection_to_the_right)
23547 current_polyline_has_connections_at_both_ends =
true;
23556 while (new_element_added && (nsorted_face_ele < nunsorted_face_ele) &&
23557 !current_polyline_has_connections_at_both_ends)
23563 for (
unsigned e = root_index;
e < nunsorted_face_ele;
e++)
23566 new_element_added =
false;
23567 element_added_to_the_left =
false;
23568 element_added_to_the_right =
false;
23573 const int edge_bound_id = edge_boundary[iproc][
e];
23577 if (!done_ele[tmp_ele_pt] &&
23578 (edge_bound_id == root_edge_bound_id))
23581 const unsigned nnodes = tmp_ele_pt->
nnode();
23584 Node* first_node_pt = 0;
23585 Node* last_node_pt = 0;
23586 if (!treat_as_inverted[iproc][
e])
23588 first_node_pt = tmp_ele_pt->
node_pt(0);
23589 last_node_pt = tmp_ele_pt->
node_pt(nnodes - 1);
23593 first_node_pt = tmp_ele_pt->
node_pt(nnodes - 1);
23594 last_node_pt = tmp_ele_pt->
node_pt(0);
23600 Node* new_added_node_pt = 0;
23603 if (initial_node_pt == last_node_pt && !connection_to_the_left)
23606 new_added_node_pt = initial_node_pt = first_node_pt;
23608 tmp_sorted_nodes_pt.push_front(first_node_pt);
23611 tmp_sorted_face_ele_pt.push_front(tmp_ele_pt);
23613 tmp_sorted_ele_pt.push_front(unsorted_ele_pt[iproc][
e]);
23616 tmp_sorted_face_index_ele.push_front(
23617 unsorted_face_index_ele[iproc][
e]);
23618 if (!treat_as_inverted[iproc][
e])
23621 is_inverted[tmp_ele_pt] =
false;
23626 is_inverted[tmp_ele_pt] =
true;
23629 new_element_added =
true;
23632 element_added_to_the_left =
true;
23635 else if (initial_node_pt == first_node_pt &&
23636 !connection_to_the_left)
23639 new_added_node_pt = initial_node_pt = last_node_pt;
23641 tmp_sorted_nodes_pt.push_front(last_node_pt);
23644 tmp_sorted_face_ele_pt.push_front(tmp_ele_pt);
23646 tmp_sorted_ele_pt.push_front(unsorted_ele_pt[iproc][
e]);
23649 tmp_sorted_face_index_ele.push_front(
23650 unsorted_face_index_ele[iproc][
e]);
23651 if (!treat_as_inverted[iproc][
e])
23654 is_inverted[tmp_ele_pt] =
true;
23659 is_inverted[tmp_ele_pt] =
false;
23662 new_element_added =
true;
23665 element_added_to_the_left =
true;
23668 else if (final_node_pt == first_node_pt &&
23669 !connection_to_the_right)
23672 new_added_node_pt = final_node_pt = last_node_pt;
23674 tmp_sorted_nodes_pt.push_back(last_node_pt);
23677 tmp_sorted_face_ele_pt.push_back(tmp_ele_pt);
23679 tmp_sorted_ele_pt.push_back(unsorted_ele_pt[iproc][
e]);
23682 tmp_sorted_face_index_ele.push_back(
23683 unsorted_face_index_ele[iproc][
e]);
23684 if (!treat_as_inverted[iproc][
e])
23687 is_inverted[tmp_ele_pt] =
false;
23692 is_inverted[tmp_ele_pt] =
true;
23695 new_element_added =
true;
23698 element_added_to_the_right =
true;
23701 else if (final_node_pt == last_node_pt &&
23702 !connection_to_the_right)
23705 new_added_node_pt = final_node_pt = first_node_pt;
23707 tmp_sorted_nodes_pt.push_back(first_node_pt);
23710 tmp_sorted_face_ele_pt.push_back(tmp_ele_pt);
23712 tmp_sorted_ele_pt.push_back(unsorted_ele_pt[iproc][
e]);
23715 tmp_sorted_face_index_ele.push_back(
23716 unsorted_face_index_ele[iproc][
e]);
23717 if (!treat_as_inverted[iproc][
e])
23720 is_inverted[tmp_ele_pt] =
true;
23725 is_inverted[tmp_ele_pt] =
false;
23728 new_element_added =
true;
23731 element_added_to_the_right =
true;
23735 if (new_element_added)
23738 done_ele[tmp_ele_pt] =
true;
23740 nsorted_face_ele++;
23744 const unsigned new_added_node_degree =
23745 global_node_degree[new_added_node_pt];
23754 if (element_added_to_the_left && !connection_to_the_left)
23757 bound_id_connection_to_the_left =
23758 this->check_connections_of_polyline_nodes(
23759 element_in_processor_pt,
23760 root_edge_bound_id,
23762 node_on_bnd_not_overlapped_by_shd_bnd,
23763 tmp_sorted_nodes_pt,
23764 local_shd_bnd_id_to_sorted_list_node_pt,
23765 new_added_node_degree,
23767 called_for_load_balance);
23771 if (bound_id_connection_to_the_left != -1)
23773 connection_to_the_left =
true;
23783 if (element_added_to_the_right && !connection_to_the_right)
23786 bound_id_connection_to_the_right =
23787 this->check_connections_of_polyline_nodes(
23788 element_in_processor_pt,
23789 root_edge_bound_id,
23791 node_on_bnd_not_overlapped_by_shd_bnd,
23792 tmp_sorted_nodes_pt,
23793 local_shd_bnd_id_to_sorted_list_node_pt,
23794 new_added_node_degree,
23796 called_for_load_balance);
23800 if (bound_id_connection_to_the_right != -1)
23802 connection_to_the_right =
true;
23811 if (connection_to_the_left && connection_to_the_right)
23813 current_polyline_has_connections_at_both_ends =
true;
23839 for (std::list<FiniteElement*>::iterator it =
23840 tmp_sorted_ele_pt.begin();
23841 it != tmp_sorted_ele_pt.end();
23844 tmp_vector_sorted_ele_pt.push_back((*it));
23851 for (std::list<FiniteElement*>::iterator it =
23852 tmp_sorted_face_ele_pt.begin();
23853 it != tmp_sorted_face_ele_pt.end();
23856 tmp_vector_sorted_face_ele_pt.push_back((*it));
23862 for (std::list<int>::iterator it = tmp_sorted_face_index_ele.begin();
23863 it != tmp_sorted_face_index_ele.end();
23866 tmp_vector_sorted_face_index_ele.push_back((*it));
23881 Vector<int> final_bound_id_connection_to_the_left;
23884 Vector<int> final_bound_id_connection_to_the_right;
23887 this->break_loops_on_shared_polyline_load_balance_helper(
23889 tmp_sorted_nodes_pt,
23890 tmp_vector_sorted_ele_pt,
23891 tmp_vector_sorted_face_ele_pt,
23892 tmp_vector_sorted_face_index_ele,
23893 bound_id_connection_to_the_left,
23894 bound_id_connection_to_the_right,
23895 final_sorted_nodes_pt,
23896 final_boundary_element_pt,
23897 final_boundary_face_element_pt,
23898 final_face_index_element,
23899 final_bound_id_connection_to_the_left,
23900 final_bound_id_connection_to_the_right);
23903 const unsigned n_final_sorted_nodes = final_sorted_nodes_pt.size();
23906 for (
unsigned i = 0;
i < n_final_sorted_nodes;
i++)
23910 local_shd_bnd_id_to_sorted_list_node_pt[local_shd_bnd_id] =
23911 final_sorted_nodes_pt[
i];
23915 proc_local_shared_boundary_id[iproc].push_back(local_shd_bnd_id);
23920 local_shd_bnd_id++;
23923 sorted_ele_pt[iproc].push_back(final_boundary_element_pt[
i]);
23926 sorted_face_ele_pt[iproc].push_back(
23927 final_boundary_face_element_pt[
i]);
23930 sorted_face_index_ele[iproc].push_back(final_face_index_element[
i]);
23933 edge_boundary_id[iproc].push_back(root_edge_bound_id);
23940 bnd_connections_ids[0] = final_bound_id_connection_to_the_left[
i];
23941 bnd_connections_ids[1] = final_bound_id_connection_to_the_right[
i];
23942 sorted_connection_info[iproc].push_back(bnd_connections_ids);
23954 if (Print_timings_level_load_balance > 2)
23956 oomph_info <<
"CPU for joining shared boundary face elements (load "
23986 double tt_start_get_new_shared_boundaries_ids = 0.0;
23987 if (Print_timings_level_load_balance > 2)
23995 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23998 if (iproc != my_rank)
24002 nshared_boundaries_with_processor[iproc] =
24003 sorted_face_ele_pt[iproc].size();
24013 const unsigned root_processor = 0;
24024 MPI_Gather(&nshared_boundaries_with_processor[0],
24029 &flat_unsigned_root_received_data[0],
24037 comm_pt->mpi_comm());
24046 unsigned new_initial_shared_boundary_id = 0;
24047 unsigned new_final_shared_boundary_id = 0;
24050 if (my_rank == root_processor)
24057 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24060 root_nshared_bound_proc_with_proc[iproc].resize(nproc);
24063 for (
unsigned jproc = 0; jproc < nproc; jproc++)
24065 root_nshared_bound_proc_with_proc[iproc][jproc] =
24066 flat_unsigned_root_received_data[(iproc * nproc) + jproc];
24075 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24077 for (
unsigned jproc = 0; jproc < iproc; jproc++)
24079 if (root_nshared_bound_proc_with_proc[iproc][jproc] !=
24080 root_nshared_bound_proc_with_proc[jproc][iproc])
24082 std::ostringstream error_stream;
24084 <<
"ROOT PROCESSOR ERROR\n\n"
24085 <<
"The number of shared boundaries between processor (" << iproc
24086 <<
") and (" << jproc <<
") is not the same:\n"
24087 <<
"Shared boundaries of processor (" << iproc
24088 <<
") with processor (" << jproc <<
"): ("
24089 << root_nshared_bound_proc_with_proc[iproc][jproc] <<
")\n"
24090 <<
"Shared boundaries of processor (" << jproc
24091 <<
") with processor (" << iproc <<
"): ("
24092 << root_nshared_bound_proc_with_proc[jproc][iproc] <<
")\n\n";
24094 OOMPH_CURRENT_FUNCTION,
24095 OOMPH_EXCEPTION_LOCATION);
24114 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24116 start_shared_bound_id_proc_with_proc[iproc].resize(nproc);
24121 unsigned shared_bound_id = this->nboundary();
24124 new_initial_shared_boundary_id = shared_bound_id;
24127 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24129 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
24132 if (root_nshared_bound_proc_with_proc[iproc][jproc] > 0)
24136 start_shared_bound_id_proc_with_proc[iproc][jproc] =
24138 start_shared_bound_id_proc_with_proc[jproc][iproc] =
24143 shared_bound_id += root_nshared_bound_proc_with_proc[iproc][jproc];
24151 new_final_shared_boundary_id = shared_bound_id;
24154 Vector<unsigned> send_start_shared_bound_id_proc_with_proc(nproc * nproc);
24158 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24160 for (
unsigned jproc = 0; jproc < nproc; jproc++)
24164 const unsigned initial_shd_bnd_id =
24165 start_shared_bound_id_proc_with_proc[iproc][jproc];
24166 flat_unsigned_root_send_receive_data.push_back(initial_shd_bnd_id);
24170 const unsigned nshared_bnd_iproc_jproc =
24171 root_nshared_bound_proc_with_proc[iproc][jproc];
24172 flat_unsigned_root_send_receive_data.push_back(
24173 nshared_bnd_iproc_jproc);
24181 flat_unsigned_root_send_receive_data.push_back(
24182 new_initial_shared_boundary_id);
24185 flat_unsigned_root_send_receive_data.push_back(
24186 new_final_shared_boundary_id);
24197 unsigned root_ndata_sent_to_all_proc =
24198 flat_unsigned_root_send_receive_data.size();
24200 MPI_Bcast(&root_ndata_sent_to_all_proc,
24204 comm_pt->mpi_comm());
24207 if (my_rank != root_processor)
24209 flat_unsigned_root_send_receive_data.resize(root_ndata_sent_to_all_proc);
24214 MPI_Bcast(&flat_unsigned_root_send_receive_data[0],
24217 root_ndata_sent_to_all_proc,
24221 comm_pt->mpi_comm());
24233 unsigned iflat_counter = 0;
24235 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24238 initial_shared_bound_id_proc_with_proc[iproc].resize(nproc);
24239 nshared_bound_proc_with_proc[iproc].resize(nproc);
24242 for (
unsigned jproc = 0; jproc < nproc; jproc++)
24246 initial_shared_bound_id_proc_with_proc[iproc][jproc] =
24247 flat_unsigned_root_send_receive_data[iflat_counter++];
24251 nshared_bound_proc_with_proc[iproc][jproc] =
24252 flat_unsigned_root_send_receive_data[iflat_counter++];
24259 new_initial_shared_boundary_id =
24260 flat_unsigned_root_send_receive_data[root_ndata_sent_to_all_proc - 2];
24263 new_final_shared_boundary_id =
24264 flat_unsigned_root_send_receive_data[root_ndata_sent_to_all_proc - 1];
24267 if (Print_timings_level_load_balance > 2)
24270 <<
"CPU for computing new shared boundaries ids (load balance) [9.6]: "
24292 double tt_start_create_new_shared_boundaries_polylines = 0.0;
24293 if (Print_timings_level_load_balance > 2)
24305 this->flush_shared_boundary_polyline_pt();
24306 this->Shared_boundary_polyline_pt.resize(nproc);
24309 this->Shared_boundaries_ids.clear();
24310 this->Shared_boundaries_ids.resize(nproc);
24311 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24313 this->Shared_boundaries_ids[iproc].clear();
24314 this->Shared_boundaries_ids[iproc].resize(nproc);
24318 this->Shared_boundary_from_processors.clear();
24319 this->Shared_boundary_overlaps_internal_boundary.clear();
24320 this->Boundary_was_splitted.clear();
24321 this->Boundary_subpolylines.clear();
24322 this->Boundary_marked_as_shared_boundary.clear();
24325 this->flush_shared_boundary_element();
24326 this->flush_face_index_at_shared_boundary();
24327 this->flush_shared_boundary_node();
24328 this->flush_sorted_shared_boundary_node();
24332 const unsigned old_local_shd_bnd_id = this->Initial_shared_boundary_id;
24335 this->Initial_shared_boundary_id = new_initial_shared_boundary_id;
24336 this->Final_shared_boundary_id = new_final_shared_boundary_id;
24346 std::map<unsigned, unsigned> local_to_global_shd_bnd_id;
24353 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24359 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
24364 if (iproc == my_rank || jproc == my_rank)
24367 unsigned ref_proc = 0;
24368 if (iproc == my_rank)
24372 else if (jproc == my_rank)
24379 const unsigned nshared_bound_iproc_jproc =
24380 nshared_bound_proc_with_proc[iproc][jproc];
24383 for (
unsigned counter = 0; counter < nshared_bound_iproc_jproc;
24387 const unsigned shd_bnd_id =
24388 initial_shared_bound_id_proc_with_proc[iproc][jproc] + counter;
24391 this->Shared_boundaries_ids[iproc][jproc].push_back(shd_bnd_id);
24392 this->Shared_boundaries_ids[jproc][iproc].push_back(shd_bnd_id);
24397 processors[0] = iproc;
24398 processors[1] = jproc;
24399 this->Shared_boundary_from_processors[shd_bnd_id] = processors;
24404 int root_edge_bound_id = edge_boundary_id[ref_proc][counter];
24407 if (root_edge_bound_id != -1)
24411 this->Shared_boundary_overlaps_internal_boundary[shd_bnd_id] =
24412 static_cast<unsigned>(root_edge_bound_id);
24425 sorted_face_ele_pt[ref_proc][counter][0];
24428 const unsigned first_face_ele_nnodes = first_face_ele_pt->
nnode();
24429 if (!is_inverted[first_face_ele_pt])
24432 Node* first_node_pt = first_face_ele_pt->
node_pt(0);
24434 node_pt_to_create_shared_polyline.push_back(first_node_pt);
24436 this->add_shared_boundary_node(shd_bnd_id, first_node_pt);
24441 Node* first_node_pt =
24442 first_face_ele_pt->
node_pt(first_face_ele_nnodes - 1);
24444 node_pt_to_create_shared_polyline.push_back(first_node_pt);
24446 this->add_shared_boundary_node(shd_bnd_id, first_node_pt);
24454 const unsigned nshared_boundary_elements =
24455 sorted_face_ele_pt[ref_proc][counter].size();
24459 for (
unsigned ie = 0; ie < nshared_boundary_elements; ie++)
24462 FiniteElement* bulk_ele_pt = sorted_ele_pt[ref_proc][counter][ie];
24466 this->add_shared_boundary_element(shd_bnd_id, bulk_ele_pt);
24470 const int face_index =
24471 sorted_face_index_ele[ref_proc][counter][ie];
24475 this->add_face_index_at_shared_boundary(shd_bnd_id, face_index);
24479 sorted_face_ele_pt[ref_proc][counter][ie];
24482 const unsigned nnodes = face_ele_pt->
nnode();
24483 if (!is_inverted[face_ele_pt])
24487 for (
unsigned n = 1; n < nnodes; n++)
24492 this->add_shared_boundary_node(shd_bnd_id, node_pt);
24498 Node* last_node_pt = face_ele_pt->
node_pt(nnodes - 1);
24499 node_pt_to_create_shared_polyline.push_back(last_node_pt);
24505 for (
int n = nnodes - 2; n >= 0; n--)
24510 this->add_shared_boundary_node(shd_bnd_id, node_pt);
24517 node_pt_to_create_shared_polyline.push_back(last_node_pt);
24524 const unsigned nnodes_to_create_shared_boundary =
24525 node_pt_to_create_shared_polyline.size();
24529 for (
unsigned n = 0; n < nnodes_to_create_shared_boundary; n++)
24531 vertices[n].resize(2);
24533 Node* tmp_node_pt = node_pt_to_create_shared_polyline[n];
24535 vertices[n][0] = tmp_node_pt->
x(0);
24536 vertices[n][1] = tmp_node_pt->
x(1);
24544 this->Boundary_curve_section_pt[shd_bnd_id] = polyline_pt;
24548 unsorted_polylines_pt.push_back(polyline_pt);
24551 this->Free_curve_section_pt.insert(polyline_pt);
24557 const unsigned local_shd_bnd_id =
24558 proc_local_shared_boundary_id[ref_proc][counter];
24562 local_to_global_shd_bnd_id[local_shd_bnd_id] = shd_bnd_id;
24569 int tmp_bnd_id_connection_to_the_left =
24570 sorted_connection_info[ref_proc][counter][0];
24572 int tmp_bnd_id_connection_to_the_right =
24573 sorted_connection_info[ref_proc][counter][1];
24577 int bnd_id_connection_to_the_left = -1;
24578 int bnd_id_connection_to_the_right = -1;
24585 if (tmp_bnd_id_connection_to_the_left == -2)
24588 bnd_id_connection_to_the_left = shd_bnd_id;
24592 if (tmp_bnd_id_connection_to_the_left == -3)
24595 bnd_id_connection_to_the_left = -1;
24600 if (tmp_bnd_id_connection_to_the_left >=
24601 static_cast<int>(old_local_shd_bnd_id))
24606 std::map<unsigned, unsigned>::iterator it =
24607 local_to_global_shd_bnd_id.find(
24608 static_cast<unsigned>(tmp_bnd_id_connection_to_the_left));
24611 if (it == local_to_global_shd_bnd_id.end())
24613 std::stringstream error_message;
24615 <<
"The global shared boundary id was not found for\n"
24616 <<
"the local shared boundary shared with processor ("
24617 << ref_proc <<
").\n"
24618 <<
"This processor: (" << my_rank <<
")\n"
24619 <<
"Boundary shared with processor: (" << ref_proc <<
")\n"
24620 <<
"Local shared boundary: ("
24621 << tmp_bnd_id_connection_to_the_left <<
")\n";
24623 OOMPH_CURRENT_FUNCTION,
24624 OOMPH_EXCEPTION_LOCATION);
24629 bnd_id_connection_to_the_left =
24630 local_to_global_shd_bnd_id[
static_cast<unsigned>(
24631 tmp_bnd_id_connection_to_the_left)];
24637 bnd_id_connection_to_the_left = tmp_bnd_id_connection_to_the_left;
24646 if (tmp_bnd_id_connection_to_the_right == -2)
24649 bnd_id_connection_to_the_right = shd_bnd_id;
24653 if (tmp_bnd_id_connection_to_the_right == -3)
24656 bnd_id_connection_to_the_right = -1;
24661 if (tmp_bnd_id_connection_to_the_right >=
24662 static_cast<int>(old_local_shd_bnd_id))
24667 std::map<unsigned, unsigned>::iterator it =
24668 local_to_global_shd_bnd_id.find(
24669 static_cast<unsigned>(tmp_bnd_id_connection_to_the_right));
24672 if (it == local_to_global_shd_bnd_id.end())
24674 std::stringstream error_message;
24676 <<
"The global shared boundary id was not found for\n"
24677 <<
"the local shared boundary shared with processor ("
24678 << ref_proc <<
").\n"
24679 <<
"This processor: (" << my_rank <<
")\n"
24680 <<
"Boundary shared with processor: (" << ref_proc <<
")\n"
24681 <<
"Local shared boundary: ("
24682 << tmp_bnd_id_connection_to_the_right <<
")\n";
24684 OOMPH_CURRENT_FUNCTION,
24685 OOMPH_EXCEPTION_LOCATION);
24689 bnd_id_connection_to_the_right =
24690 local_to_global_shd_bnd_id[
static_cast<unsigned>(
24691 tmp_bnd_id_connection_to_the_right)];
24697 bnd_id_connection_to_the_right =
24698 tmp_bnd_id_connection_to_the_right;
24704 if (bnd_id_connection_to_the_left != -1)
24707 const unsigned ubnd_id_connection_to_the_left =
24708 static_cast<unsigned>(bnd_id_connection_to_the_left);
24713 ubnd_id_connection_to_the_left;
24721 if (bnd_id_connection_to_the_right != -1)
24725 const unsigned ubnd_id_connection_to_the_right =
24726 static_cast<unsigned>(bnd_id_connection_to_the_right);
24731 ubnd_id_connection_to_the_right;
24747 const unsigned nshared_bound_iproc_jproc =
24748 nshared_bound_proc_with_proc[iproc][jproc];
24750 for (
unsigned counter = 0; counter < nshared_bound_iproc_jproc;
24754 const unsigned shd_bnd_id =
24755 initial_shared_bound_id_proc_with_proc[iproc][jproc] + counter;
24758 this->Shared_boundaries_ids[iproc][jproc].push_back(shd_bnd_id);
24759 this->Shared_boundaries_ids[jproc][iproc].push_back(shd_bnd_id);
24764 processors[0] = iproc;
24765 processors[1] = jproc;
24766 this->Shared_boundary_from_processors[shd_bnd_id] = processors;
24777 if (Print_timings_level_load_balance > 2)
24779 oomph_info <<
"CPU for creating new shared boundaries representations "
24780 "(load balance) [9.7]: "
24782 tt_start_create_new_shared_boundaries_polylines
24800 double tt_start_create_new_shared_curves = 0.0;
24801 if (Print_timings_level_load_balance > 2)
24808 if (unsorted_polylines_pt.size() > 0)
24812 this->sort_polylines_helper(unsorted_polylines_pt,
24813 this->Shared_boundary_polyline_pt[my_rank]);
24817 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24819 const unsigned nface_ele = unsorted_face_ele_pt[iproc].size();
24820 for (
unsigned e = 0;
e < nface_ele;
e++)
24822 delete unsorted_face_ele_pt[iproc][
e];
24823 unsorted_face_ele_pt[iproc][
e] = 0;
24829 if (Print_timings_level_load_balance > 2)
24832 <<
"CPU for creating the new shared curves (load balance) [9.8]: "
24850 template<
class ELEMENT>
24853 std::map<Node*, unsigned>& global_node_degree)
24856 const unsigned nproc = this->communicator_pt()->nproc();
24857 const unsigned my_rank = this->communicator_pt()->my_rank();
24868 std::map<Node*, Vector<Vector<unsigned>>> node_alias;
24876 create_adjacency_matrix_new_shared_edges_helper(unsorted_face_ele_pt,
24877 tmp_sorted_shared_node_pt,
24879 local_adjacency_matrix);
24892 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24895 package_unsigned_send_data_to_root.push_back(iproc);
24898 const unsigned n_nodes = tmp_sorted_shared_node_pt[iproc].size();
24901 package_unsigned_send_data_to_root.push_back(n_nodes);
24904 for (
unsigned ishd = 0; ishd < n_nodes; ishd++)
24907 Node* shd_node_pt = tmp_sorted_shared_node_pt[iproc][ishd];
24913 const unsigned n_alias = alias_node_info.size();
24916 package_unsigned_send_data_to_root.push_back(n_alias);
24919 for (
unsigned i = 0;
i < n_alias;
i++)
24923 package_unsigned_send_data_to_root.push_back(alias_node_info[
i][0]);
24925 package_unsigned_send_data_to_root.push_back(alias_node_info[
i][1]);
24927 package_unsigned_send_data_to_root.push_back(alias_node_info[
i][2]);
24933 for (
unsigned i = 0;
i < n_nodes;
i++)
24935 for (
unsigned j = 0; j < n_nodes; j++)
24938 package_unsigned_send_data_to_root.push_back(
24939 local_adjacency_matrix[iproc][
i][j]);
24948 const unsigned root_processor = 0;
24954 unsigned n_unsigned_data_send_to_root =
24955 package_unsigned_send_data_to_root.size();
24958 Vector<int> n_unsigned_data_received_in_root(nproc, 0);
24962 MPI_Gather(&n_unsigned_data_send_to_root,
24966 &n_unsigned_data_received_in_root[0],
24974 comm_pt->mpi_comm());
24977 unsigned n_unsigned_total_data_receive_in_root = 0;
24978 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24981 n_unsigned_total_data_receive_in_root +=
24982 n_unsigned_data_received_in_root[iproc];
24986 Vector<int> root_unsigned_offsets_receive(nproc, 0);
24987 root_unsigned_offsets_receive[0] = 0;
24988 for (
unsigned iproc = 1; iproc < nproc; iproc++)
24992 root_unsigned_offsets_receive[iproc] =
24993 root_unsigned_offsets_receive[iproc - 1] +
24994 n_unsigned_data_received_in_root[iproc - 1];
24998 if (package_unsigned_send_data_to_root.size() == 0)
25000 package_unsigned_send_data_to_root.resize(1);
25005 n_unsigned_total_data_receive_in_root);
25006 if (my_rank != root_processor)
25009 if (package_unsigned_data_received_root.size() == 0)
25011 package_unsigned_data_received_root.resize(1);
25016 MPI_Gatherv(&package_unsigned_send_data_to_root[0],
25021 n_unsigned_data_send_to_root,
25025 &package_unsigned_data_received_root[0],
25031 &n_unsigned_data_received_in_root[0],
25034 &root_unsigned_offsets_receive[0],
25041 comm_pt->mpi_comm());
25046 Vector<int> n_unsigned_data_sent_from_root(nproc, 0);
25050 if (my_rank == root_processor)
25054 unsigned decode_counter = 0;
25067 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25069 local_node_alias[iproc].resize(nproc);
25073 local_adjacency_matrix[iproc].resize(nproc);
25075 if (n_unsigned_data_received_in_root[iproc] > 0)
25079 for (
unsigned jproc = 0; jproc < nproc; jproc++)
25082 const unsigned read_jproc =
25083 package_unsigned_data_received_root[decode_counter++];
25087 if (read_jproc != jproc)
25089 std::ostringstream error_stream;
25091 <<
"The read processor is different from the jproc, this is\n"
25092 <<
"a synchronisation issue. The data are not read in the\n"
25093 <<
"sameorder as the were packaged\n"
25094 <<
"Read processor: (" << read_jproc <<
")\n"
25095 <<
"Current jproc: (" << jproc <<
")\n\n";
25097 error_stream.str(),
25098 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25099 OOMPH_EXCEPTION_LOCATION);
25104 const unsigned read_n_shd_nodes_iproc_jproc =
25105 package_unsigned_data_received_root[decode_counter++];
25108 local_node_alias[iproc][jproc].resize(read_n_shd_nodes_iproc_jproc);
25112 for (
unsigned ishd = 0; ishd < read_n_shd_nodes_iproc_jproc; ishd++)
25115 const unsigned read_n_alias_node_iproc_jproc =
25116 package_unsigned_data_received_root[decode_counter++];
25119 local_node_alias[iproc][jproc][ishd].resize(
25120 read_n_alias_node_iproc_jproc);
25122 for (
unsigned ialias = 0; ialias < read_n_alias_node_iproc_jproc;
25127 local_node_alias[iproc][jproc][ishd][ialias].resize(3);
25130 local_node_alias[iproc][jproc][ishd][ialias][0] =
25131 package_unsigned_data_received_root[decode_counter++];
25134 local_node_alias[iproc][jproc][ishd][ialias][1] =
25135 package_unsigned_data_received_root[decode_counter++];
25138 local_node_alias[iproc][jproc][ishd][ialias][2] =
25139 package_unsigned_data_received_root[decode_counter++];
25146 local_adjacency_matrix[iproc][jproc].resize(
25147 read_n_shd_nodes_iproc_jproc);
25149 for (
unsigned i = 0;
i < read_n_shd_nodes_iproc_jproc;
i++)
25152 local_adjacency_matrix[iproc][jproc][
i].resize(
25153 read_n_shd_nodes_iproc_jproc);
25154 for (
unsigned j = 0; j < read_n_shd_nodes_iproc_jproc; j++)
25157 local_adjacency_matrix[iproc][jproc][
i][j] =
25158 package_unsigned_data_received_root[decode_counter++];
25170 if (decode_counter != n_unsigned_total_data_receive_in_root)
25172 std::ostringstream error_stream;
25174 <<
"The number of data decoded in root received from others\n"
25175 <<
"processors is different from the total number of data received\n"
25176 <<
"Data decoded: (" << decode_counter <<
")\n"
25177 <<
"Data received: (" << n_unsigned_total_data_receive_in_root
25179 <<
"This is a synchronisation issue so you are probably sending\n"
25180 <<
"more or less info. than the one that is being decoded\n\n";
25182 error_stream.str(),
25183 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25184 OOMPH_EXCEPTION_LOCATION);
25194 std::map<Vector<unsigned>,
bool> alias_done;
25200 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25202 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25205 const unsigned n_shd_nodes_iproc_jproc =
25206 local_node_alias[iproc][jproc].size();
25209 const unsigned n_shd_nodes_jproc_iproc =
25210 local_node_alias[jproc][iproc].size();
25212 if (n_shd_nodes_iproc_jproc != n_shd_nodes_jproc_iproc)
25214 std::ostringstream error_stream;
25216 <<
"The number of nodes shared between iproc and jproc is\n"
25217 <<
"different from the number of nodes shared between jproc\n"
25219 <<
"Nodes shared between processor (" << iproc <<
") and "
25220 <<
"processor (" << jproc <<
"): (" << n_shd_nodes_iproc_jproc
25222 <<
"Nodes shared between processor (" << jproc <<
") and "
25223 <<
"processor (" << iproc <<
"): (" << n_shd_nodes_jproc_iproc
25226 error_stream.str(),
25227 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25228 OOMPH_EXCEPTION_LOCATION);
25233 for (
unsigned ishd = 0; ishd < n_shd_nodes_iproc_jproc; ishd++)
25237 const unsigned n_alias_iproc_jproc =
25238 local_node_alias[iproc][jproc][ishd].size();
25239 const unsigned n_alias_jproc_iproc =
25240 local_node_alias[jproc][iproc][ishd].size();
25246 bool new_alias_added =
false;
25249 for (
unsigned ialias = 0; ialias < n_alias_iproc_jproc; ialias++)
25253 local_node_alias[iproc][jproc][ishd][ialias];
25255 if (!alias_done[current_alias])
25258 node_alias.push_back(current_alias);
25260 new_alias_added =
true;
25262 alias_done[current_alias] =
true;
25268 for (
unsigned ialias = 0; ialias < n_alias_jproc_iproc; ialias++)
25272 local_node_alias[jproc][iproc][ishd][ialias];
25275 if (!alias_done[current_alias])
25278 node_alias.push_back(current_alias);
25280 new_alias_added =
true;
25282 alias_done[current_alias] =
true;
25287 unsigned counter_alias = 0;
25291 unsigned n_current_alias = node_alias.size();
25292 while (new_alias_added || counter_alias < n_current_alias)
25296 new_alias_added =
false;
25302 local_node_alias[current_alias[0]][current_alias[1]]
25303 [current_alias[2]];
25307 const unsigned n_alias = alias_of_current_alias.size();
25311 for (
unsigned k = 0; k < n_alias; k++)
25317 if (!alias_done[add_alias])
25320 node_alias.push_back(add_alias);
25323 new_alias_added =
true;
25325 alias_done[add_alias] =
true;
25333 local_node_alias[current_alias[1]][current_alias[0]]
25334 [current_alias[2]];
25338 const unsigned n_alias2 = alias_of_current_alias2.size();
25342 for (
unsigned k = 0; k < n_alias2; k++)
25348 if (!alias_done[add_alias])
25351 node_alias.push_back(add_alias);
25354 new_alias_added =
true;
25356 alias_done[add_alias] =
true;
25367 n_current_alias = node_alias.size();
25373 if (node_alias.size() > 0)
25377 global_node_alias.push_back(node_alias);
25390 const unsigned n_global_shared_nodes = global_node_alias.size();
25396 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25399 local_to_global_shared_node[iproc].resize(nproc);
25404 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25407 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25410 const unsigned n_shd_nodes = local_node_alias[iproc][jproc].size();
25413 local_to_global_shared_node[iproc][jproc].resize(n_shd_nodes, -1);
25416 local_to_global_shared_node[jproc][iproc].resize(n_shd_nodes, -1);
25426 for (
unsigned k = 0; k < n_global_shared_nodes; k++)
25429 const unsigned n_alias_global_node = global_node_alias[k].size();
25431 for (
unsigned l = 0; l < n_alias_global_node; l++)
25434 const unsigned iproc = global_node_alias[k][l][0];
25436 const unsigned jproc = global_node_alias[k][l][1];
25438 const unsigned ishd = global_node_alias[k][l][2];
25440 local_to_global_shared_node[iproc][jproc][ishd] = k;
25449 for (
unsigned k = 0; k < n_global_shared_nodes; k++)
25452 global_adjacency_matrix[k].resize(n_global_shared_nodes, 0);
25462 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25465 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25468 const unsigned n_shd_nodes = local_node_alias[iproc][jproc].size();
25475 for (
unsigned ishd = 0; ishd < n_shd_nodes; ishd++)
25477 for (
unsigned jshd = ishd + 1; jshd < n_shd_nodes; jshd++)
25480 if (local_adjacency_matrix[iproc][jproc][ishd][jshd] > 0)
25485 const int global_shd_node_left =
25486 local_to_global_shared_node[iproc][jproc][ishd];
25489 const int global_shd_node_right =
25490 local_to_global_shared_node[iproc][jproc][jshd];
25495 if (global_shd_node_left == -1)
25497 std::ostringstream error_stream;
25499 <<
"The local node in processors iproc and jproc has no\n"
25500 <<
"global node assigned\n"
25501 <<
"iproc processor: (" << iproc <<
")\n"
25502 <<
"jproc processor: (" << jproc <<
")\n"
25503 <<
"Local node: (" << ishd <<
")\n\n";
25505 "RefineableTriangleMesh::compute_shared_"
25506 "node_degree_helper()",
25507 OOMPH_EXCEPTION_LOCATION);
25512 if (global_shd_node_right == -1)
25514 std::ostringstream error_stream;
25516 <<
"The local node in processors iproc and jproc has no\n"
25517 <<
"global node assigned\n"
25518 <<
"iproc processor: (" << iproc <<
")\n"
25519 <<
"jproc processor: (" << jproc <<
")\n"
25520 <<
"Local node: (" << jshd <<
")\n\n";
25522 "RefineableTriangleMesh::compute_shared_"
25523 "node_degree_helper()",
25524 OOMPH_EXCEPTION_LOCATION);
25528 const unsigned uleft =
25529 static_cast<unsigned>(global_shd_node_left);
25530 const unsigned uright =
25531 static_cast<unsigned>(global_shd_node_right);
25534 global_adjacency_matrix[uleft][uright]++;
25537 global_adjacency_matrix[uright][uleft]++;
25540 global_node_degree[uleft]++;
25543 global_node_degree[uright]++;
25559 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25561 root_local_node_degree[iproc].resize(nproc);
25565 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25568 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25572 const unsigned n_shd_nodes = local_node_alias[iproc][jproc].size();
25575 root_local_node_degree[iproc][jproc].resize(n_shd_nodes);
25577 root_local_node_degree[jproc][iproc].resize(n_shd_nodes);
25581 for (
unsigned ishd = 0; ishd < n_shd_nodes; ishd++)
25584 const int global_shd_node_id =
25585 local_to_global_shared_node[iproc][jproc][ishd];
25589 if (global_shd_node_id == -1)
25591 std::ostringstream error_stream;
25593 <<
"The local node in processors iproc and jproc has no\n"
25594 <<
"global node assigned\n"
25595 <<
"iproc processor: (" << iproc <<
")\n"
25596 <<
"jproc processor: (" << jproc <<
")\n"
25597 <<
"Local node: (" << ishd <<
")\n\n";
25599 error_stream.str(),
25600 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25601 OOMPH_EXCEPTION_LOCATION);
25606 const unsigned uglobal_shd_node_id =
25607 static_cast<unsigned>(global_shd_node_id);
25610 const unsigned node_degree =
25611 global_node_degree[uglobal_shd_node_id];
25615 root_local_node_degree[iproc][jproc][ishd] = node_degree;
25617 root_local_node_degree[jproc][iproc][ishd] = node_degree;
25627 package_unsigned_data_sent_from_root.clear();
25631 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25634 unsigned count_n_data_sent_to_iproc = 0;
25635 for (
unsigned jproc = 0; jproc < nproc; jproc++)
25638 if (iproc != jproc)
25641 const unsigned n_shd_nodes =
25642 root_local_node_degree[iproc][jproc].size();
25645 count_n_data_sent_to_iproc += n_shd_nodes;
25648 for (
unsigned ishd = 0; ishd < n_shd_nodes; ishd++)
25650 package_unsigned_data_sent_from_root.push_back(
25651 root_local_node_degree[iproc][jproc][ishd]);
25659 n_unsigned_data_sent_from_root[iproc] = count_n_data_sent_to_iproc;
25666 int n_unsigned_data_received_from_root = 0;
25669 MPI_Scatter(&n_unsigned_data_sent_from_root[0],
25675 &n_unsigned_data_received_from_root,
25682 comm_pt->mpi_comm());
25686 n_unsigned_data_received_from_root);
25689 Vector<int> root_unsigned_offsets_sent(nproc, 0);
25690 root_unsigned_offsets_sent[0] = 0;
25691 for (
unsigned iproc = 1; iproc < nproc; iproc++)
25694 root_unsigned_offsets_sent[iproc] =
25695 root_unsigned_offsets_sent[iproc - 1] +
25696 n_unsigned_data_sent_from_root[iproc - 1];
25699 if (my_rank != root_processor)
25702 if (package_unsigned_data_sent_from_root.size() == 0)
25704 package_unsigned_data_sent_from_root.resize(1);
25709 if (package_unsigned_data_received_from_root.size() == 0)
25711 package_unsigned_data_received_from_root.resize(1);
25715 MPI_Scatterv(&package_unsigned_data_sent_from_root[0],
25720 &n_unsigned_data_sent_from_root[0],
25724 &root_unsigned_offsets_sent[0],
25727 &package_unsigned_data_received_from_root[0],
25735 n_unsigned_data_received_from_root,
25743 comm_pt->mpi_comm());
25748 std::map<Node*, bool> node_done;
25752 int decode_counter = 0;
25756 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25759 if (iproc != my_rank)
25762 const unsigned n_nodes = tmp_sorted_shared_node_pt[iproc].size();
25765 package_unsigned_send_data_to_root.push_back(n_nodes);
25768 for (
unsigned ishd = 0; ishd < n_nodes; ishd++)
25772 const unsigned node_degree =
25773 package_unsigned_data_received_from_root[decode_counter++];
25776 Node* shd_node_pt = tmp_sorted_shared_node_pt[iproc][ishd];
25779 if (!node_done[shd_node_pt])
25782 global_node_degree[shd_node_pt] = node_degree;
25784 node_done[shd_node_pt] =
true;
25791 if (global_node_degree[shd_node_pt] != node_degree)
25793 std::ostringstream error_stream;
25795 <<
"The local node has already assigned a global degree,\n"
25796 <<
"however, a different degree for the same node has been\n"
25797 <<
"read from the data sent from root processor\n"
25798 <<
"iproc processor: (" << iproc <<
")\n"
25799 <<
"Local node: (" << ishd <<
")\n"
25800 <<
"---------------------------------------------------------\n"
25801 <<
"Already assigned degree: ("
25802 << global_node_degree[shd_node_pt] <<
")\n"
25803 <<
"New found degree: (" << node_degree <<
")\n"
25804 <<
"---------------------------------------------------------\n"
25805 <<
"Node coordinates: (" << shd_node_pt->
x(0) <<
", "
25806 << shd_node_pt->
x(1) <<
")\n\n";
25808 error_stream.str(),
25809 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25810 OOMPH_EXCEPTION_LOCATION);
25824 if (decode_counter != n_unsigned_data_received_from_root)
25826 std::ostringstream error_stream;
25828 <<
"The number of data decoded received from root processor is\n"
25829 <<
"different from the total number of data received from the root\n"
25831 <<
"Data decoded: (" << decode_counter <<
")\n"
25832 <<
"Data received: (" << n_unsigned_data_received_from_root <<
")\n\n"
25833 <<
"This is a synchronisation issue so you are probably sending\n"
25834 <<
"more or less info. than the one that is being decoded\n\n";
25836 error_stream.str(),
25837 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25838 OOMPH_EXCEPTION_LOCATION);
25849 template<
class ELEMENT>
25858 const unsigned nproc = this->communicator_pt()->nproc();
25859 const unsigned my_rank = this->communicator_pt()->my_rank();
25868 node_alias.clear();
25874 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25877 if (iproc != my_rank)
25880 std::map<Node*, bool> done_node;
25885 std::map<std::pair<double, double>,
Node*,
classcomp> sorted_nodes_pt;
25888 const unsigned n_unsorted_face_ele = unsorted_face_ele_pt[iproc].size();
25891 for (
unsigned e = 0;
e < n_unsorted_face_ele;
e++)
25901 if (!done_node[left_node_pt])
25903 std::pair<double, double> vertex =
25904 std::make_pair(left_node_pt->
x(0), left_node_pt->
x(1));
25905 sorted_nodes_pt[vertex] = left_node_pt;
25907 done_node[left_node_pt] =
true;
25911 const unsigned n_nodes = face_ele_pt->
nnode();
25913 Node* right_node_pt = face_ele_pt->
node_pt(n_nodes - 1);
25918 if (!done_node[right_node_pt])
25920 std::pair<double, double> vertex =
25921 std::make_pair(right_node_pt->
x(0), right_node_pt->
x(1));
25922 sorted_nodes_pt[vertex] = right_node_pt;
25924 done_node[right_node_pt] =
true;
25933 unsigned counter = 0;
25937 for (std::map<std::pair<double, double>,
Node*>::iterator it =
25938 sorted_nodes_pt.begin();
25939 it != sorted_nodes_pt.end();
25943 Node* node_pt = (*it).second;
25945 tmp_sorted_shared_node_pt[iproc].push_back(node_pt);
25948 tmp_node_index[iproc][node_pt] = counter;
25953 alias[0] = my_rank;
25957 alias[2] = counter++;
25960 node_alias[node_pt].push_back(alias);
25970 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25973 const unsigned n_shd_nodes = tmp_sorted_shared_node_pt[iproc].size();
25975 adjacency_matrix[iproc].resize(n_shd_nodes);
25976 for (
unsigned i = 0;
i < n_shd_nodes;
i++)
25979 adjacency_matrix[iproc][
i].resize(n_shd_nodes);
25982 for (
unsigned j = 0; j < n_shd_nodes; j++)
25984 adjacency_matrix[iproc][
i][j] = 0;
25992 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25995 if (iproc != my_rank)
25998 const unsigned n_unsorted_face_ele = unsorted_face_ele_pt[iproc].size();
26001 for (
unsigned e = 0;
e < n_unsorted_face_ele;
e++)
26009 const unsigned n_nodes = face_ele_pt->
nnode();
26011 Node* right_node_pt = face_ele_pt->
node_pt(n_nodes - 1);
26014 const unsigned left_node_index = tmp_node_index[iproc][left_node_pt];
26015 const unsigned right_node_index =
26016 tmp_node_index[iproc][right_node_pt];
26020 adjacency_matrix[iproc][left_node_index][right_node_index]++;
26022 adjacency_matrix[iproc][right_node_index][left_node_index]++;
26035 template<
class ELEMENT>
26041 tmp_segment_nodes.clear();
26055 const unsigned nshared_bound_ele =
26056 this->nshared_boundary_element(shd_bnd_id);
26060 for (
unsigned e = 0;
e < nshared_bound_ele;
e++)
26064 this->shared_boundary_element_pt(shd_bnd_id,
e);
26067 int face_index = this->face_index_at_shared_boundary(shd_bnd_id,
e);
26078 nonhalo_shared_face_ele_pt.push_back(face_ele_pt);
26084 halo_shared_face_ele_pt.push_back(face_ele_pt);
26091 std::map<FiniteElement*, bool> shared_face_done;
26094 const unsigned nnonhalo_face_shared_ele = nonhalo_shared_face_ele_pt.size();
26100 const unsigned nhalo_face_shared_ele = halo_shared_face_ele_pt.size();
26104 if (nshared_bound_ele / 2 != nnonhalo_face_shared_ele)
26106 std::ostringstream error_message;
26108 <<
"The number of shared boundary elements (" << nshared_bound_ele
26109 <<
") is not the double\nof the number of unsorted nonhalo shared "
26110 <<
"face boundary elements (" << nnonhalo_face_shared_ele
26111 <<
")\n for the current boundary (" << shd_bnd_id <<
")\n\n";
26113 error_message.str(),
26114 "RefineableTriangleMesh::get_shared_boundary_segment_nodes_helper()",
26115 OOMPH_EXCEPTION_LOCATION);
26120 if (nshared_bound_ele / 2 != nhalo_face_shared_ele)
26122 std::ostringstream error_message;
26124 <<
"The number of shared boundary elements (" << nshared_bound_ele
26125 <<
") is not the double\nof the number of unsorted halo shared "
26126 <<
"face boundary elements (" << nhalo_face_shared_ele
26127 <<
")\n for the current boundary (" << shd_bnd_id <<
")\n\n";
26129 error_message.str(),
26130 "RefineableTriangleMesh::get_shared_boundary_segment_nodes_helper()",
26131 OOMPH_EXCEPTION_LOCATION);
26137 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
26140 FiniteElement* nonhalo_face_ele_pt = nonhalo_shared_face_ele_pt[inh];
26143 const unsigned nnodes_nh = nonhalo_face_ele_pt->
nnode();
26145 Node* nh_first_node_pt = nonhalo_face_ele_pt->
node_pt(0);
26146 Node* nh_last_node_pt = nonhalo_face_ele_pt->
node_pt(nnodes_nh - 1);
26150 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
26153 FiniteElement* halo_face_ele_pt = halo_shared_face_ele_pt[ih];
26156 if (!shared_face_done[halo_face_ele_pt])
26159 const unsigned nnodes_h = halo_face_ele_pt->
nnode();
26161 Node* h_first_node_pt = halo_face_ele_pt->
node_pt(0);
26162 Node* h_last_node_pt = halo_face_ele_pt->
node_pt(nnodes_h - 1);
26166 if (nh_first_node_pt == h_first_node_pt &&
26167 nh_last_node_pt == h_last_node_pt)
26170 shared_face_done[nonhalo_face_ele_pt] =
true;
26171 shared_face_done[halo_face_ele_pt] =
true;
26177 else if (nh_first_node_pt == h_last_node_pt &&
26178 nh_last_node_pt == h_first_node_pt)
26181 shared_face_done[nonhalo_face_ele_pt] =
true;
26182 shared_face_done[halo_face_ele_pt] =
true;
26197 if ((nnonhalo_face_shared_ele + nhalo_face_shared_ele) !=
26198 shared_face_done.size())
26200 std::ostringstream error_message;
26201 error_message <<
"The number of DONE shared boundary face elements ("
26202 << shared_face_done.size()
26203 <<
") is not the same\n as the sum of"
26204 <<
"the nonhalo face shared boundary elements ("
26205 << nnonhalo_face_shared_ele
26206 <<
")\nand the halo face shared "
26207 <<
"boundary elements (" << nhalo_face_shared_ele
26209 <<
"current boundary (" << shd_bnd_id <<
")\n\n";
26211 error_message.str(),
26212 "RefineableTriangleMesh::get_shared_boundary_segment_nodes_helper()",
26213 OOMPH_EXCEPTION_LOCATION);
26225 shared_face_done.clear();
26227 unsigned nsorted_face_ele = 0;
26230 std::list<Node*> sorted_nodes;
26233 FiniteElement* root_face_ele_pt = nonhalo_shared_face_ele_pt[0];
26234 nsorted_face_ele++;
26237 shared_face_done[root_face_ele_pt] =
true;
26240 const unsigned nnodes_root = root_face_ele_pt->
nnode();
26241 Node* first_node_pt = root_face_ele_pt->
node_pt(0);
26242 Node* last_node_pt = root_face_ele_pt->
node_pt(nnodes_root - 1);
26245 sorted_nodes.push_back(first_node_pt);
26246 sorted_nodes.push_back(last_node_pt);
26249 while (nsorted_face_ele < nnonhalo_face_shared_ele)
26252 bool node_added =
false;
26256 for (
unsigned iface = 1; iface < nnonhalo_face_shared_ele; iface++)
26259 nonhalo_shared_face_ele_pt[iface];
26262 if (!shared_face_done[tmp_shared_face_ele_pt])
26265 const unsigned tmp_nnodes = tmp_shared_face_ele_pt->
nnode();
26268 Node* left_node_pt = tmp_shared_face_ele_pt->
node_pt(0);
26269 Node* right_node_pt = tmp_shared_face_ele_pt->
node_pt(tmp_nnodes - 1);
26271 if (left_node_pt == first_node_pt)
26274 sorted_nodes.push_front(right_node_pt);
26275 first_node_pt = right_node_pt;
26278 else if (left_node_pt == last_node_pt)
26281 sorted_nodes.push_back(right_node_pt);
26282 last_node_pt = right_node_pt;
26285 else if (right_node_pt == first_node_pt)
26288 sorted_nodes.push_front(left_node_pt);
26289 first_node_pt = left_node_pt;
26292 else if (right_node_pt == last_node_pt)
26295 sorted_nodes.push_back(left_node_pt);
26296 last_node_pt = left_node_pt;
26304 shared_face_done[tmp_shared_face_ele_pt] =
true;
26305 nsorted_face_ele++;
26321 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
26323 delete nonhalo_shared_face_ele_pt[inh];
26324 nonhalo_shared_face_ele_pt[inh] = 0;
26329 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
26331 delete halo_shared_face_ele_pt[ih];
26332 halo_shared_face_ele_pt[ih] = 0;
26340 const unsigned n_nodes = sorted_nodes.size();
26343 tmp_segment_nodes.resize(1);
26344 tmp_segment_nodes[0].resize(n_nodes);
26347 unsigned counter = 0;
26350 for (std::list<Node*>::iterator it = sorted_nodes.begin();
26351 it != sorted_nodes.end();
26354 tmp_segment_nodes[0][counter] = (*it);
26365 template<
class ELEMENT>
26373 const unsigned nbound = this->initial_shared_boundary_id();
26376 const unsigned nproc = this->communicator_pt()->nproc();
26384 unsigned counter_face_indexes = 0;
26386 for (
unsigned b = 0; b < nbound; b++)
26389 const unsigned nboundary_ele = nboundary_element(b);
26390 for (
unsigned e = 0;
e < nboundary_ele;
e++)
26392 if (ele_pt == this->boundary_element_pt(b,
e))
26395 associated_boundaries.push_back(b);
26397 face_index_on_boundary.push_back(face_index_at_boundary(b,
e));
26398 counter_face_indexes++;
26400 if (counter_face_indexes > 2)
26402 std::stringstream error_message;
26404 <<
"A triangular element can not have more than two of its faces "
26405 <<
"on a boundary!!!\n\n";
26407 "RefineableTriangleMesh::get_required_"
26408 "elemental_information_helper()",
26409 OOMPH_EXCEPTION_LOCATION);
26413 if (counter_face_indexes == 2)
26427 const unsigned nassociated_boundaries = associated_boundaries.size();
26428 if (nassociated_boundaries > 0)
26431 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26433 "The element is a boundary element");
26436 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26437 std::stringstream junk;
26438 junk <<
"The elements is associated to " << nassociated_boundaries
26447 for (
unsigned i = 0;
i < nassociated_boundaries;
i++)
26449 unsigned b = associated_boundaries[
i];
26451 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26452 std::stringstream junk;
26453 junk <<
"Element associated to boundary " << b <<
" of "
26454 << nassociated_boundaries <<
" total associated boundaries";
26457 unsigned f = face_index_on_boundary[
i];
26459 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26460 std::stringstream junk2;
26461 junk2 <<
"Face index " << f <<
" for associated boundary " << b;
26476 const unsigned n_regions = this->nregion();
26481 unsigned counter_face_indexes_in_regions = 0;
26483 for (
unsigned b = 0; b < nbound; b++)
26486 for (
unsigned i_reg = 0; i_reg < n_regions; i_reg++)
26489 const unsigned region_id =
26490 static_cast<unsigned>(this->Region_attribute[i_reg]);
26495 const unsigned nele_in_region =
26496 this->nboundary_element_in_region(b, region_id);
26497 for (
unsigned ee = 0; ee < nele_in_region; ee++)
26502 this->boundary_element_in_region_pt(b, region_id, ee))
26509 bound_and_region[0] = b;
26511 bound_and_region[1] = region_id;
26514 associated_boundaries_and_regions.push_back(bound_and_region);
26516 face_index_on_boundary_and_region.push_back(
26517 this->face_index_at_boundary_in_region(b, region_id, ee));
26521 counter_face_indexes_in_regions++;
26524 if (counter_face_indexes_in_regions > 2)
26526 std::stringstream error_message;
26527 error_message <<
"A triangular element can not have more "
26528 "than two of its\n"
26529 <<
"faces on a boundary!!!\n\n";
26531 "RefineableTriangleMesh::get_required_"
26532 "elemental_information_helper()",
26533 OOMPH_EXCEPTION_LOCATION);
26548 const unsigned nassociated_boundaries_and_regions =
26549 associated_boundaries_and_regions.size();
26550 if (nassociated_boundaries_and_regions > 0)
26553 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26555 "The element is associated to boundaries and regions");
26559 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26560 std::stringstream junk;
26561 junk <<
"The element is associated to "
26562 << nassociated_boundaries_and_regions <<
" boundaries-regions";
26570 for (
unsigned i = 0;
i < nassociated_boundaries_and_regions;
i++)
26572 const unsigned b = associated_boundaries_and_regions[
i][0];
26574 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26575 std::stringstream junk;
26576 junk <<
"Element associated to boundary " << b <<
" of "
26577 << nassociated_boundaries_and_regions
26578 <<
" total associated boundaries-regions";
26582 const unsigned r = associated_boundaries_and_regions[
i][1];
26584 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26585 std::stringstream junk2;
26586 junk2 <<
"Element associated to region " << r <<
" of "
26587 << nassociated_boundaries_and_regions
26588 <<
" total associated boundaries-regions";
26592 const unsigned f = face_index_on_boundary_and_region[
i];
26594 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26595 std::stringstream junk3;
26596 junk3 <<
"Face index " << f <<
" for associated boundary-region ("
26597 << b <<
"-" << r <<
")";
26605 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26607 "The element is NOT associated to boundaries and regions");
26614 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26616 "The element is not associated to any original boundary");
26630 this->shared_boundaries_in_this_processor(my_rank_shared_boundaries_ids);
26633 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
26635 for (
unsigned i = 0;
i < nmy_rank_shd_bnd;
i++)
26638 const unsigned sb = my_rank_shared_boundaries_ids[
i];
26641 const unsigned nboundary_ele = this->nshared_boundary_element(sb);
26642 for (
unsigned e = 0;
e < nboundary_ele;
e++)
26644 if (ele_pt == this->shared_boundary_element_pt(sb,
e))
26647 associated_shared_boundaries.push_back(sb);
26649 face_index_on_shared_boundary.push_back(
26650 this->face_index_at_shared_boundary(sb,
e));
26657 const unsigned nassociated_shared_boundaries =
26658 associated_shared_boundaries.size();
26659 if (nassociated_shared_boundaries > 0)
26662 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26664 "The element is a shared boundary element");
26667 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26668 std::stringstream junk;
26669 junk <<
"The elements is associated to " << nassociated_shared_boundaries
26670 <<
"shared boundaries";
26675 for (
unsigned i = 0;
i < nassociated_shared_boundaries;
i++)
26677 const unsigned b = associated_shared_boundaries[
i];
26679 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26680 std::stringstream junk;
26681 junk <<
"Element associated to shared boundary " << b <<
" of "
26682 << nassociated_shared_boundaries <<
" total associated boundaries";
26686 const unsigned f = face_index_on_shared_boundary[
i];
26688 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26689 std::stringstream junk2;
26690 junk2 <<
"Face index " << f <<
" for associated shared boundary " << b;
26698 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26700 "The element is not associated to any shared boundary");
26710 for (
unsigned jproc = 0; jproc < nproc; jproc++)
26713 const unsigned n_haloed_jproc = f_haloed_ele_pt[jproc].size();
26715 for (
unsigned ihd = 0; ihd < n_haloed_jproc; ihd++)
26718 if (ele_pt == f_haloed_ele_pt[jproc][ihd])
26721 index_haloed[jproc].push_back(ihd);
26732 for (
unsigned jproc = 0; jproc < nproc; jproc++)
26735 const unsigned n_index_haloed_jproc = index_haloed[jproc].size();
26737 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26739 "The number of haloed indexes the element is with processor jproc");
26741 for (
unsigned ihd = 0; ihd < n_index_haloed_jproc; ihd++)
26744 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26746 "The haloed index of the element with jproc");
26757 template<
class ELEMENT>
26765 const unsigned nnew_nodes_on_domain = new_nodes_on_domain.size();
26766 const unsigned new_added_node_index =
26767 this->try_to_add_node_pt_load_balance(new_nodes_on_domain, nod_pt);
26770 if (new_added_node_index == nnew_nodes_on_domain)
26774 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26775 std::stringstream junk;
26776 junk <<
"Node needs to be constructed [size="
26785 get_required_nodal_information_load_balance_helper(
26786 f_halo_ele_pt, iproc, nod_pt);
26791 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26792 std::stringstream junk;
26794 <<
"]; last entry: "
26803 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26814 template<
class ELEMENT>
26821 unsigned my_rank = this->communicator_pt()->my_rank();
26822 const unsigned nproc = this->communicator_pt()->nproc();
26827 unsigned n_val = nod_pt->
nvalue();
26829 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26833 unsigned n_dim = nod_pt->
ndim();
26836 unsigned n_prev = 1;
26837 if (this->Time_stepper_pt != 0)
26840 n_prev = this->Time_stepper_pt->ntstorage();
26849 const unsigned n_bnd = this->initial_shared_boundary_id();
26850 for (
unsigned bb = 0; bb < n_bnd; bb++)
26855 original_boundaries.push_back(bb);
26859 const unsigned n_original_boundaries = original_boundaries.size();
26861 if (n_original_boundaries > 0)
26865 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26867 "Node is on the original boundaries");
26871 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26872 std::stringstream junk;
26873 junk <<
"Node is on " << n_original_boundaries <<
" original boundaries";
26878 for (
unsigned i = 0;
i < n_original_boundaries;
i++)
26881 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26882 std::stringstream junk;
26883 junk <<
"Node is on boundary " << original_boundaries[
i] <<
" of "
26897 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26899 "Node is on any original boundary");
26905 bool node_on_shared_boundary =
false;
26908 const unsigned n_shd_bnd = this->nshared_boundaries(my_rank, iproc);
26909 for (
unsigned bb = 0; bb < n_shd_bnd; bb++)
26912 unsigned i_bnd = this->shared_boundaries_ids(my_rank, iproc, bb);
26914 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
26916 node_on_shared_boundary =
true;
26924 if (node_on_shared_boundary)
26927 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26934 for (
unsigned bb = 0; bb < n_shd_bnd; bb++)
26937 const unsigned i_bnd = this->shared_boundaries_ids(my_rank, iproc, bb);
26939 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
26941 shd_boundaries.push_back(i_bnd);
26946 const unsigned n_shd_bnd_is_on = shd_boundaries.size();
26949 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26950 std::stringstream junk;
26951 junk <<
"Node is on " << n_shd_bnd_is_on <<
" shared boundaries";
26956 for (
unsigned i = 0;
i < n_shd_bnd_is_on;
i++)
26959 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26960 std::stringstream junk;
26961 junk <<
"Node is on boundary " << shd_boundaries[
i] <<
" of " << nb;
26968 unsigned shared_boundary_id = shd_boundaries[0];
26970 const unsigned n_nodes_on_shared_boundary =
26971 nsorted_shared_boundary_node(shared_boundary_id);
26973 unsigned index_node_on_shared_boundary;
26976 bool found_index_node_on_shared_boundary =
false;
26979 for (
unsigned i = 0;
i < n_nodes_on_shared_boundary;
i++)
26982 Node* shared_node_pt =
26983 sorted_shared_boundary_node_pt(shared_boundary_id,
i);
26985 if (shared_node_pt == nod_pt)
26988 index_node_on_shared_boundary =
i;
26991 found_index_node_on_shared_boundary =
true;
26999 if (!found_index_node_on_shared_boundary)
27001 std::ostringstream error_message;
27002 error_message <<
"The index of the node on boundary ("
27003 << shared_boundary_id <<
") was not found.\n"
27004 <<
"The node coordinates are (" << nod_pt->
x(0) <<
","
27005 << nod_pt->
x(1) <<
").\n";
27007 error_message.str(),
27008 "RefineableTriangleMesh::get_required_nodal_information_helper()",
27009 OOMPH_EXCEPTION_LOCATION);
27014 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27015 std::stringstream junk2;
27016 junk2 <<
"Node index on boundary " << boundaries[0] <<
" is "
27017 << index_node_on_shared_boundary;
27026 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27028 "Node is not on a shared boundary");
27043 bool node_on_shared_boundary_with_other_processors =
false;
27045 unsigned nshared_boundaries_with_other_processors_have_node = 0;
27049 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27053 if (jproc != iproc)
27056 const unsigned n_jshd_bnd = this->nshared_boundaries(my_rank, jproc);
27058 for (
unsigned bb = 0; bb < n_jshd_bnd; bb++)
27061 const unsigned j_shd_bnd =
27062 this->shared_boundaries_ids(my_rank, jproc, bb);
27064 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
27072 node_on_shared_boundary_with_other_processors =
true;
27075 nshared_boundaries_with_other_processors_have_node++;
27086 if (node_on_shared_boundary_with_other_processors)
27089 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27091 "Node is on shared boundary no related with the received processor: 4");
27098 nshared_boundaries_with_other_processors_have_node);
27099 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27100 std::stringstream junk;
27101 junk <<
"Number of other shared boundaries that the node is on: "
27102 << nshared_boundaries_with_other_processors_have_node;
27107 unsigned counter_shd_bnd_with_other_procs_have_node = 0;
27117 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27121 if (jproc != iproc)
27125 const unsigned n_jshd_bnd = this->nshared_boundaries(my_rank, jproc);
27126 for (
unsigned bb = 0; bb < n_jshd_bnd; bb++)
27129 const unsigned j_shd_bnd =
27130 this->shared_boundaries_ids(my_rank, jproc, bb);
27132 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
27135 other_processor_1.push_back(my_rank);
27137 other_processor_2.push_back(jproc);
27139 shd_bnd_ids.push_back(j_shd_bnd);
27142 counter_shd_bnd_with_other_procs_have_node++;
27153 const unsigned n_other_processors = other_processor_1.size();
27155 for (
unsigned i = 0;
i < n_other_processors;
i++)
27158 unsigned shd_bnd_id = shd_bnd_ids[
i];
27160 const unsigned n_nodes_on_shd_bnd =
27161 nsorted_shared_boundary_node(shd_bnd_id);
27164 bool found_index_node_on_shared_boundary =
false;
27166 for (
unsigned i = 0;
i < n_nodes_on_shd_bnd;
i++)
27169 Node* shared_node_pt = sorted_shared_boundary_node_pt(shd_bnd_id,
i);
27171 if (shared_node_pt == nod_pt)
27177 indexes.push_back(
i);
27180 found_index_node_on_shared_boundary =
true;
27188 if (!found_index_node_on_shared_boundary)
27190 std::ostringstream error_message;
27191 error_message <<
"The index of the node on boundary (" << shd_bnd_id
27192 <<
"), shared by other processors\nwas not found.\n"
27193 <<
"The node coordinates are (" << nod_pt->
x(0) <<
","
27194 << nod_pt->
x(1) <<
").\n";
27196 error_message.str(),
27197 "RefineableTriangleMesh::get_required_nodal_information_helper()",
27198 OOMPH_EXCEPTION_LOCATION);
27207 if (counter_shd_bnd_with_other_procs_have_node !=
27208 nshared_boundaries_with_other_processors_have_node)
27210 std::ostringstream error_message;
27211 error_message <<
"The number of shared boundaries where the node is on "
27212 <<
"is different:\n"
27213 <<
"nshared_boundaries_with_other_processors_have_node: ("
27214 << nshared_boundaries_with_other_processors_have_node
27216 <<
"counter_shd_bnd_with_other_procs_have_node: ("
27217 << counter_shd_bnd_with_other_procs_have_node <<
")\n";
27219 error_message.str(),
27220 "RefineableTriangleMesh::get_required_nodal_information_helper()",
27221 OOMPH_EXCEPTION_LOCATION);
27227 for (
unsigned i = 0;
i < n_other_processors;
i++)
27230 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27231 std::stringstream junk1;
27232 junk1 <<
"Processor where the other shared boundary "
27233 <<
"has the node: " << other_processor_1[
i];
27238 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27239 std::stringstream junk2;
27240 junk2 <<
"Processor where the other shared boundary "
27241 <<
"has the node: " << other_processor_2[
i];
27246 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27247 std::stringstream junk3;
27248 junk3 <<
"Other shared boundary id where the node is on"
27254 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27255 std::stringstream junk4;
27256 junk4 <<
"Node index on other shared boundary " << boundaries[
i]
27257 <<
" is " << indexes[
i];
27267 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27269 "Node is on any shared boundary with other processors");
27301 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27304 const unsigned n_halo_jproc = f_halo_ele_pt[jproc].size();
27306 for (
unsigned jh = 0; jh < n_halo_jproc; jh++)
27310 const unsigned n_node = halo_ele_pt->
nnode();
27312 for (
unsigned n = 0; n < n_node; n++)
27315 if (nod_pt == halo_ele_pt->
node_pt(n))
27317 halo_element_number[jproc].push_back(jh);
27318 halo_node_number_in_halo_element[jproc].push_back(n);
27334 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27338 const unsigned n_jproc_halo_ele_node_is_on =
27339 halo_element_number[jproc].size();
27342 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27343 std::stringstream junk5;
27344 junk5 <<
"Node is on " << n_jproc_halo_ele_node_is_on <<
" halo "
27345 <<
"elements with " << jproc <<
"-th processor";
27351 for (
unsigned i = 0;
i < n_jproc_halo_ele_node_is_on;
i++)
27354 const unsigned halo_element_index = halo_element_number[jproc][
i];
27356 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27357 std::stringstream junk6;
27358 junk6 <<
"Halo element index is (" << halo_element_index
27359 <<
") with processor (" << jproc <<
")";
27363 const unsigned node_index = halo_node_number_in_halo_element[jproc][
i];
27365 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27366 std::stringstream junk7;
27367 junk7 <<
"The node index on the halo element index is (" << node_index;
27383 bool on_halo_element_with_iproc_processor =
false;
27384 if (halo_element_number[iproc].size() > 0)
27386 on_halo_element_with_iproc_processor =
true;
27390 if (!node_on_shared_boundary && !on_halo_element_with_iproc_processor)
27398 if (alg_nod_pt != 0)
27406 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27411 unsigned n_ref_val = alg_nod_pt->
nref_value();
27413 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27416 for (
unsigned i_ref_val = 0; i_ref_val < n_ref_val; i_ref_val++)
27424 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27427 for (
unsigned i_geom = 0; i_geom < n_geom_obj; i_geom++)
27435 unsigned found_geom_object = 0;
27436 for (
unsigned i_list = 0; i_list < n_geom_list; i_list++)
27440 found_geom_object = i_list;
27444 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27452 if (solid_nod_pt != 0)
27455 for (
unsigned i_val = 0; i_val < n_solid_val; i_val++)
27457 for (
unsigned t = 0;
t < n_prev;
t++)
27466 const unsigned nvalues_solid_node = values_solid_node.size();
27468 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27469 std::stringstream junk;
27470 junk <<
"Number of values solid node: " << nvalues_solid_node;
27473 for (
unsigned i = 0;
i < nvalues_solid_node;
i++)
27480 for (
unsigned i_val = 0; i_val < n_val; i_val++)
27482 for (
unsigned t = 0;
t < n_prev;
t++)
27489 for (
unsigned idim = 0; idim < n_dim; idim++)
27491 for (
unsigned t = 0;
t < n_prev;
t++)
27506 template<
class ELEMENT>
27511 received_old_haloed_element_pt,
27515 other_proc_shd_bnd_node_pt,
27520 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27522 <<
" Bool: New element needs to be constructed "
27541 new_elements_on_domain.push_back(f_el_pt);
27544 this->add_element_load_balance_helper(
27545 iproc, received_old_haloed_element_pt, f_el_pt);
27548 unsigned n_node = f_el_pt->
nnode();
27549 for (
unsigned j = 0; j < n_node; j++)
27551 Node* new_nod_pt = 0;
27554 add_received_node_load_balance_helper(new_nod_pt,
27556 received_old_haloed_element_pt,
27557 new_nodes_on_domain,
27558 other_proc_shd_bnd_node_pt,
27563 node_name_to_global_index,
27564 global_shared_node_pt);
27569 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27571 <<
" Index of existing element "
27589 template<
class ELEMENT>
27591 const unsigned& iproc,
27593 received_old_haloed_element_pt,
27597 const unsigned nproc = this->communicator_pt()->nproc();
27599 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27601 <<
" Bool: Element is associated to a boundary "
27607 const unsigned is_on_original_boundary =
27609 if (is_on_original_boundary == 1)
27611 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27613 <<
" How many boundaries are associated with the element "
27618 const unsigned nassociated_boundaries =
27622 for (
unsigned b = 0; b < nassociated_boundaries; b++)
27624 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27626 <<
" Boundary associated to the element "
27632 const unsigned bnd =
27635 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27637 <<
" Face index of the element "
27643 const unsigned face_index =
27648 this->Boundary_element_pt[bnd].push_back(ele_pt);
27649 this->Face_index_at_boundary[bnd].push_back(face_index);
27654 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27656 <<
" Bool: Element is associated to a boundary-region "
27664 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27667 <<
" How many boundaries-regions are associated with the element "
27672 const unsigned nassociated_boundaries_and_regions =
27675 for (
unsigned br = 0; br < nassociated_boundaries_and_regions; br++)
27677 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27679 <<
" Boundary associated to the element "
27684 const unsigned bnd =
27687 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27689 <<
" Region associated to the element "
27694 const unsigned region =
27697 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27699 <<
" Face index of the element in boundary-region "
27703 const unsigned face_index =
27708 this->Boundary_region_element_pt[bnd][region].push_back(ele_pt);
27709 this->Face_index_region_at_boundary[bnd][region].push_back(
27720 if (is_on_original_boundary != 0)
27722 std::ostringstream error_message;
27724 <<
"The current element is not on an original boundary, this should\n"
27725 <<
"be indicated by a zero flag. However, the read value for\n"
27726 <<
"that flag is (" << is_on_original_boundary <<
").\n\n";
27728 error_message.str(),
27729 "RefineableTriangleMesh::add_element_load_balance_helper()",
27730 OOMPH_EXCEPTION_LOCATION);
27735 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27737 <<
" Bool: Element is associated to a shared boundary "
27743 const unsigned is_on_shared_boundary =
27745 if (is_on_shared_boundary == 3)
27747 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27750 <<
" How many shared boundaries are associated with the element "
27756 const unsigned nassociated_shared_boundaries =
27760 for (
unsigned b = 0; b < nassociated_shared_boundaries; b++)
27762 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27764 <<
" Shared boundary associated to the element "
27768 const unsigned bnd =
27771 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27774 <<
" Face index of the element associated to the shared boundary "
27779 const unsigned face_index =
27782 this->add_shared_boundary_element(bnd, ele_pt);
27783 this->add_face_index_at_shared_boundary(bnd, face_index);
27791 if (is_on_shared_boundary != 0)
27793 std::ostringstream error_message;
27795 <<
"The current element is not on a shared boundary, this should\n"
27796 <<
"be indicated by a zero flag. However, the read value for\n"
27797 <<
"that flag is (" << is_on_shared_boundary <<
").\n\n";
27799 error_message.str(),
27800 "RefineableTriangleMesh::add_element_load_balance_helper()",
27801 OOMPH_EXCEPTION_LOCATION);
27810 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27812 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27814 <<
" Bool: Number of haloed indexes of the element with the "
27815 << jproc <<
" processor: "
27820 const unsigned n_index_haloed_jproc =
27823 for (
unsigned ihd = 0; ihd < n_index_haloed_jproc; ihd++)
27825 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27827 <<
" Bool: The haloed element index with the " << jproc
27832 const unsigned haloed_index =
27836 received_old_haloed_element_pt[iproc][jproc][haloed_index] = ele_pt;
27846 template<
class ELEMENT>
27851 received_old_haloed_element_pt,
27854 other_proc_shd_bnd_node_pt,
27856 unsigned& node_index,
27864 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27866 <<
" Bool: New node needs to be constructed "
27874 construct_new_node_load_balance_helper(new_nod_pt,
27876 received_old_haloed_element_pt,
27877 new_nodes_on_domain,
27878 other_proc_shd_bnd_node_pt,
27883 node_name_to_global_index,
27884 global_shared_node_pt);
27888 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27890 <<
" Index of existing halo node "
27897 new_nod_pt = new_nodes_on_domain
27901 new_el_pt->
node_pt(node_index) = new_nod_pt;
27910 template<
class ELEMENT>
27915 received_old_haloed_element_pt,
27918 other_proc_shd_bnd_node_pt,
27920 unsigned& node_index,
27927 const unsigned nproc = this->communicator_pt()->nproc();
27929 const unsigned my_rank = this->communicator_pt()->my_rank();
27933 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27935 <<
" Number of values of external halo node "
27942 TimeStepper* time_stepper_pt = this->Time_stepper_pt;
27944 unsigned n_prev = time_stepper_pt->
ntstorage();
27948 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27950 <<
" Is the node on an original boundary "
27956 const unsigned node_on_original_boundaries =
27964 unsigned n_original_boundaries_node_is_on = 0;
27966 if (node_on_original_boundaries == 2)
27969 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27971 <<
" Number of boundaries the node is on: "
27975 n_original_boundaries_node_is_on =
27979 original_boundaries_node_is_on.resize(n_original_boundaries_node_is_on);
27980 zeta_coordinates.resize(n_original_boundaries_node_is_on);
27982 for (
unsigned i = 0;
i < n_original_boundaries_node_is_on;
i++)
27985 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27987 <<
" Node is on boundary "
27991 original_boundaries_node_is_on[
i] =
27993 zeta_coordinates[
i] =
28001 if (node_on_original_boundaries != 0)
28003 std::ostringstream error_message;
28005 <<
"The current node is not on an original boundary, this should\n"
28006 <<
"be indicated by a zero flag. However, the read value for\n"
28007 <<
"that flag is (" << node_on_original_boundaries <<
").\n\n";
28009 error_message.str(),
28010 "RefineableTriangleMesh::construct_new_halo_node_helper()",
28011 OOMPH_EXCEPTION_LOCATION);
28019 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28021 <<
" Is node on shared boundary? "
28025 const unsigned is_node_on_shared_boundary =
28027 if (is_node_on_shared_boundary == 1)
28030 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28032 <<
" Number of boundaries the node is on: "
28036 const unsigned n_shd_bnd_node_is_on =
28039 for (
unsigned i = 0;
i < n_shd_bnd_node_is_on;
i++)
28042 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28044 <<
" Node is on boundary "
28048 shd_bnds_node_is_on[
i] =
28053 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28055 <<
" Index of node on boundary "
28060 unsigned node_index_on_shared_boundary =
28064 new_nod_pt = this->sorted_shared_boundary_node_pt(
28065 shd_bnds_node_is_on[0], node_index_on_shared_boundary);
28071 if (is_node_on_shared_boundary != 0)
28073 std::ostringstream error_message;
28075 <<
"The current node is not on a shared boundary, this should\n"
28076 <<
"be indicated by a zero flag. However, the read value for\n"
28077 <<
"that flag is (" << is_node_on_shared_boundary <<
").\n\n";
28079 error_message.str(),
28080 "RefineableTriangleMesh::construct_new_halo_node_helper()",
28081 OOMPH_EXCEPTION_LOCATION);
28088 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28090 <<
" Is the node on shared boundaries with other processors "
28097 const unsigned is_the_node_in_shared_boundaries_with_other_processors =
28107 unsigned n_shd_bnd_with_other_procs_have_node = 0;
28110 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
28112 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28114 <<
" In how many shared boundaries with other "
28115 <<
"processors is the node "
28121 n_shd_bnd_with_other_procs_have_node =
28125 other_processor_1.resize(n_shd_bnd_with_other_procs_have_node);
28126 other_processor_2.resize(n_shd_bnd_with_other_procs_have_node);
28127 other_shared_boundaries.resize(n_shd_bnd_with_other_procs_have_node);
28128 other_indexes.resize(n_shd_bnd_with_other_procs_have_node);
28130 for (
unsigned i = 0;
i < n_shd_bnd_with_other_procs_have_node;
i++)
28132 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28134 <<
" Processor where the other shared boundary"
28140 other_processor_1[
i] =
28143 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28145 <<
" Processor where the other shared boundary"
28151 other_processor_2[
i] =
28154 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28156 <<
" Other shared boundary id where the node is on: "
28162 other_shared_boundaries[
i] =
28165 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28167 <<
" Node index on the other shared boundary "
28182 if (is_the_node_in_shared_boundaries_with_other_processors != 0)
28184 std::ostringstream error_message;
28186 <<
"The current node is not on a shared boundary with\n"
28187 <<
"other processors, this should be indicated by a zero flag.\n"
28188 <<
"However, the read value for that flag is ("
28189 << is_the_node_in_shared_boundaries_with_other_processors <<
").\n\n";
28191 error_message.str(),
28192 "RefineableTriangleMesh::construct_new_node_load_balance_helper()",
28193 OOMPH_EXCEPTION_LOCATION);
28208 for (
unsigned jproc = 0; jproc < nproc; jproc++)
28210 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28212 <<
" The node is on "
28214 <<
" halo elements with " << jproc <<
" processor"
28219 const unsigned n_jproc_halo_ele_node_is_on =
28223 halo_element_number[jproc].resize(n_jproc_halo_ele_node_is_on);
28224 halo_node_number_in_halo_element[jproc].resize(
28225 n_jproc_halo_ele_node_is_on);
28230 for (
unsigned i = 0;
i < n_jproc_halo_ele_node_is_on;
i++)
28233 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28235 <<
" The halo element index where the node is on "
28240 const unsigned halo_ele_index =
28242 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28244 <<
" The node index on the halo element where the node "
28249 const unsigned node_index_on_halo_ele =
28253 halo_element_number[jproc][
i] = halo_ele_index;
28255 halo_node_number_in_halo_element[jproc][
i] = node_index_on_halo_ele;
28264 std::set<Node*> set_haloed_node_pt;
28267 Node* haloed_node_pt = 0;
28273 bool on_haloed_element_with_iproc_processor =
false;
28274 if (halo_element_number[my_rank].size() > 0)
28278 on_haloed_element_with_iproc_processor =
true;
28281 const unsigned n_haloed_indexes = halo_element_number[my_rank].size();
28285 for (
unsigned i = 0;
i < n_haloed_indexes;
i++)
28288 const unsigned haloed_index = halo_element_number[my_rank][
i];
28290 const unsigned haloed_node_index =
28291 halo_node_number_in_halo_element[my_rank][
i];
28294 FiniteElement* tmp_haloed_ele_pt = f_haloed_ele_pt[iproc][haloed_index];
28296 Node* tmp_haloed_node_pt =
28297 tmp_haloed_ele_pt->
node_pt(haloed_node_index);
28300 haloed_node_pt = tmp_haloed_node_pt;
28303 set_haloed_node_pt.insert(tmp_haloed_node_pt);
28306 if (set_haloed_node_pt.size() > 1)
28308 std::ostringstream error_message;
28310 <<
"When adding the " << haloed_node_index <<
" node of the "
28311 << haloed_index <<
"-th haloed element\n"
28312 <<
"in the currrent processor with the " << iproc <<
" processor"
28313 <<
"it was found that\nthe node pointer is different from the other"
28314 <<
"instances of the node.\nIt means we have a repeated node."
28315 <<
"This are the node coordinates of the previous node instances\n"
28316 <<
"The last entry is for the just added node with a different "
28319 for (std::set<Node*>::iterator it = set_haloed_node_pt.begin();
28320 it != set_haloed_node_pt.end();
28323 error_message <<
"Node: (" << (*it)->
x(0) <<
", " << (*it)->x(1)
28326 error_message <<
"\n";
28328 error_message.str(),
28329 "RefineableTriangleMesh::construct_new_node_load_balance_helper()",
28330 OOMPH_EXCEPTION_LOCATION);
28340 bool found_on_haloed_element_with_other_processor =
false;
28343 for (
unsigned jproc = 0; jproc < iproc; jproc++)
28346 if (halo_element_number[jproc].size() > 0)
28349 const unsigned n_halo_indexes = halo_element_number[jproc].size();
28353 for (
unsigned i = 0;
i < n_halo_indexes;
i++)
28356 const unsigned haloed_index = halo_element_number[jproc][
i];
28358 const unsigned haloed_node_index =
28359 halo_node_number_in_halo_element[jproc][
i];
28363 std::map<unsigned, FiniteElement*>::iterator it_map =
28364 received_old_haloed_element_pt[jproc][iproc].find(haloed_index);
28366 if (it_map != received_old_haloed_element_pt[jproc][iproc].end())
28371 found_on_haloed_element_with_other_processor =
true;
28376 Node* tmp_haloed_node_pt =
28377 tmp_haloed_ele_pt->
node_pt(haloed_node_index);
28380 haloed_node_pt = tmp_haloed_node_pt;
28383 set_haloed_node_pt.insert(tmp_haloed_node_pt);
28386 if (set_haloed_node_pt.size() > 1)
28388 std::ostringstream error_message;
28390 <<
"When adding the " << haloed_node_index <<
" node of the "
28391 << haloed_index <<
"-th haloed element "
28392 <<
"of the " << jproc <<
" processor\nwith the " << iproc
28393 <<
" processor, it was found that\n"
28394 <<
"the node pointer is different from the other\n"
28395 <<
"instances of the node.\nThis means we have a repeated "
28397 <<
"These are the node coordinates of the previous node "
28399 <<
"The last entry is for the just added node with a "
28401 <<
"node pointer\n";
28402 for (std::set<Node*>::iterator it = set_haloed_node_pt.begin();
28403 it != set_haloed_node_pt.end();
28406 error_message <<
"Node: (" << (*it)->
x(0) <<
", " << (*it)->x(1)
28409 error_message <<
"\n";
28411 "RefineableTriangleMesh::construct_new_node_"
28412 "load_balance_helper()",
28413 OOMPH_EXCEPTION_LOCATION);
28431 if (on_haloed_element_with_iproc_processor ||
28432 found_on_haloed_element_with_other_processor)
28435 new_nod_pt = haloed_node_pt;
28443 if (is_node_on_shared_boundary == 1 ||
28444 (on_haloed_element_with_iproc_processor))
28449 if (node_on_original_boundaries == 2)
28455 for (
unsigned i = 0;
i < n_original_boundaries_node_is_on;
i++)
28457 add_boundary_node(original_boundaries_node_is_on[
i], new_nod_pt);
28460 zeta[0] = zeta_coordinates[
i];
28462 original_boundaries_node_is_on[
i], zeta);
28468 new_nodes_on_domain.push_back(new_nod_pt);
28471 new_el_pt->
node_pt(node_index) = new_nod_pt;
28481 bool found_node_in_other_shared_boundaries =
false;
28490 bool build_node_as_boundary_node =
false;
28492 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
28495 build_node_as_boundary_node =
true;
28502 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
28509 for (
unsigned i = 0;
i < n_shd_bnd_with_other_procs_have_node;
i++)
28511 unsigned oproc1 = other_processor_1[
i];
28512 unsigned oproc2 = other_processor_2[
i];
28516 if (oproc1 > oproc2)
28519 oproc1 = other_processor_2[
i];
28524 const unsigned shd_bnd_id =
28525 other_shared_boundaries[
i] - initial_shd_bnd_id;
28527 const unsigned index = other_indexes[
i];
28531 const unsigned n_nodes_on_other_processor =
28532 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].size();
28534 if (n_nodes_on_other_processor > 0)
28538 std::map<unsigned, Node*>::iterator it =
28539 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].find(index);
28543 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].end())
28546 found_node_in_other_shared_boundaries =
true;
28548 Node* tmp_node_pt =
28549 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id][index];
28550 found_node_pt.push_back(tmp_node_pt);
28560 if (found_node_in_other_shared_boundaries)
28563 const unsigned ntimes_node_found = found_node_pt.size();
28564 for (
unsigned j = 1; j < ntimes_node_found; j++)
28566 if (found_node_pt[j - 1] != found_node_pt[j])
28568 std::ostringstream error_message;
28570 <<
"The instances of the node that was found to be on a\n"
28571 <<
"shared boundary with other processors are not the same,\n"
28572 <<
"the coordinates for the nodes are these:\n"
28573 <<
"(" << found_node_pt[j - 1]->x(0) <<
", "
28574 << found_node_pt[j - 1]->x(1) <<
")\n"
28575 <<
"(" << found_node_pt[j]->x(0) <<
", " << found_node_pt[j]->x(1)
28577 <<
"Not be surprised if they are the same since the node is\n"
28578 <<
"repeated!!!\n";
28580 error_message.str(),
28581 "RefineableTriangleMesh::construct_new_halo_node_helper()",
28582 OOMPH_EXCEPTION_LOCATION);
28593 if (is_node_on_shared_boundary == 1)
28598 if (found_node_pt[0] != new_nod_pt)
28600 std::ostringstream error_message;
28602 <<
"The pointer of the node that was found to be on a\n"
28603 <<
"shared boundary with other processor(s) and the pointer\n"
28604 <<
"of the node on shared boundary with the receiver\n"
28605 <<
"processor (iproc) are not the same. This means we have a\n"
28606 <<
"repeated node)\n"
28607 <<
"The coordinates for the nodes are:\n"
28608 <<
"(" << found_node_pt[0]->x(0) <<
", " << found_node_pt[0]->x(1)
28610 <<
"(" << new_nod_pt->
x(0) <<
", " << new_nod_pt->
x(1) <<
")\n"
28611 <<
"Not to be surprised if they are the same since the node is\n"
28612 <<
"repeated!!!\n";
28614 error_message.str(),
28615 "RefineableTriangleMesh::construct_new_halo_node_helper()",
28616 OOMPH_EXCEPTION_LOCATION);
28625 new_nod_pt = found_node_pt[0];
28637 if (is_node_on_shared_boundary != 1 &&
28638 !on_haloed_element_with_iproc_processor)
28652 if (node_on_original_boundaries == 2 || build_node_as_boundary_node)
28658 if (!found_node_in_other_shared_boundaries ||
28659 !found_on_haloed_element_with_other_processor)
28662 if (time_stepper_pt != 0)
28677 new_el_pt->
node_pt(node_index) = new_nod_pt;
28682 for (
unsigned i = 0;
i < n_original_boundaries_node_is_on;
i++)
28684 add_boundary_node(original_boundaries_node_is_on[
i], new_nod_pt);
28687 zeta[0] = zeta_coordinates[
i];
28689 original_boundaries_node_is_on[
i], zeta);
28699 if (!found_node_in_other_shared_boundaries ||
28700 !found_on_haloed_element_with_other_processor)
28703 if (time_stepper_pt != 0)
28705 new_nod_pt = new_el_pt->
construct_node(node_index, time_stepper_pt);
28716 new_el_pt->
node_pt(node_index) = new_nod_pt;
28728 new_nodes_on_domain.push_back(new_nod_pt);
28734 if (!found_node_in_other_shared_boundaries ||
28735 !found_on_haloed_element_with_other_processor)
28738 this->add_node_pt(new_nod_pt);
28747 if (new_alg_nod_pt != 0)
28756 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28758 <<
" Alg node update id "
28763 unsigned update_id =
28770 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28772 <<
" Alg node # of ref values "
28776 unsigned n_ref_val =
28781 ref_value.resize(n_ref_val);
28782 for (
unsigned i_ref = 0; i_ref < n_ref_val; i_ref++)
28795 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28797 <<
" Alg node # of geom objects "
28801 unsigned n_geom_obj =
28806 geom_object_pt.resize(n_geom_obj);
28807 for (
unsigned i_geom = 0; i_geom < n_geom_obj; i_geom++)
28809 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28811 <<
" Alg node: geom object index "
28815 unsigned geom_index =
28830 if (!found_node_in_other_shared_boundaries ||
28831 !found_on_haloed_element_with_other_processor)
28836 update_id, alg_mesh_pt, geom_object_pt, ref_value);
28850 if (!found_node_in_other_shared_boundaries ||
28851 !found_on_haloed_element_with_other_processor)
28857 if (macro_nod_pt != 0)
28872 s_in_macro_node_update_element);
28876 new_el_pt, s_in_macro_node_update_element, geom_object_vector_pt);
28883 unsigned n_new_val = new_nod_pt->
nvalue();
28889 if (!found_node_in_other_shared_boundaries ||
28890 !found_on_haloed_element_with_other_processor)
28892 if (n_val > n_new_val)
28908 new std::map<unsigned, unsigned>;
28912 std::map<unsigned, unsigned>* map_pt =
28917 const unsigned id_face = 0;
28919 std::map<unsigned, unsigned>::const_iterator p =
28920 map_pt->find(id_face);
28923 if (p == map_pt->end())
28927 (*map_pt)[id_face] = n_new_val;
28930 new_nod_pt->
resize(n_val);
28940 if (solid_nod_pt != 0)
28943 for (
unsigned i_val = 0; i_val < n_solid_val; i_val++)
28945 for (
unsigned t = 0;
t < n_prev;
t++)
28954 if (!found_node_in_other_shared_boundaries ||
28955 !found_on_haloed_element_with_other_processor)
28958 t, i_val, read_data);
28964 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28966 <<
" Number of values solid node: "
28970 const unsigned nvalues_solid_node =
28973 for (
unsigned i = 0;
i < nvalues_solid_node;
i++)
28975 values_solid_node[
i] =
28983 if (!found_node_in_other_shared_boundaries ||
28984 !found_on_haloed_element_with_other_processor)
28986 unsigned index = 0;
28994 for (
unsigned i_val = 0; i_val < n_val; i_val++)
28996 for (
unsigned t = 0;
t < n_prev;
t++)
29005 if (!found_node_in_other_shared_boundaries ||
29006 !found_on_haloed_element_with_other_processor)
29015 unsigned n_dim = new_nod_pt->
ndim();
29016 for (
unsigned idim = 0; idim < n_dim; idim++)
29018 for (
unsigned t = 0;
t < n_prev;
t++)
29027 if (!found_node_in_other_shared_boundaries ||
29028 !found_on_haloed_element_with_other_processor)
29031 new_nod_pt->
x(
t, idim) = read_data;
29044 if (n_shd_bnd_with_other_procs_have_node > 0 &&
29048 !found_node_in_other_shared_boundaries)
29056 this->update_other_proc_shd_bnd_node_helper(new_nod_pt,
29057 other_proc_shd_bnd_node_pt,
29060 other_shared_boundaries,
29063 node_name_to_global_index,
29064 global_shared_node_pt);
29077 template<
class ELEMENT>
29082 tmp_segment_nodes.clear();
29092 unsigned n_repeated_ele = 0;
29095 const unsigned n_regions = this->nregion();
29103 for (
unsigned rr = 0; rr < n_regions; rr++)
29105 const unsigned region_id =
29106 static_cast<unsigned>(this->Region_attribute[rr]);
29109 const unsigned nel_in_region =
29110 this->nboundary_element_in_region(b, region_id);
29113 unsigned nel_repeated_in_region = 0;
29117 if (nel_in_region > 0)
29121 bool repeated =
false;
29124 for (
unsigned e = 0;
e < nel_in_region;
e++)
29128 this->boundary_element_in_region_pt(b, region_id,
e);
29130 #ifdef OOMPH_HAS_MPI
29132 if (this->is_mesh_distributed() && bulk_elem_pt->
is_halo())
29143 this->face_index_at_boundary_in_region(b, region_id,
e);
29152 const unsigned n_nodes = tmp_ele_pt->
nnode();
29154 std::pair<Node*, Node*> tmp_pair = std::make_pair(
29157 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
29161 unsigned n_done_nodes = done_nodes_pt.size();
29162 for (
unsigned l = 0; l < n_done_nodes; l++)
29164 if (tmp_pair == done_nodes_pt[l] ||
29165 tmp_pair_inverse == done_nodes_pt[l])
29167 nel_repeated_in_region++;
29178 done_nodes_pt.push_back(tmp_pair);
29180 face_el_pt.push_back(tmp_ele_pt);
29196 nel += nel_in_region;
29199 n_repeated_ele += nel_repeated_in_region;
29210 nel = this->nboundary_element(b);
29217 bool repeated =
false;
29220 for (
unsigned e = 0;
e < nel;
e++)
29225 #ifdef OOMPH_HAS_MPI
29227 if (this->is_mesh_distributed() && bulk_elem_pt->
is_halo())
29237 int face_index = this->face_index_at_boundary(b,
e);
29245 const unsigned n_nodes = tmp_ele_pt->
nnode();
29247 std::pair<Node*, Node*> tmp_pair = std::make_pair(
29250 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
29254 unsigned n_done_nodes = done_nodes_pt.size();
29255 for (
unsigned l = 0; l < n_done_nodes; l++)
29257 if (tmp_pair == done_nodes_pt[l] ||
29258 tmp_pair_inverse == done_nodes_pt[l])
29271 done_nodes_pt.push_back(tmp_pair);
29273 face_el_pt.push_back(tmp_ele_pt);
29292 nel -= n_repeated_ele;
29295 if (nel != face_el_pt.size())
29297 std::ostringstream error_message;
29299 <<
"The independet counting of face elements (" << nel <<
") for "
29300 <<
"boundary (" << b <<
") is different\n"
29301 <<
"from the real number of face elements in the container ("
29302 << face_el_pt.size() <<
")\n";
29304 error_message.str(),
29305 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29306 OOMPH_EXCEPTION_LOCATION);
29314 const unsigned nnon_halo_face_elements = nel;
29322 unsigned nsorted_face_elements = 0;
29326 std::map<FiniteElement*, bool> done_ele;
29331 std::map<FiniteElement*, bool> is_inverted;
29336 while (nsorted_face_elements < nnon_halo_face_elements)
29340 std::list<FiniteElement*> sorted_el_pt;
29344 bool found_initial_face_element =
false;
29349 unsigned iface = 0;
29350 #ifdef OOMPH_HAS_MPI
29351 if (this->is_mesh_distributed())
29353 for (iface = 0; iface < nel; iface++)
29355 ele_face_pt = face_el_pt[iface];
29357 if (!done_ele[ele_face_pt])
29362 found_initial_face_element =
true;
29365 nsorted_face_elements++;
29369 sorted_el_pt.push_back(ele_face_pt);
29371 done_ele[ele_face_pt] =
true;
29382 ele_face_pt = face_el_pt[0];
29385 found_initial_face_element =
true;
29388 nsorted_face_elements++;
29392 sorted_el_pt.push_back(ele_face_pt);
29394 done_ele[ele_face_pt] =
true;
29395 #ifdef OOMPH_HAS_MPI
29400 if (!found_initial_face_element)
29402 std::ostringstream error_message;
29403 error_message <<
"Could not find an initial face element for the "
29404 "current segment\n";
29406 error_message.str(),
29407 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29408 OOMPH_EXCEPTION_LOCATION);
29413 const unsigned nnod = ele_face_pt->
nnode();
29418 Node* right_node_pt = ele_face_pt->
node_pt(nnod - 1);
29422 bool face_element_added =
false;
29432 for (
unsigned iiface = iface; iiface < nel; iiface++)
29435 face_element_added =
false;
29438 ele_face_pt = face_el_pt[iiface];
29442 if (!done_ele[ele_face_pt])
29445 Node* local_left_node_pt = ele_face_pt->node_pt(0);
29446 Node* local_right_node_pt = ele_face_pt->node_pt(nnod - 1);
29449 if (left_node_pt == local_right_node_pt)
29451 left_node_pt = local_left_node_pt;
29452 sorted_el_pt.push_front(ele_face_pt);
29453 is_inverted[ele_face_pt] =
false;
29454 face_element_added =
true;
29457 else if (left_node_pt == local_left_node_pt)
29459 left_node_pt = local_right_node_pt;
29460 sorted_el_pt.push_front(ele_face_pt);
29461 is_inverted[ele_face_pt] =
true;
29462 face_element_added =
true;
29465 else if (right_node_pt == local_left_node_pt)
29467 right_node_pt = local_right_node_pt;
29468 sorted_el_pt.push_back(ele_face_pt);
29469 is_inverted[ele_face_pt] =
false;
29470 face_element_added =
true;
29473 else if (right_node_pt == local_right_node_pt)
29475 right_node_pt = local_left_node_pt;
29476 sorted_el_pt.push_back(ele_face_pt);
29477 is_inverted[ele_face_pt] =
true;
29478 face_element_added =
true;
29481 if (face_element_added)
29484 done_ele[ele_face_pt] =
true;
29485 nsorted_face_elements++;
29493 }
while (face_element_added &&
29494 (nsorted_face_elements < nnon_halo_face_elements));
29497 segment_sorted_ele_pt.push_back(sorted_el_pt);
29502 const unsigned nsegments = segment_sorted_ele_pt.size();
29505 if (nnon_halo_face_elements > 0 && nsegments == 0)
29507 std::ostringstream error_message;
29509 <<
"The number of segments is zero, but the number of nonhalo\n"
29510 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
29512 error_message.str(),
29513 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29514 OOMPH_EXCEPTION_LOCATION);
29523 tmp_segment_nodes.resize(nsegments);
29525 for (
unsigned is = 0; is < nsegments; is++)
29528 if (segment_sorted_ele_pt[is].size() == 0)
29530 std::ostringstream error_message;
29531 error_message <<
"The (" << is <<
")-th segment has no elements\n";
29533 error_message.str(),
29534 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29535 OOMPH_EXCEPTION_LOCATION);
29540 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
29543 const unsigned nnod = first_ele_pt->
nnode();
29547 if (is_inverted[first_ele_pt])
29549 first_node_pt = first_ele_pt->
node_pt(nnod - 1);
29553 tmp_segment_nodes[is].push_back(first_node_pt);
29556 for (std::list<FiniteElement*>::iterator it =
29557 segment_sorted_ele_pt[is].begin();
29558 it != segment_sorted_ele_pt[is].end();
29565 Node* last_node_pt = 0;
29568 if (!is_inverted[ele_pt])
29570 last_node_pt = ele_pt->
node_pt(nnod - 1);
29574 last_node_pt = ele_pt->
node_pt(0);
29578 tmp_segment_nodes[is].push_back(last_node_pt);
29587 for (
unsigned e = 0;
e < nel;
e++)
29589 delete face_el_pt[
e];
29600 template<
class ELEMENT>
29611 double min_angle = compute_area_target(elem_error, target_area);
29616 bool quantised_areas =
true;
29617 if (quantised_areas)
29619 unsigned n = target_area.size();
29620 double total_area = 0;
29626 #ifdef OOMPH_HAS_MPI
29627 if (this->is_mesh_distributed())
29631 double sub_area = 0.0;
29634 for (
unsigned e = 0;
e < n;
e++)
29640 sub_area += ele_pt->
size();
29649 &sub_area, &total_area, 1, MPI_DOUBLE, MPI_SUM, comm_pt->mpi_comm());
29653 for (
unsigned e = 0;
e < n;
e++)
29655 total_area += this->finite_element_pt(
e)->size();
29662 for (
unsigned e = 0;
e < n;
e++)
29664 total_area += this->finite_element_pt(
e)->size();
29668 for (
unsigned e = 0;
e < n;
e++)
29671 unsigned(ceil(log(target_area[
e] / total_area) / log(1.0 / 3.0))) - 1;
29672 double new_target_area = total_area * pow(1.0 / 3.0,
int(level));
29673 target_area[
e] = new_target_area;
29683 unsigned n = target_area.size();
29684 double max_area = 0.0;
29685 double min_area = DBL_MAX;
29686 for (
unsigned e = 0;
e < n;
e++)
29688 if (target_area[
e] > max_area) max_area = target_area[
e];
29689 if (target_area[
e] < min_area) min_area = target_area[
e];
29704 oomph_info <<
"Maximum target area: " << max_area << std::endl;
29705 oomph_info <<
"Minimum target area: " << min_area << std::endl;
29706 oomph_info <<
"Number of elements to be refined: " << this->Nrefined
29708 oomph_info <<
"Number of elements to be unrefined: " << this->Nunrefined
29710 oomph_info <<
"Min. angle: " << min_angle << std::endl;
29712 double orig_max_area, orig_min_area;
29713 this->max_and_min_element_size(orig_max_area, orig_min_area);
29714 oomph_info <<
"Max./min. element size in original mesh: " << orig_max_area
29715 <<
" " << orig_min_area << std::endl;
29723 bool check_only =
true;
29724 bool outer_boundary_update_necessary =
false;
29725 bool inner_boundary_update_necessary =
false;
29726 bool inner_open_boundary_update_necessary =
false;
29730 const unsigned nouter = this->Outer_boundary_pt.size();
29732 if (this->is_automatic_creation_of_vertices_on_boundaries_allowed())
29735 for (
unsigned i_outer = 0; i_outer < nouter; i_outer++)
29737 outer_boundary_update_necessary = this->update_polygon_using_face_mesh(
29738 this->Outer_boundary_pt[i_outer], check_only);
29740 if (outer_boundary_update_necessary)
break;
29745 if (!outer_boundary_update_necessary)
29749 const unsigned nhole = this->Internal_polygon_pt.size();
29751 inner_boundary_update_necessary =
29752 this->surface_remesh_for_inner_hole_boundaries(internal_point_coord,
29757 if (!inner_boundary_update_necessary)
29759 const unsigned n_open_polyline = this->Internal_open_curve_pt.size();
29761 for (
unsigned i = 0;
i < n_open_polyline;
i++)
29763 inner_open_boundary_update_necessary =
29764 this->update_open_curve_using_face_mesh(
29765 this->Internal_open_curve_pt[
i], check_only);
29767 if (inner_open_boundary_update_necessary)
break;
29779 #ifdef OOMPH_HAS_MPI
29784 int adapt_this_processor = 0;
29785 if (this->is_mesh_distributed())
29788 if ((Nrefined > 0) || (Nunrefined > max_keep_unrefined()) ||
29789 (min_angle < min_permitted_angle()) ||
29790 (outer_boundary_update_necessary) ||
29791 (inner_boundary_update_necessary) ||
29792 (inner_open_boundary_update_necessary))
29794 adapt_this_processor = 1;
29801 MPI_Allreduce(&adapt_this_processor,
29806 comm_pt->mpi_comm());
29814 if ((Nrefined > 0) || (Nunrefined > max_keep_unrefined()) ||
29815 (min_angle < min_permitted_angle()) ||
29816 (outer_boundary_update_necessary) ||
29817 (inner_boundary_update_necessary) ||
29818 (inner_open_boundary_update_necessary) || (adapt_all))
29820 if (!((Nrefined > 0) || (Nunrefined > max_keep_unrefined())))
29822 if ((outer_boundary_update_necessary) ||
29823 (inner_boundary_update_necessary) ||
29824 (inner_open_boundary_update_necessary))
29827 <<
"Mesh regeneration triggered by inaccurate interface/surface\n"
29828 <<
"representation; setting Nrefined to number of elements.\n"
29829 <<
"outer_boundary_update_necessary : "
29830 << outer_boundary_update_necessary <<
"\n"
29831 <<
"inner_boundary_update_necessary : "
29832 << inner_boundary_update_necessary <<
"\n"
29833 <<
"inner_open_boundary_update_necessary: "
29834 << inner_open_boundary_update_necessary <<
"\n";
29835 Nrefined = nelement();
29839 oomph_info <<
"Mesh regeneration triggered by min angle criterion;\n"
29840 <<
"setting Nrefined to number of elements.\n";
29841 Nrefined = nelement();
29848 #ifdef OOMPH_HAS_MPI
29849 else if (this->is_mesh_distributed() && adapt_this_processor == 0 &&
29852 oomph_info <<
"Mesh regeneration triggered by (" << adapt_all
29853 <<
") processor(s) "
29854 <<
"that require(s)\n adaptation\n";
29869 add_vertices_for_non_deletion();
29874 #ifdef OOMPH_HAS_MPI
29879 if (this->is_mesh_distributed())
29881 synchronize_shared_boundary_connections();
29894 if (this->is_automatic_creation_of_vertices_on_boundaries_allowed())
29897 unsigned nhole = this->Internal_polygon_pt.size();
29899 this->surface_remesh_for_inner_hole_boundaries(internal_point_coord);
29902 for (
unsigned i_outer = 0; i_outer < nouter; i_outer++)
29904 this->update_polygon_using_face_mesh(
29905 this->Outer_boundary_pt[i_outer]);
29910 unsigned n_open_polyline = this->Internal_open_curve_pt.size();
29911 for (
unsigned i = 0;
i < n_open_polyline;
i++)
29913 this->update_open_curve_using_face_mesh(
29914 this->Internal_open_curve_pt[
i]);
29923 const unsigned ninternal = this->Internal_polygon_pt.size();
29924 for (
unsigned i_internal = 0; i_internal < ninternal; i_internal++)
29926 this->update_polygon_using_elements_area(
29927 this->Internal_polygon_pt[i_internal], target_area);
29932 for (
unsigned i_outer = 0; i_outer < nouter; i_outer++)
29934 this->update_polygon_using_elements_area(
29935 this->Outer_boundary_pt[i_outer], target_area);
29940 const unsigned n_open_polyline = this->Internal_open_curve_pt.size();
29941 for (
unsigned i = 0;
i < n_open_polyline;
i++)
29943 this->update_open_curve_using_elements_area(
29944 this->Internal_open_curve_pt[
i], target_area);
29955 #ifdef OOMPH_HAS_MPI
29957 if (this->is_mesh_distributed())
29960 const unsigned my_rank = this->communicator_pt()->my_rank();
29963 const unsigned n_curves = this->nshared_boundary_curves(my_rank);
29965 for (
unsigned nc = 0; nc < n_curves; nc++)
29968 this->update_shared_curve_using_elements_area(
29969 this->Shared_boundary_polyline_pt[my_rank][nc],
29996 const unsigned n_boundary = this->nboundary();
29998 const double t_start_first_stage_segments_connectivity =
30004 #ifdef OOMPH_HAS_MPI
30007 if (this->is_mesh_distributed())
30009 this->Assigned_segments_initial_zeta_values.clear();
30017 for (
unsigned b = 0; b < n_boundary; ++b)
30022 #ifdef OOMPH_HAS_MPI
30023 if (this->is_mesh_distributed())
30029 this->compute_boundary_segments_connectivity_and_initial_zeta_values(
30038 if (this->boundary_geom_object_pt(b) == 0)
30040 this->
template setup_boundary_coordinates<ELEMENT>(b);
30046 #ifdef OOMPH_HAS_MPI
30047 if (this->is_mesh_distributed())
30052 this->synchronize_boundary_coordinates(b);
30061 const double t_total_first_stage_segments_connectivity =
30072 #ifdef OOMPH_HAS_MPI
30087 if (this->is_mesh_distributed())
30091 this->create_distributed_domain_representation(tmp_outer_polygons_pt,
30092 tmp_open_curves_pt);
30095 this->create_temporary_boundary_connections(tmp_outer_polygons_pt,
30096 tmp_open_curves_pt);
30112 restore_boundary_connections(resume_initial_connection_polyline_pt,
30113 resume_final_connection_polyline_pt);
30119 unsigned n_region = this->nregion();
30123 this->Regions_coordinates.begin();
30124 it != this->Regions_coordinates.end();
30131 unsigned region_id = it->first;
30134 oomph_info <<
"Region " << region_id <<
": " << it->second[0] <<
" "
30135 << it->second[1] <<
" ";
30138 unsigned n_region_element = this->nregion_element(region_id);
30139 if (n_region_element > 0)
30143 this->region_element_pt(region_id, 0);
30146 for (
unsigned n = 0; n < 3; n++)
30149 for (
unsigned i = 0;
i < 2;
i++)
30151 centroid[
i] += nod_pt->
x(
i);
30154 for (
unsigned i = 0;
i < 2;
i++)
30159 it->second = centroid;
30161 oomph_info <<
" , " << it->second[0] <<
" " << it->second[1]
30190 #ifdef OOMPH_HAS_MPI
30191 if (!this->is_mesh_distributed())
30195 closed_curve_pt.resize(nouter);
30196 for (
unsigned i = 0;
i < nouter;
i++)
30198 closed_curve_pt[
i] = this->Outer_boundary_pt[
i];
30202 const unsigned n_holes = this->Internal_polygon_pt.size();
30203 hole_pt.resize(n_holes);
30204 for (
unsigned i = 0;
i < n_holes;
i++)
30206 hole_pt[
i] = this->Internal_polygon_pt[
i];
30210 const unsigned n_open_curves = this->Internal_open_curve_pt.size();
30211 open_curves_pt.resize(n_open_curves);
30212 for (
unsigned i = 0;
i < n_open_curves;
i++)
30214 open_curves_pt[
i] = this->Internal_open_curve_pt[
i];
30220 #ifdef OOMPH_HAS_MPI
30225 const unsigned n_tmp_outer = tmp_outer_polygons_pt.size();
30226 closed_curve_pt.resize(n_tmp_outer);
30227 for (
unsigned i = 0;
i < n_tmp_outer;
i++)
30229 closed_curve_pt[
i] = tmp_outer_polygons_pt[
i];
30233 const unsigned n_open_curves = tmp_open_curves_pt.size();
30234 open_curves_pt.resize(n_open_curves);
30235 for (
unsigned i = 0;
i < n_open_curves;
i++)
30237 open_curves_pt[
i] = tmp_open_curves_pt[
i];
30266 this->Extra_holes_coordinates;
30270 this->Regions_coordinates;
30273 if (this->Use_attributes)
30279 if (!this->is_automatic_creation_of_vertices_on_boundaries_allowed())
30281 triangle_mesh_parameters
30287 #ifdef OOMPH_HAS_MPI
30288 if (this->is_mesh_distributed())
30301 if (solid_mesh_pt != 0)
30304 triangle_mesh_parameters, this->Time_stepper_pt);
30309 triangle_mesh_parameters, this->Time_stepper_pt);
30312 if (Print_timings_level_adaptation > 2)
30314 oomph_info <<
"CPU for building background mesh: "
30321 const double this_max_element_size = this->max_element_size();
30322 const double this_min_element_size = this->min_element_size();
30327 const double this_min_permitted_angle = this->min_permitted_angle();
30333 #ifdef OOMPH_HAS_MPI
30337 if (this->is_mesh_distributed())
30341 if (this->nshared_boundary_overlaps_internal_boundary() > 0)
30346 this->shared_boundary_overlaps_internal_boundary();
30351 this->shared_boundaries_ids();
30372 this->boundary_geom_object_pt();
30377 this->boundary_coordinate_limits();
30379 const double t_start_second_stage_segments_connectivity =
30382 for (
unsigned b = 0; b < n_boundary; b++)
30387 #ifdef OOMPH_HAS_MPI
30388 if (this->is_mesh_distributed())
30405 tmp_new_mesh_pt->template setup_boundary_coordinates<ELEMENT>(b);
30409 const double t_total_second_stage_segments_connectivity =
30416 for (
unsigned b = 0; b < n_boundary; b++)
30418 this->snap_nodes_onto_boundary(tmp_new_mesh_pt, b);
30421 const double t_total_snap_nodes_bg_mesh =
30424 if (Print_timings_level_adaptation > 2)
30426 oomph_info <<
"CPU for snapping nodes onto boundaries "
30427 <<
"(background mesh): " << t_total_snap_nodes_bg_mesh
30432 if (Mesh_update_fct_pt != 0)
30434 Mesh_update_fct_pt(tmp_new_mesh_pt);
30467 bool use_eulerian_coords =
false;
30468 if (solid_mesh_pt != 0)
30470 use_eulerian_coords =
true;
30474 #ifdef OOMPH_HAS_CGAL
30478 if (use_eulerian_coords)
30488 if (use_eulerian_coords)
30493 bin_dim[0] = Nbin_x_for_area_transfer;
30494 bin_dim[1] = Nbin_y_for_area_transfer;
30502 std::map<GeneralisedElement*, unsigned> element_number;
30503 unsigned nelem = this->nelement();
30504 for (
unsigned e = 0;
e < nelem;
e++)
30506 element_number[this->element_pt(
e)] =
e;
30509 #ifndef OOMPH_HAS_CGAL
30520 if (bin_array_pt == 0)
30523 "Sample point container has to be NonRefineableBinArray",
30524 OOMPH_CURRENT_FUNCTION,
30525 OOMPH_EXCEPTION_LOCATION);
30529 unsigned n_bin = 0;
30530 unsigned max_n_entry = 0;
30531 unsigned min_n_entry = UINT_MAX;
30532 unsigned tot_n_entry = 0;
30533 unsigned n_empty = 0;
30535 n_bin, max_n_entry, min_n_entry, tot_n_entry, n_empty);
30538 <<
" nbin:(" << n_bin <<
")"
30539 <<
" nempty:(" << n_empty <<
")"
30540 <<
" min:(" << min_n_entry <<
")"
30541 <<
" max:(" << max_n_entry <<
")"
30542 <<
" average entries:("
30543 << double(tot_n_entry) / double(n_bin) <<
")" << std::endl;
30548 oomph_info <<
"Going into diffusion bit...\n";
30550 oomph_info <<
"Back from diffusion bit...\n";
30556 unsigned n_bin = 0;
30557 unsigned max_n_entry = 0;
30558 unsigned min_n_entry = UINT_MAX;
30559 unsigned tot_n_entry = 0;
30560 unsigned n_empty = 0;
30562 n_bin, max_n_entry, min_n_entry, tot_n_entry, n_empty);
30565 <<
" nbin:(" << n_bin <<
")"
30566 <<
" nempty:(" << n_empty <<
")"
30567 <<
" min:(" << min_n_entry <<
")"
30568 <<
" max:(" << max_n_entry <<
")"
30569 <<
" average entries:("
30570 << double(tot_n_entry) / double(n_bin) <<
")" << std::endl;
30577 double t_total_map = 0.0;
30580 unsigned counter_map = 0;
30585 const std::map<unsigned,
30590 const unsigned n_bin = bins_pt->size();
30595 bin_min_target_area.resize(n_bin);
30596 for (
unsigned u = 0; u < n_bin; u++)
30598 bin_min_target_area[u] = 0.0;
30605 for (IT it = bins_pt->begin(); it != bins_pt->end(); it++)
30608 unsigned ib = (*it).first;
30611 const unsigned n_ele_bin = (*it).second.size();
30614 for (
unsigned ee = 0; ee < n_ele_bin; ee++)
30619 const unsigned ele_number = element_number[ele_pt];
30628 if (bin_min_target_area[ib] != 0)
30630 bin_min_target_area[ib] =
30631 std::min(bin_min_target_area[ib], target_area[ele_number]);
30635 bin_min_target_area[ib] = target_area[ele_number];
30642 oomph_info <<
"CPU for map[counter=" << counter_map
30643 <<
"]: " << t_total_map << std::endl;
30647 const bool output_bins =
false;
30650 unsigned length = bin_min_target_area.size();
30651 for (
unsigned u = 0; u < length; u++)
30654 <<
",target area: " << bin_min_target_area[u] << std::endl;
30665 #ifdef OOMPH_HAS_MPI
30667 unsigned n_ele_need_refinement = 0;
30671 double t_total_third_stage_segments_connectivity = 0.0;
30674 double t_total_transfer_target_areas = 0.0;
30677 double t_total_limit_target_areas = 0.0;
30680 double t_total_create_new_adapted_mesh = 0.0;
30683 double t_total_snap_nodes = 0.0;
30686 double t_total_wait_other_processors = 0.0;
30700 nelem = tmp_new_mesh_pt->
nelement();
30705 for (
unsigned e = 0;
e < nelem;
e++)
30708 dynamic_cast<ELEMENT*
>(tmp_new_mesh_pt->
element_pt(
e));
30709 unsigned nint = el_pt->integral_pt()->nweight();
30710 for (
unsigned ipt = 0; ipt < nint; ipt++)
30714 for (
unsigned i = 0;
i < 2;
i++)
30716 s[
i] = el_pt->integral_pt()->knot(ipt,
i);
30720 el_pt->interpolated_x(
s, x);
30727 unsigned max_sample_points =
30728 Max_sample_points_for_limited_locate_zeta_during_target_area_transfer;
30731 ->limited_locate_zeta(x, max_sample_points, geom_obj_pt,
s);
30733 if (geom_obj_pt == 0)
30735 std::stringstream error_message;
30736 error_message <<
"Limited locate zeta failed for zeta = [ "
30737 << x[0] <<
" " << x[1] <<
" ]. Makes no sense!\n";
30739 OOMPH_CURRENT_FUNCTION,
30740 OOMPH_EXCEPTION_LOCATION);
30749 std::stringstream error_message;
30750 error_message <<
"Cast to FE for GeomObject returned by "
30751 "limited locate zeta failed for zeta = [ "
30752 << x[0] <<
" " << x[1] <<
" ]. Makes no sense!\n";
30754 OOMPH_CURRENT_FUNCTION,
30755 OOMPH_EXCEPTION_LOCATION);
30762 double tg_area = target_area[element_number[fe_pt]];
30769 if (new_transferred_target_area[
e] != 0)
30771 new_transferred_target_area[
e] =
30772 std::min(new_transferred_target_area[
e], tg_area);
30776 new_transferred_target_area[
e] = tg_area;
30786 int bin_number = 0;
30787 bin_array_pt->
get_bin(x, bin_number);
30790 if (bin_number < 0)
30793 std::stringstream error_message;
30794 error_message <<
"Very odd -- we're looking for a point[ " << x[0]
30795 <<
" " << x[1] <<
" ] that's not even \n"
30796 <<
"located within the bin boundaries.\n";
30798 "RefineableTriangleMesh::adapt()",
30799 OOMPH_EXCEPTION_LOCATION);
30807 if (new_transferred_target_area[
e] != 0)
30809 new_transferred_target_area[
e] =
30810 std::min(new_transferred_target_area[
e],
30811 bin_min_target_area[bin_number]);
30815 new_transferred_target_area[
e] =
30816 bin_min_target_area[bin_number];
30828 const bool output_target_areas =
false;
30829 if (output_target_areas)
30831 unsigned length = new_transferred_target_area.size();
30832 for (
unsigned u = 0; u < length; u++)
30835 <<
",target area: " << new_transferred_target_area[u]
30839 oomph_info <<
"Time for loop over integration points in new mesh: "
30872 const double t_sub_total_transfer_target_areas =
30875 if (Print_timings_level_adaptation > 2)
30878 const unsigned n_element = this->nelement();
30880 const unsigned n_element_background = tmp_new_mesh_pt->
nelement();
30882 oomph_info <<
"CPU for transfer of target areas "
30883 <<
"[n_ele_old_mesh=" << n_element
30884 <<
", n_ele_background_mesh=" << n_element_background
30885 <<
"] (iter " << iter
30886 <<
"): " << t_sub_total_transfer_target_areas << std::endl;
30890 t_total_transfer_target_areas += t_sub_total_transfer_target_areas;
30905 #ifdef OOMPH_HAS_MPI
30906 unsigned n_ele_need_refinement_iter = 0;
30918 const unsigned nel_new = tmp_new_mesh_pt->
nelement();
30920 for (
unsigned e = 0;
e < nel_new;
e++)
30926 const double new_area = new_transferred_target_area[
e];
30927 if (new_area <= 0.0)
30929 std::ostringstream error_stream;
30931 <<
"This shouldn't happen! Element whose centroid is at "
30940 <<
" has no target area assigned\n";
30942 OOMPH_CURRENT_FUNCTION,
30943 OOMPH_EXCEPTION_LOCATION);
30949 new_target_area[
e] = new_area;
30950 if (new_target_area[
e] < f_ele_pt->
size() / 3.0)
30952 new_target_area[
e] = f_ele_pt->
size() / 3.0;
30970 #ifdef OOMPH_HAS_MPI
30972 n_ele_need_refinement_iter++;
30983 const double t_sub_total_limit_target_areas =
30987 t_total_limit_target_areas += t_sub_total_limit_target_areas;
30989 if (Print_timings_level_adaptation > 2)
30992 const unsigned n_element = this->nelement();
30994 const unsigned n_element_background = tmp_new_mesh_pt->
nelement();
30996 oomph_info <<
"CPU for limiting target areas "
30997 <<
"[n_ele_old_mesh=" << n_element
30998 <<
", n_ele_background_mesh=" << n_element_background
30999 <<
"] (iter " << iter
31000 <<
"): " << t_sub_total_limit_target_areas << std::endl;
31006 <<
"All area adjustments accommodated by max. permitted area"
31007 <<
" reduction \n";
31011 oomph_info <<
"NOT all area adjustments accommodated by max. "
31012 <<
"permitted area reduction \n";
31028 if (solid_mesh_pt != 0)
31032 tmp_new_triangulateio,
31033 this->Time_stepper_pt,
31034 this->Use_attributes,
31035 this->Allow_automatic_creation_of_vertices_on_boundaries,
31036 this->communicator_pt());
31043 tmp_new_triangulateio,
31044 this->Time_stepper_pt,
31045 this->Use_attributes,
31046 this->Allow_automatic_creation_of_vertices_on_boundaries,
31047 this->communicator_pt());
31051 const double t_sub_total_create_new_adapted_mesh =
31055 t_total_create_new_adapted_mesh += t_sub_total_create_new_adapted_mesh;
31057 if (Print_timings_level_adaptation > 2)
31060 const unsigned n_element_new_adapted_mesh = new_mesh_pt->
nelement();
31062 oomph_info <<
"CPU for creation of new adapted mesh "
31063 << t_sub_total_create_new_adapted_mesh
31064 <<
"[nele=" << n_element_new_adapted_mesh <<
"] (iter "
31065 << iter <<
"): " << t_sub_total_create_new_adapted_mesh
31069 #ifdef OOMPH_HAS_MPI
31080 if (this->nshared_boundary_overlaps_internal_boundary() > 0)
31085 this->shared_boundary_overlaps_internal_boundary();
31107 this->boundary_geom_object_pt();
31112 this->boundary_coordinate_limits();
31114 const double t_start_third_stage_segments_connectivity =
31117 for (
unsigned b = 0; b < n_boundary; b++)
31126 #ifdef OOMPH_HAS_MPI
31127 if (this->is_mesh_distributed())
31144 new_mesh_pt->template setup_boundary_coordinates<ELEMENT>(b);
31148 t_total_third_stage_segments_connectivity +=
31155 for (
unsigned b = 0; b < n_boundary; b++)
31157 this->snap_nodes_onto_boundary(new_mesh_pt, b);
31160 const double t_sub_total_snap_nodes_new_mesh =
31164 t_total_snap_nodes += t_sub_total_snap_nodes_new_mesh;
31166 if (Print_timings_level_adaptation > 2)
31168 oomph_info <<
"CPU for snapping nodes onto boundaries (new mesh) "
31169 <<
"(iter " << iter
31170 <<
"): " << t_sub_total_snap_nodes_new_mesh << std::endl;
31174 if (Mesh_update_fct_pt != 0)
31176 Mesh_update_fct_pt(new_mesh_pt);
31186 this->Time_stepper_pt,
false);
31193 delete tmp_new_mesh_pt;
31195 #ifdef OOMPH_HAS_MPI
31199 if (n_ele_need_refinement_iter == n_ele_need_refinement)
31205 n_ele_need_refinement = n_ele_need_refinement_iter;
31215 #ifdef OOMPH_HAS_MPI
31216 if (this->is_mesh_distributed())
31226 unsigned this_processor_requires_another_iteration = 1;
31231 this_processor_requires_another_iteration = 0;
31233 int nproc_not_done = this_processor_requires_another_iteration;
31238 MPI_Allreduce(&this_processor_requires_another_iteration,
31243 comm_pt->mpi_comm());
31245 if (nproc_not_done > 0)
31248 <<
"At least one processors requires further refinement. "
31249 <<
"Go for another iteration." << std::endl;
31255 const double t_sub_total_wait_other_processors =
31260 t_total_wait_other_processors += t_sub_total_wait_other_processors;
31262 if (Print_timings_level_adaptation > 2)
31264 oomph_info <<
"CPU for waiting other processors "
31265 <<
"(iter " << iter
31266 <<
"): " << t_sub_total_wait_other_processors
31278 oomph_info <<
"Going for another iteration. Current iteration ("
31279 << iter <<
")" << std::endl;
31282 tmp_new_mesh_pt = new_mesh_pt;
31290 delete mesh_geom_obj_pt;
31292 oomph_info <<
"CPU for iterative generation of new mesh (TOTAL): "
31295 if (Print_timings_level_adaptation > 1)
31297 oomph_info <<
"-- CPU for creating new adapted meshes (TOTAL): "
31298 << t_total_create_new_adapted_mesh << std::endl;
31300 oomph_info <<
"-- CPU for limiting target areas (TOTAL): "
31301 << t_total_limit_target_areas << std::endl;
31303 oomph_info <<
"-- CPU for transferring target areas (TOTAL): "
31304 << t_total_transfer_target_areas << std::endl;
31306 oomph_info <<
"-- CPU for waiting other processors (TOTAL): "
31307 << t_total_wait_other_processors << std::endl;
31319 if (!Disable_projection)
31325 if (Print_timings_projection)
31334 oomph_info <<
"About to begin projection.\n";
31343 #ifdef OOMPH_HAS_MPI
31344 if (this->is_mesh_distributed())
31352 Time* backed_up_time_pt = this->Time_stepper_pt->time_pt();
31362 project_problem_pt->
mesh_pt() = new_mesh_pt;
31367 if (!this->use_iterative_solver_for_projection())
31373 project_problem_pt->
project(
this);
31376 this->Time_stepper_pt->time_pt() = backed_up_time_pt;
31387 project_problem_pt->
mesh_pt() = new_mesh_pt;
31393 if (!this->use_iterative_solver_for_projection())
31399 project_problem_pt->
project(
this);
31403 if (Print_timings_projection)
31412 const double tt_projection =
31415 if (Print_timings_level_adaptation > 1)
31418 const unsigned n_element = this->nelement();
31420 const unsigned n_element_new = new_mesh_pt->
nelement();
31421 oomph_info <<
"CPU for projection (in mesh adaptation) "
31422 <<
"[n_ele_old_mesh=" << n_element
31423 <<
", n_ele_new_mesh=" << n_element_new
31424 <<
"]: " << tt_projection << std::endl;
31429 #ifdef OOMPH_HAS_MPI
31430 if (this->is_mesh_distributed())
31434 unsigned n_this_element_new = n_element_new;
31435 unsigned n_max_element_new_global = 0;
31437 MPI_Reduce(&n_this_element_new,
31438 &n_max_element_new_global,
31443 this->communicator_pt()->mpi_comm());
31446 double tt_this_projection = tt_projection;
31447 double tt_global_min_projection = 0.0;
31448 double tt_global_max_projection = 0.0;
31451 MPI_Reduce(&tt_this_projection,
31452 &tt_global_min_projection,
31457 this->communicator_pt()->mpi_comm());
31458 MPI_Reduce(&tt_this_projection,
31459 &tt_global_max_projection,
31464 this->communicator_pt()->mpi_comm());
31466 if (this->communicator_pt()->my_rank() == 0)
31468 oomph_info <<
"CPU for projection global (MIN): "
31469 << tt_global_min_projection << std::endl;
31470 oomph_info <<
"CPU for projection global (MAX) "
31471 <<
"[n_max_ele_new_global=" << n_max_element_new_global
31472 <<
"]: " << tt_global_max_projection << std::endl;
31474 std::cerr <<
"CPU for projection global (MIN): "
31475 << tt_global_min_projection << std::endl;
31476 std::cerr <<
"CPU for projection global (MAX): "
31477 <<
"[n_max_ele_new_global=" << n_max_element_new_global
31478 <<
"]: " << tt_global_max_projection << std::endl;
31488 oomph_info <<
"CPU for projection of solution onto new mesh: "
31492 delete project_problem_pt;
31497 oomph_info <<
"Projection disabled! The new mesh will contain zeros"
31508 unsigned nnod = nnode();
31509 for (
unsigned j = nnod; j > 0; j--)
31511 delete Node_pt[j - 1];
31512 Node_pt[j - 1] = 0;
31514 unsigned nel = nelement();
31515 for (
unsigned e = nel;
e > 0;
e--)
31517 delete Element_pt[
e - 1];
31518 Element_pt[
e - 1] = 0;
31523 nnod = new_mesh_pt->
nnode();
31524 Node_pt.resize(nnod);
31526 Element_pt.resize(nel);
31527 for (
unsigned j = 0; j < nnod; j++)
31529 Node_pt[j] = new_mesh_pt->
node_pt(j);
31531 for (
unsigned e = 0;
e < nel;
e++)
31538 unsigned nbound = 0;
31540 #ifdef OOMPH_HAS_MPI
31544 if (this->is_mesh_distributed())
31558 nbound = n_boundary;
31561 Boundary_element_pt.resize(nbound);
31562 Face_index_at_boundary.resize(nbound);
31563 Boundary_node_pt.resize(nbound);
31564 for (
unsigned b = 0; b < nbound; b++)
31567 Boundary_element_pt[b].resize(nel);
31568 Face_index_at_boundary[b].resize(nel);
31569 for (
unsigned e = 0;
e < nel;
e++)
31572 Face_index_at_boundary[b][
e] =
31576 Boundary_node_pt[b].resize(nnod);
31577 for (
unsigned j = 0; j < nnod; j++)
31584 unsigned n_region = new_mesh_pt->
nregion();
31589 this->Region_attribute.resize(n_region);
31590 for (
unsigned r = 0; r < n_region; r++)
31594 unsigned r_id =
static_cast<unsigned>(this->Region_attribute[r]);
31597 this->Region_element_pt[r_id].resize(n_region_element);
31598 for (
unsigned e = 0;
e < n_region_element;
e++)
31600 this->Region_element_pt[r_id][
e] =
31606 this->Boundary_region_element_pt.resize(nbound);
31607 this->Face_index_region_at_boundary.resize(nbound);
31610 for (
unsigned b = 0; b < nbound; ++b)
31612 for (
unsigned rr = 0; rr < n_region; rr++)
31615 unsigned r =
static_cast<unsigned>(this->Region_attribute[rr]);
31617 unsigned n_boundary_el_in_region =
31620 if (n_boundary_el_in_region > 0)
31623 this->Boundary_region_element_pt[b][r].resize(
31624 n_boundary_el_in_region);
31625 this->Face_index_region_at_boundary[b][r].resize(
31626 n_boundary_el_in_region);
31629 for (
unsigned e = 0;
e < n_boundary_el_in_region; ++
e)
31631 this->Boundary_region_element_pt[b][r][
e] =
31633 this->Face_index_region_at_boundary[b][r][
e] =
31647 #ifdef OOMPH_HAS_MPI
31648 if (this->is_mesh_distributed())
31653 if (this->is_mesh_distributed())
31655 this->Halo_node_pt.clear();
31656 this->Root_halo_element_pt.clear();
31658 this->Haloed_node_pt.clear();
31659 this->Root_haloed_element_pt.clear();
31661 this->External_halo_node_pt.clear();
31662 this->External_halo_element_pt.clear();
31664 this->External_haloed_node_pt.clear();
31665 this->External_haloed_element_pt.clear();
31670 this->reset_shared_boundary_elements_and_nodes();
31681 this->shared_boundaries_in_this_processor(
31682 my_rank_shared_boundaries_ids);
31685 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
31688 for (
unsigned i = 0;
i < nmy_rank_shd_bnd;
i++)
31691 const unsigned shd_bnd_id = my_rank_shared_boundaries_ids[
i];
31694 this->Boundary_element_pt[shd_bnd_id].clear();
31698 const unsigned tmp_nnodes = this->nshared_boundary_node(shd_bnd_id);
31699 for (
unsigned n = 0; n < tmp_nnodes; n++)
31701 Node* tmp_node_pt = this->boundary_node_pt(shd_bnd_id, n);
31708 this->set_nboundary(n_boundary);
31712 this->sort_nodes_on_shared_boundaries();
31715 this->reset_halo_haloed_scheme();
31719 for (
unsigned b = 0; b < n_boundary; b++)
31721 if (this->boundary_geom_object_pt(b) != 0)
31724 this->set_nboundary_segment_node(b, nsegments);
31729 resume_boundary_connections(resume_initial_connection_polyline_pt,
31730 resume_final_connection_polyline_pt);
31741 this->snap_nodes_onto_geometric_objects();
31749 this->Triangulateio =
31757 delete new_mesh_pt;
31760 if (Print_timings_level_adaptation > 2)
31764 oomph_info <<
"CPU for segments connectivity (first stage) [sec]: "
31765 << t_total_first_stage_segments_connectivity << std::endl;
31766 oomph_info <<
"CPU for segments connectivity (second stage) [sec]: "
31767 << t_total_second_stage_segments_connectivity << std::endl;
31768 oomph_info <<
"CPU for segments connectivity (third stage) [sec]: "
31769 << t_total_third_stage_segments_connectivity << std::endl;
31772 if (Print_timings_level_adaptation > 1)
31774 const double t_total_segments_connectivity =
31775 t_total_first_stage_segments_connectivity +
31776 t_total_second_stage_segments_connectivity +
31777 t_total_third_stage_segments_connectivity;
31779 oomph_info <<
"CPU for segments connectivity (TOTAL) [sec]: "
31780 << t_total_segments_connectivity << std::endl;
31782 if (Print_timings_level_adaptation > 2)
31785 oomph_info <<
"CPU for snapping nodes onto boundaries "
31786 <<
"(new mesh): " << t_total_snap_nodes << std::endl;
31789 t_total_snap_nodes += t_total_snap_nodes_bg_mesh;
31790 oomph_info <<
"CPU for snapping nodes onto boundaries (TOTAL): "
31791 << t_total_snap_nodes << std::endl;
31794 double max_area = 0.0;
31795 double min_area = 0.0;
31797 this->max_and_min_element_size(max_area, min_area);
31798 oomph_info <<
"Max/min element size in adapted mesh: " << max_area <<
" "
31799 << min_area << std::endl;
31801 oomph_info <<
"CPU time for final bits [sec]: "
31806 oomph_info <<
"Not enough benefit in adaptation.\n";
31812 oomph_info <<
"CPU time for adaptation [sec]: " << CPU_for_adaptation
31818 #ifdef OOMPH_HAS_MPI
31819 if (this->is_mesh_distributed())
31824 const unsigned n_proc = comm_pt->nproc();
31825 if (Print_timings_level_adaptation > 1 && n_proc > 1)
31827 double global_min_CPU_for_adaptation = 0.0;
31828 double global_max_CPU_for_adaptation = 0.0;
31829 double global_average_CPU_for_adaptation = 0.0;
31832 MPI_Reduce(&CPU_for_adaptation,
31833 &global_min_CPU_for_adaptation,
31838 comm_pt->mpi_comm());
31839 MPI_Reduce(&CPU_for_adaptation,
31840 &global_max_CPU_for_adaptation,
31845 comm_pt->mpi_comm());
31846 MPI_Reduce(&CPU_for_adaptation,
31847 &global_average_CPU_for_adaptation,
31852 comm_pt->mpi_comm());
31855 const unsigned my_rank = comm_pt->my_rank();
31859 << global_min_CPU_for_adaptation << std::endl;
31861 << global_max_CPU_for_adaptation << std::endl;
31862 oomph_info <<
"CPU for adaptation (AVERAGE): "
31863 << global_average_CPU_for_adaptation / n_proc << std::endl;
31882 template<
class ELEMENT>
31887 Boundary_connections_pt.clear();
31894 std::set<unsigned> boundary_id_with_connections;
31901 const unsigned n_outer_boundaries = this->Outer_boundary_pt.size();
31904 for (
unsigned i = 0;
i < n_outer_boundaries;
i++)
31910 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
31912 for (
unsigned p = 0; p < n_polyline; p++)
31921 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
31925 boundary_id_with_connections.insert(bnd_id);
31928 const unsigned dst_bnd_id =
31933 boundary_id_with_connections.insert(dst_bnd_id);
31941 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
31945 boundary_id_with_connections.insert(bnd_id);
31948 const unsigned dst_bnd_id =
31953 boundary_id_with_connections.insert(dst_bnd_id);
31966 const unsigned n_internal_boundaries = this->Internal_polygon_pt.size();
31969 for (
unsigned i = 0;
i < n_internal_boundaries;
i++)
31975 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
31977 for (
unsigned p = 0; p < n_polyline; p++)
31986 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
31990 boundary_id_with_connections.insert(bnd_id);
31993 const unsigned dst_bnd_id =
31998 boundary_id_with_connections.insert(dst_bnd_id);
32006 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32010 boundary_id_with_connections.insert(bnd_id);
32013 const unsigned dst_bnd_id =
32018 boundary_id_with_connections.insert(dst_bnd_id);
32031 const unsigned n_open_boundaries = this->Internal_open_curve_pt.size();
32034 for (
unsigned i = 0;
i < n_open_boundaries;
i++)
32038 this->Internal_open_curve_pt[
i];
32042 const unsigned n_curve_section = tmp_open_curve_pt->
ncurve_section();
32045 for (
unsigned p = 0; p < n_curve_section; p++)
32056 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32060 boundary_id_with_connections.insert(bnd_id);
32063 const unsigned dst_bnd_id =
32068 boundary_id_with_connections.insert(dst_bnd_id);
32076 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32080 boundary_id_with_connections.insert(bnd_id);
32083 const unsigned dst_bnd_id =
32088 boundary_id_with_connections.insert(dst_bnd_id);
32096 #ifdef OOMPH_HAS_MPI
32103 if (this->is_mesh_distributed())
32106 const unsigned my_rank = this->communicator_pt()->my_rank();
32109 const unsigned n_shared_curves = this->nshared_boundary_curves(my_rank);
32112 for (
unsigned i = 0;
i < n_shared_curves;
i++)
32116 const unsigned n_polyline = this->nshared_boundary_polyline(my_rank,
i);
32120 for (
unsigned p = 0; p < n_polyline; p++)
32124 this->shared_boundary_polyline_pt(my_rank,
i, p);
32130 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32134 boundary_id_with_connections.insert(bnd_id);
32137 const unsigned dst_bnd_id =
32142 boundary_id_with_connections.insert(dst_bnd_id);
32150 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32154 boundary_id_with_connections.insert(bnd_id);
32157 const unsigned dst_bnd_id =
32162 boundary_id_with_connections.insert(dst_bnd_id);
32180 std::map<unsigned, Vector<Vector<Node*>>> bnd_sorted_segment_node_pt;
32183 for (std::set<unsigned>::iterator it = boundary_id_with_connections.begin();
32184 it != boundary_id_with_connections.end();
32188 const unsigned bnd_id = (*it);
32189 #ifdef OOMPH_HAS_MPI
32191 if (this->is_mesh_distributed())
32194 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
32196 if (bnd_id >= init_shd_bnd_id)
32204 get_shared_boundary_segment_nodes_helper(bnd_id, tmp_shared_nodes_pt);
32207 bnd_sorted_segment_node_pt[bnd_id] = tmp_shared_nodes_pt;
32218 get_boundary_segment_nodes_helper(bnd_id, tmp_boundary_nodes_pt);
32221 bnd_sorted_segment_node_pt[bnd_id] = tmp_boundary_nodes_pt;
32235 get_boundary_segment_nodes_helper(bnd_id, tmp_boundary_nodes_pt);
32238 bnd_sorted_segment_node_pt[bnd_id] = tmp_boundary_nodes_pt;
32252 for (
unsigned i = 0;
i < n_outer_boundaries;
i++)
32258 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
32260 for (
unsigned p = 0; p < n_polyline; p++)
32269 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32272 const unsigned dst_bnd_id =
32276 const unsigned dst_chunk =
32281 bnd_sorted_segment_node_pt[bnd_id];
32285 bnd_sorted_segment_node_pt[dst_bnd_id];
32289 add_non_delete_vertices_from_boundary_helper(
32290 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32298 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32301 const unsigned dst_bnd_id =
32305 const unsigned dst_chunk =
32310 bnd_sorted_segment_node_pt[bnd_id];
32314 bnd_sorted_segment_node_pt[dst_bnd_id];
32318 add_non_delete_vertices_from_boundary_helper(
32319 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32331 for (
unsigned i = 0;
i < n_internal_boundaries;
i++)
32337 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
32339 for (
unsigned p = 0; p < n_polyline; p++)
32348 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32351 const unsigned dst_bnd_id =
32355 const unsigned dst_chunk =
32360 bnd_sorted_segment_node_pt[bnd_id];
32364 bnd_sorted_segment_node_pt[dst_bnd_id];
32368 add_non_delete_vertices_from_boundary_helper(
32369 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32377 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32380 const unsigned dst_bnd_id =
32384 const unsigned dst_chunk =
32389 bnd_sorted_segment_node_pt[bnd_id];
32393 bnd_sorted_segment_node_pt[dst_bnd_id];
32397 add_non_delete_vertices_from_boundary_helper(
32398 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32410 for (
unsigned i = 0;
i < n_open_boundaries;
i++)
32414 this->Internal_open_curve_pt[
i];
32418 const unsigned n_curve_section = tmp_open_curve_pt->
ncurve_section();
32421 for (
unsigned p = 0; p < n_curve_section; p++)
32432 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32435 const unsigned dst_bnd_id =
32439 const unsigned dst_chunk =
32444 bnd_sorted_segment_node_pt[bnd_id];
32448 bnd_sorted_segment_node_pt[dst_bnd_id];
32452 add_non_delete_vertices_from_boundary_helper(
32453 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32461 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32464 const unsigned dst_bnd_id =
32468 const unsigned dst_chunk =
32473 bnd_sorted_segment_node_pt[bnd_id];
32477 bnd_sorted_segment_node_pt[dst_bnd_id];
32481 add_non_delete_vertices_from_boundary_helper(
32482 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32490 #ifdef OOMPH_HAS_MPI
32497 if (this->is_mesh_distributed())
32500 const unsigned my_rank = this->communicator_pt()->my_rank();
32503 const unsigned n_shared_curves = this->nshared_boundary_curves(my_rank);
32506 for (
unsigned i = 0;
i < n_shared_curves;
i++)
32510 const unsigned n_polyline = this->nshared_boundary_polyline(my_rank,
i);
32514 for (
unsigned p = 0; p < n_polyline; p++)
32518 this->shared_boundary_polyline_pt(my_rank,
i, p);
32524 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32527 const unsigned dst_bnd_id =
32531 const unsigned dst_chunk =
32536 bnd_sorted_segment_node_pt[bnd_id];
32540 bnd_sorted_segment_node_pt[dst_bnd_id];
32544 add_non_delete_vertices_from_boundary_helper(
32545 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32553 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32556 const unsigned dst_bnd_id =
32560 const unsigned dst_chunk =
32565 bnd_sorted_segment_node_pt[bnd_id];
32569 bnd_sorted_segment_node_pt[dst_bnd_id];
32573 add_non_delete_vertices_from_boundary_helper(
32574 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32592 template<
class ELEMENT>
32597 const unsigned& dst_bnd_id,
32598 const unsigned& dst_bnd_chunk)
32601 const unsigned n_seg = src_bound_segment_node_pt.size();
32603 for (
unsigned iseg = 0; iseg < n_seg; iseg++)
32606 const unsigned nnode = src_bound_segment_node_pt[iseg].size();
32608 Node* left_node_pt = src_bound_segment_node_pt[iseg][0];
32609 Node* right_node_pt = src_bound_segment_node_pt[iseg][nnode - 1];
32612 const unsigned n_dst_seg = dst_bound_segment_node_pt.size();
32614 for (
unsigned jseg = 0; jseg < n_dst_seg; jseg++)
32617 const unsigned n_dst_node = dst_bound_segment_node_pt[jseg].size();
32620 for (
unsigned jnode = 0; jnode < n_dst_node; jnode++)
32624 Node* tmp_node_pt = dst_bound_segment_node_pt[jseg][jnode];
32627 if (tmp_node_pt == left_node_pt)
32631 vertex[0] = tmp_node_pt->
x(0);
32632 vertex[1] = tmp_node_pt->
x(1);
32638 Boundary_connections_pt[dst_bnd_id].insert(vertex);
32646 else if (tmp_node_pt == right_node_pt)
32650 vertex[0] = tmp_node_pt->
x(0);
32651 vertex[1] = tmp_node_pt->
x(1);
32659 Boundary_connections_pt[dst_bnd_id].insert(vertex);
32673 #ifdef OOMPH_HAS_MPI
32679 template<
class ELEMENT>
32681 ELEMENT>::synchronize_shared_boundary_connections()
32684 const unsigned nproc = this->communicator_pt()->nproc();
32686 const unsigned my_rank = this->communicator_pt()->my_rank();
32689 for (
unsigned jproc = 0; jproc < nproc; jproc++)
32694 const unsigned n_shd_bnd_jproc = this->nshared_boundaries(my_rank, jproc);
32698 if (jproc != my_rank && n_shd_bnd_jproc > 0)
32718 this->shared_boundaries_ids(my_rank, jproc);
32721 const unsigned n_shd_bnd_jproc = shd_bnd_ids.size();
32723 for (
unsigned ishd_bnd = 0; ishd_bnd < n_shd_bnd_jproc; ishd_bnd++)
32726 const unsigned shd_bnd_id = shd_bnd_ids[ishd_bnd];
32729 this->boundary_polyline_pt(shd_bnd_id);
32734 std::set<Vector<double>> no_delete_vertex;
32737 const bool boundary_receive_connections =
32738 this->boundary_connections(shd_bnd_id, chunk, no_delete_vertex);
32741 const unsigned n_non_delete_vertex = no_delete_vertex.size();
32744 if (boundary_receive_connections && n_non_delete_vertex > 0)
32747 shd_bnd_id_for_non_deletion.push_back(shd_bnd_id);
32749 chunk_for_non_deletion.push_back(chunk);
32751 number_vertices_non_deletion.push_back(n_non_delete_vertex);
32758 no_delete_vertex.begin();
32759 it != no_delete_vertex.end();
32764 tmp_vertices.push_back(vertex);
32768 vertices_for_non_deletion.push_back(tmp_vertices);
32786 MPI_Request request;
32792 const unsigned n_shd_bnd_with_non_delete_vertices =
32793 shd_bnd_id_for_non_deletion.size();
32796 const unsigned size_package = 3;
32798 const unsigned n_unsigned_data_to_send =
32799 n_shd_bnd_with_non_delete_vertices * size_package;
32809 for (
unsigned i = 0;
i < n_shd_bnd_with_non_delete_vertices;
i++)
32812 flat_package_unsigned_send[j++] = shd_bnd_id_for_non_deletion[
i];
32814 flat_package_unsigned_send[j++] = chunk_for_non_deletion[
i];
32816 flat_package_unsigned_send[j++] = number_vertices_non_deletion[
i];
32818 const unsigned n_vertices_non_deletion =
32819 number_vertices_non_deletion[
i];
32822 for (
unsigned h = 0; h < n_vertices_non_deletion; h++)
32824 flat_package_double_send.push_back(
32825 vertices_for_non_deletion[
i][h][0]);
32826 flat_package_double_send.push_back(
32827 vertices_for_non_deletion[
i][h][1]);
32833 int send_proc = jproc;
32834 int recv_proc = jproc;
32835 unsigned send_count_unsigned_values = n_unsigned_data_to_send;
32836 unsigned send_count_double_values = flat_package_double_send.size();
32841 MPI_Isend(&send_count_unsigned_values,
32846 comm_pt->mpi_comm(),
32849 unsigned receive_count_unsigned_values = 0;
32850 MPI_Recv(&receive_count_unsigned_values,
32855 comm_pt->mpi_comm(),
32858 MPI_Wait(&request, MPI_STATUS_IGNORE);
32861 if (send_count_unsigned_values != 0)
32863 MPI_Isend(&flat_package_unsigned_send[0],
32864 send_count_unsigned_values,
32868 comm_pt->mpi_comm(),
32873 if (receive_count_unsigned_values != 0)
32875 flat_package_unsigned_recv.resize(receive_count_unsigned_values);
32876 MPI_Recv(&flat_package_unsigned_recv[0],
32877 receive_count_unsigned_values,
32881 comm_pt->mpi_comm(),
32887 if (send_count_unsigned_values != 0)
32889 MPI_Wait(&request, MPI_STATUS_IGNORE);
32894 MPI_Isend(&send_count_double_values,
32899 comm_pt->mpi_comm(),
32902 unsigned receive_count_double_values = 0;
32903 MPI_Recv(&receive_count_double_values,
32908 comm_pt->mpi_comm(),
32911 MPI_Wait(&request, MPI_STATUS_IGNORE);
32914 if (send_count_double_values != 0)
32916 MPI_Isend(&flat_package_double_send[0],
32917 send_count_double_values,
32921 comm_pt->mpi_comm(),
32926 if (receive_count_double_values != 0)
32928 flat_package_double_recv.resize(receive_count_double_values);
32929 MPI_Recv(&flat_package_double_recv[0],
32930 receive_count_double_values,
32934 comm_pt->mpi_comm(),
32940 if (send_count_double_values != 0)
32942 MPI_Wait(&request, MPI_STATUS_IGNORE);
32970 for (
unsigned i = 0;
i < receive_count_unsigned_values;
i += 3)
32973 const unsigned recv_shd_bnd_id = flat_package_unsigned_recv[
i];
32974 recv_shd_bnd_id_for_non_deletion.push_back(recv_shd_bnd_id);
32976 const unsigned recv_chunk = flat_package_unsigned_recv[
i + 1];
32977 recv_chunk_for_non_deletion.push_back(recv_chunk);
32979 const unsigned recv_num_vertices = flat_package_unsigned_recv[
i + 2];
32980 recv_number_vertices_non_deletion.push_back(recv_num_vertices);
32985 for (
unsigned h = 0; h < recv_num_vertices; h++)
32988 tmp_vertex[0] = flat_package_double_recv[j++];
32989 tmp_vertex[1] = flat_package_double_recv[j++];
32991 temp_recv_vertices.push_back(tmp_vertex);
32995 recv_vertices_for_non_deletion.push_back(temp_recv_vertices);
33010 const unsigned n_recv_shd_bnd_id_for_non_deletion =
33011 recv_shd_bnd_id_for_non_deletion.size();
33014 for (
unsigned i = 0;
i < n_recv_shd_bnd_id_for_non_deletion;
i++)
33017 const unsigned shd_bnd_id = recv_shd_bnd_id_for_non_deletion[
i];
33019 unsigned chunk = recv_chunk_for_non_deletion[
i];
33026 const unsigned n_vertices = recv_number_vertices_non_deletion[
i];
33028 for (
unsigned h = 0; h < n_vertices; h++)
33032 vertex[0] = recv_vertices_for_non_deletion[
i][h][0];
33033 vertex[1] = recv_vertices_for_non_deletion[
i][h][1];
33038 Boundary_connections_pt[shd_bnd_id].insert(vertex);
33055 template<
class ELEMENT>
33065 dummy_resume_initial_connection_polyline_pt.clear();
33066 dummy_resume_final_connection_polyline_pt.clear();
33070 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
33088 const unsigned n_outer_boundaries = tmp_outer_polygons_pt.size();
33091 for (
unsigned i = 0;
i < n_outer_boundaries;
i++)
33097 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
33099 for (
unsigned p = 0; p < n_polyline; p++)
33105 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
33108 if (bnd_id < init_shd_bnd_id)
33111 restore_polyline_connections_helper(
33113 dummy_resume_initial_connection_polyline_pt,
33114 dummy_resume_final_connection_polyline_pt);
33131 const unsigned n_open_boundaries = tmp_open_curves_pt.size();
33134 for (
unsigned i = 0;
i < n_open_boundaries;
i++)
33141 const unsigned n_curve_section = tmp_open_curve_pt->
ncurve_section();
33144 for (
unsigned p = 0; p < n_curve_section; p++)
33152 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
33155 if (bnd_id < init_shd_bnd_id)
33158 restore_polyline_connections_helper(
33160 dummy_resume_initial_connection_polyline_pt,
33161 dummy_resume_final_connection_polyline_pt);
33180 template<
class ELEMENT>
33186 resume_initial_connection_polyline_pt.clear();
33187 resume_final_connection_polyline_pt.clear();
33198 const unsigned n_outer_boundaries = this->Outer_boundary_pt.size();
33201 for (
unsigned i = 0;
i < n_outer_boundaries;
i++)
33207 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
33209 for (
unsigned p = 0; p < n_polyline; p++)
33215 restore_polyline_connections_helper(
33217 resume_initial_connection_polyline_pt,
33218 resume_final_connection_polyline_pt);
33229 const unsigned n_internal_boundaries = this->Internal_polygon_pt.size();
33232 for (
unsigned i = 0;
i < n_internal_boundaries;
i++)
33238 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
33240 for (
unsigned p = 0; p < n_polyline; p++)
33246 restore_polyline_connections_helper(
33248 resume_initial_connection_polyline_pt,
33249 resume_final_connection_polyline_pt);
33260 const unsigned n_open_boundaries = this->Internal_open_curve_pt.size();
33263 for (
unsigned i = 0;
i < n_open_boundaries;
i++)
33267 this->Internal_open_curve_pt[
i];
33271 const unsigned n_curve_section = tmp_open_curve_pt->
ncurve_section();
33274 for (
unsigned p = 0; p < n_curve_section; p++)
33282 restore_polyline_connections_helper(
33284 resume_initial_connection_polyline_pt,
33285 resume_final_connection_polyline_pt);
33300 template<
class ELEMENT>
33317 const unsigned dst_bnd_id_initial =
33326 #ifdef OOMPH_HAS_MPI
33327 if (this->is_mesh_distributed())
33330 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
33332 if (dst_bnd_id_initial >= init_shd_bnd_id)
33335 const unsigned bnd_id = polyline_pt->
boundary_id();
33336 std::ostringstream error_message;
33338 <<
"INITIAL VERTEX CONNECTION\n"
33339 <<
"The current original boundary is trying to connect to a\n"
33340 <<
"shared boundary, this is not allowed. In this case the\n"
33341 <<
"shared boundary should be the one that connects with the\n"
33342 <<
"original boundary\n"
33343 <<
"The current original boundary (" << bnd_id <<
") is marked\n"
33344 <<
"to have a connection at the\nINITIAL vertex ("
33345 << src_vertex_coordinates_initial[0] <<
","
33346 << src_vertex_coordinates_initial[1] <<
")\n"
33347 <<
"with the shared boundary (" << dst_bnd_id_initial <<
")\n"
33348 <<
"This is the list of vertices on the shared destination "
33353 this->boundary_polyline_pt(dst_bnd_id_initial);
33355 const unsigned n_vertex_dst_boundary = dst_polyline->
nvertex();
33357 for (
unsigned i = 0;
i < n_vertex_dst_boundary;
i++)
33360 error_message <<
"Vertex#(i): (" << current_vertex[0] <<
", "
33361 << current_vertex[1] <<
")\n";
33364 error_message.str(),
33365 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33366 OOMPH_EXCEPTION_LOCATION);
33376 bool found_vertex_on_dst_boundary_initial =
false;
33380 unsigned sub_poly_to_connect = 0;
33383 unsigned n_vertex_connection_initial = 0;
33388 bool connecting_to_an_split_boundary =
false;
33392 bool connecting_to_an_overlaped_boundary =
false;
33394 #ifdef OOMPH_HAS_MPI
33395 if (this->is_mesh_distributed())
33400 if (this->boundary_was_splitted(dst_bnd_id_initial))
33402 connecting_to_an_split_boundary =
true;
33411 if (connecting_to_an_split_boundary)
33415 const unsigned n_sub_poly =
33416 this->nboundary_subpolylines(dst_bnd_id_initial);
33420 for (
unsigned ii = 0; ii < n_sub_poly; ii++)
33422 if (this->boundary_marked_as_shared_boundary(dst_bnd_id_initial,
33427 connecting_to_an_overlaped_boundary =
true;
33438 if (this->boundary_marked_as_shared_boundary(dst_bnd_id_initial, 0))
33441 connecting_to_an_overlaped_boundary =
true;
33452 if (!(connecting_to_an_split_boundary ||
33453 connecting_to_an_overlaped_boundary))
33457 poly_to_connect_pt = this->boundary_polyline_pt(dst_bnd_id_initial);
33467 if (!connecting_to_an_split_boundary)
33471 if (!connecting_to_an_overlaped_boundary)
33475 found_vertex_on_dst_boundary_initial =
33476 this->get_connected_vertex_number_on_destination_polyline(
33477 poly_to_connect_pt,
33478 src_vertex_coordinates_initial,
33479 n_vertex_connection_initial);
33492 #ifdef OOMPH_HAS_MPI
33500 this->boundary_subpolylines(dst_bnd_id_initial);
33503 const unsigned nsub_poly = tmp_vector_subpolylines.size();
33505 if (nsub_poly <= 1)
33507 std::ostringstream error_message;
33508 error_message <<
"The boundary (" << dst_bnd_id_initial <<
") was "
33509 <<
"marked to be splitted but\n"
33510 <<
"there are only (" << nsub_poly <<
") polylines to "
33511 <<
"represent it.\n";
33513 error_message.str(),
33514 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33515 OOMPH_EXCEPTION_LOCATION);
33526 if (!connecting_to_an_overlaped_boundary)
33534 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33537 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33539 found_vertex_on_dst_boundary_initial =
33540 this->get_connected_vertex_number_on_destination_polyline(
33541 poly_to_connect_pt,
33542 src_vertex_coordinates_initial,
33543 n_vertex_connection_initial);
33547 if (found_vertex_on_dst_boundary_initial)
33551 sub_poly_to_connect = isub;
33567 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33571 if (!this->boundary_marked_as_shared_boundary(dst_bnd_id_initial,
33575 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33578 found_vertex_on_dst_boundary_initial =
33579 this->get_connected_vertex_number_on_destination_polyline(
33580 poly_to_connect_pt,
33581 src_vertex_coordinates_initial,
33582 n_vertex_connection_initial);
33585 if (found_vertex_on_dst_boundary_initial)
33589 sub_poly_to_connect = isub;
33604 if (!found_vertex_on_dst_boundary_initial)
33607 #ifdef OOMPH_HAS_MPI
33608 if (this->is_mesh_distributed())
33618 resume_initial_connection_polyline_pt.push_back(polyline_pt);
33630 const unsigned bnd_id = polyline_pt->
boundary_id();
33631 std::ostringstream error_message;
33633 <<
"INITIAL VERTEX CONNECTION\n"
33634 <<
"It was not possible to find the associated "
33635 <<
"vertex number on the destination boundary\n"
33636 <<
"The current boundary (" << bnd_id <<
") is marked to have"
33637 <<
"a connection at the\nINITIAL vertex ("
33638 << src_vertex_coordinates_initial[0] <<
","
33639 << src_vertex_coordinates_initial[1] <<
")\n"
33640 <<
"with boundary (" << dst_bnd_id_initial <<
")\n"
33641 <<
"This is the list of vertices on the destination boundary\n";
33645 this->boundary_polyline_pt(dst_bnd_id_initial);
33647 const unsigned n_vertex_dst_boundary = dst_polyline->
nvertex();
33649 for (
unsigned i = 0;
i < n_vertex_dst_boundary;
i++)
33652 error_message <<
"Vertex#(i): (" << current_vertex[0] <<
", "
33653 << current_vertex[1] <<
")\n";
33656 error_message.str(),
33657 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33658 OOMPH_EXCEPTION_LOCATION);
33668 n_vertex_connection_initial;
33685 const unsigned dst_bnd_id_final =
33689 const unsigned tmp_n_vertices = polyline_pt->
nvertex();
33696 #ifdef OOMPH_HAS_MPI
33697 if (this->is_mesh_distributed())
33700 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
33702 if (dst_bnd_id_final >= init_shd_bnd_id)
33705 const unsigned bnd_id = polyline_pt->
boundary_id();
33706 std::ostringstream error_message;
33708 <<
"FINAL VERTEX CONNECTION\n"
33709 <<
"The current original boundary is trying to connect to a\n"
33710 <<
"shared boundary, this is not allowed. In this case the\n"
33711 <<
"shared boundary should be the one that connects with the\n"
33712 <<
"original boundary\n"
33713 <<
"The current boundary (" << bnd_id <<
") is marked to have "
33714 <<
"a connection at the\nFINAL vertex ("
33715 << src_vertex_coordinates_final[0] <<
","
33716 << src_vertex_coordinates_final[1] <<
")\n"
33717 <<
"with boundary (" << dst_bnd_id_final <<
")\n"
33718 <<
"This is the list of vertices on the destination boundary\n";
33722 this->boundary_polyline_pt(dst_bnd_id_final);
33724 const unsigned n_vertex_dst_boundary = dst_polyline->
nvertex();
33726 for (
unsigned i = 0;
i < n_vertex_dst_boundary;
i++)
33729 error_message <<
"Vertex#(" <<
i <<
"): (" << current_vertex[0]
33730 <<
", " << current_vertex[1] <<
")\n";
33733 error_message.str(),
33734 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33735 OOMPH_EXCEPTION_LOCATION);
33745 bool found_vertex_on_dst_boundary_final =
false;
33749 unsigned sub_poly_to_connect = 0;
33752 unsigned n_vertex_connection_final = 0;
33757 bool connecting_to_an_split_boundary =
false;
33761 bool connecting_to_an_overlaped_boundary =
false;
33763 #ifdef OOMPH_HAS_MPI
33764 if (this->is_mesh_distributed())
33769 if (this->boundary_was_splitted(dst_bnd_id_final))
33771 connecting_to_an_split_boundary =
true;
33780 if (connecting_to_an_split_boundary)
33784 const unsigned n_sub_poly =
33785 this->nboundary_subpolylines(dst_bnd_id_final);
33789 for (
unsigned ii = 0; ii < n_sub_poly; ii++)
33791 if (this->boundary_marked_as_shared_boundary(dst_bnd_id_final, ii))
33795 connecting_to_an_overlaped_boundary =
true;
33806 if (this->boundary_marked_as_shared_boundary(dst_bnd_id_final, 0))
33809 connecting_to_an_overlaped_boundary =
true;
33820 if (!(connecting_to_an_split_boundary ||
33821 connecting_to_an_overlaped_boundary))
33825 poly_to_connect_pt = this->boundary_polyline_pt(dst_bnd_id_final);
33835 if (!connecting_to_an_split_boundary)
33839 if (!connecting_to_an_overlaped_boundary)
33843 found_vertex_on_dst_boundary_final =
33844 this->get_connected_vertex_number_on_destination_polyline(
33845 poly_to_connect_pt,
33846 src_vertex_coordinates_final,
33847 n_vertex_connection_final);
33860 #ifdef OOMPH_HAS_MPI
33868 this->boundary_subpolylines(dst_bnd_id_final);
33871 const unsigned nsub_poly = tmp_vector_subpolylines.size();
33873 if (nsub_poly <= 1)
33875 std::ostringstream error_message;
33876 error_message <<
"The boundary (" << dst_bnd_id_final <<
") was "
33877 <<
"marked to be splitted but\n"
33878 <<
"there are only (" << nsub_poly <<
") polylines to "
33879 <<
"represent it.\n";
33881 error_message.str(),
33882 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33883 OOMPH_EXCEPTION_LOCATION);
33894 if (!connecting_to_an_overlaped_boundary)
33902 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33905 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33907 found_vertex_on_dst_boundary_final =
33908 this->get_connected_vertex_number_on_destination_polyline(
33909 poly_to_connect_pt,
33910 src_vertex_coordinates_final,
33911 n_vertex_connection_final);
33915 if (found_vertex_on_dst_boundary_final)
33919 sub_poly_to_connect = isub;
33935 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33939 if (!this->boundary_marked_as_shared_boundary(dst_bnd_id_final,
33943 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33946 found_vertex_on_dst_boundary_final =
33947 this->get_connected_vertex_number_on_destination_polyline(
33948 poly_to_connect_pt,
33949 src_vertex_coordinates_final,
33950 n_vertex_connection_final);
33953 if (found_vertex_on_dst_boundary_final)
33957 sub_poly_to_connect = isub;
33972 if (!found_vertex_on_dst_boundary_final)
33975 #ifdef OOMPH_HAS_MPI
33976 if (this->is_mesh_distributed())
33986 resume_final_connection_polyline_pt.push_back(polyline_pt);
33998 const unsigned bnd_id = polyline_pt->
boundary_id();
33999 std::ostringstream error_message;
34001 <<
"FINAL VERTEX CONNECTION\n"
34002 <<
"It was not possible to find the associated "
34003 <<
"vertex number on the destination boundary\n"
34004 <<
"The current boundary (" << bnd_id <<
") is marked to have "
34005 <<
"a connection at the\nFINAL vertex ("
34006 << src_vertex_coordinates_final[0] <<
","
34007 << src_vertex_coordinates_final[1] <<
")\n"
34008 <<
"with boundary (" << dst_bnd_id_final <<
")\n"
34009 <<
"This is the list of vertices on the destination boundary\n";
34013 this->boundary_polyline_pt(dst_bnd_id_final);
34015 const unsigned n_vertex_dst_boundary = dst_polyline->
nvertex();
34017 for (
unsigned i = 0;
i < n_vertex_dst_boundary;
i++)
34020 error_message <<
"Vertex#(" <<
i <<
"): (" << current_vertex[0]
34021 <<
", " << current_vertex[1] <<
")\n";
34024 error_message.str(),
34025 "RefineableTriangleMesh::restore_polyline_connections_helper()",
34026 OOMPH_EXCEPTION_LOCATION);
34035 n_vertex_connection_final;
34053 template<
class ELEMENT>
34060 const unsigned n_initial_poly =
34061 resume_initial_connection_polyline_pt.size();
34064 for (
unsigned p = 0; p < n_initial_poly; p++)
34068 resume_initial_connection_polyline_pt[p];
34075 const unsigned n_final_poly = resume_final_connection_polyline_pt.size();
34078 for (
unsigned p = 0; p < n_final_poly; p++)
34082 resume_final_connection_polyline_pt[p];
34088 resume_initial_connection_polyline_pt.clear();
34089 resume_final_connection_polyline_pt.clear();
34096 template<
class ELEMENT>
34100 const unsigned& dst_bnd_id,
34101 unsigned& vertex_number)
34103 bool found_associated_vertex_number =
false;
34108 const unsigned n_vertices = dst_polyline->
nvertex();
34112 for (
unsigned i = 0;
i < n_vertices;
i++)
34116 double error = (vertex_coordinates[0] - current_vertex[0]) *
34117 (vertex_coordinates[0] - current_vertex[0]) +
34118 (vertex_coordinates[1] - current_vertex[1]) *
34119 (vertex_coordinates[1] - current_vertex[1]);
34121 error = sqrt(error);
34126 found_associated_vertex_number =
true;
34131 return found_associated_vertex_number;
34143 template<
class ELEMENT>
34153 if (this->is_mesh_distributed() && !check_only)
34155 std::stringstream error_message;
34157 <<
"The updating of polygons of a distributed mesh can ONLY be\n"
34158 <<
"performed using the element's area associated to the halo(ed)\n"
34160 <<
"1) Make sure you have enabled the parallel mesh adaptation\n"
34161 <<
"option if you are working with a distributed mesh, OR\n"
34162 <<
"2) Make sure to call the update_..._using_elements_area() methods\n"
34163 <<
"if the mesh is marked as distributed\n\n";
34165 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
34171 bool unrefinement_was_performed =
false;
34172 bool refinement_was_performed =
false;
34173 bool max_length_applied =
false;
34176 const unsigned n_polyline = polygon_pt->
npolyline();
34182 get_face_mesh_representation(polygon_pt, face_mesh_pt);
34190 for (
unsigned p = 0; p < n_polyline; p++)
34195 std::set<Vector<double>> vertex_nodes;
34204 unsigned n_face_element = face_mesh_pt[p]->nelement();
34205 for (
unsigned e = 0;
e < n_face_element; ++
e)
34209 #ifdef OOMPH_HAS_MPI
34211 if (this->is_mesh_distributed() && el_pt->
is_halo())
34217 unsigned n_node = el_pt->
nnode();
34223 vertex_coord[0] = bound_left[0];
34226 for (
unsigned i = 0;
i < 2;
i++)
34228 vertex_coord[
i + 1] = el_pt->
node_pt(0)->
x(
i);
34230 vertex_nodes.insert(vertex_coord);
34237 vertex_coord[0] = bound_right[0];
34240 for (
unsigned i = 0;
i < 2;
i++)
34242 vertex_coord[
i + 1] = el_pt->
node_pt(n_node - 1)->
x(
i);
34244 vertex_nodes.insert(vertex_coord);
34248 unsigned n_poly_vertex = vertex_nodes.size();
34250 unsigned count = 0;
34251 for (std::set<
Vector<double>>::iterator it = vertex_nodes.begin();
34252 it != vertex_nodes.end();
34255 tmp_vector_vertex_node[count].resize(3);
34256 tmp_vector_vertex_node[count][0] = (*it)[0];
34257 tmp_vector_vertex_node[count][1] = (*it)[1];
34258 tmp_vector_vertex_node[count][2] = (*it)[2];
34263 unsigned n_vertex = tmp_vector_vertex_node.size();
34267 double unrefinement_tolerance =
34273 if (unrefinement_tolerance > 0.0 && n_vertex >= 3)
34275 unrefinement_was_performed = unrefine_boundary(bound,
34277 tmp_vector_vertex_node,
34278 unrefinement_tolerance,
34284 if (check_only && unrefinement_was_performed)
34288 for (
unsigned p = 0; p < n_polyline; p++)
34290 face_mesh_pt[p]->flush_node_storage();
34291 delete face_mesh_pt[p];
34300 n_vertex = tmp_vector_vertex_node.size();
34305 double refinement_tolerance =
34307 if (refinement_tolerance > 0.0 && n_vertex >= 2)
34309 refinement_was_performed = refine_boundary(face_mesh_pt[p],
34310 tmp_vector_vertex_node,
34311 refinement_tolerance,
34317 if (check_only && refinement_was_performed)
34321 for (
unsigned p = 0; p < n_polyline; p++)
34323 face_mesh_pt[p]->flush_node_storage();
34324 delete face_mesh_pt[p];
34334 n_vertex = tmp_vector_vertex_node.size();
34340 if (maximum_length > 0.0 && n_vertex >= 2)
34342 max_length_applied = apply_max_length_constraint(
34343 face_mesh_pt[p], tmp_vector_vertex_node, maximum_length);
34347 if (check_only && max_length_applied)
34351 for (
unsigned p = 0; p < n_polyline; p++)
34353 face_mesh_pt[p]->flush_node_storage();
34354 delete face_mesh_pt[p];
34362 n_vertex = tmp_vector_vertex_node.size();
34365 for (
unsigned i = 0;
i < n_vertex;
i++)
34367 vector_vertex_node[
i].resize(2);
34368 vector_vertex_node[
i][0] = tmp_vector_vertex_node[
i][1];
34369 vector_vertex_node[
i][1] = tmp_vector_vertex_node[
i][2];
34372 #ifdef OOMPH_HAS_MPI
34376 if (!this->is_mesh_distributed())
34379 if ((p > 0) && !check_only)
34383 unsigned n_prev_vertex =
34385 final_vertex_of_previous_segment =
34389 unsigned prev_seg_boundary_id =
34394 double error = 0.0;
34395 for (
unsigned i = 0;
i < 2;
i++)
34397 const double dist = final_vertex_of_previous_segment[
i] -
34398 (*vector_vertex_node.begin())[
i];
34399 error += dist * dist;
34401 error = sqrt(error);
34409 double rev_error = 0.0;
34410 for (
unsigned i = 0;
i < 2;
i++)
34412 const double dist = final_vertex_of_previous_segment[
i] -
34413 (*--vector_vertex_node.end())[
i];
34414 rev_error += dist * dist;
34416 rev_error = sqrt(rev_error);
34430 initial_vertex_of_previous_segment =
34433 unsigned prev_seg_boundary_id =
34438 double error = 0.0;
34439 for (
unsigned i = 0;
i < 2;
i++)
34441 const double dist = initial_vertex_of_previous_segment[
i] -
34442 (*vector_vertex_node.begin())[
i];
34443 error += dist * dist;
34445 error = sqrt(error);
34454 double rev_error = 0.0;
34455 for (
unsigned i = 0;
i < 2;
i++)
34457 const double dist = initial_vertex_of_previous_segment[
i] -
34458 (*--vector_vertex_node.end())[
i];
34459 rev_error += dist * dist;
34468 std::ostringstream error_stream;
34470 <<
"The distance between the first node of the current\n"
34471 <<
"line segment (boundary " << bound
34472 <<
") and either end of "
34473 <<
"the previous line segment\n"
34474 <<
"(boundary " << prev_seg_boundary_id
34475 <<
") is bigger than "
34476 <<
"the desired tolerance "
34479 <<
"This suggests that the polylines defining the "
34481 <<
"representation are not properly ordered.\n"
34482 <<
"Fail on last vertex of polyline: ("
34483 << prev_seg_boundary_id
34484 <<
") and\nfirst vertex of polyline (" << bound
34485 <<
").\nThis should have failed when first trying to "
34486 <<
"construct the\npolygon.\n";
34488 OOMPH_CURRENT_FUNCTION,
34489 OOMPH_EXCEPTION_LOCATION);
34496 std::reverse(vector_vertex_node.begin(),
34497 vector_vertex_node.end());
34511 std::ostringstream error_stream;
34513 <<
"The distance between the first node of the current\n"
34514 <<
"line segment (boundary " << bound
34515 <<
") and either end of "
34516 <<
"the previous line segment\n"
34517 <<
"(boundary " << prev_seg_boundary_id
34518 <<
") is bigger than the "
34519 <<
"desired tolerance "
34522 <<
"This suggests that the polylines defining the polygonal\n"
34523 <<
"representation are not properly ordered.\n"
34524 <<
"Fail on last vertex of polyline: ("
34525 << prev_seg_boundary_id <<
") and\nfirst vertex of polyline ("
34527 <<
"This should have failed when first trying to construct "
34531 OOMPH_CURRENT_FUNCTION,
34532 OOMPH_EXCEPTION_LOCATION);
34538 std::reverse(vector_vertex_node.begin(),
34539 vector_vertex_node.end());
34566 this->copy_connection_information(polygon_pt->
polyline_pt(p),
34567 tmp_curve_section_pt);
34570 std::set<TriangleMeshCurveSection*>::iterator it =
34573 if (it != this->Free_curve_section_pt.end())
34575 this->Free_curve_section_pt.erase(it);
34584 this->Boundary_curve_section_pt[bound] =
34597 for (
unsigned p = 0; p < n_polyline; p++)
34599 face_mesh_pt[p]->flush_node_storage();
34600 delete face_mesh_pt[p];
34614 return (unrefinement_was_performed || refinement_was_performed ||
34615 max_length_applied);
34628 template<
class ELEMENT>
34638 if (this->is_mesh_distributed() && !check_only)
34640 std::stringstream error_message;
34642 <<
"The updating of open curves of a distributed mesh can ONLY be\n"
34643 <<
"performed using the element's area associated to the halo(ed)\n"
34645 <<
"1) Make sure you have enabled the parallel mesh adaptation\n"
34646 <<
"option if you are working with a distributed mesh, OR\n"
34647 <<
"2) Make sure to call the update_..._using_elements_area() methods\n"
34648 <<
"if the mesh is marked as distributed\n\n";
34650 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
34656 bool unrefinement_was_performed =
false;
34657 bool refinement_was_performed =
false;
34658 bool max_length_applied =
false;
34667 get_face_mesh_representation(open_polyline_pt, face_mesh_pt);
34675 for (
unsigned p = 0; p < n_polyline; p++)
34680 std::set<Vector<double>> vertex_nodes;
34683 const unsigned bound =
34687 const unsigned chunk =
34691 unsigned n_face_element = face_mesh_pt[p]->nelement();
34694 for (
unsigned e = 0;
e < n_face_element; ++
e)
34697 unsigned n_node = el_pt->
nnode();
34703 vertex_coord[0] = bound_left[0];
34706 for (
unsigned i = 0;
i < 2;
i++)
34708 vertex_coord[
i + 1] = el_pt->
node_pt(0)->
x(
i);
34710 vertex_nodes.insert(vertex_coord);
34717 vertex_coord[0] = bound_right[0];
34720 for (
unsigned i = 0;
i < 2;
i++)
34722 vertex_coord[
i + 1] = el_pt->
node_pt(n_node - 1)->
x(
i);
34724 vertex_nodes.insert(vertex_coord);
34728 unsigned n_poly_vertex = vertex_nodes.size();
34730 unsigned count = 0;
34731 for (std::set<
Vector<double>>::iterator it = vertex_nodes.begin();
34732 it != vertex_nodes.end();
34735 tmp_vector_vertex_node[count].resize(3);
34736 tmp_vector_vertex_node[count][0] = (*it)[0];
34737 tmp_vector_vertex_node[count][1] = (*it)[1];
34738 tmp_vector_vertex_node[count][2] = (*it)[2];
34743 unsigned n_vertex = tmp_vector_vertex_node.size();
34747 double unrefinement_tolerance =
34753 if (unrefinement_tolerance > 0.0 && n_vertex >= 3)
34755 unrefinement_was_performed = unrefine_boundary(bound,
34757 tmp_vector_vertex_node,
34758 unrefinement_tolerance,
34764 if (check_only && unrefinement_was_performed)
34768 for (
unsigned p = 0; p < n_polyline; p++)
34770 face_mesh_pt[p]->flush_node_storage();
34771 delete face_mesh_pt[p];
34781 n_vertex = tmp_vector_vertex_node.size();
34786 double refinement_tolerance =
34788 if (refinement_tolerance > 0.0 && n_vertex >= 2)
34790 refinement_was_performed = refine_boundary(face_mesh_pt[p],
34791 tmp_vector_vertex_node,
34792 refinement_tolerance,
34798 if (check_only && refinement_was_performed)
34802 for (
unsigned p = 0; p < n_polyline; p++)
34804 face_mesh_pt[p]->flush_node_storage();
34805 delete face_mesh_pt[p];
34815 n_vertex = tmp_vector_vertex_node.size();
34820 double maximum_length =
34822 if (maximum_length > 0.0 && n_vertex >= 2)
34824 bool max_length_applied =
false;
34825 max_length_applied = apply_max_length_constraint(
34826 face_mesh_pt[p], tmp_vector_vertex_node, maximum_length);
34830 if (check_only && max_length_applied)
34834 for (
unsigned p = 0; p < n_polyline; p++)
34836 face_mesh_pt[p]->flush_node_storage();
34837 delete face_mesh_pt[p];
34845 n_vertex = tmp_vector_vertex_node.size();
34848 for (
unsigned i = 0;
i < n_vertex;
i++)
34850 vector_vertex_node[
i].resize(2);
34851 vector_vertex_node[
i][0] = tmp_vector_vertex_node[
i][1];
34852 vector_vertex_node[
i][1] = tmp_vector_vertex_node[
i][2];
34855 #ifdef OOMPH_HAS_MPI
34859 if (!this->is_mesh_distributed())
34868 if ((p > 0) && !check_only)
34873 final_vertex_of_previous_segment);
34875 unsigned prev_seg_boundary_id =
34880 double error = 0.0;
34881 for (
unsigned i = 0;
i < 2;
i++)
34883 const double dist = final_vertex_of_previous_segment[
i] -
34884 (*vector_vertex_node.begin())[
i];
34885 error += dist * dist;
34887 error = sqrt(error);
34896 for (
unsigned i = 0;
i < 2;
i++)
34898 const double dist = final_vertex_of_previous_segment[
i] -
34899 (*--vector_vertex_node.end())[
i];
34900 error += dist * dist;
34902 error = sqrt(error);
34917 initial_vertex_of_previous_segment);
34922 for (
unsigned i = 0;
i < 2;
i++)
34924 const double dist = initial_vertex_of_previous_segment[
i] -
34925 (*vector_vertex_node.begin())[
i];
34926 error += dist * dist;
34928 error = sqrt(error);
34938 for (
unsigned i = 0;
i < 2;
i++)
34940 const double dist = initial_vertex_of_previous_segment[
i] -
34941 (*--vector_vertex_node.end())[
i];
34942 error += dist * dist;
34944 error = sqrt(error);
34949 std::ostringstream error_stream;
34951 <<
"The distance between the first node of the current\n"
34952 <<
"line segment (boundary " << bound
34953 <<
") and either end of the previous line segment\n"
34954 <<
"(boundary " << prev_seg_boundary_id
34955 <<
") is bigger than "
34956 <<
"the desired tolerance "
34959 <<
"This suggests that the polylines defining the open "
34961 <<
"representation are not properly ordered.\n"
34962 <<
"Fail on last vertex of polyline: ("
34963 << prev_seg_boundary_id
34964 <<
") and\nfirst vertex of polyline (" << bound <<
").\n"
34965 <<
"This should have failed when first trying to "
34967 <<
"the open curve.\n";
34969 OOMPH_CURRENT_FUNCTION,
34970 OOMPH_EXCEPTION_LOCATION);
34977 std::reverse(vector_vertex_node.begin(),
34978 vector_vertex_node.end());
34989 std::ostringstream error_stream;
34991 <<
"The distance between the first node of the current\n"
34992 <<
"line segment (boundary " << bound
34993 <<
") and either end of "
34994 <<
"the previous line segment\n"
34995 <<
"(boundary " << prev_seg_boundary_id
34996 <<
") is bigger than the "
34997 <<
"desired tolerance "
35000 <<
"This suggests that the polylines defining the polygonal\n"
35001 <<
"representation are not properly ordered.\n"
35002 <<
"Fail on last vertex of polyline: ("
35003 << prev_seg_boundary_id <<
") and\nfirst vertex of polyline ("
35005 <<
"This should have failed when first trying to construct "
35009 OOMPH_CURRENT_FUNCTION,
35010 OOMPH_EXCEPTION_LOCATION);
35016 std::reverse(vector_vertex_node.begin(),
35017 vector_vertex_node.end());
35045 this->copy_connection_information(open_polyline_pt->
polyline_pt(p),
35046 tmp_curve_section);
35048 std::set<TriangleMeshCurveSection*>::iterator it =
35049 this->Free_curve_section_pt.find(
35052 bool delete_it_on_destructor =
false;
35054 if (it != this->Free_curve_section_pt.end())
35057 this->Free_curve_section_pt.erase(it);
35059 delete_it_on_destructor =
true;
35067 this->Boundary_curve_section_pt[bound] =
35070 if (delete_it_on_destructor)
35072 this->Free_curve_section_pt.insert(
35082 for (
unsigned p = 0; p < n_polyline; p++)
35084 face_mesh_pt[p]->flush_node_storage();
35085 delete face_mesh_pt[p];
35099 return (unrefinement_was_performed || refinement_was_performed ||
35100 max_length_applied);
35112 template<
class ELEMENT>
35117 double& unrefinement_tolerance,
35118 const bool& check_only)
35121 std::set<Vector<double>> no_delete_vertex;
35124 const bool boundary_receive_connections =
35125 this->boundary_connections(b, c, no_delete_vertex);
35129 bool unrefinement_was_performed =
false;
35131 unsigned n_vertex = vector_bnd_vertices.size();
35135 unsigned counter = 1;
35141 for (
unsigned i = 1;
i <= n_vertex - 2;
i += 2)
35144 double a_x = vector_bnd_vertices[
i - 1][1];
35145 double a_y = vector_bnd_vertices[
i - 1][2];
35146 double b_x = vector_bnd_vertices[
i][1];
35147 double b_y = vector_bnd_vertices[
i][2];
35148 double c_x = vector_bnd_vertices[
i + 1][1];
35149 double c_y = vector_bnd_vertices[
i + 1][2];
35151 double a = b_x - a_x;
35152 double b = b_y - a_y;
35153 double c = c_x - a_x;
35154 double d = c_y - a_y;
35156 double e = a * (a_x + b_x) + b * (a_y + b_y);
35157 double f = c * (a_x + c_x) + d * (a_y + c_y);
35159 double g = 2.0 * (a * (c_y - b_y) - b * (c_x - b_x));
35161 bool do_it =
false;
35162 if (std::fabs(g) < 1.0e-14)
35172 double p_x = (d *
e - b * f) / g;
35173 double p_y = (a * f - c *
e) / g;
35175 double r = sqrt(pow((a_x - p_x), 2) + pow((a_y - p_y), 2));
35177 double rhalfca_x = 0.5 * (a_x - c_x);
35178 double rhalfca_y = 0.5 * (a_y - c_y);
35180 double halfca_squared = pow(rhalfca_x, 2) + pow(rhalfca_y, 2);
35182 double sticky_out_bit = r - sqrt(std::fabs((r * r) - halfca_squared));
35187 if ((sticky_out_bit / (2.0 * sqrt(halfca_squared))) <
35188 unrefinement_tolerance)
35200 if (do_it && boundary_receive_connections)
35203 for (std::set<
Vector<double>>::iterator it = no_delete_vertex.begin();
35204 it != no_delete_vertex.end();
35209 const double x = (*it)[0];
35210 const double y = (*it)[1];
35211 double error = (b_x - x) * (b_x - x) + (b_y - y) * (b_y - y);
35212 error = sqrt(error);
35227 vector_bnd_vertices[
i].resize(0);
35246 if ((counter) == (n_vertex - 1))
35249 unsigned i = vector_bnd_vertices.size() - 2;
35255 if (vector_bnd_vertices[counter - 2].size() != 0)
35274 double a_x = vector_bnd_vertices[n][1];
35275 double a_y = vector_bnd_vertices[n][2];
35276 double b_x = vector_bnd_vertices[
i][1];
35277 double b_y = vector_bnd_vertices[
i][2];
35278 double c_x = vector_bnd_vertices[
i + 1][1];
35279 double c_y = vector_bnd_vertices[
i + 1][2];
35281 double a = b_x - a_x;
35282 double b = b_y - a_y;
35283 double c = c_x - a_x;
35284 double d = c_y - a_y;
35286 double e = a * (a_x + b_x) + b * (a_y + b_y);
35287 double f = c * (a_x + c_x) + d * (a_y + c_y);
35289 double g = 2.0 * (a * (c_y - b_y) - b * (c_x - b_x));
35291 bool do_it =
false;
35292 if (std::fabs(g) < 1.0e-14)
35302 double p_x = (d *
e - b * f) / g;
35303 double p_y = (a * f - c *
e) / g;
35305 double r = sqrt(pow((a_x - p_x), 2) + pow((a_y - p_y), 2));
35307 double rhalfca_x = 0.5 * (a_x - c_x);
35308 double rhalfca_y = 0.5 * (a_y - c_y);
35310 double halfca_squared = pow(rhalfca_x, 2) + pow(rhalfca_y, 2);
35312 double sticky_out_bit = r - sqrt(std::fabs((r * r) - halfca_squared));
35317 if ((sticky_out_bit / (2.0 * sqrt(halfca_squared))) <
35318 unrefinement_tolerance)
35330 if (do_it && boundary_receive_connections)
35333 for (std::set<
Vector<double>>::iterator it = no_delete_vertex.begin();
35334 it != no_delete_vertex.end();
35339 const double x = (*it)[0];
35340 const double y = (*it)[1];
35341 double error = (b_x - x) * (b_x - x) + (b_y - y) * (b_y - y);
35342 error = sqrt(error);
35357 vector_bnd_vertices[
i].resize(0);
35364 compact_vector.reserve(n_vertex);
35365 for (
unsigned i = 0;
i < n_vertex;
i++)
35368 if (vector_bnd_vertices[
i].size() != 0)
35370 compact_vector.push_back(vector_bnd_vertices[
i]);
35375 n_vertex = compact_vector.size();
35381 if (n_vertex != vector_bnd_vertices.size())
35383 unrefinement_was_performed =
true;
35387 vector_bnd_vertices.resize(n_vertex);
35388 for (
unsigned i = 0;
i < n_vertex;
i++)
35390 vector_bnd_vertices[
i].resize(3);
35391 vector_bnd_vertices[
i][0] = compact_vector[
i][0];
35392 vector_bnd_vertices[
i][1] = compact_vector[
i][1];
35393 vector_bnd_vertices[
i][2] = compact_vector[
i][2];
35396 return unrefinement_was_performed;
35407 template<
class ELEMENT>
35409 Mesh* face_mesh_pt,
35411 double& refinement_tolerance,
35412 const bool& check_only)
35416 bool refinement_was_performed =
false;
35423 unsigned n_vertex = vector_bnd_vertices.size();
35431 extended_vector.reserve(2 * n_vertex);
35434 for (
unsigned inod = 0; inod < n_vertex - 1; inod++)
35437 double zeta_left = vector_bnd_vertices[inod][0];
35441 for (
unsigned i = 0;
i < 2;
i++)
35443 R_left[
i] = vector_bnd_vertices[inod][
i + 1];
35447 double zeta_right = vector_bnd_vertices[inod + 1][0];
35451 for (
unsigned i = 0;
i < 2;
i++)
35453 R_right[
i] = vector_bnd_vertices[inod + 1][
i + 1];
35458 zeta_mid[0] = 0.5 * (zeta_left + zeta_right);
35463 mesh_geom_obj_pt->
position(zeta_mid, R_mid);
35468 for (
unsigned i = 0;
i < 2;
i++)
35470 R_mid_polygon[
i] = 0.5 * (R_right[
i] + R_left[
i]);
35476 sqrt((R_mid[0] - R_mid_polygon[0]) * (R_mid[0] - R_mid_polygon[0]) +
35477 (R_mid[1] - R_mid_polygon[1]) * (R_mid[1] - R_mid_polygon[1]));
35480 double length = sqrt((R_right[0] - R_left[0]) * (R_right[0] - R_left[0]) +
35481 (R_right[1] - R_left[1]) * (R_right[1] - R_left[1]));
35487 if ((distance / length) > refinement_tolerance)
35493 delete mesh_geom_obj_pt;
35498 new_node[0] = zeta_mid[0];
35499 new_node[1] = R_mid[0];
35500 new_node[2] = R_mid[1];
35503 extended_vector.push_back(vector_bnd_vertices[inod]);
35506 extended_vector.push_back(new_node);
35512 extended_vector.push_back(vector_bnd_vertices[inod]);
35517 extended_vector.push_back(vector_bnd_vertices[n_vertex - 1]);
35520 n_vertex = extended_vector.size();
35525 if (n_vertex != vector_bnd_vertices.size())
35527 refinement_was_performed =
true;
35531 vector_bnd_vertices.resize(n_vertex);
35532 for (
unsigned i = 0;
i < n_vertex;
i++)
35534 vector_bnd_vertices[
i].resize(3);
35535 vector_bnd_vertices[
i][0] = extended_vector[
i][0];
35536 vector_bnd_vertices[
i][1] = extended_vector[
i][1];
35537 vector_bnd_vertices[
i][2] = extended_vector[
i][2];
35542 delete mesh_geom_obj_pt;
35544 return refinement_was_performed;
35553 template<
class ELEMENT>
35555 Mesh* face_mesh_pt,
35557 double& max_length_constraint)
35561 bool max_length_applied =
false;
35568 unsigned n_vertex = vector_bnd_vertices.size();
35575 for (
unsigned inod = 0; inod < n_vertex - 1; inod++)
35578 double zeta_left = vector_bnd_vertices[inod][0];
35582 for (
unsigned i = 0;
i < 2;
i++)
35584 R_left[
i] = vector_bnd_vertices[inod][
i + 1];
35588 double zeta_right = vector_bnd_vertices[inod + 1][0];
35592 for (
unsigned i = 0;
i < 2;
i++)
35594 R_right[
i] = vector_bnd_vertices[inod + 1][
i + 1];
35598 extended_vector.push_back(vector_bnd_vertices[inod]);
35602 double length = std::fabs(zeta_right - zeta_left);
35605 if (length > max_length_constraint)
35607 double n_pts = length / max_length_constraint;
35609 unsigned n_points =
static_cast<unsigned>(n_pts);
35610 double zeta_increment =
35611 (zeta_right - zeta_left) / ((
double)n_points + 1);
35615 for (
unsigned s = 1;
s < n_points + 1;
s++)
35618 zeta[0] = zeta_left + zeta_increment * double(
s);
35620 mesh_geom_obj_pt->
position(zeta, vertex);
35624 new_node[0] = zeta[0];
35625 new_node[1] = vertex[0];
35626 new_node[2] = vertex[1];
35629 extended_vector.push_back(new_node);
35635 extended_vector.push_back(vector_bnd_vertices[n_vertex - 1]);
35638 n_vertex = extended_vector.size();
35643 if (n_vertex != vector_bnd_vertices.size())
35645 max_length_applied =
true;
35649 vector_bnd_vertices.resize(n_vertex);
35650 for (
unsigned i = 0;
i < n_vertex;
i++)
35652 vector_bnd_vertices[
i].resize(3);
35653 vector_bnd_vertices[
i][0] = extended_vector[
i][0];
35654 vector_bnd_vertices[
i][1] = extended_vector[
i][1];
35655 vector_bnd_vertices[
i][2] = extended_vector[
i][2];
35660 delete mesh_geom_obj_pt;
35662 return max_length_applied;
35671 template<
class ELEMENT>
35674 Mesh* face_mesh_pt)
35681 this->
template build_face_mesh<ELEMENT, FaceElementAsGeomObject>(
35682 boundary_id, face_mesh_pt);
35685 unsigned n_element = face_mesh_pt->
nelement();
35687 for (
unsigned e = 0;
e < n_element;
e++)
35704 template<
class ELEMENT>
35706 const unsigned& boundary_id,
35707 Mesh* face_mesh_pt,
35708 std::map<FiniteElement*, bool>& is_inverted,
35709 bool& inverted_face_mesh)
35711 Mesh* tmp_unsorted_face_mesh_pt =
new Mesh();
35714 create_unsorted_face_mesh_representation(boundary_id,
35715 tmp_unsorted_face_mesh_pt);
35725 std::list<FiniteElement*> sorted_el_pt;
35727 sorted_el_pt.push_back(el_pt);
35730 unsigned nnod = el_pt->
nnode();
35733 unsigned count_done = 0;
35736 unsigned n_face_element = tmp_unsorted_face_mesh_pt->
nelement();
35739 std::map<FiniteElement*, bool> done_el;
35741 is_inverted.clear();
35744 for (
unsigned ee = 1; ee < n_face_element; ee++)
35748 for (
unsigned e = 1;
e < n_face_element;
e++)
35754 if (!done_el[el_pt])
35758 std::list<FiniteElement*>::iterator it = sorted_el_pt.end();
35764 if (is_inverted[first_el_pt])
35766 left_node_pt = first_el_pt->
node_pt(nnod - 1);
35768 Node* right_node_pt = last_el_pt->
node_pt(nnod - 1);
35769 if (is_inverted[last_el_pt])
35771 right_node_pt = last_el_pt->
node_pt(0);
35775 if (left_node_pt == el_pt->node_pt(nnod - 1))
35777 sorted_el_pt.push_front(el_pt);
35778 done_el[el_pt] =
true;
35780 is_inverted[el_pt] =
false;
35784 else if (left_node_pt == el_pt->node_pt(0))
35786 sorted_el_pt.push_front(el_pt);
35787 done_el[el_pt] =
true;
35789 is_inverted[el_pt] =
true;
35793 else if (right_node_pt == el_pt->node_pt(0))
35795 sorted_el_pt.push_back(el_pt);
35796 done_el[el_pt] =
true;
35798 is_inverted[el_pt] =
false;
35802 else if (right_node_pt == el_pt->node_pt(nnod - 1))
35804 sorted_el_pt.push_back(el_pt);
35805 done_el[el_pt] =
true;
35807 is_inverted[el_pt] =
true;
35810 if (done_el[el_pt])
35819 if (count_done != (n_face_element - 1))
35821 std::ostringstream error_message;
35822 error_message <<
"When ordering FaceElements on "
35823 <<
"boundary " << boundary_id <<
" only managed to order \n"
35824 << count_done <<
" of " << n_face_element
35825 <<
" face elements.\n"
35828 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
35835 for (std::list<FiniteElement*>::iterator it = sorted_el_pt.begin();
35836 it != sorted_el_pt.end();
35854 this->Boundary_curve_section_pt[boundary_id];
35864 unsigned n_node = first_el_pt->
nnode();
35868 if (is_inverted[first_el_pt])
35870 first_node_pt = first_el_pt->
node_pt(n_node - 1);
35873 double error = (first_node_pt->
x(0) - first_vertex[0]) *
35874 (first_node_pt->
x(0) - first_vertex[0]) +
35875 (first_node_pt->
x(1) - first_vertex[1]) *
35876 (first_node_pt->
x(1) - first_vertex[1]);
35878 error = sqrt(error);
35882 inverted_face_mesh =
false;
35886 inverted_face_mesh =
true;
35895 template<
class ELEMENT>
35900 unsigned n_polyline = polygon_pt->
npolyline();
35901 face_mesh_pt.resize(n_polyline);
35907 bool eligible_for_segment_redistribution =
true;
35910 for (
unsigned p = 0; p < n_polyline; p++)
35917 GeomObject*
const geom_object_pt = this->boundary_geom_object_pt(bound);
35918 if (geom_object_pt != 0)
35920 eligible_for_segment_redistribution =
false;
35923 face_mesh_pt[p] =
new Mesh();
35924 create_unsorted_face_mesh_representation(bound, face_mesh_pt[p]);
35933 if (this->nregion() > 1)
35935 std::ostringstream warn_message;
35937 <<
"Can't currently re-distribute segments between polylines if there\n"
35938 <<
"are multiple regions; returning..." << std::endl;
35940 "RefineableTriangleMesh::get_face_mesh_representation()",
35941 OOMPH_EXCEPTION_LOCATION);
35946 if (!eligible_for_segment_redistribution)
35948 std::ostringstream warn_message;
35950 <<
"Over-ruling re-distribution of segments between polylines\n"
35951 <<
"because at least one boundary is associated with a GeomObject."
35952 <<
"Returning..." << std::endl;
35954 "RefineableTriangleMesh::get_face_mesh_representation()",
35955 OOMPH_EXCEPTION_LOCATION);
35963 double s_total = 0.0;
35969 std::vector<bool> is_reversed(n_polyline,
false);
35972 for (
unsigned p = 0; p < n_polyline; p++)
35978 std::list<FiniteElement*> ordered_el_pt;
35979 FiniteElement* el_pt = face_mesh_pt[p]->finite_element_pt(0);
35980 ordered_el_pt.push_back(el_pt);
35983 unsigned nnod = el_pt->
nnode();
35986 first_polyline_node_pt[p] = el_pt->
node_pt(0);
35987 last_polyline_node_pt[p] = el_pt->
node_pt(nnod - 1);
35990 unsigned count_done = 0;
35993 unsigned n_face_element = face_mesh_pt[p]->nelement();
35999 std::map<FiniteElement*, bool> done_el;
36002 std::map<FiniteElement*, bool> is_inverted;
36005 for (
unsigned ee = 1; ee < n_face_element; ee++)
36009 for (
unsigned e = 1;
e < n_face_element;
e++)
36012 el_pt = face_mesh_pt[p]->finite_element_pt(
e);
36015 if (!done_el[el_pt])
36019 std::list<FiniteElement*>::iterator it = ordered_el_pt.end();
36025 if (is_inverted[first_el_pt])
36027 left_node_pt = first_el_pt->
node_pt(nnod - 1);
36029 Node* right_node_pt = last_el_pt->
node_pt(nnod - 1);
36030 if (is_inverted[last_el_pt])
36032 right_node_pt = last_el_pt->
node_pt(0);
36036 if (left_node_pt == el_pt->node_pt(nnod - 1))
36038 ordered_el_pt.push_front(el_pt);
36039 done_el[el_pt] =
true;
36041 is_inverted[el_pt] =
false;
36042 first_polyline_node_pt[p] = el_pt->node_pt(0);
36046 else if (left_node_pt == el_pt->node_pt(0))
36048 ordered_el_pt.push_front(el_pt);
36049 done_el[el_pt] =
true;
36051 is_inverted[el_pt] =
true;
36052 first_polyline_node_pt[p] = el_pt->node_pt(nnod - 1);
36056 else if (right_node_pt == el_pt->node_pt(0))
36058 ordered_el_pt.push_back(el_pt);
36059 done_el[el_pt] =
true;
36061 is_inverted[el_pt] =
false;
36062 last_polyline_node_pt[p] = el_pt->node_pt(nnod - 1);
36066 else if (right_node_pt == el_pt->node_pt(nnod - 1))
36068 ordered_el_pt.push_back(el_pt);
36069 done_el[el_pt] =
true;
36071 is_inverted[el_pt] =
true;
36072 last_polyline_node_pt[p] = el_pt->node_pt(0);
36075 if (done_el[el_pt])
36084 if (count_done != (n_face_element - 1))
36086 std::ostringstream error_message;
36087 error_message <<
"When ordering FaceElements on "
36088 <<
"boundary " << bound <<
" only managed to order \n"
36089 << count_done <<
" of " << n_face_element
36090 <<
" face elements.\n"
36093 OOMPH_CURRENT_FUNCTION,
36094 OOMPH_EXCEPTION_LOCATION);
36098 ordered_face_mesh_pt[p] =
new Mesh;
36101 for (std::list<FiniteElement*>::iterator it = ordered_el_pt.begin();
36102 it != ordered_el_pt.end();
36109 ordered_face_mesh_pt[p]->add_element_pt(el_pt);
36113 for (
unsigned e = 0;
e < n_face_element; ++
e)
36115 FiniteElement* el_pt = ordered_face_mesh_pt[p]->finite_element_pt(
e);
36116 unsigned n_node = el_pt->
nnode();
36117 double element_length_squared = 0.0;
36118 for (
unsigned i = 0;
i < 2;
i++)
36120 element_length_squared +=
36125 double element_length = sqrt(element_length_squared);
36128 s_total += element_length;
36132 face_mesh_pt[p]->flush_element_and_node_storage();
36136 if ((last_polyline_node_pt[0] == first_polyline_node_pt[1]) ||
36137 (last_polyline_node_pt[0] == last_polyline_node_pt[1]))
36139 is_reversed[0] =
false;
36141 else if ((first_polyline_node_pt[0] == first_polyline_node_pt[1]) ||
36142 (first_polyline_node_pt[0] == last_polyline_node_pt[1]))
36144 is_reversed[0] =
true;
36149 std::vector<bool> mesh_done(n_polyline,
false);
36153 tmp_face_mesh_pt[0] = ordered_face_mesh_pt[0];
36154 unsigned current = 0;
36155 old_polyline_number[0] = 0;
36156 unsigned count_found = 0;
36159 for (
unsigned p = 1; p < n_polyline; p++)
36161 Node* end_node_pt = last_polyline_node_pt[current];
36162 if (is_reversed[current])
36164 end_node_pt = first_polyline_node_pt[current];
36168 for (
unsigned pp = 1; pp < n_polyline; pp++)
36170 if (!mesh_done[pp])
36173 if ((!is_reversed[current]) &&
36174 (end_node_pt == first_polyline_node_pt[pp]))
36176 tmp_face_mesh_pt[p] = ordered_face_mesh_pt[pp];
36177 mesh_done[pp] =
true;
36178 is_reversed[pp] =
false;
36179 old_polyline_number[p] = pp;
36186 else if ((!is_reversed[current]) &&
36187 (end_node_pt == last_polyline_node_pt[pp]))
36189 tmp_face_mesh_pt[p] = ordered_face_mesh_pt[pp];
36190 mesh_done[pp] =
true;
36191 is_reversed[pp] =
true;
36192 old_polyline_number[p] = pp;
36199 else if ((is_reversed[current]) &&
36200 (end_node_pt == first_polyline_node_pt[pp]))
36202 tmp_face_mesh_pt[p] = ordered_face_mesh_pt[pp];
36203 mesh_done[pp] =
true;
36204 is_reversed[pp] =
false;
36205 old_polyline_number[p] = pp;
36212 else if ((is_reversed[current]) &&
36213 (end_node_pt == last_polyline_node_pt[pp]))
36215 tmp_face_mesh_pt[p] = ordered_face_mesh_pt[pp];
36216 mesh_done[pp] =
true;
36217 is_reversed[pp] =
true;
36218 old_polyline_number[p] = pp;
36228 if (count_found != n_polyline - 1)
36230 std::ostringstream error_message;
36231 error_message <<
"Only found " << count_found <<
" out of "
36232 << n_polyline - 1 <<
" polylines to be fitted in.\n";
36234 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
36239 for (
unsigned i = 0;
i < n_polyline;
i++)
36241 ordered_face_mesh_pt[
i] = tmp_face_mesh_pt[
i];
36247 unsigned new_face_id = 0;
36251 std::map<Node*, std::map<unsigned, unsigned>>
36252 node_must_not_be_removed_from_boundary_flag;
36255 for (
unsigned p = 0; p < n_polyline; p++)
36258 unsigned n_face_element = ordered_face_mesh_pt[p]->nelement();
36259 for (
unsigned e = 0;
e < n_face_element;
e++)
36261 unsigned el_number =
e;
36262 if (is_reversed[p])
36264 el_number = n_face_element -
e - 1;
36268 ordered_face_mesh_pt[p]->finite_element_pt(el_number);
36269 unsigned n_node = el_pt->
nnode();
36272 double element_length_squared = 0.0;
36273 for (
unsigned i = 0;
i < 2;
i++)
36275 element_length_squared +=
36278 double element_length = sqrt(element_length_squared);
36281 s += element_length;
36285 if (
s < s_total /
double(n_polyline) + 1
e-6)
36288 face_mesh_pt[new_face_id]->add_element_pt(el_pt);
36290 unsigned bound_old =
36293 unsigned bound_new =
36297 for (
unsigned i = 0;
i < n_node;
i++)
36304 if (bound_new != bound_old)
36307 add_boundary_node(bound_new, nod_pt);
36311 node_must_not_be_removed_from_boundary_flag[nod_pt][bound_old] +=
36321 node_must_not_be_removed_from_boundary_flag[nod_pt][bound_old] +=
36334 if (new_face_id != n_polyline - 1)
36352 unsigned move_count = 0;
36353 for (std::map<
Node*, std::map<unsigned, unsigned>>::iterator it =
36354 node_must_not_be_removed_from_boundary_flag.begin();
36355 it != node_must_not_be_removed_from_boundary_flag.end();
36359 Node* nod_pt = (*it).first;
36362 for (std::map<unsigned, unsigned>::iterator it_2 = (*it).second.begin();
36363 it_2 != (*it).second.end();
36367 unsigned bound = (*it_2).first;
36370 if ((*it_2).second == 0)
36372 remove_boundary_node(bound, nod_pt);
36379 for (
unsigned p = 0; p < n_polyline; p++)
36385 unsigned n_face_element = face_mesh_pt[p]->nelement();
36386 for (
unsigned e = 0;
e < n_face_element;
e++)
36391 face_mesh_pt[p]->element_pt(
e));
36399 setup_boundary_element_info();
36402 for (
unsigned p = 0; p < n_polyline; p++)
36408 this->
template setup_boundary_coordinates<ELEMENT>(bound);
36412 for (
unsigned p = 0; p < n_polyline; p++)
36417 ordered_face_mesh_pt[p]->flush_element_and_node_storage();
36418 delete ordered_face_mesh_pt[p];
36425 template<
class ELEMENT>
36431 face_mesh_pt.resize(n_polyline);
36434 for (
unsigned p = 0; p < n_polyline; p++)
36439 face_mesh_pt[p] =
new Mesh();
36440 create_unsorted_face_mesh_representation(bound, face_mesh_pt[p]);
36451 template<
class ELEMENT>
36454 internal_point_coord,
36455 const bool& check_only)
36459 bool update_was_performed =
false;
36461 unsigned n_hole = internal_point_coord.size();
36462 for (
unsigned ihole = 0; ihole < n_hole; ihole++)
36475 internal_point_coord[ihole].resize(2);
36489 bool update_necessary =
36490 this->update_polygon_using_face_mesh(poly_pt, check_only);
36493 if (update_necessary)
36503 update_was_performed = this->update_polygon_using_face_mesh(poly_pt);
36521 if (this->Internal_hole_point_update_fct_pt != 0)
36523 this->Internal_hole_point_update_fct_pt(ihole, poly_pt);
36530 unsigned n_polyline = poly_pt->
npolyline();
36533 vertex_coord.resize(2);
36534 internal_point_coord[ihole].resize(2);
36538 internal_point_coord[ihole][0] = 0.0;
36539 internal_point_coord[ihole][1] = 0.0;
36541 for (
unsigned p = 0; p < n_polyline; p++)
36546 for (
unsigned v = 0; v < n_vertex; v++)
36549 for (
unsigned i = 0;
i < 2;
i++)
36551 poly_ave[
i] += vertex_coord[
i];
36556 for (
unsigned i = 0;
i < 2;
i++)
36558 internal_point_coord[ihole][
i] += poly_ave[
i] / n_vertex;
36563 for (
unsigned i = 0;
i < 2;
i++)
36565 internal_point_coord[ihole][
i] /= n_polyline;
36632 return update_was_performed;
36641 template<
class ELEMENT>
36649 std::ifstream node_file(node_file_name.c_str(), std::ios_base::in);
36652 if (!node_file.is_open())
36654 std::string error_msg(
"Failed to open node file: ");
36655 error_msg +=
"\"" + node_file_name +
"\".";
36657 error_msg, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
36662 node_file >> nnodes;
36665 unsigned dimension;
36666 node_file >> dimension;
36669 if (dimension != 2)
36672 OOMPH_CURRENT_FUNCTION,
36673 OOMPH_EXCEPTION_LOCATION);
36682 unsigned npoint_attributes;
36683 node_file >> npoint_attributes;
36687 unsigned boundary_markers_flag = 0;
36688 node_file >> boundary_markers_flag;
36691 unsigned dummy_node_number;
36693 unsigned dummy_node_attribute;
36695 unsigned dummy_node_boundary;
36699 for (
unsigned i = 0;
i < nnodes;
i++)
36701 node_file >> dummy_node_number;
36702 node_file >> x_node[
i];
36703 node_file >> y_node[
i];
36704 for (
unsigned j = 0; j < npoint_attributes; ++j)
36706 node_file >> dummy_node_attribute;
36708 if (boundary_markers_flag)
36710 node_file >> dummy_node_boundary;
36719 std::map<unsigned, Vector<std::pair<unsigned, unsigned>>>
36720 unsorted_boundary_segments;
36731 std::ifstream poly_file(poly_file_name.c_str(), std::ios_base::in);
36734 if (!poly_file.is_open())
36736 std::string error_msg(
"Failed to open poly file: ");
36737 error_msg +=
"\"" + poly_file_name +
"\".";
36739 error_msg, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
36743 unsigned n_node_poly;
36744 poly_file >> n_node_poly;
36747 poly_file >> dimension;
36750 unsigned attribute_flag;
36751 poly_file >> attribute_flag;
36754 poly_file >> boundary_markers_flag;
36759 for (
unsigned i = 0;
i < n_node_poly;
i++)
36762 poly_file >> dummy;
36763 poly_file >> dummy;
36764 poly_file >> dummy;
36766 for (
unsigned j = 0; j < attribute_flag; ++j)
36768 poly_file >> dummy;
36771 if (boundary_markers_flag == 1)
36773 poly_file >> dummy;
36778 unsigned read_value;
36781 poly_file >> read_value;
36782 const unsigned nglobal_segments = read_value;
36785 poly_file >> boundary_markers_flag;
36788 unsigned global_segment_number;
36791 std::set<unsigned> nodes_ids;
36794 for (
unsigned i = 0;
i < nglobal_segments;
i++)
36797 unsigned lnode_id = 0;
36798 unsigned rnode_id = 0;
36799 unsigned bnd_id = 0;
36800 poly_file >> global_segment_number;
36801 poly_file >> lnode_id;
36802 poly_file >> rnode_id;
36803 nodes_ids.insert(lnode_id);
36804 nodes_ids.insert(rnode_id);
36805 if (boundary_markers_flag)
36807 poly_file >> bnd_id;
36813 unsorted_boundary_segments[bnd_id - 1].push_back(
36814 std::make_pair(lnode_id, rnode_id));
36821 const unsigned nsorted_boundaries_ids = sorted_boundaries_ids.size();
36823 bool boundary_id_found =
false;
36824 for (
unsigned ib = 0; ib < nsorted_boundaries_ids; ib++)
36826 if (sorted_boundaries_ids[ib] == bnd_id - 1)
36828 boundary_id_found =
true;
36834 if (!boundary_id_found)
36836 sorted_boundaries_ids.push_back(bnd_id - 1);
36845 if (nglobal_segments != nodes_ids.size())
36847 std::ostringstream error_message;
36849 <<
"The number of nodes (" << nodes_ids.size() <<
") and segments ("
36850 << nglobal_segments <<
") is different.\nThis may mean that there "
36851 <<
"are internal non-closed boundaries defined in\nthe polyfile. "
36852 <<
"If you need this feature please use the TriangleMeshPoyLine\n"
36853 <<
"and TriangleMeshCurviLine objects to define your domain.\n\n";
36855 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
36862 const unsigned nboundary = unsorted_boundary_segments.size();
36865 if (nboundary != this->nboundary())
36867 std::ostringstream error_message;
36869 <<
"The number of boundaries on the mesh (" << this->nboundary()
36870 <<
") is different from the number of\nboundaries read from the "
36871 <<
"polyfiles (" << unsorted_boundary_segments.size() <<
")!!!\n\n\n";
36873 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
36879 const unsigned nsorted_boundaries_ids = sorted_boundaries_ids.size();
36881 if (nsorted_boundaries_ids != this->nboundary())
36883 std::ostringstream error_message;
36885 <<
"The number of boundaries on the mesh (" << this->nboundary()
36886 <<
") is different from the number of\nsorted boundaries ids read "
36887 <<
"from the polyfiles (" << nsorted_boundaries_ids <<
")!!!\n\n\n";
36889 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
36894 std::map<unsigned, std::list<unsigned>> sorted_boundary_segments;
36897 std::map<unsigned, Vector<std::pair<unsigned, unsigned>>>::iterator it;
36899 for (it = unsorted_boundary_segments.begin();
36900 it != unsorted_boundary_segments.end();
36905 const unsigned bnd_id = (*it).first;
36909 std::map<std::pair<unsigned, unsigned>,
bool> segment_done;
36910 const unsigned nsegments = segments_edges.size();
36913 std::list<unsigned> sorted_segments;
36916 unsigned left_node_id = segments_edges[0].first;
36917 unsigned right_node_id = segments_edges[0].second;
36920 sorted_segments.push_back(left_node_id);
36921 sorted_segments.push_back(right_node_id);
36924 segment_done[segments_edges[0]] =
true;
36927 unsigned nsorted_segments = 1;
36929 while (nsorted_segments < nsegments)
36931 for (
unsigned i = 1;
i < nsegments;
i++)
36934 if (!segment_done[segments_edges[
i]])
36937 unsigned current_left_node_id = segments_edges[
i].first;
36938 unsigned current_right_node_id = segments_edges[
i].second;
36942 if (current_left_node_id == right_node_id)
36946 sorted_segments.push_back(current_right_node_id);
36948 nsorted_segments++;
36950 segment_done[segments_edges[
i]] =
true;
36952 right_node_id = current_right_node_id;
36956 else if (current_right_node_id == left_node_id)
36960 sorted_segments.push_front(current_left_node_id);
36962 nsorted_segments++;
36964 segment_done[segments_edges[
i]] =
true;
36966 left_node_id = current_left_node_id;
36970 else if (current_left_node_id == left_node_id)
36974 sorted_segments.push_front(current_right_node_id);
36976 nsorted_segments++;
36978 segment_done[segments_edges[
i]] =
true;
36980 left_node_id = current_right_node_id;
36984 else if (current_right_node_id == right_node_id)
36988 sorted_segments.push_back(current_left_node_id);
36990 nsorted_segments++;
36992 segment_done[segments_edges[
i]] =
true;
36994 right_node_id = current_left_node_id;
37002 sorted_boundary_segments[bnd_id] = sorted_segments;
37008 if (sorted_boundary_segments.size() != this->nboundary())
37010 std::ostringstream error_message;
37012 <<
"The number of boundaries on the mesh (" << this->nboundary()
37013 <<
") is different from the number\nof sorted boundaries to create the "
37014 <<
"polylines (" << sorted_boundary_segments.size() <<
")\n\n";
37016 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
37023 unsigned current_polyline = 0;
37026 for (
unsigned ib = 0; ib < nsorted_boundaries_ids; ib++)
37029 const unsigned bnd_id = sorted_boundaries_ids[ib];
37034 for (std::list<unsigned>::iterator it_list =
37035 sorted_boundary_segments[bnd_id].begin();
37036 it_list != sorted_boundary_segments[bnd_id].end();
37039 nodes_ids.push_back((*it_list));
37043 const unsigned nvertices = nodes_ids.size();
37049 for (
unsigned i = 0;
i < nvertices;
i++)
37052 vertices[
i].resize(2);
37053 vertices[
i][0] = x_node[nodes_ids[
i] - 1];
37054 vertices[
i][1] = y_node[nodes_ids[
i] - 1];
37062 polylines_pt[current_polyline] =
37066 this->Boundary_curve_section_pt[bnd_id] =
37070 current_polyline++;
37077 unsigned nsorted_polylines = 0;
37080 unsigned npolygons = 0;
37086 std::map<unsigned, bool> polyline_done;
37087 while (nsorted_polylines < nboundary)
37090 std::list<TriangleMeshCurveSection*> sorted_curve_sections_pt;
37092 unsigned init_poly = 0;
37094 bool found_root_polyline =
false;
37097 for (
unsigned i = 0;
i < nboundary;
i++)
37099 if (!polyline_done[
i])
37103 nsorted_polylines++;
37106 found_root_polyline =
true;
37109 polyline_done[
i] =
true;
37111 sorted_curve_sections_pt.push_back(polylines_pt[
i]);
37118 if (!found_root_polyline)
37120 std::ostringstream error_message;
37121 error_message <<
"Was not possible to found the root polyline to "
37122 "create polygons\n\n";
37124 OOMPH_CURRENT_FUNCTION,
37125 OOMPH_EXCEPTION_LOCATION);
37130 const unsigned bnd_id = polylines_pt[init_poly]->boundary_id();
37132 unsigned left_node_id = sorted_boundary_segments[bnd_id].front();
37133 unsigned right_node_id = sorted_boundary_segments[bnd_id].back();
37136 bool closed_polygon =
false;
37141 for (
unsigned i = init_poly;
i < nboundary;
i++)
37144 if (!polyline_done[
i])
37149 const unsigned cbnd_id = polylines_pt[
i]->boundary_id();
37151 unsigned cleft_node_id = sorted_boundary_segments[cbnd_id].front();
37152 unsigned cright_node_id = sorted_boundary_segments[cbnd_id].back();
37156 if (cleft_node_id == right_node_id)
37159 sorted_curve_sections_pt.push_back(polylines_pt[
i]);
37161 polyline_done[
i] =
true;
37163 right_node_id = cright_node_id;
37165 nsorted_polylines++;
37169 else if (cright_node_id == left_node_id)
37172 sorted_curve_sections_pt.push_front(polylines_pt[
i]);
37174 polyline_done[
i] =
true;
37176 left_node_id = cleft_node_id;
37178 nsorted_polylines++;
37182 else if (cleft_node_id == left_node_id)
37185 polylines_pt[
i]->reverse();
37187 sorted_curve_sections_pt.push_front(polylines_pt[
i]);
37189 polyline_done[
i] =
true;
37191 left_node_id = cright_node_id;
37193 nsorted_polylines++;
37197 else if (cright_node_id == right_node_id)
37200 polylines_pt[
i]->reverse();
37202 sorted_curve_sections_pt.push_back(polylines_pt[
i]);
37204 polyline_done[
i] =
true;
37206 right_node_id = cleft_node_id;
37208 nsorted_polylines++;
37217 if (left_node_id == right_node_id)
37220 closed_polygon =
true;
37223 }
while (nsorted_polylines < nboundary && !closed_polygon);
37226 if (!closed_polygon)
37228 std::ostringstream error_message;
37230 <<
"It was not possible to create a closed curve, these are the "
37231 <<
"vertices of the already sorted polylines\n\n";
37232 unsigned cpolyline = 0;
37233 for (std::list<TriangleMeshCurveSection*>::iterator it_list =
37234 sorted_curve_sections_pt.begin();
37235 it_list != sorted_curve_sections_pt.end();
37238 error_message <<
"Polyline (" << cpolyline <<
")\n";
37241 const unsigned nvertex = tmp_poly_pt->
nvertex();
37242 for (
unsigned v = 0; v < nvertex; v++)
37247 error_message <<
"\n";
37251 OOMPH_CURRENT_FUNCTION,
37252 OOMPH_EXCEPTION_LOCATION);
37259 for (std::list<TriangleMeshCurveSection*>::iterator it_list =
37260 sorted_curve_sections_pt.begin();
37261 it_list != sorted_curve_sections_pt.end();
37264 tmp_sorted_curve_sections_pt.push_back((*it_list));
37272 this->Free_polygon_pt.insert(polygon_pt);
37275 polygons_pt.push_back(polygon_pt);
37288 unsigned index_outer = 0;
37290 for (
unsigned idx_outer = 0; idx_outer < npolygons; idx_outer++)
37297 bool all_inner_inside =
true;
37300 const unsigned nouter_polylines = polygons_pt[idx_outer]->npolyline();
37301 for (
unsigned p = 0; p < nouter_polylines; p++)
37304 polygons_pt[idx_outer]->polyline_pt(p);
37305 const unsigned nvertex = tmp_poly_pt->
nvertex();
37306 for (
unsigned v = 0; v < nvertex; v++)
37309 outer_vertex_coordinates.push_back(current_vertex);
37318 const unsigned ninner_polygons = polygons_pt.size() - 1;
37323 for (
unsigned i = 0;
i <= ninner_polygons;
i++)
37325 if (
i != idx_outer)
37328 const unsigned ninner_polylines = polygons_pt[
i]->npolyline();
37329 for (
unsigned p = 0; p < ninner_polylines; p++)
37332 const unsigned nvertex = tmp_poly_pt->
nvertex();
37333 for (
unsigned v = 0; v < nvertex; v++)
37338 inner_vertex_coordinates[
i].push_back(current_vertex);
37340 else if (
i > idx_outer)
37342 inner_vertex_coordinates[
i - 1].push_back(current_vertex);
37354 for (
unsigned i = 0;
i < ninner_polygons;
i++)
37358 const unsigned nvertex_internal = inner_vertex_coordinates[
i].size();
37359 for (
unsigned v = 0; v < nvertex_internal; v++)
37363 all_inner_inside &= this->is_point_inside_polygon_helper(
37364 outer_vertex_coordinates, current_point);
37368 if (!all_inner_inside)
37378 if (!all_inner_inside)
37388 if (all_inner_inside)
37390 index_outer = idx_outer;
37400 if (index_outer != 0)
37402 std::ostringstream warning_message;
37404 <<
"The first set of nodes listed in the input polyfiles does not\n"
37405 <<
"correspond to the outer closed boundary. This may lead to\n"
37406 <<
"problems at the adaptation stage if the holes coordinates\n"
37407 <<
"are no correctly associated to the inner closed boundaries.\n"
37408 <<
"You can check the generated mesh by calling the output() method\n"
37409 <<
"from the mesh object '(problem.mesh_pt()->output(string))'\n\n";
37411 OOMPH_CURRENT_FUNCTION,
37412 OOMPH_EXCEPTION_LOCATION);
37421 this->Outer_boundary_pt.resize(1);
37422 this->Outer_boundary_pt[0] = polygons_pt[index_outer];
37424 this->Internal_polygon_pt.resize(npolygons - 1);
37425 for (
unsigned i = 0;
i < npolygons;
i++)
37427 if (
i != index_outer)
37429 if (
i < index_outer)
37432 this->Internal_polygon_pt[
i] = polygons_pt[
i];
37434 else if (
i > index_outer)
37437 this->Internal_polygon_pt[
i - 1] = polygons_pt[
i];
37450 for (
unsigned i = 0;
i < npolygons - 1;
i++)
37453 const unsigned ninner_polylines =
37454 this->Internal_polygon_pt[
i]->npolyline();
37455 for (
unsigned p = 0; p < ninner_polylines; p++)
37458 this->Internal_polygon_pt[
i]->polyline_pt(p);
37461 const unsigned nvertex = tmp_poly_pt->
nvertex();
37462 for (
unsigned v = 0; v < nvertex; v++)
37465 inner_vertex_coordinates[
i].push_back(current_vertex);
37474 poly_file >> nholes;
37477 if (npolygons > 1 && (npolygons - 1) != nholes)
37479 std::ostringstream error_message;
37481 <<
"The number of holes (" << nholes <<
") does not correspond "
37482 <<
"with the number\nof internal polygons (" << npolygons - 1 <<
")\n\n"
37483 <<
"Using polyfiles as input does not currently allows the\n"
37484 <<
"definition of more than one outer polygon\n\n";
37486 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
37494 unsigned dummy_hole;
37496 for (
unsigned ihole = 0; ihole < nholes; ihole++)
37498 hole_coordinates[ihole].resize(2);
37500 poly_file >> dummy_hole;
37501 poly_file >> hole_coordinates[ihole][0];
37502 poly_file >> hole_coordinates[ihole][1];
37508 std::map<unsigned, bool> hole_done;
37512 for (
unsigned i = 0;
i < npolygons - 1;
i++)
37515 for (
unsigned h = 0; h < nholes; h++)
37523 const bool hole_in_polygon = this->is_point_inside_polygon_helper(
37524 inner_vertex_coordinates[
i], current_point);
37527 if (hole_in_polygon)
37530 hole_done[h] =
true;
37533 index_hole_of_internal_polygon[
i] = h;
37545 if (hole_done.size() != npolygons - 1)
37547 std::ostringstream error_message;
37549 <<
"Not all the holes were associated to an internal closed boundary\n"
37550 <<
"Only (" << hole_done.size()
37551 <<
") holes were assigned for a total of\n"
37552 <<
"(" << npolygons - 1 <<
") internal closed boundaries.\n"
37553 <<
"You can check the generated mesh by calling the output() method\n"
37554 <<
"from the mesh object '(problem.mesh_pt()->output(string))'\n\n";
37556 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
37561 for (
unsigned ihole = 0; ihole < nholes; ihole++)
37564 const unsigned index_hole = index_hole_of_internal_polygon[ihole];
37569 if (index_hole != ihole)
37571 std::ostringstream error_message;
37573 <<
"The hole vertices coordinates are not listed in the same order\n"
37574 <<
"as the nodes that define the internal closed boundaries.\n"
37575 <<
"This may lead to problems in case that the holes coordinates\n"
37576 <<
"were no properly assigned to the internal closed boundaries.\n"
37577 <<
"You can check the generated mesh by calling the output() method\n"
37578 <<
"from the mesh object '(problem.mesh_pt()->output(string))'\n\n";
37580 OOMPH_CURRENT_FUNCTION,
37581 OOMPH_EXCEPTION_LOCATION);
37586 this->Internal_polygon_pt[ihole]->internal_point() =
37587 hole_coordinates[index_hole];
37591 poly_file.ignore(80,
'\n');
37601 getline(poly_file, regions_info_string);
37605 if (isdigit(regions_info_string.c_str()[0]))
37607 nregions = std::atoi(regions_info_string.c_str());
37615 std::map<unsigned, Vector<double>> regions_coordinates;
37618 unsigned dummy_region;
37620 unsigned region_id;
37623 for (
unsigned iregion = 0; iregion < nregions; iregion++)
37627 poly_file >> dummy_region;
37628 poly_file >> tmp_region_coordinates[0];
37629 poly_file >> tmp_region_coordinates[1];
37630 poly_file >> region_id;
37631 regions_coordinates[region_id].resize(2);
37632 regions_coordinates[region_id][0] = tmp_region_coordinates[0];
37633 regions_coordinates[region_id][1] = tmp_region_coordinates[1];
37636 poly_file.ignore(80,
'\n');
37639 if (region_id == 0)
37641 std::ostringstream error_message;
37643 <<
"Please use another region id different from zero.\n"
37644 <<
"It is internally used as the default region number.\n";
37646 OOMPH_CURRENT_FUNCTION,
37647 OOMPH_EXCEPTION_LOCATION);
37652 this->Regions_coordinates = regions_coordinates;
37661 template<
class ELEMENT>
37666 unsigned update_was_performed =
false;
37668 const unsigned nele = this->nelement();
37679 get_face_mesh_representation(polygon_pt, face_mesh_pt);
37687 unsigned n_polyline = polygon_pt->
npolyline();
37690 for (
unsigned p = 0; p < n_polyline; p++)
37704 std::set<Vector<double>> vertex_nodes;
37715 #ifdef OOMPH_HAS_MPI
37745 const unsigned nface_element = face_mesh_pt[p]->nelement();
37752 std::map<FiniteElement*, unsigned> face_element_index_on_boundary;
37754 for (
unsigned ef = 0; ef < nface_element; ++ef)
37756 FiniteElement* ele_face_pt = face_mesh_pt[p]->finite_element_pt(ef);
37757 #ifdef OOMPH_HAS_MPI
37759 if (this->is_mesh_distributed() && ele_face_pt->
is_halo())
37765 non_halo_face_element_pt.push_back(ele_face_pt);
37766 face_element_index_on_boundary[ele_face_pt] = ef;
37770 const unsigned nnon_halo_face_element = non_halo_face_element_pt.size();
37773 std::map<FiniteElement*, bool> face_element_done;
37776 unsigned nsorted_face_elements = 0;
37778 #ifdef OOMPH_HAS_MPI
37780 unsigned nsub_boundaries = 0;
37785 while (nsorted_face_elements < nnon_halo_face_element)
37790 bool found_initial_face_element =
false;
37793 unsigned iface = 0;
37794 for (iface = 0; iface < nnon_halo_face_element; iface++)
37796 ele_face_pt = non_halo_face_element_pt[iface];
37798 if (!face_element_done[ele_face_pt])
37801 found_initial_face_element =
true;
37803 nsorted_face_elements++;
37810 if (!found_initial_face_element)
37812 std::ostringstream error_message;
37813 error_message <<
"Could not find an initial face element for the "
37814 "current segment\n";
37817 error_message.str(),
37818 "RefineableTriangleMesh::update_polygon_using_elements_area()",
37819 OOMPH_EXCEPTION_LOCATION);
37826 std::set<Vector<double>> local_vertex_nodes;
37834 std::set<Vector<double>> sorted_target_areas;
37844 unsigned nnode = ele_face_pt->
nnode();
37848 vertex_coord[0] = bound_left[0];
37851 for (
unsigned i = 0;
i < 2;
i++)
37853 vertex_coord[
i + 1] = ele_face_pt->
node_pt(0)->
x(
i);
37855 local_vertex_nodes.insert(vertex_coord);
37860 bound, bound_right);
37861 vertex_coord[0] = bound_right[0];
37864 for (
unsigned i = 0;
i < 2;
i++)
37866 vertex_coord[
i + 1] = ele_face_pt->
node_pt(nnode - 1)->
x(
i);
37868 local_vertex_nodes.insert(vertex_coord);
37872 Node* last_node_pt = ele_face_pt->
node_pt(nnode - 1);
37875 face_element_done[ele_face_pt] =
true;
37887 zeta_target_area_values[0] = std::min(bound_left[0], bound_right[0]);
37890 unsigned ef = face_element_index_on_boundary[ele_face_pt];
37892 FiniteElement* el_pt = this->boundary_element_pt(bound, ef);
37895 bool found_global_element_index =
false;
37897 for (
unsigned eg = 0; eg < nele; eg++)
37900 FiniteElement* el_compare_pt = this->finite_element_pt(eg);
37904 if (el_pt == el_compare_pt)
37906 zeta_target_area_values[1] = target_area[eg];
37908 found_global_element_index =
true;
37915 if (!found_global_element_index)
37917 std::ostringstream error_message;
37918 error_message <<
"The global index for the (" << ef
37919 <<
")-th face element "
37920 <<
"on\nthe (" << bound
37921 <<
")-th boundary was not found!!!";
37923 error_message.str(),
37924 "RefineableTriangleMesh::update_polygon_using_elements_area()",
37925 OOMPH_EXCEPTION_LOCATION);
37930 sorted_target_areas.insert(zeta_target_area_values);
37935 bool face_element_added =
false;
37945 for (
unsigned iiface = iface; iiface < nnon_halo_face_element;
37948 face_element_added =
false;
37949 ele_face_pt = non_halo_face_element_pt[iiface];
37950 if (!face_element_done[ele_face_pt])
37953 nnode = ele_face_pt->nnode();
37954 Node* left_node_pt = ele_face_pt->node_pt(0);
37955 Node* right_node_pt = ele_face_pt->node_pt(nnode - 1);
37957 if (left_node_pt == first_node_pt)
37959 first_node_pt = right_node_pt;
37960 face_element_added =
true;
37962 else if (left_node_pt == last_node_pt)
37964 last_node_pt = right_node_pt;
37965 face_element_added =
true;
37967 else if (right_node_pt == first_node_pt)
37969 first_node_pt = left_node_pt;
37970 face_element_added =
true;
37972 else if (right_node_pt == last_node_pt)
37974 last_node_pt = left_node_pt;
37975 face_element_added =
true;
37978 if (face_element_added)
37983 vertex_coord[0] = bound_left[0];
37986 for (
unsigned i = 0;
i < 2;
i++)
37988 vertex_coord[
i + 1] = left_node_pt->
x(
i);
37990 local_vertex_nodes.insert(vertex_coord);
37995 vertex_coord[0] = bound_right[0];
37998 for (
unsigned i = 0;
i < 2;
i++)
38000 vertex_coord[
i + 1] = right_node_pt->
x(
i);
38002 local_vertex_nodes.insert(vertex_coord);
38006 face_element_done[ele_face_pt] =
true;
38007 nsorted_face_elements++;
38015 zeta_target_area_values[0] =
38016 std::min(bound_left[0], bound_right[0]);
38019 ef = face_element_index_on_boundary[ele_face_pt];
38020 FiniteElement* lel_pt = this->boundary_element_pt(bound, ef);
38023 found_global_element_index =
false;
38025 for (
unsigned eg = 0; eg < nele; eg++)
38028 FiniteElement* lel_compare_pt = this->finite_element_pt(eg);
38032 if (lel_pt == lel_compare_pt)
38034 zeta_target_area_values[1] = target_area[eg];
38036 found_global_element_index =
true;
38043 if (!found_global_element_index)
38045 std::ostringstream error_message;
38046 error_message <<
"The global index for the (" << ef
38047 <<
")-th face element "
38048 <<
"on\nthe (" << bound
38049 <<
")-th boundary was not found!!!";
38051 "RefineableTriangleMesh::update_polygon_"
38052 "using_elements_area()",
38053 OOMPH_EXCEPTION_LOCATION);
38058 sorted_target_areas.insert(zeta_target_area_values);
38065 }
while (face_element_added &&
38066 (nsorted_face_elements < nnon_halo_face_element));
38074 const unsigned nlocal_nodes = local_vertex_nodes.size();
38076 local_tmp_vector_vertex_node.resize(nlocal_nodes);
38079 unsigned counter = 0;
38080 std::set<Vector<double>>::iterator it_vertex;
38081 for (it_vertex = local_vertex_nodes.begin();
38082 it_vertex != local_vertex_nodes.end();
38085 local_tmp_vector_vertex_node[counter].resize(3);
38086 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
38087 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
38088 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
38094 const unsigned ntarget_areas = sorted_target_areas.size();
38095 tmp_sorted_target_areas.resize(ntarget_areas);
38097 std::set<Vector<double>>::iterator it_area;
38098 for (it_area = sorted_target_areas.begin();
38099 it_area != sorted_target_areas.end();
38102 tmp_sorted_target_areas[counter] = (*it_area)[1];
38107 if (nlocal_nodes > 0 && (ntarget_areas != nlocal_nodes - 1))
38109 std::ostringstream error_message;
38111 <<
"The boundary (" << bound <<
") was split during the "
38112 <<
"distribution process.\n"
38113 <<
"The problem is in the association of the target areas with "
38115 <<
"elements that gave rise to the vertex coordinates.\n"
38116 <<
"The number of local nodes (" << nlocal_nodes
38117 <<
"), on the 'sub-polyline', is not\n"
38118 <<
"according with the number of target "
38119 <<
"areas (" << ntarget_areas <<
")\nfor that number of nodes.\n"
38120 <<
"The target areas number MUST be equal to the number of\n"
38121 <<
"local nodes minus one\n\n";
38123 OOMPH_CURRENT_FUNCTION,
38124 OOMPH_EXCEPTION_LOCATION);
38135 double unrefinement_tolerance =
38139 bool unrefinement_applied =
38140 unrefine_boundary_constrained_by_target_area(
38143 local_tmp_vector_vertex_node,
38144 unrefinement_tolerance,
38145 tmp_sorted_target_areas);
38148 double refinement_tolerance =
38152 bool refinement_applied = refine_boundary_constrained_by_target_area(
38154 local_tmp_vector_vertex_node,
38155 refinement_tolerance,
38156 tmp_sorted_target_areas);
38160 local_vertex_nodes.clear();
38165 unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
38166 for (
unsigned i = 0;
i < nnew_nodes;
i++)
38168 vertex_coord[0] = local_tmp_vector_vertex_node[
i][0];
38169 vertex_coord[1] = local_tmp_vector_vertex_node[
i][1];
38170 vertex_coord[2] = local_tmp_vector_vertex_node[
i][2];
38171 vertex_nodes.insert(vertex_coord);
38172 local_vertex_nodes.insert(vertex_coord);
38177 update_was_performed = (unrefinement_applied || refinement_applied);
38179 #ifdef OOMPH_HAS_MPI
38180 if (this->is_mesh_distributed())
38184 sub_vertex_nodes.push_back(local_vertex_nodes);
38193 unsigned npoly_vertex = vertex_nodes.size();
38196 tmp_vector_vertex_node.resize(npoly_vertex);
38197 unsigned count = 0;
38198 for (std::set<
Vector<double>>::iterator it = vertex_nodes.begin();
38199 it != vertex_nodes.end();
38202 tmp_vector_vertex_node[count].resize(3);
38203 tmp_vector_vertex_node[count][0] = (*it)[0];
38204 tmp_vector_vertex_node[count][1] = (*it)[1];
38205 tmp_vector_vertex_node[count][2] = (*it)[2];
38209 #ifdef OOMPH_HAS_MPI
38212 unsigned nsub_boundaries_set = sub_vertex_nodes.size();
38213 if (nsub_boundaries_set != nsub_boundaries)
38215 std::ostringstream error_message;
38217 <<
"The number of found sub-boundaries and the number of counted\n"
38218 <<
"sub-boundaries are different:\n"
38219 <<
"Number of found sub-boundaries: (" << nsub_boundaries_set <<
")\n"
38220 <<
"Number of counted sub-boundaries: (" << nsub_boundaries <<
")\n";
38222 OOMPH_CURRENT_FUNCTION,
38223 OOMPH_EXCEPTION_LOCATION);
38228 if (this->is_mesh_distributed() && nsub_boundaries > 1)
38231 this->Boundary_was_splitted[bound] =
true;
38233 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
38234 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
38237 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
38238 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
38239 unsigned subcount = 0;
38240 std::set<Vector<double>>::iterator subit;
38241 for (subit = sub_vertex_nodes[isub].begin();
38242 subit != sub_vertex_nodes[isub].end();
38245 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
38246 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
38247 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
38248 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
38258 unsigned n_vertex = tmp_vector_vertex_node.size();
38261 vector_vertex_node.resize(n_vertex);
38262 for (
unsigned i = 0;
i < n_vertex;
i++)
38264 vector_vertex_node[
i].resize(2);
38265 vector_vertex_node[
i][0] = tmp_vector_vertex_node[
i][1];
38266 vector_vertex_node[
i][1] = tmp_vector_vertex_node[
i][2];
38269 #ifdef OOMPH_HAS_MPI
38272 if (this->is_mesh_distributed() && nsub_boundaries > 1)
38277 sub_vector_vertex_node.resize(nsub_boundaries);
38278 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
38280 const unsigned subn_vertex = sub_tmp_vector_vertex_node[isub].size();
38282 sub_vector_vertex_node[isub].resize(subn_vertex);
38283 for (
unsigned i = 0;
i < subn_vertex;
i++)
38285 sub_vector_vertex_node[isub][
i].resize(2);
38286 sub_vector_vertex_node[isub][
i][0] =
38287 sub_tmp_vector_vertex_node[isub][
i][1];
38288 sub_vector_vertex_node[isub][
i][1] =
38289 sub_tmp_vector_vertex_node[isub][
i][2];
38304 #ifdef OOMPH_HAS_MPI
38308 if (!this->is_mesh_distributed())
38315 unsigned n_prev_vertex =
38317 final_vertex_of_previous_segment =
38321 unsigned prev_seg_boundary_id =
38326 double error = 0.0;
38327 for (
unsigned i = 0;
i < 2;
i++)
38329 const double dist = final_vertex_of_previous_segment[
i] -
38330 (*vector_vertex_node.begin())[
i];
38331 error += dist * dist;
38333 error = sqrt(error);
38341 double rev_error = 0.0;
38342 for (
unsigned i = 0;
i < 2;
i++)
38344 const double dist = final_vertex_of_previous_segment[
i] -
38345 (*--vector_vertex_node.end())[
i];
38346 rev_error += dist * dist;
38348 rev_error = sqrt(rev_error);
38362 initial_vertex_of_previous_segment =
38365 unsigned prev_seg_boundary_id =
38370 double error = 0.0;
38371 for (
unsigned i = 0;
i < 2;
i++)
38373 const double dist = initial_vertex_of_previous_segment[
i] -
38374 (*vector_vertex_node.begin())[
i];
38375 error += dist * dist;
38377 error = sqrt(error);
38386 double rev_error = 0.0;
38387 for (
unsigned i = 0;
i < 2;
i++)
38389 const double dist = initial_vertex_of_previous_segment[
i] -
38390 (*--vector_vertex_node.end())[
i];
38391 rev_error += dist * dist;
38400 std::ostringstream error_stream;
38402 <<
"The distance between the first node of the current\n"
38403 <<
"line segment (boundary " << bound
38404 <<
") and either end of "
38405 <<
"the previous line segment\n"
38406 <<
"(boundary " << prev_seg_boundary_id
38407 <<
") is bigger than "
38408 <<
"the desired tolerance "
38411 <<
"This suggests that the polylines defining the "
38413 <<
"representation are not properly ordered.\n"
38414 <<
"Fail on last vertex of polyline: ("
38415 << prev_seg_boundary_id <<
") and\n"
38416 <<
"first vertex of polyline (" << bound <<
").\n"
38417 <<
"This should have failed when first trying to "
38418 <<
"construct the\npolygon.\n";
38420 OOMPH_CURRENT_FUNCTION,
38421 OOMPH_EXCEPTION_LOCATION);
38428 std::reverse(vector_vertex_node.begin(),
38429 vector_vertex_node.end());
38443 std::ostringstream error_stream;
38445 <<
"The distance between the first node of the current\n"
38446 <<
"line segment (boundary " << bound
38447 <<
") and either end of "
38448 <<
"the previous line segment\n"
38449 <<
"(boundary " << prev_seg_boundary_id
38450 <<
") is bigger than the "
38451 <<
"desired tolerance "
38454 <<
"This suggests that the polylines defining the polygonal\n"
38455 <<
"representation are not properly ordered.\n"
38456 <<
"Fail on last vertex of polyline: ("
38457 << prev_seg_boundary_id <<
") and\nfirst vertex of polyline ("
38459 <<
"This should have failed when first trying to construct"
38460 <<
" the polygon.\n";
38462 OOMPH_CURRENT_FUNCTION,
38463 OOMPH_EXCEPTION_LOCATION);
38469 std::reverse(vector_vertex_node.begin(),
38470 vector_vertex_node.end());
38488 n_vertex = vector_vertex_node.size();
38500 double unrefinement_tolerance =
38504 double refinement_tolerance =
38515 #ifdef OOMPH_HAS_MPI
38518 if (this->is_mesh_distributed())
38524 this->copy_connection_information(polygon_pt->
polyline_pt(p),
38525 tmp_curve_section_pt);
38533 this->copy_connection_information(polygon_pt->
polyline_pt(p),
38534 tmp_curve_section_pt);
38540 bool delete_it_on_destructor =
false;
38542 std::set<TriangleMeshCurveSection*>::iterator it =
38545 if (it != this->Free_curve_section_pt.end())
38547 this->Free_curve_section_pt.erase(it);
38549 delete_it_on_destructor =
true;
38559 if (delete_it_on_destructor)
38564 #ifdef OOMPH_HAS_MPI
38567 if (this->is_mesh_distributed() && nsub_boundaries > 1)
38573 this->Boundary_subpolylines[bound].clear();
38576 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
38577 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
38585 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
38601 delete mesh_geom_obj_pt;
38606 for (
unsigned p = 0; p < n_polyline; p++)
38608 face_mesh_pt[p]->flush_node_storage();
38609 delete face_mesh_pt[p];
38612 return update_was_performed;
38619 template<
class ELEMENT>
38624 unsigned update_was_performed =
false;
38626 const unsigned nele = this->nelement();
38637 get_face_mesh_representation(open_curve_pt, face_mesh_pt);
38645 const unsigned ncurve_section = open_curve_pt->
ncurve_section();
38648 for (
unsigned cs = 0; cs < ncurve_section; cs++)
38663 const unsigned chunk =
38673 const unsigned nface_element = face_mesh_pt[cs]->nelement();
38681 std::map<FiniteElement*, unsigned> face_element_index_on_boundary;
38684 std::map<FiniteElement*, bool> face_element_done;
38686 for (
unsigned ef = 0; ef < nface_element; ++ef)
38688 FiniteElement* ele_face_pt = face_mesh_pt[cs]->finite_element_pt(ef);
38693 #ifdef OOMPH_HAS_MPI
38694 if (this->is_mesh_distributed())
38705 if (!face_element_done[ele_face_pt])
38710 non_halo_doubled_face_element_pt.push_back(ele_face_pt);
38712 face_element_index_on_boundary[ele_face_pt] = ef;
38714 face_element_done[ele_face_pt] =
true;
38716 const unsigned nnodes = ele_face_pt->
nnode();
38720 Node* right_node_pt = ele_face_pt->
node_pt(nnodes - 1);
38724 bool found_other_side_face_ele =
false;
38726 for (
unsigned iface = 0; iface < nface_element; iface++)
38730 face_mesh_pt[cs]->finite_element_pt(iface);
38732 if (!face_element_done[cele_face_pt])
38735 Node* cright_node_pt = cele_face_pt->
node_pt(nnodes - 1);
38737 if ((left_node_pt == cleft_node_pt &&
38738 right_node_pt == cright_node_pt) ||
38739 (left_node_pt == cright_node_pt &&
38740 right_node_pt == cleft_node_pt))
38743 non_halo_doubled_face_element_pt.push_back(cele_face_pt);
38745 face_element_done[cele_face_pt] =
true;
38747 face_element_index_on_boundary[cele_face_pt] = iface;
38750 found_other_side_face_ele =
true;
38758 if (!found_other_side_face_ele)
38760 std::ostringstream error_message;
38762 <<
"The face element at the other side of the boundary (" << bound
38763 <<
") was not found!!\n"
38764 <<
"These are the nodes of the face element:\n"
38765 <<
"(" << left_node_pt->
x(0) <<
", " << left_node_pt->
x(1) <<
") "
38766 <<
"and (" << right_node_pt->
x(0) <<
"," << right_node_pt->
x(1)
38769 error_message.str(),
38770 "RefineableTriangleMesh::update_open_curve_using_elements_area()",
38771 OOMPH_EXCEPTION_LOCATION);
38780 face_element_done.clear();
38785 std::set<Vector<double>> vertex_nodes;
38796 #ifdef OOMPH_HAS_MPI
38801 std::vector<bool> internal_to_shared_boundary;
38828 unsigned nsorted_face_elements = 0;
38830 #ifdef OOMPH_HAS_MPI
38832 unsigned nsub_boundaries = 0;
38836 const unsigned nnon_halo_doubled_face_ele =
38837 non_halo_doubled_face_element_pt.size();
38841 while (nsorted_face_elements < nnon_halo_doubled_face_ele)
38847 bool found_initial_face_element =
false;
38853 bool both_root_face_elements_are_nonhalo =
false;
38855 unsigned iface = 0;
38856 for (iface = 0; iface < nnon_halo_doubled_face_ele; iface += 2)
38858 ele_face_pt = non_halo_doubled_face_element_pt[iface];
38860 if (!face_element_done[ele_face_pt])
38863 face_element_done[ele_face_pt] =
true;
38865 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iface + 1];
38867 face_element_done[repeated_ele_face_pt] =
true;
38869 #ifdef OOMPH_HAS_MPI
38870 if (!repeated_ele_face_pt->
is_halo())
38872 both_root_face_elements_are_nonhalo =
true;
38878 nsorted_face_elements += 2;
38882 found_initial_face_element =
true;
38889 if (!found_initial_face_element)
38891 std::ostringstream error_message;
38892 error_message <<
"Could not find an initial face element for the "
38893 "current segment\n";
38895 OOMPH_CURRENT_FUNCTION,
38896 OOMPH_EXCEPTION_LOCATION);
38903 std::set<Vector<double>> local_vertex_nodes;
38911 std::set<Vector<double>> sorted_target_areas;
38921 const unsigned nnode = ele_face_pt->
nnode();
38925 vertex_coord[0] = bound_left[0];
38928 for (
unsigned i = 0;
i < 2;
i++)
38930 vertex_coord[
i + 1] = ele_face_pt->
node_pt(0)->
x(
i);
38932 local_vertex_nodes.insert(vertex_coord);
38937 bound, bound_right);
38938 vertex_coord[0] = bound_right[0];
38941 for (
unsigned i = 0;
i < 2;
i++)
38943 vertex_coord[
i + 1] = ele_face_pt->
node_pt(nnode - 1)->
x(
i);
38945 local_vertex_nodes.insert(vertex_coord);
38949 Node* last_node_pt = ele_face_pt->
node_pt(nnode - 1);
38961 zeta_target_area_values[0] = std::min(bound_left[0], bound_right[0]);
38964 const unsigned ef = face_element_index_on_boundary[ele_face_pt];
38966 FiniteElement* el_pt = this->boundary_element_pt(bound, ef);
38967 double target_area_face_element = 0.0;
38970 bool found_global_element_index =
false;
38972 for (
unsigned eg = 0; eg < nele; eg++)
38975 FiniteElement* el_compare_pt = this->finite_element_pt(eg);
38979 if (el_pt == el_compare_pt)
38981 target_area_face_element = target_area[eg];
38983 found_global_element_index =
true;
38990 if (!found_global_element_index)
38992 std::ostringstream error_message;
38993 error_message <<
"The global index for the (" << ef
38994 <<
")-th face element "
38995 <<
"on\nthe (" << bound
38996 <<
")-th boundary was not found!!!";
38998 OOMPH_CURRENT_FUNCTION,
38999 OOMPH_EXCEPTION_LOCATION);
39004 const unsigned ref =
39005 face_element_index_on_boundary[repeated_ele_face_pt];
39006 FiniteElement* rel_pt = this->boundary_element_pt(bound, ref);
39007 double target_area_repeated_face_element = 0.0;
39010 bool found_global_repeated_element_index =
false;
39012 for (
unsigned eg = 0; eg < nele; eg++)
39015 FiniteElement* el_compare_pt = this->finite_element_pt(eg);
39019 if (rel_pt == el_compare_pt)
39021 target_area_repeated_face_element = target_area[eg];
39023 found_global_repeated_element_index =
true;
39030 if (!found_global_repeated_element_index)
39032 std::ostringstream error_message;
39033 error_message <<
"The global index for the (" << ref
39034 <<
")-th face element "
39035 <<
"on\nthe (" << bound
39036 <<
")-th boundary was not found (repeated "
39037 <<
"face element)!!!";
39039 OOMPH_CURRENT_FUNCTION,
39040 OOMPH_EXCEPTION_LOCATION);
39046 zeta_target_area_values[1] =
39047 std::min(target_area_face_element, target_area_repeated_face_element);
39050 sorted_target_areas.insert(zeta_target_area_values);
39055 bool face_element_added =
false;
39065 for (
unsigned iiface = iface; iiface < nnon_halo_doubled_face_ele;
39068 face_element_added =
false;
39069 ele_face_pt = non_halo_doubled_face_element_pt[iiface];
39076 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iiface + 1];
39077 bool both_face_elements_are_nonhalo =
false;
39079 #ifdef OOMPH_HAS_MPI
39080 if (!repeated_ele_face_pt->
is_halo())
39082 both_face_elements_are_nonhalo =
true;
39086 if (!face_element_done[ele_face_pt] &&
39087 (both_face_elements_are_nonhalo ==
39088 both_root_face_elements_are_nonhalo))
39091 const unsigned nlnode = ele_face_pt->
nnode();
39093 Node* right_node_pt = ele_face_pt->
node_pt(nlnode - 1);
39095 if (left_node_pt == first_node_pt)
39097 first_node_pt = right_node_pt;
39098 face_element_added =
true;
39100 else if (left_node_pt == last_node_pt)
39102 last_node_pt = right_node_pt;
39103 face_element_added =
true;
39105 else if (right_node_pt == first_node_pt)
39107 first_node_pt = left_node_pt;
39108 face_element_added =
true;
39110 else if (right_node_pt == last_node_pt)
39112 last_node_pt = left_node_pt;
39113 face_element_added =
true;
39116 if (face_element_added)
39121 vertex_coord[0] = bound_left[0];
39124 for (
unsigned i = 0;
i < 2;
i++)
39126 vertex_coord[
i + 1] = left_node_pt->
x(
i);
39128 local_vertex_nodes.insert(vertex_coord);
39133 vertex_coord[0] = bound_right[0];
39136 for (
unsigned i = 0;
i < 2;
i++)
39138 vertex_coord[
i + 1] = right_node_pt->
x(
i);
39140 local_vertex_nodes.insert(vertex_coord);
39144 face_element_done[ele_face_pt] =
true;
39147 repeated_ele_face_pt =
39148 non_halo_doubled_face_element_pt[iiface + 1];
39149 face_element_done[repeated_ele_face_pt] =
true;
39151 nsorted_face_elements += 2;
39159 zeta_target_area_values[0] =
39160 std::min(bound_left[0], bound_right[0]);
39163 const unsigned lef =
39164 face_element_index_on_boundary[ele_face_pt];
39165 FiniteElement* lel_pt = this->boundary_element_pt(bound, lef);
39168 found_global_element_index =
false;
39170 for (
unsigned eg = 0; eg < nele; eg++)
39173 FiniteElement* lel_compare_pt = this->finite_element_pt(eg);
39177 if (lel_pt == lel_compare_pt)
39179 target_area_face_element = target_area[eg];
39181 found_global_element_index =
true;
39188 if (!found_global_element_index)
39190 std::ostringstream error_message;
39191 error_message <<
"The global index for the (" << lef
39192 <<
")-th face element "
39193 <<
"on\nthe (" << bound
39194 <<
")-th boundary was not found!!!";
39196 OOMPH_CURRENT_FUNCTION,
39197 OOMPH_EXCEPTION_LOCATION);
39202 const unsigned rlef =
39203 face_element_index_on_boundary[repeated_ele_face_pt];
39204 FiniteElement* rlel_pt = this->boundary_element_pt(bound, rlef);
39207 found_global_repeated_element_index =
false;
39209 for (
unsigned eg = 0; eg < nele; eg++)
39212 FiniteElement* lel_compare_pt = this->finite_element_pt(eg);
39216 if (rlel_pt == lel_compare_pt)
39218 target_area_repeated_face_element = target_area[eg];
39220 found_global_repeated_element_index =
true;
39227 if (!found_global_repeated_element_index)
39229 std::ostringstream error_message;
39230 error_message <<
"The global index for the (" << rlef
39231 <<
")-th face element "
39232 <<
"on\nthe (" << bound
39233 <<
")-th boundary was not found "
39234 <<
"(repeated face element)!!!";
39236 OOMPH_CURRENT_FUNCTION,
39237 OOMPH_EXCEPTION_LOCATION);
39243 zeta_target_area_values[1] = std::min(
39244 target_area_face_element, target_area_repeated_face_element);
39247 sorted_target_areas.insert(zeta_target_area_values);
39254 }
while (face_element_added &&
39255 (nsorted_face_elements < nnon_halo_doubled_face_ele));
39263 const unsigned nlocal_nodes = local_vertex_nodes.size();
39265 local_tmp_vector_vertex_node.resize(nlocal_nodes);
39268 unsigned counter = 0;
39269 std::set<Vector<double>>::iterator it_vertex;
39270 for (it_vertex = local_vertex_nodes.begin();
39271 it_vertex != local_vertex_nodes.end();
39274 local_tmp_vector_vertex_node[counter].resize(3);
39275 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
39276 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
39277 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
39283 const unsigned ntarget_areas = sorted_target_areas.size();
39284 tmp_sorted_target_areas.resize(ntarget_areas);
39286 std::set<Vector<double>>::iterator it_area;
39287 for (it_area = sorted_target_areas.begin();
39288 it_area != sorted_target_areas.end();
39291 tmp_sorted_target_areas[counter] = (*it_area)[1];
39296 if (nlocal_nodes > 0 && (ntarget_areas != nlocal_nodes - 1))
39298 std::ostringstream error_message;
39300 <<
"The boundary (" << bound <<
") was split during the "
39301 <<
"distribution process.\n"
39302 <<
"The problem comes when associating the target areas with the "
39303 <<
"elements that gave\nrise to the vertex coordinates.\n"
39304 <<
"The number of local nodes on the 'sub-polyline' ("
39305 << nlocal_nodes <<
") is not according with the number of target\n"
39306 <<
"areas (" << ntarget_areas <<
") for that number of nodes.\n"
39307 <<
"The target areas number must be equal to the number of "
39310 OOMPH_CURRENT_FUNCTION,
39311 OOMPH_EXCEPTION_LOCATION);
39318 if (local_tmp_vector_vertex_node[nlocal_nodes - 1][2] <
39319 local_tmp_vector_vertex_node[0][2])
39321 std::reverse(local_tmp_vector_vertex_node.begin(),
39322 local_tmp_vector_vertex_node.end());
39323 std::reverse(tmp_sorted_target_areas.begin(),
39324 tmp_sorted_target_areas.end());
39326 else if (local_tmp_vector_vertex_node[nlocal_nodes - 1][2] ==
39327 local_tmp_vector_vertex_node[0][2])
39329 if (local_tmp_vector_vertex_node[nlocal_nodes - 1][1] <
39330 local_tmp_vector_vertex_node[0][1])
39332 std::reverse(local_tmp_vector_vertex_node.begin(),
39333 local_tmp_vector_vertex_node.end());
39334 std::reverse(tmp_sorted_target_areas.begin(),
39335 tmp_sorted_target_areas.end());
39346 double unrefinement_tolerance =
39350 bool unrefinement_applied =
39351 unrefine_boundary_constrained_by_target_area(
39354 local_tmp_vector_vertex_node,
39355 unrefinement_tolerance,
39356 tmp_sorted_target_areas);
39359 double refinement_tolerance =
39363 bool refinement_applied = refine_boundary_constrained_by_target_area(
39365 local_tmp_vector_vertex_node,
39366 refinement_tolerance,
39367 tmp_sorted_target_areas);
39371 local_vertex_nodes.clear();
39376 const unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
39377 for (
unsigned i = 0;
i < nnew_nodes;
i++)
39379 vertex_coord[0] = local_tmp_vector_vertex_node[
i][0];
39380 vertex_coord[1] = local_tmp_vector_vertex_node[
i][1];
39381 vertex_coord[2] = local_tmp_vector_vertex_node[
i][2];
39382 vertex_nodes.insert(vertex_coord);
39383 local_vertex_nodes.insert(vertex_coord);
39388 update_was_performed = (unrefinement_applied || refinement_applied);
39390 #ifdef OOMPH_HAS_MPI
39391 if (this->is_mesh_distributed())
39396 sub_vertex_nodes.push_back(local_vertex_nodes);
39402 if (both_root_face_elements_are_nonhalo)
39404 internal_to_shared_boundary.push_back(
false);
39408 internal_to_shared_boundary.push_back(
true);
39419 const unsigned npoly_vertex = vertex_nodes.size();
39420 tmp_vector_vertex_node.resize(npoly_vertex);
39421 unsigned count = 0;
39422 for (std::set<
Vector<double>>::iterator it = vertex_nodes.begin();
39423 it != vertex_nodes.end();
39426 tmp_vector_vertex_node[count].resize(3);
39427 tmp_vector_vertex_node[count][0] = (*it)[0];
39428 tmp_vector_vertex_node[count][1] = (*it)[1];
39429 tmp_vector_vertex_node[count][2] = (*it)[2];
39433 #ifdef OOMPH_HAS_MPI
39438 const unsigned nsub_boundaries_set = sub_vertex_nodes.size();
39439 const unsigned ninternal_to_shared_boundaries =
39440 internal_to_shared_boundary.size();
39441 if (nsub_boundaries_set != ninternal_to_shared_boundaries)
39443 std::ostringstream error_message;
39445 <<
"The number of found sub-boundaries and the number of marked "
39446 <<
"internal\nboundaries are different\n"
39447 <<
"Number of found sub-boundaries: (" << nsub_boundaries_set <<
")\n"
39448 <<
"Number of marked internal boundaries: ("
39449 << ninternal_to_shared_boundaries <<
")\n\n";
39451 OOMPH_CURRENT_FUNCTION,
39452 OOMPH_EXCEPTION_LOCATION);
39458 if (nsub_boundaries_set != nsub_boundaries)
39460 std::ostringstream error_message;
39462 <<
"The number of found sub-boundaries and the number of counted\n"
39463 <<
"sub-boundaries are different:\n"
39464 <<
"Number of found sub-boundaries: (" << nsub_boundaries_set <<
")\n"
39465 <<
"Number of counted sub-boundaries: (" << nsub_boundaries
39468 OOMPH_CURRENT_FUNCTION,
39469 OOMPH_EXCEPTION_LOCATION);
39474 if (this->is_mesh_distributed() && nsub_boundaries > 1)
39477 this->Boundary_was_splitted[bound] =
true;
39480 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
39482 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
39485 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
39486 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
39487 unsigned subcount = 0;
39488 std::set<Vector<double>>::iterator subit;
39489 for (subit = sub_vertex_nodes[isub].begin();
39490 subit != sub_vertex_nodes[isub].end();
39493 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
39494 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
39495 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
39496 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
39506 unsigned n_vertex = tmp_vector_vertex_node.size();
39509 vector_vertex_node.resize(n_vertex);
39510 for (
unsigned i = 0;
i < n_vertex;
i++)
39512 vector_vertex_node[
i].resize(2);
39513 vector_vertex_node[
i][0] = tmp_vector_vertex_node[
i][1];
39514 vector_vertex_node[
i][1] = tmp_vector_vertex_node[
i][2];
39517 #ifdef OOMPH_HAS_MPI
39520 if (this->is_mesh_distributed() && nsub_boundaries > 1)
39525 sub_vector_vertex_node.resize(nsub_boundaries);
39526 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
39528 const unsigned subn_vertex = sub_tmp_vector_vertex_node[isub].size();
39530 sub_vector_vertex_node[isub].resize(subn_vertex);
39531 for (
unsigned i = 0;
i < subn_vertex;
i++)
39533 sub_vector_vertex_node[isub][
i].resize(2);
39534 sub_vector_vertex_node[isub][
i][0] =
39535 sub_tmp_vector_vertex_node[isub][
i][1];
39536 sub_vector_vertex_node[isub][
i][1] =
39537 sub_tmp_vector_vertex_node[isub][
i][2];
39552 #ifdef OOMPH_HAS_MPI
39556 if (!this->is_mesh_distributed())
39563 unsigned n_prev_vertex =
39565 final_vertex_of_previous_segment =
39567 n_prev_vertex - 1);
39569 unsigned prev_seg_boundary_id =
39574 double error = 0.0;
39575 for (
unsigned i = 0;
i < 2;
i++)
39577 const double dist = final_vertex_of_previous_segment[
i] -
39578 (*vector_vertex_node.begin())[
i];
39579 error += dist * dist;
39581 error = sqrt(error);
39589 double rev_error = 0.0;
39590 for (
unsigned i = 0;
i < 2;
i++)
39592 const double dist = final_vertex_of_previous_segment[
i] -
39593 (*--vector_vertex_node.end())[
i];
39594 rev_error += dist * dist;
39596 rev_error = sqrt(rev_error);
39610 initial_vertex_of_previous_segment =
39613 unsigned prev_seg_boundary_id =
39618 double error = 0.0;
39619 for (
unsigned i = 0;
i < 2;
i++)
39621 const double dist = initial_vertex_of_previous_segment[
i] -
39622 (*vector_vertex_node.begin())[
i];
39623 error += dist * dist;
39625 error = sqrt(error);
39634 double rev_error = 0.0;
39635 for (
unsigned i = 0;
i < 2;
i++)
39637 const double dist = initial_vertex_of_previous_segment[
i] -
39638 (*--vector_vertex_node.end())[
i];
39639 rev_error += dist * dist;
39641 rev_error = sqrt(rev_error);
39647 std::ostringstream error_stream;
39649 <<
"The distance between the first node of the current\n"
39650 <<
"line segment (boundary " << bound
39651 <<
") and either end of "
39652 <<
"the previous line segment\n"
39653 <<
"(boundary " << prev_seg_boundary_id
39654 <<
") is bigger than"
39655 <<
" the desired tolerance "
39658 <<
"This suggests that the polylines defining the "
39660 <<
"representation are not properly ordered.\n"
39661 <<
"Fail on last vertex of polyline: ("
39662 << prev_seg_boundary_id
39663 <<
") and\nfirst vertex of polyline (" << bound
39664 <<
").\nThis should have failed when first trying to "
39665 <<
"construct the\npolygon.\n";
39667 OOMPH_CURRENT_FUNCTION,
39668 OOMPH_EXCEPTION_LOCATION);
39675 std::reverse(vector_vertex_node.begin(),
39676 vector_vertex_node.end());
39689 std::ostringstream error_stream;
39691 <<
"The distance between the first node of the current\n"
39692 <<
"line segment (boundary " << bound
39693 <<
") and either end of "
39694 <<
"the previous line segment\n"
39695 <<
"(boundary " << prev_seg_boundary_id
39696 <<
") is bigger than the "
39697 <<
"desired tolerance "
39700 <<
"This suggests that the polylines defining the polygonal\n"
39701 <<
"representation are not properly ordered.\n"
39702 <<
"Fail on last vertex of polyline: ("
39703 << prev_seg_boundary_id <<
") and\nfirst vertex of polyline ("
39705 <<
"This should have failed when first trying to construct\n"
39706 <<
"the polygon.\n";
39708 OOMPH_CURRENT_FUNCTION,
39709 OOMPH_EXCEPTION_LOCATION);
39715 std::reverse(vector_vertex_node.begin(),
39716 vector_vertex_node.end());
39733 n_vertex = vector_vertex_node.size();
39745 double unrefinement_tolerance =
39749 double refinement_tolerance =
39760 #ifdef OOMPH_HAS_MPI
39763 if (this->is_mesh_distributed())
39769 this->copy_connection_information(open_curve_pt->
polyline_pt(cs),
39770 tmp_curve_section_pt);
39778 this->copy_connection_information(open_curve_pt->
polyline_pt(cs),
39779 tmp_curve_section_pt);
39785 bool delete_it_on_destructor =
false;
39787 std::set<TriangleMeshCurveSection*>::iterator it =
39790 if (it != this->Free_curve_section_pt.end())
39792 this->Free_curve_section_pt.erase(it);
39794 delete_it_on_destructor =
true;
39802 this->Boundary_curve_section_pt[bound] =
39805 if (delete_it_on_destructor)
39810 #ifdef OOMPH_HAS_MPI
39813 if (this->is_mesh_distributed() && nsub_boundaries == 1)
39816 this->Boundary_marked_as_shared_boundary[bound].clear();
39819 this->Boundary_marked_as_shared_boundary[bound].push_back(
39820 internal_to_shared_boundary[0]);
39824 else if (this->is_mesh_distributed() && nsub_boundaries > 1)
39830 this->Boundary_subpolylines[bound].clear();
39832 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
39835 this->Boundary_marked_as_shared_boundary[bound].clear();
39838 this->Boundary_marked_as_shared_boundary[bound].resize(nsub_boundaries);
39839 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
39848 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
39852 this->Boundary_marked_as_shared_boundary[bound][isub] =
39853 internal_to_shared_boundary[isub];
39863 sub_tmp_polyline_pt;
39864 this->copy_connection_information_to_sub_polylines(
39865 tmp_curve_section_pt, tmp_sub_curve_section_pt);
39875 delete mesh_geom_obj_pt;
39880 for (
unsigned p = 0; p < ncurve_section; p++)
39882 face_mesh_pt[p]->flush_node_storage();
39883 delete face_mesh_pt[p];
39886 return update_was_performed;
39889 #ifdef OOMPH_HAS_MPI
39894 template<
class ELEMENT>
39901 unsigned update_was_performed =
false;
39904 const unsigned n_polylines = vector_polyline_pt.size();
39905 for (
unsigned pp = 0; pp < n_polylines; pp++)
39908 const unsigned shd_bnd_id = vector_polyline_pt[pp]->boundary_id();
39911 const unsigned chunk = vector_polyline_pt[pp]->boundary_chunk();
39919 std::map<FiniteElement*, FiniteElement*> face_ele_pt_to_bulk_element_pt;
39928 const unsigned nshared_bound_ele =
39929 this->nshared_boundary_element(shd_bnd_id);
39933 for (
unsigned e = 0;
e < nshared_bound_ele;
e++)
39937 this->shared_boundary_element_pt(shd_bnd_id,
e);
39940 int face_index = this->face_index_at_shared_boundary(shd_bnd_id,
e);
39949 face_ele_pt_to_bulk_element_pt[face_ele_pt] = bulk_ele_pt;
39955 nonhalo_shared_face_ele_pt.push_back(face_ele_pt);
39960 halo_shared_face_ele_pt.push_back(face_ele_pt);
39970 std::map<FiniteElement*, bool> shared_face_done;
39973 const unsigned nnonhalo_face_shared_ele =
39974 nonhalo_shared_face_ele_pt.size();
39977 const unsigned nhalo_face_shared_ele = halo_shared_face_ele_pt.size();
39982 if (nshared_bound_ele / 2 != nnonhalo_face_shared_ele)
39984 std::ostringstream error_message;
39986 <<
"The number of shared boundary elements (" << nshared_bound_ele
39987 <<
") is not the double\nof the number of unsorted NONHALO shared "
39988 <<
"face boundary elements (" << nnonhalo_face_shared_ele <<
")\n"
39989 <<
"for the current boundary (" << shd_bnd_id <<
")\n\n";
39991 OOMPH_CURRENT_FUNCTION,
39992 OOMPH_EXCEPTION_LOCATION);
39997 if (nshared_bound_ele / 2 != nhalo_face_shared_ele)
39999 std::ostringstream error_message;
40001 <<
"The number of shared boundary elements (" << nshared_bound_ele
40002 <<
") is not the double\nof the number of unsorted HALO shared "
40003 <<
"face boundary elements (" << nhalo_face_shared_ele <<
")\n"
40004 <<
"for the current boundary (" << shd_bnd_id <<
")\n\n";
40006 OOMPH_CURRENT_FUNCTION,
40007 OOMPH_EXCEPTION_LOCATION);
40014 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
40017 FiniteElement* nonhalo_face_ele_pt = nonhalo_shared_face_ele_pt[inh];
40020 const unsigned nnodes_nh = nonhalo_face_ele_pt->
nnode();
40022 Node* nh_first_node_pt = nonhalo_face_ele_pt->
node_pt(0);
40023 Node* nh_last_node_pt = nonhalo_face_ele_pt->
node_pt(nnodes_nh - 1);
40027 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
40030 FiniteElement* halo_face_ele_pt = halo_shared_face_ele_pt[ih];
40033 if (!shared_face_done[halo_face_ele_pt])
40036 const unsigned nnodes_h = halo_face_ele_pt->
nnode();
40038 Node* h_first_node_pt = halo_face_ele_pt->
node_pt(0);
40039 Node* h_last_node_pt = halo_face_ele_pt->
node_pt(nnodes_h - 1);
40043 if (nh_first_node_pt == h_first_node_pt &&
40044 nh_last_node_pt == h_last_node_pt)
40051 face_ele_pt_to_bulk_element_pt[nonhalo_face_ele_pt];
40053 face_ele_pt_to_bulk_element_pt[halo_face_ele_pt];
40056 tmp_bulk_element_pt.push_back(nonhalo_bulk_ele_pt);
40057 tmp_bulk_element_pt.push_back(halo_bulk_ele_pt);
40060 unsorted_shared_bulk_ele_pt.push_back(tmp_bulk_element_pt);
40063 shared_face_done[nonhalo_face_ele_pt] =
true;
40064 shared_face_done[halo_face_ele_pt] =
true;
40070 else if (nh_first_node_pt == h_last_node_pt &&
40071 nh_last_node_pt == h_first_node_pt)
40078 face_ele_pt_to_bulk_element_pt[nonhalo_face_ele_pt];
40080 face_ele_pt_to_bulk_element_pt[halo_face_ele_pt];
40083 tmp_bulk_element_pt.push_back(nonhalo_bulk_ele_pt);
40084 tmp_bulk_element_pt.push_back(halo_bulk_ele_pt);
40087 unsorted_shared_bulk_ele_pt.push_back(tmp_bulk_element_pt);
40090 shared_face_done[nonhalo_face_ele_pt] =
true;
40091 shared_face_done[halo_face_ele_pt] =
true;
40113 const unsigned nunsorted_shared_bulk_ele =
40114 unsorted_shared_bulk_ele_pt.size();
40118 if (nshared_bound_ele / 2 != nunsorted_shared_bulk_ele)
40120 std::ostringstream error_message;
40122 <<
"The number of shared boundary elements (" << nshared_bound_ele
40123 <<
") is not the double\nof the number of unsorted shared bulk "
40124 <<
"boundary elements (" << nunsorted_shared_bulk_ele <<
")\n"
40125 <<
"for the current boundary (" << shd_bnd_id <<
")\n\n";
40127 OOMPH_CURRENT_FUNCTION,
40128 OOMPH_EXCEPTION_LOCATION);
40133 if ((nnonhalo_face_shared_ele + nhalo_face_shared_ele) !=
40134 shared_face_done.size())
40136 std::ostringstream error_message;
40137 error_message <<
"The number of DONE shared boundary face elements ("
40138 << shared_face_done.size()
40139 <<
") is not the same\n as the sum of"
40140 <<
"the nonhalo face shared boundary elements ("
40141 << nnonhalo_face_shared_ele
40142 <<
")\nand the halo face shared "
40143 <<
"boundary elements (" << nhalo_face_shared_ele
40145 <<
"current boundary (" << shd_bnd_id <<
")\n\n";
40147 OOMPH_CURRENT_FUNCTION,
40148 OOMPH_EXCEPTION_LOCATION);
40153 shared_face_done.clear();
40156 unsigned nsorted_face_ele = 0;
40160 std::list<Node*> sorted_nodes;
40163 std::list<FiniteElement*> sorted_shared_bound_elements_pt;
40166 FiniteElement* root_face_ele_pt = nonhalo_shared_face_ele_pt[0];
40167 nsorted_face_ele++;
40170 shared_face_done[root_face_ele_pt] =
true;
40173 const unsigned nnodes_root = root_face_ele_pt->
nnode();
40174 Node* first_node_pt = root_face_ele_pt->
node_pt(0);
40175 Node* last_node_pt = root_face_ele_pt->
node_pt(nnodes_root - 1);
40178 sorted_nodes.push_back(first_node_pt);
40179 sorted_nodes.push_back(last_node_pt);
40182 sorted_shared_bound_elements_pt.push_back(
40183 unsorted_shared_bulk_ele_pt[0][0]);
40184 sorted_shared_bound_elements_pt.push_back(
40185 unsorted_shared_bulk_ele_pt[0][1]);
40188 while (nsorted_face_ele < nnonhalo_face_shared_ele)
40191 bool node_added =
false;
40195 for (
unsigned iface = 1; iface < nnonhalo_face_shared_ele; iface++)
40198 nonhalo_shared_face_ele_pt[iface];
40201 if (!shared_face_done[tmp_shared_face_ele_pt])
40204 const unsigned tmp_nnodes = tmp_shared_face_ele_pt->
nnode();
40207 Node* left_node_pt = tmp_shared_face_ele_pt->
node_pt(0);
40208 Node* right_node_pt =
40209 tmp_shared_face_ele_pt->
node_pt(tmp_nnodes - 1);
40211 if (left_node_pt == first_node_pt)
40214 sorted_nodes.push_front(right_node_pt);
40215 first_node_pt = right_node_pt;
40219 sorted_shared_bound_elements_pt.push_front(
40220 unsorted_shared_bulk_ele_pt[iface][1]);
40221 sorted_shared_bound_elements_pt.push_front(
40222 unsorted_shared_bulk_ele_pt[iface][0]);
40224 else if (left_node_pt == last_node_pt)
40227 sorted_nodes.push_back(right_node_pt);
40228 last_node_pt = right_node_pt;
40232 sorted_shared_bound_elements_pt.push_back(
40233 unsorted_shared_bulk_ele_pt[iface][0]);
40234 sorted_shared_bound_elements_pt.push_back(
40235 unsorted_shared_bulk_ele_pt[iface][1]);
40237 else if (right_node_pt == first_node_pt)
40240 sorted_nodes.push_front(left_node_pt);
40241 first_node_pt = left_node_pt;
40245 sorted_shared_bound_elements_pt.push_front(
40246 unsorted_shared_bulk_ele_pt[iface][1]);
40247 sorted_shared_bound_elements_pt.push_front(
40248 unsorted_shared_bulk_ele_pt[iface][0]);
40250 else if (right_node_pt == last_node_pt)
40253 sorted_nodes.push_back(left_node_pt);
40254 last_node_pt = left_node_pt;
40258 sorted_shared_bound_elements_pt.push_back(
40259 unsorted_shared_bulk_ele_pt[iface][0]);
40260 sorted_shared_bound_elements_pt.push_back(
40261 unsorted_shared_bulk_ele_pt[iface][1]);
40268 shared_face_done[tmp_shared_face_ele_pt] =
true;
40269 nsorted_face_ele++;
40286 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
40288 delete nonhalo_shared_face_ele_pt[inh];
40289 nonhalo_shared_face_ele_pt[inh] = 0;
40293 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
40295 delete halo_shared_face_ele_pt[ih];
40296 halo_shared_face_ele_pt[ih] = 0;
40304 const unsigned n_nodes = sorted_nodes.size();
40310 unsigned counter = 0;
40311 for (std::list<Node*>::iterator it_nodes = sorted_nodes.begin();
40312 it_nodes != sorted_nodes.end();
40315 polyline_vertices[counter].resize(2);
40316 polyline_vertices[counter][0] = (*it_nodes)->x(0);
40317 polyline_vertices[counter][1] = (*it_nodes)->x(1);
40327 for (std::list<FiniteElement*>::iterator it_ele =
40328 sorted_shared_bound_elements_pt.begin();
40329 it_ele != sorted_shared_bound_elements_pt.end();
40332 sorted_shared_ele_pt.push_back((*it_ele));
40336 const unsigned n_shared_target_areas = sorted_shared_ele_pt.size();
40337 Vector<double> sorted_shared_target_areas(n_shared_target_areas);
40340 std::map<std::pair<GeneralisedElement*, unsigned>,
bool> shared_ele_done;
40343 unsigned count_found_shared_element = 0;
40346 const unsigned nele = this->nelement();
40350 for (
unsigned e = 0;
e < nele;
e++)
40355 for (
unsigned s = 0;
s < n_shared_target_areas;
s++)
40360 std::pair<GeneralisedElement*, unsigned> pair_gen_ele_idx =
40361 std::make_pair(current_shared_ele_pt,
s);
40362 if (!shared_ele_done[pair_gen_ele_idx])
40365 if (current_ele_pt == current_shared_ele_pt)
40368 sorted_shared_target_areas[
s] = target_areas[
e];
40370 shared_ele_done[pair_gen_ele_idx] =
true;
40372 count_found_shared_element++;
40378 if (count_found_shared_element == n_shared_target_areas)
40388 if (count_found_shared_element != n_shared_target_areas)
40390 std::ostringstream error_message;
40391 error_message <<
"The number of found target areas ("
40392 << count_found_shared_element
40393 <<
") is different from the "
40394 <<
"total number\nof target areas ("
40395 << n_shared_target_areas <<
") in shared boundary ("
40396 << shd_bnd_id <<
")\n\n";
40398 OOMPH_CURRENT_FUNCTION,
40399 OOMPH_EXCEPTION_LOCATION);
40404 const unsigned n_vertices = n_nodes;
40407 const unsigned n_segments = vector_polyline_pt[pp]->nsegment();
40416 if (n_segments != n_vertices - 1)
40418 std::ostringstream error_message;
40420 <<
"The number of segments from the current shared polyline "
40421 <<
"(" << n_segments <<
") does not\ncorrespond with the number of "
40422 <<
"sorted vertices (" << n_vertices - 1
40423 <<
") of the current shared\n"
40426 OOMPH_CURRENT_FUNCTION,
40427 OOMPH_EXCEPTION_LOCATION);
40432 if (n_segments != n_shared_target_areas / 2)
40434 std::ostringstream error_message;
40436 <<
"The number of segments for the current sorting of edges "
40437 <<
"(" << n_segments <<
") is different\nfrom the number of "
40438 <<
"target areas (" << n_shared_target_areas / 2 <<
")\n\n";
40440 OOMPH_CURRENT_FUNCTION,
40441 OOMPH_EXCEPTION_LOCATION);
40455 for (
unsigned s = 0;
s < n_segments;
s++)
40458 polyline_target_area[
s] =
40459 std::min(sorted_shared_target_areas[
s * 2],
40460 sorted_shared_target_areas[(
s * 2) + 1]);
40467 if (polyline_vertices[n_vertices - 1][1] < polyline_vertices[0][1])
40469 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
40470 std::reverse(polyline_target_area.begin(), polyline_target_area.end());
40472 else if (polyline_vertices[n_vertices - 1][1] == polyline_vertices[0][1])
40474 if (polyline_vertices[n_vertices - 1][0] < polyline_vertices[0][0])
40476 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
40477 std::reverse(polyline_target_area.begin(),
40478 polyline_target_area.end());
40484 bool unrefinement_applied =
false;
40487 if (n_vertices > 3)
40489 unrefinement_applied =
40490 unrefine_shared_boundary_constrained_by_target_area(
40491 shd_bnd_id, chunk, polyline_vertices, polyline_target_area);
40495 bool refinement_applied =
40496 refine_shared_boundary_constrained_by_target_area(polyline_vertices,
40497 polyline_target_area);
40500 update_was_performed |= (unrefinement_applied || refinement_applied);
40514 this->copy_connection_information(curve_section_pt, new_polyline_pt);
40519 bool delete_it_on_destructor =
false;
40523 std::set<TriangleMeshCurveSection*>::iterator it =
40524 this->Free_curve_section_pt.find(curve_section_pt);
40526 if (it != this->Free_curve_section_pt.end())
40528 this->Free_curve_section_pt.erase(it);
40529 delete curve_section_pt;
40530 delete_it_on_destructor =
true;
40534 vector_polyline_pt[pp] = new_polyline_pt;
40540 this->Boundary_curve_section_pt[shd_bnd_id] = new_curve_section_pt;
40542 if (delete_it_on_destructor)
40544 this->Free_curve_section_pt.insert(new_curve_section_pt);
40549 return update_was_performed;
40558 template<
class ELEMENT>
40564 double& unrefinement_tolerance,
40568 std::set<Vector<double>> no_delete_vertex;
40571 const bool boundary_receive_connections =
40572 this->boundary_connections(b, c, no_delete_vertex);
40576 bool unrefinement_applied =
false;
40579 if (!Do_boundary_unrefinement_constrained_by_target_areas)
40581 return unrefinement_applied;
40595 unsigned n_vertex = vector_bnd_vertices.size();
40598 const double constant_value = 4.0 / sqrt(3.0);
40604 for (
unsigned i = 1;
i < n_vertex - 1;
i += 2)
40606 if (area_constraint[
i - 1] > 0 && area_constraint[
i] > 0)
40608 const double local_zeta_first = vector_bnd_vertices[
i - 1][0];
40609 const double local_zeta_last = vector_bnd_vertices[
i + 1][0];
40610 const double local_length_zeta =
40611 std::fabs(local_zeta_last - local_zeta_first);
40613 const double x1 = vector_bnd_vertices[
i - 1][1];
40614 const double y1 = vector_bnd_vertices[
i - 1][2];
40615 const double x2 = vector_bnd_vertices[
i + 1][1];
40616 const double y2 = vector_bnd_vertices[
i + 1][2];
40617 const double local_length =
40618 sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
40620 const double x_m = vector_bnd_vertices[
i][1];
40621 const double y_m = vector_bnd_vertices[
i][2];
40623 const double average_area_constraint =
40624 (area_constraint[
i - 1] + area_constraint[
i]) / 2.0;
40628 const double length_side =
40629 sqrt(constant_value * average_area_constraint);
40631 const double length_side_zeta =
40632 (local_length_zeta * length_side) / local_length;
40635 if ((length_side_zeta / local_length_zeta) > 1.0)
40643 double a_x = vector_bnd_vertices[
i - 1][1];
40644 double a_y = vector_bnd_vertices[
i - 1][2];
40645 double b_x = vector_bnd_vertices[
i][1];
40646 double b_y = vector_bnd_vertices[
i][2];
40647 double c_x = vector_bnd_vertices[
i + 1][1];
40648 double c_y = vector_bnd_vertices[
i + 1][2];
40650 double a = b_x - a_x;
40651 double b = b_y - a_y;
40652 double c = c_x - a_x;
40653 double d = c_y - a_y;
40655 double e = a * (a_x + b_x) + b * (a_y + b_y);
40656 double f = c * (a_x + c_x) + d * (a_y + c_y);
40658 double g = 2.0 * (a * (c_y - b_y) - b * (c_x - b_x));
40660 bool do_it =
false;
40661 if (std::fabs(g) < 1.0e-14)
40667 double p_x = (d *
e - b * f) / g;
40668 double p_y = (a * f - c *
e) / g;
40670 double r = sqrt(pow((a_x - p_x), 2) + pow((a_y - p_y), 2));
40672 double rhalfca_x = 0.5 * (a_x - c_x);
40673 double rhalfca_y = 0.5 * (a_y - c_y);
40675 double halfca_squared = pow(rhalfca_x, 2) + pow(rhalfca_y, 2);
40677 double sticky_out_bit =
40678 r - sqrt(std::fabs((r * r) - halfca_squared));
40683 if ((sticky_out_bit / (2.0 * sqrt(halfca_squared))) <
40684 unrefinement_tolerance)
40692 if (do_it && boundary_receive_connections)
40696 no_delete_vertex.begin();
40697 it != no_delete_vertex.end();
40702 const double x = (*it)[0];
40703 const double y = (*it)[1];
40704 double error = (x_m - x) * (x_m - x) + (y_m - y) * (y_m - y);
40705 error = sqrt(error);
40721 vector_bnd_vertices[
i].resize(0);
40735 for (
unsigned i = 0;
i < n_vertex;
i++)
40738 if (vector_bnd_vertices[
i].size() != 0)
40740 compact_vector.push_back(vector_bnd_vertices[
i]);
40746 unsigned nsize_target = area_constraint.size();
40747 if (nsize_target == 1)
40750 compact_area_constraint.push_back(area_constraint[0]);
40754 for (
unsigned i = 1;
i < n_vertex;
i += 2)
40758 if (vector_bnd_vertices[
i].size() != 0)
40760 compact_area_constraint.push_back(area_constraint[
i - 1]);
40762 if (
i < nsize_target)
40764 compact_area_constraint.push_back(area_constraint[
i]);
40771 double new_area_constraint =
40772 (area_constraint[
i - 1] + area_constraint[
i]) / 2.0;
40773 compact_area_constraint.push_back(new_area_constraint);
40780 if (n_vertex != compact_vector.size())
40782 unrefinement_applied =
true;
40786 n_vertex = compact_vector.size();
40787 vector_bnd_vertices.resize(n_vertex);
40788 for (
unsigned i = 0;
i < n_vertex;
i++)
40790 vector_bnd_vertices[
i].resize(3);
40791 vector_bnd_vertices[
i][0] = compact_vector[
i][0];
40792 vector_bnd_vertices[
i][1] = compact_vector[
i][1];
40793 vector_bnd_vertices[
i][2] = compact_vector[
i][2];
40797 unsigned ntarget_areas = compact_area_constraint.size();
40798 area_constraint.resize(ntarget_areas);
40799 for (
unsigned i = 0;
i < ntarget_areas;
i++)
40801 area_constraint[
i] = compact_area_constraint[
i];
40806 return unrefinement_applied;
40814 template<
class ELEMENT>
40819 double& refinement_tolerance,
40824 bool refinement_applied =
false;
40827 if (!Do_boundary_refinement_constrained_by_target_areas)
40829 return refinement_applied;
40833 unsigned n_vertex = vector_bnd_vertices.size();
40836 const double constant_value = 4.0 / sqrt(3.0);
40846 for (
unsigned i = 0;
i < n_vertex - 1;
i++)
40849 new_vector.push_back(vector_bnd_vertices[
i]);
40851 if (area_constraint[
i] > 0)
40853 double local_zeta_first = vector_bnd_vertices[
i][0];
40854 double local_zeta_last = vector_bnd_vertices[
i + 1][0];
40855 const double local_length_zeta =
40856 std::fabs(local_zeta_last - local_zeta_first);
40861 if (local_zeta_first > local_zeta_last)
40863 const double tmp_zeta = local_zeta_first;
40864 local_zeta_first = local_zeta_last;
40865 local_zeta_last = tmp_zeta;
40868 const double x1 = vector_bnd_vertices[
i][1];
40869 const double y1 = vector_bnd_vertices[
i][2];
40870 const double x2 = vector_bnd_vertices[
i + 1][1];
40871 const double y2 = vector_bnd_vertices[
i + 1][2];
40872 const double local_length =
40873 sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
40876 const double length_side = sqrt(constant_value * area_constraint[
i]);
40877 const double length_side_zeta =
40878 (local_length_zeta * length_side) / local_length;
40881 const double n_seg_double = length_side_zeta / local_length_zeta;
40884 unsigned n_seg = 1;
40887 n_seg +=
static_cast<unsigned>(std::floor(1.0 / n_seg_double));
40894 double zeta_increment = (local_length_zeta) / ((
double)n_seg);
40898 for (
unsigned s = 1;
s < n_seg;
s++)
40901 zeta[0] = local_zeta_first + zeta_increment * double(
s);
40903 mesh_geom_obj_pt->
position(zeta, vertex);
40907 new_node[0] = zeta[0];
40908 new_node[1] = vertex[0];
40909 new_node[2] = vertex[1];
40912 new_vector.push_back(new_node);
40923 new_vector.push_back(vector_bnd_vertices[n_vertex - 1]);
40928 n_vertex = new_vector.size();
40929 if (n_vertex != vector_bnd_vertices.size())
40931 refinement_applied =
true;
40935 vector_bnd_vertices.resize(n_vertex);
40936 for (
unsigned i = 0;
i < n_vertex;
i++)
40938 vector_bnd_vertices[
i].resize(3);
40939 vector_bnd_vertices[
i][0] = new_vector[
i][0];
40940 vector_bnd_vertices[
i][1] = new_vector[
i][1];
40941 vector_bnd_vertices[
i][2] = new_vector[
i][2];
40946 return refinement_applied;
40956 template<
class ELEMENT>
40965 std::set<Vector<double>> no_delete_vertex;
40968 const bool boundary_receive_connections =
40969 this->boundary_connections(b, c, no_delete_vertex);
40973 bool unrefinement_applied =
false;
40976 if (!Do_shared_boundary_unrefinement_constrained_by_target_areas)
40978 return unrefinement_applied;
40994 unsigned n_vertex = vector_bnd_vertices.size();
40997 const double constant_value = 4.0 / sqrt(3.0);
41003 for (
unsigned i = 1;
i < n_vertex - 1;
i += 2)
41007 if (area_constraint[
i - 1] > 0 && area_constraint[
i] > 0)
41010 const double x1 = vector_bnd_vertices[
i - 1][0];
41011 const double y1 = vector_bnd_vertices[
i - 1][1];
41013 const double x2 = vector_bnd_vertices[
i + 1][0];
41014 const double y2 = vector_bnd_vertices[
i + 1][1];
41017 const double local_length =
41018 sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
41021 const double x_m = vector_bnd_vertices[
i][0];
41022 const double y_m = vector_bnd_vertices[
i][1];
41025 const double average_area_constraint =
41026 (area_constraint[
i - 1] + area_constraint[
i]) / 2.0;
41030 const double length_side =
41031 sqrt(constant_value * average_area_constraint);
41034 if ((length_side / local_length) > 1.0)
41040 if (do_it && boundary_receive_connections)
41044 no_delete_vertex.begin();
41045 it != no_delete_vertex.end();
41050 const double x = (*it)[0];
41051 const double y = (*it)[1];
41052 double error = (x_m - x) * (x_m - x) + (y_m - y) * (y_m - y);
41053 error = sqrt(error);
41069 vector_bnd_vertices[
i].resize(0);
41085 for (
unsigned i = 0;
i < n_vertex;
i++)
41088 if (vector_bnd_vertices[
i].size() != 0)
41090 compact_vector.push_back(vector_bnd_vertices[
i]);
41096 unsigned n_area_constraint = area_constraint.size();
41097 if (n_area_constraint == 1)
41100 compact_area_constraint.push_back(area_constraint[0]);
41104 for (
unsigned i = 1;
i < n_vertex;
i += 2)
41108 if (vector_bnd_vertices[
i].size() != 0)
41110 compact_area_constraint.push_back(area_constraint[
i - 1]);
41112 if (
i < n_area_constraint)
41114 compact_area_constraint.push_back(area_constraint[
i]);
41121 const double new_area_constraint =
41122 (area_constraint[
i - 1] + area_constraint[
i]) / 2.0;
41123 compact_area_constraint.push_back(new_area_constraint);
41130 if (n_vertex != compact_vector.size())
41132 unrefinement_applied =
true;
41136 n_vertex = compact_vector.size();
41137 vector_bnd_vertices.resize(n_vertex);
41138 for (
unsigned i = 0;
i < n_vertex;
i++)
41140 vector_bnd_vertices[
i].resize(2);
41141 vector_bnd_vertices[
i][0] = compact_vector[
i][0];
41142 vector_bnd_vertices[
i][1] = compact_vector[
i][1];
41146 unsigned ntarget_areas = compact_area_constraint.size();
41147 area_constraint.resize(ntarget_areas);
41148 for (
unsigned i = 0;
i < ntarget_areas;
i++)
41150 area_constraint[
i] = compact_area_constraint[
i];
41155 return unrefinement_applied;
41165 template<
class ELEMENT>
41173 bool refinement_applied =
false;
41176 if (!Do_shared_boundary_refinement_constrained_by_target_areas)
41178 return refinement_applied;
41182 unsigned nsegments = vector_bnd_vertices.size() - 1;
41189 const double constant_value = 4.0 / sqrt(3.0);
41191 for (
unsigned s = 0;
s < nsegments;
s++)
41197 const double x1 = left_vertex[0];
41198 const double y1 = left_vertex[1];
41199 const double x2 = right_vertex[0];
41200 const double y2 = right_vertex[1];
41203 const double segment_length =
41204 sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
41207 const double new_segment_length =
41208 sqrt(constant_value * area_constraint[
s]);
41211 const double n_seg_double = new_segment_length / segment_length;
41216 nseg +=
static_cast<unsigned>(std::floor(1.0 / n_seg_double));
41220 tmp_bnd_vertices.push_back(left_vertex);
41227 double incrementx = (right_vertex[0] - left_vertex[0]) / (
double)(nseg);
41228 double incrementy = (right_vertex[1] - left_vertex[1]) / (
double)(nseg);
41229 for (
unsigned i = 1;
i < nseg;
i++)
41232 tmp_vertex[0] = left_vertex[0] + incrementx *
i;
41233 tmp_vertex[1] = left_vertex[1] + incrementy *
i;
41234 tmp_bnd_vertices.push_back(tmp_vertex);
41242 tmp_bnd_vertices.push_back(vector_bnd_vertices[nsegments]);
41247 nsegments = tmp_bnd_vertices.size() - 1;
41248 if (nsegments != vector_bnd_vertices.size() - 1)
41250 refinement_applied =
true;
41253 vector_bnd_vertices.resize(nsegments + 1);
41254 for (
unsigned i = 0;
i < nsegments + 1;
i++)
41256 vector_bnd_vertices[
i].resize(2);
41257 vector_bnd_vertices[
i][0] = tmp_bnd_vertices[
i][0];
41258 vector_bnd_vertices[
i][1] = tmp_bnd_vertices[
i][1];
41262 return refinement_applied;
41268 template<
class ELEMENT>
41279 get_face_mesh_representation(polygon_pt, face_mesh_pt);
41287 const unsigned n_polyline = polygon_pt->
npolyline();
41290 for (
unsigned p = 0; p < n_polyline; p++)
41304 std::set<Vector<double>> vertex_nodes;
41315 #ifdef OOMPH_HAS_MPI
41342 const unsigned nface_element = face_mesh_pt[p]->nelement();
41348 std::map<FiniteElement*, unsigned> face_element_index_on_boundary;
41350 for (
unsigned ef = 0; ef < nface_element; ++ef)
41352 FiniteElement* ele_face_pt = face_mesh_pt[p]->finite_element_pt(ef);
41354 #ifdef OOMPH_HAS_MPI
41355 if (this->is_mesh_distributed())
41365 non_halo_face_element_pt.push_back(ele_face_pt);
41366 face_element_index_on_boundary[ele_face_pt] = ef;
41370 const unsigned nnon_halo_face_element = non_halo_face_element_pt.size();
41373 std::map<FiniteElement*, bool> face_element_done;
41376 unsigned nsorted_face_elements = 0;
41378 #ifdef OOMPH_HAS_MPI
41380 unsigned nsub_boundaries = 0;
41385 while (nsorted_face_elements < nnon_halo_face_element)
41390 bool found_initial_face_element =
false;
41393 unsigned iface = 0;
41394 for (iface = 0; iface < nnon_halo_face_element; iface++)
41396 ele_face_pt = non_halo_face_element_pt[iface];
41398 if (!face_element_done[ele_face_pt])
41401 found_initial_face_element =
true;
41403 nsorted_face_elements++;
41410 if (!found_initial_face_element)
41412 std::ostringstream error_message;
41413 error_message <<
"Could not find an initial face element for the "
41414 "current segment\n";
41417 error_message.str(),
41418 "RefineableTriangleMesh::update_polygon_after_restart()",
41419 OOMPH_EXCEPTION_LOCATION);
41426 std::set<Vector<double>> local_vertex_nodes;
41438 unsigned nnode = ele_face_pt->
nnode();
41442 vertex_coord[0] = bound_left[0];
41445 for (
unsigned i = 0;
i < 2;
i++)
41447 vertex_coord[
i + 1] = ele_face_pt->
node_pt(0)->
x(
i);
41449 local_vertex_nodes.insert(vertex_coord);
41454 bound, bound_right);
41455 vertex_coord[0] = bound_right[0];
41458 for (
unsigned i = 0;
i < 2;
i++)
41460 vertex_coord[
i + 1] = ele_face_pt->
node_pt(nnode - 1)->
x(
i);
41462 local_vertex_nodes.insert(vertex_coord);
41466 Node* last_node_pt = ele_face_pt->
node_pt(nnode - 1);
41469 face_element_done[ele_face_pt] =
true;
41477 bool face_element_added =
false;
41486 for (
unsigned iiface = iface; iiface < nnon_halo_face_element;
41489 face_element_added =
false;
41490 ele_face_pt = non_halo_face_element_pt[iiface];
41491 if (!face_element_done[ele_face_pt])
41494 nnode = ele_face_pt->nnode();
41495 Node* left_node_pt = ele_face_pt->node_pt(0);
41496 Node* right_node_pt = ele_face_pt->node_pt(nnode - 1);
41498 if (left_node_pt == first_node_pt)
41500 first_node_pt = right_node_pt;
41501 face_element_added =
true;
41503 else if (left_node_pt == last_node_pt)
41505 last_node_pt = right_node_pt;
41506 face_element_added =
true;
41508 else if (right_node_pt == first_node_pt)
41510 first_node_pt = left_node_pt;
41511 face_element_added =
true;
41513 else if (right_node_pt == last_node_pt)
41515 last_node_pt = left_node_pt;
41516 face_element_added =
true;
41519 if (face_element_added)
41524 vertex_coord[0] = bound_left[0];
41527 for (
unsigned i = 0;
i < 2;
i++)
41529 vertex_coord[
i + 1] = left_node_pt->
x(
i);
41531 local_vertex_nodes.insert(vertex_coord);
41536 vertex_coord[0] = bound_right[0];
41539 for (
unsigned i = 0;
i < 2;
i++)
41541 vertex_coord[
i + 1] = right_node_pt->
x(
i);
41543 local_vertex_nodes.insert(vertex_coord);
41547 face_element_done[ele_face_pt] =
true;
41548 nsorted_face_elements++;
41555 }
while (face_element_added &&
41556 (nsorted_face_elements < nnon_halo_face_element));
41564 const unsigned nlocal_nodes = local_vertex_nodes.size();
41566 local_tmp_vector_vertex_node.resize(nlocal_nodes);
41569 unsigned counter = 0;
41570 std::set<Vector<double>>::iterator it_vertex;
41571 for (it_vertex = local_vertex_nodes.begin();
41572 it_vertex != local_vertex_nodes.end();
41575 local_tmp_vector_vertex_node[counter].resize(3);
41576 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
41577 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
41578 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
41589 local_vertex_nodes.clear();
41594 unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
41595 for (
unsigned i = 0;
i < nnew_nodes;
i++)
41597 vertex_coord[0] = local_tmp_vector_vertex_node[
i][0];
41598 vertex_coord[1] = local_tmp_vector_vertex_node[
i][1];
41599 vertex_coord[2] = local_tmp_vector_vertex_node[
i][2];
41600 vertex_nodes.insert(vertex_coord);
41601 local_vertex_nodes.insert(vertex_coord);
41604 #ifdef OOMPH_HAS_MPI
41605 if (this->is_mesh_distributed())
41609 sub_vertex_nodes.push_back(local_vertex_nodes);
41618 unsigned npoly_vertex = vertex_nodes.size();
41619 tmp_vector_vertex_node.resize(npoly_vertex);
41620 unsigned count = 0;
41621 std::set<Vector<double>>::iterator it;
41622 for (it = vertex_nodes.begin(); it != vertex_nodes.end(); ++it)
41624 tmp_vector_vertex_node[count].resize(3);
41625 tmp_vector_vertex_node[count][0] = (*it)[0];
41626 tmp_vector_vertex_node[count][1] = (*it)[1];
41627 tmp_vector_vertex_node[count][2] = (*it)[2];
41631 #ifdef OOMPH_HAS_MPI
41634 unsigned nsub_boundaries_set = sub_vertex_nodes.size();
41635 if (nsub_boundaries_set != nsub_boundaries)
41637 std::ostringstream error_message;
41639 <<
"The number of found sub-boundaries and the number of counted\n"
41640 <<
"sub-boundaries are different:\n"
41641 <<
"Number of found sub-boundaries: (" << nsub_boundaries_set <<
")\n"
41642 <<
"Number of counted sub-boundaries: (" << nsub_boundaries <<
")\n";
41644 error_message.str(),
41645 "RefineableTriangleMesh::update_polygon_after_restart()",
41646 OOMPH_EXCEPTION_LOCATION);
41651 if (this->is_mesh_distributed() && nsub_boundaries > 1)
41654 this->Boundary_was_splitted[bound] =
true;
41656 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
41657 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
41660 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
41661 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
41662 unsigned subcount = 0;
41663 std::set<Vector<double>>::iterator subit;
41664 for (subit = sub_vertex_nodes[isub].begin();
41665 subit != sub_vertex_nodes[isub].end();
41668 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
41669 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
41670 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
41671 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
41682 unsigned n_vertex = tmp_vector_vertex_node.size();
41685 vector_vertex_node.resize(n_vertex);
41686 for (
unsigned i = 0;
i < n_vertex;
i++)
41688 vector_vertex_node[
i].resize(2);
41689 vector_vertex_node[
i][0] = tmp_vector_vertex_node[
i][1];
41690 vector_vertex_node[
i][1] = tmp_vector_vertex_node[
i][2];
41693 #ifdef OOMPH_HAS_MPI
41696 if (this->is_mesh_distributed() && nsub_boundaries > 1)
41701 sub_vector_vertex_node.resize(nsub_boundaries);
41702 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
41704 const unsigned subn_vertex = sub_tmp_vector_vertex_node[isub].size();
41706 sub_vector_vertex_node[isub].resize(subn_vertex);
41707 for (
unsigned i = 0;
i < subn_vertex;
i++)
41709 sub_vector_vertex_node[isub][
i].resize(2);
41710 sub_vector_vertex_node[isub][
i][0] =
41711 sub_tmp_vector_vertex_node[isub][
i][1];
41712 sub_vector_vertex_node[isub][
i][1] =
41713 sub_tmp_vector_vertex_node[isub][
i][2];
41728 #ifdef OOMPH_HAS_MPI
41732 if (!this->is_mesh_distributed())
41739 unsigned n_prev_vertex =
41741 final_vertex_of_previous_segment =
41745 unsigned prev_seg_boundary_id =
41750 double error = 0.0;
41751 for (
unsigned i = 0;
i < 2;
i++)
41753 const double dist = final_vertex_of_previous_segment[
i] -
41754 (*vector_vertex_node.begin())[
i];
41755 error += dist * dist;
41757 error = sqrt(error);
41765 double rev_error = 0.0;
41766 for (
unsigned i = 0;
i < 2;
i++)
41768 const double dist = final_vertex_of_previous_segment[
i] -
41769 (*--vector_vertex_node.end())[
i];
41770 rev_error += dist * dist;
41772 rev_error = sqrt(rev_error);
41786 initial_vertex_of_previous_segment =
41789 unsigned prev_seg_boundary_id =
41794 double error = 0.0;
41795 for (
unsigned i = 0;
i < 2;
i++)
41797 const double dist = initial_vertex_of_previous_segment[
i] -
41798 (*vector_vertex_node.begin())[
i];
41799 error += dist * dist;
41801 error = sqrt(error);
41810 double rev_error = 0.0;
41811 for (
unsigned i = 0;
i < 2;
i++)
41813 const double dist = initial_vertex_of_previous_segment[
i] -
41814 (*--vector_vertex_node.end())[
i];
41815 rev_error += dist * dist;
41824 std::ostringstream error_stream;
41826 <<
"The distance between the first node of the current\n"
41827 <<
"line segment (boundary " << bound
41828 <<
") and either end of "
41829 <<
"the previous line segment\n"
41830 <<
"(boundary " << prev_seg_boundary_id
41831 <<
") is bigger than "
41832 <<
"the desired tolerance "
41835 <<
"This suggests that the polylines defining the "
41837 <<
"representation are not properly ordered.\n"
41838 <<
"Fail on last vertex of polyline: ("
41839 << prev_seg_boundary_id
41840 <<
") and\nfirst vertex of polyline (" << bound
41841 <<
").\nThis should have failed when first trying to"
41842 <<
" construct the\npolygon.\n";
41844 error_stream.str(),
41845 "RefineableTriangleMesh::update_polygon_after_restart()",
41846 OOMPH_EXCEPTION_LOCATION);
41853 std::reverse(vector_vertex_node.begin(),
41854 vector_vertex_node.end());
41867 std::ostringstream error_stream;
41869 <<
"The distance between the first node of the current\n"
41870 <<
"line segment (boundary " << bound
41871 <<
") and either end of "
41872 <<
"the previous line segment\n"
41873 <<
"(boundary " << prev_seg_boundary_id
41874 <<
") is bigger than the "
41875 <<
"desired tolerance "
41878 <<
"This suggests that the polylines defining the polygonal\n"
41879 <<
"representation are not properly ordered.\n"
41880 <<
"Fail on last vertex of polyline: ("
41881 << prev_seg_boundary_id <<
") and\nfirst vertex of polyline ("
41883 <<
"This should have failed when first trying to construct "
41887 error_stream.str(),
41888 "RefineableTriangleMesh::update_polygon_after_restart()",
41889 OOMPH_EXCEPTION_LOCATION);
41895 std::reverse(vector_vertex_node.begin(),
41896 vector_vertex_node.end());
41911 n_vertex = vector_vertex_node.size();
41931 double unrefinement_tolerance =
41935 double refinement_tolerance =
41950 this->copy_connection_information(polygon_pt->
polyline_pt(p),
41951 tmp_curve_section_pt);
41957 bool delete_it_on_destructor =
false;
41959 std::set<TriangleMeshCurveSection*>::iterator it =
41962 if (it != this->Free_curve_section_pt.end())
41964 this->Free_curve_section_pt.erase(it);
41966 delete_it_on_destructor =
true;
41974 this->Boundary_curve_section_pt[bound] =
41977 if (delete_it_on_destructor)
41982 #ifdef OOMPH_HAS_MPI
41985 if (this->is_mesh_distributed() && nsub_boundaries > 1)
41990 this->Boundary_subpolylines[bound].clear();
41992 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
41993 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
41999 sub_vector_vertex_node[isub], bound, isub);
42003 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
42021 delete mesh_geom_obj_pt;
42026 for (
unsigned p = 0; p < n_polyline; p++)
42028 face_mesh_pt[p]->flush_node_storage();
42029 delete face_mesh_pt[p];
42037 template<
class ELEMENT>
42048 get_face_mesh_representation(open_curve_pt, face_mesh_pt);
42056 const unsigned ncurve_section = open_curve_pt->
ncurve_section();
42058 for (
unsigned cs = 0; cs < ncurve_section; cs++)
42079 const unsigned nface_element = face_mesh_pt[cs]->nelement();
42086 std::map<FiniteElement*, unsigned> face_element_index_on_boundary;
42089 std::map<FiniteElement*, bool> face_element_done;
42091 for (
unsigned ef = 0; ef < nface_element; ++ef)
42093 FiniteElement* ele_face_pt = face_mesh_pt[cs]->finite_element_pt(ef);
42098 #ifdef OOMPH_HAS_MPI
42099 if (this->is_mesh_distributed())
42110 if (!face_element_done[ele_face_pt])
42115 non_halo_doubled_face_element_pt.push_back(ele_face_pt);
42117 face_element_index_on_boundary[ele_face_pt] = ef;
42119 face_element_done[ele_face_pt] =
true;
42121 const unsigned nnodes = ele_face_pt->
nnode();
42125 Node* right_node_pt = ele_face_pt->
node_pt(nnodes - 1);
42130 bool found_other_side_face_ele =
false;
42132 for (
unsigned iface = 0; iface < nface_element; iface++)
42136 face_mesh_pt[cs]->finite_element_pt(iface);
42138 if (!face_element_done[cele_face_pt])
42141 Node* cright_node_pt = cele_face_pt->
node_pt(nnodes - 1);
42144 if ((left_node_pt == cleft_node_pt &&
42145 right_node_pt == cright_node_pt) ||
42146 (left_node_pt == cright_node_pt &&
42147 right_node_pt == cleft_node_pt))
42150 non_halo_doubled_face_element_pt.push_back(cele_face_pt);
42152 face_element_done[cele_face_pt] =
true;
42154 face_element_index_on_boundary[cele_face_pt] = iface;
42157 found_other_side_face_ele =
true;
42165 if (!found_other_side_face_ele)
42167 std::ostringstream error_message;
42169 <<
"The face element at the other side of the boundary (" << bound
42170 <<
") was not found!!\n"
42171 <<
"These are the nodes of the face element:\n"
42172 <<
"(" << left_node_pt->
x(0) <<
", " << left_node_pt->
x(1) <<
") "
42173 <<
"and (" << right_node_pt->
x(0) <<
"," << right_node_pt->
x(1)
42176 error_message.str(),
42177 "RefineableTriangleMesh::update_open_curve_after_restart()",
42178 OOMPH_EXCEPTION_LOCATION);
42187 face_element_done.clear();
42192 std::set<Vector<double>> vertex_nodes;
42203 #ifdef OOMPH_HAS_MPI
42208 std::vector<bool> internal_to_shared_boundary;
42233 unsigned nsorted_face_elements = 0;
42235 #ifdef OOMPH_HAS_MPI
42237 unsigned nsub_boundaries = 0;
42241 const unsigned nnon_halo_doubled_face_ele =
42242 non_halo_doubled_face_element_pt.size();
42246 while (nsorted_face_elements < nnon_halo_doubled_face_ele)
42252 bool found_initial_face_element =
false;
42258 bool both_root_face_elements_are_nonhalo =
false;
42260 unsigned iface = 0;
42261 for (iface = 0; iface < nnon_halo_doubled_face_ele; iface += 2)
42263 ele_face_pt = non_halo_doubled_face_element_pt[iface];
42265 if (!face_element_done[ele_face_pt])
42268 face_element_done[ele_face_pt] =
true;
42270 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iface + 1];
42272 face_element_done[repeated_ele_face_pt] =
true;
42274 #ifdef OOMPH_HAS_MPI
42275 if (!repeated_ele_face_pt->
is_halo())
42277 both_root_face_elements_are_nonhalo =
true;
42283 nsorted_face_elements += 2;
42287 found_initial_face_element =
true;
42294 if (!found_initial_face_element)
42296 std::ostringstream error_message;
42297 error_message <<
"Could not find an initial face element for the "
42298 "current segment\n";
42301 OOMPH_CURRENT_FUNCTION,
42302 OOMPH_EXCEPTION_LOCATION);
42309 std::set<Vector<double>> local_vertex_nodes;
42321 const unsigned nnode = ele_face_pt->
nnode();
42325 vertex_coord[0] = bound_left[0];
42328 for (
unsigned i = 0;
i < 2;
i++)
42330 vertex_coord[
i + 1] = ele_face_pt->
node_pt(0)->
x(
i);
42332 local_vertex_nodes.insert(vertex_coord);
42337 bound, bound_right);
42338 vertex_coord[0] = bound_right[0];
42341 for (
unsigned i = 0;
i < 2;
i++)
42343 vertex_coord[
i + 1] = ele_face_pt->
node_pt(nnode - 1)->
x(
i);
42345 local_vertex_nodes.insert(vertex_coord);
42349 Node* last_node_pt = ele_face_pt->
node_pt(nnode - 1);
42353 bool face_element_added =
false;
42363 for (
unsigned iiface = iface; iiface < nnon_halo_doubled_face_ele;
42366 face_element_added =
false;
42367 ele_face_pt = non_halo_doubled_face_element_pt[iiface];
42374 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iiface + 1];
42375 bool both_face_elements_are_nonhalo =
false;
42377 #ifdef OOMPH_HAS_MPI
42378 if (!repeated_ele_face_pt->
is_halo())
42380 both_face_elements_are_nonhalo =
true;
42384 if (!face_element_done[ele_face_pt] &&
42385 (both_face_elements_are_nonhalo ==
42386 both_root_face_elements_are_nonhalo))
42389 const unsigned nlnode = ele_face_pt->
nnode();
42391 Node* right_node_pt = ele_face_pt->
node_pt(nlnode - 1);
42393 if (left_node_pt == first_node_pt)
42395 first_node_pt = right_node_pt;
42396 face_element_added =
true;
42398 else if (left_node_pt == last_node_pt)
42400 last_node_pt = right_node_pt;
42401 face_element_added =
true;
42403 else if (right_node_pt == first_node_pt)
42405 first_node_pt = left_node_pt;
42406 face_element_added =
true;
42408 else if (right_node_pt == last_node_pt)
42410 last_node_pt = left_node_pt;
42411 face_element_added =
true;
42414 if (face_element_added)
42419 vertex_coord[0] = bound_left[0];
42422 for (
unsigned i = 0;
i < 2;
i++)
42424 vertex_coord[
i + 1] = left_node_pt->
x(
i);
42426 local_vertex_nodes.insert(vertex_coord);
42431 vertex_coord[0] = bound_right[0];
42434 for (
unsigned i = 0;
i < 2;
i++)
42436 vertex_coord[
i + 1] = right_node_pt->
x(
i);
42438 local_vertex_nodes.insert(vertex_coord);
42442 face_element_done[ele_face_pt] =
true;
42445 repeated_ele_face_pt =
42446 non_halo_doubled_face_element_pt[iiface + 1];
42447 face_element_done[repeated_ele_face_pt] =
true;
42449 nsorted_face_elements += 2;
42456 }
while (face_element_added &&
42457 (nsorted_face_elements < nnon_halo_doubled_face_ele));
42465 const unsigned nlocal_nodes = local_vertex_nodes.size();
42467 local_tmp_vector_vertex_node.resize(nlocal_nodes);
42470 unsigned counter = 0;
42471 std::set<Vector<double>>::iterator it_vertex;
42472 for (it_vertex = local_vertex_nodes.begin();
42473 it_vertex != local_vertex_nodes.end();
42476 local_tmp_vector_vertex_node[counter].resize(3);
42477 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
42478 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
42479 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
42486 if (local_tmp_vector_vertex_node[nlocal_nodes - 1][2] <
42487 local_tmp_vector_vertex_node[0][2])
42489 std::reverse(local_tmp_vector_vertex_node.begin(),
42490 local_tmp_vector_vertex_node.end());
42492 else if (local_tmp_vector_vertex_node[nlocal_nodes - 1][2] ==
42493 local_tmp_vector_vertex_node[0][2])
42495 if (local_tmp_vector_vertex_node[nlocal_nodes - 1][1] <
42496 local_tmp_vector_vertex_node[0][1])
42498 std::reverse(local_tmp_vector_vertex_node.begin(),
42499 local_tmp_vector_vertex_node.end());
42510 local_vertex_nodes.clear();
42515 const unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
42516 for (
unsigned i = 0;
i < nnew_nodes;
i++)
42518 vertex_coord[0] = local_tmp_vector_vertex_node[
i][0];
42519 vertex_coord[1] = local_tmp_vector_vertex_node[
i][1];
42520 vertex_coord[2] = local_tmp_vector_vertex_node[
i][2];
42521 vertex_nodes.insert(vertex_coord);
42522 local_vertex_nodes.insert(vertex_coord);
42525 #ifdef OOMPH_HAS_MPI
42526 if (this->is_mesh_distributed())
42531 sub_vertex_nodes.push_back(local_vertex_nodes);
42537 if (both_root_face_elements_are_nonhalo)
42539 internal_to_shared_boundary.push_back(
false);
42543 internal_to_shared_boundary.push_back(
true);
42554 const unsigned npoly_vertex = vertex_nodes.size();
42555 tmp_vector_vertex_node.resize(npoly_vertex);
42556 unsigned count = 0;
42557 std::set<Vector<double>>::iterator it;
42558 for (it = vertex_nodes.begin(); it != vertex_nodes.end(); ++it)
42560 tmp_vector_vertex_node[count].resize(3);
42561 tmp_vector_vertex_node[count][0] = (*it)[0];
42562 tmp_vector_vertex_node[count][1] = (*it)[1];
42563 tmp_vector_vertex_node[count][2] = (*it)[2];
42567 #ifdef OOMPH_HAS_MPI
42572 const unsigned nsub_boundaries_set = sub_vertex_nodes.size();
42573 const unsigned ninternal_to_shared_boundaries =
42574 internal_to_shared_boundary.size();
42575 if (nsub_boundaries_set != ninternal_to_shared_boundaries)
42577 std::ostringstream error_message;
42579 <<
"The number of found sub-boundaries and the number of marked "
42580 <<
"internal\nboundaries are different\n"
42581 <<
"Number of found sub-boundaries: (" << nsub_boundaries_set <<
")\n"
42582 <<
"Number of marked internal boundaries: ("
42583 << ninternal_to_shared_boundaries <<
")\n\n";
42585 error_message.str(),
42586 "RefineableTriangleMesh::update_open_curve_after_restart()",
42587 OOMPH_EXCEPTION_LOCATION);
42593 if (nsub_boundaries_set != nsub_boundaries)
42595 std::ostringstream error_message;
42597 <<
"The number of found sub-boundaries and the number of counted\n"
42598 <<
"sub-boundaries are different:\n"
42599 <<
"Number of found sub-boundaries: (" << nsub_boundaries_set <<
")\n"
42600 <<
"Number of counted sub-boundaries: (" << nsub_boundaries
42603 error_message.str(),
42604 "RefineableTriangleMesh::update_open_curve_after_restart()",
42605 OOMPH_EXCEPTION_LOCATION);
42610 if (this->is_mesh_distributed() && nsub_boundaries > 1)
42613 this->Boundary_was_splitted[bound] =
true;
42615 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
42616 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
42619 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
42620 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
42621 unsigned subcount = 0;
42622 std::set<Vector<double>>::iterator subit;
42623 for (subit = sub_vertex_nodes[isub].begin();
42624 subit != sub_vertex_nodes[isub].end();
42627 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
42628 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
42629 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
42630 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
42640 unsigned n_vertex = tmp_vector_vertex_node.size();
42643 vector_vertex_node.resize(n_vertex);
42644 for (
unsigned i = 0;
i < n_vertex;
i++)
42646 vector_vertex_node[
i].resize(2);
42647 vector_vertex_node[
i][0] = tmp_vector_vertex_node[
i][1];
42648 vector_vertex_node[
i][1] = tmp_vector_vertex_node[
i][2];
42651 #ifdef OOMPH_HAS_MPI
42654 if (this->is_mesh_distributed() && nsub_boundaries > 1)
42659 sub_vector_vertex_node.resize(nsub_boundaries);
42660 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
42662 const unsigned subn_vertex = sub_tmp_vector_vertex_node[isub].size();
42664 sub_vector_vertex_node[isub].resize(subn_vertex);
42665 for (
unsigned i = 0;
i < subn_vertex;
i++)
42667 sub_vector_vertex_node[isub][
i].resize(2);
42668 sub_vector_vertex_node[isub][
i][0] =
42669 sub_tmp_vector_vertex_node[isub][
i][1];
42670 sub_vector_vertex_node[isub][
i][1] =
42671 sub_tmp_vector_vertex_node[isub][
i][2];
42686 #ifdef OOMPH_HAS_MPI
42690 if (!this->is_mesh_distributed())
42697 unsigned n_prev_vertex =
42699 final_vertex_of_previous_segment =
42701 n_prev_vertex - 1);
42703 unsigned prev_seg_boundary_id =
42708 double error = 0.0;
42709 for (
unsigned i = 0;
i < 2;
i++)
42711 const double dist = final_vertex_of_previous_segment[
i] -
42712 (*vector_vertex_node.begin())[
i];
42713 error += dist * dist;
42715 error = sqrt(error);
42723 double rev_error = 0.0;
42724 for (
unsigned i = 0;
i < 2;
i++)
42726 const double dist = final_vertex_of_previous_segment[
i] -
42727 (*--vector_vertex_node.end())[
i];
42728 rev_error += dist * dist;
42730 rev_error = sqrt(rev_error);
42744 initial_vertex_of_previous_segment =
42747 unsigned prev_seg_boundary_id =
42752 double error = 0.0;
42753 for (
unsigned i = 0;
i < 2;
i++)
42755 const double dist = initial_vertex_of_previous_segment[
i] -
42756 (*vector_vertex_node.begin())[
i];
42757 error += dist * dist;
42759 error = sqrt(error);
42768 double rev_error = 0.0;
42769 for (
unsigned i = 0;
i < 2;
i++)
42771 const double dist = initial_vertex_of_previous_segment[
i] -
42772 (*--vector_vertex_node.end())[
i];
42773 rev_error += dist * dist;
42775 rev_error = sqrt(rev_error);
42781 std::ostringstream error_stream;
42783 <<
"The distance between the first node of the current\n"
42784 <<
"line segment (boundary " << bound
42785 <<
") and either end of "
42786 <<
"the previous line segment\n"
42787 <<
"(boundary " << prev_seg_boundary_id
42788 <<
") is bigger than"
42789 <<
" the desired tolerance "
42792 <<
"This suggests that the polylines defining the "
42794 <<
"representation are not properly ordered.\n"
42795 <<
"Fail on last vertex of polyline: ("
42796 << prev_seg_boundary_id
42797 <<
") and\nfirst vertex of polyline (" << bound
42798 <<
").\nThis should have failed when first trying to "
42799 <<
"construct the\npolygon.\n";
42801 "RefineableTriangleMesh::update_open_"
42802 "curve_after_restart()",
42803 OOMPH_EXCEPTION_LOCATION);
42810 std::reverse(vector_vertex_node.begin(),
42811 vector_vertex_node.end());
42824 std::ostringstream error_stream;
42826 <<
"The distance between the first node of the current\n"
42827 <<
"line segment (boundary " << bound
42828 <<
") and either end of "
42829 <<
"the previous line segment\n"
42830 <<
"(boundary " << prev_seg_boundary_id
42831 <<
") is bigger than the "
42832 <<
"desired tolerance "
42835 <<
"This suggests that the polylines defining the polygonal\n"
42836 <<
"representation are not properly ordered.\n"
42837 <<
"Fail on last vertex of polyline: ("
42838 << prev_seg_boundary_id <<
") and\nfirst vertex of polyline ("
42840 <<
"This should have failed when first trying to construct "
42844 error_stream.str(),
42845 "RefineableTriangleMesh::update_open_curve_after_restart()",
42846 OOMPH_EXCEPTION_LOCATION);
42852 std::reverse(vector_vertex_node.begin(),
42853 vector_vertex_node.end());
42871 n_vertex = vector_vertex_node.size();
42884 double unrefinement_tolerance =
42888 double refinement_tolerance =
42896 double maximum_length =
42904 this->copy_connection_information(open_curve_pt->
polyline_pt(cs),
42905 tmp_curve_section_pt);
42911 bool delete_it_on_destructor =
false;
42913 std::set<TriangleMeshCurveSection*>::iterator it =
42916 if (it != this->Free_curve_section_pt.end())
42918 this->Free_curve_section_pt.erase(it);
42920 delete_it_on_destructor =
true;
42928 this->Boundary_curve_section_pt[bound] =
42931 if (delete_it_on_destructor)
42933 this->Free_curve_section_pt.insert(
42937 #ifdef OOMPH_HAS_MPI
42941 if (this->is_mesh_distributed() && nsub_boundaries == 1)
42944 this->Boundary_marked_as_shared_boundary[bound].clear();
42947 this->Boundary_marked_as_shared_boundary[bound].push_back(
42948 internal_to_shared_boundary[0]);
42952 else if (this->is_mesh_distributed() && nsub_boundaries > 1)
42957 this->Boundary_subpolylines[bound].clear();
42959 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
42962 this->Boundary_marked_as_shared_boundary[bound].clear();
42965 this->Boundary_marked_as_shared_boundary[bound].resize(
42967 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
42973 sub_vector_vertex_node[isub], bound, isub);
42977 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
42981 this->Boundary_marked_as_shared_boundary[bound][isub] =
42982 internal_to_shared_boundary[isub];
42997 delete mesh_geom_obj_pt;
43002 for (
unsigned p = 0; p < ncurve_section; p++)
43004 face_mesh_pt[p]->flush_node_storage();
43005 delete face_mesh_pt[p];
43009 #ifdef OOMPH_HAS_MPI
43013 template<
class ELEMENT>
43018 const unsigned npolylines = vector_polyline_pt.size();
43019 for (
unsigned pp = 0; pp < npolylines; pp++)
43022 const unsigned b = vector_polyline_pt[pp]->boundary_id();
43027 std::map<std::pair<Node*, Node*>,
FiniteElement*> halo_edge_element_pt;
43028 std::map<std::pair<Node*, Node*>,
FiniteElement*> nonhalo_edge_element_pt;
43035 const unsigned nshared_bound_ele = this->nshared_boundary_element(b);
43036 for (
unsigned e = 0;
e < nshared_bound_ele;
e++)
43039 FiniteElement* current_ele_pt = this->shared_boundary_element_pt(b,
e);
43042 Node* first_node_pt = current_ele_pt->
node_pt(0);
43043 Node* second_node_pt = current_ele_pt->
node_pt(1);
43044 Node* third_node_pt = current_ele_pt->
node_pt(2);
43047 if (!current_ele_pt->
is_halo())
43050 nonhalo_edge_nodes_pt.push_back(first_node_pt);
43051 nonhalo_edge_nodes_pt.push_back(second_node_pt);
43053 nonhalo_edge_nodes_pt.push_back(second_node_pt);
43054 nonhalo_edge_nodes_pt.push_back(third_node_pt);
43056 nonhalo_edge_nodes_pt.push_back(third_node_pt);
43057 nonhalo_edge_nodes_pt.push_back(first_node_pt);
43060 std::pair<Node*, Node*> edge1 =
43061 std::make_pair(first_node_pt, second_node_pt);
43062 nonhalo_edge_element_pt[edge1] = current_ele_pt;
43064 std::pair<Node*, Node*> edge2 =
43065 std::make_pair(second_node_pt, third_node_pt);
43066 nonhalo_edge_element_pt[edge2] = current_ele_pt;
43068 std::pair<Node*, Node*> edge3 =
43069 std::make_pair(third_node_pt, first_node_pt);
43070 nonhalo_edge_element_pt[edge3] = current_ele_pt;
43075 halo_edge_nodes_pt.push_back(first_node_pt);
43076 halo_edge_nodes_pt.push_back(second_node_pt);
43078 halo_edge_nodes_pt.push_back(second_node_pt);
43079 halo_edge_nodes_pt.push_back(third_node_pt);
43081 halo_edge_nodes_pt.push_back(third_node_pt);
43082 halo_edge_nodes_pt.push_back(first_node_pt);
43085 std::pair<Node*, Node*> edge1 =
43086 std::make_pair(first_node_pt, second_node_pt);
43087 halo_edge_element_pt[edge1] = current_ele_pt;
43089 std::pair<Node*, Node*> edge2 =
43090 std::make_pair(second_node_pt, third_node_pt);
43091 halo_edge_element_pt[edge2] = current_ele_pt;
43093 std::pair<Node*, Node*> edge3 =
43094 std::make_pair(third_node_pt, first_node_pt);
43095 halo_edge_element_pt[edge3] = current_ele_pt;
43103 std::map<std::pair<Node*, Node*>,
bool> edge_done;
43112 const unsigned nnonhalo_edge_nodes = nonhalo_edge_nodes_pt.size();
43113 for (
unsigned i = 0;
i < nnonhalo_edge_nodes;
i += 2)
43116 currenti_edge[0] = nonhalo_edge_nodes_pt[
i];
43117 currenti_edge[1] = nonhalo_edge_nodes_pt[
i + 1];
43120 std::pair<Node*, Node*> new_edge =
43121 std::make_pair(currenti_edge[0], currenti_edge[1]);
43123 if (!edge_done[new_edge])
43125 const unsigned nhalo_edge_nodes = halo_edge_nodes_pt.size();
43126 for (
unsigned j = 0; j < nhalo_edge_nodes; j += 2)
43129 currentj_edge[0] = halo_edge_nodes_pt[j];
43130 currentj_edge[1] = halo_edge_nodes_pt[j + 1];
43133 if (currenti_edge[0] == currentj_edge[0] &&
43134 currenti_edge[1] == currentj_edge[1])
43137 unsorted_edges.push_back(new_edge);
43142 FiniteElement* nonhalo_ele_pt = nonhalo_edge_element_pt[new_edge];
43143 FiniteElement* halo_ele_pt = halo_edge_element_pt[new_edge];
43145 tmp_edge_element_pt.push_back(nonhalo_ele_pt);
43146 tmp_edge_element_pt.push_back(halo_ele_pt);
43149 unsorted_edges_elements_pt.push_back(tmp_edge_element_pt);
43152 edge_done[new_edge] =
true;
43160 else if (currenti_edge[0] == currentj_edge[1] &&
43161 currenti_edge[1] == currentj_edge[0])
43164 std::pair<Node*, Node*> new_edge =
43165 std::make_pair(currenti_edge[0], currenti_edge[1]);
43168 unsorted_edges.push_back(new_edge);
43171 std::pair<Node*, Node*> rev_new_edge =
43172 std::make_pair(currentj_edge[0], currentj_edge[1]);
43177 FiniteElement* nonhalo_ele_pt = nonhalo_edge_element_pt[new_edge];
43178 FiniteElement* halo_ele_pt = halo_edge_element_pt[rev_new_edge];
43180 tmp_edge_element_pt.push_back(nonhalo_ele_pt);
43181 tmp_edge_element_pt.push_back(halo_ele_pt);
43184 unsorted_edges_elements_pt.push_back(tmp_edge_element_pt);
43187 edge_done[new_edge] =
true;
43205 std::map<std::pair<Node*, Node*>,
bool> edge_sorted;
43207 const unsigned nunsorted_edges = unsorted_edges.size();
43212 if (nshared_bound_ele / 2 != nunsorted_edges)
43214 std::ostringstream error_message;
43216 <<
"The number of shared boundary elements (" << nshared_bound_ele
43217 <<
") is not the double\nof the number of unsorted edges ("
43218 << nunsorted_edges <<
") for the current boundary (" << b <<
")\n\n";
43220 error_message.str(),
43221 "RefineableTriangleMesh::update_shared_curve_after_restart()",
43222 OOMPH_EXCEPTION_LOCATION);
43226 unsigned nsorted_edges = 0;
43230 std::list<Node*> sorted_nodes;
43233 std::list<FiniteElement*> sorted_edges_elements_pt;
43236 std::pair<Node*, Node*> edge = unsorted_edges[0];
43240 edge_sorted[edge] =
true;
43243 Node* first_node_pt = edge.first;
43244 Node* last_node_pt = edge.second;
43247 sorted_nodes.push_back(first_node_pt);
43248 sorted_nodes.push_back(last_node_pt);
43251 sorted_edges_elements_pt.push_back(unsorted_edges_elements_pt[0][0]);
43252 sorted_edges_elements_pt.push_back(unsorted_edges_elements_pt[0][1]);
43256 while (nsorted_edges < nunsorted_edges)
43259 bool node_added =
false;
43263 for (
unsigned iedge = 1; iedge < nunsorted_edges; iedge++)
43265 edge = unsorted_edges[iedge];
43268 if (!edge_sorted[edge])
43271 Node* left_node_pt = edge.first;
43272 Node* right_node_pt = edge.second;
43274 if (left_node_pt == first_node_pt)
43277 sorted_nodes.push_front(right_node_pt);
43278 first_node_pt = right_node_pt;
43282 sorted_edges_elements_pt.push_front(
43283 unsorted_edges_elements_pt[iedge][1]);
43284 sorted_edges_elements_pt.push_front(
43285 unsorted_edges_elements_pt[iedge][0]);
43287 else if (left_node_pt == last_node_pt)
43290 sorted_nodes.push_back(right_node_pt);
43291 last_node_pt = right_node_pt;
43295 sorted_edges_elements_pt.push_back(
43296 unsorted_edges_elements_pt[iedge][0]);
43297 sorted_edges_elements_pt.push_back(
43298 unsorted_edges_elements_pt[iedge][1]);
43300 else if (right_node_pt == first_node_pt)
43303 sorted_nodes.push_front(left_node_pt);
43304 first_node_pt = left_node_pt;
43308 sorted_edges_elements_pt.push_front(
43309 unsorted_edges_elements_pt[iedge][1]);
43310 sorted_edges_elements_pt.push_front(
43311 unsorted_edges_elements_pt[iedge][0]);
43313 else if (right_node_pt == last_node_pt)
43316 sorted_nodes.push_back(left_node_pt);
43317 last_node_pt = left_node_pt;
43321 sorted_edges_elements_pt.push_back(
43322 unsorted_edges_elements_pt[iedge][0]);
43323 sorted_edges_elements_pt.push_back(
43324 unsorted_edges_elements_pt[iedge][1]);
43331 edge_sorted[edge] =
true;
43346 unsigned nvertex = sorted_nodes.size();
43351 unsigned counter = 0;
43352 for (std::list<Node*>::iterator it_nodes = sorted_nodes.begin();
43353 it_nodes != sorted_nodes.end();
43356 polyline_vertices[counter].resize(2);
43357 polyline_vertices[counter][0] = (*it_nodes)->x(0);
43358 polyline_vertices[counter][1] = (*it_nodes)->x(1);
43365 if (polyline_vertices[nvertex - 1][1] < polyline_vertices[0][1])
43367 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
43369 else if (polyline_vertices[nvertex - 1][1] == polyline_vertices[0][1])
43371 if (polyline_vertices[nvertex - 1][0] < polyline_vertices[0][0])
43373 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
43386 this->copy_connection_information(curve_section_pt, new_polyline_pt);
43391 bool delete_it_on_destructor =
false;
43395 std::set<TriangleMeshCurveSection*>::iterator it =
43396 this->Free_curve_section_pt.find(curve_section_pt);
43398 if (it != this->Free_curve_section_pt.end())
43400 this->Free_curve_section_pt.erase(it);
43401 delete curve_section_pt;
43402 delete_it_on_destructor =
true;
43406 vector_polyline_pt[pp] = new_polyline_pt;
43412 this->Boundary_curve_section_pt[b] = new_curve_section_pt;
43414 if (delete_it_on_destructor)
43416 this->Free_curve_section_pt.insert(new_curve_section_pt);
43428 template<
class ELEMENT>
43430 ELEMENT>::fill_boundary_elements_and_nodes_for_internal_boundaries()
43433 std::ofstream some_file;
43434 fill_boundary_elements_and_nodes_for_internal_boundaries(some_file);
43441 template<
class ELEMENT>
43444 std::ofstream& outfile)
43447 const unsigned nproc = this->communicator_pt()->nproc();
43449 unsigned my_rank = this->communicator_pt()->my_rank();
43452 std::map<unsigned, unsigned> shd_bnd_over_int_bnd =
43453 this->Shared_boundary_overlaps_internal_boundary;
43457 std::set<unsigned> internal_boundary_overlaped;
43461 if (outfile.is_open())
43463 const unsigned nbound = this->nboundary();
43464 outfile <<
"Number of boundaries: " << nbound <<
"\n\n";
43465 outfile <<
"Number of elements and nodes associated to each "
43466 <<
"boundary before\nfilling elements and nodes\n\n";
43467 for (
unsigned i = 0;
i < nbound;
i++)
43469 outfile <<
"Boundary (" <<
i <<
") Elements ("
43470 << this->nboundary_element(
i) <<
") "
43471 <<
"Nodes (" << this->nboundary_node(
i) <<
")\n";
43476 std::set<unsigned> shared_boundaries_in_this_processor;
43480 for (
unsigned iproc = 0; iproc < nproc; iproc++)
43483 if (iproc != my_rank)
43486 unsigned nshared_boundaries_with_iproc =
43487 this->nshared_boundaries(my_rank, iproc);
43489 if (nshared_boundaries_with_iproc > 0)
43493 bound_shared_with_iproc = this->shared_boundaries_ids(my_rank, iproc);
43496 for (
unsigned bs = 0; bs < nshared_boundaries_with_iproc; bs++)
43498 unsigned bnd_id = bound_shared_with_iproc[bs];
43499 shared_boundaries_in_this_processor.insert(bnd_id);
43510 for (std::map<unsigned, unsigned>::iterator it =
43511 shd_bnd_over_int_bnd.begin();
43512 it != shd_bnd_over_int_bnd.end();
43516 const unsigned shd_bnd_id = (*it).first;
43518 const unsigned int_bnd_id = (*it).second;
43521 std::set<unsigned>::iterator it_set =
43522 shared_boundaries_in_this_processor.find(shd_bnd_id);
43523 if (it_set != shared_boundaries_in_this_processor.end())
43525 internal_boundary_overlaped.insert(int_bnd_id);
43530 const unsigned nbnd_node_shd_bnd = this->nboundary_node(shd_bnd_id);
43534 if (outfile.is_open())
43536 outfile <<
"\nPass info. from shared (" << shd_bnd_id
43537 <<
") to internal (" << int_bnd_id <<
")\n";
43538 outfile <<
"Number of shared boundary nodes: " << nbnd_node_shd_bnd
43542 for (
unsigned in = 0; in < nbnd_node_shd_bnd; in++)
43545 Node* bnd_node_pt = this->boundary_node_pt(shd_bnd_id, in);
43547 this->add_boundary_node(int_bnd_id, bnd_node_pt);
43554 const unsigned nbnd_ele_shd_bnd = this->nboundary_element(shd_bnd_id);
43558 if (outfile.is_open())
43560 outfile <<
"Number of shared boundary elements: " << nbnd_ele_shd_bnd
43566 for (
unsigned ie = 0; ie < nbnd_ele_shd_bnd; ie++)
43569 FiniteElement* bnd_ele_pt = this->boundary_element_pt(shd_bnd_id, ie);
43572 Boundary_element_pt[int_bnd_id].push_back(bnd_ele_pt);
43574 int face_index = this->face_index_at_boundary(shd_bnd_id, ie);
43576 Face_index_at_boundary[int_bnd_id].push_back(face_index);
43581 const unsigned nregions = this->nregion();
43584 for (
unsigned ir = 0; ir < nregions; ir++)
43587 const unsigned region_id =
43588 static_cast<unsigned>(this->Region_attribute[ir]);
43591 const unsigned nele_ir =
43592 this->nboundary_element_in_region(shd_bnd_id, region_id);
43593 for (
unsigned ier = 0; ier < nele_ir; ier++)
43597 this->boundary_element_in_region_pt(shd_bnd_id, region_id, ier);
43600 this->Boundary_region_element_pt[int_bnd_id][region_id].push_back(
43604 int face_index = this->face_index_at_boundary_in_region(
43605 shd_bnd_id, region_id, ier);
43607 this->Face_index_region_at_boundary[int_bnd_id][region_id]
43608 .push_back(face_index);
43622 if (outfile.is_open())
43624 const unsigned nbound = this->nboundary();
43625 outfile <<
"Number of boundaries: " << nbound <<
"\n\n";
43626 outfile <<
"Number of elements and nodes associated to each "
43627 <<
"boundary after\nfilling elements and nodes\n\n";
43628 for (
unsigned i = 0;
i < nbound;
i++)
43630 outfile <<
"Boundary (" <<
i <<
") Elements ("
43631 << this->nboundary_element(
i) <<
")"
43632 <<
" Nodes (" << this->nboundary_node(
i) <<
")\n";
43640 for (std::set<unsigned>::iterator it = internal_boundary_overlaped.begin();
43641 it != internal_boundary_overlaped.end();
43644 const unsigned overlaped_internal_bnd_id = (*it);
43647 this->
template setup_boundary_coordinates<ELEMENT>(
43648 overlaped_internal_bnd_id);
43657 template<
class ELEMENT>
43662 if (!Boundary_coordinate_exists[b])
43679 std::set<Node*> tmp_boundary_node_pt;
43680 const unsigned nboundary_ele = this->nboundary_element(b);
43681 for (
unsigned e = 0;
e < nboundary_ele;
e++)
43685 #ifdef OOMPH_HAS_MPI
43691 int face_index = this->face_index_at_boundary(b,
e);
43697 const unsigned nnodes = face_ele_pt->
nnode();
43698 for (
unsigned i = 0;
i < nnodes;
i++)
43703 tmp_boundary_node_pt.insert(tmp_node_pt);
43707 delete face_ele_pt;
43709 #ifdef OOMPH_HAS_MPI
43716 const unsigned long n_boundary_node = tmp_boundary_node_pt.
size();
43719 if (n_boundary_node == 0)
43721 #ifdef OOMPH_HAS_MPI
43723 if (!this->is_mesh_distributed())
43727 #ifdef OOMPH_HAS_MPI
43733 create_unsorted_face_mesh_representation(b, face_mesh_pt);
43737 delete mesh_geom_obj_pt;
43742 delete face_mesh_pt;
43754 unsigned tmp_counter = 0;
43755 for (std::set<Node*>::iterator it_node = tmp_boundary_node_pt.begin();
43756 it_node != tmp_boundary_node_pt.end();
43757 it_node++, tmp_counter++)
43759 Node* nod_pt = (*it_node);
43761 node_coord[0] = b_coord[0];
43762 node_coord[1] = nod_pt->
x(0);
43763 node_coord[2] = nod_pt->
x(1);
43764 old_boundary_node[tmp_counter] = node_coord;
43768 std::sort(old_boundary_node.begin(), old_boundary_node.end());
43779 #ifdef OOMPH_HAS_MPI
43785 const unsigned nsegments = 1;
43788 #ifdef OOMPH_HAS_MPI
43793 if (this->is_mesh_distributed())
43798 if (n_new_boundary_node == 0)
43802 create_unsorted_face_mesh_representation(b, face_mesh_pt);
43806 delete mesh_geom_obj_pt;
43810 delete face_mesh_pt;
43821 for (
unsigned is = 0; is < nsegments; is++)
43823 #ifdef OOMPH_HAS_MPI
43824 const unsigned n_new_boundary_segment_node =
43827 const unsigned n_new_boundary_segment_node =
43833 node_coord.resize(6, 0.0);
43834 for (
unsigned n = 0; n < n_new_boundary_segment_node; n++)
43836 #ifdef OOMPH_HAS_MPI
43842 node_coord[0] = b_coord[0];
43843 node_coord[1] = nod_pt->
x(0);
43844 node_coord[2] = nod_pt->
x(1);
43846 new_boundary_node[n] = node_coord;
43850 std::sort(new_boundary_node.begin(), new_boundary_node.end());
43857 unsigned old_index = 0;
43858 for (
unsigned n = 0; n < n_new_boundary_segment_node; ++n)
43862 for (
unsigned m = old_index; m < n_boundary_node; ++m)
43864 if ((std::fabs(old_boundary_node[m][1] - new_boundary_node[n][1]) <
43866 (std::fabs(old_boundary_node[m][2] - new_boundary_node[n][2]) <
43870 new_boundary_node[n][4] = old_boundary_node[m][0];
43872 new_boundary_node[n][5] = 1.0;
43883 if ((new_boundary_node[0][5] == 0.0) ||
43884 (new_boundary_node[n_new_boundary_segment_node - 1][5] == 0.0))
43886 std::ostringstream error_stream;
43888 <<
"New boundary coordinates not found for the first and/or last "
43890 <<
"on the boundary " << b <<
". This should not happen because "
43891 <<
"these\nlimits should have been setup in the constructor\n";
43893 <<
"The distance between the new and old nodes is probably outside\n"
43894 <<
"our tolerance.\n";
43895 error_stream.precision(20);
43896 error_stream <<
"Old boundaries: \n";
43897 error_stream << old_boundary_node[0][1] <<
" "
43898 << old_boundary_node[0][2] <<
" : "
43899 << old_boundary_node[n_boundary_node - 1][1] <<
" "
43900 << old_boundary_node[n_boundary_node - 1][2] <<
"\n";
43901 error_stream <<
"New boundaries: \n"
43902 << new_boundary_node[0][1] <<
" "
43903 << new_boundary_node[0][2] <<
" : "
43904 << new_boundary_node[n_new_boundary_segment_node - 1][1]
43906 << new_boundary_node[n_new_boundary_segment_node - 1][2]
43909 "RefineableTriangleMesh::snap_nodes_onto_boundary()",
43910 OOMPH_EXCEPTION_LOCATION);
43916 if (!this->is_mesh_distributed())
43920 new_boundary_node[0][4] = new_boundary_node[0][0];
43923 new_boundary_node[n_new_boundary_segment_node - 1][4] =
43924 new_boundary_node[0][5] = 1.0;
43926 new_boundary_node[n_new_boundary_segment_node - 1][4] =
43927 new_boundary_node[n_new_boundary_segment_node - 1][0];
43928 new_boundary_node[n_new_boundary_segment_node - 1][5] = 1.0;
43933 for (
unsigned n = 1; n < n_new_boundary_segment_node - 1; ++n)
43936 if (new_boundary_node[n][5] == 0.0)
43939 nodes_to_be_snapped[is].push_back(
43940 static_cast<unsigned>(new_boundary_node[n][3]));
43944 double zeta_old_low = new_boundary_node[n - 1][0];
43945 double zeta_new_low = new_boundary_node[n - 1][4];
43949 for (
unsigned m = n + 1; m < n_new_boundary_segment_node; ++m)
43951 if (new_boundary_node[m][5] == 1.0)
43954 double zeta_old_high = new_boundary_node[m][0];
43955 double zeta_new_high = new_boundary_node[m][4];
43957 double frac = (new_boundary_node[n][0] - zeta_old_low) /
43958 (zeta_old_high - zeta_old_low);
43959 new_boundary_node[n][4] =
43960 zeta_new_low + frac * (zeta_new_high - zeta_new_low);
43961 new_boundary_node[n][5] = 1.0;
43969 for (
unsigned n = 0; n < n_new_boundary_segment_node; ++n)
43971 if (new_boundary_node[n][5] == 0)
43974 "New boundary coordinate not assigned\n",
43975 "RefineableTriangleMesh::snap_nodes_onto_boundary()",
43976 OOMPH_EXCEPTION_LOCATION);
43979 #ifdef OOMPH_HAS_MPI
43983 b, is,
static_cast<unsigned>(new_boundary_node[n][3]))
43984 ->get_coordinates_on_boundary(b, b_coord);
43986 b_coord[0] = new_boundary_node[n][4];
43989 b, is,
static_cast<unsigned>(new_boundary_node[n][3]))
43990 ->set_coordinates_on_boundary(b, b_coord);
43997 b_coord[0] = new_boundary_node[n][4];
44007 create_unsorted_face_mesh_representation(b, face_mesh_pt);
44017 for (
unsigned is = 0; is < nsegments; is++)
44019 const unsigned nnodes_to_snap = nodes_to_be_snapped[is].size();
44021 for (
unsigned in = 0; in < nnodes_to_snap; in++)
44024 unsigned n = nodes_to_be_snapped[is][in];
44025 #ifdef OOMPH_HAS_MPI
44035 mesh_geom_obj_pt->
position(b_coord, new_x);
44038 for (
unsigned i = 0;
i < 2;
i++)
44040 nod_pt->
x(
i) = new_x[
i];
44046 delete mesh_geom_obj_pt;
44050 delete face_mesh_pt;
44057 for (
unsigned j = 0; j < 6; j++)
44059 dummy_six_node_element.construct_node(j);
44065 for (
unsigned e = 0;
e < n_bound_el;
e++)
44070 unsigned nnod = el_pt->
nnode();
44086 "Have a three-noded element that's not a TElement<2,2>",
44087 OOMPH_CURRENT_FUNCTION,
44088 OOMPH_EXCEPTION_LOCATION);
44096 else if ((nnod == 6) || (nnod == 7))
44106 "Have a six-noded element that's not a TElement<2,3>",
44107 OOMPH_CURRENT_FUNCTION,
44108 OOMPH_EXCEPTION_LOCATION);
44113 "Have a seven-noded element that's not a TElement<2,3>",
44114 OOMPH_CURRENT_FUNCTION,
44115 OOMPH_EXCEPTION_LOCATION);
44135 for (
unsigned i = 0;
i < 2;
i++)
44146 for (
unsigned i = 0;
i < 2;
i++)
44162 for (
unsigned i = 0;
i < 2;
i++)
44173 for (
unsigned i = 0;
i < 2;
i++)
44189 for (
unsigned i = 0;
i < 2;
i++)
44200 for (
unsigned i = 0;
i < 2;
i++)
44217 throw OomphLibError(
"Have seven-noded element that's not a "
44218 "TBubbleEnrichedElement<2,3>",
44219 OOMPH_CURRENT_FUNCTION,
44220 OOMPH_EXCEPTION_LOCATION);
44225 for (
unsigned j = 0; j < 6; j++)
44227 for (
unsigned i = 0;
i < 2;
i++)
44229 dummy_six_node_element.node_pt(j)->x(
i) = el_pt->
node_pt(j)->
x(
i);
44234 unsigned j_enriched = 6;
44240 dummy_six_node_element.interpolated_x(
s, x);
44241 el_pt->
node_pt(j_enriched)->
x(0) = x[0];
44242 el_pt->
node_pt(j_enriched)->
x(1) = x[1];
44249 std::ostringstream error_stream;
44250 error_stream <<
"Cannot deal with this particular " << nnod
44251 <<
"-noded element yet.\n"
44252 <<
"Please implement this yourself.\n";
44254 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
44259 for (
unsigned j = 0; j < 6; j++)
44261 delete dummy_six_node_element.node_pt(j);
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
///////////////////////////////////////////////////////////////////////////// ///////////////////////...
void get_bin(const Vector< double > &zeta, int &bin_number)
Get the number of the bin containing the specified coordinate. Bin number is negative if the coordina...
const std::map< unsigned, Vector< std::pair< FiniteElement *, Vector< double > > > > * get_all_bins_content() const
Get the contents of all bins in vector.
void fill_bin_by_diffusion(const unsigned &bin_diffusion_radius=1)
Fill bin by diffusion, populating each empty bin with the same content as the first non-empty bin fou...
void get_fill_stats(unsigned &n_bin, unsigned &max_n_entry, unsigned &min_n_entry, unsigned &tot_n_entry, unsigned &n_empty) const
Provide some stats on the fill level of the associated bin.
////////////////////////////////////////////////////////////////////
virtual void update_node_update(AlgebraicNode *&node_pt)=0
Update the node update info for given node, following mesh adaptation. Must be implemented for every ...
GeomObject * geom_object_list_pt(const unsigned &i)
Access function to the ith GeomObject.
unsigned ngeom_object_list_pt()
Return number of geometric objects associated with AlgebraicMesh.
////////////////////////////////////////////////////////////////////
unsigned ngeom_object(const int &id)
Number of geometric objects involved in id-th update function.
unsigned nref_value(const int &id)
Number of reference values involved in id-th update function.
GeomObject * geom_object_pt(const unsigned &i)
Return pointer to i-th geometric object involved in default (usually first) update function.
int node_update_fct_id()
Default (usually first if there are multiple ones) node update fct id.
double ref_value(const unsigned &i)
Return i-th reference value involved in default (usually first) update function.
void add_node_update_info(const int &id, AlgebraicMesh *mesh_pt, const Vector< GeomObject * > &geom_object_pt, const Vector< double > &ref_value, const bool &called_from_constructor=false)
Add algebraic update information for node: What's the ID of the mesh update function (typically used ...
Vector< unsigned > & dimensions_of_bin_array()
Number of bins in each coordinate direction.
A class that contains the information required by Nodes that are located on Mesh boundaries....
std::map< unsigned, unsigned > *& index_of_first_value_assigned_by_face_element_pt()
Return pointer to the map giving the index of the first face element value.
/////////////////////////////////////////////////////////////////////////// /////////////////////////...
A class that represents a collection of data; each Data object may contain many different individual ...
bool is_halo() const
Is this Data a halo?
void set_value(const unsigned &i, const double &value_)
Set the i-th stored data value to specified value. The only reason that we require an explicit set fu...
unsigned nvalue() const
Return number of values stored in data object (incl pinned ones).
double value(const unsigned &i) const
Return i-th stored value. This function is not virtual so that it can be inlined. This means that if ...
int non_halo_proc_ID()
ID of processor ID that holds non-halo counterpart of halo node; negative if not a halo.
Information for documentation of results: Directory and file number to enable output in the form RESL...
void disable_doc()
Disable documentation.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
Class that is used to create FaceElement from bulk elements and to provide these FaceElement with a g...
void set_boundary_number_in_bulk_mesh(const unsigned &b)
Set function for the boundary number in bulk mesh.
A general Finite Element class.
virtual void local_coordinate_of_node(const unsigned &j, Vector< double > &s) const
Get local coordinates of node j in the element; vector sets its own size (broken virtual)
virtual Node * construct_node(const unsigned &n)
Construct the local node n and return a pointer to the newly created node object.
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
double size() const
Calculate the size of the element (length, area, volume,...) in Eulerian computational coordinates....
virtual double interpolated_x(const Vector< double > &s, const unsigned &i) const
Return FE interpolated coordinate x[i] at local coordinate s.
unsigned nnode() const
Return the number of nodes.
virtual Node * construct_boundary_node(const unsigned &n)
Construct the local node n as a boundary node; that is a node that MAY be placed on a mesh boundary a...
A Generalised Element class.
bool is_halo() const
Is this element a halo?
int non_halo_proc_ID()
ID of processor ID that holds non-halo counterpart of halo element; negative if not a halo.
bool must_be_kept_as_halo() const
Test whether the element must be kept as a halo element.
Generalised timestepper that can serve a variety of purposes in continuation, bifurcation detection a...
/////////////////////////////////////////////////////////////////////
MacroElementNodeUpdateMeshes contain MacroElementNodeUpdateNodes which have their own node update fun...
Vector< GeomObject * > geom_object_vector_pt()
Access function to the vector of GeomObject.
////////////////////////////////////////////////////////////////////
void set_node_update_info(FiniteElement *node_update_element_pt, const Vector< double > &s_in_node_update_element, const Vector< GeomObject * > &geom_object_pt)
Set node update information for node: Pass the pointer to the element that performs the update operat...
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
void position(const Vector< double > &zeta, Vector< double > &r) const
Return the position as a function of the intrinsic coordinate zeta. This provides an (expensive!...
SamplePointContainer * sample_point_container_pt() const
Pointer to the sample point container.
unsigned long nboundary_node(const unsigned &ibound) const
Return number of nodes on a particular boundary.
void flush_element_and_node_storage()
Flush storage for elements and nodes by emptying the vectors that store the pointers to them....
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
int face_index_at_boundary(const unsigned &b, const unsigned &e) const
For the e-th finite element on boundary b, return int to indicate the face_index of the face adjacent...
unsigned nboundary_element(const unsigned &b) const
Return number of finite elements that are adjacent to boundary b.
void set_nodal_and_elemental_time_stepper(TimeStepper *const &time_stepper_pt, const bool &preserve_existing_data)
Set the timestepper associated with all nodal and elemental data stored in the mesh.
unsigned nboundary() const
Return number of boundaries.
FiniteElement * boundary_element_pt(const unsigned &b, const unsigned &e) const
Return pointer to e-th finite element on boundary b.
GeneralisedElement *& element_pt(const unsigned long &e)
Return pointer to element e.
unsigned long nnode() const
Return number of nodes in the mesh.
void add_element_pt(GeneralisedElement *const &element_pt)
Add a (pointer to) an element to the mesh.
Node *& node_pt(const unsigned long &n)
Return pointer to global node n.
void flush_node_storage()
Flush storage for nodes (only) by emptying the vectors that store the pointers to them.
Node *& boundary_node_pt(const unsigned &b, const unsigned &n)
Return pointer to node n on boundary b.
unsigned long nelement() const
Return number of elements in the mesh.
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
double & x(const unsigned &i)
Return the i-th nodal coordinate.
virtual bool is_on_boundary() const
Test whether the Node lies on a boundary. The "bulk" Node cannot lie on a boundary,...
virtual void get_boundaries_pt(std::set< unsigned > *&boundaries_pt)
Return a pointer to set of mesh boundaries that this node occupies; this will be overloaded by Bounda...
virtual void remove_from_boundary(const unsigned &b)
Broken interface for removing the node from the mesh boundary b Here to provide error reporting.
void set_non_obsolete()
Mark node as non-obsolete.
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
virtual void set_coordinates_on_boundary(const unsigned &b, const unsigned &k, const Vector< double > &boundary_zeta)
Set the vector of the k-th generalised boundary coordinates on mesh boundary b. Broken virtual interf...
virtual void get_coordinates_on_boundary(const unsigned &b, const unsigned &k, Vector< double > &boundary_zeta)
Return the vector of the k-th generalised boundary coordinates on mesh boundary b....
void resize(const unsigned &n_value)
Resize the number of equations.
double value(const unsigned &i) const
Return i-th value (dofs or pinned) at this node either directly or via hanging node representation....
/////////////////////////////////////////////////////////////////////////// /////////////////////////...
An oomph-lib wrapper to the MPI_Comm communicator object. Just contains an MPI_Comm object (which is ...
An OomphLibError object which should be thrown when an run-time error is encountered....
An OomphLibWarning object which should be created as a temporary object to issue a warning....
void enable_problem_distributed()
Enable problem distributed.
void add_time_stepper_pt(TimeStepper *const &time_stepper_pt)
Add a timestepper to the problem. The function will automatically create or resize the Time object so...
Mesh *& mesh_pt()
Return a pointer to the global mesh.
Projection problem. This is created during the adaptation of unstructured meshes and it is assumed th...
void disable_use_iterative_solver_for_projection()
Disbales the use of an iterative solver for projection.
void project(Mesh *base_mesh_pt, const bool &dont_project_positions=false)
Project from base into the problem's own mesh.
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
/////////////////////////////////////////////////////////////////// /////////////////////////////////...
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.
void enable_use_eulerian_coordinates_during_setup()
Enable use of eulerian coordinates (via interpolated_x) during setup (otherwise use interpolated_zeta...
A Class for nodes that deform elastically (i.e. position is an unknown in the problem)....
void add_values_to_vector(Vector< double > &vector_of_values)
Add all data, position and time history values to the vector Overload to add the Lagrangian coordinat...
void read_values_from_vector(const Vector< double > &vector_of_values, unsigned &index)
Read all data and time history values from the vector starting from index. On return the index will b...
Data *const & variable_position_pt() const
Pointer to variable_position data (const version)
////////////////////////////////////////////////////////////////////// //////////////////////////////...
unsigned ntstorage() const
Return the number of doubles required to represent history (one for steady)
Class to keep track of discrete/continous time. It is essential to have a single Time object when usi...
TriangulateIO & triangulateio_representation()
Access to the triangulateio representation of the mesh.
Vector< double > internal_point() const
Coordinates of the internal point.
bool is_internal_point_fixed() const
Test whether the internal point is fixed.
Base class for defining a triangle mesh boundary, this class has the methods that allow to connect th...
virtual unsigned boundary_chunk() const =0
Boundary chunk (Used when a boundary is represented by more than one polyline.
double unrefinement_tolerance()
Get tolerance for unrefinement of curve section to create a better representation of curvilinear boun...
void set_unrefinement_tolerance(const double &tolerance)
Set tolerance for unrefinement of curve sections to avoid unnecessarily large numbers of elements on ...
virtual unsigned boundary_id() const =0
Boundary id.
void connect_initial_vertex_to_polyline(TriangleMeshPolyLine *polyline_pt, const unsigned &vertex_number, const double &tolerance_for_connection=1.0e-14)
Connects the initial vertex of the curve section to a desired target polyline by specifying the verte...
void resume_initial_vertex_connected()
Resumes the initial vertex connection, it may be that after load balancing the boundary to which the ...
void suspend_final_vertex_connected()
Set the final vertex connection as suspended, it will be resumed when the method to resume the connec...
unsigned initial_vertex_connected_n_vertex() const
Gets the vertex number to which the initial end is connected.
void resume_final_vertex_connected()
Resumes the final vertex connection, it may be that after load balancing the boundary to which the co...
void set_refinement_tolerance(const double &tolerance)
Set tolerance for refinement of curve sections to create a better representation of curvilinear bound...
virtual unsigned nvertex() const =0
Number of vertices.
void connect_final_vertex_to_polyline(TriangleMeshPolyLine *polyline_pt, const unsigned &vertex_number, const double &tolerance_for_connection=1.0e-14)
Connects the final vertex of the curve section to a desired target polyline by specifying the vertex ...
unsigned final_vertex_connected_n_chunk() const
Gets the boundary chunk to which the final end is connected.
void set_maximum_length(const double &maximum_length)
Allows to specify the maximum distance between two vertices that define the associated polyline of th...
unsigned final_vertex_connected_n_vertex() const
Sets the vertex number to which the final end is connected.
double refinement_tolerance()
Get tolerance for refinement of curve sections to create a better representation of curvilinear bound...
bool is_final_vertex_connected() const
Test whether final vertex is connected or not.
unsigned initial_vertex_connected_bnd_id() const
Gets the id to which the initial end is connected.
bool is_initial_vertex_connected() const
Test whether initial vertex is connected or not.
void set_initial_vertex_connected()
Sets the initial vertex as connected.
void set_final_vertex_connected()
Sets the final vertex as connected.
void suspend_initial_vertex_connected()
Set the initial vertex connection as suspended, it will be resumed when the method to resume the conn...
unsigned initial_vertex_connected_n_chunk() const
Gets the boundary chunk to which the initial end is connected.
double maximum_length()
Gets access to the maximum length variable.
unsigned final_vertex_connected_bnd_id() const
Gets the id to which the final end is connected.
virtual TriangleMeshCurveSection * curve_section_pt(const unsigned &i) const
Pointer to i-th constituent curve section.
virtual unsigned ncurve_section() const
Number of constituent curves.
////////////////////////////////////////////////////////////////////// //////////////////////////////...
TriangleMeshPolyLine * polyline_pt(const unsigned &i) const
Pointer to i-th constituent polyline.
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
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.
Class defining a polyline for use in Triangle Mesh generation.
unsigned boundary_chunk() const
Boundary chunk (Used when a boundary is represented by more than one polyline.
void final_vertex_coordinate(Vector< double > &vertex)
Get last vertex coordinates.
unsigned nvertex() const
Number of vertices.
void reverse()
Reverse the polyline, this includes the connection information and the vertices order.
void initial_vertex_coordinate(Vector< double > &vertex)
Get first vertex coordinates.
Vector< double > vertex_coordinate(const unsigned &i) const
Coordinate vector of i-th vertex (const version)
unsigned boundary_id() const
Boundary id.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
unsigned npolyline() const
Number of constituent polylines.
bool can_update_reference_configuration() const
Test whether curve can update reference.
TriangleMeshPolyLine * polyline_pt(const unsigned &i) const
Pointer to i-th constituent polyline.
bool is_redistribution_of_segments_between_polylines_enabled()
Is re-distribution of polyline segments in the curve between different boundaries during adaptation e...
virtual void reset_reference_configuration()
Virtual function that should be overloaded to update the polygons reference configuration.
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
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 ...
std::map< unsigned, Vector< double > > & boundary_segment_final_zeta()
Return direct access to the final zeta for the segments that are part of a boundary.
std::map< unsigned, Vector< double > > & boundary_initial_zeta_coordinate()
Return direct access to the initial zeta coordinate of a boundary.
double region_attribute(const unsigned &i)
Return the attribute associated with region i.
std::map< unsigned, Vector< double > > & boundary_final_coordinate()
Return direct access to the final coordinates of a boundary.
std::map< unsigned, Vector< double > > & boundary_segment_initial_zeta()
Return direct access to the initial zeta for the segments that are part of a boundary.
unsigned nboundary_segment(const unsigned &b)
Return the number of segments associated with a boundary.
unsigned long nboundary_segment_node(const unsigned &b)
Return the number of segments associated with a boundary.
FiniteElement * boundary_element_in_region_pt(const unsigned &b, const unsigned &r, const unsigned &e) const
Return pointer to the e-th element adjacent to boundary b in region r.
std::map< unsigned, Vector< double > > & boundary_segment_final_arclength()
Return direct access to the final arclength for the segments that are part of a boundary.
int face_index_at_boundary_in_region(const unsigned &b, const unsigned &r, const unsigned &e) const
Return face index of the e-th element adjacent to boundary b in region r.
std::map< unsigned, Vector< Vector< double > > > & boundary_segment_initial_coordinate()
Return direct access to the initial coordinates for the segments that are part of a boundary.
std::map< unsigned, Vector< double > > & boundary_segment_initial_arclength()
Return direct access to the initial arclength for the segments that are part of a boundary.
unsigned nboundary_element_in_region(const unsigned &b, const unsigned &r) const
Return the number of elements adjacent to boundary b in region r.
unsigned nregion()
Return the number of regions specified by attributes.
FiniteElement * region_element_pt(const unsigned &i, const unsigned &e)
Return the e-th element in the i-th region.
GeomObject * boundary_geom_object_pt(const unsigned &b)
Return the geometric object associated with the b-th boundary or null if the boundary has associated ...
std::map< unsigned, Vector< double > > & boundary_final_zeta_coordinate()
Return direct access to the final zeta coordinates of a boundary.
unsigned nregion_element(const unsigned &i)
Return the number of elements in the i-th region.
std::map< unsigned, Vector< double > > & boundary_coordinate_limits()
Return access to the vector of boundary coordinates associated with each geometric object.
std::map< unsigned, Vector< double > > & boundary_initial_coordinate()
Return direct access to the initial coordinates of a boundary.
std::map< unsigned, Vector< Vector< double > > > & boundary_segment_final_coordinate()
Return direct access to the final coordinates for the segments that are part of a boundary.
A slight extension to the standard template vector class so that we can include "graceful" array rang...
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn't been defined.
bool Doc_comprehensive_timings
Global boolean to switch on comprehensive timing – can probably be declared const false when developm...
void get_required_nodal_information_helper(int &iproc, Node *nod_pt, Mesh *const &mesh_pt, int &n_cont_inter_values, Vector< unsigned > &send_unsigneds, Vector< double > &send_doubles)
Helper function to get the required nodal information from an external haloed node so that a fully-fu...
Vector< std::string > Flat_packed_unsigneds_string
unsigned Counter_for_flat_packed_unsigneds
Counter used when processing vector of flat-packed unsigneds – this is really "private" data,...
Vector< double > Flat_packed_doubles
Vector of flat-packed doubles to be communicated with other processors.
Vector< unsigned > Flat_packed_unsigneds
Vector of flat-packed unsigneds to be communicated with other processors – this is really "private" d...
bool Doc_timings
Boolean to indicate whether to doc timings or not.
bool Doc_stats
Boolean to indicate whether to output basic info during setup_multi_domain_interaction() routines.
bool Doc_full_stats
Boolean to indicate whether to output further info during setup_multi_domain_interaction() routines.
unsigned Counter_for_flat_packed_doubles
Counter used when processing vector of flat-packed doubles – this is really "private" data,...
double timer()
returns the time in seconds after some point in past
double Tolerable_error
Acceptable discrepancy for mismatch in vertex coordinates. In paranoid mode, the code will die if the...
void initialise_triangulateio(TriangulateIO &triangle_io)
Initialise TriangulateIO structure.
void clear_triangulateio(TriangulateIO &triangulate_io, const bool &clear_hole_data)
Clear TriangulateIO structure.
TriangulateIO deep_copy_of_triangulateio_representation(TriangulateIO &triangle_io, const bool &quiet)
Make (partial) deep copy of TriangulateIO object. We only copy those items we need within oomph-lib's...
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
struct oomph::classcomp Bottom_left_sorter
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...
The Triangle data structure, modified from the triangle.h header supplied with triangle 1....
double * pointlist
Pointer to list of points x coordinate followed by y coordinate.
int numberoftriangleattributes
int * pointmarkerlist
Pointer to list of point markers.
double * trianglearealist
double * triangleattributelist
double * pointattributelist
Pointer to list of point attributes.
int numberofpointattributes
bool operator()(const std::pair< double, double > &lhs, const std::pair< double, double > &rhs) const