24#ifndef BLOCK_COMMUNICATOR_HH
25#define BLOCK_COMMUNICATOR_HH
33#ifdef PLATFORM_GPU_CUDA
39#ifdef PARALLEL_MODE_MPI
42template <
typename BLOCK>
45 const std::vector<CellID>& _cells;
49 std::unique_ptr<std::uint8_t[]> _buffer;
54 const std::vector<std::type_index>& fields,
55 const std::vector<CellID>& cells,
58 _source(block, fields),
59 _buffer(new std::uint8_t[_source.size(_cells)] { }),
60 _request(_buffer.get(), _source.
size(_cells),
77template <
typename BLOCK>
82 const std::vector<CellID>& _cells;
86 std::unique_ptr<std::uint8_t[]> _buffer;
109 bool operator <(
const ref& rhs)
const
111 return _task < rhs._task;
116 const std::vector<std::type_index>& fields,
117 const std::vector<CellID>& cells,
122 _target(block, fields),
123 _buffer(new std::uint8_t[_target.size(_cells)] { }),
124 _request(_buffer.get(), _target.
size(_cells),
130 return _rank < rhs._rank
131 || (_rank == rhs._rank && _tag < rhs._tag);
152template <
typename BLOCK>
155 const std::vector<CellID>& _targetCells;
156 const std::vector<CellID>& _sourceCells;
161 std::unique_ptr<std::uint8_t[]> _buffer;
165 const std::vector<std::type_index>& fields,
166 const std::vector<CellID>& targetCells, BLOCK& target,
167 const std::vector<CellID>& sourceCells, BLOCK& source):
168 _targetCells(targetCells),
169 _sourceCells(sourceCells),
170 _target(target, fields),
171 _source(source, fields),
172 _buffer(new std::uint8_t[_source.size(_sourceCells)] { })
174 OLB_ASSERT(_sourceCells.size() == _targetCells.size(),
175 "Source cell count must match target cell count");
180 _source.
serialize(_sourceCells, _buffer.get());
187template <
typename BLOCK>
188template <
typename T,
typename SUPER>
192#ifdef PARALLEL_MODE_MPI
199#ifdef PARALLEL_MODE_MPI
200, _mpiCommunicator(comm)
203#ifdef PARALLEL_MODE_MPI
206 if constexpr (std::is_same_v<SUPER, SuperGeometry<T,SUPER::d>>) {
207 if (!neighborhood.getCellsOutboundTo(remoteC).empty()) {
208 _sendTasks.emplace_back(_mpiCommunicator, tagCoordinator.get(loadBalancer.glob(_iC), remoteC),
209 loadBalancer.rank(remoteC),
210 neighborhood.getFieldsCommonWith(remoteC),
211 neighborhood.getCellsOutboundTo(remoteC),
212 super.template getBlock<BLOCK>(_iC));
216 _recvTasks.emplace_back(_mpiCommunicator, tagCoordinator.get(remoteC, loadBalancer.glob(_iC)),
217 loadBalancer.rank(remoteC),
218 neighborhood.getFieldsCommonWith(remoteC),
219 neighborhood.getCellsInboundFrom(remoteC),
220 super.template getBlock<BLOCK>(_iC));
224 _sendTasks.emplace_back(_mpiCommunicator, tagCoordinator.get(loadBalancer.glob(_iC), remoteC),
225 loadBalancer.rank(remoteC),
226 neighborhood.getFieldsCommonWith(remoteC),
227 neighborhood.getCellsOutboundTo(remoteC),
228 super.template getBlock<BLOCK>(_iC));
231 _recvTasks.emplace_back(_mpiCommunicator, tagCoordinator.get(remoteC, loadBalancer.glob(_iC)),
232 loadBalancer.rank(remoteC),
233 neighborhood.getFieldsCommonWith(remoteC),
234 neighborhood.getCellsInboundFrom(remoteC),
235 super.template getBlock<BLOCK>(_iC));
241 neighborhood.forNeighbors([&](
int localC) {
242 if (!neighborhood.getCellsInboundFrom(localC).empty()) {
243 _copyTasks.emplace_back(neighborhood.getFieldsCommonWith(localC),
244 neighborhood.getCellsInboundFrom(localC), super.template getBlock<BLOCK>(_iC),
245 neighborhood.getCellsRequestedFrom(localC), super.template getBlock<BLOCK>(loadBalancer.loc(localC)));
251#ifdef PARALLEL_MODE_MPI
253template <
typename BLOCK>
256 for (
auto& task : _recvTasks) {
261template <
typename BLOCK>
264 for (
auto& task : _sendTasks) {
269template <
typename BLOCK>
272 std::set<typename RecvTask::ref> pending(_recvTasks.begin(), _recvTasks.end());
273 while (!pending.empty()) {
274 auto task_iterator = pending.begin();
275 while (task_iterator != pending.end()) {
276 auto& task = *task_iterator;
277 if (task->isDone()) {
279 task_iterator = pending.erase(task_iterator);
288template <
typename BLOCK>
291 for (
auto& task : _sendTasks) {
298template <
typename BLOCK>
301 for (
auto& task : _copyTasks) {
Configurable overlap communication neighborhood of a block.
const std::vector< CellID > & getCellsOutboundTo(int iC) const
const std::vector< CellID > & getCellsInboundFrom(int iC) const
void forNeighbors(F f) const
Calls f(iC) for every neighboring cuboid ID iC.
Manual replacement for std::reference_wrapper<RecvTask>
RecvTask * operator->() const
Wrapper for a non-blocking block propagation receive request.
bool operator<(const RecvTask &rhs) const
RecvTask(MPI_Comm comm, int tag, int rank, const std::vector< std::type_index > &fields, const std::vector< CellID > &cells, BLOCK &block)
Wrapper for a non-blocking block propagation send request.
SendTask(MPI_Comm comm, int tag, int rank, const std::vector< std::type_index > &fields, const std::vector< CellID > &cells, BLOCK &block)
ConcreteBlockCommunicator(SUPER &super, LoadBalancer< T > &loadBalancer, SuperCommunicationTagCoordinator< T > &tagCoordinator, MPI_Comm comm, int iC, const BlockCommunicationNeighborhood< T, SUPER::d > &neighborhood)
Base class for all LoadBalancer.
bool isLocal(const int &glob)
returns whether glob is on this process
virtual Platform platform(int loc) const
Non-blocking MPI receive request.
Non-blocking MPI send request.
std::size_t serialize(ConstSpan< CellID > indices, std::uint8_t *buffer) const override
Serialize data at locations indices to buffer
std::size_t size(ConstSpan< CellID > indices) const override
Get serialized size for data at locations indices
std::size_t deserialize(ConstSpan< CellID > indices, const std::uint8_t *buffer) override
Deserialize data at locations indices to buffer
Communication-free negotation of unique tags for inter-cuboid communication.
Top level namespace for all of OpenLB.
@ GPU_CUDA
Vector CPU (AVX2 / AVX-512 collision)
#define OLB_ASSERT(COND, MESSAGE)