diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 4a50799e8f99a005de5969996af1ffc6170449a0..71cbd392a0d9fe26a6b5a0240ca07915eab5d881 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -7,6 +7,7 @@ target_sources( walberla_experimental walberla/experimental/sweep/SparseIndexList.hpp walberla/experimental/lbm/GenericHbbBoundary.hpp walberla/experimental/lbm/IrregularFreeSlip.hpp + walberla/experimental/communication/UniformGpuFieldPackInfoBase.hpp ) target_link_libraries( diff --git a/lib/walberla/experimental/communication/UniformGpuFieldPackInfoBase.hpp b/lib/walberla/experimental/communication/UniformGpuFieldPackInfoBase.hpp new file mode 100644 index 0000000000000000000000000000000000000000..803455e449f5d8673de519883ebcf128fbdd0c41 --- /dev/null +++ b/lib/walberla/experimental/communication/UniformGpuFieldPackInfoBase.hpp @@ -0,0 +1,87 @@ +#pragma once + +// #if defined(WALBERLA_BUILD_WITH_CUDA) || defined(WALBERLA_BUILD_WITH_HIP) + +#include "core/all.h" + +#include "gpu/communication/GeneratedGPUPackInfo.h" + +#include <concepts> +#include <span> + +namespace walberla::experimental::communication +{ + +namespace detail +{ +template< typename T > +concept UniformGpuFieldPackInfoImpl = requires(T impl, // + typename T::Field_T& field, // + std::span< typename T::Field_T::value_type > buffer, // + stencil::Direction dir, // + CellInterval& ci, // + gpuStream_t stream // +) { + typename T::Field_T; + + { impl.doPack(field, buffer, dir, ci, stream) } -> std::same_as< void >; + + { impl.doUnpack(field, buffer, dir, ci, stream) } -> std::same_as< void >; + + { impl.elementsPerCell(dir) } -> std::same_as< uint_t >; +} +} // namespace detail + +template< detail::UniformGpuFieldPackInfoImpl Impl > +class UniformGpuFieldPackInfoBase : public gpu::GeneratedGPUPackInfo +{ + public: + UniformGpuFieldPackInfoBase(BlockDataID fieldId, uint_t sliceWidth = 0) + : fieldId_{ fieldId }, sliceWidth_{ sliceWidth } + {} + + void pack(stencil::Direction dir, unsigned char* bufferPtr, IBlock* block, gpuStream_t stream) override + { + using Field_T = typename Impl::Field_T; + using value_type = typename Field_T::value_type; + Field_T& field = *block->getData< Field_T >(fieldId_); + CellInterval ci; + field->getSliceBeforeGhostLayer(dir, ci, sliceWidth_, false); + std::span< value_type > buffer{ static_cast< value_type* >(bufferPtr), this->size(dir, block) }; + impl().doPack(field, buffer, dir, stream); + } + + void unpack(stencil::Direction dir, unsigned char* buffer, IBlock* block, gpuStream_t stream) override + { + using Field_T = typename Impl::Field_T; + using value_type = typename Field_T::value_type; + Field_T& field = *block->getData< Field_T >(fieldId_); + CellInterval ci; + field->getGhostRegion(dir, ci, sliceWidth_, false); + std::span< value_type > buffer{ static_cast< value_type* >(bufferPtr), this->size(dir, block) }; + impl().doUnpack(field, buffer, dir, stream); + } + + uint_t size(stencil::Direction dir, IBlock* block) override + { + using Field_T = typename Impl::Field_T; + + auto field = block->getData< Field_T >(fieldId_); + CellInterval ci; + field->getGhostRegion(dir, ci, 1, false); + + uint_t elementsPerCell{ impl().elementsPerCell(dir) }; + return elementsPerCell * ci.numCells(); + } + + protected: + BlockDataID fieldId_; + uint_t sliceWidth_; + + private: + Impl& impl() { return static_cast< Impl& >(*this); } +}; + +} // namespace walberla::experimental::communication + +// #endif