Loading...
Searching...
No Matches
adaption.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 <unordered_map>
26#include <unordered_set>
27
28#include "patch_kernel.hpp"
29
30namespace bitpit {
31
37namespace adaption
38{
39
46
53
60
67
74
79{
80 m_cachedTypes.insert(adaption::TYPE_RENUMBERING);
81 m_cachedTypes.insert(adaption::TYPE_DELETION);
82 m_cachedTypes.insert(adaption::TYPE_CREATION);
83 m_cachedTypes.insert(adaption::TYPE_PARTITION_RECV);
84 m_cachedTypes.insert(adaption::TYPE_PARTITION_SEND);
85}
86
87
93std::size_t InfoCollection::size() const
94{
95 return m_collection.size();
96}
97
103InfoCollection::iterator InfoCollection::begin() noexcept
104{
105 return iterator(m_collection.begin());
106}
107
113InfoCollection::iterator InfoCollection::end() noexcept
114{
115 return iterator(m_collection.end());
116}
117
123InfoCollection::const_iterator InfoCollection::begin() const noexcept
124{
125 return const_iterator(cbegin());
126}
127
133InfoCollection::const_iterator InfoCollection::end() const noexcept
134{
135 return const_iterator(cend());
136}
137
143InfoCollection::const_iterator InfoCollection::cbegin() const noexcept
144{
145 return const_iterator(m_collection.cbegin());
146}
147
153InfoCollection::const_iterator InfoCollection::cend() const noexcept
154{
155 return const_iterator(m_collection.cend());
156}
157
165const std::vector<Info> & InfoCollection::data() const noexcept
166{
167 return m_collection;
168}
169
177std::vector<Info> & InfoCollection::data() noexcept
178{
179 return m_collection;
180}
181
188{
189 m_collection.emplace_back();
190
191 return m_collection.size() - 1;
192}
193
209std::size_t InfoCollection::insert(Type type, Entity entity, int rank)
210{
211 infoData_t infoData = infoData_t(type, entity, rank);
212 bool useCache = (m_cachedTypes.count(type) > 0);
213
214 if (useCache) {
215 if (m_cache.count(infoData) > 0) {
216 return m_cache.at(infoData);
217 }
218 }
219
220 m_collection.emplace_back(type, entity, rank);
221
222 std::size_t id = m_collection.size() - 1;
223 if (useCache) {
224 m_cache.insert({{infoData, id}});
225 }
226 return id;
227}
228
243std::size_t InfoCollection::insert(const Info &other)
244{
245 return insert(Info(other));
246}
247
262std::size_t InfoCollection::insert(Info &&other)
263{
264 std::size_t id = insert(other.type, other.entity, other.rank);
265 Info &info = m_collection[id];
266
267 if (info.previous.empty()) {
268 info.previous = std::move(other.previous);
269 } else {
270 appendIds(std::move(other.previous), true, &(info.previous));
271 }
272
273 if (info.current.empty()) {
274 info.current = std::move(other.current);
275 } else {
276 appendIds(std::move(other.current), true, &(info.current));
277 }
278
279 return id;
280}
281
291bool InfoCollection::erase(std::size_t id)
292{
293 if (id >= size()) {
294 return false;
295 }
296
297 const Info &info = m_collection[id];
298 if (m_cachedTypes.count(info.type)) {
299 infoData_t infoData = infoData_t(info.type, info.entity, info.rank);
300 auto cacheItr = m_cache.find(infoData);
301 if (cacheItr != m_cache.end()) {
302 m_cache.erase(cacheItr);
303 }
304 }
305
306 m_collection.erase(m_collection.begin() + id);
307
308 return true;
309}
310
317std::size_t InfoCollection::erase(Type type)
318{
319 std::size_t nErasedInfo = 0;
320
321 std::size_t id = 0;
322 while (id < m_collection.size()) {
323 const Info &info = at(id);
324 if (info.type != type) {
325 ++id;
326 continue;
327 }
328
329 erase(id);
330 ++nErasedInfo;
331 }
332
333 return nErasedInfo;
334}
335
343Info & InfoCollection::at(std::size_t id)
344{
345 if (id >= m_collection.size()) {
346 throw std::out_of_range("Requested adaption info is not in the collection");
347 }
348
349 return (*this)[id];
350}
351
359const Info & InfoCollection::at(std::size_t id) const
360{
361 if (id >= m_collection.size()) {
362 throw std::out_of_range("Requested adaption info is not in the collection");
363 }
364
365 return (*this)[id];
366}
367
375{
376 return m_collection[id];
377}
378
385const Info & InfoCollection::operator[](std::size_t id) const
386{
387 return m_collection[id];
388}
389
398std::vector<Info> InfoCollection::dump()
399{
400 std::vector<Info> exportedCollection;
401 exportedCollection.swap(m_collection);
402
403 m_cache.clear();
404
405 return exportedCollection;
406}
407
419void InfoCollection::appendIds(std::vector<long> src, bool unique, std::vector<long> *dst)
420{
421 // Early return if the source is empty
422 if (src.empty()) {
423 return;
424 }
425
426 // Early return if the destination is empty
427 if (dst->empty()) {
428 *dst = std::move(src);
429 return;
430 }
431
432 // Append the ids
433 if (unique) {
434 std::unordered_set<long> dstSet(dst->begin(), dst->end());
435 for (long id : src) {
436 if (dstSet.count(id) == 0) {
437 dst->push_back(id);
438 }
439 }
440 } else {
441 dst->insert(dst->end(), src.begin(), src.end());
442 }
443}
444
452std::size_t InfoCollection::removeIds(std::unordered_set<long> src, std::vector<long> *dst)
453{
454 // Early return if the source is empty
455 if (src.empty()) {
456 return 0;
457 }
458
459 // Early return if the destination is empty
460 if (dst->empty()) {
461 return 0;
462 }
463
464 // Remove the ids
465 std::size_t nDeletedIds = 0;
466 for (auto itr = dst->begin(); itr != dst->end(); ++itr) {
467 long vertexId = *itr;
468 if (src.count(vertexId) > 0) {
469 ++nDeletedIds;
470 } else if (nDeletedIds > 0) {
471 *(itr - nDeletedIds) = *itr;
472 }
473 }
474
475 if (nDeletedIds > 0) {
476 dst->resize(dst->size() - nDeletedIds);
477 dst->shrink_to_fit();
478 }
479
480 return nDeletedIds;
481}
482
483}
484
492
497 : m_patch(nullptr)
498{
499}
500
510
516const std::vector<long> & FlatMapping::getNumbering() const
517{
518 return m_numbering;
519}
520
526const std::vector<long> & FlatMapping::getMapping() const
527{
528 return m_mapping;
529}
530
538
546
554{
555 m_numbering.reserve(m_patch->getCellCount());
556 m_mapping.reserve(m_patch->getCellCount());
557
558 long flatId = -1;
559 for (const auto &cell : m_patch->getCells()) {
560 flatId++;
561
562 m_numbering.emplace_back();
563 long &cellId = m_numbering.back();
564 cellId = cell.getId();
565
566 m_mapping.emplace_back();
567 long &cellMapping = m_mapping.back();
568 cellMapping = flatId;
569 }
570}
571
578void CellFlatMapping::update(const std::vector<adaption::Info> &adaptionData)
579{
580 // Previous number of cells
581 long nPreviousCells = m_numbering.size();
582
583 // Current number of cells
584 long nCurrentCells = m_patch->getCellCount();
585
586 // Find the first change
587 long firstChangedFlatId = std::min(nCurrentCells, nPreviousCells);
588 long firstChangedId = m_patch->getCells().getSizeMarker(firstChangedFlatId, Element::NULL_ID);
589 for (auto &adaptionInfo : adaptionData) {
590 if (adaptionInfo.entity != adaption::ENTITY_CELL) {
591 continue;
592 }
593
594 for (const auto &currentId : adaptionInfo.current) {
595 long currentFlatId = m_patch->getCells().evalFlatIndex(currentId);
596 if (currentFlatId < firstChangedFlatId) {
597 firstChangedId = currentId;
598 firstChangedFlatId = currentFlatId;
599 }
600 }
601 }
602
603 // The mapping, until the flat id with the first change, is a no-op mapping
604 m_mapping.resize(nCurrentCells);
605 for (long flatId = 0; flatId < firstChangedFlatId; ++flatId) {
606 m_mapping[flatId] = flatId;
607 }
608
609 // If there are no changes the mapping is already updated
610 if (firstChangedId < 0) {
611 return;
612 }
613
614 // List of cells that have been deleted
615 std::unordered_set<long> removedIds;
616 for (auto &adaptionInfo : adaptionData) {
617 if (adaptionInfo.entity != adaption::ENTITY_CELL) {
618 continue;
619 }
620
621 for (const auto &previousId : adaptionInfo.previous) {
622 removedIds.insert(previousId);
623 }
624 }
625 long nRemovedCells = removedIds.size();
626
627 // Create a mapping between cell ids and previous flat ids
628 std::unordered_map<long, long> previousFlatIds;
629 std::unordered_map<long, long> removedFlatIds;
630 previousFlatIds.reserve(nCurrentCells - firstChangedFlatId - nRemovedCells);
631 removedFlatIds.reserve(nRemovedCells);
632 for (long previousFlatId = firstChangedFlatId; previousFlatId < nPreviousCells; ++previousFlatId) {
633 long previousId = m_numbering[previousFlatId];
634 if (removedIds.count(previousId) > 0) {
635 removedFlatIds.insert({{previousId, previousFlatId}});
636 } else {
637 previousFlatIds.insert({{previousId, previousFlatId}});
638 }
639 }
640
641 // Add to the mapping the added cells
642 for (auto &adaptionInfo : adaptionData) {
643 if (adaptionInfo.entity != adaption::ENTITY_CELL) {
644 continue;
645 }
646
647 // Ancestor flat index of the added cells
648 long ancestorFlatId;
649 if (adaptionInfo.previous.size() > 0) {
650 ancestorFlatId = removedFlatIds.at(adaptionInfo.previous[0]);
651 } else {
652 ancestorFlatId = -1;
653 }
654
655 // Mapping of the added cells
656 for (const auto &currentId : adaptionInfo.current) {
657 previousFlatIds.insert({{currentId, ancestorFlatId}});
658 }
659 }
660
661 std::unordered_map<long, long>().swap(removedFlatIds);
662
663 // Update numbering and mapping past the flat id with the first change
664 m_numbering.resize(nCurrentCells);
665 auto cellIterator = m_patch->getCells().find(firstChangedId);
666 for (long flatId = firstChangedFlatId; flatId < nCurrentCells; ++flatId) {
667 long cellId = cellIterator->getId();
668
669 m_numbering[flatId] = cellId;
670 m_mapping[flatId] = previousFlatIds[cellId];
671
672 cellIterator++;
673 }
674}
675
676}
void update(const std::vector< adaption::Info > &adaptionData) override
Definition adaption.cpp:578
const std::vector< long > & getMapping() const
Definition adaption.cpp:526
const std::vector< long > & getNumbering() const
Definition adaption.cpp:516
The PatchKernel class provides an interface for defining patches.
const std::vector< Info > & data() const noexcept
Definition adaption.cpp:165
const_iterator cbegin() const noexcept
Definition adaption.cpp:143
Info & operator[](std::size_t id)
Definition adaption.cpp:374
bool erase(std::size_t id)
Definition adaption.cpp:291
static std::size_t removeIds(std::unordered_set< long > src, std::vector< long > *dst)
Definition adaption.cpp:452
const_iterator cend() const noexcept
Definition adaption.cpp:153
static void appendIds(std::vector< long > src, bool unique, std::vector< long > *dst)
Definition adaption.cpp:419
std::vector< Info > dump()
Definition adaption.cpp:398
Info & at(std::size_t id)
Definition adaption.cpp:343
The namespace 'adaption' contains the routines and the data structures for handling patch adaption.
Definition adaption.cpp:38
The namespace 'patch' contains routines for interacting with the patch manager.
The Info struct defines the infomation associated to an adaption.
Definition adaption.hpp:63