1#pragma GCC diagnostic ignored "-Wattributes"
2#ifndef DUNE_MMESH_MISC_COMMUNICATION_HH
3#define DUNE_MMESH_MISC_COMMUNICATION_HH
7#include <dune/common/hybridutilities.hh>
8#include <dune/common/parallel/variablesizecommunicator.hh>
9#include <dune/grid/common/gridenums.hh>
12#include "objectstream.hh"
16template <
class Gr
id,
class MMeshType>
17class MMeshCommunication {
18 typedef MMeshCommunication<Grid, MMeshType> This;
19 typedef PartitionHelper<MMeshType> PartitionHelperType;
20 typedef typename PartitionHelperType::LinksType Links;
23 MMeshCommunication(
const This &);
24 const This &operator=(
const This &);
33 static const int dimension = Grid::dimension;
35 MMeshCommunication(
const PartitionHelperType &partitionHelper)
36 : partitionHelper_(partitionHelper), tag_(0) {}
38 template <
class PackIterator,
class UnpackIterator,
class DataHandleImp>
39 void operator()(
const PackIterator packBegin,
const PackIterator packEnd,
40 const UnpackIterator unpackBegin,
41 const UnpackIterator unpackEnd, DataHandleImp &dataHandle,
42 const PartitionType sendType,
const PartitionType recvType,
43 const bool packAll)
const {
44 typedef MMeshImpl::ObjectStream BufferType;
45 const Links &links = partitionHelper_.links();
48 std::vector<BufferType> sendBuffers(links.size()),
49 recvBuffers(links.size());
50 for (
int link = 0; link < links.size(); ++link) {
51 sendBuffers[link].clear();
52 recvBuffers[link].clear();
56 for (PackIterator it = packBegin; it != packEnd; ++it) {
57 const typename PackIterator::Entity &entity = *it;
58 if (entity.partitionType() == sendType &&
59 partitionHelper_.connectivity(entity).size() > 0) {
61 std::make_index_sequence<dimension + 1>{}, [&](
auto codim) {
62 PackData<codim>::apply(links, partitionHelper_, dataHandle,
70 for (UnpackIterator it = unpackBegin; it != unpackEnd; ++it) {
71 const typename UnpackIterator::Entity &entity = *it;
72 if (entity.partitionType() == recvType &&
73 partitionHelper_.connectivity(entity).size() > 0) {
75 std::make_index_sequence<dimension + 1>{}, [&](
auto codim) {
76 PackData<codim>::apply(links, partitionHelper_, dataHandle,
84 const auto &comm = partitionHelper_.comm();
85 MPI_Request sendRequests[links.size()];
86 for (
int link = 0; link < links.size(); ++link) {
87 BufferType &buf = sendBuffers[link];
88 int dest = links[link];
89 MPI_Request &request = sendRequests[link];
90 MPI_Isend(buf._buf, buf._wb, MPI_BYTE, dest, tag_, comm, &request);
95 std::vector<bool> received(links.size(),
false);
96 MPI_Request recvRequests[links.size()];
97 while (count < links.size()) {
98 for (
int link = 0; link < links.size(); ++link) {
99 if (received[link])
continue;
101 int source = links[link];
105 MPI_Iprobe(source, tag_, comm, &available, &status);
109 MPI_Get_count(&status, MPI_BYTE, &bufferSize);
111 BufferType &buf = recvBuffers[link];
112 buf.reserve(bufferSize);
115 MPI_Request &request = recvRequests[link];
116 MPI_Irecv(buf._buf, bufferSize, MPI_BYTE, source, tag_, comm,
118 buf.seekp(bufferSize);
121 received[link] =
true;
126 MPI_Waitall(links.size(), sendRequests, MPI_STATUSES_IGNORE);
127 MPI_Waitall(links.size(), recvRequests, MPI_STATUSES_IGNORE);
130 for (UnpackIterator it = unpackBegin; it != unpackEnd; ++it) {
131 const typename UnpackIterator::Entity &entity = *it;
132 if (entity.partitionType() == recvType &&
133 partitionHelper_.connectivity(entity).size() > 0) {
135 std::make_index_sequence<dimension + 1>{}, [&](
auto codim) {
136 UnpackData<codim>::apply(links, partitionHelper_, dataHandle,
137 recvBuffers, entity);
144 for (PackIterator it = packBegin; it != packEnd; ++it) {
145 const typename PackIterator::Entity &entity = *it;
146 if (entity.partitionType() == sendType &&
147 partitionHelper_.connectivity(entity).size() > 0) {
149 std::make_index_sequence<dimension + 1>{}, [&](
auto codim) {
150 UnpackData<codim>::apply(links, partitionHelper_, dataHandle,
151 recvBuffers, entity);
158 if (tag_ < 0) tag_ = 0;
162 const PartitionHelperType &partitionHelper_;
169template <
class Gr
id,
class MMeshType>
171struct MMeshCommunication<Grid, MMeshType>::PackData {
172 typedef typename Grid::template Codim<0>::Entity Element;
174 typedef typename Grid::template Codim<codim>::Entity Entity;
176 template <
class DataHandleIF,
class BufferType>
177 static void apply(
const Links &links,
178 const PartitionHelperType &partitionHelper,
179 DataHandleIF &dataHandle, std::vector<BufferType> &buffer,
180 const Element &element) {
182 if (!dataHandle.contains(dimension, codim))
return;
184 const auto &connectivity = partitionHelper.connectivity(element);
186 const int numSubEntities = element.subEntities(codim);
187 for (
int subEntity = 0; subEntity < numSubEntities; ++subEntity) {
189 const Entity &entity = element.template subEntity<codim>(subEntity);
191 for (
int link = 0; link < links.size(); ++link) {
193 if (connectivity.count(links[link]) > 0 ||
194 links[link] == partitionHelper.rank(element)) {
195 std::size_t size = dataHandle.size(entity);
198 buffer[link].write(size);
201 dataHandle.gather(buffer[link], entity);
211template <
class Gr
id,
class MMeshType>
213struct MMeshCommunication<Grid, MMeshType>::UnpackData {
214 using Element =
typename Grid::template Codim<0>::Entity;
216 template <
class DataHandleIF,
class BufferType>
217 static void apply(
const Links &links,
218 const PartitionHelperType &partitionHelper,
219 DataHandleIF &dataHandle, std::vector<BufferType> &buffer,
220 const Element &element) {
222 if (!dataHandle.contains(dimension, codim))
return;
224 const auto &connectivity = partitionHelper.connectivity(element);
227 const int numSubEntities = element.subEntities(codim);
228 for (
int subEntity = 0; subEntity < numSubEntities; ++subEntity) {
230 const auto &entity = element.template subEntity<codim>(subEntity);
232 for (
int link = 0; link < links.size(); ++link) {
234 if (links[link] == partitionHelper.rank(element) ||
235 connectivity.count(links[link]) > 0) {
238 buffer[link].read(size);
241 dataHandle.scatter(buffer[link], entity, size);