12#ifndef DUMUX_VTK_GRID_DATA_HANDLE_HH
13#define DUMUX_VTK_GRID_DATA_HANDLE_HH
22#include <unordered_map>
27#include <dune/common/parallel/communication.hh>
28#include <dune/common/parallel/future.hh>
29#include <dune/geometry/dimension.hh>
30#include <dune/grid/common/partitionset.hh>
31#include <dune/grid/common/datahandleif.hh>
41template<
class Gr
id,
class Gr
idInput,
class Data>
43:
public Dune::CommDataHandleIF<VtkGridDataHandle<Grid, GridInput, Data>, typename Data::value_type>
48 : gridView_(grid.levelGridView(0))
49 , idSet_(grid.localIdSet())
50 , userCellData_(cellData)
51 , userPointData_(pointData)
53 const auto rank = grid.comm().rank();
57 for (
const auto& [key, data] : userCellData_)
58 cellData_[key] = std::move(userCellData_[key]);
59 for (
const auto& [key, data] : userPointData_)
60 pointData_[key] = std::move(userPointData_[key]);
62#if DUMUX_HAVE_GRIDFORMAT
65 std::array<std::size_t, 2> numKeys{{ cellData_.size(), pointData_.size() }};
66 std::vector<std::size_t> keyComponents(numKeys[0] + numKeys[1], 0);
69 for (
const auto& [key, data] : cellData_)
70 keyComponents[n++] = rank == 0 ? data.size()/gridInput.numElements() : 0;
71 for (
const auto& [key, data] : pointData_)
72 keyComponents[n++] = rank == 0 ? data.size()/gridInput.numVertices() : 0;
73 grid.comm().broadcast(keyComponents.data(), keyComponents.size(), 0);
76 const auto begin = keyComponents.begin();
77 cellDataComponents_.assign(begin, begin + numKeys[0]);
78 pointDataComponents_.assign(begin + numKeys[0], keyComponents.end());
79 numCellDataPerElement_ = std::accumulate(cellDataComponents_.begin(), cellDataComponents_.end(), 0UL);
80 numPointDataPerVertex_ = std::accumulate(pointDataComponents_.begin(), pointDataComponents_.end(), 0UL);
84 std::array<std::size_t, 2> numKeys{{ cellData_.size(), pointData_.size() }};
85 grid.comm().broadcast(numKeys.data(), 2, 0);
89 std::vector<std::size_t> keyLengthAndComponents(2*(numKeys[0] + numKeys[1]), 0);
94 for (
const auto& [key, data] : cellData_)
95 keyLengthAndComponents[n++] = key.size();
96 for (
const auto& [key, data] : pointData_)
97 keyLengthAndComponents[n++] = key.size();
100 for (
const auto& [key, data] : cellData_)
101 keyLengthAndComponents[n++] = rank == 0 ? data.size()/gridInput.numElements() : 0;
102 for (
const auto& [key, data] : pointData_)
103 keyLengthAndComponents[n++] = rank == 0 ? data.size()/gridInput.numVertices() : 0;
105 grid.comm().broadcast(keyLengthAndComponents.data(), keyLengthAndComponents.size(), 0);
109 const auto begin = keyLengthAndComponents.begin() + numKeys[0] + numKeys[1];
110 cellDataComponents_.assign(begin, begin + numKeys[0]);
111 pointDataComponents_.assign(begin + numKeys[0], keyLengthAndComponents.end());
112 numCellDataPerElement_ = std::accumulate(cellDataComponents_.begin(), cellDataComponents_.end(), 0UL);
113 numPointDataPerVertex_ = std::accumulate(pointDataComponents_.begin(), pointDataComponents_.end(), 0UL);
116 std::string keys; keys.resize(std::accumulate(keyLengthAndComponents.begin(), begin, 0UL));
119 for (
const auto& [key, data] : cellData_)
120 for (
const auto& c : key)
122 for (
const auto& [key, data] : pointData_)
123 for (
const auto& c : key)
126 grid.comm().broadcast(keys.data(), keys.size(), 0);
130 std::size_t offset = 0;
131 for (
int keyIdx = 0; keyIdx < numKeys[0]; ++keyIdx)
133 if (std::string key{ keys, offset, keyLengthAndComponents[keyIdx] }; cellData_.count(key) == 0)
134 cellData_[key] = Data{};
136 offset += keyLengthAndComponents[keyIdx];
138 for (
int keyIdx = numKeys[0]; keyIdx < numKeys[0] + numKeys[1]; ++keyIdx)
140 if (std::string key{ keys, offset, keyLengthAndComponents[keyIdx] }; pointData_.count(key) == 0)
141 pointData_[key] = Data{};
143 offset += keyLengthAndComponents[keyIdx];
148 for (
const auto& element : elements(gridView_, Dune::Partitions::interior))
150 data_[idSet_.id(element)].resize(numCellDataPerElement_);
153 for (
const auto& [key, data] : cellData_)
155 const auto nComp = cellDataComponents_[l++];
156 for (
int k = 0; k < nComp; ++k)
157 std::swap(cellData_[key][k + nComp*gridInput.insertionIndex(element)], data_[idSet_.id(element)][n++]);
160 assert(n == numCellDataPerElement_);
163 for (
const auto& vertex : vertices(gridView_))
165 data_[idSet_.id(vertex)].resize(numPointDataPerVertex_);
168 for (
const auto& [key, data] : pointData_)
170 const auto nComp = pointDataComponents_[l++];
171 for (
int k = 0; k < nComp; ++k)
172 std::swap(pointData_[key][k + nComp*gridInput.insertionIndex(vertex)], data_[idSet_.id(vertex)][n++]);
175 assert(n == numPointDataPerVertex_);
182 const auto& indexSet = gridView_.indexSet();
186 for (
const auto& [key, data] : cellData_)
187 cellData_[key].resize(indexSet.size(0)*cellDataComponents_[n++]);
191 for (
const auto& [key, data] : pointData_)
192 pointData_[key].resize(indexSet.size(GridView::dimension)*pointDataComponents_[n++]);
195 for (
const auto& element : elements(gridView_))
198 for (
const auto& [key, data] : cellData_)
200 const auto nComp = cellDataComponents_[l++];
201 for (
int k = 0; k < nComp; ++k)
202 std::swap(cellData_[key][k + nComp*indexSet.index(element)], data_[idSet_.id(element)][n++]);
206 for (
const auto& vertex : vertices(gridView_))
209 for (
const auto& [key, data] : pointData_)
211 const auto nComp = pointDataComponents_[l++];
212 for (
int k = 0; k < nComp; ++k)
213 std::swap(pointData_[key][k + nComp*indexSet.index(vertex)], data_[idSet_.id(vertex)][n++]);
218 for (
const auto& [key, data] : cellData_)
219 userCellData_[key] = std::move(cellData_[key]);
220 for (
const auto& [key, data] : pointData_)
221 userPointData_[key] = std::move(pointData_[key]);
224 Dune::CommDataHandleIF<VtkGridDataHandle<Grid, GridInput, Data>,
typename Data::value_type>&
interface()
228 {
return codim == 0 || codim == dim; }
234 template<
class Entity>
235 std::size_t
size (
const Entity&)
const
237 if constexpr (Entity::codimension == 0)
238 return numCellDataPerElement_;
239 else if constexpr (Entity::codimension == GridView::dimension)
240 return numPointDataPerVertex_;
245 template<
class MessageBufferImp,
class Entity>
246 void gather (MessageBufferImp& buff,
const Entity& e)
const
248 if constexpr (Entity::codimension == 0)
250 const auto& data = data_[idSet_.id(e)];
251 for (
int n = 0; n < numCellDataPerElement_; ++n)
255 if constexpr (Entity::codimension == GridView::dimension)
257 const auto& data = data_[idSet_.id(e)];
258 for (
int n = 0; n < numPointDataPerVertex_; ++n)
263 template<
class MessageBufferImp,
class Entity>
264 void scatter (MessageBufferImp& buff,
const Entity& e, std::size_t n)
266 auto& data = data_[idSet_.id(e)];
269 if constexpr (Entity::codimension == 0)
270 for (
int k = 0; k < numCellDataPerElement_; ++k)
273 if constexpr (Entity::codimension == GridView::dimension)
274 for (
int k = 0; k < numPointDataPerVertex_; ++k)
279 using IdSet =
typename Grid::LocalIdSet;
287 std::map<std::string, VTKReader::Data::mapped_type> cellData_;
288 std::map<std::string, VTKReader::Data::mapped_type> pointData_;
290 std::vector<std::size_t> cellDataComponents_;
291 std::vector<std::size_t> pointDataComponents_;
293 std::size_t numCellDataPerElement_;
294 std::size_t numPointDataPerVertex_;
296 mutable std::map< typename IdSet::IdType, std::vector<typename Data::value_type> > data_;
304template<
class Gr
id,
class Gr
idInput>
308 const auto commSize = grid.comm().size();
312 const auto rank = grid.comm().rank();
317 std::cout <<
"Communicating structured VTK data...\n\n" << std::endl;
318 std::cout <<
"Grid has " << gridInput.numElements() <<
" elements and " << gridInput.numVertices() <<
" vertices." << std::endl;
324 std::map<std::string, ::Dumux::VTKReader::Data::mapped_type> sortedCellData, sortedPointData;
325 for (
const auto& [key, data] : cellData)
326 sortedCellData[key] = std::move(cellData[key]);
327 for (
const auto& [key, data] : pointData)
328 sortedPointData[key] = std::move(pointData[key]);
332 std::array<std::size_t, 2> numKeys{{ sortedCellData.size(), sortedPointData.size() }};
333 std::vector<std::size_t> keyComponents(numKeys[0] + numKeys[1], 0);
336 for (
const auto& [key, data] : sortedCellData)
337 keyComponents[n++] = rank == 0 ? data.size()/gridInput.numElements() : 0;
338 for (
const auto& [key, data] : sortedPointData)
339 keyComponents[n++] = rank == 0 ? data.size()/gridInput.numVertices() : 0;
340 grid.comm().broadcast(keyComponents.data(), keyComponents.size(), 0);
343 const auto begin = keyComponents.begin();
344 const std::size_t numCellDataPerElement = std::accumulate(begin, begin + numKeys[0], 0UL);
345 const std::size_t numPointDataPerVertex = std::accumulate(begin + numKeys[0], keyComponents.end(), 0UL);
348 std::cout <<
"Rank " << rank <<
": numbers of components for each cell and point data array: "
349 << numCellDataPerElement <<
" " << numPointDataPerVertex << std::endl;
358 const auto& gridView = grid.levelGridView(0);
359 std::vector<std::size_t> requestedData(gridView.size(0) + gridView.size(Grid::dimension));
360 const std::size_t numElements = gridView.size(0);
361 const std::size_t numVertices = gridView.size(Grid::dimension);
362 for (
const auto& element : elements(gridView))
364 requestedData[gridView.indexSet().index(element)] = gridInput.insertionIndex(element);
365 for (
const auto& vertex : subEntities(element, Dune::Codim<Grid::dimension>{}))
366 requestedData[numElements + gridView.indexSet().index(vertex)] = gridInput.insertionIndex(vertex);
370 std::vector<std::size_t> numData_;
372 numData_.resize(2*commSize);
373 std::array<std::size_t, 2> localNumData{{ numElements, numVertices }};
374 grid.comm().gather(localNumData.data(), numData_.data(), 2, 0);
379 std::cout <<
"Number of elements and vertices on each rank: ";
380 for (std::size_t i = 0; i < commSize; ++i)
381 std::cout << numData_[2*i] <<
" " << numData_[2*i + 1] <<
" ";
382 std::cout << std::endl;
387 using RequestData = std::vector<std::size_t>;
388 using FutureIndices = Dune::Future<RequestData>;
389 std::unique_ptr<FutureIndices> sendRequest;
391 sendRequest = std::make_unique<FutureIndices>(
392 std::move(grid.comm().isend(std::move(requestedData), 0, 0))
396 std::vector<RequestData> requestedDataAll(commSize);
399 std::vector<std::unique_ptr<FutureIndices>> receiveRequests(commSize-1);
400 for (std::size_t i = 0; i < commSize; ++i)
402 requestedDataAll[i].resize(numData_[2*i] + numData_[2*i + 1]);
405 requestedDataAll[i] = std::move(requestedData);
408 receiveRequests[i-1] = std::make_unique<FutureIndices>(
409 std::move(grid.comm().irecv(requestedDataAll[i], i, 0))
415 std::ranges::for_each(receiveRequests, [](
auto& request) { request->wait(); });
418 std::cout <<
"Received data from all ranks." << std::endl;
419 for (std::size_t i = 0; i < commSize; ++i)
420 std::cout <<
"From rank " << i <<
": " << requestedDataAll[i].size() <<
" index size." << std::endl;
425 using PackedData = std::vector<double>;
426 PackedData receivedFlatData(localNumData[0]*numCellDataPerElement + localNumData[1]*numPointDataPerVertex);
429 using FutureData = Dune::Future<PackedData>;
430 std::vector<std::unique_ptr<FutureData>> sendRequests(commSize-1);
431 for (std::size_t i = 0; i < commSize; ++i)
433 const auto& requestedIndices = requestedDataAll[i];
434 PackedData packedData(numData_[2*i]*numCellDataPerElement + numData_[2*i + 1]*numPointDataPerVertex);
437 std::size_t n = 0, l = 0;
438 for (
const auto& [key, data] : sortedCellData)
440 const auto nComp = keyComponents[l++];
441 for (std::size_t k = 0; k < numData_[2*i]; ++k)
443 const auto idx = requestedIndices[k];
444 for (std::size_t j = 0; j < nComp; ++j)
445 packedData[n++] = data[j + nComp*idx];
449 const auto pointDataOffsett = numData_[2*i];
450 for (
const auto& [key, data] : sortedPointData)
452 const auto nComp = keyComponents[l++];
453 for (std::size_t k = 0; k < numData_[2*i + 1]; ++k)
455 const auto idx = requestedIndices[k + pointDataOffsett];
456 for (std::size_t j = 0; j < nComp; ++j)
457 packedData[n++] = data[j + nComp*idx];
461 if (n != packedData.size())
462 DUNE_THROW(Dune::InvalidStateException,
"Packed data size does not match expected size.");
465 receivedFlatData = std::move(packedData);
469 sendRequests[i-1] = std::make_unique<FutureData>(
470 std::move(grid.comm().isend(std::move(packedData), i, 1))
476 std::ranges::for_each(sendRequests, [](
auto& request) { request->wait(); });
481 auto receiveRequest = grid.comm().irecv(receivedFlatData, 0, 1);
485 receiveRequest.wait();
489 std::cout <<
"On rank " << rank <<
", the received data size is " << receivedFlatData.size() << std::endl;
493 std::size_t n = 0, l = 0;
494 for (
const auto& [key, data] : sortedCellData)
496 auto& out = cellData[key];
497 const auto nComp = keyComponents[l++];
498 out.resize(localNumData[0]*nComp);
499 for (std::size_t k = 0; k < localNumData[0]; ++k)
500 for (std::size_t j = 0; j < nComp; ++j)
501 out[j + nComp*k] = receivedFlatData[n++];
504 for (
const auto& [key, data] : sortedPointData)
506 auto& out = pointData[key];
507 const auto nComp = keyComponents[l++];
508 out.resize(localNumData[1]*nComp);
509 for (std::size_t k = 0; k < localNumData[1]; ++k)
510 for (std::size_t j = 0; j < nComp; ++j)
511 out[j + nComp*k] = receivedFlatData[n++];
514 if (n != receivedFlatData.size())
515 DUNE_THROW(Dune::InvalidStateException,
"Unpacked data size does not match expected size.");
519 std::cout <<
"\n\n+++++++++++++++++++++++++++++++++++++++++++++" << std::endl;
std::unordered_map< std::string, std::vector< double > > Data
the cell / point data type for point data read from a grid file
Definition: vtkreader.hh:350
Definition: vtkgriddatahandle.hh:301
void communicateStructuredVtkData(const Grid &grid, const GridInput &gridInput, ::Dumux::VTKReader::Data &cellData, ::Dumux::VTKReader::Data &pointData)
Definition: vtkgriddatahandle.hh:305
A data handle for communicating grid data for VTK grids.
Definition: vtkgriddatahandle.hh:44
void gather(MessageBufferImp &buff, const Entity &e) const
Definition: vtkgriddatahandle.hh:246
typename Grid::LevelGridView GridView
Definition: vtkgriddatahandle.hh:45
VtkGridDataHandle(const Grid &grid, const GridInput &gridInput, VTKReader::Data &cellData, VTKReader::Data &pointData)
Definition: vtkgriddatahandle.hh:47
bool fixedSize(int dim, int codim) const
returns true if size per entity of given dim and codim is a constant
Definition: vtkgriddatahandle.hh:231
~VtkGridDataHandle()
Definition: vtkgriddatahandle.hh:179
bool contains(int dim, int codim) const
Definition: vtkgriddatahandle.hh:227
std::size_t size(const Entity &) const
Definition: vtkgriddatahandle.hh:235
void scatter(MessageBufferImp &buff, const Entity &e, std::size_t n)
Definition: vtkgriddatahandle.hh:264
Dune::CommDataHandleIF< VtkGridDataHandle< Grid, GridInput, Data >, typename Data::value_type > & interface()
Definition: vtkgriddatahandle.hh:224
A vtk file reader using tinyxml2 as xml backend.