24#ifndef SIMD_OPERATOR_H
25#define SIMD_OPERATOR_H
45 operator bool()
const {
56template <
typename T,
unsigned D>
64 std::array<Pack<T>,D> _packs;
73 _packs[iD] = &_data[iD][_index];
80 _packs(rhs._packs) { }
92 template <
typename U,
typename IMPL>
95 for (
unsigned iDim=0; iDim < D; ++iDim) {
110template <
typename T,
typename DESCRIPTOR,
typename V,
typename... RW_FIELDS>
123 std::tuple<FieldD<V,DESCRIPTOR,RW_FIELDS>...> _fields;
136 using FIELD =
typename decltype(field)::type;
138 auto& pack = std::get<(rw_fields::template index<FIELD>())>(_fields);
140 for (
unsigned iD=0; iD < DESCRIPTOR::template size<FIELD>(); ++iD) {
150 using FIELD =
typename decltype(field)::type;
152 auto& pack = std::get<(rw_fields::template index<FIELD>())>(_fields);
154 for (
unsigned iD=0; iD < DESCRIPTOR::template size<FIELD>(); ++iD) {
162 return std::get<(rw_fields::template index<descriptors::POPULATION>())>(_fields)[iPop];
166 template <
typename FIELD>
168 if constexpr (rw_fields::template contains<FIELD>()) {
169 if constexpr (DESCRIPTOR::template size<FIELD>() == 1) {
170 return std::get<(rw_fields::template index<FIELD>())>(_fields)[0];
172 return std::get<(rw_fields::template index<FIELD>())>(_fields);
176 if constexpr (DESCRIPTOR::template size<FIELD>() == 1) {
180 return &fieldArray[iD][_iCell];
184 __builtin_unreachable();
188 template <
typename FIELD>
190 if constexpr (rw_fields::template contains<FIELD>()) {
191 std::get<(rw_fields::template index<FIELD>())>(_fields) = value;
194 for (
unsigned iD=0; iD < DESCRIPTOR::template size<FIELD>(); ++iD) {
201 template <
typename FIELD>
203 if constexpr (rw_fields::template contains<FIELD>()) {
204 std::get<(rw_fields::template index<FIELD>())>(_fields) = value;
207 for (
unsigned iD=0; iD < DESCRIPTOR::template size<FIELD>(); ++iD) {
214 template <
typename FIELD>
217 return std::get<(rw_fields::template index<FIELD>())>(_fields);
221 template <
typename FIELD>
228 template <
typename FIELD>
229 std::enable_if_t<rw_fields::template contains<FIELD>(),V&>
231 return std::get<(rw_fields::template index<FIELD>())>(_fields)[iD];
235 template <
typename FIELD>
236 std::enable_if_t<!rw_fields::template contains<FIELD>(),V>
245template <
typename T,
typename DESCRIPTOR,
typename DYNAMICS>
252 _parameters{parameters} {
256 return DYNAMICS().collide(cell, *_parameters);
260 return typename DYNAMICS::MomentaF().computeRho(cell);
263 typename DYNAMICS::MomentaF().computeU(cell, u);
266 typename DYNAMICS::MomentaF().computeJ(cell, j);
269 typename DYNAMICS::MomentaF().computeRhoU(cell, rho, u);
272 typename DYNAMICS::MomentaF().computeStress(cell, rho, u, pi);
275 typename DYNAMICS::MomentaF().computeAllMomenta(cell, rho, u, pi);
279 if constexpr (DYNAMICS::parameters::template contains<descriptors::OMEGA>()) {
280 return _parameters->template get<descriptors::OMEGA>();
284 __builtin_unreachable();
288 typename DYNAMICS::EquilibriumF().compute(cell, rho, u, fEq);
292 typename DYNAMICS::MomentaF().defineRho(cell, rho);
296 typename DYNAMICS::MomentaF().defineU(cell, u);
300 typename DYNAMICS::MomentaF().defineRhoU(cell, rho, u);
304 typename DYNAMICS::MomentaF().defineAllMomenta(cell, rho, u, pi);
308 typename DYNAMICS::MomentaF().inverseShiftRhoU(cell, rho, u);
324template <
typename T,
typename DESCRIPTOR,
typename DYNAMICS>
328 std::unique_ptr<DYNAMICS> _dynamics;
329 std::unique_ptr<cpu::Dynamics<T,DESCRIPTOR,Platform::CPU_SIMD>> _concreteDynamics;
342 if (
auto cellStatistic = _dynamicsOfCells[iCell]->collide(cell)) {
343 statistics.
increment(cellStatistic.rho, cellStatistic.uSqr);
355 if constexpr (dynamics::is_vectorizable_v<DYNAMICS>) {
358 auto simdParameters = parameters.template copyAs<cpu::simd::Pack<T>>();
359 auto cellStatistic = DYNAMICS().collide(cell, simdParameters);
360 for (
unsigned i=0; i < cpu::simd::Pack<T>::size; ++i) {
362 if (cellStatistic.rho[i] != T{-1}) {
363 statistics.
increment(cellStatistic.rho[i], cellStatistic.uSqr[i]);
365 }
else if (subdomain[iCell+i]) {
366 applyOther(block, statistics, iCell+i);
370 for (std::size_t i=iCell; i < iCell+cpu::simd::Pack<T>::size; ++i) {
372 applyOther(block, statistics, i);
381 _dynamics(new DYNAMICS()),
382 _parameters(nullptr),
386 std::type_index
id()
const override
388 return typeid(DYNAMICS);
393 return _mask->weight();
396 void set(
CellID iCell,
bool state,
bool overlap)
override
399 if constexpr (!std::is_same_v<DYNAMICS,NoDynamics<T,DESCRIPTOR>>) {
401 _mask->set(iCell, state);
405 _dynamicsOfCells[iCell] = _concreteDynamics.get();
411 return _dynamics.get();
416 _parameters = &block.template getData<OperatorParameters<DYNAMICS>>().parameters;
417 _mask = &block.template getData<DynamicsMask<DYNAMICS>>();
418 if constexpr (dynamics::has_parametrized_momenta_v<DYNAMICS>) {
419 _dynamics->setMomentaParameters(_parameters);
424 _dynamicsOfCells = block.template getField<cpu::DYNAMICS<T,DESCRIPTOR,Platform::CPU_SIMD>>()[0].data();
433 throw std::runtime_error(
"Platform::CPU_SIMD currently only support CollisionDispatchStrategy::Dominant");
438 #ifdef PARALLEL_MODE_OMP
439 #pragma omp declare reduction(+ : typename LatticeStatistics<T>::Aggregatable : omp_out += omp_in) initializer (omp_priv={})
442 if constexpr (dynamics::is_vectorizable_v<DYNAMICS>) {
446 #ifdef PARALLEL_MODE_OMP
447 #pragma omp parallel for schedule(static) reduction(+ : statistics)
450 apply(block, subdomain, mask, *_parameters, statistics, iCell);
453 #ifdef PARALLEL_MODE_OMP
454 #pragma omp parallel for schedule(static) reduction(+ : statistics)
456 for (std::size_t iCell=0; iCell < block.
getNcells(); ++iCell) {
459 if (
auto cellStatistic = DYNAMICS().collide(cell, *_parameters)) {
460 statistics.
increment(cellStatistic.rho, cellStatistic.uSqr);
462 }
else if (subdomain[iCell]) {
463 applyOther(block, statistics, iCell);
475template <
typename T,
typename DESCRIPTOR, concepts::CellOperator OPERATOR>
477 :
public BlockO<T,DESCRIPTOR,Platform::CPU_SIMD> {
479 std::vector<CellID> _cells;
485 std::type_index
id()
const override
492 return _cells.size();
498 _cells.emplace_back(iCell);
509 std::sort(_cells.begin(), _cells.end());
510 _cells.erase(std::unique(_cells.begin(), _cells.end()), _cells.end());
513 if (_cells.size() > 0) {
515 #ifdef PARALLEL_MODE_OMP
516 #pragma omp parallel for schedule(static) firstprivate(cell)
518 for (
CellID iCell : _cells) {
528template <
typename T,
typename DESCRIPTOR, concepts::CellOperator OPERATOR>
530 :
public BlockO<T,DESCRIPTOR,Platform::CPU_SIMD> {
532 std::vector<CellID> _cells;
540 std::type_index
id()
const override
547 return _cells.size();
553 _cells.emplace_back(iCell);
560 _parameters = &block.template getData<OperatorParameters<OPERATOR>>().parameters;
566 std::sort(_cells.begin(), _cells.end());
567 _cells.erase(std::unique(_cells.begin(), _cells.end()), _cells.end());
570 if (_cells.size() > 0) {
572 #ifdef PARALLEL_MODE_OMP
573 #pragma omp parallel for schedule(static) firstprivate(cell)
575 for (
CellID iCell : _cells) {
577 OPERATOR().apply(cell, *_parameters);
589template <
typename T,
typename DESCRIPTOR, concepts::BlockOperator OPERATOR>
591 :
public BlockO<T,DESCRIPTOR,Platform::CPU_SIMD> {
593 std::type_index
id()
const override
605 throw std::logic_error(
"BlockO::set not supported for OperatorScope::PerBlock");
#define OPERATOR(OP, rhs)
LatticeStatistics< T > & getStatistics()
Return a handle to the LatticeStatistics object.
std::size_t getNcells() const
Get number of cells.
Collision operation of concrete DYNAMICS on concrete block lattices of PLATFORM.
Implementation of BlockLattice on a concrete PLATFORM.
Block application of concrete OPERATOR called using SCOPE on PLATFORM.
Cell concept for concrete block lattices on CPU platforms.
void setCellId(CellID iCell)
Implementation of the Cell concept for vectorized collision operators.
auto getField() const
Return pack-valued copy of FIELD.
V & operator[](unsigned iPop)
Return reference to iPop population pack.
std::enable_if_t< rw_fields::template contains< FIELD >(), FieldD< V, DESCRIPTOR, FIELD > & > getFieldPointer()
Return reference to pack-valued interim storage vector of r/w field.
void setField(const FieldD< V, DESCRIPTOR, FIELD > &value)
Set compoents of FIELD from pack-valued vector.
std::enable_if_t<!rw_fields::template contains< FIELD >(), FieldD< V, DESCRIPTOR, FIELD > > getFieldPointer()
Return pack-valued copy of non r/w field.
void setField(FieldD< V, DESCRIPTOR, FIELD > &&value)
Set compoents of FIELD from pack-valued vector.
std::enable_if_t<!rw_fields::template contains< FIELD >(), V > getFieldComponent(unsigned iD)
Return pack-valued copy of non r/w field component.
std::enable_if_t< rw_fields::template contains< FIELD >(), V & > getFieldComponent(unsigned iD)
Return reference to pack-valued interim storage component of r/w field.
Cell(ConcreteBlockLattice< T, DESCRIPTOR, Platform::CPU_SIMD > &lattice, std::size_t iCell, Mask< T > &mask)
Load r/w fields into SIMD packs.
~Cell()
Store modified r/w fields back into lattice taking into account the mask.
Plain column for SIMD CPU targets.
Implementation of cpu::Dynamics for concrete DYNAMICS on SIMD blocks.
void computeJ(cpu::Cell< T, DESCRIPTOR, Platform::CPU_SIMD > &cell, T *j) override
CellStatistic< T > collide(cpu::Cell< T, DESCRIPTOR, Platform::CPU_SIMD > &cell) override
void inverseShiftRhoU(cpu::Cell< T, DESCRIPTOR, Platform::CPU_SIMD > &cell, T &rho, T *u) override
T computeRho(cpu::Cell< T, DESCRIPTOR, Platform::CPU_SIMD > &cell) override
void computeRhoU(cpu::Cell< T, DESCRIPTOR, Platform::CPU_SIMD > &cell, T &rho, T *u) override
void computeStress(cpu::Cell< T, DESCRIPTOR, Platform::CPU_SIMD > &cell, T &rho, T *u, T *pi) override
void defineAllMomenta(cpu::Cell< T, DESCRIPTOR, Platform::CPU_SIMD > &cell, T &rho, T *u, T *pi) override
void defineU(cpu::Cell< T, DESCRIPTOR, Platform::CPU_SIMD > &cell, T *u) override
void computeAllMomenta(cpu::Cell< T, DESCRIPTOR, Platform::CPU_SIMD > &cell, T &rho, T *u, T *pi) override
ConcreteDynamics(ParametersOfOperatorD< T, DESCRIPTOR, DYNAMICS > *parameters)
void computeEquilibrium(cpu::Cell< T, DESCRIPTOR, Platform::CPU_SIMD > &cell, T rho, T *u, T *fEq) override
T getOmegaOrFallback(T fallback) override
void defineRhoU(cpu::Cell< T, DESCRIPTOR, Platform::CPU_SIMD > &cell, T &rho, T *u) override
void computeU(cpu::Cell< T, DESCRIPTOR, Platform::CPU_SIMD > &cell, T *u) override
void defineRho(cpu::Cell< T, DESCRIPTOR, Platform::CPU_SIMD > &cell, T &rho) override
SIMD-specific pointer to a pack of rows of a D-dimensional field.
Pack< T > * getComponentPointer(unsigned iDim)
FieldPtr< T, D > & operator=(const GenericVector< U, D, IMPL > &rhs)
FieldPtr(ColumnVector< Column< T >, D > &columns, std::size_t index)
FieldPtr(FieldPtr< T, D > &&rhs)
const Pack< T > * getComponentPointer(unsigned iDim) const
Interface for post-processing steps – header file.
void maskstore(T *target, Mask< T > mask, Pack< T > value)
Top level namespace for all of OpenLB.
std::uint32_t CellID
Type for sequential block-local cell indices.
@ Simulation
Data available on host for e.g. functor evaluation.
Platform
OpenLB execution targets.
@ CPU_SIMD
Basic scalar CPU.
Vector< typename FIELD::template value_type< T >, DESCRIPTOR::template size< FIELD >() > FieldD
Vector storing a single field instance.
CollisionDispatchStrategy
Collision dispatch strategy.
@ Dominant
Apply dominant dynamics using mask and fallback to virtual dispatch for others.
typename ParametersD< T, DESCRIPTOR >::template include< typename OPERATOR::parameters > ParametersOfOperatorD
Deduce ParametersD of OPERATOR w.r.t. T and DESCRIPTOR.
@ PerBlock
Per-block application, i.e. OPERATOR::apply is passed a ConcreteBlockLattice.
@ PerCell
Per-cell application, i.e. OPERATOR::apply is passed a CELL concept implementation.
@ PerCellWithParameters
Per-cell application with parameters, i.e. OPERATOR::apply is passed a CELL concept implementation an...
Collision operation on concrete blocks of PLATFORM.
Base of block-wide operators such as post processors.
cpu::simd::Pack< T > uSqr
Return value of any collision.
Interface for per-cell dynamics.
Generic vector of values supporting basic arithmetic.
constexpr const T & operator[](unsigned iDim) const any_platform
void increment(T rho, T uSqr)
GenericVector< T, D, FieldPtr< T, D > > type
CPU specific field mirroring BlockDynamicsMap.
Virtual interface for dynamically-dispatched dynamics access on CPU targets.