GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/common/loggingparametertree.hh
Date: 2024-05-04 19:09:25
Exec Total Coverage
Lines: 112 120 93.3%
Functions: 85 106 80.2%
Branches: 237 478 49.6%

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 645 LoggingParameterTree(const Dune::ParameterTree& params, const Dune::ParameterTree& defaultParams)
43 645 : params_(params)
44 , defaultParams_(defaultParams)
45 , usedRuntimeParams_(std::make_unique<Dune::ParameterTree>())
46
1/4
✓ Branch 2 taken 645 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
645 , usedDefaultParams_(std::make_unique<Dune::ParameterTree>())
47 645 {}
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
45/90
✓ Branch 1 taken 601 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5999 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 422091 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 459 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 28 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 25 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 25 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 25 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 25 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 25 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 25 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 25 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 25 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 25 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 25 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 25 times.
✗ Branch 47 not taken.
✓ Branch 49 taken 25 times.
✗ Branch 50 not taken.
✓ Branch 52 taken 25 times.
✗ Branch 53 not taken.
✓ Branch 55 taken 25 times.
✗ Branch 56 not taken.
✓ Branch 58 taken 25 times.
✗ Branch 59 not taken.
✓ Branch 61 taken 25 times.
✗ Branch 62 not taken.
✓ Branch 64 taken 50 times.
✗ Branch 65 not taken.
✓ Branch 67 taken 50 times.
✗ Branch 68 not taken.
✓ Branch 70 taken 50 times.
✗ Branch 71 not taken.
✓ Branch 73 taken 50 times.
✗ Branch 74 not taken.
✓ Branch 76 taken 50 times.
✗ Branch 77 not taken.
✓ Branch 79 taken 50 times.
✗ Branch 80 not taken.
✓ Branch 82 taken 50 times.
✗ Branch 83 not taken.
✓ Branch 85 taken 50 times.
✗ Branch 86 not taken.
✓ Branch 88 taken 50 times.
✗ Branch 89 not taken.
✓ Branch 91 taken 50 times.
✗ Branch 92 not taken.
✓ Branch 94 taken 50 times.
✗ Branch 95 not taken.
✓ Branch 97 taken 50 times.
✗ Branch 98 not taken.
✓ Branch 100 taken 50 times.
✗ Branch 101 not taken.
✓ Branch 103 taken 50 times.
✗ Branch 104 not taken.
✓ Branch 106 taken 50 times.
✗ Branch 107 not taken.
✓ Branch 109 taken 50 times.
✗ Branch 110 not taken.
✓ Branch 112 taken 50 times.
✗ Branch 113 not taken.
✓ Branch 115 taken 50 times.
✗ Branch 116 not taken.
✓ Branch 118 taken 50 times.
✗ Branch 119 not taken.
✓ Branch 121 taken 50 times.
✗ Branch 122 not taken.
✓ Branch 124 taken 1 times.
✗ Branch 125 not taken.
✓ Branch 127 taken 1 times.
✗ Branch 128 not taken.
✓ Branch 130 taken 1 times.
✗ Branch 131 not taken.
✓ Branch 133 taken 1 times.
✗ Branch 134 not taken.
430582 { 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 2838 bool hasKeyInGroup(const std::string& key,
79 const std::string& groupPrefix) const
80 {
81
4/4
✓ Branch 0 taken 1917 times.
✓ Branch 1 taken 921 times.
✓ Branch 2 taken 1917 times.
✓ Branch 3 taken 921 times.
5676 if (groupPrefix.empty())
82 1917 return hasKey(key);
83
84
2/2
✓ Branch 1 taken 702 times.
✓ Branch 2 taken 219 times.
921 if (hasKey(key))
85 return true;
86
87
3/6
✓ Branch 2 taken 702 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 650 times.
✓ Branch 5 taken 52 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1404 auto compoundKey = groupPrefix + "." + key;
88
3/4
✓ Branch 1 taken 702 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 545 times.
✓ Branch 4 taken 157 times.
702 if (params_.hasKey(compoundKey))
89 return true;
90
91
2/4
✓ Branch 1 taken 545 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 545 times.
545 compoundKey = findKeyInGroup(params_, key, groupPrefix);
92
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 545 times.
545 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 402 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 398 times.
402 std::vector<std::string> groupNames;
125
126
4/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 398 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 398 times.
804 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 402 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 303 times.
✓ Branch 4 taken 99 times.
✓ Branch 6 taken 303 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 303 times.
402 if (params_.hasSub(subGroupName) || defaultParams_.hasSub(subGroupName))
140
1/2
✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
99 groupNames.push_back(subGroupName);
141
142 402 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 416 void reportAll(std::ostream& stream = std::cout) const
159 {
160 832 stream << "\n# Runtime-specified parameters used:" << std::endl;
161
5/12
✓ Branch 1 taken 416 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 416 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 416 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 416 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 416 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
1248 usedRuntimeParams_->report(stream);
162
163 832 stream << "\n# Global default parameters used:" << std::endl;
164
5/12
✓ Branch 1 taken 416 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 416 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 416 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 416 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 416 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
1248 usedDefaultParams_->report(stream);
165
166 832 const auto unusedParams = getUnusedKeys();
167
4/4
✓ Branch 0 taken 228 times.
✓ Branch 1 taken 188 times.
✓ Branch 2 taken 228 times.
✓ Branch 3 taken 188 times.
832 if (!unusedParams.empty())
168 {
169
1/2
✓ Branch 2 taken 228 times.
✗ Branch 3 not taken.
456 stream << "\n# Unused parameters:" << std::endl;
170
4/4
✓ Branch 0 taken 622 times.
✓ Branch 1 taken 228 times.
✓ Branch 2 taken 622 times.
✓ Branch 3 taken 228 times.
1928 for (const auto& key : unusedParams)
171
4/8
✓ Branch 1 taken 622 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 622 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 622 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 622 times.
✗ Branch 13 not taken.
1866 stream << key << " = \"" << params_[key] << "\"" << std::endl;
172 }
173 416 }
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 7684 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 737 times.
✓ Branch 2 taken 6947 times.
16105 std::string prefix = groupPrefix;
192 7684 auto dot = prefix.rfind(".");
193
2/2
✓ Branch 0 taken 1055 times.
✓ Branch 1 taken 7602 times.
8657 while (dot != std::string::npos)
194 {
195
2/4
✓ Branch 1 taken 1055 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1055 times.
1055 prefix = prefix.substr(0, dot);
196
2/6
✓ Branch 1 taken 1055 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1055 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
2028 std::string compoundKey = prefix + "." + key;
197
198
3/4
✓ Branch 1 taken 1055 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 82 times.
✓ Branch 4 taken 973 times.
1055 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 967 times.
✓ Branch 2 taken 6 times.
1946 dot = prefix.rfind(".");
203
204 }
205
206 // the key was not found
207
2/6
✓ Branch 1 taken 7602 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7602 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
15204 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 70286 T get(const std::string& key, const T& defaultValue) const
330 {
331
2/2
✓ Branch 1 taken 3922 times.
✓ Branch 2 taken 31227 times.
70286 if (params_.hasKey(key))
332 {
333 // log that we used this parameter
334 7841 logUsedRuntimeParam_(key, params_[key]);
335 7841 return params_.template get<T>(key);
336 }
337
338 62445 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 51797 T getFromGroup(const std::string& groupPrefix,
356 const std::string& key,
357 const T& defaultValue) const
358 {
359
4/4
✓ Branch 0 taken 20598 times.
✓ Branch 1 taken 5304 times.
✓ Branch 2 taken 20598 times.
✓ Branch 3 taken 5304 times.
103594 if (groupPrefix.empty())
360 41195 return get<T>(key, defaultValue);
361
362 // first, look for the compound key
363
3/6
✓ Branch 2 taken 5304 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5282 times.
✓ Branch 5 taken 22 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
21204 std::string compoundKey = groupPrefix + "." + key;
364
3/4
✓ Branch 1 taken 5304 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1215 times.
✓ Branch 4 taken 4089 times.
10602 if (params_.hasKey(compoundKey))
365 {
366 // log that we used this parameter
367
2/4
✓ Branch 1 taken 1215 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1215 times.
✗ Branch 5 not taken.
2429 logUsedRuntimeParam_(compoundKey, params_[compoundKey]);
368
1/2
✓ Branch 1 taken 1215 times.
✗ Branch 2 not taken.
2429 return params_.template get<T>(compoundKey);
369 }
370
371 // search backwards until key is found
372
3/4
✓ Branch 1 taken 4089 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 54 times.
✓ Branch 5 taken 4035 times.
8173 compoundKey = findKeyInGroup(params_, key, groupPrefix);
373
2/2
✓ Branch 1 taken 54 times.
✓ Branch 2 taken 4035 times.
8173 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 4035 times.
✗ Branch 2 not taken.
8065 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 15439 T get(const std::string& key) const
396 {
397
2/2
✓ Branch 1 taken 5727 times.
✓ Branch 2 taken 2002 times.
15439 if (params_.hasKey(key))
398 {
399 // log that we used this parameter
400 11439 logUsedRuntimeParam_(key, params_[key]);
401 11439 return params_.template get<T>(key);
402 }
403
404
1/2
✓ Branch 1 taken 2002 times.
✗ Branch 2 not taken.
4000 else if(defaultParams_.hasKey(key))
405 {
406 // use the default
407 4000 logUsedDefaultParam_(key, defaultParams_[key]);
408 4000 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 13398 T getFromGroup(const std::string& groupPrefix,
428 const std::string& key) const
429 {
430
4/4
✓ Branch 0 taken 3225 times.
✓ Branch 1 taken 3518 times.
✓ Branch 2 taken 3225 times.
✓ Branch 3 taken 3518 times.
26796 if (groupPrefix.empty())
431 6381 return get<T>(key);
432
433 // first, look for the compound key
434
3/4
✓ Branch 2 taken 3518 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3485 times.
✓ Branch 5 taken 33 times.
14034 std::string compoundKey = groupPrefix + "." + key;
435
3/4
✓ Branch 1 taken 3518 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1447 times.
✓ Branch 4 taken 2071 times.
7017 if (params_.hasKey(compoundKey))
436 {
437 // log that we used this parameter
438
2/4
✓ Branch 1 taken 1447 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1447 times.
✗ Branch 5 not taken.
2889 logUsedRuntimeParam_(compoundKey, params_[compoundKey]);
439
1/2
✓ Branch 1 taken 1447 times.
✗ Branch 2 not taken.
2889 return params_.template get<T>(compoundKey);
440 }
441
442 // search backwards until key is found
443
3/4
✓ Branch 1 taken 2071 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✓ Branch 5 taken 2043 times.
4128 compoundKey = findKeyInGroup(params_, key, groupPrefix);
444
2/2
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 2043 times.
4128 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 2043 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2043 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2043 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 2043 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
8144 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 2043 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1064 times.
✓ Branch 4 taken 979 times.
4072 if (params_.hasKey(key))
456 {
457 // log that we used this parameter
458
2/4
✓ Branch 1 taken 1064 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1064 times.
✗ Branch 5 not taken.
2114 logUsedRuntimeParam_(key, params_[key]);
459
1/2
✓ Branch 1 taken 1064 times.
✗ Branch 2 not taken.
2114 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 979 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 979 times.
1958 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 979 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 979 times.
1958 compoundKey = findKeyInGroup(defaultParams_, key, groupPrefix);
474
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 979 times.
1958 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 979 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 979 times.
✗ Branch 4 not taken.
1958 if(defaultParams_.hasKey(key))
482 {
483 // use the default
484
2/4
✓ Branch 1 taken 979 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 979 times.
✗ Branch 5 not taken.
1958 logUsedDefaultParam_(key, defaultParams_[key]);
485
1/2
✓ Branch 1 taken 979 times.
✗ Branch 2 not taken.
1958 return defaultParams_.template get<T>(key);
486 }
487
488 DUNE_THROW(Dumux::ParameterException, "Key " << key << " not found in the parameter tree");
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 417 std::vector<std::string> getUnusedKeys() const
498 {
499
1/2
✓ Branch 1 taken 417 times.
✗ Branch 2 not taken.
417 std::vector<std::string> unusedParams;
500
4/10
✓ Branch 1 taken 417 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 417 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 417 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 417 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
834 findUnusedKeys_(params_, unusedParams);
501 417 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 3775 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 3775 const auto& keys = tree.getValueKeys();
518
4/4
✓ Branch 0 taken 8202 times.
✓ Branch 1 taken 3775 times.
✓ Branch 2 taken 8202 times.
✓ Branch 3 taken 3775 times.
19527 for (const auto& key : keys)
519
13/20
✓ Branch 1 taken 7838 times.
✓ Branch 2 taken 364 times.
✓ Branch 4 taken 7838 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 7838 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 7838 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 7215 times.
✓ Branch 13 taken 623 times.
✓ Branch 14 taken 7215 times.
✓ Branch 15 taken 364 times.
✓ Branch 16 taken 5780 times.
✓ Branch 17 taken 2058 times.
✓ Branch 18 taken 623 times.
✓ Branch 19 taken 7579 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
16040 if (key != "ParameterFile" && !usedRuntimeParams_->hasKey(prefix + key))
520
2/6
✓ Branch 2 taken 623 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 623 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
623 unusedParams.push_back(prefix + key);
521
522 // recursively loop over all subtrees
523 3775 const auto& subTreeKeys = tree.getSubKeys();
524
4/4
✓ Branch 0 taken 3358 times.
✓ Branch 1 taken 3775 times.
✓ Branch 2 taken 3358 times.
✓ Branch 3 taken 3775 times.
18041 for (const auto& key : subTreeKeys)
525
6/14
✓ Branch 2 taken 3358 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3358 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 3358 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 495 times.
✓ Branch 11 taken 2863 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3358 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
3853 findUnusedKeys_(tree.sub(key), unusedParams, prefix + key + ".");
526 3775 }
527
528 /** \brief Log the key value pair as used runtime param
529 */
530 13942 void logUsedRuntimeParam_(const std::string& key, const std::string& value) const
531 {
532
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
13942 std::scoped_lock lock{ usedRuntimeMutex_ };
533
4/8
✓ Branch 1 taken 13942 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13942 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 13942 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 13942 times.
✗ Branch 10 not taken.
27884 usedRuntimeParams_->operator[](key) = value;
534 13942 }
535
536 /** \brief Log the key value pair as used default param
537 */
538 2981 void logUsedDefaultParam_(const std::string& key, const std::string& value) const
539 {
540
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
2981 std::scoped_lock lock{ usedDefaultMutex_ };
541
4/8
✓ Branch 1 taken 2981 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2981 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2981 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2981 times.
✗ Branch 10 not taken.
5962 usedDefaultParams_->operator[](key) = value;
542 2981 }
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