30#if defined(__CUDACC__)
37#include <blockforest/communication/UniformBufferedScheme.h>
38#include <domain_decomposition/BlockDataID.h>
39#include <field/AddToStorage.h>
40#include <field/GhostLayerField.h>
41#include <field/communication/PackInfo.h>
42#include <field/vtk/VTKWriter.h>
43#include <stencil/D3Q27.h>
44#include <waLBerlaDefinitions.h>
45#if defined(__CUDACC__)
46#include <gpu/AddGPUFieldToStorage.h>
47#include <gpu/FieldAccessor.h>
48#include <gpu/FieldIndexing.h>
49#include <gpu/GPUField.h>
50#include <gpu/Kernel.h>
51#include <gpu/communication/MemcpyPackInfo.h>
52#include <gpu/communication/UniformGPUScheme.h>
56#pragma clang diagnostic push
57#pragma clang diagnostic ignored "-Wfloat-conversion"
58#pragma clang diagnostic ignored "-Wimplicit-float-conversion"
59#elif defined(__GNUC__) or defined(__GNUG__)
60#pragma GCC diagnostic push
61#pragma GCC diagnostic ignored "-Wfloat-conversion"
65#include <heffte_backends.h>
66#include <heffte_geometry.h>
69#pragma clang diagnostic pop
70#elif defined(__GNUC__) or defined(__GNUG__)
71#pragma GCC diagnostic pop
89template <
typename T, std::
size_t N>
91 std::array<T, N>
res{};
92 std::ranges::copy(
vec,
res.begin());
97 return (z * dim[1] + y) * dim[0] + x;
100template <
typename FloatType, lbmpy::Arch Architecture>
103 template <
typename T> FloatType FloatType_c(T t) {
108 template <
typename FT, lbmpy::Arch AT = lbmpy::Arch::CPU>
struct FieldTrait {
111 template <
class Field>
112 using PackInfo = field::communication::PackInfo<Field>;
113 template <
class Stencil>
115 blockforest::communication::UniformBufferedScheme<Stencil>;
118#if defined(__CUDACC__)
120 using ComplexType = std::conditional_t<std::is_same_v<FloatType, float>,
123 template <
class Field>
124 using PackInfo = gpu::communication::MemcpyPackInfo<Field>;
125 template <
class Stencil>
136 template <
class Field>
142#if defined(__CUDACC__)
143 using backend = heffte::backend::cufft;
149 std::unique_ptr<heffte::fft3d<backend>>
fft;
150 std::unique_ptr<heffte::fft3d<backend>::buffer_container<
ComplexType>>
157 box_in = std::make_unique<heffte::box3d<>>(
160 box_out = std::make_unique<heffte::box3d<>>(
165 buffer = std::make_unique<
166 heffte::fft3d<backend>::buffer_container<
ComplexType>>(
167 fft->size_workspace());
173#if defined(__CUDACC__)
179 std::unique_ptr<heffte_container<ComplexType>> heffte;
180 std::shared_ptr<FullCommunicator> m_full_communication;
182#if defined(__CUDACC__)
186 walberla::gpu::Kernel<
void (*)(walberla::gpu::FieldAccessor<ComplexType>,
187 walberla::gpu::FieldAccessor<FloatType>)>
189 walberla::gpu::Kernel<
void (*)(walberla::gpu::FieldAccessor<FloatType>,
190 walberla::gpu::FieldAccessor<FloatType>)>
193 std::vector<FloatType> m_greens;
194 std::vector<FloatType> m_potential;
195 std::vector<ComplexType> m_potential_fourier;
211#if defined(__CUDACC__)
212 m_potential_field_id = gpu::addGPUFieldToStorage<PotentialField>(
213 blocks,
"potential field", 1u, field::fzyx, 0
u,
false);
214 m_potential_field_with_ghosts_id =
215 gpu::addGPUFieldToStorage<PotentialField>(
216 blocks,
"potential field with ghosts", 1u, field::fzyx,
219 blocks,
"greens function", 1u, field::fzyx, 0
u,
false);
221 blocks,
"fourier field", 1u, field::fzyx, 0
u,
false);
229 kernel.addFieldIndexingParam(
245 m_potential_field_with_ghosts_id);
257 gpu::FieldIndexing<ComplexType>::allInner(*
fourier));
259 gpu::FieldIndexing<FloatType>::allInner(*
green));
265 gpu::FieldIndexing<FloatType>::xyz(*
potential));
269 m_potential_field_with_ghosts_id = field::addToStorage<PotentialField>(
270 blocks,
"potential field with ghosts", FloatType{0}, field::fzyx,
274 m_full_communication = std::make_shared<FullCommunicator>(
blocks);
275 m_full_communication->addPackInfo(
277 m_potential_field_with_ghosts_id));
285 return std::is_same_v<FloatType, double>;
289 return static_cast<std::size_t
>(m_potential_field_with_ghosts_id);
294 heffte::plan_options
options = heffte::default_options<
296#if defined(__CUDACC__)
299 options.algorithm = heffte::reshape_algorithm::p2p_plined;
306#if not defined(__CUDACC__)
308 m_potential = std::vector<FloatType>(heffte->fft->size_inbox());
309 m_greens = std::vector<FloatType>(heffte->fft->size_outbox());
310 m_potential_fourier =
311 std::vector<ComplexType>(heffte->fft->size_outbox());
314 for (
int x = 0; x < dim[0]; x++) {
315 for (
int y = 0; y < dim[1]; y++) {
316 for (
int z = 0; z < dim[2]; z++) {
327#if not defined(__CUDACC__)
330 heffte->fft->forward(m_potential.data(), m_potential_fourier.data(),
331 heffte->buffer->data());
334#if defined(__CUDACC__)
345 heffte->buffer->data());
360 m_potential_field_with_ghosts_id);
366 throw std::runtime_error(
"Setting potential is not supported by EKFFT");
372 std::vector<double>
out;
378 out = std::vector<double>(
ci->numCells());
379 for (
auto &
block : *lattice.get_blocks()) {
384 m_potential_field_with_ghosts_id);
405 std::vector<double>
const &)
override {
406 throw std::runtime_error(
"Setting potential is not supported by EKFFT");
410#if not defined(__CUDACC__)
414 heffte->fft->forward(m_potential.data(), m_potential_fourier.data(),
415 heffte->buffer->data());
416 std::ranges::transform(m_potential_fourier, m_greens,
417 m_potential_fourier.begin(), std::multiplies<>{});
418 heffte->fft->backward(m_potential_fourier.data(), m_potential.data(),
419 heffte->buffer->data());
423 m_potential_field_with_ghosts_id);
424 for (
int x = 0; x < dim[0]; x++) {
425 for (
int y = 0; y < dim[1]; y++) {
426 for (
int z = 0; z < dim[2]; z++) {
435#if defined(__CUDACC__)
445 heffte->buffer->data());
448 heffte->buffer->data());
460#if not defined(__CUDACC__)
466 for (
int x = 0; x < dim[0]; x++) {
467 for (
int y = 0; y < dim[1]; y++) {
468 for (
int z = 0; z < dim[2]; z++) {
477#if defined(__CUDACC__)
491#if not defined(__CUDACC__)
495 for (
int x = 0; x < dim[0]; x++) {
496 for (
int i = 0; i < m_potential_fourier.size(); i++) {
497 m_potential_fourier[i] *= m_greens[i];
499 for (
int y = 0; y < dim[1]; y++) {
500 for (
int z = 0; z < dim[2]; z++) {
507#if defined(__CUDACC__)
532 template <
typename VecType, u
int_t F_SIZE_ARG,
typename OutputType>
533 class VTKWriter :
public vtk::BlockCellDataWriter<OutputType, F_SIZE_ARG> {
545 return (
static_cast<std::size_t
>(x) *
m_dims[2] *
m_dims[1] +
546 static_cast<std::size_t
>(y) *
m_dims[2] +
547 static_cast<std::size_t
>(z)) *
561 template <
typename OutputType =
float>
563 :
public VTKWriter<std::vector<FloatType>, 1u, OutputType> {
567 using Base::evaluate;
591 m_potential_field_with_ghosts_id);
605#if defined(__CUDACC__)
609 kernel.addFieldIndexingParam(
610 gpu::FieldIndexing<FloatType>::xyz(*
field_out));
611 kernel.addFieldIndexingParam(
612 gpu::FieldIndexing<FloatType>::xyz(*
field_add));
Vector implementation and trait types for boost qvm interoperability.
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
auto const & get_grid_dimensions() const
std::pair< Utils::Vector3i, Utils::Vector3i > get_local_grid_range(bool with_halo=false) const
auto get_ghost_layers() const
OutputType evaluate(cell_idx_t const x, cell_idx_t const y, cell_idx_t const z, cell_idx_t const) override
void configure() override
std::size_t get_first_index(cell_idx_t const x, cell_idx_t const y, cell_idx_t const z)
void set_content(VecType content)
void set_dims(Vector3< uint_t > dims)
VTKWriter(ConstBlockDataID const &block_id, std::string const &id, FloatType unit_conversion)
FieldTrait< FloatType, Architecture >::template FullCommunicator< stencil::D3Q27 > FullCommunicator
bool is_gpu() const noexcept override
void reset_charge_field() override
bool set_node_potential(Utils::Vector3i const &, double) override
bool is_double_precision() const noexcept override
std::vector< double > get_slice_potential(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner) const override
void ghost_communication() override
PoissonSolverFFT(std::shared_ptr< LatticeWalberla > lattice, double permittivity)
void setup_fft(bool use_gpu_aware) override
FieldTrait< FloatType, Architecture >::ComplexType ComplexType
std::optional< double > get_node_potential(Utils::Vector3i const &node, bool consider_ghosts=false) override
void add_charge_to_field(std::size_t id, double valency) override
FieldTrait< FloatType, Architecture >::PotentialField PotentialField
void integrate_vtk_writers() override
void register_vtk_field_writers(walberla::vtk::VTKOutput &vtk_obj, LatticeModel::units_map const &units, int flag_observables) override
void set_slice_potential(Utils::Vector3i const &, Utils::Vector3i const &, std::vector< double > const &) override
FieldTrait< FloatType, Architecture >::template PackInfo< Field > PackInfo
~PoissonSolverFFT() override=default
std::size_t get_potential_field_id() const noexcept override
LatticeWalberla const & get_lattice() const noexcept override
virtual double get_permittivity() const noexcept
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)
void initialize(GhostLayerField< double, 1u > *scalar_field, double const &value)
auto get(GhostLayerField< double, 1u > const *scalar_field, Cell const &cell)
\file PackInfoPdfDoublePrecision.cpp \author pystencils
int pos_to_linear_index(int x, int y, int z, auto const &dim)
auto to_array(Utils::Vector< T, N > const &vec)
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)
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)
blockforest::communication::UniformBufferedScheme< Stencil > FullCommunicator
std::complex< FloatType > ComplexType
field::GhostLayerField< FT, 1u > PotentialField
field::communication::PackInfo< Field > PackInfo
std::unique_ptr< heffte::fft3d< backend > > fft
std::unique_ptr< heffte::box3d<> > box_in
heffte::backend::fftw backend
std::unique_ptr< heffte::box3d<> > box_out
std::unique_ptr< heffte::fft3d< backend >::buffer_container< ComplexType > > buffer
heffte_container(heffte::plan_options const &options, auto const &grid_range)