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;