17#ifdef NF_WITH_MPI_SUPPORT
40template<
typename ValueType>
61 : exec_(rhs.exec_), value_(rhs.value_), refValue_(rhs.refValue_),
62 valueFraction_(rhs.valueFraction_), refGrad_(rhs.refGrad_),
63 boundaryTypes_(rhs.boundaryTypes_), offset_(rhs.offset_), nBoundaries_(rhs.nBoundaries_),
64 nBoundaryFaces_(rhs.nBoundaryFaces_)
73 : exec_(rhs.exec_), value_(
exec, rhs.value_), refValue_(
exec, rhs.refValue_),
74 valueFraction_(
exec, rhs.valueFraction_), refGrad_(
exec, rhs.refGrad_),
76 nBoundaries_(rhs.nBoundaries_), nBoundaryFaces_(rhs.nBoundaryFaces_)
91 offset_(
SerialExecutor {}, nBoundaryTypes + 1), nBoundaries_(nBoundaryTypes),
184 return offset_.
data()[patchId + 1] - offset_.
data()[patchId];
194 nBoundaries_ = rhs.nBoundaries_;
195 nBoundaryFaces_ = rhs.nBoundaryFaces_;
198 refValue_ = rhs.refValue_;
199 valueFraction_ = rhs.valueFraction_;
200 refGrad_ = rhs.refGrad_;
201 boundaryTypes_ = rhs.boundaryTypes_;
202 offset_ = rhs.offset_;
211 nBoundaries_ = rhs.nBoundaries_;
212 nBoundaryFaces_ = rhs.nBoundaryFaces_;
214 value_ = std::move(rhs.value_);
215 refValue_ = std::move(rhs.refValue_);
216 valueFraction_ = std::move(rhs.valueFraction_);
217 refGrad_ = std::move(rhs.refGrad_);
218 boundaryTypes_ = std::move(rhs.boundaryTypes_);
219 offset_ = std::move(rhs.offset_);
223#ifdef NF_WITH_MPI_SUPPORT
224 void communicate(std::pair<localIdx, localIdx>
range,
int neighborRank)
226 const auto [rangeStart, rangeEnd] =
range;
227 const localIdx patchSize = rangeEnd - rangeStart;
229 mpi::Environment mpiEnv;
231 buf.rangeStart = rangeStart;
232 buf.patchSize = patchSize;
234 const auto byteCount =
236 const auto neighborRankLabel =
static_cast<mpi_label_t>(neighborRank);
242 const auto nProcs =
static_cast<mpi_label_t>(mpiEnv.sizeRank());
243 const auto myRankLabel =
static_cast<mpi_label_t>(mpiEnv.rank());
244 const mpi_label_t pairTag = std::min(myRankLabel, neighborRankLabel) * nProcs
245 + std::max(myRankLabel, neighborRankLabel);
247 const bool useGpuPath = mpiEnv.gpuAwareMpi() && std::holds_alternative<GPUExecutor>(exec_);
249 MPI_Request sendReq, recvReq;
254 reinterpret_cast<const char*
>(value_.data() + rangeStart),
262 reinterpret_cast<char*
>(buf.deviceRecvBuf->data()),
272 auto valH = value_.copyToHost();
273 buf.sendBuf.resize(
static_cast<std::size_t
>(patchSize));
274 buf.recvBuf.resize(
static_cast<std::size_t
>(patchSize));
275 for (
localIdx k = 0; k < patchSize; k++)
276 buf.sendBuf[
static_cast<std::size_t
>(k)] = valH.view()[rangeStart + k];
278 reinterpret_cast<const char*
>(buf.sendBuf.data()),
286 reinterpret_cast<char*
>(buf.recvBuf.data()),
294 communicating_ =
true;
295 requests_.push_back(sendReq);
296 requests_.push_back(recvReq);
297 commBuffers_.push_back(std::move(buf));
300 bool isComplete()
const
302 if (requests_.empty() || !communicating_)
return true;
303 for (
auto& req : requests_)
305 if (!mpi::test(&req))
return false;
307 communicating_ =
false;
316#ifdef NF_WITH_MPI_SUPPORT
317 if (requests_.empty() || !communicating_)
return;
318 while (!isComplete())
321 mpi::Environment mpiEnv;
322 const bool useGpuPath = mpiEnv.gpuAwareMpi() && std::holds_alternative<GPUExecutor>(exec_);
325 for (
const auto& buf : commBuffers_)
327 auto srcView = buf.deviceRecvBuf->view();
328 auto dstView = value_.view();
329 const localIdx start = buf.rangeStart;
333 KOKKOS_LAMBDA(
const localIdx k) { dstView[start + k] = srcView[k]; }
337 else if (std::holds_alternative<GPUExecutor>(exec_))
343 auto valH = value_.copyToHost();
344 for (
const auto& buf : commBuffers_)
346 for (
localIdx k = 0; k < buf.patchSize; k++)
347 valH.view()[buf.rangeStart + k] = buf.recvBuf[
static_cast<std::size_t
>(k)];
350 value_ = backToDevice;
359 for (
const auto& buf : commBuffers_)
361 ValueType* dst = value_.data() + buf.rangeStart;
362 for (
localIdx k = 0; k < buf.patchSize; k++)
363 dst[k] = buf.recvBuf[
static_cast<std::size_t
>(k)];
367 communicating_ =
false;
368 commBuffers_.clear();
378 return {offset_.
data()[patchId], offset_.
data()[patchId + 1]};
413#ifdef NF_WITH_MPI_SUPPORT
416 std::vector<ValueType> sendBuf;
417 std::vector<ValueType> recvBuf;
418 std::optional<Vector<ValueType>> deviceRecvBuf;
422 mutable std::vector<MPI_Request>
424 mutable std::vector<CommBuffer>
426 mutable bool communicating_ =
false;
440 template<
typename ValueType>
443 return in.valueNoWait();
Represents the boundary fields for a computational domain.
std::pair< localIdx, localIdx > range(localIdx patchId) const
Get the range for a given patchId.
Vector< ValueType > & refValue()
Get the view storing the Dirichlet boundary values.
ValueType BoundaryDataType
const Vector< ValueType > & refValue() const
Get the view storing the Dirichlet boundary values.
const Vector< ValueType > & value() const
Get the view storing the computed values from the boundary condition.
const Vector< int > & boundaryTypes() const
Get the view storing the boundary types.
localIdx nBoundaries() const
Get the number of boundaries.
Vector< scalar > & valueFraction()
Get the view storing the fraction of the boundary value.
localIdx nBoundaryFaces(localIdx patchId) const
Get the number of boundary faces for this patch.
BoundaryData< ValueType > & operator=(const BoundaryData< ValueType > &&rhs)
BoundaryData(const Executor &exec, localIdx nBoundaryFaces, localIdx nBoundaryTypes)
constructor with default initialized Vectors from sizes.
BoundaryData(const Executor &exec, const BoundaryData< ValueType > &rhs)
Copy constructor.
const Vector< localIdx > & offset() const
Get the view storing the offsets of each boundary.
localIdx nBoundaryFaces() const
Get the number of boundary faces.
const Vector< scalar > & valueFraction() const
Get the view storing the fraction of the boundary value.
BoundaryData(const Executor &exec, const std::vector< localIdx > &offsets)
constructor from a given offsets vector @warn all members except offsets are default constructed
Vector< ValueType > & value()
Get the view storing the computed values from the boundary condition.
const Vector< ValueType > & refGrad() const
Get the view storing the Neumann boundary values.
Vector< ValueType > & refGrad()
Get the view storing the Neumann boundary values.
BoundaryData(const BoundaryData< ValueType > &rhs)
Copy constructor.
BoundaryData< ValueType > & operator=(const BoundaryData< ValueType > &rhs)
Reference executor for serial CPU execution.
A class to contain the data and executors for a field and define some basic operations.
Vector< ValueType > copyToExecutor(Executor dstExec) const
Copies the data to a new field on a specific executor.
ValueType * data()
Direct access to the underlying field data.
Integer types used throughout NeoN.
void fence(const Executor &exec)
std::variant< SerialExecutor, CPUExecutor, GPUExecutor > Executor
void parallelFor(const ExecutorType &, std::pair< localIdx, localIdx > range, const Kernel &kernel, std::string name)
Passkey granting non-draining access to BoundaryData's value storage.
static Vector< ValueType > & value(BoundaryData< ValueType > &in)