Loading...
Searching...
No Matches
voloctree_mapper.cpp
1/*---------------------------------------------------------------------------*\
2 *
3 * bitpit
4 *
5 * Copyright (C) 2015-2021 OPTIMAD engineering Srl
6 *
7 * -------------------------------------------------------------------------
8 * License
9 * This file is part of bitpit.
10 *
11 * bitpit is free software: you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License v3 (LGPL)
13 * as published by the Free Software Foundation.
14 *
15 * bitpit is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18 * License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with bitpit. If not, see <http://www.gnu.org/licenses/>.
22 *
23\*---------------------------------------------------------------------------*/
24
25#include "voloctree_mapper.hpp"
26
27namespace bitpit {
28
64#if BITPIT_ENABLE_MPI
68VolOctreeMapper::VolOctreeMapper(const bitpit::VolOctree *referencePatch, const bitpit::VolOctree *mappedPatch, MPI_Comm communicator)
69 : VolumeMapper(referencePatch, mappedPatch, communicator)
70#else
71VolOctreeMapper::VolOctreeMapper(const bitpit::VolOctree *referencePatch, const bitpit::VolOctree *mappedPatch)
72 : VolumeMapper(referencePatch, mappedPatch)
73#endif
74{
75}
76
77#if BITPIT_ENABLE_MPI
82{
83 m_partitionIR.clear();
84}
85
89void VolOctreeMapper::clearPartitionMappingLists()
90{
91 m_partitionIR.clearLists();
92}
93#endif
94
106void VolOctreeMapper::adaptionPrepare(const std::vector<adaption::Info> &adaptionInfo, bool reference)
107{
108 m_previousMapping.clear();
110
111 if (reference) {
112 pmapper = &m_mapping;
113 } else {
114 pmapper = &m_inverseMapping;
115 }
116
117 m_previousMapping.clear();
118#if BITPIT_ENABLE_MPI
119 m_partitionIR.map_rank_previousMapping.clear();
120#endif
121 for (const adaption::Info &info : adaptionInfo) {
122 if (info.type == adaption::Type::TYPE_PARTITION_SEND ||
123 info.type == adaption::Type::TYPE_PARTITION_RECV ||
124 info.type == adaption::Type::TYPE_PARTITION_NOTICE) {
125 throw std::runtime_error ("Mapper: type of adation not supported : " + std::to_string(info.type));
126 } else {
127 if (info.type != adaption::Type::TYPE_DELETION && info.type != adaption::Type::TYPE_CREATION) {
128 for (long id : info.previous) {
129 m_previousMapping[id] = (*pmapper).at(id);
130 }
131 }
132 }
133 }
134}
135
151void VolOctreeMapper::adaptionAlter(const std::vector<adaption::Info> &adaptionInfo, bool reference, bool inverseFilled)
152{
153 if (reference) {
154 _mappingAdaptionReferenceUpdate(adaptionInfo, inverseFilled);
155 } else {
156 _mappingAdaptionMappedUpdate(adaptionInfo);
157 }
158}
159
167
178void VolOctreeMapper::_mappingAdaptionReferenceUpdate(const std::vector<adaption::Info> &adaptionInfo, bool inverseFilled)
179{
180 const VolOctree *adaptedPatch = static_cast<const VolOctree*>(m_referencePatch);
181 const VolOctree *mappedPatch = static_cast<const VolOctree*>(m_mappedPatch);
182
183 PiercedStorage<mapping::Info> *mappingAdapted = &m_mapping;
185
186 bool changedPartition = false;
187#if BITPIT_ENABLE_MPI
188 bool checkPart = true;
189 checkPart = checkPartition();
190 if (!checkPart) {
191 changedPartition = _recoverPartition();
192 }
193#endif
194
195 if (!changedPartition) {
196 for (const adaption::Info &info : adaptionInfo) {
197 if (info.type == adaption::Type::TYPE_PARTITION_SEND ||
198 info.type == adaption::Type::TYPE_PARTITION_RECV ||
199 info.type == adaption::Type::TYPE_PARTITION_NOTICE) {
200 throw std::runtime_error ("Mapper: type of adation not supported : " + std::to_string(info.type));
201 } else if (info.type == adaption::Type::TYPE_DELETION ||
202 info.type == adaption::Type::TYPE_CREATION) {
203 // Do nothing
204 } else {
205 if (inverseFilled) {
206 // Erase previous id in mappingMapped elements
207 for (long idprevious : info.previous) {
208 const std::vector<long> &mappedIds = m_previousMapping[idprevious].ids;
209
210 std::size_t imapped = 0;
211 for (long idp : mappedIds) {
212#if BITPIT_ENABLE_MPI
213 if (checkPart || m_previousMapping[idprevious].ranks[imapped] == m_rank) {
214#endif
215 std::vector<long>::iterator it = std::find((*mappingMapped)[idp].ids.begin(), (*mappingMapped)[idp].ids.end(), idprevious);
216 if (it != (*mappingMapped)[idp].ids.end()) {
217 (*mappingMapped)[idp].ids.erase(it);
218#if BITPIT_ENABLE_MPI
219 int dist = static_cast<int>(std::distance((*mappingMapped)[idp].ids.begin(), it));
220 (*mappingMapped)[idp].ranks.erase((*mappingMapped)[idp].ranks.begin()+dist);
221#endif
222 }
223#if BITPIT_ENABLE_MPI
224 } else {
225 mapping::Info &inverseMappingInfo = m_partitionIR.map_rank_inverseMapping[m_previousMapping[idprevious].ranks[imapped]][idp];
226 std::vector<long>::iterator it = std::find(inverseMappingInfo.ids.begin(), inverseMappingInfo.ids.end(), idprevious);
227 if (it != inverseMappingInfo.ids.end()) {
228 int dist = static_cast<int>(std::distance(inverseMappingInfo.ids.begin(), it));
229 inverseMappingInfo.ids.erase(it);
230 inverseMappingInfo.ranks.erase(inverseMappingInfo.ranks.begin() + dist);
231 }
232 }
233#endif
234 imapped++;
235 }
236 }
237 }
238
239 switch(info.type) {
240
241 // Renumbering
242 case adaption::Type::TYPE_RENUMBERING:
243 {
244 long id = info.current[0];
245 mapping::Info &mappingInfo = (*mappingAdapted)[id];
246
247 mappingInfo.ids.clear();
248 mappingInfo.type = m_previousMapping[info.previous[0]].type;
249 mappingInfo.entity = mapping::Entity::ENTITY_CELL;
250 mappingInfo.ids = m_previousMapping[info.previous[0]].ids;
251#if BITPIT_ENABLE_MPI
252 mappingInfo.ranks = m_previousMapping[info.previous[0]].ranks;
253#endif
254
255 if (inverseFilled) {
256 const std::vector<long> &mappedIds = mappingInfo.ids;
257
258 std::size_t imapped = 0;
259 for (long idp : mappedIds) {
260#if BITPIT_ENABLE_MPI
261 if (checkPart || mappingInfo.ranks[imapped] == m_rank) {
262#endif
263 (*mappingMapped)[idp].ids.push_back(id);
264#if BITPIT_ENABLE_MPI
265 (*mappingMapped)[idp].ranks.push_back(info.rank);
266 } else {
267 mapping::Info &inverseMappingInfo = m_partitionIR.map_rank_inverseMapping[mappingInfo.ranks[imapped]][idp];
268 inverseMappingInfo.ids.push_back(id);
269 inverseMappingInfo.ranks.push_back(info.rank);
270 }
271#endif
272 imapped++;
273 }
274 }
275 }
276 break;
277
278 // Refinement and coarsening
279 case adaption::Type::TYPE_REFINEMENT:
280 case adaption::Type::TYPE_COARSENING:
281
282 // Clear current mapper
283 for (long id : info.current) {
284 mapping::Info &mappingInfo = (*mappingAdapted)[id];
285
286 mappingInfo.ids.clear();
287#if BITPIT_ENABLE_MPI
288 mappingInfo.ranks.clear();
289#endif
290
291 mappingInfo.entity = mapping::Entity::ENTITY_CELL;
292 }
293
294 for (long idprevious : info.previous) {
295 const std::vector<long> &mappedIds = m_previousMapping[idprevious].ids;
296#if BITPIT_ENABLE_MPI
297 const std::vector<int> &mappedRanks = m_previousMapping[idprevious].ranks;
298#endif
299
300 std::size_t imapped = 0;
301 for (long mappedId : mappedIds) {
302 VolOctree::OctantInfo oinfoprev;
303 uint64_t mortonmapped;
304 uint64_t mortonlastdescmapped;
305 uint8_t levelmapped;
306#if BITPIT_ENABLE_MPI
307 int mappedRank;
308 if (checkPart || mappedRanks[imapped] == m_rank) {
309#endif
310 oinfoprev = mappedPatch->getCellOctant(mappedId);
311 const Octant *octm = mappedPatch->getOctantPointer(oinfoprev);
312 mortonmapped = mappedPatch->getTree().getMorton(octm);
313 mortonlastdescmapped = mappedPatch->getTree().getLastDescMorton(octm);
314 levelmapped = mappedPatch->getCellLevel(mappedId);
315#if BITPIT_ENABLE_MPI
316 mappedRank = mappedRanks[imapped];
317 } else {
318 OctantIR *poct = m_partitionIR.map_rank_rec_octantIR[mappedRanks[imapped]][mappedId];
319 mortonmapped = mappedPatch->getTree().getMorton(&poct->octant);
320 mortonlastdescmapped = mappedPatch->getTree().getLastDescMorton(&poct->octant);
321 levelmapped = mappedPatch->getTree().getLevel(&poct->octant);
322 mappedRank = mappedRanks[imapped];
323 }
324#endif
325
326 for (long id : info.current) {
327 // Retrieve level of current cell
328 uint8_t level;
329 uint64_t morton, mortonlastdesc;
330 level = adaptedPatch->getCellLevel(id);
331 VolOctree::OctantInfo octantIfo = adaptedPatch->getCellOctant(id);
332 const Octant *octant = adaptedPatch->getOctantPointer(octantIfo);
333 morton = adaptedPatch->getTree().getMorton(octant);
334 mortonlastdesc = adaptedPatch->getTree().getLastDescMorton(octant);
335
336 bool checkmorton = false;
337
338 checkmorton |= (morton >= mortonmapped && mortonlastdesc <= mortonlastdescmapped);
339 checkmorton |= (morton <= mortonmapped && mortonlastdesc >= mortonlastdescmapped);
340
341 if (checkmorton) {
342 if (level == levelmapped) {
343 mapping::Info &mappingInfo = (*mappingAdapted)[id];
344 if (mappingInfo.ids.size() == 0) {
345 mappingInfo.type = mapping::Type::TYPE_RENUMBERING;
346 mappingInfo.ids.push_back(mappedId);
347#if BITPIT_ENABLE_MPI
348 mappingInfo.ranks.push_back(mappedRank);
349#endif
350 }
351#if BITPIT_ENABLE_MPI
352 if (inverseFilled) {
353 if (checkPart || mappedRank == m_rank) {
354#endif
355 (*mappingMapped)[mappedId].type = mapping::Type::TYPE_RENUMBERING;
356 (*mappingMapped)[mappedId].ids.clear();
357 (*mappingMapped)[mappedId].ids.push_back(id);
358#if BITPIT_ENABLE_MPI
359 (*mappingMapped)[mappedId].ranks.push_back(info.rank);
360 } else {
361 mapping::Info &inverseMappingInfo = m_partitionIR.map_rank_inverseMapping[mappedRank][mappedId];
362 inverseMappingInfo.type = mapping::Type::TYPE_RENUMBERING;
363 inverseMappingInfo.ids.push_back(id);
364 inverseMappingInfo.ranks.push_back(info.rank);
365 }
366 }
367#endif
368 }
369 else if (level > levelmapped) {
370 mapping::Info &mappingInfo = (*mappingAdapted)[id];
371 if (mappingInfo.ids.size() == 0) {
372 mappingInfo.type = mapping::Type::TYPE_REFINEMENT;
373 mappingInfo.ids.push_back(mappedId);
374#if BITPIT_ENABLE_MPI
375 mappingInfo.ranks.push_back(mappedRank);
376#endif
377 }
378#if BITPIT_ENABLE_MPI
379 if (inverseFilled) {
380 if (checkPart || mappedRank == m_rank) {
381#endif
382 if (std::find((*mappingMapped)[mappedId].ids.begin(), (*mappingMapped)[mappedId].ids.end(), id) == (*mappingMapped)[mappedId].ids.end()) {
383 (*mappingMapped)[mappedId].ids.push_back(id);
384 (*mappingMapped)[mappedId].type = mapping::Type::TYPE_COARSENING;
385#if BITPIT_ENABLE_MPI
386 (*mappingMapped)[mappedId].ranks.push_back(info.rank);
387#endif
388 }
389#if BITPIT_ENABLE_MPI
390 } else {
391 mapping::Info &inverseMappingInfo = m_partitionIR.map_rank_inverseMapping[mappedRank][mappedId];
392 inverseMappingInfo.type = mapping::Type::TYPE_COARSENING;
393 inverseMappingInfo.ids.push_back(id);
394 inverseMappingInfo.ranks.push_back(info.rank);
395 }
396 }
397#endif
398 } else if (level < levelmapped) {
399 mapping::Info &mappingInfo = (*mappingAdapted)[id];
400 if (std::find(mappingInfo.ids.begin(), mappingInfo.ids.end(), mappedId) == mappingInfo.ids.end()) {
401 mappingInfo.type = mapping::Type::TYPE_COARSENING;
402 mappingInfo.ids.push_back(mappedId);
403#if BITPIT_ENABLE_MPI
404 mappingInfo.ranks.push_back(mappedRank);
405#endif
406 }
407#if BITPIT_ENABLE_MPI
408 if (inverseFilled) {
409 if (checkPart || mappedRank == m_rank ) {
410#endif
411 if ((*mappingMapped)[mappedId].ids.size() == 0) {
412 (*mappingMapped)[mappedId].type = mapping::Type::TYPE_REFINEMENT;
413 (*mappingMapped)[mappedId].ids.push_back(id);
414#if BITPIT_ENABLE_MPI
415 (*mappingMapped)[mappedId].ranks.push_back(info.rank);
416#endif
417 }
418#if BITPIT_ENABLE_MPI
419 } else {
420 mapping::Info &inverseMappingInfo = m_partitionIR.map_rank_inverseMapping[mappedRank][mappedId];
421 if (inverseMappingInfo.ids.size() == 0) {
422 inverseMappingInfo.type = mapping::Type::TYPE_REFINEMENT;
423 inverseMappingInfo.ids.push_back(id);
424 inverseMappingInfo.ranks.push_back(info.rank);
425 }
426 }
427 }
428#endif
429 } // End level < levelreference
430 } // End checkmorton
431 } // End id current
432
433 imapped++;
434 } // End idmapped
435 } // End idprevious
436 break;
437
438 // Default
439 default:
440 break;
441
442 } // End switch
443 } // End if deletion
444 } // End end info
445
446#if BITPIT_ENABLE_MPI
447 if (inverseFilled) {
448 _communicateInverseMapperBack();
449 }
450#endif
451 } else {
452 initialize(inverseFilled);
453 }
454}
455
462void VolOctreeMapper::_mappingAdaptionMappedUpdate(const std::vector<adaption::Info> &adaptionInfo)
463{
464 const VolOctree *adaptedPatch = static_cast<const VolOctree*>(m_mappedPatch);
465 const VolOctree *referencePatch = static_cast<const VolOctree*>(m_referencePatch);
466
467 PiercedStorage<mapping::Info> *mappingAdapted = &m_inverseMapping;
468 PiercedStorage<mapping::Info> *mappingReference = &m_mapping;
469
470 bool changedPartition = false;
471#if BITPIT_ENABLE_MPI
472 bool checkPart = true;
473 checkPart = checkPartition();
474 if (!checkPart) {
475 changedPartition = _recoverPartition();
476 }
477#endif
478
479 if (!m_inverseMapping.getKernel()) {
480 throw std::runtime_error("Updating mapping with adaption of mapped mesh possible only if inverse mapper is filled");
481 }
482
483 if (!changedPartition) {
484 std::vector<adaption::Info> adaptionInfoRef;
485#if BITPIT_ENABLE_MPI
486 if (!checkPart) {
487 _communicateMappedAdaptionInfo(adaptionInfo, &adaptionInfoRef);
488 } else {
489 adaptionInfoRef = adaptionInfo;
490 }
491#else
492 adaptionInfoRef = adaptionInfo;
493#endif
494
495 for (const adaption::Info &info : adaptionInfoRef) {
496 if (info.type == adaption::Type::TYPE_PARTITION_SEND ||
497 info.type == adaption::Type::TYPE_PARTITION_RECV ||
498 info.type == adaption::Type::TYPE_PARTITION_NOTICE) {
499 throw std::runtime_error ("Mapper: type of adation not supported : " + std::to_string(info.type));
500 } else if (info.type == adaption::Type::TYPE_DELETION ||
501 info.type == adaption::Type::TYPE_CREATION) {
502 // Do nothing
503 } else {
504 // Erase previous id in mappingReference elements
505 for (long idprevious : info.previous) {
506 std::vector<long> *mappedIds;
507#if BITPIT_ENABLE_MPI
508 if (checkPart || info.rank == m_rank) {
509#endif
510 mappedIds = &(m_previousMapping[idprevious].ids);
511#if BITPIT_ENABLE_MPI
512 } else {
513 mappedIds = &(m_partitionIR.map_rank_previousMapping[info.rank][idprevious].ids);
514 }
515#endif
516 for (long idp : *mappedIds) {
517 std::vector<long>::iterator it = std::find((*mappingReference)[idp].ids.begin(), (*mappingReference)[idp].ids.end(), idprevious);
518 if (it != (*mappingReference)[idp].ids.end()) {
519 (*mappingReference)[idp].ids.erase(it);
520#if BITPIT_ENABLE_MPI
521 int dist = static_cast<int>(std::distance((*mappingReference)[idp].ids.begin(), it));
522 (*mappingReference)[idp].ranks.erase((*mappingReference)[idp].ranks.begin()+dist);
523#endif
524 }
525 }
526 }
527
528 // Renumbering
529 if (info.type == adaption::Type::TYPE_RENUMBERING) {
530 long id = info.current[0];
531 mapping::Info &mappingInfo = (*mappingAdapted)[id];
532
533 std::vector<long> *mappedIds;
534#if BITPIT_ENABLE_MPI
535 if (checkPart || info.rank == m_rank) {
536#endif
537 mappingInfo.ids.clear();
538 mappingInfo.type = m_previousMapping[info.previous[0]].type;
539 mappingInfo.entity = mapping::Entity::ENTITY_CELL;
540 mappingInfo.ids = m_previousMapping[info.previous[0]].ids;
541 mappedIds = &(mappingInfo.ids);
542#if BITPIT_ENABLE_MPI
543 mappingInfo.ranks = m_previousMapping[info.previous[0]].ranks;
544 } else {
545 for (long _idp : info.previous) {
546 if (m_partitionIR.map_rank_inverseMapping[info.rank].count(_idp)) {
547 m_partitionIR.map_rank_inverseMapping[info.rank].erase(_idp);
548 }
549 }
550
551 m_partitionIR.map_rank_inverseMapping[info.rank][id].ids.clear();
552 m_partitionIR.map_rank_inverseMapping[info.rank][id].type = m_partitionIR.map_rank_previousMapping[info.rank][info.previous[0]].type;
553 m_partitionIR.map_rank_inverseMapping[info.rank][id].entity = mapping::Entity::ENTITY_CELL;
554 m_partitionIR.map_rank_inverseMapping[info.rank][id].ids = m_partitionIR.map_rank_previousMapping[info.rank][info.previous[0]].ids;
555 m_partitionIR.map_rank_inverseMapping[info.rank][id].ranks = m_partitionIR.map_rank_previousMapping[info.rank][info.previous[0]].ranks;
556 mappedIds = &(m_partitionIR.map_rank_inverseMapping[info.rank][id].ids);
557 }
558#endif
559 for (long idp : *mappedIds) {
560 (*mappingReference)[idp].ids.push_back(id);
561#if BITPIT_ENABLE_MPI
562 (*mappingReference)[idp].ranks.push_back(info.rank);
563#endif
564 }
565 }
566
567 // Refinement and coarsening
568 if (info.type == adaption::Type::TYPE_REFINEMENT || info.type == adaption::Type::TYPE_COARSENING) {
569 // Clear current mapper
570 for (long id : info.current) {
571#if BITPIT_ENABLE_MPI
572 if (checkPart || info.rank == m_rank) {
573#endif
574 mapping::Info &mappingInfo = (*mappingAdapted)[id];
575 mappingInfo.ids.clear();
576 mappingInfo.entity = mapping::Entity::ENTITY_CELL;
577#if BITPIT_ENABLE_MPI
578 mappingInfo.ranks.clear();
579 } else {
580 m_partitionIR.map_rank_inverseMapping[info.rank][id].ids.clear();
581 m_partitionIR.map_rank_inverseMapping[info.rank][id].ranks.clear();
582 m_partitionIR.map_rank_inverseMapping[info.rank][id].entity = mapping::Entity::ENTITY_CELL;
583 }
584#endif
585 }
586
587 for (long idprevious : info.previous) {
588 std::vector<long> *mappedIds;
589#if BITPIT_ENABLE_MPI
590 std::vector<int> *mappedRanks;
591 if (checkPart || info.rank == m_rank) {
592#endif
593 mappedIds = &(m_previousMapping[idprevious].ids);
594#if BITPIT_ENABLE_MPI
595 mappedRanks = &(m_previousMapping[idprevious].ranks);
596 } else {
597 mappedIds = &(m_partitionIR.map_rank_previousMapping[info.rank][idprevious].ids);
598 mappedRanks = &(m_partitionIR.map_rank_previousMapping[info.rank][idprevious].ranks);
599 }
600#endif
601 std::size_t icount = 0;
602 for (long mappedId : *mappedIds) {
603 VolOctree::OctantInfo oinfoprev = referencePatch->getCellOctant(mappedId);
604 const Octant *octant = referencePatch->getOctantPointer(oinfoprev);
605 uint64_t mortonreference = referencePatch->getTree().getMorton(octant);
606 uint64_t mortonlastdescreference = referencePatch->getTree().getLastDescMorton(octant);
607 uint8_t levelreference = referencePatch->getCellLevel(mappedId);
608#if BITPIT_ENABLE_MPI
609 // IT'S ALWAYS = m_rank?!...
610 int mappedRank = (*mappedRanks)[icount];
611#endif
612 for (long id : info.current) {
613 // Retrieve level of current cell
614 uint8_t level;
615 uint64_t morton, mortonlastdesc;
616#if BITPIT_ENABLE_MPI
617 if (checkPart || info.rank == m_rank) {
618#endif
619 level = adaptedPatch->getCellLevel(id);
620 VolOctree::OctantInfo octantIfo = adaptedPatch->getCellOctant(id);
621 const Octant *octant = adaptedPatch->getOctantPointer(octantIfo);
622 morton = adaptedPatch->getTree().getMorton(octant);
623 mortonlastdesc = adaptedPatch->getTree().getLastDescMorton(octant);
624#if BITPIT_ENABLE_MPI
625 } else {
626 OctantIR *octantIR = m_partitionIR.map_rank_rec_octantIR[info.rank][id];
627 level = octantIR->octant.getLevel();
628 morton = adaptedPatch->getTree().getMorton(&octantIR->octant);
629 mortonlastdesc = adaptedPatch->getTree().getLastDescMorton(&octantIR->octant);
630 }
631#endif
632
633 bool checkmorton = false;
634
635 checkmorton |= (morton >= mortonreference && mortonlastdesc <= mortonlastdescreference);
636 checkmorton |= (morton <= mortonreference && mortonlastdesc >= mortonlastdescreference);
637
638 if (checkmorton) {
639
640 if (level == levelreference) {
641#if BITPIT_ENABLE_MPI
642 if (checkPart || info.rank == m_rank) {
643#endif
644 mapping::Info &mappingInfo = (*mappingAdapted)[id];
645 if (mappingInfo.ids.size() == 0) {
646 mappingInfo.type = mapping::Type::TYPE_RENUMBERING;
647 mappingInfo.ids.push_back(mappedId);
648#if BITPIT_ENABLE_MPI
649 mappingInfo.ranks.push_back(info.rank);
650#endif
651 }
652#if BITPIT_ENABLE_MPI
653 } else {
654 if (m_partitionIR.map_rank_inverseMapping[info.rank][id].ids.size() == 0) {
655 m_partitionIR.map_rank_inverseMapping[info.rank][id].type = mapping::Type::TYPE_RENUMBERING;
656 m_partitionIR.map_rank_inverseMapping[info.rank][id].ids.push_back(mappedId);
657 m_partitionIR.map_rank_inverseMapping[info.rank][id].ranks.push_back(mappedRank);
658 }
659 }
660#endif
661 (*mappingReference)[mappedId].type = mapping::Type::TYPE_RENUMBERING;
662 (*mappingReference)[mappedId].ids.clear();
663 (*mappingReference)[mappedId].ids.push_back(id);
664#if BITPIT_ENABLE_MPI
665 (*mappingReference)[mappedId].ranks.push_back(info.rank);
666#endif
667 } else if (level > levelreference) {
668#if BITPIT_ENABLE_MPI
669 if (checkPart || info.rank == m_rank) {
670#endif
671 mapping::Info &mappingInfo = (*mappingAdapted)[id];
672 if (mappingInfo.ids.size() == 0) {
673 mappingInfo.type = mapping::Type::TYPE_REFINEMENT;
674 mappingInfo.ids.push_back(mappedId);
675#if BITPIT_ENABLE_MPI
676 mappingInfo.ranks.push_back(mappedRank);
677#endif
678 }
679#if BITPIT_ENABLE_MPI
680 } else {
681 if (m_partitionIR.map_rank_inverseMapping[info.rank][id].ids.size() == 0) {
682 m_partitionIR.map_rank_inverseMapping[info.rank][id].type = mapping::Type::TYPE_REFINEMENT;
683 m_partitionIR.map_rank_inverseMapping[info.rank][id].ids.push_back(mappedId);
684 m_partitionIR.map_rank_inverseMapping[info.rank][id].ranks.push_back(mappedRank);
685 }
686 }
687#endif
688 if (std::find((*mappingReference)[mappedId].ids.begin(), (*mappingReference)[mappedId].ids.end(), id) == (*mappingReference)[mappedId].ids.end()) {
689 (*mappingReference)[mappedId].ids.push_back(id);
690 (*mappingReference)[mappedId].type = mapping::Type::TYPE_COARSENING;
691#if BITPIT_ENABLE_MPI
692 (*mappingReference)[mappedId].ranks.push_back(info.rank);
693#endif
694 }
695 } else if (level < levelreference) {
696#if BITPIT_ENABLE_MPI
697 if (checkPart || info.rank == m_rank) {
698#endif
699 mapping::Info &mappingInfo = (*mappingAdapted)[id];
700 if (std::find(mappingInfo.ids.begin(), mappingInfo.ids.end(), mappedId) == mappingInfo.ids.end()) {
701 mappingInfo.type = mapping::Type::TYPE_COARSENING;
702 mappingInfo.ids.push_back(mappedId);
703#if BITPIT_ENABLE_MPI
704 mappingInfo.ranks.push_back(mappedRank);
705#endif
706 }
707#if BITPIT_ENABLE_MPI
708 } else {
709 if (std::find(m_partitionIR.map_rank_inverseMapping[info.rank][id].ids.begin(), m_partitionIR.map_rank_inverseMapping[info.rank][id].ids.end(), mappedId) == m_partitionIR.map_rank_inverseMapping[info.rank][id].ids.end()) {
710 m_partitionIR.map_rank_inverseMapping[info.rank][id].type = mapping::Type::TYPE_COARSENING;
711 m_partitionIR.map_rank_inverseMapping[info.rank][id].ids.push_back(mappedId);
712 m_partitionIR.map_rank_inverseMapping[info.rank][id].ranks.push_back(mappedRank);
713 }
714 }
715#endif
716 if ((*mappingReference)[mappedId].ids.size() == 0) {
717 (*mappingReference)[mappedId].type = mapping::Type::TYPE_REFINEMENT;
718 (*mappingReference)[mappedId].ids.push_back(id);
719#if BITPIT_ENABLE_MPI
720 (*mappingReference)[mappedId].ranks.push_back(info.rank);
721#endif
722 }
723 } // End level < levelreference
724 } // End checkmorton
725 } // End id current
726
727 icount++;
728 } // Enf idmapped
729 } // End idprevious
730 }
731 } // End if deletion
732 } // End info
733
734#if BITPIT_ENABLE_MPI
735 _communicateInverseMapperBack();
736#endif
737
738 } else {
739 initialize(true);
740 }
741}
742
743#if BITPIT_ENABLE_MPI
752std::unordered_map<int, std::vector<long>> VolOctreeMapper::getReceivedMappedIds() const
753{
754 std::unordered_map<int, std::vector<long>> received;
755
756 for (OctantIR octir : m_partitionIR.list_rec_octantIR_before) {
757 received[octir.rank].push_back(octir.id);
758 }
759
760 for (OctantIR octir : m_partitionIR.list_rec_octantIR_after) {
761 received[octir.rank].push_back(octir.id);
762 }
763
764 return received;
765}
766
775std::unordered_map<int, std::vector<long>> VolOctreeMapper::getSentReferenceIds() const
776{
777 std::unordered_map<int, std::vector<long>> sent;
778
779 // Recover id to be recv/send
780 std::unordered_map<int, std::set<long>> rankIdSend;
781
782 for (const Cell &cell : m_referencePatch->getCells()) {
783 long id = cell.getId();
784 auto info = m_mapping[id];
785 for (int rank : info.ranks) {
786 if (rank != m_referencePatch->getRank()) {
787 rankIdSend[rank].insert(id);
788 }
789 }
790 }
791
792 for (const auto & rankId : rankIdSend) {
793 sent[rankId.first].assign(rankId.second.begin(), rankId.second.end());
794 }
795
796 return sent;
797}
798
807std::unordered_map<int, std::vector<long>> VolOctreeMapper::getReceivedReferenceIds() const
808{
809 std::unordered_map<int, std::vector<long>> received;
810
811 // Use set to retrieve ordered ids from senders using volume mapper mapping
812 // We loop over the cells of the reference mesh, we ask the mapping for the
813 // mapped mesh ids of cells overlapping the current cell, we checks for ranks
814 // and saves non-matching rank cells in the set, rank-by-rank.
815
816 std::unordered_map<int, std::set<long>> rankIdRecv;
817
818 for (const Cell & cell : m_mappedPatch->getCells()) {
819 long id = cell.getId();
820 auto info = m_inverseMapping.at(id);
821 std::size_t idsSize = info.ids.size();
822 for (std::size_t i = 0; i < idsSize; ++i) {
823 if (info.ranks[i] != m_mappedPatch->getRank()) {
824 rankIdRecv[info.ranks[i]].insert(info.ids[i]);
825 }
826 }
827 }
828
829 for (const auto & rankId : rankIdRecv) {
830 received[rankId.first].assign(rankId.second.begin(), rankId.second.end());
831 }
832
833 return received;
834}
835
844std::unordered_map<int, std::vector<long>> VolOctreeMapper::getSentMappedIds() const
845{
846 std::unordered_map<int, std::vector<long>> sent;
847
848 for (OctantIR octir : m_partitionIR.list_sent_octantIR) {
849 sent[octir.rank].push_back(octir.id);
850 }
851
852 return sent;
853}
854
855#endif
856
866void VolOctreeMapper::_mapMeshes(bool fillInverse)
867{
868 std::array<double,3> originR = static_cast<const VolOctree*>(m_referencePatch)->getOrigin();
869 std::array<double,3> originM = static_cast<const VolOctree*>(m_mappedPatch)->getOrigin();
870
871 if (!(utils::DoubleFloatingEqual()(static_cast<const VolOctree*>(m_referencePatch)->getLength(),static_cast<const VolOctree*>(m_mappedPatch)->getLength()))
872 || !(utils::DoubleFloatingEqual()(originR[0],originM[0]))
873 || !(utils::DoubleFloatingEqual()(originR[1],originM[1]))
874 || !(utils::DoubleFloatingEqual()(originR[2],originM[2]))) {
875 throw std::runtime_error ("mesh mapper: different domain of VolOctree meshes not allowed.");
876 }
877
878#if BITPIT_ENABLE_MPI
880#endif
881
882 m_mapping.setDynamicKernel(&m_referencePatch->getCells(), PiercedSyncMaster::SyncMode::SYNC_MODE_JOURNALED);
883 if (fillInverse) {
884 m_inverseMapping.setDynamicKernel(&m_mappedPatch->getCells(), PiercedSyncMaster::SyncMode::SYNC_MODE_JOURNALED);
885 } else {
887 }
888
889#if BITPIT_ENABLE_MPI
891#endif
892 long indRef = 0;
893 _mapMeshesSamePartition(nullptr, nullptr, fillInverse, &indRef);
894
895#if BITPIT_ENABLE_MPI
896 } else {
897 bool checkPart = checkPartition();
898 if (checkPart) {
899 long indRef = 0;
900 _mapMeshesSamePartition(nullptr, nullptr, fillInverse, &indRef);
901 } else {
902 _mapMeshPartitioned(fillInverse);
903 }
904 }
905#endif
906}
907
925void VolOctreeMapper::_mapMeshesSamePartition(const std::vector<OctantIR> *octantsIRReference, const std::vector<OctantIR> *octantsIRMapped,
926 bool fillInverse, long *indRef)
927{
928 const bitpit::VolOctree *referencePatch = static_cast<const VolOctree*>(m_referencePatch);
929 const bitpit::VolOctree *mappedPatch = static_cast<const VolOctree*>(m_mappedPatch);
930
931 // Fill IR with meshes if list pointer is null
932#if BITPIT_ENABLE_MPI
933 bool localMapped = false;
934#endif
935
936 std::vector<OctantIR> tempOctantsIRReference;
937 if (!octantsIRReference) {
938 long n = referencePatch->getInternalCellCount();
939 tempOctantsIRReference.reserve(n);
940 for (long i = 0; i < n; i++) {
941 VolOctree::OctantInfo octantIfoRef(i, true);
942 const Octant *octRef = referencePatch->getOctantPointer(octantIfoRef);
943 long idRef = referencePatch->getOctantId(octantIfoRef);
944#if BITPIT_ENABLE_MPI
945 tempOctantsIRReference.emplace_back(*octRef, idRef, idRef, m_rank);
946#else
947 tempOctantsIRReference.emplace_back(*octRef, idRef, idRef);
948#endif
949 }
950 octantsIRReference = &tempOctantsIRReference;
951 }
952
953 std::vector<OctantIR> tempOctantsIRMapped;
954 if (!octantsIRMapped) {
955 long n = mappedPatch->getInternalCellCount();
956 tempOctantsIRMapped.reserve(n);
957 for (long i = 0; i < n; i++) {
958 VolOctree::OctantInfo octantIfoMap(i, true);
959 const Octant *octMap = mappedPatch->getOctantPointer(octantIfoMap);
960 long idMap = mappedPatch->getOctantId(octantIfoMap);
961#if BITPIT_ENABLE_MPI
962 tempOctantsIRMapped.emplace_back(*octMap, idMap, idMap, m_rank);
963#else
964 tempOctantsIRMapped.emplace_back(*octMap, idMap, idMap);
965#endif
966 }
967 octantsIRMapped = &tempOctantsIRMapped;
968#if BITPIT_ENABLE_MPI
969 localMapped = true;
970#endif
971 }
972
973 // Define a map for inverse mapper structure
974 //
975 // If serial the map is transfer to inverse mapper directly.
976 //
977 // If mapped mesh is parallel and partitioned the map object is
978 // communicated at the end of the procedure.
979 long nRef = octantsIRReference->size();
980 long nMap = octantsIRMapped->size();
981
982 long indMap = 0;
983 if (*indRef < nRef && nMap > 0) {
984 // Place indMap at first last desc morton greater than first morton of
985 // reference octants
986 uint64_t morton = referencePatch->getTree().getMorton(&octantsIRReference->at(*indRef).octant);
987
988 for (indMap = 0; indMap < nMap; ++indMap) {
989 uint64_t mortonMapLastdesc = mappedPatch->getTree().getLastDescMorton(&octantsIRMapped->at(indMap).octant);
990 if (mortonMapLastdesc >= morton) {
991 break;
992 }
993 }
994 }
995
996 std::unordered_map<long, mapping::Info> inverseGlobalMapping;
997 while (*indRef < nRef && indMap < nMap) {
998 long idRef = octantsIRReference->at(*indRef).id;
999 long idMap = octantsIRMapped->at(indMap).id;
1000 long gidMap = octantsIRMapped->at(indMap).globalId;
1001#if BITPIT_ENABLE_MPI
1002 int rank = octantsIRMapped->at(indMap).rank;
1003#endif
1004
1005 m_mapping[idRef].entity = mapping::Entity::ENTITY_CELL;
1006 if (fillInverse) {
1007 inverseGlobalMapping[gidMap].entity = mapping::Entity::ENTITY_CELL;
1008 }
1009
1010 if (octantsIRMapped->at(indMap).octant.getLevel() == octantsIRReference->at(*indRef).octant.getLevel()) {
1011 m_mapping[idRef].ids.push_back(idMap);
1012 m_mapping[idRef].type = mapping::Type::TYPE_RENUMBERING;
1013#if BITPIT_ENABLE_MPI
1014 m_mapping[idRef].ranks.push_back(rank);
1015#endif
1016 if (fillInverse) {
1017 inverseGlobalMapping[gidMap].ids.push_back(idRef);
1018 inverseGlobalMapping[gidMap].type = mapping::Type::TYPE_RENUMBERING;
1019#if BITPIT_ENABLE_MPI
1020 inverseGlobalMapping[gidMap].ranks.push_back(m_rank);
1021#endif
1022 }
1023 (*indRef)++;
1024 indMap++;
1025 }
1026 else if (octantsIRMapped->at(indMap).octant.getLevel() > octantsIRReference->at(*indRef).octant.getLevel()) {
1027 m_mapping[idRef].type = mapping::Type::TYPE_COARSENING;
1028
1029 uint64_t mortonlastdesc = referencePatch->getTree().getLastDescMorton(&octantsIRReference->at(*indRef).octant);
1030 uint64_t mortonMap = mappedPatch->getTree().getMorton(&octantsIRMapped->at(indMap).octant);
1031 uint64_t mortonMapLastDesc = mappedPatch->getTree().getLastDescMorton(&octantsIRMapped->at(indMap).octant);
1032 while(mortonMap <= mortonlastdesc) {
1033 m_mapping[idRef].ids.push_back(idMap);
1034#if BITPIT_ENABLE_MPI
1035 m_mapping[idRef].ranks.push_back(rank);
1036#endif
1037 if (fillInverse) {
1038 inverseGlobalMapping[gidMap].type = mapping::Type::TYPE_REFINEMENT;
1039 inverseGlobalMapping[gidMap].ids.push_back(idRef);
1040#if BITPIT_ENABLE_MPI
1041 inverseGlobalMapping[gidMap].ranks.push_back(m_rank);
1042#endif
1043 }
1044 indMap++;
1045 if (indMap == nMap) {
1046 break;
1047 }
1048 idMap = octantsIRMapped->at(indMap).id;
1049 gidMap = octantsIRMapped->at(indMap).globalId;
1050#if BITPIT_ENABLE_MPI
1051 rank = octantsIRMapped->at(indMap).rank;
1052#endif
1053 mortonMap = mappedPatch->getTree().getMorton(&octantsIRMapped->at(indMap).octant);
1054 mortonMapLastDesc = mappedPatch->getTree().getLastDescMorton(&octantsIRMapped->at(indMap).octant);
1055 }
1056 if (mortonMapLastDesc >= mortonlastdesc) {
1057 (*indRef)++;
1058 }
1059 }
1060 else if (octantsIRMapped->at(indMap).octant.getLevel() < octantsIRReference->at(*indRef).octant.getLevel()) {
1061
1062 uint64_t morton = referencePatch->getTree().getMorton(&octantsIRReference->at(*indRef).octant);
1063 uint64_t mortonlastdescmesh = mappedPatch->getTree().getLastDescMorton(&octantsIRMapped->at(indMap).octant);
1064
1065 if (fillInverse) {
1066 inverseGlobalMapping[gidMap].type = mapping::Type::TYPE_COARSENING;
1067 }
1068
1069 while (morton <= mortonlastdescmesh) {
1070 m_mapping[idRef].type = mapping::Type::TYPE_REFINEMENT;
1071 m_mapping[idRef].ids.push_back(idMap);
1072#if BITPIT_ENABLE_MPI
1073 m_mapping[idRef].ranks.push_back(rank);
1074#endif
1075 if (fillInverse) {
1076 inverseGlobalMapping[gidMap].ids.push_back(idRef);
1077#if BITPIT_ENABLE_MPI
1078 inverseGlobalMapping[gidMap].ranks.push_back(m_rank);
1079#endif
1080 }
1081 (*indRef)++;
1082 if (*indRef == nRef) {
1083 break;
1084 }
1085 morton = referencePatch->getTree().getMorton(&octantsIRReference->at(*indRef).octant);
1086 idRef = octantsIRReference->at(*indRef).id;
1087 }
1088 indMap++;
1089 }
1090 }
1091
1092 // Fill inverse mapping
1093 if (fillInverse) {
1094 std::unordered_map<long, mapping::Info> inverseLocalMapping;
1095#if BITPIT_ENABLE_MPI
1096 if (mappedPatch->isPartitioned() && !localMapped && !checkPartition()) {
1097 _communicateInverseMapper(octantsIRMapped, inverseGlobalMapping, &inverseLocalMapping);
1098 } else {
1099 inverseGlobalMapping.swap(inverseLocalMapping);
1100 }
1101#else
1102 inverseGlobalMapping.swap(inverseLocalMapping);
1103#endif
1104
1105 for (const auto &mappingEntry : inverseLocalMapping) {
1106 m_inverseMapping[mappingEntry.first].type = mappingEntry.second.type;
1107 for (long inverseMappedId : mappingEntry.second.ids){
1108 m_inverseMapping[mappingEntry.first].ids.push_back(inverseMappedId);
1109 }
1110#if BITPIT_ENABLE_MPI
1111 for (int inverseMappedRank : mappingEntry.second.ranks){
1112 m_inverseMapping[mappingEntry.first].ranks.push_back(inverseMappedRank);
1113 }
1114#endif
1115 }
1116 }
1117}
1118
1119#if BITPIT_ENABLE_MPI
1128{
1129 std::vector<uint64_t> partitionMapped = static_cast<const VolOctree*>(m_mappedPatch)->getTree().getPartitionLastDesc();
1130 std::vector<uint64_t> partitionReference = static_cast<const VolOctree*>(m_referencePatch)->getTree().getPartitionLastDesc();
1131 for (int rank = 0; rank < m_nProcs; ++rank) {
1132 if (partitionReference[rank] != partitionMapped[rank]) {
1133 return false;
1134 }
1135 }
1136
1137 return true;
1138}
1139
1146void VolOctreeMapper::_mapMeshPartitioned(bool fillInverse)
1147{
1148 _recoverPartition();
1149
1150 // Fill IR with reference mesh
1151 //
1152 // TODO: make a method to do that
1153 long n = static_cast<const VolOctree*>(m_referencePatch)->getInternalCellCount();
1154 std::vector<OctantIR> octantsIRReference;
1155 octantsIRReference.reserve(n);
1156 for (long i = 0; i < n; i++) {
1157 VolOctree::OctantInfo octantIfoRef(i, true);
1158 const Octant *octRef = static_cast<const VolOctree*>(m_referencePatch)->getOctantPointer(octantIfoRef);
1159 long idRef = static_cast<const VolOctree*>(m_referencePatch)->getOctantId(octantIfoRef);
1160 octantsIRReference.emplace_back(*octRef, idRef, idRef, m_rank);
1161 }
1162
1163 long indRef = 0;
1164 _mapMeshesSamePartition(&octantsIRReference, &m_partitionIR.list_rec_octantIR_before, fillInverse, &indRef);
1165 _mapMeshesSamePartition(&octantsIRReference, nullptr, fillInverse, &indRef);
1166 _mapMeshesSamePartition(&octantsIRReference, &m_partitionIR.list_rec_octantIR_after, fillInverse, &indRef);
1167}
1168
1175bool VolOctreeMapper::_recoverPartition()
1176{
1177 // Now the mapped mesh is repartitioned (is copied...) over the processes
1178 // to match the partitioning between the two meshes
1179
1180 // Find owner of reference partition over mapped mesh partition
1181 const VolOctree* referencePatch = static_cast<const VolOctree*>(m_referencePatch);
1182 const VolOctree* mappedPatch = static_cast<const VolOctree*>(m_mappedPatch);
1183 std::vector<uint64_t> partitionLDReference = referencePatch->getTree().getPartitionLastDesc();
1184 std::vector<uint64_t> partitionLDMapped = mappedPatch->getTree().getPartitionLastDesc();
1185 std::vector<uint64_t> partitionFDReference = referencePatch->getTree().getPartitionFirstDesc();
1186 std::vector<uint64_t> partitionFDMapped = mappedPatch->getTree().getPartitionFirstDesc();
1187
1188 if (m_partitionIR.partitionFDReference.size() != 0) {
1189 if (m_partitionIR.partitionFDMapped != partitionFDMapped ||
1190 m_partitionIR.partitionLDMapped != partitionLDMapped ||
1191 m_partitionIR.partitionFDReference != partitionFDReference ||
1192 m_partitionIR.partitionLDReference != partitionLDReference) {
1193 m_partitionIR.partitionFDReference.clear();
1194 m_partitionIR.partitionLDReference.clear();
1195 m_partitionIR.partitionFDMapped.clear();
1196 m_partitionIR.partitionLDMapped.clear();
1197 return true;
1198 }
1199 }
1200
1201 std::map<int, std::vector<int>> frommapped_rank;
1202 std::map<int,std::vector<int>> toreference_rank;
1203 for (int ref_rank = 0; ref_rank < m_nProcs; ref_rank++) {
1204 uint64_t local_first_morton = partitionFDReference[ref_rank];
1205 uint64_t local_last_morton = partitionLDReference[ref_rank];
1206
1207 for (int irank = 0; irank < m_nProcs; irank++) {
1208 if (irank != ref_rank) {
1209 if (partitionFDMapped[irank] <= local_first_morton && partitionLDMapped[irank] >= local_first_morton) {
1210 frommapped_rank[ref_rank].push_back(irank);
1211 toreference_rank[irank].push_back(ref_rank);
1212 }
1213 else if (partitionFDMapped[irank] <= local_last_morton && partitionLDMapped[irank] >= local_last_morton) {
1214 frommapped_rank[ref_rank].push_back(irank);
1215 toreference_rank[irank].push_back(ref_rank);
1216 }
1217 else if (partitionFDMapped[irank] <= local_first_morton && partitionLDMapped[irank] >= local_last_morton) {
1218 frommapped_rank[ref_rank].push_back(irank);
1219 toreference_rank[irank].push_back(ref_rank);
1220 }
1221 else if (partitionFDMapped[irank] >= local_first_morton && partitionLDMapped[irank] <= local_last_morton) {
1222 frommapped_rank[ref_rank].push_back(irank);
1223 toreference_rank[irank].push_back(ref_rank);
1224 }
1225 }
1226 }
1227 }
1228
1229 clearPartitionMappingLists();
1230
1231 // Locally the mapped mesh build the lists of octants to send
1232 std::map<int, std::vector<const Octant*>> list_octant;
1233 std::map<int, std::vector<long>> list_id;
1234 std::map<int, std::vector<long>> list_globalId;
1235
1236 // Initialize idx position in mapped tree to the first mapped
1237 // octant inside the overlapping region
1238 std::vector<int>::iterator overlap_ref_rank_begin_it = toreference_rank[m_rank].begin();
1239 std::vector<int>::iterator overlap_ref_rank_end_it = toreference_rank[m_rank].end();
1240 if (overlap_ref_rank_begin_it != overlap_ref_rank_end_it) {
1241 uint32_t first_overlap_map_idx = 0;
1242 int first_overlap_ref_rank = *overlap_ref_rank_begin_it;
1243 uint64_t reference_first_morton = partitionFDReference[first_overlap_ref_rank];
1244 uint64_t first_overlap_map_morton = mappedPatch->getTree().getLastDescMorton(first_overlap_map_idx);
1245 while (first_overlap_map_morton < reference_first_morton) {
1246 first_overlap_map_idx++;
1247 if (first_overlap_map_idx == mappedPatch->getTree().getNumOctants()) {
1248 break;
1249 }
1250 first_overlap_map_morton = mappedPatch->getTree().getLastDescMorton(first_overlap_map_idx);
1251 }
1252
1253 // Fill partitioning info structure with mapped octants in the
1254 // overlapping region
1255 if (first_overlap_map_idx < mappedPatch->getTree().getNumOctants() ) {
1256 uint32_t idx = first_overlap_map_idx;
1257 for (std::vector<int>::iterator ref_rank_it = overlap_ref_rank_begin_it; ref_rank_it != overlap_ref_rank_end_it; ++ref_rank_it) {
1258 int reference_rank = *ref_rank_it;
1259 uint64_t reference_last_morton = partitionLDReference[reference_rank];
1260 uint64_t morton = mappedPatch->getTree().getMorton(idx);
1261 while (morton < reference_last_morton) {
1262 const Octant *oct = mappedPatch->getTree().getOctant(idx);
1263 list_octant[reference_rank].push_back(oct);
1264 VolOctree::OctantInfo octantIfo(idx, true);
1265 long id = mappedPatch->getOctantId(octantIfo);
1266 list_id[reference_rank].push_back(id);
1267 long globalId = mappedPatch->getTree().getGlobalIdx(idx);
1268 list_globalId[reference_rank].push_back(globalId);
1269 m_partitionIR.list_sent_octantIR.emplace_back(*oct, id, globalId, reference_rank);
1270 idx++;
1271 if (idx == mappedPatch->getTree().getNumOctants()) {
1272 break;
1273 }
1274 morton = mappedPatch->getTree().getMorton(idx);
1275 }
1276 if (idx <= mappedPatch->getTree().getNumOctants() && idx > 0) {
1277 --idx;
1278 }
1279 }
1280 }
1281 }
1282
1283 // Communications
1284 //
1285 // Send local mapped octants to reference rank and receive mapped octants
1286 // from other processes
1287 // Note. The communicated octants have to be ordered by Morton index.
1288 // For this reason the communications must be performed ordered by rank.
1289 std::size_t octantBinarySize = Octant::getBinarySize() + 2 * sizeof(long);
1290
1291 // Build send buffers
1292 DataCommunicator octCommunicator(m_communicator);
1293
1294 // Set size
1295 //
1296 // TODO: make accessible global variables in ParaTree
1297 for (int reference_rank : toreference_rank[m_rank]) {
1298 const std::vector<const Octant*> &rankOctants = list_octant[reference_rank];
1299 std::size_t nRankOctants = rankOctants.size();
1300
1301 // Set buffer size
1302 std::size_t buffSize = sizeof(std::size_t) + nRankOctants * octantBinarySize;
1303 octCommunicator.setSend(reference_rank,buffSize);
1304
1305 // Fill buffer with octants
1306 SendBuffer &sendBuffer = octCommunicator.getSendBuffer(reference_rank);
1307 sendBuffer << nRankOctants;
1308 for (std::size_t n = 0; n < nRankOctants; ++n) {
1309 const Octant &octant = *rankOctants[n];
1310 sendBuffer << octant;
1311
1312 long id = list_id[reference_rank][n];
1313 sendBuffer << id;
1314
1315 long globalId = list_globalId[reference_rank][n];
1316 sendBuffer << globalId;
1317 }
1318 }
1319
1320 octCommunicator.discoverRecvs();
1321 octCommunicator.startAllRecvs();
1322 octCommunicator.startAllSends();
1323
1324 std::vector<int> recvRanks = octCommunicator.getRecvRanks();
1325 std::sort(recvRanks.begin(),recvRanks.end());
1326
1327 std::vector<OctantIR> &list_rec_octantIR_before = m_partitionIR.list_rec_octantIR_before;
1328 std::vector<OctantIR> &list_rec_octantIR_after = m_partitionIR.list_rec_octantIR_after;
1329 std::vector<OctantIR> *_list_rec_octantIR;
1330
1331 list_rec_octantIR_before.clear();
1332 list_rec_octantIR_after.clear();
1333
1334 for (int rank : recvRanks) {
1335 octCommunicator.waitRecv(rank);
1336
1337 if (rank < m_rank) {
1338 _list_rec_octantIR = &list_rec_octantIR_before;
1339 } else if (rank > m_rank) {
1340 _list_rec_octantIR = &list_rec_octantIR_after;
1341 } else {
1342 break;
1343 }
1344
1345 RecvBuffer &recvBuffer = octCommunicator.getRecvBuffer(rank);
1346
1347 std::size_t nRecvOctants;
1348 recvBuffer >> nRecvOctants;
1349 for (std::size_t n = 0; n < nRecvOctants; ++n) {
1350 Octant octant;
1351 recvBuffer >> octant;
1352
1353 long id;
1354 recvBuffer >> id;
1355
1356 long globalId;
1357 recvBuffer >> globalId;
1358
1359 _list_rec_octantIR->emplace_back(octant, id, globalId, rank);
1360 }
1361
1362 for (OctantIR &octantIR : *_list_rec_octantIR) {
1363 long id = octantIR.id;
1364 m_partitionIR.map_rank_rec_octantIR[rank][id] = &octantIR;
1365 }
1366 }
1367
1368 octCommunicator.waitAllSends();
1369
1370 m_partitionIR.partitionLDReference = partitionLDReference;
1371 m_partitionIR.partitionLDMapped = partitionLDMapped;
1372 m_partitionIR.partitionFDReference = partitionFDReference;
1373 m_partitionIR.partitionFDMapped = partitionFDMapped;
1374
1375 return false;
1376}
1377
1385void VolOctreeMapper::_communicateInverseMapper(const std::vector<OctantIR> *octantsIRMapped,
1386 const std::unordered_map<long, mapping::Info> &inverseGlobalMapping,
1387 std::unordered_map<long, mapping::Info> *inverseLocalMapping)
1388{
1389 // Recover mapping elements to send (to partitions of mapped mesh)
1390 std::set<int> toRanks;
1391 std::map<int, std::vector<long>> toRankGlobalId;
1392 std::map<long, long > globalIdToId;
1393 for (const OctantIR &octantIR : *octantsIRMapped) {
1394 if (!inverseGlobalMapping.count(octantIR.globalId)){
1395 continue;
1396 }
1397 toRankGlobalId[octantIR.rank].push_back(octantIR.globalId);
1398 globalIdToId[octantIR.globalId] = octantIR.id;
1399 toRanks.insert(octantIR.rank);
1400 }
1401
1402 // Build send buffers
1403 DataCommunicator mapCommunicator(m_communicator);
1404
1405 // Set size
1406 for (int rank : toRanks) {
1407 // Get buffer size
1408 std::size_t buffSize = 0;
1409 for (long globalId : toRankGlobalId[rank]) {
1410 const mapping::Info &info = inverseGlobalMapping.at(globalId);
1411 int mappedSize = info.ids.size();
1412 std::size_t infoBytes = std::size_t(sizeof(long) + sizeof(int) + sizeof(int) + sizeof(int) + (sizeof(long))*mappedSize);
1413 buffSize += infoBytes;
1414 }
1415 buffSize += std::size_t(sizeof(int));
1416 mapCommunicator.setSend(rank, buffSize);
1417
1418 // Fill buffer with octants and local map for inverse mapping
1419 SendBuffer &sendBuffer = mapCommunicator.getSendBuffer(rank);
1420 sendBuffer << int(toRankGlobalId[rank].size());
1421 for (long globalId : toRankGlobalId[rank]) {
1422 const mapping::Info &info = inverseGlobalMapping.at(globalId);
1423 sendBuffer << globalId;
1424 sendBuffer << int(info.type);
1425 sendBuffer << int(info.entity);
1426 int mappedSize = info.ids.size();
1427 sendBuffer << mappedSize;
1428 for (long refId : info.ids) {
1429 sendBuffer << refId;
1430 }
1431
1432 m_partitionIR.map_rank_inverseMapping[rank][globalIdToId[globalId]] = info;
1433
1434 }
1435 }
1436
1437 mapCommunicator.discoverRecvs();
1438 mapCommunicator.startAllRecvs();
1439 mapCommunicator.startAllSends();
1440
1441 int nCompletedRecvs = 0;
1442 while (nCompletedRecvs < mapCommunicator.getRecvCount()) {
1443 int rank = mapCommunicator.waitAnyRecv();
1444 RecvBuffer &recvBuffer = mapCommunicator.getRecvBuffer(rank);
1445
1446 int nof;
1447 recvBuffer >> nof;
1448 for (int i = 0; i < nof; i++) {
1449 long globalId;
1450 recvBuffer >> globalId;
1451
1452 uint32_t idx = static_cast<const VolOctree*>(m_mappedPatch)->getTree().getLocalIdx(globalId);
1453 VolOctree::OctantInfo octantIfo(idx, true);
1454
1455 int type;
1456 recvBuffer >> type;
1457
1458 int entity;
1459 recvBuffer >> entity;
1460
1461 long id = static_cast<const VolOctree*>(m_mappedPatch)->getOctantId(octantIfo);
1462 mapping::Info &info = (*inverseLocalMapping)[id];
1463 info.type = mapping::Type(type);
1464 info.entity = mapping::Entity(entity);
1465 int nmap;
1466 recvBuffer >> nmap;
1467 for (int j=0; j<nmap; j++) {
1468 long idref;
1469 recvBuffer >> idref;
1470 info.ids.push_back(idref);
1471 info.ranks.push_back(rank);
1472 }
1473 }
1474
1475 ++nCompletedRecvs;
1476 }
1477
1478 mapCommunicator.waitAllSends();
1479}
1480
1485void VolOctreeMapper::_communicateInverseMapperBack()
1486{
1487 // Recover mapping elements to send (to partitions of mapped mesh)
1488 std::set<int> toRanks;
1489 std::map<int, std::vector<long>> toRankId;
1490 for (const auto &mappingEntry : m_partitionIR.map_rank_inverseMapping) {
1491 toRanks.insert(mappingEntry.first);
1492
1493 const std::unordered_map<long, mapping::Info> &inverseMappingInfo = m_partitionIR.map_rank_inverseMapping[mappingEntry.first];
1494 for (const auto &submappingEntry : inverseMappingInfo) {
1495 toRankId[mappingEntry.first].push_back(submappingEntry.first);
1496 }
1497 }
1498
1499 // Build send buffers
1500 DataCommunicator mapCommunicator(m_communicator);
1501
1502 // Set size
1503 for (int rank : toRanks) {
1504 const std::unordered_map<long, mapping::Info> &inverseMappingInfo = m_partitionIR.map_rank_inverseMapping[rank];
1505
1506 // Get buffer size
1507 std::size_t buffSize = 0;
1508 for (long id : toRankId[rank]) {
1509 const mapping::Info &info = inverseMappingInfo.at(id);
1510 int mappedSize = info.ids.size();
1511 std::size_t infoBytes = std::size_t(sizeof(long) + sizeof(int) + sizeof(int) + sizeof(int) + (sizeof(long))*mappedSize);
1512 buffSize += infoBytes;
1513 }
1514 buffSize += std::size_t(sizeof(int));
1515 mapCommunicator.setSend(rank,buffSize);
1516
1517 // Fill buffer with octants and local map for inverse mapping
1518 SendBuffer &sendBuffer = mapCommunicator.getSendBuffer(rank);
1519 sendBuffer << int(toRankId[rank].size());
1520 for (long id : toRankId[rank]) {
1521 const mapping::Info &info = inverseMappingInfo.at(id);
1522 sendBuffer << id;
1523 sendBuffer << int(info.type);
1524 sendBuffer << int(info.entity);
1525 int mappedSize = info.ids.size();
1526 sendBuffer << mappedSize;
1527 for (long refId : info.ids) {
1528 sendBuffer << refId;
1529 }
1530 }
1531 }
1532
1533 mapCommunicator.discoverRecvs();
1534 mapCommunicator.startAllRecvs();
1535 mapCommunicator.startAllSends();
1536
1537 int nCompletedRecvs = 0;
1538 while (nCompletedRecvs < mapCommunicator.getRecvCount()) {
1539 int rank = mapCommunicator.waitAnyRecv();
1540 RecvBuffer &recvBuffer = mapCommunicator.getRecvBuffer(rank);
1541
1542 int nof;
1543 recvBuffer >> nof;
1544 for (int i = 0; i < nof; i++) {
1545 long id;
1546 recvBuffer >> id;
1547
1548 int type;
1549 recvBuffer >> type;
1550
1551 int entity;
1552 recvBuffer >> entity;
1553
1554 mapping::Info &info = m_inverseMapping[id];
1555 info.type = mapping::Type(type);
1556 info.entity = mapping::Entity(entity);
1557
1558 // Keep only local mapping
1559 //
1560 // If partition is changed the mapping is always recomputed and not
1561 // updated.
1562 //
1563 // Remove old ids and ranks that don't belong to this partition.
1564 auto idsIter = info.ids.begin();
1565 auto ranksIter = info.ranks.begin();
1566 while (idsIter != info.ids.end()) {
1567 int rank = *ranksIter;
1568 if (rank != m_mappedPatch->getRank()) {
1569 idsIter = info.ids.erase(idsIter);
1570 ranksIter = info.ranks.erase(ranksIter);
1571 } else {
1572 idsIter++;
1573 ranksIter++;
1574 }
1575 }
1576
1577 // Add received ids and ranks
1578 int nmap;
1579 recvBuffer >> nmap;
1580 for (int j=0; j<nmap; j++) {
1581 long idref;
1582 recvBuffer >> idref;
1583 info.ids.push_back(idref);
1584 info.ranks.push_back(rank);
1585 }
1586 }
1587
1588 ++nCompletedRecvs;
1589 }
1590
1591 mapCommunicator.waitAllSends();
1592
1593}
1594
1604void VolOctreeMapper::_communicateMappedAdaptionInfo(const std::vector<adaption::Info> &adaptionInfoMap, std::vector<adaption::Info> *adaptionInfoRef)
1605{
1606 // Recover mapping elements to send (to partitions of mapped mesh)
1607 std::set<int> toRanks;
1608 std::map<int, std::set<long>> toRankInd;
1609 std::map<int, std::vector<long>> toRankId;
1610
1611 std::size_t n = 0;
1612 for (auto &info : adaptionInfoMap) {
1613 for (long id : info.previous) {
1614 auto itPreviousMapping = m_previousMapping.find(id);
1615 if (itPreviousMapping == m_previousMapping.end()){
1616 continue;
1617 }
1618 for (int rank : itPreviousMapping->second.ranks) {
1619 toRanks.insert(rank);
1620 toRankInd[rank].insert(n);
1621 toRankId[rank].push_back(id);
1622 }
1623 }
1624 ++n;
1625 }
1626
1627 // Build send buffers
1628 DataCommunicator mapCommunicator(m_communicator);
1629
1630 // Initialize communications
1631 for (int rank : toRanks) {
1632 std::size_t buffSize = 0;
1633 for (long id : toRankId[rank]) {
1634 const mapping::Info &info = m_previousMapping.at(id);
1635 int mappedSize = info.ids.size();
1636 std::size_t infoBytes = std::size_t(sizeof(long) + 3*sizeof(int) + (sizeof(long))*mappedSize);
1637 buffSize += infoBytes;
1638 }
1639 buffSize += std::size_t(sizeof(int));
1640
1641 for (long ind : toRankInd[rank]) {
1642 const adaption::Info &info = adaptionInfoMap[ind];
1643 int currentSize = info.current.size();
1644 int previousSize = info.previous.size();
1645 std::size_t infoBytes = std::size_t(5*sizeof(int) + (sizeof(long))*(currentSize+previousSize));
1646 buffSize += infoBytes;
1647 }
1648 buffSize += std::size_t(sizeof(int));
1649
1650 mapCommunicator.setSend(rank,buffSize);
1651
1652 // Fill buffer with octants and local map for inverse mapper
1653 SendBuffer &sendBuffer = mapCommunicator.getSendBuffer(rank);
1654 sendBuffer << int(toRankId[rank].size());
1655 for (long id : toRankId[rank]) {
1656 auto itPreviousMapping = m_previousMapping.find(id);
1657 if (itPreviousMapping == m_previousMapping.end()){
1658 continue;
1659 }
1660 const mapping::Info &info = itPreviousMapping->second;
1661 sendBuffer << id;
1662 sendBuffer << int(info.type);
1663 sendBuffer << int(info.entity);
1664 int mappedSize = info.ids.size();
1665 sendBuffer << mappedSize;
1666 for (long refId : info.ids) {
1667 sendBuffer << refId;
1668 }
1669 }
1670
1671 sendBuffer << int(toRankInd[rank].size());
1672 for (long ind : toRankInd[rank]) {
1673 const adaption::Info &info = adaptionInfoMap[ind];
1674 sendBuffer << int(info.type);
1675 sendBuffer << int(info.entity);
1676 int currentSize = info.current.size();
1677 int previousSize = info.previous.size();
1678 sendBuffer << currentSize;
1679 for (long Id : info.current) {
1680 sendBuffer << Id;
1681 }
1682 sendBuffer << previousSize;
1683 for (long Id : info.previous) {
1684 sendBuffer << Id;
1685 }
1686
1687 // Rank of adaption is used to identify the rank where the adaption
1688 // occurs
1689 sendBuffer << m_rank;
1690 }
1691
1692 }
1693
1694 // Execute communications
1695 mapCommunicator.discoverRecvs();
1696 mapCommunicator.startAllRecvs();
1697 mapCommunicator.startAllSends();
1698
1699 // Retrieve data
1700 int nCompletedRecvs = 0;
1701 while (nCompletedRecvs < mapCommunicator.getRecvCount()) {
1702 int rank = mapCommunicator.waitAnyRecv();
1703
1704 RecvBuffer &recvBuffer = mapCommunicator.getRecvBuffer(rank);
1705 int nofMapper;
1706 recvBuffer >> nofMapper;
1707 for (int i = 0; i < nofMapper; i++) {
1708 long id;
1709 recvBuffer >> id;
1710
1711 int mtype;
1712 recvBuffer >> mtype;
1713
1714 int mentity;
1715 recvBuffer >> mentity;
1716
1717 mapping::Info info;
1718 info.type = mapping::Type(mtype);
1719 info.entity = mapping::Entity(mentity);
1720 int nmap;
1721 recvBuffer >> nmap;
1722 for (int j=0; j<nmap; j++) {
1723 long idref;
1724 recvBuffer >> idref;
1725 info.ids.push_back(idref);
1726 info.ranks.push_back(m_rank);
1727 }
1728 m_partitionIR.map_rank_previousMapping[rank][id] = info;
1729 m_partitionIR.map_rank_inverseMapping[rank].erase(id);
1730 }
1731
1732 int nofInfo;
1733 recvBuffer >> nofInfo;
1734 for (int i = 0; i < nofInfo; i++) {
1735 int type;
1736 recvBuffer >> type;
1737
1738 int entity;
1739 recvBuffer >> entity;
1740
1741 adaption::Info info;
1742 info.type = adaption::Type(type);
1743 info.entity = adaption::Entity(entity);
1744 int ncurrent;
1745 recvBuffer >> ncurrent;
1746 for (int j=0; j<ncurrent; j++) {
1747 long id;
1748 recvBuffer >> id;
1749 info.current.push_back(id);
1750 }
1751 int nprevious;
1752 recvBuffer >> nprevious;
1753 for (int j=0; j<nprevious; j++) {
1754 long id;
1755 recvBuffer >> id;
1756 info.previous.push_back(id);
1757 }
1758 int arank;
1759 recvBuffer >> arank;
1760 info.rank = arank;
1761 adaptionInfoRef->push_back(info);
1762 }
1763
1764 ++nCompletedRecvs;
1765 }
1766
1767 mapCommunicator.waitAllSends();
1768}
1769
1770#endif
1771
1772}
The Cell class defines the cells.
Definition cell.hpp:42
Octant class definition.
Definition Octant.hpp:89
static unsigned int getBinarySize()
Definition Octant.cpp:658
uint64_t getMorton(uint32_t idx) const
const std::vector< uint64_t > & getPartitionLastDesc() const
Definition ParaTree.cpp:975
uint64_t getLastDescMorton(const Octant *oct) const
uint8_t getLevel(uint32_t idx) const
PiercedVector< Cell > & getCells()
long getInternalCellCount() const
Metafunction for generating a pierced storage.
The VolOctreeMapper is the class to map two meshes of class VolOctree.
std::unordered_map< int, std::vector< long > > getReceivedReferenceIds() const override
std::unordered_map< int, std::vector< long > > getReceivedMappedIds() const override
std::unordered_map< int, std::vector< long > > getSentReferenceIds() const override
void adaptionPrepare(const std::vector< adaption::Info > &adaptionInfo, bool reference=true) override
void adaptionAlter(const std::vector< adaption::Info > &adaptionInfo, bool reference=true, bool inverseFilled=false) override
VolOctreeMapper(const VolOctree *referencePatch, const VolOctree *mappedPatch, MPI_Comm communicator)
std::unordered_map< int, std::vector< long > > getSentMappedIds() const override
The VolOctree defines a Octree patch.
Definition voloctree.hpp:37
int getCellLevel(long id) const
OctantInfo getCellOctant(long id) const
Octant * getOctantPointer(const OctantInfo &octantInfo)
PabloUniform & getTree()
Gets a reference to the octree associated with the patch.
long getOctantId(const OctantInfo &octantInfo) const
The VolumeMapper is the class to map two meshes.
const VolumeKernel * m_mappedPatch
std::unordered_map< long, mapping::Info > m_previousMapping
void initialize(bool fillInv=false)
PiercedStorage< mapping::Info > m_inverseMapping
PiercedStorage< mapping::Info > m_mapping
const VolumeKernel * m_referencePatch
Logger & info(log::Visibility defaultVisibility)
Definition logger.cpp:1847
The Info struct defines the information associated to an adaption.
Definition adaption.hpp:63
--- layout: doxygen_footer ---