Line | Branch | Exec | Source |
---|---|---|---|
1 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- | ||
2 | // vi: set et ts=4 sw=4 sts=4: | ||
3 | // | ||
4 | // SPDX-FileCopyrightInfo: Copyright © DuMux Project contributors, see AUTHORS.md in root folder | ||
5 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
6 | // | ||
7 | /*! | ||
8 | * \file | ||
9 | * \ingroup Parameter | ||
10 | * \brief A parameter tree that logs which parameters have been used | ||
11 | */ | ||
12 | #ifndef DUMUX_LOGGING_PARAMETER_TREE_HH | ||
13 | #define DUMUX_LOGGING_PARAMETER_TREE_HH | ||
14 | |||
15 | #include <iomanip> | ||
16 | #include <iostream> | ||
17 | #include <string> | ||
18 | #include <memory> | ||
19 | #include <mutex> | ||
20 | |||
21 | #include <dune/common/parametertree.hh> | ||
22 | #include <dumux/common/exceptions.hh> | ||
23 | |||
24 | namespace Dumux { | ||
25 | |||
26 | /*! | ||
27 | * \ingroup Parameter | ||
28 | * \brief A parameter tree that logs which parameters have been used | ||
29 | */ | ||
30 | class LoggingParameterTree | ||
31 | { | ||
32 | |||
33 | public: | ||
34 | /* | ||
35 | * \brief A logging parameter tree is always attached to an existingparameter tree | ||
36 | */ | ||
37 | LoggingParameterTree() = delete; | ||
38 | |||
39 | /* | ||
40 | * \brief Create LoggingParameterTree from ParameterTree | ||
41 | */ | ||
42 | 636 | LoggingParameterTree(const Dune::ParameterTree& params, const Dune::ParameterTree& defaultParams) | |
43 | 636 | : params_(params) | |
44 | , defaultParams_(defaultParams) | ||
45 | , usedRuntimeParams_(std::make_unique<Dune::ParameterTree>()) | ||
46 |
1/4✓ Branch 2 taken 636 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
636 | , usedDefaultParams_(std::make_unique<Dune::ParameterTree>()) |
47 | 636 | {} | |
48 | |||
49 | /** \brief test for key | ||
50 | * | ||
51 | * Tests whether given key exists. | ||
52 | * | ||
53 | * \note This ignores defaults. Hence, if the | ||
54 | * the specified key only exists in the defaults, this | ||
55 | * function returns false | ||
56 | * | ||
57 | * \param key key name | ||
58 | * \return true if key exists in structure, otherwise false | ||
59 | */ | ||
60 | ✗ | bool hasKey(const std::string& key) const | |
61 |
5/90✓ Branch 1 taken 599 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5774 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 418466 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 433 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 91 not taken.
✗ Branch 92 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 100 not taken.
✗ Branch 101 not taken.
✗ Branch 103 not taken.
✗ Branch 104 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 112 not taken.
✗ Branch 113 not taken.
✗ Branch 115 not taken.
✗ Branch 116 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 124 not taken.
✗ Branch 125 not taken.
✗ Branch 127 not taken.
✗ Branch 128 not taken.
✗ Branch 130 not taken.
✗ Branch 131 not taken.
✗ Branch 133 not taken.
✗ Branch 134 not taken.
|
425274 | { return params_.hasKey(key); } |
62 | |||
63 | /** \brief test for key in group | ||
64 | * | ||
65 | * Tests whether given key exists in a group. | ||
66 | * Given a group this function starts to look from the back | ||
67 | * for dots. In G1.G2.G3 the function first looks if the key | ||
68 | * "G3.Key" exists, then "G2.Key", ... | ||
69 | * | ||
70 | * \note This ignores defaults. Hence, if the | ||
71 | * the specified key only exists in the defaults, this | ||
72 | * function returns false | ||
73 | * | ||
74 | * \param key key name | ||
75 | * \param groupPrefix the group prefix name | ||
76 | * \return true if key exists in structure, otherwise false | ||
77 | */ | ||
78 | 2639 | bool hasKeyInGroup(const std::string& key, | |
79 | const std::string& groupPrefix) const | ||
80 | { | ||
81 |
4/4✓ Branch 0 taken 1735 times.
✓ Branch 1 taken 904 times.
✓ Branch 2 taken 1735 times.
✓ Branch 3 taken 904 times.
|
5278 | if (groupPrefix.empty()) |
82 | 1735 | return hasKey(key); | |
83 | |||
84 |
2/2✓ Branch 1 taken 690 times.
✓ Branch 2 taken 214 times.
|
904 | if (hasKey(key)) |
85 | return true; | ||
86 | |||
87 |
3/6✓ Branch 2 taken 690 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 640 times.
✓ Branch 5 taken 50 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
1380 | auto compoundKey = groupPrefix + "." + key; |
88 |
3/4✓ Branch 1 taken 690 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 538 times.
✓ Branch 4 taken 152 times.
|
690 | if (params_.hasKey(compoundKey)) |
89 | return true; | ||
90 | |||
91 |
2/4✓ Branch 1 taken 538 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 538 times.
|
538 | compoundKey = findKeyInGroup(params_, key, groupPrefix); |
92 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 538 times.
|
538 | if (compoundKey != "") |
93 | ✗ | return true; | |
94 | |||
95 | return false; | ||
96 | } | ||
97 | |||
98 | /** \brief obtain a vector of all full group names for a specified subgroup name | ||
99 | * | ||
100 | * Example: | ||
101 | * ------------ | ||
102 | * For the parameter tree | ||
103 | * | ||
104 | * [G1] | ||
105 | * MyParam1 = 1 | ||
106 | * [G2.G1] | ||
107 | * MyParam2 = 2 | ||
108 | * [G3.G2.G1] | ||
109 | * MyParam3 = 3 | ||
110 | * | ||
111 | * and groupPrefix="G3.G2" and subGroupName="G1" | ||
112 | * this returns a vector with the entries {"G3.G2.G1", "G2.G1", "G1"}. | ||
113 | * If groupPrefix = "G2", it returns {"G2.G1", "G1"}. | ||
114 | * If groupPrefix = "" the returned vector has size 1 (containing subGroupName), | ||
115 | * or size 0 if the subgroup does not exist in the parameter tree. | ||
116 | * | ||
117 | * \param subGroupName the sub group to look for | ||
118 | * \param groupPrefix the group prefix name (potentially prefixing the subgroup) | ||
119 | * \return a vector of fully qualified groups ordered by decreasing tree depth | ||
120 | */ | ||
121 | 403 | std::vector<std::string> getSubGroups(const std::string& subGroupName, | |
122 | std::string groupPrefix) const | ||
123 | { | ||
124 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 399 times.
|
403 | std::vector<std::string> groupNames; |
125 | |||
126 |
4/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 399 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 399 times.
|
806 | if (!groupPrefix.empty()) |
127 | { | ||
128 |
4/6✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 1 times.
|
11 | auto compoundGroup = groupPrefix + "." + subGroupName; |
129 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | for (std::string::size_type dotPos = 0; dotPos != std::string::npos; dotPos = groupPrefix.rfind(".")) |
130 | { | ||
131 |
2/8✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
4 | if (params_.hasSub(compoundGroup) || defaultParams_.hasSub(compoundGroup)) |
132 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | groupNames.push_back(compoundGroup); |
133 | |||
134 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
|
4 | groupPrefix = groupPrefix.substr(0, dotPos); |
135 |
4/12✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
|
4 | compoundGroup = groupPrefix + "." + subGroupName; |
136 | } | ||
137 | } | ||
138 | |||
139 |
5/8✓ Branch 1 taken 403 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 305 times.
✓ Branch 4 taken 98 times.
✓ Branch 6 taken 305 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 305 times.
|
403 | if (params_.hasSub(subGroupName) || defaultParams_.hasSub(subGroupName)) |
140 |
1/2✓ Branch 1 taken 98 times.
✗ Branch 2 not taken.
|
98 | groupNames.push_back(subGroupName); |
141 | |||
142 | 403 | return groupNames; | |
143 | } | ||
144 | |||
145 | /** \brief print the hierarchical parameter tree to stream | ||
146 | * | ||
147 | * \param stream the output stream to print to | ||
148 | */ | ||
149 | void report(std::ostream& stream = std::cout) const | ||
150 | { params_.report(stream); } | ||
151 | |||
152 | /** \brief print distinct substructure to stream | ||
153 | * | ||
154 | * Prints all entries with given prefix. | ||
155 | * | ||
156 | * \param stream Stream to print to | ||
157 | */ | ||
158 | 410 | void reportAll(std::ostream& stream = std::cout) const | |
159 | { | ||
160 | 820 | stream << "\n# Runtime-specified parameters used:" << std::endl; | |
161 |
5/12✓ Branch 1 taken 410 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 410 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 410 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 410 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 410 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
1230 | usedRuntimeParams_->report(stream); |
162 | |||
163 | 820 | stream << "\n# Global default parameters used:" << std::endl; | |
164 |
5/12✓ Branch 1 taken 410 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 410 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 410 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 410 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 410 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
1230 | usedDefaultParams_->report(stream); |
165 | |||
166 | 820 | const auto unusedParams = getUnusedKeys(); | |
167 |
4/4✓ Branch 0 taken 223 times.
✓ Branch 1 taken 187 times.
✓ Branch 2 taken 223 times.
✓ Branch 3 taken 187 times.
|
820 | if (!unusedParams.empty()) |
168 | { | ||
169 |
1/2✓ Branch 2 taken 223 times.
✗ Branch 3 not taken.
|
446 | stream << "\n# Unused parameters:" << std::endl; |
170 |
4/4✓ Branch 0 taken 615 times.
✓ Branch 1 taken 223 times.
✓ Branch 2 taken 615 times.
✓ Branch 3 taken 223 times.
|
1899 | for (const auto& key : unusedParams) |
171 |
4/8✓ Branch 1 taken 615 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 615 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 615 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 615 times.
✗ Branch 13 not taken.
|
1845 | stream << key << " = \"" << params_[key] << "\"" << std::endl; |
172 | } | ||
173 | 410 | } | |
174 | |||
175 | /*! \brief Do a backwards hierarchical search for a key in a group | ||
176 | * | ||
177 | * \note Given a group this function starts to look from the back | ||
178 | * for dots. In G1.G2.G3 the function first looks if the key | ||
179 | * "G3.Key" exists, then "G2.Key", ... | ||
180 | * The first compound key that is found is returned. If no | ||
181 | * compound key is found an empty string is returned. | ||
182 | * \param tree The tree to look in for keys | ||
183 | * \param key The key | ||
184 | * \param groupPrefix the group prefix attached to the key | ||
185 | */ | ||
186 | 7572 | std::string findKeyInGroup(const Dune::ParameterTree& tree, | |
187 | const std::string& key, | ||
188 | const std::string& groupPrefix) const | ||
189 | { | ||
190 | // search backwards until key is found | ||
191 |
2/2✓ Branch 1 taken 701 times.
✓ Branch 2 taken 6871 times.
|
15845 | std::string prefix = groupPrefix; |
192 | 7572 | auto dot = prefix.rfind("."); | |
193 |
2/2✓ Branch 0 taken 1019 times.
✓ Branch 1 taken 7490 times.
|
8509 | while (dot != std::string::npos) |
194 | { | ||
195 |
2/4✓ Branch 1 taken 1019 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1019 times.
|
1019 | prefix = prefix.substr(0, dot); |
196 |
2/6✓ Branch 1 taken 1019 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1019 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
1956 | std::string compoundKey = prefix + "." + key; |
197 | |||
198 |
3/4✓ Branch 1 taken 1019 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 82 times.
✓ Branch 4 taken 937 times.
|
1019 | if (tree.hasKey(compoundKey)) |
199 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 82 times.
|
246 | return compoundKey; |
200 | |||
201 | // look for the next dot in the current prefix | ||
202 |
2/2✓ Branch 1 taken 932 times.
✓ Branch 2 taken 5 times.
|
1874 | dot = prefix.rfind("."); |
203 | |||
204 | } | ||
205 | |||
206 | // the key was not found | ||
207 |
2/6✓ Branch 1 taken 7490 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7490 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
14980 | return ""; |
208 | } | ||
209 | |||
210 | /** \brief get value as string | ||
211 | * | ||
212 | * Returns pure string value for given key. | ||
213 | * | ||
214 | * \param key key name | ||
215 | * \param defaultValue default if key does not exist | ||
216 | * \return value as string | ||
217 | * \note This might be quite slow so call it only once, | ||
218 | * e.g. on initialization of the class configured by runtime parameters | ||
219 | */ | ||
220 | std::string get(const std::string& key, const std::string& defaultValue) const | ||
221 | { | ||
222 | if (params_.hasKey(key)) | ||
223 | { | ||
224 | // log that we used this parameter | ||
225 | const auto returnValue = params_[key]; | ||
226 | logUsedRuntimeParam_(key, returnValue); | ||
227 | return returnValue; | ||
228 | } | ||
229 | |||
230 | return defaultValue; | ||
231 | } | ||
232 | |||
233 | /** \brief get value as string, preferably from the sub-tree corresponding | ||
234 | * to a given prefix. The sub-tree is searched backwards for the parameter | ||
235 | * until its "first" occurrence. | ||
236 | * | ||
237 | * Returns pure string value for given key. | ||
238 | * | ||
239 | * \param groupPrefix The prefix of the sub tree the search should start in | ||
240 | * \param key key name | ||
241 | * \param defaultValue default if key does not exist | ||
242 | * \return value as string | ||
243 | * \note This might be quite slow so call it only once, | ||
244 | * e.g. on initialization of the class configured by runtime parameters | ||
245 | */ | ||
246 | std::string getFromGroup(const std::string& groupPrefix, | ||
247 | const std::string& key, | ||
248 | const std::string& defaultValue) const | ||
249 | { | ||
250 | if (groupPrefix.empty()) | ||
251 | return get(key, defaultValue); | ||
252 | |||
253 | // first, look for the compound key | ||
254 | std::string compoundKey = groupPrefix + "." + key; | ||
255 | if (params_.hasKey(compoundKey)) | ||
256 | { | ||
257 | // log that we used this parameter | ||
258 | const auto returnValue = params_[compoundKey]; | ||
259 | logUsedRuntimeParam_(compoundKey, returnValue); | ||
260 | return returnValue; | ||
261 | } | ||
262 | |||
263 | // search backwards until key is found | ||
264 | compoundKey = findKeyInGroup(params_, key, groupPrefix); | ||
265 | if (compoundKey != "") | ||
266 | { | ||
267 | // log that we used this parameter | ||
268 | const auto returnValue = params_[compoundKey]; | ||
269 | logUsedRuntimeParam_(compoundKey, returnValue); | ||
270 | return returnValue; | ||
271 | } | ||
272 | |||
273 | // finally, look for the key without prefix | ||
274 | return get(key, defaultValue); | ||
275 | } | ||
276 | |||
277 | /** \brief get value as string | ||
278 | * | ||
279 | * Returns pure string value for given key. | ||
280 | * | ||
281 | * \todo This is a hack so get("my_key", "xyz") compiles | ||
282 | * (without this method "xyz" resolves to bool instead of std::string) | ||
283 | * \param key key name | ||
284 | * \param defaultValue default if key does not exist | ||
285 | * \return value as string | ||
286 | * \note This might be quite slow so call it only once, | ||
287 | * e.g. on initialization of the class configured by runtime parameters | ||
288 | */ | ||
289 | std::string get(const std::string& key, const char* defaultValue) const | ||
290 | { | ||
291 | const std::string dv = defaultValue; | ||
292 | return get(key, dv); | ||
293 | } | ||
294 | |||
295 | /** \brief get value as string, preferably from the sub-tree corresponding | ||
296 | * to a given prefix. The sub-tree is searched for the parameter | ||
297 | * recursively until its "first" occurrence. | ||
298 | * | ||
299 | * Returns pure string value for given key. | ||
300 | * | ||
301 | * \param groupPrefix The prefix of the sub tree the search should start in | ||
302 | * \param key key name | ||
303 | * \param defaultValue default if key does not exist | ||
304 | * \return value as string | ||
305 | * \note This might be quite slow so call it only once, | ||
306 | * e.g. on initialization of the class configured by runtime parameters | ||
307 | */ | ||
308 | std::string getFromGroup(const std::string& groupPrefix, | ||
309 | const std::string& key, | ||
310 | const char* defaultValue) const | ||
311 | { | ||
312 | const std::string dv = defaultValue; | ||
313 | return getFromGroup(groupPrefix, key, dv); | ||
314 | } | ||
315 | |||
316 | |||
317 | /** \brief get value converted to a certain type | ||
318 | * | ||
319 | * Returns value as type T for given key. | ||
320 | * | ||
321 | * \tparam T type of returned value. | ||
322 | * \param key key name | ||
323 | * \param defaultValue default if key does not exist | ||
324 | * \return value converted to T | ||
325 | * \note This might be quite slow so call it only once, | ||
326 | * e.g. on initialization of the class configured by runtime parameters | ||
327 | */ | ||
328 | template<typename T> | ||
329 | 63728 | T get(const std::string& key, const T& defaultValue) const | |
330 | { | ||
331 |
2/2✓ Branch 1 taken 3770 times.
✓ Branch 2 taken 28100 times.
|
63728 | if (params_.hasKey(key)) |
332 | { | ||
333 | // log that we used this parameter | ||
334 | 7537 | logUsedRuntimeParam_(key, params_[key]); | |
335 | 7537 | return params_.template get<T>(key); | |
336 | } | ||
337 | |||
338 | 56191 | return defaultValue; | |
339 | } | ||
340 | |||
341 | /** \brief get value as string, preferably from the sub-tree corresponding | ||
342 | * to a given prefix. The sub-tree is searched for the parameter | ||
343 | * recursively until its "first" occurrence. | ||
344 | * | ||
345 | * Returns pure string value for given key. | ||
346 | * | ||
347 | * \param groupPrefix The prefix of the sub tree the search should start in | ||
348 | * \param key key name | ||
349 | * \param defaultValue default if key does not exist | ||
350 | * \return value as string | ||
351 | * \note This might be quite slow so call it only once, | ||
352 | * e.g. on initialization of the class configured by runtime parameters | ||
353 | */ | ||
354 | template<typename T> | ||
355 | 50701 | T getFromGroup(const std::string& groupPrefix, | |
356 | const std::string& key, | ||
357 | const T& defaultValue) const | ||
358 | { | ||
359 |
4/4✓ Branch 0 taken 20168 times.
✓ Branch 1 taken 5186 times.
✓ Branch 2 taken 20168 times.
✓ Branch 3 taken 5186 times.
|
101402 | if (groupPrefix.empty()) |
360 | 40335 | return get<T>(key, defaultValue); | |
361 | |||
362 | // first, look for the compound key | ||
363 |
3/6✓ Branch 2 taken 5186 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5165 times.
✓ Branch 5 taken 21 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
20732 | std::string compoundKey = groupPrefix + "." + key; |
364 |
3/4✓ Branch 1 taken 5186 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1169 times.
✓ Branch 4 taken 4017 times.
|
10366 | if (params_.hasKey(compoundKey)) |
365 | { | ||
366 | // log that we used this parameter | ||
367 |
2/4✓ Branch 1 taken 1169 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1169 times.
✗ Branch 5 not taken.
|
2337 | logUsedRuntimeParam_(compoundKey, params_[compoundKey]); |
368 |
1/2✓ Branch 1 taken 1169 times.
✗ Branch 2 not taken.
|
2337 | return params_.template get<T>(compoundKey); |
369 | } | ||
370 | |||
371 | // search backwards until key is found | ||
372 |
3/4✓ Branch 1 taken 4017 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 54 times.
✓ Branch 5 taken 3963 times.
|
8029 | compoundKey = findKeyInGroup(params_, key, groupPrefix); |
373 |
2/2✓ Branch 1 taken 54 times.
✓ Branch 2 taken 3963 times.
|
8029 | if (compoundKey != "") |
374 | { | ||
375 | // log that we used this parameter | ||
376 |
2/4✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 54 times.
✗ Branch 5 not taken.
|
108 | logUsedRuntimeParam_(compoundKey, params_[compoundKey]); |
377 |
1/2✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
|
108 | return params_.template get<T>(compoundKey); |
378 | } | ||
379 | |||
380 | // finally, look for the key without prefix | ||
381 |
1/2✓ Branch 1 taken 3963 times.
✗ Branch 2 not taken.
|
7921 | return get<T>(key, defaultValue); |
382 | } | ||
383 | |||
384 | /** \brief Get value | ||
385 | * | ||
386 | * \tparam T Type of the value | ||
387 | * \param key Key name | ||
388 | * \throws RangeError if key does not exist | ||
389 | * \throws NotImplemented Type is not supported | ||
390 | * \return value as T | ||
391 | * \note This might be quite slow so call it only once, | ||
392 | * e.g. on initialization of the class configured by runtime parameters | ||
393 | */ | ||
394 | template <class T> | ||
395 | 14971 | T get(const std::string& key) const | |
396 | { | ||
397 |
2/2✓ Branch 1 taken 5608 times.
✓ Branch 2 taken 1887 times.
|
14971 | if (params_.hasKey(key)) |
398 | { | ||
399 | // log that we used this parameter | ||
400 | 11201 | logUsedRuntimeParam_(key, params_[key]); | |
401 | 11201 | return params_.template get<T>(key); | |
402 | } | ||
403 | |||
404 |
1/2✓ Branch 1 taken 1887 times.
✗ Branch 2 not taken.
|
3770 | else if(defaultParams_.hasKey(key)) |
405 | { | ||
406 | // use the default | ||
407 | 3770 | logUsedDefaultParam_(key, defaultParams_[key]); | |
408 | 3770 | return defaultParams_.template get<T>(key); | |
409 | } | ||
410 | |||
411 | ✗ | DUNE_THROW(Dumux::ParameterException, "Key " << key << " not found in the parameter tree"); | |
412 | } | ||
413 | |||
414 | /** \brief get value as string, preferably from the sub-tree corresponding | ||
415 | * to a given prefix. The sub-tree is searched for the parameter | ||
416 | * recursively until its "first" occurrence. | ||
417 | * | ||
418 | * Returns pure string value for given key. | ||
419 | * | ||
420 | * \param groupPrefix The prefix of the sub tree the search should start in | ||
421 | * \param key key name | ||
422 | * \return value as string | ||
423 | * \note This might be quite slow so call it only once, | ||
424 | * e.g. on initialization of the class configured by runtime parameters | ||
425 | */ | ||
426 | template<typename T> | ||
427 | 13050 | T getFromGroup(const std::string& groupPrefix, | |
428 | const std::string& key) const | ||
429 | { | ||
430 |
4/4✓ Branch 0 taken 3102 times.
✓ Branch 1 taken 3467 times.
✓ Branch 2 taken 3102 times.
✓ Branch 3 taken 3467 times.
|
26100 | if (groupPrefix.empty()) |
431 | 6135 | return get<T>(key); | |
432 | |||
433 | // first, look for the compound key | ||
434 |
3/4✓ Branch 2 taken 3467 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3436 times.
✓ Branch 5 taken 31 times.
|
13830 | std::string compoundKey = groupPrefix + "." + key; |
435 |
3/4✓ Branch 1 taken 3467 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1414 times.
✓ Branch 4 taken 2053 times.
|
6915 | if (params_.hasKey(compoundKey)) |
436 | { | ||
437 | // log that we used this parameter | ||
438 |
2/4✓ Branch 1 taken 1414 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1414 times.
✗ Branch 5 not taken.
|
2823 | logUsedRuntimeParam_(compoundKey, params_[compoundKey]); |
439 |
1/2✓ Branch 1 taken 1414 times.
✗ Branch 2 not taken.
|
2823 | return params_.template get<T>(compoundKey); |
440 | } | ||
441 | |||
442 | // search backwards until key is found | ||
443 |
3/4✓ Branch 1 taken 2053 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✓ Branch 5 taken 2025 times.
|
4092 | compoundKey = findKeyInGroup(params_, key, groupPrefix); |
444 |
2/2✓ Branch 1 taken 28 times.
✓ Branch 2 taken 2025 times.
|
4092 | if (compoundKey != "") |
445 | { | ||
446 | // log that we used this parameter | ||
447 |
2/4✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
|
56 | logUsedRuntimeParam_(compoundKey, params_[compoundKey]); |
448 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
56 | return params_.template get<T>(compoundKey); |
449 | } | ||
450 | |||
451 | // reset the compoundKey | ||
452 |
4/12✓ Branch 1 taken 2025 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2025 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2025 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 2025 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
8072 | compoundKey = groupPrefix + "." + key; |
453 | |||
454 | // if the backward search did not succeed, try the bare key without any prefix | ||
455 |
3/4✓ Branch 1 taken 2025 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1061 times.
✓ Branch 4 taken 964 times.
|
4036 | if (params_.hasKey(key)) |
456 | { | ||
457 | // log that we used this parameter | ||
458 |
2/4✓ Branch 1 taken 1061 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1061 times.
✗ Branch 5 not taken.
|
2108 | logUsedRuntimeParam_(key, params_[key]); |
459 |
1/2✓ Branch 1 taken 1061 times.
✗ Branch 2 not taken.
|
2108 | return params_.template get<T>(key); |
460 | } | ||
461 | |||
462 | // if this did not work, repeat the procedure using the default parameters | ||
463 |
2/4✓ Branch 1 taken 964 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 964 times.
|
1928 | else if(defaultParams_.hasKey(compoundKey)) |
464 | { | ||
465 | // use the default | ||
466 | ✗ | logUsedDefaultParam_(compoundKey, defaultParams_[compoundKey]); | |
467 | ✗ | return defaultParams_.template get<T>(compoundKey); | |
468 | } | ||
469 | |||
470 | else | ||
471 | { | ||
472 | // search backwards until key is found | ||
473 |
2/4✓ Branch 1 taken 964 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 964 times.
|
1928 | compoundKey = findKeyInGroup(defaultParams_, key, groupPrefix); |
474 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 964 times.
|
1928 | if (compoundKey != "") |
475 | { | ||
476 | // log that we used this parameter | ||
477 | ✗ | logUsedDefaultParam_(compoundKey, defaultParams_[compoundKey]); | |
478 | ✗ | return defaultParams_.template get<T>(compoundKey); | |
479 | } | ||
480 | |||
481 |
2/4✓ Branch 1 taken 964 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 964 times.
✗ Branch 4 not taken.
|
1928 | if(defaultParams_.hasKey(key)) |
482 | { | ||
483 | // use the default | ||
484 |
2/4✓ Branch 1 taken 964 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 964 times.
✗ Branch 5 not taken.
|
1928 | logUsedDefaultParam_(key, defaultParams_[key]); |
485 |
1/2✓ Branch 1 taken 964 times.
✗ Branch 2 not taken.
|
1928 | return defaultParams_.template get<T>(key); |
486 | } | ||
487 | |||
488 | ✗ | DUNE_THROW(Dumux::ParameterException, "Key " << key << " not found in the parameter tree with group prefix " << groupPrefix); | |
489 | } | ||
490 | } | ||
491 | |||
492 | /** \brief Find the keys that haven't been used yet | ||
493 | * | ||
494 | * \return unusedParams Container storing unused keys | ||
495 | * \note Useful for debugging purposes | ||
496 | */ | ||
497 | 411 | std::vector<std::string> getUnusedKeys() const | |
498 | { | ||
499 |
1/2✓ Branch 1 taken 411 times.
✗ Branch 2 not taken.
|
411 | std::vector<std::string> unusedParams; |
500 |
4/10✓ Branch 1 taken 411 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 411 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 411 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 411 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
822 | findUnusedKeys_(params_, unusedParams); |
501 | 411 | return unusedParams; | |
502 | } | ||
503 | |||
504 | private: | ||
505 | /** \brief Find the keys that haven't been used yet recursively | ||
506 | * | ||
507 | * \param tree The tree to look in for unused keys | ||
508 | * \param unusedParams Container to store unused keys | ||
509 | * \param prefix the prefix attached to the key | ||
510 | */ | ||
511 | 3684 | void findUnusedKeys_(const Dune::ParameterTree& tree, | |
512 | std::vector<std::string>& unusedParams, | ||
513 | const std::string& prefix = "") const | ||
514 | { | ||
515 | // loop over all keys of the current tree | ||
516 | // store keys which were not accessed | ||
517 | 3684 | const auto& keys = tree.getValueKeys(); | |
518 |
4/4✓ Branch 0 taken 8006 times.
✓ Branch 1 taken 3684 times.
✓ Branch 2 taken 8006 times.
✓ Branch 3 taken 3684 times.
|
19058 | for (const auto& key : keys) |
519 |
13/20✓ Branch 1 taken 7646 times.
✓ Branch 2 taken 360 times.
✓ Branch 4 taken 7646 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 7646 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 7646 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 7030 times.
✓ Branch 13 taken 616 times.
✓ Branch 14 taken 7030 times.
✓ Branch 15 taken 360 times.
✓ Branch 16 taken 5627 times.
✓ Branch 17 taken 2019 times.
✓ Branch 18 taken 616 times.
✓ Branch 19 taken 7390 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
|
15652 | if (key != "ParameterFile" && !usedRuntimeParams_->hasKey(prefix + key)) |
520 |
2/6✓ Branch 2 taken 616 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 616 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
616 | unusedParams.push_back(prefix + key); |
521 | |||
522 | // recursively loop over all subtrees | ||
523 | 3684 | const auto& subTreeKeys = tree.getSubKeys(); | |
524 |
4/4✓ Branch 0 taken 3273 times.
✓ Branch 1 taken 3684 times.
✓ Branch 2 taken 3273 times.
✓ Branch 3 taken 3684 times.
|
17598 | for (const auto& key : subTreeKeys) |
525 |
6/14✓ Branch 2 taken 3273 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3273 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 3273 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 461 times.
✓ Branch 11 taken 2812 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3273 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
|
3734 | findUnusedKeys_(tree.sub(key), unusedParams, prefix + key + "."); |
526 | 3684 | } | |
527 | |||
528 | /** \brief Log the key value pair as used runtime param | ||
529 | */ | ||
530 | 13587 | void logUsedRuntimeParam_(const std::string& key, const std::string& value) const | |
531 | { | ||
532 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
13587 | std::scoped_lock lock{ usedRuntimeMutex_ }; |
533 |
4/8✓ Branch 1 taken 13587 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13587 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 13587 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 13587 times.
✗ Branch 10 not taken.
|
27174 | usedRuntimeParams_->operator[](key) = value; |
534 | 13587 | } | |
535 | |||
536 | /** \brief Log the key value pair as used default param | ||
537 | */ | ||
538 | 2851 | void logUsedDefaultParam_(const std::string& key, const std::string& value) const | |
539 | { | ||
540 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
2851 | std::scoped_lock lock{ usedDefaultMutex_ }; |
541 |
4/8✓ Branch 1 taken 2851 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2851 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2851 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2851 times.
✗ Branch 10 not taken.
|
5702 | usedDefaultParams_->operator[](key) = value; |
542 | 2851 | } | |
543 | |||
544 | const Dune::ParameterTree& params_; | ||
545 | const Dune::ParameterTree& defaultParams_; | ||
546 | |||
547 | // logging caches (externally stored) | ||
548 | std::unique_ptr<Dune::ParameterTree> usedRuntimeParams_; | ||
549 | std::unique_ptr<Dune::ParameterTree> usedDefaultParams_; | ||
550 | |||
551 | // access to the caches have to be protected for thread-safety | ||
552 | mutable std::mutex usedRuntimeMutex_; | ||
553 | mutable std::mutex usedDefaultMutex_; | ||
554 | }; | ||
555 | |||
556 | } // end namespace Dumux | ||
557 | |||
558 | #endif | ||
559 |