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/core/utility/parameters/ParameterGroup.hpp>
44 #include <opm/core/utility/parameters/ParameterStrings.hpp>
45 #include <opm/core/utility/parameters/ParameterTools.hpp>
46 #include <opm/core/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  std::ostringstream os;
77  os << val;
78  return os.str();
79  }
80 
81  template <>
82  inline std::string
83  ParameterGroup::to_string(const bool& b) {
84  if (b) {
85  return ID_true;
86  } else {
87  return ID_false;
88  }
89  }
90 
91  template <>
92  inline std::string
93  ParameterGroup::to_string(const ParameterGroup&)
94  {
95  return std::string("<parameter group>");
96  }
97 
98  inline std::pair<std::string, std::string>
99  ParameterGroup::filename_split(const std::string& filename)
100  {
101  int fpos = filename.rfind('.');
102  std::string name = filename.substr(0, fpos);
103  std::string type = filename.substr(fpos+1);
104  return std::make_pair(name, type);
105  }
106 
107  template <typename StringArray>
108  ParameterGroup::ParameterGroup(int argc, StringArray argv, bool verify_syntax,
109  const bool enable_output)
110  : path_(ID_path_root), parent_(0), output_is_enabled_(enable_output)
111  {
112  if (verify_syntax && (argc < 2)) {
113  std::cerr << "Usage: " << argv[0] << " "
114  << "[paramfilename1.param] "
115  << "[paramfilename2.param] "
116  << "[overridden_arg1=value1] "
117  << "[overridden_arg2=value2] "
118  << "[...]" << std::endl;
119  exit(EXIT_FAILURE);
120  }
121  this->parseCommandLineArguments(argc, argv, verify_syntax);
122  }
123 
124  template <typename StringArray>
125  void ParameterGroup::parseCommandLineArguments(int argc, StringArray argv, bool verify_syntax)
126  {
127  std::vector<std::string> files;
128  std::vector<std::pair<std::string, std::string> > assignments;
129  for (int i = 1; i < argc; ++i) {
130  std::string arg(argv[i]);
131  int fpos = arg.find(ID_delimiter_assignment);
132  if (fpos == int(std::string::npos)) {
133  std::string filename = arg.substr(0, fpos);
134  files.push_back(filename);
135  continue;
136  }
137  int pos = fpos + ID_delimiter_assignment.size();
138  int spos = arg.find(ID_delimiter_assignment, pos);
139  if (spos == int(std::string::npos)) {
140  std::string name = arg.substr(0, fpos);
141  std::string value = arg.substr(pos, spos);
142  assignments.push_back(std::make_pair(name, value));
143  continue;
144  }
145  OpmLog::warning("Too many assignements (' "
146  + ID_delimiter_assignment
147  + "') detected in argument " + to_string(i));
148  }
149  for (int i = 0; i < int(files.size()); ++i) {
150  std::pair<std::string, std::string> file_type = filename_split(files[i]);
151  if (file_type.second == "param") {
152  this->readParam(files[i]);
153  } else {
154  if (verify_syntax) {
155  std::cerr << "ERROR: Input '" << files[i] << "' is not a valid name for a parameter file.\n";
156  std::cerr << " Valid filename extensions are 'param'.\n";
157  OPM_THROW(std::runtime_error, "ParameterGroup cannot handle argument: " << files[i]);
158  } else {
159  unhandled_arguments_.push_back(files[i]);
160  }
161  }
162  }
163  for (int i = 0; i < int(assignments.size()); ++i) {
164  this->insertParameter(assignments[i].first, assignments[i].second);
165  }
166  }
167 
168 
169  template<typename T>
170  inline T ParameterGroup::get(const std::string& name) const
171  {
172  return this->get<T>(name, ParameterRequirementNone());
173  }
174 
175  template<typename T, class Requirement>
176  inline T ParameterGroup::get(const std::string& name,
177  const Requirement& r) const
178  {
179  setUsed();
180  std::pair<std::string, std::string> name_path = splitParam(name);
181  map_type::const_iterator it = map_.find(name_path.first);
182  if (it == map_.end()) {
183  if (parent_ != 0) {
184  // If we have a parent, ask it instead.
185  if (output_is_enabled_) {
186  OpmLog::warning(name + "not found at " + path() + ID_delimiter_path + ", asking parent.");
187  }
188  return parent_->get<T>(name, r);
189  } else {
190  // We are at the top, name has not been found.
191  std::cerr << "ERROR: The group '"
192  << this->path()
193  << "' does not contain an element named '"
194  << name
195  << "'.\n";
196  throw NotFoundException();
197  }
198  }
199  if (name_path.second == "") {
200  T val = this->translate<T>(*it, r);
201  it->second->setUsed();
202  if (output_is_enabled_) {
203  OpmLog::debug(name + " found at " + path() + ID_delimiter_path + ", value is " + to_string(val));
204  }
205  return val;
206  } else {
207  ParameterGroup& pg = dynamic_cast<ParameterGroup&>(*(*it).second);
208  pg.setUsed();
209  return pg.get<T>(name_path.second, r);
210  }
211  }
212 
213  template<typename T>
214  inline T ParameterGroup::getDefault(const std::string& name,
215  const T& default_value) const
216  {
217  return this->getDefault<T>(name, default_value, ParameterRequirementNone());
218  }
219 
220  template<typename T, class Requirement>
221  inline T ParameterGroup::getDefault(const std::string& name,
222  const T& default_value,
223  const Requirement& r) const
224  {
225  setUsed();
226  std::pair<std::string, std::string> name_path = splitParam(name);
227  map_type::const_iterator it = map_.find(name_path.first);
228  if (it == map_.end()) {
229  if (parent_ != 0) {
230  // If we have a parent, ask it instead.
231  if (output_is_enabled_) {
232  OpmLog::warning(name + " not found at " + path() + ID_delimiter_path + ", asking parent.");
233  }
234  return parent_->getDefault<T>(name, default_value, r);
235  } else {
236  // We check the requirement for the default value
237  std::string requirement_result = r(default_value);
238  if (requirement_result != "") {
239  std::cerr << "ERROR: The default value for the "
240  << " element named '"
241  << name
242  << "' in the group '"
243  << this->path()
244  << "' failed to meet a requirenemt.\n";
245  std::cerr << "The requirement enforcer returned the following message:\n"
246  << requirement_result
247  << "\n";
248  throw RequirementFailedException<Requirement>();
249  }
250  }
251  if (output_is_enabled_) {
252  OpmLog::debug(name + " not found. Using default value '" + to_string(default_value) + "'.");
253  }
254  return default_value;
255  }
256  if (name_path.second == "") {
257  T val = this->translate<T>(*it, r);
258  it->second->setUsed();
259  if (output_is_enabled_) {
260  OpmLog::debug(name + " found at " + path() + ID_delimiter_path
261  + ", value is '" + to_string(val) + "'.");
262  }
263  return val;
264  } else {
265  ParameterGroup& pg = dynamic_cast<ParameterGroup&>(*(*it).second);
266  pg.setUsed();
267  return pg.getDefault<T>(name_path.second, default_value, r);
268  }
269  }
270 
271  template<typename T, class Requirement>
272  inline T ParameterGroup::translate(const pair_type& named_data,
273  const Requirement& chk) const
274  {
275  const std::string& name = named_data.first;
276  const data_type data = named_data.second;
277  std::string conversion_error;
278  T value = ParameterMapItemTrait<T>::convert(*data, conversion_error,
279  output_is_enabled_);
280  if (conversion_error != "") {
281  std::cerr << "ERROR: Failed to convert the element named '"
282  << name
283  << "' in the group '"
284  << this->path()
285  << "' to the type '"
286  << ParameterMapItemTrait<T>::type()
287  << "'.\n";
288  std::cerr << "The conversion routine returned the following message:\n"
289  << conversion_error
290  << "\n";
291  throw WrongTypeException();
292  }
293  std::string requirement_result = chk(value);
294  if (requirement_result != "") {
295  std::cerr << "ERROR: The element named '"
296  << name
297  << "' in the group '"
298  << this->path()
299  << "' of type '"
300  << ParameterMapItemTrait<T>::type()
301  << "' failed to meet a requirenemt.\n";
302  std::cerr << "The requirement enforcer returned the following message:\n"
303  << requirement_result
304  << "\n";
305  throw RequirementFailedException<Requirement>();
306  }
307  return value;
308  }
309 } // namespace Opm
310 
311 #endif // OPM_PARAMETERGROUP_IMPL_HEADER
virtual std::string getTag() const =0
This function returns a string describing the ParameterMapItem.
Definition: ParameterRequirement.hpp:51
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:200
The parameter handlig system is structured as a tree, where each node inhertis from ParameterMapItem...
Definition: ParameterMapItem.hpp:47
Definition: AnisotropicEikonal.cpp:446
T get(const std::string &name) const
This method is used to read a parameter from the parameter group.
Definition: ParameterGroup_impl.hpp:170
void readParam(const std::string &param_filename)
Reads the contents of the param file specified by param_filename into this ParameterGroup.
Definition: ParameterGroup.cpp:106
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:214
std::string path() const
Returns the path of the parameter group.
Definition: ParameterGroup.cpp:82
ParameterGroup is a class that is used to provide run-time parameters.
Definition: ParameterGroup.hpp:81