Loading...
Searching...
No Matches
patch_info.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#if BITPIT_ENABLE_MPI==1
26# include <mpi.h>
27#endif
28
29#include "patch_info.hpp"
30#include "patch_kernel.hpp"
31
32namespace bitpit {
33
47 : m_patch(nullptr)
48{
49 setPatch(patch, false);
50}
51
58{
59 return *m_patch;
60}
61
68{
69 setPatch(patch, true);
70}
71
78void PatchInfo::setPatch(PatchKernel const *patch, bool initialize)
79{
80 // Reset information
81 if (m_patch != nullptr) {
82 reset();
83 }
84
85 // Set the patch
86 m_patch = patch;
87
88 // Call initialization
89 if (initialize) {
90 _init();
91 }
92}
93
98{
99 _reset();
100}
101
106{
107 if (m_patch == nullptr) {
108 return;
109 }
110
111 // Reset information
112 reset();
113
114 // Extract new information
115 _extract();
116}
117
122{
123 extract();
124}
125
145
150{
151 m_cellConsecutiveOffset = -1;
152}
153
158{
159 // Clear data
160 m_cellLocalToConsecutiveMap.clear();
161#if BITPIT_ENABLE_MPI==1
162 m_nGlobalInternalCells.clear();
163#endif
164
165 // Initialize data
166 _init();
167}
168
173{
174 long consecutiveId;
175
176#if BITPIT_ENABLE_MPI==1
177 // Initialize communications
178 size_t exchangeDataSize = sizeof(consecutiveId);
179 std::unique_ptr<DataCommunicator> dataCommunicator;
180
181 if (m_patch->isPartitioned()) {
182 // Create the data communicator
183 dataCommunicator = std::unique_ptr<DataCommunicator>(new DataCommunicator(m_patch->getCommunicator()));
184
185 // Set and start the receives
186 for (const auto &entry : m_patch->getGhostCellExchangeTargets()) {
187 const int rank = entry.first;
188 const auto &list = entry.second;
189
190 dataCommunicator->setRecv(rank, list.size() * exchangeDataSize);
191 dataCommunicator->startRecv(rank);
192 }
193 }
194#endif
195
196#if BITPIT_ENABLE_MPI==1
197 // Get the internal cell count of all the partitions
198 if (m_patch->isPartitioned()) {
199 m_nGlobalInternalCells.resize(m_patch->getProcessorCount());
200 long nLocalInternalCells = m_patch->getInternalCellCount();
201 MPI_Allgather(&nLocalInternalCells, 1, MPI_LONG, m_nGlobalInternalCells.data(), 1, MPI_LONG, m_patch->getCommunicator());
202 } else {
203 m_nGlobalInternalCells.resize(1);
204 m_nGlobalInternalCells[0] = m_patch->getInternalCellCount();
205 }
206#endif
207
208 // Initialize data structure for consecutive ids
209 m_cellLocalToConsecutiveMap.reserve(m_patch->getCellCount());
210
211 // Evalaute the consecutive id of the internal cells
212 if (m_patch->getInternalCellCount() > 0) {
215
216 std::size_t index = 0;
217 std::vector<std::pair<long, long>> nativeIds(m_patch->getInternalCellCount());
218 for (PatchKernel::CellConstIterator itr = beginItr; itr != endItr; ++itr) {
219 long id = itr.getId();
220 long nativeId = m_patch->_getCellNativeIndex(id);
221
222 nativeIds[index++] = std::make_pair(nativeId, id);
223 }
224
225 auto nativeIdsBegin = nativeIds.begin();
226 auto nativeIdsEnd = nativeIds.end();
227
228 std::sort(
229 nativeIdsBegin,
230 nativeIdsEnd,
231 [](const std::pair<long, long> &x, const std::pair<long, long> &y) -> bool
232 {
233 return x.first < y.first;
234 }
235 );
236
237#if BITPIT_ENABLE_MPI==1
238 m_cellConsecutiveOffset = getCellGlobalCountOffset();
239#else
240 m_cellConsecutiveOffset = 0;
241#endif
242
243 consecutiveId = m_cellConsecutiveOffset;
244 for (auto itr = nativeIdsBegin; itr != nativeIdsEnd; ++itr) {
245 m_cellLocalToConsecutiveMap.insert({itr->second, consecutiveId++});
246 }
247 }
248
249#if BITPIT_ENABLE_MPI==1
250 // Communicate the consecutive id of the ghost cells
251 if (m_patch->isPartitioned()) {
252 // Set and start the sends
253 for (const auto &entry : m_patch->getGhostCellExchangeSources()) {
254 const int rank = entry.first;
255 auto &list = entry.second;
256
257 dataCommunicator->setSend(rank, list.size() * exchangeDataSize);
258 SendBuffer &buffer = dataCommunicator->getSendBuffer(rank);
259 for (long id : list) {
260 buffer << m_cellLocalToConsecutiveMap.at(id);
261 }
262 dataCommunicator->startSend(rank);
263 }
264
265 // Receive the consecutive ids of the ghosts
266 int nCompletedRecvs = 0;
267 while (nCompletedRecvs < dataCommunicator->getRecvCount()) {
268 int rank = dataCommunicator->waitAnyRecv();
269 const auto &list = m_patch->getGhostCellExchangeTargets(rank);
270
271 RecvBuffer &buffer = dataCommunicator->getRecvBuffer(rank);
272 for (long id : list) {
273 buffer >> consecutiveId;
274 m_cellLocalToConsecutiveMap.insert({id, consecutiveId});
275 }
276
277 ++nCompletedRecvs;
278 }
279
280 // Wait for the sends to finish
281 dataCommunicator->waitAllSends();
282 }
283#endif
284}
285
292{
293 return m_cellConsecutiveOffset;
294}
295
303{
304 return m_cellLocalToConsecutiveMap.at(id);
305}
306
312const std::unordered_map<long, long> & PatchNumberingInfo::getCellConsecutiveMap() const
313{
314 return m_cellLocalToConsecutiveMap;
315}
316
317
318#if BITPIT_ENABLE_MPI==1
325{
326 long nGlobalCells = 0;
327 for (long count : m_nGlobalInternalCells) {
328 nGlobalCells += count;
329 }
330
331 return nGlobalCells;
332}
333
343
351{
352 long offset = 0;
353 for (int i = 0; i < rank; ++i) {
354 offset += m_nGlobalInternalCells[i];
355 }
356
357 return offset;
358}
359
367{
368 // Global ids and consecutive ids are the same
369 return m_cellLocalToConsecutiveMap.at(id);
370}
371
377const std::unordered_map<long, long> & PatchNumberingInfo::getCellGlobalMap() const
378{
379 // Global ids and consecutive ids are the same
380 return m_cellLocalToConsecutiveMap;
381}
382
383
391{
392 auto ghostCellOwnerItr = m_patch->m_ghostCellInfo.find(id);
393 if (ghostCellOwnerItr != m_patch->m_ghostCellInfo.end()) {
394 return ghostCellOwnerItr->second.owner;
395 } else {
396 return m_patch->getRank();
397 }
398}
399
407{
408 if (!m_patch->isPartitioned()) {
409 return m_patch->getRank();
410 }
411
412 long offset = 0;
413 for (int k = 0; k < m_patch->getProcessorCount(); ++k) {
414 offset += m_nGlobalInternalCells[k];
415 if (id < offset) {
416 return k;
417 }
418 }
419
420 return -1;
421}
422
430{
431 // Global ids and consecutive ids are the same
433}
434#endif
435
436}
The DataCommunicator class provides the infrastructure needed to exchange data among processes.
The PatchInfo class provides an interface for defining patch info.
void setPatch(PatchKernel const *patch)
PatchKernel const & getPatch() const
PatchInfo(PatchKernel const *patch)
The PatchKernel class provides an interface for defining patches.
CellConstIterator internalCellConstEnd() const
const std::unordered_map< int, std::vector< long > > & getGhostCellExchangeSources() const
CellConstIterator internalCellConstBegin() const
const std::unordered_map< int, std::vector< long > > & getGhostCellExchangeTargets() const
const MPI_Comm & getCommunicator() const
virtual long getCellCount() const
virtual long _getCellNativeIndex(long id) const
long getInternalCellCount() const
const std::unordered_map< long, long > & getCellGlobalMap() const
long getCellGlobalCountOffset() const
PatchNumberingInfo(PatchKernel const *patch=nullptr)
int getCellOwnerFromLocal(long id) const
long getCellGlobalId(long id) const
const std::unordered_map< long, long > & getCellConsecutiveMap() const
long getCellConsecutiveOffset() const
int getCellOwnerFromGlobal(long id) const
int getCellOwnerFromConsecutive(long id) const
long getCellConsecutiveId(long id) const
Iterator for the class PiercedStorage.
Buffer to be used for receive communications.
Buffer to be used for send communications.
--- layout: doxygen_footer ---