ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
LBFluidNode.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2021-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#include <config/config.hpp>
21
22#ifdef ESPRESSO_WALBERLA
23
24#include "LBFluidNode.hpp"
25
27
28#include <utils/Vector.hpp>
29#include <utils/matrix.hpp>
31
32#include <boost/mpi/collectives/all_reduce.hpp>
33#include <boost/mpi/communicator.hpp>
34
35#include <optional>
36#include <stdexcept>
37#include <string>
38#include <vector>
39
41
42static bool is_boundary_all_reduce(boost::mpi::communicator const &comm,
43 std::optional<bool> const &is_boundary) {
44 return boost::mpi::all_reduce(comm, is_boundary ? *is_boundary : false,
45 std::logical_or<>());
46}
47
48Variant LBFluidNode::do_call_method(std::string const &name,
49 VariantMap const &params) {
50 if (not name.starts_with("get_")) {
52 [&]() { lb_throw_if_expired(m_mpi_cart_comm_observer); });
53 }
54 if (name == "set_velocity_at_boundary") {
55 if (is_none(params.at("value"))) {
56 m_lb_fluid->remove_node_from_boundary(m_index);
57 } else {
58 auto const u =
59 get_value<Utils::Vector3d>(params, "value") * m_conv_velocity;
60 m_lb_fluid->set_node_velocity_at_boundary(m_index, u);
61 }
62 m_lb_fluid->ghost_communication();
63 m_lb_fluid->reallocate_ubb_field();
64 return {};
65 }
66 if (name == "get_velocity_at_boundary") {
67 auto const boundary_opt = m_lb_fluid->get_node_is_boundary(m_index);
68 if (is_boundary_all_reduce(context()->get_comm(), boundary_opt)) {
69 auto const result = m_lb_fluid->get_node_velocity_at_boundary(m_index);
70 return Utils::Mpi::reduce_optional(context()->get_comm(), result) /
71 m_conv_velocity;
72 }
73 return Variant{None{}};
74 }
75 if (name == "get_density") {
76 auto const result = m_lb_fluid->get_node_density(m_index);
77 return Utils::Mpi::reduce_optional(context()->get_comm(), result) /
78 m_conv_dens;
79 }
80 if (name == "set_density") {
81 auto const dens = get_value<double>(params, "value");
82 m_lb_fluid->set_node_density(m_index, dens * m_conv_dens);
83 m_lb_fluid->ghost_communication();
84 return {};
85 }
86 if (name == "get_population") {
87 auto const result = m_lb_fluid->get_node_population(m_index);
88 return Utils::Mpi::reduce_optional(context()->get_comm(), result);
89 }
90 if (name == "set_population") {
91 auto const pop = get_value<std::vector<double>>(params, "value");
93 if (pop.size() != m_lb_fluid->stencil_size()) {
94 throw std::runtime_error("Population must have exactly " +
95 std::to_string(m_lb_fluid->stencil_size()) +
96 " elements");
97 }
98 });
99 m_lb_fluid->set_node_population(m_index, pop);
100 m_lb_fluid->ghost_communication();
101 return {};
102 }
103 if (name == "get_velocity") {
104 auto const result = m_lb_fluid->get_node_velocity(m_index);
105 return Utils::Mpi::reduce_optional(context()->get_comm(), result) /
106 m_conv_velocity;
107 }
108 if (name == "set_velocity") {
109 auto const u =
110 get_value<Utils::Vector3d>(params, "value") * m_conv_velocity;
111 m_lb_fluid->set_node_velocity(m_index, u);
112 m_lb_fluid->ghost_communication();
113 return {};
114 }
115 if (name == "get_is_boundary") {
116 auto const result = m_lb_fluid->get_node_is_boundary(m_index);
117 return Utils::Mpi::reduce_optional(context()->get_comm(), result);
118 }
119 if (name == "get_boundary_force") {
120 auto const boundary_opt = m_lb_fluid->get_node_is_boundary(m_index);
121 if (is_boundary_all_reduce(context()->get_comm(), boundary_opt)) {
122 auto result = m_lb_fluid->get_node_boundary_force(m_index);
123 return Utils::Mpi::reduce_optional(context()->get_comm(), result) /
124 m_conv_force;
125 }
126 return Variant{None{}};
127 }
128 if (name == "get_pressure_tensor" or name == "get_pressure_tensor_neq") {
129 auto const result = m_lb_fluid->get_node_pressure_tensor(m_index);
130 auto value = std::optional<std::vector<double>>{};
131 if (result) {
132 value = (*result / m_conv_press).as_vector();
133 }
134 auto vec = Utils::Mpi::reduce_optional(context()->get_comm(), value);
135 if (context()->is_head_node()) {
136 if (name == "get_pressure_tensor_neq") {
137 auto constexpr c_sound_sq = 1. / 3.;
138 auto const density = m_lb_fluid->get_density();
139 auto const diagonal_term = density * c_sound_sq / m_conv_press;
140 vec[0] -= diagonal_term;
141 vec[4] -= diagonal_term;
142 vec[8] -= diagonal_term;
143 }
145 std::ranges::copy(vec, tensor.m_data.begin());
146 return std::vector<Variant>{tensor.row<0>().as_vector(),
147 tensor.row<1>().as_vector(),
148 tensor.row<2>().as_vector()};
149 }
150 return {};
151 }
152 if (name == "get_last_applied_force") {
153 auto const result = m_lb_fluid->get_node_last_applied_force(m_index);
154 return Utils::Mpi::reduce_optional(context()->get_comm(), result) /
155 m_conv_force;
156 }
157 if (name == "set_last_applied_force") {
158 auto const f = get_value<Utils::Vector3d>(params, "value");
159 m_lb_fluid->set_node_last_applied_force(m_index, f * m_conv_force);
160 m_lb_fluid->ghost_communication();
161 return {};
162 }
163 if (name == "get_lattice_speed") {
164 return 1. / m_conv_velocity;
165 }
166
167 return {};
168}
169
170} // namespace ScriptInterface::walberla
171
172#endif // ESPRESSO_WALBERLA
Vector implementation and trait types for boost qvm interoperability.
virtual void parallel_try_catch(std::function< void()> const &cb) const =0
Type to indicate no value in Variant.
Definition None.hpp:31
Context * context() const
Responsible context.
std::string_view name() const
Variant do_call_method(std::string const &name, VariantMap const &params) override
Matrix implementation and trait types for boost qvm interoperability.
void lb_throw_if_expired(std::optional< ResourceObserver > const &mpi_obs)
Definition LBFluid.hpp:63
static bool is_boundary_all_reduce(boost::mpi::communicator const &comm, std::optional< bool > const &is_boundary)
constexpr bool is_none(Variant const &v)
Definition Variant.hpp:163
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
T reduce_optional(boost::mpi::communicator const &comm, std::optional< T > const &result)
Reduce an optional on the head node.
Recursive variant implementation.
Definition Variant.hpp:84
Matrix representation with static size.
Definition matrix.hpp:65