21 #ifndef THUNDEREGG_SCHUR_InterfaceDomain_H
22 #define THUNDEREGG_SCHUR_InterfaceDomain_H
58 std::array<int, D - 1> iface_ns;
65 std::vector<std::shared_ptr<const PatchIfaceInfo<D>>> piinfos;
70 std::vector<std::shared_ptr<const Interface<D>>> interfaces;
74 int num_global_ifaces = 0;
84 static void IndexIfacesLocal(
const std::map<
int, std::shared_ptr<
Interface<D>>>& id_to_iface_map,
88 int curr_local_index = 0;
92 interfaces.reserve(id_to_iface_map.size());
93 for (
auto pair : id_to_iface_map) {
94 auto iface = pair.second;
96 iface->local_index = curr_local_index;
97 interfaces.push_back(iface);
99 for (
auto patch : iface->patches) {
100 if (patch.type.isNormal() || patch.type.isFineToFine() || patch.type.isCoarseToCoarse()) {
101 patch.getNonConstPiinfo()->getIfaceInfo(patch.side)->patch_local_index = curr_local_index;
102 patch.getNonConstPiinfo()->getIfaceInfo(patch.side)->col_local_index = curr_local_index;
103 patch.getNonConstPiinfo()->getIfaceInfo(patch.side)->row_local_index = curr_local_index;
104 }
else if (patch.type.isFineToCoarse()) {
105 patch.getNonConstPiinfo()->getCoarseIfaceInfo(patch.side)->coarse_col_local_index =
107 }
else if (patch.type.isCoarseToFine()) {
108 auto iface_info = patch.getNonConstPiinfo()->getFineIfaceInfo(patch.side);
109 for (
size_t i = 0; i < iface_info->fine_col_local_indexes.size(); i++) {
110 if (iface_info->fine_ids[i] == iface->id) {
111 iface_info->fine_col_local_indexes[i] = curr_local_index;
122 IndexRemainingColIfacesLocal(curr_local_index, interfaces);
123 IndexRemainingRowIfacesLocal(curr_local_index, interfaces);
124 IndexRemainingPatchIfacesLocal(curr_local_index, piinfos);
132 static void GetRemainginColIfacesLocalForPatch(
134 std::map<
int, std::set<int*>>& id_to_local_indexes_to_set)
137 if (piinfo->pinfo.hasNbr(s)) {
138 auto iface_info = piinfo->getIfaceInfo(s);
139 if (iface_info->col_local_index == -1) {
140 id_to_local_indexes_to_set[iface_info->id].insert(&iface_info->col_local_index);
143 NbrType nbr_type = piinfo->pinfo.getNbrType(s);
146 auto coarse_iface_info = piinfo->getCoarseIfaceInfo(s);
147 if (coarse_iface_info->coarse_col_local_index == -1) {
148 id_to_local_indexes_to_set[coarse_iface_info->coarse_id].insert(
149 &coarse_iface_info->coarse_col_local_index);
152 auto fine_iface_info = piinfo->getFineIfaceInfo(s);
153 for (
size_t i = 0; i < fine_iface_info->fine_col_local_indexes.size(); i++) {
154 if (fine_iface_info->fine_col_local_indexes[i] == -1) {
155 id_to_local_indexes_to_set[fine_iface_info->fine_ids[i]].insert(
156 &fine_iface_info->fine_col_local_indexes[i]);
169 static void IndexRemainingColIfacesLocal(
170 int curr_local_index,
171 const std::vector<std::shared_ptr<
Interface<D>>>& interfaces)
173 std::map<int, std::set<int*>> id_to_local_indexes_to_set;
174 for (
auto iface : interfaces) {
175 for (
auto patch : iface->patches) {
176 auto piinfo = patch.getNonConstPiinfo();
178 if (patch.type.isNormal() || patch.type.isFineToFine() || patch.type.isCoarseToCoarse()) {
179 GetRemainginColIfacesLocalForPatch(piinfo, id_to_local_indexes_to_set);
183 for (
auto id_and_local_indexes : id_to_local_indexes_to_set) {
184 for (
int* local_index_to_set : id_and_local_indexes.second) {
185 *local_index_to_set = curr_local_index;
196 static void IndexRemainingRowIfacesLocal(
197 int curr_local_index,
198 const std::vector<std::shared_ptr<
Interface<D>>>& interfaces)
200 std::map<int, std::set<int*>> id_to_local_indexes_to_set;
201 for (
auto iface : interfaces) {
202 for (
auto patch : iface->patches) {
203 auto piinfo = patch.getNonConstPiinfo();
206 if (piinfo->pinfo.hasNbr(s)) {
207 auto iface_info = piinfo->getIfaceInfo(s);
209 if (iface_info->row_local_index == -1) {
210 id_to_local_indexes_to_set[iface_info->id].insert(&iface_info->row_local_index);
216 for (
auto id_and_local_indexes : id_to_local_indexes_to_set) {
217 for (
int* local_index_to_set : id_and_local_indexes.second) {
218 *local_index_to_set = curr_local_index;
229 static void IndexRemainingPatchIfacesLocal(
230 int curr_local_index,
233 for (
auto piinfo : piinfos) {
235 if (piinfo->pinfo.hasNbr(s)) {
236 auto iface_info = piinfo->getIfaceInfo(s);
238 if (iface_info->patch_local_index == -1) {
239 iface_info->patch_local_index = curr_local_index;
252 static void IndexIfacesGlobal(
const std::vector<std::shared_ptr<
Interface<D>>>& interfaces,
256 int starting_global_index;
257 int num_local_interfaces = (int)interfaces.size();
258 MPI_Scan(&num_local_interfaces, &starting_global_index, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
259 starting_global_index -= num_local_interfaces;
262 for (
auto iface : interfaces) {
263 iface->global_index = starting_global_index + iface->local_index;
265 for (
auto patch : iface->patches) {
266 if (patch.type.isNormal() || patch.type.isFineToFine() || patch.type.isCoarseToCoarse()) {
267 auto iface_info = patch.getNonConstPiinfo()->getIfaceInfo(patch.side);
268 iface_info->global_index = iface->global_index;
269 }
else if (patch.type.isFineToCoarse()) {
270 auto iface_info = patch.getNonConstPiinfo()->getCoarseIfaceInfo(patch.side);
271 iface_info->coarse_global_index = iface->global_index;
272 }
else if (patch.type.isCoarseToFine()) {
273 auto iface_info = patch.getNonConstPiinfo()->getFineIfaceInfo(patch.side);
274 for (
size_t i = 0; i < iface_info->fine_col_local_indexes.size(); i++) {
275 if (iface_info->fine_ids[i] == iface->id) {
276 iface_info->fine_global_indexes[i] = iface->global_index;
283 SendAndReceiveGlobalIndexes(interfaces, piinfos);
291 static void SendAndReceiveGlobalIndexes(
292 const std::vector<std::shared_ptr<
Interface<D>>>& interfaces,
295 std::map<int, std::map<int, std::set<int*>>> rank_to_id_to_global_indexes_to_set;
296 std::deque<std::vector<int>> recv_buffers;
297 std::vector<MPI_Request> recv_requests;
298 SetupGlobalIndexRecvRequests(
299 interfaces, piinfos, rank_to_id_to_global_indexes_to_set, recv_buffers, recv_requests);
301 std::deque<std::vector<int>> send_buffers;
302 std::vector<MPI_Request> send_requests;
303 SetupGlobalIndexSendRequests(interfaces, send_buffers, send_requests);
305 size_t num_recvs = recv_requests.size();
306 for (
size_t i = 0; i < num_recvs; i++) {
309 MPI_Waitany(recv_requests.size(), recv_requests.data(), &index, &status);
310 const std::vector<int>& buffer = recv_buffers[index];
311 const auto& id_to_global_indexes_to_set =
312 rank_to_id_to_global_indexes_to_set[status.MPI_SOURCE];
315 size_t curr_index = 0;
316 for (
auto pair : id_to_global_indexes_to_set) {
317 for (
int* global_index_to_set : pair.second) {
318 *global_index_to_set = buffer[curr_index];
324 MPI_Waitall((
int)send_requests.size(), send_requests.data(), MPI_STATUSES_IGNORE);
337 static void SetupGlobalIndexRecvRequests(
338 const std::vector<std::shared_ptr<
Interface<D>>>& interfaces,
340 std::map<
int, std::map<
int, std::set<int*>>>& rank_to_id_to_global_indexes_to_set,
341 std::deque<std::vector<int>>& recv_buffers,
342 std::vector<MPI_Request>& recv_requests)
344 GetGlobalIndexesToSet(interfaces, piinfos, rank_to_id_to_global_indexes_to_set);
346 for (
auto pair : rank_to_id_to_global_indexes_to_set) {
347 recv_buffers.emplace_back(pair.second.size());
349 MPI_Irecv(recv_buffers.back().data(),
350 (
int)recv_buffers.back().size(),
356 recv_requests.push_back(request);
366 static void GetGlobalIndexesToSetForOuterInterfaces(
368 std::map<
int, std::map<
int, std::set<int*>>>& rank_to_id_to_global_indexes_to_set)
371 if (piinfo->pinfo.hasNbr(s)) {
372 NbrType nbr_type = piinfo->pinfo.getNbrType(s);
375 auto coarse_iface_info = piinfo->getCoarseIfaceInfo(s);
376 if (coarse_iface_info->coarse_global_index == -1) {
377 rank_to_id_to_global_indexes_to_set[coarse_iface_info->coarse_rank]
378 [coarse_iface_info->coarse_id]
379 .insert(&coarse_iface_info->coarse_global_index);
382 auto fine_iface_info = piinfo->getFineIfaceInfo(s);
383 for (
size_t i = 0; i < fine_iface_info->fine_global_indexes.size(); i++) {
384 if (fine_iface_info->fine_global_indexes[i] == -1) {
385 rank_to_id_to_global_indexes_to_set[fine_iface_info->fine_ranks[i]]
386 [fine_iface_info->fine_ids[i]]
388 &fine_iface_info->fine_global_indexes[i]);
403 static void GetGlobalIndexesToSet(
404 const std::vector<std::shared_ptr<
Interface<D>>>& interfaces,
406 std::map<
int, std::map<
int, std::set<int*>>>& rank_to_id_to_global_indexes_to_set)
409 GetGlobalIndexesToSetForPatchInterfaces(piinfos, rank_to_id_to_global_indexes_to_set);
412 for (
auto iface : interfaces) {
413 for (
auto patch : iface->patches) {
414 auto piinfo = patch.getNonConstPiinfo();
419 if (piinfo->pinfo.hasNbr(s)) {
420 auto iface_info = piinfo->getIfaceInfo(s);
422 if (iface_info->global_index == -1) {
423 rank_to_id_to_global_indexes_to_set[iface_info->rank][iface_info->id].insert(
424 &iface_info->global_index);
429 if (patch.type.isNormal() || patch.type.isFineToFine() || patch.type.isCoarseToCoarse()) {
431 GetGlobalIndexesToSetForOuterInterfaces(piinfo, rank_to_id_to_global_indexes_to_set);
443 static void GetGlobalIndexesToSetForPatchInterfaces(
445 std::map<
int, std::map<
int, std::set<int*>>>& rank_to_id_to_global_indexes_to_set)
447 for (
auto piinfo : piinfos) {
449 if (piinfo->pinfo.hasNbr(s)) {
450 auto iface_info = piinfo->getIfaceInfo(s);
452 if (iface_info->global_index == -1) {
453 rank_to_id_to_global_indexes_to_set[iface_info->rank][iface_info->id].insert(
454 &iface_info->global_index);
468 static void SetupGlobalIndexSendRequests(
469 const std::vector<std::shared_ptr<
Interface<D>>>& interfaces,
470 std::deque<std::vector<int>>& send_buffers,
471 std::vector<MPI_Request>& send_requests)
473 std::map<int, std::set<std::pair<int, int>>> rank_to_id_and_global_index_pairs;
474 GetGlobalIndexesToSend(interfaces, rank_to_id_and_global_index_pairs);
476 for (
auto pair : rank_to_id_and_global_index_pairs) {
477 send_buffers.emplace_back();
478 std::vector<int>& send_buffer = send_buffers.back();
479 send_buffer.reserve(pair.second.size());
481 for (
auto id_global_index_pair : pair.second) {
482 send_buffer.push_back(id_global_index_pair.second);
486 MPI_Isend(send_buffer.data(),
487 (
int)send_buffer.size(),
493 send_requests.push_back(request);
503 static void GetGlobalIndexesToSend(
504 const std::vector<std::shared_ptr<
Interface<D>>>& interfaces,
505 std::map<
int, std::set<std::pair<int, int>>>& rank_to_id_and_global_index_pairs)
508 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
509 for (
auto iface : interfaces) {
510 for (
auto patch : iface->patches) {
511 auto piinfo = patch.piinfo;
513 if (piinfo->pinfo.rank != rank) {
514 rank_to_id_and_global_index_pairs[piinfo->pinfo.rank].emplace(iface->id,
515 iface->global_index);
520 if (piinfo->pinfo.hasNbr(s)) {
521 auto iface_info = piinfo->getIfaceInfo(s);
523 if (iface_info->rank != rank) {
524 rank_to_id_and_global_index_pairs[iface_info->rank].emplace(iface->id,
525 iface->global_index);
530 if (patch.type.isNormal() || patch.type.isCoarseToCoarse() || patch.type.isFineToFine()) {
532 GetGlobalIndexesToSendForOuterInterfaces(
533 iface, piinfo, rank_to_id_and_global_index_pairs);
546 static void GetGlobalIndexesToSendForOuterInterfaces(
549 std::map<
int, std::set<std::pair<int, int>>>& rank_to_id_and_global_index_pairs)
552 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
554 if (piinfo->pinfo.hasNbr(s)) {
555 NbrType nbr_type = piinfo->pinfo.getNbrType(s);
558 auto coarse_iface_info = piinfo->getCoarseIfaceInfo(s);
559 if (coarse_iface_info->coarse_rank != rank) {
560 rank_to_id_and_global_index_pairs[coarse_iface_info->coarse_rank].emplace(
561 interface->id, interface->global_index);
564 auto fine_iface_info = piinfo->getFineIfaceInfo(s);
565 for (
size_t i = 0; i < fine_iface_info->fine_col_local_indexes.size(); i++) {
566 if (fine_iface_info->fine_ranks[i] != rank) {
567 rank_to_id_and_global_index_pairs[fine_iface_info->fine_ranks[i]].emplace(
568 interface->id, interface->global_index);
586 iface_ns.fill(domain.
getNs()[0]);
588 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
590 std::vector<std::shared_ptr<PatchIfaceInfo<D>>> piinfos_non_const;
595 piinfos.push_back(piinfos_non_const.back());
598 std::map<int, std::map<int, std::shared_ptr<Schur::Interface<D>>>> rank_id_iface_map;
599 std::vector<std::shared_ptr<Schur::PatchIfaceInfo<D>>> off_proc_piinfos;
602 std::vector<std::shared_ptr<Schur::Interface<D>>> interfaces_non_const;
603 IndexIfacesLocal(rank_id_iface_map[rank], piinfos_non_const, interfaces_non_const);
604 IndexIfacesGlobal(interfaces_non_const, piinfos_non_const);
606 interfaces.reserve(interfaces_non_const.size());
607 for (
auto iface : interfaces_non_const) {
608 interfaces.push_back(iface);
611 int num_ifaces = interfaces.size();
612 MPI_Allreduce(&num_ifaces, &num_global_ifaces, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
636 const std::vector<std::shared_ptr<const Interface<D>>>
getInterfaces()
const
670 extern template class InterfaceDomain<2>;
671 extern template class InterfaceDomain<3>;