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;
1289 template<
class T,
class S>
inline
1290 void extract_face_based_tags(meshdata<T,S> & mesh,
1294 std::pair<emi_face<T,tuple<T>>, emi_face<T,tuple<T>>>> & line_face,
1296 std::pair<emi_face<T,triple<T>>, emi_face<T,triple<T>>>> & tri_face,
1298 std::pair<emi_face<T,quadruple<T>>, emi_face<T,quadruple<T>>>> & quad_face,
1301 std::set<std::pair<mesh_int_t,mesh_int_t>> &membraneFace_default,
1302 std::set<std::pair<mesh_int_t,mesh_int_t>> &gapjunctionFace_default,
1303 meshdata<T,S> & surfmesh,
1304 meshdata<T,S> & surfmesh_w_counter,
1305 meshdata<T,S> & surfmesh_unique_face,
1313 surfmesh_w_counter.register_numbering(
SF::NBR_REF);
1314 surfmesh_unique_face.register_numbering(
SF::NBR_REF);
1318 compute_surface_with_tags(mesh, numbering, vertex2ptsdata, extra_tags, line_face, tri_face, quad_face);
1321 MPI_Comm_size(mesh.comm, &size);
1322 MPI_Comm_rank(mesh.comm, &rank);
1324 long int g_num_line = line_face.size();
1325 long int g_num_tri = tri_face.size();
1326 long int g_num_quad = quad_face.size();
1327 MPI_Allreduce(MPI_IN_PLACE, &g_num_line, 1, MPI_LONG, MPI_SUM, mesh.comm);
1328 MPI_Allreduce(MPI_IN_PLACE, &g_num_tri, 1, MPI_LONG, MPI_SUM, mesh.comm);
1329 MPI_Allreduce(MPI_IN_PLACE, &g_num_quad, 1, MPI_LONG, MPI_SUM, mesh.comm);
1333 long int local_extra_extra = 0;
1334 for (
const auto& [key, v] : line_face) {
1335 if (extra_tags.
find(v.first.tag) != extra_tags.
end() &&
1336 extra_tags.
find(v.second.tag) != extra_tags.
end()) {
1337 local_extra_extra++;
1340 for (
const auto& [key, v] : tri_face) {
1341 if (extra_tags.
find(v.first.tag) != extra_tags.
end() &&
1342 extra_tags.
find(v.second.tag) != extra_tags.
end()) {
1343 local_extra_extra++;
1346 for (
const auto& [key, v] : quad_face) {
1347 if (extra_tags.
find(v.first.tag) != extra_tags.
end() &&
1348 extra_tags.
find(v.second.tag) != extra_tags.
end()) {
1349 local_extra_extra++;
1352 long int global_extra_extra = 0;
1353 MPI_Allreduce(&local_extra_extra, &global_extra_extra, 1, MPI_LONG, MPI_SUM, mesh.comm);
1354 if (global_extra_extra > 0 && rank == 0) {
1355 fprintf(stderr,
"WARN: extra-extra faces detected before filtering: %ld\n", global_extra_extra);
1359 surfmesh.g_numelem = g_num_line + g_num_tri + g_num_quad;
1360 surfmesh.l_numelem = line_face.size() + tri_face.size() + quad_face.size();
1362 vector<T> cnt(surfmesh.l_numelem, 0);
1363 surfmesh.tag.resize(surfmesh.l_numelem);
1364 surfmesh.type.resize(surfmesh.l_numelem);
1365 surfmesh.con.resize(line_face.size() * 2 + tri_face.size() * 3 + quad_face.size() * 4);
1372 vector<tuple<T>> line_keys;
1373 for(
auto const& [key, val] : line_face) line_keys.push_back(key);
1374 std::sort(line_keys.begin(), line_keys.end());
1376 vector<triple<T>> tri_keys;
1377 for(
auto const& [key, val] : tri_face) tri_keys.push_back(key);
1378 std::sort(tri_keys.begin(), tri_keys.end());
1380 vector<quadruple<T>> quad_keys;
1381 for(
auto const& [key, val] : quad_face) quad_keys.push_back(key);
1382 std::sort(quad_keys.begin(), quad_keys.end());
1407 for(
auto const& key : line_keys) {
1408 auto& v = line_face.
at(key);
1409 const bool local_involved = (v.first.rank == rank) || (v.second.rank == rank);
1410 if (!local_involved) {
1416 if ((intra_tags.
find(v.first.tag) != intra_tags.
end()) && (intra_tags.
find(v.second.tag) != intra_tags.
end()))
1418 gapjunctionFace_default.insert(std::make_pair(v.first.tag,v.second.tag));
1419 gapjunctionFace_default.insert(std::make_pair(v.second.tag,v.first.tag));
1423 membraneFace_default.insert(std::make_pair(v.first.tag,v.second.tag));
1424 membraneFace_default.insert(std::make_pair(v.second.tag,v.first.tag));
1429 emi_face<T,tuple<T>> surf_neighbor =
1430 (v.first.rank == rank) ? v.first : v.second;
1432 surfmesh.type[idx] =
Line;
1433 surfmesh.tag[idx] = surf_neighbor.tag;
1434 surfmesh.con[cidx + 0] = surf_neighbor.points.v1;
1435 surfmesh.con[cidx + 1] = surf_neighbor.points.v2;
1438 if(v.first.rank == v.second.rank)
1443 assign_ownership_rank_on_faces<T, tuple<T>, tuple<T>>( key, v, rank,
1446 extra_tags, intra_tags,
1447 line_unique_face_to_elements,
1448 map_elem_oneface_to_elem_uniqueFace);
1453 for(
auto const& key : tri_keys) {
1454 auto& v = tri_face.at(key);
1455 const bool local_involved = (v.first.rank == rank) || (v.second.rank == rank);
1456 if (!local_involved) {
1462 if ((intra_tags.
find(v.first.tag) != intra_tags.
end()) && (intra_tags.
find(v.second.tag) != intra_tags.
end()))
1464 gapjunctionFace_default.insert(std::make_pair(v.first.tag,v.second.tag));
1465 gapjunctionFace_default.insert(std::make_pair(v.second.tag,v.first.tag));
1469 membraneFace_default.insert(std::make_pair(v.first.tag,v.second.tag));
1470 membraneFace_default.insert(std::make_pair(v.second.tag,v.first.tag));
1475 emi_face<T,triple<T>> surf_neighbor =
1476 (v.first.rank == rank) ? v.first : v.second;
1478 surfmesh.type[idx] =
Tri;
1479 surfmesh.tag[idx] = surf_neighbor.tag;
1480 surfmesh.con[cidx + 0] = surf_neighbor.points.v1;
1481 surfmesh.con[cidx + 1] = surf_neighbor.points.v2;
1482 surfmesh.con[cidx + 2] = surf_neighbor.points.v3;
1485 if(v.first.rank == v.second.rank)
1490 assign_ownership_rank_on_faces<T, triple<T>, triple<T>>( key, v, rank,
1493 extra_tags, intra_tags,
1494 tri_unique_face_to_elements,
1495 map_elem_oneface_to_elem_uniqueFace);
1500 for(
auto const& key : quad_keys) {
1501 auto& v = quad_face.at(key);
1502 const bool local_involved = (v.first.rank == rank) || (v.second.rank == rank);
1503 if (!local_involved) {
1509 if ((intra_tags.
find(v.first.tag) != intra_tags.
end()) && (intra_tags.
find(v.second.tag) != intra_tags.
end()))
1511 gapjunctionFace_default.insert(std::make_pair(v.first.tag,v.second.tag));
1512 gapjunctionFace_default.insert(std::make_pair(v.second.tag,v.first.tag));
1516 membraneFace_default.insert(std::make_pair(v.first.tag,v.second.tag));
1517 membraneFace_default.insert(std::make_pair(v.second.tag,v.first.tag));
1522 emi_face<T,quadruple<T>> qsurf_neighbor =
1523 (v.first.rank == rank) ? v.first : v.second;
1525 surfmesh.type[idx] =
Quad;
1526 surfmesh.tag[idx] = qsurf_neighbor.tag;
1527 surfmesh.con[cidx + 0] = qsurf_neighbor.points.v1;
1528 surfmesh.con[cidx + 1] = qsurf_neighbor.points.v2;
1529 surfmesh.con[cidx + 2] = qsurf_neighbor.points.v3;
1530 surfmesh.con[cidx + 3] = qsurf_neighbor.points.v4;
1533 if(v.first.rank == v.second.rank)
1538 assign_ownership_rank_on_faces<T, quadruple<T>, quadruple<T>>( key, v, rank,
1541 extra_tags, intra_tags,
1542 quad_unique_face_to_elements,
1543 map_elem_oneface_to_elem_uniqueFace);
1548 surfmesh.l_numelem = idx;
1549 surfmesh.tag.resize(idx);
1550 surfmesh.type.resize(idx);
1553 surfmesh.con.resize(cidx);
1555 long int g_num_surf = surfmesh.l_numelem;
1556 MPI_Allreduce(MPI_IN_PLACE, &g_num_surf, 1, MPI_LONG, MPI_SUM, mesh.comm);
1557 surfmesh.g_numelem = g_num_surf;
1560 std::cout <<
"surfmesh.g_numelem: " << surfmesh.g_numelem <<std::endl;
1561 std::cout <<
"surfmesh.l_numelem: " << surfmesh.l_numelem <<std::endl;
1565 long int g_num_w_counter_line = lsize_line;
1566 long int g_num_w_counter_tri = lsize_tri;
1567 long int g_num_w_counter_quad = lsize_quad;
1569 MPI_Allreduce(MPI_IN_PLACE, &g_num_w_counter_line, 1, MPI_LONG, MPI_SUM,
SF_COMM);
1570 MPI_Allreduce(MPI_IN_PLACE, &g_num_w_counter_tri, 1, MPI_LONG, MPI_SUM,
SF_COMM);
1571 MPI_Allreduce(MPI_IN_PLACE, &g_num_w_counter_quad, 1, MPI_LONG, MPI_SUM,
SF_COMM);
1574 surfmesh_w_counter.g_numelem = g_num_w_counter_line+g_num_w_counter_tri+g_num_w_counter_quad;
1575 surfmesh_w_counter.l_numelem = lsize_line + lsize_tri + lsize_quad;
1577 surfmesh_w_counter.tag.resize(surfmesh_w_counter.l_numelem);
1578 surfmesh_w_counter.type.resize(surfmesh_w_counter.l_numelem);
1579 surfmesh_w_counter.con.resize(lsize_line * 2 + lsize_tri * 3 + lsize_quad * 4);
1582 std::cout <<
"surfmesh_w_counter.g_numelem: " << surfmesh_w_counter.g_numelem <<std::endl;
1583 std::cout <<
"surfmesh_w_counter.l_numelem: " << surfmesh_w_counter.l_numelem <<std::endl;
1588 long int g_num_w_unique_line = lsize_unique_line;
1589 long int g_num_w_unique_tri = lsize_unique_tri;
1590 long int g_num_w_unique_quad = lsize_unique_quad;
1592 MPI_Allreduce(MPI_IN_PLACE, &g_num_w_unique_line, 1, MPI_LONG, MPI_SUM,
SF_COMM);
1593 MPI_Allreduce(MPI_IN_PLACE, &g_num_w_unique_tri, 1, MPI_LONG, MPI_SUM,
SF_COMM);
1594 MPI_Allreduce(MPI_IN_PLACE, &g_num_w_unique_quad, 1, MPI_LONG, MPI_SUM,
SF_COMM);
1597 surfmesh_unique_face.g_numelem = g_num_w_unique_line+g_num_w_unique_tri+g_num_w_unique_quad;
1598 surfmesh_unique_face.l_numelem = lsize_unique_line + lsize_unique_tri + lsize_unique_quad;
1600 surfmesh_unique_face.tag.resize(surfmesh_unique_face.l_numelem);
1601 surfmesh_unique_face.type.resize(surfmesh_unique_face.l_numelem);
1602 surfmesh_unique_face.con.resize(lsize_unique_line * 2 + lsize_unique_tri * 3 + lsize_unique_quad * 4);
1605 std::cout <<
"surfmesh_unique_face.g_numelem: " << surfmesh_unique_face.g_numelem <<std::endl;
1606 std::cout <<
"surfmesh_unique_face.l_numelem: " << surfmesh_unique_face.l_numelem <<std::endl;
1618 #ifdef EMI_DEBUG_MESH
1620 fprintf(stderr,
"RANK %d BEFORE exchange: line_hash=%zu, tri_hash=%zu, quad_hash=%zu (expected unique total=%ld)\n",
1621 rank, line_unique_face_to_elements.
size(), tri_unique_face_to_elements.
size(),
1622 quad_unique_face_to_elements.
size(), lsize_unique_line + lsize_unique_tri + lsize_unique_quad);
1630 assign_unique_first_face(line_unique_face_to_elements, mesh.comm);
1631 assign_unique_first_face(tri_unique_face_to_elements, mesh.comm);
1632 assign_unique_first_face(quad_unique_face_to_elements, mesh.comm);
1636 #ifdef EMI_DEBUG_MESH
1638 int valid_line = 0, valid_tri = 0, valid_quad = 0;
1639 for (
const auto& [key, val] : line_unique_face_to_elements) {
1640 if (val.first.index_unique >= 0 || val.second.index_unique >= 0) valid_line++;
1642 for (
const auto& [key, val] : tri_unique_face_to_elements) {
1643 if (val.first.index_unique >= 0 || val.second.index_unique >= 0) valid_tri++;
1645 for (
const auto& [key, val] : quad_unique_face_to_elements) {
1646 if (val.first.index_unique >= 0 || val.second.index_unique >= 0) valid_quad++;
1648 fprintf(stderr,
"RANK %d AFTER exchange: line_hash=%zu, tri_hash=%zu, quad_hash=%zu\n",
1649 rank, line_unique_face_to_elements.size(), tri_unique_face_to_elements.size(),
1650 quad_unique_face_to_elements.size());
1651 fprintf(stderr,
"RANK %d VALID entries (index_unique>=0): line=%d, tri=%d, quad=%d\n",
1652 rank, valid_line, valid_tri, valid_quad);
1660 for(
auto it = line_unique_face_to_elements.begin(); it != line_unique_face_to_elements.end(); ++it) {
1662 auto& first = it->second.first;
1663 auto& second = it->second.second;
1665 assign_map_between_elem_oneface_and_elem_uniqueFace(rank, first, second, map_elem_uniqueFace_to_elem_oneface, map_elem_oneface_to_elem_uniqueFace);
1668 for(
auto it = tri_unique_face_to_elements.begin(); it != tri_unique_face_to_elements.end(); ++it) {
1669 auto& first = it->second.first;
1670 auto& second = it->second.second;
1672 assign_map_between_elem_oneface_and_elem_uniqueFace(rank, first, second, map_elem_uniqueFace_to_elem_oneface, map_elem_oneface_to_elem_uniqueFace);
1675 for(
auto it = quad_unique_face_to_elements.begin(); it != quad_unique_face_to_elements.end(); ++it) {
1676 auto& first = it->second.first;
1677 auto& second = it->second.second;
1679 assign_map_between_elem_oneface_and_elem_uniqueFace(rank, first, second, map_elem_uniqueFace_to_elem_oneface, map_elem_oneface_to_elem_uniqueFace);
1692 template<
class T>
inline
1694 std::pair<emi_face<T,tuple<T>>, emi_face<T,tuple<T>>>> & line_face,
1696 std::pair<emi_face<T,triple<T>>, emi_face<T,triple<T>>>> & tri_face,
1698 std::pair<emi_face<T,quadruple<T>>, emi_face<T,quadruple<T>>>> & quad_face,
1704 MPI_Comm_size(comm, &size);
1705 MPI_Comm_rank(comm, &rank);
1708 for(
const auto & v : line_face) {
1711 if(v.second.first.rank == v.second.second.rank){
1715 emi_face<T,tuple<T>> surf_neighbor =
1716 (v.second.first.rank != rank) ? v.second.first : v.second.second;
1719 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
1720 Index_tag_old = std::make_pair(surf_neighbor.points.v1,surf_neighbor.tag);
1721 map_vertex_tag_to_dof.insert({Index_tag_old,-1});
1725 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
1726 Index_tag_old = std::make_pair(surf_neighbor.points.v2,surf_neighbor.tag);
1727 map_vertex_tag_to_dof.insert({Index_tag_old,-1});
1732 for(
const auto & v : tri_face) {
1735 if(v.second.first.rank == v.second.second.rank){
1739 emi_face<T,triple<T>> surf_neighbor =
1740 (v.second.first.rank != rank) ? v.second.first : v.second.second;
1743 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
1744 Index_tag_old = std::make_pair(surf_neighbor.points.v1,surf_neighbor.tag);
1745 map_vertex_tag_to_dof.insert({Index_tag_old,-1});
1749 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
1750 Index_tag_old = std::make_pair(surf_neighbor.points.v2,surf_neighbor.tag);
1751 map_vertex_tag_to_dof.insert({Index_tag_old,-1});
1755 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
1756 Index_tag_old = std::make_pair(surf_neighbor.points.v3,surf_neighbor.tag);
1757 map_vertex_tag_to_dof.insert({Index_tag_old,-1});
1762 for(
const auto & v : quad_face) {
1765 if(v.second.first.rank == v.second.second.rank){
1769 emi_face<T,quadruple<T>> qsurf_neighbor =
1770 (v.second.first.rank != rank) ? v.second.first : v.second.second;
1773 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
1774 Index_tag_old = std::make_pair(qsurf_neighbor.points.v1,qsurf_neighbor.tag);
1775 map_vertex_tag_to_dof.insert({Index_tag_old,-1});
1779 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
1780 Index_tag_old = std::make_pair(qsurf_neighbor.points.v2,qsurf_neighbor.tag);
1781 map_vertex_tag_to_dof.insert({Index_tag_old,-1});
1785 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
1786 Index_tag_old = std::make_pair(qsurf_neighbor.points.v3,qsurf_neighbor.tag);
1787 map_vertex_tag_to_dof.insert({Index_tag_old,-1});
1791 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
1792 Index_tag_old = std::make_pair(qsurf_neighbor.points.v4,qsurf_neighbor.tag);
1793 map_vertex_tag_to_dof.insert({Index_tag_old,-1});
1798 assign_dof_on_counter_face(map_vertex_tag_to_dof,comm);
1830 template<
class T,
class S>
inline
1831 void compute_map_vertex_to_dof(meshdata<T,S> & mesh,
1838 MPI_Comm comm = mesh.comm;
1840 MPI_Comm_size(comm, &size);
1841 MPI_Comm_rank(comm, &rank);
1845 const T* con = mesh.con.data();
1846 const T* nbr = mesh.get_numbering(numbering).data();
1851 for(
size_t i=0; i<mesh.con.size(); i++)
1853 g2ptsData[rnod[con[i]]] = vertex2ptsdata[rnod[con[i]]];
1865 for(
size_t eidx = 0; eidx < mesh.l_numelem; eidx++)
1867 T tag = mesh.tag[eidx];
1868 auto pos_extra = extra_tags.
find(tag);
1869 for (
int n = mesh.dsp[eidx]; n < mesh.dsp[eidx+1];n++)
1871 T gIndex = rnod[con[n]];
1872 T data_on_gIndex = g2ptsData[rnod[con[n]]];
1876 if((pos_extra != extra_tags.
end()) || data_on_gIndex==0){
1877 std::pair <mesh_int_t,mesh_int_t> Index_tag_old = std::make_pair(gIndex,tag);
1878 if (map_vertex_tag_to_dof.find(Index_tag_old) == map_vertex_tag_to_dof.end() )
1880 map_vertex_tag_to_dof.insert({Index_tag_old,gIndex});
1885 auto it = map_vertex_to_tags_data_ranks.
find(gIndex);
1886 if (it != map_vertex_to_tags_data_ranks.
end() )
1888 intersection_data& value = it->second;
1889 bool check_tag_rank =
true;
1890 for(
int i=0; i<MAX_INTERSECTIONS; ++i) {
1891 if(value.tags[i] == tag && value.ranks[i] == rank) {
1892 check_tag_rank =
false;
1899 for(
int i=0; i<MAX_INTERSECTIONS; ++i) {
1900 if(value.tags[i] == -1 && value.ranks[i] == -1) {
1901 value.tags[i] = tag;
1902 value.data[i] = data_on_gIndex;
1903 value.ranks[i] = rank;
1912 intersection_data value;
1913 value.tags[0] = tag;
1914 value.data[0] = data_on_gIndex;
1915 value.ranks[0] = rank;
1916 map_vertex_to_tags_data_ranks.
insert({gIndex,value});
1932 assign_counter_vertices_tuple(map_vertex_to_tags_data_ranks, comm);
1949 for(
const auto & key : map_vertex_to_tags_data_ranks)
1951 T gIndex = key.first;
1952 const intersection_data& value = key.second;
1953 T data_on_gIndex = g2ptsData[gIndex];
1956 int first_index = 0;
1957 for (
int i = 0; i < MAX_INTERSECTIONS; ++i) {
1958 if(value.tags[i] == -1 && value.ranks[i] == -1) {
1963 if(value.data[i]!=data_on_gIndex)
1967 "WARN: Due to an inconsistency in ptsData computation at gIndex %d with tag %d, "
1968 "the program is stopped while preparing the data structure to introduce DOFs.\n",
1969 gIndex, value.tags[i]);
1970 fprintf(stderr,
"\n");
1974 if (i == MAX_INTERSECTIONS -1) first_index = MAX_INTERSECTIONS;
1977 if(data_on_gIndex==1){
1979 int count_intra_tags = 0;
1980 int count_extra_tags = 0;
1981 for (
int i = 0; i < first_index; ++i) {
1982 if(value.tags[i]!=-1 && extra_tags.
find(value.tags[i])==extra_tags.
end()){
1983 count_intra_tags += 1;
1984 }
else if(value.tags[i]!=-1 && extra_tags.
find(value.tags[i])!=extra_tags.
end()){
1985 count_extra_tags += 1;
1991 if(count_intra_tags>1 || count_extra_tags == 0)
1995 "WARN: Due to an issue in defining ptsData for gIndex %d, , on the membrane"
1996 "the program is stopped while preparing the data structure to introduce DOFs.\n",
1998 fprintf(stderr,
"\n");
2002 int index_intra = -1;
2004 for (
int i = 0; i < first_index; ++i) {
2005 if(value.tags[i]!=-1 && extra_tags.
find(value.tags[i])==extra_tags.
end()){
2010 if(index_intra == -1) {
2011 fprintf(stderr,
"WARN: unhandled case in membrane while decoupling: gIndex %d", gIndex);
2012 fprintf(stderr,
"\n");
2015 if(index_intra != -1) {
2016 T tag_myocyte = value.tags[index_intra];
2017 T rank_myocyte = value.ranks[index_intra];
2019 if(rank_myocyte == rank) {
2020 std::pair <mesh_int_t,mesh_int_t> Index_tag_next = std::make_pair(gIndex,tag_myocyte);
2021 if (map_mark_new_dofs.
find(Index_tag_next) == map_mark_new_dofs.
end()) {
2022 map_mark_new_dofs.
insert({Index_tag_next,
true});
2028 else if(data_on_gIndex==2){
2030 int count_intra_tags = 0;
2031 int count_extra_tags = 0;
2032 for (
int i = 0; i < first_index; ++i) {
2033 if(value.tags[i]!=-1 && extra_tags.
find(value.tags[i])==extra_tags.
end()){
2034 count_intra_tags += 1;
2035 }
else if(value.tags[i]!=-1 && extra_tags.
find(value.tags[i])!=extra_tags.
end()){
2036 count_extra_tags += 1;
2039 if(count_intra_tags!=2 || count_extra_tags != 0){
2042 "WARN: Due to an issue in defining ptsData for gIndex %d, on the gapjunction"
2043 "the program is stopped while preparing the data structure to introduce DOFs.\n",
2045 fprintf(stderr,
"\n");
2053 bool tag1_checked =
false;
2054 bool tag2_checked =
false;
2056 for (
int i = 0; i < first_index; ++i)
2058 auto pos_extra = extra_tags.
find(value.tags[i]);
2059 if(pos_extra == extra_tags.
end()) {
2061 tag1 = value.tags[i];
2062 rank1 = value.ranks[i];
2063 tag1_checked =
true;
2065 tag2 = value.tags[i];
2066 rank2 = value.ranks[i];
2067 tag2_checked =
true;
2073 if(!tag1_checked && !tag2_checked || (rank1==rank2 && rank1!=rank) ) {
2074 fprintf(stderr,
"WARN: unhandled case in gap junction while decoupling: gIndex %d with tags %d:%d ", gIndex, tag1, tag2);
2075 fprintf(stderr,
"\n");
2079 if(rank1==rank2 && (rank1 == rank)){
2080 T smallest_tag = tag1 < tag2? tag1:tag2;
2081 std::pair <mesh_int_t,mesh_int_t> Index_tag_old = std::make_pair(gIndex,smallest_tag);
2082 if (map_vertex_tag_to_dof.find(Index_tag_old) == map_vertex_tag_to_dof.end() ) {
2083 map_vertex_tag_to_dof.insert({Index_tag_old,gIndex});
2086 T bigger_tag = tag1 < tag2? tag2:tag1;
2087 std::pair <mesh_int_t,mesh_int_t> Index_tag_new = std::make_pair(gIndex,bigger_tag);
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});
2093 else if(rank1!=rank2 && (rank1 == rank)) {
2095 std::pair <mesh_int_t,mesh_int_t> Index_tag_old = std::make_pair(gIndex,tag1);
2096 if (map_vertex_tag_to_dof.find(Index_tag_old) == map_vertex_tag_to_dof.end() ) {
2097 map_vertex_tag_to_dof.insert({Index_tag_old,gIndex});
2100 std::pair <mesh_int_t,mesh_int_t> Index_tag_new = std::make_pair(gIndex,tag1);
2101 if (map_mark_new_dofs.
find(Index_tag_new) == map_mark_new_dofs.
end() ) {
2102 map_mark_new_dofs.
insert({Index_tag_new,
true});
2107 else if(rank1!=rank2 && (rank2 == rank)) {
2109 std::pair <mesh_int_t,mesh_int_t> Index_tag_old = std::make_pair(gIndex,tag2);
2110 if (map_vertex_tag_to_dof.find(Index_tag_old) == map_vertex_tag_to_dof.end() ) {
2111 map_vertex_tag_to_dof.insert({Index_tag_old,gIndex});
2114 std::pair <mesh_int_t,mesh_int_t> Index_tag_new = std::make_pair(gIndex,tag2);
2115 if (map_mark_new_dofs.
find(Index_tag_new) == map_mark_new_dofs.
end() ) {
2116 map_mark_new_dofs.
insert({Index_tag_new,
true});
2122 else if(data_on_gIndex==3)
2125 int count_intra_tags = 0;
2126 int count_extra_tags = 0;
2127 for (
int i = 0; i < first_index; ++i) {
2128 if(value.tags[i]!=-1 && extra_tags.
find(value.tags[i])==extra_tags.
end()){
2129 count_intra_tags += 1;
2130 }
else if(value.tags[i]!=-1 && extra_tags.
find(value.tags[i])!=extra_tags.
end()){
2131 count_extra_tags += 1;
2134 if(count_intra_tags!=2 || count_extra_tags == 0){
2137 "WARN: Due to an issue in defining ptsData for gIndex %d, on intersection between membrane and gapjunction"
2138 "the program is stopped while preparing the data structure to introduce DOFs.\n",
2140 fprintf(stderr,
"\n");
2146 for (
int i = 0; i < first_index; ++i) {
2148 auto pos_extra = extra_tags.
find(value.tags[i]);
2149 if(value.tags[i]!=-1 && value.ranks[i] == rank && pos_extra == extra_tags.
end()) {
2150 std::pair <mesh_int_t,mesh_int_t> Index_tag_new = std::make_pair(gIndex,value.tags[i]);
2151 if (map_mark_new_dofs.
find(Index_tag_new) == map_mark_new_dofs.
end() )
2153 map_mark_new_dofs.
insert({Index_tag_new,
true});
2161 vector<size_t> dsp_dof(size);
2162 MPI_Allgather(&shift,
sizeof(
size_t), MPI_BYTE, dsp_dof.data(),
sizeof(
size_t), MPI_BYTE, comm);
2177 start = mesh.g_numpts;
2181 start = mesh.g_numpts;
2182 for (
int r = 0; r < rank; ++r)
2189 auto lexicographic_comp_pair = [](
const std::pair<mesh_int_t,mesh_int_t> & a,
const std::pair<mesh_int_t,mesh_int_t> & b)
2191 if (a.second == b.second)
return a.first < b.first;
2192 return a.second < b.second;
2195 map_mark_new_dofs.
sort(lexicographic_comp_pair);
2197 for(
const auto & entry : map_mark_new_dofs)
2199 T newIndex = start+
count;
2200 map_vertex_tag_to_dof.insert({entry.first,newIndex});
2211 template<
class K,
class intersection_indices>
inline
2214 size_t dsize = map.
size();
2215 vector<K> key_vec(dsize);
2216 vector<intersection_indices> value_vec(dsize);
2217 intersection_indices indices;
2219 for (
const auto& v : map) {
2220 key_vec[idx] = v.first;
2221 value_vec[idx] = v.second;
2226 MPI_Comm_size(comm, &size); MPI_Comm_rank(comm, &rank);
2228 vector<int> perm, dest(dsize);
2229 for (
size_t i = 0; i < dsize; i++)
2232 commgraph<size_t> grph;
2233 grph.configure(dest, comm);
2234 size_t nrecv =
sum(grph.rcnt);
2240 vector<K> sbuff_key(dsize), rbuff_key(nrecv);
2241 vector<intersection_indices> sbuff_value(dsize), ibuff_value(dsize), rbuff_value(nrecv);
2242 for (
size_t i = 0; i < dsize; i++) {
2243 sbuff_key[i] = key_vec[perm[i]];
2244 sbuff_value[i] = value_vec[perm[i]];
2250 for (
size_t i = 0; i < nrecv; i++)
2252 auto it = rmap.
find(rbuff_key[i]);
2253 if (it != rmap.
end())
2255 intersection_indices& map_indices = it->second;
2256 intersection_indices& r_indices = rbuff_value[i];
2258 for (
int r_indices : r_indices.indices)
2260 if (r_indices == -1)
continue;
2262 for (
int m_index : map_indices.indices)
2264 if (m_index == r_indices) {
2271 for (
size_t k = 0; k < MAX_INTERSECTIONS; ++k) {
2272 if (map_indices.indices[k] == -1) {
2273 map_indices.indices[k] = r_indices;
2282 rmap.
insert({ rbuff_key[i], rbuff_value[i] });
2286 for (
size_t i = 0; i < nrecv; i++) {
2287 auto it = rmap.
find(rbuff_key[i]);
2288 if (it != rmap.
end()) rbuff_value[i] = it->second;
2295 for (
size_t i = 0; i < dsize; i++) {
2296 auto it = map.find(sbuff_key[i]);
2297 if (it != map.end()) it->second = ibuff_value[i];
2310 template<
class T,
class S>
inline
2311 void update_emi_mesh_with_dofs(meshdata<T,S> & mesh,
2319 MPI_Comm comm = mesh.comm;
2320 mesh.globalize(numbering);
2321 for(
size_t eidx = 0; eidx < mesh.l_numelem; eidx++) {
2322 T tag = mesh.tag[eidx];
2323 T size_elem = mesh.dsp[eidx+1]-mesh.dsp[eidx];
2325 for (
int n = mesh.dsp[eidx]; n < mesh.dsp[eidx+1];n++)
2327 T gIndex = mesh.con[n];
2329 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
2330 Index_tag_old = std::make_pair(gIndex,tag);
2332 auto it_new = map_vertex_tag_to_dof.find(Index_tag_old);
2333 if (it_new != map_vertex_tag_to_dof.end() )
2336 dof2vertex.
insert({dof_new, gIndex});
2337 mesh.con[n] = dof_new;
2339 auto it = vertex2dof.
find(gIndex);
2340 if (it != vertex2dof.
end())
2342 intersection_indices& indices = it->second;
2344 for(T t : indices.indices) {
2352 for(
size_t i=0; i<MAX_INTERSECTIONS; ++i) {
2353 if(indices.indices[i] == -1) {
2354 indices.indices[i] = dof_new;
2360 intersection_indices indices;
2361 indices.indices[0] = dof_new;
2362 vertex2dof.
insert({gIndex,indices});
2368 assign_counter_dofs(vertex2dof, comm);
2371 for (
const auto& [old_idx, indices] : vertex2dof) {
2372 for (
int new_idx : indices.indices) {
2373 if (new_idx != -1) {
2375 if (dof2vertex.
find(new_idx) == dof2vertex.
end()) {
2376 dof2vertex.
insert({new_idx, old_idx});
2382 mesh.localize(numbering);
2396 template<
class T,
class S>
inline
2397 void update_map_indices_to_petsc(meshdata<T,S> & mesh,
2398 const SF_nbr numbering_ref,
const SF_nbr numbering_petsc,
2401 std::pair<mesh_int_t,mesh_int_t>> & map_vertex_tag_to_dof_petsc,
2408 elemTag_emi_mesh.
resize(mesh.l_numelem);
2409 for(
size_t eidx = 0; eidx < mesh.l_numelem; eidx++) {
2410 T tag = mesh.tag[eidx];
2411 elemTag_emi_mesh[eidx] = 1;
2412 if(extra_tags.
find(tag) == extra_tags.
end())
2413 elemTag_emi_mesh[eidx] = 2;
2414 for (
int n = mesh.dsp[eidx]; n < mesh.dsp[eidx+1];n++)
2416 T l_Indx = mesh.con[n];
2417 T petsc_Idx = petsc_nbr[l_Indx];
2418 T n_Indx = ref_nbr[l_Indx];
2419 T o_Indx = dof2vertex[n_Indx];
2421 std::pair <mesh_int_t,mesh_int_t> oIndx_tag;
2422 oIndx_tag = std::make_pair(o_Indx,tag);
2424 auto it_new = map_vertex_tag_to_dof_petsc.find(oIndx_tag);
2425 if (it_new != map_vertex_tag_to_dof_petsc.end() )
2427 std::pair <mesh_int_t,mesh_int_t> nIndx_petsc;
2428 nIndx_petsc = std::make_pair(n_Indx,petsc_Idx);
2430 (*it_new).second = nIndx_petsc;
2448 template<
class T,
class S>
2449 inline void update_faces_on_surface_mesh_after_decoupling_with_dofs(meshdata<T, S> & mesh,
2453 std::pair<emi_face<T,tuple<T>>, emi_face<T,tuple<T>>>> & line_face,
2455 std::pair<emi_face<T,triple<T>>, emi_face<T,triple<T>>>> & tri_face,
2457 std::pair<emi_face<T,quadruple<T>>, emi_face<T,quadruple<T>>>> & quad_face)
2461 MPI_Comm_size(comm, &size); MPI_Comm_rank(comm, &rank);
2468 for(
size_t i=0; i<idxbuff.size(); i++){
2469 g2l[idxbuff[i]] = i;
2470 l2g[i] = idxbuff[i];
2473 for(
size_t eidx = 0; eidx < mesh.l_numelem; eidx++) {
2474 T tag = mesh.tag[eidx];
2475 T size_elem = mesh.dsp[eidx+1]-mesh.dsp[eidx];
2476 std::vector<int> elem_nodes;
2477 for (
int n = mesh.dsp[eidx]; n < mesh.dsp[eidx+1];n++)
2479 T gIndex = mesh.con[n];
2480 elem_nodes.push_back(gIndex);
2482 std::sort(elem_nodes.begin(),elem_nodes.end());
2483 if(elem_nodes.size()==2){
2485 key.v1 = elem_nodes[0];
2486 key.v2 = elem_nodes[1];
2487 std::pair<emi_face<T,tuple<T>>, emi_face<T,tuple<T>>> value = line_face[key];
2489 line_face.erase(key);
2490 std::vector<int> new_nodes(2);
2492 auto tag_key = (value.first.rank == rank) ? value.first.tag : value.second.tag;
2494 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
2495 Index_tag_old = std::make_pair(elem_nodes[0],tag_key);
2496 mesh_int_t Index_new = map_vertex_tag_to_dof[Index_tag_old];
2497 new_nodes[0] = Index_new;
2500 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
2501 Index_tag_old = std::make_pair(elem_nodes[1],tag_key);
2502 mesh_int_t Index_new = map_vertex_tag_to_dof[Index_tag_old];
2503 new_nodes[1] = Index_new;
2505 std::sort(new_nodes.begin(),new_nodes.end());
2508 new_key.v1 = new_nodes[0];
2509 new_key.v2 = new_nodes[1];
2513 mesh_int_t Index_new1 = map_vertex_tag_to_dof[std::make_pair(value.first.points.v1, value.first.tag)];
2514 mesh_int_t Index_new2 = map_vertex_tag_to_dof[std::make_pair(value.first.points.v2, value.first.tag)];
2515 value.first.points.v1 = Index_new1;
2516 value.first.points.v2 = Index_new2;
2520 mesh_int_t Index_new1 = map_vertex_tag_to_dof[std::make_pair(value.second.points.v1, value.second.tag)];
2521 mesh_int_t Index_new2 = map_vertex_tag_to_dof[std::make_pair(value.second.points.v2, value.second.tag)];
2522 value.second.points.v1 = Index_new1;
2523 value.second.points.v2 = Index_new2;
2525 line_face.insert({new_key,value});
2527 if(elem_nodes.size()==3){
2529 key.v1 = elem_nodes[0];
2530 key.v2 = elem_nodes[1];
2531 key.v3 = elem_nodes[2];
2532 std::pair<emi_face<T,triple<T>>, emi_face<T,triple<T>>> value = tri_face[key];
2533 tri_face.erase(key);
2534 std::vector<int> new_nodes(3);
2536 auto tag_key = (value.first.rank == rank) ? value.first.tag : value.second.tag;
2538 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
2539 Index_tag_old = std::make_pair(elem_nodes[0],tag_key);
2540 mesh_int_t Index_new = map_vertex_tag_to_dof[Index_tag_old];
2541 new_nodes[0] = Index_new;
2544 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
2545 Index_tag_old = std::make_pair(elem_nodes[1],tag_key);
2546 mesh_int_t Index_new = map_vertex_tag_to_dof[Index_tag_old];
2547 new_nodes[1] = Index_new;
2550 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
2551 Index_tag_old = std::make_pair(elem_nodes[2],tag_key);
2552 mesh_int_t Index_new = map_vertex_tag_to_dof[Index_tag_old];
2553 new_nodes[2] = Index_new;
2555 std::sort(new_nodes.begin(),new_nodes.end());
2558 new_key.v1 = new_nodes[0];
2559 new_key.v2 = new_nodes[1];
2560 new_key.v3 = new_nodes[2];
2564 mesh_int_t Index_new1 = map_vertex_tag_to_dof[std::make_pair(value.first.points.v1, value.first.tag)];
2565 mesh_int_t Index_new2 = map_vertex_tag_to_dof[std::make_pair(value.first.points.v2, value.first.tag)];
2566 mesh_int_t Index_new3 = map_vertex_tag_to_dof[std::make_pair(value.first.points.v3, value.first.tag)];
2567 value.first.points.v1 = Index_new1;
2568 value.first.points.v2 = Index_new2;
2569 value.first.points.v3 = Index_new3;
2573 mesh_int_t Index_new1 = map_vertex_tag_to_dof[std::make_pair(value.second.points.v1, value.second.tag)];
2574 mesh_int_t Index_new2 = map_vertex_tag_to_dof[std::make_pair(value.second.points.v2, value.second.tag)];
2575 mesh_int_t Index_new3 = map_vertex_tag_to_dof[std::make_pair(value.second.points.v3, value.second.tag)];
2576 value.second.points.v1 = Index_new1;
2577 value.second.points.v2 = Index_new2;
2578 value.second.points.v3 = Index_new3;
2580 tri_face.insert({new_key,value});
2582 if(elem_nodes.size()==4){
2584 key.v1 = elem_nodes[0];
2585 key.v2 = elem_nodes[1];
2586 key.v3 = elem_nodes[2];
2587 key.v4 = elem_nodes[3];
2588 std::pair<emi_face<T,quadruple<T>>, emi_face<T,quadruple<T>>> value = quad_face[key];
2589 quad_face.erase(key);
2590 std::vector<int> new_nodes(4);
2592 auto tag_key = (value.first.rank == rank) ? value.first.tag : value.second.tag;
2594 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
2595 Index_tag_old = std::make_pair(elem_nodes[0],tag_key);
2596 mesh_int_t Index_new = map_vertex_tag_to_dof[Index_tag_old];
2597 new_nodes[0] = Index_new;
2600 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
2601 Index_tag_old = std::make_pair(elem_nodes[1],tag_key);
2602 mesh_int_t Index_new = map_vertex_tag_to_dof[Index_tag_old];
2603 new_nodes[1] = Index_new;
2606 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
2607 Index_tag_old = std::make_pair(elem_nodes[2],tag_key);
2608 mesh_int_t Index_new = map_vertex_tag_to_dof[Index_tag_old];
2609 new_nodes[2] = Index_new;
2612 std::pair <mesh_int_t,mesh_int_t> Index_tag_old;
2613 Index_tag_old = std::make_pair(elem_nodes[3],tag_key);
2614 mesh_int_t Index_new = map_vertex_tag_to_dof[Index_tag_old];
2615 new_nodes[3] = Index_new;
2617 std::sort(new_nodes.begin(),new_nodes.end());
2619 quadruple<T> new_key;
2620 new_key.v1 = new_nodes[0];
2621 new_key.v2 = new_nodes[1];
2622 new_key.v3 = new_nodes[2];
2623 new_key.v4 = new_nodes[3];
2627 mesh_int_t Index_new1 = map_vertex_tag_to_dof[std::make_pair(value.first.points.v1, value.first.tag)];
2628 mesh_int_t Index_new2 = map_vertex_tag_to_dof[std::make_pair(value.first.points.v2, value.first.tag)];
2629 mesh_int_t Index_new3 = map_vertex_tag_to_dof[std::make_pair(value.first.points.v3, value.first.tag)];
2630 mesh_int_t Index_new4 = map_vertex_tag_to_dof[std::make_pair(value.first.points.v4, value.first.tag)];
2631 value.first.points.v1 = Index_new1;
2632 value.first.points.v2 = Index_new2;
2633 value.first.points.v3 = Index_new3;
2634 value.first.points.v4 = Index_new4;
2638 mesh_int_t Index_new1 = map_vertex_tag_to_dof[std::make_pair(value.second.points.v1, value.second.tag)];
2639 mesh_int_t Index_new2 = map_vertex_tag_to_dof[std::make_pair(value.second.points.v2, value.second.tag)];
2640 mesh_int_t Index_new3 = map_vertex_tag_to_dof[std::make_pair(value.second.points.v3, value.second.tag)];
2641 mesh_int_t Index_new4 = map_vertex_tag_to_dof[std::make_pair(value.second.points.v4, value.second.tag)];
2642 value.second.points.v1 = Index_new1;
2643 value.second.points.v2 = Index_new2;
2644 value.second.points.v3 = Index_new3;
2645 value.second.points.v4 = Index_new4;
2647 quad_face.insert({new_key,value});
2663 template<
class T,
class S>
inline
2664 void compute_surface_mesh_with_counter_face(meshdata<T, S> & mesh,
const SF_nbr numbering,
2666 std::pair<emi_face<T,tuple<T>>, emi_face<T,tuple<T>>>> & line_face,
2668 std::pair<emi_face<T,triple<T>>, emi_face<T,triple<T>>>> & tri_face,
2670 std::pair<emi_face<T,quadruple<T>>, emi_face<T,quadruple<T>>>> & quad_face)
2672 mesh.register_numbering(numbering);
2676 MPI_Comm_size(comm, &size);
2677 MPI_Comm_rank(comm, &rank);
2680 vector<tuple<T>> line_keys;
2681 for(
auto const& [key, val] : line_face) line_keys.push_back(key);
2682 std::sort(line_keys.begin(), line_keys.end());
2684 vector<triple<T>> tri_keys;
2685 for(
auto const& [key, val] : tri_face) tri_keys.push_back(key);
2686 std::sort(tri_keys.begin(), tri_keys.end());
2688 vector<quadruple<T>> quad_keys;
2689 for(
auto const& [key, val] : quad_face) quad_keys.push_back(key);
2690 std::sort(quad_keys.begin(), quad_keys.end());
2692 vector<T> cnt(mesh.l_numelem);
2693 size_t idx = 0, cidx = 0;
2698 for(
const auto & key : line_keys) {
2699 const auto & v = line_face.at(key);
2700 bool both_faces = (v.first.rank == v.second.rank) ?
true:
false;
2704 emi_face<T,tuple<T>> surf_first;
2705 emi_face<T,tuple<T>> surf_second;
2706 if(v.first.rank == rank)
2708 surf_first = v.first;
2709 surf_second = v.second;
2713 surf_first = v.second;
2714 surf_second = v.first;
2717 mesh.type[idx] =
Line;
2718 mesh.tag[idx] = surf_first.tag;
2719 mesh.con[cidx + 0] = surf_first.points.v1;
2720 mesh.con[cidx + 1] = surf_first.points.v2;
2727 mesh.type[idx] =
Line;
2728 mesh.tag[idx] = surf_second.tag;
2729 mesh.con[cidx + 0] = surf_second.points.v1;
2730 mesh.con[cidx + 1] = surf_second.points.v2;
2737 for(
const auto & key : tri_keys) {
2738 const auto & v = tri_face.at(key);
2739 bool both_faces = (v.first.rank == v.second.rank) ?
true:
false;
2743 emi_face<T,triple<T>> surf_first;
2744 emi_face<T,triple<T>> surf_second;
2745 if(v.first.rank == rank)
2747 surf_first = v.first;
2748 surf_second = v.second;
2752 surf_first = v.second;
2753 surf_second = v.first;
2756 mesh.type[idx] =
Tri;
2757 mesh.tag[idx] = surf_first.tag;
2758 mesh.con[cidx + 0] = surf_first.points.v1;
2759 mesh.con[cidx + 1] = surf_first.points.v2;
2760 mesh.con[cidx + 2] = surf_first.points.v3;
2769 mesh.type[idx] =
Tri;
2770 mesh.tag[idx] = surf_second.tag;
2771 mesh.con[cidx + 0] = surf_second.points.v1;
2772 mesh.con[cidx + 1] = surf_second.points.v2;
2773 mesh.con[cidx + 2] = surf_second.points.v3;
2780 for(
const auto & key : quad_keys) {
2781 const auto & v = quad_face.at(key);
2782 bool both_faces = (v.first.rank == v.second.rank) ?
true:
false;
2785 emi_face<T,quadruple<T>> surf_first;
2786 emi_face<T,quadruple<T>> surf_second;
2787 if(v.first.rank == rank)
2789 surf_first = v.first;
2790 surf_second = v.second;
2794 surf_first = v.second;
2795 surf_second = v.first;
2798 mesh.type[idx] =
Quad;
2799 mesh.tag[idx] = surf_first.tag;
2800 mesh.con[cidx + 0] = surf_first.points.v1;
2801 mesh.con[cidx + 1] = surf_first.points.v2;
2802 mesh.con[cidx + 2] = surf_first.points.v3;
2803 mesh.con[cidx + 3] = surf_first.points.v4;
2812 mesh.type[idx] =
Quad;
2813 mesh.tag[idx] = surf_second.tag;
2814 mesh.con[cidx + 0] = surf_second.points.v1;
2815 mesh.con[cidx + 1] = surf_second.points.v2;
2816 mesh.con[cidx + 2] = surf_second.points.v3;
2817 mesh.con[cidx + 3] = surf_second.points.v4;
2856 template<
class T,
class S>
inline
2857 void compute_surface_mesh_with_unique_face(meshdata<T, S> & mesh,
const SF_nbr numbering,
2859 std::pair<emi_face<T,tuple<T>>, emi_face<T,tuple<T>>>> & line_face,
2861 std::pair<emi_face<T,triple<T>>, emi_face<T,triple<T>>>> & tri_face,
2863 std::pair<emi_face<T,quadruple<T>>, emi_face<T,quadruple<T>>>> & quad_face,
2866 mesh.register_numbering(numbering);
2870 MPI_Comm_size(comm, &size);
2871 MPI_Comm_rank(comm, &rank);
2874 vector<tuple<T>> line_keys;
2875 for(
auto const& [key, val] : line_face) line_keys.push_back(key);
2876 std::sort(line_keys.begin(), line_keys.end());
2878 vector<triple<T>> tri_keys;
2879 for(
auto const& [key, val] : tri_face) tri_keys.push_back(key);
2880 std::sort(tri_keys.begin(), tri_keys.end());
2882 vector<quadruple<T>> quad_keys;
2883 for(
auto const& [key, val] : quad_face) quad_keys.push_back(key);
2884 std::sort(quad_keys.begin(), quad_keys.end());
2886 vector<T> cnt(mesh.l_numelem);
2887 size_t idx = 0, cidx = 0;
2892 for(
const auto & key : line_keys) {
2893 const auto & v = line_face.at(key);
2895 bool to_take_face =
false;
2897 emi_face<T,tuple<T>> surf_take;
2898 std::pair <mesh_int_t,mesh_int_t> tag_pairs_take;
2900 if(v.first.rank == rank && v.first.mark_to_take ==
true)
2902 surf_take = v.first;
2903 to_take_face =
true;
2904 tag_pairs_take = std::make_pair(v.first.tag,v.second.tag);
2906 else if(v.second.rank == rank && v.second.mark_to_take ==
true)
2908 surf_take = v.second;
2909 to_take_face =
true;
2910 tag_pairs_take = std::make_pair(v.second.tag,v.first.tag);
2915 map_elem_uniqueFace_to_tags.insert({idx,tag_pairs_take});
2917 mesh.type[idx] =
Line;
2918 mesh.tag[idx] = surf_take.tag;
2919 mesh.con[cidx + 0] = surf_take.points.v1;
2920 mesh.con[cidx + 1] = surf_take.points.v2;
2927 for(
const auto & key : tri_keys) {
2928 const auto & v = tri_face.at(key);
2930 bool to_take_face =
false;
2932 emi_face<T,triple<T>> surf_take;
2933 std::pair <mesh_int_t,mesh_int_t> tag_pairs_take;
2935 if(v.first.rank == rank && v.first.mark_to_take ==
true)
2937 surf_take = v.first;
2938 to_take_face =
true;
2939 tag_pairs_take = std::make_pair(v.first.tag,v.second.tag);
2941 else if(v.second.rank == rank && v.second.mark_to_take ==
true)
2943 surf_take = v.second;
2944 to_take_face =
true;
2945 tag_pairs_take = std::make_pair(v.second.tag,v.first.tag);
2950 map_elem_uniqueFace_to_tags.insert({idx,tag_pairs_take});
2952 mesh.type[idx] =
Tri;
2953 mesh.tag[idx] = surf_take.tag;
2954 mesh.con[cidx + 0] = surf_take.points.v1;
2955 mesh.con[cidx + 1] = surf_take.points.v2;
2956 mesh.con[cidx + 2] = surf_take.points.v3;
2964 for(
const auto & key : quad_keys) {
2965 const auto & v = quad_face.at(key);
2968 bool to_take_face =
false;
2970 emi_face<T,quadruple<T>> surf_take;
2971 std::pair <mesh_int_t,mesh_int_t> tag_pairs_take;
2973 if(v.first.rank == rank && v.first.mark_to_take ==
true)
2975 surf_take = v.first;
2976 to_take_face =
true;
2977 tag_pairs_take = std::make_pair(v.first.tag,v.second.tag);
2979 else if(v.second.rank == rank && v.second.mark_to_take ==
true)
2981 surf_take = v.second;
2982 to_take_face =
true;
2983 tag_pairs_take = std::make_pair(v.second.tag,v.first.tag);
2988 map_elem_uniqueFace_to_tags.insert({idx,tag_pairs_take});
2990 mesh.type[idx] =
Quad;
2991 mesh.tag[idx] = surf_take.tag;
2992 mesh.con[cidx + 0] = surf_take.points.v1;
2993 mesh.con[cidx + 1] = surf_take.points.v2;
2994 mesh.con[cidx + 2] = surf_take.points.v3;
2995 mesh.con[cidx + 3] = surf_take.points.v4;
3024 template<
class T>
inline
3025 void create_reverse_elem_mapping_between_surface_meshes(
3028 hashmap::unordered_map<quadruple<T>, std::pair<emi_face<T,quadruple<T>>, emi_face<T,quadruple<T>>>>& quad_face,
3033 MPI_Comm_rank(comm, &rank);
3036 vector<tuple<T>> line_keys;
3037 for(
auto const& [key, val] : line_face) line_keys.push_back(key);
3038 std::sort(line_keys.begin(), line_keys.end());
3040 vector<triple<T>> tri_keys;
3041 for(
auto const& [key, val] : tri_face) tri_keys.push_back(key);
3042 std::sort(tri_keys.begin(), tri_keys.end());
3044 vector<quadruple<T>> quad_keys;
3045 for(
auto const& [key, val] : quad_face) quad_keys.push_back(key);
3046 std::sort(quad_keys.begin(), quad_keys.end());
3048 size_t surf_elem_idx = 0;
3049 size_t w_counter_elem_idx = 0;
3051 size_t lsize_line = 0;
3052 size_t lsize_tri = 0;
3053 size_t lsize_quad = 0;
3057 for(
const auto& key : line_keys) {
3058 const auto& v = line_face.at(key);
3059 const bool local_involved = (v.first.rank == rank) || (v.second.rank == rank);
3060 if (!local_involved) {
3063 if(v.first.rank == v.second.rank) lsize_line+=2;
3066 for(
const auto& key : tri_keys) {
3067 const auto& v = tri_face.at(key);
3068 const bool local_involved = (v.first.rank == rank) || (v.second.rank == rank);
3069 if (!local_involved) {
3072 if(v.first.rank == v.second.rank) lsize_tri+=2;
3075 for(
const auto& key : quad_keys) {
3076 const auto& v = quad_face.at(key);
3077 const bool local_involved = (v.first.rank == rank) || (v.second.rank == rank);
3078 if (!local_involved) {
3081 if(v.first.rank == v.second.rank) lsize_quad+=2;
3085 vec_one_to_both_face.
resize(lsize_line + lsize_tri + lsize_quad);
3089 for (
const auto& key : line_keys) {
3090 const auto& v = line_face.at(key);
3091 const bool local_involved = (v.first.rank == rank) || (v.second.rank == rank);
3092 if (!local_involved) {
3095 vec_one_to_both_face[w_counter_elem_idx++] = surf_elem_idx;
3096 if (v.first.rank == v.second.rank) {
3097 vec_one_to_both_face[w_counter_elem_idx++] = surf_elem_idx;
3102 for (
const auto& key : tri_keys) {
3103 const auto& v = tri_face.at(key);
3104 const bool local_involved = (v.first.rank == rank) || (v.second.rank == rank);
3105 if (!local_involved) {
3108 vec_one_to_both_face[w_counter_elem_idx++] = surf_elem_idx;
3109 if (v.first.rank == v.second.rank) {
3110 vec_one_to_both_face[w_counter_elem_idx++] = surf_elem_idx;
3115 for (
const auto& key : quad_keys) {
3116 const auto& v = quad_face.at(key);
3117 const bool local_involved = (v.first.rank == rank) || (v.second.rank == rank);
3118 if (!local_involved) {
3121 vec_one_to_both_face[w_counter_elem_idx++] = surf_elem_idx;
3122 if (v.first.rank == v.second.rank) {
3123 vec_one_to_both_face[w_counter_elem_idx++] = surf_elem_idx;
3137 template<
class T>
inline
3139 std::pair<emi_face<T,tuple<T>>, emi_face<T,tuple<T>>>> & line_face,
3141 std::pair<emi_face<T,triple<T>>, emi_face<T,triple<T>>>> & tri_face,
3143 std::pair<emi_face<T,quadruple<T>>, emi_face<T,quadruple<T>>>> & quad_face)
3145 for(
const auto & v : line_face) {
3146 SF::emi_face<mesh_int_t,SF::tuple<mesh_int_t>> surf_first = v.second.first;
3147 SF::emi_face<mesh_int_t,SF::tuple<mesh_int_t>> surf_second = v.second.second;
3149 std::vector<mesh_int_t> elem_nodes_first; elem_nodes_first.
resize(2);
3150 std::vector<mesh_int_t> elem_nodes_second; elem_nodes_second.resize(2);
3153 elem_nodes_first[0] = surf_first.points.
v1;
3154 elem_nodes_first[1] = surf_first.points.v2;
3155 std::sort(elem_nodes_first.begin(),elem_nodes_first.end());
3156 key_first.
v1 = elem_nodes_first[0];
3157 key_first.
v2 = elem_nodes_first[1];
3160 elem_nodes_second[0] = surf_second.points.
v1;
3161 elem_nodes_second[1] = surf_second.points.v2;
3162 std::sort(elem_nodes_second.begin(),elem_nodes_second.end());
3163 key_second.
v1 = elem_nodes_second[0];
3164 key_second.
v2 = elem_nodes_second[1];
3166 if(v.first.v1!=key_first.
v1 and v.first.v2!=key_first.
v2){
3167 line_face.insert({key_first,v.second});
3169 if(v.first.v1!=key_second.
v1 and v.first.v2!=key_second.
v2){
3170 line_face.insert({key_second,v.second});
3175 for(
const auto & v : tri_face) {
3176 SF::emi_face<mesh_int_t,SF::triple<mesh_int_t>> surf_first = v.second.first;
3177 SF::emi_face<mesh_int_t,SF::triple<mesh_int_t>> surf_second = v.second.second;
3179 std::vector<mesh_int_t> elem_nodes_first; elem_nodes_first.resize(3);
3180 std::vector<mesh_int_t> elem_nodes_second; elem_nodes_second.resize(3);
3183 elem_nodes_first[0] = surf_first.points.
v1;
3184 elem_nodes_first[1] = surf_first.points.v2;
3185 elem_nodes_first[2] = surf_first.points.v3;
3186 std::sort(elem_nodes_first.begin(),elem_nodes_first.end());
3187 key_first.
v1 = elem_nodes_first[0];
3188 key_first.
v2 = elem_nodes_first[1];
3189 key_first.
v3 = elem_nodes_first[2];
3192 elem_nodes_second[0] = surf_second.points.
v1;
3193 elem_nodes_second[1] = surf_second.points.v2;
3194 elem_nodes_second[2] = surf_second.points.v3;
3195 std::sort(elem_nodes_second.begin(),elem_nodes_second.end());
3196 key_second.
v1 = elem_nodes_second[0];
3197 key_second.
v2 = elem_nodes_second[1];
3198 key_second.
v3 = elem_nodes_second[2];
3200 if(v.first.v1!=key_first.
v1 and v.first.v2!=key_first.
v2 and v.first.v3!=key_first.
v3){
3201 tri_face.insert({key_first,v.second});
3203 if(v.first.v1!=key_second.
v1 and v.first.v2!=key_second.
v2 and v.first.v3!=key_second.
v3){
3204 tri_face.insert({key_second,v.second});
3208 for(
const auto & v : quad_face) {
3209 SF::emi_face<mesh_int_t,SF::quadruple<mesh_int_t>> surf_first = v.second.first;
3210 SF::emi_face<mesh_int_t,SF::quadruple<mesh_int_t>> surf_second = v.second.second;
3212 std::vector<mesh_int_t> elem_nodes_first; elem_nodes_first.resize(4);
3213 std::vector<mesh_int_t> elem_nodes_second; elem_nodes_second.resize(4);
3216 elem_nodes_first[0] = surf_first.points.
v1;
3217 elem_nodes_first[1] = surf_first.points.v2;
3218 elem_nodes_first[2] = surf_first.points.v3;
3219 elem_nodes_first[3] = surf_first.points.v4;
3220 std::sort(elem_nodes_first.begin(),elem_nodes_first.end());
3221 key_first.
v1 = elem_nodes_first[0];
3222 key_first.
v2 = elem_nodes_first[1];
3223 key_first.
v3 = elem_nodes_first[2];
3224 key_first.
v4 = elem_nodes_first[3];
3227 elem_nodes_second[0] = surf_second.points.
v1;
3228 elem_nodes_second[1] = surf_second.points.v2;
3229 elem_nodes_second[2] = surf_second.points.v3;
3230 elem_nodes_second[3] = surf_second.points.v4;
3231 std::sort(elem_nodes_second.begin(),elem_nodes_second.end());
3232 key_second.
v1 = elem_nodes_second[0];
3233 key_second.
v2 = elem_nodes_second[1];
3234 key_second.
v3 = elem_nodes_second[2];
3235 key_second.
v4 = elem_nodes_second[3];
3237 if(v.first.v1!=key_first.
v1 and v.first.v2!=key_first.
v2 and v.first.v3!=key_first.
v3 and v.first.v4!=key_first.
v4){
3238 quad_face.insert({key_first,v.second});
3240 if(v.first.v1!=key_second.
v1 and v.first.v2!=key_second.
v2 and v.first.v3!=key_second.
v3 and v.first.v4!=key_second.
v4){
3241 quad_face.insert({key_second,v.second});
3252 template<
class K>
inline
3255 size_t dsize = map.
size();
3256 vector<K> key_vec(dsize);
3257 vector<intersection_tags> value_vec(dsize);
3260 for (
const auto& v : map) {
3261 key_vec[idx] = v.first;
3262 value_vec[idx] = v.second;
3267 MPI_Comm_size(comm, &size); MPI_Comm_rank(comm, &rank);
3269 vector<int> perm, dest(dsize);
3270 for (
size_t i = 0; i < dsize; i++)
3273 commgraph<size_t> grph;
3274 grph.configure(dest, comm);
3275 size_t nrecv =
sum(grph.rcnt);
3281 vector<K> sbuff_key(dsize), rbuff_key(nrecv);
3282 vector<intersection_tags> sbuff_value(dsize), ibuff_value(dsize), rbuff_value(nrecv);
3283 for (
size_t i = 0; i < dsize; i++) {
3284 sbuff_key[i] = key_vec[perm[i]];
3285 sbuff_value[i] = value_vec[perm[i]];
3291 for (
size_t i = 0; i < nrecv; i++)
3293 auto it = rmap.
find(rbuff_key[i]);
3294 if (it != rmap.
end())
3296 intersection_tags& map_tags = it->second;
3297 intersection_tags& r_tags = rbuff_value[i];
3299 for (
int r_tag : r_tags.tags)
3301 if (r_tag == -1)
continue;
3303 for (
int m_tag : map_tags.tags)
3305 if (m_tag == r_tag) {
3312 for (
size_t k = 0; k < MAX_INTERSECTIONS; ++k) {
3313 if (map_tags.tags[k] == -1) {
3314 map_tags.tags[k] = r_tag;
3323 rmap.
insert({ rbuff_key[i], rbuff_value[i] });
3327 for (
size_t i = 0; i < nrecv; i++) {
3328 auto it = rmap.
find(rbuff_key[i]);
3329 if (it != rmap.
end()) rbuff_value[i] = it->second;
3336 for (
size_t i = 0; i < dsize; i++) {
3337 auto it = map.find(sbuff_key[i]);
3338 if (it != map.end()) it->second = ibuff_value[i];
3363 template<
class T,
class S>
inline
3364 void compute_ptsdata_from_original_mesh(meshdata<T,S> & mesh,
3370 MPI_Comm comm = mesh.comm;
3372 MPI_Comm_size(comm, &size);
3373 MPI_Comm_rank(comm, &rank);
3375 const T* con = mesh.con.data();
3382 for(
size_t eidx = 0; eidx < mesh.l_numelem; eidx++)
3384 T tag = mesh.tag[eidx];
3385 for (
int n = mesh.dsp[eidx]; n < mesh.dsp[eidx+1];n++)
3387 T gIndex = rnod[con[n]];
3389 auto it_new = map_index_to_tags.
find(gIndex);
3390 if (it_new != map_index_to_tags.
end())
3393 intersection_tags& tags = it_new->second;
3395 for(T t : tags.tags) {
3403 for(
int i=0; i <MAX_INTERSECTIONS; ++i) {
3404 if (tags.tags[i] == -1) {
3413 intersection_tags tags;
3415 map_index_to_tags.
insert({gIndex,tags});
3423 assign_counter_tags(map_index_to_tags, comm);
3426 for(
size_t eidx = 0; eidx < mesh.l_numelem; eidx++)
3428 for (
int n = mesh.dsp[eidx]; n < mesh.dsp[eidx+1];n++)
3430 T gIndex = rnod[con[n]];
3431 intersection_tags& vec_tags = map_index_to_tags[gIndex];
3432 int count_intra_tags = 0;
3433 int count_extra_tags = 0;
3437 for(T t : vec_tags.tags) {
3438 if(intra_tags.
count(t)) count_intra_tags++;
3439 if(extra_tags.
count(t)) count_extra_tags++;
3443 if(count_extra_tags>=1 && count_intra_tags==0){
3444 vertex2ptsdata[gIndex] = 0;
3445 }
else if(count_extra_tags==0 && count_intra_tags==1){
3446 vertex2ptsdata[gIndex] = 0;
3447 }
else if(count_extra_tags>=1 && count_intra_tags==1){
3448 vertex2ptsdata[gIndex] = 1;
3449 }
else if(count_extra_tags==0 && count_intra_tags==2){
3450 vertex2ptsdata[gIndex] = 2;
3451 }
else if(count_extra_tags>=1 && count_intra_tags==2){
3452 vertex2ptsdata[gIndex] = 3;
3454 else if(count_intra_tags>2){
3456 fprintf(stderr,
"More than two intracellular are connected %d. Tags:", gIndex);
3457 for(T tag : vec_tags.tags)
if(tag != -1) fprintf(stderr,
" %d", tag);
3458 fprintf(stderr,
"\n");
3463 fprintf(stderr,
"WARN: unhandled case in ptsData computation for gIndex %d. Tags:", gIndex);
3464 for(T tag : vec_tags.tags)
if(tag != -1) fprintf(stderr,
" %d", tag);
3465 fprintf(stderr,
"\n");
3480 template <
class T,
class S,
class V,
class emi_index_rank>
3483 std::pair<emi_index_rank, emi_index_rank>>& map,
3488 MPI_Comm_rank(both_mesh.
comm, &rank);
3491 SF::layout_from_count<long int>(both_mesh.
l_numelem, layout_both, both_mesh.
comm);
3494 SF::layout_from_count<long int>(unique_mesh.
l_numelem, layout_unique, unique_mesh.
comm);
3500 for (
const auto& [local_unique_idx, both_pair] : map) {
3501 const auto& first_both = both_pair.first;
3502 const auto& second_both = both_pair.second;
3505 T global_unique_row = layout_unique[rank] + local_unique_idx;
3506 row_idx[0] = global_unique_row;
3509 bool first_valid = (first_both.index >= 0 && first_both.rank >= 0);
3510 bool second_valid = (second_both.index >= 0 && second_both.rank >= 0);
3512 T global_both_col_first = -1;
3513 T global_both_col_second = -1;
3515 global_both_col_first = layout_both[first_both.rank] + first_both.index;
3518 global_both_col_second = layout_both[second_both.rank] + second_both.index;
3522 if (first_valid && second_valid && global_both_col_first == global_both_col_second) {
3523 second_valid =
false;
3528 if (first_valid)
count++;
3529 if (second_valid)
count++;
3531 if (
count == 0)
continue;
3533 double weight = 0.5;
3534 if (
count == 1) weight = 1.0;
3536 ebuff.assign(1, 1, weight);
3540 col_idx[0] = global_both_col_first;
3541 op.
set_values(row_idx, col_idx, ebuff.data(),
false);
3546 col_idx[0] = global_both_col_second;
3547 op.
set_values(row_idx, col_idx, ebuff.data(),
false);
3576 for(
size_t i=0; i<rnod.
size(); i++){
3583 for(
size_t i=0; i<v.size(); i++){
3586 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)