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 std::shared_ptr<::walberla::PoissonSolver> m_instance;
52 std::shared_ptr<LatticeWalberla> m_lattice;
53 bool m_gpu;
54 bool m_single_precision;
55
56protected:
57 void make_instance(VariantMap const &args) override {
58
59 auto *make_new_instance = &::walberla::new_ek_poisson_none;
60 if (m_gpu) {
61 std::vector<std::string> required_features;
62 required_features.emplace_back("CUDA");
64#ifdef ESPRESSO_CUDA
65 make_new_instance = &::walberla::new_ek_poisson_none_cuda;
66#endif
67 }
68 m_instance = make_new_instance(m_lattice->lattice(), m_single_precision);
69 }
70
71public:
72 Variant do_call_method(std::string const &method,
73 VariantMap const &parameters) override {
74 if (method == "save_checkpoint") {
75 auto const path = get_value<std::filesystem::path>(parameters, "path");
76 auto const mode = get_value<int>(parameters, "mode");
77 save_checkpoint(path, mode);
78 return {};
79 }
80 if (method == "load_checkpoint") {
81 auto const path = get_value<std::filesystem::path>(parameters, "path");
82 auto const mode = get_value<int>(parameters, "mode");
83 load_checkpoint(path, mode);
84 return {};
85 }
87 }
88
89 void do_construct(VariantMap const &args) override {
90 m_gpu = get_value_or<bool>(args, "gpu", false);
91 m_single_precision = get_value_or<bool>(args, "single_precision", m_gpu);
92 m_lattice = get_value<decltype(m_lattice)>(args, "lattice");
93 auto const agrid = get_value<double>(m_lattice->get_parameter("agrid"));
96
99 {"tau", AutoParameter::read_only, [this]() { return m_tau; }},
100 {"single_precision", AutoParameter::read_only,
101 [this]() { return m_single_precision; }},
102 {"gpu", AutoParameter::read_only, [this]() { return m_gpu; }},
103 {"lattice", AutoParameter::read_only, [this]() { return m_lattice; }},
104 {"shape", AutoParameter::read_only,
105 [this]() { return m_instance->get_lattice().get_grid_dimensions(); }},
106 });
107 }
108
109 [[nodiscard]] std::shared_ptr<::walberla::PoissonSolver>
111 return m_instance;
112 }
113
114private:
115 void load_checkpoint(std::filesystem::path const &path, int mode) {
116 auto &solver = *m_instance;
117
118 auto const read_metadata = [&solver](CheckpointFile &cpfile) {
119 auto const expected_grid_size =
120 solver.get_lattice().get_grid_dimensions();
124 std::stringstream message;
125 message << "grid dimensions mismatch, read [" << read_grid_size << "], "
126 << "expected [" << expected_grid_size << "].";
127 throw std::runtime_error(message.str());
128 }
129 };
130
131 auto const read_data = [&solver](CheckpointFile &cpfile) {
132 auto const grid_size = solver.get_lattice().get_grid_dimensions();
133 auto const i_max = grid_size[0];
134 auto const j_max = grid_size[1];
135 auto const k_max = grid_size[2];
136 for (int i = 0; i < i_max; i++) {
137 for (int j = 0; j < j_max; j++) {
138 for (int k = 0; k < k_max; k++) {
139 auto const ind = Utils::Vector3i{{i, j, k}};
140 double potential{};
141 cpfile.read(potential);
142 static_cast<void>(solver.set_node_potential(ind, potential));
143 }
144 }
145 }
146 };
147
148 auto const on_success = []() {};
151 }
152
153 void save_checkpoint(std::filesystem::path const &path, int mode) {
154 auto &solver = *m_instance;
155
156 auto const write_metadata =
157 [&solver, mode](std::shared_ptr<CheckpointFile> cpfile_ptr,
158 Context const &context) {
159 auto const grid_size = solver.get_lattice().get_grid_dimensions();
160 if (context.is_head_node()) {
161 cpfile_ptr->write(grid_size);
163 }
164 };
165
166 auto const on_failure = [](std::shared_ptr<CheckpointFile> const &,
167 Context const &context) {
168 if (context.is_head_node()) {
169 auto failure = true;
170 boost::mpi::broadcast(context.get_comm(), failure, 0);
171 }
172 };
173
174 auto const write_data = [&solver,
175 mode](std::shared_ptr<CheckpointFile> cpfile_ptr,
176 Context const &context) {
177 auto const get_node_checkpoint =
178 [&solver](Utils::Vector3i const &ind) -> std::optional<double> {
179 return solver.get_node_potential(ind);
180 };
181
182 auto failure = false;
183 auto const &comm = context.get_comm();
184 auto const is_head_node = context.is_head_node();
185 auto const unit_test_mode = (mode != static_cast<int>(CptMode::ascii)) and
186 (mode != static_cast<int>(CptMode::binary));
187 auto const grid_size = solver.get_lattice().get_grid_dimensions();
188 auto const i_max = grid_size[0];
189 auto const j_max = grid_size[1];
190 auto const k_max = grid_size[2];
191 double cpnode = 0.;
192 for (int i = 0; i < i_max; i++) {
193 for (int j = 0; j < j_max; j++) {
194 for (int k = 0; k < k_max; k++) {
195 auto const ind = Utils::Vector3i{{i, j, k}};
196 auto const result = get_node_checkpoint(ind);
197 if (!unit_test_mode) {
198 assert(1 == boost::mpi::all_reduce(comm,
199 static_cast<int>(!!result),
200 std::plus<>()) &&
201 "Incorrect number of return values");
202 }
203 if (is_head_node) {
204 if (result) {
205 cpnode = *result;
206 } else {
207 comm.recv(boost::mpi::any_source, 42, cpnode);
208 }
209 cpfile_ptr->write(cpnode);
210 boost::mpi::broadcast(comm, failure, 0);
211 } else {
212 if (result) {
213 comm.send(0, 42, *result);
214 }
215 boost::mpi::broadcast(comm, failure, 0);
216 if (failure) {
217 return;
218 }
219 }
220 }
221 }
222 }
223 };
224
227 }
228};
229
230} // namespace ScriptInterface::walberla
231
232#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)
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)
T get_value(Variant const &v)
Extract value of specific type T from a Variant.
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