ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
lb/Solver.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2023 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#include "config/config.hpp"
21
22#include "lb/Implementation.hpp"
23#include "lb/Solver.hpp"
24#include "lb/utils.hpp"
25
26#include "lb/LBNone.hpp"
27#include "lb/LBWalberla.hpp"
28
29#include "BoxGeometry.hpp"
30#include "system/System.hpp"
31#include "thermostat.hpp"
32
33#ifdef ESPRESSO_WALBERLA
35#endif
36
37#include <utils/Vector.hpp>
38
39#include <cassert>
40#include <cmath>
41#include <functional>
42#include <limits>
43#include <memory>
44#include <optional>
45#include <stdexcept>
46#include <string>
47#include <tuple>
48#include <variant>
49#include <vector>
50
51namespace LB {
52
53Solver::Solver() { impl = std::make_unique<Implementation>(); }
54
55static auto is_solver_set(std::unique_ptr<Solver::Implementation> const &ptr) {
56 return ptr != nullptr and ptr->solver.has_value();
57}
58
59static void check_solver(std::unique_ptr<Solver::Implementation> const &ptr) {
60 if (not is_solver_set(ptr)) {
61 throw NoLBActive{};
62 }
63}
64
65bool Solver::is_solver_set() const { return LB::is_solver_set(impl); }
66
68 System::get_system().lb.impl->solver = std::nullopt;
69 m_conv = Conversions{};
70}
71
73 check_solver(impl);
74 std::visit([](auto &ptr) { ptr->propagate(); }, *impl->solver);
75}
76
78 check_solver(impl);
79 std::visit([](auto &ptr) { ptr->ghost_communication(); }, *impl->solver);
80}
81
83 check_solver(impl);
84 std::visit([](auto &ptr) { ptr->ghost_communication_pdf(); }, *impl->solver);
85}
86
88 check_solver(impl);
89 std::visit([](auto &ptr) { ptr->ghost_communication_vel(); }, *impl->solver);
90}
91
93 if (impl->solver) {
94 auto const &system = get_system();
95 std::visit([&](auto &ptr) { ptr->sanity_checks(system); }, *impl->solver);
96 }
97}
98
99void Solver::veto_time_step(double time_step) const {
100 if (impl->solver) {
101 std::visit([=](auto &ptr) { ptr->veto_time_step(time_step); },
102 *impl->solver);
103 }
104}
105
106void Solver::veto_kT(double kT) const {
107 if (impl->solver) {
108 std::visit([=](auto &ptr) { ptr->veto_kT(kT); }, *impl->solver);
109 }
110}
111
112void Solver::lebc_sanity_checks(unsigned int shear_direction,
113 unsigned int shear_plane_normal) const {
114 if (impl->solver) {
115 auto const callback = [=](auto &ptr) {
116 ptr->lebc_sanity_checks(shear_direction, shear_plane_normal);
117 };
118 std::visit(callback, *impl->solver);
119 }
120}
121
123 if (impl->solver) {
124 auto &solver = *impl->solver;
125 std::visit([](auto &ptr) { ptr->on_cell_structure_change(); }, solver);
126 }
127}
128
130 if (impl->solver) {
131 std::visit([](auto const &ptr) { ptr->veto_boxl_change(); }, *impl->solver);
132 }
133}
134
136 if (impl->solver) {
137 std::visit([](auto &ptr) { ptr->on_boxl_change(); }, *impl->solver);
138 }
139}
140
142 if (impl->solver) {
143 std::visit([](auto &ptr) { ptr->on_node_grid_change(); }, *impl->solver);
144 }
145}
146
148 if (impl->solver) {
149 std::visit([](auto &ptr) { ptr->on_timestep_change(); }, *impl->solver);
150 }
151}
152
154 if (impl->solver) {
155 std::visit([](auto &ptr) { ptr->on_temperature_change(); }, *impl->solver);
156 }
157}
158
160 if (impl->solver) {
161 std::visit([](auto &ptr) { ptr->on_lees_edwards_change(); }, *impl->solver);
162 }
163}
164
166 if (impl->solver) {
167 std::visit([](auto &ptr) { ptr->update_collision_model(); }, *impl->solver);
168 }
169}
170
171bool Solver::is_gpu() const {
172 check_solver(impl);
173 return std::visit([](auto &ptr) { return ptr->is_gpu(); }, *impl->solver);
174}
175
176double Solver::get_agrid() const {
177 check_solver(impl);
178 return std::visit([](auto &ptr) { return ptr->get_agrid(); }, *impl->solver);
179}
180
181double Solver::get_tau() const {
182 check_solver(impl);
183 return std::visit([](auto &ptr) { return ptr->get_tau(); }, *impl->solver);
184}
185
186double Solver::get_kT() const {
187 check_solver(impl);
188 return std::visit([](auto &ptr) { return ptr->get_kT(); }, *impl->solver);
189}
190
192 check_solver(impl);
193 return std::visit([](auto &ptr) { return ptr->get_pressure_tensor(); },
194 *impl->solver);
195}
196
197std::function<bool(Utils::Vector3d const &)>
198Solver::make_lattice_position_checker(bool consider_points_in_halo) const {
199 return std::visit(
200 [&](auto &ptr) -> std::function<bool(Utils::Vector3d const &)> {
201 auto const &box_geo = *System::get_system().box_geo;
202 return [&, kernel = ptr->make_lattice_position_checker(
203 consider_points_in_halo)](Utils::Vector3d const &pos) {
204 return kernel(box_geo.folded_position(pos) * m_conv.pos_to_lb);
205 };
206 },
207 *impl->solver);
208}
209
210std::optional<Utils::Vector3d>
212 /* calculate fluid velocity at particle's position
213 this is done by linear interpolation
214 (Eq. (11) Ahlrichs and Duenweg, JCP 111(17):8225 (1999)) */
215 return std::visit(
216 [&](auto &ptr) {
217 auto const &box_geo = *System::get_system().box_geo;
218 auto const lb_pos = box_geo.folded_position(pos) * m_conv.pos_to_lb;
219 return ptr->get_velocity_at_pos(lb_pos, false);
220 },
221 *impl->solver);
222}
223
224std::optional<double>
226 return std::visit(
227 [&](auto &ptr) {
228 auto const &box_geo = *System::get_system().box_geo;
229 auto const lb_pos = box_geo.folded_position(pos) * m_conv.pos_to_lb;
230 return ptr->get_density_at_pos(lb_pos, false);
231 },
232 *impl->solver);
233}
234
236 std::vector<Utils::Vector3d> const &pos) const {
237 return std::visit(
238 [&](auto &ptr) {
239 auto const &box_geo = *System::get_system().box_geo;
240 std::vector<Utils::Vector3d> pos_lb;
241 pos_lb.reserve(pos.size());
242 for (auto const &pos_md : pos) {
243 pos_lb.emplace_back(box_geo.folded_position(pos_md) *
244 m_conv.pos_to_lb);
245 }
246 return ptr->get_densities_at_pos(pos_lb);
247 },
248 *impl->solver);
249}
250
253 return std::visit(
254 [&](auto &ptr) {
255 auto const res = ptr->get_velocity_at_pos(pos * m_conv.pos_to_lb, true);
256 assert(res);
257 return *res * m_conv.vel_to_md;
258 },
259 *impl->solver);
260}
261
263 std::vector<Utils::Vector3d> const &pos) const {
264 return std::visit(
265 [&](auto &ptr) {
266 std::vector<Utils::Vector3d> pos_lb;
267 pos_lb.reserve(pos.size());
268 for (auto const &pos_md : pos) {
269 pos_lb.emplace_back(pos_md * m_conv.pos_to_lb);
270 }
271 auto res = ptr->get_velocities_at_pos(pos_lb);
272 for (auto &v : res) {
273 v *= m_conv.vel_to_md;
274 }
275 return res;
276 },
277 *impl->solver);
278}
279
280void Solver::add_forces_at_pos(std::vector<Utils::Vector3d> const &pos,
281 std::vector<Utils::Vector3d> const &forces) {
282 std::visit(
283 [&](auto &ptr) {
284 std::vector<Utils::Vector3d> pos_lb;
285 std::vector<Utils::Vector3d> force_lb;
286 pos_lb.reserve(pos.size());
287 force_lb.reserve(pos.size());
288 for (auto const &pos_md : pos) {
289 pos_lb.emplace_back(pos_md * m_conv.pos_to_lb);
290 }
291 for (auto const &force_md : forces) {
292 force_lb.emplace_back(force_md * m_conv.force_to_lb);
293 }
294 ptr->add_forces_at_pos(pos_lb, force_lb);
295 },
296 *impl->solver);
297}
298
300 Utils::Vector3d const &force_density) {
301 std::visit(
302 [&](auto &ptr) {
303 if (not ptr->add_force_at_pos(pos * m_conv.pos_to_lb,
304 force_density * m_conv.force_to_lb)) {
305 throw std::runtime_error("Cannot apply force to LB");
306 }
307 },
308 *impl->solver);
309}
310
312 check_solver(impl);
313 return std::visit([](auto const &ptr) { return ptr->get_momentum(); },
314 *impl->solver);
315}
316
317template <> void Solver::set<LBNone>(std::shared_ptr<LBNone> lb_instance) {
318 assert(impl);
319 assert(not impl->solver.has_value());
320 impl->solver = lb_instance;
321}
322
323#ifdef ESPRESSO_WALBERLA
324template <>
325void Solver::set<LBWalberla>(std::shared_ptr<LBWalberlaBase> lb_fluid,
326 std::shared_ptr<LBWalberlaParams> lb_params) {
327 assert(impl);
328 assert(not impl->solver.has_value());
329 auto const &system = get_system();
330 auto lb_instance = std::make_shared<LBWalberla>(lb_fluid, lb_params);
331 lb_instance->sanity_checks(system);
332 auto const &lebc = system.box_geo->lees_edwards_bc();
333 lb_fluid->check_lebc(lebc.shear_direction, lebc.shear_plane_normal);
334 impl->solver = lb_instance;
335 auto const agrid = lb_instance->get_agrid();
336 auto const tau = lb_instance->get_tau();
337 m_conv = Conversions{1. / agrid, agrid / tau, tau * tau / agrid};
338}
339#endif // ESPRESSO_WALBERLA
340
341} // namespace LB
LBWalberlaBase provides the public interface of the LB waLBerla bridge.
Vector implementation and trait types for boost qvm interoperability.
std::shared_ptr< BoxGeometry > box_geo
static auto is_solver_set(std::unique_ptr< Solver::Implementation > const &ptr)
Definition lb/Solver.cpp:55
static void check_solver(std::unique_ptr< Solver::Implementation > const &ptr)
Definition lb/Solver.cpp:59
System & get_system()
void veto_boxl_change() const
void lebc_sanity_checks(unsigned int shear_direction, unsigned int shear_plane_normal) const
Perform LB LEbc parameter checks.
std::vector< double > get_interpolated_densities(std::vector< Utils::Vector3d > const &pos) const
Calculate the interpolated fluid densities in LB units.
void add_force_density(Utils::Vector3d const &pos, Utils::Vector3d const &force_density)
Add a force density to the fluid at the given position.
std::function< bool(Utils::Vector3d const &)> make_lattice_position_checker(bool consider_points_in_halo) const
Make a functor to check if a position is in the local domain.
Utils::Vector3d get_coupling_interpolated_velocity(Utils::Vector3d const &pos) const
Calculate the interpolated fluid velocity in MD units.
void sanity_checks() const
Perform LB parameter and boundary velocity checks.
Definition lb/Solver.cpp:92
void on_timestep_change()
void on_boxl_change()
void ghost_communication()
Perform a full ghost communication.
Definition lb/Solver.cpp:77
void propagate()
Propagate the LB fluid.
Definition lb/Solver.cpp:72
void reset()
Remove the LB solver.
Definition lb/Solver.cpp:67
std::optional< Utils::Vector3d > get_interpolated_velocity(Utils::Vector3d const &pos) const
Calculate the interpolated fluid velocity in LB units.
bool is_solver_set() const
Return true if a LB solver is active.
Definition lb/Solver.cpp:65
void ghost_communication_pdf()
Perform a ghost communication of the PDF field.
Definition lb/Solver.cpp:82
double get_tau() const
Get the LB time step.
void on_temperature_change()
std::optional< double > get_interpolated_density(Utils::Vector3d const &pos) const
Calculate the interpolated fluid density in LB units.
void add_forces_at_pos(std::vector< Utils::Vector3d > const &pos, std::vector< Utils::Vector3d > const &forces)
void veto_kT(double kT) const
Check if a thermostat is compatible with the LB temperature.
double get_agrid() const
Get the LB grid spacing.
Utils::VectorXd< 9 > get_pressure_tensor() const
void update_collision_model()
void veto_time_step(double time_step) const
Check if a MD time step is compatible with the LB tau.
Definition lb/Solver.cpp:99
void ghost_communication_vel()
Perform a ghost communication of the velocity field.
Definition lb/Solver.cpp:87
void on_lees_edwards_change()
void on_node_grid_change()
Utils::Vector3d get_momentum() const
void on_cell_structure_change()
std::vector< Utils::Vector3d > get_coupling_interpolated_velocities(std::vector< Utils::Vector3d > const &pos) const
Calculate the interpolated fluid velocities in MD units.
bool is_gpu() const
double get_kT() const
Get the thermal energy parameter of the LB fluid.