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 <string>
77#include <type_traits>
78#include <utility>
79#include <vector>
80
81namespace walberla {
82template <typename FloatType, lbmpy::Arch Architecture>
84private:
85 template <typename T> FloatType FloatType_c(T t) {
86 return numeric_cast<FloatType>(t);
87 }
88
89protected:
90 template <typename FT, lbmpy::Arch AT = lbmpy::Arch::CPU> struct FieldTrait {
91 using PotentialField = field::GhostLayerField<FT, 1u>;
92 };
93
94#if defined(__CUDACC__)
95 template <typename FT> struct FieldTrait<FT, lbmpy::Arch::GPU> {
96 using PotentialField = gpu::GPUField<FT>;
97 };
98#endif
99
100public:
102
103private:
104 BlockDataID m_potential_field_id;
105
106public:
107 ~PoissonSolverNone() override = default;
108 explicit PoissonSolverNone(std::shared_ptr<LatticeWalberla> lattice)
109 : PoissonSolver(std::move(lattice), 0.0) {
110 auto blocks = get_lattice().get_blocks();
111#if defined(__CUDACC__)
112 m_potential_field_id = gpu::addGPUFieldToStorage<PotentialField>(
113 blocks, "potential field", 1u, field::fzyx,
114 get_lattice().get_ghost_layers());
115#else // __CUDACC__
116 m_potential_field_id = field::addToStorage<PotentialField>(
117 blocks, "potential field", 0., field::fzyx,
118 get_lattice().get_ghost_layers());
119#endif // __CUDACC__
120 }
121
122 void setup_fft(bool use_gpu_aware) override {}
123
124 [[nodiscard]] bool is_gpu() const noexcept override {
125 return Architecture == lbmpy::Arch::GPU;
126 }
127
128 [[nodiscard]] bool is_double_precision() const noexcept override {
129 return std::is_same_v<FloatType, double>;
130 }
131
132 std::size_t get_potential_field_id() const noexcept override {
133 return static_cast<std::size_t>(m_potential_field_id);
134 }
135
136 [[nodiscard]] std::optional<double>
138 bool consider_ghosts = false) override {
139 auto bc = get_block_and_cell(get_lattice(), node, consider_ghosts);
140
141 if (not bc or get_potential_field_id() == 0u)
142 return std::nullopt;
143
144 auto const potential_field =
145 bc->block->template getData<PotentialField>(m_potential_field_id);
146 return {double_c(
147 walberla::ek::accessor::Scalar::get(potential_field, bc->cell))};
148 }
149
151 double potential) override {
152 auto bc = get_block_and_cell(get_lattice(), node, false);
153 if (!bc) {
154 return false;
155 }
156 auto potential_field =
157 bc->block->template getData<PotentialField>(m_potential_field_id);
158 ek::accessor::Scalar::set(potential_field, FloatType_c(potential),
159 bc->cell);
160 return true;
161 }
162
163 [[nodiscard]] std::vector<double>
165 Utils::Vector3i const &upper_corner) const override {
166 std::vector<double> out;
167#ifndef NDEBUG
168 uint_t values_size{0u};
169#endif
170 auto const &lattice = get_lattice();
171 if (auto const ci = get_interval(lattice, lower_corner, upper_corner)) {
172 out = std::vector<double>(ci->numCells());
173 for (auto &block : *lattice.get_blocks()) {
174 auto const block_offset = lattice.get_block_corner(block, true);
175 if (auto const bci = get_block_interval(
176 lattice, lower_corner, upper_corner, block_offset, block)) {
177 auto const potential_field =
178 block.template getData<PotentialField>(m_potential_field_id);
179 auto const values = ek::accessor::Scalar::get(potential_field, *bci);
180 assert(values.size() == bci->numCells());
181#ifndef NDEBUG
182 values_size += bci->numCells();
183#endif
184 auto kernel = [&values, &out](unsigned const block_index,
185 unsigned const local_index,
186 Utils::Vector3i const &) {
187 out[local_index] = double_c(values[block_index]);
188 };
189
190 copy_block_buffer(*bci, *ci, block_offset, lower_corner, kernel);
191 }
192 }
193 assert(values_size == ci->numCells());
194 }
195 return out;
196 }
197
198 void set_slice_potential(Utils::Vector3i const &lower_corner,
199 Utils::Vector3i const &upper_corner,
200 std::vector<double> const &potential) override {
201 auto const &lattice = get_lattice();
202 if (auto const ci = get_interval(lattice, lower_corner, upper_corner)) {
203 assert(potential.size() == ci->numCells());
204 for (auto &block : *lattice.get_blocks()) {
205 auto const block_offset = lattice.get_block_corner(block, true);
206 if (auto const bci = get_block_interval(
207 lattice, lower_corner, upper_corner, block_offset, block)) {
208 auto potential_field =
209 block.template getData<PotentialField>(m_potential_field_id);
210 std::vector<FloatType> values(bci->numCells());
211
212 auto kernel = [&values, &potential](unsigned const block_index,
213 unsigned const local_index,
214 Utils::Vector3i const &) {
215 values[block_index] =
216 numeric_cast<FloatType>(potential[local_index]);
217 };
218
219 copy_block_buffer(*bci, *ci, block_offset, lower_corner, kernel);
220 ek::accessor::Scalar::set(potential_field, values, *bci);
221 }
222 }
223 }
224 }
225 void ghost_communication() override {}
226
227 void solve() override {}
228
229 void add_charge_to_field(std::size_t id, double valency) override {}
230 void reset_charge_field() override {}
231};
232
233} // namespace walberla
Vector implementation and trait types for boost qvm interoperability.
void setup_fft(bool use_gpu_aware) override
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
LatticeWalberla const & get_lattice() const noexcept override
static double * block(double *p, std::size_t index, std::size_t size)
Definition elc.cpp:175
STL namespace.
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