version 3.10-dev
loggingparametertree.hh
Go to the documentation of this file.
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//
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>
23
24namespace Dumux {
25
31{
32
33public:
34 /*
35 * \brief A logging parameter tree is always attached to an existingparameter tree
36 */
38
39 /*
40 * \brief Create LoggingParameterTree from ParameterTree
41 */
42 LoggingParameterTree(const Dune::ParameterTree& params, const Dune::ParameterTree& defaultParams)
43 : params_(params)
44 , defaultParams_(defaultParams)
45 , usedRuntimeParams_(std::make_unique<Dune::ParameterTree>())
46 , usedDefaultParams_(std::make_unique<Dune::ParameterTree>())
47 {}
48
60 bool hasKey(const std::string& key) const
61 { return params_.hasKey(key); }
62
78 bool hasKeyInGroup(const std::string& key,
79 const std::string& groupPrefix) const
80 {
81 if (groupPrefix.empty())
82 return hasKey(key);
83
84 if (hasKey(key))
85 return true;
86
87 auto compoundKey = groupPrefix + "." + key;
88 if (params_.hasKey(compoundKey))
89 return true;
90
91 compoundKey = findKeyInGroup(params_, key, groupPrefix);
92 if (compoundKey != "")
93 return true;
94
95 return false;
96 }
97
121 std::vector<std::string> getSubGroups(const std::string& subGroupName,
122 std::string groupPrefix) const
123 {
124 std::vector<std::string> groupNames;
125
126 if (!groupPrefix.empty())
127 {
128 auto compoundGroup = groupPrefix + "." + subGroupName;
129 for (std::string::size_type dotPos = 0; dotPos != std::string::npos; dotPos = groupPrefix.rfind("."))
130 {
131 if (params_.hasSub(compoundGroup) || defaultParams_.hasSub(compoundGroup))
132 groupNames.push_back(compoundGroup);
133
134 groupPrefix = groupPrefix.substr(0, dotPos);
135 compoundGroup = groupPrefix + "." + subGroupName;
136 }
137 }
138
139 if (params_.hasSub(subGroupName) || defaultParams_.hasSub(subGroupName))
140 groupNames.push_back(subGroupName);
141
142 return groupNames;
143 }
144
149 void report(std::ostream& stream = std::cout) const
150 { params_.report(stream); }
151
158 void reportAll(std::ostream& stream = std::cout) const
159 {
160 stream << "\n# Runtime-specified parameters used:" << std::endl;
161 usedRuntimeParams_->report(stream);
162
163 stream << "\n# Global default parameters used:" << std::endl;
164 usedDefaultParams_->report(stream);
165
166 const auto unusedParams = getUnusedKeys();
167 if (!unusedParams.empty())
168 {
169 stream << "\n# Unused parameters:" << std::endl;
170 for (const auto& key : unusedParams)
171 stream << key << " = \"" << params_[key] << "\"" << std::endl;
172 }
173 }
174
186 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 std::string prefix = groupPrefix;
192 auto dot = prefix.rfind(".");
193 while (dot != std::string::npos)
194 {
195 prefix = prefix.substr(0, dot);
196 std::string compoundKey = prefix + "." + key;
197
198 if (tree.hasKey(compoundKey))
199 return compoundKey;
200
201 // look for the next dot in the current prefix
202 dot = prefix.rfind(".");
203
204 }
205
206 // the key was not found
207 return "";
208 }
209
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
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
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
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
328 template<typename T>
329 T get(const std::string& key, const T& defaultValue) const
330 {
331 if (params_.hasKey(key))
332 {
333 // log that we used this parameter
334 logUsedRuntimeParam_(key, params_[key]);
335 return params_.template get<T>(key);
336 }
337
338 return defaultValue;
339 }
340
354 template<typename T>
355 T getFromGroup(const std::string& groupPrefix,
356 const std::string& key,
357 const T& defaultValue) const
358 {
359 if (groupPrefix.empty())
360 return get<T>(key, defaultValue);
361
362 // first, look for the compound key
363 std::string compoundKey = groupPrefix + "." + key;
364 if (params_.hasKey(compoundKey))
365 {
366 // log that we used this parameter
367 logUsedRuntimeParam_(compoundKey, params_[compoundKey]);
368 return params_.template get<T>(compoundKey);
369 }
370
371 // search backwards until key is found
372 compoundKey = findKeyInGroup(params_, key, groupPrefix);
373 if (compoundKey != "")
374 {
375 // log that we used this parameter
376 logUsedRuntimeParam_(compoundKey, params_[compoundKey]);
377 return params_.template get<T>(compoundKey);
378 }
379
380 // finally, look for the key without prefix
381 return get<T>(key, defaultValue);
382 }
383
394 template <class T>
395 T get(const std::string& key) const
396 {
397 if (params_.hasKey(key))
398 {
399 // log that we used this parameter
400 logUsedRuntimeParam_(key, params_[key]);
401 return params_.template get<T>(key);
402 }
403
404 else if(defaultParams_.hasKey(key))
405 {
406 // use the default
407 logUsedDefaultParam_(key, defaultParams_[key]);
408 return defaultParams_.template get<T>(key);
409 }
410
411 DUNE_THROW(Dumux::ParameterException, "Key " << key << " not found in the parameter tree");
412 }
413
426 template<typename T>
427 T getFromGroup(const std::string& groupPrefix,
428 const std::string& key) const
429 {
430 if (groupPrefix.empty())
431 return get<T>(key);
432
433 // first, look for the compound key
434 std::string compoundKey = groupPrefix + "." + key;
435 if (params_.hasKey(compoundKey))
436 {
437 // log that we used this parameter
438 logUsedRuntimeParam_(compoundKey, params_[compoundKey]);
439 return params_.template get<T>(compoundKey);
440 }
441
442 // search backwards until key is found
443 compoundKey = findKeyInGroup(params_, key, groupPrefix);
444 if (compoundKey != "")
445 {
446 // log that we used this parameter
447 logUsedRuntimeParam_(compoundKey, params_[compoundKey]);
448 return params_.template get<T>(compoundKey);
449 }
450
451 // reset the compoundKey
452 compoundKey = groupPrefix + "." + key;
453
454 // if the backward search did not succeed, try the bare key without any prefix
455 if (params_.hasKey(key))
456 {
457 // log that we used this parameter
458 logUsedRuntimeParam_(key, params_[key]);
459 return params_.template get<T>(key);
460 }
461
462 // if this did not work, repeat the procedure using the default parameters
463 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 compoundKey = findKeyInGroup(defaultParams_, key, groupPrefix);
474 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 if(defaultParams_.hasKey(key))
482 {
483 // use the default
484 logUsedDefaultParam_(key, defaultParams_[key]);
485 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
497 std::vector<std::string> getUnusedKeys() const
498 {
499 std::vector<std::string> unusedParams;
500 findUnusedKeys_(params_, unusedParams);
501 return unusedParams;
502 }
503
504private:
511 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 const auto& keys = tree.getValueKeys();
518 for (const auto& key : keys)
519 if (key != "ParameterFile" && !usedRuntimeParams_->hasKey(prefix + key))
520 unusedParams.push_back(prefix + key);
521
522 // recursively loop over all subtrees
523 const auto& subTreeKeys = tree.getSubKeys();
524 for (const auto& key : subTreeKeys)
525 findUnusedKeys_(tree.sub(key), unusedParams, prefix + key + ".");
526 }
527
530 void logUsedRuntimeParam_(const std::string& key, const std::string& value) const
531 {
532 std::scoped_lock lock{ usedRuntimeMutex_ };
533 usedRuntimeParams_->operator[](key) = value;
534 }
535
538 void logUsedDefaultParam_(const std::string& key, const std::string& value) const
539 {
540 std::scoped_lock lock{ usedDefaultMutex_ };
541 usedDefaultParams_->operator[](key) = value;
542 }
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
A parameter tree that logs which parameters have been used.
Definition: loggingparametertree.hh:31
std::string getFromGroup(const std::string &groupPrefix, const std::string &key, const std::string &defaultValue) const
get value as string, preferably from the sub-tree corresponding to a given prefix....
Definition: loggingparametertree.hh:246
T getFromGroup(const std::string &groupPrefix, const std::string &key, const T &defaultValue) const
get value as string, preferably from the sub-tree corresponding to a given prefix....
Definition: loggingparametertree.hh:355
void report(std::ostream &stream=std::cout) const
print the hierarchical parameter tree to stream
Definition: loggingparametertree.hh:149
std::string get(const std::string &key, const std::string &defaultValue) const
get value as string
Definition: loggingparametertree.hh:220
void reportAll(std::ostream &stream=std::cout) const
print distinct substructure to stream
Definition: loggingparametertree.hh:158
std::string findKeyInGroup(const Dune::ParameterTree &tree, const std::string &key, const std::string &groupPrefix) const
Do a backwards hierarchical search for a key in a group.
Definition: loggingparametertree.hh:186
std::string getFromGroup(const std::string &groupPrefix, const std::string &key, const char *defaultValue) const
get value as string, preferably from the sub-tree corresponding to a given prefix....
Definition: loggingparametertree.hh:308
std::vector< std::string > getSubGroups(const std::string &subGroupName, std::string groupPrefix) const
obtain a vector of all full group names for a specified subgroup name
Definition: loggingparametertree.hh:121
bool hasKeyInGroup(const std::string &key, const std::string &groupPrefix) const
test for key in group
Definition: loggingparametertree.hh:78
std::string get(const std::string &key, const char *defaultValue) const
get value as string
Definition: loggingparametertree.hh:289
T get(const std::string &key) const
Get value.
Definition: loggingparametertree.hh:395
LoggingParameterTree(const Dune::ParameterTree &params, const Dune::ParameterTree &defaultParams)
Definition: loggingparametertree.hh:42
std::vector< std::string > getUnusedKeys() const
Find the keys that haven't been used yet.
Definition: loggingparametertree.hh:497
T get(const std::string &key, const T &defaultValue) const
get value converted to a certain type
Definition: loggingparametertree.hh:329
T getFromGroup(const std::string &groupPrefix, const std::string &key) const
get value as string, preferably from the sub-tree corresponding to a given prefix....
Definition: loggingparametertree.hh:427
bool hasKey(const std::string &key) const
test for key
Definition: loggingparametertree.hh:60
Exception thrown if a run-time parameter is not specified correctly.
Definition: exceptions.hh:48
Some exceptions thrown in DuMux
Definition: adapt.hh:17
Definition: common/pdesolver.hh:24