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
|