All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
parametersystem.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  This file is part of the Open Porous Media project (OPM).
5 
6  OPM 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 2 of the License, or
9  (at your option) any later version.
10 
11  OPM 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 OPM. If not, see <http://www.gnu.org/licenses/>.
18 
19  Consult the COPYING file in the top-level source directory of this
20  module for the precise wording of the license and the list of
21  copyright holders.
22 */
32 #ifndef EWOMS_PARAMETERS_HH
33 #define EWOMS_PARAMETERS_HH
34 
36 
37 #include <opm/common/ErrorMacros.hpp>
38 #include <opm/common/Exceptions.hpp>
39 #include <opm/common/Unused.hpp>
40 
41 #include <dune/common/classname.hh>
42 #include <dune/common/parametertree.hh>
43 
44 #include <map>
45 #include <list>
46 #include <sstream>
47 #include <string>
48 #include <iostream>
49 #include <unordered_map>
50 
68 #define EWOMS_REGISTER_PARAM(TypeTag, ParamType, ParamName, Description) \
69  ::Ewoms::Parameters::registerParam<TypeTag, ParamType, PTAG(ParamName)>( \
70  #ParamName, #ParamName, Description)
71 
81 #define EWOMS_END_PARAM_REGISTRATION(TypeTag) \
82  ::Ewoms::Parameters::endParamRegistration<TypeTag>()
83 
99 #define EWOMS_GET_PARAM(TypeTag, ParamType, ParamName) \
100  (::Ewoms::Parameters::get<TypeTag, ParamType, PTAG(ParamName)>(#ParamName, \
101  #ParamName))
102 
104 #define EWOMS_GET_PARAM_(TypeTag, ParamType, ParamName) \
105  (::Ewoms::Parameters::get<TypeTag, ParamType, PTAG(ParamName)>( \
106  #ParamName, #ParamName, \
107  /*errorIfNotRegistered=*/false))
108 
109 namespace Ewoms {
110 namespace Parameters {
111 
112 struct ParamInfo
113 {
114  std::string paramName;
115  std::string paramTypeName;
116  std::string typeTagName;
117  std::string propertyName;
118  std::string usageString;
119  std::string compileTimeValue;
120 
121  bool operator==(const ParamInfo& other) const
122  {
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;
129  }
130 };
131 
132 // forward declaration
133 template <class TypeTag, class ParamType, class PropTag>
134 const ParamType& get(const char *propTagName, const char *paramName,
135  bool errorIfNotRegistered = true);
136 
137 class ParamRegFinalizerBase_
138 {
139 public:
140  virtual ~ParamRegFinalizerBase_()
141  {}
142  virtual void retrieve() = 0;
143 };
144 
145 template <class TypeTag, class ParamType, class PropTag>
146 class ParamRegFinalizer_ : public ParamRegFinalizerBase_
147 {
148 public:
149  ParamRegFinalizer_(const std::string& paramName) : paramName_(paramName)
150  {}
151 
152  void retrieve()
153  {
154  // retrieve the parameter once to make sure that its value does
155  // not contain a syntax error.
156  ParamType __attribute__((unused)) dummy =
157  get<TypeTag, ParamType, PropTag>(/*propTagName=*/paramName_.data(),
158  paramName_.data(),
159  /*errorIfNotRegistered=*/true);
160  }
161 
162 private:
163  std::string paramName_;
164 };
165 } // namespace Parameters
166 
167 namespace Properties {
168 // type tag which is supposed to spliced in or inherited from if the
169 // parameter system is to be used
170 NEW_TYPE_TAG(ParameterSystem);
171 
172 NEW_PROP_TAG(ParameterMetaData);
173 NEW_PROP_TAG(ParameterGroupPrefix);
174 NEW_PROP_TAG(Description);
175 
176 
178 SET_PROP(ParameterSystem, ParameterMetaData)
179 {
180  typedef Dune::ParameterTree type;
181 
182  static Dune::ParameterTree& tree()
183  { return storage_().tree; }
184 
185  static std::map<std::string, ::Ewoms::Parameters::ParamInfo>& mutableRegistry()
186  { return storage_().registry; }
187 
188  static const std::map<std::string, ::Ewoms::Parameters::ParamInfo>& registry()
189  { return storage_().registry; }
190 
191  static std::list< ::Ewoms::Parameters::ParamRegFinalizerBase_ *> &
192  registrationFinalizers()
193  { return storage_().finalizers; }
194 
195  static bool& registrationOpen()
196  { return storage_().registrationOpen; }
197 
198 private:
199  // this is not pretty, but handling these attributes as static variables inside
200  // member functions of the ParameterMetaData property class triggers a bug in clang
201  // 3.5's address sanitizer which causes these variables to be initialized multiple
202  // times...
203  struct Storage_ {
204  Storage_()
205  { registrationOpen = true; }
206 
207  Dune::ParameterTree tree;
208  std::map<std::string, ::Ewoms::Parameters::ParamInfo> registry;
209  std::list< ::Ewoms::Parameters::ParamRegFinalizerBase_ *> finalizers;
210  bool registrationOpen;
211  };
212  static Storage_& storage_() {
213  static Storage_ obj;
214  return obj;
215  }
216 };
217 
218 SET_STRING_PROP(ParameterSystem, ParameterGroupPrefix, "");
219 SET_STRING_PROP(ParameterSystem, Description, "");
220 
221 } // namespace Properties
222 
223 namespace Parameters {
224 // function prototype declarations
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 = "");
229 
230 
231 inline void printParamUsage_(std::ostream& os, const ParamInfo& paramInfo)
232 {
233  std::string paramMessage, paramType, paramDescription;
234 
235  // convert the CamelCase name to a command line --parameter-name.
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]))
240  cmdLineName += "-";
241  cmdLineName += static_cast<char>(std::tolower(camelCaseName[i]));
242  }
243 
244  // assemble the printed output
245  paramMessage = " ";
246  paramMessage += cmdLineName;
247 
248  // add the =VALUE_TYPE part
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()) {
265  // the parameter is a flag. Do nothing!
266  }
267  else {
268  // unknown type
269  paramMessage += "=VALUE";
270  }
271 
272  // fill up the up help string to the 50th character
273  paramMessage += " ";
274  while (paramMessage.size() < 50)
275  paramMessage += " ";
276 
277  // append the parameter usage string.
278  paramMessage += paramInfo.usageString;
279  paramMessage += "\n";
280 
281  // print everything
282  os << paramMessage;
283 }
284 
285 inline void getFlattenedKeyList_(std::list<std::string>& dest,
286  const Dune::ParameterTree& tree,
287  const std::string& prefix)
288 {
289  // add the keys of the current sub-structure
290  auto keyIt = tree.getValueKeys().begin();
291  const auto& keyEndIt = tree.getValueKeys().end();
292  for (; keyIt != keyEndIt; ++keyIt) {
293  std::string newKey(prefix);
294  newKey += *keyIt;
295  dest.push_back(newKey);
296  }
297 
298  // recursively add all substructure keys
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;
304  newPrefix += ".";
305 
306  getFlattenedKeyList_(dest, tree.sub(*subStructIt), newPrefix);
307  }
308 }
309 
310 // print the values of a list of parameters
311 template <class TypeTag>
312 void printParamList_(std::ostream& os, const std::list<std::string>& keyList)
313 {
314  typedef typename GET_PROP(TypeTag, ParameterMetaData) ParamsMeta;
315 
316  const Dune::ParameterTree& tree = ParamsMeta::tree();
317 
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";
325  }
326 }
327 
328 // print the values of a list of parameters
329 template <class TypeTag>
330 void printCompileTimeParamList_(std::ostream& os,
331  const std::list<std::string>& keyList)
332 {
333  typedef typename GET_PROP(TypeTag, ParameterMetaData) ParamsMeta;
334 
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";
341  }
342 }
343 
345 
353 template <class TypeTag>
354 void printUsage(const std::string& progName, const std::string& errorMsg = "",
355  bool handleHelp = true, std::ostream& os = std::cerr)
356 {
357  typedef typename GET_PROP(TypeTag, ParameterMetaData) ParamsMeta;
358  std::string desc = GET_PROP_VALUE(TypeTag, Description);
359 
360  if (errorMsg != "") {
361  os << errorMsg << "\n"
362  << "\n";
363  }
364 
365  os << "Usage: " << progName << " [OPTIONS]\n";
366  if (desc != "")
367  os << desc << "\n";
368  os << "\n";
369  os << "Recognized options:\n";
370 
371  if (handleHelp) {
372  ParamInfo pInfo;
373  pInfo.paramName = "h,--help";
374  pInfo.usageString = "Print this help message and exit";
375  printParamUsage_(os, pInfo);
376  }
377 
378  auto paramIt = ParamsMeta::registry().begin();
379  const auto& paramEndIt = ParamsMeta::registry().end();
380  for (; paramIt != paramEndIt; ++paramIt) {
381  printParamUsage_(os, paramIt->second);
382  }
383 }
384 
400 template <class TypeTag>
401 std::string parseCommandLineOptions(int argc, char **argv, bool handleHelp = true)
402 {
403  Dune::ParameterTree& paramTree = GET_PROP(TypeTag, ParameterMetaData)::tree();
404 
405  if (handleHelp) {
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";
411  }
412  }
413  }
414 
415  // All command line options need to start with '-'
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.";
421 
422  if (handleHelp)
423  printUsage<TypeTag>(argv[0], oss.str(), handleHelp, std::cerr);
424 
425  return oss.str();
426  }
427 
428  std::string paramName, paramValue;
429 
430  // read a --my-opt=abc option. This gets transformed
431  // into the parameter "MyOpt" with the value being
432  // "abc"
433  if (argv[i][1] == '-') {
434  // There is nothing after the '-'
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.";
440 
441  if (handleHelp)
442  printUsage<TypeTag>(argv[0], oss.str(), handleHelp,
443  std::cerr);
444 
445  return oss.str();
446  }
447 
448  // copy everything after the "--" into a separate string
449  std::string s(argv[i] + 2);
450 
451  // parse argument
452  unsigned j = 0;
453  while (true) {
454  if (j >= s.size()) {
455  // encountered the end of the string, i.e. we
456  // have a parameter where the argument is empty
457  paramName = s;
458  paramValue = "";
459  break;
460  }
461  else if (s[j] == '=') {
462  // we encountered a '=' character. everything
463  // before is the name of the parameter,
464  // everything after is the value.
465  paramName = s.substr(0, j);
466  paramValue = s.substr(j + 1);
467  break;
468  }
469  else if (s[j] == '-') {
470  // remove all "-" characters and capitalize the
471  // character after them
472  s.erase(j, 1);
473  if (s.size() == j) {
474  std::ostringstream oss;
475  oss << "Parameter name of argument " << i
476  << " ('" << argv[i] << "')"
477  << " is invalid (ends with a '-' character).";
478 
479  if (handleHelp)
480  printUsage<TypeTag>(argv[0], oss.str(), handleHelp,
481  std::cerr);
482  return oss.str();
483  }
484  else if (s[j] == '-') {
485  std::ostringstream oss;
486  oss << "Malformed parameter name in argument " << i
487  << " ('" << argv[i] << "'): "
488  << "'--' in parameter name.";
489 
490  if (handleHelp)
491  printUsage<TypeTag>(argv[0], oss.str(), handleHelp,
492  std::cerr);
493  return oss.str();
494  }
495  s[j] = static_cast<char>(std::toupper(s[j]));
496  }
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).";
503 
504  if (handleHelp)
505  printUsage<TypeTag>(argv[0], oss.str(), handleHelp,
506  std::cerr);
507  return oss.str();
508  }
509 
510  ++j;
511  }
512  }
513  else {
514  // read a -myOpt abc option for the parameter "MyOpt" with
515  // a value of "abc"
516  paramName = argv[i] + 1;
517 
518  if (argc == i + 1 || argv[i + 1][0] == '-') {
519  std::ostringstream oss;
520  oss << "No argument given for parameter '" << argv[i] << "'!";
521  if (handleHelp)
522  printUsage<TypeTag>(argv[0], oss.str(), handleHelp,
523  std::cerr);
524  return oss.str();
525  }
526 
527  paramValue = argv[i + 1];
528  ++i; // In the case of '-myOpt abc' each pair counts as two arguments
529  }
530 
531  // capitalize first letter of parameter name
532  paramName[0] = static_cast<char>(std::toupper(paramName[0]));
533 
534  // Put the key=value pair into the parameter tree
535  paramTree[paramName] = paramValue;
536  }
537  return "";
538 }
539 
546 template <class TypeTag>
547 void printValues(std::ostream& os = std::cout)
548 {
549  typedef typename GET_PROP(TypeTag, ParameterMetaData) ParamsMeta;
550 
551  const Dune::ParameterTree& tree = ParamsMeta::tree();
552 
553  std::list<std::string> runTimeAllKeyList;
554  std::list<std::string> runTimeKeyList;
555  std::list<std::string> unknownKeyList;
556 
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()) {
562  // key was not registered by the program!
563  unknownKeyList.push_back(*keyIt);
564  }
565  else {
566  // the key was specified at run-time
567  runTimeKeyList.push_back(*keyIt);
568  }
569  }
570 
571  // loop over all registered parameters
572  std::list<std::string> compileTimeKeyList;
573  auto paramInfoIt = ParamsMeta::registry().begin();
574  const auto& paramInfoEndIt = ParamsMeta::registry().end();
575  for (; paramInfoIt != paramInfoEndIt; ++paramInfoIt) {
576  // check whether the key was specified at run-time
577  const auto& keyName = paramInfoIt->first;
578  if (tree.hasKey(keyName))
579  continue;
580  else
581  compileTimeKeyList.push_back(keyName);
582  }
583 
584  // report the values of all registered (and unregistered)
585  // parameters
586  if (runTimeKeyList.size() > 0) {
587  os << "# [known parameters which were specified at run-time]\n";
588  printParamList_<TypeTag>(os, runTimeKeyList);
589  }
590 
591  if (compileTimeKeyList.size() > 0) {
592  os << "# [parameters which were specified at compile-time]\n";
593  printCompileTimeParamList_<TypeTag>(os, compileTimeKeyList);
594  }
595 
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;
602  }
603  }
604 }
605 
614 template <class TypeTag>
615 bool printUnused(std::ostream& os = std::cout)
616 {
617  typedef typename GET_PROP(TypeTag, ParameterMetaData) ParamsMeta;
618 
619  const Dune::ParameterTree& tree = ParamsMeta::tree();
620  std::list<std::string> runTimeAllKeyList;
621  std::list<std::string> unknownKeyList;
622 
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()) {
628  // key was not registered by the program!
629  unknownKeyList.push_back(*keyIt);
630  }
631  }
632 
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;
639  }
640  return true;
641  }
642  return false;
643 }
644 
646 template <class TypeTag>
647 class Param
648 {
649  typedef typename GET_PROP(TypeTag, ParameterMetaData) ParamsMeta;
650 
651 public:
652  template <class ParamType, class PropTag>
653  static const ParamType& get(const char *propTagName, const char *paramName,
654  bool errorIfNotRegistered = true)
655  {
656  static const ParamType& value =
657  retrieve_<ParamType, PropTag>(propTagName,
658  paramName,
659  errorIfNotRegistered);
660  return value;
661  }
662 
663 private:
664  struct Blubb
665  {
666  std::string propertyName;
667  std::string paramTypeName;
668  std::string groupName;
669 
670  Blubb& operator=(const Blubb& b)
671  {
672  propertyName = b.propertyName;
673  paramTypeName = b.paramTypeName;
674  groupName = b.groupName;
675  return *this;
676  }
677  };
678 
679  static void check_(const std::string& paramTypeName,
680  const std::string& propertyName, const char *paramName)
681  {
682  typedef std::unordered_map<std::string, Blubb> StaticData;
683  static StaticData staticData;
684 
685  typename StaticData::iterator it = staticData.find(paramName);
686  Blubb *b;
687  if (it == staticData.end()) {
688  Blubb a;
689  a.propertyName = propertyName;
690  a.paramTypeName = paramTypeName;
691  staticData[paramName] = a;
692  b = &staticData[paramName];
693  }
694  else
695  b = &(it->second);
696 
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 << "')");
702  }
703 
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 << ")");
709  }
710  }
711 
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)
716  {
717 #ifndef NDEBUG
718  // make sure that the parameter is used consistently. since
719  // this is potentially quite expensive, it is only done if
720  // debugging code is not explicitly turned off.
721  check_(Dune::className<ParamType>(), propTagName, paramName);
722 #endif
723 
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 "
729  "registered.");
730 
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.");
735  }
736 
737  // prefix the parameter name by the model's GroupName. E.g. If
738  // the model specifies its group name to be 'Stokes', in an
739  // INI file this would result in something like:
740  //
741  // [Stokes]
742  // NewtonWriteConvergence = true
743  std::string canonicalName(paramName);
744 
745  std::string modelParamGroup(GET_PROP_VALUE(TypeTag,
746  ParameterGroupPrefix));
747  if (modelParamGroup.size()) {
748  canonicalName.insert(0, ".");
749  canonicalName.insert(0, modelParamGroup);
750  }
751 
752  // retrieve actual parameter from the parameter tree
753  const ParamType defaultValue =
754  GET_PROP_VALUE_(TypeTag, PropTag);
755  static ParamType value =
756  ParamsMeta::tree().template get<ParamType>(canonicalName, defaultValue);
757 
758  return value;
759  }
760 };
761 
762 template <class TypeTag, class ParamType, class PropTag>
763 const ParamType& get(const char *propTagName, const char *paramName,
764  bool errorIfNotRegistered)
765 {
766  return Param<TypeTag>::template get<ParamType, PropTag>(propTagName,
767  paramName,
768  errorIfNotRegistered);
769 }
770 
771 template <class TypeTag, class ParamType, class PropTag>
772 void registerParam(const char *paramName, const char *propertyName, const char *usageString)
773 {
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.");
779 
780  ParamsMeta::registrationFinalizers().push_back(
781  new ParamRegFinalizer_<TypeTag, ParamType, PropTag>(paramName));
782 
783  ParamInfo paramInfo;
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()) {
794  // allow to register a parameter twice, but only if the
795  // parameter name, type and usage string are exactly the same.
796  if (ParamsMeta::registry().at(paramName) == paramInfo)
797  return;
798  OPM_THROW(std::logic_error,
799  "Parameter " << paramName
800  << " registered twice with non-matching characteristics.");
801  }
802 
803  ParamsMeta::mutableRegistry()[paramName] = paramInfo;
804 }
805 
806 template <class TypeTag>
807 void endParamRegistration()
808 {
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 "
814  "once.");
815 
816  ParamsMeta::registrationOpen() = false;
817 
818  // loop over all parameters and retrieve their values to make sure
819  // that there is no syntax error
820  auto pIt = ParamsMeta::registrationFinalizers().begin();
821  const auto& pEndIt = ParamsMeta::registrationFinalizers().end();
822  for (; pIt != pEndIt; ++pIt) {
823  (*pIt)->retrieve();
824  delete *pIt;
825  }
826 }
828 
829 } // namespace Parameters
830 } // namespace Ewoms
831 
832 #endif
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