32 #ifndef EWOMS_PARAMETERS_HH 33 #define EWOMS_PARAMETERS_HH 37 #include <opm/common/ErrorMacros.hpp> 38 #include <opm/common/Exceptions.hpp> 39 #include <opm/common/Unused.hpp> 41 #include <dune/common/classname.hh> 42 #include <dune/common/parametertree.hh> 49 #include <unordered_map> 68 #define EWOMS_REGISTER_PARAM(TypeTag, ParamType, ParamName, Description) \ 69 ::Ewoms::Parameters::registerParam<TypeTag, ParamType, PTAG(ParamName)>( \ 70 #ParamName, #ParamName, Description) 81 #define EWOMS_END_PARAM_REGISTRATION(TypeTag) \ 82 ::Ewoms::Parameters::endParamRegistration<TypeTag>() 99 #define EWOMS_GET_PARAM(TypeTag, ParamType, ParamName) \ 100 (::Ewoms::Parameters::get<TypeTag, ParamType, PTAG(ParamName)>(#ParamName, \ 104 #define EWOMS_GET_PARAM_(TypeTag, ParamType, ParamName) \ 105 (::Ewoms::Parameters::get<TypeTag, ParamType, PTAG(ParamName)>( \ 106 #ParamName, #ParamName, \ 110 namespace Parameters {
114 std::string paramName;
115 std::string paramTypeName;
116 std::string typeTagName;
117 std::string propertyName;
118 std::string usageString;
119 std::string compileTimeValue;
121 bool operator==(
const ParamInfo& other)
const 123 return other.paramName == paramName
124 && other.paramTypeName == paramTypeName
125 && other.typeTagName == typeTagName
126 && other.propertyName == propertyName
127 && other.usageString == usageString
128 && other.compileTimeValue == compileTimeValue;
133 template <
class TypeTag,
class ParamType,
class PropTag>
134 const ParamType&
get(
const char *propTagName,
const char *paramName,
135 bool errorIfNotRegistered =
true);
137 class ParamRegFinalizerBase_
140 virtual ~ParamRegFinalizerBase_()
142 virtual void retrieve() = 0;
145 template <
class TypeTag,
class ParamType,
class PropTag>
146 class ParamRegFinalizer_ :
public ParamRegFinalizerBase_
149 ParamRegFinalizer_(
const std::string& paramName) : paramName_(paramName)
156 ParamType __attribute__((unused)) dummy =
157 get<TypeTag, ParamType, PropTag>(paramName_.data(),
163 std::string paramName_;
167 namespace Properties {
178 SET_PROP(ParameterSystem, ParameterMetaData)
180 typedef Dune::ParameterTree type;
182 static Dune::ParameterTree& tree()
183 {
return storage_().tree; }
185 static std::map<std::string, ::Ewoms::Parameters::ParamInfo>& mutableRegistry()
186 {
return storage_().registry; }
188 static const std::map<std::string, ::Ewoms::Parameters::ParamInfo>& registry()
189 {
return storage_().registry; }
191 static std::list< ::Ewoms::Parameters::ParamRegFinalizerBase_ *> &
192 registrationFinalizers()
193 {
return storage_().finalizers; }
195 static bool& registrationOpen()
196 {
return storage_().registrationOpen; }
205 { registrationOpen =
true; }
207 Dune::ParameterTree tree;
208 std::map<std::string, ::Ewoms::Parameters::ParamInfo> registry;
209 std::list< ::Ewoms::Parameters::ParamRegFinalizerBase_ *> finalizers;
210 bool registrationOpen;
212 static Storage_& storage_() {
223 namespace Parameters {
225 void printParamUsage_(std::ostream& os,
const ParamInfo& paramInfo);
226 void getFlattenedKeyList_(std::list<std::string>& dest,
227 const Dune::ParameterTree& tree,
228 const std::string& prefix =
"");
231 inline void printParamUsage_(std::ostream& os,
const ParamInfo& paramInfo)
233 std::string paramMessage, paramType, paramDescription;
236 std::string cmdLineName =
"-";
237 const std::string camelCaseName = paramInfo.paramName;
238 for (
unsigned i = 0; i < camelCaseName.size(); ++i) {
239 if (isupper(camelCaseName[i]))
241 cmdLineName +=
static_cast<char>(std::tolower(camelCaseName[i]));
246 paramMessage += cmdLineName;
249 if (paramInfo.paramTypeName ==
"std::string" 250 || paramInfo.paramTypeName ==
"const char *")
251 paramMessage +=
"=STRING";
252 else if (paramInfo.paramTypeName ==
"float" 253 || paramInfo.paramTypeName ==
"double" 254 || paramInfo.paramTypeName ==
"long double" 255 || paramInfo.paramTypeName ==
"quad")
256 paramMessage +=
"=SCALAR";
257 else if (paramInfo.paramTypeName ==
"int" 258 || paramInfo.paramTypeName ==
"unsigned int" 259 || paramInfo.paramTypeName ==
"short" 260 || paramInfo.paramTypeName ==
"unsigned short")
261 paramMessage +=
"=INTEGER";
262 else if (paramInfo.paramTypeName ==
"bool")
263 paramMessage +=
"=BOOLEAN";
264 else if (paramInfo.paramTypeName.empty()) {
269 paramMessage +=
"=VALUE";
274 while (paramMessage.size() < 50)
278 paramMessage += paramInfo.usageString;
279 paramMessage +=
"\n";
285 inline void getFlattenedKeyList_(std::list<std::string>& dest,
286 const Dune::ParameterTree& tree,
287 const std::string& prefix)
290 auto keyIt = tree.getValueKeys().begin();
291 const auto& keyEndIt = tree.getValueKeys().end();
292 for (; keyIt != keyEndIt; ++keyIt) {
293 std::string newKey(prefix);
295 dest.push_back(newKey);
299 auto subStructIt = tree.getSubKeys().begin();
300 const auto& subStructEndIt = tree.getSubKeys().end();
301 for (; subStructIt != subStructEndIt; ++subStructIt) {
302 std::string newPrefix(prefix);
303 newPrefix += *subStructIt;
306 getFlattenedKeyList_(dest, tree.sub(*subStructIt), newPrefix);
311 template <
class TypeTag>
312 void printParamList_(std::ostream& os,
const std::list<std::string>& keyList)
314 typedef typename GET_PROP(TypeTag, ParameterMetaData) ParamsMeta;
316 const Dune::ParameterTree& tree = ParamsMeta::tree();
318 auto keyIt = keyList.begin();
319 const auto& keyEndIt = keyList.end();
320 for (; keyIt != keyEndIt; ++keyIt) {
321 std::string value = ParamsMeta::registry().at(*keyIt).compileTimeValue;
322 if (tree.hasKey(*keyIt))
323 value = tree.get(*keyIt,
"");
324 os << *keyIt <<
"=\"" << value <<
"\"\n";
329 template <
class TypeTag>
330 void printCompileTimeParamList_(std::ostream& os,
331 const std::list<std::string>& keyList)
333 typedef typename GET_PROP(TypeTag, ParameterMetaData) ParamsMeta;
335 auto keyIt = keyList.begin();
336 const auto& keyEndIt = keyList.end();
337 for (; keyIt != keyEndIt; ++keyIt) {
338 const auto& paramInfo = ParamsMeta::registry().at(*keyIt);
339 os << *keyIt <<
"=\"" << paramInfo.compileTimeValue
340 <<
"\" # property: " << paramInfo.propertyName <<
"\n";
353 template <
class TypeTag>
354 void printUsage(
const std::string& progName,
const std::string& errorMsg =
"",
355 bool handleHelp =
true, std::ostream& os = std::cerr)
357 typedef typename GET_PROP(TypeTag, ParameterMetaData) ParamsMeta;
360 if (errorMsg !=
"") {
361 os << errorMsg <<
"\n" 365 os <<
"Usage: " << progName <<
" [OPTIONS]\n";
369 os <<
"Recognized options:\n";
373 pInfo.paramName =
"h,--help";
374 pInfo.usageString =
"Print this help message and exit";
375 printParamUsage_(os, pInfo);
378 auto paramIt = ParamsMeta::registry().begin();
379 const auto& paramEndIt = ParamsMeta::registry().end();
380 for (; paramIt != paramEndIt; ++paramIt) {
381 printParamUsage_(os, paramIt->second);
400 template <
class TypeTag>
403 Dune::ParameterTree& paramTree =
GET_PROP(TypeTag, ParameterMetaData)::tree();
406 for (
int i = 1; i < argc; ++i) {
407 if (std::string(
"-h") == argv[i]
408 || std::string(
"--help") == argv[i]) {
409 printUsage<TypeTag>(argv[0],
"", handleHelp, std::cout);
410 return "Help called";
416 for (
int i = 1; i < argc; ++i) {
417 if (argv[i][0] !=
'-') {
418 std::ostringstream oss;
419 oss <<
"Command line argument " << i
420 <<
" (='" << argv[i] <<
"') is invalid.";
423 printUsage<TypeTag>(argv[0], oss.str(), handleHelp, std::cerr);
428 std::string paramName, paramValue;
433 if (argv[i][1] ==
'-') {
435 if (argv[i][2] == 0 || !std::isalpha(argv[i][2])) {
436 std::ostringstream oss;
437 oss <<
"Parameter name of argument " << i
438 <<
" ('" << argv[i] <<
"') " 439 <<
"is invalid because it does not start with a letter.";
442 printUsage<TypeTag>(argv[0], oss.str(), handleHelp,
449 std::string s(argv[i] + 2);
461 else if (s[j] ==
'=') {
465 paramName = s.substr(0, j);
466 paramValue = s.substr(j + 1);
469 else if (s[j] ==
'-') {
474 std::ostringstream oss;
475 oss <<
"Parameter name of argument " << i
476 <<
" ('" << argv[i] <<
"')" 477 <<
" is invalid (ends with a '-' character).";
480 printUsage<TypeTag>(argv[0], oss.str(), handleHelp,
484 else if (s[j] ==
'-') {
485 std::ostringstream oss;
486 oss <<
"Malformed parameter name in argument " << i
487 <<
" ('" << argv[i] <<
"'): " 488 <<
"'--' in parameter name.";
491 printUsage<TypeTag>(argv[0], oss.str(), handleHelp,
495 s[j] =
static_cast<char>(std::toupper(s[j]));
497 else if (!std::isalnum(s[j])) {
498 std::ostringstream oss;
499 oss <<
"Parameter name of argument " << i
500 <<
" ('" << argv[i] <<
"')" 501 <<
" is invalid (character '" << s[j]
502 <<
"' is not a letter or digit).";
505 printUsage<TypeTag>(argv[0], oss.str(), handleHelp,
516 paramName = argv[i] + 1;
518 if (argc == i + 1 || argv[i + 1][0] ==
'-') {
519 std::ostringstream oss;
520 oss <<
"No argument given for parameter '" << argv[i] <<
"'!";
522 printUsage<TypeTag>(argv[0], oss.str(), handleHelp,
527 paramValue = argv[i + 1];
532 paramName[0] =
static_cast<char>(std::toupper(paramName[0]));
535 paramTree[paramName] = paramValue;
546 template <
class TypeTag>
549 typedef typename GET_PROP(TypeTag, ParameterMetaData) ParamsMeta;
551 const Dune::ParameterTree& tree = ParamsMeta::tree();
553 std::list<std::string> runTimeAllKeyList;
554 std::list<std::string> runTimeKeyList;
555 std::list<std::string> unknownKeyList;
557 getFlattenedKeyList_(runTimeAllKeyList, tree);
558 auto keyIt = runTimeAllKeyList.begin();
559 const auto& keyEndIt = runTimeAllKeyList.end();
560 for (; keyIt != keyEndIt; ++keyIt) {
561 if (ParamsMeta::registry().find(*keyIt) == ParamsMeta::registry().end()) {
563 unknownKeyList.push_back(*keyIt);
567 runTimeKeyList.push_back(*keyIt);
572 std::list<std::string> compileTimeKeyList;
573 auto paramInfoIt = ParamsMeta::registry().begin();
574 const auto& paramInfoEndIt = ParamsMeta::registry().end();
575 for (; paramInfoIt != paramInfoEndIt; ++paramInfoIt) {
577 const auto& keyName = paramInfoIt->first;
578 if (tree.hasKey(keyName))
581 compileTimeKeyList.push_back(keyName);
586 if (runTimeKeyList.size() > 0) {
587 os <<
"# [known parameters which were specified at run-time]\n";
588 printParamList_<TypeTag>(os, runTimeKeyList);
591 if (compileTimeKeyList.size() > 0) {
592 os <<
"# [parameters which were specified at compile-time]\n";
593 printCompileTimeParamList_<TypeTag>(os, compileTimeKeyList);
596 if (unknownKeyList.size() > 0) {
597 os <<
"# [unused run-time specified parameters]\n";
598 auto unusedKeyIt = unknownKeyList.begin();
599 const auto& unusedKeyEndIt = unknownKeyList.end();
600 for (; unusedKeyIt != unusedKeyEndIt; ++unusedKeyIt) {
601 os << *unusedKeyIt <<
"=\"" << tree.get(*unusedKeyIt,
"") <<
"\"\n" << std::flush;
614 template <
class TypeTag>
617 typedef typename GET_PROP(TypeTag, ParameterMetaData) ParamsMeta;
619 const Dune::ParameterTree& tree = ParamsMeta::tree();
620 std::list<std::string> runTimeAllKeyList;
621 std::list<std::string> unknownKeyList;
623 getFlattenedKeyList_(runTimeAllKeyList, tree);
624 auto keyIt = runTimeAllKeyList.begin();
625 const auto& keyEndIt = runTimeAllKeyList.end();
626 for (; keyIt != keyEndIt; ++keyIt) {
627 if (ParamsMeta::registry().find(*keyIt) == ParamsMeta::registry().end()) {
629 unknownKeyList.push_back(*keyIt);
633 if (unknownKeyList.size() > 0) {
634 os <<
"# [unused run-time specified parameters]\n";
635 auto unusedKeyIt = unknownKeyList.begin();
636 const auto& unusedKeyEndIt = unknownKeyList.end();
637 for (; unusedKeyIt != unusedKeyEndIt; ++unusedKeyIt) {
638 os << *unusedKeyIt <<
"=\"" << tree.get(*unusedKeyIt,
"") <<
"\"\n" << std::flush;
646 template <
class TypeTag>
649 typedef typename GET_PROP(TypeTag, ParameterMetaData) ParamsMeta;
652 template <
class ParamType,
class PropTag>
653 static const ParamType&
get(
const char *propTagName,
const char *paramName,
654 bool errorIfNotRegistered =
true)
656 static const ParamType& value =
657 retrieve_<ParamType, PropTag>(propTagName,
659 errorIfNotRegistered);
666 std::string propertyName;
667 std::string paramTypeName;
668 std::string groupName;
670 Blubb& operator=(
const Blubb& b)
672 propertyName = b.propertyName;
673 paramTypeName = b.paramTypeName;
674 groupName = b.groupName;
679 static void check_(
const std::string& paramTypeName,
680 const std::string& propertyName,
const char *paramName)
682 typedef std::unordered_map<std::string, Blubb> StaticData;
683 static StaticData staticData;
685 typename StaticData::iterator it = staticData.find(paramName);
687 if (it == staticData.end()) {
689 a.propertyName = propertyName;
690 a.paramTypeName = paramTypeName;
691 staticData[paramName] = a;
692 b = &staticData[paramName];
697 if (b->propertyName != propertyName) {
698 OPM_THROW(std::logic_error,
699 "GET_*_PARAM for parameter '" << paramName
700 <<
"' called for at least two different properties ('" 701 << b->propertyName <<
"' and '" << propertyName <<
"')");
704 if (b->paramTypeName != paramTypeName) {
705 OPM_THROW(std::logic_error,
706 "GET_*_PARAM for parameter '" << paramName
707 <<
"' called with at least two different types (" 708 << b->paramTypeName <<
" and " << paramTypeName <<
")");
712 template <
class ParamType,
class PropTag>
713 static const ParamType& retrieve_(
const char OPM_OPTIM_UNUSED *propTagName,
714 const char *paramName,
715 bool errorIfNotRegistered =
true)
721 check_(Dune::className<ParamType>(), propTagName, paramName);
724 typedef typename GET_PROP(TypeTag, ParameterMetaData) ParamsMeta;
725 if (errorIfNotRegistered) {
726 if (ParamsMeta::registrationOpen())
727 OPM_THROW(std::runtime_error,
"Parameters can only retieved " 728 "after _all_ of them have been " 731 if (ParamsMeta::registry().find(paramName) == ParamsMeta::registry().end())
732 OPM_THROW(std::runtime_error,
733 "Accessing parameter " << paramName
734 <<
" without prior registration is not allowed.");
743 std::string canonicalName(paramName);
746 ParameterGroupPrefix));
747 if (modelParamGroup.size()) {
748 canonicalName.insert(0,
".");
749 canonicalName.insert(0, modelParamGroup);
753 const ParamType defaultValue =
754 GET_PROP_VALUE_(TypeTag, PropTag);
755 static ParamType value =
756 ParamsMeta::tree().template get<ParamType>(canonicalName, defaultValue);
762 template <
class TypeTag,
class ParamType,
class PropTag>
763 const ParamType&
get(
const char *propTagName,
const char *paramName,
764 bool errorIfNotRegistered)
766 return Param<TypeTag>::template get<ParamType, PropTag>(propTagName,
768 errorIfNotRegistered);
771 template <
class TypeTag,
class ParamType,
class PropTag>
772 void registerParam(
const char *paramName,
const char *propertyName,
const char *usageString)
774 typedef typename GET_PROP(TypeTag, ParameterMetaData) ParamsMeta;
775 if (!ParamsMeta::registrationOpen())
776 OPM_THROW(std::logic_error,
777 "Parameter registration was already closed before " 778 "the parameter '" << paramName <<
"' was registered.");
780 ParamsMeta::registrationFinalizers().push_back(
781 new ParamRegFinalizer_<TypeTag, ParamType, PropTag>(paramName));
784 paramInfo.paramName = paramName;
785 paramInfo.paramTypeName = Dune::className<ParamType>();
786 std::string tmp = Dune::className<TypeTag>();
787 tmp.replace(0, strlen(
"Opm::Properties::TTag::"),
"");
788 paramInfo.propertyName = propertyName;
789 paramInfo.usageString = usageString;
790 std::ostringstream oss;
791 oss << GET_PROP_VALUE_(TypeTag, PropTag);
792 paramInfo.compileTimeValue = oss.str();
793 if (ParamsMeta::registry().find(paramName) != ParamsMeta::registry().end()) {
796 if (ParamsMeta::registry().at(paramName) == paramInfo)
798 OPM_THROW(std::logic_error,
799 "Parameter " << paramName
800 <<
" registered twice with non-matching characteristics.");
803 ParamsMeta::mutableRegistry()[paramName] = paramInfo;
806 template <
class TypeTag>
807 void endParamRegistration()
809 typedef typename GET_PROP(TypeTag, ParameterMetaData) ParamsMeta;
810 if (!ParamsMeta::registrationOpen())
811 OPM_THROW(std::logic_error,
812 "Parameter registration was already " 813 "closed. It is only possible to close it " 816 ParamsMeta::registrationOpen() =
false;
820 auto pIt = ParamsMeta::registrationFinalizers().begin();
821 const auto& pEndIt = ParamsMeta::registrationFinalizers().end();
822 for (; pIt != pEndIt; ++pIt) {
Definition: baseauxiliarymodule.hh:37
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:354
#define GET_PROP_VALUE(TypeTag, PropTagName)
Access the value attribute of a property for a type tag.
Definition: propertysystem.hh:469
std::string parseCommandLineOptions(int argc, char **argv, bool handleHelp=true)
Parse the parameters provided on the command line.
Definition: parametersystem.hh:401
#define NEW_TYPE_TAG(...)
Define a new type tag.
Definition: propertysystem.hh:169
void printValues(std::ostream &os=std::cout)
Print values of the run-time parameters.
Definition: parametersystem.hh:547
#define SET_PROP(EffTypeTagName, PropTagName)
Set a property for a specific type tag.
Definition: propertysystem.hh:297
Provides the magic behind the eWoms property system.
bool printUnused(std::ostream &os=std::cout)
Print the list of unused run-time parameters.
Definition: parametersystem.hh:615
#define NEW_PROP_TAG(PTagName)
Define a property tag.
Definition: propertysystem.hh:247
#define GET_PROP(TypeTag, PropTagName)
Retrieve a property for a type tag.
Definition: propertysystem.hh:454
#define SET_STRING_PROP(EffTypeTagName, PropTagName,...)
Set a property to a simple constant string value.
Definition: propertysystem.hh:416