dune-mmesh (unstable)

communication.hh
1#pragma GCC diagnostic ignored "-Wattributes"
2#ifndef DUNE_MMESH_MISC_COMMUNICATION_HH
3#define DUNE_MMESH_MISC_COMMUNICATION_HH
4
5#include <mpi.h>
6
7#include <dune/common/hybridutilities.hh>
8#include <dune/common/parallel/variablesizecommunicator.hh>
9#include <dune/grid/common/gridenums.hh>
10#include <vector>
11
12#include "objectstream.hh"
13
14namespace Dune {
15
16template <class Grid, class MMeshType>
17class MMeshCommunication {
18 typedef MMeshCommunication<Grid, MMeshType> This;
19 typedef PartitionHelper<MMeshType> PartitionHelperType;
20 typedef typename PartitionHelperType::LinksType Links;
21
22 // prohibit copying and assignment
23 MMeshCommunication(const This &);
24 const This &operator=(const This &);
25
26 template <int codim>
27 struct PackData;
28
29 template <int codim>
30 struct UnpackData;
31
32 public:
33 static const int dimension = Grid::dimension;
34
35 MMeshCommunication(const PartitionHelperType &partitionHelper)
36 : partitionHelper_(partitionHelper), tag_(0) {}
37
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();
46
47 // vector of message buffers
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();
53 }
54
55 // pack data on send entities
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) {
60 Hybrid::forEach(
61 std::make_index_sequence<dimension + 1>{}, [&](auto codim) {
62 PackData<codim>::apply(links, partitionHelper_, dataHandle,
63 sendBuffers, entity);
64 });
65 }
66 }
67
68 if (packAll) {
69 // pack data on receive entities
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) {
74 Hybrid::forEach(
75 std::make_index_sequence<dimension + 1>{}, [&](auto codim) {
76 PackData<codim>::apply(links, partitionHelper_, dataHandle,
77 sendBuffers, entity);
78 });
79 }
80 }
81 }
82
83 // Send to all links
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);
91 }
92
93 // Receive data
94 int count = 0;
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;
100
101 int source = links[link];
102
103 int available = 0;
104 MPI_Status status;
105 MPI_Iprobe(source, tag_, comm, &available, &status);
106
107 if (available) {
108 int bufferSize;
109 MPI_Get_count(&status, MPI_BYTE, &bufferSize);
110
111 BufferType &buf = recvBuffers[link];
112 buf.reserve(bufferSize);
113 buf.clear();
114
115 MPI_Request &request = recvRequests[link];
116 MPI_Irecv(buf._buf, bufferSize, MPI_BYTE, source, tag_, comm,
117 &request);
118 buf.seekp(bufferSize);
119
120 count++;
121 received[link] = true;
122 }
123 }
124 }
125
126 MPI_Waitall(links.size(), sendRequests, MPI_STATUSES_IGNORE);
127 MPI_Waitall(links.size(), recvRequests, MPI_STATUSES_IGNORE);
128
129 // unpack data on receive entities
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) {
134 Hybrid::forEach(
135 std::make_index_sequence<dimension + 1>{}, [&](auto codim) {
136 UnpackData<codim>::apply(links, partitionHelper_, dataHandle,
137 recvBuffers, entity);
138 });
139 }
140 }
141
142 if (packAll) {
143 // unpack data on send entities
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) {
148 Hybrid::forEach(
149 std::make_index_sequence<dimension + 1>{}, [&](auto codim) {
150 UnpackData<codim>::apply(links, partitionHelper_, dataHandle,
151 recvBuffers, entity);
152 });
153 }
154 }
155 }
156
157 tag_++;
158 if (tag_ < 0) tag_ = 0;
159 }
160
161 private:
162 const PartitionHelperType &partitionHelper_;
163 mutable int tag_;
164};
165
166// MMeshCommunication::PackData
167// -----------------------------------
168
169template <class Grid, class MMeshType>
170template <int codim>
171struct MMeshCommunication<Grid, MMeshType>::PackData {
172 typedef typename Grid::template Codim<0>::Entity Element;
173
174 typedef typename Grid::template Codim<codim>::Entity Entity;
175
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) {
181 // if codim is not contained just go on
182 if (!dataHandle.contains(dimension, codim)) return;
183
184 const auto &connectivity = partitionHelper.connectivity(element);
185
186 const int numSubEntities = element.subEntities(codim);
187 for (int subEntity = 0; subEntity < numSubEntities; ++subEntity) {
188 // get subentity
189 const Entity &entity = element.template subEntity<codim>(subEntity);
190
191 for (int link = 0; link < links.size(); ++link) {
192 // make sure entity belongs to the link
193 if (connectivity.count(links[link]) > 0 ||
194 links[link] == partitionHelper.rank(element)) {
195 std::size_t size = dataHandle.size(entity);
196
197 // write size into stream
198 buffer[link].write(size);
199
200 // write data to message buffer using data handle
201 dataHandle.gather(buffer[link], entity);
202 }
203 }
204 }
205 }
206};
207
208// MMeshCommunication::UnpackData
209// -------------------------------------
210
211template <class Grid, class MMeshType>
212template <int codim>
213struct MMeshCommunication<Grid, MMeshType>::UnpackData {
214 using Element = typename Grid::template Codim<0>::Entity;
215
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) {
221 // if codim is not contained just go on
222 if (!dataHandle.contains(dimension, codim)) return;
223
224 const auto &connectivity = partitionHelper.connectivity(element);
225
226 // get number of sub entities
227 const int numSubEntities = element.subEntities(codim);
228 for (int subEntity = 0; subEntity < numSubEntities; ++subEntity) {
229 // get subentity
230 const auto &entity = element.template subEntity<codim>(subEntity);
231
232 for (int link = 0; link < links.size(); ++link) {
233 // make sure entity belongs to the rank of the link
234 if (links[link] == partitionHelper.rank(element) ||
235 connectivity.count(links[link]) > 0) {
236 // read size from stream
237 std::size_t size(0);
238 buffer[link].read(size);
239
240 // read data from message buffer using data handle
241 dataHandle.scatter(buffer[link], entity, size);
242 }
243 }
244 }
245 }
246};
247
248} // namespace Dune
249
250#endif
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Sep 5, 22:35, 2025)