diff --git a/lib/walberla/experimental/sweep/DomainSlices.hpp b/lib/walberla/experimental/sweep/DomainSlices.hpp index 0492cb53bdc2baddae1f8b4f8468eea4b95bfc02..64ca0ea93a62661932f608931620a829e25a6b6d 100644 --- a/lib/walberla/experimental/sweep/DomainSlices.hpp +++ b/lib/walberla/experimental/sweep/DomainSlices.hpp @@ -8,9 +8,16 @@ #include "stencil/Directions.h" +#include <memory> + namespace walberla::experimental::sweep { +template< typename T > +concept Sweep = requires(T obj, IBlock* block) { + { obj(block) } -> std::same_as< void >; +}; + template< typename T > concept CellIntervalSweep = requires(T obj, IBlock* block, const CellInterval& ci) { { obj.runOnCellInterval(block, ci) } -> std::same_as< void >; @@ -23,53 +30,116 @@ struct BorderSweepSlice { shared_ptr< StructuredBlockForest > blocks; cell_idx_t offset; + cell_idx_t expand; CellInterval ci(); bool isBlockAtBorder(IBlock& b); }; template<> -CellInterval BorderSweepSlice< stencil::Direction::T >::ci() +CellInterval BorderSweepSlice< stencil::Direction::W >::ci() { - return { { 0, 0, cell_idx_c(blocks->getNumberOfZCellsPerBlock()) - (offset + 1) }, - { cell_idx_c(blocks->getNumberOfXCellsPerBlock()) - 1, // - cell_idx_c(blocks->getNumberOfYCellsPerBlock()) - 1, // - cell_idx_c(blocks->getNumberOfZCellsPerBlock()) - (offset + 1) } }; + return { { offset, -expand, -expand }, + { offset, // + cell_idx_c(blocks->getNumberOfYCellsPerBlock()) - 1 + expand, // + cell_idx_c(blocks->getNumberOfZCellsPerBlock()) - 1 + expand } }; }; template<> -bool BorderSweepSlice< stencil::Direction::B >::isBlockAtBorder(IBlock& b) +CellInterval BorderSweepSlice< stencil::Direction::E >::ci() { - return blocks->atDomainZMinBorder(b); -} + return { { cell_idx_c(blocks->getNumberOfXCellsPerBlock()) - (offset + 1), -expand, -expand }, + { cell_idx_c(blocks->getNumberOfXCellsPerBlock()) - (offset + 1), // + cell_idx_c(blocks->getNumberOfYCellsPerBlock()) - 1 + expand, // + cell_idx_c(blocks->getNumberOfZCellsPerBlock()) - 1 + expand } }; +}; + +template<> +CellInterval BorderSweepSlice< stencil::Direction::S >::ci() +{ + return { { -expand, offset, -expand }, + { cell_idx_c(blocks->getNumberOfXCellsPerBlock()) - 1 + expand, // + offset, // + cell_idx_c(blocks->getNumberOfZCellsPerBlock()) - 1 + expand } }; +}; + +template<> +CellInterval BorderSweepSlice< stencil::Direction::N >::ci() +{ + return { { -expand, cell_idx_c(blocks->getNumberOfYCellsPerBlock()) - (offset + 1), -expand }, + { cell_idx_c(blocks->getNumberOfXCellsPerBlock()) - 1 + expand, // + cell_idx_c(blocks->getNumberOfYCellsPerBlock()) - (offset + 1), // + cell_idx_c(blocks->getNumberOfZCellsPerBlock()) - 1 + expand } }; +}; template<> CellInterval BorderSweepSlice< stencil::Direction::B >::ci() { - return { { 0, 0, offset }, - { cell_idx_c(blocks->getNumberOfXCellsPerBlock()) - 1, // - cell_idx_c(blocks->getNumberOfYCellsPerBlock()) - 1, // + return { { -expand, -expand, offset }, + { cell_idx_c(blocks->getNumberOfXCellsPerBlock()) - 1 + expand, // + cell_idx_c(blocks->getNumberOfYCellsPerBlock()) - 1 + expand, // offset } }; }; +template<> +CellInterval BorderSweepSlice< stencil::Direction::T >::ci() +{ + return { { -expand, -expand, cell_idx_c(blocks->getNumberOfZCellsPerBlock()) - (offset + 1) }, + { cell_idx_c(blocks->getNumberOfXCellsPerBlock()) - 1 + expand, // + cell_idx_c(blocks->getNumberOfYCellsPerBlock()) - 1 + expand, // + cell_idx_c(blocks->getNumberOfZCellsPerBlock()) - (offset + 1) } }; +}; + +template<> +bool BorderSweepSlice< stencil::Direction::W >::isBlockAtBorder(IBlock& b) +{ + return blocks->atDomainXMinBorder(b); +} + +template<> +bool BorderSweepSlice< stencil::Direction::E >::isBlockAtBorder(IBlock& b) +{ + return blocks->atDomainXMaxBorder(b); +} + +template<> +bool BorderSweepSlice< stencil::Direction::S >::isBlockAtBorder(IBlock& b) +{ + return blocks->atDomainYMinBorder(b); +} + +template<> +bool BorderSweepSlice< stencil::Direction::N >::isBlockAtBorder(IBlock& b) +{ + return blocks->atDomainYMaxBorder(b); +} + +template<> +bool BorderSweepSlice< stencil::Direction::B >::isBlockAtBorder(IBlock& b) +{ + return blocks->atDomainZMinBorder(b); +} + template<> bool BorderSweepSlice< stencil::Direction::T >::isBlockAtBorder(IBlock& b) { return blocks->atDomainZMaxBorder(b); } + } // namespace detail -template< stencil::Direction BorderDir, CellIntervalSweep Sweep > +template< stencil::Direction BorderDir, CellIntervalSweep Sweep_T > class BorderSweep { private: - Sweep sweep_; + Sweep_T sweep_; detail::BorderSweepSlice< BorderDir > slice_; CellInterval ci_; public: - BorderSweep(const shared_ptr< StructuredBlockForest >& blocks, const Sweep& sweep, cell_idx_t offset = 0) - : sweep_{ sweep }, slice_{ blocks, offset }, ci_{ slice_.ci() } + BorderSweep(const shared_ptr< StructuredBlockForest >& blocks, const Sweep_T& sweep, cell_idx_t offset = 0, + cell_idx_t expand = 0) + : sweep_{ sweep }, slice_{ blocks, offset, expand }, ci_{ slice_.ci() } {} void operator()(IBlock* block) @@ -78,4 +148,56 @@ class BorderSweep } }; +template< Sweep Sw1, Sweep Sw2 > +class FusedSweep +{ + private: + Sw1 sw1_; + Sw2 sw2_; + + public: + FusedSweep(const Sw1& sw1, const Sw2& sw2) : sw1_{ sw1 }, sw2_{ sw2 } {} + + void operator()(IBlock* b) + { + sw1_(b); + sw2_(b); + } + + template< typename = void > + requires(CellIntervalSweep< Sw1 > && CellIntervalSweep< Sw2 >) + void runOnCellInterval(IBlock* b, const CellInterval& ci) + { + sw1_.runOnCellInterval(b, ci); + sw2_.runOnCellInterval(b, ci); + } +}; + +namespace detail +{ +auto doFuse(const Sweep auto& sw1, const Sweep auto& sw2) { return FusedSweep{ sw1, sw2 }; } + +auto doFuse(const Sweep auto& first, const Sweep auto&... others) +{ + return FusedSweep{ first, doFuse(std::forward< decltype(others) >(others)...) }; +} +} // namespace detail + +class SweepFactory +{ + private: + std::shared_ptr< StructuredBlockForest > blocks_; + + public: + SweepFactory(const shared_ptr< StructuredBlockForest >& blocks) : blocks_{ blocks } {} + + template< stencil::Direction Dir, CellIntervalSweep Sweep_T > + BorderSweep< Dir, Sweep_T > atDomainBorder(const Sweep_T& sweep, cell_idx_t offset = 0, cell_idx_t expand = 0) + { + return { blocks_, sweep, offset, expand }; + } + + auto fuse(const Sweep auto&... sweeps) { return detail::doFuse(std::forward< decltype(sweeps) >(sweeps)...); } +}; + } // namespace walberla::experimental::sweep