28 #ifndef _SF_MESH_UTILS_EMI_H
29 #define _SF_MESH_UTILS_EMI_H
37 const int MAX_INTERSECTIONS = 20;
46 struct intersection_tags {
54 int tags[MAX_INTERSECTIONS];
56 std::fill_n(tags, MAX_INTERSECTIONS, -1);
61 struct intersection_data {
62 int tags[MAX_INTERSECTIONS];
63 int data[MAX_INTERSECTIONS];
64 int ranks[MAX_INTERSECTIONS];
67 std::fill_n(tags, MAX_INTERSECTIONS, -1);
68 std::fill_n(data, MAX_INTERSECTIONS, -1);
69 std::fill_n(ranks, MAX_INTERSECTIONS, -1);
73 struct intersection_indices {
74 int indices[MAX_INTERSECTIONS];
75 intersection_indices() {
76 std::fill_n(indices, MAX_INTERSECTIONS, -1);
87 template<
class K,
class V>
inline
90 size_t dsize = map.
size();
91 vector<K> key_vec (dsize);
92 vector<V> value_vec (dsize);
97 for(
const auto & v : map) {
98 if (v.second.second.eidx == -1){
99 key_vec[idx] = v.first;
100 value_vec[idx] = v.second;
105 key_vec.resize(dsize);
106 value_vec.resize(dsize);
110 MPI_Comm_size(comm, &size); MPI_Comm_rank(comm, &rank);
112 vector<int> perm, dest(dsize);
114 for(
size_t i=0; i<dsize; i++)
117 commgraph<size_t> grph;
118 grph.configure(dest, comm);
119 size_t nrecv =
sum(grph.rcnt);
125 vector<K> sbuff_key(dsize), rbuff_key(nrecv);
126 vector<V> sbuff_value(dsize), ibuff_value(dsize), rbuff_value(nrecv);
127 for(
size_t i=0; i<dsize; i++) {
128 sbuff_key[i] = key_vec[perm[i]];
129 sbuff_value[i] = value_vec[perm[i]];
139 for (
size_t i = 0; i < nrecv; i++) {
140 auto it = rmap.
find(rbuff_key[i]);
141 if(it != rmap.
end()) {
146 if (it->second.first.tag != rbuff_value[i].first.tag) {
147 it->second.second = rbuff_value[i].first;
150 rmap.
insert({rbuff_key[i], rbuff_value[i]});
154 for (
size_t i = 0; i < nrecv; i++ ) {
155 auto it = rmap.
find(rbuff_key[i]);
156 if(it != rmap.
end()) rbuff_value[i] = it->second;
163 for (
size_t i = 0; i < dsize; i++ ) {
164 auto it = map.find(sbuff_key[i]);
165 if (it != map.end()) it->second = ibuff_value[i];
177 template<
class K,
class V>
inline
189 size_t dsize = map.
size();
190 vector<K> key_vec (dsize);
191 vector<V> value_vec (dsize);
195 for(
const auto & v : map) {
196 if (v.second.second.index_unique == -1 && v.second.second.index_one == -1){
197 key_vec[idx] = v.first;
198 value_vec[idx] = v.second;
203 key_vec.resize(dsize);
204 value_vec.resize(dsize);
208 MPI_Comm_size(comm, &size); MPI_Comm_rank(comm, &rank);
210 vector<int> perm, dest(dsize);
212 for(
size_t i=0; i<dsize; i++)
215 commgraph<size_t> grph;
216 grph.configure(dest, comm);
217 size_t nrecv =
sum(grph.rcnt);
223 vector<K> sbuff_key(dsize), rbuff_key(nrecv);
224 vector<V> sbuff_value(dsize), ibuff_value(dsize), rbuff_value(nrecv);
225 for(
size_t i=0; i<dsize; i++) {
226 sbuff_key[i] = key_vec[perm[i]];
227 sbuff_value[i] = value_vec[perm[i]];
237 for (
size_t i = 0; i < nrecv; i++) {
238 auto it = rmap.
find(rbuff_key[i]);
239 if(it != rmap.
end()) {
241 auto& existing = it->second;
242 using Face = std::decay_t<decltype(existing.first)>;
244 auto update_slot = [&](Face& slot,
const Face& src) {
248 if (src.index_unique >= 0) {
249 slot.index_unique = src.index_unique;
250 slot.rank = src.rank;
252 if (slot.rank < 0) slot.rank = src.rank;
254 if (slot.index_one < 0 && src.index_one >= 0) slot.index_one = src.index_one;
257 auto same_face = [&](
const Face& a,
const Face& b) {
259 return (a.rank >= 0 && b.rank >= 0 &&
260 a.index_one >= 0 && b.index_one >= 0 &&
261 a.rank == b.rank && a.index_one == b.index_one);
264 auto ingest = [&](
const Face& incoming) {
266 if (incoming.index_one < 0 && incoming.index_unique < 0 && incoming.rank < 0)
return;
268 if (same_face(existing.first, incoming) || existing.first.rank == incoming.rank) {
269 update_slot(existing.first, incoming);
270 }
else if (same_face(existing.second, incoming) || existing.second.rank == incoming.rank) {
271 update_slot(existing.second, incoming);
272 }
else if (existing.second.index_one == -1 && existing.second.index_unique == -1) {
274 existing.second = incoming;
275 }
else if (existing.first.index_one == -1 && existing.first.index_unique == -1) {
277 existing.first = incoming;
281 if (existing.first.index_unique < 0 && incoming.index_unique >= 0) {
282 existing.first.index_unique = incoming.index_unique;
283 existing.first.rank = incoming.rank;
284 }
else if (existing.second.index_unique < 0 && incoming.index_unique >= 0) {
285 existing.second.index_unique = incoming.index_unique;
286 existing.second.rank = incoming.rank;
292 ingest(rbuff_value[i].first);
293 ingest(rbuff_value[i].second);
296 rmap.
insert({rbuff_key[i], rbuff_value[i]});
300 for (
size_t i = 0; i < nrecv; i++ ) {
301 auto it = rmap.
find(rbuff_key[i]);
302 if(it != rmap.
end()) rbuff_value[i] = it->second;
309 for (
size_t i = 0; i < dsize; i++ ) {
310 auto it = map.find(sbuff_key[i]);
311 if (it != map.end()) {
313 it->second = ibuff_value[i];
317 map.insert({sbuff_key[i], ibuff_value[i]});
329 template<
class K>
inline
332 size_t dsize = map.
size();
333 vector<K> key_vec(dsize);
334 vector<intersection_data> value_vec(dsize);
337 for (
const auto& v : map) {
338 key_vec[idx] = v.first;
339 value_vec[idx] = v.second;
344 MPI_Comm_size(comm, &size); MPI_Comm_rank(comm, &rank);
346 vector<int> perm, dest(dsize);
347 for (
size_t i = 0; i < dsize; i++)
350 commgraph<size_t> grph;
351 grph.configure(dest, comm);
352 size_t nrecv =
sum(grph.rcnt);
358 vector<K> sbuff_key(dsize), rbuff_key(nrecv);
359 vector<intersection_data> sbuff_value(dsize), ibuff_value(dsize), rbuff_value(nrecv);
360 for (
size_t i = 0; i < dsize; i++) {
361 sbuff_key[i] = key_vec[perm[i]];
362 sbuff_value[i] = value_vec[perm[i]];
368 for (
size_t i = 0; i < nrecv; i++) {
369 auto it = rmap.
find(rbuff_key[i]);
370 if (it != rmap.
end()) {
371 intersection_data& map_val = it->second;
372 intersection_data& r_val = rbuff_value[i];
374 int first_index = -1;
375 for (
int j = 0; j < MAX_INTERSECTIONS; ++j) {
376 if (map_val.tags[j] == -1 && map_val.ranks[j] == -1) {
382 if (first_index == -1)
continue;
384 for (
int j = 0; j < MAX_INTERSECTIONS; ++j) {
385 if (r_val.tags[j] == -1)
continue;
387 int rtag = r_val.tags[j];
388 int rdata = r_val.data[j];
389 int rrank = r_val.ranks[j];
391 bool exist_rtag =
false;
392 for (
int k = 0; k < first_index; ++k) {
393 if (map_val.tags[k] == rtag && map_val.ranks[k] == rrank) {
399 if (!exist_rtag && first_index < MAX_INTERSECTIONS) {
400 map_val.tags[first_index] = rtag;
401 map_val.data[first_index] = rdata;
402 map_val.ranks[first_index] = rrank;
408 rmap.
insert({ rbuff_key[i], rbuff_value[i] });
412 for (
size_t i = 0; i < nrecv; i++) {
413 auto it = rmap.
find(rbuff_key[i]);
414 if (it != rmap.
end()) rbuff_value[i] = it->second;
421 for (
size_t i = 0; i < dsize; i++) {
422 auto it = map.find(sbuff_key[i]);
423 if (it != map.end()) it->second = ibuff_value[i];
434 template<
class K,
class V>
inline
439 MPI_Comm_size(comm, &size); MPI_Comm_rank(comm, &rank);
441 size_t dsize = map.
size();
442 vector<K> key_vec (dsize);
443 vector<V> value_vec (dsize);
448 for(
const auto & v : map) {
449 key_vec[idx] = v.first;
450 value_vec[idx] = v.second;
454 key_vec.resize(dsize);
455 value_vec.resize(dsize);
457 vector<int> perm, dest(dsize);
459 for(
size_t i=0; i<dsize; i++){
463 commgraph<size_t> grph;
464 grph.configure(dest, comm);
465 size_t nrecv =
sum(grph.rcnt);
471 vector<K> sbuff_key(dsize), rbuff_key(nrecv);
472 vector<V> sbuff_value(dsize), ibuff_value(dsize), rbuff_value(nrecv);
473 for(
size_t i=0; i<dsize; i++) {
474 sbuff_key[i] = key_vec[perm[i]];
475 sbuff_value[i] = value_vec[perm[i]];
482 for (
size_t i = 0; i < nrecv; i++) {
483 auto it = rmap.
find(rbuff_key[i]);
484 if(it != rmap.
end()) {
485 if(rbuff_value[i] != -1 and it->second == -1){
486 it->second = rbuff_value[i];
489 rmap.
insert({rbuff_key[i], rbuff_value[i]});
493 for (
size_t i = 0; i < nrecv; i++ ) {
494 auto it = rmap.
find(rbuff_key[i]);
495 if(it != rmap.
end()) {
496 if(rbuff_value[i] == -1)
497 rbuff_value[i] = it->second;
505 for (
size_t i = 0; i < dsize; i++ ) {
506 auto it = map.find(sbuff_key[i]);
507 if (it != map.end()) it->second = ibuff_value[i];
519 template<
class K,
class V>
inline
524 MPI_Comm_size(comm, &size); MPI_Comm_rank(comm, &rank);
526 size_t dsize = map.
size();
527 vector<K> key_vec (dsize);
528 vector<V> value_vec (dsize);
533 for(
const auto & v : map) {
534 key_vec[idx] = v.first;
535 value_vec[idx] = v.second;
539 key_vec.resize(dsize);
540 value_vec.resize(dsize);
542 vector<int> perm, dest(dsize);
543 for(
size_t i=0; i<dsize; i++){
547 commgraph<size_t> grph;
548 grph.configure(dest, comm);
549 size_t nrecv =
sum(grph.rcnt);
555 vector<K> sbuff_key(dsize), rbuff_key(nrecv);
556 vector<V> sbuff_value(dsize), ibuff_value(dsize), rbuff_value(nrecv);
557 for(
size_t i=0; i<dsize; i++) {
558 sbuff_key[i] = key_vec[perm[i]];
559 sbuff_value[i] = value_vec[perm[i]];
566 for (
size_t i = 0; i < nrecv; i++) {
567 auto it = rmap.
find(rbuff_key[i]);
568 if(it != rmap.
end()) {
569 if(rbuff_value[i].second != -1 and it->second.second == -1){
570 it->second = rbuff_value[i];
573 rmap.
insert({rbuff_key[i], rbuff_value[i]});
577 for (
size_t i = 0; i < nrecv; i++ ) {
578 auto it = rmap.
find(rbuff_key[i]);
579 if(it != rmap.
end()) {
580 if(rbuff_value[i].second == -1)
581 rbuff_value[i].second = it->second.second;
589 for (
size_t i = 0; i < dsize; i++ ) {
590 auto it = map.find(sbuff_key[i]);
591 if (it != map.end()) it->second = ibuff_value[i];
603 void sort_surf_local_indices(tuple<T> & ref, tuple<T> & target)
607 buff[0] = ref.v1, buff[1] = ref.v2;
610 target.v1 = buff[0], target.v2 = buff[1];
621 void sort_surf_local_indices(triple<T> & ref, triple<T> & target)
625 buff[0] = ref.v1, buff[1] = ref.v2, buff[2] = ref.v3;
628 target.v1 = buff[0], target.v2 = buff[1], target.v3 = buff[2];
639 void sort_surf_local_indices(quadruple<T> & ref, quadruple<T> & target)
643 buff[0] = ref.v1, buff[1] = ref.v2, buff[2] = ref.v3, buff[3] = ref.v4;
646 target.v1 = buff[0], target.v2 = buff[1], target.v3 = buff[2], target.v4 = buff[3];
656 template<
class K,
class V>
inline
657 void insert_surf_based_Tag(V & ref,
662 sort_surf_local_indices(ref.points, surf);
664 auto it = surfmap.find(surf);
665 if (it != surfmap.end()) {
668 if ( it->second.first.tag != ref.tag )
669 it->second.second = ref;
671 std::pair<V, V> face;
673 surfmap.insert({surf,face});
696 template<
class T,
class W,
class V,
class U>
inline
697 void insert_surf_emi(
int rank,
700 const T eidx,
const T tag,
701 const std::vector<T> & line_con,
const std::vector<T> & surf_con,
const std::vector<T> & qsurf_con,
717 for (
size_t i = 0; i < line_con.size(); i += 2) {
718 if (ptsData[line_con[i ] - 1] > 0 &&
719 ptsData[line_con[i + 1] - 1] > 0 ) {
720 line.points.v1 = ref_con[line_con[i ] - 1];
721 line.points.v2 = ref_con[line_con[i + 1] - 1];
723 insert_surf_based_Tag(line, line_face);
727 for (
size_t i = 0; i < surf_con.size(); i += 3) {
728 if (ptsData[surf_con[i ] - 1] > 0 &&
729 ptsData[surf_con[i + 1] - 1] > 0 &&
730 ptsData[surf_con[i + 2] - 1] > 0 ) {
731 face.points.v1 = ref_con[surf_con[i ] - 1];
732 face.points.v2 = ref_con[surf_con[i + 1] - 1];
733 face.points.v3 = ref_con[surf_con[i + 2] - 1];
735 insert_surf_based_Tag(face, surfmap);
739 for (
size_t i = 0; i < qsurf_con.size(); i += 4) {
740 if (ptsData[qsurf_con[i ] - 1] > 0 &&
741 ptsData[qsurf_con[i + 1] - 1] > 0 &&
742 ptsData[qsurf_con[i + 2] - 1] > 0 &&
743 ptsData[qsurf_con[i + 3] - 1] > 0) {
744 qface.points.v1 = ref_con[qsurf_con[i ] - 1];
745 qface.points.v2 = ref_con[qsurf_con[i + 1] - 1];
746 qface.points.v3 = ref_con[qsurf_con[i + 2] - 1];
747 qface.points.v4 = ref_con[qsurf_con[i + 3] - 1];
749 insert_surf_based_Tag(qface, qsurfmap);
760 template<
class T,
class V>
767 bool mark_to_take =
false;
774 struct emi_unique_face {
807 struct emi_index_rank {
823 template<
class T,
class S>
inline
824 void compute_surface_with_tags(meshdata<T,S> & mesh,
829 std::pair<emi_face<T,tuple<T>>, emi_face<T,tuple<T>>>> & line_face,
831 std::pair<emi_face<T,triple<T>>, emi_face<T,triple<T>>>> & tri_surf,
833 std::pair<emi_face<T,quadruple<T>>, emi_face<T,quadruple<T>>>> & quad_surf)
837 MPI_Comm_size(comm, &size);
838 MPI_Comm_rank(comm, &rank);
840 const T* con = mesh.con.data();
841 const T* nbr = mesh.get_numbering(numbering).data();
846 for(
size_t i=0; i<mesh.con.size(); i++){
847 g2ptsData[rnod[con[i]]] = vertex2ptsdata[rnod[con[i]]];
850 const vector<T> & ref_eidx = mesh.get_numbering(
NBR_ELEM_REF);
855 for(
size_t eidx = 0; eidx < mesh.l_numelem; eidx++) {
856 T tag = mesh.tag[eidx];
857 T size_elem = mesh.dsp[eidx+1]-mesh.dsp[eidx];
859 vector<T> dofvec(size_elem);
860 vector<T> ptsDatavec(size_elem);
862 for (
int n = mesh.dsp[eidx], i = 0; n < mesh.dsp[eidx+1];n++,i++)
864 dofvec[i] = rnod[con[n]];
865 ptsDatavec[i] = g2ptsData[rnod[con[n]]];
867 std::vector<T> surf_con ;
868 std::vector<T> qsurf_con;
869 std::vector<T> line_con;
870 switch(mesh.type[eidx]) {
911 qsurf_con = {1,2,3,4};
919 qsurf_con = {1,2,6,4,
928 qsurf_con = {1,2,3,4,
937 fprintf(stderr,
"%s error: Unsupported element in surface computation!\n", __func__);
940 insert_surf_emi(rank, dofvec, ptsDatavec, ref_eidx[eidx], mesh.tag[eidx], line_con, surf_con, qsurf_con, line_face, tri_surf, quad_surf);
944 assign_counter_face(line_face, mesh.comm);
945 assign_counter_face(tri_surf, mesh.comm);
946 assign_counter_face(quad_surf, mesh.comm);
950 for(
auto it = line_face.begin(); it != line_face.end(); ) {
951 if( it->second.second.eidx == -1 ||(extra_tags.
find(it->second.first.tag) != extra_tags.
end() && extra_tags.
find(it->second.second.tag) != extra_tags.
end()))
952 it = line_face.erase(it);
957 for(
auto it = tri_surf.begin(); it != tri_surf.end(); ) {
958 if( it->second.second.eidx == -1 ||(extra_tags.
find(it->second.first.tag) != extra_tags.
end() && extra_tags.
find(it->second.second.tag) != extra_tags.
end()))
959 it = tri_surf.erase(it);
964 for(
auto it = quad_surf.begin(); it != quad_surf.end(); ) {
965 if( it->second.second.eidx == -1 ||(extra_tags.
find(it->second.first.tag) != extra_tags.
end() && extra_tags.
find(it->second.second.tag) != extra_tags.
end()))
966 it = quad_surf.erase(it);
985 inline bool should_take_first(
int tag1,
int tag2,
989 bool tag1_is_intra = (intra_tags.
find(tag1) != intra_tags.
end());
990 bool tag2_is_intra = (intra_tags.
find(tag2) != intra_tags.
end());
991 bool tag1_is_extra = (extra_tags.
find(tag1) != extra_tags.
end());
992 bool tag2_is_extra = (extra_tags.
find(tag2) != extra_tags.
end());
995 if(tag1_is_intra && tag2_is_intra) {
1000 if(tag1_is_intra && tag2_is_extra) {
1003 if(tag2_is_intra && tag1_is_extra) {
1033 void assign_map_between_elem_oneface_and_elem_uniqueFace(
int rank,
1034 emi_unique_face <mesh_int_t> first,
1035 emi_unique_face <mesh_int_t> second,
1040 if(second.index_one==-1 && second.index_unique==-1){
1041 second.index_one = first.index_one;
1042 second.index_unique = first.index_unique;
1045 else if(first.rank != second.rank) {
1047 int our_index_one = (first.rank == rank) ? first.index_one :
1048 (second.rank == rank) ? second.index_one : -1;
1050 int owner_index_unique = (first.index_unique >= 0) ? first.index_unique :
1051 (second.index_unique >= 0) ? second.index_unique : -1;
1052 int owner_rank = (first.index_unique >= 0) ? first.rank :
1053 (second.index_unique >= 0) ? second.rank : -1;
1056 if(our_index_one >= 0 && owner_index_unique >= 0 && owner_rank >= 0 && owner_rank != rank) {
1057 map_elem_oneface_to_elem_uniqueFace[our_index_one].index = owner_index_unique;
1058 map_elem_oneface_to_elem_uniqueFace[our_index_one].rank = owner_rank;
1065 int local_index_unique = -1;
1066 emi_index_rank<mesh_int_t> value1, value2;
1068 if (first.index_unique >= 0 && first.rank == rank) {
1070 local_index_unique = first.index_unique;
1071 value1.index = first.index_one;
1072 value1.rank = first.rank;
1073 value2.index = second.index_one;
1074 value2.rank = second.rank;
1075 }
else if (second.index_unique >= 0 && second.rank == rank) {
1077 local_index_unique = second.index_unique;
1078 value1.index = second.index_one;
1079 value1.rank = second.rank;
1080 value2.index = first.index_one;
1081 value2.rank = first.rank;
1084 if (local_index_unique >= 0) {
1085 auto itr = map_elem_uniqueFace_to_elem_oneface.find(local_index_unique);
1086 if (itr == map_elem_uniqueFace_to_elem_oneface.end()) {
1087 std::pair <emi_index_rank<mesh_int_t>,emi_index_rank<mesh_int_t>> value;
1088 value = std::make_pair(value1, value2);
1089 map_elem_uniqueFace_to_elem_oneface.insert({local_index_unique, value});
1116 template <
class T,
class Key,
class Po
intsKey>
1117 inline void assign_ownership_rank_on_faces(
const Key& key,
1118 std::pair<emi_face<T, PointsKey>, emi_face<T, PointsKey>>& v,
1124 hashmap::unordered_map<Key,std::pair<emi_unique_face<mesh_int_t>, emi_unique_face<mesh_int_t>>>& unique_face_to_elements,
1127 const bool same_rank = (v.first.rank == v.second.rank);
1133 const bool first_intra = (intra_tags.
find(v.first.tag) != intra_tags.
end());
1134 const bool second_intra = (intra_tags.
find(v.second.tag) != intra_tags.
end());
1137 bool take_first_by_tags =
true;
1138 if (first_intra != second_intra) {
1139 take_first_by_tags = first_intra;
1140 }
else if (v.first.tag != v.second.tag) {
1141 take_first_by_tags = (v.first.tag < v.second.tag);
1144 take_first_by_tags = (v.first.rank <= v.second.rank);
1147 int owner_rank = take_first_by_tags ? v.first.rank : v.second.rank;
1149 const bool i_am_owner = (rank == owner_rank);
1153 auto& chosen = take_first_by_tags ? v.first : v.second;
1155 chosen.mark_to_take =
true;
1156 chosen.index_unique = lsize_unique;
1157 chosen.index_one = idx_oneface;
1159 map_elem_oneface_to_elem_uniqueFace[idx_oneface].index = lsize_unique;
1160 map_elem_oneface_to_elem_uniqueFace[idx_oneface].rank = rank;
1166 auto it = unique_face_to_elements.find(key);
1167 if (it == unique_face_to_elements.end()) {
1168 emi_unique_face<mesh_int_t> first;
1169 emi_unique_face<mesh_int_t> second;
1173 first.index_unique = lsize_unique;
1174 first.index_one = idx_oneface;
1178 second.index_unique = -1;
1179 second.index_one = -1;
1180 second.rank = same_rank ? rank : (rank == v.first.rank ? v.second.rank : v.first.rank);
1183 first.index_unique = -1;
1184 first.index_one = idx_oneface;
1187 second.index_unique = -1;
1188 second.index_one = -1;
1189 second.rank = owner_rank;
1192 unique_face_to_elements.insert({ key, std::make_pair(first, second) });
1195 auto& existing = it->second;
1198 emi_unique_face<mesh_int_t>* slot =
nullptr;
1199 if (existing.first.rank == rank || existing.first.rank < 0) {
1200 slot = &existing.first;
1201 }
else if (existing.second.rank == rank || existing.second.rank < 0) {
1202 slot = &existing.second;
1203 }
else if (existing.first.index_one == idx_oneface) {
1204 slot = &existing.first;
1205 }
else if (existing.second.index_one == idx_oneface) {
1206 slot = &existing.second;
1207 }
else if (existing.first.index_unique < 0) {
1208 slot = &existing.first;
1209 }
else if (existing.second.index_unique < 0) {
1210 slot = &existing.second;
1214 if (slot->rank < 0) slot->rank = rank;
1215 if (slot->index_one < 0) slot->index_one = idx_oneface;
1216 if (i_am_owner && slot->index_unique < 0) {
1217 slot->index_unique = lsize_unique;
1287 template<
class T,
class S>
inline
1288 void extract_face_based_tags(meshdata<T,S> & mesh,
1292 std::pair<emi_face<T,tuple<T>>, emi_face<T,tuple<T>>>> & line_face,
1294 std::pair<emi_face<T,triple<T>>, emi_face<T,triple<T>>>> & tri_face,
1296 std::pair<emi_face<T,quadruple<T>>, emi_face<T,quadruple<T>>>> & quad_face,
1299 meshdata<T,S> & surfmesh,
1300 meshdata<T,S> & surfmesh_w_counter,
1301 meshdata<T,S> & surfmesh_unique_face,
1309 surfmesh_w_counter.register_numbering(
SF::NBR_REF);
1310 surfmesh_unique_face.register_numbering(
SF::NBR_REF);
1314 compute_surface_with_tags(mesh, numbering, vertex2ptsdata, extra_tags, line_face, tri_face, quad_face);
1317 MPI_Comm_size(mesh.comm, &size);
1318 MPI_Comm_rank(mesh.comm, &rank);
1320 long int g_num_line = line_face.size();
1321 long int g_num_tri = tri_face.size();
1322 long int g_num_quad = quad_face.size();
1323 MPI_Allreduce(MPI_IN_PLACE, &g_num_line, 1, MPI_LONG, MPI_SUM, mesh.comm);
1324 MPI_Allreduce(MPI_IN_PLACE, &g_num_tri, 1, MPI_LONG, MPI_SUM, mesh.comm);
1325 MPI_Allreduce(MPI_IN_PLACE, &g_num_quad, 1, MPI_LONG, MPI_SUM, mesh.comm);
1329 long int local_extra_extra = 0;
1330 for (
const auto& [key, v] : line_face) {
1331 if (extra_tags.
find(v.first.tag) != extra_tags.
end() &&
1332 extra_tags.
find(v.second.tag) != extra_tags.
end()) {
1333 local_extra_extra++;
1336 for (
const auto& [key, v] : tri_face) {
1337 if (extra_tags.
find(v.first.tag) != extra_tags.
end() &&
1338 extra_tags.
find(v.second.tag) != extra_tags.
end()) {
1339 local_extra_extra++;
1342 for (
const auto& [key, v] : quad_face) {
1343 if (extra_tags.
find(v.first.tag) != extra_tags.
end() &&
1344 extra_tags.
find(v.second.tag) != extra_tags.
end()) {
1345 local_extra_extra++;
1348 long int global_extra_extra = 0;
1349 MPI_Allreduce(&local_extra_extra, &global_extra_extra, 1, MPI_LONG, MPI_SUM, mesh.comm);
1350 if (global_extra_extra > 0 && rank == 0) {
1351 fprintf(stderr,
"WARN: extra-extra faces detected before filtering: %ld\n", global_extra_extra);
1355 surfmesh.g_numelem = g_num_line + g_num_tri + g_num_quad;
1356 surfmesh.l_numelem = line_face.size() + tri_face.size() + quad_face.size();
1358 vector<T> cnt(surfmesh.l_numelem, 0);
1359 surfmesh.tag.resize(surfmesh.l_numelem);
1360 surfmesh.type.resize(surfmesh.l_numelem);
1361 surfmesh.con.resize(line_face.size() * 2 + tri_face.size() * 3 + quad_face.size() * 4);
1368 vector<tuple<T>> line_keys;
1369 for(
auto const& [key, val] : line_face) line_keys.push_back(key);
1370 std::sort(line_keys.begin(), line_keys.end());
1372 vector<triple<T>> tri_keys;
1373 for(
auto const& [key, val] : tri_face) tri_keys.push_back(key);
1374 std::sort(tri_keys.begin(), tri_keys.end());
1376 vector<quadruple<T>> quad_keys;
1377 for(
auto const& [key, val] : quad_face) quad_keys.push_back(key);
1378 std::sort(quad_keys.begin(), quad_keys.end());
1403 for(
auto const& key : line_keys) {
1404 auto& v = line_face.
at(key);
1405 const bool local_involved = (v.first.rank == rank) || (v.second.rank == rank);
1406 if (!local_involved) {
1412 if ((intra_tags.
find(v.first.tag) != intra_tags.
end()) && (intra_tags.
find(v.second.tag) != intra_tags.
end())) {
1418 emi_face<T,tuple<T>> surf_neighbor =
1419 (v.first.rank == rank) ? v.first : v.second;
1421 surfmesh.type[idx] =
Line;
1422 surfmesh.tag[idx] = surf_neighbor.tag;
1423 surfmesh.con[cidx + 0] = surf_neighbor.points.v1;
1424 surfmesh.con[cidx + 1] = surf_neighbor.points.v2;
1427 if(v.first.rank == v.second.rank)
1432 assign_ownership_rank_on_faces<T, tuple<T>, tuple<T>>( key, v, rank,
1435 extra_tags, intra_tags,
1436 line_unique_face_to_elements,
1437 map_elem_oneface_to_elem_uniqueFace);
1442 for(
auto const& key : tri_keys) {
1443 auto& v = tri_face.at(key);
1444 const bool local_involved = (v.first.rank == rank) || (v.second.rank == rank);
1445 if (!local_involved) {
1450 if ((intra_tags.
find(v.first.tag) != intra_tags.
end()) && (intra_tags.
find(v.second.tag) != intra_tags.
end())) {
1456 emi_face<T,triple<T>> surf_neighbor =
1457 (v.first.rank == rank) ? v.first : v.second;
1459 surfmesh.type[idx] =
Tri;
1460 surfmesh.tag[idx] = surf_neighbor.tag;
1461 surfmesh.con[cidx + 0] = surf_neighbor.points.v1;
1462 surfmesh.con[cidx + 1] = surf_neighbor.points.v2;
1463 surfmesh.con[cidx + 2] = surf_neighbor.points.v3;
1466 if(v.first.rank == v.second.rank)
1471 assign_ownership_rank_on_faces<T, triple<T>, triple<T>>( key, v, rank,
1474 extra_tags, intra_tags,
1475 tri_unique_face_to_elements,
1476 map_elem_oneface_to_elem_uniqueFace);
1481 for(
auto const& key : quad_keys) {
1482 auto& v = quad_face.at(key);
1483 const bool local_involved = (v.first.rank == rank) || (v.second.rank == rank);
1484 if (!local_involved) {
1489 if ((intra_tags.
find(v.first.tag) != intra_tags.
end()) && (intra_tags.
find(v.second.tag) != intra_tags.
end())) {
1495 emi_face<T,quadruple<T>> qsurf_neighbor =
1496 (v.first.rank == rank) ? v.first : v.second;
1498 surfmesh.type[idx] =
Quad;
1499 surfmesh.tag[idx] = qsurf_neighbor.tag;
1500 surfmesh.con[cidx + 0] = qsurf_neighbor.points.v1;
1501 surfmesh.con[cidx + 1] = qsurf_neighbor.points.v2;
1502 surfmesh.con[cidx + 2] = qsurf_neighbor.points.v3;
1503 surfmesh.con[cidx + 3] = qsurf_neighbor.points.v4;
1506 if(v.first.rank == v.second.rank)
1511 assign_ownership_rank_on_faces<T, quadruple<T>, quadruple<T>>( key, v, rank,
1514 extra_tags, intra_tags,
1515 quad_unique_face_to_elements,
1516 map_elem_oneface_to_elem_uniqueFace);
1521 surfmesh.l_numelem = idx;
1522 surfmesh.tag.resize(idx);
1523 surfmesh.type.resize(idx);
1526 surfmesh.con.resize(cidx);
1528 long int g_num_surf = surfmesh.l_numelem;
1529 MPI_Allreduce(MPI_IN_PLACE, &g_num_surf, 1, MPI_LONG, MPI_SUM, mesh.comm);
1530 surfmesh.g_numelem = g_num_surf;
1533 std::cout <<
"surfmesh.g_numelem: " << surfmesh.g_numelem <<std::endl;
1534 std::cout <<
"surfmesh.l_numelem: " << surfmesh.l_numelem <<std::endl;
1538 long int g_num_w_counter_line = lsize_line;
1539 long int g_num_w_counter_tri = lsize_tri;
1540 long int g_num_w_counter_quad = lsize_quad;
1542 MPI_Allreduce(MPI_IN_PLACE, &g_num_w_counter_line, 1, MPI_LONG, MPI_SUM,
SF_COMM);
1543 MPI_Allreduce(MPI_IN_PLACE, &g_num_w_counter_tri, 1, MPI_LONG, MPI_SUM,
SF_COMM);
1544 MPI_Allreduce(MPI_IN_PLACE, &g_num_w_counter_quad, 1, MPI_LONG, MPI_SUM,
SF_COMM);
1547 surfmesh_w_counter.g_numelem = g_num_w_counter_line+g_num_w_counter_tri+g_num_w_counter_quad;
1548 surfmesh_w_counter.l_numelem = lsize_line + lsize_tri + lsize_quad;
1550 surfmesh_w_counter.tag.resize(surfmesh_w_counter.l_numelem);
1551 surfmesh_w_counter.type.resize(surfmesh_w_counter.l_numelem);
1552 surfmesh_w_counter.con.resize(lsize_line * 2 + lsize_tri * 3 + lsize_quad * 4);
1555 std::cout <<
"surfmesh_w_counter.g_numelem: " << surfmesh_w_counter.g_numelem <<std::endl;
1556 std::cout <<
"surfmesh_w_counter.l_numelem: " << surfmesh_w_counter.l_numelem <<std::endl;
1561 long int g_num_w_unique_line = lsize_unique_line;
1562 long int g_num_w_unique_tri = lsize_unique_tri;
1563 long int g_num_w_unique_quad = lsize_unique_quad;
1565 MPI_Allreduce(MPI_IN_PLACE, &g_num_w_unique_line, 1, MPI_LONG, MPI_SUM,
SF_COMM);
1566 MPI_Allreduce(MPI_IN_PLACE, &g_num_w_unique_tri, 1, MPI_LONG, MPI_SUM,
SF_COMM);
1567 MPI_Allreduce(MPI_IN_PLACE, &g_num_w_unique_quad, 1, MPI_LONG, MPI_SUM,
SF_COMM);
1570 surfmesh_unique_face.g_numelem = g_num_w_unique_line+g_num_w_unique_tri+g_num_w_unique_quad;
1571 surfmesh_unique_face.l_numelem = lsize_unique_line + lsize_unique_tri + lsize_unique_quad;
1573 surfmesh_unique_face.tag.resize(surfmesh_unique_face.l_numelem);
1574 surfmesh_unique_face.type.resize(surfmesh_unique_face.l_numelem);
1575 surfmesh_unique_face.con.resize(lsize_unique_line * 2 + lsize_unique_tri * 3 + lsize_unique_quad * 4);
1578 std::cout <<
"surfmesh_unique_face.g_numelem: " << surfmesh_unique_face.g_numelem <<std::endl;
1579 std::cout <<
"surfmesh_unique_face.l_numelem: " << surfmesh_unique_face.l_numelem <<std::endl;
1591 #ifdef EMI_DEBUG_MESH
1593 fprintf(stderr,
"RANK %d BEFORE exchange: line_hash=%zu, tri_hash=%zu, quad_hash=%zu (expected unique total=%ld)\n",
1594 rank, line_unique_face_to_elements.
size(), tri_unique_face_to_elements.
size(),
1595 quad_unique_face_to_elements.
size(), lsize_unique_line + lsize_unique_tri + lsize_unique_quad);
1603 assign_unique_first_face(line_unique_face_to_elements, mesh.comm);
1604 assign_unique_first_face(tri_unique_face_to_elements, mesh.comm);
1605 assign_unique_first_face(quad_unique_face_to_elements, mesh.comm);
1609 #ifdef EMI_DEBUG_MESH
1611 int valid_line = 0, valid_tri = 0, valid_quad = 0;
1612 for (
const auto& [key, val] : line_unique_face_to_elements) {
1613 if (val.first.index_unique >= 0 || val.second.index_unique >= 0) valid_line++;
1615 for (
const auto& [key, val] : tri_unique_face_to_elements) {
1616 if (val.first.index_unique >= 0 || val.second.index_unique >= 0) valid_tri++;
1618 for (
const auto& [key, val] : quad_unique_face_to_elements) {
1619 if (val.first.index_unique >= 0 || val.second.index_unique >= 0) valid_quad++;
1621 fprintf(stderr,
"RANK %d AFTER exchange: line_hash=%zu, tri_hash=%zu, quad_hash=%zu\n",
1622 rank, line_unique_face_to_elements.size(), tri_unique_face_to_elements.size(),
1623 quad_unique_face_to_elements.size());
1624 fprintf(stderr,
"RANK %d VALID entries (index_unique>=0): line=%d, tri=%d, quad=%d\n",
1625 rank, valid_line, valid_tri, valid_quad);
1633 for(
auto it = line_unique_face_to_elements.begin(); it != line_unique_face_to_elements.end(); ++it) {
1635 auto& first = it->second.first;
1636 auto& second = it->second.second;
1638 assign_map_between_elem_oneface_and_elem_uniqueFace(rank, first, second, map_elem_uniqueFace_to_elem_oneface, map_elem_oneface_to_elem_uniqueFace);
1641 for(
auto it = tri_unique_face_to_elements.begin(); it != tri_unique_face_to_elements.end(); ++it) {
1642 auto& first = it->second.first;
1643 auto& second = it->second.second;
1645 assign_map_between_elem_oneface_and_elem_uniqueFace(rank, first, second, map_elem_uniqueFace_to_elem_oneface, map_elem_oneface_to_elem_uniqueFace);
1648 for(
auto it = quad_unique_face_to_elements.begin(); it != quad_unique_face_to_elements.end(); ++it) {
1649 auto& first = it->second.first;
1650 auto& second = it->second.second;
1652 assign_map_between_elem_oneface_and_elem_uniqueFace(rank, first, second, map_elem_uniqueFace_to_elem_oneface, map_elem_oneface_to_elem_uniqueFace);
1665 template<
class T>
inline
1667 std::pair<emi_face<T,tuple<T>>, emi_face<T,tuple<T>>>> & line_face,
1669 std::pair<emi_face<T,triple<T>>, emi_face<T,triple<T>>>> & tri_face,
1671 std::pair<emi_face<T,quadruple<T>>, emi_face<T,quadruple<T>>>> & quad_face,
1677 MPI_Comm_size(comm, &size);
1678 MPI_Comm_rank(comm, &rank);
1681 for(
const auto & v : line_face) {
1684 if(v.second.first.rank == v.second.second.rank){
1688 emi_face<T,tuple<T>> surf_neighbor =
1689 (v.second.first.rank != rank) ? v.second.first : v.second.second;
1692 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
1693 Index_tag_old = std::make_pair(surf_neighbor.points.v1,surf_neighbor.tag);
1694 map_vertex_tag_to_dof.insert({Index_tag_old,-1});
1698 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
1699 Index_tag_old = std::make_pair(surf_neighbor.points.v2,surf_neighbor.tag);
1700 map_vertex_tag_to_dof.insert({Index_tag_old,-1});
1705 for(
const auto & v : tri_face) {
1708 if(v.second.first.rank == v.second.second.rank){
1712 emi_face<T,triple<T>> surf_neighbor =
1713 (v.second.first.rank != rank) ? v.second.first : v.second.second;
1716 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
1717 Index_tag_old = std::make_pair(surf_neighbor.points.v1,surf_neighbor.tag);
1718 map_vertex_tag_to_dof.insert({Index_tag_old,-1});
1722 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
1723 Index_tag_old = std::make_pair(surf_neighbor.points.v2,surf_neighbor.tag);
1724 map_vertex_tag_to_dof.insert({Index_tag_old,-1});
1728 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
1729 Index_tag_old = std::make_pair(surf_neighbor.points.v3,surf_neighbor.tag);
1730 map_vertex_tag_to_dof.insert({Index_tag_old,-1});
1735 for(
const auto & v : quad_face) {
1738 if(v.second.first.rank == v.second.second.rank){
1742 emi_face<T,quadruple<T>> qsurf_neighbor =
1743 (v.second.first.rank != rank) ? v.second.first : v.second.second;
1746 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
1747 Index_tag_old = std::make_pair(qsurf_neighbor.points.v1,qsurf_neighbor.tag);
1748 map_vertex_tag_to_dof.insert({Index_tag_old,-1});
1752 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
1753 Index_tag_old = std::make_pair(qsurf_neighbor.points.v2,qsurf_neighbor.tag);
1754 map_vertex_tag_to_dof.insert({Index_tag_old,-1});
1758 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
1759 Index_tag_old = std::make_pair(qsurf_neighbor.points.v3,qsurf_neighbor.tag);
1760 map_vertex_tag_to_dof.insert({Index_tag_old,-1});
1764 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
1765 Index_tag_old = std::make_pair(qsurf_neighbor.points.v4,qsurf_neighbor.tag);
1766 map_vertex_tag_to_dof.insert({Index_tag_old,-1});
1771 assign_dof_on_counter_face(map_vertex_tag_to_dof,comm);
1803 template<
class T,
class S>
inline
1804 void compute_map_vertex_to_dof(meshdata<T,S> & mesh,
1811 MPI_Comm comm = mesh.comm;
1813 MPI_Comm_size(comm, &size);
1814 MPI_Comm_rank(comm, &rank);
1818 const T* con = mesh.con.data();
1819 const T* nbr = mesh.get_numbering(numbering).data();
1824 for(
size_t i=0; i<mesh.con.size(); i++)
1826 g2ptsData[rnod[con[i]]] = vertex2ptsdata[rnod[con[i]]];
1838 for(
size_t eidx = 0; eidx < mesh.l_numelem; eidx++)
1840 T tag = mesh.tag[eidx];
1841 auto pos_extra = extra_tags.
find(tag);
1842 for (
int n = mesh.dsp[eidx]; n < mesh.dsp[eidx+1];n++)
1844 T gIndex = rnod[con[n]];
1845 T data_on_gIndex = g2ptsData[rnod[con[n]]];
1849 if((pos_extra != extra_tags.
end()) || data_on_gIndex==0){
1850 std::pair <mesh_int_t,mesh_int_t> Index_tag_old = std::make_pair(gIndex,tag);
1851 if (map_vertex_tag_to_dof.find(Index_tag_old) == map_vertex_tag_to_dof.end() )
1853 map_vertex_tag_to_dof.insert({Index_tag_old,gIndex});
1858 auto it = map_vertex_to_tags_data_ranks.
find(gIndex);
1859 if (it != map_vertex_to_tags_data_ranks.
end() )
1861 intersection_data& value = it->second;
1862 bool check_tag_rank =
true;
1863 for(
int i=0; i<MAX_INTERSECTIONS; ++i) {
1864 if(value.tags[i] == tag && value.ranks[i] == rank) {
1865 check_tag_rank =
false;
1872 for(
int i=0; i<MAX_INTERSECTIONS; ++i) {
1873 if(value.tags[i] == -1 && value.ranks[i] == -1) {
1874 value.tags[i] = tag;
1875 value.data[i] = data_on_gIndex;
1876 value.ranks[i] = rank;
1885 intersection_data value;
1886 value.tags[0] = tag;
1887 value.data[0] = data_on_gIndex;
1888 value.ranks[0] = rank;
1889 map_vertex_to_tags_data_ranks.
insert({gIndex,value});
1905 assign_counter_vertices_tuple(map_vertex_to_tags_data_ranks, comm);
1922 for(
const auto & key : map_vertex_to_tags_data_ranks)
1924 T gIndex = key.first;
1925 const intersection_data& value = key.second;
1926 T data_on_gIndex = g2ptsData[gIndex];
1929 int first_index = 0;
1930 for (
int i = 0; i < MAX_INTERSECTIONS; ++i) {
1931 if(value.tags[i] == -1 && value.ranks[i] == -1) {
1936 if(value.data[i]!=data_on_gIndex)
1940 "WARN: Due to an inconsistency in ptsData computation at gIndex %d with tag %d, "
1941 "the program is stopped while preparing the data structure to introduce DOFs.\n",
1942 gIndex, value.tags[i]);
1943 fprintf(stderr,
"\n");
1947 if (i == MAX_INTERSECTIONS -1) first_index = MAX_INTERSECTIONS;
1950 if(data_on_gIndex==1){
1952 int count_intra_tags = 0;
1953 int count_extra_tags = 0;
1954 for (
int i = 0; i < first_index; ++i) {
1955 if(value.tags[i]!=-1 && extra_tags.
find(value.tags[i])==extra_tags.
end()){
1956 count_intra_tags += 1;
1957 }
else if(value.tags[i]!=-1 && extra_tags.
find(value.tags[i])!=extra_tags.
end()){
1958 count_extra_tags += 1;
1964 if(count_intra_tags>1 || count_extra_tags == 0)
1968 "WARN: Due to an issue in defining ptsData for gIndex %d, , on the membrane"
1969 "the program is stopped while preparing the data structure to introduce DOFs.\n",
1971 fprintf(stderr,
"\n");
1975 int index_intra = -1;
1977 for (
int i = 0; i < first_index; ++i) {
1978 if(value.tags[i]!=-1 && extra_tags.
find(value.tags[i])==extra_tags.
end()){
1983 if(index_intra == -1) {
1984 fprintf(stderr,
"WARN: unhandled case in membrane while decoupling: gIndex %d", gIndex);
1985 fprintf(stderr,
"\n");
1988 if(index_intra != -1) {
1989 T tag_myocyte = value.tags[index_intra];
1990 T rank_myocyte = value.ranks[index_intra];
1992 if(rank_myocyte == rank) {
1993 std::pair <mesh_int_t,mesh_int_t> Index_tag_next = std::make_pair(gIndex,tag_myocyte);
1994 if (map_mark_new_dofs.
find(Index_tag_next) == map_mark_new_dofs.
end()) {
1995 map_mark_new_dofs.
insert({Index_tag_next,
true});
2001 else if(data_on_gIndex==2){
2003 int count_intra_tags = 0;
2004 int count_extra_tags = 0;
2005 for (
int i = 0; i < first_index; ++i) {
2006 if(value.tags[i]!=-1 && extra_tags.
find(value.tags[i])==extra_tags.
end()){
2007 count_intra_tags += 1;
2008 }
else if(value.tags[i]!=-1 && extra_tags.
find(value.tags[i])!=extra_tags.
end()){
2009 count_extra_tags += 1;
2012 if(count_intra_tags!=2 || count_extra_tags != 0){
2015 "WARN: Due to an issue in defining ptsData for gIndex %d, on the gapjunction"
2016 "the program is stopped while preparing the data structure to introduce DOFs.\n",
2018 fprintf(stderr,
"\n");
2026 bool tag1_checked =
false;
2027 bool tag2_checked =
false;
2029 for (
int i = 0; i < first_index; ++i)
2031 auto pos_extra = extra_tags.
find(value.tags[i]);
2032 if(pos_extra == extra_tags.
end()) {
2034 tag1 = value.tags[i];
2035 rank1 = value.ranks[i];
2036 tag1_checked =
true;
2038 tag2 = value.tags[i];
2039 rank2 = value.ranks[i];
2040 tag2_checked =
true;
2046 if(!tag1_checked && !tag2_checked || (rank1==rank2 && rank1!=rank) ) {
2047 fprintf(stderr,
"WARN: unhandled case in gap junction while decoupling: gIndex %d with tags %d:%d ", gIndex, tag1, tag2);
2048 fprintf(stderr,
"\n");
2052 if(rank1==rank2 && (rank1 == rank)){
2053 T smallest_tag = tag1 < tag2? tag1:tag2;
2054 std::pair <mesh_int_t,mesh_int_t> Index_tag_old = std::make_pair(gIndex,smallest_tag);
2055 if (map_vertex_tag_to_dof.find(Index_tag_old) == map_vertex_tag_to_dof.end() ) {
2056 map_vertex_tag_to_dof.insert({Index_tag_old,gIndex});
2059 T bigger_tag = tag1 < tag2? tag2:tag1;
2060 std::pair <mesh_int_t,mesh_int_t> Index_tag_new = std::make_pair(gIndex,bigger_tag);
2061 if (map_mark_new_dofs.
find(Index_tag_new) == map_mark_new_dofs.
end() ) {
2062 map_mark_new_dofs.
insert({Index_tag_new,
true});
2066 else if(rank1!=rank2 && (rank1 == rank)) {
2068 std::pair <mesh_int_t,mesh_int_t> Index_tag_old = std::make_pair(gIndex,tag1);
2069 if (map_vertex_tag_to_dof.find(Index_tag_old) == map_vertex_tag_to_dof.end() ) {
2070 map_vertex_tag_to_dof.insert({Index_tag_old,gIndex});
2073 std::pair <mesh_int_t,mesh_int_t> Index_tag_new = std::make_pair(gIndex,tag1);
2074 if (map_mark_new_dofs.
find(Index_tag_new) == map_mark_new_dofs.
end() ) {
2075 map_mark_new_dofs.
insert({Index_tag_new,
true});
2080 else if(rank1!=rank2 && (rank2 == rank)) {
2082 std::pair <mesh_int_t,mesh_int_t> Index_tag_old = std::make_pair(gIndex,tag2);
2083 if (map_vertex_tag_to_dof.find(Index_tag_old) == map_vertex_tag_to_dof.end() ) {
2084 map_vertex_tag_to_dof.insert({Index_tag_old,gIndex});
2087 std::pair <mesh_int_t,mesh_int_t> Index_tag_new = std::make_pair(gIndex,tag2);
2088 if (map_mark_new_dofs.
find(Index_tag_new) == map_mark_new_dofs.
end() ) {
2089 map_mark_new_dofs.
insert({Index_tag_new,
true});
2095 else if(data_on_gIndex==3)
2098 int count_intra_tags = 0;
2099 int count_extra_tags = 0;
2100 for (
int i = 0; i < first_index; ++i) {
2101 if(value.tags[i]!=-1 && extra_tags.
find(value.tags[i])==extra_tags.
end()){
2102 count_intra_tags += 1;
2103 }
else if(value.tags[i]!=-1 && extra_tags.
find(value.tags[i])!=extra_tags.
end()){
2104 count_extra_tags += 1;
2107 if(count_intra_tags!=2 || count_extra_tags == 0){
2110 "WARN: Due to an issue in defining ptsData for gIndex %d, on intersection between membrane and gapjunction"
2111 "the program is stopped while preparing the data structure to introduce DOFs.\n",
2113 fprintf(stderr,
"\n");
2119 for (
int i = 0; i < first_index; ++i) {
2121 auto pos_extra = extra_tags.
find(value.tags[i]);
2122 if(value.tags[i]!=-1 && value.ranks[i] == rank && pos_extra == extra_tags.
end()) {
2123 std::pair <mesh_int_t,mesh_int_t> Index_tag_new = std::make_pair(gIndex,value.tags[i]);
2124 if (map_mark_new_dofs.
find(Index_tag_new) == map_mark_new_dofs.
end() )
2126 map_mark_new_dofs.
insert({Index_tag_new,
true});
2134 vector<size_t> dsp_dof(size);
2135 MPI_Allgather(&shift,
sizeof(
size_t), MPI_BYTE, dsp_dof.data(),
sizeof(
size_t), MPI_BYTE, comm);
2150 start = mesh.g_numpts;
2154 start = mesh.g_numpts;
2155 for (
int r = 0; r < rank; ++r)
2162 auto lexicographic_comp_pair = [](
const std::pair<mesh_int_t,mesh_int_t> & a,
const std::pair<mesh_int_t,mesh_int_t> & b)
2164 if (a.second == b.second)
return a.first < b.first;
2165 return a.second < b.second;
2168 map_mark_new_dofs.
sort(lexicographic_comp_pair);
2170 for(
const auto & entry : map_mark_new_dofs)
2172 T newIndex = start+
count;
2173 map_vertex_tag_to_dof.insert({entry.first,newIndex});
2184 template<
class K,
class intersection_indices>
inline
2187 size_t dsize = map.
size();
2188 vector<K> key_vec(dsize);
2189 vector<intersection_indices> value_vec(dsize);
2190 intersection_indices indices;
2192 for (
const auto& v : map) {
2193 key_vec[idx] = v.first;
2194 value_vec[idx] = v.second;
2199 MPI_Comm_size(comm, &size); MPI_Comm_rank(comm, &rank);
2201 vector<int> perm, dest(dsize);
2202 for (
size_t i = 0; i < dsize; i++)
2205 commgraph<size_t> grph;
2206 grph.configure(dest, comm);
2207 size_t nrecv =
sum(grph.rcnt);
2213 vector<K> sbuff_key(dsize), rbuff_key(nrecv);
2214 vector<intersection_indices> sbuff_value(dsize), ibuff_value(dsize), rbuff_value(nrecv);
2215 for (
size_t i = 0; i < dsize; i++) {
2216 sbuff_key[i] = key_vec[perm[i]];
2217 sbuff_value[i] = value_vec[perm[i]];
2223 for (
size_t i = 0; i < nrecv; i++)
2225 auto it = rmap.
find(rbuff_key[i]);
2226 if (it != rmap.
end())
2228 intersection_indices& map_indices = it->second;
2229 intersection_indices& r_indices = rbuff_value[i];
2231 for (
int r_indices : r_indices.indices)
2233 if (r_indices == -1)
continue;
2235 for (
int m_index : map_indices.indices)
2237 if (m_index == r_indices) {
2244 for (
size_t k = 0; k < MAX_INTERSECTIONS; ++k) {
2245 if (map_indices.indices[k] == -1) {
2246 map_indices.indices[k] = r_indices;
2255 rmap.
insert({ rbuff_key[i], rbuff_value[i] });
2259 for (
size_t i = 0; i < nrecv; i++) {
2260 auto it = rmap.
find(rbuff_key[i]);
2261 if (it != rmap.
end()) rbuff_value[i] = it->second;
2268 for (
size_t i = 0; i < dsize; i++) {
2269 auto it = map.find(sbuff_key[i]);
2270 if (it != map.end()) it->second = ibuff_value[i];
2283 template<
class T,
class S>
inline
2284 void update_emi_mesh_with_dofs(meshdata<T,S> & mesh,
2292 MPI_Comm comm = mesh.comm;
2293 mesh.globalize(numbering);
2294 for(
size_t eidx = 0; eidx < mesh.l_numelem; eidx++) {
2295 T tag = mesh.tag[eidx];
2296 T size_elem = mesh.dsp[eidx+1]-mesh.dsp[eidx];
2298 for (
int n = mesh.dsp[eidx]; n < mesh.dsp[eidx+1];n++)
2300 T gIndex = mesh.con[n];
2302 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
2303 Index_tag_old = std::make_pair(gIndex,tag);
2305 auto it_new = map_vertex_tag_to_dof.find(Index_tag_old);
2306 if (it_new != map_vertex_tag_to_dof.end() )
2309 dof2vertex.
insert({dof_new, gIndex});
2310 mesh.con[n] = dof_new;
2312 auto it = vertex2dof.
find(gIndex);
2313 if (it != vertex2dof.
end())
2315 intersection_indices& indices = it->second;
2317 for(T t : indices.indices) {
2325 for(
size_t i=0; i<MAX_INTERSECTIONS; ++i) {
2326 if(indices.indices[i] == -1) {
2327 indices.indices[i] = dof_new;
2333 intersection_indices indices;
2334 indices.indices[0] = dof_new;
2335 vertex2dof.
insert({gIndex,indices});
2341 assign_counter_dofs(vertex2dof, comm);
2344 for (
const auto& [old_idx, indices] : vertex2dof) {
2345 for (
int new_idx : indices.indices) {
2346 if (new_idx != -1) {
2348 if (dof2vertex.
find(new_idx) == dof2vertex.
end()) {
2349 dof2vertex.
insert({new_idx, old_idx});
2355 mesh.localize(numbering);
2369 template<
class T,
class S>
inline
2370 void update_map_indices_to_petsc(meshdata<T,S> & mesh,
2371 const SF_nbr numbering_ref,
const SF_nbr numbering_petsc,
2374 std::pair<mesh_int_t,mesh_int_t>> & map_vertex_tag_to_dof_petsc,
2381 elemTag_emi_mesh.
resize(mesh.l_numelem);
2382 for(
size_t eidx = 0; eidx < mesh.l_numelem; eidx++) {
2383 T tag = mesh.tag[eidx];
2384 elemTag_emi_mesh[eidx] = 1;
2385 if(extra_tags.
find(tag) == extra_tags.
end())
2386 elemTag_emi_mesh[eidx] = 2;
2387 for (
int n = mesh.dsp[eidx]; n < mesh.dsp[eidx+1];n++)
2389 T l_Indx = mesh.con[n];
2390 T petsc_Idx = petsc_nbr[l_Indx];
2391 T n_Indx = ref_nbr[l_Indx];
2392 T o_Indx = dof2vertex[n_Indx];
2394 std::pair <mesh_int_t,mesh_int_t> oIndx_tag;
2395 oIndx_tag = std::make_pair(o_Indx,tag);
2397 auto it_new = map_vertex_tag_to_dof_petsc.find(oIndx_tag);
2398 if (it_new != map_vertex_tag_to_dof_petsc.end() )
2400 std::pair <mesh_int_t,mesh_int_t> nIndx_petsc;
2401 nIndx_petsc = std::make_pair(n_Indx,petsc_Idx);
2403 (*it_new).second = nIndx_petsc;
2421 template<
class T,
class S>
2422 inline void update_faces_on_surface_mesh_after_decoupling_with_dofs(meshdata<T, S> & mesh,
2426 std::pair<emi_face<T,tuple<T>>, emi_face<T,tuple<T>>>> & line_face,
2428 std::pair<emi_face<T,triple<T>>, emi_face<T,triple<T>>>> & tri_face,
2430 std::pair<emi_face<T,quadruple<T>>, emi_face<T,quadruple<T>>>> & quad_face)
2434 MPI_Comm_size(comm, &size); MPI_Comm_rank(comm, &rank);
2441 for(
size_t i=0; i<idxbuff.size(); i++){
2442 g2l[idxbuff[i]] = i;
2443 l2g[i] = idxbuff[i];
2446 for(
size_t eidx = 0; eidx < mesh.l_numelem; eidx++) {
2447 T tag = mesh.tag[eidx];
2448 T size_elem = mesh.dsp[eidx+1]-mesh.dsp[eidx];
2449 std::vector<int> elem_nodes;
2450 for (
int n = mesh.dsp[eidx]; n < mesh.dsp[eidx+1];n++)
2452 T gIndex = mesh.con[n];
2453 elem_nodes.push_back(gIndex);
2455 std::sort(elem_nodes.begin(),elem_nodes.end());
2456 if(elem_nodes.size()==2){
2458 key.v1 = elem_nodes[0];
2459 key.v2 = elem_nodes[1];
2460 std::pair<emi_face<T,tuple<T>>, emi_face<T,tuple<T>>> value = line_face[key];
2462 line_face.erase(key);
2463 std::vector<int> new_nodes(2);
2465 auto tag_key = (value.first.rank == rank) ? value.first.tag : value.second.tag;
2467 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
2468 Index_tag_old = std::make_pair(elem_nodes[0],tag_key);
2469 mesh_int_t Index_new = map_vertex_tag_to_dof[Index_tag_old];
2470 new_nodes[0] = Index_new;
2473 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
2474 Index_tag_old = std::make_pair(elem_nodes[1],tag_key);
2475 mesh_int_t Index_new = map_vertex_tag_to_dof[Index_tag_old];
2476 new_nodes[1] = Index_new;
2478 std::sort(new_nodes.begin(),new_nodes.end());
2481 new_key.v1 = new_nodes[0];
2482 new_key.v2 = new_nodes[1];
2486 mesh_int_t Index_new1 = map_vertex_tag_to_dof[std::make_pair(value.first.points.v1, value.first.tag)];
2487 mesh_int_t Index_new2 = map_vertex_tag_to_dof[std::make_pair(value.first.points.v2, value.first.tag)];
2488 value.first.points.v1 = Index_new1;
2489 value.first.points.v2 = Index_new2;
2493 mesh_int_t Index_new1 = map_vertex_tag_to_dof[std::make_pair(value.second.points.v1, value.second.tag)];
2494 mesh_int_t Index_new2 = map_vertex_tag_to_dof[std::make_pair(value.second.points.v2, value.second.tag)];
2495 value.second.points.v1 = Index_new1;
2496 value.second.points.v2 = Index_new2;
2498 line_face.insert({new_key,value});
2500 if(elem_nodes.size()==3){
2502 key.v1 = elem_nodes[0];
2503 key.v2 = elem_nodes[1];
2504 key.v3 = elem_nodes[2];
2505 std::pair<emi_face<T,triple<T>>, emi_face<T,triple<T>>> value = tri_face[key];
2506 tri_face.erase(key);
2507 std::vector<int> new_nodes(3);
2509 auto tag_key = (value.first.rank == rank) ? value.first.tag : value.second.tag;
2511 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
2512 Index_tag_old = std::make_pair(elem_nodes[0],tag_key);
2513 mesh_int_t Index_new = map_vertex_tag_to_dof[Index_tag_old];
2514 new_nodes[0] = Index_new;
2517 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
2518 Index_tag_old = std::make_pair(elem_nodes[1],tag_key);
2519 mesh_int_t Index_new = map_vertex_tag_to_dof[Index_tag_old];
2520 new_nodes[1] = Index_new;
2523 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
2524 Index_tag_old = std::make_pair(elem_nodes[2],tag_key);
2525 mesh_int_t Index_new = map_vertex_tag_to_dof[Index_tag_old];
2526 new_nodes[2] = Index_new;
2528 std::sort(new_nodes.begin(),new_nodes.end());
2531 new_key.v1 = new_nodes[0];
2532 new_key.v2 = new_nodes[1];
2533 new_key.v3 = new_nodes[2];
2537 mesh_int_t Index_new1 = map_vertex_tag_to_dof[std::make_pair(value.first.points.v1, value.first.tag)];
2538 mesh_int_t Index_new2 = map_vertex_tag_to_dof[std::make_pair(value.first.points.v2, value.first.tag)];
2539 mesh_int_t Index_new3 = map_vertex_tag_to_dof[std::make_pair(value.first.points.v3, value.first.tag)];
2540 value.first.points.v1 = Index_new1;
2541 value.first.points.v2 = Index_new2;
2542 value.first.points.v3 = Index_new3;
2546 mesh_int_t Index_new1 = map_vertex_tag_to_dof[std::make_pair(value.second.points.v1, value.second.tag)];
2547 mesh_int_t Index_new2 = map_vertex_tag_to_dof[std::make_pair(value.second.points.v2, value.second.tag)];
2548 mesh_int_t Index_new3 = map_vertex_tag_to_dof[std::make_pair(value.second.points.v3, value.second.tag)];
2549 value.second.points.v1 = Index_new1;
2550 value.second.points.v2 = Index_new2;
2551 value.second.points.v3 = Index_new3;
2553 tri_face.insert({new_key,value});
2555 if(elem_nodes.size()==4){
2557 key.v1 = elem_nodes[0];
2558 key.v2 = elem_nodes[1];
2559 key.v3 = elem_nodes[2];
2560 key.v4 = elem_nodes[3];
2561 std::pair<emi_face<T,quadruple<T>>, emi_face<T,quadruple<T>>> value = quad_face[key];
2562 quad_face.erase(key);
2563 std::vector<int> new_nodes(4);
2565 auto tag_key = (value.first.rank == rank) ? value.first.tag : value.second.tag;
2567 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
2568 Index_tag_old = std::make_pair(elem_nodes[0],tag_key);
2569 mesh_int_t Index_new = map_vertex_tag_to_dof[Index_tag_old];
2570 new_nodes[0] = Index_new;
2573 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
2574 Index_tag_old = std::make_pair(elem_nodes[1],tag_key);
2575 mesh_int_t Index_new = map_vertex_tag_to_dof[Index_tag_old];
2576 new_nodes[1] = Index_new;
2579 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
2580 Index_tag_old = std::make_pair(elem_nodes[2],tag_key);
2581 mesh_int_t Index_new = map_vertex_tag_to_dof[Index_tag_old];
2582 new_nodes[2] = Index_new;
2585 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
2586 Index_tag_old = std::make_pair(elem_nodes[3],tag_key);
2587 mesh_int_t Index_new = map_vertex_tag_to_dof[Index_tag_old];
2588 new_nodes[3] = Index_new;
2590 std::sort(new_nodes.begin(),new_nodes.end());
2592 quadruple<T> new_key;
2593 new_key.v1 = new_nodes[0];
2594 new_key.v2 = new_nodes[1];
2595 new_key.v3 = new_nodes[2];
2596 new_key.v4 = new_nodes[3];
2600 mesh_int_t Index_new1 = map_vertex_tag_to_dof[std::make_pair(value.first.points.v1, value.first.tag)];
2601 mesh_int_t Index_new2 = map_vertex_tag_to_dof[std::make_pair(value.first.points.v2, value.first.tag)];
2602 mesh_int_t Index_new3 = map_vertex_tag_to_dof[std::make_pair(value.first.points.v3, value.first.tag)];
2603 mesh_int_t Index_new4 = map_vertex_tag_to_dof[std::make_pair(value.first.points.v4, value.first.tag)];
2604 value.first.points.v1 = Index_new1;
2605 value.first.points.v2 = Index_new2;
2606 value.first.points.v3 = Index_new3;
2607 value.first.points.v4 = Index_new4;
2611 mesh_int_t Index_new1 = map_vertex_tag_to_dof[std::make_pair(value.second.points.v1, value.second.tag)];
2612 mesh_int_t Index_new2 = map_vertex_tag_to_dof[std::make_pair(value.second.points.v2, value.second.tag)];
2613 mesh_int_t Index_new3 = map_vertex_tag_to_dof[std::make_pair(value.second.points.v3, value.second.tag)];
2614 mesh_int_t Index_new4 = map_vertex_tag_to_dof[std::make_pair(value.second.points.v4, value.second.tag)];
2615 value.second.points.v1 = Index_new1;
2616 value.second.points.v2 = Index_new2;
2617 value.second.points.v3 = Index_new3;
2618 value.second.points.v4 = Index_new4;
2620 quad_face.insert({new_key,value});
2636 template<
class T,
class S>
inline
2637 void compute_surface_mesh_with_counter_face(meshdata<T, S> & mesh,
const SF_nbr numbering,
2639 std::pair<emi_face<T,tuple<T>>, emi_face<T,tuple<T>>>> & line_face,
2641 std::pair<emi_face<T,triple<T>>, emi_face<T,triple<T>>>> & tri_face,
2643 std::pair<emi_face<T,quadruple<T>>, emi_face<T,quadruple<T>>>> & quad_face)
2645 mesh.register_numbering(numbering);
2649 MPI_Comm_size(comm, &size);
2650 MPI_Comm_rank(comm, &rank);
2653 vector<tuple<T>> line_keys;
2654 for(
auto const& [key, val] : line_face) line_keys.push_back(key);
2655 std::sort(line_keys.begin(), line_keys.end());
2657 vector<triple<T>> tri_keys;
2658 for(
auto const& [key, val] : tri_face) tri_keys.push_back(key);
2659 std::sort(tri_keys.begin(), tri_keys.end());
2661 vector<quadruple<T>> quad_keys;
2662 for(
auto const& [key, val] : quad_face) quad_keys.push_back(key);
2663 std::sort(quad_keys.begin(), quad_keys.end());
2665 vector<T> cnt(mesh.l_numelem);
2666 size_t idx = 0, cidx = 0;
2671 for(
const auto & key : line_keys) {
2672 const auto & v = line_face.at(key);
2673 bool both_faces = (v.first.rank == v.second.rank) ?
true:
false;
2677 emi_face<T,tuple<T>> surf_first;
2678 emi_face<T,tuple<T>> surf_second;
2679 if(v.first.rank == rank)
2681 surf_first = v.first;
2682 surf_second = v.second;
2686 surf_first = v.second;
2687 surf_second = v.first;
2690 mesh.type[idx] =
Line;
2691 mesh.tag[idx] = surf_first.tag;
2692 mesh.con[cidx + 0] = surf_first.points.v1;
2693 mesh.con[cidx + 1] = surf_first.points.v2;
2700 mesh.type[idx] =
Line;
2701 mesh.tag[idx] = surf_second.tag;
2702 mesh.con[cidx + 0] = surf_second.points.v1;
2703 mesh.con[cidx + 1] = surf_second.points.v2;
2710 for(
const auto & key : tri_keys) {
2711 const auto & v = tri_face.at(key);
2712 bool both_faces = (v.first.rank == v.second.rank) ?
true:
false;
2716 emi_face<T,triple<T>> surf_first;
2717 emi_face<T,triple<T>> surf_second;
2718 if(v.first.rank == rank)
2720 surf_first = v.first;
2721 surf_second = v.second;
2725 surf_first = v.second;
2726 surf_second = v.first;
2729 mesh.type[idx] =
Tri;
2730 mesh.tag[idx] = surf_first.tag;
2731 mesh.con[cidx + 0] = surf_first.points.v1;
2732 mesh.con[cidx + 1] = surf_first.points.v2;
2733 mesh.con[cidx + 2] = surf_first.points.v3;
2742 mesh.type[idx] =
Tri;
2743 mesh.tag[idx] = surf_second.tag;
2744 mesh.con[cidx + 0] = surf_second.points.v1;
2745 mesh.con[cidx + 1] = surf_second.points.v2;
2746 mesh.con[cidx + 2] = surf_second.points.v3;
2753 for(
const auto & key : quad_keys) {
2754 const auto & v = quad_face.at(key);
2755 bool both_faces = (v.first.rank == v.second.rank) ?
true:
false;
2758 emi_face<T,quadruple<T>> surf_first;
2759 emi_face<T,quadruple<T>> surf_second;
2760 if(v.first.rank == rank)
2762 surf_first = v.first;
2763 surf_second = v.second;
2767 surf_first = v.second;
2768 surf_second = v.first;
2771 mesh.type[idx] =
Quad;
2772 mesh.tag[idx] = surf_first.tag;
2773 mesh.con[cidx + 0] = surf_first.points.v1;
2774 mesh.con[cidx + 1] = surf_first.points.v2;
2775 mesh.con[cidx + 2] = surf_first.points.v3;
2776 mesh.con[cidx + 3] = surf_first.points.v4;
2785 mesh.type[idx] =
Quad;
2786 mesh.tag[idx] = surf_second.tag;
2787 mesh.con[cidx + 0] = surf_second.points.v1;
2788 mesh.con[cidx + 1] = surf_second.points.v2;
2789 mesh.con[cidx + 2] = surf_second.points.v3;
2790 mesh.con[cidx + 3] = surf_second.points.v4;
2829 template<
class T,
class S>
inline
2830 void compute_surface_mesh_with_unique_face(meshdata<T, S> & mesh,
const SF_nbr numbering,
2832 std::pair<emi_face<T,tuple<T>>, emi_face<T,tuple<T>>>> & line_face,
2834 std::pair<emi_face<T,triple<T>>, emi_face<T,triple<T>>>> & tri_face,
2836 std::pair<emi_face<T,quadruple<T>>, emi_face<T,quadruple<T>>>> & quad_face,
2839 mesh.register_numbering(numbering);
2843 MPI_Comm_size(comm, &size);
2844 MPI_Comm_rank(comm, &rank);
2847 vector<tuple<T>> line_keys;
2848 for(
auto const& [key, val] : line_face) line_keys.push_back(key);
2849 std::sort(line_keys.begin(), line_keys.end());
2851 vector<triple<T>> tri_keys;
2852 for(
auto const& [key, val] : tri_face) tri_keys.push_back(key);
2853 std::sort(tri_keys.begin(), tri_keys.end());
2855 vector<quadruple<T>> quad_keys;
2856 for(
auto const& [key, val] : quad_face) quad_keys.push_back(key);
2857 std::sort(quad_keys.begin(), quad_keys.end());
2859 vector<T> cnt(mesh.l_numelem);
2860 size_t idx = 0, cidx = 0;
2865 for(
const auto & key : line_keys) {
2866 const auto & v = line_face.at(key);
2868 bool to_take_face =
false;
2870 emi_face<T,tuple<T>> surf_take;
2871 std::pair <mesh_int_t,mesh_int_t> tag_pairs_take;
2873 if(v.first.rank == rank && v.first.mark_to_take ==
true)
2875 surf_take = v.first;
2876 to_take_face =
true;
2877 tag_pairs_take = std::make_pair(v.first.tag,v.second.tag);
2879 else if(v.second.rank == rank && v.second.mark_to_take ==
true)
2881 surf_take = v.second;
2882 to_take_face =
true;
2883 tag_pairs_take = std::make_pair(v.second.tag,v.first.tag);
2888 map_elem_uniqueFace_to_tags.insert({idx,tag_pairs_take});
2890 mesh.type[idx] =
Line;
2891 mesh.tag[idx] = surf_take.tag;
2892 mesh.con[cidx + 0] = surf_take.points.v1;
2893 mesh.con[cidx + 1] = surf_take.points.v2;
2900 for(
const auto & key : tri_keys) {
2901 const auto & v = tri_face.at(key);
2903 bool to_take_face =
false;
2905 emi_face<T,triple<T>> surf_take;
2906 std::pair <mesh_int_t,mesh_int_t> tag_pairs_take;
2908 if(v.first.rank == rank && v.first.mark_to_take ==
true)
2910 surf_take = v.first;
2911 to_take_face =
true;
2912 tag_pairs_take = std::make_pair(v.first.tag,v.second.tag);
2914 else if(v.second.rank == rank && v.second.mark_to_take ==
true)
2916 surf_take = v.second;
2917 to_take_face =
true;
2918 tag_pairs_take = std::make_pair(v.second.tag,v.first.tag);
2923 map_elem_uniqueFace_to_tags.insert({idx,tag_pairs_take});
2925 mesh.type[idx] =
Tri;
2926 mesh.tag[idx] = surf_take.tag;
2927 mesh.con[cidx + 0] = surf_take.points.v1;
2928 mesh.con[cidx + 1] = surf_take.points.v2;
2929 mesh.con[cidx + 2] = surf_take.points.v3;
2937 for(
const auto & key : quad_keys) {
2938 const auto & v = quad_face.at(key);
2941 bool to_take_face =
false;
2943 emi_face<T,quadruple<T>> surf_take;
2944 std::pair <mesh_int_t,mesh_int_t> tag_pairs_take;
2946 if(v.first.rank == rank && v.first.mark_to_take ==
true)
2948 surf_take = v.first;
2949 to_take_face =
true;
2950 tag_pairs_take = std::make_pair(v.first.tag,v.second.tag);
2952 else if(v.second.rank == rank && v.second.mark_to_take ==
true)
2954 surf_take = v.second;
2955 to_take_face =
true;
2956 tag_pairs_take = std::make_pair(v.second.tag,v.first.tag);
2961 map_elem_uniqueFace_to_tags.insert({idx,tag_pairs_take});
2963 mesh.type[idx] =
Quad;
2964 mesh.tag[idx] = surf_take.tag;
2965 mesh.con[cidx + 0] = surf_take.points.v1;
2966 mesh.con[cidx + 1] = surf_take.points.v2;
2967 mesh.con[cidx + 2] = surf_take.points.v3;
2968 mesh.con[cidx + 3] = surf_take.points.v4;
2997 template<
class T>
inline
2998 void create_reverse_elem_mapping_between_surface_meshes(
3001 hashmap::unordered_map<quadruple<T>, std::pair<emi_face<T,quadruple<T>>, emi_face<T,quadruple<T>>>>& quad_face,
3006 MPI_Comm_rank(comm, &rank);
3009 vector<tuple<T>> line_keys;
3010 for(
auto const& [key, val] : line_face) line_keys.push_back(key);
3011 std::sort(line_keys.begin(), line_keys.end());
3013 vector<triple<T>> tri_keys;
3014 for(
auto const& [key, val] : tri_face) tri_keys.push_back(key);
3015 std::sort(tri_keys.begin(), tri_keys.end());
3017 vector<quadruple<T>> quad_keys;
3018 for(
auto const& [key, val] : quad_face) quad_keys.push_back(key);
3019 std::sort(quad_keys.begin(), quad_keys.end());
3021 size_t surf_elem_idx = 0;
3022 size_t w_counter_elem_idx = 0;
3024 size_t lsize_line = 0;
3025 size_t lsize_tri = 0;
3026 size_t lsize_quad = 0;
3030 for(
const auto& key : line_keys) {
3031 const auto& v = line_face.at(key);
3032 const bool local_involved = (v.first.rank == rank) || (v.second.rank == rank);
3033 if (!local_involved) {
3036 if(v.first.rank == v.second.rank) lsize_line+=2;
3039 for(
const auto& key : tri_keys) {
3040 const auto& v = tri_face.at(key);
3041 const bool local_involved = (v.first.rank == rank) || (v.second.rank == rank);
3042 if (!local_involved) {
3045 if(v.first.rank == v.second.rank) lsize_tri+=2;
3048 for(
const auto& key : quad_keys) {
3049 const auto& v = quad_face.at(key);
3050 const bool local_involved = (v.first.rank == rank) || (v.second.rank == rank);
3051 if (!local_involved) {
3054 if(v.first.rank == v.second.rank) lsize_quad+=2;
3058 vec_one_to_both_face.
resize(lsize_line + lsize_tri + lsize_quad);
3062 for (
const auto& key : line_keys) {
3063 const auto& v = line_face.at(key);
3064 const bool local_involved = (v.first.rank == rank) || (v.second.rank == rank);
3065 if (!local_involved) {
3068 vec_one_to_both_face[w_counter_elem_idx++] = surf_elem_idx;
3069 if (v.first.rank == v.second.rank) {
3070 vec_one_to_both_face[w_counter_elem_idx++] = surf_elem_idx;
3075 for (
const auto& key : tri_keys) {
3076 const auto& v = tri_face.at(key);
3077 const bool local_involved = (v.first.rank == rank) || (v.second.rank == rank);
3078 if (!local_involved) {
3081 vec_one_to_both_face[w_counter_elem_idx++] = surf_elem_idx;
3082 if (v.first.rank == v.second.rank) {
3083 vec_one_to_both_face[w_counter_elem_idx++] = surf_elem_idx;
3088 for (
const auto& key : quad_keys) {
3089 const auto& v = quad_face.at(key);
3090 const bool local_involved = (v.first.rank == rank) || (v.second.rank == rank);
3091 if (!local_involved) {
3094 vec_one_to_both_face[w_counter_elem_idx++] = surf_elem_idx;
3095 if (v.first.rank == v.second.rank) {
3096 vec_one_to_both_face[w_counter_elem_idx++] = surf_elem_idx;
3110 template<
class T>
inline
3112 std::pair<emi_face<T,tuple<T>>, emi_face<T,tuple<T>>>> & line_face,
3114 std::pair<emi_face<T,triple<T>>, emi_face<T,triple<T>>>> & tri_face,
3116 std::pair<emi_face<T,quadruple<T>>, emi_face<T,quadruple<T>>>> & quad_face)
3119 std::vector<std::pair<tuple<T>, std::pair<emi_face<T,tuple<T>>, emi_face<T,tuple<T>>>>> line_inserts;
3120 for(
const auto & v : line_face) {
3121 SF::emi_face<mesh_int_t,SF::tuple<mesh_int_t>> surf_first = v.second.first;
3122 SF::emi_face<mesh_int_t,SF::tuple<mesh_int_t>> surf_second = v.second.second;
3124 std::vector<mesh_int_t> elem_nodes_first; elem_nodes_first.
resize(2);
3125 std::vector<mesh_int_t> elem_nodes_second; elem_nodes_second.resize(2);
3128 elem_nodes_first[0] = surf_first.points.
v1;
3129 elem_nodes_first[1] = surf_first.points.v2;
3130 std::sort(elem_nodes_first.begin(),elem_nodes_first.end());
3131 key_first.
v1 = elem_nodes_first[0];
3132 key_first.
v2 = elem_nodes_first[1];
3135 elem_nodes_second[0] = surf_second.points.
v1;
3136 elem_nodes_second[1] = surf_second.points.v2;
3137 std::sort(elem_nodes_second.begin(),elem_nodes_second.end());
3138 key_second.
v1 = elem_nodes_second[0];
3139 key_second.
v2 = elem_nodes_second[1];
3141 const bool same_key_first = (v.first.v1 == key_first.
v1 && v.first.v2 == key_first.
v2);
3142 if (!same_key_first && line_face.find(key_first) == line_face.end()) {
3143 line_inserts.push_back({key_first, v.second});
3145 const bool same_key_second = (v.first.v1 == key_second.
v1 && v.first.v2 == key_second.
v2);
3146 if (!same_key_second && line_face.find(key_second) == line_face.end()) {
3147 line_inserts.push_back({key_second, v.second});
3150 for (
const auto & entry : line_inserts) line_face.insert(entry);
3152 std::vector<std::pair<triple<T>, std::pair<emi_face<T,triple<T>>, emi_face<T,triple<T>>>>> tri_inserts;
3153 for(
const auto & v : tri_face) {
3154 SF::emi_face<mesh_int_t,SF::triple<mesh_int_t>> surf_first = v.second.first;
3155 SF::emi_face<mesh_int_t,SF::triple<mesh_int_t>> surf_second = v.second.second;
3157 std::vector<mesh_int_t> elem_nodes_first; elem_nodes_first.resize(3);
3158 std::vector<mesh_int_t> elem_nodes_second; elem_nodes_second.resize(3);
3161 elem_nodes_first[0] = surf_first.points.
v1;
3162 elem_nodes_first[1] = surf_first.points.v2;
3163 elem_nodes_first[2] = surf_first.points.v3;
3164 std::sort(elem_nodes_first.begin(),elem_nodes_first.end());
3165 key_first.
v1 = elem_nodes_first[0];
3166 key_first.
v2 = elem_nodes_first[1];
3167 key_first.
v3 = elem_nodes_first[2];
3170 elem_nodes_second[0] = surf_second.points.
v1;
3171 elem_nodes_second[1] = surf_second.points.v2;
3172 elem_nodes_second[2] = surf_second.points.v3;
3173 std::sort(elem_nodes_second.begin(),elem_nodes_second.end());
3174 key_second.
v1 = elem_nodes_second[0];
3175 key_second.
v2 = elem_nodes_second[1];
3176 key_second.
v3 = elem_nodes_second[2];
3178 const bool same_key_first = (v.first.v1 == key_first.
v1 &&
3179 v.first.v2 == key_first.
v2 &&
3180 v.first.v3 == key_first.
v3);
3181 if (!same_key_first && tri_face.find(key_first) == tri_face.end()) {
3182 tri_inserts.push_back({key_first, v.second});
3184 const bool same_key_second = (v.first.v1 == key_second.
v1 &&
3185 v.first.v2 == key_second.
v2 &&
3186 v.first.v3 == key_second.
v3);
3187 if (!same_key_second && tri_face.find(key_second) == tri_face.end()) {
3188 tri_inserts.push_back({key_second, v.second});
3191 for (
const auto & entry : tri_inserts) tri_face.insert(entry);
3193 std::vector<std::pair<quadruple<T>, std::pair<emi_face<T,quadruple<T>>, emi_face<T,quadruple<T>>>>> quad_inserts;
3194 for(
const auto & v : quad_face) {
3195 SF::emi_face<mesh_int_t,SF::quadruple<mesh_int_t>> surf_first = v.second.first;
3196 SF::emi_face<mesh_int_t,SF::quadruple<mesh_int_t>> surf_second = v.second.second;
3198 std::vector<mesh_int_t> elem_nodes_first; elem_nodes_first.resize(4);
3199 std::vector<mesh_int_t> elem_nodes_second; elem_nodes_second.resize(4);
3202 elem_nodes_first[0] = surf_first.points.
v1;
3203 elem_nodes_first[1] = surf_first.points.v2;
3204 elem_nodes_first[2] = surf_first.points.v3;
3205 elem_nodes_first[3] = surf_first.points.v4;
3206 std::sort(elem_nodes_first.begin(),elem_nodes_first.end());
3207 key_first.
v1 = elem_nodes_first[0];
3208 key_first.
v2 = elem_nodes_first[1];
3209 key_first.
v3 = elem_nodes_first[2];
3210 key_first.
v4 = elem_nodes_first[3];
3213 elem_nodes_second[0] = surf_second.points.
v1;
3214 elem_nodes_second[1] = surf_second.points.v2;
3215 elem_nodes_second[2] = surf_second.points.v3;
3216 elem_nodes_second[3] = surf_second.points.v4;
3217 std::sort(elem_nodes_second.begin(),elem_nodes_second.end());
3218 key_second.
v1 = elem_nodes_second[0];
3219 key_second.
v2 = elem_nodes_second[1];
3220 key_second.
v3 = elem_nodes_second[2];
3221 key_second.
v4 = elem_nodes_second[3];
3223 const bool same_key_first = (v.first.v1 == key_first.
v1 &&
3224 v.first.v2 == key_first.
v2 &&
3225 v.first.v3 == key_first.
v3 &&
3226 v.first.v4 == key_first.
v4);
3227 if (!same_key_first && quad_face.find(key_first) == quad_face.end()) {
3228 quad_inserts.push_back({key_first, v.second});
3230 const bool same_key_second = (v.first.v1 == key_second.
v1 &&
3231 v.first.v2 == key_second.
v2 &&
3232 v.first.v3 == key_second.
v3 &&
3233 v.first.v4 == key_second.
v4);
3234 if (!same_key_second && quad_face.find(key_second) == quad_face.end()) {
3235 quad_inserts.push_back({key_second, v.second});
3238 for (
const auto & entry : quad_inserts) quad_face.insert(entry);
3247 template<
class K>
inline
3250 size_t dsize = map.
size();
3251 vector<K> key_vec(dsize);
3252 vector<intersection_tags> value_vec(dsize);
3255 for (
const auto& v : map) {
3256 key_vec[idx] = v.first;
3257 value_vec[idx] = v.second;
3262 MPI_Comm_size(comm, &size); MPI_Comm_rank(comm, &rank);
3264 vector<int> perm, dest(dsize);
3265 for (
size_t i = 0; i < dsize; i++)
3268 commgraph<size_t> grph;
3269 grph.configure(dest, comm);
3270 size_t nrecv =
sum(grph.rcnt);
3276 vector<K> sbuff_key(dsize), rbuff_key(nrecv);
3277 vector<intersection_tags> sbuff_value(dsize), ibuff_value(dsize), rbuff_value(nrecv);
3278 for (
size_t i = 0; i < dsize; i++) {
3279 sbuff_key[i] = key_vec[perm[i]];
3280 sbuff_value[i] = value_vec[perm[i]];
3286 for (
size_t i = 0; i < nrecv; i++)
3288 auto it = rmap.
find(rbuff_key[i]);
3289 if (it != rmap.
end())
3291 intersection_tags& map_tags = it->second;
3292 intersection_tags& r_tags = rbuff_value[i];
3294 for (
int r_tag : r_tags.tags)
3296 if (r_tag == -1)
continue;
3298 for (
int m_tag : map_tags.tags)
3300 if (m_tag == r_tag) {
3307 for (
size_t k = 0; k < MAX_INTERSECTIONS; ++k) {
3308 if (map_tags.tags[k] == -1) {
3309 map_tags.tags[k] = r_tag;
3318 rmap.
insert({ rbuff_key[i], rbuff_value[i] });
3322 for (
size_t i = 0; i < nrecv; i++) {
3323 auto it = rmap.
find(rbuff_key[i]);
3324 if (it != rmap.
end()) rbuff_value[i] = it->second;
3331 for (
size_t i = 0; i < dsize; i++) {
3332 auto it = map.find(sbuff_key[i]);
3333 if (it != map.end()) it->second = ibuff_value[i];
3358 template<
class T,
class S>
inline
3359 void compute_ptsdata_from_original_mesh(meshdata<T,S> & mesh,
3365 MPI_Comm comm = mesh.comm;
3367 MPI_Comm_size(comm, &size);
3368 MPI_Comm_rank(comm, &rank);
3370 const T* con = mesh.con.data();
3377 for(
size_t eidx = 0; eidx < mesh.l_numelem; eidx++)
3379 T tag = mesh.tag[eidx];
3380 for (
int n = mesh.dsp[eidx]; n < mesh.dsp[eidx+1];n++)
3382 T gIndex = rnod[con[n]];
3384 auto it_new = map_index_to_tags.
find(gIndex);
3385 if (it_new != map_index_to_tags.
end())
3388 intersection_tags& tags = it_new->second;
3390 for(T t : tags.tags) {
3398 for(
int i=0; i <MAX_INTERSECTIONS; ++i) {
3399 if (tags.tags[i] == -1) {
3408 intersection_tags tags;
3410 map_index_to_tags.
insert({gIndex,tags});
3418 assign_counter_tags(map_index_to_tags, comm);
3421 for(
size_t eidx = 0; eidx < mesh.l_numelem; eidx++)
3423 for (
int n = mesh.dsp[eidx]; n < mesh.dsp[eidx+1];n++)
3425 T gIndex = rnod[con[n]];
3426 intersection_tags& vec_tags = map_index_to_tags[gIndex];
3427 int count_intra_tags = 0;
3428 int count_extra_tags = 0;
3432 for(T t : vec_tags.tags) {
3433 if(intra_tags.
count(t)) count_intra_tags++;
3434 if(extra_tags.
count(t)) count_extra_tags++;
3438 if(count_extra_tags>=1 && count_intra_tags==0){
3439 vertex2ptsdata[gIndex] = 0;
3440 }
else if(count_extra_tags==0 && count_intra_tags==1){
3441 vertex2ptsdata[gIndex] = 0;
3442 }
else if(count_extra_tags>=1 && count_intra_tags==1){
3443 vertex2ptsdata[gIndex] = 1;
3444 }
else if(count_extra_tags==0 && count_intra_tags==2){
3445 vertex2ptsdata[gIndex] = 2;
3446 }
else if(count_extra_tags>=1 && count_intra_tags==2){
3447 vertex2ptsdata[gIndex] = 3;
3449 else if(count_intra_tags>2){
3451 fprintf(stderr,
"More than two intracellular are connected %d. Tags:", gIndex);
3452 for(T tag : vec_tags.tags)
if(tag != -1) fprintf(stderr,
" %d", tag);
3453 fprintf(stderr,
"\n");
3458 fprintf(stderr,
"WARN: unhandled case in ptsData computation for gIndex %d. Tags:", gIndex);
3459 for(T tag : vec_tags.tags)
if(tag != -1) fprintf(stderr,
" %d", tag);
3460 fprintf(stderr,
"\n");
3483 template <
class T,
class S,
class V,
class emi_index_rank>
3486 std::pair<emi_index_rank, emi_index_rank>>& map,
3493 MPI_Comm_rank(both_mesh.
comm, &rank);
3496 SF::layout_from_count<long int>(both_mesh.
l_numelem, layout_both, both_mesh.
comm);
3499 SF::layout_from_count<long int>(unique_mesh.
l_numelem, layout_unique, unique_mesh.
comm);
3505 for (
const auto& [local_unique_idx, both_pair] : map) {
3506 const auto& first_both = both_pair.first;
3507 const auto& second_both = both_pair.second;
3511 T global_unique_row = layout_unique[rank] + local_unique_idx;
3512 row_idx[0] = global_unique_row;
3515 bool first_valid = (first_both.index >= 0 && first_both.rank >= 0);
3516 bool second_valid = (second_both.index >= 0 && second_both.rank >= 0);
3518 T global_both_col_first = -1;
3519 T global_both_col_second = -1;
3521 global_both_col_first = layout_both[first_both.rank] + first_both.index;
3524 global_both_col_second = layout_both[second_both.rank] + second_both.index;
3529 if (first_valid && second_valid && global_both_col_first == global_both_col_second) {
3530 second_valid =
false;
3535 if (first_valid)
count++;
3536 if (second_valid)
count++;
3538 if (
count == 0)
continue;
3542 double weight = 0.5;
3543 if (
count == 1) weight = 1.0;
3545 ebuff.assign(1, 1, weight);
3549 col_idx[0] = global_both_col_first;
3550 op.
set_values(row_idx, col_idx, ebuff.data(),
false);
3555 col_idx[0] = global_both_col_second;
3556 op.
set_values(row_idx, col_idx, ebuff.data(),
false);
3585 for(
size_t i=0; i<rnod.
size(); i++){
3592 for(
size_t i=0; i<v.size(); i++){
3595 if (dof2ptsData[g] > 0) {
#define SF_COMM
the default SlimFem MPI communicator
Functions related to EMI mesh IO.
Functions handling a distributed mesh.
virtual void finish_assembly()=0
virtual void set_values(const vector< T > &row_idx, const vector< T > &col_idx, const vector< S > &vals, bool add)=0
The mesh storage class. It contains both element and vertex data.
size_t l_numelem
local number of elements
MPI_Comm comm
the parallel mesh is defined on a MPI world
A vector storing arbitrary data.
size_t size() const
The current size of the vector.
void resize(size_t n)
Resize a vector.
iterator find(const K &key)
Search for key. Return iterator.
void sort(Compare comp=Compare())
Sort data entries.
void insert(InputIterator first, InputIterator last)
Insert Iterator range.
T & at(const K &key)
Data access by key.
iterator find(const K &key)
hm_int count(const K &key) const
void dsp_from_cnt(const vector< T > &cnt, vector< T > &dsp)
Compute displacements from counts.
void interval(vector< T > &vec, size_t start, size_t end)
Create an integer interval between start and end.
void binary_sort_copy(vector< T > &_V, vector< S > &_W)
T sum(const vector< T > &vec)
Compute sum of a vector's entries.
void unique_resize(vector< T > &_P)
void count(const vector< T > &data, vector< S > &cnt)
Count number of occurrences of indices.
void MPI_Exchange(commgraph< T > &grph, vector< S > &send, vector< S > &recv, MPI_Comm comm)
Exchange data in parallel over MPI.
void binary_sort(vector< T > &_V)
SF_nbr
Enumeration encoding the different supported numberings.
@ NBR_ELEM_REF
The element numbering of the reference mesh (the one stored on HD).
@ NBR_REF
The nodal numbering of the reference mesh (the one stored on HD).
void dsp_from_cnt(const std::vector< T > &cnt, std::vector< T > &dsp)
Compute displacements from counts.
static hm_uint hash(const T &a)