Branch data Line data Source code
1 : : //
2 : : // Class ParameterList
3 : : // Ippl related parameters (e.g. tolerance in case of iterative solvers).
4 : : // Example:
5 : : // ippl::ParameterList params;
6 : : // params.add<double>("tolerance", 1.0e-8);
7 : : // params.get<double>("tolerance");
8 : : //
9 : : //
10 : : #ifndef IPPL_PARAMETER_LIST_H
11 : : #define IPPL_PARAMETER_LIST_H
12 : :
13 : : #include <iomanip>
14 : : #include <iostream>
15 : : #include <map>
16 : : #include <string>
17 : : #include <utility>
18 : :
19 : : #include "Types/Variant.h"
20 : :
21 : : #include "Utility/IpplException.h"
22 : :
23 : : namespace ippl {
24 : :
25 : : /*!
26 : : * @file ParameterList.h
27 : : * @class ParameterList
28 : : */
29 : : class ParameterList {
30 : : public:
31 : : // allowed parameter types
32 : : using variant_t =
33 : : std::variant<double, float, bool, std::string, unsigned int, int, ParameterList>;
34 : :
35 : 14 : ParameterList() = default;
36 : 0 : ParameterList(const ParameterList&) = default;
37 : :
38 : : /*!
39 : : * Add a single parameter to this list.
40 : : * @param key is the name of the parameter
41 : : * @param value is the parameter value
42 : : */
43 : : template <typename T>
44 : 23 : void add(const std::string& key, const T& value) {
45 [ + + ]: 23 : if (params_m.contains(key)) {
46 [ + - + - ]: 2 : throw IpplException("ParameterList::add()",
47 [ + - + - ]: 2 : "Parameter '" + key + "' already exists.");
48 : : }
49 : 22 : params_m[key] = value;
50 : 22 : }
51 : :
52 : : /*!
53 : : * Obtain the value of a parameter. This function
54 : : * throws an error if the key is not contained.
55 : : * @param key the name of the parameter
56 : : * @returns the value of a parameter
57 : : */
58 : : template <typename T>
59 : 29 : T get(const std::string& key) const {
60 [ + + ]: 29 : if (!params_m.contains(key)) {
61 [ + - + - ]: 2 : throw IpplException("ParameterList::get()",
62 [ + - + - ]: 2 : "Parameter '" + key + "' not contained.");
63 : : }
64 : 28 : return std::get<T>(params_m.at(key));
65 : : }
66 : :
67 : : /*!
68 : : * Obtain the value of a parameter. If the key is
69 : : * not contained, the default value is returned.
70 : : * @param key the name of the parameter
71 : : * @param defval the default value of the parameter
72 : : * @returns the value of a parameter
73 : : */
74 : : template <typename T>
75 : : T get(const std::string& key, const T& defval) const {
76 : : if (!params_m.contains(key)) {
77 : : return defval;
78 : : }
79 : : return std::get<T>(params_m.at(key));
80 : : }
81 : :
82 : : /*!
83 : : * Merge a parameter list into this parameter list.
84 : : * @param p the parameter list to merge into this
85 : : */
86 : 1 : void merge(const ParameterList& p) noexcept {
87 [ + + ]: 3 : for (const auto& [key, value] : p.params_m) {
88 : 2 : params_m[key] = value;
89 : : }
90 : 1 : }
91 : :
92 : : /*!
93 : : * Update the parameter values of this list with the
94 : : * values provided in the input parameter list.
95 : : * @param p the input parameter list with update parameter values
96 : : */
97 : 1 : void update(const ParameterList& p) noexcept {
98 [ + + ]: 3 : for (const auto& [key, value] : p.params_m) {
99 [ + + ]: 2 : if (params_m.contains(key)) {
100 : 1 : params_m[key] = value;
101 : : }
102 : : }
103 : 1 : }
104 : :
105 : : /*!
106 : : * Update the single parameter value of this list.
107 : : * @param key is the name of the parameter
108 : : * @param value is the parameter value
109 : : */
110 : : template <typename T>
111 : 2 : void update(const std::string& key, const T& value) {
112 [ + + ]: 2 : if (!params_m.contains(key)) {
113 [ + - + - ]: 2 : throw IpplException("ParameterList::update()",
114 [ + - + - ]: 2 : "Parameter '" + key + "' does not exist.");
115 : : }
116 : 1 : params_m[key] = value;
117 : 1 : }
118 : :
119 : : template <class Stream>
120 : : friend Stream& operator<<(Stream& stream, const ParameterList& sp) {
121 : : std::cout << "HI" << std::endl;
122 : : for (const auto& [key, value] : sp.params_m) {
123 : : const auto& keyLocal = key;
124 : : std::visit(
125 : : [&](auto&& arg) {
126 : : stream << std::make_pair(keyLocal, arg);
127 : : },
128 : : value);
129 : : }
130 : :
131 : : return stream;
132 : : }
133 : :
134 : : /*!
135 : : * Print this parameter list.
136 : : */
137 : : friend std::ostream& operator<<(std::ostream& os, const ParameterList& sp) {
138 : : static int indent = -4;
139 : :
140 : : indent += 4;
141 : : if (indent > 0) {
142 : : os << '\n';
143 : : }
144 : : for (const auto& [key, value] : sp.params_m) {
145 : : const auto& keyLocal = key;
146 : : std::visit(
147 : : [&](auto&& arg) {
148 : : // 21 March 2021
149 : : // https://stackoverflow.com/questions/15884284/c-printing-spaces-or-tabs-given-a-user-input-integer
150 : : os << std::string(indent, ' ') << std::left << std::setw(20) << keyLocal
151 : : << " " << arg;
152 : : },
153 : : value);
154 : : // 21 March 2021
155 : : // https://stackoverflow.com/questions/289715/last-key-in-a-stdmap
156 : : if (key != std::prev(sp.params_m.end())->first) {
157 : : os << '\n';
158 : : }
159 : : }
160 : : indent -= 4;
161 : :
162 : : return os;
163 : : }
164 : 0 : ParameterList& operator=(const ParameterList& other) {
165 [ # # ]: 0 : if (this != &other) {
166 : : // Copy members from 'other' to 'this'
167 : 0 : params_m = other.params_m;
168 : : }
169 : 0 : return *this;
170 : : }
171 : :
172 : : protected:
173 : : std::map<std::string, variant_t> params_m;
174 : : };
175 : : } // namespace ippl
176 : :
177 : : #endif
|