22#include <blockforest/communication/UniformBufferedScheme.h>
23#include <field/AddToStorage.h>
24#include <field/FlagField.h>
25#include <field/FlagUID.h>
26#include <field/GhostLayerField.h>
27#include <field/communication/PackInfo.h>
28#include <field/iterators/IteratorMacros.h>
29#include <field/vtk/FlagFieldCellFilter.h>
30#include <field/vtk/VTKWriter.h>
31#include <stencil/D3Q27.h>
32#include <waLBerlaDefinitions.h>
33#if defined(__CUDACC__) and defined(WALBERLA_BUILD_WITH_CUDA)
34#include <gpu/AddGPUFieldToStorage.h>
35#include <gpu/communication/MemcpyPackInfo.h>
36#include <gpu/communication/UniformGPUScheme.h>
39#include "../BoundaryHandling.hpp"
40#include "../BoundaryPackInfo.hpp"
41#include "../utils/boundary.hpp"
42#include "../utils/types_conversion.hpp"
44#if defined(__CUDACC__) and defined(WALBERLA_BUILD_WITH_CUDA)
75#if not defined(WALBERLA_BUILD_WITH_CUDA)
77 "waLBerla was compiled without CUDA support");
79 using ContinuityKernel =
81 using DiffusiveFluxKernelUnthermalized =
82 typename detail::KernelTrait<FloatType,
84 using DiffusiveFluxKernelThermalized =
typename detail::KernelTrait<
85 FloatType,
Architecture>::DiffusiveFluxKernelThermalized;
86 using AdvectiveFluxKernel =
87 typename detail::KernelTrait<FloatType,
89 using FrictionCouplingKernel =
90 typename detail::KernelTrait<FloatType,
92 using DiffusiveFluxKernelElectrostaticUnthermalized =
93 typename detail::KernelTrait<
94 FloatType,
Architecture>::DiffusiveFluxKernelElectrostatic;
95 using DiffusiveFluxKernelElectrostaticThermalized =
96 typename detail::KernelTrait<
97 FloatType,
Architecture>::DiffusiveFluxKernelElectrostaticThermalized;
99 using DiffusiveFluxKernel = std::variant<DiffusiveFluxKernelUnthermalized,
100 DiffusiveFluxKernelThermalized>;
101 using DiffusiveFluxKernelElectrostatic =
102 std::variant<DiffusiveFluxKernelElectrostaticUnthermalized,
103 DiffusiveFluxKernelElectrostaticThermalized>;
122 template <
typename FT, lbmpy::Arch AT = lbmpy::Arch::CPU>
struct FieldTrait {
126 template <
class Field>
127 using PackInfo = field::communication::PackInfo<Field>;
128 template <
class Stencil>
130 blockforest::communication::UniformBufferedScheme<Stencil>;
131 template <
class Stencil>
133 blockforest::communication::UniformBufferedScheme<Stencil>;
135 using FlagField = walberla::FlagField<walberla::uint8_t>;
136#if defined(__CUDACC__) and defined(WALBERLA_BUILD_WITH_CUDA)
140 template <
class Field>
141 using MemcpyPackInfo = gpu::communication::MemcpyPackInfo<Field>;
144 template <
typename Stencil>
145 class UniformGPUScheme
146 :
public gpu::communication::UniformGPUScheme<Stencil> {
148 explicit UniformGPUScheme(
auto const &
bf)
149 : gpu::communication::UniformGPUScheme<Stencil>(
156 template <
class Stencil>
158 template <
class Stencil>
160 blockforest::communication::UniformBufferedScheme<Stencil>;
162 using GPUField = gpu::GPUField<FloatType>;
192 return std::is_same_v<FloatType, double>;
196 FloatType m_diffusion;
201 bool m_friction_coupling;
225 std::unique_ptr<DiffusiveFluxKernelElectrostatic>
244 template <
typename Field>
248#if defined(__CUDACC__) and defined(WALBERLA_BUILD_WITH_CUDA)
250 auto field_id = gpu::addGPUFieldToStorage<GPUField>(
252 if constexpr (std::is_same_v<Field, _DensityField>) {
257 }
else if constexpr (std::is_same_v<Field, _FluxField>) {
261 std::array<FloatType, FluxCount>{});
267 return field::addToStorage<Field>(
blocks,
tag, FloatType{value},
289 typename stencil::D3Q27>;
292 typename stencil::D3Q27>;
297 template <
class Field>
326 set_diffusion_kernels();
342 std::make_shared<BoundaryFullCommunicator>(
blocks);
367 return m_friction_coupling;
373 return static_cast<bool>(
385 return {
static_cast<uint64_t>(kernel->getTime_step())};
390 auto visitor = [m_diffusion = m_diffusion](
auto &kernel) {
391 kernel.setD(m_diffusion);
399 std::visit([m_kT = m_kT](
auto &kernel) { kernel.setKt(m_kT); },
406 [m_valency = m_valency](
auto &kernel) { kernel.setZ(m_valency); },
420 std::get_if<DiffusiveFluxKernelElectrostaticThermalized>(
424 throw std::runtime_error(
"This EK instance is unthermalized");
427 static_cast<uint32_t>(std::numeric_limits<uint_t>::max()));
428 kernel->setTime_step(
static_cast<uint32_t>(counter));
433 m_ext_efield = field;
436 [
this](
auto &kernel) {
447 (*m_full_communication)();
462 void set_diffusion_kernels() {
463 auto kernel = DiffusiveFluxKernelUnthermalized(
465 m_diffusive_flux = std::make_unique<DiffusiveFluxKernel>(std::move(kernel));
474 std::make_unique<DiffusiveFluxKernelElectrostatic>(
482 auto kernel = DiffusiveFluxKernelThermalized(
500 m_diffusive_flux = std::make_unique<DiffusiveFluxKernel>(std::move(kernel));
502 std::make_unique<DiffusiveFluxKernelElectrostatic>(
506 void kernel_boundary_density() {
508 (*m_boundary_density)(&
block);
512 void kernel_boundary_flux() {
514 (*m_boundary_flux)(&
block);
518 void kernel_continuity() {
520 (*m_continuity).run(&
block);
524 void kernel_diffusion() {
526 std::visit([&
block](
auto &kernel) { kernel.run(&
block); },
532 kernel->setTime_step(kernel->getTime_step() + 1u);
535 std::get_if<DiffusiveFluxKernelElectrostaticThermalized>(
542 void kernel_advection(std::size_t
const velocity_id) {
550 void kernel_friction_coupling(std::size_t
const force_id,
551 double const lb_density) {
552 auto kernel = FrictionCouplingKernel(
560 void kernel_diffusion_electrostatic(std::size_t
const potential_id) {
562 std::visit([phiID](
auto &kernel) { kernel.setPhiID(phiID); },
566 std::visit([&
block](
auto &kernel) { kernel.run(&
block); },
571 std::get_if<DiffusiveFluxKernelElectrostaticThermalized>(
578 kernel->setTime_step(kernel->getTime_step() + 1u);
582 void kernel_migration() {}
584 void update_boundary_fields() {
601 std::size_t
force_id,
double lb_density)
override {
604 update_boundary_fields();
611 throw std::runtime_error(
"Walberla EK: electrostatic potential enabled "
612 "but no field accessible. potential id is " +
621 kernel_boundary_flux();
624 if (
force_id == walberla::BlockDataID{}) {
625 throw std::runtime_error(
"Walberla EK: friction coupling enabled but "
626 "no force field accessible. force_id is " +
628 ". Hint: LB may be inactive.");
630 kernel_friction_coupling(
force_id, lb_density);
635 throw std::runtime_error(
"Walberla EK: advection enabled but no "
636 "velocity field accessible. velocity_id is " +
638 ". Hint: LB may be inactive.");
641 kernel_boundary_flux();
646 kernel_boundary_density();
654 static_assert(std::is_same_v<std::size_t, walberla::uint_t>);
690 std::vector<double>
out;
696 out = std::vector<double>(
ci->numCells());
729 std::vector<double>
const &
density)
override {
740 std::vector<FloatType>
values(
bci->numCells());
755 [[
nodiscard]] std::optional<Utils::Vector3d>
775 std::vector<double>
out;
781 out = std::vector<double>(3u *
ci->numCells());
800 for (
uint_t f = 0
u; f < 3u; ++f) {
804 for (
uint_t f = 0
u; f < 3u; ++f) {
840 [[
nodiscard]] std::optional<Utils::Vector3d>
885 std::vector<std::optional<double>>
const &
density)
override {
898 auto const &
opt = *
it;
912 [[
nodiscard]] std::vector<std::optional<double>>
916 std::vector<std::optional<double>>
out;
922 auto const n_values =
ci->numCells();
923 out.reserve(n_values);
932 out.emplace_back(std::nullopt);
944 std::vector<std::optional<Utils::Vector3d>>
const &
flux)
override {
958 auto const &
opt = *
it;
972 [[
nodiscard]] std::vector<std::optional<Utils::Vector3d>>
976 std::vector<std::optional<Utils::Vector3d>>
out;
982 auto const n_values =
ci->numCells();
983 out.reserve(n_values);
992 out.emplace_back(std::nullopt);
1005 std::vector<bool>
out;
1011 auto const n_values =
ci->numCells();
1012 out.reserve(n_values);
1043 return std::nullopt;
1053 return std::nullopt;
1063 return std::nullopt;
1071 const std::vector<double> &
data_flat)
override {
1081 const std::vector<double> &
data_flat)
override {
1113 template <
typename VecType, u
int_t F_SIZE_ARG,
typename OutputType>
1114 class VTKWriter :
public vtk::BlockCellDataWriter<OutputType, F_SIZE_ARG> {
1118 : vtk::BlockCellDataWriter<OutputType,
F_SIZE_ARG>(id),
1126 return (
static_cast<std::size_t
>(x) *
m_dims[2] *
m_dims[1] +
1127 static_cast<std::size_t
>(y) *
m_dims[2] +
1128 static_cast<std::size_t
>(z)) *
1142 template <
typename OutputType =
float>
1144 :
public VTKWriter<std::vector<FloatType>, 1u, OutputType> {
1148 using Base::evaluate;
1159 template <
typename OutputType =
float>
1161 :
public VTKWriter<std::vector<FloatType>, 3u, OutputType> {
1165 using Base::evaluate;
1176 template <
typename OutputType =
float>
1179 using Base = vtk::BlockCellDataWriter<OutputType, 1u>;
1180 using Base::evaluate;
1183 : vtk::BlockCellDataWriter<OutputType, 1u>(id),
1229 Cell const global(offset[0] + x, offset[1] + y, offset[2] + z);
1230 auto const density =
1231 m_boundary_density->get_node_value_at_boundary(global);
1232 Cell const local(x, y, z);
1233 ek::accessor::Scalar::set(density_field, density, local);
1260 std::size_t index = 0
u;
1261 for (
auto x =
bci.xMin(); x <=
bci.xMax(); ++x) {
1262 for (
auto y =
bci.yMin(); y <=
bci.yMax(); ++y) {
1263 for (
auto z =
bci.zMin(); z <=
bci.zMax(); ++z) {
Vector implementation and trait types for boost qvm interoperability.
Interface of a lattice-based electrokinetic model.
std::map< std::string, std::shared_ptr< VTKHandle > > m_vtk_auto
VTK writers that are executed automatically.
std::unordered_map< std::string, double > units_map
Class that runs and controls the BlockForest in waLBerla.
auto const & get_grid_dimensions() const
walberla::blockforest::StructuredBlockForest Lattice_T
std::pair< Utils::Vector3i, Utils::Vector3i > get_local_grid_range(bool with_halo=false) const
Utils::Vector3i get_block_corner(IBlock const &block, bool lower) const
Boundary class optimized for sparse data.
vtk::BlockCellDataWriter< OutputType, 1u > Base
FlagUID const m_boundary_flag
FlagField const * m_flag_field
OutputType evaluate(cell_idx_t const x, cell_idx_t const y, cell_idx_t const z, cell_idx_t const) override
BoundaryVTKWriter(ConstBlockDataID const &flag_field_id, std::string const &id, FlagUID const &boundary_flag)
ConstBlockDataID const m_flag_field_id
FlagField::flag_t m_boundary_flag_value
void configure() override
OutputType evaluate(cell_idx_t const x, cell_idx_t const y, cell_idx_t const z, cell_idx_t const) override
OutputType evaluate(cell_idx_t const x, cell_idx_t const y, cell_idx_t const z, cell_idx_t const f) override
void set_dims(Vector3< uint_t > dims)
std::size_t get_first_index(cell_idx_t const x, cell_idx_t const y, cell_idx_t const z)
VTKWriter(ConstBlockDataID const &block_id, std::string const &id, FloatType unit_conversion)
void set_content(VecType content)
void configure() override
Class that runs and controls the EK on waLBerla.
~EKinWalberlaImpl() override=default
void set_slice_flux_boundary(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner, std::vector< std::optional< Utils::Vector3d > > const &flux) override
void set_kT(double kT) override
std::optional< double > get_node_density_at_boundary(Utils::Vector3i const &node, bool consider_ghosts=false) const override
double get_kT() const noexcept override
std::unique_ptr< DiffusiveFluxKernelElectrostatic > m_diffusive_flux_electrostatic
walberla::FlagField< walberla::uint8_t > FlagField
void set_friction_coupling(bool friction_coupling) override
void set_rng_state(uint64_t counter) override
void integrate(std::size_t potential_id, std::size_t velocity_id, std::size_t force_id, double lb_density) override
bool set_node_density_boundary(Utils::Vector3i const &node, double density) override
void set_slice_density(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner, std::vector< double > const &density) override
BlockDataID m_density_field_id
std::shared_ptr< FullCommunicator > m_full_communication
std::bitset< GhostComm::SIZE > m_pending_ghost_comm
std::vector< double > get_slice_density(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner) const override
void update_density_boundary_from_shape(const std::vector< int > &raster_flat, const std::vector< double > &data_flat) override
void update_flux_boundary_from_shape(const std::vector< int > &raster_flat, const std::vector< double > &data_flat) override
std::vector< bool > get_slice_is_boundary(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner) const override
void set_ext_efield(Utils::Vector3d const &field) override
bool set_node_density(Utils::Vector3i const &node, double density) override
double get_diffusion() const noexcept override
void set_valency(double valency) override
bool is_thermalized() const noexcept override
auto add_to_storage(std::string const tag, FloatType value)
Convenience function to add a field with a custom allocator.
std::optional< double > get_node_density(Utils::Vector3i const &node, bool consider_ghosts=false) const override
std::size_t get_density_id() const noexcept override
unsigned int get_seed() const noexcept override
BlockDataID m_flag_field_flux_id
std::unique_ptr< ContinuityKernel > m_continuity
double get_valency() const noexcept override
typename FieldTrait< FloatType, Architecture >::FluxField FluxField
void clear_flux_boundaries() override
std::shared_ptr< BoundaryModelFlux > m_boundary_flux
void set_slice_density_boundary(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner, std::vector< std::optional< double > > const &density) override
void reset_flux_boundary_handling(std::shared_ptr< BlockStorage > const &blocks)
bool get_advection() const noexcept override
std::optional< Utils::Vector3d > get_node_flux_vector(Utils::Vector3i const &node, bool consider_ghosts=false) const override
typename FieldTrait< FloatType, Architecture >::template BoundaryCommScheme< typename stencil::D3Q27 > BoundaryFullCommunicator
typename FieldTrait< FloatType, Architecture >::template RegularCommScheme< typename stencil::D3Q27 > FullCommunicator
void reallocate_density_boundary_field()
std::optional< uint64_t > get_rng_state() const override
void set_advection(bool advection) override
BlockDataID m_flag_field_density_id
bool remove_node_from_density_boundary(Utils::Vector3i const &node) override
typename FieldTrait< FloatType, Architecture >::template PackInfo< Field > PackInfo
bool get_friction_coupling() const noexcept override
Utils::Vector3d get_ext_efield() const noexcept override
stencil::D3Q27 Stencil
Stencil for collision and streaming operations.
LatticeWalberla const & get_lattice() const noexcept override
bool remove_node_from_flux_boundary(Utils::Vector3i const &node) override
bool is_double_precision() const noexcept override
void integrate_vtk_writers() override
typename FieldTrait< FloatType, Architecture >::DensityField DensityField
FloatType FloatType_c(T t)
bool is_gpu() const noexcept override
void clear_density_boundaries() override
std::optional< bool > get_node_is_flux_boundary(Utils::Vector3i const &node, bool consider_ghosts) const override
void ghost_communication() override
LatticeWalberla::Lattice_T BlockStorage
Lattice model (e.g.
void ghost_communication_boundary()
void reset_density_boundary_handling(std::shared_ptr< BlockStorage > const &blocks)
std::vector< std::optional< Utils::Vector3d > > get_slice_flux_at_boundary(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner) const override
ResourceObserver m_mpi_cart_comm_observer
std::vector< std::optional< double > > get_slice_density_at_boundary(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner) const override
BlockDataID m_flux_field_id
void register_vtk_field_writers(walberla::vtk::VTKOutput &vtk_obj, LatticeModel::units_map const &units, int flag_observables) override
std::optional< Utils::Vector3d > get_node_flux_at_boundary(Utils::Vector3i const &node, bool consider_ghosts=false) const override
std::vector< double > get_slice_flux_vector(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner) const override
typename FieldTrait< FloatType >::DensityField _DensityField
std::shared_ptr< BoundaryFullCommunicator > m_boundary_communicator
std::optional< bool > get_node_is_density_boundary(Utils::Vector3i const &node, bool consider_ghosts) const override
std::unique_ptr< DiffusiveFluxKernel > m_diffusive_flux
void set_diffusion(double diffusion) override
std::size_t stencil_size() const noexcept override
FlagUID const Boundary_flag
Flag for boundary cells.
bool set_node_flux_boundary(Utils::Vector3i const &node, Utils::Vector3d const &flux) override
void reallocate_flux_boundary_field()
typename FieldTrait< FloatType >::FluxField _FluxField
std::optional< bool > get_node_is_boundary(Utils::Vector3i const &node, bool consider_ghosts=false) const override
std::unique_ptr< BoundaryModelDensity > m_boundary_density
EKinWalberlaImpl(std::shared_ptr< LatticeWalberla > lattice, double diffusion, double kT, double valency, Utils::Vector3d const &ext_efield, double density, bool advection, bool friction_coupling, bool thermalized, unsigned int seed)
std::shared_ptr< LatticeWalberla > m_lattice
Block forest.
FlagUID const Domain_flag
Flag for domain cells, i.e.
void register_vtk_field_filters(walberla::vtk::VTKOutput &vtk_obj) override
void setup_boundary_handle(std::shared_ptr< LatticeWalberla > lattice, std::shared_ptr< Boundary_T > boundary)
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
static double * block(double *p, std::size_t index, std::size_t size)
auto get_vector(GhostLayerField< double, uint_t{13u}> const *flux_field, Cell const &cell)
void initialize(GhostLayerField< double, uint_t{13u}> *flux_field, std::array< double, 13 > const &values)
void initialize(GhostLayerField< double, 1u > *scalar_field, double const &value)
void set(GhostLayerField< double, 1u > *scalar_field, double const &value, Cell const &cell)
auto get(GhostLayerField< double, 1u > const *scalar_field, Cell const &cell)
static FUNC_PREFIX double *RESTRICT const double *RESTRICT const int64_t const int64_t const int64_t const int64_t const int64_t const int64_t const int64_t const int64_t const int64_t const int64_t const uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t seed
\file PackInfoPdfDoublePrecision.cpp \author pystencils
auto to_vector3d(Vector3< T > const &v) noexcept
std::vector< double > fill_3D_scalar_array(std::vector< double > const &vec_flat, Utils::Vector3i const &grid_size)
void set_boundary_from_grid(BoundaryModel &boundary, LatticeWalberla const &lattice, std::vector< int > const &raster_flat, std::vector< DataType > const &data_flat)
void copy_block_buffer(CellInterval const &bci, CellInterval const &ci, Utils::Vector3i const &block_offset, Utils::Vector3i const &lower_corner, auto &&kernel)
Synchronize data between a sliced block and a container.
std::optional< BlockAndCell > get_block_and_cell(::LatticeWalberla const &lattice, signed_integral_vector auto const &node, bool consider_ghost_layers)
Cell to_cell(signed_integral_vector auto const &xyz)
ResourceObserver get_mpi_cart_comm_observer()
Get an observer on waLBerla's MPI Cartesian communicator status.
std::optional< walberla::cell::CellInterval > get_block_interval(::LatticeWalberla const &lattice, Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner, Utils::Vector3i const &block_offset, IBlock const &block)
std::optional< walberla::cell::CellInterval > get_interval(::LatticeWalberla const &lattice, Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner)
std::vector< Utils::Vector3d > fill_3D_vector_array(std::vector< double > const &vec_flat, Utils::Vector3i const &grid_size)
Observer to monitor the lifetime of a shared resource.
blockforest::communication::UniformBufferedScheme< Stencil > RegularCommScheme
GhostLayerField< FT, FluxCount > FluxField
field::communication::PackInfo< Field > PackInfo
GhostLayerField< FT, 1 > DensityField
blockforest::communication::UniformBufferedScheme< Stencil > BoundaryCommScheme
GhostCommFlags
Ghost communication operations.
@ DENS
density communication
@ FLB
flux boundary communication