30 #ifndef EWOMS_PARAMETERS_HH
31 #define EWOMS_PARAMETERS_HH
34 #include <opm/common/ErrorMacros.hpp>
35 #include <opm/common/Exceptions.hpp>
36 #include <opm/material/common/ClassName.hpp>
38 #include <dune/common/parametertree.hh>
45 #include <unordered_map>
64 #define EWOMS_REGISTER_PARAM(TypeTag, ParamType, ParamName, Description) \
65 ::Ewoms::Parameters::registerParam<TypeTag, ParamType, PTAG(ParamName)>( \
66 #ParamName, #ParamName, Description)
77 #define EWOMS_END_PARAM_REGISTRATION(TypeTag) \
78 ::Ewoms::Parameters::endParamRegistration<TypeTag>()
95 #define EWOMS_GET_PARAM(TypeTag, ParamType, ParamName) \
96 (::Ewoms::Parameters::get<TypeTag, ParamType, PTAG(ParamName)>(#ParamName, \
100 #define EWOMS_GET_PARAM_(TypeTag, ParamType, ParamName) \
101 (::Ewoms::Parameters::get<TypeTag, ParamType, PTAG(ParamName)>( \
102 #ParamName, #ParamName, \
106 namespace Parameters {
110 std::string paramName;
111 std::string paramTypeName;
112 std::string typeTagName;
113 std::string propertyName;
114 std::string usageString;
115 std::string compileTimeValue;
117 bool operator==(
const ParamInfo &other)
const
119 return other.paramName == paramName
120 && other.paramTypeName == paramTypeName
121 && other.typeTagName == typeTagName
122 && other.propertyName == propertyName
123 && other.usageString == usageString
124 && other.compileTimeValue == compileTimeValue;
129 template <
class TypeTag,
class ParamType,
class PropTag>
130 const ParamType &
get(
const char *propTagName,
const char *paramName,
131 bool errorIfNotRegistered =
true);
133 class ParamRegFinalizerBase_
136 virtual ~ParamRegFinalizerBase_()
138 virtual void retrieve() = 0;
141 template <
class TypeTag,
class ParamType,
class PropTag>
142 class ParamRegFinalizer_ :
public ParamRegFinalizerBase_
145 ParamRegFinalizer_(
const std::string ¶mName) : paramName_(paramName)
152 ParamType __attribute__((unused)) dummy =
153 get<TypeTag, ParamType, PropTag>(paramName_.data(),
159 std::string paramName_;
163 namespace Properties {
174 SET_PROP(ParameterSystem, ParameterMetaData)
176 typedef Dune::ParameterTree type;
178 static Dune::ParameterTree &tree()
179 {
return storage_().tree; }
181 static std::map<std::string, ::Ewoms::Parameters::ParamInfo> &mutableRegistry()
182 {
return storage_().registry; }
184 static const std::map<std::string, ::Ewoms::Parameters::ParamInfo> ®istry()
185 {
return storage_().registry; }
187 static std::list< ::Ewoms::Parameters::ParamRegFinalizerBase_ *> &
188 registrationFinalizers()
189 {
return storage_().finalizers; }
191 static bool ®istrationOpen()
192 {
return storage_().registrationOpen; }
201 { registrationOpen =
true; }
203 Dune::ParameterTree tree;
204 std::map<std::string, ::Ewoms::Parameters::ParamInfo> registry;
205 std::list< ::Ewoms::Parameters::ParamRegFinalizerBase_ *> finalizers;
206 bool registrationOpen;
208 static Storage_& storage_() {
219 namespace Parameters {
221 void printParamUsage_(std::ostream &os,
const ParamInfo ¶mInfo);
222 void getFlattenedKeyList_(std::list<std::string> &dest,
223 const Dune::ParameterTree &tree,
224 const std::string &prefix =
"");
227 void printParamUsage_(std::ostream &os,
const ParamInfo ¶mInfo)
229 std::string paramMessage, paramType, paramDescription;
232 std::string cmdLineName =
"-";
233 const std::string camelCaseName = paramInfo.paramName;
234 for (
unsigned i = 0; i < camelCaseName.size(); ++i) {
235 if (isupper(camelCaseName[i]))
237 cmdLineName +=
static_cast<char>(std::tolower(camelCaseName[i]));
242 paramMessage += cmdLineName;
245 if (paramInfo.paramTypeName ==
"std::string"
246 || paramInfo.paramTypeName ==
"const char *")
247 paramMessage +=
"=STRING";
248 else if (paramInfo.paramTypeName ==
"float"
249 || paramInfo.paramTypeName ==
"double"
250 || paramInfo.paramTypeName ==
"long double"
251 || paramInfo.paramTypeName ==
"quad")
252 paramMessage +=
"=SCALAR";
253 else if (paramInfo.paramTypeName ==
"int"
254 || paramInfo.paramTypeName ==
"unsigned int"
255 || paramInfo.paramTypeName ==
"short"
256 || paramInfo.paramTypeName ==
"unsigned short")
257 paramMessage +=
"=INTEGER";
258 else if (paramInfo.paramTypeName ==
"bool")
259 paramMessage +=
"=BOOLEAN";
260 else if (paramInfo.paramTypeName.empty()) {
265 paramMessage +=
"=VALUE";
270 while (paramMessage.size() < 50)
274 paramMessage += paramInfo.usageString;
275 paramMessage +=
"\n";
281 void getFlattenedKeyList_(std::list<std::string> &dest,
282 const Dune::ParameterTree &tree,
283 const std::string &prefix)
286 auto keyIt = tree.getValueKeys().begin();
287 const auto &keyEndIt = tree.getValueKeys().end();
288 for (; keyIt != keyEndIt; ++keyIt) {
289 std::string newKey(prefix);
291 dest.push_back(newKey);
295 auto subStructIt = tree.getSubKeys().begin();
296 const auto &subStructEndIt = tree.getSubKeys().end();
297 for (; subStructIt != subStructEndIt; ++subStructIt) {
298 std::string newPrefix(prefix);
299 newPrefix += *subStructIt;
302 getFlattenedKeyList_(dest, tree.sub(*subStructIt), newPrefix);
307 template <
class TypeTag>
308 void printParamList_(std::ostream &os,
const std::list<std::string> &keyList)
310 typedef typename GET_PROP(TypeTag, ParameterMetaData) ParamsMeta;
312 const Dune::ParameterTree &tree = ParamsMeta::tree();
314 auto keyIt = keyList.begin();
315 const auto &keyEndIt = keyList.end();
316 for (; keyIt != keyEndIt; ++keyIt) {
317 std::string value = ParamsMeta::registry().at(*keyIt).compileTimeValue;
318 if (tree.hasKey(*keyIt))
319 value = tree.get(*keyIt,
"");
320 os << *keyIt <<
"=\"" << value <<
"\"\n";
325 template <
class TypeTag>
326 void printCompileTimeParamList_(std::ostream &os,
327 const std::list<std::string> &keyList)
329 typedef typename GET_PROP(TypeTag, ParameterMetaData) ParamsMeta;
331 auto keyIt = keyList.begin();
332 const auto &keyEndIt = keyList.end();
333 for (; keyIt != keyEndIt; ++keyIt) {
334 const auto ¶mInfo = ParamsMeta::registry().at(*keyIt);
335 os << *keyIt <<
"=\"" << paramInfo.compileTimeValue
336 <<
"\" # property: " << paramInfo.propertyName <<
"\n";
349 template <
class TypeTag>
350 void printUsage(
const std::string &progName,
const std::string &errorMsg =
"",
351 bool handleHelp =
true, std::ostream &os = std::cerr)
353 typedef typename GET_PROP(TypeTag, ParameterMetaData) ParamsMeta;
356 if (errorMsg !=
"") {
357 os << errorMsg <<
"\n"
361 os <<
"Usage: " << progName <<
" [OPTIONS]\n";
365 os <<
"Recognized options:\n";
369 pInfo.paramName =
"h,--help";
370 pInfo.usageString =
"Print this help message and exit";
371 printParamUsage_(os, pInfo);
374 auto paramIt = ParamsMeta::registry().begin();
375 const auto ¶mEndIt = ParamsMeta::registry().end();
376 for (; paramIt != paramEndIt; ++paramIt) {
377 printParamUsage_(os, paramIt->second);
396 template <
class TypeTag>
399 Dune::ParameterTree ¶mTree =
GET_PROP(TypeTag, ParameterMetaData)::tree();
402 for (
int i = 1; i < argc; ++i) {
403 if (std::string(
"-h") == argv[i]
404 || std::string(
"--help") == argv[i]) {
405 printUsage<TypeTag>(argv[0],
"", handleHelp, std::cout);
406 return "Help called";
412 for (
int i = 1; i < argc; ++i) {
413 if (argv[i][0] !=
'-') {
414 std::ostringstream oss;
415 oss <<
"Command line argument " << i
416 <<
" (='" << argv[i] <<
"') is invalid.";
419 printUsage<TypeTag>(argv[0], oss.str(), handleHelp, std::cerr);
424 std::string paramName, paramValue;
429 if (argv[i][1] ==
'-') {
431 if (argv[i][2] == 0 || !std::isalpha(argv[i][2])) {
432 std::ostringstream oss;
433 oss <<
"Parameter name of argument " << i
434 <<
" ('" << argv[i] <<
"') "
435 <<
"is invalid because it does not start with a letter.";
438 printUsage<TypeTag>(argv[0], oss.str(), handleHelp,
445 std::string s(argv[i] + 2);
457 else if (s[j] ==
'=') {
461 paramName = s.substr(0, j);
462 paramValue = s.substr(j + 1);
465 else if (s[j] ==
'-') {
470 std::ostringstream oss;
471 oss <<
"Parameter name of argument " << i
472 <<
" ('" << argv[i] <<
"')"
473 <<
" is invalid (ends with a '-' character).";
476 printUsage<TypeTag>(argv[0], oss.str(), handleHelp,
480 else if (s[j] ==
'-') {
481 std::ostringstream oss;
482 oss <<
"Malformed parameter name in argument " << i
483 <<
" ('" << argv[i] <<
"'): "
484 <<
"'--' in parameter name.";
487 printUsage<TypeTag>(argv[0], oss.str(), handleHelp,
491 s[j] =
static_cast<char>(std::toupper(s[j]));
493 else if (!std::isalnum(s[j])) {
494 std::ostringstream oss;
495 oss <<
"Parameter name of argument " << i
496 <<
" ('" << argv[i] <<
"')"
497 <<
" is invalid (character '" << s[j]
498 <<
"' is not a letter or digit).";
501 printUsage<TypeTag>(argv[0], oss.str(), handleHelp,
512 paramName = argv[i] + 1;
514 if (argc == i + 1 || argv[i + 1][0] ==
'-') {
515 std::ostringstream oss;
516 oss <<
"No argument given for parameter '" << argv[i] <<
"'!";
518 printUsage<TypeTag>(argv[0], oss.str(), handleHelp,
523 paramValue = argv[i + 1];
528 paramName[0] =
static_cast<char>(std::toupper(paramName[0]));
531 paramTree[paramName] = paramValue;
542 template <
class TypeTag>
545 typedef typename GET_PROP(TypeTag, ParameterMetaData) ParamsMeta;
547 const Dune::ParameterTree &tree = ParamsMeta::tree();
549 std::list<std::string> runTimeAllKeyList;
550 std::list<std::string> runTimeKeyList;
551 std::list<std::string> unknownKeyList;
553 getFlattenedKeyList_(runTimeAllKeyList, tree);
554 auto keyIt = runTimeAllKeyList.begin();
555 const auto &keyEndIt = runTimeAllKeyList.end();
556 for (; keyIt != keyEndIt; ++keyIt) {
557 if (ParamsMeta::registry().find(*keyIt) == ParamsMeta::registry().end()) {
559 unknownKeyList.push_back(*keyIt);
563 runTimeKeyList.push_back(*keyIt);
568 std::list<std::string> compileTimeKeyList;
569 auto paramInfoIt = ParamsMeta::registry().begin();
570 const auto ¶mInfoEndIt = ParamsMeta::registry().end();
571 for (; paramInfoIt != paramInfoEndIt; ++paramInfoIt) {
573 const auto &keyName = paramInfoIt->first;
574 if (tree.hasKey(keyName))
577 compileTimeKeyList.push_back(keyName);
582 if (runTimeKeyList.size() > 0) {
583 os <<
"# [known parameters which were specified at run-time]\n";
584 printParamList_<TypeTag>(os, runTimeKeyList);
587 if (compileTimeKeyList.size() > 0) {
588 os <<
"# [parameters which were specified at compile-time]\n";
589 printCompileTimeParamList_<TypeTag>(os, compileTimeKeyList);
592 if (unknownKeyList.size() > 0) {
593 os <<
"# [unused run-time specified parameters]\n";
594 auto unusedKeyIt = unknownKeyList.begin();
595 const auto &unusedKeyEndIt = unknownKeyList.end();
596 for (; unusedKeyIt != unusedKeyEndIt; ++unusedKeyIt) {
597 os << *unusedKeyIt <<
"=\"" << tree.get(*unusedKeyIt,
"") <<
"\"\n" << std::flush;
610 template <
class TypeTag>
613 typedef typename GET_PROP(TypeTag, ParameterMetaData) ParamsMeta;
615 const Dune::ParameterTree &tree = ParamsMeta::tree();
616 std::list<std::string> runTimeAllKeyList;
617 std::list<std::string> unknownKeyList;
619 getFlattenedKeyList_(runTimeAllKeyList, tree);
620 auto keyIt = runTimeAllKeyList.begin();
621 const auto &keyEndIt = runTimeAllKeyList.end();
622 for (; keyIt != keyEndIt; ++keyIt) {
623 if (ParamsMeta::registry().find(*keyIt) == ParamsMeta::registry().end()) {
625 unknownKeyList.push_back(*keyIt);
629 if (unknownKeyList.size() > 0) {
630 os <<
"# [unused run-time specified parameters]\n";
631 auto unusedKeyIt = unknownKeyList.begin();
632 const auto &unusedKeyEndIt = unknownKeyList.end();
633 for (; unusedKeyIt != unusedKeyEndIt; ++unusedKeyIt) {
634 os << *unusedKeyIt <<
"=\"" << tree.get(*unusedKeyIt,
"") <<
"\"\n" << std::flush;
642 template <
class TypeTag>
645 typedef typename GET_PROP(TypeTag, ParameterMetaData) ParamsMeta;
648 template <class ParamType, class PropTag>
649 static const ParamType &get(const
char *propTagName, const
char *paramName,
650 bool errorIfNotRegistered = true)
652 static const ParamType &value =
653 retrieve_<ParamType, PropTag>(propTagName,
655 errorIfNotRegistered);
662 std::string propertyName;
663 std::string paramTypeName;
664 std::string groupName;
666 Blubb &operator=(
const Blubb &b)
668 propertyName = b.propertyName;
669 paramTypeName = b.paramTypeName;
670 groupName = b.groupName;
675 static void check_(
const std::string ¶mTypeName,
676 const std::string &propertyName,
const char *paramName)
678 typedef std::unordered_map<std::string, Blubb> StaticData;
679 static StaticData staticData;
681 typename StaticData::iterator it = staticData.find(paramName);
683 if (it == staticData.end()) {
685 a.propertyName = propertyName;
686 a.paramTypeName = paramTypeName;
687 staticData[paramName] = a;
688 b = &staticData[paramName];
693 if (b->propertyName != propertyName) {
694 OPM_THROW(std::logic_error,
695 "GET_*_PARAM for parameter '" << paramName
696 <<
"' called for at least two different properties ('"
697 << b->propertyName <<
"' and '" << propertyName <<
"')");
700 if (b->paramTypeName != paramTypeName) {
701 OPM_THROW(std::logic_error,
702 "GET_*_PARAM for parameter '" << paramName
703 <<
"' called with at least two different types ("
704 << b->paramTypeName <<
" and " << paramTypeName <<
")");
708 template <
class ParamType,
class PropTag>
709 static const ParamType &retrieve_(
const char *propTagName,
710 const char *paramName,
711 bool errorIfNotRegistered =
true)
717 check_(Opm::className<ParamType>(), propTagName, paramName);
720 typedef typename GET_PROP(TypeTag, ParameterMetaData) ParamsMeta;
721 if (errorIfNotRegistered) {
722 if (ParamsMeta::registrationOpen())
723 OPM_THROW(std::runtime_error,
"Parameters can only retieved "
724 "after _all_ of them have been "
727 if (ParamsMeta::registry().find(paramName) == ParamsMeta::registry().end())
728 OPM_THROW(std::runtime_error,
729 "Accessing parameter " << paramName
730 <<
" without prior registration is not allowed.");
739 std::string canonicalName(paramName);
742 ParameterGroupPrefix));
743 if (modelParamGroup.size()) {
744 canonicalName.insert(0,
".");
745 canonicalName.insert(0, modelParamGroup);
749 const ParamType defaultValue = GET_PROP_VALUE_(TypeTag, PropTag);
750 static ParamType value =
751 ParamsMeta::tree().template get<ParamType>(canonicalName, defaultValue);
757 template <
class TypeTag,
class ParamType,
class PropTag>
758 const ParamType &
get(
const char *propTagName,
const char *paramName,
759 bool errorIfNotRegistered)
761 return Param<TypeTag>::template get<ParamType, PropTag>(propTagName,
763 errorIfNotRegistered);
766 template <
class TypeTag,
class ParamType,
class PropTag>
767 void registerParam(
const char *paramName,
const char *propertyName,
const char *usageString)
769 typedef typename GET_PROP(TypeTag, ParameterMetaData) ParamsMeta;
770 if (!ParamsMeta::registrationOpen())
771 OPM_THROW(
std::logic_error,
772 "Parameter registration was already closed before "
773 "the parameter '" << paramName << "' was registered.");
775 ParamsMeta::registrationFinalizers().push_back(
776 new ParamRegFinalizer_<TypeTag, ParamType, PropTag>(paramName));
779 paramInfo.paramName = paramName;
780 paramInfo.paramTypeName = Opm::className<ParamType>();
781 std::
string tmp = Opm::className<TypeTag>();
782 tmp.replace(0, strlen("Opm::Properties::TTag::"), "");
783 paramInfo.propertyName = propertyName;
784 paramInfo.usageString = usageString;
785 std::ostringstream oss;
786 oss << GET_PROP_VALUE_(TypeTag, PropTag);
787 paramInfo.compileTimeValue = oss.str();
788 if (ParamsMeta::registry().find(paramName) != ParamsMeta::registry().end()) {
791 if (ParamsMeta::registry().at(paramName) == paramInfo)
793 OPM_THROW(std::logic_error,
794 "Parameter " << paramName
795 <<
" registered twice with non-matching characteristics.");
798 ParamsMeta::mutableRegistry()[paramName] = paramInfo;
801 template <
class TypeTag>
802 void endParamRegistration()
804 typedef typename GET_PROP(TypeTag, ParameterMetaData) ParamsMeta;
805 if (!ParamsMeta::registrationOpen())
806 OPM_THROW(
std::logic_error,
807 "Parameter registration was already "
808 "closed. It is only possible to close it "
811 ParamsMeta::registrationOpen() = false;
815 auto pIt = ParamsMeta::registrationFinalizers().begin();
816 const auto &pEndIt = ParamsMeta::registrationFinalizers().end();
817 for (; pIt != pEndIt; ++pIt) {
std::string parseCommandLineOptions(int argc, char **argv, bool handleHelp=true)
Parse the parameters provided on the command line.
Definition: parametersystem.hh:397
#define GET_PROP(TypeTag, PropTagName)
Retrieve a property for a type tag.
Definition: propertysystem.hh:453
#define GET_PROP_VALUE(TypeTag, PropTagName)
Access the value attribute of a property for a type tag.
Definition: propertysystem.hh:468
void printUsage(const std::string &progName, const std::string &errorMsg="", bool handleHelp=true, std::ostream &os=std::cerr)
Print a usage message for all run-time parameters.
Definition: parametersystem.hh:350
void printValues(std::ostream &os=std::cout)
Print values of the run-time parameters.
Definition: parametersystem.hh:543
SET_PROP(NumericModel, ParameterTree)
Set the ParameterTree property.
Definition: basicproperties.hh:117
NEW_PROP_TAG(Grid)
The type of the DUNE grid.
Definition: baseauxiliarymodule.hh:35
bool printUnused(std::ostream &os=std::cout)
Print the list of unused run-time parameters.
Definition: parametersystem.hh:611
Provides the magic behind the eWoms property system.
SET_STRING_PROP(NumericModel, ModelParameterGroup,"")
use the global group as default for the model's parameter group