ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
EKSpeciesNode.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 "EKSpeciesNode.hpp"
25#include "errorhandling.hpp"
26
27#include "LatticeIndices.hpp"
28
30
31#include <utils/Vector.hpp>
33
34#include <boost/mpi/collectives/all_reduce.hpp>
35#include <boost/serialization/vector.hpp>
36
37#include <cassert>
38#include <memory>
39#include <optional>
40#include <stdexcept>
41#include <string>
42
44
45static bool is_boundary_all_reduce(boost::mpi::communicator const &comm,
46 std::optional<bool> const &is_boundary) {
47 return boost::mpi::all_reduce(comm, is_boundary ? *is_boundary : false,
48 std::logical_or<>());
49}
50
51Variant EKSpeciesNode::do_call_method(std::string const &name,
52 VariantMap const &params) {
53 if (name == "override_index") {
54 // this hidden feature is used to iterate an EK slice without
55 // rebuilding a EKSpeciesNode for each node in the slice
56 auto const index = get_value<Utils::Vector3i>(params, "index");
57 if (not is_index_valid(index, m_grid_size)) {
58 return 1;
59 }
60 m_index = index;
61 return 0;
62 }
63 if (name == "set_density") {
64 auto const dens = get_value<double>(params, "value");
65 m_ek_species->set_node_density(m_index, dens * m_conv_dens);
66 m_ek_species->ghost_communication();
67 return {};
68 }
69 if (name == "get_density") {
70 auto const result = m_ek_species->get_node_density(m_index);
71 return Utils::Mpi::reduce_optional(context()->get_comm(), result) /
72 m_conv_dens;
73 }
74 if (name == "get_flux_vector") {
75 auto const result = m_ek_species->get_node_flux_vector(m_index);
76 return Utils::Mpi::reduce_optional(context()->get_comm(), result) /
77 m_conv_flux;
78 }
79 if (name == "get_is_boundary") {
80 auto const result = m_ek_species->get_node_is_boundary(m_index);
81 return Utils::Mpi::reduce_optional(context()->get_comm(), result);
82 }
83 if (name == "get_node_density_at_boundary") {
84 auto const boundary_opt =
85 m_ek_species->get_node_is_density_boundary(m_index);
86 if (is_boundary_all_reduce(context()->get_comm(), boundary_opt)) {
87 auto const result = m_ek_species->get_node_density_at_boundary(m_index);
88 return Utils::Mpi::reduce_optional(context()->get_comm(), result) /
89 m_conv_dens;
90 }
91 return Variant{None{}};
92 }
93 if (name == "set_node_density_at_boundary") {
94 if (is_none(params.at("value"))) {
95 m_ek_species->remove_node_from_density_boundary(m_index);
96 } else {
97 auto const dens = get_value<double>(params, "value") * m_conv_dens;
98 m_ek_species->set_node_density_boundary(m_index, dens);
99 }
100 return {};
101 }
102 if (name == "get_node_flux_at_boundary") {
103 auto const boundary_opt = m_ek_species->get_node_is_flux_boundary(m_index);
104 if (is_boundary_all_reduce(context()->get_comm(), boundary_opt)) {
105 auto const result = m_ek_species->get_node_flux_at_boundary(m_index);
106 return Utils::Mpi::reduce_optional(context()->get_comm(), result) /
107 m_conv_flux;
108 }
109 return Variant{None{}};
110 }
111 if (name == "set_node_flux_at_boundary") {
112 if (is_none(params.at("value"))) {
113 m_ek_species->remove_node_from_flux_boundary(m_index);
114 } else {
115 context()->parallel_try_catch([&]() {
116 if (get_lattice().get_ghost_layers() < 2) {
117 if (context()->get_comm().size() > 1) {
118 throw std::runtime_error("The number of ghostlayers should be > 1 "
119 "when using flux boundaries and mpi.");
120 }
121 runtimeWarningMsg() << "The number of ghostlayers should be > 1 when "
122 "using flux boundaries and mpi.";
123 }
124 });
125 auto const flux =
126 get_value<Utils::Vector3d>(params, "value") * m_conv_flux;
127 m_ek_species->set_node_flux_boundary(m_index, flux);
128 }
129 return {};
130 }
131
132 return {};
133}
134
135} // namespace ScriptInterface::walberla
136
137#endif // ESPRESSO_WALBERLA
Vector implementation and trait types for boost qvm interoperability.
virtual void parallel_try_catch(std::function< void()> const &cb) const =0
bool is_index_valid(Utils::Vector3i const &index, Utils::Vector3i const &shape) const
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
::LatticeWalberla const & get_lattice() const
This file contains the errorhandling code for severe errors, like a broken bond or illegal parameter ...
#define runtimeWarningMsg()
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.
static SteepestDescentParameters params
Currently active steepest descent instance.
Recursive variant implementation.
Definition Variant.hpp:84