QMCPACK
OhmmsParameter.h
Go to the documentation of this file.
1 //////////////////////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois/NCSA Open Source License.
3 // See LICENSE file in top directory for details.
4 //
5 // Copyright (c) 2016 Jeongnim Kim and QMCPACK developers.
6 //
7 // File developed by: Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
8 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
9 // Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory
10 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
11 //
12 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
13 //////////////////////////////////////////////////////////////////////////////////////
14 
15 
16 #ifndef OHMMS_OHMMSPARAMETER_H
17 #define OHMMS_OHMMSPARAMETER_H
18 
19 #include <stdexcept>
21 #include "Host/OutputManager.h"
22 #include "ModernStringUtils.hpp"
23 
24 /** generic class for parameter xmlNode
25  *
26  * <parameter/> node is used to generically add a named parameter whose
27  *value is the content of an xmlNode. The definition confirms docbook::parameter
28  *\htmlonly
29  Usage is:
30  &lt;parameter name="<b>aname</b>" &gt; <b>value</b> &lt;/parameter&gt;
31  <br>
32  Example is:
33  &lt;parameter name="temperature" &gt; 200 &lt;/parameter&gt;
34  <br>
35  <ul>
36  <li> <b>name</b> is the name of the parameter.
37  <li> <b>value</b> is the content of the parameter of type T.
38  </ul>
39  <ul> Two kinds of template parameter T are valid:
40  <li> intrinsic C/C variables, such as int,double
41  <li> Ohmms basic data types in OhmmsPETE, such as TinyVector&lt;T,D&gt; and Tensor&lt;T,D&gt;
42  </ul>
43  Using other types are valid, as far as the operators << and >> can handle the xmlChar*.
44 
45  \endhtmlonly
46  */
47 
48 enum class TagStatus
49 {
50  OPTIONAL, // there is a default value
51  REQUIRED, // no default value, input required.
52  DEPRECATED, // deprecated input tag. Input becomes optional
53  DELETED, // deleted input tag. Hard stop if detected.
54  UNSUPPORTED // not supported input tags due to incompatible changes. Hard stop if detected.
55 };
56 
57 inline void checkTagStatus(const std::string& tagname, TagStatus status)
58 {
59  if (status == TagStatus::DELETED)
60  {
61  std::ostringstream msg;
62  msg << "Input tag \"" << tagname << "\" has been deleted. Please remove it from the input file!" << std::endl;
63  throw std::runtime_error(msg.str());
64  }
65  else if (status == TagStatus::UNSUPPORTED)
66  {
67  std::ostringstream msg;
68  msg << "Input tag \"" << tagname << "\" is not supported. Please remove it from the input file!" << std::endl;
69  throw std::runtime_error(msg.str());
70  }
71  else if (status == TagStatus::DEPRECATED)
72  qmcplusplus::app_warning() << "Input tag \"" << tagname
73  << "\" has been deprecated and will be deleted in the next release!" << std::endl;
74 }
75 
76 
77 template<class T>
79 {
80  //@{
81  ///reference to a value of type T
82  T& ref_;
83  ///valid candidate values, if not empty, the first one is the default.
84  std::vector<T> candidate_values_;
85  ///pointer to the corresponding xmlNode
86  xmlNodePtr node_;
87  /// The status of the tag
89  //@}
90 
91  void checkValues()
92  {
93  // when the size is 1, values are unbounded and the given value is the default value
94  if (candidate_values_.size() > 1 &&
95  std::find(candidate_values_.begin(), candidate_values_.end(), ref_) == candidate_values_.end())
96  {
97  std::ostringstream msg;
98  msg << "Input tag \"" << myName << "\" value \"" << ref_ << "\" is not valid. Candidate values are : ";
99  for (const auto& value : candidate_values_)
100  msg << " \"" << value << "\"";
101  msg << std::endl;
102  throw std::runtime_error(msg.str());
103  }
104  }
105 
106 public:
107  /*!\fn OhmmsParameter(...) constructor
108  *\param a the value to be referenced
109  *\param aname the name of this object
110  *\param candidate_values candidate values to be checked against, the first element is the default value. It can be left empty for backward compatibility or unbounded input.
111  *\param status Tag status, See TagStatus enum.
112  */
114  const std::string& aname,
115  std::vector<T>&& candidate_values = {},
117  : OhmmsElementBase(aname.c_str()),
118  ref_(a),
119  candidate_values_(std::move(candidate_values)),
120  node_(NULL),
121  tag_staus_(status)
122  {
123  // set default value
124  if (status != TagStatus::REQUIRED && !candidate_values_.empty())
125  ref_ = candidate_values_[0];
126  }
127 
128  ///print to an std::ostream
129  inline bool get(std::ostream& os) const override
130  {
131  os << "<parameter name=\"" << myName << "\">" << ref_ << "</parameter>" << std::endl;
132  return true;
133  }
134 
135  /*!inline bool put(xmlNodePtr cur), used by ParameterSet
136  *\param cur the current xmlNode whose content is assigned to ref_
137  */
138  inline bool put(xmlNodePtr cur) override
139  {
141  node_ = cur;
142  putContent(ref_, cur);
143  checkValues();
144  return true;
145  }
146 
147 
148  ///read from std::istream, used by OhmmsAttributeSet
149  inline bool put(std::istream& is) override
150  {
152  is >> ref_;
153  checkValues();
154  return true;
155  }
156 
157  /*!\fn bool add(xmlNodePtr parent)
158  *\param parent the parent node to which a xmlNode for this object is appended.
159  *\brief This function is used by the users to add a xmlNode, when the
160  *input file does not contain the corresponding <parameter/>. The content
161  *of the new xmlNode is the current value of ref_.
162  */
163  bool add(xmlNodePtr parent) override
164  {
165  if (!node_)
166  {
167  node_ = xmlNewChild(parent, parent->ns, (const xmlChar*)"parameter", NULL);
168  xmlNewProp(node_, (const xmlChar*)"name", (const xmlChar*)(myName.c_str()));
170  }
171  return true;
172  }
173 
174  inline void setValue(T x) { ref_ = x; }
175 
176  ///reset member data
177  inline void reset() override { getContent(ref_, node_); }
178 };
179 
180 /*!\class OhmmsParameter<bool>
181  *\brief A specialization of OhmmsParameter<T> for T = boolean.
182  */
183 template<>
184 class OhmmsParameter<bool> : public OhmmsElementBase
185 {
186  //@{
187  ///reference to a value of type T
188  bool& ref_;
189  ///valid candidate values, if not empty, the first one is the default.
190  std::vector<bool> candidate_values_;
191  ///pointer to the corresponding xmlNode
192  xmlNodePtr node_;
193  /// The status of the tag
195  //@}
196 
197 public:
198  /*!\fn OhmmsParameter(bool& a, const char* aname, const char* uname)
199  *\param a the boolean to be referenced.
200  *\param aname the name of this object
201  *\param candidate_values valid input values
202  */
203  OhmmsParameter(bool& a,
204  const std::string& aname,
205  std::vector<bool>&& candidate_values = {},
207  : OhmmsElementBase(aname.c_str()),
208  ref_(a),
209  candidate_values_(std::move(candidate_values)),
210  node_(NULL),
211  tag_staus_(status)
212  {
213  // set default value.
214  if (!candidate_values_.empty())
215  ref_ = candidate_values_[0];
216  }
217 
218  ///print to an std::ostream
219  inline bool get(std::ostream& os) const override
220  {
221  os << "<parameter name=\"" << myName << "\"> " << (ref_ ? "yes" : "no") << " </parameter>" << std::endl;
222  return true;
223  }
224 
225  /*!inline bool put(xmlNodePtr cur)
226  *\param cur the current xmlNode whose content is assigned to ref_
227  *\brief If the content is empty, the negation of the current value is taken.
228  *Example is <parameter name="force"/> to turn on the force-evaluation flag
229  *of NoPropagator.
230  */
231  inline bool put(xmlNodePtr cur) override
232  {
234  node_ = cur;
235  const XMLNodeString ac(cur);
236  std::istringstream stream(ac);
237  return put(stream);
238  }
239 
240  inline void setValue(bool x) { ref_ = x; }
241 
242  ///read from std::istream
243  inline bool put(std::istream& is) override
244  {
246  std::string input_value;
247  is >> input_value;
248  std::string input_value_lower_case = qmcplusplus::lowerCase(input_value);
249 
250  if (input_value_lower_case == "yes" || input_value_lower_case == "true")
251  ref_ = true;
252  else if (input_value_lower_case == "no" || input_value_lower_case == "false")
253  ref_ = false;
254  else if (input_value.empty())
255  throw std::runtime_error(myName + " requires a single value input.");
256  else
257  throw std::runtime_error(myName + " only accepts 'yes'/'no'/'true'/'false' but the input value is '" +
258  input_value + "'.");
259 
260  std::string dummy;
261  is >> dummy;
262  if (!dummy.empty())
263  throw std::runtime_error(myName + " only accepts a single value input.");
264  return true;
265  }
266 
267  /*!\fn bool add(xmlNodePtr parent)
268  *\param parent the parent node to which a xmlNode for this object is appended.
269  *\brief This function is used by the users to add a xmlNode, when the
270  *input file does not contain the corresponding <parameter/>. The content
271  *of the new xmlNode is the current value of ref_.
272  */
273  bool add(xmlNodePtr parent) override
274  {
275  if (!node_)
276  {
277  node_ = xmlNewChild(parent, parent->ns, (const xmlChar*)"parameter", NULL);
278  xmlNewProp(node_, (const xmlChar*)"name", (const xmlChar*)(myName.c_str()));
280  }
281  return true;
282  }
283 
284  ///reset member data
285  inline void reset() override { getContent(ref_, node_); }
286 };
287 #endif /*OHMMS_OHMMSPARAMETER_H*/
OhmmsParameter(bool &a, const std::string &aname, std::vector< bool > &&candidate_values={}, TagStatus status=TagStatus::OPTIONAL)
bool put(std::istream &is) override
read from std::istream, used by OhmmsAttributeSet
std::ostream & app_warning()
Definition: OutputManager.h:69
std::vector< bool > candidate_values_
valid candidate values, if not empty, the first one is the default.
std::string myName
the name of the node, corresponds to the xml tag
Declaration of OutputManager class.
bool put(xmlNodePtr cur) override
bool put(xmlNodePtr cur) override
If the content is empty, the negation of the current value is taken. Example is <parameter name="forc...
std::vector< T > candidate_values_
valid candidate values, if not empty, the first one is the default.
void reset() override
reset member data
T & ref_
reference to a value of type T
void checkTagStatus(const std::string &tagname, TagStatus status)
Declaration of OhmmsElementBase and define xml-related macros.
void reset() override
reset member data
bool add(xmlNodePtr parent) override
This function is used by the users to add a xmlNode, when the input file does not contain the corresp...
Abstract class to provide xml-compatible I/O interfaces for the derived classes.
std::string lowerCase(const std::string_view s)
++17
bool & ref_
reference to a value of type T
bool add(xmlNodePtr parent) override
This function is used by the users to add a xmlNode, when the input file does not contain the corresp...
xmlNodePtr node_
pointer to the corresponding xmlNode
bool putContent(T &a, xmlNodePtr cur)
replaces a&#39;s value with the first "element" in the "string" returned by XMLNodeString{cur}.
Definition: libxmldefs.h:88
OhmmsParameter(T &a, const std::string &aname, std::vector< T > &&candidate_values={}, TagStatus status=TagStatus::OPTIONAL)
convert xmlNode contents into a std::string
bool getContent(const T &a, xmlNodePtr cur)
write a value to a node.
Definition: libxmldefs.h:119
OhmmsElementBase(const char *aname="none")
constructor with a name
TagStatus tag_staus_
The status of the tag.
xmlNodePtr node_
pointer to the corresponding xmlNode
bool put(std::istream &is) override
read from std::istream
TagStatus tag_staus_
The status of the tag.
void setValue(T x)
TagStatus
generic class for parameter xmlNode