opm-common
ParameterGroup_impl.hpp
1 //===========================================================================
2 //
3 // File: ParameterGroup_impl.hpp
4 //
5 // Created: Tue Jun 2 19:06:46 2009
6 //
7 // Author(s): Bård Skaflestad <bard.skaflestad@sintef.no>
8 // Atgeirr F Rasmussen <atgeirr@sintef.no>
9 //
10 // $Date$
11 //
12 // $Revision$
13 //
14 //===========================================================================
15 
16 /*
17  Copyright 2009, 2010 SINTEF ICT, Applied Mathematics.
18  Copyright 2009, 2010 Statoil ASA.
19 
20  This file is part of the Open Porous Media project (OPM).
21 
22  OPM is free software: you can redistribute it and/or modify
23  it under the terms of the GNU General Public License as published by
24  the Free Software Foundation, either version 3 of the License, or
25  (at your option) any later version.
26 
27  OPM is distributed in the hope that it will be useful,
28  but WITHOUT ANY WARRANTY; without even the implied warranty of
29  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30  GNU General Public License for more details.
31 
32  You should have received a copy of the GNU General Public License
33  along with OPM. If not, see <http://www.gnu.org/licenses/>.
34 */
35 
36 #ifndef OPM_PARAMETERGROUP_IMPL_HEADER
37 #define OPM_PARAMETERGROUP_IMPL_HEADER
38 
39 #include <iostream>
40 #include <string>
41 #include <stdexcept>
42 
43 #include <opm/common/utility/parameters/ParameterGroup.hpp>
44 #include <opm/common/utility/parameters/ParameterStrings.hpp>
45 #include <opm/common/utility/parameters/ParameterTools.hpp>
46 #include <opm/common/utility/parameters/Parameter.hpp>
47 #include <opm/common/ErrorMacros.hpp>
48 #include <opm/common/OpmLog/OpmLog.hpp>
49 
50 namespace Opm {
51  template<>
53  static ParameterGroup
54  convert(const ParameterMapItem& item,
55  std::string& conversion_error,
56  bool enable_output)
57  {
58  std::string tag = item.getTag();
59  if (tag != ID_xmltag__param_grp) {
60  conversion_error = "The XML tag was '" + tag +
61  "' but should be '" +
62  ID_xmltag__param_grp + "'.\n";
63  return ParameterGroup("", 0, enable_output);
64  }
65  conversion_error = "";
66  const ParameterGroup& pg = dynamic_cast<const ParameterGroup&>(item);
67  return pg;
68  }
69  static std::string type() {return "ParameterGroup";}
70  };
71 
72  template <typename T>
73  inline std::string
74  ParameterGroup::to_string(const T& val)
75  {
76  return std::to_string(val);
77  }
78 
79  template <>
80  inline std::string
81  ParameterGroup::to_string<std::string>(const std::string& val)
82  {
83  return val;
84  }
85 
86  template <>
87  inline std::string
88  ParameterGroup::to_string(const bool& b) {
89  if (b) {
90  return ID_true;
91  } else {
92  return ID_false;
93  }
94  }
95 
96  template <>
97  inline std::string
98  ParameterGroup::to_string(const ParameterGroup&)
99  {
100  return std::string("<parameter group>");
101  }
102 
103  inline std::pair<std::string, std::string>
104  ParameterGroup::filename_split(const std::string& filename)
105  {
106  int fpos = filename.rfind('.');
107  std::string name = filename.substr(0, fpos);
108  std::string type = filename.substr(fpos+1);
109  return std::make_pair(name, type);
110  }
111 
112  template <typename StringArray>
113  ParameterGroup::ParameterGroup(int argc, StringArray argv, bool verify_syntax,
114  const bool enable_output)
115  : path_(ID_path_root), parent_(0), output_is_enabled_(enable_output)
116  {
117  if (verify_syntax && (argc < 2)) {
118  std::cerr << "Usage: " << argv[0] << " "
119  << "[paramfilename1.param] "
120  << "[paramfilename2.param] "
121  << "[overridden_arg1=value1] "
122  << "[overridden_arg2=value2] "
123  << "[...]" << std::endl;
124  exit(EXIT_FAILURE);
125  }
126  this->parseCommandLineArguments(argc, argv, verify_syntax);
127  }
128 
129  template <typename StringArray>
130  void ParameterGroup::parseCommandLineArguments(int argc, StringArray argv, bool verify_syntax)
131  {
132  std::vector<std::string> files;
133  std::vector<std::pair<std::string, std::string> > assignments;
134  for (int i = 1; i < argc; ++i) {
135  std::string arg(argv[i]);
136  int fpos = arg.find(ID_delimiter_assignment);
137  if (fpos == int(std::string::npos)) {
138  std::string filename = arg.substr(0, fpos);
139  files.push_back(filename);
140  continue;
141  }
142  int pos = fpos + ID_delimiter_assignment.size();
143  int spos = arg.find(ID_delimiter_assignment, pos);
144  if (spos == int(std::string::npos)) {
145  std::string name = arg.substr(0, fpos);
146  std::string value = arg.substr(pos, spos);
147  assignments.push_back(std::make_pair(name, value));
148  continue;
149  }
150  OpmLog::warning("Too many assignments (' "
151  + ID_delimiter_assignment
152  + "') detected in argument " + to_string(i));
153  }
154  for (int i = 0; i < int(files.size()); ++i) {
155  std::pair<std::string, std::string> file_type = filename_split(files[i]);
156  if (file_type.second == "param") {
157  this->readParam(files[i]);
158  } else {
159  if (verify_syntax) {
160  std::cerr << "ERROR: Input '" << files[i] << "' is not a valid name for a parameter file.\n";
161  std::cerr << " Valid filename extensions are 'param'.\n";
162  OPM_THROW(std::runtime_error, "ParameterGroup cannot handle argument: " + files[i]);
163  } else {
164  unhandled_arguments_.push_back(files[i]);
165  }
166  }
167  }
168  for (int i = 0; i < int(assignments.size()); ++i) {
169  this->insertParameter(assignments[i].first, assignments[i].second);
170  }
171  }
172 
173 
174  template<typename T>
175  inline T ParameterGroup::get(const std::string& name) const
176  {
177  return this->get<T>(name, ParameterRequirementNone());
178  }
179 
180  template<typename T, class Requirement>
181  inline T ParameterGroup::get(const std::string& name,
182  const Requirement& r) const
183  {
184  setUsed();
185  std::pair<std::string, std::string> name_path = splitParam(name);
186  map_type::const_iterator it = map_.find(name_path.first);
187  if (it == map_.end()) {
188  if (parent_ != 0) {
189  // If we have a parent, ask it instead.
190  if (output_is_enabled_) {
191  OpmLog::warning(name + "not found at " + path() + ID_delimiter_path + ", asking parent.");
192  }
193  return parent_->get<T>(name, r);
194  } else {
195  // We are at the top, name has not been found.
196  std::cerr << "ERROR: The group '"
197  << this->path()
198  << "' does not contain an element named '"
199  << name
200  << "'.\n";
201  throw NotFoundException();
202  }
203  }
204  if (name_path.second == "") {
205  T val = this->translate<T>(*it, r);
206  it->second->setUsed();
207  if (output_is_enabled_) {
208  OpmLog::debug(name + " found at " + path() + ID_delimiter_path + ", value is " + to_string(val));
209  }
210  return val;
211  } else {
212  ParameterGroup& pg = dynamic_cast<ParameterGroup&>(*(*it).second);
213  pg.setUsed();
214  return pg.get<T>(name_path.second, r);
215  }
216  }
217 
218  template<typename T>
219  inline T ParameterGroup::getDefault(const std::string& name,
220  const T& default_value) const
221  {
222  return this->getDefault<T>(name, default_value, ParameterRequirementNone());
223  }
224 
225  template<typename T, class Requirement>
226  inline T ParameterGroup::getDefault(const std::string& name,
227  const T& default_value,
228  const Requirement& r) const
229  {
230  setUsed();
231  std::pair<std::string, std::string> name_path = splitParam(name);
232  map_type::const_iterator it = map_.find(name_path.first);
233  if (it == map_.end()) {
234  if (parent_ != 0) {
235  // If we have a parent, ask it instead.
236  if (output_is_enabled_) {
237  OpmLog::warning(name + " not found at " + path() + ID_delimiter_path + ", asking parent.");
238  }
239  return parent_->getDefault<T>(name, default_value, r);
240  } else {
241  // We check the requirement for the default value
242  std::string requirement_result = r(default_value);
243  if (requirement_result != "") {
244  std::cerr << "ERROR: The default value for the "
245  << " element named '"
246  << name
247  << "' in the group '"
248  << this->path()
249  << "' failed to meet a requirenemt.\n";
250  std::cerr << "The requirement enforcer returned the following message:\n"
251  << requirement_result
252  << "\n";
253  throw RequirementFailedException<Requirement>();
254  }
255  }
256  if (output_is_enabled_) {
257  OpmLog::debug(name + " not found. Using default value '" + to_string(default_value) + "'.");
258  }
259  return default_value;
260  }
261  if (name_path.second == "") {
262  T val = this->translate<T>(*it, r);
263  it->second->setUsed();
264  if (output_is_enabled_) {
265  OpmLog::debug(name + " found at " + path() + ID_delimiter_path
266  + ", value is '" + to_string(val) + "'.");
267  }
268  return val;
269  } else {
270  ParameterGroup& pg = dynamic_cast<ParameterGroup&>(*(*it).second);
271  pg.setUsed();
272  return pg.getDefault<T>(name_path.second, default_value, r);
273  }
274  }
275 
276  template<typename T, class Requirement>
277  inline T ParameterGroup::translate(const pair_type& named_data,
278  const Requirement& chk) const
279  {
280  const std::string& name = named_data.first;
281  const data_type data = named_data.second;
282  std::string conversion_error;
283  T value = ParameterMapItemTrait<T>::convert(*data, conversion_error,
284  output_is_enabled_);
285  if (conversion_error != "") {
286  std::cerr << "ERROR: Failed to convert the element named '"
287  << name
288  << "' in the group '"
289  << this->path()
290  << "' to the type '"
291  << ParameterMapItemTrait<T>::type()
292  << "'.\n";
293  std::cerr << "The conversion routine returned the following message:\n"
294  << conversion_error
295  << "\n";
296  throw WrongTypeException();
297  }
298  std::string requirement_result = chk(value);
299  if (requirement_result != "") {
300  std::cerr << "ERROR: The element named '"
301  << name
302  << "' in the group '"
303  << this->path()
304  << "' of type '"
305  << ParameterMapItemTrait<T>::type()
306  << "' failed to meet a requirenemt.\n";
307  std::cerr << "The requirement enforcer returned the following message:\n"
308  << requirement_result
309  << "\n";
310  throw RequirementFailedException<Requirement>();
311  }
312  return value;
313  }
314 } // namespace Opm
315 
316 #endif // OPM_PARAMETERGROUP_IMPL_HEADER
const std::string & path() const
Returns the path of the parameter group.
Definition: ParameterGroup.cpp:82
virtual std::string getTag() const =0
This function returns a string describing the ParameterMapItem.
Definition: ParameterRequirement.hpp:48
Definition: ParameterMapItem.hpp:64
void insertParameter(const std::string &name, const std::string &value)
Insert a new parameter item into the group.
Definition: ParameterGroup.cpp:201
The parameter handlig system is structured as a tree, where each node inhertis from ParameterMapItem...
Definition: ParameterMapItem.hpp:47
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:30
T get(const std::string &name) const
This method is used to read a parameter from the parameter group.
Definition: ParameterGroup_impl.hpp:175
void readParam(const std::string &param_filename)
Reads the contents of the param file specified by param_filename into this ParameterGroup.
Definition: ParameterGroup.cpp:107
T getDefault(const std::string &name, const T &default_value) const
This method is used to read a parameter from the parameter group.
Definition: ParameterGroup_impl.hpp:219
ParameterGroup is a class that is used to provide run-time parameters.
Definition: ParameterGroup.hpp:81