ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
script_interface/reaction_methods/ReactionAlgorithm.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 "ReactionAlgorithm.hpp"
21
23
24#include "SingleReaction.hpp"
25
26#include "config/config.hpp"
27
35
36#include <utils/contains.hpp>
37
38#include <boost/serialization/serialization.hpp>
39
40#include <memory>
41#include <stdexcept>
42#include <string>
43#include <tuple>
44#include <unordered_map>
45#include <vector>
46
47namespace ScriptInterface {
48namespace ReactionMethods {
49
52 {{"reactions", AutoParameter::read_only,
53 [this]() {
54 std::vector<Variant> out;
55 for (auto const &e : m_reactions) {
56 out.emplace_back(e);
57 }
58 return out;
59 }},
60 {"kT", AutoParameter::read_only, [this]() { return RE()->get_kT(); }},
61 {"search_algorithm",
62 [this](Variant const &v) {
64 auto const key = get_value<std::string>(v);
65 if (key == "order_n") {
66 RE()->neighbor_search_order_n = true;
67 } else if (key == "parallel") {
68 RE()->neighbor_search_order_n = false;
69 } else {
70 throw std::invalid_argument("Unknown search algorithm '" + key +
71 "'");
72 }
73 });
74 },
75 [this]() {
76 if (RE()->neighbor_search_order_n) {
77 return std::string("order_n");
78 }
79 return std::string("parallel");
80 }},
81 {"particle_inside_exclusion_range_touched",
82 [this](Variant const &v) {
83 RE()->particle_inside_exclusion_range_touched = get_value<bool>(v);
84 },
85 [this]() { return RE()->particle_inside_exclusion_range_touched; }},
86 {"default_charges", AutoParameter::read_only,
87 [this]() {
88 return make_unordered_map_of_variants(RE()->charges_of_types);
89 }},
90 {"exclusion_range", AutoParameter::read_only,
91 [this]() { return RE()->get_exclusion_range(); }},
92 {"exclusion_radius_per_type",
93 [this](Variant const &v) {
95 RE()->set_exclusion_radius_per_type(
96 get_value<std::unordered_map<int, double>>(v));
97 });
98 },
99 [this]() {
101 RE()->exclusion_radius_per_type);
102 }}});
103}
104
106 VariantMap const &params) {
107 if (name == "calculate_factorial_expression") {
108 if (context()->is_head_node()) {
109 auto &bookkeeping = RE()->get_old_system_state();
110 auto &old_particle_numbers = bookkeeping.old_particle_numbers;
111 auto &reaction = *m_reactions[bookkeeping.reaction_id]->get_reaction();
112 return calculate_factorial_expression(reaction, old_particle_numbers);
113 }
114 return {};
115 }
116 if (name == "get_random_reaction_index") {
117 return RE()->i_random(static_cast<int>(RE()->reactions.size()));
118 }
119 if (name == "potential_energy") {
120 return RE()->calculate_potential_energy();
121 }
122 if (name == "create_new_trial_state") {
123 auto const reaction_id = get_value<int>(params, "reaction_id");
124 Variant result{};
125 context()->parallel_try_catch([&]() {
126 auto const optional = RE()->create_new_trial_state(reaction_id);
127 if (optional) {
128 result = *optional;
129 }
130 });
131 return result;
132 }
133 if (name == "make_reaction_mc_move_attempt") {
134 auto const bf = get_value<double>(params, "bf");
135 auto const E_pot_old = get_value<double>(params, "E_pot_old");
136 auto const E_pot_new = get_value<double>(params, "E_pot_new");
137 auto const reaction_id = get_value<int>(params, "reaction_id");
138 Variant result;
139 context()->parallel_try_catch([&]() {
140 result = RE()->make_reaction_mc_move_attempt(reaction_id, bf, E_pot_old,
141 E_pot_new);
142 });
143 return result;
144 }
145 if (name == "setup_bookkeeping_of_empty_pids") {
146 RE()->setup_bookkeeping_of_empty_pids();
147 } else if (name == "remove_constraint") {
148 RE()->remove_constraint();
149 } else if (name == "set_cylindrical_constraint_in_z_direction") {
150 context()->parallel_try_catch([&]() {
151 RE()->set_cyl_constraint(get_value<double>(params, "center_x"),
152 get_value<double>(params, "center_y"),
153 get_value<double>(params, "radius"));
154 });
155 } else if (name == "set_wall_constraints_in_z_direction") {
156 context()->parallel_try_catch([&]() {
157 RE()->set_slab_constraint(get_value<double>(params, "slab_start_z"),
158 get_value<double>(params, "slab_end_z"));
159 });
160 } else if (name == "get_wall_constraints_in_z_direction") {
161 if (context()->is_head_node()) {
162 return RE()->get_slab_constraint_parameters();
163 }
164 return {};
165 } else if (name == "set_volume") {
167 [&]() { RE()->set_volume(get_value<double>(params, "volume")); });
168 } else if (name == "get_volume") {
169 return RE()->get_volume();
170 } else if (name == "get_acceptance_rate_reaction") {
171 auto const index = get_value<int>(params, "reaction_id");
172 context()->parallel_try_catch([&]() {
173 if (index < 0 or index >= static_cast<int>(m_reactions.size())) {
174 throw std::out_of_range("No reaction with id " + std::to_string(index));
175 }
176 });
177 return m_reactions[index]->get_reaction()->get_acceptance_rate();
178 } else if (name == "set_non_interacting_type") {
179 auto const type = get_value<int>(params, "type");
180 context()->parallel_try_catch([&]() {
181 if (type < 0) {
182 throw std::domain_error("Invalid type: " + std::to_string(type));
183 }
184 });
185 RE()->non_interacting_type = type;
186 ::init_type_map(type);
187 } else if (name == "get_non_interacting_type") {
188 return RE()->non_interacting_type;
189 } else if (name == "displacement_mc_move_for_particles_of_type") {
190 auto const type = get_value<int>(params, "type_mc");
191 auto const n_particles =
192 get_value_or<int>(params, "particle_number_to_be_changed", 1);
193 auto result = false;
194 context()->parallel_try_catch([&]() {
195 result = RE()->make_displacement_mc_move_attempt(type, n_particles);
196 });
197 return result;
198 } else if (name == "delete_particle") {
200 [&]() { RE()->delete_particle(get_value<int>(params, "p_id")); });
201 } else if (name == "delete_reaction") {
202 auto const reaction_id = get_value<int>(params, "reaction_id");
203 auto const index = get_reaction_index(reaction_id);
204 // delete forward and backward reactions
205 delete_reaction(index + 1);
206 delete_reaction(index + 0);
207 } else if (name == "add_reaction") {
208 auto const reaction =
209 get_value<std::shared_ptr<SingleReaction>>(params, "reaction");
210 m_reactions.push_back(reaction);
211 RE()->add_reaction(reaction->get_reaction());
212 } else if (name == "change_reaction_constant") {
213 auto const gamma = get_value<double>(params, "gamma");
214 auto const reaction_id = get_value<int>(params, "reaction_id");
215 context()->parallel_try_catch([&]() {
216 if (reaction_id % 2 == 1) {
217 throw std::invalid_argument("Only forward reactions can be selected");
218 }
219 if (gamma <= 0.) {
220 throw std::domain_error("gamma needs to be a strictly positive value");
221 }
222 });
223 auto const index = get_reaction_index(reaction_id);
224 m_reactions[index + 0]->get_reaction()->gamma = gamma;
225 m_reactions[index + 1]->get_reaction()->gamma = 1. / gamma;
226 } else if (name == "set_charge_of_type") {
227 auto const type = get_value<int>(params, "type");
228 auto const charge = get_value<double>(params, "charge");
229 RE()->charges_of_types[type] = charge;
230 } else if (context()->is_head_node()) {
231 throw std::runtime_error("unknown method '" + name + "()'");
232 }
233 return {};
234}
235
236} /* namespace ReactionMethods */
237} /* namespace ScriptInterface */
void add_parameters(std::vector< AutoParameter > &&params)
virtual void parallel_try_catch(std::function< void()> const &cb) const =0
virtual bool is_head_node() const =0
boost::string_ref name() const
Context * context() const
Responsible context.
Variant do_call_method(std::string const &name, VariantMap const &params) override
virtual double calculate_factorial_expression(::ReactionMethods::SingleReaction const &reaction, std::unordered_map< int, int > const &particle_numbers) const
virtual std::shared_ptr<::ReactionMethods::ReactionAlgorithm > RE()=0
int get_reaction_index(int reaction_id) const
Check reaction id is within the reaction container bounds.
std::vector< std::shared_ptr< SingleReaction > > m_reactions
Keep track of the script interface pointer of each reaction.
This file contains the defaults for ESPResSo.
This file contains the asynchronous MPI communication.
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:69
auto make_unordered_map_of_variants(std::unordered_map< K, V > const &v)
Definition Variant.hpp:80
boost::make_recursive_variant< None, bool, int, std::size_t, double, std::string, ObjectRef, Utils::Vector3b, Utils::Vector3i, Utils::Vector2d, Utils::Vector3d, Utils::Vector4d, std::vector< int >, std::vector< double >, std::vector< boost::recursive_variant_ >, std::unordered_map< int, boost::recursive_variant_ >, std::unordered_map< std::string, boost::recursive_variant_ > >::type Variant
Possible types for parameters.
Definition Variant.hpp:67
void init_type_map(int type)
Particles creation and deletion.
static SteepestDescentParameters params
Currently active steepest descent instance.
static constexpr const ReadOnly read_only