ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
PoissonSolverNone.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2022-2026 The ESPResSo project
3 *
4 * This file is part of ESPResSo.
5 *
6 * ESPResSo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * ESPResSo is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#pragma once
21
25
26#include "greens_function.hpp"
27
30#if defined(__CUDACC__)
33#endif
34
35#include <utils/Vector.hpp>
36
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/vtk/VTKWriter.h>
42#include <stencil/D3Q27.h>
43#include <waLBerlaDefinitions.h>
44#if defined(__CUDACC__)
45#include <gpu/AddGPUFieldToStorage.h>
46#include <gpu/FieldAccessor.h>
47#include <gpu/FieldIndexing.h>
48#include <gpu/GPUField.h>
49#include <gpu/HostFieldAllocator.h>
50#include <gpu/Kernel.h>
51#include <gpu/communication/UniformGPUScheme.h>
52#endif
53
54#if defined(__clang__)
55#pragma clang diagnostic push
56#pragma clang diagnostic ignored "-Wfloat-conversion"
57#pragma clang diagnostic ignored "-Wimplicit-float-conversion"
58#elif defined(__GNUC__) or defined(__GNUG__)
59#pragma GCC diagnostic push
60#pragma GCC diagnostic ignored "-Wfloat-conversion"
61#endif
62
63#if defined(__clang__)
64#pragma clang diagnostic pop
65#elif defined(__GNUC__) or defined(__GNUG__)
66#pragma GCC diagnostic pop
67#endif
68
69#include <algorithm>
70#include <array>
71#include <complex>
72#include <cstddef>
73#include <functional>
74#include <memory>
75#include <optional>
76#include <ranges>
77#include <string>
78#include <type_traits>
79#include <utility>
80#include <vector>
81
82namespace walberla {
83template <typename FloatType, lbmpy::Arch Architecture>
85private:
86 template <typename T> FloatType FloatType_c(T t) {
88 }
89
90protected:
91 template <typename FT, lbmpy::Arch AT = lbmpy::Arch::CPU> struct FieldTrait {
92 using PotentialField = field::GhostLayerField<FT, 1u>;
93 };
94
95#if defined(__CUDACC__)
96 template <typename FT> struct FieldTrait<FT, lbmpy::Arch::GPU> {
97 using PotentialField = gpu::GPUField<FT>;
98 };
99#endif
100
101public:
103
104private:
105 BlockDataID m_potential_field_id;
106
107public:
108 ~PoissonSolverNone() override = default;
109 explicit PoissonSolverNone(std::shared_ptr<LatticeWalberla> lattice)
110 : PoissonSolver(std::move(lattice), 0.0) {
111 auto blocks = get_lattice().get_blocks();
112#if defined(__CUDACC__)
113 if constexpr (Architecture == lbmpy::Arch::GPU) {
114 m_potential_field_id = gpu::addGPUFieldToStorage<PotentialField>(
115 blocks, "potential field", 1u, field::fzyx,
116 get_lattice().get_ghost_layers());
117 for (auto &block : *blocks) {
118 auto field =
119 block.template getData<PotentialField>(m_potential_field_id);
120 ek::accessor::Scalar::initialize(field, FloatType{0});
121 }
122 }
123#endif // __CUDACC__
124 if constexpr (Architecture == lbmpy::Arch::CPU) {
125 m_potential_field_id = field::addToStorage<PotentialField>(
126 blocks, "potential field", FloatType{0}, field::fzyx,
128 }
129 }
130
131 void setup_fft(bool) override {}
132
133 [[nodiscard]] bool is_gpu() const noexcept override {
135 }
136
138 return std::is_same_v<FloatType, double>;
139 }
140
141 std::size_t get_potential_field_id() const noexcept override {
142 return static_cast<std::size_t>(m_potential_field_id);
143 }
144
145 [[nodiscard]] std::optional<double>
147 bool consider_ghosts = false) override {
149
150 if (not bc or get_potential_field_id() == 0u)
151 return std::nullopt;
152
153 auto const potential_field =
154 bc->block->template getData<PotentialField>(m_potential_field_id);
155 return {double_c(
157 }
158
160 double potential) override {
161 auto bc = get_block_and_cell(get_lattice(), node, false);
162 if (!bc) {
163 return false;
164 }
165 auto potential_field =
166 bc->block->template getData<PotentialField>(m_potential_field_id);
168 bc->cell);
169 return true;
170 }
171
172 [[nodiscard]] std::vector<double>
174 Utils::Vector3i const &upper_corner) const override {
175 std::vector<double> out;
176#ifndef NDEBUG
178#endif
179 auto const &lattice = get_lattice();
180 if (auto const ci = get_interval(lattice, lower_corner, upper_corner)) {
181 out = std::vector<double>(ci->numCells());
182 for (auto &block : *lattice.get_blocks()) {
183 auto const block_offset = lattice.get_block_corner(block, true);
184 if (auto const bci = get_block_interval(
186 auto const potential_field =
187 block.template getData<PotentialField>(m_potential_field_id);
189 assert(values.size() == bci->numCells());
190#ifndef NDEBUG
191 values_size += bci->numCells();
192#endif
193 auto kernel = [&values, &out](unsigned const block_index,
194 unsigned const local_index,
195 Utils::Vector3i const &) {
197 };
198
200 }
201 }
202 assert(values_size == ci->numCells());
203 }
204 return out;
205 }
206
209 std::vector<double> const &potential) override {
210 auto const &lattice = get_lattice();
211 if (auto const ci = get_interval(lattice, lower_corner, upper_corner)) {
212 assert(potential.size() == ci->numCells());
213 for (auto &block : *lattice.get_blocks()) {
214 auto const block_offset = lattice.get_block_corner(block, true);
215 if (auto const bci = get_block_interval(
217 auto potential_field =
218 block.template getData<PotentialField>(m_potential_field_id);
219 std::vector<FloatType> values(bci->numCells());
220
221 auto kernel = [&values, &potential](unsigned const block_index,
222 unsigned const local_index,
223 Utils::Vector3i const &) {
226 };
227
230 }
231 }
232 }
233 }
234 void ghost_communication() override {}
235
236 void solve() override { integrate_vtk_writers(); }
237
238 void add_charge_to_field(std::size_t id, double valency) override {}
239 void reset_charge_field() override {}
240
241protected:
242 void integrate_vtk_writers() override {
243 for (auto const &vtk_handle : m_vtk_auto | std::views::values) {
244 if (vtk_handle->enabled) {
245 vtk::writeFiles(vtk_handle->ptr)();
246 vtk_handle->execution_count++;
247 }
248 }
249 }
250
251protected:
252 template <typename VecType, uint_t F_SIZE_ARG, typename OutputType>
253 class VTKWriter : public vtk::BlockCellDataWriter<OutputType, F_SIZE_ARG> {
254 public:
255 VTKWriter(ConstBlockDataID const &block_id, std::string const &id,
256 FloatType unit_conversion)
257 : vtk::BlockCellDataWriter<OutputType, F_SIZE_ARG>(id),
259
260 protected:
261 void configure() override { WALBERLA_ASSERT_NOT_NULLPTR(this->block_); }
262
263 std::size_t get_first_index(cell_idx_t const x, cell_idx_t const y,
264 cell_idx_t const z) {
265 return (static_cast<std::size_t>(x) * m_dims[2] * m_dims[1] +
266 static_cast<std::size_t>(y) * m_dims[2] +
267 static_cast<std::size_t>(z)) *
269 }
270
271 FloatType m_conversion;
274
275 public:
277
278 void set_dims(Vector3<uint_t> dims) { m_dims = dims; }
279 };
280
281 template <typename OutputType = float>
283 : public VTKWriter<std::vector<FloatType>, 1u, OutputType> {
284 public:
285 using Base = VTKWriter<std::vector<FloatType>, 1u, OutputType>;
286 using Base::Base;
287 using Base::evaluate;
288
289 protected:
290 OutputType evaluate(cell_idx_t const x, cell_idx_t const y,
291 cell_idx_t const z, cell_idx_t const) override {
292 WALBERLA_ASSERT(!this->m_content.empty());
293 auto const potential = this->m_content[this->get_first_index(x, y, z)];
295 }
296 };
297
298public:
299 void register_vtk_field_writers(walberla::vtk::VTKOutput &vtk_obj,
301 int flag_observables) override {
302 if (flag_observables & static_cast<int>(EKPoissonOutputVTK::potential)) {
303 auto const unit_conversion = FloatType_c(units.at("potential"));
304 auto const blocks = get_lattice().get_blocks();
307 m_potential_field_id, "potential", unit_conversion);
308 auto before_function = [this, blocks, potential_writer]() {
309 for (auto &block : *blocks) {
310 auto *potential_field =
311 block.template getData<PotentialField>(m_potential_field_id);
312 auto const bci = potential_field->xyzSize();
313 potential_writer->set_content(
316 uint_c(bci.xSize()), uint_c(bci.ySize()), uint_c(bci.zSize())));
317 }
318 };
319 vtk_obj.addBeforeFunction(std::move(before_function));
320 vtk_obj.addCellDataWriter(potential_writer);
321 }
322 }
323};
324
325} // namespace walberla
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
OutputType evaluate(cell_idx_t const x, cell_idx_t const y, cell_idx_t const z, cell_idx_t const) override
VTKWriter(ConstBlockDataID const &block_id, std::string const &id, FloatType unit_conversion)
std::size_t get_first_index(cell_idx_t const x, cell_idx_t const y, cell_idx_t const z)
bool is_double_precision() const noexcept override
~PoissonSolverNone() override=default
bool is_gpu() const noexcept override
std::size_t get_potential_field_id() const noexcept override
void set_slice_potential(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner, std::vector< double > const &potential) override
std::vector< double > get_slice_potential(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner) const override
PoissonSolverNone(std::shared_ptr< LatticeWalberla > lattice)
void add_charge_to_field(std::size_t id, double valency) override
FieldTrait< FloatType, Architecture >::PotentialField PotentialField
bool set_node_potential(Utils::Vector3i const &node, double potential) override
std::optional< double > get_node_potential(Utils::Vector3i const &node, bool consider_ghosts=false) override
void register_vtk_field_writers(walberla::vtk::VTKOutput &vtk_obj, LatticeModel::units_map const &units, int flag_observables) override
LatticeWalberla const & get_lattice() const noexcept override
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)
Definition elc.cpp:175
STL namespace.
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)
\file PackInfoPdfDoublePrecision.cpp \author pystencils
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)
field::GhostLayerField< FT, 1u > PotentialField