Loading [MathJax]/extensions/TeX/AMSmath.js
ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages Concepts
AutoParameters.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2022 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#pragma once
21
25
26#include <algorithm>
27#include <span>
28#include <stdexcept>
29#include <string>
30#include <type_traits>
31#include <unordered_map>
32#include <utility>
33#include <vector>
34
35namespace ScriptInterface {
36
37/**
38 * @brief Bind parameters in the script interface.
39 *
40 * This class implements @c ScriptInterfaceBase, binding
41 * the parameters added by add_parameters or by the constructor.
42 * To use it, derive from this class and add parameters. For example,
43 * given a class A
44 * ~~~{.cpp}
45 * class A {
46 * public:
47 * int i() { return m_i; }
48 * private:
49 * int m_i;
50 * };
51 * ~~~
52 * that should have @c i exposed, this can be achieved by extending it
53 * like this:
54 * ~~~{.cpp}
55 * class A : public AutoParameters {
56 * public:
57 * A() : AutoParameters({"name_for_i", i}) {}
58 * int i() { return m_i; }
59 * private:
60 * int m_i;
61 * };
62 * ~~~
63 *
64 * If there is more complicated logic needed, specific setters and
65 * getters can be provided. E.g. given a class B like
66 * ~~~{.cpp}
67 * class B {
68 * public:
69 * void set_i(int);
70 * int get_i();
71 * private:
72 * int m_i;
73 * };
74 * ~~~
75 * we can use a lambdas to set and get the parameter like this:
76 * ~~~{.cpp}
77 * class B : public AutoParameters {
78 * public:
79 * B() : AutoParameters({"name_for_i",
80 * [this](Variant const& v) {set_i(get_value<int>(v));},
81 * [this]() {return get_i();}
82 * }) {}
83 * void set_i(int);
84 * int get_i();
85 * private:
86 * int m_i;
87 * };
88 * ~~~
89 * (this has to be captured in the lambdas to have access to the member
90 * functions of the class).
91 */
92template <typename Derived, typename Base = ObjectHandle>
93class AutoParameters : public Base {
94 static_assert(std::is_base_of_v<ObjectHandle, Base>);
95
96public:
97 /** @brief Exception thrown when accessing an unknown parameter */
98 struct UnknownParameter : public Exception {
99 explicit UnknownParameter(std::string const &name)
100 : Exception("Unknown parameter '" + name + "'.") {}
101 };
102
103 /** @brief Exception thrown when writing to a read-only parameter */
104 struct WriteError : public Exception {
105 explicit WriteError(std::string const &name)
106 : Exception("Parameter '" + name + "' is read-only.") {}
107 };
108
109protected:
110 // NOLINTNEXTLINE(bugprone-crtp-constructor-accessibility)
111 AutoParameters() = default;
112 // NOLINTNEXTLINE(bugprone-crtp-constructor-accessibility)
113 explicit AutoParameters(std::vector<AutoParameter> &&params) {
114 add_parameters(std::move(params));
115 }
116 ~AutoParameters() override = default;
117
118 void add_parameters(std::vector<AutoParameter> &&params) {
119 for (auto const &p : params) {
120 if (m_parameters.count(p.name)) {
121 m_parameters.erase(p.name);
122 if (auto const it = std::ranges::find(m_key_order, p.name);
123 it != m_key_order.end()) {
124 m_key_order.erase(it);
125 }
126 }
127 m_key_order.emplace_back(p.name);
128 m_parameters.emplace(p.name, std::move(p));
129 }
130 }
131
132 auto const &get_parameter_insertion_order() const { return m_key_order; }
133
134public:
135 /* ObjectHandle implementation */
136 std::span<const boost::string_ref> valid_parameters() const final {
137 static std::vector<boost::string_ref> valid_params;
138 valid_params.clear();
139
140 for (auto const &p : m_parameters) {
141 valid_params.emplace_back(p.first);
142 }
143
144 return valid_params;
145 }
146
147 Variant get_parameter(const std::string &name) const final {
148 try {
149 return m_parameters.at(name).get();
150 } catch (std::out_of_range const &) {
151 throw UnknownParameter{name};
152 }
153 }
154
155 void do_set_parameter(const std::string &name, const Variant &value) final {
156 try {
157 m_parameters.at(name).set(value);
158 } catch (AutoParameter::WriteError const &) {
159 throw WriteError{name};
160 } catch (std::out_of_range const &) {
161 throw UnknownParameter{name};
162 }
163 }
164
165 std::vector<std::pair<std::string, Variant>>
167 std::vector<std::pair<std::string, Variant>> parameter_pack{};
168 auto const params = this->get_parameters();
169 for (auto const &key : m_key_order) {
170 parameter_pack.emplace_back(key, params.at(key));
171 }
172 return parameter_pack;
173 }
174
175private:
176 /** @brief Data structure for the stored parameters. */
177 std::unordered_map<std::string, AutoParameter> m_parameters;
178 /** @brief Keep track of the insertion order of parameters. */
179 std::vector<std::string> m_key_order;
180};
181} // namespace ScriptInterface
Bind parameters in the script interface.
AutoParameters(std::vector< AutoParameter > &&params)
void do_set_parameter(const std::string &name, const Variant &value) final
std::span< const boost::string_ref > valid_parameters() const final
~AutoParameters() override=default
Variant get_parameter(const std::string &name) const final
std::vector< std::pair< std::string, Variant > > serialize_parameters() const final
void add_parameters(std::vector< AutoParameter > &&params)
auto const & get_parameter_insertion_order() const
VariantMap get_parameters() const
Get current parameters.
boost::string_ref name() const
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
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
static SteepestDescentParameters params
Currently active steepest descent instance.
Exception thrown when accessing an unknown parameter.
Exception thrown when writing to a read-only parameter.