24#ifndef BLOCK_DYNAMICS_MAP_H
25#define BLOCK_DYNAMICS_MAP_H
36template<
typename T,
typename DESCRIPTOR>
struct AbstractCollisionO;
37template<
typename T,
typename DESCRIPTOR, Platform PLATFORM>
struct BlockCollisionO;
38template<
typename T,
typename DESCRIPTOR, Platform PLATFORM>
class ConcreteBlockLattice;
48template <
typename T,
typename DESCRIPTOR, Platform PLATFORM>
63 return _dynamics->
collide(abstractCell);
72 _dynamics->
computeU(abstractCell, u);
76 _dynamics->
computeJ(abstractCell, j);
89 _dynamics->
defineU(abstractCell, u);
112 throw std::runtime_error(
"getOmegaOrFallback not supported for legacy dynamics");
132template <
typename T,
typename DESCRIPTOR, Platform PLATFORM>
141 std::map<Dynamics<T,DESCRIPTOR>*,
142 std::unique_ptr<cpu::Dynamics<T,DESCRIPTOR,PLATFORM>>> _concreteDynamics;
148 auto iter = _concreteDynamics.find(_legacyDynamics[iCell]);
149 if (iter == _concreteDynamics.end()) {
150 iter = std::get<0>(_concreteDynamics.emplace(
151 _legacyDynamics[iCell],
153 _legacyDynamics[iCell])));
155 return std::get<1>(*iter).get();
161 _legacyDynamics{dynamics}
164 std::type_index
id()
const override
171 return _mask.weight();
174 void set(
CellID iCell,
bool state,
bool overlap)
override
177 _mask.set(iCell, state);
180 _dynamicsOfCells[iCell] = resolve(iCell);
194 _dynamicsOfCells = block.template getField<cpu::DYNAMICS<T,DESCRIPTOR,PLATFORM>>()[0].data();
207 throw std::runtime_error(
"LegacyBlockCollisionO only supports CollisionDispatchStrategy::Dominant");
211 #ifdef PARALLEL_MODE_OMP
212 #pragma omp declare reduction(+ : typename LatticeStatistics<T>::Aggregatable : omp_out += omp_in) initializer (omp_priv={})
215 if constexpr (DESCRIPTOR::d == 3) {
216 #ifdef PARALLEL_MODE_OMP
217 #pragma omp parallel for schedule(dynamic,1) reduction(+ : statistics)
219 for (
int iX=0; iX < block.
getNx(); ++iX) {
220 auto cell = block.
get(iX,0,0);
221 for (
int iY=0; iY < block.
getNy(); ++iY) {
222 for (
int iZ=0; iZ < block.
getNz(); ++iZ) {
225 cell.setCellId(iCell);
226 if (
auto cellStatistic = _legacyDynamics[iCell]->collide(cell)) {
227 statistics.increment(cellStatistic.rho, cellStatistic.uSqr);
231 if (
auto cellStatistic = _dynamicsOfCells[iCell]->collide(cell)) {
232 statistics.increment(cellStatistic.rho, cellStatistic.uSqr);
239 #ifdef PARALLEL_MODE_OMP
240 #pragma omp parallel for schedule(dynamic,1) reduction(+ : statistics)
242 for (
int iX=0; iX < block.
getNx(); ++iX) {
243 auto cell = block.
get(iX,0);
244 for (
int iY=0; iY < block.
getNy(); ++iY) {
247 cell.setCellId(iCell);
248 if (
auto cellStatistic = _legacyDynamics[iCell]->collide(cell)) {
249 statistics.increment(cellStatistic.rho, cellStatistic.uSqr);
253 if (
auto cellStatistic = _dynamicsOfCells[iCell]->collide(cell)) {
254 statistics.increment(cellStatistic.rho, cellStatistic.uSqr);
277template <
typename T,
typename DESCRIPTOR>
285 template <
typename DYNAMICS>
287 _id(typeid(DYNAMICS)),
289 return new DYNAMICS();
292 static_assert(dynamics::is_generic_v<T,DESCRIPTOR,DYNAMICS>,
293 "Promised DYNAMICS must be generic");
295 #ifdef PLATFORM_CPU_SISD
297 return new ConcreteBlockCollisionO<T,DESCRIPTOR,Platform::CPU_SISD,DYNAMICS>();
299 #ifdef PLATFORM_CPU_SIMD
301 return new ConcreteBlockCollisionO<T,DESCRIPTOR,Platform::CPU_SIMD,DYNAMICS>();
303 #ifdef PLATFORM_GPU_CUDA
305 return new ConcreteBlockCollisionO<T,DESCRIPTOR,Platform::GPU_CUDA,DYNAMICS>();
308 throw std::invalid_argument(
"Invalid PLATFORM");
314 std::type_index
id()
const {
324 template <Platform PLATFORM>
332template <
typename DYNAMICS>
334 typename DYNAMICS::descriptor_t>;
342 template <
typename T,
typename DESCRIPTOR, Platform PLATFORM>
357template<
typename T,
typename DESCRIPTOR, Platform PLATFORM>
362 std::map<std::type_index,
363 std::unique_ptr<BlockCollisionO<T,DESCRIPTOR,PLATFORM>>> _map;
365 std::unique_ptr<Dynamics<T,DESCRIPTOR>*[]> _dynamicsOfCells;
366 std::unique_ptr<BlockCollisionO<T,DESCRIPTOR,PLATFORM>*[]> _operatorOfCells;
376 auto iter = _map.find(promise.id());
377 if (iter == _map.end()) {
378 iter = _map.emplace(std::piecewise_construct,
379 std::forward_as_tuple(promise.id()),
380 std::forward_as_tuple(promise.template realize<PLATFORM>())).first;
381 iter->second->
setup(_lattice);
383 return *(iter->second);
389 if (_operatorOfCells[iCell] !=
nullptr) {
390 _map.at(_operatorOfCells[iCell]->
id())->set(iCell,
false, !_coreMask[iCell]);
392 collisionO.
set(iCell,
true, !_coreMask[iCell]);
393 _operatorOfCells[iCell] = &collisionO;
395 _dynamicsOfCells[iCell] = dynamics;
403 _dynamicsOfCells(new
Dynamics<T,DESCRIPTOR>* [_lattice.getNcells()] {
nullptr }),
405 _coreMask(lattice.template getData<CollisionSubdomainMask>()),
406 _dominantCollisionO(
nullptr)
409 _coreMask.set(_lattice.
getCellId(lattice),
true);
414 using LegacyO = LegacyBlockCollisionO<T,DESCRIPTOR,PLATFORM>;
415 _map[
typeid(LegacyO)] = std::make_unique<LegacyO>(_lattice.
getNcells(),
416 _dynamicsOfCells.get());
417 _map[
typeid(LegacyO)]->setup(_lattice);
427 return resolve(std::forward<
decltype(promise)>(promise)).getDynamics();
432 return _dynamicsOfCells[iCell];
437 return _dynamicsOfCells[iCell];
443 set(iCell, resolve(std::forward<
decltype(promise)>(promise)));
444 _dominantCollisionO =
nullptr;
454 auto iter = _map.find(dynamics->
id());
455 if (iter != _map.end()) {
456 set(iCell, *iter->second);
459 if (iter != _map.end()) {
462 _dynamicsOfCells[iCell] = dynamics;
463 set(iCell, *iter->second);
465 throw std::runtime_error(
"Legacy dynamics not supported on this platform");
468 _dominantCollisionO =
nullptr;
484 if (!_dominantCollisionO) {
485 _dominantCollisionO = std::max_element(_map.begin(),
487 [](
const auto& lhs,
const auto& rhs) ->
bool {
488 return lhs.second->weight() < rhs.second->weight();
491 _dominantCollisionO->
apply(_lattice, _coreMask, strategy);
495 for (
auto& [
id, collisionO] : _map) {
496 if (collisionO->
weight() > 0) {
497 collisionO->
apply(_lattice, _coreMask, strategy);
503 throw std::runtime_error(
"Invalid collision dispatch strategy");
511 std::stringstream out;
512 for (
auto& [_, collisionO] : _map) {
513 out << collisionO->
getDynamics()->getName() <<
", "
514 <<
static_cast<double>(collisionO.
weight()) / (_coreMask.weight())
Map between cell indices and concrete dynamics.
void set(std::size_t iCell, DynamicsPromise< T, DESCRIPTOR > &&promise)
Assigns promised dynamics to cell index iCell.
void set(std::size_t iCell, Dynamics< T, DESCRIPTOR > *dynamics)
Assigns dynamics pointer to cell index iCell.
void collide(CollisionDispatchStrategy strategy)
Executes local collision step for entire non-overlap area of lattice.
const Dynamics< T, DESCRIPTOR > * get(std::size_t iCell) const
std::string describe()
Returns a human-readable string listing all managed dynamics and their assigned fraction of cells.
Dynamics< T, DESCRIPTOR > * get(DynamicsPromise< T, DESCRIPTOR > &&promise)
Returns a pointer to dynamics matching the promise.
BlockDynamicsMap(ConcreteBlockLattice< T, DESCRIPTOR, PLATFORM > &lattice)
Constructor for a BlockDynamicsMap.
Dynamics< T, DESCRIPTOR > * get(std::size_t iCell)
Platform-abstracted block lattice for external access and inter-block interaction.
Cell< T, DESCRIPTOR > get(CellID iCell)
Get Cell interface for index iCell.
LatticeStatistics< T > & getStatistics()
Return a handle to the LatticeStatistics object.
std::size_t getNcells() const
Get number of cells.
int getNy() const
Read only access to block height.
void forCoreSpatialLocations(F f) const
int getNx() const
Read only access to block width.
CellID getCellId(LatticeR< D > latticeR) const
Get 1D cell ID.
int getNz() const
Read only access to block height.
Collision operation of concrete DYNAMICS on concrete block lattices of PLATFORM.
Implementation of BlockLattice on a concrete PLATFORM.
Factory for instances of a specific Dynamics type.
std::function< Dynamics< T, DESCRIPTOR > *()> _dynamicsConstructor
BlockCollisionO< T, DESCRIPTOR, PLATFORM > * realize()
Returns new instance of the collision operator for promised DYNAMICS.
Dynamics< T, DESCRIPTOR > * realize()
Returns new instance of the promised DYNAMICS.
std::function< AbstractCollisionO< T, DESCRIPTOR > *(Platform)> _operatorConstructor
std::type_index id() const
Returns type index of the promised DYNAMICS.
DynamicsPromise(meta::id< DYNAMICS > id=meta::id< DYNAMICS >{})
Concrete collision operator for legacy dynamics.
Dynamics< T, DESCRIPTOR > * getDynamics() override
LegacyBlockCollisionO(std::size_t count, Dynamics< T, DESCRIPTOR > **dynamics)
void apply(ConcreteBlockLattice< T, DESCRIPTOR, PLATFORM > &block, ConcreteBlockMask< T, PLATFORM > &subdomain, CollisionDispatchStrategy strategy) override
Apply collision on subdomain of block.
std::type_index id() const override
std::size_t weight() const override
Returns number of assigned cells.
void set(CellID iCell, bool state, bool overlap) override
Set whether iCell is covered by the present collision step.
void setup(ConcreteBlockLattice< T, DESCRIPTOR, PLATFORM > &block) override
Setup collision on block.
Concrete CPU dynamics for legacy dynamics.
void computeStress(cpu::Cell< T, DESCRIPTOR, PLATFORM > &cell, T &rho, T *u, T *pi) override
T getOmegaOrFallback(T fallback) override
void defineAllMomenta(cpu::Cell< T, DESCRIPTOR, PLATFORM > &cell, T &rho, T *u, T *pi) override
void computeU(cpu::Cell< T, DESCRIPTOR, PLATFORM > &cell, T *u) override
void defineRhoU(cpu::Cell< T, DESCRIPTOR, PLATFORM > &cell, T &rho, T *u) override
void defineRho(cpu::Cell< T, DESCRIPTOR, PLATFORM > &cell, T &rho) override
T computeRho(cpu::Cell< T, DESCRIPTOR, PLATFORM > &cell) override
LegacyConcreteDynamics(ConcreteBlockLattice< T, DESCRIPTOR, PLATFORM > &lattice, Dynamics< T, DESCRIPTOR > *dynamics)
void computeAllMomenta(cpu::Cell< T, DESCRIPTOR, PLATFORM > &cell, T &rho, T *u, T *pi) override
void computeRhoU(cpu::Cell< T, DESCRIPTOR, PLATFORM > &cell, T &rho, T *u) override
void inverseShiftRhoU(cpu::Cell< T, DESCRIPTOR, PLATFORM > &cell, T &rho, T *u) override
void computeJ(cpu::Cell< T, DESCRIPTOR, PLATFORM > &cell, T *j) override
void defineU(cpu::Cell< T, DESCRIPTOR, PLATFORM > &cell, T *u) override
T computeEquilibrium(int iPop, T rho, T *u) override
CellStatistic< T > collide(cpu::Cell< T, DESCRIPTOR, PLATFORM > &cell) override
Cell concept for concrete block lattices on CPU platforms.
Top level namespace for all of OpenLB.
std::uint32_t CellID
Type for sequential block-local cell indices.
Platform
OpenLB execution targets.
@ CPU_SIMD
Basic scalar CPU.
@ GPU_CUDA
Vector CPU (AVX2 / AVX-512 collision)
constexpr bool isPlatformCPU(Platform platform)
Returns true if platform is equal to Platform::CPU_*.
CollisionDispatchStrategy
Collision dispatch strategy.
@ Individual
Apply all dynamics individually (async for Platform::GPU_CUDA)
@ Dominant
Apply dominant dynamics using mask and fallback to virtual dispatch for others.
DynamicsPromise(meta::id< DYNAMICS >) -> DynamicsPromise< typename DYNAMICS::value_t, typename DYNAMICS::descriptor_t >
virtual void set(CellID iCell, bool state, bool overlap)=0
Set whether iCell is covered by the present collision step.
virtual std::size_t weight() const =0
Returns number of assigned cells.
virtual Dynamics< T, DESCRIPTOR > * getDynamics()=0
Collision operation on concrete blocks of PLATFORM.
virtual void setup(ConcreteBlockLattice< T, DESCRIPTOR, PLATFORM > &block)=0
Setup collision on block.
virtual void apply(ConcreteBlockLattice< T, DESCRIPTOR, PLATFORM > &block, ConcreteBlockMask< T, PLATFORM > &subdomain, CollisionDispatchStrategy strategy)=0
Apply collision on subdomain of block using strategy.
Return value of any collision.
Mask describing the subdomain on which to apply the collision step.
Interface for per-cell dynamics.
virtual void inverseShiftRhoU(ConstCell< T, DESCRIPTOR > &cell, T &rho, T u[DESCRIPTOR::d]) const
Calculate population momenta s.t. the physical momenta are reproduced by the computeRhoU.
virtual T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d]) const any_platform=0
Return iPop equilibrium for given first and second momenta.
virtual T computeRho(ConstCell< T, DESCRIPTOR > &cell) const =0
Compute particle density.
virtual std::type_index id()=0
Expose unique type-identifier for RTTI.
virtual void computeU(ConstCell< T, DESCRIPTOR > &cell, T u[DESCRIPTOR::d]) const =0
Compute fluid velocity.
virtual void computeStress(ConstCell< T, DESCRIPTOR > &cell, T rho, const T u[DESCRIPTOR::d], T pi[util::TensorVal< DESCRIPTOR >::n]) const =0
Compute stress tensor.
virtual void defineU(Cell< T, DESCRIPTOR > &cell, const T u[DESCRIPTOR::d])=0
Set fluid velocity.
virtual void defineRhoU(Cell< T, DESCRIPTOR > &cell, T rho, const T u[DESCRIPTOR::d])=0
Define fluid velocity and particle density.
virtual void computeRhoU(ConstCell< T, DESCRIPTOR > &cell, T &rho, T u[DESCRIPTOR::d]) const =0
Compute fluid velocity and particle density.
virtual void defineRho(Cell< T, DESCRIPTOR > &cell, T rho)=0
Set particle density.
virtual void computeAllMomenta(ConstCell< T, DESCRIPTOR > &cell, T &rho, T u[DESCRIPTOR::d], T pi[util::TensorVal< DESCRIPTOR >::n]) const =0
Compute all momenta up to second order.
virtual void computeJ(ConstCell< T, DESCRIPTOR > &cell, T j[DESCRIPTOR::d]) const =0
Compute fluid momentum.
virtual void defineAllMomenta(Cell< T, DESCRIPTOR > &cell, T rho, const T u[DESCRIPTOR::d], const T pi[util::TensorVal< DESCRIPTOR >::n])=0
Define all momenta up to second order.
virtual CellStatistic< T > collide(Cell< T, DESCRIPTOR > &cell)
Perform purely-local collision step on Cell interface (legacy, to be deprecated)
Virtual interface for dynamically-dispatched dynamics access on CPU targets.