3.5-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
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 * See the file COPYING for full copying permissions. *
5 * *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
24#ifndef DUMUX_LOGGING_PARAMETER_TREE_HH
25#define DUMUX_LOGGING_PARAMETER_TREE_HH
26
27#include <iomanip>
28#include <iostream>
29#include <string>
30#include <memory>
31#include <mutex>
32
33#include <dune/common/parametertree.hh>
35
36namespace Dumux {
37
43{
44
45public:
46 /*
47 * \brief A logging parameter tree is always attached to an existingparameter tree
48 */
50
51 /*
52 * \brief Create LoggingParameterTree from ParameterTree
53 */
54 LoggingParameterTree(const Dune::ParameterTree& params, const Dune::ParameterTree& defaultParams)
55 : params_(params)
56 , defaultParams_(defaultParams)
57 , usedRuntimeParams_(std::make_unique<Dune::ParameterTree>())
58 , usedDefaultParams_(std::make_unique<Dune::ParameterTree>())
59 {}
60
72 bool hasKey(const std::string& key) const
73 { return params_.hasKey(key); }
74
90 bool hasKeyInGroup(const std::string& key,
91 const std::string& groupPrefix) const
92 {
93 if (groupPrefix.empty())
94 return hasKey(key);
95
96 if (hasKey(key))
97 return true;
98
99 auto compoundKey = groupPrefix + "." + key;
100 if (params_.hasKey(compoundKey))
101 return true;
102
103 compoundKey = findKeyInGroup(params_, key, groupPrefix);
104 if (compoundKey != "")
105 return true;
106
107 return false;
108 }
109
133 std::vector<std::string> getSubGroups(const std::string& subGroupName,
134 std::string groupPrefix) const
135 {
136 std::vector<std::string> groupNames;
137
138 if (!groupPrefix.empty())
139 {
140 auto compoundGroup = groupPrefix + "." + subGroupName;
141 for (std::string::size_type dotPos = 0; dotPos != std::string::npos; dotPos = groupPrefix.rfind("."))
142 {
143 if (params_.hasSub(compoundGroup) || defaultParams_.hasSub(compoundGroup))
144 groupNames.push_back(compoundGroup);
145
146 groupPrefix = groupPrefix.substr(0, dotPos);
147 compoundGroup = groupPrefix + "." + subGroupName;
148 }
149 }
150
151 if (params_.hasSub(subGroupName) || defaultParams_.hasSub(subGroupName))
152 groupNames.push_back(subGroupName);
153
154 return groupNames;
155 }
156
161 void report(std::ostream& stream = std::cout) const
162 { params_.report(stream); }
163
170 void reportAll(std::ostream& stream = std::cout) const
171 {
172 stream << "\n# Runtime-specified parameters used:" << std::endl;
173 usedRuntimeParams_->report(stream);
174
175 stream << "\n# Global default parameters used:" << std::endl;
176 usedDefaultParams_->report(stream);
177
178 const auto unusedParams = getUnusedKeys();
179 if (!unusedParams.empty())
180 {
181 stream << "\n# Unused parameters:" << std::endl;
182 for (const auto& key : unusedParams)
183 stream << key << " = \"" << params_[key] << "\"" << std::endl;
184 }
185 }
186
198 std::string findKeyInGroup(const Dune::ParameterTree& tree,
199 const std::string& key,
200 const std::string& groupPrefix) const
201 {
202 // search backwards until key is found
203 std::string prefix = groupPrefix;
204 auto dot = prefix.rfind(".");
205 while (dot != std::string::npos)
206 {
207 prefix = prefix.substr(0, dot);
208 std::string compoundKey = prefix + "." + key;
209
210 if (tree.hasKey(compoundKey))
211 return compoundKey;
212
213 // look for the next dot in the current prefix
214 dot = prefix.rfind(".");
215
216 }
217
218 // the key was not found
219 return "";
220 }
221
232 std::string get(const std::string& key, const std::string& defaultValue) const
233 {
234 if (params_.hasKey(key))
235 {
236 // log that we used this parameter
237 const auto returnValue = params_[key];
238 logUsedRuntimeParam_(key, returnValue);
239 return returnValue;
240 }
241
242 return defaultValue;
243 }
244
258 std::string getFromGroup(const std::string& groupPrefix,
259 const std::string& key,
260 const std::string& defaultValue) const
261 {
262 if (groupPrefix.empty())
263 return get(key, defaultValue);
264
265 // first, look for the compound key
266 std::string compoundKey = groupPrefix + "." + key;
267 if (params_.hasKey(compoundKey))
268 {
269 // log that we used this parameter
270 const auto returnValue = params_[compoundKey];
271 logUsedRuntimeParam_(compoundKey, returnValue);
272 return returnValue;
273 }
274
275 // search backwards until key is found
276 compoundKey = findKeyInGroup(params_, key, groupPrefix);
277 if (compoundKey != "")
278 {
279 // log that we used this parameter
280 const auto returnValue = params_[compoundKey];
281 logUsedRuntimeParam_(compoundKey, returnValue);
282 return returnValue;
283 }
284
285 // finally, look for the key without prefix
286 return get(key, defaultValue);
287 }
288
301 std::string get(const std::string& key, const char* defaultValue) const
302 {
303 const std::string dv = defaultValue;
304 return get(key, dv);
305 }
306
320 std::string getFromGroup(const std::string& groupPrefix,
321 const std::string& key,
322 const char* defaultValue) const
323 {
324 const std::string dv = defaultValue;
325 return getFromGroup(groupPrefix, key, dv);
326 }
327
328
340 template<typename T>
341 T get(const std::string& key, const T& defaultValue) const
342 {
343 if (params_.hasKey(key))
344 {
345 // log that we used this parameter
346 logUsedRuntimeParam_(key, params_[key]);
347 return params_.template get<T>(key);
348 }
349
350 return defaultValue;
351 }
352
366 template<typename T>
367 T getFromGroup(const std::string& groupPrefix,
368 const std::string& key,
369 const T& defaultValue) const
370 {
371 if (groupPrefix.empty())
372 return get<T>(key, defaultValue);
373
374 // first, look for the compound key
375 std::string compoundKey = groupPrefix + "." + key;
376 if (params_.hasKey(compoundKey))
377 {
378 // log that we used this parameter
379 logUsedRuntimeParam_(compoundKey, params_[compoundKey]);
380 return params_.template get<T>(compoundKey);
381 }
382
383 // search backwards until key is found
384 compoundKey = findKeyInGroup(params_, key, groupPrefix);
385 if (compoundKey != "")
386 {
387 // log that we used this parameter
388 logUsedRuntimeParam_(compoundKey, params_[compoundKey]);
389 return params_.template get<T>(compoundKey);
390 }
391
392 // finally, look for the key without prefix
393 return get<T>(key, defaultValue);
394 }
395
406 template <class T>
407 T get(const std::string& key) const
408 {
409 if (params_.hasKey(key))
410 {
411 // log that we used this parameter
412 logUsedRuntimeParam_(key, params_[key]);
413 return params_.template get<T>(key);
414 }
415
416 else if(defaultParams_.hasKey(key))
417 {
418 // use the default
419 logUsedDefaultParam_(key, defaultParams_[key]);
420 return defaultParams_.template get<T>(key);
421 }
422
423 DUNE_THROW(Dumux::ParameterException, "Key " << key << " not found in the parameter tree");
424 }
425
438 template<typename T>
439 T getFromGroup(const std::string& groupPrefix,
440 const std::string& key) const
441 {
442 if (groupPrefix.empty())
443 return get<T>(key);
444
445 // first, look for the compound key
446 std::string compoundKey = groupPrefix + "." + key;
447 if (params_.hasKey(compoundKey))
448 {
449 // log that we used this parameter
450 logUsedRuntimeParam_(compoundKey, params_[compoundKey]);
451 return params_.template get<T>(compoundKey);
452 }
453
454 // search backwards until key is found
455 compoundKey = findKeyInGroup(params_, key, groupPrefix);
456 if (compoundKey != "")
457 {
458 // log that we used this parameter
459 logUsedRuntimeParam_(compoundKey, params_[compoundKey]);
460 return params_.template get<T>(compoundKey);
461 }
462
463 // reset the compoundKey
464 compoundKey = groupPrefix + "." + key;
465
466 // if the backward search did not succeed, try the bare key without any prefix
467 if (params_.hasKey(key))
468 {
469 // log that we used this parameter
470 logUsedRuntimeParam_(key, params_[key]);
471 return params_.template get<T>(key);
472 }
473
474 // if this did not work, repeat the procedure using the default parameters
475 else if(defaultParams_.hasKey(compoundKey))
476 {
477 // use the default
478 logUsedDefaultParam_(compoundKey, defaultParams_[compoundKey]);
479 return defaultParams_.template get<T>(compoundKey);
480 }
481
482 else
483 {
484 // search backwards until key is found
485 compoundKey = findKeyInGroup(defaultParams_, key, groupPrefix);
486 if (compoundKey != "")
487 {
488 // log that we used this parameter
489 logUsedDefaultParam_(compoundKey, defaultParams_[compoundKey]);
490 return defaultParams_.template get<T>(compoundKey);
491 }
492
493 if(defaultParams_.hasKey(key))
494 {
495 // use the default
496 logUsedDefaultParam_(key, defaultParams_[key]);
497 return defaultParams_.template get<T>(key);
498 }
499
500 DUNE_THROW(Dumux::ParameterException, "Key " << key << " not found in the parameter tree");
501 }
502 }
503
509 std::vector<std::string> getUnusedKeys() const
510 {
511 std::vector<std::string> unusedParams;
512 findUnusedKeys_(params_, unusedParams);
513 return unusedParams;
514 }
515
516private:
523 void findUnusedKeys_(const Dune::ParameterTree& tree,
524 std::vector<std::string>& unusedParams,
525 const std::string& prefix = "") const
526 {
527 // loop over all keys of the current tree
528 // store keys which were not accessed
529 const auto& keys = tree.getValueKeys();
530 for (const auto& key : keys)
531 if (key != "ParameterFile" && !usedRuntimeParams_->hasKey(prefix + key))
532 unusedParams.push_back(prefix + key);
533
534 // recursively loop over all subtrees
535 const auto& subTreeKeys = tree.getSubKeys();
536 for (const auto& key : subTreeKeys)
537 findUnusedKeys_(tree.sub(key), unusedParams, prefix + key + ".");
538 }
539
542 void logUsedRuntimeParam_(const std::string& key, const std::string& value) const
543 {
544 std::scoped_lock lock{ usedRuntimeMutex_ };
545 usedRuntimeParams_->operator[](key) = value;
546 }
547
550 void logUsedDefaultParam_(const std::string& key, const std::string& value) const
551 {
552 std::scoped_lock lock{ usedDefaultMutex_ };
553 usedDefaultParams_->operator[](key) = value;
554 }
555
556 const Dune::ParameterTree& params_;
557 const Dune::ParameterTree& defaultParams_;
558
559 // logging caches (externally stored)
560 std::unique_ptr<Dune::ParameterTree> usedRuntimeParams_;
561 std::unique_ptr<Dune::ParameterTree> usedDefaultParams_;
562
563 // access to the caches have to be protected for thread-safety
564 mutable std::mutex usedRuntimeMutex_;
565 mutable std::mutex usedDefaultMutex_;
566};
567
568} // end namespace Dumux
569
570#endif
Some exceptions thrown in DuMux
Definition: adapt.hh:29
Definition: common/pdesolver.hh:36
Exception thrown if a run-time parameter is not specified correctly.
Definition: exceptions.hh:60
A parameter tree that logs which parameters have been used.
Definition: loggingparametertree.hh:43
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:258
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:367
void report(std::ostream &stream=std::cout) const
print the hierarchical parameter tree to stream
Definition: loggingparametertree.hh:161
std::string get(const std::string &key, const std::string &defaultValue) const
get value as string
Definition: loggingparametertree.hh:232
void reportAll(std::ostream &stream=std::cout) const
print distinct substructure to stream
Definition: loggingparametertree.hh:170
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:198
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:320
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:133
bool hasKeyInGroup(const std::string &key, const std::string &groupPrefix) const
test for key in group
Definition: loggingparametertree.hh:90
std::string get(const std::string &key, const char *defaultValue) const
get value as string
Definition: loggingparametertree.hh:301
T get(const std::string &key) const
Get value.
Definition: loggingparametertree.hh:407
LoggingParameterTree(const Dune::ParameterTree &params, const Dune::ParameterTree &defaultParams)
Definition: loggingparametertree.hh:54
std::vector< std::string > getUnusedKeys() const
Find the keys that haven't been used yet.
Definition: loggingparametertree.hh:509
T get(const std::string &key, const T &defaultValue) const
get value converted to a certain type
Definition: loggingparametertree.hh:341
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:439
bool hasKey(const std::string &key) const
test for key
Definition: loggingparametertree.hh:72