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 WALBERLA
35#endif
36
37#include <utils/Vector.hpp>
38
39#include <cassert>
40#include <cmath>
41#include <limits>
42#include <memory>
43#include <optional>
44#include <stdexcept>
45#include <string>
46#include <tuple>
47#include <variant>
48#include <vector>
49
50namespace LB {
51
52Solver::Solver() { impl = std::make_unique<Implementation>(); }
53
54static auto is_solver_set(std::unique_ptr<Solver::Implementation> const &ptr) {
55 return ptr != nullptr and ptr->solver.has_value();
56}
57
58static void check_solver(std::unique_ptr<Solver::Implementation> const &ptr) {
59 if (not is_solver_set(ptr)) {
60 throw NoLBActive{};
61 }
62}
63
64bool Solver::is_solver_set() const { return LB::is_solver_set(impl); }
65
67 System::get_system().lb.impl->solver = std::nullopt;
68 m_conv = Conversions{};
69}
70
72 check_solver(impl);
73 std::visit([](auto &ptr) { ptr->propagate(); }, *impl->solver);
74}
75
77 if (impl->solver) {
78 auto const &system = get_system();
79 std::visit([&](auto &ptr) { ptr->sanity_checks(system); }, *impl->solver);
80 }
81}
82
83void Solver::veto_time_step(double time_step) const {
84 if (impl->solver) {
85 std::visit([=](auto &ptr) { ptr->veto_time_step(time_step); },
86 *impl->solver);
87 }
88}
89
90void Solver::veto_kT(double kT) const {
91 if (impl->solver) {
92 std::visit([=](auto &ptr) { ptr->veto_kT(kT); }, *impl->solver);
93 }
94}
95
96void Solver::lebc_sanity_checks(unsigned int shear_direction,
97 unsigned int shear_plane_normal) const {
98 if (impl->solver) {
99 auto const callback = [=](auto &ptr) {
100 ptr->lebc_sanity_checks(shear_direction, shear_plane_normal);
101 };
102 std::visit(callback, *impl->solver);
103 }
104}
105
107 if (impl->solver) {
108 auto &solver = *impl->solver;
109 std::visit([](auto &ptr) { ptr->on_cell_structure_change(); }, solver);
110 }
111}
112
114 if (impl->solver) {
115 std::visit([](auto const &ptr) { ptr->veto_boxl_change(); }, *impl->solver);
116 }
117}
118
120 if (impl->solver) {
121 std::visit([](auto &ptr) { ptr->on_boxl_change(); }, *impl->solver);
122 }
123}
124
126 if (impl->solver) {
127 std::visit([](auto &ptr) { ptr->on_node_grid_change(); }, *impl->solver);
128 }
129}
130
132 if (impl->solver) {
133 std::visit([](auto &ptr) { ptr->on_timestep_change(); }, *impl->solver);
134 }
135}
136
138 if (impl->solver) {
139 std::visit([](auto &ptr) { ptr->on_temperature_change(); }, *impl->solver);
140 }
141}
142
143bool Solver::is_gpu() const {
144 check_solver(impl);
145 return std::visit([](auto &ptr) { return ptr->is_gpu(); }, *impl->solver);
146}
147
148double Solver::get_agrid() const {
149 check_solver(impl);
150 return std::visit([](auto &ptr) { return ptr->get_agrid(); }, *impl->solver);
151}
152
153double Solver::get_tau() const {
154 check_solver(impl);
155 return std::visit([](auto &ptr) { return ptr->get_tau(); }, *impl->solver);
156}
157
158double Solver::get_kT() const {
159 check_solver(impl);
160 return std::visit([](auto &ptr) { return ptr->get_kT(); }, *impl->solver);
161}
162
164 check_solver(impl);
165 return std::visit([](auto &ptr) { return ptr->get_pressure_tensor(); },
166 *impl->solver);
167}
168
169std::optional<Utils::Vector3d>
171 /* calculate fluid velocity at particle's position
172 this is done by linear interpolation
173 (Eq. (11) Ahlrichs and Duenweg, JCP 111(17):8225 (1999)) */
174 return std::visit(
175 [&](auto &ptr) {
176 auto const &box_geo = *System::get_system().box_geo;
177 auto const lb_pos = box_geo.folded_position(pos) * m_conv.pos_to_lb;
178 return ptr->get_velocity_at_pos(lb_pos, false);
179 },
180 *impl->solver);
181}
182
183std::optional<double>
185 return std::visit(
186 [&](auto &ptr) {
187 auto const &box_geo = *System::get_system().box_geo;
188 auto const lb_pos = box_geo.folded_position(pos) * m_conv.pos_to_lb;
189 return ptr->get_density_at_pos(lb_pos, false);
190 },
191 *impl->solver);
192}
193
196 return std::visit(
197 [&](auto &ptr) {
198 auto const res = ptr->get_velocity_at_pos(pos * m_conv.pos_to_lb, true);
199 assert(res);
200 return *res * m_conv.vel_to_md;
201 },
202 *impl->solver);
203}
204
206 std::vector<Utils::Vector3d> const &pos) const {
207 return std::visit(
208 [&](auto &ptr) {
209 std::vector<Utils::Vector3d> pos_lb;
210 pos_lb.reserve(pos.size());
211 for (auto const &pos_md : pos) {
212 pos_lb.emplace_back(pos_md * m_conv.pos_to_lb);
213 }
214 auto res = ptr->get_velocities_at_pos(pos_lb);
215 for (auto &v : res) {
216 v *= m_conv.vel_to_md;
217 }
218 return res;
219 },
220 *impl->solver);
221}
222
223void Solver::add_forces_at_pos(std::vector<Utils::Vector3d> const &pos,
224 std::vector<Utils::Vector3d> const &forces) {
225 std::visit(
226 [&](auto &ptr) {
227 std::vector<Utils::Vector3d> pos_lb;
228 std::vector<Utils::Vector3d> force_lb;
229 pos_lb.reserve(pos.size());
230 force_lb.reserve(pos.size());
231 for (auto const &pos_md : pos) {
232 pos_lb.emplace_back(pos_md * m_conv.pos_to_lb);
233 }
234 for (auto const &force_md : forces) {
235 force_lb.emplace_back(force_md * m_conv.force_to_lb);
236 }
237 ptr->add_forces_at_pos(pos_lb, force_lb);
238 },
239 *impl->solver);
240}
241
243 Utils::Vector3d const &force_density) {
244 std::visit(
245 [&](auto &ptr) {
246 if (not ptr->add_force_at_pos(pos * m_conv.pos_to_lb,
247 force_density * m_conv.force_to_lb)) {
248 throw std::runtime_error("Cannot apply force to LB");
249 }
250 },
251 *impl->solver);
252}
253
255 check_solver(impl);
256 return std::visit([](auto const &ptr) { return ptr->get_momentum(); },
257 *impl->solver);
258}
259
260template <> void Solver::set<LBNone>(std::shared_ptr<LBNone> lb_instance) {
261 assert(impl);
262 assert(not impl->solver.has_value());
263 impl->solver = lb_instance;
264}
265
266#ifdef WALBERLA
267template <>
268void Solver::set<LBWalberla>(std::shared_ptr<LBWalberlaBase> lb_fluid,
269 std::shared_ptr<LBWalberlaParams> lb_params) {
270 assert(impl);
271 assert(not impl->solver.has_value());
272 auto const &system = get_system();
273 auto lb_instance = std::make_shared<LBWalberla>(lb_fluid, lb_params);
274 lb_instance->sanity_checks(system);
275 auto const &lebc = system.box_geo->lees_edwards_bc();
276 lb_fluid->check_lebc(lebc.shear_direction, lebc.shear_plane_normal);
277 impl->solver = lb_instance;
278 auto const agrid = lb_instance->get_agrid();
279 auto const tau = lb_instance->get_tau();
280 m_conv = Conversions{1. / agrid, agrid / tau, tau * tau / agrid};
281}
282#endif // WALBERLA
283
284} // namespace LB
LBWalberlaBase provides the public interface of the LB waLBerla bridge.
Vector implementation and trait types for boost qvm interoperability.
__shared__ int pos[MAXDEPTH *THREADS5/WARPSIZE]
__shared__ float res[]
std::shared_ptr< BoxGeometry > box_geo
This file contains the defaults for ESPResSo.
static auto is_solver_set(std::unique_ptr< Solver::Implementation > const &ptr)
Definition lb/Solver.cpp:54
static void check_solver(std::unique_ptr< Solver::Implementation > const &ptr)
Definition lb/Solver.cpp:58
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.
Definition lb/Solver.cpp:96
void add_force_density(Utils::Vector3d const &pos, Utils::Vector3d const &force_density)
Add a force density to the fluid at the given position.
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:76
void on_timestep_change()
void on_boxl_change()
void propagate()
Propagate the LB fluid.
Definition lb/Solver.cpp:71
void reset()
Remove the LB solver.
Definition lb/Solver.cpp:66
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:64
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.
Definition lb/Solver.cpp:90
double get_agrid() const
Get the LB grid spacing.
Utils::VectorXd< 9 > get_pressure_tensor() const
void veto_time_step(double time_step) const
Check if a MD time step is compatible with the LB tau.
Definition lb/Solver.cpp:83
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
bool is_gpu() const
double get_kT() const
Get the thermal energy parameter of the LB fluid.