32#ifndef OPM_PARAMETER_SYSTEM_HH
33#define OPM_PARAMETER_SYSTEM_HH
38#include <opm/material/common/quad.hpp>
41#include <dune/common/classname.hh>
42#include <dune/common/parametertree.hh>
95template <
class TypeTag,
template<
class,
class>
class Property>
96auto get(
bool errorIfNotRegistered =
true);
106template <
class TypeTag,
template<
class,
class>
class Property>
114 std::ignore = get<TypeTag, Property>(
true);
131template<
class TypeTag,
class MyTypeTag>
136template<
class TypeTag>
139 using type = Dune::ParameterTree;
141 static Dune::ParameterTree&
tree()
142 {
return *storage_().tree; }
145 {
return storage_().registry; }
147 static const std::map<std::string, ::Opm::Parameters::ParamInfo>&
registry()
148 {
return storage_().registry; }
151 {
return storage_().finalizers; }
154 {
return storage_().registrationOpen; }
158 storage_().tree.reset(
new Dune::ParameterTree());
159 storage_().finalizers.clear();
160 storage_().registrationOpen =
true;
161 storage_().registry.clear();
172 tree.reset(
new Dune::ParameterTree());
173 registrationOpen =
true;
176 std::unique_ptr<Dune::ParameterTree> tree;
177 std::map<std::string, ::Opm::Parameters::ParamInfo> registry;
178 std::list<std::unique_ptr<::Opm::Parameters::ParamRegFinalizerBase_> > finalizers;
179 bool registrationOpen;
181 static Storage_& storage_() {
194 const Dune::ParameterTree& tree,
195 const std::string& prefix =
"");
204 int lastBreakPos = 0;
206 for (; inPos < int(msg.size()); ++ inPos, ++ ttyPos) {
207 if (msg[inPos] ==
'\n') {
208 result += msg.substr(startInPos, inPos - startInPos + 1);
209 startInPos = inPos + 1;
210 lastBreakPos = startInPos + 1;
217 if (std::isspace(msg[inPos]))
218 lastBreakPos = inPos;
220 if (ttyPos >= maxWidth) {
221 if (lastBreakPos > startInPos) {
222 result += msg.substr(startInPos, lastBreakPos - startInPos);
223 startInPos = lastBreakPos + 1;
224 lastBreakPos = startInPos;
228 result += msg.substr(startInPos, inPos - startInPos);
230 lastBreakPos = startInPos;
235 for (
int i = 0; i < indentWidth; ++i)
237 ttyPos = indentWidth;
241 result += msg.substr(startInPos);
248 int ttyWidth = 10*1000;
249 if (isatty(STDOUT_FILENO)) {
250#if defined TIOCGWINSZ
252 struct winsize ttySize;
253 ioctl(STDOUT_FILENO, TIOCGWINSZ, &ttySize);
254 ttyWidth = std::max<int>(80, ttySize.ws_col);
266 std::string paramMessage, paramType, paramDescription;
271 std::string cmdLineName =
"-";
272 const std::string camelCaseName = paramInfo.
paramName;
273 for (
unsigned i = 0; i < camelCaseName.size(); ++i) {
274 if (isupper(camelCaseName[i]))
276 cmdLineName +=
static_cast<char>(std::tolower(camelCaseName[i]));
281 paramMessage += cmdLineName;
284 bool isString =
false;
285 if (paramInfo.
paramTypeName == Dune::className<std::string>()
288 paramMessage +=
"=STRING";
298 paramMessage +=
"=SCALAR";
300 || paramInfo.
paramTypeName == Dune::className<unsigned int>()
302 || paramInfo.
paramTypeName == Dune::className<unsigned short>())
303 paramMessage +=
"=INTEGER";
305 paramMessage +=
"=BOOLEAN";
311 paramMessage +=
"=VALUE";
316 while (paramMessage.size() < 50)
325 if (paramMessage.back() !=
'.')
327 paramMessage +=
" Default: ";
330 paramMessage +=
"false";
332 paramMessage +=
"true";
335 paramMessage +=
"\"";
337 paramMessage +=
"\"";
343 paramMessage =
breakLines_(paramMessage, 52, ttyWidth);
344 paramMessage +=
"\n";
351 const Dune::ParameterTree& tree,
352 const std::string& prefix)
355 for (
const auto& valueKey : tree.getValueKeys()) {
356 std::string newKey(prefix + valueKey);
357 dest.push_back(newKey);
361 for (
const auto& subKey : tree.getSubKeys()) {
362 std::string newPrefix(prefix + subKey +
'.');
368template <
class TypeTag>
369void printParamList_(std::ostream& os,
const std::list<std::string>& keyList,
bool printDefaults =
false)
373 const Dune::ParameterTree& tree = ParamsMeta::tree();
375 for (
const auto& key : keyList) {
376 const auto& paramInfo = ParamsMeta::registry().at(key);
377 const std::string& defaultValue = paramInfo.compileTimeValue;
378 std::string value = defaultValue;
379 if (tree.hasKey(key))
380 value = tree.get(key,
"");
381 os << key <<
"=\"" << value <<
"\"";
383 os <<
" # default: \"" << defaultValue <<
"\"";
399template <
class TypeTag>
401 const std::string& errorMsg =
"",
402 std::ostream& os = std::cerr,
403 const bool showAll =
false)
407 if (errorMsg !=
"") {
408 os << errorMsg <<
"\n"
415 os <<
"Recognized options:\n";
417 if (!helpPreamble.empty()) {
420 pInfo.
usageString =
"Print this help message and exit";
423 pInfo.
usageString =
"Print all parameters, including obsolete, hidden and deprecated ones.";
427 auto paramIt = ParamsMeta::registry().begin();
428 const auto& paramEndIt = ParamsMeta::registry().end();
429 for (; paramIt != paramEndIt; ++paramIt) {
430 if (showAll || !paramIt->second.isHidden)
436inline int noPositionalParameters_(std::set<std::string>&,
437 std::string& errorMsg,
443 errorMsg = std::string(
"Illegal parameter \"")+argv[paramIdx]+
"\".";
453 for (i = 0; i < s.size(); ++ i)
454 if (!std::isspace(s[i]))
460 bool capitalizeFirstLetter =
true,
461 const std::string& errorPrefix =
"")
466 throw std::runtime_error(errorPrefix+
"Empty parameter names are invalid");
468 if (!std::isalpha(s[0]))
469 throw std::runtime_error(errorPrefix+
"Parameter name '" + s +
"' is invalid: First character must be a letter");
471 if (capitalizeFirstLetter)
472 result +=
static_cast<char>(std::toupper(s[0]));
476 for (
unsigned i = 1; i < s.size(); ++i) {
479 if (s.size() <= i || !std::isalpha(s[i]))
480 throw std::runtime_error(errorPrefix+
"Invalid parameter name '" + s +
"'");
481 result +=
static_cast<char>(std::toupper(s[i]));
483 else if (!std::isalnum(s[i]))
484 throw std::runtime_error(errorPrefix+
"Invalid parameter name '" + s +
"'");
495 for (i = 0; i < s.size(); ++ i)
496 if (std::isspace(s[i]) || s[i] ==
'=')
499 std::string ret = s.substr(0, i);
507 if (s.empty() || s[0] !=
'"')
508 throw std::runtime_error(errorPrefix+
"Expected quoted string");
512 for (; i < s.size(); ++i) {
517 throw std::runtime_error(errorPrefix+
"Unexpected end of quoted string");
521 else if (s[i] ==
'r')
523 else if (s[i] ==
't')
525 else if (s[i] ==
'"')
527 else if (s[i] ==
'\\')
530 throw std::runtime_error(errorPrefix+
"Unknown escape character '\\" + s[i] +
"'");
532 else if (s[i] ==
'"')
545 for (i = 0; i < s.size(); ++ i)
546 if (std::isspace(s[i]))
549 std::string ret = s.substr(0, i);
570template <
class TypeTag,
class PositionalArgumentCallback>
573 const std::string& helpPreamble =
"",
574 const PositionalArgumentCallback& posArgCallback = noPositionalParameters_)
579 if (!helpPreamble.empty()) {
580 for (
int i = 1; i < argc; ++i) {
581 if (std::string(
"-h") == argv[i]
582 || std::string(
"--help") == argv[i]) {
583 printUsage<TypeTag>(helpPreamble,
"", std::cout);
584 return "Help called";
586 if (std::string(
"--help-all") == argv[i]) {
587 printUsage<TypeTag>(helpPreamble,
"", std::cout,
true);
588 return "Help called";
593 std::set<std::string> seenKeys;
594 int numPositionalParams = 0;
595 for (
int i = 1; i < argc; ++i) {
597 if (strlen(argv[i]) < 4
599 || argv[i][1] !=
'-')
601 std::string errorMsg;
602 int numHandled = posArgCallback(seenKeys, errorMsg, argc, argv, i, numPositionalParams);
604 if (numHandled < 1) {
605 std::ostringstream oss;
607 if (!helpPreamble.empty())
608 printUsage<TypeTag>(helpPreamble, errorMsg, std::cerr);
613 ++ numPositionalParams;
619 std::string paramName, paramValue;
626 if (argv[i][2] == 0 || !std::isalpha(argv[i][2])) {
627 std::ostringstream oss;
628 oss <<
"Parameter name of argument " << i
629 <<
" ('" << argv[i] <<
"') "
630 <<
"is invalid because it does not start with a letter.";
632 if (!helpPreamble.empty())
633 printUsage<TypeTag>(helpPreamble, oss.str(), std::cerr);
639 std::string s(argv[i] + 2);
643 if (seenKeys.count(paramName) > 0) {
645 std::string(
"Parameter '")+paramName+
"' specified multiple times as a "
646 "command line parameter";
648 if (!helpPreamble.empty())
649 printUsage<TypeTag>(helpPreamble, msg, std::cerr);
652 seenKeys.insert(paramName);
654 if (s.empty() || s[0] !=
'=') {
656 std::string(
"Parameter '")+paramName+
"' is missing a value. "
657 +
" Please use "+argv[i]+
"=value.";
659 if (!helpPreamble.empty())
660 printUsage<TypeTag>(helpPreamble, msg, std::cerr);
664 paramValue = s.substr(1);
667 paramTree[paramName] = paramValue;
678template <
class TypeTag>
683 std::set<std::string> seenKeys;
684 std::ifstream ifs(fileName);
685 unsigned curLineNum = 0;
689 std::getline(ifs, curLine);
691 std::string errorPrefix = fileName+
":"+std::to_string(curLineNum)+
": ";
697 if (curLine.empty() || curLine[0] ==
'#' || curLine[0] ==
';')
704 std::string canonicalKey =
transformKey_(key,
true, errorPrefix);
706 if (seenKeys.count(canonicalKey) > 0)
707 throw std::runtime_error(errorPrefix+
"Parameter '"+canonicalKey+
"' seen multiple times in the same file");
708 seenKeys.insert(canonicalKey);
712 if (curLine.empty() || curLine[0] !=
'=')
713 std::runtime_error(errorPrefix+
"Syntax error, expecting 'key=value'");
715 curLine = curLine.substr(1);
718 if (curLine.empty() || curLine[0] ==
'#' || curLine[0] ==
';')
719 std::runtime_error(errorPrefix+
"Syntax error, expecting 'key=value'");
723 if (curLine[0] ==
'"')
730 if (!curLine.empty() && curLine[0] !=
'#' && curLine[0] !=
';')
731 std::runtime_error(errorPrefix+
"Syntax error, expecting 'key=value'");
734 if (overwrite || !paramTree.hasKey(canonicalKey))
735 paramTree[canonicalKey] = value;
745template <
class TypeTag>
750 const Dune::ParameterTree& tree = ParamsMeta::tree();
752 std::list<std::string> runTimeAllKeyList;
753 std::list<std::string> runTimeKeyList;
754 std::list<std::string> unknownKeyList;
757 for (
const auto& key : runTimeAllKeyList) {
758 if (ParamsMeta::registry().find(key) == ParamsMeta::registry().end()) {
760 unknownKeyList.push_back(key);
764 runTimeKeyList.push_back(key);
769 std::list<std::string> compileTimeKeyList;
770 for (
const auto& reg : ParamsMeta::registry()) {
772 if (tree.hasKey(reg.first)) {
775 compileTimeKeyList.push_back(reg.first);
781 if (runTimeKeyList.size() > 0) {
782 os <<
"# [known parameters which were specified at run-time]\n";
783 printParamList_<TypeTag>(os, runTimeKeyList,
true);
786 if (compileTimeKeyList.size() > 0) {
787 os <<
"# [parameters which were specified at compile-time]\n";
788 printParamList_<TypeTag>(os, compileTimeKeyList,
false);
791 if (unknownKeyList.size() > 0) {
792 os <<
"# [unused run-time specified parameters]\n";
793 for (
const auto& unused : unknownKeyList) {
794 os << unused <<
"=\"" << tree.get(unused,
"") <<
"\"\n" << std::flush;
807template <
class TypeTag>
812 const Dune::ParameterTree& tree = ParamsMeta::tree();
813 std::list<std::string> runTimeAllKeyList;
814 std::list<std::string> unknownKeyList;
817 for (
const auto& key : runTimeAllKeyList) {
818 if (ParamsMeta::registry().find(key) == ParamsMeta::registry().end()) {
820 unknownKeyList.push_back(key);
824 if (unknownKeyList.size() > 0) {
825 os <<
"# [unused run-time specified parameters]\n";
826 for (
const auto& unused : unknownKeyList) {
827 os << unused <<
"=\"" << tree.get(unused,
"") <<
"\"\n" << std::flush;
834template <
class TypeTag,
template<
class,
class>
class Param>
835auto get(
bool errorIfNotRegistered)
838 const std::string paramName = getPropName<TypeTag, Param>();
839 const auto defaultValue = getPropValue<TypeTag, Param>();
840 using ParamType = std::conditional_t<std::is_same_v<
decltype(defaultValue),
841 const char*
const>, std::string,
842 std::remove_const_t<
decltype(defaultValue)>>;
843 if (errorIfNotRegistered) {
844 if (ParamsMeta::registrationOpen())
845 throw std::runtime_error(
"Parameters can only retrieved after _all_ of them have "
848 if (ParamsMeta::registry().find(paramName) == ParamsMeta::registry().end())
849 throw std::runtime_error(
"Accessing parameter " + paramName
850 +
" without prior registration is not allowed.");
860 return ParamsMeta::tree().template get<ParamType>(paramName, defaultValue);
869template <
class TypeTag,
class Container>
870void getLists(Container& usedParams, Container& unusedParams)
873 unusedParams.clear();
876 if (ParamsMeta::registrationOpen())
877 throw std::runtime_error(
"Parameter lists can only retieved after _all_ of them have "
881 std::list<std::string> allKeysList;
882 const auto& paramTree = ParamsMeta::tree();
885 for (
const auto& key : allKeysList) {
886 if (ParamsMeta::registry().find(key) == ParamsMeta::registry().end()) {
888 unusedParams.emplace_back(key, paramTree[key]);
892 usedParams.emplace_back(key, paramTree[key]);
897template <
class TypeTag>
910template <
class TypeTag,
template<
class,
class>
class Param>
911bool isSet(
bool errorIfNotRegistered =
true)
914 const std::string paramName = getPropName<TypeTag,Param>();
916 if (errorIfNotRegistered) {
917 if (ParamsMeta::registrationOpen())
918 throw std::runtime_error(
"Parameters can only checked after _all_ of them have "
921 if (ParamsMeta::registry().find(paramName) == ParamsMeta::registry().end())
922 throw std::runtime_error(
"Accessing parameter "+std::string(paramName)
923 +
" without prior registration is not allowed.");
927 return ParamsMeta::tree().hasKey(paramName);
946template <
class TypeTag,
template<
class,
class>
class Param>
950 const std::string paramName = getPropName<TypeTag,Param>();
951 if (!ParamsMeta::registrationOpen()) {
952 throw std::logic_error(
"Parameter registration was already closed before "
953 "the parameter '" + paramName +
"' was registered.");
956 const auto defaultValue = getPropValue<TypeTag, Param>();
957 using ParamType = std::conditional_t<std::is_same_v<
decltype(defaultValue),
958 const char*
const>, std::string,
959 std::remove_const_t<
decltype(defaultValue)>>;
960 ParamsMeta::registrationFinalizers().push_back(
966 std::string tmp = Dune::className<TypeTag>();
967 tmp.replace(0, strlen(
"Opm::Properties::TTag::"),
"");
969 std::ostringstream oss;
973 if (ParamsMeta::registry().find(paramName) != ParamsMeta::registry().end()) {
976 if (ParamsMeta::registry().at(paramName) == paramInfo)
978 throw std::logic_error(
"Parameter " + paramName
979 +
" registered twice with non-matching characteristics.");
982 ParamsMeta::mutableRegistry()[paramName] = paramInfo;
990template <
class TypeTag,
template<
class,
class>
class Param>
993 const std::string paramName = getPropName<TypeTag,Param>();
995 if (!ParamsMeta::registrationOpen())
996 throw std::logic_error(
"Parameter '" +paramName +
"' declared as hidden"
997 " when parameter registration was already closed.");
999 auto paramInfoIt = ParamsMeta::mutableRegistry().find(paramName);
1000 if (paramInfoIt == ParamsMeta::mutableRegistry().end())
1001 throw std::logic_error(
"Tried to declare unknown parameter '"
1002 + paramName +
"' hidden.");
1004 auto& paramInfo = paramInfoIt->second;
1005 paramInfo.isHidden =
true;
1015template <
class TypeTag>
1019 if (!ParamsMeta::registrationOpen())
1020 throw std::logic_error(
"Parameter registration was already closed. It is only possible "
1021 "to close it once.");
1023 ParamsMeta::registrationOpen() =
false;
1027 for (
const auto& param : ParamsMeta::registrationFinalizers()) {
1030 ParamsMeta::registrationFinalizers().clear();
Definition: parametersystem.hh:108
void retrieve() override
Definition: parametersystem.hh:110
Definition: parametersystem.hh:99
virtual void retrieve()=0
virtual ~ParamRegFinalizerBase_()
Definition: parametersystem.hh:101
void registerParam(const char *usageString)
Register a run-time parameter.
Definition: parametersystem.hh:947
bool printUnused(std::ostream &os=std::cout)
Print the list of unused run-time parameters.
Definition: parametersystem.hh:808
void parseParameterFile(const std::string &fileName, bool overwrite=true)
Read the parameters from an INI-style file.
Definition: parametersystem.hh:679
void printUsage(const std::string &helpPreamble, const std::string &errorMsg="", std::ostream &os=std::cerr, const bool showAll=false)
Print a usage message for all run-time parameters.
Definition: parametersystem.hh:400
std::string parseCommandLineOptions(int argc, const char **argv, const std::string &helpPreamble="", const PositionalArgumentCallback &posArgCallback=noPositionalParameters_)
Parse the parameters provided on the command line.
Definition: parametersystem.hh:571
auto get(bool errorIfNotRegistered=true)
Retrieve a runtime parameter.
Definition: parametersystem.hh:835
void printValues(std::ostream &os=std::cout)
Print values of the run-time parameters.
Definition: parametersystem.hh:746
Definition: parametersystem.hh:59
std::string parseUnquotedValue_(std::string &s, const std::string &)
Definition: parametersystem.hh:542
void removeLeadingSpace_(std::string &s)
Definition: parametersystem.hh:450
int getTtyWidth_()
Definition: parametersystem.hh:246
std::string parseQuotedValue_(std::string &s, const std::string &errorPrefix)
Definition: parametersystem.hh:505
void printParamUsage_(std::ostream &os, const ParamInfo ¶mInfo)
Definition: parametersystem.hh:264
std::string breakLines_(const std::string &msg, int indentWidth, int maxWidth)
Definition: parametersystem.hh:197
void printParamList_(std::ostream &os, const std::list< std::string > &keyList, bool printDefaults=false)
Definition: parametersystem.hh:369
bool isSet(bool errorIfNotRegistered=true)
Returns true if a parameter has been specified at runtime, false otherwise.
Definition: parametersystem.hh:911
std::string transformKey_(const std::string &s, bool capitalizeFirstLetter=true, const std::string &errorPrefix="")
Definition: parametersystem.hh:459
std::string parseKey_(std::string &s)
Definition: parametersystem.hh:492
void hideParam()
Indicate that a given parameter should not be mentioned in the help message.
Definition: parametersystem.hh:991
void endParamRegistration()
Indicate that all parameters are registered for a given type tag.
Definition: parametersystem.hh:1016
void getLists(Container &usedParams, Container &unusedParams)
Retrieves the lists of parameters specified at runtime and their values.
Definition: parametersystem.hh:870
void reset()
Definition: parametersystem.hh:898
void getFlattenedKeyList_(std::list< std::string > &dest, const Dune::ParameterTree &tree, const std::string &prefix="")
Definition: parametersystem.hh:350
Definition: blackoilmodel.hh:72
Definition: blackoilboundaryratevector.hh:37
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type GetProp
get the type of a property (equivalent to old macro GET_PROP(...))
Definition: propertysystem.hh:233
The Opm property system, traits with inheritance.
Definition: parametersystem.hh:62
bool operator==(const ParamInfo &other) const
Definition: parametersystem.hh:70
std::string usageString
Definition: parametersystem.hh:66
std::string typeTagName
Definition: parametersystem.hh:65
bool isHidden
Definition: parametersystem.hh:68
std::string paramTypeName
Definition: parametersystem.hh:64
std::string compileTimeValue
Definition: parametersystem.hh:67
std::string paramName
Definition: parametersystem.hh:63
Definition: parametersystem.hh:127
a tag to mark properties as undefined
Definition: propertysystem.hh:40