24#ifndef GPU_CUDA_OPERATOR_HH
25#define GPU_CUDA_OPERATOR_HH
37struct CollisionSubdomainMask;
46template <
typename T,
typename DESCRIPTOR,
typename DYNAMICS>
56 return DYNAMICS().collide(cell, _parameters);
65 _parameters{parameters},
76 apply(lattice, iCell);
85 statistic = apply(lattice, iCell);
94template <
typename T,
typename DESCRIPTOR,
typename DYNAMICS>
101 _parameters{parameters}
106 DYNAMICS().collide(cell, _parameters);
112 statistic =
DYNAMICS().collide(cell, _parameters);
120template <
typename OPERATOR>
131 template <
typename T,
typename DESCRIPTOR>
147template <
typename OPERATOR>
149 template <
typename T,
typename DESCRIPTOR>
159template <
typename T,
typename DESCRIPTOR,
typename OPERATOR>
166 _parameters{parameters}
171 OPERATOR().apply(cell, _parameters);
178template <
typename COUPLER>
180 template <
typename CONTEXT>
182 CellID iCell) __device__ {
183 auto cells = lattices.exchange_values([&](
auto name) ->
auto {
184 return Cell{lattices.get(name), iCell};
186 COUPLER().apply(cells);
192template <
typename COUPLER,
typename COUPLEES>
195 typename COUPLER::parameters::template decompose_into<
200 template <
typename PARAMETERS>
202 _parameters{parameters}
205 template <
typename CONTEXT>
207 CellID iCell) __device__ {
208 auto cells = lattices.exchange_values([&](
auto name) ->
auto {
209 return Cell{lattices.get(name), iCell};
211 COUPLER().apply(cells, _parameters);
218template <
typename COUPLER,
typename COUPLEES>
223 typename COUPLER::parameters,
232 template <
typename PARAMETERS>
234 _parameters{parameters}
237 template <
typename CONTEXT>
239 CellID iParticle) __device__ {
240 using V =
typename CONTEXT::template value_t<names::Points>::value_t;
241 using DESCRIPTOR =
typename CONTEXT::template value_t<names::Points>::descriptor_t;
242 const auto originR = _parameters.template get<fields::BLOCK_LOWER>();
243 const auto deltaX = _parameters.template get<fields::converter::PHYS_DELTA_X>();
245 .template getField<fields::PHYS_R>());
248 auto cells = lattices.exchange_values([&](
auto name) ->
auto {
249 if constexpr (std::is_same_v<
typename decltype(name)::type,
names::Points>) {
252 const auto iCell = lattices.get(name).getCellId(latticeR);
253 return Cell{lattices.get(name), iCell};
256 COUPLER().apply(cells, _parameters);
278template <
typename T,
typename DESCRIPTOR,
typename... DYNAMICS>
282 bool* subdomain = block.template getData<CollisionSubdomainMask>().deviceData();
284 if (block.statisticsEnabled()) {
289 block.template getData<OperatorParameters<DYNAMICS>>().parameters,
298 block.template getData<OperatorParameters<DYNAMICS>>().parameters,
311template <
typename CONTEXT,
typename... OPERATORS>
312void call_operators(CONTEXT lattice,
bool* subdomain, OPERATORS... ops) __global__ {
313 const CellID iCell = blockIdx.x * blockDim.x + threadIdx.x;
314 if (!(iCell < lattice.getNcells()) || !subdomain[iCell]) {
317 (ops(lattice, iCell) || ... );
324template <
typename CONTEXT,
typename... OPERATORS>
326 const CellID iCell = blockIdx.x * blockDim.x + threadIdx.x;
327 if (!(iCell < lattice.getNcells()) || !subdomain[iCell]) {
330 typename CONTEXT::value_t** statistic = lattice.template getField<descriptors::STATISTIC>();
331 int* statisticGenerated = lattice.template getField<descriptors::STATISTIC_GENERATED>()[0];
333 if ((ops(lattice, iCell, cellStatistic) || ... )) {
335 statisticGenerated[iCell] = 1;
336 statistic[0][iCell] = cellStatistic.rho;
337 statistic[1][iCell] = cellStatistic.uSqr;
339 statisticGenerated[iCell] = 0;
340 statistic[0][iCell] = 0;
341 statistic[1][iCell] = 0;
347template <
typename CONTEXT,
typename... OPERATORS>
349 const CellID* indices, std::size_t nIndices,
350 OPERATORS... ops) __global__ {
351 const std::size_t iIndex = blockIdx.x * blockDim.x + threadIdx.x;
352 if (!(iIndex < nIndices)) {
355 (ops(lattice, indices[iIndex]) || ... );
362template <
typename CONTEXT,
typename... OPERATORS>
364 const CellID* indices, std::size_t nIndices,
365 OPERATORS... ops) __global__ {
366 const std::size_t iIndex = blockIdx.x * blockDim.x + threadIdx.x;
367 if (!(iIndex < nIndices)) {
370 typename CONTEXT::value_t** statistic = lattice.template getField<descriptors::STATISTIC>();
371 int* statisticGenerated = lattice.template getField<descriptors::STATISTIC_GENERATED>()[0];
373 if ((ops(lattice, indices[iIndex], cellStatistic) || ... )) {
375 statisticGenerated[indices[iIndex]] = 1;
376 statistic[0][indices[iIndex]] = cellStatistic.rho;
377 statistic[1][indices[iIndex]] = cellStatistic.uSqr;
379 statisticGenerated[indices[iIndex]] = 0;
380 statistic[0][indices[iIndex]] = 0;
381 statistic[1][indices[iIndex]] = 0;
387template <
typename CONTEXTS,
typename... OPERATORS>
389 const CellID iCell = blockIdx.x * blockDim.x + threadIdx.x;
390 const auto nCells = lattices.template get<0>().getNcells();
391 if (!(iCell < nCells) || !subdomain[iCell]) {
394 (ops(lattices, iCell) || ... );
398template <
typename CONTEXTS,
typename... OPERATORS>
400 std::size_t nParticles,
401 OPERATORS... ops) __global__ {
402 const CellID iParticle = blockIdx.x * blockDim.x + threadIdx.x;
403 if (!(iParticle < nParticles)) {
406 (ops(lattices, iParticle) || ... );
411template <
typename T,
typename DESCRIPTOR,
typename DYNAMICS,
typename PARAMETERS=
typename DYNAMICS::ParametersD>
422template <
typename CONTEXT,
typename... ARGS>
424 const auto block_size = 32;
425 const auto block_count = (lattice.getNcells() + block_size - 1) / block_size;
427 lattice, subdomain, std::forward<decltype(args)>(args)...);
432template <
typename CONTEXT,
typename... ARGS>
434 const auto block_size = 32;
435 const auto block_count = (lattice.getNcells() + block_size - 1) / block_size;
437 lattice, subdomain, std::forward<decltype(args)>(args)...);
445template <
typename CONTEXT,
typename... ARGS>
447 const auto block_size = 32;
448 const auto block_count = (lattice.getNcells() + block_size - 1) / block_size;
450 lattice, subdomain, std::forward<decltype(args)>(args)...);
455template <
typename CONTEXT,
typename... ARGS>
457 const auto block_size = 32;
458 const auto block_count = (lattice.getNcells() + block_size - 1) / block_size;
460 lattice, subdomain, std::forward<decltype(args)>(args)...);
468template <
typename CONTEXT,
typename... ARGS>
472 const auto block_size = 32;
473 const auto block_count = (cells.
size() + block_size - 1) / block_size;
477 std::forward<
decltype(args)>(args)...);
482template <
typename CONTEXT,
typename... ARGS>
487 const auto block_size = 32;
488 const auto block_count = (cells.
size() + block_size - 1) / block_size;
492 std::forward<
decltype(args)>(args)...);
497template <
typename CONTEXT,
typename... ARGS>
502 const auto block_size = 32;
503 const auto block_count = (cells.
size() + block_size - 1) / block_size;
507 std::forward<
decltype(args)>(args)...);
512template <
typename CONTEXT,
typename... ARGS>
514 const auto nCells = lattices.template get<0>().getNcells();
515 const auto block_size = 32;
516 const auto block_count = (nCells + block_size - 1) / block_size;
518 lattices, subdomain, std::forward<decltype(args)>(args)...);
523template <
typename CONTEXT,
typename... ARGS>
526 const auto block_size = 32;
527 const auto block_count = (nParticles + block_size - 1) / block_size;
529 lattices, nParticles, std::forward<decltype(args)>(args)...);
537template <
typename T,
typename DESCRIPTOR,
typename DYNAMICS>
539 _dynamics(new DYNAMICS()),
540 _parameters(nullptr),
544 _stream(cudaStreamDefault)
547template <
typename T,
typename DESCRIPTOR,
typename DYNAMICS>
552 using namespace gpu::cuda;
553 DeviceContext<T,DESCRIPTOR> lattice(block);
555 call_operators_with_statistics(
557 subdomain.deviceData(),
558 MaskedCollision<T,DESCRIPTOR,DYNAMICS>{_parameters->parameters, _mask->deviceData()},
559 DynamicDispatchCollision{});
563 subdomain.deviceData(),
564 MaskedCollision<T,DESCRIPTOR,DYNAMICS>{_parameters->parameters, _mask->deviceData()},
565 DynamicDispatchCollision{});
569template <
typename T,
typename DESCRIPTOR,
typename DYNAMICS>
570void ConcreteBlockCollisionO<T,DESCRIPTOR,Platform::GPU_CUDA,DYNAMICS>::applyIndividual(
571 ConcreteBlockLattice<T,DESCRIPTOR,Platform::GPU_CUDA>& block,
572 ConcreteBlockMask<T,Platform::GPU_CUDA>& subdomain)
574 using namespace gpu::cuda;
575 DeviceContext<T,DESCRIPTOR> lattice(block);
577 if (_mask->weight() > 0.5*subdomain.weight()) {
578 if (block.statisticsEnabled()) {
582 subdomain.deviceData(),
583 MaskedCollision<T,DESCRIPTOR,DYNAMICS>{_parameters->parameters, _mask->deviceData()});
588 subdomain.deviceData(),
589 MaskedCollision<T,DESCRIPTOR,DYNAMICS>{_parameters->parameters, _mask->deviceData()});
597 for (
CellID iCell=0; iCell < block.getNcells(); ++iCell) {
598 if (_mask->operator[](iCell)) {
599 _cells.push_back(iCell);
606 if (block.statisticsEnabled()) {
611 ListedCollision<T,DESCRIPTOR,DYNAMICS>{_parameters->parameters});
617 ListedCollision<T,DESCRIPTOR,DYNAMICS>{_parameters->parameters});
622template <
typename T,
typename DESCRIPTOR,
typename DYNAMICS>
627 _parameters = &block.template getData<OperatorParameters<DYNAMICS>>();
628 _mask = &block.template getData<DynamicsMask<DYNAMICS>>();
634 _deviceDynamics.get(),
635 _parameters->deviceData());
639 _dynamicsOfCells = block.template getField<gpu::cuda::DYNAMICS<T,DESCRIPTOR>>()[0].data();
643template <
typename T,
typename DESCRIPTOR, concepts::CellOperator OPERATOR>
647 _stream{cudaStreamDefault}
650template <
typename T,
typename DESCRIPTOR, concepts::CellOperator OPERATOR>
654 if (_cells.size() > 0) {
656 _cells.deduplicate();
668template <
typename T,
typename DESCRIPTOR, concepts::CellOperator OPERATOR>
672 _stream{cudaStreamDefault}
675template <
typename T,
typename DESCRIPTOR, concepts::CellOperator OPERATOR>
679 if (_cells.size() > 0) {
681 _cells.deduplicate();
685 using namespace gpu::cuda;
686 DeviceBlockLattice<T,DESCRIPTOR> lattice(block);
687 async_call_list_operators(_stream.get(),
690 ListedPostProcessorWithParameters<T,DESCRIPTOR,OPERATOR>{_parameters->parameters});
695template <
typename COUPLER,
typename COUPLEES>
700 _mask = std::make_unique<ConcreteBlockMask<typename COUPLEES::values_t::template get<0>::value_t,
702 _lattices.template get<0>()->template getData<CollisionSubdomainMask>()
705 _mask->set(iCell, state);
708template <
typename COUPLER,
typename COUPLEES>
711 auto deviceLattice = _lattices.exchange_values([&](
auto name) ->
auto {
717 deviceLattice, _mask->deviceData(),
720 auto& mask = _lattices.template get<0>()->template getData<CollisionSubdomainMask>();
722 deviceLattice, mask.deviceData(),
727template <
typename COUPLER,
typename COUPLEES>
732 _mask = std::make_unique<ConcreteBlockMask<typename COUPLEES::values_t::template get<0>::value_t,
734 _lattices.template get<0>()->template getData<CollisionSubdomainMask>()
737 _mask->set(iCell, state);
740template <
typename COUPLER,
typename COUPLEES>
743 auto deviceLattice = _lattices.exchange_values([&](
auto name) ->
auto {
749 deviceLattice, _mask->deviceData(),
752 auto& mask = _lattices.template get<0>()->template getData<CollisionSubdomainMask>();
754 deviceLattice, mask.deviceData(),
759template <
typename COUPLER,
typename COUPLEES>
763 throw std::bad_function_call();
766template <
typename COUPLER,
typename COUPLEES>
774 auto deviceLattice = _lattices.exchange_values([&](
auto name) ->
auto {
775 if constexpr (std::is_same_v<
typename decltype(name)::type,
names::Points>) {
#define OPERATOR(OP, rhs)
bool statisticsEnabled() const
Collision operation of concrete DYNAMICS on concrete block lattices of PLATFORM.
Coupling of COUPLEES using concrete OPERATOR with SCOPE on PLATFORM lattices.
Implementation of BlockLattice on a concrete PLATFORM.
Block application of concrete OPERATOR called using SCOPE on PLATFORM.
Particle coupling of COUPLEES using concrete OPERATOR with SCOPE on PLATFORM lattices.
Device-side implementation of the Cell concept for post processors.
Plain column for CUDA GPU targets.
const T * deviceData() const
std::size_t size() const override
Implementation of gpu::cuda::Dynamics for concrete DYNAMICS.
Device-side implementation of the data-only Cell concept for collision steps.
Device-side view of a block lattice.
Structure for passing pointers to on-device data into CUDA kernels.
List-based application of DYNAMICS::collide for use in kernel::call_list_operators.
bool operator()(DeviceContext< T, DESCRIPTOR > &lattice, CellID iCell) __device__
bool operator()(DeviceContext< T, DESCRIPTOR > &lattice, CellID iCell, CellStatistic< T > &statistic) __device__
ListedCollision(ParametersOfOperatorD< T, DESCRIPTOR, DYNAMICS > ¶meters) __host__
List-based application of OPERATOR::apply with parameters.
bool operator()(DeviceBlockLattice< T, DESCRIPTOR > &lattice, CellID iCell) __device__
ListedPostProcessorWithParameters(ParametersOfOperatorD< T, DESCRIPTOR, OPERATOR > ¶meters) __host__
Masked application of DYNAMICS::collide for use in kernel::call_operators.
bool operator()(DeviceContext< T, DESCRIPTOR > &lattice, CellID iCell) __device__
Chainable call operator for use in kernel::call_operators.
MaskedCollision(ParametersOfOperatorD< T, DESCRIPTOR, DYNAMICS > ¶meters, bool *mask) any_platform
Constructor (commonly called on the host side)
bool operator()(DeviceContext< T, DESCRIPTOR > &lattice, CellID iCell, CellStatistic< T > &statistic) __device__
Chainable call operator with statistics storage.
Masked application of OPERATOR::apply.
MaskedPostProcessor(bool *mask) any_platform
bool operator()(DeviceBlockLattice< T, DESCRIPTOR > &lattice, CellID iCell) __device__
Unrestricted application of COUPLING::apply with parameters.
bool operator()(CONTEXT &lattices, CellID iParticle) __device__
ParticleCouplingWithParameters(PARAMETERS ¶meters) any_platform
Unrestricted application of COUPLING::apply with parameters.
bool operator()(CONTEXT &lattices, CellID iCell) __device__
UnmaskedCouplingWithParameters(PARAMETERS ¶meters) any_platform
void check()
Check errors.
T * malloc(std::size_t size)
Allocate data on device.
void call_coupling_operators(CONTEXTS lattices, bool *subdomain, OPERATORS... ops) __global__
CUDA kernel for applying UnmaskedCoupling(WithParameters)
void call_particle_coupling_operators(CONTEXTS lattices, std::size_t nParticles, OPERATORS... ops) __global__
CUDA kernel for applying UnmaskedCoupling(WithParameters)
void call_list_operators(CONTEXT lattice, const CellID *indices, std::size_t nIndices, OPERATORS... ops) __global__
CUDA kernel for applying generic OPERATORS with OperatorScope::PerCell or ListedCollision.
void construct_dynamics(void *target, PARAMETERS *parameters) __global__
CUDA kernel for constructing on-device ConcreteDynamics.
void call_operators(CONTEXT lattice, bool *subdomain, OPERATORS... ops) __global__
CUDA kernel for applying purely local collision steps.
void call_list_operators_with_statistics(CONTEXT lattice, const CellID *indices, std::size_t nIndices, OPERATORS... ops) __global__
CUDA kernel for applying ListedCollision.
void call_operators_with_statistics(CONTEXT lattice, bool *subdomain, OPERATORS... ops) __global__
CUDA kernel for applying purely local collision steps while tracking statistics.
void async_call_list_operators(cudaStream_t stream, CONTEXT &lattice, const gpu::cuda::Column< CellID > &cells, ARGS &&... args)
Apply operators to listed cell indices (async version)
void async_call_operators(cudaStream_t stream, CONTEXT &lattice, bool *subdomain, ARGS &&... args)
Apply masked collision operators to lattice (async)
void call_operators(CONTEXT &lattice, bool *subdomain, ARGS &&... args)
Apply masked collision operators to lattice.
void async_call_list_operators_with_statistics(cudaStream_t stream, CONTEXT &lattice, const gpu::cuda::Column< CellID > &cells, ARGS &&... args)
Apply ListedCollision with statistics (async version)
void async_call_operators_with_statistics(cudaStream_t stream, CONTEXT &lattice, bool *subdomain, ARGS &&... args)
Apply masked collision operators to lattice while tracking statistics (async)
void call_list_operators(CONTEXT &lattice, const gpu::cuda::Column< CellID > &cells, ARGS &&... args)
Apply operators to listed cell indices.
void call_particle_coupling_operators(CONTEXT &lattices, ARGS &&... args)
Apply coupling on particles and lattices.
void call_operators_with_statistics(CONTEXT &lattice, bool *subdomain, ARGS &&... args)
Apply masked collision operators to lattice while tracking statistics.
std::function< void(ConcreteBlockLattice< T, DESCRIPTOR, Platform::GPU_CUDA > &)> getFusedCollisionO()
Helper for constructing fused collision operators.
void call_coupling_operators(CONTEXT &lattices, bool *subdomain, ARGS &&... args)
Apply coupling on subdomain.
ADf< T, DIM > floor(const ADf< T, DIM > &a)
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.
@ GPU_CUDA
Vector CPU (AVX2 / AVX-512 collision)
typename ParametersD< T, DESCRIPTOR >::template include< typename OPERATOR::parameters > ParametersOfOperatorD
Deduce ParametersD of OPERATOR w.r.t. T and DESCRIPTOR.
Base of block-wide coupling operators executed by SuperLatticeCoupling.
Return value of any collision.
Describe mask of DYNAMICS in Data.
On-device field mirroring BlockDynamicsMap.
Last node in a MaskedDynamics chain in kernel::call_operators.
List-based application of OPERATOR::apply.
bool operator()(DeviceBlockLattice< T, DESCRIPTOR > &lattice, CellID iCell) __device__
Unrestricted application of COUPLING::apply.
bool operator()(CONTEXT &lattices, CellID iCell) __device__