ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
script_interface/walberla/EKNone.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
22#include <config/config.hpp>
23
24#ifdef ESPRESSO_WALBERLA
25
26#include "EKPoissonSolver.hpp"
28
31
35
36#include <boost/mpi.hpp>
37#include <boost/mpi/collectives/all_reduce.hpp>
38#include <boost/mpi/collectives/broadcast.hpp>
39
40#include <cassert>
41#include <filesystem>
42#include <memory>
43#include <optional>
44#include <sstream>
45#include <stdexcept>
46#include <string>
47
49
50class EKNone : public EKPoissonSolver {
51 bool m_gpu;
52 bool m_single_precision;
53
54protected:
55 void make_instance(VariantMap const &args) override {
56
57 auto *make_new_instance = &::walberla::new_ek_poisson_none;
58 if (m_gpu) {
59 std::vector<std::string> required_features;
60 required_features.emplace_back("CUDA");
62#ifdef ESPRESSO_CUDA
63 make_new_instance = &::walberla::new_ek_poisson_none_cuda;
64#endif
65 }
66 m_instance = make_new_instance(m_lattice->lattice(), m_single_precision);
67 }
68
69public:
70 Variant do_call_method(std::string const &method,
71 VariantMap const &parameters) override {
72 if (method == "save_checkpoint") {
73 auto const path = get_value<std::filesystem::path>(parameters, "path");
74 auto const mode = get_value<int>(parameters, "mode");
75 save_checkpoint(path, mode);
76 return {};
77 }
78 if (method == "load_checkpoint") {
79 auto const path = get_value<std::filesystem::path>(parameters, "path");
80 auto const mode = get_value<int>(parameters, "mode");
81 load_checkpoint(path, mode);
82 return {};
83 }
85 }
86
87 void do_construct(VariantMap const &args) override {
88 m_gpu = get_value_or<bool>(args, "gpu", false);
89 m_single_precision = get_value_or<bool>(args, "single_precision", m_gpu);
93 auto const agrid = get_value<double>(m_lattice->get_parameter("agrid"));
97 for (auto &vtk : m_vtk_writers) {
98 vtk->attach_to_lattice(m_instance, get_lattice_to_md_units_conversion());
99 }
100 }
101
104 {"tau", AutoParameter::read_only, [this]() { return m_tau; }},
105 {"single_precision", AutoParameter::read_only,
106 [this]() { return m_single_precision; }},
107 {"gpu", AutoParameter::read_only, [this]() { return m_gpu; }},
108 {"lattice", AutoParameter::read_only, [this]() { return m_lattice; }},
109 {"shape", AutoParameter::read_only,
110 [this]() { return m_instance->get_lattice().get_grid_dimensions(); }},
111 {"vtk_writers", AutoParameter::read_only,
112 [this]() { return serialize_vtk_writers(); }},
113 });
114 }
115
116 [[nodiscard]] std::shared_ptr<::walberla::PoissonSolver>
118 return m_instance;
119 }
120
121private:
122 void load_checkpoint(std::filesystem::path const &path, int mode) {
123 auto &solver = *m_instance;
124
125 auto const read_metadata = [&solver](CheckpointFile &cpfile) {
126 auto const expected_grid_size =
127 solver.get_lattice().get_grid_dimensions();
131 std::stringstream message;
132 message << "grid dimensions mismatch, read [" << read_grid_size << "], "
133 << "expected [" << expected_grid_size << "].";
134 throw std::runtime_error(message.str());
135 }
136 };
137
138 auto const read_data = [&solver](CheckpointFile &cpfile) {
139 auto const grid_size = solver.get_lattice().get_grid_dimensions();
140 auto const i_max = grid_size[0];
141 auto const j_max = grid_size[1];
142 auto const k_max = grid_size[2];
143 for (int i = 0; i < i_max; i++) {
144 for (int j = 0; j < j_max; j++) {
145 for (int k = 0; k < k_max; k++) {
146 auto const ind = Utils::Vector3i{{i, j, k}};
147 double potential{};
148 cpfile.read(potential);
149 static_cast<void>(solver.set_node_potential(ind, potential));
150 }
151 }
152 }
153 };
154
155 auto const on_success = []() {};
158 }
159
160 void save_checkpoint(std::filesystem::path const &path, int mode) {
161 auto &solver = *m_instance;
162
163 auto const write_metadata =
164 [&solver, mode](std::shared_ptr<CheckpointFile> cpfile_ptr,
165 Context const &context) {
166 auto const grid_size = solver.get_lattice().get_grid_dimensions();
167 if (context.is_head_node()) {
168 cpfile_ptr->write(grid_size);
170 }
171 };
172
173 auto const on_failure = [](std::shared_ptr<CheckpointFile> const &,
174 Context const &context) {
175 if (context.is_head_node()) {
176 auto failure = true;
177 boost::mpi::broadcast(context.get_comm(), failure, 0);
178 }
179 };
180
181 auto const write_data = [&solver,
182 mode](std::shared_ptr<CheckpointFile> cpfile_ptr,
183 Context const &context) {
184 auto const get_node_checkpoint =
185 [&solver](Utils::Vector3i const &ind) -> std::optional<double> {
186 return solver.get_node_potential(ind);
187 };
188
189 auto failure = false;
190 auto const &comm = context.get_comm();
191 auto const is_head_node = context.is_head_node();
192 auto const unit_test_mode = (mode != static_cast<int>(CptMode::ascii)) and
193 (mode != static_cast<int>(CptMode::binary));
194 auto const grid_size = solver.get_lattice().get_grid_dimensions();
195 auto const i_max = grid_size[0];
196 auto const j_max = grid_size[1];
197 auto const k_max = grid_size[2];
198 double cpnode = 0.;
199 for (int i = 0; i < i_max; i++) {
200 for (int j = 0; j < j_max; j++) {
201 for (int k = 0; k < k_max; k++) {
202 auto const ind = Utils::Vector3i{{i, j, k}};
203 auto const result = get_node_checkpoint(ind);
204 if (!unit_test_mode) {
205 assert(1 == boost::mpi::all_reduce(comm,
206 static_cast<int>(!!result),
207 std::plus<>()) &&
208 "Incorrect number of return values");
209 }
210 if (is_head_node) {
211 if (result) {
212 cpnode = *result;
213 } else {
214 comm.recv(boost::mpi::any_source, 42, cpnode);
215 }
216 cpfile_ptr->write(cpnode);
217 boost::mpi::broadcast(comm, failure, 0);
218 } else {
219 if (result) {
220 comm.send(0, 42, *result);
221 }
222 boost::mpi::broadcast(comm, failure, 0);
223 if (failure) {
224 return;
225 }
226 }
227 }
228 }
229 }
230 };
231
234 }
235};
236
237} // namespace ScriptInterface::walberla
238
239#endif // ESPRESSO_WALBERLA
void add_parameters(std::vector< AutoParameter > &&params)
virtual bool is_head_node() const =0
virtual boost::mpi::communicator const & get_comm() const =0
virtual Variant do_call_method(const std::string &, const VariantMap &)
Local implementation of call_method.
Context * context() const
Responsible context.
Variant do_call_method(std::string const &method, VariantMap const &parameters) override
void do_construct(VariantMap const &args) override
void make_instance(VariantMap const &args) override
std::shared_ptr<::walberla::PoissonSolver > get_instance() const noexcept override
void set_potential_conversion(double agrid, double tau)
::LatticeModel::units_map get_lattice_to_md_units_conversion() const override
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
void check_features(std::vector< std::string > const &features)
Definition CodeInfo.cpp:74
void save_checkpoint_common(Context const &context, std::string const classname, std::filesystem::path const &path, int mode, F1 const write_metadata, F2 const write_data, F3 const on_failure)
void unit_test_handle(int mode)
Inject code for unit tests.
void load_checkpoint_common(Context const &context, std::string const classname, std::filesystem::path const &path, int mode, F1 const read_metadata, F2 const read_data, F3 const on_success)
std::unordered_map< std::string, Variant > VariantMap
Definition Variant.hpp:133
std::shared_ptr< walberla::PoissonSolver > new_ek_poisson_none(std::shared_ptr< LatticeWalberla > const &lattice, bool single_precision)
std::shared_ptr< walberla::PoissonSolver > new_ek_poisson_none_cuda(std::shared_ptr< LatticeWalberla > const &lattice, bool single_precision)
static constexpr const ReadOnly read_only
Recursive variant implementation.
Definition Variant.hpp:84