30 #ifndef OOMPH_TRIANGLE_MESH_TEMPLATE_CC 31 #define OOMPH_TRIANGLE_MESH_TEMPLATE_CC 36 #include "../generic/map_matrix.h" 37 #include "../generic/multi_domain.h" 38 #include "../generic/projection.h" 39 #include "../generic/face_element_as_geometric_object.h" 48 template<
class ELEMENT>
50 const bool &use_attributes)
53 MeshChecker::assert_geometric_element<TElementGeometricBase,ELEMENT>(2);
56 unsigned nelem = Tmp_mesh_pt->nelement();
57 Element_pt.resize(nelem);
60 unsigned nnode_scaffold = Tmp_mesh_pt->nnode();
64 std::map<Node*, unsigned> old_global_number;
67 for (
unsigned inod = 0; inod < nnode_scaffold; inod++)
69 Node* old_node_pt = Tmp_mesh_pt->node_pt(inod);
70 old_global_number[old_node_pt] = inod;
74 Oomph_vertex_nodes_id.
resize(nnode_scaffold);
77 Node_pt.resize(nnode_scaffold, 0);
80 unsigned nbound = Tmp_mesh_pt->nboundary();
83 set_nboundary(nbound);
84 Boundary_element_pt.resize(nbound);
85 Face_index_at_boundary.resize(nbound);
91 Boundary_region_element_pt.resize(nbound);
92 Face_index_region_at_boundary.resize(nbound);
96 for (
unsigned e = 0;
e < nelem;
e++)
98 Element_pt[
e] =
new ELEMENT;
102 unsigned nnod_el = Tmp_mesh_pt->finite_element_pt(0)->nnode();
107 std::map<Node*, unsigned> global_number;
108 unsigned global_count = 0;
111 std::map<double, Vector<FiniteElement*> > element_attribute_map;
118 element_attribute_map[0].resize(0);
122 for (
unsigned e = 0;
e < nelem;
e++)
125 for (
unsigned j = 0; j < nnod_el; j++)
128 Node* scaffold_node_pt = Tmp_mesh_pt->finite_element_pt(
e)->node_pt(j);
132 unsigned j_global = global_number[scaffold_node_pt];
138 Oomph_vertex_nodes_id[global_count] =
139 old_global_number[scaffold_node_pt];
143 std::set<unsigned>* boundaries_pt;
147 Node* new_node_pt = 0;
150 if (boundaries_pt != 0)
154 finite_element_pt(
e)->construct_boundary_node(j,time_stepper_pt);
157 for (std::set<unsigned>::iterator it = boundaries_pt->begin(); it
158 != boundaries_pt->end(); ++it)
160 add_boundary_node(*it, new_node_pt);
167 new_node_pt = finite_element_pt(
e)->construct_node(j,time_stepper_pt);
174 global_number[scaffold_node_pt] = global_count;
180 Node_pt[global_count - 1] = new_node_pt;
183 for (
unsigned i = 0;
i < finite_element_pt(
e)->dim();
i++)
185 new_node_pt->
x(
i) = scaffold_node_pt->
x(
i);
191 finite_element_pt(
e)->node_pt(j) = Node_pt[j_global - 1];
198 element_attribute_map[Tmp_mesh_pt->element_attribute(
e)].push_back(
199 finite_element_pt(
e));
207 unsigned n_attribute = element_attribute_map.size();
210 this->Region_attribute.resize(n_attribute);
215 element_attribute_map.begin(); it!=element_attribute_map.end(); ++it)
217 this->Region_attribute[count] = it->first;
218 Region_element_pt[
static_cast<unsigned>(Region_attribute[count])] =
229 unsigned boundary_id=0;
233 unsigned n_node_1d = finite_element_pt(0)->nnode_1d();
234 unsigned dim = finite_element_pt(0)->dim();
240 unsigned n_node = finite_element_pt(0)->nnode();
243 unsigned n_global_edge = Tmp_mesh_pt->nglobal_edge();
247 for (
unsigned e = 0;
e < nelem;
e++)
251 FiniteElement*
const tmp_elem_pt = Tmp_mesh_pt->finite_element_pt(
e);
254 unsigned n_edge_node = 3 * (n_node_1d - 1);
258 for (
unsigned n = n_edge_node; n < n_node; ++n)
268 for (
unsigned i = 0;
i < dim;
i++)
274 Node_pt.push_back(new_node_pt);
282 for (
unsigned j = 0; j < 3; j++)
285 boundary_id = Tmp_mesh_pt->edge_boundary(
e, j);
288 unsigned edge_index = Tmp_mesh_pt->edge_index(
e, j);
291 if (nodes_on_global_edge[edge_index].size() == 0)
294 for (
unsigned j2 = 0; j2 < n_node_1d - 2; ++j2)
297 Node* new_node_pt = 0;
304 this->add_boundary_node(boundary_id - 1, new_node_pt);
317 for (
unsigned i = 0;
i < dim;
i++)
323 Node_pt.push_back(new_node_pt);
326 nodes_on_global_edge[edge_index].push_back(new_node_pt);
338 for (
unsigned j2 = 0; j2 < n_node_1d - 2; ++j2)
342 elem_pt->
node_pt(n) = nodes_on_global_edge[edge_index][n_node_1d - 3
352 Boundary_element_pt[boundary_id - 1].push_back(elem_pt);
355 Face_index_at_boundary[boundary_id - 1].push_back((j + 2) % 3);
360 unsigned tmp_region =
361 static_cast<unsigned> (Tmp_mesh_pt->element_attribute(
e));
363 Boundary_region_element_pt[boundary_id - 1]
364 [tmp_region].push_back(elem_pt);
367 Face_index_region_at_boundary[boundary_id - 1]
368 [tmp_region].push_back((j + 2) % 3);
377 Lookup_for_elements_next_boundary_is_setup =
true;
388 template<
class ELEMENT>
405 unsigned n_repeated_ele = 0;
407 const unsigned n_regions = this->nregion();
411 std::map<FiniteElement*,FiniteElement*> face_to_bulk_element_pt;
420 for (
unsigned rr = 0 ; rr < n_regions; rr++)
422 const unsigned region_id =
423 static_cast<unsigned>(this->Region_attribute[rr]);
426 const unsigned nel_in_region =
427 this->nboundary_element_in_region(b, region_id);
429 unsigned nel_repetead_in_region = 0;
433 if (nel_in_region > 0)
437 bool repeated =
false;
440 for (
unsigned e = 0;
e < nel_in_region;
e++)
444 this->boundary_element_in_region_pt(b, region_id,
e);
448 if (this->is_mesh_distributed() && bulk_elem_pt->
is_halo())
459 this->face_index_at_boundary_in_region(b,region_id,
e);
467 const unsigned n_nodes = tmp_ele_pt->
nnode();
469 std::pair<Node*, Node*> tmp_pair =
470 std::make_pair(tmp_ele_pt->
node_pt(0),
471 tmp_ele_pt->
node_pt(n_nodes - 1));
473 std::pair<Node*, Node*> tmp_pair_inverse =
474 std::make_pair(tmp_ele_pt->
node_pt(n_nodes - 1),
478 const unsigned n_done_nodes = done_nodes_pt.size();
479 for (
unsigned l = 0; l < n_done_nodes; l++)
481 if (tmp_pair == done_nodes_pt[l] ||
482 tmp_pair_inverse == done_nodes_pt[l])
484 nel_repetead_in_region++;
494 done_nodes_pt.push_back(tmp_pair);
496 face_el_pt.push_back(tmp_ele_pt);
498 face_to_bulk_element_pt[tmp_ele_pt] = bulk_elem_pt;
512 nele += nel_in_region;
514 n_repeated_ele += nel_repetead_in_region;
523 nele = this->nboundary_element(b);
530 bool repeated =
false;
533 for (
unsigned e = 0;
e < nele;
e++)
540 if (this->is_mesh_distributed() && bulk_elem_pt->
is_halo())
550 int face_index = this->face_index_at_boundary(b,
e);
558 const unsigned n_nodes = tmp_ele_pt->
nnode();
560 std::pair<Node*, Node*> tmp_pair =
561 std::make_pair(tmp_ele_pt->
node_pt(0),
562 tmp_ele_pt->
node_pt(n_nodes - 1));
564 std::pair<Node*, Node*> tmp_pair_inverse =
565 std::make_pair(tmp_ele_pt->
node_pt(n_nodes - 1),
569 const unsigned n_done_nodes = done_nodes_pt.size();
570 for (
unsigned l = 0; l < n_done_nodes; l++)
572 if (tmp_pair == done_nodes_pt[l] ||
573 tmp_pair_inverse == done_nodes_pt[l])
587 done_nodes_pt.push_back(tmp_pair);
589 face_el_pt.push_back(tmp_ele_pt);
591 face_to_bulk_element_pt[tmp_ele_pt] = bulk_elem_pt;
609 nele-= n_repeated_ele;
612 if (nele!=face_el_pt.size())
614 std::ostringstream error_message;
616 <<
"The independent counting of face elements ("<<nele<<
") for " 617 <<
"boundary ("<<b<<
") is different\n" 618 <<
"from the real number of face elements in the container (" 619 << face_el_pt.size() <<
")\n";
621 "TriangleMesh::identify_boundary_segments_and_assign_initial_zeta_values()",
622 OOMPH_EXCEPTION_LOCATION);
635 std::vector<bool> is_halo_face_element(nele,
false);
638 unsigned nnon_halo_face_elements = 0;
641 for (
unsigned ie = 0; ie < nele; ie++)
646 FiniteElement* tmp_bulk_ele_pt = face_to_bulk_element_pt[face_ele_pt];
648 if (!tmp_bulk_ele_pt->
is_halo())
650 is_halo_face_element[ie] =
false;
651 nnon_halo_face_elements++;
656 is_halo_face_element[ie] =
true;
662 const unsigned nhalo_face_element = nele - nnon_halo_face_elements;
663 if (nhalo_face_element > 0)
665 std::ostringstream error_message;
667 <<
"There should not be halo face elements since they were not " 668 <<
"considered when computing the face elements\n\n" 669 <<
"The number of found halo face elements is: " 670 << nhalo_face_element <<
"\n\n";
672 "TriangleMesh::identify_boundary_segments_and_assign_initial_zeta_values()",
673 OOMPH_EXCEPTION_LOCATION);
683 unsigned nsorted_face_elements = 0;
687 std::map<FiniteElement*, bool> done_el;
691 std::map<FiniteElement*, bool> is_inverted;
694 while(nsorted_face_elements < nnon_halo_face_elements)
698 std::list<FiniteElement*> sorted_el_pt;
699 sorted_el_pt.clear();
703 bool found_initial_face_element =
false;
709 for (iface = 0; iface < nele; iface++)
711 if (!is_halo_face_element[iface])
713 ele_face_pt = face_el_pt[iface];
715 if (!done_el[ele_face_pt])
718 found_initial_face_element =
true;
720 nsorted_face_elements++;
722 sorted_el_pt.push_back(ele_face_pt);
724 done_el[ele_face_pt] =
true;
731 if (!found_initial_face_element)
733 std::ostringstream error_message;
735 <<
"Could not find an initial face element for the current segment\n";
737 "TriangleMesh::identify_boundary_segments_and_assign_initial_zeta_values()",
738 OOMPH_EXCEPTION_LOCATION);
743 const unsigned nnod = ele_face_pt->
nnode();
748 Node* right_node_pt = ele_face_pt->
node_pt(nnod - 1);
752 bool face_element_added =
false;
761 for (
unsigned iiface = iface; iiface < nele; iiface++)
764 face_element_added =
false;
767 ele_face_pt = face_el_pt[iiface];
771 if (!(done_el[ele_face_pt] || is_halo_face_element[iiface]))
774 Node* local_left_node_pt = ele_face_pt->
node_pt(0);
775 Node* local_right_node_pt = ele_face_pt->
node_pt(nnod - 1);
777 if (left_node_pt == local_right_node_pt)
779 left_node_pt = local_left_node_pt;
780 sorted_el_pt.push_front(ele_face_pt);
781 is_inverted[ele_face_pt] =
false;
782 face_element_added =
true;
785 else if (left_node_pt == local_left_node_pt)
787 left_node_pt = local_right_node_pt;
788 sorted_el_pt.push_front(ele_face_pt);
789 is_inverted[ele_face_pt] =
true;
790 face_element_added =
true;
793 else if (right_node_pt == local_left_node_pt)
795 right_node_pt = local_right_node_pt;
796 sorted_el_pt.push_back(ele_face_pt);
797 is_inverted[ele_face_pt] =
false;
798 face_element_added =
true;
801 else if (right_node_pt == local_right_node_pt)
803 right_node_pt = local_left_node_pt;
804 sorted_el_pt.push_back(ele_face_pt);
805 is_inverted[ele_face_pt] =
true;
806 face_element_added =
true;
809 if (face_element_added)
811 done_el[ele_face_pt] =
true;
812 nsorted_face_elements++;
818 }
while(face_element_added &&
819 (nsorted_face_elements < nnon_halo_face_elements));
822 segment_sorted_ele_pt.push_back(sorted_el_pt);
827 const unsigned nsegments = segment_sorted_ele_pt.size();
858 if (nnon_halo_face_elements > 0 && nsegments == 0)
860 std::ostringstream error_message;
862 <<
"The number of segments is zero, but the number of nonhalo\n" 863 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
865 "TriangleMesh::identify_boundary_segments_and_assign_initial_zeta_values()",
866 OOMPH_EXCEPTION_LOCATION);
872 for (
unsigned is = 0; is < nsegments; is++)
875 if (segment_sorted_ele_pt[is].size() == 0)
877 std::ostringstream error_message;
879 <<
"The (" << is <<
")-th segment has no elements\n";
881 "TriangleMesh::identify_boundary_segments_and_assign_initial_zeta_values()",
882 OOMPH_EXCEPTION_LOCATION);
887 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
890 const unsigned nnod = first_ele_pt->
nnode();
893 Node *first_node_pt = first_ele_pt->node_pt(0);
894 if (is_inverted[first_ele_pt])
896 first_node_pt = first_ele_pt->node_pt(nnod-1);
900 FiniteElement* last_ele_pt = segment_sorted_ele_pt[is].back();
904 if (is_inverted[last_ele_pt])
906 last_node_pt = last_ele_pt->node_pt(0);
910 double x_left = first_node_pt->
x(0);
911 double y_left = first_node_pt->
x(1);
920 if (this->boundary_geom_object_pt(b)!=0)
923 initial_zeta_segment[is] = zeta[0];
925 final_zeta_segment[is] = zeta[0];
929 std::set<Node*> local_nodes_pt;
930 local_nodes_pt.insert(first_node_pt);
933 for (std::list<FiniteElement*>::iterator it =
934 segment_sorted_ele_pt[is].begin();
935 it != segment_sorted_ele_pt[is].end(); it++)
943 if (is_inverted[el_pt])
950 for (
unsigned j = 1; j < nnod; j++)
952 Node* nod_pt = el_pt->node_pt(k_nod);
956 double x_right = nod_pt->
x(0);
957 double y_right = nod_pt->
x(1);
961 (x_right - x_left) * (x_right - x_left) + (y_right - y_left)
962 * (y_right - y_left));
979 local_nodes_pt.insert(nod_pt);
985 segment_arclength[is] = zeta[0];
988 nvertices_per_segment[is] = local_nodes_pt.size();
991 segment_all_nodes_pt.push_back(local_nodes_pt);
997 if (segment_all_nodes_pt.size() != nsegments)
999 std::ostringstream error_message;
1001 <<
"The number of segments ("<<nsegments<<
") and the number of " 1002 <<
"sets of nodes ("<<segment_all_nodes_pt.size()<<
") representing\n" 1003 <<
"the\nsegments is different!!!\n\n";
1005 error_message.str(),
1006 OOMPH_CURRENT_FUNCTION,
1007 OOMPH_EXCEPTION_LOCATION);
1035 const unsigned nsegments_initial_coordinates =
1038 const unsigned nsegments_final_coordinates =
1041 if (nsegments_initial_coordinates!=nsegments_final_coordinates)
1043 std::stringstream error_message;
1045 <<
"The number of segments that present initial coordinates " 1046 <<nsegments_initial_coordinates<<
" is different from " 1047 <<
"the\nnumber of segments that present final coordinates " 1048 <<nsegments_final_coordinates<<
"\n\n";
1050 error_message.str(),
1051 OOMPH_CURRENT_FUNCTION,
1052 OOMPH_EXCEPTION_LOCATION);
1057 if (nsegments_initial_coordinates != nsegments)
1059 std::stringstream error_message;
1061 <<
"Working with boundary ("<< b <<
").\n The number of initial and " 1062 <<
"final coordinates (" 1063 <<nsegments_initial_coordinates<<
") is different from\n" 1064 <<
"the number of found segments ("<< nsegments <<
").\n\n";
1066 error_message.str(),
1067 OOMPH_CURRENT_FUNCTION,
1068 OOMPH_EXCEPTION_LOCATION);
1080 Vector<double> original_mesh_segment_initial_arclength(nsegments);
1083 for (
unsigned is = 0; is < nsegments; is++)
1085 original_mesh_segment_initial_coordinate[is].resize(2);
1086 original_mesh_segment_final_coordinate[is].resize(2);
1087 for (
unsigned k = 0; k < 2; k++)
1089 original_mesh_segment_initial_coordinate[is][k] =
1091 original_mesh_segment_final_coordinate[is][k] =
1095 if (this->boundary_geom_object_pt(b)!=0)
1097 original_mesh_segment_initial_zeta[is] =
1099 original_mesh_segment_final_zeta[is] =
1104 original_mesh_segment_initial_arclength[is] =
1106 original_mesh_segment_final_arclength[is] =
1112 Boundary_segment_inverted[b].clear();
1113 Boundary_segment_initial_coordinate[b].clear();
1114 Boundary_segment_final_coordinate[b].clear();
1116 Boundary_segment_initial_zeta[b].clear();
1117 Boundary_segment_final_zeta[b].clear();
1119 Boundary_segment_initial_arclength[b].clear();
1120 Boundary_segment_final_arclength[b].clear();
1126 std::map<unsigned,bool> segment_done;
1127 for (
unsigned is = 0; is < nsegments; is++)
1131 bool found_original_segment =
false;
1140 segment_sorted_ele_pt[is].front();
1143 const unsigned nnod = current_seg_initial_ele_pt->
nnode();
1146 Node *current_seg_first_node_pt=
1147 current_seg_initial_ele_pt->
node_pt(0);
1148 if (is_inverted[current_seg_initial_ele_pt])
1150 current_seg_first_node_pt =
1151 current_seg_initial_ele_pt->node_pt(nnod-1);
1156 segment_sorted_ele_pt[is].back();
1159 Node *current_seg_last_node_pt =
1160 current_seg_last_ele_pt->
node_pt(nnod-1);
1161 if (is_inverted[current_seg_last_ele_pt])
1163 current_seg_last_node_pt =
1164 current_seg_last_ele_pt->node_pt(0);
1168 for (
unsigned i = 0;
i < 2;
i++)
1170 current_seg_initial_coord[
i]=current_seg_first_node_pt->
x(
i);
1171 current_seg_final_coord[
i]=current_seg_last_node_pt->
x(
i);
1178 for (
unsigned orig_s = 0; orig_s < nsegments; orig_s++)
1180 if (!segment_done[orig_s])
1184 original_mesh_segment_initial_coordinate[orig_s];
1186 original_mesh_segment_final_coordinate[orig_s];
1191 ((current_seg_initial_coord[0] - initial_coordinate[0])*
1192 (current_seg_initial_coord[0] - initial_coordinate[0]))
1194 ((current_seg_initial_coord[1] - initial_coordinate[1])*
1195 (current_seg_initial_coord[1] - initial_coordinate[1]));
1205 ((current_seg_final_coord[0] - final_coordinate[0])*
1206 (current_seg_final_coord[0] - final_coordinate[0]))
1208 ((current_seg_final_coord[1] - final_coordinate[1])*
1209 (current_seg_final_coord[1] - final_coordinate[1]));
1219 current_segment_to_original_segment_index[is] = orig_s;
1222 Boundary_segment_inverted[b].push_back(0);
1225 Boundary_segment_initial_coordinate[b].push_back(
1226 initial_coordinate);
1227 Boundary_segment_final_coordinate[b].push_back(
1231 if (this->boundary_geom_object_pt(b)!=0)
1234 Boundary_segment_initial_zeta[b].push_back(
1235 original_mesh_segment_initial_zeta[orig_s]);
1236 Boundary_segment_final_zeta[b].push_back(
1237 original_mesh_segment_final_zeta[orig_s]);
1243 Boundary_segment_initial_arclength[b].push_back(
1244 original_mesh_segment_initial_arclength[orig_s]);
1245 Boundary_segment_final_arclength[b].push_back(
1246 original_mesh_segment_final_arclength[orig_s]);
1249 segment_done[orig_s] =
true;
1251 found_original_segment =
true;
1263 ((current_seg_initial_coord[0] - final_coordinate[0])*
1264 (current_seg_initial_coord[0] - final_coordinate[0]))
1266 ((current_seg_initial_coord[1] - final_coordinate[1])*
1267 (current_seg_initial_coord[1] - final_coordinate[1]));
1268 dist_inv = sqrt(dist_inv);
1278 ((current_seg_final_coord[0] - initial_coordinate[0])*
1279 (current_seg_final_coord[0] - initial_coordinate[0]))
1281 ((current_seg_final_coord[1] - initial_coordinate[1])*
1282 (current_seg_final_coord[1] - initial_coordinate[1]));
1283 dist_inv = sqrt(dist_inv);
1292 current_segment_to_original_segment_index[is] = orig_s;
1295 Boundary_segment_inverted[b].push_back(1);
1298 Boundary_segment_initial_coordinate[b].push_back(
1299 initial_coordinate);
1300 Boundary_segment_final_coordinate[b].push_back(
1304 if (this->boundary_geom_object_pt(b)!=0)
1307 Boundary_segment_initial_zeta[b].push_back(
1308 original_mesh_segment_initial_zeta[orig_s]);
1309 Boundary_segment_final_zeta[b].push_back(
1310 original_mesh_segment_final_zeta[orig_s]);
1315 Boundary_segment_initial_arclength[b].push_back(
1316 original_mesh_segment_initial_arclength[orig_s]);
1317 Boundary_segment_final_arclength[b].push_back(
1318 original_mesh_segment_final_arclength[orig_s]);
1321 segment_done[orig_s] =
true;
1323 found_original_segment =
true;
1338 if (!found_original_segment)
1340 std::stringstream error_message;
1342 <<
"The ("<<is<<
")-th segment on the current segment was not\n" 1343 <<
"found when trying to identify it with the original mesh's\n" 1344 <<
"segment coordinates\n";
1346 OOMPH_CURRENT_FUNCTION,
1347 OOMPH_EXCEPTION_LOCATION);
1368 if (
this != original_mesh_pt)
1381 const double boundary_arclength =
1382 std::max(first_node_zeta_coordinate[0],
1383 last_node_zeta_coordinate[0]);
1385 for (
unsigned is = 0; is < nsegments; is++)
1390 if (boundary_geom_object_pt(b)==0)
1407 FiniteElement* first_ele_pt=segment_sorted_ele_pt[is].front();
1410 const unsigned nnod = first_ele_pt->
nnode();
1414 if (is_inverted[first_ele_pt])
1416 first_node_pt = first_ele_pt->node_pt(nnod-1);
1420 FiniteElement* last_ele_pt=segment_sorted_ele_pt[is].back();
1423 Node *last_node_pt = last_ele_pt->
node_pt(nnod-1);
1424 if (is_inverted[last_ele_pt])
1426 last_node_pt = last_ele_pt->node_pt(0);
1433 if (!Boundary_segment_inverted[b][is])
1436 get_coordinates_on_boundary(b, current_segment_initial_arclen);
1438 get_coordinates_on_boundary(b, current_segment_final_arclen);
1443 get_coordinates_on_boundary(b, current_segment_final_arclen);
1445 get_coordinates_on_boundary(b, current_segment_initial_arclen);
1453 bool increasing_order =
false;
1457 if (current_segment_initial_arclen[0] <
1458 current_segment_final_arclen[0])
1460 increasing_order =
true;
1464 else if (current_segment_initial_arclen[0] >
1465 current_segment_final_arclen[0])
1467 increasing_order =
false;
1472 std::stringstream error_message;
1474 <<
"It was not possible to identify if the zeta values on " 1475 <<
"boundary ("<<b<<
")\nand segment ("<<is<<
") should go in " 1476 <<
"increasing or decreasing order.\n--- New mesh ---\n" 1477 <<
"Current segment initial arclength: (" 1478 << current_segment_initial_arclen[0]<<
")\n" 1479 <<
"First node coordinates: (" 1480 << first_node_pt->
x(0) <<
", " << first_node_pt->
x(1) <<
")\n" 1481 <<
"Current segment final arclength: (" 1482 << current_segment_final_arclen[0]<<
")\n" 1483 <<
"Last node coordinates: (" 1484 << last_node_pt->
x(0) <<
", " << last_node_pt->
x(1) <<
")\n" 1485 <<
"Current segment arclength: (" 1486 << segment_arclength[is] <<
")\n";
1488 OOMPH_CURRENT_FUNCTION,
1489 OOMPH_EXCEPTION_LOCATION);
1495 const unsigned prev_s =
1496 current_segment_to_original_segment_index[is];
1497 const double original_segment_initial_arclength =
1499 const double original_segment_final_arclength =
1504 bool original_increasing_order =
false;
1509 double starting_arclength = 0.0;
1510 if (original_segment_final_arclength >
1511 original_segment_initial_arclength)
1514 original_increasing_order =
true;
1516 starting_arclength = original_segment_initial_arclength;
1518 else if (original_segment_final_arclength <
1519 original_segment_initial_arclength)
1522 original_increasing_order =
false;
1524 starting_arclength = original_segment_final_arclength;
1529 std::stringstream error_message;
1531 <<
"It was not possible to identify if the zeta values on " 1532 <<
"boundary ("<<b<<
")\nand segment ("<<is<<
") should go in " 1533 <<
"increasing or decreasing order.\n--- Original mesh ---\n" 1534 <<
"Original segment initial arclength: (" 1535 << original_segment_initial_arclength<<
")\n" 1536 <<
"Original segment final arclength: (" 1537 << original_segment_final_arclength<<
")\n";
1539 OOMPH_CURRENT_FUNCTION,
1540 OOMPH_EXCEPTION_LOCATION);
1547 if (increasing_order && original_increasing_order)
1563 std::set<Node*> seg_nodes_pt = segment_all_nodes_pt[is];
1566 for (std::set<Node*>::iterator it = seg_nodes_pt.begin();
1567 it != seg_nodes_pt.end(); it++)
1572 Node* nod_pt = (*it);
1577 starting_arclength + (zeta[0] * segment_arclength[is]);
1579 zeta[0] = temp / boundary_arclength;
1581 if (std::fabs(zeta[0] - 1.0) < 1.0e-14)
1585 else if (std::fabs(zeta[0]) < 1.0e-14)
1594 else if (!increasing_order && original_increasing_order)
1610 std::set<Node*> seg_nodes_pt = segment_all_nodes_pt[is];
1613 for (std::set<Node*>::iterator it = seg_nodes_pt.begin();
1614 it != seg_nodes_pt.end(); it++)
1619 Node* nod_pt = (*it);
1624 starting_arclength + ((1.0 - zeta[0]) * segment_arclength[is]);
1626 zeta[0] = temp / boundary_arclength;
1628 if (std::fabs(zeta[0] - 1.0) < 1.0
e-14)
1632 else if (std::fabs(zeta[0]) < 1.0
e-14)
1640 else if (increasing_order && !original_increasing_order)
1656 std::set<Node*> seg_nodes_pt = segment_all_nodes_pt[is];
1659 for (std::set<Node*>::iterator it = seg_nodes_pt.begin();
1660 it != seg_nodes_pt.end(); it++)
1665 Node* nod_pt = (*it);
1670 starting_arclength + ((1.0 - zeta[0]) * segment_arclength[is]);
1672 zeta[0] = temp / boundary_arclength;
1674 if (std::fabs(zeta[0] - 1.0) < 1.0
e-14)
1678 else if (std::fabs(zeta[0]) < 1.0
e-14)
1686 else if (!increasing_order && !original_increasing_order)
1702 std::set<Node*> seg_nodes_pt = segment_all_nodes_pt[is];
1705 for (std::set<Node*>::iterator it = seg_nodes_pt.begin();
1706 it != seg_nodes_pt.end(); it++)
1711 Node* nod_pt = (*it);
1716 starting_arclength + (zeta[0] * segment_arclength[is]);
1718 zeta[0] = temp / boundary_arclength;
1720 if (std::fabs(zeta[0] - 1.0) < 1.0e-14)
1724 else if (std::fabs(zeta[0]) < 1.0e-14)
1736 for (std::list<FiniteElement*>::iterator it_list =
1737 segment_sorted_ele_pt[is].begin();
1738 it_list != segment_sorted_ele_pt[is].end();
1742 const unsigned nnod = (*it_list)->nnode();
1745 Node *first_node_pt = (*it_list)->node_pt(0);
1746 if(is_inverted[(*it_list)])
1748 first_node_pt = (*it_list)->node_pt(nnod-1);
1752 Node *last_node_pt = (*it_list)->node_pt(nnod-1);
1753 if(is_inverted[(*it_list)])
1755 last_node_pt = (*it_list)->node_pt(0);
1761 if (zeta[0] < 0.0 || zeta[0] > 1.0)
1763 std::ostringstream error_message;
1765 <<
"The boundary coordinate of the first node on boundary (" 1766 << b <<
")\nand segment (" << is <<
") is out of the " 1767 <<
"allowed values [0,1]\n" 1768 <<
"The node boundary coordinate: (" << zeta[0] <<
")\n" 1769 <<
"The vertex coordinates are: (" 1770 << first_node_pt->
x(0) <<
", " << first_node_pt->
x(1) <<
")\n";
1772 OOMPH_CURRENT_FUNCTION,
1773 OOMPH_EXCEPTION_LOCATION);
1778 if (zeta[0] < 0.0 || zeta[0] > 1.0)
1780 std::ostringstream error_message;
1782 <<
"The boundary coordinate of the last node on boundary (" 1783 << b <<
")\nand segment (" << is <<
") is out of the " 1784 <<
"allowed values [0,1]\n" 1785 <<
"The node boundary coordinate: (" << zeta[0] <<
")\n" 1786 <<
"The vertex coordinates are: (" 1787 << last_node_pt->
x(0) <<
", " << last_node_pt->
x(1) <<
")\n";
1789 OOMPH_CURRENT_FUNCTION,
1790 OOMPH_EXCEPTION_LOCATION);
1793 #endif // #ifdef PARANOID 1809 Boundary_initial_coordinate[b] =
1812 Boundary_final_coordinate[b] =
1817 Boundary_initial_zeta_coordinate[b] =
1820 Boundary_final_zeta_coordinate[b] =
1827 Assigned_segments_initial_zeta_values[b] =
true;
1830 for (
unsigned i = 0;
i < nele;
i++)
1832 delete face_el_pt[
i];
1844 template<
class ELEMENT>
1857 const unsigned nproc = comm_pt->nproc();
1859 const unsigned my_rank = comm_pt->my_rank();
1867 bool is_internal_boundary =
false;
1871 std::map<FiniteElement*,FiniteElement*> face_to_bulk_element_pt;
1875 select_boundary_face_elements(all_face_ele_pt, b, is_internal_boundary,
1876 face_to_bulk_element_pt);
1879 const unsigned n_all_face_ele = all_face_ele_pt.size();
1887 std::vector<bool> is_halo_face_element(n_all_face_ele,
false);
1890 unsigned nnon_halo_face_elements = 0;
1894 for (
unsigned ie = 0; ie < n_all_face_ele; ie++)
1898 FiniteElement* tmp_bulk_ele_pt = face_to_bulk_element_pt[face_ele_pt];
1900 if (!tmp_bulk_ele_pt->
is_halo())
1903 is_halo_face_element[ie] =
false;
1905 nnon_halo_face_elements++;
1910 is_halo_face_element[ie] =
true;
1916 const unsigned nhalo_face_element = n_all_face_ele - nnon_halo_face_elements;
1924 unsigned nsorted_face_elements = 0;
1928 std::map<FiniteElement*, bool> done_el;
1932 std::map<FiniteElement*, bool> is_inverted;
1935 while(nsorted_face_elements < nnon_halo_face_elements)
1939 std::list<FiniteElement*> sorted_el_pt;
1940 sorted_el_pt.clear();
1945 bool found_initial_face_element =
false;
1951 for (iface = 0; iface < n_all_face_ele; iface++)
1953 if (!is_halo_face_element[iface])
1955 ele_face_pt = all_face_ele_pt[iface];
1957 if (!done_el[ele_face_pt])
1960 found_initial_face_element =
true;
1962 nsorted_face_elements++;
1964 sorted_el_pt.push_back(ele_face_pt);
1966 done_el[ele_face_pt] =
true;
1973 if (!found_initial_face_element)
1975 std::ostringstream error_message;
1977 <<
"Could not find an initial face element for the current segment\n";
1980 OOMPH_CURRENT_FUNCTION,
1981 OOMPH_EXCEPTION_LOCATION);
1986 const unsigned nnod = ele_face_pt->
nnode();
1991 Node* right_node_pt = ele_face_pt->
node_pt(nnod - 1);
1995 bool face_element_added =
false;
2004 for (
unsigned iiface = iface; iiface < n_all_face_ele; iiface++)
2007 face_element_added =
false;
2010 ele_face_pt = all_face_ele_pt[iiface];
2014 if (!(done_el[ele_face_pt] || is_halo_face_element[iiface]))
2017 Node* local_left_node_pt = ele_face_pt->
node_pt(0);
2018 Node* local_right_node_pt = ele_face_pt->
node_pt(nnod - 1);
2021 if (left_node_pt == local_right_node_pt)
2023 left_node_pt = local_left_node_pt;
2024 sorted_el_pt.push_front(ele_face_pt);
2025 is_inverted[ele_face_pt] =
false;
2026 face_element_added =
true;
2029 else if (left_node_pt == local_left_node_pt)
2031 left_node_pt = local_right_node_pt;
2032 sorted_el_pt.push_front(ele_face_pt);
2033 is_inverted[ele_face_pt] =
true;
2034 face_element_added =
true;
2037 else if (right_node_pt == local_left_node_pt)
2039 right_node_pt = local_right_node_pt;
2040 sorted_el_pt.push_back(ele_face_pt);
2041 is_inverted[ele_face_pt] =
false;
2042 face_element_added =
true;
2045 else if (right_node_pt == local_right_node_pt)
2047 right_node_pt = local_left_node_pt;
2048 sorted_el_pt.push_back(ele_face_pt);
2049 is_inverted[ele_face_pt] =
true;
2050 face_element_added =
true;
2053 if (face_element_added)
2055 done_el[ele_face_pt] =
true;
2056 nsorted_face_elements++;
2062 }
while(face_element_added &&
2063 (nsorted_face_elements < nnon_halo_face_elements));
2066 segment_sorted_ele_pt.push_back(sorted_el_pt);
2083 const unsigned nsegments = segment_sorted_ele_pt.size();
2087 if (nnon_halo_face_elements > 0 && nsegments == 0)
2089 std::ostringstream error_message;
2091 <<
"The number of segments is zero, but the number of nonhalo\n" 2092 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
2094 OOMPH_CURRENT_FUNCTION,
2095 OOMPH_EXCEPTION_LOCATION);
2114 for (
unsigned is = 0; is < nsegments; is++)
2117 if (segment_sorted_ele_pt[is].size() == 0)
2119 std::ostringstream error_message;
2121 <<
"The (" << is <<
")-th segment has no elements\n";
2123 OOMPH_CURRENT_FUNCTION,
2124 OOMPH_EXCEPTION_LOCATION);
2129 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
2132 const unsigned nnod = first_ele_pt->nnode();
2135 Node *first_node_pt = first_ele_pt->node_pt(0);
2136 if (is_inverted[first_ele_pt])
2138 first_node_pt = first_ele_pt->node_pt(nnod-1);
2142 double x_left = first_node_pt->
x(0);
2143 double y_left = first_node_pt->
x(1);
2152 if (this->boundary_geom_object_pt(b)!=0)
2157 initial_zeta_segment[is] = zeta[0];
2160 FiniteElement* last_ele_pt = segment_sorted_ele_pt[is].back();
2163 Node *last_node_pt = last_ele_pt->
node_pt(nnod-1);
2164 if (is_inverted[last_ele_pt])
2166 last_node_pt = last_ele_pt->node_pt(0);
2172 final_zeta_segment[is] = zeta[0];
2178 std::set<Node*> local_nodes_pt;
2180 local_nodes_pt.insert(first_node_pt);
2183 for (std::list<FiniteElement*>::iterator it =
2184 segment_sorted_ele_pt[is].begin();
2185 it != segment_sorted_ele_pt[is].end(); it++)
2194 if (is_inverted[el_pt])
2201 for (
unsigned j = 1; j < nnod; j++)
2203 Node* nod_pt = el_pt->node_pt(k_nod);
2207 double x_right = nod_pt->
x(0);
2208 double y_right = nod_pt->
x(1);
2212 (x_right - x_left) * (x_right - x_left) + (y_right - y_left)
2213 * (y_right - y_left));
2230 local_nodes_pt.insert(nod_pt);
2239 segment_arclength[is] = zeta[0];
2244 nvertices_per_segment[is] = local_nodes_pt.size();
2247 segment_all_nodes_pt.push_back(local_nodes_pt);
2269 unsigned proc_with_initial_seg = 0;
2270 unsigned proc_with_final_seg = 0;
2274 unsigned initial_segment = 0;
2275 unsigned final_segment = 0;
2284 for (
unsigned is = 0; is < nsegments; is++)
2286 for (std::list<FiniteElement*>::iterator it_seg =
2287 segment_sorted_ele_pt[is].begin();
2288 it_seg != segment_sorted_ele_pt[is].end();
2291 segment_sorted_nonhalo_ele_pt[is].push_back((*it_seg));
2298 for (
unsigned is = 0; is < nsegments; is++)
2301 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
2304 const unsigned nnod = first_ele_pt->
nnode();
2308 if (is_inverted[first_ele_pt])
2310 first_node_pt = first_ele_pt->node_pt(nnod-1);
2314 FiniteElement* last_ele_pt = segment_sorted_ele_pt[is].back();
2317 Node *last_node_pt = last_ele_pt->
node_pt(nnod-1);
2318 if (is_inverted[last_ele_pt])
2320 last_node_pt = last_ele_pt->node_pt(0);
2327 bool attached_left_halo =
false;
2328 bool attached_right_halo =
false;
2329 if (nhalo_face_element > 0)
2331 for (
unsigned iiface = 0; iiface < n_all_face_ele; iiface++)
2347 if (is_halo_face_element[iiface])
2350 Node* left_node_pt = halo_face_ele_pt->
node_pt(0);
2351 Node* right_node_pt = halo_face_ele_pt->
node_pt(nnod-1);
2353 if (!attached_left_halo && (first_node_pt == right_node_pt ||
2354 first_node_pt == left_node_pt))
2357 segment_sorted_ele_pt[is].push_front(halo_face_ele_pt);
2361 attached_left_halo =
true;
2364 else if (!attached_right_halo && (last_node_pt == left_node_pt ||
2365 last_node_pt == right_node_pt))
2368 segment_sorted_ele_pt[is].push_back(halo_face_ele_pt);
2371 attached_right_halo =
true;
2375 if (attached_left_halo && attached_right_halo)
2425 for (
unsigned is = 0; is < nsegments; is++)
2428 FiniteElement* left_face_ele_pt=segment_sorted_ele_pt[is].front();
2433 face_to_bulk_element_pt[left_face_ele_pt];
2436 if (tmp_left_bulk_ele_pt->
is_halo())
2443 std::ostringstream error_message;
2445 <<
"The current bulk element (left) is marked as halo but " 2446 <<
"the processor holding\nthe non-halo counterpart is " 2449 OOMPH_CURRENT_FUNCTION,
2450 OOMPH_EXCEPTION_LOCATION);
2454 unsigned left_processor =
static_cast<unsigned>(left_proc);
2455 left_processor_plus_one[is] = left_processor + 1;
2462 this->halo_element_pt(left_processor);
2466 bool left_halo_element_found =
false;
2469 const unsigned n_halo_left = left_halo_element_pt.size();
2470 for (
unsigned lh = 0; lh < n_halo_left; lh++)
2472 if (left_element_pt == left_halo_element_pt[lh])
2474 left_halo_element[is] = lh;
2476 left_halo_element_found =
true;
2483 if (!left_halo_element_found)
2485 std::ostringstream error_message;
2487 <<
"The current bulk element (left) marked as halo was " 2488 <<
"not found in the vector of halo\nelements associated " 2489 <<
"with the (" << left_processor <<
") processor.\n\n";
2491 OOMPH_CURRENT_FUNCTION,
2492 OOMPH_EXCEPTION_LOCATION);
2498 left_face_ele_pt = segment_sorted_nonhalo_ele_pt[is].front();
2501 tmp_left_bulk_ele_pt = face_to_bulk_element_pt[left_face_ele_pt];
2505 if (tmp_left_bulk_ele_pt->
is_halo())
2507 std::ostringstream error_message;
2509 <<
"The bulk element represetation of the left-most nonhalo face\n" 2510 <<
"element of the current segment ("<<is<<
") is marked as halo,\n" 2511 <<
"but the face element created from it is nonhalo\n";
2513 OOMPH_CURRENT_FUNCTION,
2514 OOMPH_EXCEPTION_LOCATION);
2520 left_element_pt = tmp_left_bulk_ele_pt;
2524 bool left_haloed_element_found =
false;
2530 this->haloed_element_pt(left_processor);
2532 const unsigned nhaloed_left = left_haloed_element_pt.size();
2533 for (
unsigned lhd = 0; lhd < nhaloed_left; lhd++)
2535 if (left_element_pt == left_haloed_element_pt[lhd])
2537 left_haloed_element[is] = lhd;
2539 left_haloed_element_found =
true;
2546 if (!left_haloed_element_found)
2548 std::ostringstream error_message;
2550 <<
"The current bulk element (left) marked as haloed was " 2551 <<
"not found in the vector of haloed\nelements associated " 2552 <<
"with processor ("<< left_processor <<
").\n";
2554 OOMPH_CURRENT_FUNCTION,
2555 OOMPH_EXCEPTION_LOCATION);
2562 left_processor_plus_one[is] = 0;
2564 left_halo_element[is] = 0;
2566 left_haloed_element[is] = 0;
2570 FiniteElement* right_face_ele_pt = segment_sorted_ele_pt[is].back();
2575 face_to_bulk_element_pt[right_face_ele_pt];
2578 if (tmp_right_bulk_ele_pt->
is_halo())
2585 std::ostringstream error_message;
2587 <<
"The current bulk element (right) is marked as halo but " 2588 <<
"the processor holding\nthe non-halo counterpart is " 2591 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
2592 OOMPH_EXCEPTION_LOCATION);
2596 unsigned right_processor =
static_cast<unsigned>(right_proc);
2597 right_processor_plus_one[is] = right_processor + 1;
2604 this->halo_element_pt(right_processor);
2608 bool right_halo_element_found =
false;
2611 const unsigned nhalo_right = right_halo_element_pt.size();
2612 for (
unsigned rh = 0; rh < nhalo_right; rh++)
2614 if (right_element_pt == right_halo_element_pt[rh])
2616 right_halo_element[is] = rh;
2618 right_halo_element_found =
true;
2624 if (!right_halo_element_found)
2626 std::ostringstream error_message;
2628 <<
"The current bulk element (right) marked as halo was not " 2629 <<
"found in the vector of halo\nelements associated with " 2630 <<
"the (" << right_processor <<
") processor.\n\n";
2632 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
2633 OOMPH_EXCEPTION_LOCATION);
2639 right_face_ele_pt = segment_sorted_nonhalo_ele_pt[is].back();
2642 tmp_right_bulk_ele_pt=face_to_bulk_element_pt[right_face_ele_pt];
2645 if (tmp_right_bulk_ele_pt->
is_halo())
2647 std::ostringstream error_message;
2649 <<
"The bulk element represetation of the right-most nonhalo face\n" 2650 <<
"element of the current segment ("<<is<<
") is marked as halo,\n" 2651 <<
"but the face element created from it is nonhalo\n";
2653 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
2654 OOMPH_EXCEPTION_LOCATION);
2660 right_element_pt = tmp_right_bulk_ele_pt;
2664 bool right_haloed_element_found =
false;
2669 this->haloed_element_pt(right_processor);
2671 const unsigned nhaloed_right = right_haloed_element_pt.size();
2672 for (
unsigned rhd = 0; rhd < nhaloed_right; rhd++)
2674 if (right_element_pt == right_haloed_element_pt[rhd])
2676 right_haloed_element[is] = rhd;
2678 right_haloed_element_found =
true;
2685 if (!right_haloed_element_found)
2687 std::ostringstream error_message;
2689 <<
"The current bulk element (right) marked as haloed was not " 2690 <<
"found in the vector of haloed\nelements associated with " 2691 <<
"the ("<< right_processor <<
") processor.\n\n";
2693 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
2694 OOMPH_EXCEPTION_LOCATION);
2702 right_processor_plus_one[is] = 0;
2704 right_halo_element[is] = 0;
2706 right_haloed_element[is] = 0;
2722 const unsigned root_processor = 0;
2729 unsigned nsegments_mpi = nsegments;
2730 MPI_Gather(&nsegments_mpi, 1, MPI_UNSIGNED,
2731 &root_nsegments_per_processor[0], 1, MPI_UNSIGNED,
2732 root_processor, comm_pt->mpi_comm());
2740 const unsigned spu = 7;
2742 for (
unsigned is = 0; is < nsegments; is++)
2744 flat_packed_unsigned_send_data[(spu*is)+0]=left_processor_plus_one[is];
2745 flat_packed_unsigned_send_data[(spu*is)+1]=right_processor_plus_one[is];
2746 flat_packed_unsigned_send_data[(spu*is)+2]=left_halo_element[is];
2747 flat_packed_unsigned_send_data[(spu*is)+3]=right_halo_element[is];
2748 flat_packed_unsigned_send_data[(spu*is)+4]=left_haloed_element[is];
2749 flat_packed_unsigned_send_data[(spu*is)+5]=right_haloed_element[is];
2750 flat_packed_unsigned_send_data[(spu*is)+6]=nvertices_per_segment[is];
2754 const unsigned nudata_to_send = flat_packed_unsigned_send_data.size();
2760 unsigned root_nutotal_data_receive = 0;
2761 for (
unsigned ip = 0; ip < nproc; ip++)
2765 root_nudata_to_receive[ip] = root_nsegments_per_processor[ip] * spu;
2767 root_nutotal_data_receive+= root_nudata_to_receive[ip];
2773 root_uoffsets_receive[0] = 0;
2774 for (
unsigned ip = 1; ip < nproc; ip++)
2777 root_uoffsets_receive[ip] =
2778 root_uoffsets_receive[ip-1] + root_nudata_to_receive[ip-1];
2782 if (flat_packed_unsigned_send_data.size()==0)
2784 flat_packed_unsigned_send_data.resize(1);
2789 root_nutotal_data_receive);
2790 if (my_rank!=root_processor)
2793 if (flat_packed_unsigned_receive_data.size()==0)
2795 flat_packed_unsigned_receive_data.resize(1);
2799 MPI_Gatherv(&flat_packed_unsigned_send_data[0],
2805 &flat_packed_unsigned_receive_data[0],
2810 &root_nudata_to_receive[0],
2812 &root_uoffsets_receive[0],
2817 comm_pt->mpi_comm());
2820 flat_packed_unsigned_send_data.clear();
2821 flat_packed_unsigned_send_data.resize(0);
2827 const unsigned spd = 1;
2829 for (
unsigned is = 0; is < nsegments; is++)
2831 flat_packed_double_send_data[(spd*is)+0]=segment_arclength[is];
2835 const unsigned nddata_to_send = flat_packed_double_send_data.size();
2840 unsigned root_ndtotal_data_receive = 0;
2841 for (
unsigned ip =0; ip < nproc; ip++)
2843 root_nddata_to_receive[ip] = root_nsegments_per_processor[ip] * spd;
2844 root_ndtotal_data_receive+= root_nddata_to_receive[ip];
2850 root_doffsets_receive[0] = 0;
2851 for (
unsigned ip = 1; ip < nproc; ip++)
2854 root_doffsets_receive[ip] =
2855 root_doffsets_receive[ip-1] + root_nddata_to_receive[ip-1];
2859 if (flat_packed_double_send_data.size()==0)
2861 flat_packed_double_send_data.resize(1);
2865 Vector<double> flat_packed_double_receive_data(root_ndtotal_data_receive);
2866 if (my_rank!=root_processor)
2869 if (flat_packed_double_receive_data.size()==0)
2871 flat_packed_double_receive_data.resize(1);
2875 MPI_Gatherv(&flat_packed_double_send_data[0],
2881 &flat_packed_double_receive_data[0],
2885 &root_nddata_to_receive[0],
2887 &root_doffsets_receive[0],
2892 comm_pt->mpi_comm());
2895 flat_packed_double_send_data.clear();
2896 flat_packed_double_send_data.resize(0);
2918 double root_accumulated_arclength = 0.0;
2922 unsigned root_accumulated_vertices_before_segment = 0;
2926 if (my_rank == root_processor)
2972 unsigned ucounter = 0;
2973 unsigned dcounter = 0;
2974 for (
unsigned ip = 0; ip < nproc; ip++)
2977 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
2979 root_left_processor_plus_one[ip].resize(nsegs_iproc);
2980 root_right_processor_plus_one[ip].resize(nsegs_iproc);
2981 root_left_halo_element[ip].resize(nsegs_iproc);
2982 root_right_halo_element[ip].resize(nsegs_iproc);
2983 root_left_haloed_element[ip].resize(nsegs_iproc);
2984 root_right_haloed_element[ip].resize(nsegs_iproc);
2987 root_nvertices_per_segment[ip].resize(nsegs_iproc);
2988 root_segment_arclength[ip].resize(nsegs_iproc);
2989 root_segment_inverted[ip].resize(nsegs_iproc);
2993 for(
unsigned is = 0; is < nsegs_iproc; is++)
2996 root_left_processor_plus_one[ip][is] =
2997 flat_packed_unsigned_receive_data[ucounter++];
2998 root_right_processor_plus_one[ip][is] =
2999 flat_packed_unsigned_receive_data[ucounter++];
3000 root_left_halo_element[ip][is] =
3001 flat_packed_unsigned_receive_data[ucounter++];
3002 root_right_halo_element[ip][is] =
3003 flat_packed_unsigned_receive_data[ucounter++];
3004 root_left_haloed_element[ip][is] =
3005 flat_packed_unsigned_receive_data[ucounter++];
3006 root_right_haloed_element[ip][is] =
3007 flat_packed_unsigned_receive_data[ucounter++];
3008 root_nvertices_per_segment[ip][is] =
3009 flat_packed_unsigned_receive_data[ucounter++];
3012 root_segment_arclength[ip][is] =
3013 flat_packed_double_receive_data[dcounter++];
3024 for (
unsigned ip = 0; ip < nproc; ip++)
3026 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3027 left_connected_segment_plus_one[ip].resize(nsegs_iproc,-1);
3028 right_connected_segment_plus_one[ip].resize(nsegs_iproc,-1);
3033 std::list<std::pair<unsigned, unsigned> > proc_seg_connectivity;
3034 proc_seg_connectivity.clear();
3037 std::map<std::pair<unsigned, unsigned>,
bool> done_segment;
3041 unsigned left_proc = 0;
3042 unsigned right_proc = 0;
3043 unsigned left_seg = 0;
3044 unsigned right_seg = 0;
3045 for (
unsigned ip = 0; ip < nproc; ip++)
3047 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3048 if (nsegs_iproc > 0)
3050 right_proc = left_proc = ip;
3051 right_seg = left_seg = 0;
3058 std::pair<unsigned, unsigned> add_segment =
3059 std::make_pair(left_proc, left_seg);
3060 done_segment[add_segment] =
true;
3061 proc_seg_connectivity.push_back(add_segment);
3065 bool added_segment_to_the_left =
false;
3066 bool added_segment_to_the_right =
false;
3071 std::pair<unsigned, unsigned> left_pair =
3072 proc_seg_connectivity.front();
3073 left_proc = left_pair.first;
3074 left_seg = left_pair.second;
3078 const unsigned new_left_proc =
3079 root_left_processor_plus_one[left_proc][left_seg];
3081 if (new_left_proc != 0)
3084 added_segment_to_the_left =
false;
3086 const unsigned left_halo_id =
3087 root_left_halo_element[left_proc][left_seg];
3090 const unsigned left_haloed_id =
3091 root_left_haloed_element[left_proc][left_seg];
3095 const unsigned nsegs_new_left_proc =
3096 root_nsegments_per_processor[new_left_proc-1];
3098 for (
unsigned ils = 0; ils < nsegs_new_left_proc; ils++)
3100 std::pair<unsigned, unsigned> candidate_seg =
3101 std::make_pair(new_left_proc-1, ils);
3104 if (!done_segment[candidate_seg])
3108 const unsigned right_proc_of_new_left_proc =
3109 root_right_processor_plus_one[new_left_proc-1][ils];
3112 const unsigned left_proc_of_new_left_proc =
3113 root_left_processor_plus_one[new_left_proc-1][ils];
3116 if (right_proc_of_new_left_proc != 0 &&
3117 right_proc_of_new_left_proc-1 == left_proc)
3122 const unsigned right_halo_id =
3123 root_right_halo_element[new_left_proc-1][ils];
3124 const unsigned right_haloed_id =
3125 root_right_haloed_element[new_left_proc-1][ils];
3126 if (left_halo_id == right_haloed_id &&
3127 left_haloed_id == right_halo_id)
3131 left_connected_segment_plus_one[left_proc][left_seg]=
3134 proc_seg_connectivity.push_front(candidate_seg);
3135 added_segment_to_the_left =
true;
3141 if (left_proc_of_new_left_proc != 0 &&
3142 left_proc_of_new_left_proc-1 == left_proc)
3147 const unsigned inv_left_halo_id =
3148 root_left_halo_element[new_left_proc-1][ils];
3149 const unsigned inv_left_haloed_id =
3150 root_left_haloed_element[new_left_proc-1][ils];
3151 if (left_halo_id == inv_left_haloed_id &&
3152 left_haloed_id == inv_left_halo_id)
3156 left_connected_segment_plus_one[left_proc][left_seg]=
3159 proc_seg_connectivity.push_front(candidate_seg);
3163 const unsigned tmp_proc =
3164 root_left_processor_plus_one[new_left_proc-1][ils];
3165 const unsigned tmp_halo =
3166 root_left_halo_element[new_left_proc-1][ils];
3167 const unsigned tmp_haloed =
3168 root_left_haloed_element[new_left_proc-1][ils];
3170 root_left_processor_plus_one[new_left_proc-1][ils] =
3171 root_right_processor_plus_one[new_left_proc-1][ils];
3172 root_left_halo_element[new_left_proc-1][ils] =
3173 root_right_halo_element[new_left_proc-1][ils];
3174 root_left_haloed_element[new_left_proc-1][ils] =
3175 root_right_haloed_element[new_left_proc-1][ils];
3177 root_right_processor_plus_one[new_left_proc-1][ils] =
3179 root_right_halo_element[new_left_proc-1][ils]=tmp_halo;
3180 root_right_haloed_element[new_left_proc-1][ils] =
3185 root_segment_inverted[new_left_proc-1][ils] = 1;
3187 added_segment_to_the_left =
true;
3195 if (!added_segment_to_the_left)
3197 std::ostringstream error_message;
3199 <<
"The corresponding processor and segment to the left of " 3200 <<
"the current left\nmost segment was not found\n";
3202 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
3203 OOMPH_EXCEPTION_LOCATION);
3210 added_segment_to_the_left =
false;
3214 std::pair<unsigned, unsigned> right_pair =
3215 proc_seg_connectivity.back();
3216 right_proc = right_pair.first;
3217 right_seg = right_pair.second;
3221 const unsigned new_right_proc =
3222 root_right_processor_plus_one[right_proc][right_seg];
3224 if (new_right_proc != 0)
3227 added_segment_to_the_right =
false;
3229 const unsigned right_halo_id =
3230 root_right_halo_element[right_proc][right_seg];
3233 const unsigned right_haloed_id =
3234 root_right_haloed_element[right_proc][right_seg];
3238 const unsigned nsegs_new_right_proc =
3239 root_nsegments_per_processor[new_right_proc-1];
3241 for (
unsigned irs = 0; irs < nsegs_new_right_proc; irs++)
3243 std::pair<unsigned, unsigned> candidate_seg =
3244 std::make_pair(new_right_proc-1, irs);
3247 if (!done_segment[candidate_seg])
3251 const unsigned left_proc_of_new_right_proc =
3252 root_left_processor_plus_one[new_right_proc-1][irs];
3255 const unsigned right_proc_of_new_right_proc =
3256 root_right_processor_plus_one[new_right_proc-1][irs];
3259 if (left_proc_of_new_right_proc != 0 &&
3260 left_proc_of_new_right_proc-1 == right_proc)
3265 const unsigned left_halo_id =
3266 root_left_halo_element[new_right_proc-1][irs];
3267 const unsigned left_haloed_id =
3268 root_left_haloed_element[new_right_proc-1][irs];
3270 if (right_halo_id == left_haloed_id &&
3271 right_haloed_id == left_halo_id)
3275 right_connected_segment_plus_one[right_proc][right_seg]=
3278 proc_seg_connectivity.push_back(candidate_seg);
3279 added_segment_to_the_right =
true;
3285 if (right_proc_of_new_right_proc != 0 &&
3286 right_proc_of_new_right_proc-1 == right_proc)
3292 const unsigned inv_right_halo_id =
3293 root_right_halo_element[new_right_proc-1][irs];
3294 const unsigned inv_right_haloed_id =
3295 root_right_haloed_element[new_right_proc-1][irs];
3296 if (right_halo_id == inv_right_haloed_id &&
3297 right_haloed_id == inv_right_halo_id)
3301 right_connected_segment_plus_one[right_proc][right_seg]=
3304 proc_seg_connectivity.push_back(candidate_seg);
3307 const unsigned tmp_proc =
3308 root_left_processor_plus_one[new_right_proc-1][irs];
3309 const unsigned tmp_halo =
3310 root_left_halo_element[new_right_proc-1][irs];
3311 const unsigned tmp_haloed =
3312 root_left_haloed_element[new_right_proc-1][irs];
3314 root_left_processor_plus_one[new_right_proc-1][irs] =
3315 root_right_processor_plus_one[new_right_proc-1][irs];
3316 root_left_halo_element[new_right_proc-1][irs] =
3317 root_right_halo_element[new_right_proc-1][irs];
3318 root_left_haloed_element[new_right_proc-1][irs] =
3319 root_right_haloed_element[new_right_proc-1][irs];
3321 root_right_processor_plus_one[new_right_proc-1][irs] =
3323 root_right_halo_element[new_right_proc-1][irs]=tmp_halo;
3324 root_right_haloed_element[new_right_proc-1][irs] =
3329 root_segment_inverted[new_right_proc-1][irs] = 1;
3331 added_segment_to_the_right =
true;
3339 if (!added_segment_to_the_right)
3341 std::ostringstream error_message;
3343 <<
"The corresponding processor and segment to the right of " 3344 <<
"the current right\nmost segment was not found\n";
3346 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
3347 OOMPH_EXCEPTION_LOCATION);
3354 added_segment_to_the_right =
false;
3357 }
while(added_segment_to_the_left || added_segment_to_the_right);
3365 const unsigned ntotal_segments = proc_seg_connectivity.size();
3367 unsigned tmp_total_segments = 0;
3368 for (
unsigned ip =0; ip < nproc; ip++)
3370 tmp_total_segments+= root_nsegments_per_processor[ip];
3375 if (ntotal_segments!=tmp_total_segments)
3377 std::ostringstream error_message;
3379 <<
"The number of sorted segments (" << ntotal_segments <<
") on " 3380 <<
"boundary ("<< b <<
")\nis different from the total number of " 3381 <<
"segments ("<< tmp_total_segments <<
") in all\nprocessors.\n\n";
3383 OOMPH_CURRENT_FUNCTION,
3384 OOMPH_EXCEPTION_LOCATION);
3393 for (
unsigned ip = 0; ip < nproc; ip++)
3395 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3396 root_initial_segment_arclength[ip].resize(nsegs_iproc);
3397 root_nvertices_before_segment[ip].resize(nsegs_iproc);
3404 for (std::list<std::pair<unsigned, unsigned> >::iterator
3405 it_list = proc_seg_connectivity.begin();
3406 it_list != proc_seg_connectivity.end(); it_list++)
3408 const unsigned iproc =
static_cast<unsigned>((*it_list).first);
3409 const unsigned iseg =
static_cast<unsigned>((*it_list).second);
3410 const double iseg_arclength = root_segment_arclength[iproc][iseg];
3411 const unsigned iseg_nvertices = root_nvertices_per_segment[iproc][iseg];
3413 aux_initial_segment_arclength[ucounter] = root_accumulated_arclength;
3414 aux_nvertices_before_segment[ucounter] =
3415 root_accumulated_vertices_before_segment;
3418 root_initial_segment_arclength[iproc][iseg] = root_accumulated_arclength;
3420 root_nvertices_before_segment[iproc][iseg] =
3421 root_accumulated_vertices_before_segment;
3424 root_accumulated_arclength+= iseg_arclength;
3426 root_accumulated_vertices_before_segment+= iseg_nvertices - 1;
3435 root_accumulated_vertices_before_segment++;
3438 proc_with_initial_seg = proc_seg_connectivity.front().first;
3439 proc_with_final_seg = proc_seg_connectivity.back().first;
3442 initial_segment = proc_seg_connectivity.front().second;
3443 final_segment = proc_seg_connectivity.back().second;
3448 unsigned root_ntotal_segments = 0;
3449 for (
unsigned ip =0; ip < nproc; ip++)
3451 root_ntotal_segments+= root_nsegments_per_processor[ip];
3458 const unsigned rspu = 2;
3459 flat_packed_unsigned_send_data.clear();
3460 flat_packed_unsigned_send_data.resize(root_ntotal_segments*rspu);
3461 unsigned ucounter = 0;
3463 for (
unsigned ip = 0; ip < nproc; ip++)
3465 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3466 for (
unsigned is = 0; is < nsegs_iproc; is++)
3468 flat_packed_unsigned_send_data[ucounter++] =
3469 root_nvertices_before_segment[ip][is];
3470 flat_packed_unsigned_send_data[ucounter++] =
3471 root_segment_inverted[ip][is];
3477 for (
unsigned ip =0; ip < nproc; ip++)
3480 root_nudata_to_send[ip] = root_nsegments_per_processor[ip] * rspu;
3485 root_uoffsets_send[0] = 0;
3486 for (
unsigned ip = 1; ip < nproc; ip++)
3489 root_uoffsets_send[ip] =
3490 root_uoffsets_send[ip-1] + root_nudata_to_send[ip-1];
3494 unsigned nutotal_data_receive = nsegments * rspu;
3496 if (my_rank!=root_processor)
3499 if (flat_packed_unsigned_send_data.size()==0)
3501 flat_packed_unsigned_send_data.resize(1);
3506 flat_packed_unsigned_receive_data.clear();
3507 flat_packed_unsigned_receive_data.resize(nutotal_data_receive);
3509 if (flat_packed_unsigned_receive_data.size()==0)
3511 flat_packed_unsigned_receive_data.resize(1);
3514 MPI_Scatterv(&flat_packed_unsigned_send_data[0],
3515 &root_nudata_to_send[0],
3516 &root_uoffsets_send[0],
3518 &flat_packed_unsigned_receive_data[0],
3519 nutotal_data_receive,
3522 comm_pt->mpi_comm());
3527 const unsigned rspd = 1;
3528 flat_packed_double_send_data.clear();
3529 flat_packed_double_send_data.resize(root_ntotal_segments*rspd);
3530 unsigned dcounter = 0;
3532 for (
unsigned ip = 0; ip < nproc; ip++)
3534 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3535 for (
unsigned is = 0; is < nsegs_iproc; is++)
3537 flat_packed_double_send_data[dcounter++] =
3538 root_initial_segment_arclength[ip][is];
3544 for (
unsigned ip =0; ip < nproc; ip++)
3547 root_nddata_to_send[ip] = root_nsegments_per_processor[ip] * rspd;
3552 root_doffsets_send[0] = 0;
3553 for (
unsigned ip = 1; ip < nproc; ip++)
3556 root_doffsets_send[ip] =
3557 root_doffsets_send[ip-1] + root_nddata_to_send[ip-1];
3561 unsigned ndtotal_data_receive = nsegments * rspd;
3563 if (my_rank!=root_processor)
3566 if (flat_packed_double_send_data.size()==0)
3568 flat_packed_double_send_data.resize(1);
3573 flat_packed_double_receive_data.clear();
3574 flat_packed_double_receive_data.resize(ndtotal_data_receive);
3576 if (flat_packed_double_receive_data.size()==0)
3578 flat_packed_double_receive_data.resize(1);
3581 MPI_Scatterv(&flat_packed_double_send_data[0],
3582 &root_nddata_to_send[0],
3583 &root_doffsets_send[0],
3585 &flat_packed_double_receive_data[0],
3586 ndtotal_data_receive,
3589 comm_pt->mpi_comm());
3598 for (
unsigned is = 0; is < nsegments; is++)
3601 nvertices_before_segment[is] =
3602 flat_packed_unsigned_receive_data[ucounter++];
3604 segment_inverted[is] = flat_packed_unsigned_receive_data[ucounter++];
3606 initial_segment_arclength[is] =
3607 flat_packed_double_receive_data[dcounter++];
3613 const unsigned numore_info = 5;
3616 flat_package_unsigned_more_info[0] = root_accumulated_vertices_before_segment;
3617 flat_package_unsigned_more_info[1] = proc_with_initial_seg;
3618 flat_package_unsigned_more_info[2] = proc_with_final_seg;
3619 flat_package_unsigned_more_info[3] = initial_segment;
3620 flat_package_unsigned_more_info[4] = final_segment;
3623 MPI_Bcast(&flat_package_unsigned_more_info[0], numore_info,
3624 MPI_UNSIGNED, root_processor, comm_pt->mpi_comm());
3627 root_accumulated_vertices_before_segment = flat_package_unsigned_more_info[0];
3628 proc_with_initial_seg = flat_package_unsigned_more_info[1];
3629 proc_with_final_seg = flat_package_unsigned_more_info[2];
3630 initial_segment = flat_package_unsigned_more_info[3];
3631 final_segment = flat_package_unsigned_more_info[4];
3634 MPI_Bcast(&root_accumulated_arclength, 1, MPI_DOUBLE,
3635 root_processor, comm_pt->mpi_comm());
3644 Boundary_initial_coordinate[b].clear();
3645 Boundary_final_coordinate[b].clear();
3647 Boundary_initial_zeta_coordinate[b].clear();
3648 Boundary_final_zeta_coordinate[b].clear();
3651 Boundary_segment_inverted[b].clear();
3652 Boundary_segment_initial_coordinate[b].clear();
3653 Boundary_segment_final_coordinate[b].clear();
3655 Boundary_segment_initial_zeta[b].clear();
3656 Boundary_segment_final_zeta[b].clear();
3658 Boundary_segment_initial_arclength[b].clear();
3659 Boundary_segment_final_arclength[b].clear();
3663 for (
unsigned is = 0; is < nsegments; is++)
3676 segment_sorted_nonhalo_ele_pt[is].front();
3681 if (first_seg_ele_pt->
is_halo())
3683 std::ostringstream error_message;
3685 <<
"The first face element in the (" << is <<
")-th segment is halo\n";
3687 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
3688 OOMPH_EXCEPTION_LOCATION);
3693 const unsigned nnod = first_seg_ele_pt->
nnode();
3696 Node *first_seg_node_pt = first_seg_ele_pt->
node_pt(0);
3697 if (is_inverted[first_seg_ele_pt])
3699 first_seg_node_pt = first_seg_ele_pt->node_pt(nnod-1);
3704 segment_sorted_nonhalo_ele_pt[is].back();
3709 if (last_seg_ele_pt->
is_halo())
3711 std::ostringstream error_message;
3713 <<
"The last face element in the (" << is <<
")-th segment is halo\n";
3715 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
3716 OOMPH_EXCEPTION_LOCATION);
3721 Node *last_seg_node_pt = last_seg_ele_pt->
node_pt(nnod-1);
3722 if (is_inverted[last_seg_ele_pt])
3724 last_seg_node_pt = last_seg_ele_pt->node_pt(0);
3728 for (
unsigned i = 0;
i < 2;
i++)
3730 first_seg_coord[
i] = first_seg_node_pt->
x(
i);
3731 last_seg_coord[
i] = last_seg_node_pt->x(
i);
3736 Boundary_segment_inverted[b].push_back(segment_inverted[is]);
3740 if (!segment_inverted[is])
3744 Boundary_segment_initial_coordinate[b].push_back(first_seg_coord);
3745 Boundary_segment_final_coordinate[b].push_back(last_seg_coord);
3752 Boundary_segment_initial_coordinate[b].push_back(last_seg_coord);
3753 Boundary_segment_final_coordinate[b].push_back(first_seg_coord);
3760 if (boundary_geom_object_pt(b)!=0)
3765 if (segment_inverted[is])
3767 Boundary_segment_initial_zeta[b].push_back(final_zeta_segment[is]);
3768 Boundary_segment_final_zeta[b].push_back(initial_zeta_segment[is]);
3772 Boundary_segment_initial_zeta[b].push_back(initial_zeta_segment[is]);
3773 Boundary_segment_final_zeta[b].push_back(final_zeta_segment[is]);
3780 Boundary_segment_initial_arclength[b].push_back(
3781 initial_segment_arclength[is]);
3783 Boundary_segment_final_arclength[b].push_back(
3784 initial_segment_arclength[is] + segment_arclength[is]);
3792 if (segment_all_nodes_pt.size() != nsegments)
3794 std::ostringstream error_message;
3796 <<
"The number of segments ("<<nsegments<<
") and the number of " 3797 <<
"set of nodes ("<<segment_all_nodes_pt.size()<<
") representing\n" 3798 <<
"the\nsegments is different!!!\n\n";
3800 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
3801 OOMPH_EXCEPTION_LOCATION);
3825 const unsigned ndtotal_data = 3;
3826 Vector<double> flat_packed_double_data_initial_seg(ndtotal_data);
3830 if (my_rank == proc_with_initial_seg)
3835 Node *first_node_pt = 0;
3837 if (!segment_inverted[initial_segment])
3841 first_ele_pt = segment_sorted_ele_pt[initial_segment].front();
3844 const unsigned nnod = first_ele_pt->
nnode();
3847 first_node_pt = first_ele_pt->
node_pt(0);
3848 if (is_inverted[first_ele_pt])
3850 first_node_pt = first_ele_pt->node_pt(nnod-1);
3857 first_ele_pt = segment_sorted_ele_pt[initial_segment].back();
3860 const unsigned nnod = first_ele_pt->
nnode();
3863 first_node_pt = first_ele_pt->
node_pt(nnod-1);
3864 if (is_inverted[first_ele_pt])
3866 first_node_pt = first_ele_pt->node_pt(0);
3871 for (
unsigned i = 0;
i < 2;
i++)
3873 flat_packed_double_data_initial_seg[
i] = first_node_pt->
x(
i);
3882 if (this->boundary_geom_object_pt(b)!=0)
3890 if (tmp_zeta[0] >= 1.0
e-14)
3897 flat_packed_double_data_initial_seg[2] = tmp_zeta[0];
3903 MPI_Bcast(&flat_packed_double_data_initial_seg[0], ndtotal_data,
3904 MPI_DOUBLE, proc_with_initial_seg, comm_pt->mpi_comm());
3908 for (
unsigned i = 0;
i < 2;
i++)
3910 first_coordinate[
i] = flat_packed_double_data_initial_seg[
i];
3912 first_node_zeta_coordinate[0]=flat_packed_double_data_initial_seg[2];
3921 if (my_rank == proc_with_final_seg)
3927 Node *last_node_pt = 0;
3930 if (!segment_inverted[final_segment])
3934 last_ele_pt = segment_sorted_ele_pt[final_segment].back();
3937 const unsigned nnod = last_ele_pt->
nnode();
3940 last_node_pt = last_ele_pt->
node_pt(nnod-1);
3941 if (is_inverted[last_ele_pt])
3943 last_node_pt = last_ele_pt->node_pt(0);
3950 last_ele_pt = segment_sorted_ele_pt[final_segment].front();
3953 const unsigned nnod = last_ele_pt->
nnode();
3956 last_node_pt = last_ele_pt->
node_pt(0);
3957 if (is_inverted[last_ele_pt])
3959 last_node_pt = last_ele_pt->node_pt(nnod-1);
3964 for (
unsigned i = 0;
i < 2;
i++)
3966 flat_packed_double_data_final_seg[
i]=last_node_pt->
x(
i);
3975 if (this->boundary_geom_object_pt(b)!=0)
3984 if (std::fabs(tmp_zeta[0] - root_accumulated_arclength) >= 1.0
e-14)
3986 tmp_zeta[0] = root_accumulated_arclength;
3991 flat_packed_double_data_final_seg[2] = tmp_zeta[0];
3997 MPI_Bcast(&flat_packed_double_data_final_seg[0], ndtotal_data,
3998 MPI_DOUBLE, proc_with_final_seg, comm_pt->mpi_comm());
4002 for (
unsigned i = 0;
i < 2;
i++)
4004 last_coordinate[
i] = flat_packed_double_data_final_seg[
i];
4006 last_node_zeta_coordinate[0]=flat_packed_double_data_final_seg[2];
4010 Boundary_initial_coordinate[b] = first_coordinate;
4011 Boundary_final_coordinate[b] = last_coordinate;
4013 Boundary_initial_zeta_coordinate[b] = first_node_zeta_coordinate;
4014 Boundary_final_zeta_coordinate[b] = last_node_zeta_coordinate;
4018 if (is_internal_boundary)
4029 re_assign_initial_zeta_values_for_internal_boundary(
4030 b, segment_sorted_nonhalo_ele_pt, is_inverted);
4041 identify_boundary_segments_and_assign_initial_zeta_values(b,
this);
4045 for (
unsigned i = 0;
i < n_all_face_ele;
i++)
4047 delete all_face_ele_pt[
i];
4048 all_face_ele_pt[
i] = 0;
4061 template<
class ELEMENT>
4065 Vector<std::list<FiniteElement*> > &old_segment_sorted_ele_pt,
4066 std::map<FiniteElement*, bool> &old_is_inverted)
4081 unsigned n_repeated_ele = 0;
4083 const unsigned n_regions = this->nregion();
4092 for (
unsigned rr = 0 ; rr < n_regions; rr++)
4094 const unsigned region_id =
4095 static_cast<unsigned>(this->Region_attribute[rr]);
4098 const unsigned nel_in_region =
4099 this->nboundary_element_in_region(b, region_id);
4101 unsigned nel_repetead_in_region = 0;
4105 if (nel_in_region > 0)
4107 bool repeated =
false;
4110 for (
unsigned e = 0;
e < nel_in_region;
e++)
4115 this->boundary_element_in_region_pt(b, region_id,
e);
4126 this->face_index_at_boundary_in_region(b,region_id,
e);
4134 const unsigned n_nodes = tmp_ele_pt->
nnode();
4136 std::pair<Node*, Node*> tmp_pair =
4137 std::make_pair(tmp_ele_pt->
node_pt(0),
4138 tmp_ele_pt->
node_pt(n_nodes - 1));
4140 std::pair<Node*, Node*> tmp_pair_inverse =
4141 std::make_pair(tmp_ele_pt->
node_pt(n_nodes - 1),
4145 const unsigned repeated_nodes_size = done_nodes_pt.size();
4146 for (
unsigned l = 0; l < repeated_nodes_size; l++)
4148 if (tmp_pair == done_nodes_pt[l] ||
4149 tmp_pair_inverse == done_nodes_pt[l])
4151 nel_repetead_in_region++;
4161 done_nodes_pt.push_back(tmp_pair);
4163 face_el_pt.push_back(tmp_ele_pt);
4177 nele += nel_in_region;
4179 n_repeated_ele += nel_repetead_in_region;
4188 nele = this->nboundary_element(b);
4194 bool repeated =
false;
4197 for (
unsigned e = 0;
e < nele;
e++)
4211 int face_index = this->face_index_at_boundary(b,
e);
4219 const unsigned n_nodes = tmp_ele_pt->
nnode();
4221 std::pair<Node*, Node*> tmp_pair =
4222 std::make_pair(tmp_ele_pt->
node_pt(0),
4223 tmp_ele_pt->
node_pt(n_nodes - 1));
4225 std::pair<Node*, Node*> tmp_pair_inverse =
4226 std::make_pair(tmp_ele_pt->
node_pt(n_nodes - 1),
4230 const unsigned repeated_nodes_size = done_nodes_pt.size();
4231 for (
unsigned l = 0; l < repeated_nodes_size; l++)
4233 if (tmp_pair == done_nodes_pt[l] ||
4234 tmp_pair_inverse == done_nodes_pt[l])
4248 done_nodes_pt.push_back(tmp_pair);
4250 face_el_pt.push_back(tmp_ele_pt);
4268 nele-= n_repeated_ele;
4271 if (nele!=face_el_pt.size())
4273 std::ostringstream error_message;
4275 <<
"The independet counting of face elements ("<<nele<<
") for " 4276 <<
"boundary ("<<b<<
") is different\n" 4277 <<
"from the real number of face elements in the container (" 4278 << face_el_pt.size() <<
")\n";
4281 OOMPH_CURRENT_FUNCTION,
4282 OOMPH_EXCEPTION_LOCATION);
4291 const unsigned nnon_halo_face_elements = face_el_pt.size();
4298 unsigned nsorted_face_elements = 0;
4301 std::map<FiniteElement*, bool> done_el;
4304 std::map<FiniteElement*, bool> is_inverted;
4307 while(nsorted_face_elements < nnon_halo_face_elements)
4311 std::list<FiniteElement*> sorted_el_pt;
4315 bool found_initial_face_element =
false;
4321 for (iface = 0; iface < nele; iface++)
4323 ele_face_pt = face_el_pt[iface];
4325 if (!done_el[ele_face_pt])
4329 found_initial_face_element =
true;
4332 nsorted_face_elements++;
4337 sorted_el_pt.push_back(ele_face_pt);
4339 done_el[ele_face_pt] =
true;
4345 if (!found_initial_face_element)
4347 std::ostringstream error_message;
4349 <<
"Could not find an initial face element for the current segment\n";
4351 "TriangleMesh::re_assign_initial_zeta_values_for_internal_boundary()",
4352 OOMPH_EXCEPTION_LOCATION);
4357 const unsigned nnod = ele_face_pt->
nnode();
4362 Node* right_node_pt = ele_face_pt->
node_pt(nnod - 1);
4366 bool face_element_added =
false;
4375 for (
unsigned iiface = iface; iiface < nele; iiface++)
4378 face_element_added =
false;
4381 ele_face_pt = face_el_pt[iiface];
4385 if (!(done_el[ele_face_pt]))
4388 Node* local_left_node_pt = ele_face_pt->node_pt(0);
4389 Node* local_right_node_pt = ele_face_pt->node_pt(nnod - 1);
4392 if (left_node_pt == local_right_node_pt)
4394 left_node_pt = local_left_node_pt;
4395 sorted_el_pt.push_front(ele_face_pt);
4396 is_inverted[ele_face_pt] =
false;
4397 face_element_added =
true;
4400 else if (left_node_pt == local_left_node_pt)
4402 left_node_pt = local_right_node_pt;
4403 sorted_el_pt.push_front(ele_face_pt);
4404 is_inverted[ele_face_pt] =
true;
4405 face_element_added =
true;
4408 else if (right_node_pt == local_left_node_pt)
4410 right_node_pt = local_right_node_pt;
4411 sorted_el_pt.push_back(ele_face_pt);
4412 is_inverted[ele_face_pt] =
false;
4413 face_element_added =
true;
4416 else if (right_node_pt == local_right_node_pt)
4418 right_node_pt = local_left_node_pt;
4419 sorted_el_pt.push_back(ele_face_pt);
4420 is_inverted[ele_face_pt] =
true;
4421 face_element_added =
true;
4424 if (face_element_added)
4426 done_el[ele_face_pt] =
true;
4427 nsorted_face_elements++;
4435 }
while(face_element_added &&
4436 (nsorted_face_elements < nnon_halo_face_elements));
4439 segment_sorted_ele_pt.push_back(sorted_el_pt);
4450 const unsigned nsegments = segment_sorted_ele_pt.size();
4453 if (nnon_halo_face_elements > 0 && nsegments == 0)
4455 std::ostringstream error_message;
4457 <<
"The number of segments is zero, but the number of nonhalo\n" 4458 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
4460 OOMPH_CURRENT_FUNCTION,
4461 OOMPH_EXCEPTION_LOCATION);
4493 for (
unsigned is = 0; is < nsegments; is++)
4496 if (segment_sorted_ele_pt[is].size() == 0)
4498 std::ostringstream error_message;
4500 <<
"The (" << is <<
")-th segment has no elements\n";
4502 "TriangleMesh::re_assign_initial_zeta_values_for_internal_boundary()",
4503 OOMPH_EXCEPTION_LOCATION);
4508 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
4511 const unsigned nnod = first_ele_pt->nnode();
4514 Node *first_node_pt = first_ele_pt->node_pt(0);
4515 if (is_inverted[first_ele_pt])
4517 first_node_pt = first_ele_pt->node_pt(nnod-1);
4521 double x_left = first_node_pt->
x(0);
4522 double y_left = first_node_pt->
x(1);
4531 if (this->boundary_geom_object_pt(b)!=0)
4534 initial_zeta_segment[is] = zeta[0];
4537 FiniteElement* last_ele_pt = segment_sorted_ele_pt[is].back();
4540 Node *last_node_pt = last_ele_pt->
node_pt(nnod-1);
4541 if (is_inverted[last_ele_pt])
4543 last_node_pt = last_ele_pt->node_pt(0);
4547 final_zeta_segment[is] = zeta[0];
4552 std::set<Node*> local_nodes_pt;
4553 local_nodes_pt.insert(first_node_pt);
4557 sorted_node_arclength.push_back(0.0);
4562 sorted_nodes_pt.push_back(first_node_pt);
4565 for (std::list<FiniteElement*>::iterator it =
4566 segment_sorted_ele_pt[is].begin();
4567 it != segment_sorted_ele_pt[is].end(); it++)
4575 if (is_inverted[el_pt])
4582 for (
unsigned j = 1; j < nnod; j++)
4584 Node* nod_pt = el_pt->node_pt(k_nod);
4588 double x_right = nod_pt->
x(0);
4589 double y_right = nod_pt->
x(1);
4593 (x_right - x_left) * (x_right - x_left) + (y_right - y_left)
4594 * (y_right - y_left));
4599 if (this->boundary_geom_object_pt(b)==0)
4611 local_nodes_pt.insert(nod_pt);
4614 sorted_node_arclength.push_back(zeta[0]);
4617 sorted_nodes_pt.push_back(nod_pt);
4626 segment_arclength[is] = zeta[0];
4631 nvertices_per_segment[is] = local_nodes_pt.size();
4634 segment_all_nodes_pt[is] = local_nodes_pt;
4637 sorted_segment_node_arclength[is] = sorted_node_arclength;
4640 sorted_segment_all_nodes_pt[is] = sorted_nodes_pt;
4655 const unsigned old_nsegments = old_segment_sorted_ele_pt.size();
4662 old_boundary_segment_initial_coordinate(old_nsegments);
4664 old_boundary_segment_final_coordinate(old_nsegments);
4669 Vector<double> old_boundary_segment_initial_arclength(old_nsegments);
4670 Vector<double> old_boundary_segment_final_arclength(old_nsegments);
4673 for (
unsigned old_is = 0; old_is < old_nsegments; old_is++)
4675 old_boundary_segment_inverted[old_is] =
4676 boundary_segment_inverted(b)[old_is];
4678 old_boundary_segment_initial_coordinate[old_is].resize(2);
4679 old_boundary_segment_final_coordinate[old_is].resize(2);
4680 for (
unsigned i = 0;
i < 2;
i++)
4682 old_boundary_segment_initial_coordinate[old_is][
i] =
4683 boundary_segment_initial_coordinate(b)[old_is][
i];
4685 old_boundary_segment_final_coordinate[old_is][
i] =
4686 boundary_segment_final_coordinate(b)[old_is][
i];
4690 if (this->boundary_geom_object_pt(b)!=0)
4692 old_boundary_segment_initial_zeta[old_is] =
4693 boundary_segment_initial_zeta(b)[old_is];
4695 old_boundary_segment_final_zeta[old_is] =
4696 boundary_segment_final_zeta(b)[old_is];
4701 old_boundary_segment_initial_arclength[old_is] =
4702 boundary_segment_initial_arclength(b)[old_is];
4704 old_boundary_segment_final_arclength[old_is] =
4705 boundary_segment_final_arclength(b)[old_is];
4713 Boundary_segment_inverted[b].clear();
4714 Boundary_segment_initial_coordinate[b].clear();
4715 Boundary_segment_final_coordinate[b].clear();
4717 Boundary_segment_initial_zeta[b].clear();
4718 Boundary_segment_final_zeta[b].clear();
4720 Boundary_segment_initial_arclength[b].clear();
4721 Boundary_segment_final_arclength[b].clear();
4724 Boundary_segment_inverted[b].resize(nsegments);
4725 Boundary_segment_initial_coordinate[b].resize(nsegments);
4726 Boundary_segment_final_coordinate[b].resize(nsegments);
4729 if (this->boundary_geom_object_pt(b)!=0)
4731 Boundary_segment_initial_zeta[b].resize(nsegments);
4732 Boundary_segment_final_zeta[b].resize(nsegments);
4736 Boundary_segment_initial_arclength[b].resize(nsegments);
4737 Boundary_segment_final_arclength[b].resize(nsegments);
4741 std::map<unsigned, bool> done_segment;
4744 unsigned re_assigned_segments = 0;
4747 for (
unsigned old_is = 0; old_is < old_nsegments; old_is++)
4750 const double old_initial_arclength =
4751 old_boundary_segment_initial_arclength[old_is];
4752 const double old_final_arclength =
4753 old_boundary_segment_final_arclength[old_is];
4755 const unsigned old_inverted_segment =
4756 old_boundary_segment_inverted[old_is];
4760 bool old_increasing_order =
false;
4761 if (old_initial_arclength < old_final_arclength)
4762 {old_increasing_order =
true;}
4767 old_segment_sorted_ele_pt[old_is].front();
4770 const unsigned nnod = first_old_seg_ele_pt->
nnode();
4773 Node *first_old_seg_node_pt = first_old_seg_ele_pt->
node_pt(0);
4774 if (old_is_inverted[first_old_seg_ele_pt])
4776 first_old_seg_node_pt = first_old_seg_ele_pt->node_pt(nnod-1);
4781 old_segment_sorted_ele_pt[old_is].back();
4784 Node *last_old_seg_node_pt = last_old_seg_ele_pt->
node_pt(nnod-1);
4785 if (old_is_inverted[last_old_seg_ele_pt])
4787 last_old_seg_node_pt = last_old_seg_ele_pt->node_pt(0);
4791 if (old_inverted_segment)
4793 Node* temp_node_pt = first_old_seg_node_pt;
4794 first_old_seg_node_pt = last_old_seg_node_pt;
4795 last_old_seg_node_pt = temp_node_pt;
4801 for (
unsigned is = 0; is < nsegments; is++)
4803 if (!done_segment[is])
4807 bool found_first_old_seg_node =
false;
4808 bool found_last_old_seg_node =
false;
4809 bool same_order =
false;
4812 FiniteElement* first_seg_ele_pt = segment_sorted_ele_pt[is].front();
4813 Node* first_seg_node_pt = first_seg_ele_pt->
node_pt(0);
4814 if (is_inverted[first_seg_ele_pt])
4815 {first_seg_node_pt = first_seg_ele_pt->node_pt(nnod-1);}
4818 const double segment_first_node_zeta =
4819 sorted_segment_node_arclength[is][0];
4823 for (
unsigned i = 0;
i < 2;
i++)
4824 {first_node_coord[
i] = first_seg_node_pt->
x(
i);}
4827 FiniteElement* last_seg_ele_pt = segment_sorted_ele_pt[is].back();
4828 Node* last_seg_node_pt = last_seg_ele_pt->
node_pt(nnod-1);
4829 if (is_inverted[last_seg_ele_pt])
4830 {last_seg_node_pt = last_seg_ele_pt->node_pt(0);}
4833 const double segment_final_node_zeta = segment_arclength[is];
4837 for (
unsigned i = 0;
i < 2;
i++)
4838 {last_node_coord[
i] = last_seg_node_pt->
x(
i);}
4841 Vector<Node*> segment_node_pt = sorted_segment_all_nodes_pt[is];
4843 const unsigned nsegment_node = segment_node_pt.size();
4844 for (
unsigned in = 0; in < nsegment_node; in++)
4846 Node* current_node_pt = segment_node_pt[in];
4847 if (!found_first_old_seg_node &&
4848 first_old_seg_node_pt == current_node_pt)
4852 const double current_node_zeta =
4853 sorted_segment_node_arclength[is][in];
4857 if (!found_last_old_seg_node)
4860 Boundary_segment_initial_coordinate[b][is] = first_node_coord;
4863 if (this->boundary_geom_object_pt(b)!=0)
4870 Boundary_segment_initial_zeta[b][is] =
4871 initial_zeta_segment[is];
4877 const double distance =
4878 std::fabs(current_node_zeta - segment_first_node_zeta);
4880 double new_initial_arclength = old_initial_arclength;
4883 if (old_increasing_order)
4886 new_initial_arclength-= distance;
4891 new_initial_arclength+= distance;
4895 Boundary_segment_initial_arclength[b][is] =
4896 new_initial_arclength;
4903 Boundary_segment_initial_coordinate[b][is] = last_node_coord;
4906 if (this->boundary_geom_object_pt(b)!=0)
4914 Boundary_segment_initial_zeta[b][is] =
4915 final_zeta_segment[is];
4921 const double distance =
4922 std::fabs(current_node_zeta - segment_final_node_zeta);
4924 double new_initial_arclength = old_initial_arclength;
4927 if (old_increasing_order)
4930 new_initial_arclength-= distance;
4935 new_initial_arclength+= distance;
4939 Boundary_segment_initial_arclength[b][is] =
4940 new_initial_arclength;
4946 found_first_old_seg_node =
true;
4954 if (found_first_old_seg_node && !found_last_old_seg_node)
4955 {same_order =
true;}
4957 if (!found_last_old_seg_node &&
4958 last_old_seg_node_pt == current_node_pt)
4962 const double current_node_zeta =
4963 sorted_segment_node_arclength[is][in];
4967 if (found_first_old_seg_node)
4970 Boundary_segment_final_coordinate[b][is] = last_node_coord;
4973 if (this->boundary_geom_object_pt(b)!=0)
4980 Boundary_segment_final_zeta[b][is] =
4981 final_zeta_segment[is];
4987 const double distance =
4988 std::fabs(current_node_zeta - segment_final_node_zeta);
4990 double new_final_arclength = old_final_arclength;
4993 if (old_increasing_order)
4996 new_final_arclength+= distance;
5001 new_final_arclength-= distance;
5005 Boundary_segment_final_arclength[b][is] = new_final_arclength;
5012 Boundary_segment_final_coordinate[b][is] = first_node_coord;
5015 if (this->boundary_geom_object_pt(b)!=0)
5023 Boundary_segment_final_zeta[b][is] =
5024 initial_zeta_segment[is];
5030 const double distance =
5031 std::fabs(current_node_zeta - segment_first_node_zeta);
5033 double new_final_arclength = old_final_arclength;
5036 if (old_increasing_order)
5039 new_final_arclength+= distance;
5044 new_final_arclength-= distance;
5048 Boundary_segment_final_arclength[b][is] = new_final_arclength;
5054 found_last_old_seg_node =
true;
5061 if (!found_first_old_seg_node && found_last_old_seg_node)
5062 {same_order =
false;}
5064 if (found_first_old_seg_node && found_last_old_seg_node)
5069 {Boundary_segment_inverted[b][is] = old_inverted_segment;}
5071 {Boundary_segment_inverted[b][is] = !old_inverted_segment;}
5074 done_segment[is] =
true;
5077 re_assigned_segments++;
5086 if ((found_first_old_seg_node && !found_last_old_seg_node) ||
5087 (!found_first_old_seg_node && found_last_old_seg_node))
5089 std::stringstream error_message;
5091 <<
"Working with boundary ("<< b <<
").\nOnly the first node or " 5092 <<
"the last node of the old segment (" << old_is <<
") was\n" 5093 <<
"found. Both, first and last node should have been found in " 5094 <<
"the same segment!!!.\n" 5095 <<
"Found first seg node:" << found_first_old_seg_node <<
"\n" 5096 <<
"Found last seg node:" << found_last_old_seg_node <<
"\n\n";
5098 "TriangleMesh::re_assign_initial_zeta_values_for_internal_boundary()",
5099 OOMPH_EXCEPTION_LOCATION);
5112 for (
unsigned is = 0; is < nsegments; is++)
5115 if (!done_segment[is])
5119 segment_sorted_ele_pt[is].front();
5121 const unsigned nnod = first_seg_ele_pt->
nnode();
5123 Node* first_seg_node_pt = first_seg_ele_pt->
node_pt(0);
5124 if (is_inverted[first_seg_ele_pt])
5125 {first_seg_node_pt = first_seg_ele_pt->node_pt(nnod-1);}
5128 const double segment_first_node_zeta =
5129 sorted_segment_node_arclength[is][0];
5133 for (
unsigned i = 0;
i < 2;
i++)
5134 {first_node_coord[
i] = first_seg_node_pt->
x(
i);}
5138 segment_sorted_ele_pt[is].back();
5139 Node* last_seg_node_pt = last_seg_ele_pt->
node_pt(nnod-1);
5140 if (is_inverted[last_seg_ele_pt])
5141 {last_seg_node_pt = last_seg_ele_pt->node_pt(0);}
5144 const double segment_final_node_zeta = segment_arclength[is];
5148 for (
unsigned i = 0;
i < 2;
i++)
5149 {last_node_coord[
i] = last_seg_node_pt->
x(
i);}
5152 Boundary_segment_initial_coordinate[b][is] = first_node_coord;
5155 if (this->boundary_geom_object_pt(b)!=0)
5162 Boundary_segment_initial_zeta[b][is] =
5163 initial_zeta_segment[is];
5169 Boundary_segment_initial_arclength[b][is] =
5170 segment_first_node_zeta;
5175 Boundary_segment_final_coordinate[b][is] = last_node_coord;
5178 if (this->boundary_geom_object_pt(b)!=0)
5185 Boundary_segment_final_zeta[b][is] =
5186 final_zeta_segment[is];
5192 Boundary_segment_final_arclength[b][is] =
5193 segment_final_node_zeta;
5197 Boundary_segment_inverted[b][is] = 0;
5200 done_segment[is] =
true;
5203 re_assigned_segments++;
5211 if (re_assigned_segments != nsegments)
5213 std::stringstream error_message;
5215 <<
"Working with boundary ("<< b <<
").\nThe number of re-assigned " 5216 <<
"segments (" << re_assigned_segments
5217 <<
") is different from the number\nof segments ("<< nsegments
5220 "TriangleMesh::re_assign_initial_zeta_values_for_internal_boundary()",
5221 OOMPH_EXCEPTION_LOCATION);
5226 for (
unsigned i = 0;
i < nele;
i++)
5228 delete face_el_pt[
i];
5243 template <
class ELEMENT>
5247 bool &is_internal_boundary,
5248 std::map<FiniteElement*,FiniteElement*>
5249 &face_to_bulk_element_pt)
5254 const unsigned my_rank = comm_pt->my_rank();
5264 const unsigned nregions = this->nregion();
5270 for (
unsigned ir = 0 ; ir < nregions; ir++)
5272 const unsigned region_id =
5273 static_cast<unsigned>(this->Region_attribute[ir]);
5276 const unsigned nele_in_region =
5277 this->nboundary_element_in_region(b, region_id);
5281 if (nele_in_region > 0)
5284 for (
unsigned e = 0;
e < nele_in_region;
e++)
5289 this->boundary_element_in_region_pt(b, region_id,
e);
5294 this->face_index_at_boundary_in_region(b,region_id,
e);
5301 face_to_bulk_element_pt[tmp_face_el_pt] = bulk_ele_pt;
5306 tmp_face_ele_pt.push_back(tmp_face_el_pt);
5320 const unsigned nbound_ele = this->nboundary_element(b);
5326 for (
unsigned e = 0;
e < nbound_ele;
e++)
5334 int face_index = this->face_index_at_boundary(b,
e);
5341 face_to_bulk_element_pt[tmp_face_el_pt] = bulk_ele_pt;
5346 tmp_face_ele_pt.push_back(tmp_face_el_pt);
5355 std::map<FiniteElement*,bool> done_face;
5359 is_internal_boundary =
false;
5367 const unsigned n_tmp_face_ele = tmp_face_ele_pt.size();
5368 for (
unsigned ie = 0; ie < n_tmp_face_ele; ie++)
5372 if (!done_face[main_face_ele_pt])
5375 done_face[main_face_ele_pt] =
true;
5377 const unsigned nnodes = main_face_ele_pt->nnode();
5379 Node* main_first_node_pt = main_face_ele_pt->node_pt(0);
5380 Node* main_last_node_pt = main_face_ele_pt->node_pt(nnodes-1);
5384 for (
unsigned iie = ie + 1; iie < n_tmp_face_ele; iie++)
5387 FiniteElement* dependant_face_ele_pt = tmp_face_ele_pt[iie];
5388 if (!done_face[dependant_face_ele_pt])
5392 Node* dependant_first_node_pt =
5393 dependant_face_ele_pt->node_pt(0);
5394 Node* dependant_last_node_pt =
5395 dependant_face_ele_pt->node_pt(nnodes-1);
5398 if (((dependant_first_node_pt == main_first_node_pt) &&
5399 (dependant_last_node_pt == main_last_node_pt)) ||
5400 ((dependant_first_node_pt == main_last_node_pt) &&
5401 (dependant_last_node_pt == main_first_node_pt)))
5405 is_internal_boundary =
true;
5407 done_face[dependant_face_ele_pt] =
true;
5419 face_to_bulk_element_pt[main_face_ele_pt];
5421 face_to_bulk_element_pt[dependant_face_ele_pt];
5425 int processor_in_charge_main_bulk_ele =
5427 int processor_in_charge_dependant_bulk_ele =
5433 if (processor_in_charge_main_bulk_ele < 0)
5435 processor_in_charge_main_bulk_ele=
5436 static_cast<int>(my_rank);
5438 if (processor_in_charge_dependant_bulk_ele < 0)
5440 processor_in_charge_dependant_bulk_ele=
5441 static_cast<int>(my_rank);
5446 bool add_main_face_element =
true;
5447 if (processor_in_charge_dependant_bulk_ele >
5448 processor_in_charge_main_bulk_ele)
5451 add_main_face_element =
false;
5453 else if (processor_in_charge_main_bulk_ele ==
5454 processor_in_charge_dependant_bulk_ele)
5464 const unsigned n_bulk_nodes =
5465 main_bulk_ele_pt->
nnode();
5466 for (
unsigned inode = 0; inode < n_bulk_nodes;
5469 for (
unsigned idim = 0; idim < 2; idim++)
5471 main_ele_coordinates[idim]+=
5472 main_bulk_ele_pt->
node_pt(inode)->
5474 dependant_ele_coordinates[idim]+=
5475 dependant_bulk_ele_pt->
node_pt(inode)->
5482 for (
unsigned idim = 0; idim < 2; idim++)
5484 main_ele_coordinates[idim]/=
5485 (double)n_bulk_nodes;
5486 dependant_ele_coordinates[idim]/=
5487 (double)n_bulk_nodes;
5493 if (dependant_ele_coordinates[1] <
5494 main_ele_coordinates[1])
5495 {add_main_face_element =
false;}
5496 else if(dependant_ele_coordinates[1]==
5497 main_ele_coordinates[1])
5500 if(dependant_ele_coordinates[0] <
5501 main_ele_coordinates[0])
5502 {add_main_face_element =
false;}
5507 if (add_main_face_element)
5512 face_ele_pt.push_back(main_face_ele_pt);
5515 free_memory_face_ele_pt.
5516 push_back(dependant_face_ele_pt);
5523 face_ele_pt.push_back(dependant_face_ele_pt);
5526 free_memory_face_ele_pt.
5527 push_back(main_face_ele_pt);
5546 const unsigned n_free_face_ele = free_memory_face_ele_pt.size();
5547 if (n_free_face_ele == 0)
5555 face_ele_pt.resize(n_tmp_face_ele);
5557 for (
unsigned i = 0;
i < n_tmp_face_ele;
i++)
5559 face_ele_pt[
i] = tmp_face_ele_pt[
i];
5567 for (
unsigned i = 0;
i < n_free_face_ele;
i++)
5569 delete free_memory_face_ele_pt[
i];
5570 free_memory_face_ele_pt[
i] = 0;
5582 template <
class ELEMENT>
5593 const unsigned nproc = comm_pt->nproc();
5594 const unsigned my_rank = comm_pt->my_rank();
5600 const unsigned nregions = this->nregion();
5604 std::map<FiniteElement*,FiniteElement*> face_to_bulk_element_pt;
5610 for (
unsigned ir = 0 ; ir < nregions; ir++)
5612 const unsigned region_id =
5613 static_cast<unsigned>(this->Region_attribute[ir]);
5616 const unsigned nele_in_region =
5617 this->nboundary_element_in_region(b, region_id);
5621 if (nele_in_region > 0)
5624 for (
unsigned e = 0;
e < nele_in_region;
e++)
5628 this->boundary_element_in_region_pt(b, region_id,
e);
5631 int face_index=this->face_index_at_boundary_in_region(b,region_id,
e);
5640 tmp_face_ele_pt.push_back(tmp_face_el_pt);
5642 face_to_bulk_element_pt[tmp_face_el_pt] = bulk_ele_pt;
5656 const unsigned nbound_ele = this->nboundary_element(b);
5662 for (
unsigned e = 0;
e < nbound_ele;
e++)
5668 int face_index = this->face_index_at_boundary(b,
e);
5676 tmp_face_ele_pt.push_back(tmp_face_el_pt);
5678 face_to_bulk_element_pt[tmp_face_el_pt] = bulk_ele_pt;
5692 std::map<FiniteElement*,bool> done_face;
5695 bool is_internal_boundary =
false;
5699 bool is_internal_boundary_paranoid =
false;
5703 unsigned nfound_face_elements = 0;
5707 const unsigned nbound_ele = tmp_face_ele_pt.size();
5708 for (
unsigned ie = 0; ie < nbound_ele; ie++)
5712 if (!done_face[main_face_ele_pt])
5715 done_face[main_face_ele_pt] =
true;
5717 const unsigned nnodes = main_face_ele_pt->nnode();
5719 Node* main_first_node_pt = main_face_ele_pt->node_pt(0);
5720 Node* main_last_node_pt = main_face_ele_pt->node_pt(nnodes-1);
5722 for (
unsigned iie = ie + 1; iie < nbound_ele; iie++)
5725 FiniteElement* dependant_face_ele_pt = tmp_face_ele_pt[iie];
5726 if (!done_face[dependant_face_ele_pt])
5729 Node* dependant_first_node_pt =
5730 dependant_face_ele_pt->node_pt(0);
5731 Node* dependant_last_node_pt =
5732 dependant_face_ele_pt->node_pt(nnodes-1);
5735 if (((dependant_first_node_pt == main_first_node_pt) &&
5736 (dependant_last_node_pt == main_last_node_pt)) ||
5737 ((dependant_first_node_pt == main_last_node_pt) &&
5738 (dependant_last_node_pt == main_first_node_pt)))
5742 nfound_face_elements+=2;
5746 is_internal_boundary =
true;
5748 done_face[dependant_face_ele_pt] =
true;
5758 face_to_bulk_element_pt[main_face_ele_pt];
5760 face_to_bulk_element_pt[dependant_face_ele_pt];
5763 int processor_in_charge_main_bulk_ele =
5765 int processor_in_charge_dependant_bulk_ele =
5771 if (processor_in_charge_main_bulk_ele < 0)
5773 processor_in_charge_main_bulk_ele=
static_cast<int>(my_rank);
5775 if (processor_in_charge_dependant_bulk_ele < 0)
5777 processor_in_charge_dependant_bulk_ele=
static_cast<int>(my_rank);
5781 bool add_main_face_element =
true;
5782 if (processor_in_charge_dependant_bulk_ele >
5783 processor_in_charge_main_bulk_ele)
5786 add_main_face_element =
false;
5788 else if (processor_in_charge_main_bulk_ele ==
5789 processor_in_charge_dependant_bulk_ele)
5797 const unsigned n_bulk_nodes = main_bulk_ele_pt->
nnode();
5798 for (
unsigned inode = 0; inode < n_bulk_nodes; inode++)
5800 for (
unsigned idim = 0; idim < 2; idim++)
5802 main_ele_coordinates[idim]+=
5803 main_bulk_ele_pt->
node_pt(inode)->
x(idim);
5804 dependant_ele_coordinates[idim]+=
5805 dependant_bulk_ele_pt->
node_pt(inode)->
x(idim);
5810 for (
unsigned idim = 0; idim < 2; idim++)
5812 main_ele_coordinates[idim]/=(double)n_bulk_nodes;
5813 dependant_ele_coordinates[idim]/=(double)n_bulk_nodes;
5819 if (dependant_ele_coordinates[1] < main_ele_coordinates[1])
5820 {add_main_face_element =
false;}
5821 else if(dependant_ele_coordinates[1]==main_ele_coordinates[1])
5824 if(dependant_ele_coordinates[0] < main_ele_coordinates[0])
5825 {add_main_face_element =
false;}
5830 if (add_main_face_element)
5834 face_ele_pt.push_back(main_face_ele_pt);
5840 face_ele_pt.push_back(dependant_face_ele_pt);
5853 const unsigned nface_ele = face_ele_pt.size();
5859 if (nbound_ele > 0 && nfound_face_elements == nbound_ele)
5860 {is_internal_boundary_paranoid =
true;}
5862 if (nbound_ele > 0 && is_internal_boundary_paranoid &&
5863 nbound_ele!=nface_ele*2)
5865 std::ostringstream error_message;
5867 <<
"The info. to perform the synchronisation of the boundary " 5868 <<
"coordinates was not completely established\n" 5869 <<
"In this case it was the number of non repeated boundary elements\n" 5870 <<
"Number of boundary elements: (" << nbound_ele <<
")\n" 5871 <<
"Number of nonrepeated boundary elements: (" << nface_ele <<
")\n";
5873 "TriangleMesh::synchronize_boundary_coordinates()",
5874 OOMPH_EXCEPTION_LOCATION);
5884 std::vector<bool> is_halo_face_element(nface_ele,
false);
5887 unsigned nnon_halo_face_elements = 0;
5889 for (
unsigned ie = 0; ie < nface_ele; ie++)
5893 FiniteElement* tmp_bulk_ele_pt = face_to_bulk_element_pt[face_el_pt];
5895 if (!tmp_bulk_ele_pt->
is_halo())
5897 is_halo_face_element[ie] =
false;
5898 nnon_halo_face_elements++;
5903 is_halo_face_element[ie] =
true;
5916 std::map<Node*,bool> done_node;
5936 std::map<Node*,bool> done_haloed_face_node;
5939 for (
unsigned iface = 0; iface < nface_ele; iface++)
5942 if (!is_halo_face_element[iface])
5947 const unsigned nnodes = ele_face_pt->
nnode();
5949 for (
unsigned in = 0; in < nnodes; in++)
5953 if (!done_node[face_node_pt])
5956 done_node[face_node_pt] =
true;
5958 if (face_node_pt->is_halo())
5963 if (int_nonhalo_ID < 0)
5965 std::ostringstream error_message;
5967 <<
"The node was marked to be halo but the processor in " 5968 <<
"charge was found to be -1\n\n";
5970 "TriangleMesh::synchronize_boundary_coordinates()",
5971 OOMPH_EXCEPTION_LOCATION);
5974 const unsigned ip =
static_cast<unsigned>(int_nonhalo_ID);
5978 face_halo_node_pt[ip].push_back(face_node_pt);
5982 bool found_halo_node =
false;
5984 const unsigned nhalo_iproc = this->nhalo_node(ip);
5985 for (
unsigned ihn = 0; ihn < nhalo_iproc; ihn++)
5987 Node* compare_face_node_pt = this->halo_node_pt(ip, ihn);
5988 if (compare_face_node_pt == face_node_pt)
5992 face_halo_node_id[ip].push_back(ihn);
5995 found_halo_node =
true;
6002 if (!found_halo_node)
6004 std::ostringstream error_message;
6006 <<
"The halo id of the current node: (" 6007 << face_node_pt->x(0) <<
", " << face_node_pt->x(1)
6008 <<
") with processor (" << ip <<
") was not found!!!\n\n";
6010 "TriangleMesh::synchronize_boundary_coordinates()",
6011 OOMPH_EXCEPTION_LOCATION);
6021 for (
unsigned ip = 0; ip < nproc; ip++)
6033 const unsigned nhaloed_iproc = this->nhaloed_node(ip);
6034 for (
unsigned ihdn = 0; ihdn < nhaloed_iproc; ihdn++)
6036 Node* compare_face_node_pt=this->haloed_node_pt(ip, ihdn);
6037 if (face_node_pt == compare_face_node_pt)
6041 face_haloed_node_pt[ip].push_back(face_node_pt);
6044 face_haloed_node_id[ip].push_back(ihdn);
6048 done_haloed_face_node[face_node_pt] =
true;
6074 for (
unsigned ip = 0; ip < nproc; ip++)
6079 const unsigned nhalo_face_nodes = face_halo_node_pt[ip].size();
6081 if (nhalo_face_nodes!=face_halo_node_id[ip].size())
6083 std::ostringstream error_message;
6085 <<
"The number of found halo face nodes (" << nhalo_face_nodes
6086 <<
") is different from the number of\nfound halo face ids (" 6087 << face_halo_node_id[ip].size() <<
")!!!\n\n";
6089 "TriangleMesh::synchronize_boundary_coordinates()",
6090 OOMPH_EXCEPTION_LOCATION);
6100 for (
unsigned ihfn = 0; ihfn < nhalo_face_nodes; ihfn++)
6103 Node *halo_face_node_pt = face_halo_node_pt[ip][ihfn];
6105 const unsigned halo_id = face_halo_node_id[ip][ihfn];
6110 flat_unsigned_send_packed_data.push_back(halo_id);
6111 flat_double_send_packed_data.push_back(zeta[0]);
6116 MPI_Request request;
6119 int send_proc =
static_cast<int>(ip);
6121 int receive_proc =
static_cast<int>(ip);
6129 unsigned nflat_unsigned_send = flat_unsigned_send_packed_data.size();
6130 MPI_Isend(&nflat_unsigned_send,1,MPI_UNSIGNED,
6131 send_proc,1,comm_pt->mpi_comm(),&request);
6133 unsigned nflat_unsigned_receive = 0;
6134 MPI_Recv(&nflat_unsigned_receive,1,MPI_UNSIGNED,
6135 receive_proc,1,comm_pt->mpi_comm(),&status);
6137 MPI_Wait(&request,MPI_STATUS_IGNORE);
6139 if (nflat_unsigned_send!=0)
6141 MPI_Isend(&flat_unsigned_send_packed_data[0],nflat_unsigned_send,
6142 MPI_UNSIGNED,send_proc,2,comm_pt->mpi_comm(),&request);
6145 if (nflat_unsigned_receive!=0)
6147 flat_unsigned_receive_packed_data.resize(nflat_unsigned_receive);
6148 MPI_Recv(&flat_unsigned_receive_packed_data[0],nflat_unsigned_receive,
6149 MPI_UNSIGNED,receive_proc,2,comm_pt->mpi_comm(),&status);
6152 if (nflat_unsigned_send!=0)
6154 MPI_Wait(&request,MPI_STATUS_IGNORE);
6159 unsigned nflat_double_send = flat_double_send_packed_data.size();
6160 MPI_Isend(&nflat_double_send,1,MPI_DOUBLE,
6161 send_proc,3,comm_pt->mpi_comm(),&request);
6163 unsigned nflat_double_receive = 0;
6164 MPI_Recv(&nflat_double_receive,1,MPI_DOUBLE,
6165 receive_proc,3,comm_pt->mpi_comm(),&status);
6167 MPI_Wait(&request,MPI_STATUS_IGNORE);
6169 if (nflat_double_send!=0)
6171 MPI_Isend(&flat_double_send_packed_data[0],nflat_double_send,
6172 MPI_DOUBLE,send_proc,4,comm_pt->mpi_comm(),&request);
6175 if (nflat_double_receive!=0)
6177 flat_double_receive_packed_data.resize(nflat_double_receive);
6178 MPI_Recv(&flat_double_receive_packed_data[0],nflat_double_receive,
6179 MPI_DOUBLE,receive_proc,4,comm_pt->mpi_comm(),&status);
6182 if (nflat_double_send!=0)
6184 MPI_Wait(&request,MPI_STATUS_IGNORE);
6189 if (nflat_unsigned_receive!=nflat_double_receive)
6191 std::ostringstream error_message;
6193 <<
"The number of unsigned received data (" 6194 << nflat_unsigned_receive <<
") is different from the " 6195 <<
"number\nof double received data (" 6196 << nflat_double_receive <<
")!!!\n\n";
6198 "TriangleMesh::synchronize_boundary_coordinates()",
6199 OOMPH_EXCEPTION_LOCATION);
6206 for (
unsigned iflat_packed = 0; iflat_packed < nflat_unsigned_receive;
6210 const unsigned haloed_id =
6211 flat_unsigned_receive_packed_data[iflat_packed];
6214 zeta[0] = flat_double_receive_packed_data[iflat_packed];
6217 Node* haloed_face_node_pt = this->haloed_node_pt(ip, haloed_id);
6231 if (!done_haloed_face_node[haloed_face_node_pt])
6234 haloed_face_node_pt->set_coordinates_on_boundary(b, zeta);
6237 for (
unsigned iiproc = 0; iiproc < nproc; iiproc++)
6240 if (iiproc != my_rank)
6243 const unsigned nhaloed_node_iiproc = this->nhaloed_node(iiproc);
6244 for (
unsigned ihdn = 0; ihdn < nhaloed_node_iiproc; ihdn++)
6246 Node* compare_haloed_node_pt=this->haloed_node_pt(iiproc,ihdn);
6247 if (haloed_face_node_pt == compare_haloed_node_pt)
6251 face_haloed_node_pt[iiproc].push_back(haloed_face_node_pt);
6254 face_haloed_node_id[iiproc].push_back(ihdn);
6275 for (
unsigned ip = 0; ip < nproc; ip++)
6287 const unsigned nhaloed_face_nodes = face_haloed_node_pt[ip].size();
6289 for (
unsigned ihdfn = 0; ihdfn < nhaloed_face_nodes; ihdfn++)
6292 Node *haloed_face_node_pt = face_haloed_node_pt[ip][ihdfn];
6294 const unsigned haloed_id = face_haloed_node_id[ip][ihdfn];
6299 flat_unsigned_send_packed_data.push_back(haloed_id);
6300 flat_double_send_packed_data.push_back(zeta[0]);
6305 MPI_Request request;
6308 int send_proc =
static_cast<int>(ip);
6310 int receive_proc =
static_cast<int>(ip);
6318 unsigned nflat_unsigned_send = flat_unsigned_send_packed_data.size();
6319 MPI_Isend(&nflat_unsigned_send,1,MPI_UNSIGNED,
6320 send_proc,1,comm_pt->mpi_comm(),&request);
6322 unsigned nflat_unsigned_receive = 0;
6323 MPI_Recv(&nflat_unsigned_receive,1,MPI_UNSIGNED,
6324 receive_proc,1,comm_pt->mpi_comm(),&status);
6326 MPI_Wait(&request,MPI_STATUS_IGNORE);
6328 if (nflat_unsigned_send!=0)
6330 MPI_Isend(&flat_unsigned_send_packed_data[0],nflat_unsigned_send,
6331 MPI_UNSIGNED,send_proc,2,comm_pt->mpi_comm(),&request);
6334 if (nflat_unsigned_receive!=0)
6336 flat_unsigned_receive_packed_data.resize(nflat_unsigned_receive);
6337 MPI_Recv(&flat_unsigned_receive_packed_data[0],nflat_unsigned_receive,
6338 MPI_UNSIGNED,receive_proc,2,comm_pt->mpi_comm(),&status);
6341 if (nflat_unsigned_send!=0)
6343 MPI_Wait(&request,MPI_STATUS_IGNORE);
6348 unsigned nflat_double_send = flat_double_send_packed_data.size();
6349 MPI_Isend(&nflat_double_send,1,MPI_DOUBLE,
6350 send_proc,3,comm_pt->mpi_comm(),&request);
6352 unsigned nflat_double_receive = 0;
6353 MPI_Recv(&nflat_double_receive,1,MPI_DOUBLE,
6354 receive_proc,3,comm_pt->mpi_comm(),&status);
6356 MPI_Wait(&request,MPI_STATUS_IGNORE);
6358 if (nflat_double_send!=0)
6360 MPI_Isend(&flat_double_send_packed_data[0],nflat_double_send,
6361 MPI_DOUBLE,send_proc,4,comm_pt->mpi_comm(),&request);
6364 if (nflat_double_receive!=0)
6366 flat_double_receive_packed_data.resize(nflat_double_receive);
6367 MPI_Recv(&flat_double_receive_packed_data[0],nflat_double_receive,
6368 MPI_DOUBLE,receive_proc,4,comm_pt->mpi_comm(),&status);
6371 if (nflat_double_send!=0)
6373 MPI_Wait(&request,MPI_STATUS_IGNORE);
6378 if (nflat_unsigned_receive!=nflat_double_receive)
6380 std::ostringstream error_message;
6382 <<
"The number of unsigned received data (" 6383 << nflat_unsigned_receive <<
") is different from the " 6384 <<
"number\nof double received data (" 6385 << nflat_double_receive <<
")!!!\n\n";
6387 "TriangleMesh::synchronize_boundary_coordinates()",
6388 OOMPH_EXCEPTION_LOCATION);
6395 for (
unsigned iflat_packed = 0; iflat_packed < nflat_unsigned_receive;
6399 const unsigned halo_id =
6400 flat_unsigned_receive_packed_data[iflat_packed];
6403 zeta[0] = flat_double_receive_packed_data[iflat_packed];
6406 Node* halo_face_node_pt = this->halo_node_pt(ip, halo_id);
6423 for (
unsigned ie = 0; ie < nbound_ele; ie++)
6425 delete tmp_face_ele_pt[ie];
6426 tmp_face_ele_pt[ie] = 0;
6431 if (is_internal_boundary)
6433 re_scale_re_assigned_initial_zeta_values_for_internal_boundary(b);
6444 template<
class ELEMENT>
6462 unsigned n_repeated_ele = 0;
6464 const unsigned n_regions = this->nregion();
6473 for (
unsigned rr = 0 ; rr < n_regions; rr++)
6475 const unsigned region_id =
6476 static_cast<unsigned>(this->Region_attribute[rr]);
6479 const unsigned nel_in_region =
6480 this->nboundary_element_in_region(b, region_id);
6482 unsigned nel_repetead_in_region = 0;
6486 if (nel_in_region > 0)
6488 bool repeated =
false;
6491 for (
unsigned e = 0;
e < nel_in_region;
e++)
6496 this->boundary_element_in_region_pt(b, region_id,
e);
6507 this->face_index_at_boundary_in_region(b,region_id,
e);
6515 const unsigned n_nodes = tmp_ele_pt->
nnode();
6517 std::pair<Node*, Node*> tmp_pair =
6518 std::make_pair(tmp_ele_pt->
node_pt(0),
6519 tmp_ele_pt->
node_pt(n_nodes - 1));
6521 std::pair<Node*, Node*> tmp_pair_inverse =
6522 std::make_pair(tmp_ele_pt->
node_pt(n_nodes - 1),
6526 const unsigned n_done_nodes = done_nodes_pt.size();
6527 for (
unsigned l = 0; l < n_done_nodes; l++)
6529 if (tmp_pair == done_nodes_pt[l] ||
6530 tmp_pair_inverse == done_nodes_pt[l])
6532 nel_repetead_in_region++;
6542 done_nodes_pt.push_back(tmp_pair);
6544 face_el_pt.push_back(tmp_ele_pt);
6558 nele += nel_in_region;
6560 n_repeated_ele += nel_repetead_in_region;
6569 nele = this->nboundary_element(b);
6575 bool repeated =
false;
6578 for (
unsigned e = 0;
e < nele;
e++)
6593 int face_index = this->face_index_at_boundary(b,
e);
6601 const unsigned n_nodes = tmp_ele_pt->
nnode();
6603 std::pair<Node*, Node*> tmp_pair =
6604 std::make_pair(tmp_ele_pt->
node_pt(0),
6605 tmp_ele_pt->
node_pt(n_nodes - 1));
6607 std::pair<Node*, Node*> tmp_pair_inverse =
6608 std::make_pair(tmp_ele_pt->
node_pt(n_nodes - 1),
6612 const unsigned n_done_nodes = done_nodes_pt.size();
6613 for (
unsigned l = 0; l < n_done_nodes; l++)
6615 if (tmp_pair == done_nodes_pt[l] ||
6616 tmp_pair_inverse == done_nodes_pt[l])
6630 done_nodes_pt.push_back(tmp_pair);
6632 face_el_pt.push_back(tmp_ele_pt);
6650 nele-= n_repeated_ele;
6653 if (nele!=face_el_pt.size())
6655 std::ostringstream error_message;
6657 <<
"The independet counting of face elements ("<<nele<<
") for " 6658 <<
"boundary ("<<b<<
") is different\n" 6659 <<
"from the real number of face elements in the container (" 6660 << face_el_pt.size() <<
")\n";
6663 "TriangleMesh::re_scale_re_assigned_initial_zeta_values_for_internal_boundary()",
6664 OOMPH_EXCEPTION_LOCATION);
6674 const unsigned nnon_halo_face_elements = face_el_pt.size();
6681 unsigned nsorted_face_elements = 0;
6684 std::map<FiniteElement*, bool> done_el;
6687 std::map<FiniteElement*, bool> is_inverted;
6690 while(nsorted_face_elements < nnon_halo_face_elements)
6694 std::list<FiniteElement*> sorted_el_pt;
6698 bool found_initial_face_element =
false;
6704 for (iface = 0; iface < nele; iface++)
6706 ele_face_pt = face_el_pt[iface];
6708 if (!done_el[ele_face_pt])
6711 found_initial_face_element =
true;
6713 nsorted_face_elements++;
6715 sorted_el_pt.push_back(ele_face_pt);
6717 done_el[ele_face_pt] =
true;
6723 if (!found_initial_face_element)
6725 std::ostringstream error_message;
6727 <<
"Could not find an initial face element for the current segment\n";
6730 "TriangleMesh::re_scale_re_assigned_initial_zeta_values_for_internal_boundary()",
6731 OOMPH_EXCEPTION_LOCATION);
6736 const unsigned nnod = ele_face_pt->
nnode();
6741 Node* right_node_pt = ele_face_pt->
node_pt(nnod - 1);
6745 bool face_element_added =
false;
6754 for (
unsigned iiface = iface; iiface < nele; iiface++)
6757 face_element_added =
false;
6760 ele_face_pt = face_el_pt[iiface];
6763 if (!(done_el[ele_face_pt]))
6766 Node* local_left_node_pt = ele_face_pt->node_pt(0);
6767 Node* local_right_node_pt = ele_face_pt->node_pt(nnod - 1);
6770 if (left_node_pt == local_right_node_pt)
6772 left_node_pt = local_left_node_pt;
6773 sorted_el_pt.push_front(ele_face_pt);
6774 is_inverted[ele_face_pt] =
false;
6775 face_element_added =
true;
6778 else if (left_node_pt == local_left_node_pt)
6780 left_node_pt = local_right_node_pt;
6781 sorted_el_pt.push_front(ele_face_pt);
6782 is_inverted[ele_face_pt] =
true;
6783 face_element_added =
true;
6786 else if (right_node_pt == local_left_node_pt)
6788 right_node_pt = local_right_node_pt;
6789 sorted_el_pt.push_back(ele_face_pt);
6790 is_inverted[ele_face_pt] =
false;
6791 face_element_added =
true;
6794 else if (right_node_pt == local_right_node_pt)
6796 right_node_pt = local_left_node_pt;
6797 sorted_el_pt.push_back(ele_face_pt);
6798 is_inverted[ele_face_pt] =
true;
6799 face_element_added =
true;
6802 if (face_element_added)
6804 done_el[ele_face_pt] =
true;
6805 nsorted_face_elements++;
6811 }
while(face_element_added &&
6812 (nsorted_face_elements < nnon_halo_face_elements));
6815 segment_sorted_ele_pt.push_back(sorted_el_pt);
6831 const unsigned nsegments = segment_sorted_ele_pt.size();
6834 if (nnon_halo_face_elements > 0 && nsegments == 0)
6836 std::ostringstream error_message;
6838 <<
"The number of segments is zero, but the number of nonhalo\n" 6839 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
6841 "TriangleMesh::re_scale_re_assigned_initial_zeta_values_for_internal_boundary()",
6842 OOMPH_EXCEPTION_LOCATION);
6857 for (
unsigned is = 0; is < nsegments; is++)
6860 if (segment_sorted_ele_pt[is].size() == 0)
6862 std::ostringstream error_message;
6864 <<
"The (" << is <<
")-th segment has no elements\n";
6866 "TriangleMesh::re_scale_re_assigned_initial_zeta_values_for_internal_boundary()",
6867 OOMPH_EXCEPTION_LOCATION);
6872 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
6875 const unsigned nnod = first_ele_pt->nnode();
6878 Node *first_node_pt = first_ele_pt->node_pt(0);
6879 if (is_inverted[first_ele_pt])
6881 first_node_pt = first_ele_pt->node_pt(nnod-1);
6885 FiniteElement* last_ele_pt = segment_sorted_ele_pt[is].back();
6888 Node *last_node_pt = last_ele_pt->
node_pt(nnod-1);
6889 if (is_inverted[last_ele_pt])
6891 last_node_pt = last_ele_pt->node_pt(0);
6895 double x_left = first_node_pt->
x(0);
6896 double y_left = first_node_pt->
x(1);
6905 if (this->boundary_geom_object_pt(b)!=0)
6908 initial_zeta_segment[is] = zeta[0];
6910 final_zeta_segment[is] = zeta[0];
6914 std::set<Node*> local_nodes_pt;
6915 local_nodes_pt.insert(first_node_pt);
6918 for (std::list<FiniteElement*>::iterator it =
6919 segment_sorted_ele_pt[is].begin();
6920 it != segment_sorted_ele_pt[is].end(); it++)
6928 if (is_inverted[el_pt])
6935 for (
unsigned j = 1; j < nnod; j++)
6937 Node* nod_pt = el_pt->node_pt(k_nod);
6941 double x_right = nod_pt->
x(0);
6942 double y_right = nod_pt->
x(1);
6946 (x_right - x_left) * (x_right - x_left) + (y_right - y_left)
6947 * (y_right - y_left));
6955 local_nodes_pt.insert(nod_pt);
6961 segment_arclength[is] = zeta[0];
6964 segment_all_nodes_pt.push_back(local_nodes_pt);
6976 Boundary_segment_inverted[b].clear();
6977 Boundary_segment_initial_coordinate[b].clear();
6978 Boundary_segment_final_coordinate[b].clear();
6980 Boundary_segment_initial_zeta[b].clear();
6981 Boundary_segment_final_zeta[b].clear();
6983 Boundary_segment_initial_arclength[b].clear();
6984 Boundary_segment_final_arclength[b].clear();
6989 first_node_zeta_coordinate = boundary_initial_zeta_coordinate(b);
6990 last_node_zeta_coordinate = boundary_final_zeta_coordinate(b);
6993 const double boundary_arclength =
6994 std::max(first_node_zeta_coordinate[0], last_node_zeta_coordinate[0]);
6998 for (
unsigned is = 0; is < nsegments; is++)
7001 FiniteElement* first_face_ele_pt = segment_sorted_ele_pt[is].front();
7004 const unsigned nnod = first_face_ele_pt->
nnode();
7007 Node* first_node_pt = first_face_ele_pt->
node_pt(0);
7008 if (is_inverted[first_face_ele_pt])
7010 first_node_pt = first_face_ele_pt->node_pt(nnod-1);
7018 FiniteElement* last_face_ele_pt = segment_sorted_ele_pt[is].back();
7021 Node* last_node_pt = last_face_ele_pt->
node_pt(nnod-1);
7022 if (is_inverted[last_face_ele_pt])
7024 last_node_pt = last_face_ele_pt->node_pt(0);
7035 for (
unsigned i = 0;
i < 2;
i++)
7037 first_node_coord[
i] = first_node_pt->
x(
i);
7038 last_node_coord[
i] = last_node_pt->
x(
i);
7042 Boundary_segment_inverted[b].push_back(0);
7043 Boundary_segment_initial_coordinate[b].push_back(first_node_coord);
7044 Boundary_segment_final_coordinate[b].push_back(last_node_coord);
7047 if (this->boundary_geom_object_pt(b)!=0)
7049 Boundary_segment_initial_zeta[b].push_back(zeta_first[0]);
7050 Boundary_segment_final_zeta[b].push_back(zeta_last[0]);
7055 Boundary_segment_initial_arclength[b].push_back(
7056 zeta_first[0] * boundary_arclength);
7057 Boundary_segment_final_arclength[b].push_back(
7058 zeta_last[0] * boundary_arclength);
7064 for (
unsigned i = 0;
i < nele;
i++)
7066 delete face_el_pt[
i];
7072 #endif // OOMPH_HAS_MPI 7076 #ifdef OOMPH_HAS_TRIANGLE_LIB 7081 template <
class ELEMENT>
7085 bool &use_attributes)
7090 std::ifstream poly_file(poly_file_name.c_str(),std::ios_base::in);
7094 OOMPH_CURRENT_FUNCTION,
7095 OOMPH_EXCEPTION_LOCATION);
7102 poly_file.ignore(80,
'\n');
7105 unsigned invertices;
7106 poly_file>>invertices;
7111 (
double *) malloc(triangulate_io.
numberofpoints * 2 *
sizeof(
double));
7115 poly_file>>mesh_dim;
7126 OOMPH_CURRENT_FUNCTION,
7127 OOMPH_EXCEPTION_LOCATION);
7133 poly_file>> nextras;
7139 unsigned nodemarkers;
7140 poly_file>>nodemarkers;
7146 if(nextras!=0 || nodemarkers!=0)
7148 oomph_info <<
"====================================================" 7149 << std::endl<<std::endl;
7150 oomph_info <<
"Reading the .poly file via oomph_lib \n" 7151 <<
"point's attribute and point's markers \n" 7152 <<
"are automatically set to 0"<<std::endl;
7153 oomph_info <<
"====================================================" 7159 unsigned dummy_value;
7160 unsigned count_point=0;
7164 getline(poly_file,test_string,
'#');
7165 poly_file.ignore(80,
'\n');
7169 for(
unsigned count=0;count<invertices;count++)
7171 poly_file>>dummy_value;
7172 poly_file>>triangulate_io.
pointlist[count_point];
7173 poly_file>>triangulate_io.
pointlist[count_point+1];
7174 if(nextras!=0 || nodemarkers!=0)
7176 for(
unsigned j=0;j<nextras;j++)
7178 poly_file>>dummy_value;
7181 else if(nextras!=0 && nodemarkers!=0)
7183 for(
unsigned j=0;j<nextras;j++)
7185 poly_file>>dummy_value;
7186 poly_file>>dummy_value;
7190 poly_file.ignore(80,
'\n');
7193 if(poly_file.get() ==
'#')
7195 poly_file.ignore(80,
'\n');
7211 unsigned inelements;
7212 poly_file>>inelements;
7214 unsigned segment_markers;
7215 poly_file>>segment_markers;
7220 if(segment_markers!=1)
7223 std::ostringstream error_stream;
7225 <<
"The segment marker should be provided \n" 7226 <<
"In order to assign each segment to a boundary \n "<< std::endl;
7229 OOMPH_CURRENT_FUNCTION,
7230 OOMPH_EXCEPTION_LOCATION);
7241 for(
unsigned i=0;
i<2*inelements;
i+=2)
7243 poly_file>>dummy_seg;
7246 if(segment_markers!=0)
7252 poly_file.ignore(80,
'\n');
7257 if(getline(poly_file,test_string,
'#'))
7259 poly_file.ignore(80,
'\n');
7261 unsigned dummy_hole;
7267 (
double *) malloc(triangulate_io.
numberofholes * 2 *
sizeof(
double));
7271 for(
unsigned i=0;
i<2*nhole;
i+=2)
7273 poly_file>>dummy_hole;
7275 poly_file>>triangulate_io.
holelist[
i+1];
7281 if(getline(poly_file,test_string,
'#'))
7283 poly_file.ignore(80,
'\n');
7285 unsigned dummy_region;
7288 std::cerr <<
"Regions: "<< nregion << std::endl;
7293 (
double *) malloc(triangulate_io.
numberofregions * 4 *
sizeof(
double));
7297 {use_attributes=
true;}
7301 for(
unsigned i=0;
i<nregion;
i++)
7303 poly_file>>dummy_region;
7315 #ifdef OOMPH_HAS_TRIANGLE_LIB 7316 #ifdef OOMPH_HAS_MPI 7321 template<
class ELEMENT>
7326 if (this->is_mesh_distributed())
7329 const unsigned nboundary = this->nboundary();
7330 dump_file << nboundary
7331 <<
" # number of original boundaries" << std::endl;
7334 const unsigned nshared_boundaries = this->nshared_boundaries();
7335 dump_file << nshared_boundaries
7336 <<
" # number of shared boundaries" << std::endl;
7339 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
7340 dump_file << init_shd_bnd_id
7341 <<
" # initial shared boundaries id" << std::endl;
7343 const unsigned final_shd_bnd_id = this->final_shared_boundary_id();
7344 dump_file << final_shd_bnd_id
7345 <<
" # final shared boundaries id" << std::endl;
7348 const unsigned nprocs = this->shared_boundaries_ids().size();
7349 dump_file << nprocs <<
" # number of processors" << std::endl;
7353 for (
unsigned ip = 0; ip < nprocs; ip++)
7355 for (
unsigned jp = 0; jp < nprocs; jp++)
7361 const unsigned nshared_boundaries_iproc_jproc =
7362 this->shared_boundaries_ids(ip, jp).size();
7366 dump_file << nshared_boundaries_iproc_jproc
7367 <<
" # number of shared boundaries with in two " 7368 <<
"processors" << std::endl;
7369 for (
unsigned is = 0; is < nshared_boundaries_iproc_jproc; is++)
7371 const unsigned shared_boundary_id =
7372 this->shared_boundaries_ids(ip, jp, is);
7373 dump_file << ip <<
" " << jp <<
" " << shared_boundary_id
7374 <<
" # ip jp shared_boundary of processors ip and jp" 7387 const unsigned nshared_boundaries_overlap_internal_boundaries =
7388 this->nshared_boundary_overlaps_internal_boundary();
7389 dump_file << nshared_boundaries_overlap_internal_boundaries
7390 <<
" # number of shared boundaries that overlap internal " 7391 <<
"boundaries" << std::endl;
7393 if (nshared_boundaries_overlap_internal_boundaries > 0)
7395 for (
unsigned isb = init_shd_bnd_id; isb < final_shd_bnd_id; isb++)
7399 if (this->shared_boundary_overlaps_internal_boundary(isb))
7403 const unsigned overlapped_internal_boundary =
7404 shared_boundary_overlapping_internal_boundary(isb);
7406 dump_file << isb <<
" " << overlapped_internal_boundary
7407 <<
" # the shared boundary overlaps the internal " 7408 <<
"boundary " << std::endl;
7419 for (
unsigned b = 0; b < nboundary; b++)
7424 if (Assigned_segments_initial_zeta_values[b])
7428 dump_file <<
"1 # assigned boundary coordinates initial zeta values" 7435 Vector<double> initial_coordinates=this->boundary_initial_coordinate(b);
7437 Vector<double> final_coordinates=this->boundary_final_coordinate(b);
7439 dump_file << std::setprecision(14)
7440 << initial_coordinates[0] <<
" " << initial_coordinates[1]
7441 <<
" # initial coordinates for the current boundary" 7444 dump_file << std::setprecision(14)
7445 << final_coordinates[0] <<
" " << final_coordinates[1]
7446 <<
" # final coordinates for the current boundary" 7453 const unsigned zeta_size =
7454 this->boundary_initial_zeta_coordinate(b).size();
7458 std::ostringstream error_message;
7460 <<
"The dimension for the zeta values container is different\n" 7461 <<
"from 1, the current implementation only supports\n" 7462 <<
"one-dimensioned zeta containers\n\n";
7464 "TriangleMesh::dump_distributed_info_for_restart()",
7465 OOMPH_EXCEPTION_LOCATION);
7469 Vector<double> zeta_initial = this->boundary_initial_zeta_coordinate(b);
7470 Vector<double> zeta_final = this->boundary_final_zeta_coordinate(b);
7472 dump_file << std::setprecision(14)
7474 <<
" # initial zeta value for the current boundary" 7477 dump_file << std::setprecision(14)
7479 <<
" # final zeta value for the current boundary" 7483 const unsigned nsegments = this->nboundary_segment(b);
7485 dump_file << b <<
" " << nsegments
7486 <<
" # of segments for the current boundary" 7490 for (
unsigned is = 0; is < nsegments; is++)
7494 this->boundary_segment_initial_coordinate(b)[is];
7496 this->boundary_segment_final_coordinate(b)[is];
7498 dump_file << std::setprecision(14)
7499 << initial_segment_coordinates[0] <<
" " 7500 << initial_segment_coordinates[1]
7501 <<
" # initial segment coordinates for the current boundary" 7504 dump_file << std::setprecision(14)
7505 << final_segment_coordinates[0] <<
" " 7506 << final_segment_coordinates[1]
7507 <<
" # final segment coordinates for the current boundary" 7512 if (this->boundary_geom_object_pt(b)!=0)
7514 const double zeta_segment_initial =
7515 this->boundary_segment_initial_zeta(b)[is];
7516 const double zeta_segment_final =
7517 this->boundary_segment_final_zeta(b)[is];
7519 dump_file << std::setprecision(14)
7520 << zeta_segment_initial
7521 <<
" # initial segment zeta value for the current boundary" 7524 dump_file << std::setprecision(14)
7525 << zeta_segment_final
7526 <<
" # final segment zeta value for the current boundary" 7531 const double arclength_segment_initial =
7532 this->boundary_segment_initial_arclength(b)[is];
7533 const double arclength_segment_final =
7534 this->boundary_segment_final_arclength(b)[is];
7536 dump_file << std::setprecision(14)
7537 << arclength_segment_initial
7538 <<
" # initial segment arclength for the current boundary" 7541 dump_file << std::setprecision(14)
7542 << arclength_segment_final
7543 <<
" # final segment arclength for the current boundary" 7555 dump_file <<
"0 # assigned boundary coordinates initial zeta values" 7568 template<
class ELEMENT>
7573 if (this->is_mesh_distributed())
7576 const unsigned n_boundary = read_unsigned_line_helper(restart_file);
7579 if (n_boundary != this->nboundary())
7581 std::ostringstream error_message;
7583 <<
"The number of boundaries (" << n_boundary <<
") on the " 7584 <<
"file used for restarting is different\nfrom the number of " 7585 <<
"boundaries ("<< this->nboundary() <<
") on the current " 7588 "TriangleMesh::read_distributed_info_for_restart()",
7589 OOMPH_EXCEPTION_LOCATION);
7594 unsigned n_shared_boundaries =
7595 read_unsigned_line_helper(restart_file);
7598 n_shared_boundaries++;
7599 n_shared_boundaries--;
7602 unsigned init_shd_bnd_id = read_unsigned_line_helper(restart_file);
7608 unsigned final_shd_bnd_id = read_unsigned_line_helper(restart_file);
7616 const unsigned n_procs = read_unsigned_line_helper(restart_file);
7619 if (static_cast<int>(n_procs) != this->communicator_pt()->nproc())
7621 std::ostringstream error_message;
7623 <<
"The number of previously used processors ("<< n_procs
7624 <<
") (read from the restart file) is different\nfrom the " 7625 <<
"number of current used processors (" 7626 << this->communicator_pt()->nproc() <<
")\n\n";
7628 "TriangleMesh::read_distributed_info_for_restart()",
7629 OOMPH_EXCEPTION_LOCATION);
7634 this->shared_boundaries_ids().clear();
7635 this->shared_boundary_from_processors().clear();
7636 this->shared_boundary_overlaps_internal_boundary().clear();
7640 this->shared_boundaries_ids().resize(n_procs);
7644 for (
unsigned ip = 0; ip < n_procs; ip++)
7648 this->shared_boundaries_ids(ip).resize(n_procs);
7649 for (
unsigned jp = 0; jp < n_procs; jp++)
7655 const unsigned nshared_boundaries_iproc_jproc =
7656 read_unsigned_line_helper(restart_file);
7657 for (
unsigned is = 0; is < nshared_boundaries_iproc_jproc; is++)
7661 restart_file >> tmp_ip;
7663 restart_file >> tmp_jp;
7667 const unsigned shared_boundary_id =
7668 read_unsigned_line_helper(restart_file);
7672 this->shared_boundaries_ids(ip, jp).
7673 push_back(shared_boundary_id);
7680 this->shared_boundary_from_processors()[shared_boundary_id] =
7693 const unsigned nshared_boundaries_overlap_internal_boundaries =
7694 read_unsigned_line_helper(restart_file);
7696 for (
unsigned isb = 0;
7697 isb < nshared_boundaries_overlap_internal_boundaries;
7701 unsigned shared_boundary_overlapping;
7702 restart_file >> shared_boundary_overlapping;
7704 const unsigned overlapped_internal_boundary =
7705 read_unsigned_line_helper(restart_file);
7709 this->shared_boundary_overlaps_internal_boundary()
7710 [shared_boundary_overlapping] = overlapped_internal_boundary;
7718 for (
unsigned b = 0; b < n_boundary; b++)
7722 const unsigned boundary_coordinates_initial_zeta_values_assigned =
7723 read_unsigned_line_helper(restart_file);
7725 if (boundary_coordinates_initial_zeta_values_assigned)
7730 Boundary_initial_coordinate[b].clear();
7731 Boundary_final_coordinate[b].clear();
7733 Boundary_initial_zeta_coordinate[b].clear();
7734 Boundary_final_zeta_coordinate[b].clear();
7737 Boundary_segment_inverted[b].clear();
7738 Boundary_segment_initial_coordinate[b].clear();
7739 Boundary_segment_final_coordinate[b].clear();
7741 Boundary_segment_initial_zeta[b].clear();
7742 Boundary_segment_final_zeta[b].clear();
7744 Boundary_segment_initial_arclength[b].clear();
7745 Boundary_segment_final_arclength[b].clear();
7754 restart_file >> initial_coordinates[0] >> initial_coordinates[1];
7757 restart_file.ignore(80,
'\n');
7762 restart_file >> final_coordinates[0] >> final_coordinates[1];
7765 restart_file.ignore(80,
'\n');
7770 this->boundary_initial_coordinate(b)=initial_coordinates;
7771 this->boundary_final_coordinate(b)=final_coordinates;
7775 restart_file >> zeta_initial[0];
7778 restart_file.ignore(80,
'\n');
7781 restart_file >> zeta_final[0];
7784 restart_file.ignore(80,
'\n');
7787 this->boundary_initial_zeta_coordinate(b) = zeta_initial;
7788 this->boundary_final_zeta_coordinate(b) = zeta_final;
7791 unsigned current_boundary;
7792 restart_file >> current_boundary;
7795 if (current_boundary != b)
7797 std::ostringstream error_message;
7799 <<
"The current boundary id from the restart file (" 7800 << current_boundary <<
") is different from\nthe boundary id " 7801 << b <<
"currently used to re-establish the initial and\nfinal " 7802 <<
"segment's zeta values\n\n";
7804 "TriangleMesh::read_distributed_info_for_restart()",
7805 OOMPH_EXCEPTION_LOCATION);
7811 restart_file >> nsegments;
7814 restart_file.ignore(80,
'\n');
7819 for (
unsigned is = 0; is < nsegments; is++)
7825 restart_file >> initial_segment_coordinates[0]
7826 >> initial_segment_coordinates[1];
7829 restart_file.ignore(80,
'\n');
7834 restart_file >> final_segment_coordinates[0]
7835 >> final_segment_coordinates[1];
7838 restart_file.ignore(80,
'\n');
7841 this->boundary_segment_initial_coordinate(b).push_back(
7842 initial_segment_coordinates);
7843 this->boundary_segment_final_coordinate(b).push_back(
7844 final_segment_coordinates);
7847 if (this->boundary_geom_object_pt(b)!=0)
7850 restart_file >> zeta_segment_initial[0];
7853 restart_file.ignore(80,
'\n');
7856 restart_file >> zeta_segment_final[0];
7859 restart_file.ignore(80,
'\n');
7862 this->boundary_segment_initial_zeta(b).push_back(
7863 zeta_segment_initial[0]);
7864 this->boundary_segment_final_zeta(b).push_back(
7865 zeta_segment_final[0]);
7870 restart_file >> arclength_segment_initial[0];
7873 restart_file.ignore(80,
'\n');
7876 restart_file >> arclength_segment_final[0];
7879 restart_file.ignore(80,
'\n');
7882 this->boundary_segment_initial_arclength(b).push_back(
7883 arclength_segment_initial[0]);
7884 this->boundary_segment_final_arclength(b).push_back(
7885 arclength_segment_final[0]);
7898 #endif // #ifdef OOMPH_HAS_MPI 7899 #endif // #ifdef OOMPH_HAS_TRIANGLE_LIB 7905 template<
class ELEMENT>
7907 std::ostream &outfile)
7916 std::set<Node*> boundary_nodes_pt;
7917 const unsigned n_boundary_ele = this->nboundary_element(b);
7918 for (
unsigned e = 0;
e < n_boundary_ele;
e++)
7922 #ifdef OOMPH_HAS_MPI 7928 int face_index = this->face_index_at_boundary(b,
e);
7931 bulk_ele_pt, face_index);
7934 const unsigned n_nodes = face_ele_pt->
nnode();
7935 for (
unsigned i = 0;
i < n_nodes;
i++)
7940 boundary_nodes_pt.insert(tmp_node_pt);
7946 #ifdef OOMPH_HAS_MPI 7952 outfile <<
"ZONE T=\"Boundary nodes" << b <<
"\"\n";
7954 std::set<Vector<double> > set_node_coord;
7956 for (std::set<Node*>::iterator it = boundary_nodes_pt.begin();
7957 it != boundary_nodes_pt.end(); it++)
7959 Node *inode_pt = (*it);
7962 const unsigned n_dim = inode_pt->
ndim();
7968 node_coord[0] = zeta[0];
7969 for (
unsigned j = 0; j < n_dim; j++)
7971 node_coord[j+1] = inode_pt->
x(j);
7973 set_node_coord.insert(node_coord);
7976 for (std::set<
Vector<double> >::iterator it = set_node_coord.begin();
7977 it != set_node_coord.end(); it++)
7983 const unsigned n_dim = node_coord.size()-1;
7984 for (
unsigned j = 0; j < n_dim; j++)
7986 outfile << node_coord[j+1] <<
" ";
7989 outfile <<
"0.0" << std::endl;
7993 outfile <<
"ZONE T=\"Boundary coordinates " << b <<
"\"\n";
7994 for (std::set<
Vector<double> >::iterator it = set_node_coord.begin();
7995 it != set_node_coord.end(); it++)
8001 const unsigned n_dim = node_coord.size()-1;
8002 for (
unsigned j = 0; j < n_dim; j++)
8004 outfile << node_coord[j+1] <<
" ";
8008 outfile << node_coord[0] << std::endl;
8013 #ifdef OOMPH_HAS_MPI 8020 template<
class ELEMENT>
8031 const unsigned my_rank = this->communicator_pt()->my_rank();
8053 const unsigned nouter=this->Outer_boundary_pt.size();
8054 for (
unsigned i = 0;
i < nouter;
i++)
8056 const unsigned npolylines = this->Outer_boundary_pt[
i]->npolyline();
8057 for (
unsigned p = 0; p < npolylines; p++)
8061 this->Outer_boundary_pt[
i]->polyline_pt(p);
8062 const unsigned nvertex = tmp_polyline_pt->
nvertex();
8068 const unsigned bound_id = tmp_polyline_pt->
boundary_id();
8069 if (!boundary_was_splitted(bound_id))
8071 unsorted_outer_polyline_pt.push_back(tmp_polyline_pt);
8077 boundary_subpolylines(bound_id);
8078 const unsigned nsub_poly = tmp_vector_polylines.size();
8082 std::ostringstream error_message;
8084 <<
"The boundary ("<<bound_id<<
") was marked to be splitted but\n" 8085 <<
"there are only ("<<nsub_poly<<
") polylines to represent it.\n";
8087 OOMPH_CURRENT_FUNCTION,
8088 OOMPH_EXCEPTION_LOCATION);
8093 for (
unsigned isub = 0; isub < nsub_poly; isub++)
8095 unsorted_outer_polyline_pt.push_back(tmp_vector_polylines[isub]);
8097 const unsigned nsvertex = tmp_vector_polylines[isub]->nvertex();
8100 std::ostringstream error_message;
8102 <<
"The current chunk ("<< isub <<
") of the polyline with\n" 8103 <<
"boundary id (" << bound_id <<
") has no vertices\n";
8105 OOMPH_CURRENT_FUNCTION,
8106 OOMPH_EXCEPTION_LOCATION);
8108 #endif // #ifdef PARANOID 8116 unsigned nunsorted_outer_polyline = unsorted_outer_polyline_pt.size();
8117 if (nunsorted_outer_polyline > 0)
8122 sort_polylines_helper(unsorted_outer_polyline_pt, sorted_outer_curves_pt);
8141 const unsigned ninternal_closed=this->Internal_polygon_pt.size();
8142 for (
unsigned i = 0;
i < ninternal_closed;
i++)
8144 const unsigned npolylines = this->Internal_polygon_pt[
i]->npolyline();
8145 for (
unsigned p = 0; p < npolylines; p++)
8149 this->Internal_polygon_pt[
i]->polyline_pt(p);
8150 const unsigned nvertex = tmp_polyline_pt->
nvertex();
8156 const unsigned bound_id = tmp_polyline_pt->
boundary_id();
8157 if (!boundary_was_splitted(bound_id))
8159 unsorted_internal_closed_polyline_pt.push_back(tmp_polyline_pt);
8165 boundary_subpolylines(bound_id);
8166 const unsigned nsub_poly = tmp_vector_polylines.size();
8170 std::ostringstream error_message;
8172 <<
"The boundary ("<<bound_id<<
") was marked to be splitted but\n" 8173 <<
"there are only ("<<nsub_poly<<
") polylines to represent it.\n";
8175 OOMPH_CURRENT_FUNCTION,
8176 OOMPH_EXCEPTION_LOCATION);
8181 for (
unsigned isub = 0; isub < nsub_poly; isub++)
8183 unsorted_internal_closed_polyline_pt.push_back(tmp_vector_polylines[isub]);
8185 const unsigned nsvertex = tmp_vector_polylines[isub]->nvertex();
8188 std::ostringstream error_message;
8190 <<
"The current chunk ("<< isub <<
") of the polyline with\n" 8191 <<
"boundary id (" << bound_id <<
") has no vertices\n";
8193 OOMPH_CURRENT_FUNCTION,
8194 OOMPH_EXCEPTION_LOCATION);
8196 #endif // #ifdef PARANOID 8203 const unsigned nunsorted_internal_closed_polyline =
8204 unsorted_internal_closed_polyline_pt.size();
8206 if (nunsorted_internal_closed_polyline > 0)
8210 sort_polylines_helper(unsorted_internal_closed_polyline_pt,
8211 sorted_internal_closed_curves_pt);
8229 const unsigned ninternal_open = this->Internal_open_curve_pt.size();
8230 for (
unsigned i = 0;
i < ninternal_open;
i++)
8232 const unsigned ncurve_section =
8233 this->Internal_open_curve_pt[
i]->ncurve_section();
8234 for (
unsigned p = 0; p < ncurve_section; p++)
8238 this->Internal_open_curve_pt[
i]->polyline_pt(p);
8239 const unsigned nvertex = tmp_polyline_pt->
nvertex();
8245 const unsigned bound_id = tmp_polyline_pt->
boundary_id();
8246 if (!boundary_was_splitted(bound_id))
8250 if (!boundary_marked_as_shared_boundary(bound_id, 0))
8252 unsorted_internal_open_polyline_pt.push_back(tmp_polyline_pt);
8259 boundary_subpolylines(bound_id);
8260 const unsigned nsub_poly = tmp_vector_polylines.size();
8264 std::ostringstream error_message;
8266 <<
"The boundary ("<<bound_id<<
") was marked to be splitted but\n" 8267 <<
"there are only ("<<nsub_poly<<
") polylines to represent it.\n";
8269 OOMPH_CURRENT_FUNCTION,
8270 OOMPH_EXCEPTION_LOCATION);
8275 for (
unsigned isub = 0; isub < nsub_poly; isub++)
8279 if (!boundary_marked_as_shared_boundary(bound_id, isub))
8281 unsorted_internal_open_polyline_pt.push_back(tmp_vector_polylines[isub]);
8284 const unsigned nsvertex = tmp_vector_polylines[isub]->nvertex();
8287 std::ostringstream error_message;
8289 <<
"The current chunk ("<< isub <<
") of the polyline with\n" 8290 <<
"boundary id (" << bound_id <<
") has no vertices\n";
8292 OOMPH_CURRENT_FUNCTION,
8293 OOMPH_EXCEPTION_LOCATION);
8295 #endif // #ifdef PARANOID 8302 const unsigned nunsorted_internal_open_polyline =
8303 unsorted_internal_open_polyline_pt.size();
8305 if (nunsorted_internal_open_polyline > 0)
8309 sort_polylines_helper(unsorted_internal_open_polyline_pt,
8310 sorted_internal_open_curves_pt);
8330 const unsigned ncurves = nshared_boundary_curves(my_rank);
8331 for (
unsigned i = 0;
i < ncurves;
i++)
8333 const unsigned npolylines = nshared_boundary_polyline(my_rank,
i);
8334 for (
unsigned p = 0; p < npolylines; p++)
8336 const unsigned nvertex =
8337 shared_boundary_polyline_pt(my_rank,
i, p)->nvertex();
8341 shared_boundary_polyline_pt(my_rank,
i, p);
8345 if (this->nshared_boundary_overlaps_internal_boundary() > 0)
8348 const unsigned shd_bnd_id = tmp_shared_poly_pt->
boundary_id();
8352 if (this->shared_boundary_overlaps_internal_boundary(shd_bnd_id))
8354 unsorted_shared_to_internal_polyline_pt.push_back(
8355 tmp_shared_poly_pt);
8358 unsorted_shared_polyline_pt.push_back(tmp_shared_poly_pt);
8364 const unsigned nunsorted_shared_polyline =
8365 unsorted_shared_polyline_pt.size();
8367 if (nunsorted_shared_polyline > 0)
8371 sort_polylines_helper(unsorted_shared_polyline_pt, sorted_shared_curves_pt);
8381 const unsigned nouter_curves = sorted_outer_curves_pt.size();
8382 const unsigned ninternal_closed_curves =
8383 sorted_internal_closed_curves_pt.size();
8384 const unsigned nshared_curves = sorted_shared_curves_pt.size();
8385 const unsigned ntotal_curves = nouter_curves +
8386 ninternal_closed_curves +
8390 unsigned counter = 0;
8395 for (
unsigned i = 0;
i < nshared_curves;
i++,counter++)
8397 all_curves_pt[counter] = sorted_shared_curves_pt[
i];
8401 for (
unsigned i = 0;
i < ninternal_closed_curves;
i++,counter++)
8403 all_curves_pt[counter] = sorted_internal_closed_curves_pt[
i];
8407 for (
unsigned i = 0;
i < nouter_curves;
i++,counter++)
8409 all_curves_pt[counter] = sorted_outer_curves_pt[
i];
8414 this->create_tmp_polygons_helper(all_curves_pt,polygons_pt);
8416 this->create_tmp_open_curves_helper(sorted_internal_open_curves_pt,
8417 unsorted_shared_to_internal_polyline_pt,
8431 this->create_shared_polylines_connections();
8448 const unsigned n_holes = this->Internal_polygon_pt.size();
8449 for (
unsigned h = 0; h < n_holes; h++)
8452 this->Internal_polygon_pt[h]->internal_point();
8454 if (!hole_coordinates.empty())
8456 new_holes_coordinates.push_back(hole_coordinates);
8462 if (First_time_compute_holes_left_by_halo_elements)
8465 const unsigned n_extra_holes = Extra_holes_coordinates.size();
8466 for (
unsigned h = 0; h < n_extra_holes; h++)
8469 new_holes_coordinates.push_back(hole_coordinates);
8473 Original_extra_holes_coordinates = Extra_holes_coordinates;
8476 First_time_compute_holes_left_by_halo_elements =
false;
8483 const unsigned n_original_extra_holes =
8484 Original_extra_holes_coordinates.size();
8485 for (
unsigned h = 0; h < n_original_extra_holes; h++)
8487 Vector<double> hole_coordinates = Original_extra_holes_coordinates[h];
8488 new_holes_coordinates.push_back(hole_coordinates);
8494 compute_holes_left_by_halo_elements_helper(new_holes_coordinates);
8498 update_holes_information_helper(polygons_pt, new_holes_coordinates);
8504 Extra_holes_coordinates = new_holes_coordinates;
8517 template<
class ELEMENT>
8533 const unsigned ncurves = polylines_pt.size();
8536 const unsigned nunsorted_curves = ncurves;
8538 unsigned nsorted_curves = 0;
8541 std::vector<bool> done_curve(ncurves);
8546 std::list<Vector<TriangleMeshPolyLine*> > list_building_polygon_pt;
8549 bool root_curve_found =
false;
8554 unsigned root_curve_idx = 0;
8557 for (
unsigned ic = 0; ic < ncurves; ic++)
8559 if (!done_curve[ic])
8561 root_curve_idx = ic;
8564 root_curve_found =
true;
8566 done_curve[ic] =
true;
8573 if (!root_curve_found)
8575 std::stringstream err;
8576 err <<
"The root curve to create a polygon from the shared and " 8577 <<
"original boundaries was not found!!!\n";
8579 "TriangleMesh::create_tmp_polygons_helper()",
8580 OOMPH_EXCEPTION_LOCATION);
8588 list_building_polygon_pt.push_back(root_curve_pt);
8595 const unsigned nroot_curve_polyline = root_curve_pt.size();
8597 root_curve_pt[0]->initial_vertex_coordinate(root_curve_initial_vertex);
8598 root_curve_pt[nroot_curve_polyline-1]->
8599 final_vertex_coordinate(root_curve_final_vertex);
8603 ((root_curve_initial_vertex[0] - root_curve_final_vertex[0])*
8604 (root_curve_initial_vertex[0] - root_curve_final_vertex[0]))
8606 ((root_curve_initial_vertex[1] - root_curve_final_vertex[1])*
8607 (root_curve_initial_vertex[1] - root_curve_final_vertex[1]));
8614 curve_section_pt(nroot_curve_polyline);
8617 for (
unsigned i = 0;
i < nroot_curve_polyline;
i++)
8618 {curve_section_pt[
i] = root_curve_pt[
i];}
8625 this->Free_polygon_pt.insert(new_polygon_pt);
8628 polygons_pt.push_back(new_polygon_pt);
8635 bool added_curve =
false;
8640 bool polygon_created =
false;
8644 added_curve =
false;
8647 for (
unsigned ic = root_curve_idx+1; ic < ncurves; ic++)
8649 if (!done_curve[ic])
8657 const unsigned ncurrent_curve_polyline = current_curve_pt.size();
8664 current_curve_pt[0]->
8665 initial_vertex_coordinate(current_curve_initial_vertex);
8666 current_curve_pt[ncurrent_curve_polyline-1]->
8667 final_vertex_coordinate(current_curve_final_vertex);
8673 ((current_curve_final_vertex[0] - root_curve_initial_vertex[0])*
8674 (current_curve_final_vertex[0] - root_curve_initial_vertex[0]))
8676 ((current_curve_final_vertex[1] - root_curve_initial_vertex[1])*
8677 (current_curve_final_vertex[1] - root_curve_initial_vertex[1]));
8683 list_building_polygon_pt.push_front(current_curve_pt);
8685 done_curve[ic] =
true;
8687 root_curve_initial_vertex[0] = current_curve_initial_vertex[0];
8688 root_curve_initial_vertex[1] = current_curve_initial_vertex[1];
8697 ((current_curve_initial_vertex[0] - root_curve_initial_vertex[0])*
8698 (current_curve_initial_vertex[0] - root_curve_initial_vertex[0]))
8700 ((current_curve_initial_vertex[1] - root_curve_initial_vertex[1])*
8701 (current_curve_initial_vertex[1] - root_curve_initial_vertex[1]));
8707 tmp_curve_pt(ncurrent_curve_polyline);
8709 for (
unsigned it = 0; it < ncurrent_curve_polyline; it++)
8711 current_curve_pt[it]->reverse();
8712 tmp_curve_pt[it] = current_curve_pt[it];
8716 for (
int i = ncurrent_curve_polyline - 1;
i >= 0;
i--,count++)
8717 {current_curve_pt[count] = tmp_curve_pt[
i];}
8719 list_building_polygon_pt.push_front(current_curve_pt);
8721 done_curve[ic] =
true;
8723 root_curve_initial_vertex[0] = current_curve_final_vertex[0];
8724 root_curve_initial_vertex[1] = current_curve_final_vertex[1];
8733 ((current_curve_initial_vertex[0] - root_curve_final_vertex[0])*
8734 (current_curve_initial_vertex[0] - root_curve_final_vertex[0]))
8736 ((current_curve_initial_vertex[1] - root_curve_final_vertex[1])*
8737 (current_curve_initial_vertex[1] - root_curve_final_vertex[1]));
8743 list_building_polygon_pt.push_back(current_curve_pt);
8745 done_curve[ic] =
true;
8747 root_curve_final_vertex[0] = current_curve_final_vertex[0];
8748 root_curve_final_vertex[1] = current_curve_final_vertex[1];
8757 ((current_curve_final_vertex[0] - root_curve_final_vertex[0])*
8758 (current_curve_final_vertex[0] - root_curve_final_vertex[0]))
8760 ((current_curve_final_vertex[1] - root_curve_final_vertex[1])*
8761 (current_curve_final_vertex[1] - root_curve_final_vertex[1]));
8767 tmp_curve_pt(ncurrent_curve_polyline);
8769 for (
unsigned it = 0; it < ncurrent_curve_polyline; it++)
8771 current_curve_pt[it]->reverse();
8772 tmp_curve_pt[it] = current_curve_pt[it];
8776 for (
int i = ncurrent_curve_polyline - 1;
i >= 0;
i--,count++)
8777 {current_curve_pt[count] = tmp_curve_pt[
i];}
8779 list_building_polygon_pt.push_back(current_curve_pt);
8781 done_curve[ic] =
true;
8783 root_curve_final_vertex[0] = current_curve_initial_vertex[0];
8784 root_curve_final_vertex[1] = current_curve_initial_vertex[1];
8798 ((root_curve_initial_vertex[0] - root_curve_final_vertex[0])*
8799 (root_curve_initial_vertex[0] - root_curve_final_vertex[0]))
8801 ((root_curve_initial_vertex[1] - root_curve_final_vertex[1])*
8802 (root_curve_initial_vertex[1] - root_curve_final_vertex[1]));
8808 added_curve =
false;
8811 polygon_created =
true;
8817 }
while(added_curve);
8820 if (!polygon_created)
8822 std::stringstream error_message;
8824 <<
"It was no possible to create a TriangleMeshPolygon with " 8825 <<
"the input set of curves\n" 8826 <<
"These are the initial and final vertices in the current " 8827 <<
"sorted list of\nTriangleMeshPolyLines\n\n";
8830 unsigned icurve = 0;
8832 = list_building_polygon_pt.begin();
8833 it != list_building_polygon_pt.end(); it++, icurve++)
8835 const unsigned ncurrent_curve_polyline = (*it).size();
8837 <<
"TriangleMeshCurve #" << icurve <<
"\n" 8838 <<
"-----------------------------------\n";
8839 for (
unsigned ip = 0; ip < ncurrent_curve_polyline; ip++)
8843 (*it)[ip]->initial_vertex_coordinate(init_vertex);
8844 (*it)[ip]->final_vertex_coordinate(final_vertex);
8846 <<
"TriangleMeshPolyLine #" << ip <<
"\n" 8847 <<
"Initial vertex: ("<<init_vertex[0]<<
","<<init_vertex[1]<<
")\n" 8848 <<
"Final vertex: ("<<final_vertex[0]<<
","<<final_vertex[1]<<
")\n";
8853 "TriangleMesh::create_tmp_polygons_helper()",
8854 OOMPH_EXCEPTION_LOCATION);
8860 unsigned ntotal_polylines = 0;
8863 = list_building_polygon_pt.begin();
8864 it != list_building_polygon_pt.end(); it++)
8866 ntotal_polylines+=(*it).size();
8873 unsigned counter = 0;
8875 = list_building_polygon_pt.begin();
8876 it != list_building_polygon_pt.end(); it++)
8878 const unsigned ncurrent_curve_polyline = (*it).size();
8879 for (
unsigned ip = 0; ip < ncurrent_curve_polyline; ip++,counter++)
8881 curve_section_pt[counter] = (*it)[ip];
8890 this->Free_polygon_pt.insert(new_polygon_pt);
8893 polygons_pt.push_back(new_polygon_pt);
8898 }
while(nsorted_curves < nunsorted_curves);
8907 template<
class ELEMENT>
8915 const unsigned ninternal_open_curves = sorted_open_curves_pt.size();
8919 for (
unsigned i = 0;
i < ninternal_open_curves;
i++)
8922 const unsigned npoly = sorted_open_curves_pt[
i].size();
8924 for (
unsigned j = 0; j < npoly; j++)
8926 tmp_curve_section[j] = sorted_open_curves_pt[
i][j];
8933 this->Free_open_curve_pt.insert(new_open_curve_pt);
8936 open_curves_pt.push_back(new_open_curve_pt);
8948 template<
class ELEMENT>
8950 std::set<FiniteElement*> &element_in_processor_pt,
8951 const int &root_edge_bnd_id,
8952 std::map<std::pair<Node*,Node*>,
bool> &overlapped_face,
8953 std::map<
unsigned, std::map<Node*, bool> >
8954 &node_on_bnd_not_overlapped_by_shd_bnd,
8955 std::list<Node*> ¤t_polyline_nodes,
8956 std::map<
unsigned, std::list<Node*> >
8957 &shared_bnd_id_to_sorted_list_node_pt,
8958 const unsigned &node_degree,
8960 const bool called_from_load_balance)
8963 int flag_to_return = -1;
8972 bool overlapping_internal_boundary =
false;
8974 unsigned internal_overlaping_bnd_id = 0;
8975 if (root_edge_bnd_id != -1)
8978 overlapping_internal_boundary =
true;
8980 internal_overlaping_bnd_id =
static_cast<unsigned>(root_edge_bnd_id);
8991 bool is_node_living_in_non_overlapped_boundary =
false;
8995 const unsigned noriginal_bnd = this->initial_shared_boundary_id();
8996 for (
unsigned bb=0;bb<noriginal_bnd;bb++)
9004 if (overlapping_internal_boundary)
9013 const bool on_bnd_edge_not_overlapped_by_shd_bnd =
9014 node_on_bnd_not_overlapped_by_shd_bnd[bb][new_node_pt];
9015 if (bb != internal_overlaping_bnd_id ||
9016 ((bb == internal_overlaping_bnd_id) &&
9017 (on_bnd_edge_not_overlapped_by_shd_bnd)))
9020 if (bb != internal_overlaping_bnd_id)
9022 is_node_living_in_non_overlapped_boundary =
true;
9032 const unsigned n_bound_ele = this->nboundary_element(bb);
9033 if (n_bound_ele > 0)
9037 for (
unsigned e = 0;
e < n_bound_ele;
e++)
9043 std::set<FiniteElement*>::iterator it =
9044 element_in_processor_pt.find(bulk_ele_pt);
9046 if (it!=element_in_processor_pt.end())
9049 bool found_node =
false;
9051 int face_index = this->face_index_at_boundary(bb,
e);
9056 const unsigned n_node_face = face_ele_pt->
nnode();
9059 Node* last_node_pt = face_ele_pt->
node_pt(n_node_face-1);
9061 std::pair<Node*, Node*> tmp_edge =
9062 std::make_pair(first_node_pt, last_node_pt);
9066 if (!overlapped_face[tmp_edge])
9069 for (
unsigned n = 0; n < n_node_face; n++)
9072 if (face_ele_pt->
node_pt(n) == new_node_pt)
9088 flag_to_return = bb;
9089 return flag_to_return;
9117 const unsigned n_bound_ele = this->nboundary_element(bb);
9118 if (n_bound_ele > 0)
9122 for (
unsigned e = 0;
e < n_bound_ele;
e++)
9128 std::set<FiniteElement*>::iterator it =
9129 element_in_processor_pt.find(bulk_ele_pt);
9131 if (it!=element_in_processor_pt.end())
9134 bool found_node =
false;
9136 int face_index = this->face_index_at_boundary(bb,
e);
9141 const unsigned n_node_face = face_ele_pt->
nnode();
9144 Node* last_node_pt = face_ele_pt->
node_pt(n_node_face-1);
9146 std::pair<Node*, Node*> tmp_edge =
9147 std::make_pair(first_node_pt, last_node_pt);
9151 if (!overlapped_face[tmp_edge])
9154 for (
unsigned n = 0; n < n_node_face; n++)
9157 if (face_ele_pt->
node_pt(n) == new_node_pt)
9173 flag_to_return = bb;
9174 return flag_to_return;
9199 if (!overlapping_internal_boundary)
9204 flag_to_return = -3;
9211 if (is_node_living_in_non_overlapped_boundary)
9213 flag_to_return = -3;
9222 if (flag_to_return >= 0)
9224 return flag_to_return;
9237 for (std::map<
unsigned, std::list<Node*> >::iterator it =
9238 shared_bnd_id_to_sorted_list_node_pt.begin();
9239 it != shared_bnd_id_to_sorted_list_node_pt.end();
9245 const unsigned i_bnd_id = (*it).first;
9248 std::list<Node*>::iterator it_list = (*it).second.begin();
9250 const unsigned n_nodes = (*it).second.size();
9252 for (
unsigned i = 0;
i < n_nodes;
i++, it_list++)
9255 if ((*it_list) == new_node_pt)
9259 candidate_shared_bnd_to_connect.push_back(i_bnd_id);
9270 const unsigned n_candidate_shared_bnd_to_connect =
9271 candidate_shared_bnd_to_connect.size();
9274 if (n_candidate_shared_bnd_to_connect > 0)
9281 if (called_from_load_balance)
9283 return candidate_shared_bnd_to_connect[0];
9296 shared_boundaries_in_this_processor(shared_bound_in_this_proc);
9302 const unsigned n_shared_bound_in_this_proc =
9303 shared_bound_in_this_proc.size();
9306 for (
unsigned i = 0;
i < n_candidate_shared_bnd_to_connect;
i++)
9309 const unsigned i_candidate_shared_bnd =
9310 candidate_shared_bnd_to_connect[
i];
9313 for (
unsigned j = 0; j < n_shared_bound_in_this_proc; j++)
9316 if (i_candidate_shared_bnd == shared_bound_in_this_proc[j])
9319 flag_to_return = i_candidate_shared_bnd;
9320 return flag_to_return;
9331 flag_to_return = -3;
9337 if (flag_to_return >= 0)
9339 return flag_to_return;
9348 unsigned nrepeated = 0;
9349 for (std::list<Node*>::iterator it_list = current_polyline_nodes.begin();
9350 it_list != current_polyline_nodes.end();
9355 if ((*it_list) == new_node_pt) {nrepeated++;}
9364 flag_to_return = -2;
9370 if (node_degree > 2)
9372 flag_to_return = -3;
9376 return flag_to_return;
9387 template<
class ELEMENT>
9391 const unsigned my_rank = this->communicator_pt()->my_rank();
9395 this->Shared_boundary_polyline_pt[my_rank];
9399 const unsigned ncurves = shared_curves_pt.size();
9400 for (
unsigned icurve = 0; icurve < ncurves; icurve++)
9403 const unsigned npoly = shared_curves_pt[icurve].size();
9404 for (
unsigned ipoly = 0; ipoly < npoly; ipoly++)
9410 const unsigned bound_id = shd_poly_pt->
boundary_id();
9413 const bool is_connected_to_the_left =
9417 const bool is_connected_to_the_right =
9423 if (is_connected_to_the_left || is_connected_to_the_right)
9427 const unsigned n_vertex = shd_poly_pt->
nvertex();
9434 if (is_connected_to_the_left)
9438 const unsigned uconnection_to_the_left =
9446 bool connecting_to_an_split_boundary =
false;
9450 bool connecting_to_an_overlaped_boundary =
false;
9453 if (uconnection_to_the_left == bound_id)
9456 poly_to_connect_pt = shd_poly_pt;
9461 const unsigned initial_shd_bnd_id = initial_shared_boundary_id();
9463 if (uconnection_to_the_left >= initial_shd_bnd_id)
9467 poly_to_connect_pt =
9468 boundary_polyline_pt(uconnection_to_the_left);
9476 if (boundary_was_splitted(uconnection_to_the_left))
9478 connecting_to_an_split_boundary =
true;
9488 if (connecting_to_an_split_boundary)
9492 const unsigned n_sub_poly =
9493 nboundary_subpolylines(uconnection_to_the_left);
9498 for (
unsigned ii =0; ii < n_sub_poly; ii++)
9500 if (boundary_marked_as_shared_boundary(
9501 uconnection_to_the_left, ii))
9505 connecting_to_an_overlaped_boundary =
true;
9516 if (boundary_marked_as_shared_boundary(
9517 uconnection_to_the_left, 0))
9521 connecting_to_an_overlaped_boundary =
true;
9528 if (!(connecting_to_an_split_boundary ||
9529 connecting_to_an_overlaped_boundary))
9533 poly_to_connect_pt =
9534 boundary_polyline_pt(uconnection_to_the_left);
9545 if (!connecting_to_an_split_boundary)
9547 if (boundary_was_splitted(uconnection_to_the_left))
9549 std::stringstream error;
9551 <<
"The current shared boundary (" << bound_id <<
") was " 9552 <<
"marked to have a connection\nto the left with the " 9553 <<
"boundary (" << uconnection_to_the_left <<
").\n" 9554 <<
"The problem is that the destination boundary (possibly\n" 9555 <<
"another shared boundary) is marked to be split\n" 9556 <<
"There should not be split shared boundaries\n\n";
9559 "TriangleMesh::create_shared_polylines_connections()",
9560 OOMPH_EXCEPTION_LOCATION);
9577 if (!connecting_to_an_split_boundary)
9581 if (!connecting_to_an_overlaped_boundary)
9585 unsigned vertex_index = 0;
9587 const bool found_vertex_index =
9588 get_connected_vertex_number_on_destination_polyline(
9589 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9593 if (!found_vertex_index)
9595 std::stringstream error;
9597 <<
"The current shared boundary (" << bound_id <<
") was " 9598 <<
"marked to have a connection\nto the left with the " 9599 <<
"boundary (" << uconnection_to_the_left <<
").\n" 9600 <<
"The problem is that the left vertex of the current\n" 9601 <<
"shared boundary is not in the list of vertices of the\n" 9602 <<
"boundary to connect.\n\n" 9603 <<
"This is the left vertex of the current shared boundary\n" 9604 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", " 9605 << shd_bnd_left_vertex[1] <<
")\n\n" 9606 <<
"This is the list of vertices on the destination " 9608 const unsigned n_v = poly_to_connect_pt->
nvertex();
9609 for (
unsigned i = 0;
i < n_v;
i++)
9614 <<
"Vertex #"<<
i<<
": ("<<cvertex[0]<<
", "<<cvertex[1]<<
")\n";
9618 "TriangleMesh::create_shared_polylines_connections()",
9619 OOMPH_EXCEPTION_LOCATION);
9626 poly_to_connect_pt, vertex_index);
9636 unsigned vertex_index = 0;
9638 bool found_vertex_index =
false;
9643 get_shared_boundaries_overlapping_internal_boundary(
9644 uconnection_to_the_left, dst_shd_bnd_ids);
9648 const unsigned n_shd_bnd_overlap_int_bnd =
9649 dst_shd_bnd_ids.size();
9653 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
9656 const unsigned new_connection_to_the_left =
9657 dst_shd_bnd_ids[ss];
9661 poly_to_connect_pt =
9662 boundary_polyline_pt(new_connection_to_the_left);
9664 if (poly_to_connect_pt!=0)
9668 found_vertex_index =
9669 get_connected_vertex_number_on_destination_polyline(
9670 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9675 if (found_vertex_index)
9685 if (!found_vertex_index)
9687 std::stringstream error;
9689 <<
"The current shared boundary (" << bound_id <<
") was " 9690 <<
"marked to have a connection\nto the left with the " 9691 <<
"boundary (" << uconnection_to_the_left <<
").\n" 9692 <<
"This last boundary is marked to be overlaped by " 9693 <<
"shared boundaries\n" 9694 <<
"The problem is that the left vertex of the current\n" 9695 <<
"shared boundary is not in the list of vertices of the\n" 9696 <<
"boundary to connect.\n\n" 9697 <<
"This is the left vertex of the current shared boundary\n" 9698 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", " 9699 << shd_bnd_left_vertex[1] <<
")\n\n" 9700 <<
"This is the list of vertices on the destination " 9703 get_shared_boundaries_overlapping_internal_boundary(
9704 uconnection_to_the_left, dst_shd_bnd_ids);
9705 const unsigned n_shd_bnd_overlap_int_bnd =
9706 dst_shd_bnd_ids.size();
9707 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
9709 const unsigned new_connection_to_the_left =
9710 dst_shd_bnd_ids[ss];
9711 poly_to_connect_pt =
9712 boundary_polyline_pt(new_connection_to_the_left);
9713 if (poly_to_connect_pt != 0)
9715 const unsigned shd_bnd_id_overlap =
9717 error <<
"Shared boundary id(" 9718 << shd_bnd_id_overlap <<
")\n";
9719 const unsigned n_v = poly_to_connect_pt->
nvertex();
9720 for (
unsigned i = 0;
i < n_v;
i++)
9725 <<
"Vertex #"<<
i<<
": ("<<cvertex[0]<<
", " 9726 <<cvertex[1]<<
")\n";
9733 "TriangleMesh::create_shared_polylines_connections()",
9734 OOMPH_EXCEPTION_LOCATION);
9743 poly_to_connect_pt, vertex_index);
9755 boundary_subpolylines(uconnection_to_the_left);
9758 const unsigned nsub_poly = tmp_vector_subpolylines.size();
9762 std::ostringstream error_message;
9764 <<
"The boundary (" << uconnection_to_the_left <<
") was " 9765 <<
"marked to be splitted but\n" 9766 <<
"there are only ("<<nsub_poly<<
") polylines to " 9767 <<
"represent it.\n";
9769 error_message.str(),
9770 "TriangleMesh::create_shared_polylines_connections()",
9771 OOMPH_EXCEPTION_LOCATION);
9783 if (!connecting_to_an_overlaped_boundary)
9789 unsigned vertex_index = 0;
9791 unsigned sub_poly_to_connect = 0;
9793 bool found_vertex_index =
false;
9797 for (
unsigned isub = 0; isub < nsub_poly; isub++)
9800 poly_to_connect_pt = tmp_vector_subpolylines[isub];
9802 found_vertex_index =
9803 get_connected_vertex_number_on_destination_polyline(
9804 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9807 if (found_vertex_index)
9811 sub_poly_to_connect = isub;
9819 if (!found_vertex_index)
9821 std::stringstream error;
9823 <<
"The current shared boundary (" << bound_id <<
") was " 9824 <<
"marked to have a connection\nto the left with the " 9825 <<
"boundary (" << uconnection_to_the_left <<
").\n" 9826 <<
"The problem is that the left vertex of the current\n" 9827 <<
"shared boundary is not in the list of vertices of any\n" 9828 <<
"of the sub polylines that represent the boundary to\n" 9830 <<
"This is the left vertex of the current shared boundary\n" 9831 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", " 9832 << shd_bnd_left_vertex[1] <<
")\n\n" 9833 <<
"This is the list of vertices on the destination " 9835 for (
unsigned p = 0; p < nsub_poly; p++)
9837 error <<
"Subpolyline #("<< p <<
")\n";
9838 poly_to_connect_pt = tmp_vector_subpolylines[p];
9839 const unsigned n_v = poly_to_connect_pt->
nvertex();
9840 for (
unsigned i = 0;
i < n_v;
i++)
9845 <<
"Vertex #"<<
i<<
": ("<<cvertex[0]<<
", " 9846 <<cvertex[1]<<
")\n";
9851 "TriangleMesh::create_shared_polylines_connections()",
9852 OOMPH_EXCEPTION_LOCATION);
9861 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
9872 unsigned vertex_index = 0;
9874 unsigned sub_poly_to_connect = 0;
9876 bool found_vertex_index =
false;
9881 get_shared_boundaries_overlapping_internal_boundary(
9882 uconnection_to_the_left, dst_shd_bnd_ids);
9886 const unsigned n_shd_bnd_overlap_int_bnd =
9887 dst_shd_bnd_ids.size();
9891 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
9894 const unsigned new_connection_to_the_left =
9895 dst_shd_bnd_ids[ss];
9899 if (bound_id != new_connection_to_the_left)
9903 poly_to_connect_pt =
9904 boundary_polyline_pt(new_connection_to_the_left);
9906 if (poly_to_connect_pt != 0)
9910 found_vertex_index =
9911 get_connected_vertex_number_on_destination_polyline(
9912 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9917 if (found_vertex_index)
9929 if (!found_vertex_index)
9933 for (
unsigned isub = 0; isub < nsub_poly; isub++)
9937 if (!boundary_marked_as_shared_boundary(
9938 uconnection_to_the_left, isub))
9941 poly_to_connect_pt = tmp_vector_subpolylines[isub];
9943 found_vertex_index =
9944 get_connected_vertex_number_on_destination_polyline(
9945 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9948 if (found_vertex_index)
9952 sub_poly_to_connect = isub;
9965 if (!found_vertex_index)
9967 std::stringstream error;
9969 <<
"The current shared boundary (" << bound_id <<
") was " 9970 <<
"marked to have a connection\nto the left with the " 9971 <<
"boundary (" << uconnection_to_the_left <<
").\n" 9972 <<
"This last boundary is marked to be overlaped by " 9973 <<
"shared boundaries\n" 9974 <<
"The problem is that the left vertex of the current\n" 9975 <<
"shared boundary is not in the list of vertices of " 9976 <<
"the\nboundary to connect.\n\n" 9977 <<
"This is the left vertex of the current shared " 9979 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", " 9980 << shd_bnd_left_vertex[1] <<
")\n\n" 9981 <<
"This is the list of vertices on the destination " 9982 <<
"boundary (only those subpolylines not marked as " 9983 <<
"overlaped by\nshared boundaries)\n";
9984 for (
unsigned p = 0; p < nsub_poly; p++)
9986 if (!boundary_marked_as_shared_boundary(
9987 uconnection_to_the_left, p))
9989 error <<
"Subpolyline #("<< p <<
")\n";
9990 poly_to_connect_pt = tmp_vector_subpolylines[p];
9991 const unsigned n_v = poly_to_connect_pt->
nvertex();
9992 for (
unsigned i = 0;
i < n_v;
i++)
9997 <<
"Vertex #"<<
i<<
": ("<<cvertex[0]<<
", " 9998 <<cvertex[1]<<
")\n";
10002 error <<
"\nThis is the list of vertices of the shared " 10003 <<
"polylines that overlap\nthe internal " 10006 get_shared_boundaries_overlapping_internal_boundary(
10007 uconnection_to_the_left, dst_shd_bnd_ids);
10008 const unsigned n_shd_bnd_overlap_int_bnd =
10009 dst_shd_bnd_ids.size();
10010 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10012 const unsigned new_connection_to_the_left =
10013 dst_shd_bnd_ids[ss];
10014 poly_to_connect_pt =
10015 boundary_polyline_pt(new_connection_to_the_left);
10016 if (poly_to_connect_pt != 0)
10018 const unsigned shd_bnd_id_overlap =
10020 error <<
"Shared boundary id(" 10021 << shd_bnd_id_overlap <<
")\n";
10022 const unsigned n_v = poly_to_connect_pt->
nvertex();
10023 for (
unsigned i = 0;
i < n_v;
i++)
10028 <<
"Vertex #"<<
i<<
": ("<<cvertex[0]<<
", " 10029 <<cvertex[1]<<
")\n";
10036 "TriangleMesh::create_shared_polylines_connections()",
10037 OOMPH_EXCEPTION_LOCATION);
10046 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
10056 if (is_connected_to_the_right)
10060 const unsigned uconnection_to_the_right =
10068 bool connecting_to_an_split_boundary =
false;
10072 bool connecting_to_an_overlaped_boundary =
false;
10075 if (uconnection_to_the_right == bound_id)
10078 poly_to_connect_pt = shd_poly_pt;
10083 const unsigned initial_shd_bnd_id = initial_shared_boundary_id();
10085 if (uconnection_to_the_right >= initial_shd_bnd_id)
10089 poly_to_connect_pt =
10090 boundary_polyline_pt(uconnection_to_the_right);
10098 if (boundary_was_splitted(uconnection_to_the_right))
10100 connecting_to_an_split_boundary =
true;
10110 if (connecting_to_an_split_boundary)
10114 const unsigned n_sub_poly =
10115 nboundary_subpolylines(uconnection_to_the_right);
10120 for (
unsigned ii =0; ii < n_sub_poly; ii++)
10122 if (boundary_marked_as_shared_boundary(
10123 uconnection_to_the_right, ii))
10127 connecting_to_an_overlaped_boundary =
true;
10138 if (boundary_marked_as_shared_boundary(
10139 uconnection_to_the_right, 0))
10143 connecting_to_an_overlaped_boundary =
true;
10150 if (!(connecting_to_an_split_boundary ||
10151 connecting_to_an_overlaped_boundary))
10155 poly_to_connect_pt =
10156 boundary_polyline_pt(uconnection_to_the_right);
10167 if (!connecting_to_an_split_boundary)
10169 if (boundary_was_splitted(uconnection_to_the_right))
10171 std::stringstream error;
10173 <<
"The current shared boundary (" << bound_id <<
") was " 10174 <<
"marked to have a connection\nto the right with the " 10175 <<
"boundary (" << uconnection_to_the_right <<
").\n" 10176 <<
"The problem is that the destination boundary (possibly\n" 10177 <<
"another shared boundary) is marked to be split\n" 10178 <<
"There should not be split shared boundaries\n\n";
10181 "TriangleMesh::create_shared_polylines_connections()",
10182 OOMPH_EXCEPTION_LOCATION);
10200 if (!connecting_to_an_split_boundary)
10204 if (!connecting_to_an_overlaped_boundary)
10209 unsigned vertex_index = 0;
10210 const bool found_vertex_index =
10211 get_connected_vertex_number_on_destination_polyline(
10212 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10216 if (!found_vertex_index)
10218 std::stringstream error;
10220 <<
"The current shared boundary (" << bound_id <<
") was " 10221 <<
"marked to have a connection\nto the right with the " 10222 <<
"boundary (" << uconnection_to_the_right <<
").\n" 10223 <<
"The problem is that the right vertex of the current\n" 10224 <<
"shared boundary is not in the list of vertices of the\n" 10225 <<
"boundary to connect.\n\n" 10226 <<
"This is the right vertex of the current shared boundary\n" 10227 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", " 10228 << shd_bnd_right_vertex[1] <<
")\n\n" 10229 <<
"This is the list of vertices on the destination boundary\n";
10230 const unsigned n_v = poly_to_connect_pt->
nvertex();
10231 for (
unsigned i = 0;
i < n_v;
i++)
10236 <<
"Vertex #"<<
i<<
": ("<<cvertex[0]<<
", "<<cvertex[1]<<
")\n";
10240 "TriangleMesh::create_shared_polylines_connections()",
10241 OOMPH_EXCEPTION_LOCATION);
10248 poly_to_connect_pt, vertex_index);
10258 unsigned vertex_index = 0;
10260 bool found_vertex_index =
false;
10265 get_shared_boundaries_overlapping_internal_boundary(
10266 uconnection_to_the_right, dst_shd_bnd_ids);
10270 const unsigned n_shd_bnd_overlap_int_bnd =
10271 dst_shd_bnd_ids.size();
10275 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10278 const unsigned new_connection_to_the_right =
10279 dst_shd_bnd_ids[ss];
10283 poly_to_connect_pt =
10284 boundary_polyline_pt(new_connection_to_the_right);
10286 if (poly_to_connect_pt!=0)
10290 found_vertex_index =
10291 get_connected_vertex_number_on_destination_polyline(
10292 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10297 if (found_vertex_index)
10307 if (!found_vertex_index)
10309 std::stringstream error;
10311 <<
"The current shared boundary (" << bound_id <<
") was " 10312 <<
"marked to have a connection\nto the right with the " 10313 <<
"boundary (" << uconnection_to_the_right <<
").\n" 10314 <<
"This last boundary is marked to be overlaped by " 10315 <<
"shared boundaries\n" 10316 <<
"The problem is that the right vertex of the current\n" 10317 <<
"shared boundary is not in the list of vertices of the\n" 10318 <<
"boundary to connect.\n\n" 10319 <<
"This is the right vertex of the current shared boundary\n" 10320 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", " 10321 << shd_bnd_right_vertex[1] <<
")\n\n" 10322 <<
"This is the list of vertices on the destination " 10325 get_shared_boundaries_overlapping_internal_boundary(
10326 uconnection_to_the_right, dst_shd_bnd_ids);
10327 const unsigned n_shd_bnd_overlap_int_bnd =
10328 dst_shd_bnd_ids.size();
10329 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10331 const unsigned new_connection_to_the_right =
10332 dst_shd_bnd_ids[ss];
10333 poly_to_connect_pt =
10334 boundary_polyline_pt(new_connection_to_the_right);
10335 if (poly_to_connect_pt != 0)
10337 const unsigned shd_bnd_id_overlap =
10339 error <<
"Shared boundary id(" 10340 << shd_bnd_id_overlap <<
")\n";
10341 const unsigned n_v = poly_to_connect_pt->
nvertex();
10342 for (
unsigned i = 0;
i < n_v;
i++)
10347 <<
"Vertex #"<<
i<<
": ("<<cvertex[0]<<
", " 10348 <<cvertex[1]<<
")\n";
10355 "TriangleMesh::create_shared_polylines_connections()",
10356 OOMPH_EXCEPTION_LOCATION);
10365 poly_to_connect_pt, vertex_index);
10377 boundary_subpolylines(uconnection_to_the_right);
10380 const unsigned nsub_poly = tmp_vector_subpolylines.size();
10382 if (nsub_poly <= 1)
10384 std::ostringstream error_message;
10386 <<
"The boundary (" << uconnection_to_the_right <<
") was " 10387 <<
"marked to be splitted but\n" 10388 <<
"there are only ("<<nsub_poly<<
") polylines to " 10389 <<
"represent it.\n";
10391 error_message.str(),
10392 "TriangleMesh::create_shared_polylines_connections()",
10393 OOMPH_EXCEPTION_LOCATION);
10406 if (!connecting_to_an_overlaped_boundary)
10412 unsigned vertex_index = 0;
10414 unsigned sub_poly_to_connect = 0;
10416 bool found_vertex_index =
false;
10420 for (
unsigned isub = 0; isub < nsub_poly; isub++)
10423 poly_to_connect_pt = tmp_vector_subpolylines[isub];
10425 found_vertex_index =
10426 get_connected_vertex_number_on_destination_polyline(
10427 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10430 if (found_vertex_index)
10434 sub_poly_to_connect = isub;
10442 if (!found_vertex_index)
10444 std::stringstream error;
10446 <<
"The current shared boundary (" << bound_id <<
") was " 10447 <<
"marked to have a connection\nto the right with the " 10448 <<
"boundary (" << uconnection_to_the_right <<
").\n" 10449 <<
"The problem is that the right vertex of the current\n" 10450 <<
"shared boundary is not in the list of vertices of any\n" 10451 <<
"of the sub polylines that represent the boundary to\n" 10453 <<
"This is the right vertex of the current shared boundary\n" 10454 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", " 10455 << shd_bnd_right_vertex[1] <<
")\n\n" 10456 <<
"This is the list of vertices on the destination " 10458 for (
unsigned p = 0; p < nsub_poly; p++)
10460 error <<
"Subpolyline #("<< p <<
")\n";
10461 poly_to_connect_pt = tmp_vector_subpolylines[p];
10462 const unsigned n_v = poly_to_connect_pt->
nvertex();
10463 for (
unsigned i = 0;
i < n_v;
i++)
10468 <<
"Vertex #"<<
i<<
": ("<<cvertex[0]
10469 <<
", "<<cvertex[1]<<
")\n";
10474 "TriangleMesh::create_shared_polylines_connections()",
10475 OOMPH_EXCEPTION_LOCATION);
10484 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
10495 unsigned vertex_index = 0;
10497 unsigned sub_poly_to_connect = 0;
10499 bool found_vertex_index =
false;
10504 get_shared_boundaries_overlapping_internal_boundary(
10505 uconnection_to_the_right, dst_shd_bnd_ids);
10509 const unsigned n_shd_bnd_overlap_int_bnd =
10510 dst_shd_bnd_ids.size();
10514 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10517 const unsigned new_connection_to_the_right =
10518 dst_shd_bnd_ids[ss];
10522 if (bound_id != new_connection_to_the_right)
10526 poly_to_connect_pt =
10527 boundary_polyline_pt(new_connection_to_the_right);
10529 if (poly_to_connect_pt != 0)
10533 found_vertex_index =
10534 get_connected_vertex_number_on_destination_polyline(
10535 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10540 if (found_vertex_index)
10552 if (!found_vertex_index)
10556 for (
unsigned isub = 0; isub < nsub_poly; isub++)
10560 if (!boundary_marked_as_shared_boundary(
10561 uconnection_to_the_right, isub))
10564 poly_to_connect_pt = tmp_vector_subpolylines[isub];
10566 found_vertex_index =
10567 get_connected_vertex_number_on_destination_polyline(
10568 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10571 if (found_vertex_index)
10575 sub_poly_to_connect = isub;
10588 if (!found_vertex_index)
10590 std::stringstream error;
10592 <<
"The current shared boundary (" << bound_id <<
") was " 10593 <<
"marked to have a connection\nto the right with the " 10594 <<
"boundary (" << uconnection_to_the_right <<
").\n" 10595 <<
"This last boundary is marked to be overlaped by " 10596 <<
"shared boundaries\n" 10597 <<
"The problem is that the right vertex of the current\n" 10598 <<
"shared boundary is not in the list of vertices of " 10599 <<
"the\nboundary to connect.\n\n" 10600 <<
"This is the right vertex of the current shared " 10602 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", " 10603 << shd_bnd_right_vertex[1] <<
")\n\n" 10604 <<
"This is the list of vertices on the destination " 10605 <<
"boundary (only those subpolylines not marked as " 10606 <<
"overlaped by\nshared boundaries)\n";
10607 for (
unsigned p = 0; p < nsub_poly; p++)
10609 if (!boundary_marked_as_shared_boundary(
10610 uconnection_to_the_right, p))
10612 error <<
"Subpolyline #("<< p <<
")\n";
10613 poly_to_connect_pt = tmp_vector_subpolylines[p];
10614 const unsigned n_v = poly_to_connect_pt->
nvertex();
10615 for (
unsigned i = 0;
i < n_v;
i++)
10620 <<
"Vertex #"<<
i<<
": ("<<cvertex[0]<<
", " 10621 <<cvertex[1]<<
")\n";
10625 error <<
"\nThis is the list of vertices of the shared " 10626 <<
"polylines that overlap\nthe internal " 10629 get_shared_boundaries_overlapping_internal_boundary(
10630 uconnection_to_the_right, dst_shd_bnd_ids);
10631 const unsigned n_shd_bnd_overlap_int_bnd =
10632 dst_shd_bnd_ids.size();
10633 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10635 const unsigned new_connection_to_the_right =
10636 dst_shd_bnd_ids[ss];
10637 poly_to_connect_pt =
10638 boundary_polyline_pt(new_connection_to_the_right);
10639 if (poly_to_connect_pt != 0)
10641 const unsigned shd_bnd_id_overlap =
10643 error <<
"Shared boundary id(" 10644 << shd_bnd_id_overlap <<
")\n";
10645 const unsigned n_v = poly_to_connect_pt->
nvertex();
10646 for (
unsigned i = 0;
i < n_v;
i++)
10651 <<
"Vertex #"<<
i<<
": ("<<cvertex[0]<<
", " 10652 <<cvertex[1]<<
")\n";
10659 "TriangleMesh::create_shared_polylines_connections()",
10660 OOMPH_EXCEPTION_LOCATION);
10669 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
10689 template<
class ELEMENT>
10694 const unsigned n_proc = this->communicator_pt()->nproc();
10695 const unsigned my_rank = this->communicator_pt()->my_rank();
10699 std::map<FiniteElement*, bool> done_ele;
10703 for (
unsigned iproc = 0; iproc < n_proc; iproc++)
10706 if (iproc != my_rank)
10709 const unsigned n_shd_bnd_iproc = nshared_boundaries(my_rank, iproc);
10714 const unsigned n_shd_bnd_iproc_rev = nshared_boundaries(iproc, my_rank);
10715 if (n_shd_bnd_iproc != n_shd_bnd_iproc_rev)
10717 std::ostringstream error_stream;
10719 <<
"The number of shared boundaries of processor (" 10720 << my_rank <<
") with processor(" << iproc <<
"): (" 10721 << n_shd_bnd_iproc <<
")\n" 10722 <<
"is different from the number of shared boundaries of " 10723 <<
"processor (" << iproc <<
")\nwith processor (" 10724 << my_rank <<
"): (" << n_shd_bnd_iproc <<
")\n\n";
10726 OOMPH_CURRENT_FUNCTION,
10727 OOMPH_EXCEPTION_LOCATION);
10733 for (
unsigned i = 0;
i < n_shd_bnd_iproc;
i++)
10736 const unsigned shd_bnd_id = shared_boundaries_ids(my_rank, iproc,
i);
10739 const unsigned n_shd_bnd_ele = nshared_boundary_element(shd_bnd_id);
10742 for (
unsigned e = 0;
e < n_shd_bnd_ele;
e++)
10745 FiniteElement* ele_pt = shared_boundary_element_pt(shd_bnd_id,
e);
10751 if (!done_ele[ele_pt])
10754 const unsigned n_nodes = ele_pt->nnode();
10759 for (
unsigned k = 0; k < n_nodes; k++)
10761 Node* tmp_node_pt = ele_pt->node_pt(k);
10763 for (
unsigned d = 0; d < 2; d++)
10765 element_centroid[d]+=tmp_node_pt->
x(d);
10770 for (
unsigned d = 0; d < 2; d++)
10772 element_centroid[d] =
10773 element_centroid[d] / (double)n_nodes;
10777 output_holes_coordinates.push_back(element_centroid);
10800 template<
class ELEMENT>
10821 const unsigned n_input_holes = output_holes_coordinates.size();
10824 if (n_input_holes == 0)
10830 const unsigned n_polygons = polygons_pt.size();
10839 for (
unsigned p = 0; p < n_polygons; p++)
10842 const unsigned n_polylines = polygons_pt[p]->npolyline();
10844 for (
unsigned pp = 0; pp < n_polylines; pp++)
10848 polygons_pt[p]->polyline_pt(pp);
10850 const unsigned n_vertices = tmp_poly_pt->
nvertex();
10854 for (
unsigned v = 0; v < n_vertices-1; v++)
10858 vertices_polygons[p].push_back(current_vertex);
10870 std::vector<bool> is_outer_polygon(n_polygons,
true);
10874 if (n_polygons > 1)
10883 for (
unsigned p = 0; p < n_polygons; p++)
10889 const unsigned n_vertices = tmp_inner_polygon.size();
10892 polygon_edge_middle_vertex[p].resize(n_vertices-1);
10896 for (
unsigned e = 0;
e < n_vertices - 1;
e++)
10899 const unsigned dim = 2;
10900 polygon_edge_middle_vertex[p][
e].resize(dim);
10901 for (
unsigned d = 0; d < dim; d++)
10903 polygon_edge_middle_vertex[p][
e][d] =
10904 (tmp_inner_polygon[
e][d] + tmp_inner_polygon[
e+1][d]) / 2.0;
10913 for (
unsigned idx_inner = 0; idx_inner < n_polygons; idx_inner++)
10918 bool is_inner_polygon =
false;
10923 for (
unsigned i = 0;
i < n_polygons;
i++)
10926 if (
i != idx_inner)
10929 const unsigned n_edges =
10930 polygon_edge_middle_vertex[idx_inner].size();
10933 for (
unsigned e = 0;
e < n_edges;
e++)
10937 polygon_edge_middle_vertex[idx_inner][
e];
10940 const bool is_point_inside =
10941 is_point_inside_polygon_helper(vertices_polygons[
i],
10946 if (is_point_inside)
10949 is_inner_polygon =
true;
10960 if (is_inner_polygon)
10970 if (is_inner_polygon)
10973 is_outer_polygon[idx_inner] =
false;
10979 is_outer_polygon[idx_inner] =
true;
10988 unsigned n_outer_polygons = 0;
10989 unsigned n_inner_polygons = 0;
10993 for (
unsigned i = 0;
i < n_polygons;
i++)
10995 if (is_outer_polygon[
i])
10998 n_outer_polygons++;
11003 n_inner_polygons++;
11005 index_inner_polygon.push_back(i);
11024 std::vector<bool> is_inside_an_inner_polygon(n_input_holes,
false);
11028 std::vector<bool> is_outside_the_outer_polygons(n_input_holes,
true);
11032 std::vector<bool> is_inside_the_convex_hull(n_input_holes,
false);
11036 vertex_inside_inner_polygon(n_inner_polygons);
11041 for (
unsigned i = 0;
i < n_inner_polygons;
i++)
11044 const unsigned ii = index_inner_polygon[
i];
11047 for (
unsigned h = 0; h < n_input_holes; h++)
11051 if (!is_inside_an_inner_polygon[h])
11054 const bool is_inside_polygon =
11055 is_point_inside_polygon_helper(vertices_polygons[ii],
11056 output_holes_coordinates[h]);
11060 if (is_inside_polygon)
11063 is_inside_an_inner_polygon[h] =
true;
11065 vertex_inside_inner_polygon[
i].
11066 push_back(output_holes_coordinates[h]);
11078 for (
unsigned h = 0; h < n_input_holes; h++)
11082 if (!is_inside_an_inner_polygon[h])
11086 for (
unsigned i = 0;
i < n_polygons;
i++)
11089 if (is_outer_polygon[
i])
11092 const bool is_inside_polygon =
11093 is_point_inside_polygon_helper(vertices_polygons[i],
11094 output_holes_coordinates[h]);
11099 if (is_inside_polygon)
11102 is_outside_the_outer_polygons[h] =
false;
11116 is_outside_the_outer_polygons[h] =
false;
11123 std::vector<Point> input_vertices_convex_hull;
11126 for (
unsigned p = 0; p < n_polygons; p++)
11129 const unsigned n_vertices = vertices_polygons[p].size();
11131 for (
unsigned v = 0; v < n_vertices; v++)
11136 point.
x = vertices_polygons[p][v][0];
11137 point.
y = vertices_polygons[p][v][1];
11139 input_vertices_convex_hull.push_back(point);
11144 std::vector<Point> output_vertices_convex_hull =
11145 convex_hull(input_vertices_convex_hull);
11148 const unsigned n_vertices_convex_hull = output_vertices_convex_hull.size();
11152 for (
unsigned i = 0;
i < n_vertices_convex_hull;
i++)
11155 vertices_convex_hull[
i].resize(2);
11157 vertices_convex_hull[
i][0] = output_vertices_convex_hull[
i].x;
11158 vertices_convex_hull[
i][1] = output_vertices_convex_hull[
i].y;
11164 for (
unsigned h = 0; h < n_input_holes; h++)
11167 if (is_outside_the_outer_polygons[h])
11170 const bool is_inside_convex_hull =
11171 is_point_inside_polygon_helper(vertices_convex_hull,
11172 output_holes_coordinates[h]);
11175 if (is_inside_convex_hull)
11178 is_inside_the_convex_hull[h] =
true;
11185 is_inside_the_convex_hull[h] =
true;
11193 for (
unsigned h = 0; h < n_input_holes; h++)
11196 if ((is_inside_an_inner_polygon[h]) ||
11197 (is_outside_the_outer_polygons[h] && is_inside_the_convex_hull[h]))
11200 hole_kept.push_back(output_holes_coordinates[h]);
11205 output_holes_coordinates.clear();
11207 output_holes_coordinates = hole_kept;
11215 template<
class ELEMENT>
11218 &unsorted_polylines_pt,
11220 &sorted_polylines_pt)
11222 unsigned n_unsorted_polylines = unsorted_polylines_pt.size();
11223 unsigned n_sorted_polylines = 0;
11224 unsigned curves_index = 0;
11227 std::map<TriangleMeshPolyLine*, bool> done_polyline;
11233 std::list<TriangleMeshPolyLine*> sorted_polyline_list_pt;
11234 bool changes =
false;
11243 bool found_root_polyline =
false;
11244 while (pp < n_unsorted_polylines && !found_root_polyline)
11246 if (!done_polyline[unsorted_polylines_pt[pp]])
11247 {found_root_polyline =
true;}
11253 if (pp < n_unsorted_polylines)
11256 left_pt = right_pt = unsorted_polylines_pt[pp];
11257 done_polyline[left_pt] =
true;
11259 n_sorted_polylines++;
11263 sorted_polyline_list_pt.push_back(left_pt);
11275 for (
unsigned i = pp+1;
i < n_unsorted_polylines;
i++)
11278 unsorted_polylines_pt[
i];
11279 if (!done_polyline[current_polyline_pt])
11283 current_polyline_pt->initial_vertex_coordinate(initial_vertex);
11284 current_polyline_pt->final_vertex_coordinate(final_vertex);
11290 if (left_vertex == final_vertex)
11292 left_pt = current_polyline_pt;
11293 sorted_polyline_list_pt.push_front(left_pt);
11294 done_polyline[left_pt] =
true;
11295 n_sorted_polylines++;
11301 else if (right_vertex == initial_vertex)
11303 right_pt = current_polyline_pt;
11304 sorted_polyline_list_pt.push_back(right_pt);
11305 done_polyline[right_pt] =
true;
11306 n_sorted_polylines++;
11312 else if (left_vertex == initial_vertex)
11314 current_polyline_pt->
reverse();
11315 left_pt = current_polyline_pt;
11316 sorted_polyline_list_pt.push_front(left_pt);
11317 done_polyline[left_pt] =
true;
11318 n_sorted_polylines++;
11324 else if (right_vertex == final_vertex)
11326 current_polyline_pt->
reverse();
11327 right_pt = current_polyline_pt;
11328 sorted_polyline_list_pt.push_back(right_pt);
11329 done_polyline[right_pt] =
true;
11330 n_sorted_polylines++;
11336 if (changes) {
break;}
11348 if (!found_root_polyline)
11350 std::stringstream err;
11351 err <<
"It was not possible to find a root polyline to sort the " 11352 <<
"others around it.\nThe number of unsorted and sorted " 11353 <<
"polylines is different, it means that\nnot all the " 11354 <<
"polylines have been sorted.\n" 11355 <<
"Found root polyline: ("<<found_root_polyline<<
")\n" 11356 <<
"Sorted polylines: ("<<n_sorted_polylines<<
")\n" 11357 <<
"Unsorted polylines: ("<<n_unsorted_polylines<<
")\n";
11358 throw OomphLibError(err.str(),
"TriangleMesh::sort_polylines_helper()",
11359 OOMPH_EXCEPTION_LOCATION);
11366 unsigned n_sorted_polyline_on_list = sorted_polyline_list_pt.size();
11370 tmp_sorted_polylines(n_sorted_polyline_on_list);
11371 unsigned counter = 0;
11373 std::list<TriangleMeshPolyLine*>::iterator it_polyline;
11374 for (it_polyline = sorted_polyline_list_pt.begin();
11375 it_polyline != sorted_polyline_list_pt.end();
11378 tmp_sorted_polylines[counter] = *it_polyline;
11382 sorted_polylines_pt.push_back(tmp_sorted_polylines);
11386 }
while(n_sorted_polylines < n_unsorted_polylines);
11391 if (n_sorted_polylines != n_unsorted_polylines)
11393 std::stringstream err;
11394 err <<
"The number of polylines on the unsorted and sorted vectors" 11395 <<
" is different,\n" 11396 <<
"it means that not all the polylines have been sorted.\n" 11397 <<
"Sorted polylines: "<<n_sorted_polylines
11398 <<
"\nUnsorted polylines: "<<n_unsorted_polylines;
11399 throw OomphLibError(err.str(),
"TriangleMesh::sort_polylines_helper()",
11400 OOMPH_EXCEPTION_LOCATION);
11409 template<
class ELEMENT>
11415 std::map<
Data*,std::set<unsigned> > &processors_associated_with_data,
11416 const bool& overrule_keep_as_halo_element_status)
11419 const unsigned nproc = comm_pt->nproc();
11420 const unsigned my_rank = comm_pt->my_rank();
11428 for (
unsigned iproc = 0; iproc < nproc; iproc++)
11429 {halo_element_pt[iproc].resize(nproc);}
11434 std::map<GeneralisedElement*, unsigned> element_to_global_index;
11437 this->get_halo_elements_on_all_procs(nproc, element_domain,
11439 processors_associated_with_data,
11440 overrule_keep_as_halo_element_status,
11441 element_to_global_index,
11445 flush_shared_boundary_polyline_pt();
11446 Shared_boundary_polyline_pt.resize(nproc);
11452 std::set<FiniteElement*> element_in_processor_pt;
11453 const unsigned n_ele = backed_up_f_el_pt.size();
11454 for (
unsigned e = 0;
e < n_ele;
e++)
11456 if (element_domain[
e] == my_rank)
11458 element_in_processor_pt.insert(backed_up_f_el_pt[
e]);
11465 std::map<std::pair<Node*,Node*>,
unsigned> elements_edges_on_boundary;
11466 this->get_element_edges_on_boundary(elements_edges_on_boundary);
11470 this->create_polylines_from_halo_elements_helper(element_domain,
11471 element_to_global_index,
11472 element_in_processor_pt,
11474 elements_edges_on_boundary,
11475 Shared_boundary_polyline_pt);
11484 template<
class ELEMENT>
11488 std::map<
Data*,std::set<unsigned> > &processors_associated_with_data,
11489 const bool&overrule_keep_as_halo_element_status,
11490 std::map<GeneralisedElement*, unsigned> &element_to_global_index,
11493 const unsigned n_ele = backed_up_el_pt.size();
11496 for (
unsigned iproc = 0; iproc < nproc; iproc++)
11503 for (
unsigned e=0;
e<n_ele;
e++)
11507 unsigned el_domain=element_domain[
e];
11511 if (el_domain!=iproc)
11516 if ((this->Keep_all_elements_as_halos) ||
11519 if (!overrule_keep_as_halo_element_status)
11523 if (!already_added[el_domain][el_pt])
11525 output_halo_elements_pt[iproc][el_domain].push_back(el_pt);
11526 already_added[el_domain][el_pt] =
true;
11527 element_to_global_index[el_pt] =
e;
11536 if(finite_el_pt!=0)
11538 unsigned n_node = finite_el_pt->
nnode();
11539 for (
unsigned n=0;n<n_node;n++)
11544 std::set<unsigned>::iterator it =
11545 processors_associated_with_data[nod_pt].find(iproc);
11546 if (it!=processors_associated_with_data[nod_pt].end())
11550 if (!already_added[el_domain][el_pt])
11552 output_halo_elements_pt[iproc][el_domain].push_back(el_pt);
11553 already_added[el_domain][el_pt] =
true;
11554 element_to_global_index[el_pt] =
e;
11573 template <
class ELEMENT>
11575 std::map<std::pair<Node*,Node*>,
unsigned> &element_edges_on_boundary)
11578 const unsigned nbound = this->nboundary();
11580 for (
unsigned b = 0; b < nbound; b++)
11583 std::map<std::pair<Node*, Node*>,
bool> edge_done;
11585 const unsigned nbound_ele = this->nboundary_element(b);
11586 for (
unsigned e = 0;
e < nbound_ele;
e++)
11591 int face_index = this->face_index_at_boundary(b,
e);
11596 const unsigned nnodes = face_ele_pt->
nnode();
11599 Node* last_node_pt = face_ele_pt->
node_pt(nnodes-1);
11602 std::pair<Node*,Node*> edge =
11603 std::make_pair(first_node_pt, last_node_pt);
11606 if (!edge_done[edge])
11609 edge_done[edge] =
true;
11612 std::pair<Node*,Node*> inv_edge =
11613 std::make_pair(last_node_pt, first_node_pt);
11616 edge_done[inv_edge] =
true;
11619 element_edges_on_boundary[edge] = b;
11623 delete face_ele_pt;
11639 template<
class ELEMENT>
11642 std::map<GeneralisedElement*, unsigned> &element_to_global_index,
11643 std::set<FiniteElement*> &element_in_processor_pt,
11645 std::map<std::pair<Node*,Node*>,
unsigned> &elements_edges_on_boundary,
11648 const unsigned nproc = this->communicator_pt()->nproc();
11649 const unsigned my_rank = this->communicator_pt()->my_rank();
11674 std::map<std::pair<Node*,Node*>,
bool> overlapped_edge;
11680 Shared_boundaries_ids.resize(nproc);
11681 for (
unsigned j = 0 ; j < nproc; j++)
11683 edges[j].resize(nproc);
11684 edge_element_pt[j].resize(nproc);
11685 edge_element_face[j].resize(nproc);
11686 edge_boundary[j].resize(nproc);
11689 Shared_boundaries_ids[j].resize(nproc);
11695 for (
unsigned iproc = 0; iproc < nproc; iproc++)
11702 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
11719 halo_elements_iproc_with_jproc = input_halo_elements[iproc][jproc];
11722 const unsigned nhalo_elements_iproc_with_jproc =
11723 halo_elements_iproc_with_jproc.size();
11725 if (nhalo_elements_iproc_with_jproc > 0)
11728 halo_elements_jproc_with_iproc = input_halo_elements[jproc][iproc];
11732 const unsigned nhalo_elements_jproc_with_iproc =
11733 halo_elements_jproc_with_iproc.size();
11736 if (nhalo_elements_jproc_with_iproc == 0)
11741 std::stringstream err;
11742 err <<
"There are no halo elements from processor ("<<jproc<<
") " 11743 <<
"with processor ("<<iproc<<
").\n" 11744 <<
"This is strange since there are halo elements from " 11745 <<
"processor ("<<iproc<<
") with processor ("<<jproc<<
").\n" 11746 <<
"Number of halo elements from ("<<iproc<<
") to (" 11747 <<jproc<<
") : ("<< nhalo_elements_iproc_with_jproc<<
")\n" 11748 <<
"Number of halo elements from ("<<jproc<<
") to (" 11749 <<iproc<<
") : ("<< nhalo_elements_jproc_with_iproc<<
")\n";
11751 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11752 OOMPH_EXCEPTION_LOCATION);
11757 unsigned halo_edges_counter_iproc = 0;
11759 unsigned halo_edges_counter_jproc = 0;
11762 std::map<std::pair<Node*,Node*>,
FiniteElement*> edgesi_to_element_pt;
11766 std::map<std::pair<std::pair<Node*,Node*>,
FiniteElement*>,
int>
11767 edgesi_element_pt_to_face_index;
11770 std::map<std::pair<Node*,Node*>,FiniteElement*> edgesj_to_element_pt;
11774 std::map<std::pair<std::pair<Node*,Node*>, FiniteElement*>,
int>
11775 edgesj_element_pt_to_face_index;
11781 for (
unsigned ih = 0; ih < nhalo_elements_iproc_with_jproc; ih++)
11785 element_to_global_index[halo_elements_iproc_with_jproc[ih]];
11787 if (element_domain[e] != jproc)
11790 std::stringstream err;
11791 err <<
"There was a problem on the ihalo-jhalo classification.\n" 11792 <<
"One of the elements, (the one with the ("<<e<<
")-th " 11793 <<
"index ) is not on the ("<<jproc<<
")-th processor\n" 11794 <<
"but it was stored as a halo element of processor (" 11795 << iproc<<
") with processor ("<<jproc<<
").\n";
11798 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11799 OOMPH_EXCEPTION_LOCATION);
11803 FiniteElement* el_pt =
11804 dynamic_cast<FiniteElement*
>(halo_elements_iproc_with_jproc[ih]);
11808 std::stringstream err;
11809 err <<
"The halo element ("<<ih<<
") could not be casted to the " 11810 <<
"FiniteElement type.\n";
11813 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11814 OOMPH_EXCEPTION_LOCATION);
11819 const unsigned n_nodes = el_pt->nnode();
11826 std::stringstream err;
11827 err <<
"The number of nodes of the "<<ih<<
"-th halo element is" 11828 <<
" ("<< n_nodes <<
").\nWe can not work with triangle " 11829 <<
"elements with less than three nodes\n";
11831 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11832 OOMPH_EXCEPTION_LOCATION);
11837 Node *first_node_pt = el_pt->node_pt(0);
11838 Node *second_node_pt = el_pt->node_pt(1);
11839 Node *third_node_pt = el_pt->node_pt(2);
11842 halo_edges_iproc.push_back(first_node_pt);
11843 halo_edges_iproc.push_back(second_node_pt);
11844 halo_edges_counter_jproc++;
11846 halo_edges_iproc.push_back(second_node_pt);
11847 halo_edges_iproc.push_back(third_node_pt);
11848 halo_edges_counter_jproc++;
11850 halo_edges_iproc.push_back(third_node_pt);
11851 halo_edges_iproc.push_back(first_node_pt);
11852 halo_edges_counter_jproc++;
11855 std::pair<Node*, Node*> edge1 =
11856 std::make_pair(first_node_pt, second_node_pt);
11857 edgesi_to_element_pt[edge1] = el_pt;
11859 std::pair<Node*, Node*> edge2 =
11860 std::make_pair(second_node_pt, third_node_pt);
11861 edgesi_to_element_pt[edge2] = el_pt;
11863 std::pair<Node*, Node*> edge3 =
11864 std::make_pair(third_node_pt, first_node_pt);
11865 edgesi_to_element_pt[edge3] = el_pt;
11868 std::pair<std::pair<Node*, Node*>, FiniteElement*> edge_ele1 =
11869 std::make_pair(edge1, el_pt);
11870 edgesi_element_pt_to_face_index[edge_ele1] = 2;
11872 std::pair<std::pair<Node*, Node*>, FiniteElement*> edge_ele2 =
11873 std::make_pair(edge2, el_pt);
11874 edgesi_element_pt_to_face_index[edge_ele2] = 0;
11876 std::pair<std::pair<Node*, Node*>, FiniteElement*> edge_ele3 =
11877 std::make_pair(edge3, el_pt);
11878 edgesi_element_pt_to_face_index[edge_ele3] = 1;
11886 for (
unsigned jh = 0; jh < nhalo_elements_jproc_with_iproc; jh++)
11890 element_to_global_index[halo_elements_jproc_with_iproc[jh]];
11892 if (element_domain[e] != iproc)
11895 std::stringstream err;
11896 err <<
"There was a problem on the jhalo-ihalo classification.\n" 11897 <<
"One of the elements, (the one with the ("<<e<<
")-th " 11898 <<
"index ) is not on the ("<<iproc<<
")-th processor\n" 11899 <<
"but it was stored as a halo element of processor (" 11900 << jproc<<
") with processor ("<<iproc<<
").\n";
11903 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11904 OOMPH_EXCEPTION_LOCATION);
11908 FiniteElement* el_pt =
11909 dynamic_cast<FiniteElement*
>(halo_elements_jproc_with_iproc[jh]);
11912 std::stringstream err;
11913 err <<
"The halo element ("<<jh<<
") could not be casted to the " 11914 <<
"FiniteElement type.\n";
11917 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11918 OOMPH_EXCEPTION_LOCATION);
11923 const unsigned n_nodes = el_pt->nnode();
11930 std::stringstream err;
11931 err <<
"The number of nodes of the "<<jh<<
"-th halo element is" 11932 <<
" ("<< n_nodes <<
").\nWe can not work with triangle " 11933 <<
"elements with less than three nodes\n";
11935 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11936 OOMPH_EXCEPTION_LOCATION);
11941 Node *first_node_pt = el_pt->node_pt(0);
11942 Node *second_node_pt = el_pt->node_pt(1);
11943 Node *third_node_pt = el_pt->node_pt(2);
11946 halo_edges_jproc.push_back(first_node_pt);
11947 halo_edges_jproc.push_back(second_node_pt);
11948 halo_edges_counter_iproc++;
11950 halo_edges_jproc.push_back(second_node_pt);
11951 halo_edges_jproc.push_back(third_node_pt);
11952 halo_edges_counter_iproc++;
11954 halo_edges_jproc.push_back(third_node_pt);
11955 halo_edges_jproc.push_back(first_node_pt);
11956 halo_edges_counter_iproc++;
11959 std::pair<Node*, Node*> edge1 =
11960 std::make_pair(first_node_pt, second_node_pt);
11961 edgesj_to_element_pt[edge1] = el_pt;
11963 std::pair<Node*, Node*> edge2 =
11964 std::make_pair(second_node_pt, third_node_pt);
11965 edgesj_to_element_pt[edge2] = el_pt;
11967 std::pair<Node*, Node*> edge3 =
11968 std::make_pair(third_node_pt, first_node_pt);
11969 edgesj_to_element_pt[edge3] = el_pt;
11972 std::pair<std::pair<Node*, Node*>, FiniteElement*> edge_ele1 =
11973 std::make_pair(edge1, el_pt);
11974 edgesj_element_pt_to_face_index[edge_ele1] = 2;
11976 std::pair<std::pair<Node*, Node*>, FiniteElement*> edge_ele2 =
11977 std::make_pair(edge2, el_pt);
11978 edgesj_element_pt_to_face_index[edge_ele2] = 0;
11980 std::pair<std::pair<Node*, Node*>, FiniteElement*> edge_ele3 =
11981 std::make_pair(edge3, el_pt);
11982 edgesj_element_pt_to_face_index[edge_ele3] = 1;
11995 unsigned nhalo_iedges = halo_edges_iproc.size();
11996 unsigned nhalo_jedges = halo_edges_jproc.size();
12000 for (
unsigned ihe = 0; ihe < nhalo_iedges; ihe+=2)
12004 ihalo_edge[0] = halo_edges_iproc[ihe];
12005 ihalo_edge[1] = halo_edges_iproc[ihe+1];
12008 std::pair<Node*,Node*> tmp_edge = std::make_pair(ihalo_edge[0],
12013 int edge_boundary_id = -1;
12015 std::map<std::pair<Node*,Node*>,
unsigned >::iterator it;
12016 it = elements_edges_on_boundary.find(tmp_edge);
12019 if (it != elements_edges_on_boundary.end())
12023 edge_boundary_id = (*it).second;
12029 std::pair<Node*,Node*> rtmp_edge = std::make_pair(ihalo_edge[1],
12031 it = elements_edges_on_boundary.find(rtmp_edge);
12032 if (it != elements_edges_on_boundary.end())
12036 edge_boundary_id = (*it).second;
12043 for (
unsigned jhe = 0; jhe < nhalo_jedges; jhe+=2)
12047 jhalo_edge[0] = halo_edges_jproc[jhe];
12048 jhalo_edge[1] = halo_edges_jproc[jhe+1];
12051 if (ihalo_edge[0] == jhalo_edge[0] &&
12052 ihalo_edge[1] == jhalo_edge[1])
12055 std::pair<Node*, Node*> new_edge =
12056 std::make_pair(ihalo_edge[0], ihalo_edge[1]);
12061 FiniteElement* haloi_ele_pt = 0;
12062 haloi_ele_pt = edgesi_to_element_pt[new_edge];
12063 FiniteElement* haloj_ele_pt = 0;
12064 haloj_ele_pt = edgesj_to_element_pt[new_edge];
12067 if (haloi_ele_pt == 0 || haloj_ele_pt == 0)
12069 std::stringstream err;
12070 err <<
"There is no associated elements with the new " 12071 <<
"shared boundary. This is an storing problem,\n" 12072 <<
"possibly related with a memory leak problem!!!\n" 12073 <<
"The nodes that compound the edge are these:\n" 12074 <<
"On processor ("<<iproc<<
"):\n" 12075 <<
"("<<ihalo_edge[0]->x(0)<<
", "<<ihalo_edge[0]->x(1)
12076 <<
") and ("<<ihalo_edge[1]->x(0)<<
", " 12077 <<ihalo_edge[1]->x(1)<<
")\n\n" 12078 <<
"On processor ("<<jproc<<
"):\n" 12079 <<
"("<<jhalo_edge[0]->x(0)<<
", "<<jhalo_edge[0]->x(1)
12080 <<
") and ("<<jhalo_edge[1]->x(0)<<
", " 12081 <<jhalo_edge[1]->x(1)<<
")\n\n" 12082 <<
"The nodes coordinates should be the same!!!\n";
12084 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12085 OOMPH_EXCEPTION_LOCATION);
12089 edges[iproc][jproc].push_back(new_edge);
12092 if (edge_boundary_id >= 0)
12095 overlapped_edge[new_edge] =
true;
12098 std::pair<Node*, Node*> rev_new_edge =
12099 std::make_pair(ihalo_edge[1], ihalo_edge[0]);
12102 overlapped_edge[rev_new_edge] =
true;
12108 edge_boundary[iproc][jproc].push_back(edge_boundary_id);
12112 tmp_elements_pt.push_back(haloi_ele_pt);
12113 tmp_elements_pt.push_back(haloj_ele_pt);
12116 edge_element_pt[iproc][jproc].push_back(tmp_elements_pt);
12122 std::pair<std::pair<Node*,Node*>, FiniteElement*>
12123 edge_elementi_pair = make_pair(new_edge, haloi_ele_pt);
12125 std::pair<std::pair<Node*,Node*>, FiniteElement*>
12126 edge_elementj_pair = make_pair(new_edge, haloj_ele_pt);
12130 int face_index_haloi_ele = -1;
12131 face_index_haloi_ele =
12132 edgesi_element_pt_to_face_index[edge_elementi_pair];
12133 int face_index_haloj_ele = -1;
12134 face_index_haloj_ele =
12135 edgesj_element_pt_to_face_index[edge_elementj_pair];
12137 if (face_index_haloi_ele == -1 || face_index_haloj_ele == -1)
12139 std::stringstream err;
12140 err <<
"There is no associated face indexes to the" 12141 <<
"elements that gave\nrise to the shared edge\n" 12142 <<
"The nodes that compound the edge are these:\n" 12143 <<
"On processor ("<<iproc<<
"):\n" 12144 <<
"("<<ihalo_edge[0]->x(0)<<
", "<<ihalo_edge[0]->x(1)
12145 <<
") and ("<<ihalo_edge[1]->x(0)<<
", " 12146 <<ihalo_edge[1]->x(1)<<
")\n\n" 12147 <<
"On processor ("<<jproc<<
"):\n" 12148 <<
"("<<jhalo_edge[0]->x(0)<<
", "<<jhalo_edge[0]->x(1)
12149 <<
") and ("<<jhalo_edge[1]->x(0)<<
", " 12150 <<jhalo_edge[1]->x(1)<<
")\n\n" 12151 <<
"The nodes coordinates should be the same!!!\n";
12153 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12154 OOMPH_EXCEPTION_LOCATION);
12160 tmp_edge_element_face_index.push_back(face_index_haloi_ele);
12161 tmp_edge_element_face_index.push_back(face_index_haloj_ele);
12163 edge_element_face[iproc][jproc].
12164 push_back(tmp_edge_element_face_index);
12172 else if (ihalo_edge[0] == jhalo_edge[1] &&
12173 ihalo_edge[1] == jhalo_edge[0])
12176 std::pair<Node*, Node*> new_edge =
12177 std::make_pair(ihalo_edge[0], ihalo_edge[1]);
12181 FiniteElement* haloi_ele_pt = 0;
12182 haloi_ele_pt = edgesi_to_element_pt[new_edge];
12184 FiniteElement* haloj_ele_pt = 0;
12187 std::pair<Node*, Node*> new_edge_reversed =
12188 std::make_pair(jhalo_edge[0], jhalo_edge[1]);
12189 haloj_ele_pt = edgesj_to_element_pt[new_edge_reversed];
12192 if (haloi_ele_pt == 0 || haloj_ele_pt == 0)
12194 std::stringstream err;
12195 err <<
"There is no associated elements with the new " 12196 <<
"shared boundary (reversed version). This is an " 12197 <<
"storing problem, possibly related with a memory " 12198 <<
"leak problem!!!\n" 12199 <<
"The nodes that compound the edge are these:\n" 12200 <<
"On processor ("<<iproc<<
"):\n" 12201 <<
"("<<ihalo_edge[0]->x(0)<<
", "<<ihalo_edge[0]->x(1)
12202 <<
") and ("<<ihalo_edge[1]->x(0)<<
", " 12203 <<ihalo_edge[1]->x(1)<<
")\n\n" 12204 <<
"On processor ("<<jproc<<
"):\n" 12205 <<
"("<<jhalo_edge[0]->x(0)<<
", "<<jhalo_edge[0]->x(1)
12206 <<
") and ("<<jhalo_edge[1]->x(0)<<
", " 12207 <<jhalo_edge[1]->x(1)<<
")\n\n" 12208 <<
"The nodes coordinates should be the same!!!\n";
12210 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12211 OOMPH_EXCEPTION_LOCATION);
12215 edges[iproc][jproc].push_back(new_edge);
12218 if (edge_boundary_id >= 0)
12221 overlapped_edge[new_edge] =
true;
12224 std::pair<Node*, Node*> rev_new_edge =
12225 std::make_pair(ihalo_edge[1], ihalo_edge[0]);
12228 overlapped_edge[rev_new_edge] =
true;
12233 edge_boundary[iproc][jproc].push_back(edge_boundary_id);
12237 tmp_elements_pt.push_back(haloi_ele_pt);
12238 tmp_elements_pt.push_back(haloj_ele_pt);
12241 edge_element_pt[iproc][jproc].push_back(tmp_elements_pt);
12247 std::pair<std::pair<Node*,Node*>, FiniteElement*>
12248 edge_elementi_pair = make_pair(new_edge, haloi_ele_pt);
12250 std::pair<std::pair<Node*,Node*>, FiniteElement*>
12251 edge_elementj_pair = make_pair(new_edge_reversed,
12256 int face_index_haloi_ele = -1;
12257 face_index_haloi_ele =
12258 edgesi_element_pt_to_face_index[edge_elementi_pair];
12259 int face_index_haloj_ele = -1;
12260 face_index_haloj_ele =
12261 edgesj_element_pt_to_face_index[edge_elementj_pair];
12263 if (face_index_haloi_ele == -1 || face_index_haloj_ele == -1)
12265 std::stringstream err;
12266 err <<
"There is no associated face indexes to the" 12267 <<
"elements that gave\nrise to the shared edge\n" 12268 <<
"The nodes that compound the edge are these:\n" 12269 <<
"On processor ("<<iproc<<
"):\n" 12270 <<
"("<<ihalo_edge[0]->x(0)<<
", "<<ihalo_edge[0]->x(1)
12271 <<
") and ("<<ihalo_edge[1]->x(0)<<
", " 12272 <<ihalo_edge[1]->x(1)<<
")\n\n" 12273 <<
"On processor ("<<jproc<<
"):\n" 12274 <<
"("<<jhalo_edge[0]->x(0)<<
", "<<jhalo_edge[0]->x(1)
12275 <<
") and ("<<jhalo_edge[1]->x(0)<<
", " 12276 <<jhalo_edge[1]->x(1)<<
")\n\n" 12277 <<
"The nodes coordinates should be the same!!!\n";
12279 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12280 OOMPH_EXCEPTION_LOCATION);
12286 tmp_edge_element_face_index.push_back(face_index_haloi_ele);
12287 tmp_edge_element_face_index.push_back(face_index_haloj_ele);
12289 edge_element_face[iproc][jproc].
12290 push_back(tmp_edge_element_face_index);
12315 std::map<Node*, unsigned> global_shared_node_degree;
12319 std::map<std::pair<Node*, Node*>,
bool> edge_done;
12320 #endif // #ifdef PARANOID 12322 std::map<Node*,bool> node_done;
12326 for (
unsigned iproc = 0; iproc < nproc; iproc++)
12333 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
12336 const unsigned nshd_edges = edges[iproc][jproc].size();
12342 const unsigned nedge_element = edge_element_pt[iproc][jproc].size();
12343 if (nshd_edges != nedge_element)
12345 std::stringstream error_message;
12347 <<
"The number of shared edges between processor iproc and jproc\n" 12348 <<
"is different form the number of edge elements between the\n" 12349 <<
"pair of processors\n" 12350 <<
"iproc: (" << iproc <<
")\n" 12351 <<
"jproc: (" << jproc <<
")\n" 12352 <<
"# of shared edges: (" << nshd_edges <<
")\n" 12353 <<
"# of edge elements: (" << nedge_element <<
")\n\n";
12355 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12356 OOMPH_EXCEPTION_LOCATION);
12360 const unsigned nedge_element_face =
12361 edge_element_face[iproc][jproc].size();
12362 if (nshd_edges != nedge_element_face)
12364 std::stringstream error_message;
12366 <<
"The number of shared edges between processor iproc and jproc\n" 12367 <<
"is different form the number of edge element faces between the\n" 12368 <<
"pair of processors\n" 12369 <<
"iproc: (" << iproc <<
")\n" 12370 <<
"jproc: (" << jproc <<
")\n" 12371 <<
"# of shared edges: (" << nshd_edges <<
")\n" 12372 <<
"# of edge element faces: (" << nedge_element_face <<
")\n\n";
12374 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12375 OOMPH_EXCEPTION_LOCATION);
12379 const unsigned nedge_boundary = edge_boundary[iproc][jproc].size();
12380 if (nshd_edges != nedge_boundary)
12382 std::stringstream error_message;
12384 <<
"The number of shared edges between processor iproc and jproc\n" 12385 <<
"is different form the number of edge boundaries ids between the\n" 12386 <<
"pair of processors\n" 12387 <<
"iproc: (" << iproc <<
")\n" 12388 <<
"jproc: (" << jproc <<
")\n" 12389 <<
"# of shared edges: (" << nshd_edges <<
")\n" 12390 <<
"# of edge boundaries ids: (" << nedge_boundary <<
")\n\n";
12392 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12393 OOMPH_EXCEPTION_LOCATION);
12396 #endif // #ifdef PARANOID 12399 for (
unsigned se = 0; se < nshd_edges; se++)
12402 std::pair<Node*, Node*> edge = edges[iproc][jproc][se];
12405 if (edge_done[edge])
12407 std::stringstream error_message;
12409 <<
"The shared edge between processor iproc and processor\n" 12410 <<
"jproc has been already visited, this is weird since the\n" 12411 <<
"edge should not be shared by other pair of processors\n" 12412 <<
"iproc: (" << iproc <<
")\n" 12413 <<
"jproc: (" << jproc <<
")\n" 12414 <<
"First node of edge: (" << edge.first->x(0) <<
", " 12415 << edge.first->x(1) <<
")\n" 12416 <<
"Second node of edge: (" << edge.second->x(0) <<
", " 12417 << edge.second->x(1) <<
")\n" 12418 <<
"Associated edge boundary id: (" 12419 << edge_boundary[iproc][jproc][se] <<
")\n\n";
12421 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12422 OOMPH_EXCEPTION_LOCATION);
12426 edge_done[edge] =
true;
12428 std::pair<Node*, Node*> rev_edge =
12429 std::make_pair(edge.second, edge.first);
12431 edge_done[rev_edge] =
true;
12432 #endif // #ifdef PARANOID 12435 Node* left_node_pt = edge.first;
12436 Node* right_node_pt = edge.second;
12439 if (!node_done[left_node_pt])
12443 global_shared_node_degree[left_node_pt] = 1;
12449 global_shared_node_degree[left_node_pt]++;
12453 if (!node_done[right_node_pt])
12457 global_shared_node_degree[right_node_pt] = 1;
12462 global_shared_node_degree[right_node_pt]++;
12477 std::map<unsigned, std::map<Node*, bool> >
12478 node_on_bnd_not_overlapped_by_shd_bnd;
12481 for (std::map<std::pair<Node*,Node*>,
unsigned>::iterator it_map =
12482 elements_edges_on_boundary.begin();
12483 it_map != elements_edges_on_boundary.end(); it_map++)
12486 std::pair<Node*,Node*> edge_pair = (*it_map).first;
12489 if (!overlapped_edge[edge_pair])
12493 unsigned b = (*it_map).second;
12496 Node* left_node_pt = edge_pair.first;
12497 node_on_bnd_not_overlapped_by_shd_bnd[b][left_node_pt] =
true;
12500 Node* right_node_pt = edge_pair.second;
12501 node_on_bnd_not_overlapped_by_shd_bnd[b][right_node_pt] =
true;
12521 std::map<unsigned, std::list<Node*> > shared_bnd_id_to_sorted_list_node_pt;
12525 unsigned shared_boundary_id_start = this->nboundary();
12526 Initial_shared_boundary_id = shared_boundary_id_start;
12532 for (
unsigned iproc = 0; iproc < nproc; iproc++)
12539 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
12547 unsigned npolylines_counter = 0;
12548 const unsigned nedges = edges[iproc][jproc].size();
12554 unsigned nsorted_edges = 0;
12557 std::map<std::pair<Node*,Node*>,
bool> edge_done;
12561 while(nsorted_edges < nedges)
12565 std::list<FiniteElement*> tmp_boundary_element_pt;
12568 std::list<int> tmp_face_index_element;
12570 std::pair<Node*,Node*> edge;
12572 bool found_initial_edge =
false;
12574 int root_edge_bound_id = -1;
12575 unsigned iedge = 0;
12576 for (iedge = 0; iedge < nedges; iedge++)
12578 edge = edges[iproc][jproc][iedge];
12580 if (!edge_done[edge])
12583 root_edge_bound_id = edge_boundary[iproc][jproc][iedge];
12585 found_initial_edge =
true;
12594 if (!found_initial_edge)
12596 std::ostringstream error_message;
12598 <<
"All the edge are already done, but the number of done\n" 12599 <<
"edges ("<<nsorted_edges<<
") is still less than the total\n" 12600 <<
"number of edges (" << nedges <<
").\n";
12603 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12604 OOMPH_EXCEPTION_LOCATION);
12610 std::list<Node*> sorted_nodes;
12611 sorted_nodes.clear();
12614 Node *first_node_pt = edge.first;
12615 Node *last_node_pt = edge.second;
12618 sorted_nodes.push_back(first_node_pt);
12619 sorted_nodes.push_back(last_node_pt);
12623 tmp_boundary_element_pt.
12624 push_back(edge_element_pt[iproc][jproc][iedge-1][0]);
12625 tmp_boundary_element_pt.
12626 push_back(edge_element_pt[iproc][jproc][iedge-1][1]);
12630 tmp_face_index_element.
12631 push_back(edge_element_face[iproc][jproc][iedge-1][0]);
12632 tmp_face_index_element.
12633 push_back(edge_element_face[iproc][jproc][iedge-1][1]);
12636 edge_done[edge] =
true;
12641 bool node_added =
true;
12645 bool node_added_to_the_left =
true;
12646 bool node_added_to_the_right =
true;
12664 bool connection_to_the_left =
false;
12669 bool connection_to_the_right =
false;
12673 bool current_polyline_has_connections_at_both_ends =
false;
12680 int bound_id_connection_to_the_left = -1;
12681 int bound_id_connection_to_the_right = -1;
12684 const unsigned first_node_degree =
12685 global_shared_node_degree[first_node_pt];
12689 bound_id_connection_to_the_left =
12690 check_connections_of_polyline_nodes(
12691 element_in_processor_pt,
12692 root_edge_bound_id,
12694 node_on_bnd_not_overlapped_by_shd_bnd,
12696 shared_bnd_id_to_sorted_list_node_pt,
12706 if (bound_id_connection_to_the_left != -1)
12708 connection_to_the_left =
true;
12712 const unsigned last_node_degree =
12713 global_shared_node_degree[last_node_pt];
12717 bound_id_connection_to_the_right =
12718 check_connections_of_polyline_nodes(
12719 element_in_processor_pt,
12720 root_edge_bound_id,
12722 node_on_bnd_not_overlapped_by_shd_bnd,
12724 shared_bnd_id_to_sorted_list_node_pt,
12733 if (bound_id_connection_to_the_right != -1)
12735 connection_to_the_right =
true;
12740 if (connection_to_the_left && connection_to_the_right)
12741 {current_polyline_has_connections_at_both_ends =
true;}
12748 while(node_added && (nsorted_edges < nedges)
12749 && !current_polyline_has_connections_at_both_ends)
12754 for (
unsigned iiedge = iedge; iiedge < nedges; iiedge++)
12757 node_added =
false;
12758 node_added_to_the_left =
false;
12759 node_added_to_the_right =
false;
12761 edge = edges[iproc][jproc][iiedge];
12762 const int edge_bound_id = edge_boundary[iproc][jproc][iiedge];
12768 if (!edge_done[edge] &&
12769 (edge_bound_id == root_edge_bound_id))
12772 Node* left_node_pt = edge.first;
12773 Node* right_node_pt = edge.second;
12776 Node* new_added_node_pt = 0;
12779 if (left_node_pt == first_node_pt &&
12780 !connection_to_the_left)
12783 sorted_nodes.push_front(right_node_pt);
12785 new_added_node_pt = first_node_pt = right_node_pt;
12789 node_added_to_the_left =
true;
12792 else if (left_node_pt == last_node_pt &&
12793 !connection_to_the_right)
12796 sorted_nodes.push_back(right_node_pt);
12798 new_added_node_pt = last_node_pt = right_node_pt;
12802 node_added_to_the_right =
true;
12805 else if (right_node_pt == first_node_pt &&
12806 !connection_to_the_left)
12809 sorted_nodes.push_front(left_node_pt);
12811 new_added_node_pt = first_node_pt = left_node_pt;
12815 node_added_to_the_left =
true;
12818 else if (right_node_pt == last_node_pt &&
12819 !connection_to_the_right)
12822 sorted_nodes.push_back(left_node_pt);
12824 new_added_node_pt = last_node_pt = left_node_pt;
12828 node_added_to_the_right =
true;
12838 edge_done[edge] =
true;
12842 const unsigned added_node_degree =
12843 global_shared_node_degree[new_added_node_pt];
12845 if (node_added_to_the_left)
12848 tmp_boundary_element_pt.push_front(
12849 edge_element_pt[iproc][jproc][iiedge][1]);
12850 tmp_boundary_element_pt.push_front(
12851 edge_element_pt[iproc][jproc][iiedge][0]);
12853 tmp_face_index_element.push_front(
12854 edge_element_face[iproc][jproc][iiedge][1]);
12855 tmp_face_index_element.push_front(
12856 edge_element_face[iproc][jproc][iiedge][0]);
12859 if (node_added_to_the_right)
12862 tmp_boundary_element_pt.push_back(
12863 edge_element_pt[iproc][jproc][iiedge][0]);
12864 tmp_boundary_element_pt.push_back(
12865 edge_element_pt[iproc][jproc][iiedge][1]);
12867 tmp_face_index_element.push_back(
12868 edge_element_face[iproc][jproc][iiedge][0]);
12869 tmp_face_index_element.push_back(
12870 edge_element_face[iproc][jproc][iiedge][1]);
12880 if (node_added_to_the_left && !connection_to_the_left)
12883 bound_id_connection_to_the_left =
12884 check_connections_of_polyline_nodes(
12885 element_in_processor_pt,
12886 root_edge_bound_id,
12888 node_on_bnd_not_overlapped_by_shd_bnd,
12890 shared_bnd_id_to_sorted_list_node_pt,
12892 new_added_node_pt);
12899 if (bound_id_connection_to_the_left != -1)
12901 connection_to_the_left =
true;
12911 if (node_added_to_the_right && !connection_to_the_right)
12914 bound_id_connection_to_the_right =
12915 check_connections_of_polyline_nodes(
12916 element_in_processor_pt,
12917 root_edge_bound_id,
12919 node_on_bnd_not_overlapped_by_shd_bnd,
12921 shared_bnd_id_to_sorted_list_node_pt,
12923 new_added_node_pt);
12930 if (bound_id_connection_to_the_right != -1)
12932 connection_to_the_right =
true;
12940 if (connection_to_the_left && connection_to_the_right)
12941 {current_polyline_has_connections_at_both_ends =
true;}
12964 const unsigned n_bnd_ele = tmp_boundary_element_pt.size();
12970 unsigned help_counter = 0;
12972 for (std::list<FiniteElement*>::iterator it_bnd_ele =
12973 tmp_boundary_element_pt.begin();
12974 it_bnd_ele != tmp_boundary_element_pt.end();
12977 tmp_bnd_ele_pt[help_counter++] = (*it_bnd_ele);
12982 for (std::list<int>::iterator it_face_idx =
12983 tmp_face_index_element.begin();
12984 it_face_idx != tmp_face_index_element.end();
12987 tmp_face_idx_ele[help_counter++] = (*it_face_idx);
13000 Vector<int> final_bound_id_connection_to_the_left;
13003 Vector<int> final_bound_id_connection_to_the_right;
13006 break_loops_on_shared_polyline_helper(
13007 shared_boundary_id_start,
13009 tmp_bnd_ele_pt, tmp_face_idx_ele,
13010 bound_id_connection_to_the_left, bound_id_connection_to_the_right,
13011 final_sorted_nodes_pt,
13012 final_boundary_element_pt, final_face_index_element,
13013 final_bound_id_connection_to_the_left,
13014 final_bound_id_connection_to_the_right);
13017 const unsigned n_final_sorted_nodes =
13018 final_sorted_nodes_pt.size();
13021 for (
unsigned i = 0;
i < n_final_sorted_nodes;
i++)
13026 shared_bnd_id_to_sorted_list_node_pt[shared_boundary_id_start] =
13027 final_sorted_nodes_pt[
i];
13031 create_shared_polyline(my_rank, shared_boundary_id_start,
13032 iproc, jproc, final_sorted_nodes_pt[
i],
13033 root_edge_bound_id,
13034 final_boundary_element_pt[i],
13035 final_face_index_element[i],
13036 unsorted_polylines_pt,
13037 final_bound_id_connection_to_the_left[i],
13038 final_bound_id_connection_to_the_right[i]);
13042 npolylines_counter++;
13046 shared_boundary_id_start++;
13059 if (unsorted_polylines_pt[iproc].size() > 0)
13063 sort_polylines_helper(unsorted_polylines_pt[iproc],
13064 output_polylines_pt[iproc]);
13068 const unsigned nunsorted_polylines_iproc =
13069 unsorted_polylines_pt[iproc].size();
13072 unsigned tmp_ntotal_polylines = 0;
13074 for (
unsigned ii = 0 ; ii < output_polylines_pt[iproc].size(); ii++)
13075 {tmp_ntotal_polylines+= output_polylines_pt[iproc][ii].size();}
13076 if (tmp_ntotal_polylines != nunsorted_polylines_iproc)
13078 std::ostringstream error_message;
13080 <<
" The total number of unsorted polylines (" 13081 << nunsorted_polylines_iproc <<
") in common with\nprocessor (" 13082 << iproc<<
") is different from the total number of sorted " 13083 <<
"polylines (" << tmp_ntotal_polylines <<
") with\nthe same " 13086 OOMPH_CURRENT_FUNCTION,
13087 OOMPH_EXCEPTION_LOCATION);
13094 this->Final_shared_boundary_id = shared_boundary_id_start;
13102 template<
class ELEMENT>
13104 const unsigned &initial_shd_bnd_id,
13105 std::list<Node*> &input_nodes,
13108 const int &input_connect_to_the_left,
13109 const int &input_connect_to_the_right,
13110 Vector<std::list<Node*> > &output_sorted_nodes_pt,
13117 Node* left_node_pt = input_nodes.front();
13118 Node* right_node_pt = input_nodes.back();
13127 std::list<Node*>::iterator it = input_nodes.begin();
13130 unsigned counter = 0;
13133 while(it != input_nodes.end())
13138 if (it == input_nodes.end())
13150 std::list<Node*> sub_nodes;
13159 sub_nodes.push_back(*it);
13169 sub_nodes.push_back((*it));
13172 sub_bnd_ele_pt.push_back(input_boundary_element_pt[counter]);
13173 sub_bnd_ele_pt.push_back(input_boundary_element_pt[counter+1]);
13176 sub_face_idx_ele.push_back(input_face_index_element[counter]);
13177 sub_face_idx_ele.push_back(input_face_index_element[counter+1]);
13184 }
while((*it) != left_node_pt &&
13185 (*it) != right_node_pt &&
13186 it != input_nodes.end());
13189 tmp_sub_nodes.push_back(sub_nodes);
13191 tmp_sub_bnd_ele_pt.push_back(sub_bnd_ele_pt);
13193 tmp_sub_face_idx_ele.push_back(sub_face_idx_ele);
13201 const unsigned n_sub_list = tmp_sub_nodes.size();
13204 if (n_sub_list > 3)
13206 std::stringstream error_message;
13208 <<
"The number of sub-list of nodes created from the shared\n" 13209 <<
"polyline with loops was (" << n_sub_list <<
").\n" 13210 <<
"We can only handle up to three sub-list of nodes\n";
13212 OOMPH_CURRENT_FUNCTION,
13213 OOMPH_EXCEPTION_LOCATION);
13219 if (n_sub_list == 1 && (left_node_pt != right_node_pt))
13227 output_sorted_nodes_pt = tmp_sub_nodes;
13229 output_boundary_element_pt = tmp_sub_bnd_ele_pt;
13231 output_face_index_element = tmp_sub_face_idx_ele;
13237 if (input_connect_to_the_left == -2)
13239 std::stringstream error_message;
13241 <<
"The connection flag to the left (" 13242 << input_connect_to_the_left <<
") indicates a connection\n" 13243 <<
"with the same polyline.\n However, only one sub-polyline was " 13244 <<
"found and no loop\nwas identified\n\n";
13246 OOMPH_CURRENT_FUNCTION,
13247 OOMPH_EXCEPTION_LOCATION);
13252 if (input_connect_to_the_left == -3)
13254 output_connect_to_the_left.push_back(-1);
13258 output_connect_to_the_left.push_back(input_connect_to_the_left);
13262 if (input_connect_to_the_right == -2)
13264 std::stringstream error_message;
13266 <<
"The connection flag to the right (" 13267 << input_connect_to_the_right <<
") indicates a connection\n" 13268 <<
"with the same polyline.\n However, only one sub-polyline was " 13269 <<
"found and no loop\nwas identified\n\n";
13271 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13272 OOMPH_EXCEPTION_LOCATION);
13277 if (input_connect_to_the_right == -3)
13279 output_connect_to_the_right.push_back(-1);
13283 output_connect_to_the_right.push_back(input_connect_to_the_right);
13291 unsigned tmp_shd_bnd_id = initial_shd_bnd_id;
13299 Node* left_sub_node_pt = tmp_sub_nodes[0].front();
13300 Node* right_sub_node_pt = tmp_sub_nodes[0].back();
13303 if (left_sub_node_pt == right_sub_node_pt)
13309 std::list<Node*> first_half_node_pt;
13310 std::list<Node*> second_half_node_pt;
13319 const unsigned n_sub_nodes = tmp_sub_nodes[0].size();
13323 const unsigned n_sub_nodes_half =
static_cast<unsigned>(n_sub_nodes / 2.0);
13328 std::list<Node*>::iterator it_sub = tmp_sub_nodes[0].begin();
13331 first_half_node_pt.push_back(*it_sub);
13337 unsigned counter_nodes = 0;
13338 unsigned counter2 = 0;
13341 for (;it_sub != tmp_sub_nodes[0].end(); it_sub++)
13344 first_half_node_pt.push_back(*it_sub);
13347 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
13348 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2+1]);
13350 first_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
13351 first_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2+1]);
13359 if (counter_nodes == n_sub_nodes_half)
13370 second_half_node_pt.push_back(*it_sub);
13376 for (;it_sub != tmp_sub_nodes[0].end(); it_sub++)
13379 second_half_node_pt.push_back(*it_sub);
13382 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
13383 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2+1]);
13385 second_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
13386 second_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2+1]);
13394 output_sorted_nodes_pt.push_back(first_half_node_pt);
13395 output_sorted_nodes_pt.push_back(second_half_node_pt);
13398 output_boundary_element_pt.push_back(first_half_ele_pt);
13399 output_boundary_element_pt.push_back(second_half_ele_pt);
13402 output_face_index_element.push_back(first_half_face_idx);
13403 output_face_index_element.push_back(second_half_face_idx);
13414 if (input_connect_to_the_left == -3)
13417 output_connect_to_the_left.push_back(-1);
13420 else if (input_connect_to_the_left == -2)
13423 output_connect_to_the_left.push_back(-1);
13428 output_connect_to_the_left.push_back(input_connect_to_the_left);
13434 output_connect_to_the_right.push_back(-1);
13445 output_connect_to_the_left.push_back(tmp_shd_bnd_id-1);
13451 if (n_sub_list == 1)
13453 if (input_connect_to_the_right == -3)
13456 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13458 else if (input_connect_to_the_right == -2)
13461 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13463 else if (input_connect_to_the_right == -1)
13466 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13471 output_connect_to_the_right.push_back(input_connect_to_the_right);
13477 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13490 output_sorted_nodes_pt.push_back(tmp_sub_nodes[0]);
13493 output_boundary_element_pt.push_back(tmp_sub_bnd_ele_pt[0]);
13496 output_face_index_element.push_back(tmp_sub_face_idx_ele[0]);
13504 if (input_connect_to_the_left == -3)
13507 output_connect_to_the_left.push_back(-1);
13510 else if (input_connect_to_the_left == -2)
13513 output_connect_to_the_left.push_back(tmp_shd_bnd_id+1);
13518 output_connect_to_the_left.push_back(input_connect_to_the_left);
13524 output_connect_to_the_right.push_back(tmp_shd_bnd_id+1);
13532 if (n_sub_list > 1)
13536 left_sub_node_pt = tmp_sub_nodes[1].front();
13537 right_sub_node_pt = tmp_sub_nodes[1].back();
13540 if (left_sub_node_pt == right_sub_node_pt)
13546 std::list<Node*> first_half_node_pt;
13547 std::list<Node*> second_half_node_pt;
13556 const unsigned n_sub_nodes = tmp_sub_nodes[1].size();
13560 const unsigned n_sub_nodes_half =
static_cast<unsigned>(n_sub_nodes / 2.0);
13565 std::list<Node*>::iterator it_sub = tmp_sub_nodes[1].begin();
13568 first_half_node_pt.push_back(*it_sub);
13574 unsigned counter_nodes = 0;
13575 unsigned counter2 = 0;
13578 for (;it_sub != tmp_sub_nodes[1].end(); it_sub++)
13581 first_half_node_pt.push_back(*it_sub);
13583 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2]);
13584 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2+1]);
13586 first_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2]);
13587 first_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2+1]);
13595 if (counter_nodes == n_sub_nodes_half)
13606 second_half_node_pt.push_back(*it_sub);
13612 for (;it_sub != tmp_sub_nodes[1].end(); it_sub++)
13615 second_half_node_pt.push_back(*it_sub);
13617 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2]);
13618 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2+1]);
13620 second_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2]);
13621 second_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2+1]);
13629 output_sorted_nodes_pt.push_back(first_half_node_pt);
13630 output_sorted_nodes_pt.push_back(second_half_node_pt);
13633 output_boundary_element_pt.push_back(first_half_ele_pt);
13634 output_boundary_element_pt.push_back(second_half_ele_pt);
13637 output_face_index_element.push_back(first_half_face_idx);
13638 output_face_index_element.push_back(second_half_face_idx);
13649 output_connect_to_the_left.push_back(tmp_shd_bnd_id-1);
13654 output_connect_to_the_right.push_back(-1);
13665 output_connect_to_the_left.push_back(tmp_shd_bnd_id-1);
13671 if (n_sub_list == 2)
13674 if (input_connect_to_the_right == -1)
13677 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13680 else if (input_connect_to_the_right == -2)
13683 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13686 else if (input_connect_to_the_right == -3)
13689 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13694 output_connect_to_the_right.push_back(input_connect_to_the_right);
13704 std::stringstream error_message;
13706 <<
"The second sub-list of nodes creates a loop but this is not\n" 13707 <<
"the last list of sub-nodes.\n" 13708 <<
"This configuration is not supported\n";
13710 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13711 OOMPH_EXCEPTION_LOCATION);
13722 output_sorted_nodes_pt.push_back(tmp_sub_nodes[1]);
13725 output_boundary_element_pt.push_back(tmp_sub_bnd_ele_pt[1]);
13728 output_face_index_element.push_back(tmp_sub_face_idx_ele[1]);
13736 output_connect_to_the_left.push_back(tmp_shd_bnd_id-1);
13742 if (n_sub_list == 2)
13745 if (input_connect_to_the_right == -3)
13748 output_connect_to_the_right.push_back(-1);
13752 else if (input_connect_to_the_right == -2)
13754 std::stringstream error_message;
13756 <<
"The connection flag to the right (" 13757 << input_connect_to_the_right <<
") indicates a connection\n" 13758 <<
"with the same polyline.\n However, the second sub-list of\n" 13759 <<
"nodes was found not making a loop so no connection with\n" 13760 <<
"itself should be marked\n\n";
13762 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13763 OOMPH_EXCEPTION_LOCATION);
13769 output_connect_to_the_right.push_back(input_connect_to_the_right);
13775 output_connect_to_the_right.push_back(tmp_shd_bnd_id+1);
13786 if (n_sub_list > 2)
13790 left_sub_node_pt = tmp_sub_nodes[2].front();
13791 right_sub_node_pt = tmp_sub_nodes[2].back();
13794 if (left_sub_node_pt == right_sub_node_pt)
13800 std::list<Node*> first_half_node_pt;
13801 std::list<Node*> second_half_node_pt;
13810 const unsigned n_sub_nodes = tmp_sub_nodes[2].size();
13814 const unsigned n_sub_nodes_half =
static_cast<unsigned>(n_sub_nodes / 2.0);
13819 std::list<Node*>::iterator it_sub = tmp_sub_nodes[2].begin();
13822 first_half_node_pt.push_back(*it_sub);
13828 unsigned counter_nodes = 0;
13829 unsigned counter2 = 0;
13832 for (;it_sub != tmp_sub_nodes[2].end(); it_sub++)
13835 first_half_node_pt.push_back(*it_sub);
13837 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2]);
13838 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2+1]);
13840 first_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2]);
13841 first_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2+1]);
13849 if (counter_nodes == n_sub_nodes_half)
13860 second_half_node_pt.push_back(*it_sub);
13866 for (;it_sub != tmp_sub_nodes[2].end(); it_sub++)
13869 second_half_node_pt.push_back(*it_sub);
13871 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2]);
13872 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2+1]);
13874 second_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2]);
13875 second_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2+1]);
13883 output_sorted_nodes_pt.push_back(first_half_node_pt);
13884 output_sorted_nodes_pt.push_back(second_half_node_pt);
13887 output_boundary_element_pt.push_back(first_half_ele_pt);
13888 output_boundary_element_pt.push_back(second_half_ele_pt);
13891 output_face_index_element.push_back(first_half_face_idx);
13892 output_face_index_element.push_back(second_half_face_idx);
13900 output_connect_to_the_left.push_back(tmp_shd_bnd_id-1);
13905 output_connect_to_the_right.push_back(-1);
13916 output_connect_to_the_left.push_back(tmp_shd_bnd_id-1);
13920 if (input_connect_to_the_right == -3)
13923 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13925 else if (input_connect_to_the_right == -2)
13928 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13930 else if (input_connect_to_the_right == -1)
13933 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13938 output_connect_to_the_right.push_back(input_connect_to_the_right);
13951 output_sorted_nodes_pt.push_back(tmp_sub_nodes[2]);
13954 output_boundary_element_pt.push_back(tmp_sub_bnd_ele_pt[2]);
13957 output_face_index_element.push_back(tmp_sub_face_idx_ele[2]);
13965 output_connect_to_the_left.push_back(tmp_shd_bnd_id-1);
13970 if (input_connect_to_the_right == -3)
13972 std::stringstream error_message;
13974 <<
"The connection flag to the right (" 13975 << input_connect_to_the_right <<
") indicates 'no connection and\n" 13976 <<
"stop adding nodes'.\n However, the thrid sub-list of\n" 13977 <<
"nodes must have a connection to the right with the same\n" 13978 <<
"shared polyline or with any other polyline\n\n";
13980 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13981 OOMPH_EXCEPTION_LOCATION);
13983 else if (input_connect_to_the_right == -1)
13985 std::stringstream error_message;
13987 <<
"The connection flag to the right (" 13988 << input_connect_to_the_right <<
") indicates 'no connection.\n" 13989 <<
"However, the thrid sub-list of nodes must have a connection\n" 13990 <<
"to the right with the same shared polyline or with any other\n" 13993 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13994 OOMPH_EXCEPTION_LOCATION);
13997 else if (input_connect_to_the_right == -2)
14000 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
14005 output_connect_to_the_right.push_back(input_connect_to_the_right);
14021 template<
class ELEMENT>
14024 const unsigned &initial_shd_bnd_id,
14025 std::list<Node*> &input_nodes,
14029 const int &input_connect_to_the_left,
14030 const int &input_connect_to_the_right,
14031 Vector<std::list<Node*> > &output_sorted_nodes_pt,
14039 Node* left_node_pt = input_nodes.front();
14040 Node* right_node_pt = input_nodes.back();
14050 std::list<Node*>::iterator it = input_nodes.begin();
14053 unsigned counter = 0;
14056 while(it != input_nodes.end())
14061 if (it == input_nodes.end())
14073 std::list<Node*> sub_nodes;
14085 sub_nodes.push_back(*it);
14095 sub_nodes.push_back((*it));
14098 sub_bnd_ele_pt.push_back(input_boundary_element_pt[counter]);
14101 sub_bnd_face_ele_pt.push_back(input_boundary_face_element_pt[counter]);
14104 sub_face_idx_ele.push_back(input_face_index_element[counter]);
14111 }
while((*it) != left_node_pt &&
14112 (*it) != right_node_pt &&
14113 it != input_nodes.end());
14116 tmp_sub_nodes.push_back(sub_nodes);
14119 tmp_sub_bnd_ele_pt.push_back(sub_bnd_ele_pt);
14121 tmp_sub_bnd_face_ele_pt.push_back(sub_bnd_face_ele_pt);
14123 tmp_sub_face_idx_ele.push_back(sub_face_idx_ele);
14131 const unsigned n_sub_list = tmp_sub_nodes.size();
14134 if (n_sub_list > 1)
14136 std::stringstream error_message;
14138 <<
"The number of sub-list of nodes created from the shared\n" 14139 <<
"polyline with loops was (" << n_sub_list <<
").\n" 14140 <<
"We can only handle one list which may still contain loops\n" 14141 <<
"(or repeated nodes)\n";
14143 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14144 OOMPH_EXCEPTION_LOCATION);
14150 if (n_sub_list == 1 && (left_node_pt != right_node_pt))
14158 output_sorted_nodes_pt = tmp_sub_nodes;
14160 output_boundary_element_pt = tmp_sub_bnd_ele_pt;
14162 output_boundary_face_element_pt = tmp_sub_bnd_face_ele_pt;
14164 output_face_index_element = tmp_sub_face_idx_ele;
14170 if (input_connect_to_the_left == -2)
14172 std::stringstream error_message;
14174 <<
"The connection flag to the left (" 14175 << input_connect_to_the_left <<
") indicates a connection\n" 14176 <<
"with the same polyline.\n However, only one sub-polyline was " 14177 <<
"found and no loops\nwere identified\n\n";
14179 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14180 OOMPH_EXCEPTION_LOCATION);
14185 if (input_connect_to_the_left == -3)
14187 output_connect_to_the_left.push_back(-1);
14191 output_connect_to_the_left.push_back(input_connect_to_the_left);
14195 if (input_connect_to_the_right == -2)
14197 std::stringstream error_message;
14199 <<
"The connection flag to the right (" 14200 << input_connect_to_the_right <<
") indicates a connection\n" 14201 <<
"with the same polyline.\n However, only one sub-polyline was " 14202 <<
"found and no loops\nwere identified\n\n";
14204 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14205 OOMPH_EXCEPTION_LOCATION);
14210 if (input_connect_to_the_right == -3)
14212 output_connect_to_the_right.push_back(-1);
14216 output_connect_to_the_right.push_back(input_connect_to_the_right);
14224 unsigned tmp_shd_bnd_id = initial_shd_bnd_id;
14232 Node* left_sub_node_pt = tmp_sub_nodes[0].front();
14233 Node* right_sub_node_pt = tmp_sub_nodes[0].back();
14236 if (left_sub_node_pt == right_sub_node_pt)
14242 std::list<Node*> first_half_node_pt;
14243 std::list<Node*> second_half_node_pt;
14255 const unsigned n_sub_nodes = tmp_sub_nodes[0].size();
14259 const unsigned n_sub_nodes_half =
static_cast<unsigned>(n_sub_nodes / 2.0);
14264 std::list<Node*>::iterator it_sub = tmp_sub_nodes[0].begin();
14267 first_half_node_pt.push_back(*it_sub);
14273 unsigned counter_nodes = 0;
14274 unsigned counter2 = 0;
14277 for (;it_sub != tmp_sub_nodes[0].end(); it_sub++)
14280 first_half_node_pt.push_back(*it_sub);
14283 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
14285 first_half_ele_face_pt.push_back(tmp_sub_bnd_face_ele_pt[0][counter2]);
14287 first_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
14295 if (counter_nodes == n_sub_nodes_half)
14306 second_half_node_pt.push_back(*it_sub);
14312 for (;it_sub != tmp_sub_nodes[0].end(); it_sub++)
14315 second_half_node_pt.push_back(*it_sub);
14318 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
14320 second_half_ele_face_pt.push_back(tmp_sub_bnd_face_ele_pt[0][counter2]);
14322 second_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
14330 output_sorted_nodes_pt.push_back(first_half_node_pt);
14331 output_sorted_nodes_pt.push_back(second_half_node_pt);
14334 output_boundary_element_pt.push_back(first_half_ele_pt);
14335 output_boundary_element_pt.push_back(second_half_ele_pt);
14338 output_boundary_face_element_pt.push_back(first_half_ele_face_pt);
14339 output_boundary_face_element_pt.push_back(second_half_ele_face_pt);
14342 output_face_index_element.push_back(first_half_face_idx);
14343 output_face_index_element.push_back(second_half_face_idx);
14354 if (input_connect_to_the_left == -3)
14357 output_connect_to_the_left.push_back(-1);
14360 else if (input_connect_to_the_left == -2)
14363 output_connect_to_the_left.push_back(-1);
14368 output_connect_to_the_left.push_back(input_connect_to_the_left);
14374 output_connect_to_the_right.push_back(-1);
14385 output_connect_to_the_left.push_back(tmp_shd_bnd_id-1);
14391 if (n_sub_list == 1)
14393 if (input_connect_to_the_right == -3)
14396 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
14398 else if (input_connect_to_the_right == -2)
14401 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
14403 else if (input_connect_to_the_right == -1)
14406 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
14411 output_connect_to_the_right.push_back(input_connect_to_the_right);
14417 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
14427 std::stringstream error_message;
14429 <<
"The initial and final node in the current shared polyline are not\n" 14430 <<
"the same and the number of sublists is ("<< n_sub_list <<
").\n" 14431 <<
"We can not handle more than one sublist in the method to break\n" 14432 <<
"loops at the load balance stage\n\n";
14434 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14435 OOMPH_EXCEPTION_LOCATION);
14446 template<
class ELEMENT>
14449 const unsigned &shd_bnd_id,
14450 const unsigned &iproc,
14451 const unsigned &jproc,
14452 std::list<Node*> &sorted_nodes,
14453 const int &root_edge_bnd_id,
14457 &unsorted_polylines_pt,
14458 const int &connect_to_the_left_flag,
14459 const int &connect_to_the_right_flag)
14470 Shared_boundaries_ids[iproc][jproc].push_back(shd_bnd_id);
14473 Shared_boundaries_ids[jproc][iproc].push_back(shd_bnd_id);
14478 processors[0] = iproc;
14479 processors[1] = jproc;
14480 Shared_boundary_from_processors[shd_bnd_id] = processors;
14486 if (iproc == my_rank || jproc == my_rank)
14493 const unsigned n_nodes = sorted_nodes.size();
14498 unsigned counter = 0;
14500 for (std::list<Node*>::iterator it = sorted_nodes.begin();
14501 it != sorted_nodes.end(); it++)
14503 vertices[counter].resize(2);
14504 vertices[counter][0] = (*it)->x(0);
14505 vertices[counter][1] = (*it)->x(1);
14521 if (root_edge_bnd_id != -1)
14525 Shared_boundary_overlaps_internal_boundary[shd_bnd_id] =
14526 static_cast<unsigned>(root_edge_bnd_id);
14534 const unsigned n_shared_boundary_elements = bulk_bnd_ele_pt.size();
14538 const unsigned n_face_index = face_index_ele.size();
14539 if (n_shared_boundary_elements != n_face_index)
14541 std::ostringstream error_message;
14543 <<
"The number of shared boundary elements is different from the\n" 14544 <<
"number of face indexes associated to the shared boundary\n" 14546 <<
"Number of shared boundary elements: (" 14547 << n_shared_boundary_elements <<
")\n" 14548 <<
"Number of face indexes: (" << n_face_index <<
")\n\n";
14550 "TriangleMesh::create_shared_polyline()",
14551 OOMPH_EXCEPTION_LOCATION);
14557 for (
unsigned i = 0 ;
i < n_shared_boundary_elements;
i++)
14559 add_shared_boundary_element(shd_bnd_id, bulk_bnd_ele_pt[
i]);
14560 add_face_index_at_shared_boundary(shd_bnd_id, face_index_ele[i]);
14564 for (std::list<Node*>::iterator it = sorted_nodes.begin();
14565 it != sorted_nodes.end(); it++)
14567 add_shared_boundary_node(shd_bnd_id, (*it));
14575 this->Boundary_curve_section_pt[shd_bnd_id] = polyline_pt;
14580 const unsigned n_procs = unsorted_polylines_pt.size();
14585 unsorted_polylines_pt[iproc].push_back(polyline_pt);
14589 unsorted_polylines_pt[jproc].push_back(polyline_pt);
14595 unsorted_polylines_pt[0].push_back(polyline_pt);
14599 this->Free_curve_section_pt.insert(polyline_pt);
14609 if (connect_to_the_left_flag < 0)
14612 if (connect_to_the_left_flag != -1)
14614 std::ostringstream error_message;
14616 <<
"The only accepted values for the connection flags are:\n" 14617 <<
"POSITIVE values or -1, any other value is rejected, please\n" 14618 <<
"check that you previously called the methods to deal with\n" 14619 <<
"other flag values\n" 14620 <<
"The current flag value for connection to the left is: (" 14621 << connect_to_the_left_flag<<
")\n\n";
14623 "TriangleMesh::create_shared_polyline()",
14624 OOMPH_EXCEPTION_LOCATION);
14629 if (connect_to_the_right_flag < 0)
14632 if (connect_to_the_right_flag != -1)
14634 std::ostringstream error_message;
14636 <<
"The only accepted values for the connection flags are:\n" 14637 <<
"POSITIVE values or -1, any other value is rejected, please\n" 14638 <<
"check that you previously called the methods to deal with\n" 14639 <<
"other flag values\n" 14640 <<
"The current flag value for connection to the right is: (" 14641 << connect_to_the_right_flag<<
")\n\n";
14643 "TriangleMesh::create_shared_polyline()",
14644 OOMPH_EXCEPTION_LOCATION);
14650 if (connect_to_the_left_flag != -1)
14653 const unsigned bnd_id_connection_to_the_left =
14654 static_cast<unsigned>(connect_to_the_left_flag);
14659 bnd_id_connection_to_the_left;
14666 if (connect_to_the_right_flag != -1)
14669 const unsigned bnd_id_connection_to_the_right =
14670 static_cast<unsigned>(connect_to_the_right_flag);
14675 bnd_id_connection_to_the_right;
14689 template <
class ELEMENT>
14693 &ntmp_boundary_elements_in_region,
14697 const unsigned nbound = this->nboundary();
14700 const unsigned n_regions = this->nregion();
14703 for (
unsigned b = 0; b < nbound; b++)
14708 const unsigned nbound_ele = this->nboundary_element(b);
14711 Vector<int> backed_up_face_index_at_boundary(nbound_ele);
14712 for (
unsigned e = 0;
e < nbound_ele;
e++)
14715 backed_up_boundary_element_pt[
e] = this->boundary_element_pt(b,
e);
14717 backed_up_face_index_at_boundary[
e] =
14718 this->face_index_at_boundary(b,
e);
14723 backed_up_boundary_region_element_pt(n_regions);
14728 for (
unsigned ir = 0; ir < n_regions; ir++)
14731 const unsigned region_id =
14732 static_cast<unsigned>(this->region_attribute(ir));
14734 const unsigned nbnd_region_ele =
14735 this->nboundary_element_in_region(b, region_id);
14738 for (
unsigned e = 0;
e < nbnd_region_ele;
e++)
14741 backed_up_boundary_region_element_pt[ir][
e] =
14742 this->boundary_element_in_region_pt(b, region_id,
e);
14745 backed_up_face_index_at_boundary_region[ir][
e] =
14746 this->face_index_at_boundary_in_region(b, region_id,
e);
14752 this->Boundary_element_pt[b].clear();
14753 this->Face_index_at_boundary[b].clear();
14756 this->Boundary_region_element_pt[b].clear();
14757 this->Face_index_region_at_boundary[b].clear();
14766 const unsigned nold_bnd_ele = ntmp_boundary_elements[b];
14768 for (
unsigned e = 0;
e < nold_bnd_ele;
e++)
14773 std::find(deleted_elements.begin(),
14774 deleted_elements.end(),
14778 if (it == deleted_elements.end())
14781 this->Boundary_element_pt[b].push_back(add_ele_pt);
14782 const int face_index = backed_up_face_index_at_boundary[
e];
14783 this->Face_index_at_boundary[b].push_back(face_index);
14791 for (
unsigned ir = 0; ir < n_regions; ir++)
14794 const unsigned region_id =
14795 static_cast<unsigned>(this->region_attribute(ir));
14798 const unsigned nold_bnd_region_ele =
14799 ntmp_boundary_elements_in_region[b][ir];
14803 for (
unsigned e = 0;
e < nold_bnd_region_ele;
e++)
14807 backed_up_boundary_region_element_pt[ir][
e];
14810 std::find(deleted_elements.begin(),
14811 deleted_elements.end(),
14815 if (it == deleted_elements.end())
14818 backed_up_boundary_region_element_pt[ir][
e];
14819 this->Boundary_region_element_pt[b][region_id].push_back(add_ele_pt);
14820 const int face_index = backed_up_face_index_at_boundary_region[ir][
e];
14821 this->Face_index_region_at_boundary[b][region_id].
14822 push_back(face_index);
14834 for (
unsigned e = nold_bnd_ele;
e < nbound_ele;
e++)
14837 this->Boundary_element_pt[b].push_back(add_ele_pt);
14838 const int face_index = backed_up_face_index_at_boundary[
e];
14839 this->Face_index_at_boundary[b].push_back(face_index);
14845 for (
unsigned ir = 0; ir < n_regions; ir++)
14848 const unsigned region_id =
14849 static_cast<unsigned>(this->region_attribute(ir));
14852 const unsigned nold_bnd_region_ele =
14853 ntmp_boundary_elements_in_region[b][ir];
14856 const unsigned nbnd_region_ele =
14857 this->nboundary_element_in_region(b, region_id);
14861 for (
unsigned e = nold_bnd_region_ele;
e < nbnd_region_ele;
e++)
14863 FiniteElement* add_ele_pt = backed_up_boundary_region_element_pt[ir][
e];
14864 this->Boundary_region_element_pt[b][region_id].push_back(add_ele_pt);
14865 const int face_index = backed_up_face_index_at_boundary_region[ir][
e];
14866 this->Face_index_region_at_boundary[b][region_id].push_back(face_index);
14874 Lookup_for_elements_next_boundary_is_setup=
true;
14878 #endif // OOMPH_HAS_MPI 14880 #ifdef OOMPH_HAS_TRIANGLE_LIB 14885 template <
class ELEMENT>
14905 (
double *) malloc(triangulate_io.
numberofpoints * 2 *
sizeof(
double));
14918 for(
unsigned count_point=0;count_point<n_points*2;count_point++)
14920 triangle_refine.
pointlist[count_point]=
14925 if (count_point%2==0)
14927 x_coord[count_point/2] = triangulate_io.
pointlist[count_point];
14931 y_coord[(count_point-1)/2] = triangulate_io.
pointlist[count_point];
14936 for(
unsigned count_marker=0;count_marker<n_points;count_marker++)
14943 for(
unsigned count_seg=0;count_seg<n_segments*2;count_seg++)
14950 for(
unsigned count_markers=0;count_markers<n_segments;count_markers++)
14961 (
double*) malloc(triangulate_io.
numberofholes * 2 *
sizeof(
double));
14964 for(
unsigned count_hole=0;count_hole<n_holes*2;count_hole++)
14966 triangle_refine.
holelist[count_hole] = triangulate_io.
holelist[count_hole];
14974 if (n_triangles!=target_area.size())
14976 std::stringstream err;
14977 err <<
"Number of triangles in triangulate_io=" 14978 << n_triangles <<
" doesn't match\n" 14979 <<
"size of target area vector (" 14980 << target_area.size() <<
")\n";
14983 OOMPH_CURRENT_FUNCTION,
14984 OOMPH_EXCEPTION_LOCATION);
14995 for(
unsigned count_tri=0;count_tri<n_triangles*3;count_tri++)
15004 for(
unsigned count_area=0;count_area<n_triangles;count_area++)
15017 for(
unsigned count_attribute=0;
15027 #ifdef OOMPH_HAS_MPI 15042 const std::pair<double, double> &rhs)
const 15044 double diff_y=lhs.second-rhs.second;
15055 double diff_x=lhs.first-rhs.first;
15056 if (fabs(diff_x)<Tol)
15058 std::ostringstream warning_message;
15060 <<
"Dodgy \"lower left\" (lexicographic) comparison " 15061 <<
"of points with cooordinates: " 15062 <<
" lhs = ( " << lhs.first <<
" , " << lhs.second <<
" ) \n" 15063 <<
" rhs = ( " << rhs.first <<
" , " << rhs.second <<
" ) \n" 15064 <<
"x and y coordinates differ by less than tolerance!\n" 15065 <<
"diff_x = " << diff_x <<
"\n" 15066 <<
"diff_y = " << diff_y <<
"\n" 15067 <<
"Tol = " << Tol <<
"\n";
15069 OOMPH_CURRENT_FUNCTION,
15070 OOMPH_EXCEPTION_LOCATION);
15073 if (lhs.first < rhs.first)
15130 template <
class ELEMENT>
15135 this->shared_boundaries_in_this_processor(my_rank_shared_boundaries_ids);
15138 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
15141 for (
unsigned i = 0;
i < nmy_rank_shd_bnd;
i++)
15146 std::map<std::pair<double, double>,
Node*,
classcomp> sorted_nodes_pt;
15153 double min_distance_squared=DBL_MAX;
15158 const unsigned b = my_rank_shared_boundaries_ids[
i];
15161 const unsigned nbnd_node = this->nshared_boundary_node(b);
15165 for (
unsigned i_node = 0; i_node < nbnd_node; i_node++)
15167 Node* node_pt = this->shared_boundary_node_pt(b, i_node);
15168 std::pair<double, double> vertex = std::make_pair(node_pt->
x(0),
15170 sorted_nodes_pt[vertex] = node_pt;
15177 for (
unsigned j_node = 0; j_node < nbnd_node; j_node++)
15179 if (i_node!=j_node)
15181 Node* node2_pt = this->shared_boundary_node_pt(b, j_node);
15184 double squared_distance=0.0;
15185 for (
unsigned ii=0;ii<2;ii++)
15188 (node_pt->
x(ii)-node2_pt->
x(ii))*
15189 (node_pt->
x(ii)-node2_pt->
x(ii));
15191 if (squared_distance<min_distance_squared)
15193 min_distance_squared=squared_distance;
15200 std::ostringstream warning_message;
15202 <<
"Minimum distance between nodes on boundary " << b <<
"\n" 15203 <<
"is " << sqrt(min_distance_squared) <<
" which is less than " 15205 <<
"This may screw up the ordering of the nodes on shared boundaries\n";
15207 OOMPH_CURRENT_FUNCTION,
15208 OOMPH_EXCEPTION_LOCATION);
15215 unsigned counter = 0;
15217 this->Sorted_shared_boundary_node_pt[b].resize(nbnd_node);
15223 for (std::map<std::pair<double, double>, Node*>::iterator it_map
15224 = sorted_nodes_pt.begin(); it_map != sorted_nodes_pt.end(); it_map++)
15227 this->Sorted_shared_boundary_node_pt[b][counter++] = (*it_map).second;
15239 template <
class ELEMENT>
15242 const bool update_elements,
15243 const bool flush_nodes,
15244 const bool update_nodes)
15247 const unsigned my_rank = this->communicator_pt()->my_rank();
15253 const unsigned initial_id = this->initial_shared_boundary_id();
15256 const unsigned final_id = this->final_shared_boundary_id();
15258 if (flush_elements)
15261 this->flush_shared_boundary_element();
15263 this->flush_face_index_at_shared_boundary();
15269 this->flush_shared_boundary_node();
15272 for (
unsigned b = initial_id; b < final_id; b++)
15276 procs_from_shrd_bnd = this->shared_boundary_from_processors(b);
15277 bool current_processor_has_b_boundary =
false;
15278 const unsigned n_procs_from_shrd_bnd = procs_from_shrd_bnd.size();
15279 for (
unsigned p = 0; p < n_procs_from_shrd_bnd; p++)
15281 if (procs_from_shrd_bnd[p] == my_rank)
15283 current_processor_has_b_boundary =
true;
15288 if (current_processor_has_b_boundary)
15290 if (update_elements)
15292 const unsigned nboundary_ele = this->nboundary_element(b);
15293 for (
unsigned e = 0;
e < nboundary_ele;
e++)
15298 this->add_shared_boundary_element(b, bnd_ele_pt);
15300 int face_index = this->face_index_at_boundary(b,
e);
15301 this->add_face_index_at_shared_boundary(b, face_index);
15309 const unsigned nboundary_node = this->nboundary_node(b);
15310 for (
unsigned n = 0; n < nboundary_node; n++)
15312 Node* bnd_node_pt = this->boundary_node_pt(b, n);
15313 this->add_shared_boundary_node(b, bnd_node_pt);
15326 template <
class ELEMENT>
15330 unsigned nproc = this->communicator_pt()->nproc();
15332 unsigned my_rank = this->communicator_pt()->my_rank();
15335 double tt_start = 0.0;
15350 other_proc_shd_bnd_node_pt(nproc);
15352 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15355 other_proc_shd_bnd_node_pt[iproc].resize(nproc);
15356 for (
unsigned jproc = 0; jproc < nproc; jproc++)
15359 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
15360 const unsigned final_shd_bnd_id = this->final_shared_boundary_id();
15361 const unsigned nshared_bound = final_shd_bnd_id - initial_shd_bnd_id;
15362 other_proc_shd_bnd_node_pt[iproc][jproc].resize(nshared_bound);
15375 std::map<Vector<unsigned>,
unsigned> node_name_to_global_index;
15382 double t_start_global_node_names_and_shared_nodes =
15388 compute_global_node_names_and_shared_nodes(other_proc_shd_bnd_node_pt,
15390 node_name_to_global_index,
15391 global_shared_node_pt);
15394 const unsigned n_ele = this->nelement();
15396 if (Print_timings_level_adaptation>1)
15400 double t_final_global_node_names_and_shared_nodes =
15402 oomph_info <<
"CPU for computing global node names and shared nodes " 15403 <<
"[n_ele="<< n_ele <<
"]: " 15404 << t_final_global_node_names_and_shared_nodes << std::endl;
15421 double t_start_send_info_shd_nodes_on_original_bnds =
15426 send_boundary_node_info_of_shared_nodes(global_node_names,
15427 node_name_to_global_index,
15428 global_shared_node_pt);
15430 if (Print_timings_level_adaptation>1)
15435 <<
"CPU for sending info. of shared nodes on original boundaries: " 15464 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15466 const unsigned n_shd_bnd_iproc = this->nshared_boundaries(my_rank, iproc);
15467 ele_with_node_on_shd_bnd_pt[iproc].resize(n_shd_bnd_iproc);
15474 for (
unsigned e = 0;
e < n_ele;
e++)
15479 const unsigned n_nodes = ele_pt->
nnode();
15482 for (
unsigned n = 0; n < n_nodes; n++)
15491 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15496 const unsigned n_shd_bnd_iproc =
15497 this->nshared_boundaries(my_rank, iproc);
15500 if (iproc != my_rank && n_shd_bnd_iproc > 0)
15505 this->shared_boundaries_ids(my_rank, iproc);
15508 for (
unsigned isb = 0; isb < n_shd_bnd_iproc; isb++)
15510 const unsigned shd_bnd_id = shd_bnd_ids[isb];
15511 const unsigned n_ele_shd_bnd =
15512 this->nshared_boundary_element(shd_bnd_id);
15516 if (n_ele_shd_bnd > 0 &&
15517 this->is_node_on_shared_boundary(shd_bnd_id, node_pt))
15521 ele_with_node_on_shd_bnd_pt[iproc][isb].push_back(ele_pt);
15564 double t_start_regenerate_halo_ed_elements_nodes_first_stage =
15568 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15571 if (iproc != my_rank)
15574 const unsigned nshared_boundaries_with_iproc =
15575 this->nshared_boundaries(my_rank, iproc);
15577 if (nshared_boundaries_with_iproc > 0)
15591 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 15597 bound_shared_with_iproc = this->shared_boundaries_ids(my_rank, iproc);
15600 for (
unsigned bs = 0; bs < nshared_boundaries_with_iproc; bs++)
15602 const unsigned bnd_id = bound_shared_with_iproc[bs];
15604 const unsigned nel_bnd = this->nshared_boundary_element(bnd_id);
15615 std::map<FiniteElement*,bool> already_added;
15618 for (
unsigned e = 0;
e < nel_bnd;
e++)
15622 this->shared_boundary_element_pt(bnd_id,
e);
15627 if (!already_added[ele_pt])
15630 haloed_element.push_back(ele_pt);
15632 already_added[ele_pt] =
true;
15643 const unsigned n_ele_with_node_on_shd_bnd =
15644 ele_with_node_on_shd_bnd_pt[iproc][bs].size();
15647 for (
unsigned iele = 0; iele < n_ele_with_node_on_shd_bnd; iele++)
15651 ele_with_node_on_shd_bnd_pt[iproc][bs][iele];
15653 if (!already_added[ele_pt])
15656 haloed_element.push_back(ele_pt);
15658 already_added[ele_pt] =
true;
15666 const unsigned nhaloed_ele = haloed_element.size();
15674 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 15675 std::stringstream junk;
15676 junk <<
"Number of haloed elements " << nhaloed_ele;
15681 for (
unsigned e = 0;
e < nhaloed_ele;
e++)
15685 const unsigned nroot_haloed_ele =
15686 this->nroot_haloed_element(iproc);
15691 const unsigned haloed_ele_index =
15692 this->try_to_add_root_haloed_element_pt(iproc, gen_ele_pt);
15696 if (nroot_haloed_ele == haloed_ele_index)
15699 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 15704 get_required_elemental_information_helper(iproc, ele_pt);
15707 const unsigned nnodes = ele_pt->
nnode();
15708 for (
unsigned j = 0; j < nnodes; j++)
15714 add_haloed_node_helper(iproc, node_pt);
15721 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 15725 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 15740 int send_proc =
static_cast<int>(iproc);
15742 int recv_proc =
static_cast<int>(iproc);
15743 send_and_receive_elements_nodes_info(send_proc, recv_proc);
15756 for (
unsigned bs = 0; bs < nshared_boundaries_with_iproc; bs++)
15759 const unsigned nhaloed_ele =
15762 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 15764 <<
" Number of elements need to be constructed " 15770 for (
unsigned e = 0;
e < nhaloed_ele;
e++)
15774 create_halo_element(iproc,
15775 iproc_currently_created_nodes_pt[iproc],
15776 other_proc_shd_bnd_node_pt,
15778 node_name_to_global_index,
15779 global_shared_node_pt);
15791 if (Print_timings_level_adaptation>1)
15794 double t_final_regenerate_halo_ed_elements_nodes_first_stage =
15797 oomph_info <<
"CPU for re-generating halo(ed) elements/nodes " 15798 <<
"(first stage) [n_ele="<< n_ele <<
"]: " 15799 << t_final_regenerate_halo_ed_elements_nodes_first_stage
15816 double t_start_regenerate_halo_ed_elements_nodes_second_stage =
15821 reset_halo_haloed_scheme_helper(other_proc_shd_bnd_node_pt,
15822 iproc_currently_created_nodes_pt,
15824 node_name_to_global_index,
15825 global_shared_node_pt);
15827 if (Print_timings_level_adaptation>1)
15830 double t_final_regenerate_halo_ed_elements_nodes_second_stage =
15833 oomph_info <<
"CPU for re-generating halo(ed) elements/nodes " 15834 <<
"(second stage) [n_ele="<< n_ele <<
"]: " 15835 << t_final_regenerate_halo_ed_elements_nodes_second_stage
15847 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 15853 if (Print_timings_level_adaptation>1)
15857 <<
"CPU for resetting halo-haloed scheme (without classification of halo and haloed nodes): " 15858 << tt_end-tt_start << std::endl;
15864 const bool report_stats =
true;
15869 this->classify_halo_and_haloed_nodes(tmp_doc_info,report_stats);
15873 if (Print_timings_level_adaptation>1)
15877 <<
"CPU for resetting halo-haloed scheme (with classification of halo and haloed nodes): " 15878 << tt_end-tt_start << std::endl;
15896 template <
class ELEMENT>
15900 &other_proc_shd_bnd_node_pt,
15906 const unsigned nproc = this->communicator_pt()->nproc();
15908 const unsigned my_rank = this->communicator_pt()->my_rank();
15920 unsigned counter_nodes = 0;
15922 std::map<Node*, bool> done_node;
15924 std::map<Node*, unsigned> local_node_number;
15945 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15948 if (iproc != my_rank)
15951 const unsigned n_shd_bnds_with_iproc =
15952 this->nshared_boundaries(my_rank, iproc);
15956 this->shared_boundaries_ids(my_rank, iproc);
15959 for (
unsigned ishd = 0; ishd < n_shd_bnds_with_iproc; ishd++)
15962 std::map<Node*,bool> done_node_shd_bnd;
15964 unsigned shd_bnd_id = bnd_shd_with_iproc[ishd];
15966 const unsigned n_shd_bnd_ele =
15967 this->nshared_boundary_element(shd_bnd_id);
15970 for (
unsigned e = 0;
e < n_shd_bnd_ele;
e++)
15974 this->shared_boundary_element_pt(shd_bnd_id,
e);
15977 const unsigned n_nodes = ele_pt->
nnode();
15980 for (
unsigned n = 0; n < n_nodes; n++)
15988 if (!done_node_shd_bnd[node_pt] &&
15989 this->is_node_on_shared_boundary(shd_bnd_id,
15993 done_node_shd_bnd[node_pt] =
true;
15998 const unsigned n_nodes_shd_bnd =
15999 nsorted_shared_boundary_node(shd_bnd_id);
16002 unsigned index = 0;
16006 bool found_node_on_shared_boundary =
false;
16010 for (
unsigned k = 0; k < n_nodes_shd_bnd; k++)
16013 Node* shd_bnd_node_pt =
16014 sorted_shared_boundary_node_pt(shd_bnd_id, k);
16017 if (shd_bnd_node_pt == node_pt)
16023 found_node_on_shared_boundary =
true;
16032 if (!found_node_on_shared_boundary)
16034 std::ostringstream error_message;
16036 <<
"The index of the node on boundary ("<<shd_bnd_id
16037 <<
") was not found.\n" 16038 <<
"These are the node coordinates\n" 16039 <<
"("<<node_pt->
x(0)<<
","<<node_pt->
x(1)<<
").\n";
16041 OOMPH_CURRENT_FUNCTION,
16042 OOMPH_EXCEPTION_LOCATION);
16048 node_name[0] = my_rank;
16049 node_name[1] = iproc;
16050 node_name[2] = shd_bnd_id;
16051 node_name[3] = index;
16056 if (!done_node[node_pt])
16061 local_node_pt.push_back(node_pt);
16064 local_node_number[node_pt] = counter_nodes;
16066 node_name[4] = counter_nodes;
16070 done_node[node_pt] =
true;
16075 first_node_name[0] = node_name;
16076 local_node_names.push_back(first_node_name);
16083 unsigned node_number = local_node_number[node_pt];
16086 node_name[4] = node_number;
16090 local_node_names[node_number].push_back(node_name);
16116 unsigned n_total_local_names = 0;
16118 const unsigned n_local_nodes = local_node_names.size();
16121 for (
unsigned i = 0;
i < n_local_nodes;
i++)
16124 const unsigned n_inode_names = local_node_names[
i].size();
16126 n_total_local_names+=n_inode_names;
16131 const unsigned n_info_per_node_name = 5;
16133 Vector<unsigned> flat_packed_send_udata(n_total_local_names*n_info_per_node_name);
16135 unsigned counter = 0;
16137 for (
unsigned i = 0;
i < n_local_nodes;
i++)
16140 const unsigned n_inode_names = local_node_names[
i].size();
16142 for (
unsigned j = 0 ; j < n_inode_names; j++)
16145 flat_packed_send_udata[counter++]=local_node_names[
i][j][0];
16147 flat_packed_send_udata[counter++]=local_node_names[
i][j][1];
16149 flat_packed_send_udata[counter++]=local_node_names[
i][j][2];
16151 flat_packed_send_udata[counter++]=local_node_names[
i][j][3];
16153 flat_packed_send_udata[counter++]=local_node_names[
i][j][4];
16163 const unsigned n_udata_send_to_root = flat_packed_send_udata.size();
16176 const unsigned root_processor = 0;
16184 MPI_Gather(&n_total_local_names, 1, MPI_UNSIGNED,
16185 &root_n_names_per_processor[0], 1, MPI_UNSIGNED,
16186 root_processor, comm_pt->mpi_comm());
16190 unsigned root_n_total_udata_receive = 0;
16192 for (
unsigned iproc = 0; iproc < nproc; iproc++)
16194 root_n_udata_to_receive[iproc]=
16195 root_n_names_per_processor[iproc]*n_info_per_node_name;
16196 root_n_total_udata_receive+=root_n_udata_to_receive[iproc];
16202 root_uoffsets_receive[0] = 0;
16203 for (
unsigned iproc = 1; iproc < nproc; iproc++)
16206 root_uoffsets_receive[iproc] =
16207 root_uoffsets_receive[iproc-1] + root_n_udata_to_receive[iproc-1];
16212 if (flat_packed_send_udata.size()==0)
16214 flat_packed_send_udata.resize(1);
16218 Vector<unsigned> root_flat_packed_receive_udata(root_n_total_udata_receive);
16221 if (my_rank!=root_processor)
16224 if (root_flat_packed_receive_udata.size()==0)
16226 root_flat_packed_receive_udata.resize(1);
16231 MPI_Gatherv(&flat_packed_send_udata[0],
16234 n_udata_send_to_root,
16237 &root_flat_packed_receive_udata[0],
16241 &root_n_udata_to_receive[0],
16244 &root_uoffsets_receive[0],
16250 comm_pt->mpi_comm());
16253 flat_packed_send_udata.clear();
16254 flat_packed_send_udata.resize(0);
16268 if (my_rank == root_processor)
16283 unsigned rcounter = 0;
16285 for (
unsigned iproc = 0; iproc < nproc; iproc++)
16288 const unsigned n_local_names_iproc =
16289 root_n_names_per_processor[iproc];
16290 for (
unsigned i = 0;
i < n_local_names_iproc;
i++)
16294 for (
unsigned j = 0; j < n_info_per_node_name; j++)
16295 {node_name[j] = root_flat_packed_receive_udata[rcounter++];}
16298 root_local_node_names.push_back(node_name);
16305 const unsigned n_root_local_node_names =
16306 root_local_node_names.size();
16321 std::map<Vector<unsigned>,
bool> done_name;
16325 for (
unsigned i = 0;
i < n_root_local_node_names;
i++)
16331 if (!done_name[node_name])
16334 done_name[node_name] =
true;
16338 bool found_both_names_node =
false;
16343 for (
unsigned j =
i+1; j < n_root_local_node_names; j++)
16348 if (!done_name[node_name_r])
16352 if (node_name[0] == node_name_r[1] &&
16353 node_name[1] == node_name_r[0] &&
16354 node_name[2] == node_name_r[2] &&
16355 node_name[3] == node_name_r[3])
16358 done_name[node_name_r] =
true;
16361 node_name_counter_part[
i] = j;
16364 node_name_counter_part[j] =
i;
16367 found_both_names_node =
true;
16379 if (!found_both_names_node)
16381 std::ostringstream error_message;
16383 <<
"The counter-part of the current name node was " 16384 <<
"not found,\nthe current node name is:\n" 16385 <<
"iproc:("<<node_name[0]<<
")\n" 16386 <<
"jproc:("<<node_name[1]<<
")\n" 16387 <<
"ishd_bnd:("<<node_name[2]<<
")\n" 16388 <<
"index:("<<node_name[3]<<
")\n";
16390 OOMPH_CURRENT_FUNCTION,
16391 OOMPH_EXCEPTION_LOCATION);
16407 for (
unsigned i = 0;
i < n_root_local_node_names;
i++)
16413 if (!done_name[node_name])
16419 all_node_names.push_back(node_name);
16422 unsigned idx_c = node_name_counter_part[
i];
16427 all_node_names.push_back(node_name_r);
16433 unsigned n_current_names = all_node_names.size();
16436 unsigned icounter = 0;
16439 while(icounter < n_current_names)
16447 if (!done_name[current_node_name])
16450 done_name[current_node_name] =
true;
16455 for (
unsigned j=
i+1;j<n_root_local_node_names;j++)
16461 if (!done_name[other_node_name])
16464 if ((current_node_name[0] == other_node_name[0]) &&
16465 (current_node_name[4] == other_node_name[4]))
16470 done_name[other_node_name] =
true;
16474 = std::find(all_node_names.begin(),
16475 all_node_names.end(),
16477 if (it==all_node_names.end())
16479 all_node_names.push_back(other_node_name);
16481 unsigned k = node_name_counter_part[j];
16484 root_local_node_names[k];
16488 if (!done_name[other_node_name_r])
16490 all_node_names.push_back(other_node_name_r);
16505 n_current_names = all_node_names.size();
16513 root_global_node_names.push_back(all_node_names);
16526 flat_packed_root_send_receive_udata.clear();
16528 const unsigned n_global_nodes = root_global_node_names.size();
16531 flat_packed_root_send_receive_udata.push_back(n_global_nodes);
16534 for (
unsigned i = 0;
i < n_global_nodes;
i++)
16538 root_global_node_names[
i];
16540 const unsigned n_names_global_inode = global_inode_names.size();
16543 flat_packed_root_send_receive_udata.push_back(n_names_global_inode);
16545 for (
unsigned j = 0; j < n_names_global_inode; j++)
16548 for (
unsigned k = 0; k < n_info_per_node_name; k++)
16552 flat_packed_root_send_receive_udata.
16553 push_back(global_inode_names[j][k]);
16574 unsigned root_n_udata_sent_to_all_proc =
16575 flat_packed_root_send_receive_udata.size();
16577 MPI_Bcast(&root_n_udata_sent_to_all_proc,
16579 1, MPI_UNSIGNED, root_processor,
16580 comm_pt->mpi_comm());
16583 if (my_rank != root_processor)
16585 flat_packed_root_send_receive_udata.
16586 resize(root_n_udata_sent_to_all_proc);
16590 MPI_Bcast(&flat_packed_root_send_receive_udata[0],
16594 root_n_udata_sent_to_all_proc,
16599 comm_pt->mpi_comm());
16604 const unsigned n_global_nodes =
16605 flat_packed_root_send_receive_udata[counter++];
16612 global_node_names.resize(n_global_nodes);
16614 unsigned n_read_global_nodes = 0;
16615 while (n_read_global_nodes < n_global_nodes)
16618 const unsigned n_names_global_inode =
16619 flat_packed_root_send_receive_udata[counter++];
16621 const unsigned i = n_read_global_nodes;
16623 global_node_names[
i].resize(n_names_global_inode);
16625 for (
unsigned j = 0; j < n_names_global_inode; j++)
16628 global_node_names[
i][j].resize(n_info_per_node_name);
16631 for (
unsigned k = 0; k < n_info_per_node_name; k++)
16635 global_node_names[
i][j][k] =
16636 flat_packed_root_send_receive_udata[counter++];
16643 node_name[0] = global_node_names[
i][j][0];
16644 node_name[1] = global_node_names[
i][j][1];
16645 node_name[2] = global_node_names[
i][j][2];
16646 node_name[3] = global_node_names[
i][j][3];
16651 node_name_to_global_index[node_name] =
i;
16656 n_read_global_nodes++;
16662 if (counter != root_n_udata_sent_to_all_proc)
16664 std::ostringstream error_stream;
16666 <<
"The info. received from root regarding the global names of " 16667 <<
"the nodes\nwas not completely read.\n" 16668 <<
"The number of data sent/received from root is: (" 16669 <<root_n_udata_sent_to_all_proc<<
")\n" 16670 <<
"The number of data read from the received info. is: (" 16671 <<counter<<
")\n\n";
16673 OOMPH_CURRENT_FUNCTION,
16674 OOMPH_EXCEPTION_LOCATION);
16692 global_shared_node_pt.resize(n_global_nodes, 0);
16695 for (
unsigned i = 0;
i < n_global_nodes;
i++)
16699 bool is_this_a_local_node_name =
false;
16700 unsigned local_node_number;
16702 const unsigned n_names_global_inode = global_node_names[
i].size();
16704 for (
unsigned j = 0; j < n_names_global_inode; j++)
16707 const unsigned iproc = global_node_names[
i][j][0];
16708 local_node_number = global_node_names[
i][j][4];
16711 if (my_rank == iproc)
16714 is_this_a_local_node_name =
true;
16723 if (is_this_a_local_node_name)
16728 const unsigned n_names_local_node =
16729 local_node_names[local_node_number].size();
16730 unsigned n_names_found_on_global_name_node = 0;
16735 global_shared_node_pt[
i] = local_node_pt[local_node_number];
16741 for (
unsigned j = 0; j < n_names_global_inode; j++)
16744 const unsigned iproc = global_node_names[
i][j][0];
16747 if (iproc != my_rank)
16750 local_node_names[local_node_number].
16751 push_back(global_node_names[
i][j]);
16756 const unsigned jproc = global_node_names[
i][j][1];
16757 const unsigned ishd_bnd = global_node_names[
i][j][2];
16758 const unsigned idx = global_node_names[
i][j][3];
16759 const unsigned n_local_node = global_node_names[
i][j][4];
16761 for (
unsigned k = 0; k < n_names_local_node; k++)
16763 if ((local_node_names[local_node_number][k][0] == iproc) &&
16764 (local_node_names[local_node_number][k][1] == jproc) &&
16765 (local_node_names[local_node_number][k][2] == ishd_bnd) &&
16766 (local_node_names[local_node_number][k][3] == idx) &&
16767 (local_node_names[local_node_number][k][4] == n_local_node))
16771 n_names_found_on_global_name_node++;
16785 if (n_names_local_node != n_names_found_on_global_name_node)
16787 std::ostringstream error_stream;
16789 <<
"The local node names corresponding to the local " 16790 <<
"node ("<< local_node_number <<
") were\n" 16791 <<
"not found on the global node names.\n\n" 16792 <<
"These are the names of the local node\n" 16793 <<
"Name k: iproc, jproc, ishd_bnd, idx. #node\n";
16794 for (
unsigned k = 0; k < n_names_local_node; k++)
16796 error_stream<<
"Name("<<k<<
"): " 16797 <<local_node_names[local_node_number][k][0]
16798 <<
", "<<local_node_names[local_node_number][k][1]
16799 <<
", "<<local_node_names[local_node_number][k][2]
16800 <<
", "<<local_node_names[local_node_number][k][3]
16801 <<
", "<<local_node_names[local_node_number][k][4]
16806 <<
"\n\nThese are the names of the global node\n" 16807 <<
"Name k: iproc, jproc, ishd_bnd, idx. #node\n";
16808 for (
unsigned k = 0; k < n_names_global_inode; k++)
16810 error_stream<<
"Name("<<k<<
"): " 16811 <<global_node_names[
i][k][0] <<
", " 16812 <<global_node_names[
i][k][1] <<
", " 16813 <<global_node_names[
i][k][2] <<
", " 16814 <<global_node_names[
i][k][3] <<
", " 16815 <<global_node_names[
i][k][4] <<
"\n";
16819 OOMPH_CURRENT_FUNCTION,
16820 OOMPH_EXCEPTION_LOCATION);
16846 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
16849 for (
unsigned i = 0 ;
i < n_local_nodes;
i++)
16852 const unsigned n_names = local_node_names[
i].size();
16856 Node* node_pt = local_node_pt[
i];
16859 for (
unsigned j = 0; j < n_names; j++)
16862 const unsigned iproc = local_node_names[
i][j][0];
16863 const unsigned jproc = local_node_names[
i][j][1];
16864 const unsigned ishd_bnd =
16865 local_node_names[
i][j][2] - initial_shd_bnd_id;
16866 const unsigned index = local_node_names[
i][j][3];
16873 other_proc_shd_bnd_node_pt[iproc][jproc][ishd_bnd][index]=node_pt;
16877 other_proc_shd_bnd_node_pt[jproc][iproc][ishd_bnd][index]=node_pt;
16896 template <
class ELEMENT>
16904 const unsigned nproc = this->communicator_pt()->nproc();
16905 const unsigned my_rank = this->communicator_pt()->my_rank();
16908 const unsigned n_nodes_on_shd_bnds = global_node_names.size();
16919 std::map<Node*, unsigned> node_pt_to_global_shd_bnd_index;
16923 for (
unsigned i = 0;
i < n_nodes_on_shd_bnds;
i++)
16927 const unsigned n_names = global_node_names[
i].size();
16929 for (
unsigned j = 0; j < n_names; j++)
16933 node_name[0] = global_node_names[
i][j][0];
16934 node_name[1] = global_node_names[
i][j][1];
16935 node_name[2] = global_node_names[
i][j][2];
16936 node_name[3] = global_node_names[
i][j][3];
16939 if (node_name[0]==my_rank)
16942 const unsigned jproc = node_name[1];
16945 std::map<Vector<unsigned>,
unsigned>::iterator it =
16946 node_name_to_global_index.find(node_name);
16947 if (it!=node_name_to_global_index.end())
16951 if (
i!=(*it).second)
16953 std::ostringstream error_message;
16955 <<
"The global node number "<<(*it).second
16956 <<
") obtained from the current node\n" 16957 <<
"name is not the same as the current node number (" 16960 <<
"iproc:"<<node_name[0]<<
"\n" 16961 <<
"jproc:"<<node_name[1]<<
"\n" 16962 <<
"shd_bnd_id:"<<node_name[2]<<
"\n" 16963 <<
"index:"<<node_name[3]<<
"\n\n";
16965 OOMPH_CURRENT_FUNCTION,
16966 OOMPH_EXCEPTION_LOCATION);
16972 std::ostringstream error_message;
16974 <<
"The node name is not registerd as living in this processor.\n" 16976 <<
"iproc:"<<node_name[0]<<
"\n" 16977 <<
"jproc:"<<node_name[1]<<
"\n" 16978 <<
"shd_bnd_id:"<<node_name[2]<<
"\n" 16979 <<
"index:"<<node_name[3]<<
"\n\n";
16981 OOMPH_CURRENT_FUNCTION,
16982 OOMPH_EXCEPTION_LOCATION);
16985 #endif // #ifdef PARANOID 16988 Node* node_pt = global_shared_node_pt[
i];
16993 std::ostringstream error_message;
16995 <<
"There is not global shared node within this\n" 16996 <<
"global node number ("<<
i<<
"). The global shared\n" 16997 <<
"node pointer is null\n\n";
16999 OOMPH_CURRENT_FUNCTION,
17000 OOMPH_EXCEPTION_LOCATION);
17002 #endif // #ifdef PARANOID 17006 node_on_shd_bnd_pt[jproc].insert(node_pt);
17009 node_pt_to_global_shd_bnd_index[node_pt] =
i;
17012 else if (node_name[1]==my_rank)
17015 const unsigned jproc = node_name[0];
17018 std::map<Vector<unsigned>,
unsigned>::iterator it =
17019 node_name_to_global_index.find(node_name);
17020 if (it!=node_name_to_global_index.end())
17024 if (
i!=(*it).second)
17026 std::ostringstream error_message;
17028 <<
"The global node number "<<(*it).second
17029 <<
") obtained from the current node\n" 17030 <<
"name is not the same as the current node number (" 17033 <<
"iproc:"<<node_name[0]<<
"\n" 17034 <<
"jproc:"<<node_name[1]<<
"\n" 17035 <<
"shd_bnd_id:"<<node_name[2]<<
"\n" 17036 <<
"index:"<<node_name[3]<<
"\n\n";
17038 OOMPH_CURRENT_FUNCTION,
17039 OOMPH_EXCEPTION_LOCATION);
17045 std::ostringstream error_message;
17047 <<
"The node name is not registerd as living in this processor.\n" 17049 <<
"iproc:"<<node_name[0]<<
"\n" 17050 <<
"jproc:"<<node_name[1]<<
"\n" 17051 <<
"shd_bnd_id:"<<node_name[2]<<
"\n" 17052 <<
"index:"<<node_name[3]<<
"\n\n";
17054 OOMPH_CURRENT_FUNCTION,
17055 OOMPH_EXCEPTION_LOCATION);
17058 #endif // #ifdef PARANOID 17061 Node* node_pt = global_shared_node_pt[
i];
17066 std::ostringstream error_message;
17068 <<
"There is not global shared node within this\n" 17069 <<
"global node number ("<<
i<<
"). The global shared\n" 17070 <<
"node pointer is null\n\n";
17072 OOMPH_CURRENT_FUNCTION,
17073 OOMPH_EXCEPTION_LOCATION);
17075 #endif // #ifdef PARANOID 17079 node_on_shd_bnd_pt[jproc].insert(node_pt);
17082 node_pt_to_global_shd_bnd_index[node_pt] =
i;
17109 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17112 std::set<Node*> nodes_shared_pt = node_on_shd_bnd_pt[iproc];
17115 for (std::set<Node*>::iterator it = nodes_shared_pt.begin();
17116 it!=nodes_shared_pt.end(); it++)
17119 Node* node_pt = (*it);
17126 const unsigned n_bnd=this->initial_shared_boundary_id();
17129 for (
unsigned bb = 0; bb < n_bnd; bb++)
17135 on_original_boundaries.push_back(bb);
17140 zeta_coordinate.push_back(zeta[0]);
17146 if (on_original_boundaries.size()>0)
17149 std::map<Node*,unsigned>::iterator it_index =
17150 node_pt_to_global_shd_bnd_index.find(node_pt);
17152 if (it_index==node_pt_to_global_shd_bnd_index.end())
17154 std::ostringstream error_message;
17156 <<
"We could not find the global shared node index associated\n" 17157 <<
"with the node pointer with vertices coordinates:\n" 17158 <<
"("<<node_pt->
x(0)<<
", "<<node_pt->
x(1)<<
")\n\n";
17160 OOMPH_CURRENT_FUNCTION,
17161 OOMPH_EXCEPTION_LOCATION);
17165 const unsigned global_shared_node_number = (*it_index).second;
17167 global_node_on_shared_bound[iproc].push_back(global_shared_node_number);
17169 global_node_original_boundaries[iproc].
17170 push_back(on_original_boundaries);
17172 global_node_zeta_coordinate[iproc].push_back(zeta_coordinate);
17196 MPI_Request request;
17199 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17202 const unsigned n_shd_nodes_my_rank_iproc =
17203 node_on_shd_bnd_pt[iproc].size();
17207 if (n_shd_nodes_my_rank_iproc > 0 && iproc != my_rank)
17213 flat_package_unsigned_send.push_back(n_shd_nodes_my_rank_iproc);
17216 const unsigned n_global_shared_node_on_original_boundary =
17217 global_node_on_shared_bound[iproc].size();
17221 flat_package_unsigned_send.
17222 push_back(n_global_shared_node_on_original_boundary);
17229 for (
unsigned i = 0;
i < n_global_shared_node_on_original_boundary;
i++)
17232 const unsigned global_shared_node_index =
17233 global_node_on_shared_bound[iproc][
i];
17237 flat_package_unsigned_send.push_back(global_shared_node_index);
17241 global_node_original_boundaries[iproc][
i];
17245 global_node_zeta_coordinate[iproc][
i];
17249 const unsigned n_original_boundaries =
17250 on_original_boundaries.size();
17254 flat_package_unsigned_send.push_back(n_original_boundaries);
17258 for (
unsigned j = 0; j < n_original_boundaries; j++)
17262 flat_package_unsigned_send.push_back(on_original_boundaries[j]);
17264 flat_package_double_send.push_back(zeta_coordinate[j]);
17272 const unsigned n_udata_send = flat_package_unsigned_send.size();
17273 int n_udata_send_int = n_udata_send;
17276 MPI_Isend(&n_udata_send_int,1,MPI_UNSIGNED,
17277 iproc,1,comm_pt->mpi_comm(), &request);
17279 int n_udata_received_int = 0;
17280 MPI_Recv(&n_udata_received_int,1,MPI_UNSIGNED,
17281 iproc,1,comm_pt->mpi_comm(),&status);
17282 MPI_Wait(&request,MPI_STATUS_IGNORE);
17284 if (n_udata_send!=0)
17286 MPI_Isend(&flat_package_unsigned_send[0],
17287 n_udata_send,MPI_UNSIGNED,
17288 iproc,2,comm_pt->mpi_comm(),&request);
17291 const unsigned n_udata_received =
17292 static_cast<unsigned>(n_udata_received_int);
17297 if (n_udata_received!=0)
17299 MPI_Recv(&flat_package_unsigned_receive[0],
17300 n_udata_received,MPI_UNSIGNED,
17301 iproc,2,comm_pt->mpi_comm(),&status);
17304 if (n_udata_send!=0)
17306 MPI_Wait(&request,MPI_STATUS_IGNORE);
17312 const unsigned n_ddata_send = flat_package_double_send.size();
17313 int n_ddata_send_int = n_ddata_send;
17316 MPI_Isend(&n_ddata_send_int,1,MPI_UNSIGNED,
17317 iproc,1,comm_pt->mpi_comm(), &request);
17319 int n_ddata_received_int = 0;
17320 MPI_Recv(&n_ddata_received_int,1,MPI_UNSIGNED,
17321 iproc,1,comm_pt->mpi_comm(),&status);
17322 MPI_Wait(&request,MPI_STATUS_IGNORE);
17324 if (n_ddata_send!=0)
17326 MPI_Isend(&flat_package_double_send[0],
17327 n_ddata_send,MPI_DOUBLE,
17328 iproc,2,comm_pt->mpi_comm(),&request);
17331 const unsigned n_ddata_received =
17332 static_cast<unsigned>(n_ddata_received_int);
17337 if (n_ddata_received!=0)
17339 MPI_Recv(&flat_package_double_receive[0],
17340 n_ddata_received,MPI_DOUBLE,
17341 iproc,2,comm_pt->mpi_comm(),&status);
17344 if (n_ddata_send!=0)
17346 MPI_Wait(&request,MPI_STATUS_IGNORE);
17354 unsigned n_shared_nodes_received = flat_package_unsigned_receive[0];
17358 n_shared_nodes_received++;
17359 n_shared_nodes_received--;
17362 if (n_shd_nodes_my_rank_iproc != n_shared_nodes_received)
17364 std::ostringstream error_message;
17366 <<
"The number of shared nodes between the pair of processors is\n" 17368 <<
"N.shared nodes proc ("<<my_rank<<
") with proc ("<<iproc<<
"): (" 17369 <<n_shd_nodes_my_rank_iproc<<
"\n" 17370 <<
"N.shared nodes proc ("<<iproc<<
") with proc ("<<my_rank<<
"): (" 17371 <<n_shared_nodes_received<<
"\n\n" 17372 <<
"You should have got the same error in proc: ("<<iproc<<
")\n\n";
17374 OOMPH_CURRENT_FUNCTION,
17375 OOMPH_EXCEPTION_LOCATION);
17388 unsigned current_index_data = 2;
17389 unsigned current_index_ddata = 0;
17390 while(current_index_data < n_udata_received)
17393 const unsigned global_shared_node_index =
17394 flat_package_unsigned_receive[current_index_data++];
17401 const unsigned n_original_boundaries =
17402 flat_package_unsigned_receive[current_index_data++];
17405 node_pt = global_shared_node_pt[global_shared_node_index];
17409 std::ostringstream error_message;
17411 <<
"The global shared node ("<<global_shared_node_index<<
") " 17412 <<
"could not be found in this processor!!!\n" 17413 <<
"However, it was found in processor ("<<iproc<<
"). The " 17414 <<
"data may be no synchronised,\ntherefore " 17415 <<
"we may be looking for a global shared node number that " 17416 <<
"do not\ncorrespond with the one that was sent by " 17417 <<
"processor ("<<iproc<<
")\n\n";
17419 OOMPH_CURRENT_FUNCTION,
17420 OOMPH_EXCEPTION_LOCATION);
17422 #endif // #ifdef PARANOID 17426 for (
unsigned i = 0;
i < n_original_boundaries;
i++)
17430 const unsigned original_bound_id =
17431 flat_package_unsigned_receive[current_index_data++];
17434 this->add_boundary_node(original_bound_id, node_pt);
17438 zeta[0] = flat_package_double_receive[current_index_ddata++];
17462 template <
class ELEMENT>
17465 &other_proc_shd_bnd_node_pt,
17472 const unsigned nproc = this->communicator_pt()->nproc();
17473 const unsigned my_rank = this->communicator_pt()->my_rank();
17481 std::map<Node*, bool> is_global_shared_node;
17482 std::map<Node*, unsigned> global_shared_node_index;
17485 const unsigned n_global_shared_nodes = global_shared_node_pt.size();
17487 for (
unsigned i = 0;
i < n_global_shared_nodes;
i++)
17490 Node* node_pt = global_shared_node_pt[
i];
17492 is_global_shared_node[node_pt] =
true;
17494 global_shared_node_index[node_pt] =
i;
17517 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17519 if (iproc!=my_rank)
17523 this->root_haloed_element_pt(iproc);
17526 const unsigned n_haloed_ele =
17527 this->nroot_haloed_element(iproc);
17530 for (
unsigned ihd = 0; ihd < n_haloed_ele; ihd++)
17537 const unsigned n_nodes = ele_pt->
nnode();
17539 for (
unsigned n = 0; n < n_nodes; n++)
17544 if (is_global_shared_node[node_pt])
17547 const unsigned global_index = global_shared_node_index[node_pt];
17550 global_node_names[global_index];
17553 const unsigned n_names = iglobal_names.size();
17557 for (
unsigned j = 0; j < n_names; j++)
17561 const unsigned proc1 = iglobal_names[j][0];
17562 const unsigned proc2 = iglobal_names[j][1];
17565 additional_elements_pt[proc1].insert(gele_pt);
17566 additional_elements_pt[proc2].insert(gele_pt);
17589 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17591 if (iproc!=my_rank)
17595 std::set<GeneralisedElement*> iproc_ele_pt =
17596 additional_elements_pt[iproc];
17599 for (std::set<GeneralisedElement*>::iterator it =
17600 iproc_ele_pt.begin(); it!=iproc_ele_pt.end(); it++)
17607 this->root_haloed_element_pt(iproc);
17610 const unsigned n_haloed_ele = this->nroot_haloed_element(iproc);
17614 bool send_ele_to_iproc_processor =
true;
17619 for (
unsigned ihd = 0; ihd < n_haloed_ele; ihd++)
17623 if (gele_pt == ghd_ele_pt)
17626 send_ele_to_iproc_processor =
false;
17635 if (send_ele_to_iproc_processor)
17641 send_haloed_ele_pt[iproc].push_back(ele_pt);
17663 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17666 if (iproc != my_rank)
17669 const unsigned n_additional_haloed_ele =
17670 send_haloed_ele_pt[iproc].size();
17675 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 17683 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 17684 std::stringstream junk;
17685 junk <<
"Number of haloed elements " << nhaloed_ele;
17690 for (
unsigned e = 0;
e < n_additional_haloed_ele;
e++)
17694 const unsigned nroot_haloed_ele =
17695 this->nroot_haloed_element(iproc);
17703 const unsigned haloed_ele_index =
17704 this->try_to_add_root_haloed_element_pt(iproc, gen_ele_pt);
17708 if (nroot_haloed_ele == haloed_ele_index)
17711 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 17716 get_required_elemental_information_helper(iproc, ele_pt);
17719 const unsigned nnodes = ele_pt->
nnode();
17720 for (
unsigned j = 0; j < nnodes; j++)
17726 add_haloed_node_helper(iproc, node_pt);
17734 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 17738 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 17749 int send_proc =
static_cast<int>(iproc);
17751 int recv_proc =
static_cast<int>(iproc);
17752 send_and_receive_elements_nodes_info(send_proc, recv_proc);
17759 const unsigned n_additional_halo_ele =
17762 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 17764 <<
" Number of elements need to be constructed " 17770 for (
unsigned e = 0;
e < n_additional_halo_ele;
e++)
17774 create_halo_element(iproc,
17775 iproc_currently_created_nodes_pt[iproc],
17776 other_proc_shd_bnd_node_pt,
17778 node_name_to_global_index,
17779 global_shared_node_pt);
17798 template<
class ELEMENT>
17804 const unsigned nbound = this->initial_shared_boundary_id();
17812 unsigned counter_face_indexes = 0;
17814 for (
unsigned b = 0; b < nbound; b++)
17817 const unsigned nboundary_ele = nboundary_element(b);
17818 for (
unsigned e = 0;
e < nboundary_ele;
e++)
17820 if (ele_pt == this->boundary_element_pt(b,
e))
17823 associated_boundaries.push_back(b);
17825 face_index_on_boundary.push_back(face_index_at_boundary(b,
e));
17826 counter_face_indexes++;
17828 if (counter_face_indexes > 2)
17830 std::stringstream error_message;
17832 <<
"A triangular element can not have more than two of its faces " 17833 <<
"on a boundary!!!\n\n";
17835 OOMPH_CURRENT_FUNCTION,
17836 OOMPH_EXCEPTION_LOCATION);
17840 if (counter_face_indexes==2) {
break;}
17841 #endif // #ifdef PARANOID 17851 const unsigned nassociated_boundaries = associated_boundaries.size();
17852 if (nassociated_boundaries > 0)
17855 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 17859 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 17860 std::stringstream junk;
17861 junk <<
"The elements is associated to " << nassociated_boundaries <<
" boundaries";
17869 for (
unsigned i = 0;
i < nassociated_boundaries;
i++)
17871 unsigned b = associated_boundaries[
i];
17873 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 17874 std::stringstream junk;
17875 junk <<
"Element associated to boundary " << b <<
" of " << nassociated_boundaries <<
" total associated boundaries";
17878 unsigned f = face_index_on_boundary[
i];
17880 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 17881 std::stringstream junk2;
17882 junk2 <<
"Face index " << f <<
" for associated boundary " << b;
17897 const unsigned n_regions = this->nregion();
17902 unsigned counter_face_indexes_in_regions = 0;
17904 for (
unsigned b = 0; b < nbound; b++)
17907 for (
unsigned i_reg = 0 ; i_reg < n_regions; i_reg++)
17910 const unsigned region_id =
17911 static_cast<unsigned>(this->Region_attribute[i_reg]);
17916 const unsigned nele_in_region =
17917 this->nboundary_element_in_region(b, region_id);
17918 for (
unsigned ee = 0; ee < nele_in_region; ee++)
17923 this->boundary_element_in_region_pt(b, region_id, ee))
17930 bound_and_region[0] = b;
17932 bound_and_region[1] = region_id;
17935 associated_boundaries_and_regions.push_back(bound_and_region);
17937 face_index_on_boundary_and_region.push_back(
17938 this->face_index_at_boundary_in_region(b,region_id,ee));
17942 counter_face_indexes_in_regions++;
17945 if (counter_face_indexes_in_regions > 2)
17947 std::stringstream error_message;
17949 <<
"A triangular element can not have more than two of its\n" 17950 <<
"faces on a boundary!!!\n\n";
17952 OOMPH_CURRENT_FUNCTION,
17953 OOMPH_EXCEPTION_LOCATION);
17968 const unsigned nassociated_boundaries_and_regions =
17969 associated_boundaries_and_regions.size();
17970 if (nassociated_boundaries_and_regions > 0)
17973 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 17978 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 17979 std::stringstream junk;
17980 junk <<
"The element is associated to " << nassociated_boundaries_and_regions <<
" boundaries-regions";
17988 for (
unsigned i = 0;
i < nassociated_boundaries_and_regions;
i++)
17990 const unsigned b = associated_boundaries_and_regions[
i][0];
17992 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 17993 std::stringstream junk;
17994 junk <<
"Element associated to boundary " << b <<
" of " << nassociated_boundaries_and_regions <<
" total associated boundaries-regions";
17998 const unsigned r = associated_boundaries_and_regions[
i][1];
18000 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18001 std::stringstream junk2;
18002 junk2 <<
"Element associated to region " << r <<
" of " << nassociated_boundaries_and_regions <<
" total associated boundaries-regions";
18006 const unsigned f = face_index_on_boundary_and_region[
i];
18008 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18009 std::stringstream junk3;
18010 junk3 <<
"Face index " << f <<
" for associated boundary-region (" << b <<
"-" << r <<
")";
18018 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18027 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18042 this->shared_boundaries_in_this_processor(my_rank_shared_boundaries_ids);
18045 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
18047 for (
unsigned i = 0;
i < nmy_rank_shd_bnd;
i++)
18050 const unsigned sb = my_rank_shared_boundaries_ids[
i];
18053 const unsigned nboundary_ele = this->nshared_boundary_element(sb);
18054 for (
unsigned e = 0;
e < nboundary_ele;
e++)
18056 if (ele_pt == this->shared_boundary_element_pt(sb,
e))
18059 associated_shared_boundaries.push_back(sb);
18061 face_index_on_shared_boundary.push_back(
18062 this->face_index_at_shared_boundary(sb,
e));
18069 const unsigned nassociated_shared_boundaries =
18070 associated_shared_boundaries.size();
18071 if (nassociated_shared_boundaries > 0)
18074 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18078 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18079 std::stringstream junk;
18080 junk <<
"The elements is associated to " << nassociated_shared_boundaries <<
"shared boundaries";
18085 for (
unsigned i = 0;
i < nassociated_shared_boundaries;
i++)
18087 const unsigned b = associated_shared_boundaries[
i];
18089 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18090 std::stringstream junk;
18091 junk <<
"Element associated to shared boundary " << b <<
" of " << nassociated_shared_boundaries <<
" total associated boundaries";
18095 const unsigned f = face_index_on_shared_boundary[
i];
18097 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18098 std::stringstream junk2;
18099 junk2 <<
"Face index " << f <<
" for associated shared boundary " << b;
18107 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18119 template<
class ELEMENT>
18124 unsigned my_rank = this->communicator_pt()->my_rank();
18125 const unsigned nproc = this->communicator_pt()->nproc();
18130 unsigned n_val=nod_pt->
nvalue();
18132 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18136 unsigned n_dim=nod_pt->
ndim();
18140 if (this->Time_stepper_pt!=0)
18143 n_prev=this->Time_stepper_pt->ntstorage();
18152 const unsigned n_bnd = this->initial_shared_boundary_id();
18153 for (
unsigned bb=0;bb<n_bnd;bb++)
18158 original_boundaries.push_back(bb);
18163 const unsigned n_original_boundaries = original_boundaries.size();
18165 if (n_original_boundaries > 0)
18169 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18174 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18175 std::stringstream junk;
18176 junk <<
"Node is on "<< n_original_boundaries <<
" original boundaries";
18181 for (
unsigned i=0;
i<n_original_boundaries;
i++)
18184 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18185 std::stringstream junk;
18186 junk<<
"Node is on boundary "<<original_boundaries[
i]<<
" of "<< nb;
18199 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18206 bool node_on_shared_boundary =
false;
18209 const unsigned n_shd_bnd = this->nshared_boundaries(my_rank, iproc);
18210 for (
unsigned bb=0;bb<n_shd_bnd;bb++)
18213 unsigned i_bnd = this->shared_boundaries_ids(my_rank, iproc, bb);
18215 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
18217 node_on_shared_boundary =
true;
18225 if (node_on_shared_boundary)
18228 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18235 for (
unsigned bb = 0; bb < n_shd_bnd; bb++)
18238 const unsigned i_bnd =
18239 this->shared_boundaries_ids(my_rank, iproc, bb);
18241 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
18243 shd_boundaries.push_back(i_bnd);
18248 const unsigned n_shd_bnd_is_on = shd_boundaries.size();
18251 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18252 std::stringstream junk;
18253 junk <<
"Node is on "<< n_shd_bnd_is_on <<
" shared boundaries";
18258 for (
unsigned i=0;
i<n_shd_bnd_is_on;
i++)
18261 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18262 std::stringstream junk;
18263 junk <<
"Node is on boundary " << shd_boundaries[
i] <<
" of " << nb;
18270 unsigned shared_boundary_id = shd_boundaries[0];
18272 const unsigned n_nodes_on_shared_boundary =
18273 nsorted_shared_boundary_node(shared_boundary_id);
18275 unsigned index_node_on_shared_boundary;
18278 bool found_index_node_on_shared_boundary =
false;
18281 for (
unsigned i = 0;
i < n_nodes_on_shared_boundary;
i++)
18284 Node* shared_node_pt =
18285 sorted_shared_boundary_node_pt(shared_boundary_id,
i);
18287 if (shared_node_pt == nod_pt)
18290 index_node_on_shared_boundary =
i;
18293 found_index_node_on_shared_boundary =
true;
18301 if (!found_index_node_on_shared_boundary)
18303 std::ostringstream error_message;
18305 <<
"The index of the node on boundary (" 18306 <<shared_boundary_id<<
") was not found.\n" 18307 <<
"The node coordinates are ("<<nod_pt->
x(0)<<
"," 18308 <<nod_pt->
x(1)<<
").\n";
18310 error_message.str(),
18311 "RefineableTriangleMesh::get_required_nodal_information_helper()",
18312 OOMPH_EXCEPTION_LOCATION);
18317 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18318 std::stringstream junk2;
18319 junk2 <<
"Node index on boundary "<<boundaries[0]<<
" is " 18320 <<index_node_on_shared_boundary;
18329 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18345 bool node_on_shared_boundary_with_other_processors =
false;
18347 unsigned nshared_boundaries_with_other_processors_have_node = 0;
18351 for (
unsigned jproc = 0; jproc < nproc; jproc++)
18355 if (jproc != iproc)
18358 const unsigned n_jshd_bnd =
18359 this->nshared_boundaries(my_rank, jproc);
18361 for (
unsigned bb=0;bb<n_jshd_bnd;bb++)
18364 const unsigned j_shd_bnd =
18365 this->shared_boundaries_ids(my_rank, jproc, bb);
18367 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
18375 node_on_shared_boundary_with_other_processors =
true;
18378 nshared_boundaries_with_other_processors_have_node++;
18389 if (node_on_shared_boundary_with_other_processors)
18392 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18400 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18401 std::stringstream junk;
18402 junk <<
"Number of other shared boundaries that the node is on: " 18403 << nshared_boundaries_with_other_processors_have_node;
18408 unsigned counter_shd_bnd_with_other_procs_have_node = 0;
18418 for (
unsigned jproc = 0; jproc < nproc; jproc++)
18422 if (jproc != iproc)
18426 const unsigned n_jshd_bnd =
18427 this->nshared_boundaries(my_rank, jproc);
18428 for (
unsigned bb = 0; bb < n_jshd_bnd; bb++)
18431 const unsigned j_shd_bnd =
18432 this->shared_boundaries_ids(my_rank, jproc, bb);
18434 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
18437 other_processor_1.push_back(my_rank);
18439 other_processor_2.push_back(jproc);
18441 shd_bnd_ids.push_back(j_shd_bnd);
18444 counter_shd_bnd_with_other_procs_have_node++;
18455 const unsigned n_other_processors = other_processor_1.size();
18457 for (
unsigned i = 0;
i < n_other_processors;
i++)
18460 unsigned shd_bnd_id = shd_bnd_ids[
i];
18462 const unsigned n_nodes_on_shd_bnd =
18463 nsorted_shared_boundary_node(shd_bnd_id);
18466 bool found_index_node_on_shared_boundary =
false;
18468 for (
unsigned i = 0;
i < n_nodes_on_shd_bnd;
i++)
18471 Node* shared_node_pt =
18472 sorted_shared_boundary_node_pt(shd_bnd_id,
i);
18474 if (shared_node_pt == nod_pt)
18480 indexes.push_back(
i);
18483 found_index_node_on_shared_boundary =
true;
18491 if (!found_index_node_on_shared_boundary)
18493 std::ostringstream error_message;
18495 <<
"The index of the node on boundary (" 18496 <<shd_bnd_id<<
"), shared by other processors\nwas not found.\n" 18497 <<
"The node coordinates are ("<<nod_pt->
x(0)<<
"," 18498 <<nod_pt->
x(1)<<
").\n";
18500 error_message.str(),
18501 "RefineableTriangleMesh::get_required_nodal_information_helper()",
18502 OOMPH_EXCEPTION_LOCATION);
18511 if (counter_shd_bnd_with_other_procs_have_node !=
18512 nshared_boundaries_with_other_processors_have_node)
18514 std::ostringstream error_message;
18516 <<
"The number of shared boundaries where the node is on " 18517 <<
"is different:\n" 18518 <<
"nshared_boundaries_with_other_processors_have_node: (" 18519 << nshared_boundaries_with_other_processors_have_node
18521 <<
"counter_shd_bnd_with_other_procs_have_node: (" 18522 << counter_shd_bnd_with_other_procs_have_node
18525 error_message.str(),
18526 "RefineableTriangleMesh::get_required_nodal_information_helper()",
18527 OOMPH_EXCEPTION_LOCATION);
18533 for (
unsigned i = 0;
i < n_other_processors;
i++)
18536 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18537 std::stringstream junk1;
18538 junk1 <<
"Processor where the other shared boundary " 18539 <<
"has the node: " << other_processor_1[
i];
18544 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18545 std::stringstream junk2;
18546 junk2 <<
"Processor where the other shared boundary " 18547 <<
"has the node: " << other_processor_2[
i];
18552 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18553 std::stringstream junk3;
18554 junk3 <<
"Other shared boundary id where the node is on" 18560 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18561 std::stringstream junk4;
18562 junk4 <<
"Node index on other shared boundary " 18563 <<boundaries[
i] <<
" is " 18574 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18583 if (!node_on_shared_boundary)
18599 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18604 unsigned n_ref_val=alg_nod_pt->
nref_value();
18606 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18609 for (
unsigned i_ref_val=0;i_ref_val<n_ref_val;i_ref_val++)
18617 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18620 for (
unsigned i_geom=0;i_geom<n_geom_obj;i_geom++)
18628 unsigned found_geom_object=0;
18629 for (
unsigned i_list=0;i_list<n_geom_list;i_list++)
18633 found_geom_object=i_list;
18637 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18645 if (solid_nod_pt!=0)
18648 for (
unsigned i_val=0;i_val<n_solid_val;i_val++)
18650 for (
unsigned t=0;
t<n_prev;
t++)
18659 const unsigned nvalues_solid_node = values_solid_node.size();
18661 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18662 std::stringstream junk;
18663 junk <<
"Number of values solid node: " 18664 << nvalues_solid_node;
18667 for (
unsigned i = 0;
i < nvalues_solid_node;
i++)
18674 for (
unsigned i_val=0;i_val<n_val;i_val++)
18676 for (
unsigned t=0;
t<n_prev;
t++)
18683 for (
unsigned idim=0;idim<n_dim;idim++)
18685 for (
unsigned t=0;
t<n_prev;
t++)
18698 template<
class ELEMENT>
18703 const unsigned n_haloed_nod = this->nhaloed_node(iproc);
18704 const unsigned haloed_node_index =
18705 this->try_to_add_haloed_node_pt(iproc,nod_pt);
18708 if (haloed_node_index==n_haloed_nod)
18712 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18713 std::stringstream junk;
18714 junk <<
"Node needs to be constructed [size=" 18728 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18729 std::stringstream junk;
18730 junk <<
"Node was already added [size=" 18740 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18751 template<
class ELEMENT>
18760 MPI_Request request;
18769 MPI_Isend(&send_count_double_values,1,MPI_UNSIGNED,
18770 send_proc,1,comm_pt->mpi_comm(),&request);
18772 int receive_count_double_values=0;
18773 MPI_Recv(&receive_count_double_values,1,MPI_INT,
18774 recv_proc,1,comm_pt->mpi_comm(),&status);
18775 MPI_Wait(&request,MPI_STATUS_IGNORE);
18777 if (send_count_double_values!=0)
18780 send_proc,2,comm_pt->mpi_comm(),&request);
18782 if (receive_count_double_values!=0)
18784 received_double_values.resize(receive_count_double_values);
18785 MPI_Recv(&received_double_values[0],receive_count_double_values,
18786 MPI_DOUBLE,recv_proc,2,comm_pt->mpi_comm(),&status);
18788 if (send_count_double_values!=0)
18790 MPI_Wait(&request,MPI_STATUS_IGNORE);
18796 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18799 if (send_count_unsigned_string != send_count_unsigned_values)
18801 std::ostringstream error_message;
18803 <<
"The number of unsigned values to send to processor (" 18804 << send_proc <<
") is different from the\nnumber of annotated strings " 18805 <<
"for the communication\n\n";
18807 OOMPH_CURRENT_FUNCTION,
18808 OOMPH_EXCEPTION_LOCATION);
18810 #endif // #ifdef PARANOID 18812 MPI_Isend(&send_count_unsigned_values,1,MPI_UNSIGNED,
18813 send_proc,14,comm_pt->mpi_comm(),&request);
18815 int receive_count_unsigned_values=0;
18816 MPI_Recv(&receive_count_unsigned_values,1,MPI_INT,recv_proc,14,
18817 comm_pt->mpi_comm(),&status);
18819 MPI_Wait(&request,MPI_STATUS_IGNORE);
18821 if (send_count_unsigned_values!=0)
18824 MPI_UNSIGNED,send_proc,15,comm_pt->mpi_comm(),&request);
18825 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18826 for (
unsigned i=0;
i<send_count_unsigned_values;
i++)
18828 oomph_info <<
"Sent:" <<
i <<
" to orig_proc:" << send_proc
18834 if (receive_count_unsigned_values!=0)
18836 received_unsigned_values.resize(receive_count_unsigned_values);
18837 MPI_Recv(&received_unsigned_values[0],receive_count_unsigned_values,
18838 MPI_UNSIGNED,recv_proc,15,comm_pt->mpi_comm(),&status);
18841 if (send_count_unsigned_values!=0)
18843 MPI_Wait(&request,MPI_STATUS_IGNORE);
18853 for (
int ii=0;ii<receive_count_double_values;ii++)
18858 for (
int ii=0;ii<receive_count_unsigned_values;ii++)
18869 template<
class ELEMENT>
18874 &other_proc_shd_bnd_node_pt,
18876 &global_node_names,
18878 &node_name_to_global_index,
18881 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18883 <<
" Bool: New element needs to be constructed " 18895 this->add_element_pt(new_el_pt);
18898 this->add_root_halo_element_pt(iproc, new_el_pt);
18904 this->add_halo_element_helper(iproc,f_el_pt);
18907 unsigned n_node=f_el_pt->
nnode();
18909 for (
unsigned j=0;j<n_node;j++)
18911 Node* new_nod_pt=0;
18914 add_halo_node_helper(new_nod_pt,
18915 new_nodes_on_domain,
18916 other_proc_shd_bnd_node_pt,
18919 node_name_to_global_index,
18920 global_shared_node_pt);
18927 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18930 <<
" Index of existing halo element " 18935 unsigned halo_ele_index=
18940 dynamic_cast<FiniteElement*
>(this->root_halo_element_pt(iproc,
18946 throw OomphLibError(
"Halo element is not a FiniteElement\n",
18947 OOMPH_CURRENT_FUNCTION,
18948 OOMPH_EXCEPTION_LOCATION);
18961 template<
class ELEMENT>
18965 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18967 <<
" Bool: Element is associated to an original boundary " 18974 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18977 <<
" How many boundaries are associated with the element " 18981 const unsigned nassociated_boundaries =
18984 for (
unsigned b = 0; b < nassociated_boundaries; b++)
18986 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18989 <<
" Boundary associated to the element " 18993 const unsigned bnd =
18996 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 18999 <<
" Face index of the element " 19003 const unsigned face_index =
19008 this->Boundary_element_pt[bnd].push_back(ele_pt);
19009 this->Face_index_at_boundary[bnd].push_back(face_index);
19014 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19016 <<
" Bool: Element is associated to a boundary-region " 19023 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19026 <<
" How many boundaries-regions are associated with the element " 19030 const unsigned nassociated_boundaries_and_regions =
19033 for (
unsigned br = 0; br < nassociated_boundaries_and_regions; br++)
19035 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19038 <<
" Boundary associated to the element " 19042 const unsigned bnd =
19045 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19048 <<
" Region associated to the element " 19052 const unsigned region =
19055 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19058 <<
" Face index of the element in boundary-region " 19062 const unsigned face_index =
19067 this->Boundary_region_element_pt[bnd][region].push_back(ele_pt);
19068 this->Face_index_region_at_boundary[bnd][region].push_back(face_index);
19077 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19079 <<
" Bool: Element is associated to a shared boundary " 19085 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19088 <<
" How many shared boundaries are associated with the element " 19092 const unsigned nassociated_shared_boundaries =
19095 for (
unsigned b = 0; b < nassociated_shared_boundaries; b++)
19097 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19100 <<
" Shared boundary associated to the element " 19104 const unsigned bnd =
19107 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19110 <<
" Face index of the element associated to the shared boundary " 19115 const unsigned face_index =
19118 this->add_shared_boundary_element(bnd, ele_pt);
19119 this->add_face_index_at_shared_boundary(bnd, face_index);
19130 template<
class ELEMENT>
19135 &other_proc_shd_bnd_node_pt,
19137 unsigned& node_index,
19145 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19147 <<
" Bool: New node needs to be constructed " 19155 construct_new_halo_node_helper(new_nod_pt, new_nodes_on_domain,
19156 other_proc_shd_bnd_node_pt,
19157 iproc, node_index, new_el_pt,
19159 node_name_to_global_index,
19160 global_shared_node_pt);
19164 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19166 <<
" Index of existing halo node " 19172 new_nod_pt = new_nodes_on_domain[
19175 new_el_pt->
node_pt(node_index)=new_nod_pt;
19185 template<
class ELEMENT>
19190 &other_proc_shd_bnd_node_pt,
19191 unsigned& iproc,
unsigned& node_index,
19199 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19201 <<
" Number of values of external halo node " 19208 TimeStepper* time_stepper_pt=this->Time_stepper_pt;
19210 unsigned n_prev=time_stepper_pt->
ntstorage();
19214 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19216 <<
" Is the node on an original boundary " 19222 const unsigned node_on_original_boundaries =
19230 unsigned n_original_boundaries_node_is_on = 0;
19232 if (node_on_original_boundaries==2)
19235 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19237 <<
" Number of boundaries the node is on: " 19241 n_original_boundaries_node_is_on =
19245 original_boundaries_node_is_on.resize(n_original_boundaries_node_is_on);
19246 zeta_coordinates.resize(n_original_boundaries_node_is_on);
19248 for (
unsigned i=0;
i<n_original_boundaries_node_is_on;
i++)
19251 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19253 <<
" Node is on boundary " 19257 original_boundaries_node_is_on[
i] =
19259 zeta_coordinates[
i] =
19267 if (node_on_original_boundaries != 0)
19269 std::ostringstream error_message;
19271 <<
"The current node is not on an original boundary, this should\n" 19272 <<
"be indicated by a zero flag. However, the read value for\n" 19273 <<
"that flag is ("<<node_on_original_boundaries<<
").\n\n";
19275 error_message.str(),
19276 "RefineableTriangleMesh::construct_new_halo_node_helper()",
19277 OOMPH_EXCEPTION_LOCATION);
19285 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19287 <<
" Is node on shared boundary? " 19291 const unsigned is_node_on_shared_boundary =
19293 if (is_node_on_shared_boundary == 1)
19296 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19298 <<
" Number of boundaries the node is on: " 19302 const unsigned n_shd_bnd_node_is_on =
19305 for (
unsigned i=0;
i<n_shd_bnd_node_is_on;
i++)
19308 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19310 <<
" Node is on boundary " 19314 shd_bnds_node_is_on[
i] =
19319 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19321 <<
" Index of node on boundary " 19326 unsigned node_index_on_shared_boundary =
19331 this->sorted_shared_boundary_node_pt(shd_bnds_node_is_on[0],
19332 node_index_on_shared_boundary);
19338 if (is_node_on_shared_boundary != 0)
19340 std::ostringstream error_message;
19342 <<
"The current node is not on a shared boundary, this should\n" 19343 <<
"be indicated by a zero flag. However, the read value for\n" 19344 <<
"that flag is ("<<is_node_on_shared_boundary<<
").\n\n";
19346 error_message.str(),
19347 "RefineableTriangleMesh::construct_new_halo_node_helper()",
19348 OOMPH_EXCEPTION_LOCATION);
19355 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19357 <<
" Is the node on shared boundaries with other processors " 19364 const unsigned is_the_node_in_shared_boundaries_with_other_processors =
19374 unsigned n_shd_bnd_with_other_procs_have_node = 0;
19377 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
19379 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19381 <<
" In how many shared boundaries with other " 19382 <<
"processors is the node " 19388 n_shd_bnd_with_other_procs_have_node =
19392 other_processor_1.resize(n_shd_bnd_with_other_procs_have_node);
19393 other_processor_2.resize(n_shd_bnd_with_other_procs_have_node);
19394 other_shared_boundaries.resize(n_shd_bnd_with_other_procs_have_node);
19395 other_indexes.resize(n_shd_bnd_with_other_procs_have_node);
19397 for (
unsigned i = 0;
i < n_shd_bnd_with_other_procs_have_node;
i++)
19399 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19401 <<
" Processor where the other shared boundary" 19407 other_processor_1[
i] =
19410 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19412 <<
" Processor where the other shared boundary" 19418 other_processor_2[
i] =
19421 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19423 <<
" Other shared boundary id where the node is on: " 19429 other_shared_boundaries[
i] =
19432 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19434 <<
" Node index on the other shared boundary " 19449 if (is_the_node_in_shared_boundaries_with_other_processors != 0)
19451 std::ostringstream error_message;
19453 <<
"The current node is not on a shared boundary with\n" 19454 <<
"other processors, this should be indicated by a zero flag.\n" 19455 <<
"However, the read value for that flag is (" 19456 <<is_the_node_in_shared_boundaries_with_other_processors<<
").\n\n";
19458 error_message.str(),
19459 "RefineableTriangleMesh::construct_new_halo_node_helper()",
19460 OOMPH_EXCEPTION_LOCATION);
19469 if (is_node_on_shared_boundary == 1)
19474 if (node_on_original_boundaries==2)
19480 for (
unsigned i = 0;
i < n_original_boundaries_node_is_on;
i++)
19482 add_boundary_node(original_boundaries_node_is_on[
i], new_nod_pt);
19485 zeta[0] = zeta_coordinates[
i];
19487 original_boundaries_node_is_on[i],zeta);
19493 new_nodes_on_domain.push_back(new_nod_pt);
19496 new_el_pt->
node_pt(node_index) = new_nod_pt;
19506 bool found_node_in_other_shared_boundaries =
false;
19515 bool build_node_as_boundary_node =
false;
19517 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
19520 build_node_as_boundary_node =
true;
19527 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
19533 for (
unsigned i = 0;
i < n_shd_bnd_with_other_procs_have_node;
i++)
19544 unsigned oproc1 = other_processor_1[
i];
19545 unsigned oproc2 = other_processor_2[
i];
19546 if (other_processor_1[
i] > other_processor_2[
i])
19548 oproc1 = other_processor_2[
i];
19549 oproc2 = other_processor_1[
i];
19554 const unsigned shd_bnd_id =
19555 other_shared_boundaries[
i] - initial_shd_bnd_id;
19558 const unsigned index = other_indexes[
i];
19562 const unsigned n_nodes_on_other_processor =
19563 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].size();
19565 if (n_nodes_on_other_processor > 0)
19569 std::map<unsigned, Node*>::iterator it =
19570 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].
19575 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].end())
19578 found_node_in_other_shared_boundaries =
true;
19580 Node* tmp_node_pt = (*it).second;
19583 found_node_pt.push_back(tmp_node_pt);
19594 if (found_node_in_other_shared_boundaries)
19597 const unsigned n_times_node_found = found_node_pt.size();
19598 for (
unsigned j = 1; j < n_times_node_found; j++)
19600 if (found_node_pt[j-1] != found_node_pt[j])
19602 std::ostringstream error_message;
19604 <<
"The instances of the node that was found on\n" 19605 <<
"shared boundaries with other processors (but not\n" 19606 <<
"on shared boundaries with this processor) are not\n" 19608 <<
"These are the coordinates of the instances of the\n" 19610 <<
"(" << found_node_pt[j-1]->x(0) <<
", " 19611 << found_node_pt[j-1]->x(1) <<
")\n" 19612 <<
"(" << found_node_pt[j]->x(0) <<
", " 19613 << found_node_pt[j]->x(1) <<
")\n" 19614 <<
"Dont be surprised if they are the same since the " 19615 <<
"node is\nrepeated.\n";
19617 OOMPH_CURRENT_FUNCTION,
19618 OOMPH_EXCEPTION_LOCATION);
19623 #endif // #ifdef PARANOID 19629 if (is_node_on_shared_boundary == 1)
19638 if (found_node_pt[0] != new_nod_pt)
19640 std::ostringstream error_message;
19642 <<
"The pointer of the node that was found to be on a\n" 19643 <<
"shared boundary with other processor(s) and the pointer\n" 19644 <<
"of the node on shared boundary with the receiver\n" 19645 <<
"processor (iproc) are not the same. This means we have a\n" 19646 <<
"repeated node)\n" 19647 <<
"The coordinates for the nodes are:\n" 19648 <<
"(" << found_node_pt[0]->x(0) <<
", " 19649 << found_node_pt[0]->x(1) <<
")\n" 19650 <<
"(" << new_nod_pt->
x(0) <<
", " 19651 << new_nod_pt->
x(1) <<
")\n" 19652 <<
"Dont be surprised if they are the same since the " 19653 <<
"node is\nrepeated.\n";
19655 OOMPH_CURRENT_FUNCTION,
19656 OOMPH_EXCEPTION_LOCATION);
19667 new_nod_pt = found_node_pt[0];
19678 if (is_node_on_shared_boundary != 1)
19692 if (node_on_original_boundaries==2 || build_node_as_boundary_node)
19696 if (!found_node_in_other_shared_boundaries)
19699 if (time_stepper_pt!=0)
19713 new_el_pt->
node_pt(node_index) = new_nod_pt;
19718 for (
unsigned i = 0;
i < n_original_boundaries_node_is_on;
i++)
19720 add_boundary_node(original_boundaries_node_is_on[
i], new_nod_pt);
19723 zeta[0] = zeta_coordinates[
i];
19725 original_boundaries_node_is_on[i],zeta);
19733 if (!found_node_in_other_shared_boundaries)
19736 if (time_stepper_pt!=0)
19738 new_nod_pt=new_el_pt->
construct_node(node_index, time_stepper_pt);
19748 new_el_pt->
node_pt(node_index) = new_nod_pt;
19759 new_nodes_on_domain.push_back(new_nod_pt);
19763 if (!found_node_in_other_shared_boundaries)
19766 this->add_node_pt(new_nod_pt);
19775 if (new_alg_nod_pt!=0)
19784 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19786 <<
" Alg node update id " 19798 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19800 <<
" Alg node # of ref values " 19809 ref_value.resize(n_ref_val);
19810 for (
unsigned i_ref=0;i_ref<n_ref_val;i_ref++)
19823 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19825 <<
" Alg node # of geom objects " 19834 geom_object_pt.resize(n_geom_obj);
19835 for (
unsigned i_geom=0;i_geom<n_geom_obj;i_geom++)
19837 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19839 <<
" Alg node: geom object index " 19851 geom_object_pt[i_geom]=alg_mesh_pt->
19852 geom_object_list_pt(geom_index);
19857 if (!found_node_in_other_shared_boundaries)
19862 (update_id,alg_mesh_pt,geom_object_pt,ref_value);
19873 if (!found_node_in_other_shared_boundaries)
19879 if (macro_nod_pt!=0)
19889 geom_object_vector_pt=
19895 (node_index,s_in_macro_node_update_element);
19899 (new_el_pt,s_in_macro_node_update_element,
19900 geom_object_vector_pt);
19906 unsigned n_new_val=new_nod_pt->
nvalue();
19910 if (!found_node_in_other_shared_boundaries)
19912 if (n_val>n_new_val)
19928 new std::map<unsigned, unsigned>;
19932 std::map<unsigned, unsigned>* map_pt=
19937 const unsigned id_face = 0;
19939 std::map<unsigned, unsigned>::const_iterator p=map_pt->find(id_face);
19942 if(p==map_pt->end())
19946 (*map_pt)[id_face] = n_new_val;
19949 new_nod_pt->
resize(n_val);
19958 if (solid_nod_pt!=0)
19961 for (
unsigned i_val=0;i_val<n_solid_val;i_val++)
19963 for (
unsigned t=0;
t<n_prev;
t++)
19970 if (!found_node_in_other_shared_boundaries)
19973 set_value(
t, i_val, read_data);
19980 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION 19982 <<
" Number of values solid node: " 19986 const unsigned nvalues_solid_node =
19989 for (
unsigned i = 0;
i < nvalues_solid_node;
i++)
19991 values_solid_node[
i] =
19997 if (!found_node_in_other_shared_boundaries)
19999 unsigned index = 0;
20007 for (
unsigned i_val=0;i_val<n_val;i_val++)
20009 for (
unsigned t=0;
t<n_prev;
t++)
20017 if (!found_node_in_other_shared_boundaries)
20027 unsigned n_dim=new_nod_pt->
ndim();
20028 for (
unsigned idim=0;idim<n_dim;idim++)
20030 for (
unsigned t=0;
t<n_prev;
t++)
20038 if (!found_node_in_other_shared_boundaries)
20041 new_nod_pt->
x(
t,idim) = read_data;
20053 if (n_shd_bnd_with_other_procs_have_node > 0 &&
20057 !found_node_in_other_shared_boundaries)
20065 this->update_other_proc_shd_bnd_node_helper(new_nod_pt,
20066 other_proc_shd_bnd_node_pt,
20069 other_shared_boundaries,
20072 node_name_to_global_index,
20073 global_shared_node_pt);
20083 template<
class ELEMENT>
20088 &other_proc_shd_bnd_node_pt,
20099 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
20104 const unsigned n_data = other_processor_1.size();
20105 #endif // #ifdef PARANOID 20109 node_name[0] = other_processor_1[0];
20110 node_name[1] = other_processor_2[0];
20111 node_name[2] = other_shared_boundaries[0];
20112 node_name[3] = other_indexes[0];
20116 std::map<Vector<unsigned>,
unsigned>::iterator it =
20117 node_name_to_global_index.find(node_name);
20118 if (it==node_name_to_global_index.end())
20120 std::ostringstream error_stream;
20122 <<
"The node name does not exist in the global node names\n" 20123 <<
"This is the name of the node\n" 20124 <<
"Name: iproc, jproc, ishd_bnd, idx\n" 20125 <<
"Name: " << node_name[0] <<
", " << node_name[1] <<
", " 20126 << node_name[2] <<
", " << node_name[3] <<
"\n";
20128 OOMPH_CURRENT_FUNCTION,
20129 OOMPH_EXCEPTION_LOCATION);
20131 #endif // #ifdef PARANOID 20134 const unsigned iglobal_node = node_name_to_global_index[node_name];
20136 global_shared_node_pt[iglobal_node] = new_node_pt;
20140 const unsigned n_names = inode_names.size();
20145 unsigned n_found_node_names_on_global_node_name = 0;
20147 for (
unsigned j = 0; j < n_data; j++)
20150 for (
unsigned k = 0; k < n_names; k++)
20153 if (inode_names[k][0] == other_processor_1[j] &&
20154 inode_names[k][1] == other_processor_2[j] &&
20155 inode_names[k][2] == other_shared_boundaries[j] &&
20156 inode_names[k][3] == other_indexes[j])
20160 n_found_node_names_on_global_node_name++;
20168 if (n_found_node_names_on_global_node_name != n_data)
20170 std::ostringstream error_stream;
20172 <<
"Not all the node names of the current node were found on the\n" 20173 <<
"global node names. This happened when adding the node pointer\n" 20174 <<
"to the data structure that keeps tracks of nodes on shared\n" 20175 <<
"boundaries with other processors\n\n" 20176 <<
"These are the names of the current node\n" 20177 <<
"Name k: iproc, jproc, ishd_bnd, idx\n";
20178 for (
unsigned j = 0; j < n_data; j++)
20180 error_stream<<
"Name("<<j<<
"): " 20181 <<other_processor_1[j] <<
", " 20182 <<other_processor_2[j] <<
", " 20183 <<other_shared_boundaries[j] <<
", " 20184 <<other_indexes[j] <<
"\n";
20188 <<
"\n\nThese are the names of the global node\n" 20189 <<
"Name k: iproc, jproc, ishd_bnd, idx\n";
20190 for (
unsigned k = 0; k < n_names; k++)
20192 error_stream<<
"Name("<<k<<
"): " 20193 <<inode_names[k][0] <<
", " 20194 <<inode_names[k][1] <<
", " 20195 <<inode_names[k][2] <<
", " 20196 <<inode_names[k][3] <<
"\n";
20200 OOMPH_CURRENT_FUNCTION,
20201 OOMPH_EXCEPTION_LOCATION);
20203 #endif // #ifdef PARANOID 20206 for (
unsigned j = 0; j < n_names; j++)
20209 const unsigned iproc = inode_names[j][0];
20210 const unsigned jproc = inode_names[j][1];
20211 const unsigned ishd_bnd = inode_names[j][2] - initial_shd_bnd_id;
20212 const unsigned index = inode_names[j][3];
20218 other_proc_shd_bnd_node_pt[iproc][jproc][ishd_bnd][index]
20223 other_proc_shd_bnd_node_pt[jproc][iproc][ishd_bnd][index]
20243 template <
class ELEMENT>
20246 target_domain_for_local_non_halo_element)
20248 oomph_info <<
"Load balance (unstructured mesh) [BEGIN]" << std::endl;
20252 if (!this->is_mesh_distributed())
20254 std::ostringstream warning_message;
20256 <<
"\n===============================================================\n" 20257 <<
"The load balancing can only be performed in distributed meshes,\n" 20258 <<
"your mesh has not been distributed.\n" 20259 <<
"===============================================================\n\n";
20261 OOMPH_CURRENT_FUNCTION,
20262 OOMPH_EXCEPTION_LOCATION);
20268 const unsigned nproc = this->communicator_pt()->nproc();
20270 const unsigned my_rank = this->communicator_pt()->my_rank();
20275 std::ostringstream warning_message;
20277 <<
"\n===============================================================\n" 20278 <<
"The load balancing can only be performed when there are at least\n" 20279 <<
"two procesors, the current number of processors is one.\n" 20280 <<
"===============================================================\n\n";
20282 OOMPH_CURRENT_FUNCTION,
20283 OOMPH_EXCEPTION_LOCATION);
20289 double t_start_overall_load_balance=0.0;
20290 if (Print_timings_level_load_balance>1)
20296 const unsigned nelement_before_load_balance = this->nelement();
20301 if (nnon_halo_element() !=
20302 target_domain_for_local_non_halo_element.size())
20304 std::ostringstream error_message;
20306 <<
"The number of non halo elements in the current mesh (" 20307 << nnon_halo_element() <<
") and the number\n" 20308 <<
"of target areas for the local non halo elements (" 20309 << target_domain_for_local_non_halo_element.size()
20310 <<
") is different\n\n";
20312 OOMPH_CURRENT_FUNCTION,
20313 OOMPH_EXCEPTION_LOCATION);
20319 for (
unsigned e = 0;
e < nelement_before_load_balance;
e++)
20321 backed_up_ele_pt[
e] = this->finite_element_pt(
e);
20329 double tt_start_get_domains_halo_elements=0.0;
20330 if (Print_timings_level_load_balance>1)
20353 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20357 if (iproc != my_rank)
20360 const unsigned n_halo_iproc = this->nroot_halo_element(iproc);
20362 new_domains_halo_elements[iproc].resize(n_halo_iproc);
20365 const unsigned n_haloed_iproc = this->nroot_haloed_element(iproc);
20367 new_domains_haloed_elements[iproc].resize(n_haloed_iproc);
20380 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20384 if (iproc != my_rank)
20387 const unsigned n_haloed_iproc = this->nroot_haloed_element(iproc);
20390 for (
unsigned ihd = 0; ihd < n_haloed_iproc; ihd++)
20394 this->root_haloed_element_pt(iproc, ihd);
20397 unsigned nh_count4 = 0;
20399 for (
unsigned e = 0;
e < nelement_before_load_balance;
e++)
20411 if (ele_pt == haloed_ele_pt)
20414 const unsigned element_domain =
20415 target_domain_for_local_non_halo_element[nh_count4-1];
20420 new_domains_haloed_elements[iproc][ihd] = element_domain;
20423 counter_for_found_haloed_elements[iproc]++;
20444 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20448 if (iproc != my_rank)
20451 const unsigned n_haloed_iproc = this->nroot_haloed_element(iproc);
20455 if (n_haloed_iproc != counter_for_found_haloed_elements[iproc])
20457 std::ostringstream error_message;
20459 <<
"The independent counting of found haloed elements (" 20460 << counter_for_found_haloed_elements[iproc] <<
") with processor (" 20461 << iproc <<
") is not equal to the number of haloed elements (" 20462 << n_haloed_iproc <<
") with processor (" << iproc <<
")\n";
20464 OOMPH_CURRENT_FUNCTION,
20465 OOMPH_EXCEPTION_LOCATION);
20483 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20487 if (iproc != my_rank)
20490 const unsigned n_haloed_ele_iproc = this->nroot_haloed_element(iproc);
20492 nhaloed_elements_with_iproc[iproc] = n_haloed_ele_iproc;
20495 for (
unsigned i = 0;
i < n_haloed_ele_iproc;
i++)
20497 new_domains_haloed_flat_unsigned.push_back(
20498 new_domains_haloed_elements[iproc][
i]);
20506 Vector<int> offset_haloed_elements_with_iproc(nproc);
20507 offset_haloed_elements_with_iproc[0] = 0;
20508 for (
unsigned ip = 1; ip < nproc; ip++)
20511 offset_haloed_elements_with_iproc[ip] =
20512 offset_haloed_elements_with_iproc[ip-1] +
20513 nhaloed_elements_with_iproc[ip-1];
20522 unsigned counter_halo_ele_with_all_procs = 0;
20529 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20533 if (iproc != my_rank)
20536 const unsigned n_halo_ele_iproc = this->nroot_halo_element(iproc);
20538 nhalo_elements_with_iproc[iproc] = n_halo_ele_iproc;
20540 counter_halo_ele_with_all_procs+= n_halo_ele_iproc;
20546 Vector<int> offset_halo_elements_with_iproc(nproc);
20547 offset_halo_elements_with_iproc[0] = 0;
20548 for (
unsigned ip = 1; ip < nproc; ip++)
20551 offset_halo_elements_with_iproc[ip] =
20552 offset_halo_elements_with_iproc[ip-1] +
20553 nhalo_elements_with_iproc[ip-1];
20562 new_domains_halo_flat_unsigned(counter_halo_ele_with_all_procs);
20566 MPI_Alltoallv(&new_domains_haloed_flat_unsigned[0],
20567 &nhaloed_elements_with_iproc[0],
20568 &offset_haloed_elements_with_iproc[0],
20570 &new_domains_halo_flat_unsigned[0],
20571 &nhalo_elements_with_iproc[0],
20572 &offset_halo_elements_with_iproc[0],
20574 this->communicator_pt()->mpi_comm());
20580 unsigned counter_new_domains_halo_ele = 0;
20581 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20585 if (iproc != my_rank)
20588 const unsigned ntmp_halo_elements_with_iproc =
20589 nhalo_elements_with_iproc[iproc];
20592 for (
unsigned i = 0;
i < ntmp_halo_elements_with_iproc;
i++)
20596 new_domains_halo_elements[iproc][
i] =
20597 new_domains_halo_flat_unsigned[counter_new_domains_halo_ele++];
20603 if (Print_timings_level_load_balance>1)
20605 oomph_info <<
"CPU for getting domains halo elements (load balance) [1]: " 20621 double tt_start_get_fe_version_from_ge_halo_ed=0.0;
20622 if (Print_timings_level_load_balance>1)
20632 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20635 if (iproc != my_rank)
20638 const unsigned nhalo_ele_iproc = this->nroot_halo_element(iproc);
20641 this->root_halo_element_pt(iproc);
20643 f_halo_element_pt[iproc].resize(nhalo_ele_iproc);
20645 for (
unsigned ih = 0; ih < nhalo_ele_iproc; ih++)
20651 f_halo_element_pt[iproc][ih] = ele_pt;
20655 const unsigned nhaloed_ele_iproc = this->nroot_haloed_element(iproc);
20658 this->root_haloed_element_pt(iproc);
20660 f_haloed_element_pt[iproc].resize(nhaloed_ele_iproc);
20662 for (
unsigned ihd = 0; ihd < nhaloed_ele_iproc; ihd++)
20666 dynamic_cast<FiniteElement*
>(haloed_element_pt_iproc[ihd]);
20668 f_haloed_element_pt[iproc][ihd] = ele_pt;
20677 if (Print_timings_level_load_balance>1)
20679 oomph_info <<
"CPU for getting finite element versions from generalised halo(ed) elements (load balance) [2]: " 20697 double tt_start_prepare_element_to_send=0.0;
20698 if (Print_timings_level_load_balance>1)
20708 std::map<Data*,std::set<unsigned> >
20709 processors_associated_with_data_before_load_balance;
20713 unsigned nh_count3 = 0;
20714 for (
unsigned e = 0;
e < nelement_before_load_balance;
e++)
20722 const unsigned element_domain =
20723 target_domain_for_local_non_halo_element[nh_count3++];
20726 elements_to_send_pt[element_domain].push_back(ele_pt);
20729 const unsigned n_nodes = ele_pt->
nnode();
20731 for (
unsigned j = 0; j < n_nodes; j++)
20736 processors_associated_with_data_before_load_balance[node_pt].
20737 insert(element_domain);
20749 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20752 if (iproc != my_rank)
20755 const unsigned n_halo_ele_iproc = this->nroot_halo_element(iproc);
20758 this->root_halo_element_pt(iproc);
20760 for (
unsigned ih = 0; ih < n_halo_ele_iproc; ih++)
20763 const unsigned element_domain =
20764 new_domains_halo_elements[iproc][ih];
20771 const unsigned n_nodes = ele_pt->
nnode();
20773 for (
unsigned j = 0; j < n_nodes; j++)
20779 processors_associated_with_data_before_load_balance[node_pt].
20780 insert(element_domain);
20791 if (Print_timings_level_load_balance>1)
20793 oomph_info <<
"CPU for preparing elements to send to other processors (load balance) [3]: " 20817 double tt_start_compute_new_local_halo_elements=0.0;
20818 if (Print_timings_level_load_balance>1)
20853 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20856 new_local_halo_element_pt[iproc].resize(nproc);
20864 unsigned nh_count5 = 0;
20865 for (
unsigned e = 0;
e < nelement_before_load_balance;
e++)
20873 const unsigned ele_domain =
20874 target_domain_for_local_non_halo_element[nh_count5++];
20877 if (ele_domain != iproc)
20880 const unsigned nnodes = ele_pt->
nnode();
20882 for (
unsigned j = 0; j < nnodes; j++)
20887 std::set<unsigned>::iterator it =
20888 processors_associated_with_data_before_load_balance[node_pt].
20892 processors_associated_with_data_before_load_balance[node_pt].
20899 if (!new_local_halo_already_added[ele_domain][ele_pt])
20903 new_local_halo_element_pt[iproc][ele_domain].
20906 new_local_halo_already_added[ele_domain][ele_pt] =
true;
20944 for (
unsigned jproc = 0; jproc < nproc; jproc++)
20948 if (jproc != my_rank)
20951 const unsigned n_halo_ele_jproc = this->nroot_halo_element(jproc);
20954 this->root_halo_element_pt(jproc);
20957 for (
unsigned jh = 0; jh < n_halo_ele_jproc; jh++)
20960 const unsigned ele_domain = new_domains_halo_elements[jproc][jh];
20991 if (ele_domain != iproc)
20997 const unsigned nnodes = ele_pt->
nnode();
20999 for (
unsigned j = 0; j < nnodes; j++)
21006 std::set<unsigned>::iterator it =
21007 processors_associated_with_data_before_load_balance[node_pt].
21011 processors_associated_with_data_before_load_balance[node_pt].end())
21018 if (!new_local_halo_already_added[ele_domain][ele_pt])
21022 new_local_halo_element_pt[iproc][ele_domain].
21024 new_local_halo_already_added[ele_domain][ele_pt] =
true;
21053 if (Print_timings_level_load_balance>1)
21055 oomph_info <<
"CPU for computing new local halo elements (load balance) [4]: " 21075 double tt_start_compute_new_local_shd_bnd_ele=0.0;
21076 if (Print_timings_level_load_balance>1)
21084 new_local_halo_shared_boundary_element_pt(nproc);
21086 new_local_halo_shared_boundary_element_face_index(nproc);
21089 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21091 new_local_halo_shared_boundary_element_pt[iproc].resize(nproc);
21092 new_local_halo_shared_boundary_element_face_index[iproc].resize(nproc);
21100 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21106 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
21108 this->get_shared_boundary_elements_and_face_indexes(
21109 new_local_halo_element_pt[iproc][jproc],
21110 new_local_halo_element_pt[jproc][iproc],
21111 new_local_halo_shared_boundary_element_pt[iproc][jproc],
21112 new_local_halo_shared_boundary_element_face_index[iproc][jproc],
21113 new_local_halo_shared_boundary_element_pt[jproc][iproc],
21114 new_local_halo_shared_boundary_element_face_index[jproc][iproc]);
21119 if (Print_timings_level_load_balance>1)
21121 oomph_info <<
"CPU for computing new local shared boundary elements (load balance) [5]: " 21141 double tt_start_send_elements_to_other_processors=0.0;
21142 if (Print_timings_level_load_balance>1)
21150 this->sort_nodes_on_shared_boundaries();
21161 new_received_haloed_shared_boundary_element_pt(nproc);
21163 new_received_haloed_shared_boundary_element_face_index(nproc);
21169 other_proc_shd_bnd_node_pt(nproc);
21171 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21174 other_proc_shd_bnd_node_pt[iproc].resize(nproc);
21175 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21178 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
21179 const unsigned final_shd_bnd_id = this->final_shared_boundary_id();
21180 const unsigned n_shared_bound = final_shd_bnd_id - initial_shd_bnd_id;
21181 other_proc_shd_bnd_node_pt[iproc][jproc].resize(n_shared_bound);
21194 std::map<Vector<unsigned>,
unsigned> node_name_to_global_index;
21202 compute_global_node_names_and_shared_nodes(other_proc_shd_bnd_node_pt,
21204 node_name_to_global_index,
21205 global_shared_node_pt);
21211 received_old_haloed_element_pt(nproc);
21218 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21220 received_old_haloed_element_pt[iproc].resize(nproc);
21225 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21227 if (iproc != my_rank)
21241 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 21246 const unsigned nelements_to_send = elements_to_send_pt[iproc].size();
21253 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 21254 std::stringstream junk;
21255 junk <<
"Number of elements to send from processor " << my_rank
21256 <<
" to processor " << iproc <<
": (" 21257 << nelements_to_send <<
")";
21262 for (
unsigned e = 0;
e < nelements_to_send;
e++)
21268 const unsigned ncurrently_sent_elements =
21269 currently_sent_elements.size();
21272 const unsigned index_ele = try_to_add_element_pt_load_balance(
21273 currently_sent_elements, send_ele_pt);
21276 if (index_ele == ncurrently_sent_elements)
21279 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 21284 get_required_elemental_information_load_balance_helper(
21286 f_haloed_element_pt,
21290 const unsigned nnodes = send_ele_pt->
nnode();
21293 for (
unsigned j = 0; j < nnodes; j++)
21298 add_node_load_balance_helper(iproc,
21300 currently_sent_nodes,
21309 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 21313 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 21333 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21339 const unsigned njproc_iproc_new_local_halo_shared_boundary_ele =
21340 new_local_halo_shared_boundary_element_pt[jproc][iproc].size();
21347 unsigned nfound_new_local_halo_shared_bound_ele_index = 0;
21350 unsigned nnon_halo_new_local_halo_shared_bound_ele = 0;
21354 for (
unsigned e = 0;
21355 e < njproc_iproc_new_local_halo_shared_boundary_ele;
e++)
21359 new_local_halo_shared_boundary_element_pt[jproc][iproc][
e];
21363 if (!shared_ele_pt->
is_halo())
21365 nnon_halo_new_local_halo_shared_bound_ele++;
21370 const unsigned ncurrently_sent_elements =
21371 currently_sent_elements.size();
21373 for (
unsigned ics = 0; ics < ncurrently_sent_elements; ics++)
21376 currently_sent_elements[ics];
21379 if (currently_sent_ele_pt == shared_ele_pt)
21383 new_local_halo_shared_boundary_ele_index.push_back(ics);
21386 nfound_new_local_halo_shared_bound_ele_index++;
21398 if (nfound_new_local_halo_shared_bound_ele_index !=
21399 nnon_halo_new_local_halo_shared_bound_ele)
21401 std::ostringstream error_message;
21403 <<
"Was only possible to identify (" 21404 << nfound_new_local_halo_shared_bound_ele_index <<
") of (" 21405 << nnon_halo_new_local_halo_shared_bound_ele <<
") shared " 21406 <<
"elements between\nprocessor ("<<iproc<<
") and ("<<jproc<<
") " 21407 <<
"when sending elements to processor ("<<iproc<<
")\n\n";
21409 OOMPH_CURRENT_FUNCTION,
21410 OOMPH_EXCEPTION_LOCATION);
21416 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 21417 std::stringstream junk;
21418 junk <<
"Flag for synchronisation 9999";
21425 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 21426 std::stringstream junk2;
21427 junk2 <<
"Number of new local halo shared boundary elements " 21428 << nnon_halo_new_local_halo_shared_bound_ele;
21434 unsigned counter_nonhalo_sent = 0;
21437 for (
unsigned e = 0;
21438 e < njproc_iproc_new_local_halo_shared_boundary_ele;
e++)
21442 new_local_halo_shared_boundary_element_pt[jproc][iproc][
e];
21446 if (!shared_ele_pt->
is_halo())
21450 const unsigned ele_index =
21451 new_local_halo_shared_boundary_ele_index[counter_nonhalo_sent++];
21453 const unsigned face_index =
21454 new_local_halo_shared_boundary_element_face_index[jproc][iproc][
e];
21459 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 21460 std::stringstream junk;
21461 junk <<
"The index of the halo shared boundary element " 21469 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 21470 std::stringstream junk2;
21471 junk2 <<
"The face index of the halo shared boundary element " 21486 int send_proc =
static_cast<int>(iproc);
21488 int recv_proc =
static_cast<int>(iproc);
21489 send_and_receive_elements_nodes_info(send_proc, recv_proc);
21504 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 21506 <<
" Number of elements need to be constructed " 21512 const unsigned nelements_to_create =
21515 for (
unsigned e = 0;
e < nelements_to_create;
e++)
21519 create_element_load_balance_helper(iproc,
21520 f_haloed_element_pt,
21521 received_old_haloed_element_pt,
21522 currently_created_elements,
21523 currently_created_nodes,
21524 other_proc_shd_bnd_node_pt,
21526 node_name_to_global_index,
21527 global_shared_node_pt);
21533 const unsigned nreceived_elements = currently_created_elements.size();
21534 received_elements_pt[iproc].resize(nreceived_elements);
21535 for (
unsigned e = 0;
e < nreceived_elements;
e++)
21536 {received_elements_pt[iproc][
e] = currently_created_elements[
e];}
21542 new_received_haloed_shared_boundary_element_pt[iproc].resize(nproc);
21543 new_received_haloed_shared_boundary_element_face_index[iproc].resize(nproc);
21546 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21549 const unsigned synchronisation_flag =
21552 if (synchronisation_flag != 9999)
21554 std::ostringstream error_message;
21556 <<
"The synchronisation flag was not read, the\n" 21557 <<
"information sent between processor (" << my_rank <<
") " 21558 <<
"and ("<< iproc <<
")\nis no longer synchronised\n\n";
21560 OOMPH_CURRENT_FUNCTION,
21561 OOMPH_EXCEPTION_LOCATION);
21567 const unsigned niproc_jproc_new_received_haloed_shared_boundary_ele =
21571 for (
unsigned e = 0;
21572 e < niproc_jproc_new_received_haloed_shared_boundary_ele;
e++)
21576 const unsigned ele_index =
21580 const unsigned face_index =
21585 currently_created_elements[ele_index];
21590 new_received_haloed_shared_boundary_element_pt[iproc][jproc].
21591 push_back(shared_ele_pt);
21593 new_received_haloed_shared_boundary_element_face_index[iproc][jproc].
21594 push_back(face_index);
21605 if (Print_timings_level_load_balance>1)
21607 oomph_info <<
"CPU for sending elements to their new processors (load balance) [6]: " 21627 double tt_start_compute_additional_shared_boundaries=0.0;
21628 if (Print_timings_level_load_balance>1)
21637 tmp_group1_shared_boundary_element_pt(nproc);
21639 tmp_group1_shared_boundary_element_face_index(nproc);
21641 tmp_group2_shared_boundary_element_pt(nproc);
21643 tmp_group2_shared_boundary_element_face_index(nproc);
21667 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21669 if (my_rank < iproc)
21672 this->get_shared_boundary_elements_and_face_indexes(
21673 received_elements_pt[iproc], elements_to_send_pt[iproc],
21674 tmp_group1_shared_boundary_element_pt[iproc],
21675 tmp_group1_shared_boundary_element_face_index[iproc],
21676 tmp_group2_shared_boundary_element_pt[iproc],
21677 tmp_group2_shared_boundary_element_face_index[iproc]);
21680 else if (my_rank > iproc)
21683 this->get_shared_boundary_elements_and_face_indexes(
21684 elements_to_send_pt[iproc], received_elements_pt[iproc],
21685 tmp_group1_shared_boundary_element_pt[iproc],
21686 tmp_group1_shared_boundary_element_face_index[iproc],
21687 tmp_group2_shared_boundary_element_pt[iproc],
21688 tmp_group2_shared_boundary_element_face_index[iproc]);
21695 if (Print_timings_level_load_balance>1)
21697 oomph_info <<
"CPU for computing additional shared boundaries (load balance) [7]: " 21717 double tt_start_sort_shared_boundaries=0.0;
21718 if (Print_timings_level_load_balance>1)
21743 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21746 if (my_rank < iproc)
21750 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21753 if (jproc != my_rank)
21756 const unsigned nrecvd_haloed_shared_bound_ele_jproc_iproc =
21757 new_received_haloed_shared_boundary_element_pt[jproc][iproc].size();
21758 for (
unsigned e = 0;
21759 e < nrecvd_haloed_shared_bound_ele_jproc_iproc;
e++)
21763 new_received_haloed_shared_boundary_element_pt[jproc][iproc][
e];
21765 const unsigned face_index =
21766 new_received_haloed_shared_boundary_element_face_index[jproc][iproc][
e];
21769 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
21770 new_shared_boundary_element_face_index[iproc].push_back(face_index);
21780 const unsigned nlocal_haloed_shared_bound_ele_iproc_my_rank =
21781 new_local_halo_shared_boundary_element_pt[iproc][my_rank].size();
21782 for (
unsigned e = 0;
21783 e < nlocal_haloed_shared_bound_ele_iproc_my_rank;
e++)
21787 new_local_halo_shared_boundary_element_pt[iproc][my_rank][
e];
21789 const unsigned face_index =
21790 new_local_halo_shared_boundary_element_face_index[iproc][my_rank][
e];
21798 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
21799 new_shared_boundary_element_face_index[iproc].push_back(face_index);
21806 const unsigned ntmp_group1_shared_bound_ele_iproc =
21807 tmp_group1_shared_boundary_element_pt[iproc].size();
21808 for (
unsigned e = 0;
e < ntmp_group1_shared_bound_ele_iproc;
e++)
21812 tmp_group1_shared_boundary_element_pt[iproc][
e];
21814 const unsigned face_index =
21815 tmp_group1_shared_boundary_element_face_index[iproc][
e];
21818 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
21819 new_shared_boundary_element_face_index[iproc].push_back(face_index);
21825 else if (my_rank > iproc)
21833 const unsigned nlocal_haloed_shared_bound_ele_iproc_my_rank =
21834 new_local_halo_shared_boundary_element_pt[iproc][my_rank].size();
21835 for (
unsigned e = 0;
21836 e < nlocal_haloed_shared_bound_ele_iproc_my_rank;
e++)
21840 new_local_halo_shared_boundary_element_pt[iproc][my_rank][
e];
21842 const unsigned face_index =
21843 new_local_halo_shared_boundary_element_face_index[iproc][my_rank][
e];
21851 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
21852 new_shared_boundary_element_face_index[iproc].push_back(face_index);
21857 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21860 if (jproc != my_rank)
21864 const unsigned nrecvd_haloed_shared_bound_ele_jproc_iproc =
21865 new_received_haloed_shared_boundary_element_pt[jproc][iproc].size();
21866 for (
unsigned e = 0;
21867 e < nrecvd_haloed_shared_bound_ele_jproc_iproc;
e++)
21871 new_received_haloed_shared_boundary_element_pt[jproc][iproc][
e];
21873 const unsigned face_index =
21874 new_received_haloed_shared_boundary_element_face_index[jproc][iproc][
e];
21877 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
21878 new_shared_boundary_element_face_index[iproc].push_back(face_index);
21888 const unsigned ntmp_group2_shared_bound_ele_iproc =
21889 tmp_group2_shared_boundary_element_pt[iproc].size();
21890 for (
unsigned e = 0;
e < ntmp_group2_shared_bound_ele_iproc;
e++)
21894 tmp_group2_shared_boundary_element_pt[iproc][
e];
21896 const unsigned face_index =
21897 tmp_group2_shared_boundary_element_face_index[iproc][
e];
21900 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
21901 new_shared_boundary_element_face_index[iproc].push_back(face_index);
21910 if (Print_timings_level_load_balance>1)
21912 oomph_info <<
"CPU for sorting shared boundaries (load balance) [8]: " 21934 double tt_start_create_new_shared_boundaries=0.0;
21935 if (Print_timings_level_load_balance>1)
21948 std::set<FiniteElement*> element_in_processor_pt;
21952 unsigned nh_count6 = 0;
21953 for (
unsigned e = 0;
e < nelement_before_load_balance;
e++)
21961 if (target_domain_for_local_non_halo_element[nh_count6++] == my_rank)
21964 element_in_processor_pt.insert(ele_pt);
21974 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21977 if (iproc != my_rank)
21981 const unsigned n_received_ele = received_elements_pt[iproc].size();
21982 for (
unsigned ie = 0; ie < n_received_ele; ie++)
21988 element_in_processor_pt.insert(ele_pt);
21997 create_new_shared_boundaries(element_in_processor_pt,
21998 new_shared_boundary_element_pt,
21999 new_shared_boundary_element_face_index);
22002 if (Print_timings_level_load_balance>1)
22004 oomph_info <<
"CPU for creating new shared boundaries (load balance) [9]: " 22027 double tt_start_delete_elements=0.0;
22028 if (Print_timings_level_load_balance>1)
22041 this->Halo_node_pt.clear();
22042 this->Root_halo_element_pt.clear();
22044 this->Haloed_node_pt.clear();
22045 this->Root_haloed_element_pt.clear();
22048 const unsigned nnodes = this->nnode();
22049 for (
unsigned j = 0; j < nnodes; j++)
22051 this->node_pt(j)->set_obsolete();
22055 this->flush_element_storage();
22058 this->delete_all_external_storage();
22061 this->External_halo_node_pt.clear();
22062 this->External_halo_element_pt.clear();
22064 this->External_haloed_node_pt.clear();
22065 this->External_haloed_element_pt.clear();
22071 unsigned nh_count7 = 0;
22072 for (
unsigned e = 0;
e < nelement_before_load_balance;
e++)
22078 if (target_domain_for_local_non_halo_element[nh_count7++] == my_rank)
22081 this->add_element_pt(ele_pt);
22083 const unsigned nele_nodes = ele_pt->
nnode();
22085 for (
unsigned j = 0; j < nele_nodes; j++)
22095 deleted_elements.push_back(ele_pt);
22105 deleted_elements.push_back(ele_pt);
22114 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22116 if (iproc != my_rank)
22120 const unsigned nreceived_ele = received_elements_pt[iproc].size();
22121 for (
unsigned ie = 0; ie < nreceived_ele; ie++)
22126 this->add_element_pt(ele_pt);
22128 const unsigned nele_nodes = ele_pt->
nnode();
22130 for (
unsigned j = 0; j < nele_nodes; j++)
22143 this->prune_dead_nodes();
22146 if (Print_timings_level_load_balance>1)
22148 oomph_info <<
"CPU for deleting elements no longer belonging to this processor (load balance) [10]: " 22167 double tt_start_re_etablish_halo_ed_info=0.0;
22168 if (Print_timings_level_load_balance>1)
22177 this->sort_nodes_on_shared_boundaries();
22184 const unsigned tmp_nboundary = this->nboundary();
22190 const unsigned n_regions = this->nregion();
22193 for (
unsigned ib = 0; ib < tmp_nboundary; ib++)
22196 ntmp_boundary_elements[ib] = this->nboundary_element(ib);
22199 ntmp_boundary_elements_in_region[ib].resize(n_regions);
22202 for (
unsigned rr = 0 ; rr < n_regions; rr++)
22205 const unsigned region_id =
22206 static_cast<unsigned>(this->region_attribute(rr));
22211 ntmp_boundary_elements_in_region[ib][rr] =
22212 this->nboundary_element_in_region(ib, region_id);
22219 this->reset_halo_haloed_scheme();
22222 const unsigned nelement_after_load_balance = this->nelement();
22226 this->reset_boundary_element_info(ntmp_boundary_elements,
22227 ntmp_boundary_elements_in_region,
22253 for (
unsigned b = 0; b < tmp_nboundary; b++)
22255 if (this->boundary_geom_object_pt(b)!=0)
22258 this->flush_boundary_segment_node(b);
22264 get_boundary_segment_nodes_helper(b, dummy_segment_node_pt);
22267 const unsigned nsegments = dummy_segment_node_pt.size();
22271 this->set_nboundary_segment_node(b, nsegments);
22277 if (Print_timings_level_load_balance>1)
22279 oomph_info <<
"CPU for re-establishing halo(ed) information (load balance) [11]: " 22291 if (Print_timings_level_load_balance>1)
22293 oomph_info <<
"CPU for load balance [n_ele_before=" 22294 <<nelement_before_load_balance<<
", n_ele_after=" 22295 <<nelement_after_load_balance<<
"]: " 22300 oomph_info <<
"Load balance (unstructured mesh) [END]" << std::endl;
22309 template <
class ELEMENT>
22325 const unsigned nfirst_element = first_element_pt.size();
22327 for (
unsigned ef = 0; ef < nfirst_element; ef++)
22332 bool first_ele_is_halo =
false;
22335 first_ele_is_halo =
true;
22338 for (
unsigned ifface = 0; ifface < 3; ifface++)
22343 first_face[0] = fele_pt->
node_pt(1);
22344 first_face[1] = fele_pt->
node_pt(2);
22346 else if (ifface == 1)
22348 first_face[0] = fele_pt->
node_pt(2);
22349 first_face[1] = fele_pt->
node_pt(0);
22351 else if (ifface == 2)
22353 first_face[0] = fele_pt->
node_pt(0);
22354 first_face[1] = fele_pt->
node_pt(1);
22361 const unsigned nsecond_element = second_element_pt.size();
22363 for (
unsigned es = 0; es < nsecond_element; es++)
22368 bool second_ele_is_halo =
false;
22371 second_ele_is_halo =
true;
22378 if (!(first_ele_is_halo && second_ele_is_halo))
22381 for (
unsigned isface = 0; isface < 3; isface++)
22386 second_face[0] = sele_pt->
node_pt(1);
22387 second_face[1] = sele_pt->
node_pt(2);
22389 else if (isface == 1)
22391 second_face[0] = sele_pt->
node_pt(2);
22392 second_face[1] = sele_pt->
node_pt(0);
22394 else if (isface == 2)
22396 second_face[0] = sele_pt->
node_pt(0);
22397 second_face[1] = sele_pt->
node_pt(1);
22402 if (first_face[0] == second_face[0] &&
22403 first_face[1] == second_face[1])
22406 first_shared_boundary_element_pt.push_back(fele_pt);
22408 first_shared_boundary_element_face_index.push_back(ifface);
22411 second_shared_boundary_element_pt.push_back(sele_pt);
22413 second_shared_boundary_element_face_index.push_back(isface);
22421 es = nsecond_element;
22425 else if (first_face[0] == second_face[1] &&
22426 first_face[1] == second_face[0])
22429 first_shared_boundary_element_pt.push_back(fele_pt);
22431 first_shared_boundary_element_face_index.push_back(ifface);
22434 second_shared_boundary_element_pt.push_back(sele_pt);
22436 second_shared_boundary_element_face_index.push_back(isface);
22444 es = nsecond_element;
22464 template <
class ELEMENT>
22467 &element_in_processor_pt,
22469 &new_shared_boundary_element_pt,
22471 &new_shared_boundary_element_face_index)
22474 const unsigned nproc = this->communicator_pt()->nproc();
22476 const unsigned my_rank = this->communicator_pt()->my_rank();
22486 double tt_start_get_edges_from_shd_bnd_face_ele=0.0;
22487 if (Print_timings_level_load_balance>2)
22502 std::map<std::pair<Node*, Node*>,
unsigned> elements_edges_on_boundary;
22505 this->get_element_edges_on_boundary(elements_edges_on_boundary);
22508 std::map<std::pair<Node*,Node*>,
bool> overlapped_edge;
22518 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22521 if (iproc != my_rank)
22525 const unsigned n_shared_bound_ele =
22526 new_shared_boundary_element_pt[iproc].size();
22533 unsigned nrepeated_faces = 0;
22537 for (
unsigned iele = 0; iele < n_shared_bound_ele; iele++)
22541 new_shared_boundary_element_pt[iproc][iele];
22545 static_cast<int>(new_shared_boundary_element_face_index[iproc][iele]);
22553 bool done_face =
false;
22557 const unsigned nnode_face_ele = tmp_ele_pt->
nnode();
22558 Node* first_face_node_pt = tmp_ele_pt->
node_pt(0);
22559 Node* last_face_node_pt = tmp_ele_pt->
node_pt(nnode_face_ele - 1);
22562 const unsigned ndone_faces = done_faces.size();
22564 for (
unsigned n = 0; n < ndone_faces; n++)
22566 Node* first_done_face_node_pt = done_faces[n].first;
22567 Node* second_done_face_node_pt = done_faces[n].second;
22568 if (first_face_node_pt == first_done_face_node_pt &&
22569 last_face_node_pt == second_done_face_node_pt)
22576 else if (first_face_node_pt == second_done_face_node_pt &&
22577 last_face_node_pt == first_done_face_node_pt)
22590 tmp_unsorted_face_ele_pt[iproc].push_back(tmp_ele_pt);
22592 tmp_unsorted_ele_pt[iproc].push_back(bulk_ele_pt);
22594 tmp_unsorted_face_index_ele[iproc].push_back(face_index);
22596 std::pair<Node*, Node*> tmp_edge =
22597 std::make_pair(first_face_node_pt, last_face_node_pt);
22599 done_faces.push_back(tmp_edge);
22603 int edge_boundary_id = -1;
22604 std::map<std::pair<Node*,Node*>,
unsigned >::iterator it;
22605 it = elements_edges_on_boundary.find(tmp_edge);
22608 if (it != elements_edges_on_boundary.end())
22612 edge_boundary_id = (*it).second;
22614 overlapped_edge[tmp_edge] =
true;
22616 std::pair<Node*, Node*> rev_tmp_edge =
22617 std::make_pair(last_face_node_pt, first_face_node_pt);
22619 overlapped_edge[rev_tmp_edge] =
true;
22624 std::pair<Node*,Node*> rtmp_edge =
22625 std::make_pair(last_face_node_pt, first_face_node_pt);
22626 it = elements_edges_on_boundary.find(rtmp_edge);
22627 if (it != elements_edges_on_boundary.end())
22631 edge_boundary_id = (*it).second;
22633 overlapped_edge[rtmp_edge] =
true;
22636 overlapped_edge[tmp_edge] =
true;
22640 tmp_edge_boundary[iproc].push_back(edge_boundary_id);
22656 if (Print_timings_level_load_balance>2)
22658 oomph_info <<
"CPU for getting edges from shared boundary face elements (load balance) [9.1]: " 22680 double tt_start_sort_shared_face_elements=0.0;
22681 if (Print_timings_level_load_balance>2)
22707 std::vector<std::vector<bool> > tmp_treat_as_inverted(nproc);
22710 std::vector<std::vector<bool> > treat_as_inverted(nproc);
22716 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22719 if (iproc != my_rank)
22722 const unsigned n_face_ele = tmp_unsorted_face_ele_pt[iproc].size();
22729 tmp_treat_as_inverted[iproc].resize(n_face_ele);
22733 for (
unsigned e = 0;
e < n_face_ele;
e++)
22736 FiniteElement* face_ele_pt = tmp_unsorted_face_ele_pt[iproc][
e];
22738 const unsigned n_node = face_ele_pt->
nnode();
22743 bottom_left[0] = node_pt->
x(0);
22744 bottom_left[1] = node_pt->
x(1);
22746 tmp_treat_as_inverted[iproc][
e] =
false;
22749 for (
unsigned n = 1; n < n_node; n++)
22753 if (node_pt->
x(1) < bottom_left[1])
22755 bottom_left[0] = node_pt->
x(0);
22756 bottom_left[1] = node_pt->
x(1);
22759 tmp_treat_as_inverted[iproc][
e] =
true;
22761 else if (node_pt->
x(1) == bottom_left[1])
22763 if (node_pt->
x(0) < bottom_left[0])
22765 bottom_left[0] = node_pt->
x(0);
22766 bottom_left[1] = node_pt->
x(1);
22769 tmp_treat_as_inverted[iproc][
e] =
true;
22776 centroid_vertices[
e].resize(2);
22778 centroid_vertices[
e][0] =
22780 face_ele_pt->
node_pt(n_node-1)->
x(0))*0.5;
22781 centroid_vertices[
e][1] =
22783 face_ele_pt->
node_pt(n_node-1)->
x(1))*0.5;
22788 unsigned n_sorted_bottom_left = 0;
22790 std::vector<bool> done_face(n_face_ele,
false);
22793 while (n_sorted_bottom_left < n_face_ele)
22796 unsigned index = 0;
22798 for (
unsigned e = 0;
e < n_face_ele;
e++)
22804 current_bottom_left[0] = centroid_vertices[
e][0];
22805 current_bottom_left[1] = centroid_vertices[
e][1];
22815 for (
unsigned e = index + 1;
e < n_face_ele;
e++)
22820 if (centroid_vertices[e][1] < current_bottom_left[1])
22823 current_bottom_left[0] = centroid_vertices[
e][0];
22824 current_bottom_left[1] = centroid_vertices[
e][1];
22828 else if (centroid_vertices[e][1] == current_bottom_left[1])
22830 if (centroid_vertices[e][0] < current_bottom_left[0])
22833 current_bottom_left[0] = centroid_vertices[
e][0];
22834 current_bottom_left[1] = centroid_vertices[
e][1];
22846 unsorted_face_ele_pt[iproc].
22847 push_back(tmp_unsorted_face_ele_pt[iproc][index]);
22849 unsorted_ele_pt[iproc].
22850 push_back(tmp_unsorted_ele_pt[iproc][index]);
22852 unsorted_face_index_ele[iproc].
22853 push_back(tmp_unsorted_face_index_ele[iproc][index]);
22855 edge_boundary[iproc].
22856 push_back(tmp_edge_boundary[iproc][index]);
22858 treat_as_inverted[iproc].
22859 push_back(tmp_treat_as_inverted[iproc][index]);
22862 done_face[index] =
true;
22865 n_sorted_bottom_left++;
22872 const unsigned tmp_n_face_ele = unsorted_face_ele_pt[iproc].size();
22874 if (tmp_n_face_ele != n_face_ele)
22876 std::ostringstream error_stream;
22878 <<
"The number of face elements before sorting them starting\n" 22879 <<
"from their bottom-left vertex is different from the number\n" 22880 <<
"of face elements after the sorting\n" 22881 <<
"N. ele before sorting: (" << n_face_ele <<
")\n" 22882 <<
"N. ele after sorting: (" << tmp_n_face_ele <<
")\n";
22884 "RefineableTriangleMesh::create_new_shared_boundaries()",
22885 OOMPH_EXCEPTION_LOCATION);
22894 if (Print_timings_level_load_balance>2)
22896 oomph_info <<
"CPU for sorting shared boundary face elements (load balance) [9.2]: " 22919 double tt_start_compute_valency_of_nodes=0.0;
22920 if (Print_timings_level_load_balance>2)
22926 std::map<Node*, unsigned> global_node_degree;
22929 compute_shared_node_degree_helper(unsorted_face_ele_pt,
22930 global_node_degree);
22933 if (Print_timings_level_load_balance>2)
22935 oomph_info <<
"CPU for computing the valency of nodes (load balance) [9.3]: " 22954 double tt_start_nodes_on_non_overlapped_shd_bnd=0.0;
22955 if (Print_timings_level_load_balance>2)
22962 std::map<unsigned, std::map<Node*, bool> >
22963 node_on_bnd_not_overlapped_by_shd_bnd;
22966 for (std::map<std::pair<Node*,Node*>,
unsigned>::iterator it_map =
22967 elements_edges_on_boundary.begin();
22968 it_map != elements_edges_on_boundary.end(); it_map++)
22971 std::pair<Node*,Node*> edge_pair = (*it_map).first;
22973 if (!overlapped_edge[edge_pair])
22977 unsigned b = (*it_map).second;
22980 Node* left_node_pt = edge_pair.first;
22981 node_on_bnd_not_overlapped_by_shd_bnd[b][left_node_pt] =
true;
22984 Node* right_node_pt = edge_pair.second;
22985 node_on_bnd_not_overlapped_by_shd_bnd[b][right_node_pt] =
true;
22993 if (Print_timings_level_load_balance>2)
22995 oomph_info <<
"CPU for computing nodes on non overlapped shared boundaries (load balance) [9.4]: " 23019 double tt_start_join_shd_bnd_face_ele=0.0;
23020 if (Print_timings_level_load_balance>2)
23052 std::map<unsigned, std::list<Node*> >
23053 local_shd_bnd_id_to_sorted_list_node_pt;
23058 unsigned local_shd_bnd_id = this->Initial_shared_boundary_id;
23063 std::map<FiniteElement*, bool> done_ele;
23066 std::map<FiniteElement*, bool> is_inverted;
23070 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23073 if (iproc != my_rank)
23077 const unsigned nunsorted_face_ele =
23078 unsorted_face_ele_pt[iproc].size();
23080 unsigned nsorted_face_ele = 0;
23083 while (nsorted_face_ele < nunsorted_face_ele)
23092 bool found_root_element =
false;
23096 unsigned root_index = 0;
23099 std::list<FiniteElement*> tmp_sorted_face_ele_pt;
23102 std::list<FiniteElement*> tmp_sorted_ele_pt;
23106 std::list<int> tmp_sorted_face_index_ele;
23111 std::list<Node*> tmp_sorted_nodes_pt;
23113 tmp_sorted_nodes_pt.clear();
23116 Node* initial_node_pt = 0;
23117 Node* final_node_pt = 0;
23121 int root_edge_bound_id = -1;
23125 for (
unsigned e = 0;
e < nunsorted_face_ele;
e++)
23130 if (!done_ele[root_ele_pt])
23134 root_edge_bound_id = edge_boundary[iproc][
e];
23137 tmp_sorted_face_ele_pt.push_back(root_ele_pt);
23139 tmp_sorted_ele_pt.push_back(unsorted_ele_pt[iproc][
e]);
23142 tmp_sorted_face_index_ele.push_back(
23143 unsorted_face_index_ele[iproc][e]);
23146 const unsigned nnodes = root_ele_pt->nnode();
23148 if (!treat_as_inverted[iproc][e])
23150 initial_node_pt = root_ele_pt->node_pt(0);
23151 final_node_pt = root_ele_pt->node_pt(nnodes-1);
23155 initial_node_pt = root_ele_pt->node_pt(nnodes-1);
23156 final_node_pt = root_ele_pt->node_pt(0);
23159 tmp_sorted_nodes_pt.push_back(initial_node_pt);
23160 tmp_sorted_nodes_pt.push_back(final_node_pt);
23163 done_ele[root_ele_pt] =
true;
23165 if (!treat_as_inverted[iproc][e])
23168 is_inverted[root_ele_pt] =
false;
23173 is_inverted[root_ele_pt] =
true;
23176 nsorted_face_ele++;
23181 found_root_element =
true;
23191 if (!found_root_element)
23193 std::ostringstream error_stream;
23195 <<
"It was not possible the found the root element\n\n";
23197 OOMPH_CURRENT_FUNCTION,
23198 OOMPH_EXCEPTION_LOCATION);
23206 bool new_element_added =
true;
23216 bool element_added_to_the_left =
false;
23217 bool element_added_to_the_right =
false;
23221 bool connection_to_the_left =
false;
23225 bool connection_to_the_right =
false;
23230 bool current_polyline_has_connections_at_both_ends =
false;
23242 int bound_id_connection_to_the_left = -1;
23243 int bound_id_connection_to_the_right = -1;
23247 const unsigned initial_node_degree =
23248 global_node_degree[initial_node_pt];
23252 const bool called_for_load_balance=
true;
23256 bound_id_connection_to_the_left =
23257 this->check_connections_of_polyline_nodes(
23258 element_in_processor_pt,
23259 root_edge_bound_id,
23261 node_on_bnd_not_overlapped_by_shd_bnd,
23262 tmp_sorted_nodes_pt,
23263 local_shd_bnd_id_to_sorted_list_node_pt,
23264 initial_node_degree,
23266 called_for_load_balance);
23270 if (bound_id_connection_to_the_left != -1)
23272 connection_to_the_left =
true;
23277 const unsigned final_node_degree =
23278 global_node_degree[final_node_pt];
23281 bound_id_connection_to_the_right =
23282 this->check_connections_of_polyline_nodes(
23283 element_in_processor_pt,
23284 root_edge_bound_id,
23286 node_on_bnd_not_overlapped_by_shd_bnd,
23287 tmp_sorted_nodes_pt,
23288 local_shd_bnd_id_to_sorted_list_node_pt,
23291 called_for_load_balance);
23295 if (bound_id_connection_to_the_right != -1)
23297 connection_to_the_right =
true;
23302 if (connection_to_the_left && connection_to_the_right)
23303 {current_polyline_has_connections_at_both_ends =
true;}
23311 while(new_element_added &&
23312 (nsorted_face_ele < nunsorted_face_ele)
23313 && !current_polyline_has_connections_at_both_ends)
23319 for (
unsigned e = root_index;
e < nunsorted_face_ele;
e++)
23322 new_element_added =
false;
23323 element_added_to_the_left =
false;
23324 element_added_to_the_right =
false;
23329 const int edge_bound_id = edge_boundary[iproc][
e];
23333 if (!done_ele[tmp_ele_pt]
23334 && (edge_bound_id == root_edge_bound_id))
23337 const unsigned nnodes = tmp_ele_pt->
nnode();
23340 Node* first_node_pt = 0;
23341 Node* last_node_pt = 0;
23342 if (!treat_as_inverted[iproc][
e])
23344 first_node_pt = tmp_ele_pt->
node_pt(0);
23345 last_node_pt = tmp_ele_pt->
node_pt(nnodes-1);
23349 first_node_pt = tmp_ele_pt->
node_pt(nnodes-1);
23350 last_node_pt = tmp_ele_pt->
node_pt(0);
23356 Node* new_added_node_pt = 0;
23359 if (initial_node_pt == last_node_pt &&
23360 !connection_to_the_left)
23363 new_added_node_pt = initial_node_pt = first_node_pt;
23365 tmp_sorted_nodes_pt.push_front(first_node_pt);
23368 tmp_sorted_face_ele_pt.push_front(tmp_ele_pt);
23370 tmp_sorted_ele_pt.push_front(unsorted_ele_pt[iproc][e]);
23373 tmp_sorted_face_index_ele.push_front(
23374 unsorted_face_index_ele[iproc][e]);
23375 if (!treat_as_inverted[iproc][e])
23378 is_inverted[tmp_ele_pt] =
false;
23383 is_inverted[tmp_ele_pt] =
true;
23386 new_element_added =
true;
23389 element_added_to_the_left =
true;
23392 else if (initial_node_pt == first_node_pt &&
23393 !connection_to_the_left)
23396 new_added_node_pt = initial_node_pt = last_node_pt;
23398 tmp_sorted_nodes_pt.push_front(last_node_pt);
23401 tmp_sorted_face_ele_pt.push_front(tmp_ele_pt);
23403 tmp_sorted_ele_pt.push_front(unsorted_ele_pt[iproc][e]);
23406 tmp_sorted_face_index_ele.push_front(
23407 unsorted_face_index_ele[iproc][e]);
23408 if (!treat_as_inverted[iproc][e])
23411 is_inverted[tmp_ele_pt] =
true;
23416 is_inverted[tmp_ele_pt] =
false;
23419 new_element_added =
true;
23422 element_added_to_the_left =
true;
23425 else if (final_node_pt == first_node_pt
23426 && !connection_to_the_right)
23429 new_added_node_pt = final_node_pt = last_node_pt;
23431 tmp_sorted_nodes_pt.push_back(last_node_pt);
23434 tmp_sorted_face_ele_pt.push_back(tmp_ele_pt);
23436 tmp_sorted_ele_pt.push_back(unsorted_ele_pt[iproc][e]);
23439 tmp_sorted_face_index_ele.push_back(
23440 unsorted_face_index_ele[iproc][e]);
23441 if (!treat_as_inverted[iproc][e])
23444 is_inverted[tmp_ele_pt] =
false;
23449 is_inverted[tmp_ele_pt] =
true;
23452 new_element_added =
true;
23455 element_added_to_the_right =
true;
23458 else if (final_node_pt == last_node_pt &&
23459 !connection_to_the_right)
23462 new_added_node_pt = final_node_pt = first_node_pt;
23464 tmp_sorted_nodes_pt.push_back(first_node_pt);
23467 tmp_sorted_face_ele_pt.push_back(tmp_ele_pt);
23469 tmp_sorted_ele_pt.push_back(unsorted_ele_pt[iproc][e]);
23472 tmp_sorted_face_index_ele.push_back(
23473 unsorted_face_index_ele[iproc][e]);
23474 if (!treat_as_inverted[iproc][e])
23477 is_inverted[tmp_ele_pt] =
true;
23482 is_inverted[tmp_ele_pt] =
false;
23485 new_element_added =
true;
23488 element_added_to_the_right =
true;
23492 if (new_element_added)
23495 done_ele[tmp_ele_pt] =
true;
23497 nsorted_face_ele++;
23501 const unsigned new_added_node_degree =
23502 global_node_degree[new_added_node_pt];
23511 if (element_added_to_the_left && !connection_to_the_left)
23514 bound_id_connection_to_the_left =
23515 this->check_connections_of_polyline_nodes(
23516 element_in_processor_pt,
23517 root_edge_bound_id,
23519 node_on_bnd_not_overlapped_by_shd_bnd,
23520 tmp_sorted_nodes_pt,
23521 local_shd_bnd_id_to_sorted_list_node_pt,
23522 new_added_node_degree,
23524 called_for_load_balance);
23528 if (bound_id_connection_to_the_left != -1)
23530 connection_to_the_left =
true;
23540 if (element_added_to_the_right && !connection_to_the_right)
23543 bound_id_connection_to_the_right =
23544 this->check_connections_of_polyline_nodes(
23545 element_in_processor_pt,
23546 root_edge_bound_id,
23548 node_on_bnd_not_overlapped_by_shd_bnd,
23549 tmp_sorted_nodes_pt,
23550 local_shd_bnd_id_to_sorted_list_node_pt,
23551 new_added_node_degree,
23553 called_for_load_balance);
23557 if (bound_id_connection_to_the_right != -1)
23559 connection_to_the_right =
true;
23568 if (connection_to_the_left && connection_to_the_right)
23569 {current_polyline_has_connections_at_both_ends =
true;}
23594 for (std::list<FiniteElement*>::iterator it =
23595 tmp_sorted_ele_pt.begin(); it != tmp_sorted_ele_pt.end(); it++)
23597 tmp_vector_sorted_ele_pt.push_back((*it));
23604 for (std::list<FiniteElement*>::iterator it =
23605 tmp_sorted_face_ele_pt.begin();
23606 it != tmp_sorted_face_ele_pt.end(); it++)
23608 tmp_vector_sorted_face_ele_pt.push_back((*it));
23614 for (std::list<int>::iterator it =
23615 tmp_sorted_face_index_ele.begin();
23616 it != tmp_sorted_face_index_ele.end(); it++)
23618 tmp_vector_sorted_face_index_ele.push_back((*it));
23633 Vector<int> final_bound_id_connection_to_the_left;
23636 Vector<int> final_bound_id_connection_to_the_right;
23639 this->break_loops_on_shared_polyline_load_balance_helper(
23641 tmp_sorted_nodes_pt,
23642 tmp_vector_sorted_ele_pt,
23643 tmp_vector_sorted_face_ele_pt, tmp_vector_sorted_face_index_ele,
23644 bound_id_connection_to_the_left, bound_id_connection_to_the_right,
23645 final_sorted_nodes_pt,
23646 final_boundary_element_pt,
23647 final_boundary_face_element_pt, final_face_index_element,
23648 final_bound_id_connection_to_the_left,
23649 final_bound_id_connection_to_the_right);
23652 const unsigned n_final_sorted_nodes = final_sorted_nodes_pt.size();
23655 for (
unsigned i = 0;
i < n_final_sorted_nodes;
i++)
23659 local_shd_bnd_id_to_sorted_list_node_pt[local_shd_bnd_id] =
23660 final_sorted_nodes_pt[
i];
23664 proc_local_shared_boundary_id[iproc].push_back(local_shd_bnd_id);
23669 local_shd_bnd_id++;
23672 sorted_ele_pt[iproc].push_back(final_boundary_element_pt[
i]);
23675 sorted_face_ele_pt[iproc].
23676 push_back(final_boundary_face_element_pt[i]);
23679 sorted_face_index_ele[iproc].push_back(final_face_index_element[i]);
23682 edge_boundary_id[iproc].push_back(root_edge_bound_id);
23689 bnd_connections_ids[0] = final_bound_id_connection_to_the_left[
i];
23690 bnd_connections_ids[1] = final_bound_id_connection_to_the_right[
i];
23691 sorted_connection_info[iproc].push_back(bnd_connections_ids);
23703 if (Print_timings_level_load_balance>2)
23705 oomph_info <<
"CPU for joining shared boundary face elements (load balance) [9.5]: " 23734 double tt_start_get_new_shared_boundaries_ids=0.0;
23735 if (Print_timings_level_load_balance>2)
23743 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23746 if (iproc != my_rank)
23750 nshared_boundaries_with_processor[iproc] =
23751 sorted_face_ele_pt[iproc].size();
23761 const unsigned root_processor = 0;
23772 MPI_Gather(&nshared_boundaries_with_processor[0],
23777 &flat_unsigned_root_received_data[0],
23785 comm_pt->mpi_comm());
23794 unsigned new_initial_shared_boundary_id = 0;
23795 unsigned new_final_shared_boundary_id = 0;
23798 if (my_rank == root_processor)
23805 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23808 root_nshared_bound_proc_with_proc[iproc].resize(nproc);
23811 for (
unsigned jproc = 0; jproc < nproc; jproc++)
23813 root_nshared_bound_proc_with_proc[iproc][jproc] =
23814 flat_unsigned_root_received_data[(iproc * nproc) + jproc];
23823 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23825 for (
unsigned jproc = 0; jproc < iproc; jproc++)
23827 if (root_nshared_bound_proc_with_proc[iproc][jproc] !=
23828 root_nshared_bound_proc_with_proc[jproc][iproc])
23830 std::ostringstream error_stream;
23832 <<
"ROOT PROCESSOR ERROR\n\n" 23833 <<
"The number of shared boundaries between processor (" 23834 << iproc <<
") and (" << jproc <<
") is not the same:\n" 23835 <<
"Shared boundaries of processor (" << iproc
23836 <<
") with processor (" << jproc <<
"): (" 23837 << root_nshared_bound_proc_with_proc[iproc][jproc] <<
")\n" 23838 <<
"Shared boundaries of processor (" << jproc
23839 <<
") with processor (" << iproc <<
"): (" 23840 << root_nshared_bound_proc_with_proc[jproc][iproc] <<
")\n\n";
23842 OOMPH_CURRENT_FUNCTION,
23843 OOMPH_EXCEPTION_LOCATION);
23862 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23863 {start_shared_bound_id_proc_with_proc[iproc].resize(nproc);}
23867 unsigned shared_bound_id = this->nboundary();
23870 new_initial_shared_boundary_id = shared_bound_id;
23873 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23875 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
23878 if (root_nshared_bound_proc_with_proc[iproc][jproc] > 0)
23882 start_shared_bound_id_proc_with_proc[iproc][jproc] = shared_bound_id;
23883 start_shared_bound_id_proc_with_proc[jproc][iproc] = shared_bound_id;
23887 shared_bound_id+= root_nshared_bound_proc_with_proc[iproc][jproc];
23895 new_final_shared_boundary_id = shared_bound_id;
23902 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23904 for (
unsigned jproc = 0; jproc < nproc; jproc++)
23908 const unsigned initial_shd_bnd_id =
23909 start_shared_bound_id_proc_with_proc[iproc][jproc];
23910 flat_unsigned_root_send_receive_data.push_back(initial_shd_bnd_id);
23914 const unsigned nshared_bnd_iproc_jproc =
23915 root_nshared_bound_proc_with_proc[iproc][jproc];
23916 flat_unsigned_root_send_receive_data.push_back(nshared_bnd_iproc_jproc);
23924 flat_unsigned_root_send_receive_data.
23925 push_back(new_initial_shared_boundary_id);
23928 flat_unsigned_root_send_receive_data.
23929 push_back(new_final_shared_boundary_id);
23940 unsigned root_ndata_sent_to_all_proc =
23941 flat_unsigned_root_send_receive_data.size();
23943 MPI_Bcast(&root_ndata_sent_to_all_proc,
23944 1, MPI_UNSIGNED, root_processor,
23945 comm_pt->mpi_comm());
23948 if (my_rank != root_processor)
23950 flat_unsigned_root_send_receive_data.resize(root_ndata_sent_to_all_proc);
23955 MPI_Bcast(&flat_unsigned_root_send_receive_data[0],
23958 root_ndata_sent_to_all_proc,
23962 comm_pt->mpi_comm());
23974 unsigned iflat_counter = 0;
23976 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23979 initial_shared_bound_id_proc_with_proc[iproc].resize(nproc);
23980 nshared_bound_proc_with_proc[iproc].resize(nproc);
23983 for (
unsigned jproc = 0; jproc < nproc; jproc++)
23987 initial_shared_bound_id_proc_with_proc[iproc][jproc] =
23988 flat_unsigned_root_send_receive_data[iflat_counter++];
23992 nshared_bound_proc_with_proc[iproc][jproc] =
23993 flat_unsigned_root_send_receive_data[iflat_counter++];
24000 new_initial_shared_boundary_id =
24001 flat_unsigned_root_send_receive_data[root_ndata_sent_to_all_proc-2];
24004 new_final_shared_boundary_id =
24005 flat_unsigned_root_send_receive_data[root_ndata_sent_to_all_proc-1];
24008 if (Print_timings_level_load_balance>2)
24010 oomph_info <<
"CPU for computing new shared boundaries ids (load balance) [9.6]: " 24032 double tt_start_create_new_shared_boundaries_polylines=0.0;
24033 if (Print_timings_level_load_balance>2)
24045 this->flush_shared_boundary_polyline_pt();
24046 this->Shared_boundary_polyline_pt.resize(nproc);
24049 this->Shared_boundaries_ids.clear();
24050 this->Shared_boundaries_ids.resize(nproc);
24051 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24053 this->Shared_boundaries_ids[iproc].clear();
24054 this->Shared_boundaries_ids[iproc].resize(nproc);
24058 this->Shared_boundary_from_processors.clear();
24059 this->Shared_boundary_overlaps_internal_boundary.clear();
24060 this->Boundary_was_splitted.clear();
24061 this->Boundary_subpolylines.clear();
24062 this->Boundary_marked_as_shared_boundary.clear();
24065 this->flush_shared_boundary_element();
24066 this->flush_face_index_at_shared_boundary();
24067 this->flush_shared_boundary_node();
24068 this->flush_sorted_shared_boundary_node();
24072 const unsigned old_local_shd_bnd_id = this->Initial_shared_boundary_id;
24075 this->Initial_shared_boundary_id = new_initial_shared_boundary_id;
24076 this->Final_shared_boundary_id = new_final_shared_boundary_id;
24086 std::map<unsigned, unsigned> local_to_global_shd_bnd_id;
24093 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24099 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
24104 if (iproc == my_rank || jproc == my_rank)
24107 unsigned ref_proc = 0;
24108 if (iproc == my_rank)
24109 {ref_proc = jproc;}
24110 else if (jproc == my_rank)
24111 {ref_proc = iproc;}
24115 const unsigned nshared_bound_iproc_jproc =
24116 nshared_bound_proc_with_proc[iproc][jproc];
24119 for (
unsigned counter = 0;
24120 counter < nshared_bound_iproc_jproc;
24124 const unsigned shd_bnd_id =
24125 initial_shared_bound_id_proc_with_proc[iproc][jproc] + counter;
24128 this->Shared_boundaries_ids[iproc][jproc].push_back(shd_bnd_id);
24129 this->Shared_boundaries_ids[jproc][iproc].push_back(shd_bnd_id);
24134 processors[0] = iproc;
24135 processors[1] = jproc;
24136 this->Shared_boundary_from_processors[shd_bnd_id] = processors;
24141 int root_edge_bound_id = edge_boundary_id[ref_proc][counter];
24144 if (root_edge_bound_id != -1)
24148 this->Shared_boundary_overlaps_internal_boundary[shd_bnd_id] =
24149 static_cast<unsigned>(root_edge_bound_id);
24162 sorted_face_ele_pt[ref_proc][counter][0];
24165 const unsigned first_face_ele_nnodes = first_face_ele_pt->
nnode();
24166 if (!is_inverted[first_face_ele_pt])
24169 Node* first_node_pt = first_face_ele_pt->node_pt(0);
24171 node_pt_to_create_shared_polyline.push_back(first_node_pt);
24173 this->add_shared_boundary_node(shd_bnd_id, first_node_pt);
24178 Node* first_node_pt =
24179 first_face_ele_pt->node_pt(first_face_ele_nnodes - 1);
24181 node_pt_to_create_shared_polyline.push_back(first_node_pt);
24183 this->add_shared_boundary_node(shd_bnd_id, first_node_pt);
24191 const unsigned nshared_boundary_elements =
24192 sorted_face_ele_pt[ref_proc][counter].size();
24196 for (
unsigned ie = 0 ; ie < nshared_boundary_elements; ie++)
24199 FiniteElement* bulk_ele_pt = sorted_ele_pt[ref_proc][counter][ie];
24203 this->add_shared_boundary_element(shd_bnd_id,
24208 const int face_index =
24209 sorted_face_index_ele[ref_proc][counter][ie];
24213 this->add_face_index_at_shared_boundary(shd_bnd_id,
24218 sorted_face_ele_pt[ref_proc][counter][ie];
24221 const unsigned nnodes = face_ele_pt->
nnode();
24222 if (!is_inverted[face_ele_pt])
24226 for (
unsigned n = 1; n < nnodes; n++)
24229 Node* node_pt = face_ele_pt->node_pt(n);
24231 this->add_shared_boundary_node(shd_bnd_id, node_pt);
24237 Node* last_node_pt = face_ele_pt->node_pt(nnodes - 1);
24238 node_pt_to_create_shared_polyline.push_back(last_node_pt);
24244 for (
int n = nnodes-2; n >= 0; n--)
24247 Node* node_pt = face_ele_pt->node_pt(n);
24249 this->add_shared_boundary_node(shd_bnd_id, node_pt);
24255 Node* last_node_pt = face_ele_pt->node_pt(0);
24256 node_pt_to_create_shared_polyline.push_back(last_node_pt);
24263 const unsigned nnodes_to_create_shared_boundary =
24264 node_pt_to_create_shared_polyline.size();
24268 for (
unsigned n = 0; n < nnodes_to_create_shared_boundary; n++)
24270 vertices[n].resize(2);
24272 Node* tmp_node_pt = node_pt_to_create_shared_polyline[n];
24274 vertices[n][0] = tmp_node_pt->
x(0);
24275 vertices[n][1] = tmp_node_pt->
x(1);
24283 this->Boundary_curve_section_pt[shd_bnd_id] = polyline_pt;
24287 unsorted_polylines_pt.push_back(polyline_pt);
24290 this->Free_curve_section_pt.insert(polyline_pt);
24296 const unsigned local_shd_bnd_id =
24297 proc_local_shared_boundary_id[ref_proc][counter];
24301 local_to_global_shd_bnd_id[local_shd_bnd_id] = shd_bnd_id;
24308 int tmp_bnd_id_connection_to_the_left =
24309 sorted_connection_info[ref_proc][counter][0];
24311 int tmp_bnd_id_connection_to_the_right =
24312 sorted_connection_info[ref_proc][counter][1];
24316 int bnd_id_connection_to_the_left = -1;
24317 int bnd_id_connection_to_the_right = -1;
24324 if (tmp_bnd_id_connection_to_the_left == -2)
24327 bnd_id_connection_to_the_left = shd_bnd_id;
24331 if (tmp_bnd_id_connection_to_the_left == -3)
24334 bnd_id_connection_to_the_left = -1;
24339 if (tmp_bnd_id_connection_to_the_left >=
24340 static_cast<int>(old_local_shd_bnd_id))
24345 std::map<unsigned, unsigned>::iterator it =
24346 local_to_global_shd_bnd_id.find(
24347 static_cast<unsigned>(tmp_bnd_id_connection_to_the_left));
24350 if (it==local_to_global_shd_bnd_id.end())
24352 std::stringstream error_message;
24354 <<
"The global shared boundary id was not found for\n" 24355 <<
"the local shared boundary shared with processor (" 24356 << ref_proc <<
").\n" 24357 <<
"This processor: (" << my_rank <<
")\n" 24358 <<
"Boundary shared with processor: (" << ref_proc <<
")\n" 24359 <<
"Local shared boundary: (" 24360 << tmp_bnd_id_connection_to_the_left <<
")\n";
24362 OOMPH_CURRENT_FUNCTION,
24363 OOMPH_EXCEPTION_LOCATION);
24368 bnd_id_connection_to_the_left =
24369 local_to_global_shd_bnd_id[
24370 static_cast<unsigned>(tmp_bnd_id_connection_to_the_left)];
24377 bnd_id_connection_to_the_left =
24378 tmp_bnd_id_connection_to_the_left;
24387 if (tmp_bnd_id_connection_to_the_right == -2)
24390 bnd_id_connection_to_the_right = shd_bnd_id;
24394 if (tmp_bnd_id_connection_to_the_right == -3)
24397 bnd_id_connection_to_the_right = -1;
24402 if (tmp_bnd_id_connection_to_the_right >=
24403 static_cast<int>(old_local_shd_bnd_id))
24408 std::map<unsigned, unsigned>::iterator it =
24409 local_to_global_shd_bnd_id.find(
24410 static_cast<unsigned>(tmp_bnd_id_connection_to_the_right));
24413 if (it==local_to_global_shd_bnd_id.end())
24415 std::stringstream error_message;
24417 <<
"The global shared boundary id was not found for\n" 24418 <<
"the local shared boundary shared with processor (" 24419 << ref_proc <<
").\n" 24420 <<
"This processor: (" << my_rank <<
")\n" 24421 <<
"Boundary shared with processor: (" << ref_proc <<
")\n" 24422 <<
"Local shared boundary: (" 24423 << tmp_bnd_id_connection_to_the_right <<
")\n";
24425 OOMPH_CURRENT_FUNCTION,
24426 OOMPH_EXCEPTION_LOCATION);
24430 bnd_id_connection_to_the_right =
24431 local_to_global_shd_bnd_id[
24432 static_cast<unsigned>(tmp_bnd_id_connection_to_the_right)];
24439 bnd_id_connection_to_the_right =
24440 tmp_bnd_id_connection_to_the_right;
24446 if (bnd_id_connection_to_the_left != -1)
24449 const unsigned ubnd_id_connection_to_the_left =
24450 static_cast<unsigned>(bnd_id_connection_to_the_left);
24455 ubnd_id_connection_to_the_left;
24463 if (bnd_id_connection_to_the_right != -1)
24467 const unsigned ubnd_id_connection_to_the_right =
24468 static_cast<unsigned>(bnd_id_connection_to_the_right);
24473 ubnd_id_connection_to_the_right;
24489 const unsigned nshared_bound_iproc_jproc =
24490 nshared_bound_proc_with_proc[iproc][jproc];
24492 for (
unsigned counter = 0;
24493 counter < nshared_bound_iproc_jproc;
24497 const unsigned shd_bnd_id =
24498 initial_shared_bound_id_proc_with_proc[iproc][jproc] + counter;
24501 this->Shared_boundaries_ids[iproc][jproc].push_back(shd_bnd_id);
24502 this->Shared_boundaries_ids[jproc][iproc].push_back(shd_bnd_id);
24507 processors[0] = iproc;
24508 processors[1] = jproc;
24509 this->Shared_boundary_from_processors[shd_bnd_id] = processors;
24520 if (Print_timings_level_load_balance>2)
24522 oomph_info <<
"CPU for creating new shared boundaries representations (load balance) [9.7]: " 24541 double tt_start_create_new_shared_curves=0.0;
24542 if (Print_timings_level_load_balance>2)
24549 if (unsorted_polylines_pt.size() > 0)
24553 this->sort_polylines_helper(unsorted_polylines_pt,
24554 this->Shared_boundary_polyline_pt[my_rank]);
24558 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24560 const unsigned nface_ele = unsorted_face_ele_pt[iproc].size();
24561 for (
unsigned e = 0;
e < nface_ele;
e++)
24563 delete unsorted_face_ele_pt[iproc][
e];
24564 unsorted_face_ele_pt[iproc][
e] = 0;
24570 if (Print_timings_level_load_balance>2)
24572 oomph_info <<
"CPU for creating the new shared curves (load balance) [9.8]: " 24591 template <
class ELEMENT>
24594 &unsorted_face_ele_pt,
24595 std::map<Node*, unsigned>
24596 &global_node_degree)
24599 const unsigned nproc = this->communicator_pt()->nproc();
24600 const unsigned my_rank = this->communicator_pt()->my_rank();
24611 std::map<Node*, Vector<Vector<unsigned> > > node_alias;
24619 create_adjacency_matrix_new_shared_edges_helper(unsorted_face_ele_pt,
24620 tmp_sorted_shared_node_pt,
24622 local_adjacency_matrix);
24635 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24638 package_unsigned_send_data_to_root.push_back(iproc);
24641 const unsigned n_nodes = tmp_sorted_shared_node_pt[iproc].size();
24644 package_unsigned_send_data_to_root.push_back(n_nodes);
24647 for (
unsigned ishd = 0; ishd < n_nodes; ishd++)
24650 Node* shd_node_pt = tmp_sorted_shared_node_pt[iproc][ishd];
24656 const unsigned n_alias = alias_node_info.size();
24659 package_unsigned_send_data_to_root.push_back(n_alias);
24662 for (
unsigned i = 0;
i < n_alias;
i++)
24666 package_unsigned_send_data_to_root.push_back(alias_node_info[
i][0]);
24668 package_unsigned_send_data_to_root.push_back(alias_node_info[i][1]);
24670 package_unsigned_send_data_to_root.push_back(alias_node_info[i][2]);
24676 for (
unsigned i = 0;
i < n_nodes;
i++)
24678 for (
unsigned j = 0; j < n_nodes; j++)
24681 package_unsigned_send_data_to_root.
24682 push_back(local_adjacency_matrix[iproc][
i][j]);
24691 const unsigned root_processor = 0;
24697 unsigned n_unsigned_data_send_to_root =
24698 package_unsigned_send_data_to_root.size();
24701 Vector<int> n_unsigned_data_received_in_root(nproc, 0);
24705 MPI_Gather(&n_unsigned_data_send_to_root,
24709 &n_unsigned_data_received_in_root[0],
24717 comm_pt->mpi_comm());
24720 unsigned n_unsigned_total_data_receive_in_root = 0;
24721 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24724 n_unsigned_total_data_receive_in_root+=
24725 n_unsigned_data_received_in_root[iproc];
24729 Vector<int> root_unsigned_offsets_receive(nproc,0);
24730 root_unsigned_offsets_receive[0] = 0;
24731 for (
unsigned iproc = 1; iproc < nproc; iproc++)
24735 root_unsigned_offsets_receive[iproc] =
24736 root_unsigned_offsets_receive[iproc-1] +
24737 n_unsigned_data_received_in_root[iproc-1];
24741 if (package_unsigned_send_data_to_root.size()==0)
24743 package_unsigned_send_data_to_root.resize(1);
24748 package_unsigned_data_received_root(n_unsigned_total_data_receive_in_root);
24749 if (my_rank!=root_processor)
24752 if (package_unsigned_data_received_root.size()==0)
24754 package_unsigned_data_received_root.resize(1);
24759 MPI_Gatherv(&package_unsigned_send_data_to_root[0],
24764 n_unsigned_data_send_to_root,
24768 &package_unsigned_data_received_root[0],
24774 &n_unsigned_data_received_in_root[0],
24777 &root_unsigned_offsets_receive[0],
24784 comm_pt->mpi_comm());
24789 Vector<int> n_unsigned_data_sent_from_root(nproc, 0);
24793 if (my_rank == root_processor)
24797 unsigned decode_counter = 0;
24806 local_node_alias(nproc);
24811 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24813 local_node_alias[iproc].resize(nproc);
24817 local_adjacency_matrix[iproc].resize(nproc);
24819 if (n_unsigned_data_received_in_root[iproc] > 0)
24823 for (
unsigned jproc = 0; jproc < nproc; jproc++)
24826 const unsigned read_jproc =
24827 package_unsigned_data_received_root[decode_counter++];
24831 if (read_jproc != jproc)
24833 std::ostringstream error_stream;
24835 <<
"The read processor is different from the jproc, this is\n" 24836 <<
"a synchronisation issue. The data are not read in the\n" 24837 <<
"sameorder as the were packaged\n" 24838 <<
"Read processor: (" << read_jproc <<
")\n" 24839 <<
"Current jproc: (" << jproc <<
")\n\n";
24841 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
24842 OOMPH_EXCEPTION_LOCATION);
24847 const unsigned read_n_shd_nodes_iproc_jproc =
24848 package_unsigned_data_received_root[decode_counter++];
24851 local_node_alias[iproc][jproc].resize(read_n_shd_nodes_iproc_jproc);
24855 for (
unsigned ishd = 0; ishd < read_n_shd_nodes_iproc_jproc; ishd++)
24858 const unsigned read_n_alias_node_iproc_jproc =
24859 package_unsigned_data_received_root[decode_counter++];
24862 local_node_alias[iproc][jproc][ishd].
24863 resize(read_n_alias_node_iproc_jproc);
24865 for (
unsigned ialias = 0;
24866 ialias < read_n_alias_node_iproc_jproc; ialias++)
24870 local_node_alias[iproc][jproc][ishd][ialias].resize(3);
24873 local_node_alias[iproc][jproc][ishd][ialias][0] =
24874 package_unsigned_data_received_root[decode_counter++];
24877 local_node_alias[iproc][jproc][ishd][ialias][1] =
24878 package_unsigned_data_received_root[decode_counter++];
24881 local_node_alias[iproc][jproc][ishd][ialias][2] =
24882 package_unsigned_data_received_root[decode_counter++];
24889 local_adjacency_matrix[iproc][jproc].
24890 resize(read_n_shd_nodes_iproc_jproc);
24892 for (
unsigned i = 0;
i < read_n_shd_nodes_iproc_jproc;
i++)
24895 local_adjacency_matrix[iproc][jproc][
i].
24896 resize(read_n_shd_nodes_iproc_jproc);
24897 for (
unsigned j = 0; j < read_n_shd_nodes_iproc_jproc; j++)
24900 local_adjacency_matrix[iproc][jproc][
i][j] =
24901 package_unsigned_data_received_root[decode_counter++];
24913 if (decode_counter != n_unsigned_total_data_receive_in_root)
24915 std::ostringstream error_stream;
24917 <<
"The number of data decoded in root received from others\n" 24918 <<
"processors is different from the total number of data received\n" 24919 <<
"Data decoded: (" << decode_counter <<
")\n" 24920 <<
"Data received: ("<<n_unsigned_total_data_receive_in_root<<
")\n\n" 24921 <<
"This is a synchronisation issue so you are probably sending\n" 24922 <<
"more or less info. than the one that is being decoded\n\n";
24924 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
24925 OOMPH_EXCEPTION_LOCATION);
24935 std::map<Vector<unsigned>,
bool> alias_done;
24941 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24943 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
24946 const unsigned n_shd_nodes_iproc_jproc =
24947 local_node_alias[iproc][jproc].size();
24950 const unsigned n_shd_nodes_jproc_iproc =
24951 local_node_alias[jproc][iproc].size();
24953 if (n_shd_nodes_iproc_jproc != n_shd_nodes_jproc_iproc)
24955 std::ostringstream error_stream;
24957 <<
"The number of nodes shared between iproc and jproc is\n" 24958 <<
"different from the number of nodes shared between jproc\n" 24960 <<
"Nodes shared between processor (" << iproc <<
") and " 24961 <<
"processor ("<<jproc<<
"): ("<<n_shd_nodes_iproc_jproc<<
")\n" 24962 <<
"Nodes shared between processor (" << jproc <<
") and " 24963 <<
"processor ("<<iproc<<
"): ("<<n_shd_nodes_jproc_iproc<<
")\n\n";
24965 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
24966 OOMPH_EXCEPTION_LOCATION);
24971 for (
unsigned ishd = 0; ishd < n_shd_nodes_iproc_jproc; ishd++)
24975 const unsigned n_alias_iproc_jproc =
24976 local_node_alias[iproc][jproc][ishd].size();
24977 const unsigned n_alias_jproc_iproc =
24978 local_node_alias[jproc][iproc][ishd].size();
24984 bool new_alias_added =
false;
24987 for (
unsigned ialias = 0; ialias < n_alias_iproc_jproc; ialias++)
24991 local_node_alias[iproc][jproc][ishd][ialias];
24993 if (!alias_done[current_alias])
24996 node_alias.push_back(current_alias);
24998 new_alias_added =
true;
25000 alias_done[current_alias] =
true;
25006 for (
unsigned ialias = 0; ialias < n_alias_jproc_iproc; ialias++)
25010 local_node_alias[jproc][iproc][ishd][ialias];
25013 if (!alias_done[current_alias])
25016 node_alias.push_back(current_alias);
25018 new_alias_added =
true;
25020 alias_done[current_alias] =
true;
25025 unsigned counter_alias = 0;
25029 unsigned n_current_alias = node_alias.size();
25030 while(new_alias_added || counter_alias < n_current_alias)
25033 new_alias_added =
false;
25039 local_node_alias[current_alias[0]]
25041 [current_alias[2]];
25045 const unsigned n_alias = alias_of_current_alias.size();
25049 for (
unsigned k = 0; k < n_alias; k++)
25053 alias_of_current_alias[k];
25056 if (!alias_done[add_alias])
25059 node_alias.push_back(add_alias);
25062 new_alias_added =
true;
25064 alias_done[add_alias] =
true;
25072 local_node_alias[current_alias[1]]
25074 [current_alias[2]];
25078 const unsigned n_alias2 = alias_of_current_alias2.size();
25082 for (
unsigned k = 0; k < n_alias2; k++)
25086 alias_of_current_alias2[k];
25089 if (!alias_done[add_alias])
25092 node_alias.push_back(add_alias);
25095 new_alias_added =
true;
25097 alias_done[add_alias] =
true;
25108 n_current_alias = node_alias.size();
25114 if (node_alias.size() > 0)
25118 global_node_alias.push_back(node_alias);
25131 const unsigned n_global_shared_nodes = global_node_alias.size();
25137 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25140 local_to_global_shared_node[iproc].resize(nproc);
25145 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25148 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25151 const unsigned n_shd_nodes =
25152 local_node_alias[iproc][jproc].size();
25155 local_to_global_shared_node[iproc][jproc].resize(n_shd_nodes,-1);
25158 local_to_global_shared_node[jproc][iproc].resize(n_shd_nodes,-1);
25168 for (
unsigned k = 0 ; k < n_global_shared_nodes; k++)
25171 const unsigned n_alias_global_node = global_node_alias[k].size();
25173 for (
unsigned l = 0; l < n_alias_global_node; l++)
25176 const unsigned iproc = global_node_alias[k][l][0];
25178 const unsigned jproc = global_node_alias[k][l][1];
25180 const unsigned ishd = global_node_alias[k][l][2];
25182 local_to_global_shared_node[iproc][jproc][ishd] = k;
25191 for (
unsigned k = 0; k < n_global_shared_nodes; k++)
25194 global_adjacency_matrix[k].resize(n_global_shared_nodes,0);
25204 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25207 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25210 const unsigned n_shd_nodes =
25211 local_node_alias[iproc][jproc].size();
25218 for (
unsigned ishd = 0; ishd < n_shd_nodes; ishd++)
25220 for (
unsigned jshd = ishd + 1; jshd < n_shd_nodes; jshd++)
25223 if (local_adjacency_matrix[iproc][jproc][ishd][jshd] > 0)
25228 const int global_shd_node_left =
25229 local_to_global_shared_node[iproc][jproc][ishd];
25232 const int global_shd_node_right =
25233 local_to_global_shared_node[iproc][jproc][jshd];
25238 if (global_shd_node_left == -1)
25240 std::ostringstream error_stream;
25242 <<
"The local node in processors iproc and jproc has no\n" 25243 <<
"global node assigned\n" 25244 <<
"iproc processor: (" << iproc <<
")\n" 25245 <<
"jproc processor: ("<<jproc<<
")\n" 25246 <<
"Local node: (" << ishd <<
")\n\n";
25248 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25249 OOMPH_EXCEPTION_LOCATION);
25254 if (global_shd_node_right == -1)
25256 std::ostringstream error_stream;
25258 <<
"The local node in processors iproc and jproc has no\n" 25259 <<
"global node assigned\n" 25260 <<
"iproc processor: (" << iproc <<
")\n" 25261 <<
"jproc processor: ("<<jproc<<
")\n" 25262 <<
"Local node: (" << jshd <<
")\n\n";
25264 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25265 OOMPH_EXCEPTION_LOCATION);
25269 const unsigned uleft =
25270 static_cast<unsigned>(global_shd_node_left);
25271 const unsigned uright =
25272 static_cast<unsigned>(global_shd_node_right);
25275 global_adjacency_matrix[uleft][uright]++;
25278 global_adjacency_matrix[uright][uleft]++;
25281 global_node_degree[uleft]++;
25284 global_node_degree[uright]++;
25300 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25302 root_local_node_degree[iproc].resize(nproc);
25306 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25309 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25313 const unsigned n_shd_nodes = local_node_alias[iproc][jproc].size();
25316 root_local_node_degree[iproc][jproc].resize(n_shd_nodes);
25318 root_local_node_degree[jproc][iproc].resize(n_shd_nodes);
25322 for (
unsigned ishd = 0; ishd < n_shd_nodes; ishd++)
25325 const int global_shd_node_id =
25326 local_to_global_shared_node[iproc][jproc][ishd];
25330 if (global_shd_node_id == -1)
25332 std::ostringstream error_stream;
25334 <<
"The local node in processors iproc and jproc has no\n" 25335 <<
"global node assigned\n" 25336 <<
"iproc processor: (" << iproc <<
")\n" 25337 <<
"jproc processor: ("<<jproc<<
")\n" 25338 <<
"Local node: (" << ishd <<
")\n\n";
25340 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25341 OOMPH_EXCEPTION_LOCATION);
25346 const unsigned uglobal_shd_node_id =
25347 static_cast<unsigned>(global_shd_node_id);
25350 const unsigned node_degree =
25351 global_node_degree[uglobal_shd_node_id];
25355 root_local_node_degree[iproc][jproc][ishd] = node_degree;
25357 root_local_node_degree[jproc][iproc][ishd] = node_degree;
25367 package_unsigned_data_sent_from_root.clear();
25371 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25374 unsigned count_n_data_sent_to_iproc = 0;
25375 for (
unsigned jproc = 0; jproc < nproc; jproc++)
25378 if (iproc != jproc)
25381 const unsigned n_shd_nodes =
25382 root_local_node_degree[iproc][jproc].size();
25385 count_n_data_sent_to_iproc+=n_shd_nodes;
25388 for (
unsigned ishd = 0; ishd < n_shd_nodes; ishd++)
25390 package_unsigned_data_sent_from_root.
25391 push_back(root_local_node_degree[iproc][jproc][ishd]);
25399 n_unsigned_data_sent_from_root[iproc] = count_n_data_sent_to_iproc;
25406 int n_unsigned_data_received_from_root = 0;
25409 MPI_Scatter(&n_unsigned_data_sent_from_root[0],
25415 &n_unsigned_data_received_from_root,
25422 comm_pt->mpi_comm());
25426 package_unsigned_data_received_from_root(n_unsigned_data_received_from_root);
25430 root_unsigned_offsets_sent[0] = 0;
25431 for (
unsigned iproc = 1; iproc < nproc; iproc++)
25434 root_unsigned_offsets_sent[iproc] =
25435 root_unsigned_offsets_sent[iproc-1] +
25436 n_unsigned_data_sent_from_root[iproc-1];
25439 if (my_rank!=root_processor)
25442 if (package_unsigned_data_sent_from_root.size()==0)
25444 package_unsigned_data_sent_from_root.resize(1);
25449 if (package_unsigned_data_received_from_root.size()==0)
25451 package_unsigned_data_received_from_root.resize(1);
25455 MPI_Scatterv(&package_unsigned_data_sent_from_root[0],
25460 &n_unsigned_data_sent_from_root[0],
25464 &root_unsigned_offsets_sent[0],
25467 &package_unsigned_data_received_from_root[0],
25475 n_unsigned_data_received_from_root,
25483 comm_pt->mpi_comm());
25488 std::map<Node*, bool> node_done;
25492 int decode_counter = 0;
25496 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25499 if (iproc != my_rank)
25502 const unsigned n_nodes = tmp_sorted_shared_node_pt[iproc].size();
25505 package_unsigned_send_data_to_root.push_back(n_nodes);
25508 for (
unsigned ishd = 0; ishd < n_nodes; ishd++)
25512 const unsigned node_degree =
25513 package_unsigned_data_received_from_root[decode_counter++];
25516 Node* shd_node_pt =
25517 tmp_sorted_shared_node_pt[iproc][ishd];
25520 if (!node_done[shd_node_pt])
25523 global_node_degree[shd_node_pt] = node_degree;
25525 node_done[shd_node_pt] =
true;
25532 if (global_node_degree[shd_node_pt] != node_degree)
25534 std::ostringstream error_stream;
25536 <<
"The local node has already assigned a global degree,\n" 25537 <<
"however, a different degree for the same node has been\n" 25538 <<
"read from the data sent from root processor\n" 25539 <<
"iproc processor: (" << iproc <<
")\n" 25540 <<
"Local node: (" << ishd <<
")\n" 25541 <<
"---------------------------------------------------------\n" 25542 <<
"Already assigned degree: (" 25543 << global_node_degree[shd_node_pt] <<
")\n" 25544 <<
"New found degree: (" << node_degree <<
")\n" 25545 <<
"---------------------------------------------------------\n" 25546 <<
"Node coordinates: (" << shd_node_pt->x(0) <<
", " 25547 << shd_node_pt->x(1) <<
")\n\n";
25549 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25550 OOMPH_EXCEPTION_LOCATION);
25554 #endif // #ifdef PARANOID 25564 if (decode_counter != n_unsigned_data_received_from_root)
25566 std::ostringstream error_stream;
25568 <<
"The number of data decoded received from root processor is\n" 25569 <<
"different from the total number of data received from the root\n" 25571 <<
"Data decoded: (" << decode_counter <<
")\n" 25572 <<
"Data received: ("<<n_unsigned_data_received_from_root<<
")\n\n" 25573 <<
"This is a synchronisation issue so you are probably sending\n" 25574 <<
"more or less info. than the one that is being decoded\n\n";
25576 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25577 OOMPH_EXCEPTION_LOCATION);
25589 template <
class ELEMENT>
25598 const unsigned nproc = this->communicator_pt()->nproc();
25599 const unsigned my_rank = this->communicator_pt()->my_rank();
25608 node_alias.clear();
25614 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25617 if (iproc != my_rank)
25620 std::map<Node*, bool> done_node;
25625 std::map<std::pair<double, double>,
Node*,
classcomp> sorted_nodes_pt;
25628 const unsigned n_unsorted_face_ele =
25629 unsorted_face_ele_pt[iproc].size();
25632 for (
unsigned e = 0;
e < n_unsorted_face_ele;
e++)
25637 Node* left_node_pt = face_ele_pt->
node_pt(0);
25642 if (!done_node[left_node_pt])
25644 std::pair<double, double> vertex =
25645 std::make_pair(left_node_pt->x(0), left_node_pt->x(1));
25646 sorted_nodes_pt[vertex] = left_node_pt;
25648 done_node[left_node_pt] =
true;
25652 const unsigned n_nodes = face_ele_pt->
nnode();
25654 Node* right_node_pt = face_ele_pt->
node_pt(n_nodes-1);
25659 if (!done_node[right_node_pt])
25661 std::pair<double, double> vertex =
25662 std::make_pair(right_node_pt->x(0), right_node_pt->x(1));
25663 sorted_nodes_pt[vertex] = right_node_pt;
25665 done_node[right_node_pt] =
true;
25674 unsigned counter = 0;
25678 for (std::map<std::pair<double, double>, Node*>::iterator it
25679 = sorted_nodes_pt.begin(); it != sorted_nodes_pt.end(); it++)
25682 Node* node_pt = (*it).second;
25684 tmp_sorted_shared_node_pt[iproc].push_back(node_pt);
25687 tmp_node_index[iproc][node_pt] = counter;
25692 alias[0] = my_rank;
25696 alias[2] = counter++;
25699 node_alias[node_pt].push_back(alias);
25709 for (
unsigned iproc = 0 ; iproc < nproc; iproc++)
25712 const unsigned n_shd_nodes = tmp_sorted_shared_node_pt[iproc].size();
25714 adjacency_matrix[iproc].resize(n_shd_nodes);
25715 for (
unsigned i = 0;
i < n_shd_nodes;
i++)
25718 adjacency_matrix[iproc][
i].resize(n_shd_nodes);
25721 for (
unsigned j = 0; j < n_shd_nodes; j++)
25723 adjacency_matrix[iproc][
i][j] = 0;
25731 for (
unsigned iproc = 0 ; iproc < nproc; iproc++)
25734 if (iproc != my_rank)
25737 const unsigned n_unsorted_face_ele =
25738 unsorted_face_ele_pt[iproc].size();
25741 for (
unsigned e = 0;
e < n_unsorted_face_ele;
e++)
25749 const unsigned n_nodes = face_ele_pt->
nnode();
25751 Node* right_node_pt = face_ele_pt->
node_pt(n_nodes-1);
25754 const unsigned left_node_index = tmp_node_index[iproc][left_node_pt];
25755 const unsigned right_node_index = tmp_node_index[iproc][right_node_pt];
25759 adjacency_matrix[iproc][left_node_index][right_node_index]++;
25761 adjacency_matrix[iproc][right_node_index][left_node_index]++;
25775 template <
class ELEMENT>
25781 tmp_segment_nodes.clear();
25795 const unsigned nshared_bound_ele =
25796 this->nshared_boundary_element(shd_bnd_id);
25800 for (
unsigned e = 0;
e < nshared_bound_ele;
e++)
25804 this->shared_boundary_element_pt(shd_bnd_id,
e);
25807 int face_index = this->face_index_at_shared_boundary(shd_bnd_id,
e);
25818 nonhalo_shared_face_ele_pt.push_back(face_ele_pt);
25824 halo_shared_face_ele_pt.push_back(face_ele_pt);
25831 std::map<FiniteElement*, bool> shared_face_done;
25834 const unsigned nnonhalo_face_shared_ele =
25835 nonhalo_shared_face_ele_pt.size();
25841 const unsigned nhalo_face_shared_ele =
25842 halo_shared_face_ele_pt.size();
25846 if (nshared_bound_ele / 2 != nnonhalo_face_shared_ele)
25848 std::ostringstream error_message;
25850 <<
"The number of shared boundary elements (" << nshared_bound_ele
25851 <<
") is not the double\nof the number of unsorted nonhalo shared " 25852 <<
"face boundary elements (" << nnonhalo_face_shared_ele
25853 <<
")\n for the current boundary ("<< shd_bnd_id <<
")\n\n";
25855 "RefineableTriangleMesh::get_shared_boundary_segment_nodes_helper()",
25856 OOMPH_EXCEPTION_LOCATION);
25861 if (nshared_bound_ele / 2 != nhalo_face_shared_ele)
25863 std::ostringstream error_message;
25865 <<
"The number of shared boundary elements (" << nshared_bound_ele
25866 <<
") is not the double\nof the number of unsorted halo shared " 25867 <<
"face boundary elements (" << nhalo_face_shared_ele
25868 <<
")\n for the current boundary ("<< shd_bnd_id <<
")\n\n";
25870 "RefineableTriangleMesh::get_shared_boundary_segment_nodes_helper()",
25871 OOMPH_EXCEPTION_LOCATION);
25877 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
25880 FiniteElement* nonhalo_face_ele_pt = nonhalo_shared_face_ele_pt[inh];
25883 const unsigned nnodes_nh = nonhalo_face_ele_pt->
nnode();
25885 Node* nh_first_node_pt = nonhalo_face_ele_pt->
node_pt(0);
25886 Node* nh_last_node_pt = nonhalo_face_ele_pt->
node_pt(nnodes_nh-1);
25890 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
25893 FiniteElement* halo_face_ele_pt = halo_shared_face_ele_pt[ih];
25896 if (!shared_face_done[halo_face_ele_pt])
25899 const unsigned nnodes_h = halo_face_ele_pt->nnode();
25901 Node* h_first_node_pt = halo_face_ele_pt->node_pt(0);
25902 Node* h_last_node_pt = halo_face_ele_pt->node_pt(nnodes_h-1);
25906 if (nh_first_node_pt == h_first_node_pt &&
25907 nh_last_node_pt == h_last_node_pt)
25910 shared_face_done[nonhalo_face_ele_pt] =
true;
25911 shared_face_done[halo_face_ele_pt] =
true;
25917 else if (nh_first_node_pt == h_last_node_pt &&
25918 nh_last_node_pt == h_first_node_pt)
25921 shared_face_done[nonhalo_face_ele_pt] =
true;
25922 shared_face_done[halo_face_ele_pt] =
true;
25937 if ((nnonhalo_face_shared_ele + nhalo_face_shared_ele) !=
25938 shared_face_done.size())
25940 std::ostringstream error_message;
25942 <<
"The number of DONE shared boundary face elements (" 25943 << shared_face_done.size() <<
") is not the same\n as the sum of" 25944 <<
"the nonhalo face shared boundary elements (" 25945 << nnonhalo_face_shared_ele <<
")\nand the halo face shared " 25946 <<
"boundary elements ("<< nhalo_face_shared_ele <<
") for the\n/" 25947 <<
"current boundary (" << shd_bnd_id <<
")\n\n";
25949 "RefineableTriangleMesh::get_shared_boundary_segment_nodes_helper()",
25950 OOMPH_EXCEPTION_LOCATION);
25952 #endif // #ifdef PARANOID 25962 shared_face_done.clear();
25964 unsigned nsorted_face_ele = 0;
25967 std::list<Node*> sorted_nodes;
25970 FiniteElement* root_face_ele_pt = nonhalo_shared_face_ele_pt[0];
25971 nsorted_face_ele++;
25974 shared_face_done[root_face_ele_pt] =
true;
25977 const unsigned nnodes_root = root_face_ele_pt->
nnode();
25978 Node *first_node_pt = root_face_ele_pt->
node_pt(0);
25979 Node *last_node_pt = root_face_ele_pt->
node_pt(nnodes_root-1);
25982 sorted_nodes.push_back(first_node_pt);
25983 sorted_nodes.push_back(last_node_pt);
25986 while (nsorted_face_ele < nnonhalo_face_shared_ele)
25989 bool node_added =
false;
25993 for (
unsigned iface = 1; iface < nnonhalo_face_shared_ele; iface++)
25996 nonhalo_shared_face_ele_pt[iface];
25999 if (!shared_face_done[tmp_shared_face_ele_pt])
26002 const unsigned tmp_nnodes = tmp_shared_face_ele_pt->nnode();
26005 Node* left_node_pt = tmp_shared_face_ele_pt->node_pt(0);
26006 Node* right_node_pt = tmp_shared_face_ele_pt->node_pt(tmp_nnodes-1);
26008 if (left_node_pt == first_node_pt)
26011 sorted_nodes.push_front(right_node_pt);
26012 first_node_pt = right_node_pt;
26015 else if (left_node_pt == last_node_pt)
26018 sorted_nodes.push_back(right_node_pt);
26019 last_node_pt = right_node_pt;
26022 else if (right_node_pt == first_node_pt)
26025 sorted_nodes.push_front(left_node_pt);
26026 first_node_pt = left_node_pt;
26029 else if (right_node_pt == last_node_pt)
26032 sorted_nodes.push_back(left_node_pt);
26033 last_node_pt = left_node_pt;
26041 shared_face_done[tmp_shared_face_ele_pt] =
true;
26042 nsorted_face_ele++;
26058 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
26060 delete nonhalo_shared_face_ele_pt[inh];
26061 nonhalo_shared_face_ele_pt[inh] = 0;
26066 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
26068 delete halo_shared_face_ele_pt[ih];
26069 halo_shared_face_ele_pt[ih] = 0;
26077 const unsigned n_nodes = sorted_nodes.size();
26080 tmp_segment_nodes.resize(1);
26081 tmp_segment_nodes[0].resize(n_nodes);
26084 unsigned counter = 0;
26087 for (std::list<Node*>::iterator it = sorted_nodes.begin();
26088 it != sorted_nodes.end(); it++)
26090 tmp_segment_nodes[0][counter] = (*it);
26102 template<
class ELEMENT>
26110 const unsigned nbound = this->initial_shared_boundary_id();
26113 const unsigned nproc = this->communicator_pt()->nproc();
26121 unsigned counter_face_indexes = 0;
26123 for (
unsigned b = 0; b < nbound; b++)
26126 const unsigned nboundary_ele = nboundary_element(b);
26127 for (
unsigned e = 0;
e < nboundary_ele;
e++)
26129 if (ele_pt == this->boundary_element_pt(b,
e))
26132 associated_boundaries.push_back(b);
26134 face_index_on_boundary.push_back(face_index_at_boundary(b,
e));
26135 counter_face_indexes++;
26137 if (counter_face_indexes > 2)
26139 std::stringstream error_message;
26141 <<
"A triangular element can not have more than two of its faces " 26142 <<
"on a boundary!!!\n\n";
26144 "RefineableTriangleMesh::get_required_elemental_information_helper()",
26145 OOMPH_EXCEPTION_LOCATION);
26149 if (counter_face_indexes==2) {
break;}
26150 #endif // #ifdef PARANOID 26160 const unsigned nassociated_boundaries = associated_boundaries.size();
26161 if (nassociated_boundaries > 0)
26164 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26168 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26169 std::stringstream junk;
26170 junk <<
"The elements is associated to " << nassociated_boundaries <<
" boundaries";
26178 for (
unsigned i = 0;
i < nassociated_boundaries;
i++)
26180 unsigned b = associated_boundaries[
i];
26182 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26183 std::stringstream junk;
26184 junk <<
"Element associated to boundary " << b <<
" of " << nassociated_boundaries <<
" total associated boundaries";
26187 unsigned f = face_index_on_boundary[
i];
26189 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26190 std::stringstream junk2;
26191 junk2 <<
"Face index " << f <<
" for associated boundary " << b;
26206 const unsigned n_regions = this->nregion();
26211 unsigned counter_face_indexes_in_regions = 0;
26213 for (
unsigned b = 0; b < nbound; b++)
26216 for (
unsigned i_reg = 0 ; i_reg < n_regions; i_reg++)
26219 const unsigned region_id =
26220 static_cast<unsigned>(this->Region_attribute[i_reg]);
26225 const unsigned nele_in_region =
26226 this->nboundary_element_in_region(b, region_id);
26227 for (
unsigned ee = 0; ee < nele_in_region; ee++)
26232 this->boundary_element_in_region_pt(b, region_id, ee))
26239 bound_and_region[0] = b;
26241 bound_and_region[1] = region_id;
26244 associated_boundaries_and_regions.push_back(bound_and_region);
26246 face_index_on_boundary_and_region.push_back(
26247 this->face_index_at_boundary_in_region(b,region_id,ee));
26251 counter_face_indexes_in_regions++;
26254 if (counter_face_indexes_in_regions > 2)
26256 std::stringstream error_message;
26258 <<
"A triangular element can not have more than two of its\n" 26259 <<
"faces on a boundary!!!\n\n";
26261 "RefineableTriangleMesh::get_required_elemental_information_helper()",
26262 OOMPH_EXCEPTION_LOCATION);
26277 const unsigned nassociated_boundaries_and_regions =
26278 associated_boundaries_and_regions.size();
26279 if (nassociated_boundaries_and_regions > 0)
26282 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26287 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26288 std::stringstream junk;
26289 junk <<
"The element is associated to " << nassociated_boundaries_and_regions <<
" boundaries-regions";
26297 for (
unsigned i = 0;
i < nassociated_boundaries_and_regions;
i++)
26299 const unsigned b = associated_boundaries_and_regions[
i][0];
26301 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26302 std::stringstream junk;
26303 junk <<
"Element associated to boundary " << b <<
" of " << nassociated_boundaries_and_regions <<
" total associated boundaries-regions";
26307 const unsigned r = associated_boundaries_and_regions[
i][1];
26309 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26310 std::stringstream junk2;
26311 junk2 <<
"Element associated to region " << r <<
" of " << nassociated_boundaries_and_regions <<
" total associated boundaries-regions";
26315 const unsigned f = face_index_on_boundary_and_region[
i];
26317 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26318 std::stringstream junk3;
26319 junk3 <<
"Face index " << f <<
" for associated boundary-region (" << b <<
"-" << r <<
")";
26327 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26336 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26351 this->shared_boundaries_in_this_processor(my_rank_shared_boundaries_ids);
26354 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
26356 for (
unsigned i = 0;
i < nmy_rank_shd_bnd;
i++)
26359 const unsigned sb = my_rank_shared_boundaries_ids[
i];
26362 const unsigned nboundary_ele = this->nshared_boundary_element(sb);
26363 for (
unsigned e = 0;
e < nboundary_ele;
e++)
26365 if (ele_pt == this->shared_boundary_element_pt(sb,
e))
26368 associated_shared_boundaries.push_back(sb);
26370 face_index_on_shared_boundary.push_back(
26371 this->face_index_at_shared_boundary(sb,
e));
26378 const unsigned nassociated_shared_boundaries =
26379 associated_shared_boundaries.size();
26380 if (nassociated_shared_boundaries > 0)
26383 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26387 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26388 std::stringstream junk;
26389 junk <<
"The elements is associated to " << nassociated_shared_boundaries <<
"shared boundaries";
26394 for (
unsigned i = 0;
i < nassociated_shared_boundaries;
i++)
26396 const unsigned b = associated_shared_boundaries[
i];
26398 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26399 std::stringstream junk;
26400 junk <<
"Element associated to shared boundary " << b <<
" of " << nassociated_shared_boundaries <<
" total associated boundaries";
26404 const unsigned f = face_index_on_shared_boundary[
i];
26406 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26407 std::stringstream junk2;
26408 junk2 <<
"Face index " << f <<
" for associated shared boundary " << b;
26416 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26427 for (
unsigned jproc = 0; jproc < nproc; jproc++)
26430 const unsigned n_haloed_jproc = f_haloed_ele_pt[jproc].size();
26432 for (
unsigned ihd =0; ihd < n_haloed_jproc; ihd++)
26435 if (ele_pt == f_haloed_ele_pt[jproc][ihd])
26438 index_haloed[jproc].push_back(ihd);
26449 for (
unsigned jproc = 0; jproc < nproc; jproc++)
26452 const unsigned n_index_haloed_jproc = index_haloed[jproc].size();
26454 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26457 for (
unsigned ihd = 0; ihd < n_index_haloed_jproc; ihd++)
26460 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26473 template <
class ELEMENT>
26481 const unsigned nnew_nodes_on_domain= new_nodes_on_domain.size();
26482 const unsigned new_added_node_index =
26483 this->try_to_add_node_pt_load_balance(new_nodes_on_domain, nod_pt);
26486 if (new_added_node_index == nnew_nodes_on_domain)
26490 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26491 std::stringstream junk;
26492 junk <<
"Node needs to be constructed [size=" 26501 get_required_nodal_information_load_balance_helper(f_halo_ele_pt,
26508 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26509 std::stringstream junk;
26510 junk <<
"Node was already added [size=" 26520 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26532 template<
class ELEMENT>
26539 unsigned my_rank = this->communicator_pt()->my_rank();
26540 const unsigned nproc = this->communicator_pt()->nproc();
26545 unsigned n_val=nod_pt->
nvalue();
26547 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26551 unsigned n_dim=nod_pt->
ndim();
26555 if (this->Time_stepper_pt!=0)
26558 n_prev=this->Time_stepper_pt->ntstorage();
26567 const unsigned n_bnd = this->initial_shared_boundary_id();
26568 for (
unsigned bb=0;bb<n_bnd;bb++)
26573 original_boundaries.push_back(bb);
26578 const unsigned n_original_boundaries = original_boundaries.size();
26580 if (n_original_boundaries > 0)
26584 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26589 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26590 std::stringstream junk;
26591 junk <<
"Node is on "<< n_original_boundaries <<
" original boundaries";
26596 for (
unsigned i=0;
i<n_original_boundaries;
i++)
26599 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26600 std::stringstream junk;
26601 junk<<
"Node is on boundary "<<original_boundaries[
i]<<
" of "<< nb;
26614 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26621 bool node_on_shared_boundary =
false;
26624 const unsigned n_shd_bnd = this->nshared_boundaries(my_rank, iproc);
26625 for (
unsigned bb=0;bb<n_shd_bnd;bb++)
26628 unsigned i_bnd = this->shared_boundaries_ids(my_rank, iproc, bb);
26630 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
26632 node_on_shared_boundary =
true;
26640 if (node_on_shared_boundary)
26643 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26650 for (
unsigned bb = 0; bb < n_shd_bnd; bb++)
26653 const unsigned i_bnd =
26654 this->shared_boundaries_ids(my_rank, iproc, bb);
26656 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
26658 shd_boundaries.push_back(i_bnd);
26663 const unsigned n_shd_bnd_is_on = shd_boundaries.size();
26666 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26667 std::stringstream junk;
26668 junk <<
"Node is on "<< n_shd_bnd_is_on <<
" shared boundaries";
26673 for (
unsigned i=0;
i<n_shd_bnd_is_on;
i++)
26676 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26677 std::stringstream junk;
26678 junk <<
"Node is on boundary " << shd_boundaries[
i] <<
" of " << nb;
26685 unsigned shared_boundary_id = shd_boundaries[0];
26687 const unsigned n_nodes_on_shared_boundary =
26688 nsorted_shared_boundary_node(shared_boundary_id);
26690 unsigned index_node_on_shared_boundary;
26693 bool found_index_node_on_shared_boundary =
false;
26696 for (
unsigned i = 0;
i < n_nodes_on_shared_boundary;
i++)
26699 Node* shared_node_pt =
26700 sorted_shared_boundary_node_pt(shared_boundary_id,
i);
26702 if (shared_node_pt == nod_pt)
26705 index_node_on_shared_boundary =
i;
26708 found_index_node_on_shared_boundary =
true;
26716 if (!found_index_node_on_shared_boundary)
26718 std::ostringstream error_message;
26720 <<
"The index of the node on boundary (" 26721 <<shared_boundary_id<<
") was not found.\n" 26722 <<
"The node coordinates are ("<<nod_pt->
x(0)<<
"," 26723 <<nod_pt->
x(1)<<
").\n";
26725 error_message.str(),
26726 "RefineableTriangleMesh::get_required_nodal_information_helper()",
26727 OOMPH_EXCEPTION_LOCATION);
26732 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26733 std::stringstream junk2;
26734 junk2 <<
"Node index on boundary "<<boundaries[0]<<
" is " 26735 <<index_node_on_shared_boundary;
26744 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26760 bool node_on_shared_boundary_with_other_processors =
false;
26762 unsigned nshared_boundaries_with_other_processors_have_node = 0;
26766 for (
unsigned jproc = 0; jproc < nproc; jproc++)
26770 if (jproc != iproc)
26773 const unsigned n_jshd_bnd =
26774 this->nshared_boundaries(my_rank, jproc);
26776 for (
unsigned bb=0;bb<n_jshd_bnd;bb++)
26779 const unsigned j_shd_bnd =
26780 this->shared_boundaries_ids(my_rank, jproc, bb);
26782 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
26790 node_on_shared_boundary_with_other_processors =
true;
26793 nshared_boundaries_with_other_processors_have_node++;
26804 if (node_on_shared_boundary_with_other_processors)
26807 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26815 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26816 std::stringstream junk;
26817 junk <<
"Number of other shared boundaries that the node is on: " 26818 << nshared_boundaries_with_other_processors_have_node;
26823 unsigned counter_shd_bnd_with_other_procs_have_node = 0;
26833 for (
unsigned jproc = 0; jproc < nproc; jproc++)
26837 if (jproc != iproc)
26841 const unsigned n_jshd_bnd =
26842 this->nshared_boundaries(my_rank, jproc);
26843 for (
unsigned bb = 0; bb < n_jshd_bnd; bb++)
26846 const unsigned j_shd_bnd =
26847 this->shared_boundaries_ids(my_rank, jproc, bb);
26849 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
26852 other_processor_1.push_back(my_rank);
26854 other_processor_2.push_back(jproc);
26856 shd_bnd_ids.push_back(j_shd_bnd);
26859 counter_shd_bnd_with_other_procs_have_node++;
26870 const unsigned n_other_processors = other_processor_1.size();
26872 for (
unsigned i = 0;
i < n_other_processors;
i++)
26875 unsigned shd_bnd_id = shd_bnd_ids[
i];
26877 const unsigned n_nodes_on_shd_bnd =
26878 nsorted_shared_boundary_node(shd_bnd_id);
26881 bool found_index_node_on_shared_boundary =
false;
26883 for (
unsigned i = 0;
i < n_nodes_on_shd_bnd;
i++)
26886 Node* shared_node_pt =
26887 sorted_shared_boundary_node_pt(shd_bnd_id,
i);
26889 if (shared_node_pt == nod_pt)
26895 indexes.push_back(
i);
26898 found_index_node_on_shared_boundary =
true;
26906 if (!found_index_node_on_shared_boundary)
26908 std::ostringstream error_message;
26910 <<
"The index of the node on boundary (" 26911 <<shd_bnd_id<<
"), shared by other processors\nwas not found.\n" 26912 <<
"The node coordinates are ("<<nod_pt->
x(0)<<
"," 26913 <<nod_pt->
x(1)<<
").\n";
26915 error_message.str(),
26916 "RefineableTriangleMesh::get_required_nodal_information_helper()",
26917 OOMPH_EXCEPTION_LOCATION);
26926 if (counter_shd_bnd_with_other_procs_have_node !=
26927 nshared_boundaries_with_other_processors_have_node)
26929 std::ostringstream error_message;
26931 <<
"The number of shared boundaries where the node is on " 26932 <<
"is different:\n" 26933 <<
"nshared_boundaries_with_other_processors_have_node: (" 26934 << nshared_boundaries_with_other_processors_have_node
26936 <<
"counter_shd_bnd_with_other_procs_have_node: (" 26937 << counter_shd_bnd_with_other_procs_have_node
26940 error_message.str(),
26941 "RefineableTriangleMesh::get_required_nodal_information_helper()",
26942 OOMPH_EXCEPTION_LOCATION);
26948 for (
unsigned i = 0;
i < n_other_processors;
i++)
26951 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26952 std::stringstream junk1;
26953 junk1 <<
"Processor where the other shared boundary " 26954 <<
"has the node: " << other_processor_1[
i];
26959 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26960 std::stringstream junk2;
26961 junk2 <<
"Processor where the other shared boundary " 26962 <<
"has the node: " << other_processor_2[
i];
26967 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26968 std::stringstream junk3;
26969 junk3 <<
"Other shared boundary id where the node is on" 26975 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 26976 std::stringstream junk4;
26977 junk4 <<
"Node index on other shared boundary " 26978 <<boundaries[
i] <<
" is " 26989 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27022 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27025 const unsigned n_halo_jproc = f_halo_ele_pt[jproc].size();
27027 for (
unsigned jh = 0; jh < n_halo_jproc; jh++)
27031 const unsigned n_node = halo_ele_pt->
nnode();
27033 for (
unsigned n = 0; n < n_node; n++)
27036 if (nod_pt == halo_ele_pt->
node_pt(n))
27038 halo_element_number[jproc].push_back(jh);
27039 halo_node_number_in_halo_element[jproc].push_back(n);
27055 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27059 const unsigned n_jproc_halo_ele_node_is_on =
27060 halo_element_number[jproc].size();
27063 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27064 std::stringstream junk5;
27065 junk5 <<
"Node is on " << n_jproc_halo_ele_node_is_on <<
" halo " 27066 <<
"elements with " << jproc <<
"-th processor";
27072 for (
unsigned i = 0;
i < n_jproc_halo_ele_node_is_on;
i++)
27075 const unsigned halo_element_index = halo_element_number[jproc][
i];
27077 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27078 std::stringstream junk6;
27079 junk6 <<
"Halo element index is ("<<halo_element_index
27080 <<
") with processor ("<<jproc<<
")";
27084 const unsigned node_index = halo_node_number_in_halo_element[jproc][
i];
27086 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27087 std::stringstream junk7;
27088 junk7 <<
"The node index on the halo element index is (" 27105 bool on_halo_element_with_iproc_processor =
false;
27106 if (halo_element_number[iproc].size() > 0)
27108 on_halo_element_with_iproc_processor =
true;
27112 if (!node_on_shared_boundary && !on_halo_element_with_iproc_processor)
27128 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27133 unsigned n_ref_val=alg_nod_pt->
nref_value();
27135 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27138 for (
unsigned i_ref_val=0;i_ref_val<n_ref_val;i_ref_val++)
27146 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27149 for (
unsigned i_geom=0;i_geom<n_geom_obj;i_geom++)
27157 unsigned found_geom_object=0;
27158 for (
unsigned i_list=0;i_list<n_geom_list;i_list++)
27162 found_geom_object=i_list;
27166 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27174 if (solid_nod_pt!=0)
27177 for (
unsigned i_val=0;i_val<n_solid_val;i_val++)
27179 for (
unsigned t=0;
t<n_prev;
t++)
27188 const unsigned nvalues_solid_node = values_solid_node.size();
27190 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27191 std::stringstream junk;
27192 junk <<
"Number of values solid node: " 27193 << nvalues_solid_node;
27196 for (
unsigned i = 0;
i < nvalues_solid_node;
i++)
27203 for (
unsigned i_val=0;i_val<n_val;i_val++)
27205 for (
unsigned t=0;
t<n_prev;
t++)
27212 for (
unsigned idim=0;idim<n_dim;idim++)
27214 for (
unsigned t=0;
t<n_prev;
t++)
27230 template <
class ELEMENT>
27235 &received_old_haloed_element_pt,
27239 &other_proc_shd_bnd_node_pt,
27244 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27246 <<
" Bool: New element needs to be constructed " 27265 new_elements_on_domain.push_back(f_el_pt);
27268 this->add_element_load_balance_helper(iproc,
27269 received_old_haloed_element_pt,
27273 unsigned n_node=f_el_pt->
nnode();
27274 for (
unsigned j=0;j<n_node;j++)
27276 Node* new_nod_pt=0;
27279 add_received_node_load_balance_helper(new_nod_pt,
27281 received_old_haloed_element_pt,
27282 new_nodes_on_domain,
27283 other_proc_shd_bnd_node_pt,
27286 node_name_to_global_index,
27287 global_shared_node_pt);
27292 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27295 <<
" Index of existing element " 27314 template<
class ELEMENT>
27319 &received_old_haloed_element_pt,
27323 const unsigned nproc = this->communicator_pt()->nproc();
27325 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27327 <<
" Bool: Element is associated to a boundary " 27333 const unsigned is_on_original_boundary =
27335 if (is_on_original_boundary == 1)
27337 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27340 <<
" How many boundaries are associated with the element " 27345 const unsigned nassociated_boundaries =
27349 for (
unsigned b = 0; b < nassociated_boundaries; b++)
27351 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27354 <<
" Boundary associated to the element " 27360 const unsigned bnd =
27363 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27366 <<
" Face index of the element " 27372 const unsigned face_index =
27377 this->Boundary_element_pt[bnd].push_back(ele_pt);
27378 this->Face_index_at_boundary[bnd].push_back(face_index);
27383 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27385 <<
" Bool: Element is associated to a boundary-region " 27393 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27396 <<
" How many boundaries-regions are associated with the element " 27401 const unsigned nassociated_boundaries_and_regions =
27404 for (
unsigned br = 0; br < nassociated_boundaries_and_regions; br++)
27406 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27409 <<
" Boundary associated to the element " 27414 const unsigned bnd =
27417 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27420 <<
" Region associated to the element " 27425 const unsigned region =
27428 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27431 <<
" Face index of the element in boundary-region " 27435 const unsigned face_index =
27440 this->Boundary_region_element_pt[bnd][region].push_back(ele_pt);
27441 this->Face_index_region_at_boundary[bnd][region].push_back(face_index);
27451 if (is_on_original_boundary != 0)
27453 std::ostringstream error_message;
27455 <<
"The current element is not on an original boundary, this should\n" 27456 <<
"be indicated by a zero flag. However, the read value for\n" 27457 <<
"that flag is ("<<is_on_original_boundary<<
").\n\n";
27459 error_message.str(),
27460 "RefineableTriangleMesh::add_element_load_balance_helper()",
27461 OOMPH_EXCEPTION_LOCATION);
27466 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27468 <<
" Bool: Element is associated to a shared boundary " 27474 const unsigned is_on_shared_boundary =
27476 if (is_on_shared_boundary == 3)
27478 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27481 <<
" How many shared boundaries are associated with the element " 27487 const unsigned nassociated_shared_boundaries =
27491 for (
unsigned b = 0; b < nassociated_shared_boundaries; b++)
27493 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27496 <<
" Shared boundary associated to the element " 27500 const unsigned bnd =
27503 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27506 <<
" Face index of the element associated to the shared boundary " 27511 const unsigned face_index =
27514 this->add_shared_boundary_element(bnd, ele_pt);
27515 this->add_face_index_at_shared_boundary(bnd, face_index);
27523 if (is_on_shared_boundary != 0)
27525 std::ostringstream error_message;
27527 <<
"The current element is not on a shared boundary, this should\n" 27528 <<
"be indicated by a zero flag. However, the read value for\n" 27529 <<
"that flag is ("<<is_on_shared_boundary<<
").\n\n";
27531 error_message.str(),
27532 "RefineableTriangleMesh::add_element_load_balance_helper()",
27533 OOMPH_EXCEPTION_LOCATION);
27542 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27544 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27546 <<
" Bool: Number of haloed indexes of the element with the " 27547 << jproc <<
" processor: " 27552 const unsigned n_index_haloed_jproc =
27555 for (
unsigned ihd = 0; ihd < n_index_haloed_jproc; ihd++)
27557 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27559 <<
" Bool: The haloed element index with the " 27560 << jproc <<
" processor: " 27564 const unsigned haloed_index =
27568 received_old_haloed_element_pt[iproc][jproc][haloed_index] = ele_pt;
27579 template <
class ELEMENT>
27586 &received_old_haloed_element_pt,
27589 std::map<unsigned, Node*> > > >
27590 &other_proc_shd_bnd_node_pt,
27592 unsigned& node_index,
27595 &global_node_names,
27597 &node_name_to_global_index,
27602 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27604 <<
" Bool: New node needs to be constructed " 27612 construct_new_node_load_balance_helper(new_nod_pt,
27614 received_old_haloed_element_pt,
27615 new_nodes_on_domain,
27616 other_proc_shd_bnd_node_pt,
27621 node_name_to_global_index,
27622 global_shared_node_pt);
27626 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27628 <<
" Index of existing halo node " 27635 new_nod_pt = new_nodes_on_domain[
27639 new_el_pt->
node_pt(node_index) = new_nod_pt;
27650 template<
class ELEMENT>
27656 &received_old_haloed_element_pt,
27659 &other_proc_shd_bnd_node_pt,
27660 unsigned& iproc,
unsigned& node_index,
27667 const unsigned nproc = this->communicator_pt()->nproc();
27669 const unsigned my_rank = this->communicator_pt()->my_rank();
27673 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27675 <<
" Number of values of external halo node " 27682 TimeStepper* time_stepper_pt=this->Time_stepper_pt;
27684 unsigned n_prev=time_stepper_pt->
ntstorage();
27688 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27690 <<
" Is the node on an original boundary " 27696 const unsigned node_on_original_boundaries =
27704 unsigned n_original_boundaries_node_is_on = 0;
27706 if (node_on_original_boundaries==2)
27709 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27711 <<
" Number of boundaries the node is on: " 27715 n_original_boundaries_node_is_on =
27719 original_boundaries_node_is_on.resize(n_original_boundaries_node_is_on);
27720 zeta_coordinates.resize(n_original_boundaries_node_is_on);
27722 for (
unsigned i=0;
i<n_original_boundaries_node_is_on;
i++)
27725 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27727 <<
" Node is on boundary " 27731 original_boundaries_node_is_on[
i] =
27733 zeta_coordinates[
i] =
27741 if (node_on_original_boundaries != 0)
27743 std::ostringstream error_message;
27745 <<
"The current node is not on an original boundary, this should\n" 27746 <<
"be indicated by a zero flag. However, the read value for\n" 27747 <<
"that flag is ("<<node_on_original_boundaries<<
").\n\n";
27749 error_message.str(),
27750 "RefineableTriangleMesh::construct_new_halo_node_helper()",
27751 OOMPH_EXCEPTION_LOCATION);
27759 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27761 <<
" Is node on shared boundary? " 27765 const unsigned is_node_on_shared_boundary =
27767 if (is_node_on_shared_boundary == 1)
27770 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27772 <<
" Number of boundaries the node is on: " 27776 const unsigned n_shd_bnd_node_is_on =
27779 for (
unsigned i=0;
i<n_shd_bnd_node_is_on;
i++)
27782 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27784 <<
" Node is on boundary " 27788 shd_bnds_node_is_on[
i] =
27793 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27795 <<
" Index of node on boundary " 27800 unsigned node_index_on_shared_boundary =
27805 this->sorted_shared_boundary_node_pt(shd_bnds_node_is_on[0],
27806 node_index_on_shared_boundary);
27812 if (is_node_on_shared_boundary != 0)
27814 std::ostringstream error_message;
27816 <<
"The current node is not on a shared boundary, this should\n" 27817 <<
"be indicated by a zero flag. However, the read value for\n" 27818 <<
"that flag is ("<<is_node_on_shared_boundary<<
").\n\n";
27820 error_message.str(),
27821 "RefineableTriangleMesh::construct_new_halo_node_helper()",
27822 OOMPH_EXCEPTION_LOCATION);
27829 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27831 <<
" Is the node on shared boundaries with other processors " 27838 const unsigned is_the_node_in_shared_boundaries_with_other_processors =
27848 unsigned n_shd_bnd_with_other_procs_have_node = 0;
27851 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
27853 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27855 <<
" In how many shared boundaries with other " 27856 <<
"processors is the node " 27862 n_shd_bnd_with_other_procs_have_node =
27866 other_processor_1.resize(n_shd_bnd_with_other_procs_have_node);
27867 other_processor_2.resize(n_shd_bnd_with_other_procs_have_node);
27868 other_shared_boundaries.resize(n_shd_bnd_with_other_procs_have_node);
27869 other_indexes.resize(n_shd_bnd_with_other_procs_have_node);
27871 for (
unsigned i = 0;
i < n_shd_bnd_with_other_procs_have_node;
i++)
27873 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27875 <<
" Processor where the other shared boundary" 27881 other_processor_1[
i] =
27884 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27886 <<
" Processor where the other shared boundary" 27892 other_processor_2[
i] =
27895 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27897 <<
" Other shared boundary id where the node is on: " 27903 other_shared_boundaries[
i] =
27906 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27908 <<
" Node index on the other shared boundary " 27923 if (is_the_node_in_shared_boundaries_with_other_processors != 0)
27925 std::ostringstream error_message;
27927 <<
"The current node is not on a shared boundary with\n" 27928 <<
"other processors, this should be indicated by a zero flag.\n" 27929 <<
"However, the read value for that flag is (" 27930 <<is_the_node_in_shared_boundaries_with_other_processors<<
").\n\n";
27932 error_message.str(),
27933 "RefineableTriangleMesh::construct_new_node_load_balance_helper()",
27934 OOMPH_EXCEPTION_LOCATION);
27949 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27951 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27953 <<
" The node is on " 27955 <<
" halo elements with " << jproc <<
" processor" 27960 const unsigned n_jproc_halo_ele_node_is_on =
27964 halo_element_number[jproc].resize(n_jproc_halo_ele_node_is_on);
27965 halo_node_number_in_halo_element[jproc].resize(n_jproc_halo_ele_node_is_on);
27970 for (
unsigned i = 0;
i < n_jproc_halo_ele_node_is_on;
i++)
27973 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27975 <<
" The halo element index where the node is on " 27980 const unsigned halo_ele_index =
27982 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 27984 <<
" The node index on the halo element where the node " 27989 const unsigned node_index_on_halo_ele =
27993 halo_element_number[jproc][
i] = halo_ele_index;
27995 halo_node_number_in_halo_element[jproc][
i] = node_index_on_halo_ele;
28004 std::set<Node*> set_haloed_node_pt;
28007 Node* haloed_node_pt = 0;
28013 bool on_haloed_element_with_iproc_processor =
false;
28014 if (halo_element_number[my_rank].size() > 0)
28018 on_haloed_element_with_iproc_processor =
true;
28021 const unsigned n_haloed_indexes = halo_element_number[my_rank].size();
28025 for (
unsigned i = 0;
i < n_haloed_indexes;
i++)
28028 const unsigned haloed_index = halo_element_number[my_rank][
i];
28030 const unsigned haloed_node_index =
28031 halo_node_number_in_halo_element[my_rank][
i];
28034 FiniteElement* tmp_haloed_ele_pt = f_haloed_ele_pt[iproc][haloed_index];
28036 Node* tmp_haloed_node_pt = tmp_haloed_ele_pt->
node_pt(haloed_node_index);
28039 haloed_node_pt = tmp_haloed_node_pt;
28042 set_haloed_node_pt.insert(tmp_haloed_node_pt);
28045 if (set_haloed_node_pt.size() > 1)
28047 std::ostringstream error_message;
28049 <<
"When adding the " << haloed_node_index <<
" node of the " 28050 << haloed_index <<
"-th haloed element\n" 28051 <<
"in the currrent processor with the " << iproc <<
" processor" 28052 <<
"it was found that\nthe node pointer is different from the other" 28053 <<
"instances of the node.\nIt means we have a repeated node." 28054 <<
"This are the node coordinates of the previous node instances\n" 28055 <<
"The last entry is for the just added node with a different node\n" 28057 for (std::set<Node*>::iterator it = set_haloed_node_pt.begin();
28058 it != set_haloed_node_pt.end(); it++)
28061 <<
"Node: ("<< (*it)->
x(0)<<
", "<<(*it)->x(1)<<
")\n";
28063 error_message <<
"\n";
28065 error_message.str(),
28066 "RefineableTriangleMesh::construct_new_node_load_balance_helper()",
28067 OOMPH_EXCEPTION_LOCATION);
28077 bool found_on_haloed_element_with_other_processor =
false;
28080 for (
unsigned jproc = 0; jproc < iproc; jproc++)
28083 if (halo_element_number[jproc].size() > 0)
28086 const unsigned n_halo_indexes = halo_element_number[jproc].size();
28090 for (
unsigned i = 0;
i < n_halo_indexes;
i++)
28093 const unsigned haloed_index = halo_element_number[jproc][
i];
28095 const unsigned haloed_node_index =
28096 halo_node_number_in_halo_element[jproc][
i];
28100 std::map<unsigned,FiniteElement*>::iterator it_map =
28101 received_old_haloed_element_pt[jproc][iproc].find(haloed_index);
28103 if (it_map != received_old_haloed_element_pt[jproc][iproc].end())
28108 found_on_haloed_element_with_other_processor =
true;
28113 Node* tmp_haloed_node_pt =
28114 tmp_haloed_ele_pt->
node_pt(haloed_node_index);
28117 haloed_node_pt = tmp_haloed_node_pt;
28120 set_haloed_node_pt.insert(tmp_haloed_node_pt);
28123 if (set_haloed_node_pt.size() > 1)
28125 std::ostringstream error_message;
28127 <<
"When adding the " << haloed_node_index <<
" node of the " 28128 << haloed_index <<
"-th haloed element " 28129 <<
"of the " << jproc <<
" processor\nwith the " 28130 << iproc <<
" processor, it was found that\n" 28131 <<
"the node pointer is different from the other\n" 28132 <<
"instances of the node.\nThis means we have a repeated node.\n" 28133 <<
"These are the node coordinates of the previous node " 28135 <<
"The last entry is for the just added node with a different\n" 28136 <<
"node pointer\n";
28137 for (std::set<Node*>::iterator it = set_haloed_node_pt.begin();
28138 it != set_haloed_node_pt.end(); it++)
28141 <<
"Node: ("<< (*it)->
x(0)<<
", "<<(*it)->x(1)<<
")\n";
28143 error_message <<
"\n";
28145 error_message.str(),
28146 "RefineableTriangleMesh::construct_new_node_load_balance_helper()",
28147 OOMPH_EXCEPTION_LOCATION);
28165 if (on_haloed_element_with_iproc_processor ||
28166 found_on_haloed_element_with_other_processor)
28169 new_nod_pt = haloed_node_pt;
28177 if (is_node_on_shared_boundary == 1 ||
28178 (on_haloed_element_with_iproc_processor))
28183 if (node_on_original_boundaries==2)
28189 for (
unsigned i = 0;
i < n_original_boundaries_node_is_on;
i++)
28191 add_boundary_node(original_boundaries_node_is_on[
i], new_nod_pt);
28194 zeta[0] = zeta_coordinates[
i];
28196 original_boundaries_node_is_on[i],zeta);
28202 new_nodes_on_domain.push_back(new_nod_pt);
28205 new_el_pt->
node_pt(node_index) = new_nod_pt;
28215 bool found_node_in_other_shared_boundaries =
false;
28224 bool build_node_as_boundary_node =
false;
28226 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
28229 build_node_as_boundary_node =
true;
28236 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
28243 for (
unsigned i = 0;
i < n_shd_bnd_with_other_procs_have_node;
i++)
28245 unsigned oproc1 = other_processor_1[
i];
28246 unsigned oproc2 = other_processor_2[
i];
28250 if (oproc1 > oproc2)
28253 oproc1 = other_processor_2[
i];
28258 const unsigned shd_bnd_id =
28259 other_shared_boundaries[
i] - initial_shd_bnd_id;
28261 const unsigned index = other_indexes[
i];
28265 const unsigned n_nodes_on_other_processor =
28266 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].size();
28268 if (n_nodes_on_other_processor > 0)
28272 std::map<unsigned, Node*>::iterator it =
28273 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].
28278 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].end())
28281 found_node_in_other_shared_boundaries =
true;
28283 Node* tmp_node_pt =
28284 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id][index];
28285 found_node_pt.push_back(tmp_node_pt);
28295 if (found_node_in_other_shared_boundaries)
28298 const unsigned ntimes_node_found = found_node_pt.size();
28299 for (
unsigned j = 1; j < ntimes_node_found; j++)
28301 if (found_node_pt[j-1] != found_node_pt[j])
28303 std::ostringstream error_message;
28305 <<
"The instances of the node that was found to be on a\n" 28306 <<
"shared boundary with other processors are not the same,\n" 28307 <<
"the coordinates for the nodes are these:\n" 28308 <<
"(" << found_node_pt[j-1]->x(0) <<
", " 28309 << found_node_pt[j-1]->x(1) <<
")\n" 28310 <<
"(" << found_node_pt[j]->x(0) <<
", " 28311 << found_node_pt[j]->x(1) <<
")\n" 28312 <<
"Not be surprised if they are the same since the node is\n" 28315 error_message.str(),
28316 "RefineableTriangleMesh::construct_new_halo_node_helper()",
28317 OOMPH_EXCEPTION_LOCATION);
28328 if (is_node_on_shared_boundary == 1)
28333 if (found_node_pt[0] != new_nod_pt)
28335 std::ostringstream error_message;
28337 <<
"The pointer of the node that was found to be on a\n" 28338 <<
"shared boundary with other processor(s) and the pointer\n" 28339 <<
"of the node on shared boundary with the receiver\n" 28340 <<
"processor (iproc) are not the same. This means we have a\n" 28341 <<
"repeated node)\n" 28342 <<
"The coordinates for the nodes are:\n" 28343 <<
"(" << found_node_pt[0]->x(0) <<
", " 28344 << found_node_pt[0]->x(1) <<
")\n" 28345 <<
"(" << new_nod_pt->
x(0) <<
", " 28346 << new_nod_pt->
x(1) <<
")\n" 28347 <<
"Not to be surprised if they are the same since the node is\n" 28350 error_message.str(),
28351 "RefineableTriangleMesh::construct_new_halo_node_helper()",
28352 OOMPH_EXCEPTION_LOCATION);
28361 new_nod_pt = found_node_pt[0];
28373 if (is_node_on_shared_boundary != 1 &&
28374 !on_haloed_element_with_iproc_processor)
28388 if (node_on_original_boundaries==2 || build_node_as_boundary_node)
28394 if (!found_node_in_other_shared_boundaries ||
28395 !found_on_haloed_element_with_other_processor)
28398 if (time_stepper_pt!=0)
28413 new_el_pt->
node_pt(node_index) = new_nod_pt;
28418 for (
unsigned i = 0;
i < n_original_boundaries_node_is_on;
i++)
28420 add_boundary_node(original_boundaries_node_is_on[
i], new_nod_pt);
28423 zeta[0] = zeta_coordinates[
i];
28425 original_boundaries_node_is_on[i],zeta);
28435 if (!found_node_in_other_shared_boundaries ||
28436 !found_on_haloed_element_with_other_processor)
28439 if (time_stepper_pt!=0)
28441 new_nod_pt=new_el_pt->
construct_node(node_index, time_stepper_pt);
28452 new_el_pt->
node_pt(node_index) = new_nod_pt;
28464 new_nodes_on_domain.push_back(new_nod_pt);
28470 if (!found_node_in_other_shared_boundaries ||
28471 !found_on_haloed_element_with_other_processor)
28474 this->add_node_pt(new_nod_pt);
28484 if (new_alg_nod_pt!=0)
28493 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 28495 <<
" Alg node update id " 28507 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 28509 <<
" Alg node # of ref values " 28518 ref_value.resize(n_ref_val);
28519 for (
unsigned i_ref=0;i_ref<n_ref_val;i_ref++)
28532 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 28534 <<
" Alg node # of geom objects " 28543 geom_object_pt.resize(n_geom_obj);
28544 for (
unsigned i_geom=0;i_geom<n_geom_obj;i_geom++)
28546 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 28548 <<
" Alg node: geom object index " 28560 geom_object_pt[i_geom]=alg_mesh_pt->
28561 geom_object_list_pt(geom_index);
28568 if (!found_node_in_other_shared_boundaries ||
28569 !found_on_haloed_element_with_other_processor)
28574 (update_id,alg_mesh_pt,geom_object_pt,ref_value);
28588 if (!found_node_in_other_shared_boundaries ||
28589 !found_on_haloed_element_with_other_processor)
28595 if (macro_nod_pt!=0)
28605 geom_object_vector_pt=
28611 (node_index,s_in_macro_node_update_element);
28615 (new_el_pt,s_in_macro_node_update_element,
28616 geom_object_vector_pt);
28623 unsigned n_new_val=new_nod_pt->
nvalue();
28629 if (!found_node_in_other_shared_boundaries ||
28630 !found_on_haloed_element_with_other_processor)
28632 if (n_val>n_new_val)
28648 new std::map<unsigned, unsigned>;
28652 std::map<unsigned, unsigned>* map_pt=
28657 const unsigned id_face = 0;
28659 std::map<unsigned, unsigned>::const_iterator p=map_pt->find(id_face);
28662 if(p==map_pt->end())
28666 (*map_pt)[id_face] = n_new_val;
28669 new_nod_pt->
resize(n_val);
28679 if (solid_nod_pt!=0)
28682 for (
unsigned i_val=0;i_val<n_solid_val;i_val++)
28684 for (
unsigned t=0;
t<n_prev;
t++)
28693 if (!found_node_in_other_shared_boundaries ||
28694 !found_on_haloed_element_with_other_processor)
28697 set_value(
t, i_val, read_data);
28705 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE 28707 <<
" Number of values solid node: " 28711 const unsigned nvalues_solid_node =
28714 for (
unsigned i = 0;
i < nvalues_solid_node;
i++)
28716 values_solid_node[
i] =
28724 if (!found_node_in_other_shared_boundaries ||
28725 !found_on_haloed_element_with_other_processor)
28727 unsigned index = 0;
28736 for (
unsigned i_val=0;i_val<n_val;i_val++)
28738 for (
unsigned t=0;
t<n_prev;
t++)
28747 if (!found_node_in_other_shared_boundaries ||
28748 !found_on_haloed_element_with_other_processor)
28759 unsigned n_dim=new_nod_pt->
ndim();
28760 for (
unsigned idim=0;idim<n_dim;idim++)
28762 for (
unsigned t=0;
t<n_prev;
t++)
28771 if (!found_node_in_other_shared_boundaries ||
28772 !found_on_haloed_element_with_other_processor)
28775 new_nod_pt->
x(
t,idim) = read_data;
28788 if (n_shd_bnd_with_other_procs_have_node > 0 &&
28792 !found_node_in_other_shared_boundaries)
28801 this->update_other_proc_shd_bnd_node_helper(new_nod_pt,
28802 other_proc_shd_bnd_node_pt,
28805 other_shared_boundaries,
28808 node_name_to_global_index,
28809 global_shared_node_pt);
28815 #endif // #ifdef OOMPH_HAS_MPI 28823 template <
class ELEMENT>
28828 tmp_segment_nodes.clear();
28838 unsigned n_repeated_ele = 0;
28841 const unsigned n_regions = this->nregion();
28849 for (
unsigned rr = 0 ; rr < n_regions; rr++)
28851 const unsigned region_id =
28852 static_cast<unsigned>(this->Region_attribute[rr]);
28855 const unsigned nel_in_region =
28856 this->nboundary_element_in_region(b, region_id);
28859 unsigned nel_repeated_in_region = 0;
28863 if (nel_in_region > 0)
28867 bool repeated =
false;
28870 for (
unsigned e = 0;
e < nel_in_region;
e++)
28874 this->boundary_element_in_region_pt(b, region_id,
e);
28876 #ifdef OOMPH_HAS_MPI 28878 if (this->is_mesh_distributed() && bulk_elem_pt->
is_halo())
28889 this->face_index_at_boundary_in_region(b, region_id,
e);
28895 bulk_elem_pt, face_index);
28898 const unsigned n_nodes = tmp_ele_pt->
nnode();
28900 std::pair<Node*, Node*> tmp_pair =
28901 std::make_pair(tmp_ele_pt->
node_pt(0),
28902 tmp_ele_pt->
node_pt(n_nodes - 1));
28904 std::pair<Node*, Node*> tmp_pair_inverse =
28905 std::make_pair(tmp_ele_pt->
node_pt(n_nodes - 1),
28909 unsigned n_done_nodes = done_nodes_pt.size();
28910 for (
unsigned l = 0; l < n_done_nodes; l++)
28912 if (tmp_pair == done_nodes_pt[l] || tmp_pair_inverse
28913 == done_nodes_pt[l])
28915 nel_repeated_in_region++;
28926 done_nodes_pt.push_back(tmp_pair);
28928 face_el_pt.push_back(tmp_ele_pt);
28944 nel += nel_in_region;
28947 n_repeated_ele += nel_repeated_in_region;
28958 nel = this->nboundary_element(b);
28965 bool repeated =
false;
28968 for (
unsigned e = 0;
e < nel;
e++)
28973 #ifdef OOMPH_HAS_MPI 28975 if (this->is_mesh_distributed() && bulk_elem_pt->
is_halo())
28985 int face_index = this->face_index_at_boundary(b,
e);
28990 bulk_elem_pt, face_index);
28993 const unsigned n_nodes = tmp_ele_pt->
nnode();
28995 std::pair<Node*, Node*> tmp_pair =
28996 std::make_pair(tmp_ele_pt->
node_pt(0),
28997 tmp_ele_pt->
node_pt(n_nodes - 1));
28999 std::pair<Node*, Node*> tmp_pair_inverse =
29000 std::make_pair(tmp_ele_pt->
node_pt(n_nodes - 1),
29004 unsigned n_done_nodes = done_nodes_pt.size();
29005 for (
unsigned l = 0; l < n_done_nodes; l++)
29007 if (tmp_pair == done_nodes_pt[l] || tmp_pair_inverse
29008 == done_nodes_pt[l])
29021 done_nodes_pt.push_back(tmp_pair);
29023 face_el_pt.push_back(tmp_ele_pt);
29042 nel -= n_repeated_ele;
29045 if (nel!=face_el_pt.size())
29047 std::ostringstream error_message;
29049 <<
"The independet counting of face elements ("<<nel<<
") for " 29050 <<
"boundary ("<<b<<
") is different\n" 29051 <<
"from the real number of face elements in the container (" 29052 << face_el_pt.size() <<
")\n";
29054 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29055 OOMPH_EXCEPTION_LOCATION);
29063 const unsigned nnon_halo_face_elements = nel;
29071 unsigned nsorted_face_elements = 0;
29075 std::map<FiniteElement*, bool> done_ele;
29080 std::map<FiniteElement*, bool> is_inverted;
29085 while(nsorted_face_elements < nnon_halo_face_elements)
29089 std::list<FiniteElement*> sorted_el_pt;
29093 bool found_initial_face_element =
false;
29098 unsigned iface = 0;
29099 #ifdef OOMPH_HAS_MPI 29100 if (this->is_mesh_distributed())
29102 for (iface = 0; iface < nel; iface++)
29104 ele_face_pt = face_el_pt[iface];
29106 if (!done_ele[ele_face_pt])
29111 found_initial_face_element =
true;
29114 nsorted_face_elements++;
29118 sorted_el_pt.push_back(ele_face_pt);
29120 done_ele[ele_face_pt] =
true;
29127 #endif // #ifdef OOMPH_HAS_MPI 29131 ele_face_pt = face_el_pt[0];
29134 found_initial_face_element =
true;
29137 nsorted_face_elements++;
29141 sorted_el_pt.push_back(ele_face_pt);
29143 done_ele[ele_face_pt] =
true;
29144 #ifdef OOMPH_HAS_MPI 29149 if (!found_initial_face_element)
29151 std::ostringstream error_message;
29153 <<
"Could not find an initial face element for the current segment\n";
29155 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29156 OOMPH_EXCEPTION_LOCATION);
29161 const unsigned nnod = ele_face_pt->
nnode();
29166 Node* right_node_pt = ele_face_pt->
node_pt(nnod - 1);
29170 bool face_element_added =
false;
29180 for (
unsigned iiface=iface;iiface<nel;iiface++)
29183 face_element_added =
false;
29186 ele_face_pt = face_el_pt[iiface];
29190 if (!done_ele[ele_face_pt])
29193 Node* local_left_node_pt = ele_face_pt->node_pt(0);
29194 Node* local_right_node_pt = ele_face_pt->node_pt(nnod - 1);
29197 if (left_node_pt == local_right_node_pt)
29199 left_node_pt = local_left_node_pt;
29200 sorted_el_pt.push_front(ele_face_pt);
29201 is_inverted[ele_face_pt] =
false;
29202 face_element_added =
true;
29205 else if (left_node_pt == local_left_node_pt)
29207 left_node_pt = local_right_node_pt;
29208 sorted_el_pt.push_front(ele_face_pt);
29209 is_inverted[ele_face_pt] =
true;
29210 face_element_added =
true;
29213 else if (right_node_pt == local_left_node_pt)
29215 right_node_pt = local_right_node_pt;
29216 sorted_el_pt.push_back(ele_face_pt);
29217 is_inverted[ele_face_pt] =
false;
29218 face_element_added =
true;
29221 else if (right_node_pt == local_right_node_pt)
29223 right_node_pt = local_left_node_pt;
29224 sorted_el_pt.push_back(ele_face_pt);
29225 is_inverted[ele_face_pt] =
true;
29226 face_element_added =
true;
29229 if (face_element_added)
29232 done_ele[ele_face_pt] =
true;
29233 nsorted_face_elements++;
29241 }
while(face_element_added &&
29242 (nsorted_face_elements < nnon_halo_face_elements));
29245 segment_sorted_ele_pt.push_back(sorted_el_pt);
29250 const unsigned nsegments = segment_sorted_ele_pt.size();
29253 if (nnon_halo_face_elements > 0 && nsegments == 0)
29255 std::ostringstream error_message;
29257 <<
"The number of segments is zero, but the number of nonhalo\n" 29258 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
29260 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29261 OOMPH_EXCEPTION_LOCATION);
29270 tmp_segment_nodes.resize(nsegments);
29272 for (
unsigned is = 0; is < nsegments; is++)
29275 if (segment_sorted_ele_pt[is].size() == 0)
29277 std::ostringstream error_message;
29279 <<
"The (" << is <<
")-th segment has no elements\n";
29281 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29282 OOMPH_EXCEPTION_LOCATION);
29287 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
29290 const unsigned nnod = first_ele_pt->nnode();
29293 Node *first_node_pt = first_ele_pt->node_pt(0);
29294 if (is_inverted[first_ele_pt])
29296 first_node_pt = first_ele_pt->node_pt(nnod-1);
29300 tmp_segment_nodes[is].push_back(first_node_pt);
29303 for (std::list<FiniteElement*>::iterator it =
29304 segment_sorted_ele_pt[is].begin();
29305 it != segment_sorted_ele_pt[is].end(); it++)
29311 Node* last_node_pt = 0;
29314 if (!is_inverted[ele_pt])
29316 last_node_pt = ele_pt->node_pt(nnod-1);
29320 last_node_pt = ele_pt->node_pt(0);
29324 tmp_segment_nodes[is].push_back(last_node_pt);
29333 for (
unsigned e = 0;
e < nel;
e++)
29335 delete face_el_pt[
e];
29347 template <
class ELEMENT>
29359 double min_angle=compute_area_target(elem_error,
29365 bool quantised_areas=
true;
29366 if (quantised_areas)
29368 unsigned n=target_area.size();
29369 double total_area=0;
29375 #ifdef OOMPH_HAS_MPI 29376 if (this->is_mesh_distributed())
29380 double sub_area = 0.0;
29383 for (
unsigned e=0;
e<n;
e++)
29389 sub_area+=ele_pt->
size();
29397 MPI_Allreduce(&sub_area, &total_area, 1, MPI_DOUBLE, MPI_SUM,
29398 comm_pt->mpi_comm());
29402 for (
unsigned e=0;
e<n;
e++)
29404 total_area+=this->finite_element_pt(
e)->size();
29410 #else // #ifdef OOMPH_HAS_MPI 29411 for (
unsigned e=0;
e<n;
e++)
29413 total_area+=this->finite_element_pt(
e)->size();
29415 #endif // #ifdef OOMPH_HAS_MPI 29417 for (
unsigned e=0;
e<n;
e++)
29420 unsigned(ceil(log(target_area[
e]/total_area)/log(1.0/3.0)))-1;
29421 double new_target_area=total_area*pow(1.0/3.0,
int(level));
29422 target_area[
e]=new_target_area;
29432 unsigned n=target_area.size();
29433 double max_area=0.0;
29434 double min_area=DBL_MAX;
29435 for (
unsigned e=0;
e<n;
e++)
29437 if (target_area[
e]>max_area) max_area=target_area[
e];
29438 if (target_area[
e]<min_area) min_area=target_area[
e];
29453 oomph_info <<
"Maximum target area: " << max_area << std::endl;
29454 oomph_info <<
"Minimum target area: " << min_area << std::endl;
29455 oomph_info <<
"Number of elements to be refined: " 29456 << this->Nrefined << std::endl;
29457 oomph_info <<
"Number of elements to be unrefined: " 29458 << this->Nunrefined << std::endl;
29459 oomph_info <<
"Min. angle: " << min_angle << std::endl;
29461 double orig_max_area, orig_min_area;
29462 this->max_and_min_element_size(orig_max_area, orig_min_area);
29463 oomph_info <<
"Max./min. element size in original mesh: " 29464 << orig_max_area <<
" " 29465 << orig_min_area << std::endl;
29473 bool check_only=
true;
29474 bool outer_boundary_update_necessary=
false;
29475 bool inner_boundary_update_necessary=
false;
29476 bool inner_open_boundary_update_necessary=
false;
29480 const unsigned nouter=this->Outer_boundary_pt.size();
29482 if (this->is_automatic_creation_of_vertices_on_boundaries_allowed())
29485 for (
unsigned i_outer = 0; i_outer < nouter; i_outer++)
29487 outer_boundary_update_necessary=
29488 this->update_polygon_using_face_mesh(this->Outer_boundary_pt[i_outer],
29491 if (outer_boundary_update_necessary)
break;
29496 if (!outer_boundary_update_necessary)
29500 const unsigned nhole=this->Internal_polygon_pt.size();
29502 inner_boundary_update_necessary=
29503 this->surface_remesh_for_inner_hole_boundaries(internal_point_coord,
29508 if (!inner_boundary_update_necessary)
29510 const unsigned n_open_polyline =
29511 this->Internal_open_curve_pt.size();
29513 for (
unsigned i = 0;
i < n_open_polyline;
i++)
29515 inner_open_boundary_update_necessary=
29516 this->update_open_curve_using_face_mesh(
29517 this->Internal_open_curve_pt[
i], check_only);
29519 if (inner_open_boundary_update_necessary)
break;
29531 #ifdef OOMPH_HAS_MPI 29536 int adapt_this_processor = 0;
29537 if (this->is_mesh_distributed())
29540 if ( (Nrefined > 0) || (Nunrefined > max_keep_unrefined()) ||
29541 (min_angle < min_permitted_angle())
29542 || (outer_boundary_update_necessary)
29543 || (inner_boundary_update_necessary)
29544 || (inner_open_boundary_update_necessary) )
29545 {adapt_this_processor = 1;}
29551 MPI_Allreduce(&adapt_this_processor, &adapt_all, 1, MPI_INT, MPI_SUM,
29552 comm_pt->mpi_comm());
29560 if ( (Nrefined > 0) || (Nunrefined > max_keep_unrefined()) ||
29561 (min_angle < min_permitted_angle()) || (outer_boundary_update_necessary)
29562 || (inner_boundary_update_necessary)
29563 || (inner_open_boundary_update_necessary) || (adapt_all) )
29565 if (! ( (Nrefined > 0) || (Nunrefined > max_keep_unrefined()) ) )
29568 if ( (outer_boundary_update_necessary)
29569 || (inner_boundary_update_necessary)
29570 || (inner_open_boundary_update_necessary) )
29573 <<
"Mesh regeneration triggered by inaccurate interface/surface\n" 29574 <<
"representation; setting Nrefined to number of elements.\n" 29575 <<
"outer_boundary_update_necessary : " 29576 << outer_boundary_update_necessary <<
"\n" 29577 <<
"inner_boundary_update_necessary : " 29578 << inner_boundary_update_necessary <<
"\n" 29579 <<
"inner_open_boundary_update_necessary: " 29580 << inner_open_boundary_update_necessary <<
"\n";
29581 Nrefined=nelement();
29586 <<
"Mesh regeneration triggered by min angle criterion;\n" 29587 <<
"setting Nrefined to number of elements.\n";
29588 Nrefined=nelement();
29595 #ifdef OOMPH_HAS_MPI 29596 else if (this->is_mesh_distributed() &&
29597 adapt_this_processor == 0 && adapt_all > 0)
29600 <<
"Mesh regeneration triggered by (" << adapt_all <<
") processor(s) " 29601 <<
"that require(s)\n adaptation\n";
29616 add_vertices_for_non_deletion();
29621 #ifdef OOMPH_HAS_MPI 29626 if (this->is_mesh_distributed())
29628 synchronize_shared_boundary_connections();
29630 #endif // #ifdef OOMPH_HAS_MPI 29641 if (this->is_automatic_creation_of_vertices_on_boundaries_allowed())
29644 unsigned nhole=this->Internal_polygon_pt.size();
29646 this->surface_remesh_for_inner_hole_boundaries(internal_point_coord);
29649 for (
unsigned i_outer = 0; i_outer < nouter; i_outer++)
29651 this->update_polygon_using_face_mesh(
29652 this->Outer_boundary_pt[i_outer]);
29657 unsigned n_open_polyline = this->Internal_open_curve_pt.size();
29658 for (
unsigned i = 0;
i < n_open_polyline;
i++)
29660 this->update_open_curve_using_face_mesh(
29661 this->Internal_open_curve_pt[
i]);
29671 const unsigned ninternal=this->Internal_polygon_pt.size();
29672 for (
unsigned i_internal = 0; i_internal < ninternal; i_internal++)
29674 this->update_polygon_using_elements_area(
29675 this->Internal_polygon_pt[i_internal], target_area);
29680 for (
unsigned i_outer = 0; i_outer < nouter; i_outer++)
29682 this->update_polygon_using_elements_area(
29683 this->Outer_boundary_pt[i_outer], target_area);
29688 const unsigned n_open_polyline = this->Internal_open_curve_pt.size();
29689 for (
unsigned i = 0;
i < n_open_polyline;
i++)
29691 this->update_open_curve_using_elements_area(
29692 this->Internal_open_curve_pt[
i], target_area);
29703 #ifdef OOMPH_HAS_MPI 29705 if (this->is_mesh_distributed())
29708 const unsigned my_rank = this->communicator_pt()->my_rank();
29711 const unsigned n_curves = this->nshared_boundary_curves(my_rank);
29713 for (
unsigned nc = 0; nc < n_curves; nc ++)
29716 this->update_shared_curve_using_elements_area(
29717 this->Shared_boundary_polyline_pt[my_rank][nc],
29743 const unsigned n_boundary = this->nboundary();
29745 const double t_start_first_stage_segments_connectivity =
29751 #ifdef OOMPH_HAS_MPI 29754 if (this->is_mesh_distributed())
29756 this->Assigned_segments_initial_zeta_values.clear();
29758 #endif // #ifdef OOMPH_HAS_MPI 29764 for(
unsigned b=0;b<n_boundary;++b)
29769 #ifdef OOMPH_HAS_MPI 29770 if (this->is_mesh_distributed())
29777 compute_boundary_segments_connectivity_and_initial_zeta_values(b);
29785 if(this->boundary_geom_object_pt(b)==0)
29787 this->
template setup_boundary_coordinates<ELEMENT>(b);
29793 #ifdef OOMPH_HAS_MPI 29794 if (this->is_mesh_distributed())
29799 this->synchronize_boundary_coordinates(b);
29808 const double t_total_first_stage_segments_connectivity =
29819 #ifdef OOMPH_HAS_MPI 29834 if (this->is_mesh_distributed())
29838 this->create_distributed_domain_representation(tmp_outer_polygons_pt,
29839 tmp_open_curves_pt);
29842 this->create_temporary_boundary_connections(tmp_outer_polygons_pt,
29843 tmp_open_curves_pt);
29859 restore_boundary_connections(resume_initial_connection_polyline_pt,
29860 resume_final_connection_polyline_pt);
29866 unsigned n_region = this->nregion();
29870 this->Regions_coordinates.begin();
29871 it!=this->Regions_coordinates.end(); ++it)
29877 unsigned region_id = it->first;
29880 oomph_info <<
"Region " << region_id <<
": " 29881 << it->second[0] <<
" " << it->second[1] <<
" ";
29884 unsigned n_region_element = this->nregion_element(region_id);
29885 if(n_region_element > 0)
29888 FiniteElement*
const elem_pt = this->region_element_pt(region_id,0);
29891 for(
unsigned n=0;n<3;n++)
29894 for(
unsigned i=0;
i<2;
i++) {centroid[
i] += nod_pt->
x(
i);}
29896 for(
unsigned i=0;
i<2;
i++) {centroid[
i] /= 3;}
29898 it->second = centroid;
29901 it->second[0] <<
" " << it->second[1] << std::endl;
29929 #ifdef OOMPH_HAS_MPI 29930 if (!this->is_mesh_distributed())
29934 closed_curve_pt.resize(nouter);
29935 for (
unsigned i = 0;
i < nouter;
i++)
29937 closed_curve_pt[
i] = this->Outer_boundary_pt[
i];
29941 const unsigned n_holes = this->Internal_polygon_pt.size();
29942 hole_pt.resize(n_holes);
29943 for (
unsigned i = 0;
i < n_holes;
i++)
29945 hole_pt[
i] = this->Internal_polygon_pt[
i];
29949 const unsigned n_open_curves = this->Internal_open_curve_pt.size();
29950 open_curves_pt.resize(n_open_curves);
29951 for (
unsigned i = 0;
i < n_open_curves;
i++)
29953 open_curves_pt[
i] = this->Internal_open_curve_pt[
i];
29959 #ifdef OOMPH_HAS_MPI 29964 const unsigned n_tmp_outer = tmp_outer_polygons_pt.size();
29965 closed_curve_pt.resize(n_tmp_outer);
29966 for (
unsigned i = 0;
i < n_tmp_outer;
i++)
29968 closed_curve_pt[
i] = tmp_outer_polygons_pt[
i];
29972 const unsigned n_open_curves = tmp_open_curves_pt.size();
29973 open_curves_pt.resize(n_open_curves);
29974 for (
unsigned i = 0;
i < n_open_curves;
i++)
29976 open_curves_pt[
i] = tmp_open_curves_pt[
i];
30006 this->Extra_holes_coordinates;
30010 this->Regions_coordinates;
30013 if (this->Use_attributes)
30019 if (!this->is_automatic_creation_of_vertices_on_boundaries_allowed())
30026 #ifdef OOMPH_HAS_MPI 30027 if (this->is_mesh_distributed())
30038 const double t_start_building_background_mesh =
30041 if (solid_mesh_pt!=0)
30044 (triangle_mesh_parameters, this->Time_stepper_pt);
30049 (triangle_mesh_parameters, this->Time_stepper_pt);
30052 if (Print_timings_level_adaptation>2)
30054 oomph_info <<
"CPU for building background mesh: " 30061 const double this_max_element_size = this->max_element_size();
30062 const double this_min_element_size = this->min_element_size();
30067 const double this_min_permitted_angle = this->min_permitted_angle();
30073 #ifdef OOMPH_HAS_MPI 30077 if (this->is_mesh_distributed())
30081 if (this->nshared_boundary_overlaps_internal_boundary() > 0)
30086 this->shared_boundary_overlaps_internal_boundary();
30091 this->shared_boundaries_ids();
30096 fill_boundary_elements_and_nodes_for_internal_boundaries();
30101 #endif // #ifdef OOMPH_HAS_MPI 30112 this->boundary_geom_object_pt();
30117 this->boundary_coordinate_limits();
30119 const double t_start_second_stage_segments_connectivity =
30122 for (
unsigned b=0;b<n_boundary;b++)
30127 #ifdef OOMPH_HAS_MPI 30128 if (this->is_mesh_distributed())
30133 identify_boundary_segments_and_assign_initial_zeta_values(b,
this);
30144 tmp_new_mesh_pt->template setup_boundary_coordinates<ELEMENT>(b);
30149 const double t_total_second_stage_segments_connectivity =
30156 for(
unsigned b=0;b<n_boundary;b++)
30158 this->snap_nodes_onto_boundary(tmp_new_mesh_pt,b);
30161 const double t_total_snap_nodes_bg_mesh=
30164 if (Print_timings_level_adaptation>2)
30166 oomph_info<<
"CPU for snapping nodes onto boundaries " 30167 <<
"(background mesh): " 30168 << t_total_snap_nodes_bg_mesh << std::endl;
30172 if(Mesh_update_fct_pt!=0)
30174 Mesh_update_fct_pt(tmp_new_mesh_pt);
30207 bool use_eulerian_coords=
false;
30208 if (solid_mesh_pt!=0)
30210 use_eulerian_coords=
true;
30214 #ifdef OOMPH_HAS_CGAL 30218 if (use_eulerian_coords)
30228 if (use_eulerian_coords)
30233 bin_dim[0]=Nbin_x_for_area_transfer;
30234 bin_dim[1]=Nbin_y_for_area_transfer;
30242 std::map<GeneralisedElement*,unsigned> element_number;
30243 unsigned nelem=this->nelement();
30244 for (
unsigned e=0;
e<nelem;
e++)
30246 element_number[this->element_pt(
e)]=
e;
30249 #ifndef OOMPH_HAS_CGAL 30259 sample_point_container_pt());
30260 if (bin_array_pt==0)
30263 "Sample point container has to be NonRefineableBinArray",
30264 OOMPH_CURRENT_FUNCTION,
30265 OOMPH_EXCEPTION_LOCATION);
30270 unsigned max_n_entry=0;
30271 unsigned min_n_entry=UINT_MAX;
30272 unsigned tot_n_entry=0;
30273 unsigned n_empty=0;
30275 tot_n_entry,n_empty);
30278 <<
" nbin:("<<n_bin<<
")" 30279 <<
" nempty:("<<n_empty<<
")" 30280 <<
" min:("<<min_n_entry<<
")" 30281 <<
" max:("<<max_n_entry<<
")" 30282 <<
" average entries:(" 30283 << double(tot_n_entry)/double(n_bin)<<
")" 30289 oomph_info <<
"Going into diffusion bit...\n";
30291 oomph_info <<
"Back from diffusion bit...\n";
30299 unsigned max_n_entry=0;
30300 unsigned min_n_entry=UINT_MAX;
30301 unsigned tot_n_entry=0;
30302 unsigned n_empty=0;
30304 tot_n_entry,n_empty);
30307 <<
" nbin:("<<n_bin<<
")" 30308 <<
" nempty:("<<n_empty<<
")" 30309 <<
" min:("<<min_n_entry<<
")" 30310 <<
" max:("<<max_n_entry<<
")" 30311 <<
" average entries:(" 30312 << double(tot_n_entry)/double(n_bin)<<
")" 30320 double t_total_map=0.0;
30323 unsigned counter_map = 0;
30333 const unsigned n_bin=bins_pt->size();
30338 bin_min_target_area.resize(n_bin);
30339 for (
unsigned u=0;u<n_bin;u++)
30341 bin_min_target_area[u]=0.0;
30345 typedef std::map<unsigned,
30346 Vector<std::pair<FiniteElement*,
30348 for (IT it=bins_pt->begin();it!=bins_pt->end();it++)
30351 unsigned ib=(*it).first;
30354 const unsigned n_ele_bin = (*it).second.size();
30357 for (
unsigned ee=0;ee<n_ele_bin;ee++)
30362 const unsigned ele_number = element_number[ele_pt];
30371 if (bin_min_target_area[ib]!=0)
30373 bin_min_target_area[ib]=
30374 std::min(bin_min_target_area[ib], target_area[ele_number]);
30378 bin_min_target_area[ib]=target_area[ele_number];
30385 oomph_info <<
"CPU for map[counter="<<counter_map<<
"]: " 30386 << t_total_map << std::endl;
30390 const bool output_bins=
false;
30393 unsigned length=bin_min_target_area.size();
30394 for (
unsigned u = 0;u<length;u++)
30396 oomph_info <<
"Bin n" << u <<
",target area: " 30397 << bin_min_target_area[u]<<std::endl;
30408 #ifdef OOMPH_HAS_MPI 30410 unsigned n_ele_need_refinement = 0;
30414 double t_total_third_stage_segments_connectivity = 0.0;
30417 double t_total_transfer_target_areas = 0.0;
30420 double t_total_limit_target_areas = 0.0;
30423 double t_total_create_new_adapted_mesh = 0.0;
30426 double t_total_snap_nodes = 0.0;
30429 double t_total_wait_other_processors = 0.0;
30443 nelem=tmp_new_mesh_pt->
nelement();
30448 for (
unsigned e=0;
e<nelem;
e++)
30450 ELEMENT* el_pt=
dynamic_cast<ELEMENT*
>(tmp_new_mesh_pt->
element_pt(
e));
30451 unsigned nint=el_pt->integral_pt()->nweight();
30452 for (
unsigned ipt=0;ipt<nint;ipt++)
30456 for(
unsigned i=0;
i<2;
i++)
30458 s[
i] = el_pt->integral_pt()->knot(ipt,
i);
30462 el_pt->interpolated_x(s,x);
30469 unsigned max_sample_points=
30470 Max_sample_points_for_limited_locate_zeta_during_target_area_transfer;
30472 sample_point_container_pt())->
30473 limited_locate_zeta(x,max_sample_points,
30476 if (geom_obj_pt==0)
30478 std::stringstream error_message;
30480 <<
"Limited locate zeta failed for zeta = [ " 30481 << x[0] <<
" " << x[1] <<
" ]. Makes no sense!\n";
30483 OOMPH_CURRENT_FUNCTION,
30484 OOMPH_EXCEPTION_LOCATION);
30489 FiniteElement* fe_pt=
dynamic_cast<FiniteElement*
>(geom_obj_pt);
30493 std::stringstream error_message;
30495 <<
"Cast to FE for GeomObject returned by limited locate zeta failed for zeta = [ " 30496 << x[0] <<
" " << x[1] <<
" ]. Makes no sense!\n";
30498 OOMPH_CURRENT_FUNCTION,
30499 OOMPH_EXCEPTION_LOCATION);
30505 double tg_area=target_area[element_number[fe_pt]];
30512 if (new_transferred_target_area[
e]!=0)
30514 new_transferred_target_area[
e]=
30515 std::min(new_transferred_target_area[
e],
30520 new_transferred_target_area[
e]=tg_area;
30531 bin_array_pt->
get_bin(x,bin_number);
30537 std::stringstream error_message;
30539 <<
"Very odd -- we're looking for a point[ " 30540 << x[0] <<
" " << x[1] <<
" ] that's not even \n" 30541 <<
"located within the bin boundaries.\n";
30543 "RefineableTriangleMesh::adapt()",
30544 OOMPH_EXCEPTION_LOCATION);
30552 if (new_transferred_target_area[
e]!=0)
30554 new_transferred_target_area[
e]=
30555 std::min(new_transferred_target_area[
e],
30556 bin_min_target_area[bin_number]);
30560 new_transferred_target_area[
e]=bin_min_target_area[bin_number];
30573 const bool output_target_areas=
false;
30574 if (output_target_areas)
30576 unsigned length=new_transferred_target_area.size();
30577 for (
unsigned u = 0; u < length;u++)
30579 oomph_info <<
"Element" << u <<
",target area: " 30580 << new_transferred_target_area[u] << std::endl;
30583 oomph_info <<
"Time for loop over integration points in new mesh: " 30615 const double t_sub_total_transfer_target_areas =
30618 if (Print_timings_level_adaptation>2)
30621 const unsigned n_element = this->nelement();
30623 const unsigned n_element_background = tmp_new_mesh_pt->
nelement();
30625 oomph_info <<
"CPU for transfer of target areas " 30626 <<
"[n_ele_old_mesh=" 30627 << n_element <<
", n_ele_background_mesh=" 30628 << n_element_background<<
"] (iter "<< iter <<
"): " 30629 << t_sub_total_transfer_target_areas<< std::endl;
30633 t_total_transfer_target_areas+=t_sub_total_transfer_target_areas;
30647 #ifdef OOMPH_HAS_MPI 30648 unsigned n_ele_need_refinement_iter = 0;
30660 const unsigned nel_new=tmp_new_mesh_pt->
nelement();
30662 for (
unsigned e=0;
e<nel_new;
e++)
30668 const double new_area=new_transferred_target_area[
e];
30671 std::ostringstream error_stream;
30672 error_stream <<
"This shouldn't happen! Element whose centroid is at " 30675 f_ele_pt->
node_pt(2)->
x(0))/3.0 <<
" " 30678 f_ele_pt->
node_pt(2)->
x(1))/3.0 <<
" " 30679 <<
" has no target area assigned\n";
30681 OOMPH_CURRENT_FUNCTION,
30682 OOMPH_EXCEPTION_LOCATION);
30690 new_target_area[
e]=new_area;
30691 if (new_target_area[
e]<f_ele_pt->
size()/3.0)
30693 new_target_area[
e]=f_ele_pt->
size()/3.0;
30713 #ifdef OOMPH_HAS_MPI 30715 n_ele_need_refinement_iter++;
30726 const double t_sub_total_limit_target_areas =
30730 t_total_limit_target_areas+=t_sub_total_limit_target_areas;
30732 if (Print_timings_level_adaptation>2)
30735 const unsigned n_element = this->nelement();
30737 const unsigned n_element_background = tmp_new_mesh_pt->
nelement();
30739 oomph_info <<
"CPU for limiting target areas " 30740 <<
"[n_ele_old_mesh=" 30741 << n_element <<
", n_ele_background_mesh=" 30742 << n_element_background<<
"] (iter "<< iter <<
"): " 30743 << t_sub_total_limit_target_areas<< std::endl;
30749 <<
"All area adjustments accommodated by max. permitted area" 30750 <<
" reduction \n";
30755 <<
"NOT all area adjustments accommodated by max. " 30756 <<
"permitted area reduction \n";
30769 const double t_start_create_new_adapted_mesh =
30773 if (solid_mesh_pt!=0)
30777 tmp_new_triangulateio,
30778 this->Time_stepper_pt,
30779 this->Use_attributes,
30780 this->Allow_automatic_creation_of_vertices_on_boundaries,
30781 this->communicator_pt());
30788 tmp_new_triangulateio,
30789 this->Time_stepper_pt,
30790 this->Use_attributes,
30791 this->Allow_automatic_creation_of_vertices_on_boundaries,
30792 this->communicator_pt());
30796 const double t_sub_total_create_new_adapted_mesh =
30800 t_total_create_new_adapted_mesh+=t_sub_total_create_new_adapted_mesh;
30802 if (Print_timings_level_adaptation>2)
30805 const unsigned n_element_new_adapted_mesh = new_mesh_pt->
nelement();
30807 oomph_info <<
"CPU for creation of new adapted mesh " 30808 << t_sub_total_create_new_adapted_mesh
30809 <<
"[nele="<<n_element_new_adapted_mesh
30810 <<
"] (iter "<< iter <<
"): " 30811 << t_sub_total_create_new_adapted_mesh << std::endl;
30814 #ifdef OOMPH_HAS_MPI 30825 if (this->nshared_boundary_overlaps_internal_boundary() > 0)
30830 this->shared_boundary_overlaps_internal_boundary();
30835 this->shared_boundaries_ids();
30840 fill_boundary_elements_and_nodes_for_internal_boundaries();
30845 #endif // #ifdef OOMPH_HAS_MPI 30853 this->boundary_geom_object_pt();
30858 this->boundary_coordinate_limits();
30860 const double t_start_third_stage_segments_connectivity =
30863 for (
unsigned b=0;b<n_boundary;b++)
30872 #ifdef OOMPH_HAS_MPI 30873 if (this->is_mesh_distributed())
30878 identify_boundary_segments_and_assign_initial_zeta_values(b,
this);
30889 new_mesh_pt->template setup_boundary_coordinates<ELEMENT>(b);
30894 t_total_third_stage_segments_connectivity+=
30901 for(
unsigned b=0;b<n_boundary;b++)
30903 this->snap_nodes_onto_boundary(new_mesh_pt,b);
30906 const double t_sub_total_snap_nodes_new_mesh =
30910 t_total_snap_nodes+=t_sub_total_snap_nodes_new_mesh;
30912 if (Print_timings_level_adaptation>2)
30914 oomph_info <<
"CPU for snapping nodes onto boundaries (new mesh) " 30915 <<
"(iter "<<iter<<
"): " 30916 << t_sub_total_snap_nodes_new_mesh<< std::endl;
30920 if (Mesh_update_fct_pt!=0)
30922 Mesh_update_fct_pt(new_mesh_pt);
30929 if(dynamic_cast<GeneralisedTimeStepper*>(this->Time_stepper_pt))
30932 this->Time_stepper_pt,
false);
30938 delete tmp_new_mesh_pt;
30940 #ifdef OOMPH_HAS_MPI 30944 if (n_ele_need_refinement_iter == n_ele_need_refinement)
30948 n_ele_need_refinement = n_ele_need_refinement_iter;
30949 #endif // #ifdef OOMPH_HAS_MPI 30958 #ifdef OOMPH_HAS_MPI 30959 if (this->is_mesh_distributed())
30969 unsigned this_processor_requires_another_iteration = 1;
30972 if (done){this_processor_requires_another_iteration = 0;}
30973 int nproc_not_done = this_processor_requires_another_iteration;
30978 MPI_Allreduce(&this_processor_requires_another_iteration,
30980 MPI_UNSIGNED,MPI_SUM,comm_pt->mpi_comm());
30982 if (nproc_not_done > 0)
30984 oomph_info <<
"At least one processors requires further refinement. " 30985 <<
"Go for another iteration." << std::endl;
30991 const double t_sub_total_wait_other_processors =
30996 t_total_wait_other_processors+=t_sub_total_wait_other_processors;
30998 if (Print_timings_level_adaptation>2)
31000 oomph_info <<
"CPU for waiting other processors " 31001 <<
"(iter "<<iter<<
"): " 31002 << t_sub_total_wait_other_processors
31014 oomph_info <<
"Going for another iteration. Current iteration (" 31015 << iter <<
")" << std::endl;
31018 tmp_new_mesh_pt=new_mesh_pt;
31026 delete mesh_geom_obj_pt;
31028 oomph_info <<
"CPU for iterative generation of new mesh (TOTAL): " 31032 if (Print_timings_level_adaptation>1)
31034 oomph_info <<
"-- CPU for creating new adapted meshes (TOTAL): " 31035 << t_total_create_new_adapted_mesh << std::endl;
31037 oomph_info <<
"-- CPU for limiting target areas (TOTAL): " 31038 << t_total_limit_target_areas << std::endl;
31040 oomph_info <<
"-- CPU for transferring target areas (TOTAL): " 31041 << t_total_transfer_target_areas << std::endl;
31043 oomph_info <<
"-- CPU for waiting other processors (TOTAL): " 31044 << t_total_wait_other_processors << std::endl;
31056 if (!Disable_projection)
31062 if (Print_timings_projection)
31071 oomph_info <<
"About to begin projection.\n";
31080 #ifdef OOMPH_HAS_MPI 31081 if (this->is_mesh_distributed())
31089 Time* backed_up_time_pt = this->Time_stepper_pt->time_pt();
31099 project_problem_pt->
mesh_pt()=new_mesh_pt;
31104 if(!this->use_iterative_solver_for_projection())
31110 project_problem_pt->
project(
this);
31113 this->Time_stepper_pt->time_pt() = backed_up_time_pt;
31121 #endif // #ifdef OOMPH_HAS_MPI 31124 project_problem_pt->
mesh_pt()=new_mesh_pt;
31130 if(!this->use_iterative_solver_for_projection())
31136 project_problem_pt->
project(
this);
31140 if (Print_timings_projection)
31151 if (Print_timings_level_adaptation>1)
31154 const unsigned n_element = this->nelement();
31156 const unsigned n_element_new = new_mesh_pt->
nelement();
31157 oomph_info <<
"CPU for projection (in mesh adaptation) " 31158 <<
"[n_ele_old_mesh="<< n_element
31159 <<
", n_ele_new_mesh="<< n_element_new<<
"]: " 31160 << tt_projection << std::endl;
31165 #ifdef OOMPH_HAS_MPI 31166 if (this->is_mesh_distributed())
31170 unsigned n_this_element_new = n_element_new;
31171 unsigned n_max_element_new_global = 0;
31173 MPI_Reduce(&n_this_element_new, &n_max_element_new_global,
31174 1, MPI_UNSIGNED, MPI_MAX, 0,
31175 this->communicator_pt()->mpi_comm());
31178 double tt_this_projection = tt_projection;
31179 double tt_global_min_projection = 0.0;
31180 double tt_global_max_projection = 0.0;
31183 MPI_Reduce(&tt_this_projection, &tt_global_min_projection,
31184 1, MPI_DOUBLE, MPI_MIN, 0,
31185 this->communicator_pt()->mpi_comm());
31186 MPI_Reduce(&tt_this_projection, &tt_global_max_projection,
31187 1, MPI_DOUBLE, MPI_MAX, 0,
31188 this->communicator_pt()->mpi_comm());
31190 if (this->communicator_pt()->my_rank() == 0)
31192 oomph_info <<
"CPU for projection global (MIN): " 31193 << tt_global_min_projection << std::endl;
31194 oomph_info <<
"CPU for projection global (MAX) " 31195 <<
"[n_max_ele_new_global=" 31196 << n_max_element_new_global<<
"]: " 31197 << tt_global_max_projection << std::endl;
31199 std::cerr <<
"CPU for projection global (MIN): " 31200 << tt_global_min_projection << std::endl;
31201 std::cerr <<
"CPU for projection global (MAX): " 31202 <<
"[n_max_ele_new_global=" 31203 << n_max_element_new_global<<
"]: " 31204 << tt_global_max_projection << std::endl;
31209 #endif // #ifdef OOMPH_HAS_MPI 31216 oomph_info <<
"CPU for projection of solution onto new mesh: " 31221 delete project_problem_pt;
31226 oomph_info <<
"Projection disabled! The new mesh will contain zeros" 31237 unsigned nnod=nnode();
31238 for(
unsigned j=nnod;j>0;j--)
31240 delete Node_pt[j-1];
31243 unsigned nel=nelement();
31244 for(
unsigned e=nel;
e>0;
e--)
31246 delete Element_pt[
e-1];
31247 Element_pt[
e-1] = 0;
31252 nnod=new_mesh_pt->
nnode();
31253 Node_pt.resize(nnod);
31255 Element_pt.resize(nel);
31256 for(
unsigned j=0;j<nnod;j++)
31258 Node_pt[j] = new_mesh_pt->
node_pt(j);
31260 for(
unsigned e=0;
e<nel;
e++)
31267 unsigned nbound = 0;
31269 #ifdef OOMPH_HAS_MPI 31273 if (this->is_mesh_distributed())
31287 nbound = n_boundary;
31290 Boundary_element_pt.resize(nbound);
31291 Face_index_at_boundary.resize(nbound);
31292 Boundary_node_pt.resize(nbound);
31293 for (
unsigned b=0;b<nbound;b++)
31296 Boundary_element_pt[b].resize(nel);
31297 Face_index_at_boundary[b].resize(nel);
31298 for (
unsigned e=0;
e<nel;
e++)
31304 Boundary_node_pt[b].resize(nnod);
31305 for (
unsigned j=0;j<nnod;j++)
31312 unsigned n_region = new_mesh_pt->
nregion();
31317 this->Region_attribute.resize(n_region);
31318 for(
unsigned r=0;r<n_region;r++)
31322 unsigned r_id =
static_cast<unsigned>(this->Region_attribute[r]);
31325 this->Region_element_pt[r_id].resize(n_region_element);
31326 for(
unsigned e=0;
e<n_region_element;
e++)
31328 this->Region_element_pt[r_id][
e] =
31334 this->Boundary_region_element_pt.resize(nbound);
31335 this->Face_index_region_at_boundary.resize(nbound);
31338 for(
unsigned b=0;b<nbound;++b)
31340 for (
unsigned rr = 0 ; rr < n_region; rr++)
31343 unsigned r =
static_cast<unsigned>(this->Region_attribute[rr]);
31345 unsigned n_boundary_el_in_region =
31348 if(n_boundary_el_in_region > 0)
31351 this->Boundary_region_element_pt[b][r].
31352 resize(n_boundary_el_in_region);
31353 this->Face_index_region_at_boundary[b][r].
31354 resize(n_boundary_el_in_region);
31357 for(
unsigned e=0;
e<n_boundary_el_in_region;++
e)
31359 this->Boundary_region_element_pt[b][r][
e]
31361 this->Face_index_region_at_boundary[b][r][
e]
31375 #ifdef OOMPH_HAS_MPI 31376 if (this->is_mesh_distributed())
31381 if (this->is_mesh_distributed())
31383 this->Halo_node_pt.clear();
31384 this->Root_halo_element_pt.clear();
31386 this->Haloed_node_pt.clear();
31387 this->Root_haloed_element_pt.clear();
31389 this->External_halo_node_pt.clear();
31390 this->External_halo_element_pt.clear();
31392 this->External_haloed_node_pt.clear();
31393 this->External_haloed_element_pt.clear();
31398 this->reset_shared_boundary_elements_and_nodes();
31409 this->shared_boundaries_in_this_processor(my_rank_shared_boundaries_ids);
31412 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
31415 for (
unsigned i = 0;
i < nmy_rank_shd_bnd;
i++)
31418 const unsigned shd_bnd_id = my_rank_shared_boundaries_ids[
i];
31421 this->Boundary_element_pt[shd_bnd_id].clear();
31425 const unsigned tmp_nnodes =
31426 this->nshared_boundary_node(shd_bnd_id);
31427 for (
unsigned n = 0; n < tmp_nnodes; n++)
31429 Node* tmp_node_pt = this->boundary_node_pt(shd_bnd_id, n);
31436 this->set_nboundary(n_boundary);
31440 this->sort_nodes_on_shared_boundaries();
31443 this->reset_halo_haloed_scheme();
31447 for (
unsigned b = 0; b < n_boundary; b++)
31449 if (this->boundary_geom_object_pt(b)!=0)
31452 this->set_nboundary_segment_node(b, nsegments);
31457 resume_boundary_connections(resume_initial_connection_polyline_pt,
31458 resume_final_connection_polyline_pt);
31462 #endif // #ifdef OOMPH_HAS_MPI 31469 this->snap_nodes_onto_geometric_objects();
31477 this->Triangulateio=
31485 delete new_mesh_pt;
31488 if (Print_timings_level_adaptation>2)
31492 oomph_info <<
"CPU for segments connectivity (first stage) [sec]: " 31493 << t_total_first_stage_segments_connectivity << std::endl;
31494 oomph_info <<
"CPU for segments connectivity (second stage) [sec]: " 31495 << t_total_second_stage_segments_connectivity << std::endl;
31496 oomph_info <<
"CPU for segments connectivity (third stage) [sec]: " 31497 << t_total_third_stage_segments_connectivity << std::endl;
31500 if (Print_timings_level_adaptation>1)
31502 const double t_total_segments_connectivity =
31503 t_total_first_stage_segments_connectivity +
31504 t_total_second_stage_segments_connectivity +
31505 t_total_third_stage_segments_connectivity;
31507 oomph_info <<
"CPU for segments connectivity (TOTAL) [sec]: " 31508 << t_total_segments_connectivity << std::endl;
31510 if (Print_timings_level_adaptation>2)
31513 oomph_info <<
"CPU for snapping nodes onto boundaries " 31515 << t_total_snap_nodes << std::endl;
31518 t_total_snap_nodes+=t_total_snap_nodes_bg_mesh;
31519 oomph_info <<
"CPU for snapping nodes onto boundaries (TOTAL): " 31520 << t_total_snap_nodes << std::endl;
31523 double max_area=0.0;
31524 double min_area=0.0;
31526 this->max_and_min_element_size(max_area, min_area);
31527 oomph_info <<
"Max/min element size in adapted mesh: " 31529 << min_area << std::endl;
31531 oomph_info <<
"CPU time for final bits [sec]: " 31537 oomph_info <<
"Not enough benefit in adaptation.\n";
31543 oomph_info <<
"CPU time for adaptation [sec]: " 31544 << CPU_for_adaptation << std::endl;
31549 #ifdef OOMPH_HAS_MPI 31550 if (this->is_mesh_distributed())
31555 const unsigned n_proc = comm_pt->nproc();
31556 if (Print_timings_level_adaptation>1 && n_proc>1)
31558 double global_min_CPU_for_adaptation = 0.0;
31559 double global_max_CPU_for_adaptation = 0.0;
31560 double global_average_CPU_for_adaptation = 0.0;
31563 MPI_Reduce(&CPU_for_adaptation, &global_min_CPU_for_adaptation,
31564 1, MPI_DOUBLE, MPI_MIN, 0, comm_pt->mpi_comm());
31565 MPI_Reduce(&CPU_for_adaptation, &global_max_CPU_for_adaptation,
31566 1, MPI_DOUBLE, MPI_MAX, 0, comm_pt->mpi_comm());
31567 MPI_Reduce(&CPU_for_adaptation, &global_average_CPU_for_adaptation,
31568 1, MPI_DOUBLE, MPI_SUM, 0, comm_pt->mpi_comm());
31571 const unsigned my_rank = comm_pt->my_rank();
31575 << global_min_CPU_for_adaptation << std::endl;
31577 << global_max_CPU_for_adaptation << std::endl;
31578 oomph_info <<
"CPU for adaptation (AVERAGE): " 31579 << global_average_CPU_for_adaptation/n_proc << std::endl;
31590 #endif // #ifdef OOMPH_HAS_MPI 31601 template<
class ELEMENT>
31606 Boundary_connections_pt.clear();
31613 std::set<unsigned> boundary_id_with_connections;
31620 const unsigned n_outer_boundaries = this->Outer_boundary_pt.size();
31623 for (
unsigned i = 0;
i < n_outer_boundaries;
i++)
31629 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
31631 for (
unsigned p = 0; p < n_polyline; p++)
31641 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
31645 boundary_id_with_connections.insert(bnd_id);
31648 const unsigned dst_bnd_id =
31653 boundary_id_with_connections.insert(dst_bnd_id);
31661 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
31665 boundary_id_with_connections.insert(bnd_id);
31668 const unsigned dst_bnd_id =
31673 boundary_id_with_connections.insert(dst_bnd_id);
31686 const unsigned n_internal_boundaries = this->Internal_polygon_pt.size();
31689 for (
unsigned i = 0;
i < n_internal_boundaries;
i++)
31695 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
31697 for (
unsigned p = 0; p < n_polyline; p++)
31707 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
31711 boundary_id_with_connections.insert(bnd_id);
31714 const unsigned dst_bnd_id =
31719 boundary_id_with_connections.insert(dst_bnd_id);
31727 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
31731 boundary_id_with_connections.insert(bnd_id);
31734 const unsigned dst_bnd_id =
31739 boundary_id_with_connections.insert(dst_bnd_id);
31752 const unsigned n_open_boundaries = this->Internal_open_curve_pt.size();
31755 for (
unsigned i = 0;
i < n_open_boundaries;
i++)
31759 this->Internal_open_curve_pt[
i];
31763 const unsigned n_curve_section = tmp_open_curve_pt->
ncurve_section();
31766 for (
unsigned p = 0; p < n_curve_section; p++)
31777 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
31781 boundary_id_with_connections.insert(bnd_id);
31784 const unsigned dst_bnd_id =
31789 boundary_id_with_connections.insert(dst_bnd_id);
31797 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
31801 boundary_id_with_connections.insert(bnd_id);
31804 const unsigned dst_bnd_id =
31809 boundary_id_with_connections.insert(dst_bnd_id);
31817 #ifdef OOMPH_HAS_MPI 31824 if (this->is_mesh_distributed())
31827 const unsigned my_rank = this->communicator_pt()->my_rank();
31830 const unsigned n_shared_curves =
31831 this->nshared_boundary_curves(my_rank);
31834 for (
unsigned i = 0;
i < n_shared_curves;
i ++)
31838 const unsigned n_polyline =
31839 this->nshared_boundary_polyline(my_rank,
i);
31843 for (
unsigned p = 0; p < n_polyline; p++)
31847 this->shared_boundary_polyline_pt(my_rank,
i, p);
31853 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
31857 boundary_id_with_connections.insert(bnd_id);
31860 const unsigned dst_bnd_id =
31865 boundary_id_with_connections.insert(dst_bnd_id);
31873 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
31877 boundary_id_with_connections.insert(bnd_id);
31880 const unsigned dst_bnd_id =
31885 boundary_id_with_connections.insert(dst_bnd_id);
31895 #endif // #ifdef OOMPH_HAS_MPI 31903 std::map<unsigned, Vector<Vector<Node*> > > bnd_sorted_segment_node_pt;
31906 for (std::set<unsigned>::iterator it =
31907 boundary_id_with_connections.begin();
31908 it != boundary_id_with_connections.end(); it++)
31911 const unsigned bnd_id = (*it);
31912 #ifdef OOMPH_HAS_MPI 31914 if (this->is_mesh_distributed())
31917 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
31919 if (bnd_id >= init_shd_bnd_id)
31927 get_shared_boundary_segment_nodes_helper(bnd_id,
31928 tmp_shared_nodes_pt);
31931 bnd_sorted_segment_node_pt[bnd_id] = tmp_shared_nodes_pt;
31942 get_boundary_segment_nodes_helper(bnd_id,
31943 tmp_boundary_nodes_pt);
31946 bnd_sorted_segment_node_pt[bnd_id] = tmp_boundary_nodes_pt;
31952 #endif // #ifdef OOMPH_HAS_MPI 31960 get_boundary_segment_nodes_helper(bnd_id,
31961 tmp_boundary_nodes_pt);
31964 bnd_sorted_segment_node_pt[bnd_id] = tmp_boundary_nodes_pt;
31978 for (
unsigned i = 0;
i < n_outer_boundaries;
i++)
31984 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
31986 for (
unsigned p = 0; p < n_polyline; p++)
31996 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
31999 const unsigned dst_bnd_id =
32003 const unsigned dst_chunk =
32008 bnd_sorted_segment_node_pt[bnd_id];
32012 bnd_sorted_segment_node_pt[dst_bnd_id];
32016 add_non_delete_vertices_from_boundary_helper(
32017 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32025 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32028 const unsigned dst_bnd_id =
32032 const unsigned dst_chunk =
32037 bnd_sorted_segment_node_pt[bnd_id];
32041 bnd_sorted_segment_node_pt[dst_bnd_id];
32045 add_non_delete_vertices_from_boundary_helper(
32046 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32058 for (
unsigned i = 0;
i < n_internal_boundaries;
i++)
32064 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
32066 for (
unsigned p = 0; p < n_polyline; p++)
32076 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32079 const unsigned dst_bnd_id =
32083 const unsigned dst_chunk =
32088 bnd_sorted_segment_node_pt[bnd_id];
32092 bnd_sorted_segment_node_pt[dst_bnd_id];
32096 add_non_delete_vertices_from_boundary_helper(
32097 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32105 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32108 const unsigned dst_bnd_id =
32112 const unsigned dst_chunk =
32117 bnd_sorted_segment_node_pt[bnd_id];
32121 bnd_sorted_segment_node_pt[dst_bnd_id];
32125 add_non_delete_vertices_from_boundary_helper(
32126 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32138 for (
unsigned i = 0;
i < n_open_boundaries;
i++)
32142 this->Internal_open_curve_pt[
i];
32146 const unsigned n_curve_section = tmp_open_curve_pt->
ncurve_section();
32149 for (
unsigned p = 0; p < n_curve_section; p++)
32160 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32163 const unsigned dst_bnd_id =
32167 const unsigned dst_chunk =
32172 bnd_sorted_segment_node_pt[bnd_id];
32176 bnd_sorted_segment_node_pt[dst_bnd_id];
32180 add_non_delete_vertices_from_boundary_helper(
32181 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32189 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32192 const unsigned dst_bnd_id =
32196 const unsigned dst_chunk =
32201 bnd_sorted_segment_node_pt[bnd_id];
32205 bnd_sorted_segment_node_pt[dst_bnd_id];
32209 add_non_delete_vertices_from_boundary_helper(
32210 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32218 #ifdef OOMPH_HAS_MPI 32225 if (this->is_mesh_distributed())
32228 const unsigned my_rank = this->communicator_pt()->my_rank();
32231 const unsigned n_shared_curves =
32232 this->nshared_boundary_curves(my_rank);
32235 for (
unsigned i = 0;
i < n_shared_curves;
i ++)
32239 const unsigned n_polyline =
32240 this->nshared_boundary_polyline(my_rank,
i);
32244 for (
unsigned p = 0; p < n_polyline; p++)
32248 this->shared_boundary_polyline_pt(my_rank,
i, p);
32254 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32257 const unsigned dst_bnd_id =
32261 const unsigned dst_chunk =
32266 bnd_sorted_segment_node_pt[bnd_id];
32270 bnd_sorted_segment_node_pt[dst_bnd_id];
32274 add_non_delete_vertices_from_boundary_helper(
32275 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32283 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32286 const unsigned dst_bnd_id =
32290 const unsigned dst_chunk =
32295 bnd_sorted_segment_node_pt[bnd_id];
32299 bnd_sorted_segment_node_pt[dst_bnd_id];
32303 add_non_delete_vertices_from_boundary_helper(
32304 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32314 #endif // #ifdef OOMPH_HAS_MPI 32323 template<
class ELEMENT>
32328 const unsigned &dst_bnd_id,
const unsigned &dst_bnd_chunk)
32331 const unsigned n_seg = src_bound_segment_node_pt.size();
32333 for (
unsigned iseg = 0; iseg < n_seg; iseg++)
32336 const unsigned nnode = src_bound_segment_node_pt[iseg].size();
32338 Node* left_node_pt = src_bound_segment_node_pt[iseg][0];
32339 Node* right_node_pt = src_bound_segment_node_pt[iseg][nnode-1];
32342 const unsigned n_dst_seg = dst_bound_segment_node_pt.size();
32344 for (
unsigned jseg = 0; jseg < n_dst_seg; jseg++)
32347 const unsigned n_dst_node = dst_bound_segment_node_pt[jseg].size();
32350 for (
unsigned jnode = 0; jnode < n_dst_node; jnode++)
32354 Node* tmp_node_pt = dst_bound_segment_node_pt[jseg][jnode];
32357 if (tmp_node_pt == left_node_pt)
32361 vertex[0] = tmp_node_pt->
x(0);
32362 vertex[1] = tmp_node_pt->
x(1);
32368 Boundary_connections_pt[dst_bnd_id].insert(vertex);
32376 else if (tmp_node_pt == right_node_pt)
32380 vertex[0] = tmp_node_pt->
x(0);
32381 vertex[1] = tmp_node_pt->
x(1);
32389 Boundary_connections_pt[dst_bnd_id].insert(vertex);
32404 #ifdef OOMPH_HAS_MPI 32410 template<
class ELEMENT>
32415 const unsigned nproc = this->communicator_pt()->nproc();
32417 const unsigned my_rank = this->communicator_pt()->my_rank();
32420 for (
unsigned jproc = 0; jproc < nproc; jproc++)
32425 const unsigned n_shd_bnd_jproc =
32426 this->nshared_boundaries(my_rank, jproc);
32430 if (jproc != my_rank && n_shd_bnd_jproc > 0)
32450 this->shared_boundaries_ids(my_rank, jproc);
32453 const unsigned n_shd_bnd_jproc = shd_bnd_ids.size();
32455 for (
unsigned ishd_bnd=0;ishd_bnd<n_shd_bnd_jproc;ishd_bnd++)
32458 const unsigned shd_bnd_id = shd_bnd_ids[ishd_bnd];
32461 this->boundary_polyline_pt(shd_bnd_id);
32466 std::set<Vector<double> > no_delete_vertex;
32469 const bool boundary_receive_connections =
32470 this->boundary_connections(shd_bnd_id, chunk,
32474 const unsigned n_non_delete_vertex = no_delete_vertex.size();
32477 if (boundary_receive_connections && n_non_delete_vertex > 0)
32480 shd_bnd_id_for_non_deletion.push_back(shd_bnd_id);
32482 chunk_for_non_deletion.push_back(chunk);
32484 number_vertices_non_deletion.push_back(n_non_delete_vertex);
32491 no_delete_vertex.begin();
32492 it != no_delete_vertex.end(); it++)
32496 tmp_vertices.push_back(vertex);
32500 vertices_for_non_deletion.push_back(tmp_vertices);
32518 MPI_Request request;
32524 const unsigned n_shd_bnd_with_non_delete_vertices =
32525 shd_bnd_id_for_non_deletion.size();
32528 const unsigned size_package = 3;
32530 const unsigned n_unsigned_data_to_send =
32531 n_shd_bnd_with_non_delete_vertices*size_package;
32541 for (
unsigned i=0;
i<n_shd_bnd_with_non_delete_vertices;
i++)
32544 flat_package_unsigned_send[j++] =
32545 shd_bnd_id_for_non_deletion[
i];
32547 flat_package_unsigned_send[j++] =
32548 chunk_for_non_deletion[
i];
32550 flat_package_unsigned_send[j++] =
32551 number_vertices_non_deletion[
i];
32553 const unsigned n_vertices_non_deletion =
32554 number_vertices_non_deletion[
i];
32557 for (
unsigned h=0;h<n_vertices_non_deletion;h++)
32559 flat_package_double_send.push_back(
32560 vertices_for_non_deletion[
i][h][0]);
32561 flat_package_double_send.push_back(
32562 vertices_for_non_deletion[
i][h][1]);
32568 int send_proc = jproc;
32569 int recv_proc = jproc;
32570 unsigned send_count_unsigned_values = n_unsigned_data_to_send;
32571 unsigned send_count_double_values = flat_package_double_send.size();
32576 MPI_Isend(&send_count_unsigned_values,1,MPI_UNSIGNED,
32577 send_proc,1,comm_pt->mpi_comm(),&request);
32579 unsigned receive_count_unsigned_values=0;
32580 MPI_Recv(&receive_count_unsigned_values,1,MPI_UNSIGNED,
32581 recv_proc,1,comm_pt->mpi_comm(),&status);
32583 MPI_Wait(&request,MPI_STATUS_IGNORE);
32586 if (send_count_unsigned_values!=0)
32588 MPI_Isend(&flat_package_unsigned_send[0],
32589 send_count_unsigned_values,MPI_UNSIGNED,
32590 send_proc,2,comm_pt->mpi_comm(),&request);
32594 if (receive_count_unsigned_values!=0)
32596 flat_package_unsigned_recv.resize(receive_count_unsigned_values);
32597 MPI_Recv(&flat_package_unsigned_recv[0],
32598 receive_count_unsigned_values,
32599 MPI_UNSIGNED,recv_proc,2,comm_pt->mpi_comm(),&status);
32604 if (send_count_unsigned_values!=0)
32606 MPI_Wait(&request,MPI_STATUS_IGNORE);
32611 MPI_Isend(&send_count_double_values,1,MPI_UNSIGNED,
32612 send_proc,1,comm_pt->mpi_comm(),&request);
32614 unsigned receive_count_double_values=0;
32615 MPI_Recv(&receive_count_double_values,1,MPI_UNSIGNED,
32616 recv_proc,1,comm_pt->mpi_comm(),&status);
32618 MPI_Wait(&request,MPI_STATUS_IGNORE);
32621 if (send_count_double_values!=0)
32623 MPI_Isend(&flat_package_double_send[0],
32624 send_count_double_values,MPI_DOUBLE,
32625 send_proc,2,comm_pt->mpi_comm(),&request);
32629 if (receive_count_double_values!=0)
32631 flat_package_double_recv.resize(receive_count_double_values);
32632 MPI_Recv(&flat_package_double_recv[0],
32633 receive_count_double_values,
32634 MPI_DOUBLE,recv_proc,2,comm_pt->mpi_comm(),&status);
32639 if (send_count_double_values!=0)
32641 MPI_Wait(&request,MPI_STATUS_IGNORE);
32669 for (
unsigned i=0;
i<receive_count_unsigned_values;
i+=3)
32672 const unsigned recv_shd_bnd_id =
32673 flat_package_unsigned_recv[
i];
32674 recv_shd_bnd_id_for_non_deletion.push_back(recv_shd_bnd_id);
32676 const unsigned recv_chunk =
32677 flat_package_unsigned_recv[
i+1];
32678 recv_chunk_for_non_deletion.push_back(recv_chunk);
32680 const unsigned recv_num_vertices =
32681 flat_package_unsigned_recv[
i+2];
32682 recv_number_vertices_non_deletion.push_back(recv_num_vertices);
32687 for (
unsigned h=0;h<recv_num_vertices;h++)
32690 tmp_vertex[0] = flat_package_double_recv[j++];
32691 tmp_vertex[1] = flat_package_double_recv[j++];
32693 temp_recv_vertices.push_back(tmp_vertex);
32697 recv_vertices_for_non_deletion.push_back(temp_recv_vertices);
32712 const unsigned n_recv_shd_bnd_id_for_non_deletion =
32713 recv_shd_bnd_id_for_non_deletion.size();
32716 for (
unsigned i=0;
i<n_recv_shd_bnd_id_for_non_deletion;
i++)
32719 const unsigned shd_bnd_id =
32720 recv_shd_bnd_id_for_non_deletion[
i];
32722 unsigned chunk = recv_chunk_for_non_deletion[
i];
32729 const unsigned n_vertices =
32730 recv_number_vertices_non_deletion[
i];
32732 for (
unsigned h=0;h<n_vertices;h++)
32736 vertex[0] = recv_vertices_for_non_deletion[
i][h][0];
32737 vertex[1] = recv_vertices_for_non_deletion[
i][h][1];
32742 Boundary_connections_pt[shd_bnd_id].insert(vertex);
32753 #endif // #ifdef OOMPH_HAS_MPI 32760 template<
class ELEMENT>
32770 dummy_resume_initial_connection_polyline_pt.clear();
32771 dummy_resume_final_connection_polyline_pt.clear();
32775 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
32793 const unsigned n_outer_boundaries = tmp_outer_polygons_pt.size();
32796 for (
unsigned i = 0;
i < n_outer_boundaries;
i++)
32802 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
32804 for (
unsigned p = 0; p < n_polyline; p++)
32811 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32814 if (bnd_id < init_shd_bnd_id)
32817 restore_polyline_connections_helper(
32819 dummy_resume_initial_connection_polyline_pt,
32820 dummy_resume_final_connection_polyline_pt);
32837 const unsigned n_open_boundaries = tmp_open_curves_pt.size();
32840 for (
unsigned i = 0;
i < n_open_boundaries;
i++)
32847 const unsigned n_curve_section = tmp_open_curve_pt->
ncurve_section();
32850 for (
unsigned p = 0; p < n_curve_section; p++)
32858 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32861 if (bnd_id < init_shd_bnd_id)
32864 restore_polyline_connections_helper(
32866 dummy_resume_initial_connection_polyline_pt,
32867 dummy_resume_final_connection_polyline_pt);
32887 template<
class ELEMENT>
32893 resume_initial_connection_polyline_pt.clear();
32894 resume_final_connection_polyline_pt.clear();
32905 const unsigned n_outer_boundaries = this->Outer_boundary_pt.size();
32908 for (
unsigned i = 0;
i < n_outer_boundaries;
i++)
32914 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
32916 for (
unsigned p = 0; p < n_polyline; p++)
32923 restore_polyline_connections_helper(
32925 resume_initial_connection_polyline_pt,
32926 resume_final_connection_polyline_pt);
32937 const unsigned n_internal_boundaries = this->Internal_polygon_pt.size();
32940 for (
unsigned i = 0;
i < n_internal_boundaries;
i++)
32946 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
32948 for (
unsigned p = 0; p < n_polyline; p++)
32955 restore_polyline_connections_helper(
32957 resume_initial_connection_polyline_pt,
32958 resume_final_connection_polyline_pt);
32969 const unsigned n_open_boundaries = this->Internal_open_curve_pt.size();
32972 for (
unsigned i = 0;
i < n_open_boundaries;
i++)
32976 this->Internal_open_curve_pt[
i];
32980 const unsigned n_curve_section = tmp_open_curve_pt->
ncurve_section();
32983 for (
unsigned p = 0; p < n_curve_section; p++)
32991 restore_polyline_connections_helper(
32993 resume_initial_connection_polyline_pt,
32994 resume_final_connection_polyline_pt);
33010 template<
class ELEMENT>
33028 const unsigned dst_bnd_id_initial =
33037 #ifdef OOMPH_HAS_MPI 33038 if (this->is_mesh_distributed())
33041 const unsigned init_shd_bnd_id =
33042 this->initial_shared_boundary_id();
33044 if (dst_bnd_id_initial >= init_shd_bnd_id)
33047 const unsigned bnd_id = polyline_pt->
boundary_id();
33048 std::ostringstream error_message;
33050 <<
"INITIAL VERTEX CONNECTION\n" 33051 <<
"The current original boundary is trying to connect to a\n" 33052 <<
"shared boundary, this is not allowed. In this case the\n" 33053 <<
"shared boundary should be the one that connects with the\n" 33054 <<
"original boundary\n" 33055 <<
"The current original boundary (" << bnd_id <<
") is marked\n" 33056 <<
"to have a connection at the\nINITIAL vertex (" 33057 << src_vertex_coordinates_initial[0] <<
"," 33058 << src_vertex_coordinates_initial[1] <<
")\n" 33059 <<
"with the shared boundary ("<< dst_bnd_id_initial <<
")\n" 33060 <<
"This is the list of vertices on the shared destination boundary\n";
33064 this->boundary_polyline_pt(dst_bnd_id_initial);
33066 const unsigned n_vertex_dst_boundary = dst_polyline->
nvertex();
33068 for (
unsigned i = 0;
i < n_vertex_dst_boundary;
i++)
33073 << current_vertex[0] <<
", " << current_vertex[1] <<
")\n";
33076 error_message.str(),
33077 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33078 OOMPH_EXCEPTION_LOCATION);
33082 #endif // #ifdef OOMPH_HAS_MPI 33084 #endif // #ifdef PARANOID 33088 bool found_vertex_on_dst_boundary_initial =
false;
33092 unsigned sub_poly_to_connect = 0;
33095 unsigned n_vertex_connection_initial = 0;
33100 bool connecting_to_an_split_boundary =
false;
33104 bool connecting_to_an_overlaped_boundary =
false;
33106 #ifdef OOMPH_HAS_MPI 33107 if (this->is_mesh_distributed())
33112 if (this->boundary_was_splitted(dst_bnd_id_initial))
33114 connecting_to_an_split_boundary =
true;
33123 if (connecting_to_an_split_boundary)
33127 const unsigned n_sub_poly =
33128 this->nboundary_subpolylines(dst_bnd_id_initial);
33132 for (
unsigned ii =0; ii < n_sub_poly; ii++)
33135 boundary_marked_as_shared_boundary(dst_bnd_id_initial, ii))
33139 connecting_to_an_overlaped_boundary =
true;
33151 boundary_marked_as_shared_boundary(dst_bnd_id_initial, 0))
33154 connecting_to_an_overlaped_boundary =
true;
33160 #endif // #ifdef OOMPH_HAS_MPI 33165 if (!(connecting_to_an_split_boundary ||
33166 connecting_to_an_overlaped_boundary))
33170 poly_to_connect_pt = this->boundary_polyline_pt(dst_bnd_id_initial);
33180 if (!connecting_to_an_split_boundary)
33184 if (!connecting_to_an_overlaped_boundary)
33188 found_vertex_on_dst_boundary_initial =
33189 this->get_connected_vertex_number_on_destination_polyline(
33190 poly_to_connect_pt,
33191 src_vertex_coordinates_initial,
33192 n_vertex_connection_initial);
33205 #ifdef OOMPH_HAS_MPI 33213 this->boundary_subpolylines(dst_bnd_id_initial);
33216 const unsigned nsub_poly = tmp_vector_subpolylines.size();
33218 if (nsub_poly <= 1)
33220 std::ostringstream error_message;
33222 <<
"The boundary (" << dst_bnd_id_initial <<
") was " 33223 <<
"marked to be splitted but\n" 33224 <<
"there are only ("<<nsub_poly<<
") polylines to " 33225 <<
"represent it.\n";
33227 error_message.str(),
33228 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33229 OOMPH_EXCEPTION_LOCATION);
33240 if (!connecting_to_an_overlaped_boundary)
33248 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33251 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33253 found_vertex_on_dst_boundary_initial =
33254 this->get_connected_vertex_number_on_destination_polyline(
33255 poly_to_connect_pt,
33256 src_vertex_coordinates_initial,
33257 n_vertex_connection_initial);
33261 if (found_vertex_on_dst_boundary_initial)
33265 sub_poly_to_connect = isub;
33281 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33286 boundary_marked_as_shared_boundary(dst_bnd_id_initial, isub))
33289 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33292 found_vertex_on_dst_boundary_initial =
33293 this->get_connected_vertex_number_on_destination_polyline(
33294 poly_to_connect_pt,
33295 src_vertex_coordinates_initial,
33296 n_vertex_connection_initial);
33299 if (found_vertex_on_dst_boundary_initial)
33303 sub_poly_to_connect = isub;
33314 #endif // #ifdef OOMPH_HAS_MPI 33318 if (!found_vertex_on_dst_boundary_initial)
33321 #ifdef OOMPH_HAS_MPI 33322 if (this->is_mesh_distributed())
33332 resume_initial_connection_polyline_pt.push_back(polyline_pt);
33339 #endif // #ifdef OOMPH_HAS_MPI 33344 const unsigned bnd_id = polyline_pt->
boundary_id();
33345 std::ostringstream error_message;
33347 <<
"INITIAL VERTEX CONNECTION\n" 33348 <<
"It was not possible to find the associated " 33349 <<
"vertex number on the destination boundary\n" 33350 <<
"The current boundary (" << bnd_id <<
") is marked to have" 33351 <<
"a connection at the\nINITIAL vertex (" 33352 << src_vertex_coordinates_initial[0] <<
"," 33353 << src_vertex_coordinates_initial[1] <<
")\n" 33354 <<
"with boundary ("<< dst_bnd_id_initial <<
")\n" 33355 <<
"This is the list of vertices on the destination boundary\n";
33359 this->boundary_polyline_pt(dst_bnd_id_initial);
33361 const unsigned n_vertex_dst_boundary = dst_polyline->
nvertex();
33363 for (
unsigned i = 0;
i < n_vertex_dst_boundary;
i++)
33368 << current_vertex[0] <<
", " << current_vertex[1] <<
")\n";
33371 error_message.str(),
33372 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33373 OOMPH_EXCEPTION_LOCATION);
33383 n_vertex_connection_initial;
33387 sub_poly_to_connect;
33401 const unsigned dst_bnd_id_final =
33405 const unsigned tmp_n_vertices = polyline_pt->
nvertex();
33412 #ifdef OOMPH_HAS_MPI 33413 if (this->is_mesh_distributed())
33416 const unsigned init_shd_bnd_id =
33417 this->initial_shared_boundary_id();
33419 if (dst_bnd_id_final >= init_shd_bnd_id)
33422 const unsigned bnd_id = polyline_pt->
boundary_id();
33423 std::ostringstream error_message;
33425 <<
"FINAL VERTEX CONNECTION\n" 33426 <<
"The current original boundary is trying to connect to a\n" 33427 <<
"shared boundary, this is not allowed. In this case the\n" 33428 <<
"shared boundary should be the one that connects with the\n" 33429 <<
"original boundary\n" 33430 <<
"The current boundary (" << bnd_id <<
") is marked to have " 33431 <<
"a connection at the\nFINAL vertex (" 33432 << src_vertex_coordinates_final[0] <<
"," 33433 << src_vertex_coordinates_final[1] <<
")\n" 33434 <<
"with boundary ("<< dst_bnd_id_final <<
")\n" 33435 <<
"This is the list of vertices on the destination boundary\n";
33439 this->boundary_polyline_pt(dst_bnd_id_final);
33441 const unsigned n_vertex_dst_boundary = dst_polyline->
nvertex();
33443 for (
unsigned i = 0;
i < n_vertex_dst_boundary;
i++)
33447 <<
"Vertex#("<<
i<<
"): (" 33448 << current_vertex[0] <<
", " << current_vertex[1] <<
")\n";
33451 error_message.str(),
33452 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33453 OOMPH_EXCEPTION_LOCATION);
33457 #endif // #ifdef OOMPH_HAS_MPI 33459 #endif // #ifdef PARANOID 33463 bool found_vertex_on_dst_boundary_final =
false;
33467 unsigned sub_poly_to_connect = 0;
33470 unsigned n_vertex_connection_final = 0;
33475 bool connecting_to_an_split_boundary =
false;
33479 bool connecting_to_an_overlaped_boundary =
false;
33481 #ifdef OOMPH_HAS_MPI 33482 if (this->is_mesh_distributed())
33487 if (this->boundary_was_splitted(dst_bnd_id_final))
33489 connecting_to_an_split_boundary =
true;
33498 if (connecting_to_an_split_boundary)
33502 const unsigned n_sub_poly =
33503 this->nboundary_subpolylines(dst_bnd_id_final);
33507 for (
unsigned ii =0; ii < n_sub_poly; ii++)
33510 boundary_marked_as_shared_boundary(dst_bnd_id_final, ii))
33514 connecting_to_an_overlaped_boundary =
true;
33526 boundary_marked_as_shared_boundary(dst_bnd_id_final, 0))
33529 connecting_to_an_overlaped_boundary =
true;
33535 #endif // #ifdef OOMPH_HAS_MPI 33540 if (!(connecting_to_an_split_boundary ||
33541 connecting_to_an_overlaped_boundary))
33545 poly_to_connect_pt = this->boundary_polyline_pt(dst_bnd_id_final);
33555 if (!connecting_to_an_split_boundary)
33559 if (!connecting_to_an_overlaped_boundary)
33563 found_vertex_on_dst_boundary_final =
33564 this->get_connected_vertex_number_on_destination_polyline(
33565 poly_to_connect_pt,
33566 src_vertex_coordinates_final,
33567 n_vertex_connection_final);
33580 #ifdef OOMPH_HAS_MPI 33588 this->boundary_subpolylines(dst_bnd_id_final);
33591 const unsigned nsub_poly = tmp_vector_subpolylines.size();
33593 if (nsub_poly <= 1)
33595 std::ostringstream error_message;
33597 <<
"The boundary (" << dst_bnd_id_final <<
") was " 33598 <<
"marked to be splitted but\n" 33599 <<
"there are only ("<<nsub_poly<<
") polylines to " 33600 <<
"represent it.\n";
33602 error_message.str(),
33603 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33604 OOMPH_EXCEPTION_LOCATION);
33615 if (!connecting_to_an_overlaped_boundary)
33623 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33626 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33628 found_vertex_on_dst_boundary_final =
33629 this->get_connected_vertex_number_on_destination_polyline(
33630 poly_to_connect_pt,
33631 src_vertex_coordinates_final,
33632 n_vertex_connection_final);
33636 if (found_vertex_on_dst_boundary_final)
33640 sub_poly_to_connect = isub;
33656 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33661 boundary_marked_as_shared_boundary(dst_bnd_id_final, isub))
33664 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33667 found_vertex_on_dst_boundary_final =
33668 this->get_connected_vertex_number_on_destination_polyline(
33669 poly_to_connect_pt,
33670 src_vertex_coordinates_final,
33671 n_vertex_connection_final);
33674 if (found_vertex_on_dst_boundary_final)
33678 sub_poly_to_connect = isub;
33689 #endif // #ifdef OOMPH_HAS_MPI 33693 if (!found_vertex_on_dst_boundary_final)
33696 #ifdef OOMPH_HAS_MPI 33697 if (this->is_mesh_distributed())
33707 resume_final_connection_polyline_pt.push_back(polyline_pt);
33714 #endif // #ifdef OOMPH_HAS_MPI 33719 const unsigned bnd_id = polyline_pt->
boundary_id();
33720 std::ostringstream error_message;
33722 <<
"FINAL VERTEX CONNECTION\n" 33723 <<
"It was not possible to find the associated " 33724 <<
"vertex number on the destination boundary\n" 33725 <<
"The current boundary (" << bnd_id <<
") is marked to have " 33726 <<
"a connection at the\nFINAL vertex (" 33727 << src_vertex_coordinates_final[0] <<
"," 33728 << src_vertex_coordinates_final[1] <<
")\n" 33729 <<
"with boundary ("<< dst_bnd_id_final <<
")\n" 33730 <<
"This is the list of vertices on the destination boundary\n";
33734 this->boundary_polyline_pt(dst_bnd_id_final);
33736 const unsigned n_vertex_dst_boundary = dst_polyline->
nvertex();
33738 for (
unsigned i = 0;
i < n_vertex_dst_boundary;
i++)
33742 <<
"Vertex#("<<
i<<
"): (" 33743 << current_vertex[0] <<
", " << current_vertex[1] <<
")\n";
33746 error_message.str(),
33747 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33748 OOMPH_EXCEPTION_LOCATION);
33757 n_vertex_connection_final;
33761 sub_poly_to_connect;
33777 template<
class ELEMENT>
33784 const unsigned n_initial_poly =
33785 resume_initial_connection_polyline_pt.size();
33788 for (
unsigned p = 0; p < n_initial_poly; p++)
33792 resume_initial_connection_polyline_pt[p];
33799 const unsigned n_final_poly =
33800 resume_final_connection_polyline_pt.size();
33803 for (
unsigned p = 0; p < n_final_poly; p++)
33807 resume_final_connection_polyline_pt[p];
33813 resume_initial_connection_polyline_pt.clear();
33814 resume_final_connection_polyline_pt.clear();
33822 template<
class ELEMENT>
33826 const unsigned &dst_bnd_id,
33827 unsigned &vertex_number)
33830 bool found_associated_vertex_number =
false;
33834 this->boundary_polyline_pt(dst_bnd_id);
33836 const unsigned n_vertices = dst_polyline->
nvertex();
33840 for (
unsigned i = 0;
i < n_vertices;
i++)
33847 (vertex_coordinates[0] - current_vertex[0])*
33848 (vertex_coordinates[0] - current_vertex[0])
33850 (vertex_coordinates[1] - current_vertex[1])*
33851 (vertex_coordinates[1] - current_vertex[1]);
33853 error = sqrt(error);
33859 found_associated_vertex_number =
true;
33865 return found_associated_vertex_number;
33878 template<
class ELEMENT>
33881 const bool& check_only)
33889 if (this->is_mesh_distributed() && !check_only)
33891 std::stringstream error_message;
33893 <<
"The updating of polygons of a distributed mesh can ONLY be\n" 33894 <<
"performed using the element's area associated to the halo(ed)\n" 33896 <<
"1) Make sure you have enabled the parallel mesh adaptation\n" 33897 <<
"option if you are working with a distributed mesh, OR\n" 33898 <<
"2) Make sure to call the update_..._using_elements_area() methods\n" 33899 <<
"if the mesh is marked as distributed\n\n";
33901 OOMPH_CURRENT_FUNCTION,
33902 OOMPH_EXCEPTION_LOCATION);
33908 bool unrefinement_was_performed=
false;
33909 bool refinement_was_performed=
false;
33910 bool max_length_applied =
false;
33913 const unsigned n_polyline = polygon_pt->
npolyline();
33919 get_face_mesh_representation(polygon_pt,face_mesh_pt);
33927 for(
unsigned p=0;p<n_polyline;p++)
33932 std::set<Vector<double> > vertex_nodes;
33941 unsigned n_face_element = face_mesh_pt[p]->nelement();
33942 for(
unsigned e=0;
e<n_face_element;++
e)
33946 #ifdef OOMPH_HAS_MPI 33948 if (this->is_mesh_distributed() && el_pt->
is_halo()) {
continue;}
33951 unsigned n_node = el_pt->
nnode();
33957 vertex_coord[0] = bound_left[0];
33960 for(
unsigned i=0;
i<2;
i++)
33962 vertex_coord[
i+1] = el_pt->
node_pt(0)->
x(
i);
33964 vertex_nodes.insert(vertex_coord);
33970 get_coordinates_on_boundary(bound,bound_right);
33971 vertex_coord[0] = bound_right[0];
33974 for(
unsigned i=0;
i<2;
i++)
33976 vertex_coord[
i+1] = el_pt->
node_pt(n_node-1)->
x(
i);
33978 vertex_nodes.insert(vertex_coord);
33983 unsigned n_poly_vertex = vertex_nodes.size();
33986 for(std::set<
Vector<double> >::iterator it = vertex_nodes.begin();
33987 it!=vertex_nodes.end();++it)
33989 tmp_vector_vertex_node[count].resize(3);
33990 tmp_vector_vertex_node[count][0] = (*it)[0];
33991 tmp_vector_vertex_node[count][1] = (*it)[1];
33992 tmp_vector_vertex_node[count][2] = (*it)[2];
33997 unsigned n_vertex=tmp_vector_vertex_node.size();
34001 double unrefinement_tolerance=
34007 if (unrefinement_tolerance>0.0 && n_vertex>=3)
34009 unrefinement_was_performed =
34010 unrefine_boundary(bound, chunk, tmp_vector_vertex_node,
34011 unrefinement_tolerance, check_only);
34016 if (check_only && unrefinement_was_performed)
34020 for(
unsigned p=0;p<n_polyline;p++)
34022 face_mesh_pt[p]->flush_node_storage();
34023 delete face_mesh_pt[p];
34032 n_vertex=tmp_vector_vertex_node.size();
34037 double refinement_tolerance=
34039 if (refinement_tolerance>0.0 && n_vertex >= 2)
34041 refinement_was_performed =
34042 refine_boundary(face_mesh_pt[p], tmp_vector_vertex_node,
34043 refinement_tolerance, check_only);
34048 if (check_only && refinement_was_performed)
34052 for(
unsigned p=0;p<n_polyline;p++)
34054 face_mesh_pt[p]->flush_node_storage();
34055 delete face_mesh_pt[p];
34065 n_vertex=tmp_vector_vertex_node.size();
34071 if (maximum_length > 0.0 && n_vertex >= 2)
34073 max_length_applied =
34074 apply_max_length_constraint(face_mesh_pt[p],
34075 tmp_vector_vertex_node,
34080 if (check_only && max_length_applied)
34084 for(
unsigned p=0;p<n_polyline;p++)
34086 face_mesh_pt[p]->flush_node_storage();
34087 delete face_mesh_pt[p];
34096 n_vertex=tmp_vector_vertex_node.size();
34099 for(
unsigned i=0;
i<n_vertex;
i++)
34101 vector_vertex_node[
i].resize(2);
34102 vector_vertex_node[
i][0]=tmp_vector_vertex_node[
i][1];
34103 vector_vertex_node[
i][1]=tmp_vector_vertex_node[
i][2];
34106 #ifdef OOMPH_HAS_MPI 34110 if (!this->is_mesh_distributed())
34113 if ( (p > 0) && !check_only )
34117 unsigned n_prev_vertex =
34119 final_vertex_of_previous_segment =
34121 vertex_coordinate(n_prev_vertex-1);
34123 unsigned prev_seg_boundary_id =
34128 double error = 0.0;
34129 for(
unsigned i=0;
i<2;
i++)
34131 const double dist =
34132 final_vertex_of_previous_segment[
i] -
34133 (*vector_vertex_node.begin())[
i];
34134 error += dist*dist;
34136 error = sqrt(error);
34144 double rev_error = 0.0;
34145 for(
unsigned i=0;
i<2;
i++)
34147 const double dist =
34148 final_vertex_of_previous_segment[
i] -
34149 (*--vector_vertex_node.end())[
i];
34150 rev_error += dist*dist;
34152 rev_error = sqrt(rev_error);
34167 initial_vertex_of_previous_segment =
34169 vertex_coordinate(0);
34171 unsigned prev_seg_boundary_id =
34176 double error = 0.0;
34177 for(
unsigned i=0;
i<2;
i++)
34179 const double dist =
34180 initial_vertex_of_previous_segment[
i] -
34181 (*vector_vertex_node.begin())[
i];
34182 error += dist*dist;
34184 error = sqrt(error);
34192 double rev_error = 0.0;
34193 for(
unsigned i=0;
i<2;
i++)
34195 const double dist =
34196 initial_vertex_of_previous_segment[
i] -
34197 (*--vector_vertex_node.end())[
i];
34198 rev_error += dist*dist;
34200 rev_error = sqrt(rev_error);
34206 std::ostringstream error_stream;
34208 <<
"The distance between the first node of the current\n" 34209 <<
"line segment (boundary " << bound <<
") and either end of " 34210 <<
"the previous line segment\n" 34211 <<
"(boundary " << prev_seg_boundary_id <<
") is bigger than " 34212 <<
"the desired tolerance " <<
34214 <<
"This suggests that the polylines defining the polygonal\n" 34215 <<
"representation are not properly ordered.\n" 34216 <<
"Fail on last vertex of polyline: (" 34217 << prev_seg_boundary_id<<
") and\nfirst vertex of polyline (" 34218 << bound <<
").\nThis should have failed when first trying to " 34219 <<
"construct the\npolygon.\n";
34221 OOMPH_CURRENT_FUNCTION,
34222 OOMPH_EXCEPTION_LOCATION);
34229 std::reverse(vector_vertex_node.begin(),
34230 vector_vertex_node.end());
34244 std::ostringstream error_stream;
34246 <<
"The distance between the first node of the current\n" 34247 <<
"line segment (boundary " << bound <<
") and either end of " 34248 <<
"the previous line segment\n" 34249 <<
"(boundary " << prev_seg_boundary_id <<
") is bigger than the " 34250 <<
"desired tolerance " <<
34252 <<
"This suggests that the polylines defining the polygonal\n" 34253 <<
"representation are not properly ordered.\n" 34254 <<
"Fail on last vertex of polyline: (" << prev_seg_boundary_id
34255 <<
") and\nfirst vertex of polyline (" << bound <<
").\n" 34256 <<
"This should have failed when first trying to construct the\n" 34259 OOMPH_CURRENT_FUNCTION,
34260 OOMPH_EXCEPTION_LOCATION);
34266 std::reverse(vector_vertex_node.begin(),vector_vertex_node.end());
34286 unrefinement_tolerance);
34288 refinement_tolerance);
34295 this->copy_connection_information(polygon_pt->
polyline_pt(p),
34296 tmp_curve_section_pt);
34301 bool delete_it_on_destructor =
false;
34303 std::set<TriangleMeshCurveSection*>::iterator it =
34306 if (it!=this->Free_curve_section_pt.end())
34308 this->Free_curve_section_pt.erase(it);
34310 delete_it_on_destructor =
true;
34320 if (delete_it_on_destructor)
34331 for(
unsigned p=0;p<n_polyline;p++)
34333 face_mesh_pt[p]->flush_node_storage();
34334 delete face_mesh_pt[p];
34348 return (unrefinement_was_performed ||
34349 refinement_was_performed ||
34350 max_length_applied);
34364 template<
class ELEMENT>
34367 const bool& check_only)
34375 if (this->is_mesh_distributed() && !check_only)
34377 std::stringstream error_message;
34379 <<
"The updating of open curves of a distributed mesh can ONLY be\n" 34380 <<
"performed using the element's area associated to the halo(ed)\n" 34382 <<
"1) Make sure you have enabled the parallel mesh adaptation\n" 34383 <<
"option if you are working with a distributed mesh, OR\n" 34384 <<
"2) Make sure to call the update_..._using_elements_area() methods\n" 34385 <<
"if the mesh is marked as distributed\n\n";
34387 OOMPH_CURRENT_FUNCTION,
34388 OOMPH_EXCEPTION_LOCATION);
34394 bool unrefinement_was_performed=
false;
34395 bool refinement_was_performed=
false;
34396 bool max_length_applied =
false;
34405 get_face_mesh_representation(open_polyline_pt, face_mesh_pt);
34413 for(
unsigned p=0;p<n_polyline;p++)
34418 std::set<Vector<double> > vertex_nodes;
34421 const unsigned bound =
34425 const unsigned chunk =
34429 unsigned n_face_element = face_mesh_pt[p]->nelement();
34432 for(
unsigned e=0;
e<n_face_element;++
e)
34435 unsigned n_node = el_pt->
nnode();
34441 vertex_coord[0] = bound_left[0];
34444 for(
unsigned i=0;
i<2;
i++)
34446 vertex_coord[
i+1] = el_pt->
node_pt(0)->
x(
i);
34448 vertex_nodes.insert(vertex_coord);
34454 vertex_coord[0] = bound_right[0];
34457 for(
unsigned i=0;
i<2;
i++)
34459 vertex_coord[
i+1] = el_pt->
node_pt(n_node-1)->
x(
i);
34461 vertex_nodes.insert(vertex_coord);
34466 unsigned n_poly_vertex = vertex_nodes.size();
34469 for(std::set<
Vector<double> >::iterator it = vertex_nodes.begin();
34470 it!=vertex_nodes.end();++it)
34472 tmp_vector_vertex_node[count].resize(3);
34473 tmp_vector_vertex_node[count][0] = (*it)[0];
34474 tmp_vector_vertex_node[count][1] = (*it)[1];
34475 tmp_vector_vertex_node[count][2] = (*it)[2];
34480 unsigned n_vertex=tmp_vector_vertex_node.size();
34484 double unrefinement_tolerance=
34490 if (unrefinement_tolerance>0.0 && n_vertex>=3)
34492 unrefinement_was_performed =
34493 unrefine_boundary(bound, chunk, tmp_vector_vertex_node,
34494 unrefinement_tolerance, check_only);
34499 if (check_only && unrefinement_was_performed)
34503 for(
unsigned p=0;p<n_polyline;p++)
34505 face_mesh_pt[p]->flush_node_storage();
34506 delete face_mesh_pt[p];
34516 n_vertex=tmp_vector_vertex_node.size();
34521 double refinement_tolerance=
34523 if (refinement_tolerance>0.0 && n_vertex >= 2)
34525 refinement_was_performed =
34526 refine_boundary(face_mesh_pt[p], tmp_vector_vertex_node,
34527 refinement_tolerance, check_only);
34532 if (check_only && refinement_was_performed)
34536 for(
unsigned p=0;p<n_polyline;p++)
34538 face_mesh_pt[p]->flush_node_storage();
34539 delete face_mesh_pt[p];
34549 n_vertex=tmp_vector_vertex_node.size();
34555 if (maximum_length > 0.0 && n_vertex >= 2)
34557 bool max_length_applied =
false;
34558 max_length_applied =
34559 apply_max_length_constraint(face_mesh_pt[p],
34560 tmp_vector_vertex_node,
34565 if (check_only && max_length_applied)
34569 for(
unsigned p=0;p<n_polyline;p++)
34571 face_mesh_pt[p]->flush_node_storage();
34572 delete face_mesh_pt[p];
34581 n_vertex=tmp_vector_vertex_node.size();
34584 for(
unsigned i=0;
i<n_vertex;
i++)
34586 vector_vertex_node[
i].resize(2);
34587 vector_vertex_node[
i][0]=tmp_vector_vertex_node[
i][1];
34588 vector_vertex_node[
i][1]=tmp_vector_vertex_node[
i][2];
34591 #ifdef OOMPH_HAS_MPI 34595 if (!this->is_mesh_distributed())
34604 if( (p > 0) && !check_only )
34609 final_vertex_coordinate(final_vertex_of_previous_segment);
34611 unsigned prev_seg_boundary_id =
34616 double error = 0.0;
34617 for(
unsigned i=0;
i<2;
i++)
34619 const double dist =
34620 final_vertex_of_previous_segment[
i] -
34621 (*vector_vertex_node.begin())[
i];
34622 error += dist*dist;
34624 error = sqrt(error);
34633 for(
unsigned i=0;
i<2;
i++)
34635 const double dist =
34636 final_vertex_of_previous_segment[
i] -
34637 (*--vector_vertex_node.end())[
i];
34638 error += dist*dist;
34640 error = sqrt(error);
34655 initial_vertex_coordinate(initial_vertex_of_previous_segment);
34660 for(
unsigned i=0;
i<2;
i++)
34662 const double dist =
34663 initial_vertex_of_previous_segment[
i] -
34664 (*vector_vertex_node.begin())[
i];
34665 error += dist*dist;
34667 error = sqrt(error);
34676 for(
unsigned i=0;
i<2;
i++)
34678 const double dist =
34679 initial_vertex_of_previous_segment[
i] -
34680 (*--vector_vertex_node.end())[
i];
34681 error += dist*dist;
34683 error = sqrt(error);
34688 std::ostringstream error_stream;
34690 <<
"The distance between the first node of the current\n" 34691 <<
"line segment (boundary " << bound
34692 <<
") and either end of the previous line segment\n" 34693 <<
"(boundary " << prev_seg_boundary_id <<
") is bigger than " 34694 <<
"the desired tolerance " <<
34696 <<
"This suggests that the polylines defining the open " 34698 <<
"representation are not properly ordered.\n" 34699 <<
"Fail on last vertex of polyline: (" 34700 << prev_seg_boundary_id
34701 <<
") and\nfirst vertex of polyline (" << bound <<
").\n" 34702 <<
"This should have failed when first trying to construct\n" 34703 <<
"the open curve.\n";
34705 OOMPH_CURRENT_FUNCTION,
34706 OOMPH_EXCEPTION_LOCATION);
34713 std::reverse(vector_vertex_node.begin(),
34714 vector_vertex_node.end());
34725 std::ostringstream error_stream;
34727 <<
"The distance between the first node of the current\n" 34728 <<
"line segment (boundary " << bound <<
") and either end of " 34729 <<
"the previous line segment\n" 34730 <<
"(boundary "<<prev_seg_boundary_id<<
") is bigger than the " 34731 <<
"desired tolerance " <<
34733 <<
"This suggests that the polylines defining the polygonal\n" 34734 <<
"representation are not properly ordered.\n" 34735 <<
"Fail on last vertex of polyline: ("<<prev_seg_boundary_id
34736 <<
") and\nfirst vertex of polyline ("<<bound<<
").\n" 34737 <<
"This should have failed when first trying to construct the\n" 34740 OOMPH_CURRENT_FUNCTION,
34741 OOMPH_EXCEPTION_LOCATION);
34747 std::reverse(vector_vertex_node.begin(),vector_vertex_node.end());
34769 unrefinement_tolerance);
34771 refinement_tolerance);
34778 this->copy_connection_information(open_polyline_pt->
polyline_pt(p),
34779 tmp_curve_section);
34781 std::set<TriangleMeshCurveSection*>::iterator it =
34784 bool delete_it_on_destructor =
false;
34786 if (it!=this->Free_curve_section_pt.end())
34789 this->Free_curve_section_pt.erase(it);
34791 delete_it_on_destructor =
true;
34799 this->Boundary_curve_section_pt[bound] =
34802 if (delete_it_on_destructor)
34804 this->Free_curve_section_pt.insert(
34814 for(
unsigned p=0;p<n_polyline;p++)
34816 face_mesh_pt[p]->flush_node_storage();
34817 delete face_mesh_pt[p];
34831 return (unrefinement_was_performed ||
34832 refinement_was_performed ||
34833 max_length_applied);
34846 template<
class ELEMENT>
34851 double &unrefinement_tolerance,
34852 const bool &check_only)
34855 std::set<Vector<double> > no_delete_vertex;
34858 const bool boundary_receive_connections =
34859 this->boundary_connections(b, c, no_delete_vertex);
34863 bool unrefinement_was_performed=
false;
34865 unsigned n_vertex = vector_bnd_vertices.size();
34869 unsigned counter=1;
34875 for(
unsigned i=1;
i<=n_vertex-2;
i+=2)
34878 double a_x=vector_bnd_vertices[
i-1][1];
34879 double a_y=vector_bnd_vertices[
i-1][2];
34880 double b_x=vector_bnd_vertices[
i][1];
34881 double b_y=vector_bnd_vertices[
i][2];
34882 double c_x=vector_bnd_vertices[
i+1][1];
34883 double c_y=vector_bnd_vertices[
i+1][2];
34890 double e=a*(a_x+b_x)+b*(a_y+b_y);
34891 double f=c*(a_x+c_x)+d*(a_y+c_y);
34893 double g=2.0*(a*(c_y-b_y)-b*(c_x-b_x));
34896 if (std::fabs(g)<1.0e-14)
34899 if(check_only) {
return true;}
34903 double p_x=(d*e-b*f)/g;
34904 double p_y=(a*f-c*
e)/g;
34906 double r=sqrt(pow((a_x-p_x),2)+pow((a_y-p_y),2));
34908 double rhalfca_x=0.5*(a_x-c_x);
34909 double rhalfca_y=0.5*(a_y-c_y);
34911 double halfca_squared=pow(rhalfca_x,2)+pow(rhalfca_y,2);
34913 double sticky_out_bit=r-sqrt(std::fabs((r*r) - halfca_squared));
34918 if ((sticky_out_bit/(2.0*sqrt(halfca_squared)))<
34919 unrefinement_tolerance)
34922 if(check_only) {
return true;}
34928 if (do_it && boundary_receive_connections)
34931 for (std::set<
Vector<double> >::iterator it = no_delete_vertex.begin();
34932 it != no_delete_vertex.end(); it++)
34936 const double x = (*it)[0];
34937 const double y = (*it)[1];
34938 double error = (b_x - x)*(b_x - x) + (b_y - y)*(b_y - y);
34939 error = sqrt(error);
34955 vector_bnd_vertices[
i].resize(0);
34974 if( (counter)==(n_vertex-1) )
34977 unsigned i=vector_bnd_vertices.size()-2;
34983 if(vector_bnd_vertices[counter-2].size()!=0)
35002 double a_x=vector_bnd_vertices[n][1];
35003 double a_y=vector_bnd_vertices[n][2];
35004 double b_x=vector_bnd_vertices[
i][1];
35005 double b_y=vector_bnd_vertices[
i][2];
35006 double c_x=vector_bnd_vertices[i+1][1];
35007 double c_y=vector_bnd_vertices[i+1][2];
35014 double e=a*(a_x+b_x)+b*(a_y+b_y);
35015 double f=c*(a_x+c_x)+d*(a_y+c_y);
35017 double g=2.0*(a*(c_y-b_y)-b*(c_x-b_x));
35020 if (std::fabs(g)<1.0e-14)
35023 if(check_only) {
return true;}
35027 double p_x=(d*e-b*f)/g;
35028 double p_y=(a*f-c*
e)/g;
35030 double r=sqrt(pow((a_x-p_x),2)+pow((a_y-p_y),2));
35032 double rhalfca_x=0.5*(a_x-c_x);
35033 double rhalfca_y=0.5*(a_y-c_y);
35035 double halfca_squared=pow(rhalfca_x,2)+pow(rhalfca_y,2);
35037 double sticky_out_bit=r-sqrt(std::fabs((r*r) - halfca_squared));
35042 if ((sticky_out_bit/(2.0*sqrt(halfca_squared)))<
35043 unrefinement_tolerance)
35046 if(check_only) {
return true;}
35052 if (do_it && boundary_receive_connections)
35055 for (std::set<
Vector<double> >::iterator it = no_delete_vertex.begin();
35056 it != no_delete_vertex.end(); it++)
35060 const double x = (*it)[0];
35061 const double y = (*it)[1];
35062 double error = (b_x - x)*(b_x - x) + (b_y - y)*(b_y - y);
35063 error = sqrt(error);
35080 vector_bnd_vertices[
i].resize(0);
35087 compact_vector.reserve(n_vertex);
35088 for (
unsigned i=0;
i<n_vertex;
i++)
35091 if (vector_bnd_vertices[
i].size()!=0)
35093 compact_vector.push_back(vector_bnd_vertices[
i]);
35098 n_vertex =compact_vector.size();
35104 if( n_vertex != vector_bnd_vertices.size() )
35106 unrefinement_was_performed=
true;
35110 vector_bnd_vertices.resize(n_vertex);
35111 for(
unsigned i=0;
i<n_vertex;
i++)
35113 vector_bnd_vertices[
i].resize(3);
35114 vector_bnd_vertices[
i][0]=compact_vector[
i][0];
35115 vector_bnd_vertices[
i][1]=compact_vector[
i][1];
35116 vector_bnd_vertices[
i][2]=compact_vector[
i][2];
35119 return unrefinement_was_performed;
35131 template<
class ELEMENT>
35135 double &refinement_tolerance,
35136 const bool &check_only)
35140 bool refinement_was_performed=
false;
35147 unsigned n_vertex=vector_bnd_vertices.size();
35155 extended_vector.reserve(2*n_vertex);
35158 for(
unsigned inod=0;inod<n_vertex-1;inod++)
35161 double zeta_left=vector_bnd_vertices[inod][0];
35165 for(
unsigned i=0;
i<2;
i++)
35167 R_left[
i]=vector_bnd_vertices[inod][
i+1];
35171 double zeta_right=vector_bnd_vertices[inod+1][0];
35175 for(
unsigned i=0;
i<2;
i++)
35177 R_right[
i]=vector_bnd_vertices[inod+1][
i+1];
35182 zeta_mid[0]=0.5*(zeta_left+zeta_right);
35187 mesh_geom_obj_pt->
position(zeta_mid,R_mid);
35192 for(
unsigned i=0;
i<2;
i++)
35194 R_mid_polygon[
i]=0.5*(R_right[
i]+R_left[
i]);
35199 double distance=sqrt((R_mid[0]-R_mid_polygon[0])*
35200 (R_mid[0]-R_mid_polygon[0])+
35201 (R_mid[1]-R_mid_polygon[1])*
35202 (R_mid[1]-R_mid_polygon[1]));
35205 double length=sqrt((R_right[0]-R_left[0])*(R_right[0]-R_left[0])+
35206 (R_right[1]-R_left[1])*(R_right[1]-R_left[1]));
35212 if((distance/length) > refinement_tolerance)
35219 delete mesh_geom_obj_pt;
35224 new_node[0]=zeta_mid[0];
35225 new_node[1]=R_mid[0];
35226 new_node[2]=R_mid[1];
35229 extended_vector.push_back(vector_bnd_vertices[inod]);
35232 extended_vector.push_back(new_node);
35239 extended_vector.push_back(vector_bnd_vertices[inod]);
35244 extended_vector.push_back(vector_bnd_vertices[n_vertex-1]);
35247 n_vertex=extended_vector.size();
35252 if( n_vertex != vector_bnd_vertices.size() )
35254 refinement_was_performed=
true;
35258 vector_bnd_vertices.resize(n_vertex);
35259 for(
unsigned i=0;
i<n_vertex;
i++)
35261 vector_bnd_vertices[
i].resize(3);
35262 vector_bnd_vertices[
i][0]=extended_vector[
i][0];
35263 vector_bnd_vertices[
i][1]=extended_vector[
i][1];
35264 vector_bnd_vertices[
i][2]=extended_vector[
i][2];
35269 delete mesh_geom_obj_pt;
35271 return refinement_was_performed;
35281 template<
class ELEMENT>
35285 double &max_length_constraint)
35289 bool max_length_applied=
false;
35296 unsigned n_vertex=vector_bnd_vertices.size();
35303 for(
unsigned inod=0;inod<n_vertex-1;inod++)
35306 double zeta_left=vector_bnd_vertices[inod][0];
35310 for(
unsigned i=0;
i<2;
i++)
35312 R_left[
i]=vector_bnd_vertices[inod][
i+1];
35316 double zeta_right=vector_bnd_vertices[inod+1][0];
35320 for(
unsigned i=0;
i<2;
i++)
35322 R_right[
i]=vector_bnd_vertices[inod+1][
i+1];
35326 extended_vector.push_back(vector_bnd_vertices[inod]);
35330 double length=std::fabs(zeta_right-zeta_left);
35333 if (length > max_length_constraint)
35335 double n_pts = length/max_length_constraint;
35337 unsigned n_points =
static_cast<unsigned>(n_pts);
35338 double zeta_increment = (zeta_right-zeta_left)/((
double)n_points+1);
35342 for(
unsigned s=1;
s<n_points+1;
s++)
35345 zeta[0]= zeta_left + zeta_increment*double(
s);
35347 mesh_geom_obj_pt->
position(zeta, vertex);
35351 new_node[0]=zeta[0];
35352 new_node[1]=vertex[0];
35353 new_node[2]=vertex[1];
35356 extended_vector.push_back(new_node);
35362 extended_vector.push_back(vector_bnd_vertices[n_vertex-1]);
35365 n_vertex=extended_vector.size();
35370 if( n_vertex != vector_bnd_vertices.size() )
35372 max_length_applied =
true;
35376 vector_bnd_vertices.resize(n_vertex);
35377 for(
unsigned i=0;
i<n_vertex;
i++)
35379 vector_bnd_vertices[
i].resize(3);
35380 vector_bnd_vertices[
i][0]=extended_vector[
i][0];
35381 vector_bnd_vertices[
i][1]=extended_vector[
i][1];
35382 vector_bnd_vertices[
i][2]=extended_vector[
i][2];
35387 delete mesh_geom_obj_pt;
35389 return max_length_applied;
35399 template<
class ELEMENT>
35402 const unsigned &boundary_id,
35403 Mesh* face_mesh_pt)
35410 this->
template build_face_mesh<ELEMENT,FaceElementAsGeomObject>
35411 (boundary_id,face_mesh_pt);
35414 unsigned n_element = face_mesh_pt->
nelement();
35416 for(
unsigned e=0;
e<n_element;
e++)
35436 template<
class ELEMENT>
35439 const unsigned &boundary_id,
35440 Mesh* face_mesh_pt,
35441 std::map<FiniteElement*, bool> &is_inverted,
35442 bool &inverted_face_mesh)
35444 Mesh *tmp_unsorted_face_mesh_pt =
new Mesh();
35447 create_unsorted_face_mesh_representation(
35448 boundary_id, tmp_unsorted_face_mesh_pt);
35458 std::list<FiniteElement*> sorted_el_pt;
35460 sorted_el_pt.push_back(el_pt);
35463 unsigned nnod=el_pt->
nnode();
35466 unsigned count_done=0;
35469 unsigned n_face_element = tmp_unsorted_face_mesh_pt->
nelement();
35472 std::map<FiniteElement*,bool> done_el;
35474 is_inverted.clear();
35477 for (
unsigned ee=1;ee<n_face_element;ee++)
35481 for (
unsigned e=1;
e<n_face_element;
e++)
35487 if (!done_el[el_pt])
35491 std::list<FiniteElement*>::iterator it=sorted_el_pt.end();
35497 if (is_inverted[first_el_pt])
35499 left_node_pt=first_el_pt->node_pt(nnod-1);
35502 if (is_inverted[last_el_pt])
35504 right_node_pt=last_el_pt->node_pt(0);
35508 if (left_node_pt==el_pt->node_pt(nnod-1))
35510 sorted_el_pt.push_front(el_pt);
35511 done_el[el_pt]=
true;
35513 is_inverted[el_pt]=
false;
35517 else if (left_node_pt==el_pt->node_pt(0))
35519 sorted_el_pt.push_front(el_pt);
35520 done_el[el_pt]=
true;
35522 is_inverted[el_pt]=
true;
35526 else if(right_node_pt==el_pt->node_pt(0))
35528 sorted_el_pt.push_back(el_pt);
35529 done_el[el_pt]=
true;
35531 is_inverted[el_pt]=
false;
35535 else if (right_node_pt==el_pt->node_pt(nnod-1))
35537 sorted_el_pt.push_back(el_pt);
35538 done_el[el_pt]=
true;
35540 is_inverted[el_pt]=
true;
35543 if (done_el[el_pt])
35552 if (count_done!=(n_face_element-1))
35554 std::ostringstream error_message;
35556 <<
"When ordering FaceElements on " 35557 <<
"boundary " << boundary_id <<
" only managed to order \n" << count_done
35558 <<
" of " << n_face_element <<
" face elements.\n" 35561 error_message.str(),
35562 OOMPH_CURRENT_FUNCTION,
35563 OOMPH_EXCEPTION_LOCATION);
35570 for (std::list<FiniteElement*>::iterator it=sorted_el_pt.begin();
35571 it!=sorted_el_pt.end();it++)
35588 this->Boundary_curve_section_pt[boundary_id];
35600 unsigned n_node = first_el_pt->
nnode();
35604 if (is_inverted[first_el_pt])
35606 first_node_pt = first_el_pt->node_pt(n_node-1);
35609 double error = (first_node_pt->
x(0) - first_vertex[0])*
35610 (first_node_pt->
x(0) - first_vertex[0]) +
35611 (first_node_pt->
x(1) - first_vertex[1])*
35612 (first_node_pt->
x(1) - first_vertex[1]);
35614 error = sqrt(error);
35619 inverted_face_mesh =
false;
35623 inverted_face_mesh =
true;
35633 template<
class ELEMENT>
35639 unsigned n_polyline = polygon_pt->
npolyline();
35640 face_mesh_pt.resize(n_polyline);
35646 bool eligible_for_segment_redistribution=
true;
35649 for(
unsigned p=0;p<n_polyline;p++)
35659 this->boundary_geom_object_pt(bound);
35660 if(geom_object_pt!=0)
35662 eligible_for_segment_redistribution=
false;
35665 face_mesh_pt[p] =
new Mesh();
35666 create_unsorted_face_mesh_representation(
35667 bound, face_mesh_pt[p]);
35677 if(this->nregion() > 1)
35679 std::ostringstream warn_message;
35681 <<
"Can't currently re-distribute segments between polylines if there\n" 35682 <<
"are multiple regions; returning..." << std::endl;
35684 "RefineableTriangleMesh::get_face_mesh_representation()",
35685 OOMPH_EXCEPTION_LOCATION);
35690 if (!eligible_for_segment_redistribution)
35692 std::ostringstream warn_message;
35694 <<
"Over-ruling re-distribution of segments between polylines\n" 35695 <<
"because at least one boundary is associated with a GeomObject." 35696 <<
"Returning..." << std::endl;
35698 "RefineableTriangleMesh::get_face_mesh_representation()",
35699 OOMPH_EXCEPTION_LOCATION);
35707 double s_total=0.0;
35713 std::vector<bool> is_reversed(n_polyline,
false);
35716 for(
unsigned p=0;p<n_polyline;p++)
35723 std::list<FiniteElement*> ordered_el_pt;
35724 FiniteElement* el_pt=face_mesh_pt[p]->finite_element_pt(0);
35725 ordered_el_pt.push_back(el_pt);
35728 unsigned nnod=el_pt->
nnode();
35731 first_polyline_node_pt[p]=el_pt->
node_pt(0);
35732 last_polyline_node_pt[p]=el_pt->
node_pt(nnod-1);
35735 unsigned count_done=0;
35738 unsigned n_face_element = face_mesh_pt[p]->nelement();
35745 std::map<FiniteElement*,bool> done_el;
35748 std::map<FiniteElement*,bool> is_inverted;
35751 for (
unsigned ee=1;ee<n_face_element;ee++)
35755 for (
unsigned e=1;
e<n_face_element;
e++)
35758 el_pt=face_mesh_pt[p]->finite_element_pt(
e);
35761 if (!done_el[el_pt])
35765 std::list<FiniteElement*>::iterator it=ordered_el_pt.end();
35771 if (is_inverted[first_el_pt])
35773 left_node_pt=first_el_pt->node_pt(nnod-1);
35776 if (is_inverted[last_el_pt])
35778 right_node_pt=last_el_pt->node_pt(0);
35782 if (left_node_pt==el_pt->node_pt(nnod-1))
35784 ordered_el_pt.push_front(el_pt);
35785 done_el[el_pt]=
true;
35787 is_inverted[el_pt]=
false;
35788 first_polyline_node_pt[p]=el_pt->node_pt(0);
35792 else if (left_node_pt==el_pt->node_pt(0))
35794 ordered_el_pt.push_front(el_pt);
35795 done_el[el_pt]=
true;
35797 is_inverted[el_pt]=
true;
35798 first_polyline_node_pt[p]=el_pt->node_pt(nnod-1);
35802 else if(right_node_pt==el_pt->node_pt(0))
35804 ordered_el_pt.push_back(el_pt);
35805 done_el[el_pt]=
true;
35807 is_inverted[el_pt]=
false;
35808 last_polyline_node_pt[p]=el_pt->node_pt(nnod-1);
35812 else if (right_node_pt==el_pt->node_pt(nnod-1))
35814 ordered_el_pt.push_back(el_pt);
35815 done_el[el_pt]=
true;
35817 is_inverted[el_pt]=
true;
35818 last_polyline_node_pt[p]=el_pt->node_pt(0);
35821 if (done_el[el_pt])
35830 if (count_done!=(n_face_element-1))
35832 std::ostringstream error_message;
35834 <<
"When ordering FaceElements on " 35835 <<
"boundary " << bound <<
" only managed to order \n" << count_done
35836 <<
" of " << n_face_element <<
" face elements.\n" 35839 error_message.str(),
35840 OOMPH_CURRENT_FUNCTION,
35841 OOMPH_EXCEPTION_LOCATION);
35845 ordered_face_mesh_pt[p] =
new Mesh;
35848 for (std::list<FiniteElement*>::iterator it=ordered_el_pt.begin();
35849 it!=ordered_el_pt.end();it++)
35855 ordered_face_mesh_pt[p]->add_element_pt(el_pt);
35859 for(
unsigned e=0;
e<n_face_element;++
e)
35861 FiniteElement* el_pt=ordered_face_mesh_pt[p]->finite_element_pt(
e);
35862 unsigned n_node=el_pt->
nnode();
35863 double element_length_squared=0.0;
35864 for(
unsigned i=0;
i<2;
i++)
35866 element_length_squared += pow(el_pt->
node_pt(n_node-1)->
x(
i)-
35871 double element_length=sqrt(element_length_squared);
35874 s_total += element_length;
35878 face_mesh_pt[p]->flush_element_and_node_storage();
35882 if ((last_polyline_node_pt[0]==first_polyline_node_pt[1])||
35883 (last_polyline_node_pt[0]==last_polyline_node_pt[1]))
35885 is_reversed[0]=
false;
35887 else if ((first_polyline_node_pt[0]==first_polyline_node_pt[1])||
35888 (first_polyline_node_pt[0]==last_polyline_node_pt[1]))
35890 is_reversed[0]=
true;
35895 std::vector<bool> mesh_done(n_polyline,
false);
35899 tmp_face_mesh_pt[0]=ordered_face_mesh_pt[0];
35900 unsigned current=0;
35901 old_polyline_number[0]=0;
35902 unsigned count_found=0;
35905 for(
unsigned p=1;p<n_polyline;p++)
35907 Node* end_node_pt=last_polyline_node_pt[current];
35908 if (is_reversed[current])
35910 end_node_pt=first_polyline_node_pt[current];
35914 for(
unsigned pp=1;pp<n_polyline;pp++)
35916 if (!mesh_done[pp])
35919 if ((!is_reversed[current])&&
35920 (end_node_pt==first_polyline_node_pt[pp]))
35922 tmp_face_mesh_pt[p]=ordered_face_mesh_pt[pp];
35923 mesh_done[pp]=
true;
35924 is_reversed[pp]=
false;
35925 old_polyline_number[p]=pp;
35932 else if ((!is_reversed[current])&&
35933 (end_node_pt==last_polyline_node_pt[pp]))
35935 tmp_face_mesh_pt[p]=ordered_face_mesh_pt[pp];
35936 mesh_done[pp]=
true;
35937 is_reversed[pp]=
true;
35938 old_polyline_number[p]=pp;
35945 else if ((is_reversed[current])&&
35946 (end_node_pt==first_polyline_node_pt[pp]))
35948 tmp_face_mesh_pt[p]=ordered_face_mesh_pt[pp];
35949 mesh_done[pp]=
true;
35950 is_reversed[pp]=
false;
35951 old_polyline_number[p]=pp;
35958 else if ((is_reversed[current])&&
35959 (end_node_pt==last_polyline_node_pt[pp]))
35961 tmp_face_mesh_pt[p]=ordered_face_mesh_pt[pp];
35962 mesh_done[pp]=
true;
35963 is_reversed[pp]=
true;
35964 old_polyline_number[p]=pp;
35974 if (count_found!=n_polyline-1)
35976 std::ostringstream error_message;
35977 error_message <<
"Only found " << count_found
35978 <<
" out of " << n_polyline-1
35979 <<
" polylines to be fitted in.\n";
35981 error_message.str(),
35982 OOMPH_CURRENT_FUNCTION,
35983 OOMPH_EXCEPTION_LOCATION);
35988 for (
unsigned i=0;
i<n_polyline;
i++)
35990 ordered_face_mesh_pt[
i]=tmp_face_mesh_pt[
i];
35996 unsigned new_face_id=0;
36000 std::map<Node*,std::map<unsigned,unsigned> >
36001 node_must_not_be_removed_from_boundary_flag;
36004 for(
unsigned p=0;p<n_polyline;p++)
36007 unsigned n_face_element = ordered_face_mesh_pt[p]->nelement();
36008 for (
unsigned e=0;
e<n_face_element;
e++)
36010 unsigned el_number=
e;
36011 if (is_reversed[p])
36013 el_number=n_face_element-
e-1;
36017 ordered_face_mesh_pt[p]->finite_element_pt(el_number);
36018 unsigned n_node = el_pt->
nnode();
36021 double element_length_squared=0.0;
36022 for(
unsigned i=0;
i<2;
i++)
36024 element_length_squared += pow(el_pt->
node_pt(n_node-1)->
x(
i)-
36027 double element_length=sqrt(element_length_squared);
36030 s += element_length;
36034 if(s < s_total/
double(n_polyline)+1
e-6)
36037 face_mesh_pt[new_face_id]->add_element_pt(el_pt);
36039 unsigned bound_old =
36042 unsigned bound_new =
36046 for(
unsigned i=0;
i<n_node;
i++)
36053 if(bound_new != bound_old)
36056 add_boundary_node(bound_new,nod_pt);
36060 node_must_not_be_removed_from_boundary_flag[nod_pt][bound_old]+=0;
36069 node_must_not_be_removed_from_boundary_flag[nod_pt][bound_old]+=1;
36081 if(new_face_id!=n_polyline-1)
36099 unsigned move_count=0;
36100 for (std::map<
Node*,std::map<unsigned,unsigned> >::iterator
36101 it=node_must_not_be_removed_from_boundary_flag.begin();
36102 it!=node_must_not_be_removed_from_boundary_flag.end();it++)
36105 Node* nod_pt=(*it).first;
36108 for (std::map<unsigned,unsigned>::iterator
36109 it_2=(*it).second.begin();it_2!=(*it).second.end();it_2++)
36112 unsigned bound=(*it_2).first;
36115 if((*it_2).second==0)
36117 remove_boundary_node(bound,nod_pt);
36124 for(
unsigned p=0;p<n_polyline;p++)
36131 unsigned n_face_element = face_mesh_pt[p]->nelement();
36132 for(
unsigned e=0;
e<n_face_element;
e++)
36137 (face_mesh_pt[p]->element_pt(
e));
36145 setup_boundary_element_info();
36148 for(
unsigned p=0;p<n_polyline;p++)
36155 this->
template setup_boundary_coordinates<ELEMENT>(bound);
36159 for(
unsigned p=0;p<n_polyline;p++)
36164 ordered_face_mesh_pt[p]->flush_element_and_node_storage();
36165 delete ordered_face_mesh_pt[p];
36173 template<
class ELEMENT>
36181 face_mesh_pt.resize(n_polyline);
36184 for(
unsigned p=0;p<n_polyline;p++)
36191 face_mesh_pt[p] =
new Mesh();
36192 create_unsorted_face_mesh_representation(
36193 bound, face_mesh_pt[p]);
36206 template <
class ELEMENT>
36209 &internal_point_coord,
36210 const bool& check_only)
36214 bool update_was_performed=
false;
36216 unsigned n_hole = internal_point_coord.size();
36217 for(
unsigned ihole=0;ihole<n_hole;ihole++)
36221 = this->Internal_polygon_pt[ihole];
36231 internal_point_coord[ihole].resize(2);
36245 bool update_necessary=
36246 this->update_polygon_using_face_mesh(poly_pt,check_only);
36249 if(update_necessary)
36259 update_was_performed=
36260 this->update_polygon_using_face_mesh(poly_pt);
36278 if(this->Internal_hole_point_update_fct_pt!=0)
36280 this->Internal_hole_point_update_fct_pt(ihole,poly_pt);
36287 unsigned n_polyline = poly_pt->
npolyline();
36290 vertex_coord.resize(2);
36291 internal_point_coord[ihole].resize(2);
36295 internal_point_coord[ihole][0] = 0.0;
36296 internal_point_coord[ihole][1] = 0.0;
36298 for(
unsigned p=0;p<n_polyline;p++)
36303 for(
unsigned v=0;v<n_vertex;v++)
36306 for(
unsigned i=0;
i<2;
i++)
36308 poly_ave[
i] += vertex_coord[
i];
36313 for(
unsigned i=0;
i<2;
i++)
36315 internal_point_coord[ihole][
i] += poly_ave[
i]/n_vertex;
36320 for(
unsigned i=0;
i<2;
i++)
36322 internal_point_coord[ihole][
i] /= n_polyline;
36386 return update_was_performed;
36395 template<
class ELEMENT>
36404 std::ifstream node_file(node_file_name.c_str(),std::ios_base::in);
36407 if(!node_file.is_open())
36409 std::string error_msg(
"Failed to open node file: ");
36410 error_msg +=
"\"" + node_file_name +
"\".";
36412 OOMPH_EXCEPTION_LOCATION);
36417 node_file >> nnodes;
36420 unsigned dimension;
36421 node_file >> dimension;
36427 OOMPH_CURRENT_FUNCTION,
36428 OOMPH_EXCEPTION_LOCATION);
36437 unsigned npoint_attributes;
36438 node_file >> npoint_attributes;;
36441 unsigned boundary_markers_flag=0;
36442 node_file >> boundary_markers_flag;
36445 unsigned dummy_node_number;
36447 unsigned dummy_node_attribute;
36449 unsigned dummy_node_boundary;
36453 for(
unsigned i=0;
i<nnodes;
i++)
36455 node_file>>dummy_node_number;
36456 node_file>>x_node[
i];
36457 node_file>>y_node[
i];
36458 for(
unsigned j=0;j<npoint_attributes;++j)
36460 node_file>>dummy_node_attribute;
36462 if(boundary_markers_flag)
36464 node_file>>dummy_node_boundary;
36473 std::map<unsigned,Vector<std::pair<unsigned,unsigned> > >
36474 unsorted_boundary_segments;
36485 std::ifstream poly_file(poly_file_name.c_str(),std::ios_base::in);
36488 if(!poly_file.is_open())
36490 std::string error_msg(
"Failed to open poly file: ");
36491 error_msg +=
"\"" + poly_file_name +
"\".";
36493 OOMPH_EXCEPTION_LOCATION);
36497 unsigned n_node_poly;
36498 poly_file >> n_node_poly;
36501 poly_file >> dimension;
36504 unsigned attribute_flag;
36505 poly_file >> attribute_flag;
36508 poly_file >> boundary_markers_flag;
36513 for(
unsigned i=0;
i<n_node_poly;
i++)
36520 for(
unsigned j=0;j<attribute_flag;++j)
36522 poly_file >> dummy;
36525 if(boundary_markers_flag==1)
36532 unsigned read_value;
36535 poly_file >> read_value;
36536 const unsigned nglobal_segments = read_value;
36539 poly_file >> boundary_markers_flag;
36542 unsigned global_segment_number;
36545 std::set<unsigned> nodes_ids;
36548 for(
unsigned i=0;
i<nglobal_segments;
i++)
36551 unsigned lnode_id=0;
36552 unsigned rnode_id=0;
36554 poly_file >> global_segment_number;
36555 poly_file >> lnode_id;
36556 poly_file >> rnode_id;
36557 nodes_ids.insert(lnode_id);
36558 nodes_ids.insert(rnode_id);
36559 if(boundary_markers_flag)
36561 poly_file >> bnd_id;
36567 unsorted_boundary_segments[bnd_id-1].push_back(
36568 std::make_pair(lnode_id, rnode_id));
36575 const unsigned nsorted_boundaries_ids =
36576 sorted_boundaries_ids.size();
36578 bool boundary_id_found =
false;
36579 for (
unsigned ib = 0; ib < nsorted_boundaries_ids; ib++)
36581 if (sorted_boundaries_ids[ib] == bnd_id - 1)
36583 boundary_id_found =
true;
36589 if (!boundary_id_found)
36591 sorted_boundaries_ids.push_back(bnd_id - 1);
36601 if (nglobal_segments != nodes_ids.size())
36603 std::ostringstream error_message;
36605 <<
"The number of nodes (" << nodes_ids.size() <<
") and segments (" 36606 << nglobal_segments <<
") is different.\nThis may mean that there " 36607 <<
"are internal non-closed boundaries defined in\nthe polyfile. " 36608 <<
"If you need this feature please use the TriangleMeshPoyLine\n" 36609 <<
"and TriangleMeshCurviLine objects to define your domain.\n\n";
36611 OOMPH_CURRENT_FUNCTION,
36612 OOMPH_EXCEPTION_LOCATION);
36619 const unsigned nboundary = unsorted_boundary_segments.size();
36622 if (nboundary != this->nboundary())
36624 std::ostringstream error_message;
36626 <<
"The number of boundaries on the mesh (" << this->nboundary()
36627 <<
") is different from the number of\nboundaries read from the " 36628 <<
"polyfiles (" << unsorted_boundary_segments.size() <<
")!!!\n\n\n";
36630 OOMPH_CURRENT_FUNCTION,
36631 OOMPH_EXCEPTION_LOCATION);
36637 const unsigned nsorted_boundaries_ids =
36638 sorted_boundaries_ids.size();
36640 if (nsorted_boundaries_ids != this->nboundary())
36642 std::ostringstream error_message;
36644 <<
"The number of boundaries on the mesh (" << this->nboundary()
36645 <<
") is different from the number of\nsorted boundaries ids read " 36646 <<
"from the polyfiles (" << nsorted_boundaries_ids <<
")!!!\n\n\n";
36648 OOMPH_CURRENT_FUNCTION,
36649 OOMPH_EXCEPTION_LOCATION);
36654 std::map<unsigned, std::list<unsigned> > sorted_boundary_segments;
36657 std::map<unsigned,Vector<std::pair<unsigned,unsigned> > >::iterator it;
36659 for (it = unsorted_boundary_segments.begin();
36660 it != unsorted_boundary_segments.end();
36665 const unsigned bnd_id = (*it).first;
36669 std::map<std::pair<unsigned, unsigned>,
bool> segment_done;
36670 const unsigned nsegments = segments_edges.size();
36673 std::list<unsigned> sorted_segments;
36676 unsigned left_node_id = segments_edges[0].first;
36677 unsigned right_node_id = segments_edges[0].second;
36680 sorted_segments.push_back(left_node_id);
36681 sorted_segments.push_back(right_node_id);
36684 segment_done[segments_edges[0]] =
true;
36687 unsigned nsorted_segments = 1;
36689 while(nsorted_segments < nsegments)
36691 for (
unsigned i = 1;
i < nsegments;
i++)
36694 if (!segment_done[segments_edges[
i]])
36697 unsigned current_left_node_id = segments_edges[
i].first;
36698 unsigned current_right_node_id = segments_edges[
i].second;
36702 if (current_left_node_id == right_node_id)
36706 sorted_segments.push_back(current_right_node_id);
36708 nsorted_segments++;
36710 segment_done[segments_edges[
i]] =
true;
36712 right_node_id = current_right_node_id;
36716 else if (current_right_node_id == left_node_id)
36720 sorted_segments.push_front(current_left_node_id);
36722 nsorted_segments++;
36724 segment_done[segments_edges[
i]] =
true;
36726 left_node_id = current_left_node_id;
36730 else if (current_left_node_id == left_node_id)
36734 sorted_segments.push_front(current_right_node_id);
36736 nsorted_segments++;
36738 segment_done[segments_edges[
i]] =
true;
36740 left_node_id = current_right_node_id;
36744 else if (current_right_node_id == right_node_id)
36748 sorted_segments.push_back(current_left_node_id);
36750 nsorted_segments++;
36752 segment_done[segments_edges[
i]] =
true;
36754 right_node_id = current_left_node_id;
36762 sorted_boundary_segments[bnd_id] = sorted_segments;
36768 if (sorted_boundary_segments.size() != this->nboundary())
36770 std::ostringstream error_message;
36772 <<
"The number of boundaries on the mesh (" << this->nboundary()
36773 <<
") is different from the number\nof sorted boundaries to create the " 36774 <<
"polylines (" << sorted_boundary_segments.size() <<
")\n\n";
36776 OOMPH_CURRENT_FUNCTION,
36777 OOMPH_EXCEPTION_LOCATION);
36784 unsigned current_polyline = 0;
36787 for (
unsigned ib = 0; ib < nsorted_boundaries_ids; ib++)
36790 const unsigned bnd_id = sorted_boundaries_ids[ib];
36795 for (std::list<unsigned>::iterator it_list =
36796 sorted_boundary_segments[bnd_id].begin();
36797 it_list != sorted_boundary_segments[bnd_id].end();
36799 {nodes_ids.push_back((*it_list));}
36802 const unsigned nvertices = nodes_ids.size();
36808 for (
unsigned i = 0;
i < nvertices;
i++)
36811 vertices[
i].resize(2);
36812 vertices[
i][0] = x_node[nodes_ids[
i]-1];
36813 vertices[
i][1] = y_node[nodes_ids[
i]-1];
36821 polylines_pt[current_polyline] =
36825 this->Boundary_curve_section_pt[bnd_id] =
36829 current_polyline++;
36836 unsigned nsorted_polylines = 0;
36839 unsigned npolygons = 0;
36845 std::map<unsigned, bool> polyline_done;
36846 while(nsorted_polylines < nboundary)
36849 std::list<TriangleMeshCurveSection*> sorted_curve_sections_pt;
36851 unsigned init_poly = 0;
36853 bool found_root_polyline =
false;
36856 for (
unsigned i = 0;
i < nboundary;
i++)
36858 if (!polyline_done[
i])
36862 nsorted_polylines++;
36865 found_root_polyline =
true;
36868 polyline_done[
i] =
true;
36870 sorted_curve_sections_pt.push_back(polylines_pt[i]);
36877 if (!found_root_polyline)
36879 std::ostringstream error_message;
36881 <<
"Was not possible to found the root polyline to create polygons\n\n";
36883 OOMPH_CURRENT_FUNCTION,
36884 OOMPH_EXCEPTION_LOCATION);
36889 const unsigned bnd_id = polylines_pt[init_poly]->boundary_id();
36891 unsigned left_node_id = sorted_boundary_segments[bnd_id].front();
36892 unsigned right_node_id = sorted_boundary_segments[bnd_id].back();
36895 bool closed_polygon =
false;
36900 for (
unsigned i = init_poly;
i < nboundary;
i++)
36903 if (!polyline_done[
i])
36908 const unsigned cbnd_id = polylines_pt[
i]->boundary_id();
36910 unsigned cleft_node_id = sorted_boundary_segments[cbnd_id].front();
36911 unsigned cright_node_id = sorted_boundary_segments[cbnd_id].back();
36915 if (cleft_node_id == right_node_id)
36918 sorted_curve_sections_pt.push_back(polylines_pt[i]);
36920 polyline_done[
i] =
true;
36922 right_node_id = cright_node_id;
36924 nsorted_polylines++;
36928 else if (cright_node_id == left_node_id)
36931 sorted_curve_sections_pt.push_front(polylines_pt[i]);
36933 polyline_done[
i] =
true;
36935 left_node_id = cleft_node_id;
36937 nsorted_polylines++;
36941 else if (cleft_node_id == left_node_id)
36944 polylines_pt[
i]->reverse();
36946 sorted_curve_sections_pt.push_front(polylines_pt[i]);
36948 polyline_done[
i] =
true;
36950 left_node_id = cright_node_id;
36952 nsorted_polylines++;
36956 else if (cright_node_id == right_node_id)
36959 polylines_pt[
i]->reverse();
36961 sorted_curve_sections_pt.push_back(polylines_pt[i]);
36963 polyline_done[
i] =
true;
36965 right_node_id = cleft_node_id;
36967 nsorted_polylines++;
36976 if (left_node_id == right_node_id)
36979 closed_polygon =
true;
36982 }
while(nsorted_polylines < nboundary && !closed_polygon);
36985 if (!closed_polygon)
36987 std::ostringstream error_message;
36989 <<
"It was not possible to create a closed curve, these are the " 36990 <<
"vertices of the already sorted polylines\n\n";
36991 unsigned cpolyline = 0;
36992 for (std::list<TriangleMeshCurveSection*>::iterator it_list =
36993 sorted_curve_sections_pt.begin();
36994 it_list != sorted_curve_sections_pt.end();
36997 error_message <<
"Polyline (" << cpolyline <<
")\n";
37000 const unsigned nvertex = tmp_poly_pt->
nvertex();
37001 for (
unsigned v = 0; v < nvertex; v++)
37006 error_message <<
"\n";
37010 OOMPH_CURRENT_FUNCTION,
37011 OOMPH_EXCEPTION_LOCATION);
37018 for (std::list<TriangleMeshCurveSection*>::iterator it_list =
37019 sorted_curve_sections_pt.begin();
37020 it_list != sorted_curve_sections_pt.end();
37022 {tmp_sorted_curve_sections_pt.push_back((*it_list));}
37029 this->Free_polygon_pt.insert(polygon_pt);
37032 polygons_pt.push_back(polygon_pt);
37045 unsigned index_outer = 0;
37047 for (
unsigned idx_outer = 0; idx_outer < npolygons; idx_outer++)
37054 bool all_inner_inside =
true;
37057 const unsigned nouter_polylines = polygons_pt[idx_outer]->npolyline();
37058 for (
unsigned p = 0; p < nouter_polylines; p++)
37061 polygons_pt[idx_outer]->polyline_pt(p);
37062 const unsigned nvertex = tmp_poly_pt->
nvertex();
37063 for (
unsigned v = 0; v < nvertex; v++)
37066 outer_vertex_coordinates.push_back(current_vertex);
37075 const unsigned ninner_polygons = polygons_pt.size() - 1;
37080 for (
unsigned i = 0;
i <= ninner_polygons;
i++)
37082 if (
i != idx_outer)
37085 const unsigned ninner_polylines = polygons_pt[
i]->npolyline();
37086 for (
unsigned p = 0; p < ninner_polylines; p++)
37089 const unsigned nvertex = tmp_poly_pt->
nvertex();
37090 for (
unsigned v = 0; v < nvertex; v++)
37095 inner_vertex_coordinates[
i].push_back(current_vertex);
37097 else if (
i > idx_outer)
37099 inner_vertex_coordinates[
i-1].push_back(current_vertex);
37111 for (
unsigned i = 0;
i < ninner_polygons;
i++)
37115 const unsigned nvertex_internal = inner_vertex_coordinates[
i].size();
37116 for (
unsigned v = 0; v < nvertex_internal; v++)
37120 all_inner_inside &=
37121 this->is_point_inside_polygon_helper(outer_vertex_coordinates,
37126 if (!all_inner_inside)
37136 if (!all_inner_inside)
37146 if (all_inner_inside)
37148 index_outer = idx_outer;
37158 if (index_outer != 0)
37160 std::ostringstream warning_message;
37162 <<
"The first set of nodes listed in the input polyfiles does not\n" 37163 <<
"correspond to the outer closed boundary. This may lead to\n" 37164 <<
"problems at the adaptation stage if the holes coordinates\n" 37165 <<
"are no correctly associated to the inner closed boundaries.\n" 37166 <<
"You can check the generated mesh by calling the output() method\n" 37167 <<
"from the mesh object '(problem.mesh_pt()->output(string))'\n\n";
37169 OOMPH_CURRENT_FUNCTION,
37170 OOMPH_EXCEPTION_LOCATION);
37179 this->Outer_boundary_pt.resize(1);
37180 this->Outer_boundary_pt[0] = polygons_pt[index_outer];
37182 this->Internal_polygon_pt.resize(npolygons-1);
37183 for (
unsigned i = 0;
i < npolygons;
i++)
37185 if (
i != index_outer)
37187 if (
i < index_outer)
37190 this->Internal_polygon_pt[
i] = polygons_pt[
i];
37192 else if (
i > index_outer)
37195 this->Internal_polygon_pt[
i-1] = polygons_pt[
i];
37208 for (
unsigned i = 0;
i < npolygons-1;
i++)
37211 const unsigned ninner_polylines =
37212 this->Internal_polygon_pt[
i]->npolyline();
37213 for (
unsigned p = 0; p < ninner_polylines; p++)
37216 this->Internal_polygon_pt[
i]->polyline_pt(p);
37219 const unsigned nvertex = tmp_poly_pt->
nvertex();
37220 for (
unsigned v = 0; v < nvertex; v++)
37223 inner_vertex_coordinates[
i].push_back(current_vertex);
37232 poly_file >> nholes;
37235 if (npolygons > 1 && (npolygons - 1) != nholes)
37237 std::ostringstream error_message;
37239 <<
"The number of holes (" << nholes <<
") does not correspond " 37240 <<
"with the number\nof internal polygons (" 37241 << npolygons - 1 <<
")\n\n" 37242 <<
"Using polyfiles as input does not currently allows the\n" 37243 <<
"definition of more than one outer polygon\n\n";
37245 OOMPH_CURRENT_FUNCTION,
37246 OOMPH_EXCEPTION_LOCATION);
37254 unsigned dummy_hole;
37256 for(
unsigned ihole=0;ihole<nholes;ihole++)
37258 hole_coordinates[ihole].resize(2);
37260 poly_file >> dummy_hole;
37261 poly_file >> hole_coordinates[ihole][0];
37262 poly_file >> hole_coordinates[ihole][1];
37268 std::map<unsigned, bool> hole_done;
37272 for (
unsigned i = 0;
i < npolygons-1;
i++)
37275 for (
unsigned h = 0; h < nholes; h++)
37283 const bool hole_in_polygon =
37284 this->is_point_inside_polygon_helper(inner_vertex_coordinates[
i],
37288 if (hole_in_polygon)
37291 hole_done[h] =
true;
37294 index_hole_of_internal_polygon[
i] = h;
37306 if (hole_done.size() != npolygons-1)
37308 std::ostringstream error_message;
37310 <<
"Not all the holes were associated to an internal closed boundary\n" 37311 <<
"Only ("<<hole_done.size()<<
") holes were assigned for a total of\n" 37312 <<
"(" << npolygons-1 <<
") internal closed boundaries.\n" 37313 <<
"You can check the generated mesh by calling the output() method\n" 37314 <<
"from the mesh object '(problem.mesh_pt()->output(string))'\n\n";
37316 OOMPH_CURRENT_FUNCTION,
37317 OOMPH_EXCEPTION_LOCATION);
37322 for (
unsigned ihole = 0; ihole < nholes; ihole++)
37325 const unsigned index_hole = index_hole_of_internal_polygon[ihole];
37330 if (index_hole != ihole)
37332 std::ostringstream error_message;
37334 <<
"The hole vertices coordinates are not listed in the same order\n" 37335 <<
"as the nodes that define the internal closed boundaries.\n" 37336 <<
"This may lead to problems in case that the holes coordinates\n" 37337 <<
"were no properly assigned to the internal closed boundaries.\n" 37338 <<
"You can check the generated mesh by calling the output() method\n" 37339 <<
"from the mesh object '(problem.mesh_pt()->output(string))'\n\n";
37341 OOMPH_CURRENT_FUNCTION,
37342 OOMPH_EXCEPTION_LOCATION);
37347 this->Internal_polygon_pt[ihole]->internal_point() =
37348 hole_coordinates[index_hole];
37352 poly_file.ignore(80,
'\n');
37362 getline(poly_file, regions_info_string);
37366 if (isdigit(regions_info_string.c_str()[0]))
37368 nregions = std::atoi(regions_info_string.c_str());
37376 std::map<unsigned, Vector<double> > regions_coordinates;
37379 unsigned dummy_region;
37381 unsigned region_id;
37384 for(
unsigned iregion=0;iregion<nregions;iregion++)
37388 poly_file >> dummy_region;
37389 poly_file >> tmp_region_coordinates[0];
37390 poly_file >> tmp_region_coordinates[1];
37391 poly_file >> region_id;
37392 regions_coordinates[region_id].resize(2);
37393 regions_coordinates[region_id][0] = tmp_region_coordinates[0];
37394 regions_coordinates[region_id][1] = tmp_region_coordinates[1];
37397 poly_file.ignore(80,
'\n');
37400 if (region_id == 0)
37402 std::ostringstream error_message;
37403 error_message <<
"Please use another region id different from zero.\n" 37404 <<
"It is internally used as the default region number.\n";
37406 OOMPH_CURRENT_FUNCTION,
37407 OOMPH_EXCEPTION_LOCATION);
37413 this->Regions_coordinates = regions_coordinates;
37423 template <
class ELEMENT>
37429 unsigned update_was_performed =
false;
37431 const unsigned nele = this->nelement();
37442 get_face_mesh_representation(polygon_pt,face_mesh_pt);
37450 unsigned n_polyline = polygon_pt->
npolyline();
37453 for(
unsigned p = 0; p < n_polyline; p++)
37466 std::set<Vector<double> > vertex_nodes;
37477 #ifdef OOMPH_HAS_MPI 37507 const unsigned nface_element = face_mesh_pt[p]->nelement();
37514 std::map<FiniteElement*,unsigned> face_element_index_on_boundary;
37516 for(
unsigned ef=0;ef<nface_element;++ef)
37518 FiniteElement* ele_face_pt = face_mesh_pt[p]->finite_element_pt(ef);
37519 #ifdef OOMPH_HAS_MPI 37521 if (this->is_mesh_distributed() && ele_face_pt->
is_halo())
37525 non_halo_face_element_pt.push_back(ele_face_pt);
37526 face_element_index_on_boundary[ele_face_pt] = ef;
37530 const unsigned nnon_halo_face_element = non_halo_face_element_pt.size();
37533 std::map<FiniteElement*,bool> face_element_done;
37536 unsigned nsorted_face_elements = 0;
37538 #ifdef OOMPH_HAS_MPI 37540 unsigned nsub_boundaries = 0;
37541 #endif // #ifdef OOMPH_HAS_MPI 37545 while(nsorted_face_elements < nnon_halo_face_element)
37550 bool found_initial_face_element =
false;
37553 unsigned iface = 0;
37554 for (iface = 0; iface < nnon_halo_face_element; iface++)
37556 ele_face_pt = non_halo_face_element_pt[iface];
37558 if (!face_element_done[ele_face_pt])
37561 found_initial_face_element =
true;
37563 nsorted_face_elements++;
37570 if (!found_initial_face_element)
37572 std::ostringstream error_message;
37574 <<
"Could not find an initial face element for the current segment\n";
37577 "RefineableTriangleMesh::update_polygon_using_elements_area()",
37578 OOMPH_EXCEPTION_LOCATION);
37585 std::set<Vector<double> > local_vertex_nodes;
37593 std::set<Vector<double> > sorted_target_areas;
37603 unsigned nnode = ele_face_pt->
nnode();
37607 vertex_coord[0] = bound_left[0];
37610 for(
unsigned i=0;
i<2;
i++)
37612 vertex_coord[
i+1] = ele_face_pt->
node_pt(0)->
x(
i);
37614 local_vertex_nodes.insert(vertex_coord);
37618 ele_face_pt->
node_pt(nnode-1)->
37619 get_coordinates_on_boundary(bound,bound_right);
37620 vertex_coord[0] = bound_right[0];
37623 for(
unsigned i=0;
i<2;
i++)
37625 vertex_coord[
i+1] = ele_face_pt->
node_pt(nnode-1)->
x(
i);
37627 local_vertex_nodes.insert(vertex_coord);
37631 Node *last_node_pt = ele_face_pt->
node_pt(nnode-1);
37634 face_element_done[ele_face_pt] =
true;
37646 zeta_target_area_values[0] =
37647 std::min(bound_left[0], bound_right[0]);
37650 unsigned ef = face_element_index_on_boundary[ele_face_pt];
37652 FiniteElement *el_pt = this->boundary_element_pt(bound, ef);
37655 bool found_global_element_index =
false;
37657 for (
unsigned eg = 0 ; eg < nele; eg++)
37660 FiniteElement *el_compare_pt = this->finite_element_pt(eg);
37664 if (el_pt == el_compare_pt)
37666 zeta_target_area_values[1] = target_area[eg];
37668 found_global_element_index =
true;
37675 if (!found_global_element_index)
37677 std::ostringstream error_message;
37679 <<
"The global index for the ("<< ef <<
")-th face element " 37680 <<
"on\nthe ("<< bound <<
")-th boundary was not found!!!";
37682 "RefineableTriangleMesh::update_polygon_using_elements_area()",
37683 OOMPH_EXCEPTION_LOCATION);
37688 sorted_target_areas.insert(zeta_target_area_values);
37693 bool face_element_added =
false;
37703 for (
unsigned iiface=iface;iiface<nnon_halo_face_element;iiface++)
37705 face_element_added =
false;
37706 ele_face_pt = non_halo_face_element_pt[iiface];
37707 if (!face_element_done[ele_face_pt])
37710 nnode = ele_face_pt->nnode();
37711 Node* left_node_pt = ele_face_pt->node_pt(0);
37712 Node* right_node_pt = ele_face_pt->node_pt(nnode-1);
37714 if (left_node_pt == first_node_pt)
37716 first_node_pt = right_node_pt;
37717 face_element_added =
true;
37719 else if (left_node_pt == last_node_pt)
37721 last_node_pt = right_node_pt;
37722 face_element_added =
true;
37724 else if (right_node_pt == first_node_pt)
37726 first_node_pt = left_node_pt;
37727 face_element_added =
true;
37729 else if (right_node_pt == last_node_pt)
37731 last_node_pt = left_node_pt;
37732 face_element_added =
true;
37735 if (face_element_added)
37740 vertex_coord[0] = bound_left[0];
37743 for(
unsigned i=0;
i<2;
i++)
37745 vertex_coord[
i+1] = left_node_pt->
x(
i);
37747 local_vertex_nodes.insert(vertex_coord);
37752 vertex_coord[0] = bound_right[0];
37755 for(
unsigned i=0;
i<2;
i++)
37757 vertex_coord[
i+1] = right_node_pt->
x(
i);
37759 local_vertex_nodes.insert(vertex_coord);
37763 face_element_done[ele_face_pt] =
true;
37764 nsorted_face_elements++;
37772 zeta_target_area_values[0] =
37773 std::min(bound_left[0], bound_right[0]);
37776 ef = face_element_index_on_boundary[ele_face_pt];
37777 FiniteElement *lel_pt = this->boundary_element_pt(bound, ef);
37780 found_global_element_index =
false;
37782 for (
unsigned eg = 0 ; eg < nele; eg++)
37785 FiniteElement *lel_compare_pt = this->finite_element_pt(eg);
37789 if (lel_pt == lel_compare_pt)
37791 zeta_target_area_values[1] = target_area[eg];
37793 found_global_element_index =
true;
37800 if (!found_global_element_index)
37802 std::ostringstream error_message;
37804 <<
"The global index for the ("<< ef <<
")-th face element " 37805 <<
"on\nthe ("<< bound <<
")-th boundary was not found!!!";
37807 "RefineableTriangleMesh::update_polygon_using_elements_area()",
37808 OOMPH_EXCEPTION_LOCATION);
37813 sorted_target_areas.insert(zeta_target_area_values);
37820 }
while(face_element_added &&
37821 (nsorted_face_elements < nnon_halo_face_element));
37829 const unsigned nlocal_nodes = local_vertex_nodes.size();
37831 local_tmp_vector_vertex_node.resize(nlocal_nodes);
37834 unsigned counter = 0;
37835 std::set<Vector<double> >::iterator it_vertex;
37836 for (it_vertex = local_vertex_nodes.begin();
37837 it_vertex != local_vertex_nodes.end();
37840 local_tmp_vector_vertex_node[counter].resize(3);
37841 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
37842 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
37843 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
37849 const unsigned ntarget_areas = sorted_target_areas.size();
37850 tmp_sorted_target_areas.resize(ntarget_areas);
37852 std::set<Vector<double> >::iterator it_area;
37853 for(it_area = sorted_target_areas.begin();
37854 it_area != sorted_target_areas.end();
37857 tmp_sorted_target_areas[counter] = (*it_area)[1];
37862 if (nlocal_nodes > 0 && (ntarget_areas != nlocal_nodes - 1) )
37864 std::ostringstream error_message;
37866 <<
"The boundary (" << bound <<
") was split during the " 37867 <<
"distribution process.\n" 37868 <<
"The problem is in the association of the target areas with the\n" 37869 <<
"elements that gave rise to the vertex coordinates.\n" 37870 <<
"The number of local nodes (" << nlocal_nodes
37871 <<
"), on the 'sub-polyline', is not\n" 37872 <<
"according with the number of target " 37873 <<
"areas ("<< ntarget_areas <<
")\nfor that number of nodes.\n" 37874 <<
"The target areas number MUST be equal to the number of\n" 37875 <<
"local nodes minus one\n\n";
37877 OOMPH_CURRENT_FUNCTION,
37878 OOMPH_EXCEPTION_LOCATION);
37889 double unrefinement_tolerance=
37893 bool unrefinement_applied =
37894 unrefine_boundary_constrained_by_target_area(
37895 bound, chunk, local_tmp_vector_vertex_node,
37896 unrefinement_tolerance, tmp_sorted_target_areas);
37899 double refinement_tolerance=
37903 bool refinement_applied =
37904 refine_boundary_constrained_by_target_area(
37905 mesh_geom_obj_pt, local_tmp_vector_vertex_node,
37906 refinement_tolerance, tmp_sorted_target_areas);
37910 local_vertex_nodes.clear();
37915 unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
37916 for (
unsigned i = 0;
i < nnew_nodes;
i++)
37918 vertex_coord[0] = local_tmp_vector_vertex_node[
i][0];
37919 vertex_coord[1] = local_tmp_vector_vertex_node[
i][1];
37920 vertex_coord[2] = local_tmp_vector_vertex_node[
i][2];
37921 vertex_nodes.insert(vertex_coord);
37922 local_vertex_nodes.insert(vertex_coord);
37927 update_was_performed = (unrefinement_applied || refinement_applied);
37929 #ifdef OOMPH_HAS_MPI 37930 if (this->is_mesh_distributed())
37934 sub_vertex_nodes.push_back(local_vertex_nodes);
37943 unsigned npoly_vertex = vertex_nodes.size();
37946 tmp_vector_vertex_node.resize(npoly_vertex);
37947 unsigned count = 0;
37948 for(std::set<
Vector<double> >::iterator it = vertex_nodes.begin();
37949 it!=vertex_nodes.end(); ++it)
37951 tmp_vector_vertex_node[count].resize(3);
37952 tmp_vector_vertex_node[count][0] = (*it)[0];
37953 tmp_vector_vertex_node[count][1] = (*it)[1];
37954 tmp_vector_vertex_node[count][2] = (*it)[2];
37958 #ifdef OOMPH_HAS_MPI 37961 unsigned nsub_boundaries_set = sub_vertex_nodes.size();
37962 if (nsub_boundaries_set != nsub_boundaries)
37964 std::ostringstream error_message;
37966 <<
"The number of found sub-boundaries and the number of counted\n" 37967 <<
"sub-boundaries are different:\n" 37968 <<
"Number of found sub-boundaries: ("<<nsub_boundaries_set<<
")\n" 37969 <<
"Number of counted sub-boundaries: ("<<nsub_boundaries<<
")\n";
37971 OOMPH_CURRENT_FUNCTION,
37972 OOMPH_EXCEPTION_LOCATION);
37977 if (this->is_mesh_distributed() && nsub_boundaries > 1)
37980 this->Boundary_was_splitted[bound] =
true;
37982 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
37983 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
37986 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
37987 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
37988 unsigned subcount = 0;
37989 std::set<Vector<double> >::iterator subit;
37990 for(subit = sub_vertex_nodes[isub].begin();
37991 subit != sub_vertex_nodes[isub].end(); ++subit)
37993 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
37994 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
37995 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
37996 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
38002 #endif // OOMPH_HAS_MPI 38006 unsigned n_vertex=tmp_vector_vertex_node.size();
38009 vector_vertex_node.resize(n_vertex);
38010 for(
unsigned i=0;
i<n_vertex;
i++)
38012 vector_vertex_node[
i].resize(2);
38013 vector_vertex_node[
i][0]=tmp_vector_vertex_node[
i][1];
38014 vector_vertex_node[
i][1]=tmp_vector_vertex_node[
i][2];
38017 #ifdef OOMPH_HAS_MPI 38020 if (this->is_mesh_distributed() && nsub_boundaries > 1)
38025 sub_vector_vertex_node.resize(nsub_boundaries);
38026 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
38028 const unsigned subn_vertex =
38029 sub_tmp_vector_vertex_node[isub].size();
38031 sub_vector_vertex_node[isub].resize(subn_vertex);
38032 for(
unsigned i=0;
i<subn_vertex;
i++)
38034 sub_vector_vertex_node[isub][
i].resize(2);
38035 sub_vector_vertex_node[isub][
i][0]=
38036 sub_tmp_vector_vertex_node[isub][
i][1];
38037 sub_vector_vertex_node[isub][
i][1]=
38038 sub_tmp_vector_vertex_node[isub][
i][2];
38048 #endif // OOMPH_HAS_MPI 38053 #ifdef OOMPH_HAS_MPI 38057 if (!this->is_mesh_distributed())
38064 unsigned n_prev_vertex =
38066 final_vertex_of_previous_segment =
38068 vertex_coordinate(n_prev_vertex-1);
38070 unsigned prev_seg_boundary_id =
38075 double error = 0.0;
38076 for(
unsigned i=0;
i<2;
i++)
38078 const double dist =
38079 final_vertex_of_previous_segment[
i] -
38080 (*vector_vertex_node.begin())[
i];
38081 error += dist*dist;
38083 error = sqrt(error);
38091 double rev_error = 0.0;
38092 for(
unsigned i=0;
i<2;
i++)
38094 const double dist =
38095 final_vertex_of_previous_segment[
i] -
38096 (*--vector_vertex_node.end())[
i];
38097 rev_error += dist*dist;
38099 rev_error = sqrt(rev_error);
38113 initial_vertex_of_previous_segment =
38115 vertex_coordinate(0);
38117 unsigned prev_seg_boundary_id =
38122 double error = 0.0;
38123 for(
unsigned i=0;
i<2;
i++)
38125 const double dist =
38126 initial_vertex_of_previous_segment[
i] -
38127 (*vector_vertex_node.begin())[
i];
38128 error += dist*dist;
38130 error = sqrt(error);
38138 double rev_error = 0.0;
38139 for(
unsigned i=0;
i<2;
i++)
38141 const double dist =
38142 initial_vertex_of_previous_segment[
i] -
38143 (*--vector_vertex_node.end())[
i];
38144 rev_error += dist*dist;
38146 rev_error = sqrt(rev_error);
38152 std::ostringstream error_stream;
38154 <<
"The distance between the first node of the current\n" 38155 <<
"line segment (boundary "<<bound<<
") and either end of " 38156 <<
"the previous line segment\n" 38157 <<
"(boundary "<<prev_seg_boundary_id<<
") is bigger than " 38158 <<
"the desired tolerance " 38161 <<
"This suggests that the polylines defining the " 38163 <<
"representation are not properly ordered.\n" 38164 <<
"Fail on last vertex of polyline: (" 38165 << prev_seg_boundary_id <<
") and\n" 38166 <<
"first vertex of polyline (" << bound <<
").\n" 38167 <<
"This should have failed when first trying to " 38168 <<
"construct the\npolygon.\n";
38170 OOMPH_CURRENT_FUNCTION,
38171 OOMPH_EXCEPTION_LOCATION);
38178 std::reverse(vector_vertex_node.begin(),
38179 vector_vertex_node.end());
38193 std::ostringstream error_stream;
38195 <<
"The distance between the first node of the current\n" 38196 <<
"line segment (boundary " << bound <<
") and either end of " 38197 <<
"the previous line segment\n" 38198 <<
"(boundary "<<prev_seg_boundary_id<<
") is bigger than the " 38199 <<
"desired tolerance " <<
38201 <<
"This suggests that the polylines defining the polygonal\n" 38202 <<
"representation are not properly ordered.\n" 38203 <<
"Fail on last vertex of polyline: ("<<prev_seg_boundary_id
38204 <<
") and\nfirst vertex of polyline ("<<bound <<
").\n" 38205 <<
"This should have failed when first trying to construct" 38206 <<
" the polygon.\n";
38208 OOMPH_CURRENT_FUNCTION,
38209 OOMPH_EXCEPTION_LOCATION);
38215 std::reverse(vector_vertex_node.begin(),vector_vertex_node.end());
38233 n_vertex = vector_vertex_node.size();
38245 double unrefinement_tolerance=
38249 double refinement_tolerance=
38260 #ifdef OOMPH_HAS_MPI 38263 if (this->is_mesh_distributed())
38269 this->copy_connection_information(polygon_pt->
polyline_pt(p),
38270 tmp_curve_section_pt);
38278 this->copy_connection_information(polygon_pt->
polyline_pt(p),
38279 tmp_curve_section_pt);
38285 bool delete_it_on_destructor =
false;
38287 std::set<TriangleMeshCurveSection*>::iterator it =
38290 if (it!=this->Free_curve_section_pt.end())
38292 this->Free_curve_section_pt.erase(it);
38294 delete_it_on_destructor =
true;
38304 if (delete_it_on_destructor)
38309 #ifdef OOMPH_HAS_MPI 38312 if (this->is_mesh_distributed() && nsub_boundaries > 1)
38318 this->Boundary_subpolylines[bound].clear();
38321 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
38322 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
38330 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
38342 #endif // OOMPH_HAS_MPI 38346 delete mesh_geom_obj_pt;
38351 for(
unsigned p=0;p<n_polyline;p++)
38353 face_mesh_pt[p]->flush_node_storage();
38354 delete face_mesh_pt[p];
38357 return update_was_performed;
38365 template <
class ELEMENT>
38371 unsigned update_was_performed =
false;
38373 const unsigned nele = this->nelement();
38384 get_face_mesh_representation(open_curve_pt,face_mesh_pt);
38392 const unsigned ncurve_section = open_curve_pt->
ncurve_section();
38395 for(
unsigned cs = 0; cs < ncurve_section; cs++)
38406 const unsigned bound =
38410 const unsigned chunk =
38420 const unsigned nface_element = face_mesh_pt[cs]->nelement();
38428 std::map<FiniteElement*,unsigned> face_element_index_on_boundary;
38431 std::map<FiniteElement*,bool> face_element_done;
38433 for(
unsigned ef = 0; ef < nface_element; ++ef)
38435 FiniteElement* ele_face_pt = face_mesh_pt[cs]->finite_element_pt(ef);
38440 #ifdef OOMPH_HAS_MPI 38441 if (this->is_mesh_distributed())
38444 if (ele_face_pt->
is_halo()) {
continue;}
38449 if (!face_element_done[ele_face_pt])
38454 non_halo_doubled_face_element_pt.push_back(ele_face_pt);
38456 face_element_index_on_boundary[ele_face_pt] = ef;
38458 face_element_done[ele_face_pt] =
true;
38460 const unsigned nnodes = ele_face_pt->nnode();
38463 Node* left_node_pt = ele_face_pt->node_pt(0);
38464 Node* right_node_pt = ele_face_pt->node_pt(nnodes-1);
38468 bool found_other_side_face_ele =
false;
38470 for (
unsigned iface = 0; iface < nface_element; iface++)
38474 face_mesh_pt[cs]->finite_element_pt(iface);
38476 if (!face_element_done[cele_face_pt])
38478 Node* cleft_node_pt = cele_face_pt->node_pt(0);
38479 Node* cright_node_pt = cele_face_pt->node_pt(nnodes-1);
38481 if ((left_node_pt == cleft_node_pt &&
38482 right_node_pt == cright_node_pt) ||
38483 (left_node_pt == cright_node_pt &&
38484 right_node_pt == cleft_node_pt))
38487 non_halo_doubled_face_element_pt.push_back(cele_face_pt);
38489 face_element_done[cele_face_pt] =
true;
38491 face_element_index_on_boundary[cele_face_pt] = iface;
38494 found_other_side_face_ele =
true;
38502 if (!found_other_side_face_ele)
38504 std::ostringstream error_message;
38506 <<
"The face element at the other side of the boundary (" 38507 << bound <<
") was not found!!\n" 38508 <<
"These are the nodes of the face element:\n" 38509 <<
"("<<left_node_pt->
x(0)<<
", "<<left_node_pt->
x(1)<<
") " 38510 <<
"and ("<<right_node_pt->
x(0)<<
","<<right_node_pt->
x(1)<<
")\n\n";
38512 "RefineableTriangleMesh::update_open_curve_using_elements_area()",
38513 OOMPH_EXCEPTION_LOCATION);
38522 face_element_done.clear();
38527 std::set<Vector<double> > vertex_nodes;
38538 #ifdef OOMPH_HAS_MPI 38543 std::vector<bool> internal_to_shared_boundary;
38563 #endif // #ifdef OOMPH_HAS_MPI 38570 unsigned nsorted_face_elements = 0;
38572 #ifdef OOMPH_HAS_MPI 38574 unsigned nsub_boundaries = 0;
38575 #endif // #ifdef OOMPH_HAS_MPI 38578 const unsigned nnon_halo_doubled_face_ele =
38579 non_halo_doubled_face_element_pt.size();
38583 while(nsorted_face_elements < nnon_halo_doubled_face_ele)
38589 bool found_initial_face_element =
false;
38595 bool both_root_face_elements_are_nonhalo =
false;
38597 unsigned iface = 0;
38598 for (iface = 0; iface < nnon_halo_doubled_face_ele; iface+=2)
38600 ele_face_pt = non_halo_doubled_face_element_pt[iface];
38602 if (!face_element_done[ele_face_pt])
38605 face_element_done[ele_face_pt] =
true;
38607 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iface+1];
38609 face_element_done[repeated_ele_face_pt] =
true;
38611 #ifdef OOMPH_HAS_MPI 38612 if (!repeated_ele_face_pt->
is_halo())
38613 {both_root_face_elements_are_nonhalo =
true;}
38614 #endif // #ifdef OOMPH_HAS_MPI 38618 nsorted_face_elements+=2;
38622 found_initial_face_element =
true;
38629 if (!found_initial_face_element)
38631 std::ostringstream error_message;
38633 <<
"Could not find an initial face element for the current segment\n";
38635 OOMPH_CURRENT_FUNCTION,
38636 OOMPH_EXCEPTION_LOCATION);
38643 std::set<Vector<double> > local_vertex_nodes;
38651 std::set<Vector<double> > sorted_target_areas;
38661 const unsigned nnode = ele_face_pt->
nnode();
38665 vertex_coord[0] = bound_left[0];
38668 for(
unsigned i=0;
i<2;
i++)
38670 vertex_coord[
i+1] = ele_face_pt->
node_pt(0)->
x(
i);
38672 local_vertex_nodes.insert(vertex_coord);
38678 vertex_coord[0] = bound_right[0];
38681 for(
unsigned i=0;
i<2;
i++)
38683 vertex_coord[
i+1] = ele_face_pt->
node_pt(nnode-1)->
x(
i);
38685 local_vertex_nodes.insert(vertex_coord);
38689 Node *last_node_pt = ele_face_pt->
node_pt(nnode-1);
38701 zeta_target_area_values[0] = std::min(bound_left[0], bound_right[0]);
38704 const unsigned ef = face_element_index_on_boundary[ele_face_pt];
38706 FiniteElement *el_pt = this->boundary_element_pt(bound, ef);
38707 double target_area_face_element = 0.0;
38710 bool found_global_element_index =
false;
38712 for (
unsigned eg = 0 ; eg < nele; eg++)
38715 FiniteElement *el_compare_pt = this->finite_element_pt(eg);
38719 if (el_pt == el_compare_pt)
38721 target_area_face_element = target_area[eg];
38723 found_global_element_index =
true;
38730 if (!found_global_element_index)
38732 std::ostringstream error_message;
38734 <<
"The global index for the ("<< ef <<
")-th face element " 38735 <<
"on\nthe ("<< bound <<
")-th boundary was not found!!!";
38737 OOMPH_CURRENT_FUNCTION,
38738 OOMPH_EXCEPTION_LOCATION);
38743 const unsigned ref = face_element_index_on_boundary[repeated_ele_face_pt];
38744 FiniteElement *rel_pt = this->boundary_element_pt(bound, ref);
38745 double target_area_repeated_face_element = 0.0;
38748 bool found_global_repeated_element_index =
false;
38750 for (
unsigned eg = 0 ; eg < nele; eg++)
38753 FiniteElement *el_compare_pt = this->finite_element_pt(eg);
38757 if (rel_pt == el_compare_pt)
38759 target_area_repeated_face_element = target_area[eg];
38761 found_global_repeated_element_index =
true;
38768 if (!found_global_repeated_element_index)
38770 std::ostringstream error_message;
38772 <<
"The global index for the ("<< ref <<
")-th face element " 38773 <<
"on\nthe ("<< bound <<
")-th boundary was not found (repeated " 38774 <<
"face element)!!!";
38776 OOMPH_CURRENT_FUNCTION,
38777 OOMPH_EXCEPTION_LOCATION);
38783 zeta_target_area_values[1]=std::min(target_area_face_element,
38784 target_area_repeated_face_element);
38787 sorted_target_areas.insert(zeta_target_area_values);
38792 bool face_element_added =
false;
38802 for (
unsigned iiface=iface;
38803 iiface<nnon_halo_doubled_face_ele;iiface+=2)
38805 face_element_added =
false;
38806 ele_face_pt = non_halo_doubled_face_element_pt[iiface];
38813 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iiface+1];
38814 bool both_face_elements_are_nonhalo =
false;
38816 #ifdef OOMPH_HAS_MPI 38817 if (!repeated_ele_face_pt->
is_halo())
38818 {both_face_elements_are_nonhalo =
true;}
38819 #endif // #ifdef OOMPH_HAS_MPI 38821 if (!face_element_done[ele_face_pt] &&
38822 (both_face_elements_are_nonhalo ==
38823 both_root_face_elements_are_nonhalo))
38826 const unsigned nlnode = ele_face_pt->
nnode();
38828 Node* right_node_pt = ele_face_pt->
node_pt(nlnode-1);
38830 if (left_node_pt == first_node_pt)
38832 first_node_pt = right_node_pt;
38833 face_element_added =
true;
38835 else if (left_node_pt == last_node_pt)
38837 last_node_pt = right_node_pt;
38838 face_element_added =
true;
38840 else if (right_node_pt == first_node_pt)
38842 first_node_pt = left_node_pt;
38843 face_element_added =
true;
38845 else if (right_node_pt == last_node_pt)
38847 last_node_pt = left_node_pt;
38848 face_element_added =
true;
38851 if (face_element_added)
38856 vertex_coord[0] = bound_left[0];
38859 for(
unsigned i=0;
i<2;
i++)
38861 vertex_coord[
i+1] = left_node_pt->
x(
i);
38863 local_vertex_nodes.insert(vertex_coord);
38868 vertex_coord[0] = bound_right[0];
38871 for(
unsigned i=0;
i<2;
i++)
38873 vertex_coord[
i+1] = right_node_pt->
x(
i);
38875 local_vertex_nodes.insert(vertex_coord);
38879 face_element_done[ele_face_pt] =
true;
38882 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iiface+1];
38883 face_element_done[repeated_ele_face_pt] =
true;
38885 nsorted_face_elements+=2;
38893 zeta_target_area_values[0] =
38894 std::min(bound_left[0], bound_right[0]);
38897 const unsigned lef = face_element_index_on_boundary[ele_face_pt];
38898 FiniteElement *lel_pt = this->boundary_element_pt(bound, lef);
38901 found_global_element_index =
false;
38903 for (
unsigned eg = 0 ; eg < nele; eg++)
38906 FiniteElement *lel_compare_pt = this->finite_element_pt(eg);
38910 if (lel_pt == lel_compare_pt)
38912 target_area_face_element = target_area[eg];
38914 found_global_element_index =
true;
38921 if (!found_global_element_index)
38923 std::ostringstream error_message;
38925 <<
"The global index for the ("<< lef <<
")-th face element " 38926 <<
"on\nthe ("<< bound <<
")-th boundary was not found!!!";
38928 OOMPH_CURRENT_FUNCTION,
38929 OOMPH_EXCEPTION_LOCATION);
38934 const unsigned rlef =
38935 face_element_index_on_boundary[repeated_ele_face_pt];
38936 FiniteElement *rlel_pt = this->boundary_element_pt(bound, rlef);
38939 found_global_repeated_element_index =
false;
38941 for (
unsigned eg = 0 ; eg < nele; eg++)
38944 FiniteElement *lel_compare_pt = this->finite_element_pt(eg);
38948 if (rlel_pt == lel_compare_pt)
38950 target_area_repeated_face_element = target_area[eg];
38952 found_global_repeated_element_index =
true;
38959 if (!found_global_repeated_element_index)
38961 std::ostringstream error_message;
38963 <<
"The global index for the ("<< rlef <<
")-th face element " 38964 <<
"on\nthe ("<< bound <<
")-th boundary was not found " 38965 <<
"(repeated face element)!!!";
38967 OOMPH_CURRENT_FUNCTION,
38968 OOMPH_EXCEPTION_LOCATION);
38974 zeta_target_area_values[1] =
38975 std::min(target_area_face_element,
38976 target_area_repeated_face_element);
38979 sorted_target_areas.insert(zeta_target_area_values);
38986 }
while(face_element_added &&
38987 (nsorted_face_elements < nnon_halo_doubled_face_ele));
38995 const unsigned nlocal_nodes = local_vertex_nodes.size();
38997 local_tmp_vector_vertex_node.resize(nlocal_nodes);
39000 unsigned counter = 0;
39001 std::set<Vector<double> >::iterator it_vertex;
39002 for (it_vertex = local_vertex_nodes.begin();
39003 it_vertex != local_vertex_nodes.end();
39006 local_tmp_vector_vertex_node[counter].resize(3);
39007 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
39008 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
39009 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
39015 const unsigned ntarget_areas = sorted_target_areas.size();
39016 tmp_sorted_target_areas.resize(ntarget_areas);
39018 std::set<Vector<double> >::iterator it_area;
39019 for(it_area = sorted_target_areas.begin();
39020 it_area != sorted_target_areas.end();
39023 tmp_sorted_target_areas[counter] = (*it_area)[1];
39028 if (nlocal_nodes > 0 && (ntarget_areas != nlocal_nodes - 1) )
39030 std::ostringstream error_message;
39032 <<
"The boundary (" << bound <<
") was split during the " 39033 <<
"distribution process.\n" 39034 <<
"The problem comes when associating the target areas with the " 39035 <<
"elements that gave\nrise to the vertex coordinates.\n" 39036 <<
"The number of local nodes on the 'sub-polyline' (" 39037 << nlocal_nodes <<
") is not according with the number of target\n" 39038 <<
"areas ("<< ntarget_areas <<
") for that number of nodes.\n" 39039 <<
"The target areas number must be equal to the number of nodes-1\n";
39041 OOMPH_CURRENT_FUNCTION,
39042 OOMPH_EXCEPTION_LOCATION);
39049 if (local_tmp_vector_vertex_node[nlocal_nodes-1][2] <
39050 local_tmp_vector_vertex_node[0][2])
39052 std::reverse(local_tmp_vector_vertex_node.begin(),
39053 local_tmp_vector_vertex_node.end());
39054 std::reverse(tmp_sorted_target_areas.begin(),
39055 tmp_sorted_target_areas.end());
39057 else if (local_tmp_vector_vertex_node[nlocal_nodes-1][2] ==
39058 local_tmp_vector_vertex_node[0][2])
39060 if (local_tmp_vector_vertex_node[nlocal_nodes-1][1] <
39061 local_tmp_vector_vertex_node[0][1])
39063 std::reverse(local_tmp_vector_vertex_node.begin(),
39064 local_tmp_vector_vertex_node.end());
39065 std::reverse(tmp_sorted_target_areas.begin(),
39066 tmp_sorted_target_areas.end());
39077 double unrefinement_tolerance=
39081 bool unrefinement_applied =
39082 unrefine_boundary_constrained_by_target_area(
39083 bound, chunk, local_tmp_vector_vertex_node,
39084 unrefinement_tolerance, tmp_sorted_target_areas);
39087 double refinement_tolerance=
39091 bool refinement_applied =
39092 refine_boundary_constrained_by_target_area(
39093 mesh_geom_obj_pt, local_tmp_vector_vertex_node,
39094 refinement_tolerance, tmp_sorted_target_areas);
39098 local_vertex_nodes.clear();
39103 const unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
39104 for (
unsigned i = 0;
i < nnew_nodes;
i++)
39106 vertex_coord[0] = local_tmp_vector_vertex_node[
i][0];
39107 vertex_coord[1] = local_tmp_vector_vertex_node[
i][1];
39108 vertex_coord[2] = local_tmp_vector_vertex_node[
i][2];
39109 vertex_nodes.insert(vertex_coord);
39110 local_vertex_nodes.insert(vertex_coord);
39115 update_was_performed = (unrefinement_applied || refinement_applied);
39117 #ifdef OOMPH_HAS_MPI 39118 if (this->is_mesh_distributed())
39123 sub_vertex_nodes.push_back(local_vertex_nodes);
39129 if (both_root_face_elements_are_nonhalo)
39130 {internal_to_shared_boundary.push_back(
false);}
39132 {internal_to_shared_boundary.push_back(
true);}
39142 const unsigned npoly_vertex = vertex_nodes.size();
39143 tmp_vector_vertex_node.resize(npoly_vertex);
39144 unsigned count = 0;
39145 for (std::set<
Vector<double> >::iterator it = vertex_nodes.begin();
39146 it!=vertex_nodes.end(); ++it)
39148 tmp_vector_vertex_node[count].resize(3);
39149 tmp_vector_vertex_node[count][0] = (*it)[0];
39150 tmp_vector_vertex_node[count][1] = (*it)[1];
39151 tmp_vector_vertex_node[count][2] = (*it)[2];
39155 #ifdef OOMPH_HAS_MPI 39160 const unsigned nsub_boundaries_set = sub_vertex_nodes.size();
39161 const unsigned ninternal_to_shared_boundaries =
39162 internal_to_shared_boundary.size();
39163 if (nsub_boundaries_set != ninternal_to_shared_boundaries)
39165 std::ostringstream error_message;
39167 <<
"The number of found sub-boundaries and the number of marked " 39168 <<
"internal\nboundaries are different\n" 39169 <<
"Number of found sub-boundaries: ("<<nsub_boundaries_set<<
")\n" 39170 <<
"Number of marked internal boundaries: (" 39171 << ninternal_to_shared_boundaries <<
")\n\n";
39173 OOMPH_CURRENT_FUNCTION,
39174 OOMPH_EXCEPTION_LOCATION);
39180 if (nsub_boundaries_set != nsub_boundaries)
39182 std::ostringstream error_message;
39184 <<
"The number of found sub-boundaries and the number of counted\n" 39185 <<
"sub-boundaries are different:\n" 39186 <<
"Number of found sub-boundaries: ("<<nsub_boundaries_set<<
")\n" 39187 <<
"Number of counted sub-boundaries: ("<<nsub_boundaries<<
")\n\n";
39189 OOMPH_CURRENT_FUNCTION,
39190 OOMPH_EXCEPTION_LOCATION);
39195 if (this->is_mesh_distributed() && nsub_boundaries > 1)
39198 this->Boundary_was_splitted[bound] =
true;
39201 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
39203 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
39206 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
39207 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
39208 unsigned subcount = 0;
39209 std::set<Vector<double> >::iterator subit;
39210 for(subit = sub_vertex_nodes[isub].begin();
39211 subit != sub_vertex_nodes[isub].end(); ++subit)
39213 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
39214 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
39215 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
39216 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
39222 #endif // OOMPH_HAS_MPI 39226 unsigned n_vertex=tmp_vector_vertex_node.size();
39229 vector_vertex_node.resize(n_vertex);
39230 for(
unsigned i=0;
i<n_vertex;
i++)
39232 vector_vertex_node[
i].resize(2);
39233 vector_vertex_node[
i][0]=tmp_vector_vertex_node[
i][1];
39234 vector_vertex_node[
i][1]=tmp_vector_vertex_node[
i][2];
39237 #ifdef OOMPH_HAS_MPI 39240 if (this->is_mesh_distributed() && nsub_boundaries > 1)
39245 sub_vector_vertex_node.resize(nsub_boundaries);
39246 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
39248 const unsigned subn_vertex =
39249 sub_tmp_vector_vertex_node[isub].size();
39251 sub_vector_vertex_node[isub].resize(subn_vertex);
39252 for(
unsigned i=0;
i<subn_vertex;
i++)
39254 sub_vector_vertex_node[isub][
i].resize(2);
39255 sub_vector_vertex_node[isub][
i][0]=
39256 sub_tmp_vector_vertex_node[isub][
i][1];
39257 sub_vector_vertex_node[isub][
i][1]=
39258 sub_tmp_vector_vertex_node[isub][
i][2];
39268 #endif // OOMPH_HAS_MPI 39273 #ifdef OOMPH_HAS_MPI 39277 if (!this->is_mesh_distributed())
39284 unsigned n_prev_vertex =
39286 final_vertex_of_previous_segment =
39288 vertex_coordinate(n_prev_vertex-1);
39290 unsigned prev_seg_boundary_id =
39295 double error = 0.0;
39296 for(
unsigned i=0;
i<2;
i++)
39298 const double dist =
39299 final_vertex_of_previous_segment[
i] -
39300 (*vector_vertex_node.begin())[
i];
39301 error += dist*dist;
39303 error = sqrt(error);
39311 double rev_error = 0.0;
39312 for(
unsigned i=0;
i<2;
i++)
39314 const double dist =
39315 final_vertex_of_previous_segment[
i] -
39316 (*--vector_vertex_node.end())[
i];
39317 rev_error += dist*dist;
39319 rev_error = sqrt(rev_error);
39333 initial_vertex_of_previous_segment =
39336 unsigned prev_seg_boundary_id =
39341 double error = 0.0;
39342 for(
unsigned i=0;
i<2;
i++)
39344 const double dist =
39345 initial_vertex_of_previous_segment[
i] -
39346 (*vector_vertex_node.begin())[
i];
39347 error += dist*dist;
39349 error = sqrt(error);
39357 double rev_error = 0.0;
39358 for(
unsigned i=0;
i<2;
i++)
39360 const double dist =
39361 initial_vertex_of_previous_segment[
i] -
39362 (*--vector_vertex_node.end())[
i];
39363 rev_error += dist*dist;
39365 rev_error = sqrt(rev_error);
39371 std::ostringstream error_stream;
39373 <<
"The distance between the first node of the current\n" 39374 <<
"line segment (boundary "<<bound<<
") and either end of " 39375 <<
"the previous line segment\n" 39376 <<
"(boundary "<<prev_seg_boundary_id<<
") is bigger than" 39377 <<
" the desired tolerance " <<
39379 <<
"This suggests that the polylines defining the polygonal\n" 39380 <<
"representation are not properly ordered.\n" 39381 <<
"Fail on last vertex of polyline: (" 39382 <<prev_seg_boundary_id<<
") and\nfirst vertex of polyline (" 39383 <<bound<<
").\nThis should have failed when first trying to " 39384 <<
"construct the\npolygon.\n";
39386 OOMPH_CURRENT_FUNCTION,
39387 OOMPH_EXCEPTION_LOCATION);
39393 std::reverse(vector_vertex_node.begin(),
39394 vector_vertex_node.end());
39407 std::ostringstream error_stream;
39409 <<
"The distance between the first node of the current\n" 39410 <<
"line segment (boundary " << bound <<
") and either end of " 39411 <<
"the previous line segment\n" 39412 <<
"(boundary "<<prev_seg_boundary_id<<
") is bigger than the " 39413 <<
"desired tolerance " <<
39415 <<
"This suggests that the polylines defining the polygonal\n" 39416 <<
"representation are not properly ordered.\n" 39417 <<
"Fail on last vertex of polyline: ("<<prev_seg_boundary_id
39418 <<
") and\nfirst vertex of polyline (" <<bound <<
").\n" 39419 <<
"This should have failed when first trying to construct\n" 39420 <<
"the polygon.\n";
39422 OOMPH_CURRENT_FUNCTION,
39423 OOMPH_EXCEPTION_LOCATION);
39429 std::reverse(vector_vertex_node.begin(),vector_vertex_node.end());
39447 n_vertex = vector_vertex_node.size();
39459 double unrefinement_tolerance=
39463 double refinement_tolerance=
39474 #ifdef OOMPH_HAS_MPI 39477 if (this->is_mesh_distributed())
39483 this->copy_connection_information(open_curve_pt->
polyline_pt(cs),
39484 tmp_curve_section_pt);
39492 this->copy_connection_information(open_curve_pt->
polyline_pt(cs),
39493 tmp_curve_section_pt);
39499 bool delete_it_on_destructor =
false;
39501 std::set<TriangleMeshCurveSection*>::iterator it =
39504 if (it!=this->Free_curve_section_pt.end())
39506 this->Free_curve_section_pt.erase(it);
39508 delete_it_on_destructor =
true;
39516 this->Boundary_curve_section_pt[bound] =
39519 if (delete_it_on_destructor)
39524 #ifdef OOMPH_HAS_MPI 39527 if (this->is_mesh_distributed() && nsub_boundaries == 1)
39530 this->Boundary_marked_as_shared_boundary[bound].clear();
39533 this->Boundary_marked_as_shared_boundary[bound].push_back(
39534 internal_to_shared_boundary[0]);
39538 else if (this->is_mesh_distributed() && nsub_boundaries > 1)
39544 this->Boundary_subpolylines[bound].clear();
39546 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
39549 this->Boundary_marked_as_shared_boundary[bound].clear();
39552 this->Boundary_marked_as_shared_boundary[bound].resize(nsub_boundaries);
39553 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
39562 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
39566 this->Boundary_marked_as_shared_boundary[bound][isub] =
39567 internal_to_shared_boundary[isub];
39577 sub_tmp_polyline_pt;
39578 this->copy_connection_information_to_sub_polylines(
39579 tmp_curve_section_pt, tmp_sub_curve_section_pt);
39585 #endif // OOMPH_HAS_MPI 39589 delete mesh_geom_obj_pt;
39594 for(
unsigned p = 0; p < ncurve_section; p++)
39596 face_mesh_pt[p]->flush_node_storage();
39597 delete face_mesh_pt[p];
39600 return update_was_performed;
39604 #ifdef OOMPH_HAS_MPI 39609 template <
class ELEMENT>
39612 &vector_polyline_pt,
39617 unsigned update_was_performed =
false;
39620 const unsigned n_polylines = vector_polyline_pt.size();
39621 for (
unsigned pp = 0; pp < n_polylines; pp++)
39624 const unsigned shd_bnd_id = vector_polyline_pt[pp]->boundary_id();
39627 const unsigned chunk = vector_polyline_pt[pp]->boundary_chunk();
39635 std::map<FiniteElement*, FiniteElement*> face_ele_pt_to_bulk_element_pt;
39644 const unsigned nshared_bound_ele =
39645 this->nshared_boundary_element(shd_bnd_id);
39649 for (
unsigned e = 0;
e < nshared_bound_ele;
e++)
39653 this->shared_boundary_element_pt(shd_bnd_id,
e);
39656 int face_index = this->face_index_at_shared_boundary(shd_bnd_id,
e);
39665 face_ele_pt_to_bulk_element_pt[face_ele_pt] = bulk_ele_pt;
39671 nonhalo_shared_face_ele_pt.push_back(face_ele_pt);
39676 halo_shared_face_ele_pt.push_back(face_ele_pt);
39686 std::map<FiniteElement*, bool> shared_face_done;
39689 const unsigned nnonhalo_face_shared_ele =
39690 nonhalo_shared_face_ele_pt.size();
39693 const unsigned nhalo_face_shared_ele =
39694 halo_shared_face_ele_pt.size();
39699 if (nshared_bound_ele / 2 != nnonhalo_face_shared_ele)
39701 std::ostringstream error_message;
39703 <<
"The number of shared boundary elements (" << nshared_bound_ele
39704 <<
") is not the double\nof the number of unsorted NONHALO shared " 39705 <<
"face boundary elements (" << nnonhalo_face_shared_ele <<
")\n" 39706 <<
"for the current boundary ("<< shd_bnd_id <<
")\n\n";
39708 OOMPH_CURRENT_FUNCTION,
39709 OOMPH_EXCEPTION_LOCATION);
39714 if (nshared_bound_ele / 2 != nhalo_face_shared_ele)
39716 std::ostringstream error_message;
39718 <<
"The number of shared boundary elements (" << nshared_bound_ele
39719 <<
") is not the double\nof the number of unsorted HALO shared " 39720 <<
"face boundary elements (" << nhalo_face_shared_ele <<
")\n" 39721 <<
"for the current boundary ("<< shd_bnd_id <<
")\n\n";
39723 OOMPH_CURRENT_FUNCTION,
39724 OOMPH_EXCEPTION_LOCATION);
39731 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
39734 FiniteElement* nonhalo_face_ele_pt = nonhalo_shared_face_ele_pt[inh];
39737 const unsigned nnodes_nh = nonhalo_face_ele_pt->
nnode();
39739 Node* nh_first_node_pt = nonhalo_face_ele_pt->
node_pt(0);
39740 Node* nh_last_node_pt = nonhalo_face_ele_pt->
node_pt(nnodes_nh-1);
39744 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
39747 FiniteElement* halo_face_ele_pt = halo_shared_face_ele_pt[ih];
39750 if (!shared_face_done[halo_face_ele_pt])
39753 const unsigned nnodes_h = halo_face_ele_pt->nnode();
39755 Node* h_first_node_pt = halo_face_ele_pt->node_pt(0);
39756 Node* h_last_node_pt = halo_face_ele_pt->node_pt(nnodes_h-1);
39760 if (nh_first_node_pt == h_first_node_pt &&
39761 nh_last_node_pt == h_last_node_pt)
39768 face_ele_pt_to_bulk_element_pt[nonhalo_face_ele_pt];
39770 face_ele_pt_to_bulk_element_pt[halo_face_ele_pt];
39773 tmp_bulk_element_pt.push_back(nonhalo_bulk_ele_pt);
39774 tmp_bulk_element_pt.push_back(halo_bulk_ele_pt);
39777 unsorted_shared_bulk_ele_pt.push_back(tmp_bulk_element_pt);
39780 shared_face_done[nonhalo_face_ele_pt] =
true;
39781 shared_face_done[halo_face_ele_pt] =
true;
39787 else if (nh_first_node_pt == h_last_node_pt &&
39788 nh_last_node_pt == h_first_node_pt)
39795 face_ele_pt_to_bulk_element_pt[nonhalo_face_ele_pt];
39797 face_ele_pt_to_bulk_element_pt[halo_face_ele_pt];
39800 tmp_bulk_element_pt.push_back(nonhalo_bulk_ele_pt);
39801 tmp_bulk_element_pt.push_back(halo_bulk_ele_pt);
39804 unsorted_shared_bulk_ele_pt.push_back(tmp_bulk_element_pt);
39807 shared_face_done[nonhalo_face_ele_pt] =
true;
39808 shared_face_done[halo_face_ele_pt] =
true;
39830 const unsigned nunsorted_shared_bulk_ele =
39831 unsorted_shared_bulk_ele_pt.size();
39835 if (nshared_bound_ele / 2 != nunsorted_shared_bulk_ele)
39837 std::ostringstream error_message;
39839 <<
"The number of shared boundary elements (" << nshared_bound_ele
39840 <<
") is not the double\nof the number of unsorted shared bulk " 39841 <<
"boundary elements (" << nunsorted_shared_bulk_ele <<
")\n" 39842 <<
"for the current boundary ("<< shd_bnd_id <<
")\n\n";
39844 OOMPH_CURRENT_FUNCTION,
39845 OOMPH_EXCEPTION_LOCATION);
39850 if ((nnonhalo_face_shared_ele + nhalo_face_shared_ele) !=
39851 shared_face_done.size())
39853 std::ostringstream error_message;
39855 <<
"The number of DONE shared boundary face elements (" 39856 << shared_face_done.size() <<
") is not the same\n as the sum of" 39857 <<
"the nonhalo face shared boundary elements (" 39858 << nnonhalo_face_shared_ele <<
")\nand the halo face shared " 39859 <<
"boundary elements ("<< nhalo_face_shared_ele <<
") for the\n/" 39860 <<
"current boundary (" << shd_bnd_id <<
")\n\n";
39862 OOMPH_CURRENT_FUNCTION,
39863 OOMPH_EXCEPTION_LOCATION);
39868 shared_face_done.clear();
39871 unsigned nsorted_face_ele = 0;
39875 std::list<Node*> sorted_nodes;
39878 std::list<FiniteElement*> sorted_shared_bound_elements_pt;
39881 FiniteElement* root_face_ele_pt = nonhalo_shared_face_ele_pt[0];
39882 nsorted_face_ele++;
39885 shared_face_done[root_face_ele_pt] =
true;
39888 const unsigned nnodes_root = root_face_ele_pt->
nnode();
39889 Node *first_node_pt = root_face_ele_pt->
node_pt(0);
39890 Node *last_node_pt = root_face_ele_pt->
node_pt(nnodes_root-1);
39893 sorted_nodes.push_back(first_node_pt);
39894 sorted_nodes.push_back(last_node_pt);
39897 sorted_shared_bound_elements_pt.push_back(
39898 unsorted_shared_bulk_ele_pt[0][0]);
39899 sorted_shared_bound_elements_pt.push_back(
39900 unsorted_shared_bulk_ele_pt[0][1]);
39903 while (nsorted_face_ele < nnonhalo_face_shared_ele)
39906 bool node_added =
false;
39910 for (
unsigned iface = 1; iface < nnonhalo_face_shared_ele; iface++)
39913 nonhalo_shared_face_ele_pt[iface];
39916 if (!shared_face_done[tmp_shared_face_ele_pt])
39919 const unsigned tmp_nnodes = tmp_shared_face_ele_pt->nnode();
39922 Node* left_node_pt = tmp_shared_face_ele_pt->node_pt(0);
39923 Node* right_node_pt = tmp_shared_face_ele_pt->node_pt(tmp_nnodes-1);
39925 if (left_node_pt == first_node_pt)
39928 sorted_nodes.push_front(right_node_pt);
39929 first_node_pt = right_node_pt;
39933 sorted_shared_bound_elements_pt.push_front(
39934 unsorted_shared_bulk_ele_pt[iface][1]);
39935 sorted_shared_bound_elements_pt.push_front(
39936 unsorted_shared_bulk_ele_pt[iface][0]);
39938 else if (left_node_pt == last_node_pt)
39941 sorted_nodes.push_back(right_node_pt);
39942 last_node_pt = right_node_pt;
39946 sorted_shared_bound_elements_pt.push_back(
39947 unsorted_shared_bulk_ele_pt[iface][0]);
39948 sorted_shared_bound_elements_pt.push_back(
39949 unsorted_shared_bulk_ele_pt[iface][1]);
39951 else if (right_node_pt == first_node_pt)
39954 sorted_nodes.push_front(left_node_pt);
39955 first_node_pt = left_node_pt;
39959 sorted_shared_bound_elements_pt.push_front(
39960 unsorted_shared_bulk_ele_pt[iface][1]);
39961 sorted_shared_bound_elements_pt.push_front(
39962 unsorted_shared_bulk_ele_pt[iface][0]);
39964 else if (right_node_pt == last_node_pt)
39967 sorted_nodes.push_back(left_node_pt);
39968 last_node_pt = left_node_pt;
39972 sorted_shared_bound_elements_pt.push_back(
39973 unsorted_shared_bulk_ele_pt[iface][0]);
39974 sorted_shared_bound_elements_pt.push_back(
39975 unsorted_shared_bulk_ele_pt[iface][1]);
39982 shared_face_done[tmp_shared_face_ele_pt] =
true;
39983 nsorted_face_ele++;
40000 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
40002 delete nonhalo_shared_face_ele_pt[inh];
40003 nonhalo_shared_face_ele_pt[inh] = 0;
40007 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
40009 delete halo_shared_face_ele_pt[ih];
40010 halo_shared_face_ele_pt[ih] = 0;
40018 const unsigned n_nodes = sorted_nodes.size();
40024 unsigned counter = 0;
40025 for (std::list<Node*>::iterator it_nodes = sorted_nodes.begin();
40026 it_nodes != sorted_nodes.end();
40029 polyline_vertices[counter].resize(2);
40030 polyline_vertices[counter][0] = (*it_nodes)->x(0);
40031 polyline_vertices[counter][1] = (*it_nodes)->x(1);
40041 for (std::list<FiniteElement*>::iterator it_ele =
40042 sorted_shared_bound_elements_pt.begin();
40043 it_ele != sorted_shared_bound_elements_pt.end();
40045 {sorted_shared_ele_pt.push_back((*it_ele));}
40048 const unsigned n_shared_target_areas = sorted_shared_ele_pt.size();
40049 Vector<double> sorted_shared_target_areas(n_shared_target_areas);
40052 std::map<std::pair<GeneralisedElement*, unsigned>,
bool> shared_ele_done;
40055 unsigned count_found_shared_element = 0;
40058 const unsigned nele = this->nelement();
40062 for (
unsigned e = 0;
e < nele;
e++)
40067 for (
unsigned s = 0;
s < n_shared_target_areas;
s++)
40072 std::pair<GeneralisedElement*, unsigned> pair_gen_ele_idx =
40073 std::make_pair(current_shared_ele_pt,
s);
40074 if (!shared_ele_done[pair_gen_ele_idx])
40077 if (current_ele_pt == current_shared_ele_pt)
40080 sorted_shared_target_areas[
s] = target_areas[
e];
40082 shared_ele_done[pair_gen_ele_idx] =
true;
40084 count_found_shared_element++;
40090 if (count_found_shared_element == n_shared_target_areas)
40098 if (count_found_shared_element != n_shared_target_areas)
40100 std::ostringstream error_message;
40102 <<
"The number of found target areas (" 40103 << count_found_shared_element <<
") is different from the " 40104 <<
"total number\nof target areas (" 40105 << n_shared_target_areas <<
") in shared boundary (" 40106 << shd_bnd_id <<
")\n\n";
40108 OOMPH_CURRENT_FUNCTION,
40109 OOMPH_EXCEPTION_LOCATION);
40114 const unsigned n_vertices = n_nodes;
40117 const unsigned n_segments = vector_polyline_pt[pp]->nsegment();
40126 if (n_segments != n_vertices-1)
40128 std::ostringstream error_message;
40130 <<
"The number of segments from the current shared polyline " 40131 <<
"(" << n_segments <<
") does not\ncorrespond with the number of " 40132 <<
"sorted vertices (" << n_vertices-1 <<
") of the current shared\n" 40135 OOMPH_CURRENT_FUNCTION,
40136 OOMPH_EXCEPTION_LOCATION);
40141 if (n_segments != n_shared_target_areas/2)
40143 std::ostringstream error_message;
40145 <<
"The number of segments for the current sorting of edges " 40146 <<
"(" << n_segments <<
") is different\nfrom the number of " 40147 <<
"target areas (" << n_shared_target_areas/2 <<
")\n\n";
40149 OOMPH_CURRENT_FUNCTION,
40150 OOMPH_EXCEPTION_LOCATION);
40164 for (
unsigned s = 0;
s < n_segments;
s++)
40167 polyline_target_area[
s] = std::min(sorted_shared_target_areas[
s*2],
40168 sorted_shared_target_areas[(s*2)+1]);
40175 if (polyline_vertices[n_vertices-1][1] < polyline_vertices[0][1])
40177 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
40178 std::reverse(polyline_target_area.begin(), polyline_target_area.end());
40180 else if (polyline_vertices[n_vertices-1][1] == polyline_vertices[0][1])
40182 if (polyline_vertices[n_vertices-1][0] < polyline_vertices[0][0])
40184 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
40185 std::reverse(polyline_target_area.begin(), polyline_target_area.end());
40191 bool unrefinement_applied =
false;
40194 if (n_vertices > 3)
40196 unrefinement_applied =
40197 unrefine_shared_boundary_constrained_by_target_area(
40198 shd_bnd_id, chunk, polyline_vertices, polyline_target_area);
40202 bool refinement_applied =
40203 refine_shared_boundary_constrained_by_target_area(polyline_vertices,
40204 polyline_target_area);
40207 update_was_performed |= (unrefinement_applied || refinement_applied);
40221 this->copy_connection_information(curve_section_pt, new_polyline_pt);
40226 bool delete_it_on_destructor =
false;
40230 std::set<TriangleMeshCurveSection*>::iterator it =
40231 this->Free_curve_section_pt.find(curve_section_pt);
40233 if (it!=this->Free_curve_section_pt.end())
40235 this->Free_curve_section_pt.erase(it);
40236 delete curve_section_pt;
40237 delete_it_on_destructor =
true;
40241 vector_polyline_pt[pp] = new_polyline_pt;
40247 this->Boundary_curve_section_pt[shd_bnd_id] = new_curve_section_pt;
40249 if (delete_it_on_destructor)
40251 this->Free_curve_section_pt.insert(new_curve_section_pt);
40256 return update_was_performed;
40259 #endif // #ifdef OOMPH_HAS_MPI 40266 template<
class ELEMENT>
40271 &vector_bnd_vertices,
40272 double &unrefinement_tolerance,
40276 std::set<Vector<double> > no_delete_vertex;
40279 const bool boundary_receive_connections =
40280 this->boundary_connections(b, c, no_delete_vertex);
40284 bool unrefinement_applied =
false;
40287 if (!Do_boundary_unrefinement_constrained_by_target_areas)
40289 return unrefinement_applied;
40303 unsigned n_vertex = vector_bnd_vertices.size();
40306 const double constant_value = 4.0/sqrt(3.0);
40312 for (
unsigned i = 1;
i < n_vertex-1;
i+=2)
40314 if (area_constraint[
i-1] > 0 && area_constraint[
i] > 0)
40316 const double local_zeta_first = vector_bnd_vertices[
i-1][0];
40317 const double local_zeta_last = vector_bnd_vertices[
i+1][0];
40318 const double local_length_zeta =
40319 std::fabs(local_zeta_last-local_zeta_first);
40321 const double x1 = vector_bnd_vertices[
i-1][1];
40322 const double y1 = vector_bnd_vertices[
i-1][2];
40323 const double x2 = vector_bnd_vertices[
i+1][1];
40324 const double y2 = vector_bnd_vertices[
i+1][2];
40325 const double local_length =
40326 sqrt(((x1-x2)*(x1-x2)) + ((y1-y2)*(y1-y2)));
40328 const double x_m = vector_bnd_vertices[
i][1];
40329 const double y_m = vector_bnd_vertices[
i][2];
40331 const double average_area_constraint =
40332 (area_constraint[
i-1] + area_constraint[
i]) / 2.0;
40336 const double length_side =
40337 sqrt(constant_value*average_area_constraint);
40339 const double length_side_zeta =
40340 (local_length_zeta * length_side) / local_length;
40343 if ((length_side_zeta / local_length_zeta) > 1.0)
40350 double a_x=vector_bnd_vertices[
i-1][1];
40351 double a_y=vector_bnd_vertices[
i-1][2];
40352 double b_x=vector_bnd_vertices[
i][1];
40353 double b_y=vector_bnd_vertices[
i][2];
40354 double c_x=vector_bnd_vertices[
i+1][1];
40355 double c_y=vector_bnd_vertices[
i+1][2];
40362 double e=a*(a_x+b_x)+b*(a_y+b_y);
40363 double f=c*(a_x+c_x)+d*(a_y+c_y);
40365 double g=2.0*(a*(c_y-b_y)-b*(c_x-b_x));
40368 if (std::fabs(g)<1.0e-14)
40374 double p_x=(d*e-b*f)/g;
40375 double p_y=(a*f-c*
e)/g;
40377 double r=sqrt(pow((a_x-p_x),2)+pow((a_y-p_y),2));
40379 double rhalfca_x=0.5*(a_x-c_x);
40380 double rhalfca_y=0.5*(a_y-c_y);
40382 double halfca_squared=pow(rhalfca_x,2)+pow(rhalfca_y,2);
40384 double sticky_out_bit=r-sqrt(std::fabs((r*r) - halfca_squared));
40389 if ((sticky_out_bit/(2.0*sqrt(halfca_squared)))<
40390 unrefinement_tolerance)
40398 if (do_it && boundary_receive_connections)
40402 no_delete_vertex.begin();
40403 it != no_delete_vertex.end(); it++)
40407 const double x = (*it)[0];
40408 const double y = (*it)[1];
40409 double error = (x_m - x)*(x_m - x) + (y_m - y)*(y_m - y);
40410 error = sqrt(error);
40427 vector_bnd_vertices[
i].resize(0);
40441 for(
unsigned i = 0;
i < n_vertex;
i++)
40444 if (vector_bnd_vertices[
i].size()!=0)
40446 compact_vector.push_back(vector_bnd_vertices[
i]);
40452 unsigned nsize_target = area_constraint.size();
40453 if (nsize_target == 1)
40456 compact_area_constraint.push_back(area_constraint[0]);
40460 for(
unsigned i = 1;
i < n_vertex;
i+=2)
40464 if (vector_bnd_vertices[
i].size()!=0)
40466 compact_area_constraint.push_back(area_constraint[
i-1]);
40468 if (
i < nsize_target)
40470 compact_area_constraint.push_back(area_constraint[
i]);
40477 double new_area_constraint =
40478 (area_constraint[
i-1] + area_constraint[
i]) / 2.0;
40479 compact_area_constraint.push_back(new_area_constraint);
40486 if( n_vertex != compact_vector.size() )
40488 unrefinement_applied =
true;
40492 n_vertex = compact_vector.size();
40493 vector_bnd_vertices.resize(n_vertex);
40494 for(
unsigned i = 0;
i < n_vertex;
i++)
40496 vector_bnd_vertices[
i].resize(3);
40497 vector_bnd_vertices[
i][0] = compact_vector[
i][0];
40498 vector_bnd_vertices[
i][1] = compact_vector[
i][1];
40499 vector_bnd_vertices[
i][2] = compact_vector[
i][2];
40503 unsigned ntarget_areas = compact_area_constraint.size();
40504 area_constraint.resize(ntarget_areas);
40505 for(
unsigned i = 0;
i < ntarget_areas;
i++)
40507 area_constraint[
i] = compact_area_constraint[
i];
40512 return unrefinement_applied;
40521 template<
class ELEMENT>
40526 &vector_bnd_vertices,
40527 double &refinement_tolerance,
40532 bool refinement_applied =
false;
40535 if (!Do_boundary_refinement_constrained_by_target_areas)
40537 return refinement_applied;
40541 unsigned n_vertex=vector_bnd_vertices.size();
40544 const double constant_value = 4.0/sqrt(3.0);
40554 for (
unsigned i = 0;
i < n_vertex-1;
i++)
40557 new_vector.push_back(vector_bnd_vertices[
i]);
40559 if (area_constraint[i] > 0)
40561 double local_zeta_first = vector_bnd_vertices[
i][0];
40562 double local_zeta_last = vector_bnd_vertices[i+1][0];
40563 const double local_length_zeta =
40564 std::fabs(local_zeta_last-local_zeta_first);
40569 if (local_zeta_first > local_zeta_last)
40571 const double tmp_zeta = local_zeta_first;
40572 local_zeta_first = local_zeta_last;
40573 local_zeta_last = tmp_zeta;
40576 const double x1 = vector_bnd_vertices[
i][1];
40577 const double y1 = vector_bnd_vertices[
i][2];
40578 const double x2 = vector_bnd_vertices[i+1][1];
40579 const double y2 = vector_bnd_vertices[i+1][2];
40580 const double local_length =
40581 sqrt(((x1-x2)*(x1-x2)) + ((y1-y2)*(y1-y2)));
40584 const double length_side = sqrt(constant_value*area_constraint[i]);
40585 const double length_side_zeta =
40586 (local_length_zeta * length_side) / local_length;
40589 const double n_seg_double = length_side_zeta/local_length_zeta;
40592 unsigned n_seg = 1;
40595 n_seg+=
static_cast<unsigned>(std::floor(1.0/n_seg_double));
40602 double zeta_increment = (local_length_zeta)/((
double)n_seg);
40606 for(
unsigned s=1;
s<n_seg;
s++)
40609 zeta[0]= local_zeta_first + zeta_increment*double(
s);
40611 mesh_geom_obj_pt->
position(zeta, vertex);
40615 new_node[0]=zeta[0];
40616 new_node[1]=vertex[0];
40617 new_node[2]=vertex[1];
40620 new_vector.push_back(new_node);
40631 new_vector.push_back(vector_bnd_vertices[n_vertex-1]);
40636 n_vertex=new_vector.size();
40637 if( n_vertex != vector_bnd_vertices.size() )
40639 refinement_applied =
true;
40643 vector_bnd_vertices.resize(n_vertex);
40644 for(
unsigned i=0;
i<n_vertex;
i++)
40646 vector_bnd_vertices[
i].resize(3);
40647 vector_bnd_vertices[
i][0]=new_vector[
i][0];
40648 vector_bnd_vertices[
i][1]=new_vector[
i][1];
40649 vector_bnd_vertices[
i][2]=new_vector[
i][2];
40654 return refinement_applied;
40665 template <
class ELEMENT>
40674 std::set<Vector<double> > no_delete_vertex;
40677 const bool boundary_receive_connections =
40678 this->boundary_connections(b, c, no_delete_vertex);
40682 bool unrefinement_applied =
false;
40685 if (!Do_shared_boundary_unrefinement_constrained_by_target_areas)
40687 return unrefinement_applied;
40703 unsigned n_vertex = vector_bnd_vertices.size();
40706 const double constant_value = 4.0/sqrt(3.0);
40712 for (
unsigned i = 1;
i < n_vertex-1;
i+=2)
40716 if (area_constraint[
i-1] > 0 && area_constraint[
i] > 0)
40719 const double x1 = vector_bnd_vertices[
i-1][0];
40720 const double y1 = vector_bnd_vertices[
i-1][1];
40722 const double x2 = vector_bnd_vertices[
i+1][0];
40723 const double y2 = vector_bnd_vertices[
i+1][1];
40726 const double local_length =
40727 sqrt(((x1-x2)*(x1-x2)) + ((y1-y2)*(y1-y2)));
40730 const double x_m = vector_bnd_vertices[
i][0];
40731 const double y_m = vector_bnd_vertices[
i][1];
40734 const double average_area_constraint =
40735 (area_constraint[
i-1] + area_constraint[
i]) / 2.0;
40739 const double length_side =
40740 sqrt(constant_value*average_area_constraint);
40743 if ((length_side / local_length) > 1.0)
40749 if (do_it && boundary_receive_connections)
40753 no_delete_vertex.begin();
40754 it != no_delete_vertex.end(); it++)
40758 const double x = (*it)[0];
40759 const double y = (*it)[1];
40760 double error = (x_m - x)*(x_m - x) + (y_m - y)*(y_m - y);
40761 error = sqrt(error);
40778 vector_bnd_vertices[
i].resize(0);
40794 for(
unsigned i = 0;
i < n_vertex;
i++)
40797 if (vector_bnd_vertices[
i].size()!=0)
40799 compact_vector.push_back(vector_bnd_vertices[
i]);
40805 unsigned n_area_constraint = area_constraint.size();
40806 if (n_area_constraint == 1)
40809 compact_area_constraint.push_back(area_constraint[0]);
40813 for(
unsigned i = 1;
i < n_vertex;
i+=2)
40817 if (vector_bnd_vertices[
i].size()!=0)
40819 compact_area_constraint.push_back(area_constraint[
i-1]);
40821 if (
i < n_area_constraint)
40823 compact_area_constraint.push_back(area_constraint[
i]);
40830 const double new_area_constraint =
40831 (area_constraint[
i-1] + area_constraint[
i]) / 2.0;
40832 compact_area_constraint.push_back(new_area_constraint);
40839 if( n_vertex != compact_vector.size() )
40841 unrefinement_applied =
true;
40845 n_vertex = compact_vector.size();
40846 vector_bnd_vertices.resize(n_vertex);
40847 for(
unsigned i = 0;
i < n_vertex;
i++)
40849 vector_bnd_vertices[
i].resize(2);
40850 vector_bnd_vertices[
i][0] = compact_vector[
i][0];
40851 vector_bnd_vertices[
i][1] = compact_vector[
i][1];
40855 unsigned ntarget_areas = compact_area_constraint.size();
40856 area_constraint.resize(ntarget_areas);
40857 for(
unsigned i = 0;
i < ntarget_areas;
i++)
40859 area_constraint[
i] = compact_area_constraint[
i];
40864 return unrefinement_applied;
40875 template <
class ELEMENT>
40883 bool refinement_applied =
false;
40886 if (!Do_shared_boundary_refinement_constrained_by_target_areas)
40888 return refinement_applied;
40892 unsigned nsegments = vector_bnd_vertices.size() - 1;
40899 const double constant_value = 4.0/sqrt(3.0);
40901 for (
unsigned s = 0;
s < nsegments;
s++)
40907 const double x1 = left_vertex[0];
40908 const double y1 = left_vertex[1];
40909 const double x2 = right_vertex[0];
40910 const double y2 = right_vertex[1];
40913 const double segment_length =
40914 sqrt(((x1-x2)*(x1-x2))+((y1-y2)*(y1-y2)));
40917 const double new_segment_length =
40918 sqrt(constant_value*area_constraint[
s]);
40921 const double n_seg_double = new_segment_length / segment_length;
40926 nseg+=
static_cast<unsigned>(std::floor(1.0/n_seg_double));
40930 tmp_bnd_vertices.push_back(left_vertex);
40937 double incrementx = (right_vertex[0] - left_vertex[0])/(
double)(nseg);
40938 double incrementy = (right_vertex[1] - left_vertex[1])/(
double)(nseg);
40939 for (
unsigned i = 1;
i < nseg;
i++)
40942 tmp_vertex[0] = left_vertex[0] + incrementx*
i;
40943 tmp_vertex[1] = left_vertex[1] + incrementy*
i;
40944 tmp_bnd_vertices.push_back(tmp_vertex);
40952 tmp_bnd_vertices.push_back(vector_bnd_vertices[nsegments]);
40957 nsegments = tmp_bnd_vertices.size() - 1;
40958 if( nsegments != vector_bnd_vertices.size() - 1 )
40960 refinement_applied =
true;
40963 vector_bnd_vertices.resize(nsegments + 1);
40964 for(
unsigned i = 0;
i < nsegments + 1;
i++)
40966 vector_bnd_vertices[
i].resize(2);
40967 vector_bnd_vertices[
i][0] = tmp_bnd_vertices[
i][0];
40968 vector_bnd_vertices[
i][1] = tmp_bnd_vertices[
i][1];
40972 return refinement_applied;
40979 template <
class ELEMENT>
40991 get_face_mesh_representation(polygon_pt,face_mesh_pt);
40999 const unsigned n_polyline = polygon_pt->
npolyline();
41002 for(
unsigned p=0;p<n_polyline;p++)
41015 std::set<Vector<double> > vertex_nodes;
41026 #ifdef OOMPH_HAS_MPI 41053 const unsigned nface_element = face_mesh_pt[p]->nelement();
41059 std::map<FiniteElement*,unsigned> face_element_index_on_boundary;
41061 for(
unsigned ef=0;ef<nface_element;++ef)
41063 FiniteElement* ele_face_pt = face_mesh_pt[p]->finite_element_pt(ef);
41065 #ifdef OOMPH_HAS_MPI 41066 if (this->is_mesh_distributed())
41069 if (ele_face_pt->
is_halo()) {
continue;}
41073 non_halo_face_element_pt.push_back(ele_face_pt);
41074 face_element_index_on_boundary[ele_face_pt] = ef;
41078 const unsigned nnon_halo_face_element = non_halo_face_element_pt.size();
41081 std::map<FiniteElement*,bool> face_element_done;
41084 unsigned nsorted_face_elements = 0;
41086 #ifdef OOMPH_HAS_MPI 41088 unsigned nsub_boundaries = 0;
41089 #endif // #ifdef OOMPH_HAS_MPI 41093 while(nsorted_face_elements < nnon_halo_face_element)
41098 bool found_initial_face_element =
false;
41101 unsigned iface = 0;
41102 for (iface = 0; iface < nnon_halo_face_element; iface++)
41104 ele_face_pt = non_halo_face_element_pt[iface];
41106 if (!face_element_done[ele_face_pt])
41109 found_initial_face_element =
true;
41111 nsorted_face_elements++;
41118 if (!found_initial_face_element)
41120 std::ostringstream error_message;
41122 <<
"Could not find an initial face element for the current segment\n";
41125 "RefineableTriangleMesh::update_polygon_after_restart()",
41126 OOMPH_EXCEPTION_LOCATION);
41133 std::set<Vector<double> > local_vertex_nodes;
41145 unsigned nnode = ele_face_pt->
nnode();
41149 vertex_coord[0] = bound_left[0];
41152 for(
unsigned i=0;
i<2;
i++)
41154 vertex_coord[
i+1] = ele_face_pt->
node_pt(0)->
x(
i);
41156 local_vertex_nodes.insert(vertex_coord);
41160 ele_face_pt->
node_pt(nnode-1)->
41161 get_coordinates_on_boundary(bound,bound_right);
41162 vertex_coord[0] = bound_right[0];
41165 for(
unsigned i=0;
i<2;
i++)
41167 vertex_coord[
i+1] = ele_face_pt->
node_pt(nnode-1)->
x(
i);
41169 local_vertex_nodes.insert(vertex_coord);
41173 Node *last_node_pt = ele_face_pt->
node_pt(nnode-1);
41176 face_element_done[ele_face_pt] =
true;
41184 bool face_element_added =
false;
41193 for (
unsigned iiface=iface;iiface<nnon_halo_face_element;iiface++)
41195 face_element_added =
false;
41196 ele_face_pt = non_halo_face_element_pt[iiface];
41197 if (!face_element_done[ele_face_pt])
41200 nnode = ele_face_pt->nnode();
41201 Node* left_node_pt = ele_face_pt->node_pt(0);
41202 Node* right_node_pt = ele_face_pt->node_pt(nnode-1);
41204 if (left_node_pt == first_node_pt)
41206 first_node_pt = right_node_pt;
41207 face_element_added =
true;
41209 else if (left_node_pt == last_node_pt)
41211 last_node_pt = right_node_pt;
41212 face_element_added =
true;
41214 else if (right_node_pt == first_node_pt)
41216 first_node_pt = left_node_pt;
41217 face_element_added =
true;
41219 else if (right_node_pt == last_node_pt)
41221 last_node_pt = left_node_pt;
41222 face_element_added =
true;
41225 if (face_element_added)
41230 vertex_coord[0] = bound_left[0];
41233 for(
unsigned i=0;
i<2;
i++)
41235 vertex_coord[
i+1] = left_node_pt->
x(
i);
41237 local_vertex_nodes.insert(vertex_coord);
41242 vertex_coord[0] = bound_right[0];
41245 for(
unsigned i=0;
i<2;
i++)
41247 vertex_coord[
i+1] = right_node_pt->
x(
i);
41249 local_vertex_nodes.insert(vertex_coord);
41253 face_element_done[ele_face_pt] =
true;
41254 nsorted_face_elements++;
41261 }
while(face_element_added &&
41262 (nsorted_face_elements < nnon_halo_face_element));
41270 const unsigned nlocal_nodes = local_vertex_nodes.size();
41272 local_tmp_vector_vertex_node.resize(nlocal_nodes);
41275 unsigned counter = 0;
41276 std::set<Vector<double> >::iterator it_vertex;
41277 for (it_vertex = local_vertex_nodes.begin();
41278 it_vertex != local_vertex_nodes.end();
41281 local_tmp_vector_vertex_node[counter].resize(3);
41282 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
41283 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
41284 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
41295 local_vertex_nodes.clear();
41300 unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
41301 for (
unsigned i = 0;
i < nnew_nodes;
i++)
41303 vertex_coord[0] = local_tmp_vector_vertex_node[
i][0];
41304 vertex_coord[1] = local_tmp_vector_vertex_node[
i][1];
41305 vertex_coord[2] = local_tmp_vector_vertex_node[
i][2];
41306 vertex_nodes.insert(vertex_coord);
41307 local_vertex_nodes.insert(vertex_coord);
41310 #ifdef OOMPH_HAS_MPI 41311 if (this->is_mesh_distributed())
41315 sub_vertex_nodes.push_back(local_vertex_nodes);
41324 unsigned npoly_vertex = vertex_nodes.size();
41325 tmp_vector_vertex_node.resize(npoly_vertex);
41326 unsigned count = 0;
41327 std::set<Vector<double> >::iterator it;
41328 for(it = vertex_nodes.begin(); it!=vertex_nodes.end(); ++it)
41330 tmp_vector_vertex_node[count].resize(3);
41331 tmp_vector_vertex_node[count][0] = (*it)[0];
41332 tmp_vector_vertex_node[count][1] = (*it)[1];
41333 tmp_vector_vertex_node[count][2] = (*it)[2];
41337 #ifdef OOMPH_HAS_MPI 41340 unsigned nsub_boundaries_set = sub_vertex_nodes.size();
41341 if (nsub_boundaries_set != nsub_boundaries)
41343 std::ostringstream error_message;
41345 <<
"The number of found sub-boundaries and the number of counted\n" 41346 <<
"sub-boundaries are different:\n" 41347 <<
"Number of found sub-boundaries: ("<<nsub_boundaries_set<<
")\n" 41348 <<
"Number of counted sub-boundaries: ("<<nsub_boundaries<<
")\n";
41350 "RefineableTriangleMesh::update_polygon_after_restart()",
41351 OOMPH_EXCEPTION_LOCATION);
41356 if (this->is_mesh_distributed() && nsub_boundaries > 1)
41359 this->Boundary_was_splitted[bound] =
true;
41361 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
41362 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
41365 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
41366 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
41367 unsigned subcount = 0;
41368 std::set<Vector<double> >::iterator subit;
41369 for(subit = sub_vertex_nodes[isub].begin();
41370 subit != sub_vertex_nodes[isub].end(); ++subit)
41372 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
41373 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
41374 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
41375 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
41381 #endif // OOMPH_HAS_MPI 41386 unsigned n_vertex=tmp_vector_vertex_node.size();
41389 vector_vertex_node.resize(n_vertex);
41390 for(
unsigned i=0;
i<n_vertex;
i++)
41392 vector_vertex_node[
i].resize(2);
41393 vector_vertex_node[
i][0]=tmp_vector_vertex_node[
i][1];
41394 vector_vertex_node[
i][1]=tmp_vector_vertex_node[
i][2];
41397 #ifdef OOMPH_HAS_MPI 41400 if (this->is_mesh_distributed() && nsub_boundaries > 1)
41405 sub_vector_vertex_node.resize(nsub_boundaries);
41406 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
41408 const unsigned subn_vertex =
41409 sub_tmp_vector_vertex_node[isub].size();
41411 sub_vector_vertex_node[isub].resize(subn_vertex);
41412 for(
unsigned i=0;
i<subn_vertex;
i++)
41414 sub_vector_vertex_node[isub][
i].resize(2);
41415 sub_vector_vertex_node[isub][
i][0]=
41416 sub_tmp_vector_vertex_node[isub][
i][1];
41417 sub_vector_vertex_node[isub][
i][1]=
41418 sub_tmp_vector_vertex_node[isub][
i][2];
41428 #endif // OOMPH_HAS_MPI 41433 #ifdef OOMPH_HAS_MPI 41437 if (!this->is_mesh_distributed())
41444 unsigned n_prev_vertex =
41446 final_vertex_of_previous_segment =
41448 vertex_coordinate(n_prev_vertex-1);
41450 unsigned prev_seg_boundary_id =
41455 double error = 0.0;
41456 for(
unsigned i=0;
i<2;
i++)
41458 const double dist =
41459 final_vertex_of_previous_segment[
i] -
41460 (*vector_vertex_node.begin())[
i];
41461 error += dist*dist;
41463 error = sqrt(error);
41471 double rev_error = 0.0;
41472 for(
unsigned i=0;
i<2;
i++)
41474 const double dist =
41475 final_vertex_of_previous_segment[
i] -
41476 (*--vector_vertex_node.end())[
i];
41477 rev_error += dist*dist;
41479 rev_error = sqrt(rev_error);
41493 initial_vertex_of_previous_segment =
41495 vertex_coordinate(0);
41497 unsigned prev_seg_boundary_id =
41502 double error = 0.0;
41503 for(
unsigned i=0;
i<2;
i++)
41505 const double dist =
41506 initial_vertex_of_previous_segment[
i] -
41507 (*vector_vertex_node.begin())[
i];
41508 error += dist*dist;
41510 error = sqrt(error);
41518 double rev_error = 0.0;
41519 for(
unsigned i=0;
i<2;
i++)
41521 const double dist =
41522 initial_vertex_of_previous_segment[
i] -
41523 (*--vector_vertex_node.end())[
i];
41524 rev_error += dist*dist;
41526 rev_error = sqrt(rev_error);
41532 std::ostringstream error_stream;
41534 <<
"The distance between the first node of the current\n" 41535 <<
"line segment (boundary " << bound <<
") and either end of " 41536 <<
"the previous line segment\n" 41537 <<
"(boundary " << prev_seg_boundary_id <<
") is bigger than " 41538 <<
"the desired tolerance " <<
41540 <<
"This suggests that the polylines defining the polygonal\n" 41541 <<
"representation are not properly ordered.\n" 41542 <<
"Fail on last vertex of polyline: (" 41543 << prev_seg_boundary_id<<
") and\nfirst vertex of polyline (" 41544 << bound <<
").\nThis should have failed when first trying to" 41545 <<
" construct the\npolygon.\n";
41547 "RefineableTriangleMesh::update_polygon_after_restart()",
41548 OOMPH_EXCEPTION_LOCATION);
41554 std::reverse(vector_vertex_node.begin(),
41555 vector_vertex_node.end());
41568 std::ostringstream error_stream;
41570 <<
"The distance between the first node of the current\n" 41571 <<
"line segment (boundary " << bound <<
") and either end of " 41572 <<
"the previous line segment\n" 41573 <<
"(boundary " << prev_seg_boundary_id <<
") is bigger than the " 41574 <<
"desired tolerance " <<
41576 <<
"This suggests that the polylines defining the polygonal\n" 41577 <<
"representation are not properly ordered.\n" 41578 <<
"Fail on last vertex of polyline: (" << prev_seg_boundary_id
41579 <<
") and\nfirst vertex of polyline (" << bound <<
").\n" 41580 <<
"This should have failed when first trying to construct the\n" 41583 error_stream.str(),
41584 "RefineableTriangleMesh::update_polygon_after_restart()",
41585 OOMPH_EXCEPTION_LOCATION);
41591 std::reverse(vector_vertex_node.begin(),vector_vertex_node.end());
41606 n_vertex = vector_vertex_node.size();
41626 double unrefinement_tolerance=
41630 double refinement_tolerance=
41635 unrefinement_tolerance);
41637 refinement_tolerance);
41647 this->copy_connection_information(polygon_pt->
polyline_pt(p),
41648 tmp_curve_section_pt);
41654 bool delete_it_on_destructor =
false;
41656 std::set<TriangleMeshCurveSection*>::iterator it =
41659 if (it!=this->Free_curve_section_pt.end())
41661 this->Free_curve_section_pt.erase(it);
41663 delete_it_on_destructor =
true;
41673 if (delete_it_on_destructor)
41678 #ifdef OOMPH_HAS_MPI 41681 if (this->is_mesh_distributed() && nsub_boundaries > 1)
41686 this->Boundary_subpolylines[bound].clear();
41688 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
41689 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
41698 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
41710 #endif // OOMPH_HAS_MPI 41716 delete mesh_geom_obj_pt;
41721 for(
unsigned p=0;p<n_polyline;p++)
41723 face_mesh_pt[p]->flush_node_storage();
41724 delete face_mesh_pt[p];
41733 template <
class ELEMENT>
41744 get_face_mesh_representation(open_curve_pt,face_mesh_pt);
41752 const unsigned ncurve_section = open_curve_pt->
ncurve_section();
41754 for(
unsigned cs = 0; cs < ncurve_section; cs++)
41774 const unsigned nface_element = face_mesh_pt[cs]->nelement();
41781 std::map<FiniteElement*,unsigned> face_element_index_on_boundary;
41784 std::map<FiniteElement*,bool> face_element_done;
41786 for(
unsigned ef = 0; ef < nface_element; ++ef)
41788 FiniteElement* ele_face_pt = face_mesh_pt[cs]->finite_element_pt(ef);
41793 #ifdef OOMPH_HAS_MPI 41794 if (this->is_mesh_distributed())
41797 if (ele_face_pt->
is_halo()) {
continue;}
41802 if (!face_element_done[ele_face_pt])
41807 non_halo_doubled_face_element_pt.push_back(ele_face_pt);
41809 face_element_index_on_boundary[ele_face_pt] = ef;
41811 face_element_done[ele_face_pt] =
true;
41813 const unsigned nnodes = ele_face_pt->nnode();
41816 Node* left_node_pt = ele_face_pt->node_pt(0);
41817 Node* right_node_pt = ele_face_pt->node_pt(nnodes-1);
41822 bool found_other_side_face_ele =
false;
41824 for (
unsigned iface = 0; iface < nface_element; iface++)
41828 face_mesh_pt[cs]->finite_element_pt(iface);
41830 if (!face_element_done[cele_face_pt])
41832 Node* cleft_node_pt = cele_face_pt->node_pt(0);
41833 Node* cright_node_pt = cele_face_pt->node_pt(nnodes-1);
41836 if ((left_node_pt == cleft_node_pt &&
41837 right_node_pt == cright_node_pt) ||
41838 (left_node_pt == cright_node_pt &&
41839 right_node_pt == cleft_node_pt))
41842 non_halo_doubled_face_element_pt.push_back(cele_face_pt);
41844 face_element_done[cele_face_pt] =
true;
41846 face_element_index_on_boundary[cele_face_pt] = iface;
41849 found_other_side_face_ele =
true;
41857 if (!found_other_side_face_ele)
41859 std::ostringstream error_message;
41861 <<
"The face element at the other side of the boundary (" 41862 << bound <<
") was not found!!\n" 41863 <<
"These are the nodes of the face element:\n" 41864 <<
"("<<left_node_pt->
x(0)<<
", "<<left_node_pt->
x(1)<<
") " 41865 <<
"and ("<<right_node_pt->
x(0)<<
","<<right_node_pt->
x(1)<<
")\n\n";
41867 "RefineableTriangleMesh::update_open_curve_after_restart()",
41868 OOMPH_EXCEPTION_LOCATION);
41877 face_element_done.clear();
41882 std::set<Vector<double> > vertex_nodes;
41893 #ifdef OOMPH_HAS_MPI 41898 std::vector<bool> internal_to_shared_boundary;
41923 unsigned nsorted_face_elements = 0;
41925 #ifdef OOMPH_HAS_MPI 41927 unsigned nsub_boundaries = 0;
41928 #endif // #ifdef OOMPH_HAS_MPI 41931 const unsigned nnon_halo_doubled_face_ele =
41932 non_halo_doubled_face_element_pt.size();
41936 while(nsorted_face_elements < nnon_halo_doubled_face_ele)
41942 bool found_initial_face_element =
false;
41948 bool both_root_face_elements_are_nonhalo =
false;
41950 unsigned iface = 0;
41951 for (iface = 0; iface < nnon_halo_doubled_face_ele; iface+=2)
41953 ele_face_pt = non_halo_doubled_face_element_pt[iface];
41955 if (!face_element_done[ele_face_pt])
41958 face_element_done[ele_face_pt] =
true;
41960 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iface+1];
41962 face_element_done[repeated_ele_face_pt] =
true;
41964 #ifdef OOMPH_HAS_MPI 41965 if (!repeated_ele_face_pt->
is_halo())
41966 {both_root_face_elements_are_nonhalo =
true;}
41967 #endif // #ifdef OOMPH_HAS_MPI 41971 nsorted_face_elements+=2;
41975 found_initial_face_element =
true;
41982 if (!found_initial_face_element)
41984 std::ostringstream error_message;
41986 <<
"Could not find an initial face element for the current segment\n";
41989 OOMPH_CURRENT_FUNCTION,
41990 OOMPH_EXCEPTION_LOCATION);
41997 std::set<Vector<double> > local_vertex_nodes;
42009 const unsigned nnode = ele_face_pt->
nnode();
42013 vertex_coord[0] = bound_left[0];
42016 for(
unsigned i=0;
i<2;
i++)
42018 vertex_coord[
i+1] = ele_face_pt->
node_pt(0)->
x(
i);
42020 local_vertex_nodes.insert(vertex_coord);
42026 vertex_coord[0] = bound_right[0];
42029 for(
unsigned i=0;
i<2;
i++)
42031 vertex_coord[
i+1] = ele_face_pt->
node_pt(nnode-1)->
x(
i);
42033 local_vertex_nodes.insert(vertex_coord);
42037 Node *last_node_pt = ele_face_pt->
node_pt(nnode-1);
42041 bool face_element_added =
false;
42051 for (
unsigned iiface=iface;
42052 iiface<nnon_halo_doubled_face_ele;iiface+=2)
42054 face_element_added =
false;
42055 ele_face_pt = non_halo_doubled_face_element_pt[iiface];
42062 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iiface+1];
42063 bool both_face_elements_are_nonhalo =
false;
42065 #ifdef OOMPH_HAS_MPI 42066 if (!repeated_ele_face_pt->
is_halo())
42067 {both_face_elements_are_nonhalo =
true;}
42068 #endif // #ifdef OOMPH_HAS_MPI 42070 if (!face_element_done[ele_face_pt] &&
42071 (both_face_elements_are_nonhalo ==
42072 both_root_face_elements_are_nonhalo))
42075 const unsigned nlnode = ele_face_pt->
nnode();
42077 Node* right_node_pt = ele_face_pt->
node_pt(nlnode-1);
42079 if (left_node_pt == first_node_pt)
42081 first_node_pt = right_node_pt;
42082 face_element_added =
true;
42084 else if (left_node_pt == last_node_pt)
42086 last_node_pt = right_node_pt;
42087 face_element_added =
true;
42089 else if (right_node_pt == first_node_pt)
42091 first_node_pt = left_node_pt;
42092 face_element_added =
true;
42094 else if (right_node_pt == last_node_pt)
42096 last_node_pt = left_node_pt;
42097 face_element_added =
true;
42100 if (face_element_added)
42105 vertex_coord[0] = bound_left[0];
42108 for(
unsigned i=0;
i<2;
i++)
42110 vertex_coord[
i+1] = left_node_pt->
x(
i);
42112 local_vertex_nodes.insert(vertex_coord);
42117 vertex_coord[0] = bound_right[0];
42120 for(
unsigned i=0;
i<2;
i++)
42122 vertex_coord[
i+1] = right_node_pt->
x(
i);
42124 local_vertex_nodes.insert(vertex_coord);
42128 face_element_done[ele_face_pt] =
true;
42131 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iiface+1];
42132 face_element_done[repeated_ele_face_pt] =
true;
42134 nsorted_face_elements+=2;
42141 }
while(face_element_added &&
42142 (nsorted_face_elements < nnon_halo_doubled_face_ele));
42150 const unsigned nlocal_nodes = local_vertex_nodes.size();
42152 local_tmp_vector_vertex_node.resize(nlocal_nodes);
42155 unsigned counter = 0;
42156 std::set<Vector<double> >::iterator it_vertex;
42157 for (it_vertex = local_vertex_nodes.begin();
42158 it_vertex != local_vertex_nodes.end();
42161 local_tmp_vector_vertex_node[counter].resize(3);
42162 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
42163 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
42164 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
42171 if (local_tmp_vector_vertex_node[nlocal_nodes-1][2] <
42172 local_tmp_vector_vertex_node[0][2])
42174 std::reverse(local_tmp_vector_vertex_node.begin(),
42175 local_tmp_vector_vertex_node.end());
42177 else if (local_tmp_vector_vertex_node[nlocal_nodes-1][2] ==
42178 local_tmp_vector_vertex_node[0][2])
42180 if (local_tmp_vector_vertex_node[nlocal_nodes-1][1] <
42181 local_tmp_vector_vertex_node[0][1])
42183 std::reverse(local_tmp_vector_vertex_node.begin(),
42184 local_tmp_vector_vertex_node.end());
42195 local_vertex_nodes.clear();
42200 const unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
42201 for (
unsigned i = 0;
i < nnew_nodes;
i++)
42203 vertex_coord[0] = local_tmp_vector_vertex_node[
i][0];
42204 vertex_coord[1] = local_tmp_vector_vertex_node[
i][1];
42205 vertex_coord[2] = local_tmp_vector_vertex_node[
i][2];
42206 vertex_nodes.insert(vertex_coord);
42207 local_vertex_nodes.insert(vertex_coord);
42210 #ifdef OOMPH_HAS_MPI 42211 if (this->is_mesh_distributed())
42216 sub_vertex_nodes.push_back(local_vertex_nodes);
42222 if (both_root_face_elements_are_nonhalo)
42223 {internal_to_shared_boundary.push_back(
false);}
42225 {internal_to_shared_boundary.push_back(
true);}
42235 const unsigned npoly_vertex = vertex_nodes.size();
42236 tmp_vector_vertex_node.resize(npoly_vertex);
42237 unsigned count = 0;
42238 std::set<Vector<double> >::iterator it;
42239 for (it = vertex_nodes.begin(); it!=vertex_nodes.end(); ++it)
42241 tmp_vector_vertex_node[count].resize(3);
42242 tmp_vector_vertex_node[count][0] = (*it)[0];
42243 tmp_vector_vertex_node[count][1] = (*it)[1];
42244 tmp_vector_vertex_node[count][2] = (*it)[2];
42248 #ifdef OOMPH_HAS_MPI 42253 const unsigned nsub_boundaries_set = sub_vertex_nodes.size();
42254 const unsigned ninternal_to_shared_boundaries =
42255 internal_to_shared_boundary.size();
42256 if (nsub_boundaries_set != ninternal_to_shared_boundaries)
42258 std::ostringstream error_message;
42260 <<
"The number of found sub-boundaries and the number of marked " 42261 <<
"internal\nboundaries are different\n" 42262 <<
"Number of found sub-boundaries: ("<<nsub_boundaries_set<<
")\n" 42263 <<
"Number of marked internal boundaries: (" 42264 << ninternal_to_shared_boundaries <<
")\n\n";
42266 "RefineableTriangleMesh::update_open_curve_after_restart()",
42267 OOMPH_EXCEPTION_LOCATION);
42273 if (nsub_boundaries_set != nsub_boundaries)
42275 std::ostringstream error_message;
42277 <<
"The number of found sub-boundaries and the number of counted\n" 42278 <<
"sub-boundaries are different:\n" 42279 <<
"Number of found sub-boundaries: ("<<nsub_boundaries_set<<
")\n" 42280 <<
"Number of counted sub-boundaries: ("<<nsub_boundaries<<
")\n\n";
42282 "RefineableTriangleMesh::update_open_curve_after_restart()",
42283 OOMPH_EXCEPTION_LOCATION);
42288 if (this->is_mesh_distributed() && nsub_boundaries > 1)
42291 this->Boundary_was_splitted[bound] =
true;
42293 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
42294 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
42297 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
42298 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
42299 unsigned subcount = 0;
42300 std::set<Vector<double> >::iterator subit;
42301 for(subit = sub_vertex_nodes[isub].begin();
42302 subit != sub_vertex_nodes[isub].end(); ++subit)
42304 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
42305 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
42306 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
42307 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
42313 #endif // OOMPH_HAS_MPI 42317 unsigned n_vertex=tmp_vector_vertex_node.size();
42320 vector_vertex_node.resize(n_vertex);
42321 for(
unsigned i=0;
i<n_vertex;
i++)
42323 vector_vertex_node[
i].resize(2);
42324 vector_vertex_node[
i][0]=tmp_vector_vertex_node[
i][1];
42325 vector_vertex_node[
i][1]=tmp_vector_vertex_node[
i][2];
42328 #ifdef OOMPH_HAS_MPI 42331 if (this->is_mesh_distributed() && nsub_boundaries > 1)
42336 sub_vector_vertex_node.resize(nsub_boundaries);
42337 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
42339 const unsigned subn_vertex =
42340 sub_tmp_vector_vertex_node[isub].size();
42342 sub_vector_vertex_node[isub].resize(subn_vertex);
42343 for(
unsigned i=0;
i<subn_vertex;
i++)
42345 sub_vector_vertex_node[isub][
i].resize(2);
42346 sub_vector_vertex_node[isub][
i][0]=
42347 sub_tmp_vector_vertex_node[isub][
i][1];
42348 sub_vector_vertex_node[isub][
i][1]=
42349 sub_tmp_vector_vertex_node[isub][
i][2];
42359 #endif // OOMPH_HAS_MPI 42364 #ifdef OOMPH_HAS_MPI 42368 if (!this->is_mesh_distributed())
42375 unsigned n_prev_vertex =
42377 final_vertex_of_previous_segment =
42379 vertex_coordinate(n_prev_vertex-1);
42381 unsigned prev_seg_boundary_id =
42386 double error = 0.0;
42387 for(
unsigned i=0;
i<2;
i++)
42389 const double dist =
42390 final_vertex_of_previous_segment[
i] -
42391 (*vector_vertex_node.begin())[
i];
42392 error += dist*dist;
42394 error = sqrt(error);
42402 double rev_error = 0.0;
42403 for(
unsigned i=0;
i<2;
i++)
42405 const double dist =
42406 final_vertex_of_previous_segment[
i] -
42407 (*--vector_vertex_node.end())[
i];
42408 rev_error += dist*dist;
42410 rev_error = sqrt(rev_error);
42424 initial_vertex_of_previous_segment =
42427 unsigned prev_seg_boundary_id =
42432 double error = 0.0;
42433 for(
unsigned i=0;
i<2;
i++)
42435 const double dist =
42436 initial_vertex_of_previous_segment[
i] -
42437 (*vector_vertex_node.begin())[
i];
42438 error += dist*dist;
42440 error = sqrt(error);
42448 double rev_error = 0.0;
42449 for(
unsigned i=0;
i<2;
i++)
42451 const double dist =
42452 initial_vertex_of_previous_segment[
i] -
42453 (*--vector_vertex_node.end())[
i];
42454 rev_error += dist*dist;
42456 rev_error = sqrt(rev_error);
42462 std::ostringstream error_stream;
42464 <<
"The distance between the first node of the current\n" 42465 <<
"line segment (boundary "<<bound<<
") and either end of " 42466 <<
"the previous line segment\n" 42467 <<
"(boundary "<<prev_seg_boundary_id<<
") is bigger than" 42468 <<
" the desired tolerance " <<
42470 <<
"This suggests that the polylines defining the polygonal\n" 42471 <<
"representation are not properly ordered.\n" 42472 <<
"Fail on last vertex of polyline: (" 42473 <<prev_seg_boundary_id<<
") and\nfirst vertex of polyline (" 42474 <<bound<<
").\nThis should have failed when first trying to " 42475 <<
"construct the\npolygon.\n";
42477 "RefineableTriangleMesh::update_open_curve_after_restart()",
42478 OOMPH_EXCEPTION_LOCATION);
42484 std::reverse(vector_vertex_node.begin(),
42485 vector_vertex_node.end());
42498 std::ostringstream error_stream;
42500 <<
"The distance between the first node of the current\n" 42501 <<
"line segment (boundary " << bound <<
") and either end of " 42502 <<
"the previous line segment\n" 42503 <<
"(boundary " << prev_seg_boundary_id <<
") is bigger than the " 42504 <<
"desired tolerance " <<
42506 <<
"This suggests that the polylines defining the polygonal\n" 42507 <<
"representation are not properly ordered.\n" 42508 <<
"Fail on last vertex of polyline: (" << prev_seg_boundary_id
42509 <<
") and\nfirst vertex of polyline (" << bound <<
").\n" 42510 <<
"This should have failed when first trying to construct the\n" 42513 error_stream.str(),
42514 "RefineableTriangleMesh::update_open_curve_after_restart()",
42515 OOMPH_EXCEPTION_LOCATION);
42521 std::reverse(vector_vertex_node.begin(),vector_vertex_node.end());
42539 n_vertex = vector_vertex_node.size();
42552 double unrefinement_tolerance=
42556 double refinement_tolerance=
42571 this->copy_connection_information(open_curve_pt->
polyline_pt(cs),
42572 tmp_curve_section_pt);
42578 bool delete_it_on_destructor =
false;
42580 std::set<TriangleMeshCurveSection*>::iterator it =
42583 if (it!=this->Free_curve_section_pt.end())
42585 this->Free_curve_section_pt.erase(it);
42587 delete_it_on_destructor =
true;
42595 this->Boundary_curve_section_pt[bound]=open_curve_pt->
curve_section_pt(cs);
42597 if (delete_it_on_destructor)
42602 #ifdef OOMPH_HAS_MPI 42606 if (this->is_mesh_distributed() && nsub_boundaries == 1)
42609 this->Boundary_marked_as_shared_boundary[bound].clear();
42612 this->Boundary_marked_as_shared_boundary[bound].push_back(
42613 internal_to_shared_boundary[0]);
42617 else if (this->is_mesh_distributed() && nsub_boundaries > 1)
42622 this->Boundary_subpolylines[bound].clear();
42624 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
42627 this->Boundary_marked_as_shared_boundary[bound].clear();
42630 this->Boundary_marked_as_shared_boundary[bound].resize(nsub_boundaries);
42631 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
42640 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
42644 this->Boundary_marked_as_shared_boundary[bound][isub] =
42645 internal_to_shared_boundary[isub];
42655 #endif // OOMPH_HAS_MPI 42661 delete mesh_geom_obj_pt;
42666 for(
unsigned p = 0; p < ncurve_section; p++)
42668 face_mesh_pt[p]->flush_node_storage();
42669 delete face_mesh_pt[p];
42674 #ifdef OOMPH_HAS_MPI 42678 template <
class ELEMENT>
42681 &vector_polyline_pt)
42684 const unsigned npolylines = vector_polyline_pt.size();
42685 for (
unsigned pp = 0; pp < npolylines; pp++)
42688 const unsigned b = vector_polyline_pt[pp]->boundary_id();
42693 std::map<std::pair<Node*, Node*>,
FiniteElement*> halo_edge_element_pt;
42694 std::map<std::pair<Node*, Node*>,
FiniteElement*> nonhalo_edge_element_pt;
42701 const unsigned nshared_bound_ele = this->nshared_boundary_element(b);
42702 for (
unsigned e = 0;
e < nshared_bound_ele;
e++)
42705 FiniteElement* current_ele_pt = this->shared_boundary_element_pt(b,
e);
42708 Node *first_node_pt = current_ele_pt->
node_pt(0);
42709 Node *second_node_pt = current_ele_pt->
node_pt(1);
42710 Node *third_node_pt = current_ele_pt->
node_pt(2);
42713 if (!current_ele_pt->
is_halo())
42716 nonhalo_edge_nodes_pt.push_back(first_node_pt);
42717 nonhalo_edge_nodes_pt.push_back(second_node_pt);
42719 nonhalo_edge_nodes_pt.push_back(second_node_pt);
42720 nonhalo_edge_nodes_pt.push_back(third_node_pt);
42722 nonhalo_edge_nodes_pt.push_back(third_node_pt);
42723 nonhalo_edge_nodes_pt.push_back(first_node_pt);
42726 std::pair<Node*, Node*> edge1 = std::make_pair(first_node_pt,
42728 nonhalo_edge_element_pt[edge1] = current_ele_pt;
42730 std::pair<Node*, Node*> edge2 = std::make_pair(second_node_pt,
42732 nonhalo_edge_element_pt[edge2] = current_ele_pt;
42734 std::pair<Node*, Node*> edge3 = std::make_pair(third_node_pt,
42736 nonhalo_edge_element_pt[edge3] = current_ele_pt;
42741 halo_edge_nodes_pt.push_back(first_node_pt);
42742 halo_edge_nodes_pt.push_back(second_node_pt);
42744 halo_edge_nodes_pt.push_back(second_node_pt);
42745 halo_edge_nodes_pt.push_back(third_node_pt);
42747 halo_edge_nodes_pt.push_back(third_node_pt);
42748 halo_edge_nodes_pt.push_back(first_node_pt);
42751 std::pair<Node*, Node*> edge1 = std::make_pair(first_node_pt,
42753 halo_edge_element_pt[edge1] = current_ele_pt;
42755 std::pair<Node*, Node*> edge2 = std::make_pair(second_node_pt,
42757 halo_edge_element_pt[edge2] = current_ele_pt;
42759 std::pair<Node*, Node*> edge3 = std::make_pair(third_node_pt,
42761 halo_edge_element_pt[edge3] = current_ele_pt;
42769 std::map<std::pair<Node*,Node*>,
bool> edge_done;
42778 const unsigned nnonhalo_edge_nodes = nonhalo_edge_nodes_pt.size();
42779 for (
unsigned i = 0;
i < nnonhalo_edge_nodes;
i+=2)
42782 currenti_edge[0] = nonhalo_edge_nodes_pt[
i];
42783 currenti_edge[1] = nonhalo_edge_nodes_pt[
i+1];
42786 std::pair<Node*, Node*> new_edge =
42787 std::make_pair(currenti_edge[0], currenti_edge[1]);
42789 if (!edge_done[new_edge])
42791 const unsigned nhalo_edge_nodes = halo_edge_nodes_pt.size();
42792 for (
unsigned j = 0; j < nhalo_edge_nodes; j+=2)
42795 currentj_edge[0] = halo_edge_nodes_pt[j];
42796 currentj_edge[1] = halo_edge_nodes_pt[j+1];
42799 if (currenti_edge[0] == currentj_edge[0] &&
42800 currenti_edge[1] == currentj_edge[1])
42803 unsorted_edges.push_back(new_edge);
42808 FiniteElement* nonhalo_ele_pt = nonhalo_edge_element_pt[new_edge];
42809 FiniteElement* halo_ele_pt = halo_edge_element_pt[new_edge];
42811 tmp_edge_element_pt.push_back(nonhalo_ele_pt);
42812 tmp_edge_element_pt.push_back(halo_ele_pt);
42815 unsorted_edges_elements_pt.push_back(tmp_edge_element_pt);
42818 edge_done[new_edge] =
true;
42826 else if (currenti_edge[0] == currentj_edge[1] &&
42827 currenti_edge[1] == currentj_edge[0])
42830 std::pair<Node*, Node*> new_edge =
42831 std::make_pair(currenti_edge[0], currenti_edge[1]);
42834 unsorted_edges.push_back(new_edge);
42837 std::pair<Node*, Node*> rev_new_edge =
42838 std::make_pair(currentj_edge[0], currentj_edge[1]);
42843 FiniteElement* nonhalo_ele_pt = nonhalo_edge_element_pt[new_edge];
42844 FiniteElement* halo_ele_pt = halo_edge_element_pt[rev_new_edge];
42846 tmp_edge_element_pt.push_back(nonhalo_ele_pt);
42847 tmp_edge_element_pt.push_back(halo_ele_pt);
42850 unsorted_edges_elements_pt.push_back(tmp_edge_element_pt);
42853 edge_done[new_edge] =
true;
42871 std::map<std::pair<Node*,Node*>,
bool> edge_sorted;
42873 const unsigned nunsorted_edges = unsorted_edges.size();
42878 if (nshared_bound_ele / 2 != nunsorted_edges)
42880 std::ostringstream error_message;
42882 <<
"The number of shared boundary elements (" << nshared_bound_ele
42883 <<
") is not the double\nof the number of unsorted edges (" 42884 << nunsorted_edges <<
") for the current boundary ("<< b <<
")\n\n";
42886 "RefineableTriangleMesh::update_shared_curve_after_restart()",
42887 OOMPH_EXCEPTION_LOCATION);
42891 unsigned nsorted_edges = 0;
42895 std::list<Node*> sorted_nodes;
42898 std::list<FiniteElement*> sorted_edges_elements_pt;
42901 std::pair<Node*,Node*> edge = unsorted_edges[0];
42905 edge_sorted[edge] =
true;
42908 Node *first_node_pt = edge.first;
42909 Node *last_node_pt = edge.second;
42912 sorted_nodes.push_back(first_node_pt);
42913 sorted_nodes.push_back(last_node_pt);
42916 sorted_edges_elements_pt.push_back(unsorted_edges_elements_pt[0][0]);
42917 sorted_edges_elements_pt.push_back(unsorted_edges_elements_pt[0][1]);
42921 while (nsorted_edges < nunsorted_edges)
42924 bool node_added =
false;
42928 for (
unsigned iedge = 1; iedge < nunsorted_edges; iedge++)
42930 edge = unsorted_edges[iedge];
42933 if (!edge_sorted[edge])
42936 Node* left_node_pt = edge.first;
42937 Node* right_node_pt = edge.second;
42939 if (left_node_pt == first_node_pt)
42942 sorted_nodes.push_front(right_node_pt);
42943 first_node_pt = right_node_pt;
42947 sorted_edges_elements_pt.push_front(
42948 unsorted_edges_elements_pt[iedge][1]);
42949 sorted_edges_elements_pt.push_front(
42950 unsorted_edges_elements_pt[iedge][0]);
42952 else if (left_node_pt == last_node_pt)
42955 sorted_nodes.push_back(right_node_pt);
42956 last_node_pt = right_node_pt;
42960 sorted_edges_elements_pt.push_back(
42961 unsorted_edges_elements_pt[iedge][0]);
42962 sorted_edges_elements_pt.push_back(
42963 unsorted_edges_elements_pt[iedge][1]);
42965 else if (right_node_pt == first_node_pt)
42968 sorted_nodes.push_front(left_node_pt);
42969 first_node_pt = left_node_pt;
42973 sorted_edges_elements_pt.push_front(
42974 unsorted_edges_elements_pt[iedge][1]);
42975 sorted_edges_elements_pt.push_front(
42976 unsorted_edges_elements_pt[iedge][0]);
42978 else if (right_node_pt == last_node_pt)
42981 sorted_nodes.push_back(left_node_pt);
42982 last_node_pt = left_node_pt;
42986 sorted_edges_elements_pt.push_back(
42987 unsorted_edges_elements_pt[iedge][0]);
42988 sorted_edges_elements_pt.push_back(
42989 unsorted_edges_elements_pt[iedge][1]);
42996 edge_sorted[edge] =
true;
43011 unsigned nvertex = sorted_nodes.size();
43016 unsigned counter = 0;
43017 for (std::list<Node*>::iterator it_nodes = sorted_nodes.begin();
43018 it_nodes != sorted_nodes.end();
43021 polyline_vertices[counter].resize(2);
43022 polyline_vertices[counter][0] = (*it_nodes)->x(0);
43023 polyline_vertices[counter][1] = (*it_nodes)->x(1);
43030 if (polyline_vertices[nvertex-1][1] < polyline_vertices[0][1])
43032 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
43034 else if (polyline_vertices[nvertex-1][1] == polyline_vertices[0][1])
43036 if (polyline_vertices[nvertex-1][0] < polyline_vertices[0][0])
43038 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
43051 this->copy_connection_information(curve_section_pt, new_polyline_pt);
43056 bool delete_it_on_destructor =
false;
43060 std::set<TriangleMeshCurveSection*>::iterator it =
43061 this->Free_curve_section_pt.find(curve_section_pt);
43063 if (it!=this->Free_curve_section_pt.end())
43065 this->Free_curve_section_pt.erase(it);
43066 delete curve_section_pt;
43067 delete_it_on_destructor =
true;
43071 vector_polyline_pt[pp] = new_polyline_pt;
43077 this->Boundary_curve_section_pt[b] = new_curve_section_pt;
43079 if (delete_it_on_destructor)
43081 this->Free_curve_section_pt.insert(new_curve_section_pt);
43094 template <
class ELEMENT>
43099 std::ofstream some_file;
43100 fill_boundary_elements_and_nodes_for_internal_boundaries(some_file);
43107 template <
class ELEMENT>
43110 std::ofstream& outfile)
43113 const unsigned nproc = this->communicator_pt()->nproc();
43115 unsigned my_rank = this->communicator_pt()->my_rank();
43118 std::map<unsigned, unsigned> shd_bnd_over_int_bnd =
43119 this->Shared_boundary_overlaps_internal_boundary;
43123 std::set<unsigned> internal_boundary_overlaped;
43127 if (outfile.is_open())
43129 const unsigned nbound = this->nboundary();
43130 outfile <<
"Number of boundaries: " << nbound <<
"\n\n";
43131 outfile <<
"Number of elements and nodes associated to each " 43132 <<
"boundary before\nfilling elements and nodes\n\n";
43133 for (
unsigned i = 0;
i < nbound;
i++)
43135 outfile <<
"Boundary (" <<
i <<
") Elements (" 43136 << this->nboundary_element(
i) <<
") " <<
"Nodes (" 43137 << this->nboundary_node(
i) <<
")\n";
43142 std::set<unsigned> shared_boundaries_in_this_processor;
43146 for (
unsigned iproc = 0; iproc < nproc; iproc++)
43149 if (iproc != my_rank)
43152 unsigned nshared_boundaries_with_iproc =
43153 this->nshared_boundaries(my_rank, iproc);
43155 if (nshared_boundaries_with_iproc > 0)
43159 bound_shared_with_iproc = this->shared_boundaries_ids(my_rank,
43163 for (
unsigned bs = 0; bs < nshared_boundaries_with_iproc; bs++)
43165 unsigned bnd_id = bound_shared_with_iproc[bs];
43166 shared_boundaries_in_this_processor.insert(bnd_id);
43177 for (std::map<unsigned, unsigned>::iterator it =
43178 shd_bnd_over_int_bnd.begin(); it != shd_bnd_over_int_bnd.end(); it++)
43181 const unsigned shd_bnd_id = (*it).first;
43183 const unsigned int_bnd_id = (*it).second;
43186 std::set<unsigned>::iterator it_set =
43187 shared_boundaries_in_this_processor.find(shd_bnd_id);
43188 if (it_set != shared_boundaries_in_this_processor.end())
43190 internal_boundary_overlaped.insert(int_bnd_id);
43195 const unsigned nbnd_node_shd_bnd = this->nboundary_node(shd_bnd_id);
43199 if (outfile.is_open())
43201 outfile <<
"\nPass info. from shared (" << shd_bnd_id
43202 <<
") to internal (" << int_bnd_id <<
")\n";
43203 outfile <<
"Number of shared boundary nodes: " 43204 << nbnd_node_shd_bnd <<
"\n";
43207 for (
unsigned in = 0; in < nbnd_node_shd_bnd; in++)
43210 Node* bnd_node_pt = this->boundary_node_pt(shd_bnd_id, in);
43212 this->add_boundary_node(int_bnd_id, bnd_node_pt);
43219 const unsigned nbnd_ele_shd_bnd = this->nboundary_element(shd_bnd_id);
43223 if (outfile.is_open())
43225 outfile <<
"Number of shared boundary elements: " 43226 << nbnd_ele_shd_bnd <<
"\n\n";
43231 for (
unsigned ie = 0; ie < nbnd_ele_shd_bnd; ie++)
43234 FiniteElement* bnd_ele_pt = this->boundary_element_pt(shd_bnd_id, ie);
43237 Boundary_element_pt[int_bnd_id].push_back(bnd_ele_pt);
43239 int face_index = this->face_index_at_boundary(shd_bnd_id, ie);
43241 Face_index_at_boundary[int_bnd_id].push_back(face_index);
43246 const unsigned nregions = this->nregion();
43249 for (
unsigned ir = 0 ; ir < nregions; ir++)
43252 const unsigned region_id =
43253 static_cast<unsigned>(this->Region_attribute[ir]);
43256 const unsigned nele_ir = this->nboundary_element_in_region(shd_bnd_id,
43258 for (
unsigned ier = 0; ier < nele_ir; ier++)
43262 this->boundary_element_in_region_pt(shd_bnd_id, region_id, ier);
43265 this->Boundary_region_element_pt[int_bnd_id][region_id].
43266 push_back(bnd_ele_pt);
43270 this->face_index_at_boundary_in_region(shd_bnd_id, region_id, ier);
43272 this->Face_index_region_at_boundary[int_bnd_id][region_id].
43273 push_back(face_index);
43287 if (outfile.is_open())
43289 const unsigned nbound = this->nboundary();
43290 outfile <<
"Number of boundaries: " << nbound <<
"\n\n";
43291 outfile <<
"Number of elements and nodes associated to each " 43292 <<
"boundary after\nfilling elements and nodes\n\n";
43293 for (
unsigned i = 0;
i < nbound;
i++)
43295 outfile <<
"Boundary (" <<
i <<
") Elements (" 43296 << this->nboundary_element(
i) <<
")" <<
" Nodes (" 43297 << this->nboundary_node(
i) <<
")\n";
43305 for (std::set<unsigned>::iterator it = internal_boundary_overlaped.begin();
43306 it != internal_boundary_overlaped.end(); it++)
43308 const unsigned overlaped_internal_bnd_id = (*it);
43311 this->
template setup_boundary_coordinates<ELEMENT>(overlaped_internal_bnd_id);
43316 #endif // #ifdef OOMPH_HAS_MPI 43321 template <
class ELEMENT>
43327 if (!Boundary_coordinate_exists[b])
43343 std::set<Node*> tmp_boundary_node_pt;
43344 const unsigned nboundary_ele = this->nboundary_element(b);
43345 for (
unsigned e = 0;
e < nboundary_ele;
e++)
43349 #ifdef OOMPH_HAS_MPI 43355 int face_index = this->face_index_at_boundary(b,
e);
43358 bulk_ele_pt, face_index);
43361 const unsigned nnodes = face_ele_pt->
nnode();
43362 for (
unsigned i = 0;
i < nnodes;
i++)
43367 tmp_boundary_node_pt.insert(tmp_node_pt);
43371 delete face_ele_pt;
43373 #ifdef OOMPH_HAS_MPI 43380 const unsigned long n_boundary_node = tmp_boundary_node_pt.
size();
43383 if (n_boundary_node==0)
43385 #ifdef OOMPH_HAS_MPI 43387 if (!this->is_mesh_distributed())
43391 #ifdef OOMPH_HAS_MPI 43397 create_unsorted_face_mesh_representation(b, face_mesh_pt);
43401 delete mesh_geom_obj_pt;
43406 delete face_mesh_pt;
43418 unsigned tmp_counter = 0;
43419 for(std::set<Node*>::iterator it_node = tmp_boundary_node_pt.begin();
43420 it_node != tmp_boundary_node_pt.end(); it_node++, tmp_counter++)
43422 Node* nod_pt = (*it_node);
43424 node_coord[0] = b_coord[0];
43425 node_coord[1] = nod_pt->
x(0);
43426 node_coord[2] = nod_pt->
x(1);
43427 old_boundary_node[tmp_counter] = node_coord;
43431 std::sort(old_boundary_node.begin(),old_boundary_node.end());
43442 #ifdef OOMPH_HAS_MPI 43448 const unsigned nsegments = 1;
43449 #endif // #ifdef OOMPH_HAS_MPI 43451 #ifdef OOMPH_HAS_MPI 43456 if (this->is_mesh_distributed())
43461 if (n_new_boundary_node==0)
43465 create_unsorted_face_mesh_representation(b, face_mesh_pt);
43469 delete mesh_geom_obj_pt;
43473 delete face_mesh_pt;
43477 #endif // #ifdef OOMPH_HAS_MPI 43484 for (
unsigned is = 0; is < nsegments; is++)
43486 #ifdef OOMPH_HAS_MPI 43487 const unsigned n_new_boundary_segment_node =
43490 const unsigned n_new_boundary_segment_node = new_mesh_pt->
nboundary_node(b);
43491 #endif // #ifdef OOMPH_HAS_MPI 43495 node_coord.resize(6,0.0);
43496 for(
unsigned n = 0; n < n_new_boundary_segment_node; n++)
43498 #ifdef OOMPH_HAS_MPI 43502 #endif // #ifdef OOMPH_HAS_MPI 43504 node_coord[0] = b_coord[0];
43505 node_coord[1] = nod_pt->
x(0);
43506 node_coord[2] = nod_pt->
x(1);
43508 new_boundary_node[n] = node_coord;
43512 std::sort(new_boundary_node.begin(),new_boundary_node.end());
43519 unsigned old_index = 0;
43520 for(
unsigned n=0;n<n_new_boundary_segment_node;++n)
43524 for(
unsigned m=old_index;m<n_boundary_node;++m)
43527 (std::fabs(old_boundary_node[m][1]-new_boundary_node[n][1])<1.0
e-14)
43529 (std::fabs(old_boundary_node[m][2]-new_boundary_node[n][2])<1.0e-14))
43532 new_boundary_node[n][4] = old_boundary_node[m][0];
43534 new_boundary_node[n][5] = 1.0;
43545 if((new_boundary_node[0][5]==0.0) ||
43546 (new_boundary_node[n_new_boundary_segment_node-1][5] == 0.0))
43548 std::ostringstream error_stream;
43550 <<
"New boundary coordinates not found for the first and/or last " 43552 <<
"on the boundary " << b <<
". This should not happen because " 43553 <<
"these\nlimits should have been setup in the constructor\n";
43555 <<
"The distance between the new and old nodes is probably outside\n" 43556 <<
"our tolerance.\n";
43557 error_stream.precision(20);
43558 error_stream <<
"Old boundaries: \n";
43560 old_boundary_node[0][1] <<
" " << old_boundary_node[0][2]
43562 old_boundary_node[n_boundary_node-1][1] <<
" " <<
43563 old_boundary_node[n_boundary_node-1][2] <<
"\n";
43564 error_stream <<
"New boundaries: \n" <<
43565 new_boundary_node[0][1] <<
" " << new_boundary_node[0][2] <<
" : " <<
43566 new_boundary_node[n_new_boundary_segment_node-1][1] <<
" " <<
43567 new_boundary_node[n_new_boundary_segment_node-1][2] <<
"\n";
43569 "RefineableTriangleMesh::snap_nodes_onto_boundary()",
43570 OOMPH_EXCEPTION_LOCATION);
43576 if (!this->is_mesh_distributed())
43580 new_boundary_node[0][4] = new_boundary_node[0][0];
43583 new_boundary_node[n_new_boundary_segment_node-1][4] =
43584 new_boundary_node[0][5] = 1.0;
43586 new_boundary_node[n_new_boundary_segment_node-1][4] =
43587 new_boundary_node[n_new_boundary_segment_node-1][0];
43588 new_boundary_node[n_new_boundary_segment_node-1][5] = 1.0;
43593 for(
unsigned n=1;n<n_new_boundary_segment_node-1;++n)
43596 if(new_boundary_node[n][5]==0.0)
43599 nodes_to_be_snapped[is].push_back(
43600 static_cast<unsigned>(new_boundary_node[n][3]));
43604 double zeta_old_low = new_boundary_node[n-1][0];
43605 double zeta_new_low = new_boundary_node[n-1][4];
43609 for(
unsigned m=n+1;m<n_new_boundary_segment_node;++m)
43611 if(new_boundary_node[m][5]==1.0)
43614 double zeta_old_high = new_boundary_node[m][0];
43615 double zeta_new_high = new_boundary_node[m][4];
43617 double frac = (new_boundary_node[n][0] - zeta_old_low)/
43618 (zeta_old_high - zeta_old_low);
43619 new_boundary_node[n][4] = zeta_new_low
43620 + frac*(zeta_new_high - zeta_new_low);
43621 new_boundary_node[n][5] = 1.0;
43629 for(
unsigned n=0;n<n_new_boundary_segment_node;++n)
43631 if(new_boundary_node[n][5]==0)
43634 "New boundary coordinate not assigned\n",
43635 "RefineableTriangleMesh::snap_nodes_onto_boundary()",
43636 OOMPH_EXCEPTION_LOCATION);
43639 #ifdef OOMPH_HAS_MPI 43642 b,is,static_cast<unsigned>(new_boundary_node[n][3]))
43643 ->get_coordinates_on_boundary(b,b_coord);
43645 b_coord[0] = new_boundary_node[n][4];
43647 b,is,static_cast<unsigned>(new_boundary_node[n][3]))
43648 ->set_coordinates_on_boundary(b,b_coord);
43652 b,static_cast<unsigned>(new_boundary_node[n][3]))
43653 ->get_coordinates_on_boundary(b,b_coord);
43655 b_coord[0] = new_boundary_node[n][4];
43657 b,static_cast<unsigned>(new_boundary_node[n][3]))
43658 ->set_coordinates_on_boundary(b,b_coord);
43659 #endif // #ifdef OOMPH_HAS_MPI 43666 create_unsorted_face_mesh_representation(b, face_mesh_pt);
43676 for(
unsigned is = 0; is < nsegments; is++)
43678 const unsigned nnodes_to_snap = nodes_to_be_snapped[is].size();
43680 for (
unsigned in = 0; in < nnodes_to_snap; in++)
43683 unsigned n = nodes_to_be_snapped[is][in];
43684 #ifdef OOMPH_HAS_MPI 43690 #endif // #ifdef OOMPH_HAS_MPI 43694 mesh_geom_obj_pt->
position(b_coord,new_x);
43697 for(
unsigned i=0;
i<2;
i++)
43699 nod_pt->
x(
i) = new_x[
i];
43705 delete mesh_geom_obj_pt;
43709 delete face_mesh_pt;
43716 for (
unsigned j=0;j<6;j++)
43718 dummy_six_node_element.construct_node(j);
43724 for(
unsigned e=0;
e<n_bound_el;
e++)
43729 unsigned nnod=el_pt->
nnode();
43745 "Have a three-noded element that's not a TElement<2,2>",
43746 OOMPH_CURRENT_FUNCTION,
43747 OOMPH_EXCEPTION_LOCATION);
43755 else if ((nnod==6)||(nnod==7))
43766 "Have a six-noded element that's not a TElement<2,3>",
43767 OOMPH_CURRENT_FUNCTION,
43768 OOMPH_EXCEPTION_LOCATION);
43773 "Have a seven-noded element that's not a TElement<2,3>",
43774 OOMPH_CURRENT_FUNCTION,
43775 OOMPH_EXCEPTION_LOCATION);
43795 for(
unsigned i=0;
i<2;
i++)
43806 for(
unsigned i=0;
i<2;
i++)
43822 for(
unsigned i=0;
i<2;
i++)
43833 for(
unsigned i=0;
i<2;
i++)
43849 for(
unsigned i=0;
i<2;
i++)
43860 for(
unsigned i=0;
i<2;
i++)
43878 "Have seven-noded element that's not a TBubbleEnrichedElement<2,3>",
43879 OOMPH_CURRENT_FUNCTION,
43880 OOMPH_EXCEPTION_LOCATION);
43884 for (
unsigned j=0;j<6;j++)
43886 for (
unsigned i=0;
i<2;
i++)
43888 dummy_six_node_element.node_pt(j)->x(
i)=el_pt->
node_pt(j)->
x(
i);
43893 unsigned j_enriched=6;
43899 dummy_six_node_element.interpolated_x(s,x);
43900 el_pt->
node_pt(j_enriched)->
x(0) = x[0];
43901 el_pt->
node_pt(j_enriched)->
x(1) = x[1];
43908 std::ostringstream error_stream;
43910 <<
"Cannot deal with this particular " << nnod
43911 <<
"-noded element yet.\n" 43912 <<
"Please implement this yourself.\n";
43914 OOMPH_CURRENT_FUNCTION,
43915 OOMPH_EXCEPTION_LOCATION);
43920 for (
unsigned j=0;j<6;j++)
43922 delete dummy_six_node_element.node_pt(j);
43929 #endif // #ifdef OOMPH_HAS_TRIANGLE_LIB unsigned nboundary_element(const unsigned &b) const
Return number of finite elements that are adjacent to boundary b.
A Generalised Element class.
bool is_redistribution_of_segments_between_polylines_enabled()
Is re-distribution of polyline segments in the curve between different boundaries during adaptation e...
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.
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 add_haloed_node_helper(unsigned &iproc, Node *nod_pt)
Helper function to add haloed node.
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 ...
virtual TriangleMeshCurveSection * curve_section_pt(const unsigned &i) const
Pointer to i-th constituent curve section.
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) ...
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...
unsigned nboundary_segment(const unsigned &b)
Return the number of segments associated with a boundary.
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 ...
unsigned boundary_chunk() const
std::map< unsigned, Vector< double > > & boundary_final_coordinate()
Return direct access to the final coordinates of a boundary.
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...
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 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...
double * pointlist
Pointer to list of points x coordinate followed by y coordinate.
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 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...
double & min_element_size()
Min element size allowed during adaptation.
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.
void set_initial_vertex_connected()
Sets the initial vertex as connected.
GeomObject * geom_object_pt(const unsigned &i)
Return pointer to i-th geometric object involved in default (usually first) update function...
unsigned nboundary_element_in_region(const unsigned &b, const unsigned &r) const
Return the number of elements adjacent to boundary b in region r.
double * pointattributelist
Pointer to list of point attributes.
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...
Unstructured refineable Triangle Mesh upgraded to solid mesh.
void final_vertex_coordinate(Vector< double > &vertex)
Get last vertex coordinates.
std::map< unsigned, Vector< double > > & regions_coordinates()
Helper function for getting access to the regions coordinates.
Node *& boundary_node_pt(const unsigned &b, const unsigned &n)
Return pointer to node n on boundary b.
void add_vertices_for_non_deletion()
Mark the vertices that are not allowed for deletion by the unrefienment/refinement polyline methods...
int * pointmarkerlist
Pointer to list of point markers.
void get_required_elemental_information_helper(unsigned &iproc, FiniteElement *ele_pt)
Helper function to get the required elemental information from an haloed element. This info...
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 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...
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...
const void synchronize_shared_boundary_connections()
Synchronise the vertices that are marked for non deletion.
TriangleMeshPolyLine * polyline_pt(const unsigned &i) const
Pointer to i-th constituent polyline.
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 ...
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 ...
TriangulateIO & triangulateio_representation()
Access to the triangulateio representation of the mesh.
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_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...
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.
Information for documentation of results: Directory and file number to enable output in the form RESL...
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...
Vector< TriangleMeshOpenCurve * > internal_open_curves_pt() const
Helper function for getting the internal open boundaries.
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...
unsigned Counter_for_flat_packed_unsigneds
Counter used when processing vector of flat-packed unsigneds – this is really "private" data...
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 update_polygon_after_restart(TriangleMeshPolygon *&polygon_pt)
Updates the polylines representation after restart.
void update_open_curve_after_restart(TriangleMeshOpenCurve *&open_curve_pt)
Updates the open curve representation after restart.
Class to keep track of discrete/continous time. It is essential to have a single Time object when usi...
Helper object for dealing with the parameters used for the NonRefineableBinArray objects.
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...
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...
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 ...
unsigned nref_value(const int &id)
Number of reference values involved in id-th update function.
std::map< unsigned, Vector< double > > & boundary_coordinate_limits()
Return access to the vector of boundary coordinates associated with each geometric object...
void adapt(const Vector< double > &elem_error)
Adapt mesh, based on elemental error provided.
void sort_nodes_on_shared_boundaries()
Sort the nodes on shared boundaries so that the processors that share a boundary agree with the order...
Helper object for dealing with the parameters used for the CGALSamplePointContainer objects...
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...
virtual void reset_boundary_element_info(Vector< unsigned > &ntmp_boundary_elements, Vector< Vector< unsigned > > &ntmp_boundary_elements_in_region, Vector< FiniteElement *> &deleted_elements)
Reset the boundary elements info. after load balance have taken place.
A general Finite Element class.
bool Doc_timings
Boolean to indicate whether to doc timings or not.
unsigned final_vertex_connected_n_chunk() const
Gets the boundary chunk to which the final end is connected.
virtual void reset_reference_configuration()
Virtual function that should be overloaded to update the polygons reference configuration.
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 ...
std::map< unsigned, Vector< double > > & boundary_initial_coordinate()
Return direct access to the initial coordinates of a boundary.
Vector< std::string > Flat_packed_unsigneds_string
int non_halo_proc_ID()
ID of processor ID that holds non-halo counterpart of halo node; negative if not a halo...
void enable_use_attributes()
Helper function for enabling the use of attributes.
FiniteElement * boundary_element_pt(const unsigned &b, const unsigned &e) const
Return pointer to e-th finite element on boundary b.
Helper object for dealing with the parameters used for the TriangleMesh objects.
CGAL-based SamplePointContainer.
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_...
Vector< double > internal_point() const
Coordinates of the internal point.
void snap_nodes_onto_boundary(RefineableTriangleMesh< ELEMENT > *&new_mesh_pt, const unsigned &b)
Snap the boundary nodes onto any curvilinear boundaries.
double refinement_tolerance()
Get tolerance for refinement of curve sections to create a better representation of curvilinear bound...
bool is_halo() const
Is this element a halo?
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...
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
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...
unsigned long nboundary_node(const unsigned &ibound) const
Return number of nodes on a particular boundary.
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 project(Mesh *base_mesh_pt, const bool &dont_project_positions=false)
Project from base into the problem's own mesh.
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 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...
Mesh *& mesh_pt()
Return a pointer to the global mesh.
TriangleMeshPolyLine * polyline_pt(const unsigned &i) const
Pointer to i-th constituent polyline.
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...
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 nvalue() const
Return number of values stored in data object (incl pinned ones).
std::map< unsigned, Vector< double > > & boundary_final_zeta_coordinate()
Return direct access to the final zeta coordinates of a boundary.
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 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 set_boundary_number_in_bulk_mesh(const unsigned &b)
Set function for the boundary number in bulk mesh.
bool Doc_comprehensive_timings
Global boolean to switch on comprehensive timing – can probably be declared const false when develop...
Vector< unsigned > Flat_packed_unsigneds
Vector of flat-packed unsigneds to be communicated with other processors – this is really "private" ...
GeomObject * geom_object_list_pt(const unsigned &i)
Access function to the ith GeomObject.
void output_boundary_coordinates(const unsigned &b, std::ostream &outfile)
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 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 ...
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 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.
bool is_initial_vertex_connected() const
Test whether initial vertex is connected or not.
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. Broken virtual interface provides run-time error checking.
double region_attribute(const unsigned &i)
Return the attribute associated with region i.
void resume_initial_vertex_connected()
int node_update_fct_id()
Default (usually first if there are multiple ones) node update fct id.
Vector< Vector< Node * > > & boundary_segment_node_pt(const unsigned &b)
Return direct access to nodes associated with a boundary but sorted in segments.
void set_refinement_tolerance(const double &tolerance)
Set tolerance for refinement of curve sections to create a better representation of curvilinear bound...
void set_communicator_pt(OomphCommunicator *comm_pt)
Function to set communicator (mesh is then assumed to be distributed)
void dump_distributed_info_for_restart(std::ostream &dump_file)
Used to dump info. related with distributed triangle meshes.
unsigned long nelement() const
Return number of elements in the mesh.
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 ...
double maximum_length()
Gets access to the maximum length variable.
double & max_element_size()
Max element size allowed during adaptation.
struct oomph::classcomp Bottom_left_sorter
bool operator()(const std::pair< double, double > &lhs, const std::pair< double, double > &rhs) const
bool Doc_full_stats
Boolean to indicate whether to output further info during setup_multi_domain_interaction() routines...
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...
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
virtual void remove_from_boundary(const unsigned &b)
Broken interface for removing the node from the mesh boundary b Here to provide error reporting...
bool must_be_kept_as_halo() const
Test whether the element must be kept as a halo element.
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...
double & x(const unsigned &i)
Return the i-th nodal coordinate.
A class that contains the information required by Nodes that are located on Mesh boundaries. A BoundaryNode of a particular type is obtained by combining a given Node with this class. By differentiating between Nodes and BoundaryNodes we avoid a lot of un-necessary storage in the bulk Nodes.
int non_halo_proc_ID()
ID of processor ID that holds non-halo counterpart of halo element; negative if not a halo...
virtual double interpolated_x(const Vector< double > &s, const unsigned &i) const
Return FE interpolated coordinate x[i] at local coordinate s.
void synchronize_boundary_coordinates(const unsigned &b)
In charge of sinchronize the boundary coordinates for internal boundaries that were split as part of ...
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...
unsigned nvertex() const
Number of vertices.
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...
const bool shared_boundary_overlaps_internal_boundary(const unsigned &shd_bnd_id)
Checks if the shared boundary overlaps an internal boundary.
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.
Class defining a polyline for use in Triangle Mesh generation.
void update_shared_curve_after_restart(Vector< TriangleMeshPolyLine *> &vector_polyline_pt)
Updates the shared polylines representation after restart.
void flush_node_storage()
Flush storage for nodes (only) by emptying the vectors that store the pointers to them...
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!) def...
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...
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 ...
void enable_problem_distributed()
Enable problem distributed.
GeneralisedElement *& element_pt(const unsigned long &e)
Return pointer to element e.
unsigned initial_vertex_connected_n_vertex() const
Gets the vertex number to which the initial end is connected.
unsigned boundary_id() const
Boundary id.
FiniteElement * region_element_pt(const unsigned &i, const unsigned &e)
Return the e-th element in the i-th region.
void clear_triangulateio(TriangulateIO &triangulate_io, const bool &clear_hole_data)
Clear TriangulateIO structure.
virtual Node * construct_node(const unsigned &n)
Construct the local node n and return a pointer to the newly created node object. ...
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...
virtual bool surface_remesh_for_inner_hole_boundaries(Vector< Vector< double > > &internal_point_coord, const bool &check_only=false)
Generate a new PSLG representation of the inner hole boundaries. Optional boolean is used to run it a...
double * triangleattributelist
unsigned nboundary() const
Return number of boundaries.
void create_shared_polylines_connections()
Establish the connections of the polylines previously marked as having connections. This connections were marked in the function TriangleMesh::create_polylines_from_halo_elements_helper().
double Tolerable_error
Acceptable discrepancy for mismatch in vertex coordinates. In paranoid mode, the code will die if the...
void build_from_scaffold(TimeStepper *time_stepper_pt, const bool &use_attributes)
Build mesh from scaffold.
std::map< unsigned, Vector< double > > & boundary_initial_zeta_coordinate()
Return direct access to the initial zeta coordinate of a boundary.
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...
Vector< unsigned > & dimensions_of_bin_array()
Number of bins in each coordinate direction.
void suspend_final_vertex_connected()
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...
virtual unsigned nvertex() const =0
Number of vertices.
virtual unsigned boundary_chunk() const =0
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 send_and_receive_elements_nodes_info(int &send_proc, int &recv_proc)
Helper function to send back halo and haloed information.
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 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 initial_vertex_coordinate(Vector< double > &vertex)
Get first vertex coordinates.
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 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...
bool is_final_vertex_connected() const
Test whether final vertex is connected or not.
virtual unsigned boundary_id() const =0
Boundary id.
A class that represents a collection of data; each Data object may contain many different individual ...
Vector< Vector< double > > extra_holes_coordinates() const
Helper function for getting the extra holes.
unsigned nregion()
Return the number of regions specified by attributes.
void suspend_initial_vertex_connected()
void disable_automatic_creation_of_vertices_on_boundaries()
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.
Data *const & variable_position_pt() const
Pointer to variable_position data (const version)
void set_final_vertex_connected()
Sets the final vertex as connected.
Vector< TriangleMeshClosedCurve * > internal_closed_curve_pt() const
Helper function for getting the internal closed boundaries.
double unrefinement_tolerance()
Get tolerance for unrefinement of curve section to create a better representation of curvilinear boun...
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...
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
double timer()
returns the time in seconds after some point in past
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 initialise_triangulateio(TriangulateIO &triangle_io)
Initialise TriangulateIO structure.
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...
void set_maximum_length(const double &maximum_length)
Allows to specify the maximum distance between two vertices that define the associated polyline of th...
Vector< double > Flat_packed_doubles
Vector of flat-packed doubles to be communicated with other processors.
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 set_unrefinement_tolerance(const double &tolerance)
Set tolerance for unrefinement of curve sections to avoid unnecessarily large numbers of elements on ...
unsigned ntstorage() const
Return the number of doubles required to represent history (one for steady)
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.
Node *& node_pt(const unsigned long &n)
Return pointer to global node n.
void disable_use_iterative_solver_for_projection()
Disbales the use of an iterative solver for projection.
bool apply_max_length_constraint(Mesh *face_mesh_pt, Vector< Vector< double > > &vector_bnd_vertices, double &max_length_constraint)
unsigned long nnode() const
Return number of nodes in the mesh.
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...
int numberoftriangleattributes
void reset_halo_haloed_scheme()
In charge of. re-establish the halo(ed) scheme on all processors. Sends info. to create halo elements...
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.
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...
int numberofpointattributes
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...
void resume_final_vertex_connected()
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...
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
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.
const std::map< unsigned, Vector< std::pair< FiniteElement *, Vector< double > > > > * get_all_bins_content() const
Get the contents of all bins in vector.
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 disable_doc()
Disable documentation.
double ref_value(const unsigned &i)
Return i-th reference value involved in default (usually first) update function.
A Class for nodes that deform elastically (i.e. position is an unknown in the problem). The idea is that the Eulerian positions are stored in a Data object and the Lagrangian coordinates are stored in addition. The pointer that addresses the Eulerian positions is set to the pointer to Value in the Data object. Hence, SolidNode uses knowledge of the internal structure of Data and must be a friend of the Data class. In order to allow a mesh to deform via an elastic-style equation in deforming-domain problems, the positions are stored separately from the values, so that elastic problems may be combined with any other type of problem.
void fill_boundary_elements_and_nodes_for_internal_boundaries()
unsigned ngeom_object_list_pt()
Return number of geometric objects associated with AlgebraicMesh.
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...
NonRefineableBinArray class.
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...
void resize(const unsigned &n_value)
Resize the number of equations.
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 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...
double element_area() const
Helper function for getting the element area.
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn't been defined.
unsigned ngeom_object(const int &id)
Number of geometric objects involved in id-th update function.
double * trianglearealist
void enable_use_eulerian_coordinates_during_setup()
bool is_internal_point_fixed() const
Test whether the internal point is fixed.
Vector< double > vertex_coordinate(const unsigned &i) const
Coordinate vector of i-th vertex (const version)
void add_element_pt(GeneralisedElement *const &element_pt)
Add a (pointer to) an element to the mesh.
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...
virtual bool is_on_boundary() const
Test whether the Node lies on a boundary. The "bulk" Node cannot lie on a boundary, so return false. This will be overloaded by BoundaryNodes.
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...
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 final_vertex_connected_bnd_id() const
Gets the id to which the final end is connected.
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 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 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...
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.
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. This info. involves the association of the element to a boundary or region, and if its part of the halo(ed) elements within a processor.
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 ...
unsigned initial_vertex_connected_n_chunk() const
Gets the boundary chunk to which the initial end is connected.
unsigned long nboundary_segment_node(const unsigned &b)
Return the number of segments associated with a boundary.
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 flush_element_and_node_storage()
Flush storage for elements and nodes by emptying the vectors that store the pointers to them...
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...
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.
unsigned nregion_element(const unsigned &i)
Return the number of elements in the i-th region.
void read_distributed_info_for_restart(std::istream &restart_file)
Used to read info. related with distributed triangle meshes.
void set_non_obsolete()
Mark node as non-obsolete.
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...
unsigned nnode() const
Return the number of nodes.
double & min_permitted_angle()
Min angle before remesh gets triggered.
Base class for time-stepping schemes. Timestepper provides an approximation of the temporal derivativ...
bool Doc_stats
Boolean to indicate whether to output basic info during setup_multi_domain_interaction() routines...
unsigned final_vertex_connected_n_vertex() const
Sets the vertex number to which the final end is connected.
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 ...
Unstructured refineable Triangle Mesh.
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 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...
Vector< unsigned > oomph_vertex_nodes_id()
Return the vector that contains the oomph-lib node number for all vertex nodes in the TriangulateIO 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.
Vector< GeomObject * > geom_object_vector_pt()
Access function to the vector of GeomObject.
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...
double value(const unsigned &i) const
Return i-th value (dofs or pinned) at this node either directly or via hanging node representation...
bool can_update_reference_configuration() const
Test whether curve can update reference.
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, these elements are then used on the function that computes the shared boundaries among the processors.
virtual unsigned ncurve_section() const
Number of constituent curves.
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...
unsigned Counter_for_flat_packed_doubles
Counter used when processing vector of flat-packed doubles – this is really "private" data...
unsigned initial_vertex_connected_bnd_id() const
Gets the id to which the initial end is connected.
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.
Vector< Vector< Vector< unsigned > > > shared_boundaries_ids() const
unsigned npolyline() const
Number of constituent polylines.
An oomph-lib wrapper to the MPI_Comm communicator object. Just contains an MPI_Comm object (which is ...
Class defining a closed polygon for the Triangle mesh generation.