Loading...
Searching...
No Matches
voloctree_parallel.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#if BITPIT_ENABLE_MPI==1
25
26#include <mpi.h>
27#include <unordered_set>
28
29#include "voloctree.hpp"
30
31using namespace std;
32
33namespace bitpit {
34
41void VolOctree::initializeTreePartitioning()
42{
43 // Move all the octants to the first processor
44 //
45 // Assigning a null weight to every octant but the last octant and then
46 // doing a load balance will have the effect of moving all the octants
47 // to the first process.
48 std::vector<double> octantWeightStorage;
49 const std::vector<double> *octantWeights;
50
51 std::size_t nOctants = m_tree->getNumOctants();
52 if (nOctants > 1) {
53 octantWeightStorage.assign(nOctants, 0.);
54 octantWeightStorage[nOctants - 1] = 1.;
55 octantWeights = &octantWeightStorage;
56 } else {
57 octantWeights = nullptr;
58 }
59
60 m_tree->loadBalance(octantWeights);
61}
62
70void VolOctree::initializeTreeHaloSize(std::size_t haloSize)
71{
72 m_tree->setNofGhostLayers(haloSize);
73}
74
81void VolOctree::setCommunicator(MPI_Comm communicator)
82{
83 PatchKernel::setCommunicator(communicator);
84
85 m_tree->setComm(communicator);
86}
87
96{
97 return std::numeric_limits<uint32_t>::max();
98}
99
107void VolOctree::_setHaloSize(std::size_t haloSize)
108{
109 initializeTreeHaloSize(haloSize);
110}
111
126std::vector<adaption::Info> VolOctree::_partitioningPrepare(const std::unordered_map<long, double> &cellWeights, double defaultWeight, bool trackPartitioning)
127{
128 // Eval partitioning weights
129 computePartitioningOctantWeights(cellWeights, defaultWeight);
130
131 // Generate partitioning information
132 std::vector<adaption::Info> partitioningData;
133 if (trackPartitioning) {
134 int currentRank = getRank();
135 PabloUniform::LoadBalanceRanges loadBalanceRanges = m_tree->evalLoadBalanceRanges(m_partitioningOctantWeights.get());
136 for (const auto &entry : loadBalanceRanges.sendRanges) {
137 int receiver = entry.first;
138 if (receiver == currentRank) {
139 continue;
140 }
141
142 adaption::Type adaptionType;
143 if (loadBalanceRanges.sendAction == PabloUniform::LoadBalanceRanges::ACTION_DELETE) {
144 adaptionType = adaption::TYPE_DELETION;
145 } else {
146 adaptionType = adaption::TYPE_PARTITION_SEND;
147 }
148
149 partitioningData.emplace_back();
150 adaption::Info &partitioningInfo = partitioningData.back();
151 partitioningInfo.entity = adaption::ENTITY_CELL;
152 partitioningInfo.type = adaptionType;
153 partitioningInfo.rank = receiver;
154
155 const std::array<uint32_t, 2> &sendRange = entry.second;
156 uint32_t beginTreeId = sendRange[0];
157 uint32_t endTreeId = sendRange[1];
158 partitioningInfo.previous.reserve(endTreeId - beginTreeId);
159 for (uint32_t treeId = beginTreeId; treeId < endTreeId; ++treeId) {
160 OctantInfo octantInfo(treeId, true);
161 partitioningInfo.previous.emplace_back();
162 long &cellId = partitioningInfo.previous.back();
163 cellId = getOctantId(octantInfo);
164 }
165 }
166 }
167
168 return partitioningData;
169}
170
182std::vector<adaption::Info> VolOctree::_partitioningAlter(bool trackPartitioning)
183{
184 std::vector<adaption::Info> partitioningData;
185
186 // Early return if the dimension of the tree is null
187 if (m_tree->getDim() == 0) {
188 return partitioningData;
189 }
190
191 // Updating the tree
192 m_tree->loadBalance(m_partitioningOctantWeights.get());
193
194 // Sync the patch
195 partitioningData = sync(trackPartitioning);
196
197 // The bounding box is frozen, it is not updated automatically
198 setBoundingBox();
199
200 return partitioningData;
201}
202
207{
208 // Clear partitioning weights
209 clearPartitioningOctantWeights();
210}
211
220{
221 const std::vector<uint32_t> &ghostOctantSources = m_tree->getBordersPerProc().at(rank);
222 std::size_t nGhostSources = ghostOctantSources.size();
223
224 std::vector<long> ghostCellSources(nGhostSources);
225 for (std::size_t k = 0; k < nGhostSources; ++k) {
226 OctantInfo octantInfo(ghostOctantSources[k], true);
227 ghostCellSources[k] = getOctantId(octantInfo);
228 }
229
230 return ghostCellSources;
231}
232
242void VolOctree::computePartitioningOctantWeights(const std::unordered_map<long, double> &cellWeights, double defaultWeight)
243{
244 bool useWeights = !cellWeights.empty();
245 MPI_Allreduce(MPI_IN_PLACE, &useWeights, 1, MPI_C_BOOL, MPI_LOR, getCommunicator());
246 if (!useWeights) {
247 clearPartitioningOctantWeights();
248 return;
249 }
250
251 CellConstIterator beginItr = internalCellConstBegin();
252 CellConstIterator endItr = internalCellConstEnd();
253
254 std::size_t nOctants = m_tree->getNumOctants();
255 m_partitioningOctantWeights = std::unique_ptr<std::vector<double>>(new std::vector<double>(nOctants, defaultWeight));
256 for (CellConstIterator cellItr = beginItr; cellItr != endItr; ++cellItr) {
257 long cellId = cellItr.getId();
258 auto weightItr = cellWeights.find(cellId);
259 if (weightItr != cellWeights.end()) {
260 OctantInfo octantInfo = getCellOctant(cellId);
261 uint32_t treeId = octantInfo.id;
262 (*m_partitioningOctantWeights)[treeId] = weightItr->second;
263 }
264 }
265}
266
270void VolOctree::clearPartitioningOctantWeights()
271{
272 m_partitioningOctantWeights.reset();
273}
274
275}
276
277#endif
CellConstIterator internalCellConstEnd() const
CellConstIterator internalCellConstBegin() const
const MPI_Comm & getCommunicator() const
virtual void setCommunicator(MPI_Comm communicator)
std::vector< long > _findGhostCellExchangeSources(int rank) override
OctantInfo getCellOctant(long id) const
void _setHaloSize(std::size_t haloSize) override
std::size_t _getMaxHaloSize() override
std::vector< adaption::Info > _partitioningAlter(bool trackPartitioning) override
void _partitioningCleanup() override
std::vector< adaption::Info > _partitioningPrepare(const std::unordered_map< long, double > &cellWeights, double defaultWeight, bool trackPartitioning) override
void setCommunicator(MPI_Comm communicator) override
long getOctantId(const OctantInfo &octantInfo) const
The Info struct defines the information associated to an adaption.
Definition adaption.hpp:63
--- layout: doxygen_footer ---