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-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#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 <string>
37#include <vector>
38
40
41static bool is_boundary_all_reduce(boost::mpi::communicator const &comm,
42 std::optional<bool> const &is_boundary) {
43 return boost::mpi::all_reduce(comm, is_boundary ? *is_boundary : false,
44 std::logical_or<>());
45}
46
47Variant LBFluidNode::do_call_method(std::string const &name,
48 VariantMap const &params) {
49 if (not name.starts_with("get_")) {
51 [&]() { lb_throw_if_expired(m_mpi_cart_comm_observer); });
52 }
53 if (name == "set_velocity_at_boundary") {
54 if (is_none(params.at("value"))) {
55 m_lb_fluid->remove_node_from_boundary(m_index);
56 } else {
57 auto const u =
58 get_value<Utils::Vector3d>(params, "value") * m_conv_velocity;
59 m_lb_fluid->set_node_velocity_at_boundary(m_index, u);
60 }
61 m_lb_fluid->ghost_communication();
62 m_lb_fluid->reallocate_ubb_field();
63 return {};
64 }
65 if (name == "get_velocity_at_boundary") {
66 auto const boundary_opt = m_lb_fluid->get_node_is_boundary(m_index);
67 if (is_boundary_all_reduce(context()->get_comm(), boundary_opt)) {
68 auto const result = m_lb_fluid->get_node_velocity_at_boundary(m_index);
69 return Utils::Mpi::reduce_optional(context()->get_comm(), result) /
70 m_conv_velocity;
71 }
72 return Variant{None{}};
73 }
74 if (name == "get_density") {
75 auto const result = m_lb_fluid->get_node_density(m_index);
76 return Utils::Mpi::reduce_optional(context()->get_comm(), result) /
77 m_conv_dens;
78 }
79 if (name == "set_density") {
80 auto const dens = get_value<double>(params, "value");
81 m_lb_fluid->set_node_density(m_index, dens * m_conv_dens);
82 m_lb_fluid->ghost_communication();
83 return {};
84 }
85 if (name == "get_population") {
86 auto const result = m_lb_fluid->get_node_population(m_index);
87 return Utils::Mpi::reduce_optional(context()->get_comm(), result);
88 }
89 if (name == "set_population") {
90 auto const pop = get_value<std::vector<double>>(params, "value");
91 m_lb_fluid->set_node_population(m_index, pop);
92 m_lb_fluid->ghost_communication();
93 return {};
94 }
95 if (name == "get_velocity") {
96 auto const result = m_lb_fluid->get_node_velocity(m_index);
97 return Utils::Mpi::reduce_optional(context()->get_comm(), result) /
98 m_conv_velocity;
99 }
100 if (name == "set_velocity") {
101 auto const u =
102 get_value<Utils::Vector3d>(params, "value") * m_conv_velocity;
103 m_lb_fluid->set_node_velocity(m_index, u);
104 m_lb_fluid->ghost_communication();
105 return {};
106 }
107 if (name == "get_is_boundary") {
108 auto const result = m_lb_fluid->get_node_is_boundary(m_index);
109 return Utils::Mpi::reduce_optional(context()->get_comm(), result);
110 }
111 if (name == "get_boundary_force") {
112 auto const boundary_opt = m_lb_fluid->get_node_is_boundary(m_index);
113 if (is_boundary_all_reduce(context()->get_comm(), boundary_opt)) {
114 auto result = m_lb_fluid->get_node_boundary_force(m_index);
115 return Utils::Mpi::reduce_optional(context()->get_comm(), result) /
116 m_conv_force;
117 }
118 return Variant{None{}};
119 }
120 if (name == "get_pressure_tensor" or name == "get_pressure_tensor_neq") {
121 auto const result = m_lb_fluid->get_node_pressure_tensor(m_index);
122 auto value = std::optional<std::vector<double>>{};
123 if (result) {
124 value = (*result / m_conv_press).as_vector();
125 }
126 auto vec = Utils::Mpi::reduce_optional(context()->get_comm(), value);
127 if (context()->is_head_node()) {
128 if (name == "get_pressure_tensor_neq") {
129 auto constexpr c_sound_sq = 1. / 3.;
130 auto const density = m_lb_fluid->get_density();
131 auto const diagonal_term = density * c_sound_sq / m_conv_press;
132 vec[0] -= diagonal_term;
133 vec[4] -= diagonal_term;
134 vec[8] -= diagonal_term;
135 }
137 std::ranges::copy(vec, tensor.m_data.begin());
138 return std::vector<Variant>{tensor.row<0>().as_vector(),
139 tensor.row<1>().as_vector(),
140 tensor.row<2>().as_vector()};
141 }
142 return {};
143 }
144 if (name == "get_last_applied_force") {
145 auto const result = m_lb_fluid->get_node_last_applied_force(m_index);
146 return Utils::Mpi::reduce_optional(context()->get_comm(), result) /
147 m_conv_force;
148 }
149 if (name == "set_last_applied_force") {
150 auto const f = get_value<Utils::Vector3d>(params, "value");
151 m_lb_fluid->set_node_last_applied_force(m_index, f * m_conv_force);
152 m_lb_fluid->ghost_communication();
153 return {};
154 }
155 if (name == "get_lattice_speed") {
156 return 1. / m_conv_velocity;
157 }
158
159 return {};
160}
161
162} // namespace ScriptInterface::walberla
163
164#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:32
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