MADNESS 0.10.1
chem/QCCalculationParametersBase.h
Go to the documentation of this file.
1/*
2 * QCCalculationParametersBase.h
3 *
4 * Created on: 27 Jun 2019
5 * Author: fbischoff
6 */
7
8#ifndef SRC_APPS_CHEM_QCCALCULATIONPARAMETERSBASE_H_
9#define SRC_APPS_CHEM_QCCALCULATIONPARAMETERSBASE_H_
10
12#include <string>
13#include <algorithm>
14#include <iomanip>
15#include <typeindex>
16#include <map>
17#include <set>
18#include <fstream>
19#include <typeinfo>
20// #include <madness/external/gtest/include/gtest/internal/gtest-type-util.h>
21
22#include "madness/misc/misc.h"
24#include "madness/world/world.h"
26#include <nlohmann/json.hpp>
27
28
29namespace madness {
30 using json = nlohmann::json;
31
32 template <typename T>
33 static typename std::enable_if<std::is_floating_point<T>::value, void>::type
34 check_for_inf(const std::string& str, T& arg) {
35 std::string sinf;
36 std::stringstream ss;
37 ss << std::numeric_limits<T>::infinity();
38 sinf = ss.str();
39
40 if (sinf == str) arg = std::numeric_limits<T>::infinity();
41 }
42
43 template <typename T>
44 static typename std::enable_if<!std::is_floating_point<T>::value, void>::type
45 check_for_inf(const std::string& str, T& arg) {
46 return;
47 }
48
49 /// inverting the print method from print.h for std::vector
50 /// TODO: move this where it belongs (into print.h ??)
51 template <typename T, typename A=std::allocator<T>>
52 std::istream& operator>>(std::istream& is, std::vector<T, A>& v) {
53 // get the full line from opening to closing brackets [ .. ]
54 std::string word, line = "";
55 while (is >> word) {
56 line += word;
57 if (word.find(']') != std::string::npos) break;
58 }
59 if (line.size() != 0) is.clear();
60
61 // remove enclosing brackets and commas
62 auto find_c = [](char& c) { return ((c == ',') or (c == '[') or (c == ']')); };
63 std::replace_if(line.begin(), line.end(), find_c, ' '); // 0 2 0 4 0 6 0 8 0
64
65 // stream the values into the container; a string element may be in double quotes,
66 // as a string value may: a regenerated input file (madqc's mad.in) writes a list
67 // as JSON, ["iao","lowdin"], and the quotes are not part of the elements
68 std::stringstream sline(line);
69 T tmp;
70 while (sline >> word) {
71 if constexpr (std::is_same_v<T, std::string>) {
72 if (word.size() >= 2 and word.front() == '"' and word.back() == '"')
73 word = word.substr(1, word.size() - 2);
74 if (word.empty()) continue;
75 }
76 std::stringstream sword(word);
77 sword >> tmp;
78 check_for_inf(word, tmp);
79 v.push_back(tmp);
80 }
81 if (sline.bad()) {
82 madness::print("error while reading vector from istream: ");
83 madness::print(line, "\n");
84 throw std::runtime_error("IO error");
85 }
86
87 return is;
88 }
89
90
91 /// inverting the print method from print.h for std::vector
92 /// TODO: move this where it belongs (into print.h ??)
93 template <typename Q, typename T>
94 std::istream& operator>>(std::istream& is, std::pair<T, Q>& p) {
95 // get all words from the line
96 std::string word, line = "";
97 while (is >> word) {
98 line += word + " ";
99 };
100 // have to set this here to account for the error handling later..
101 is.clear();
102
103 // remove enclosing brackets and commas
104 auto find_c = [](char& c) { return ((c == ',') or (c == '(') or (c == ')')); };
105 std::replace_if(line.begin(), line.end(), find_c, ' '); // 0 2 0 4 0 6 0 8 0
106
107 // stream the values into the container
108 std::stringstream sline(line);
109 T tmp1;
110 Q tmp2;
111 sline >> tmp1 >> tmp2;
112 if (sline.bad() or sline.fail()) {
113 madness::print("error while reading vector from istream: ");
114 madness::print(line, "\n");
115 throw std::runtime_error("IO error");
116 }
117 p = std::pair<T, Q>(tmp1, tmp2);
118
119 return is;
120 }
121
122
123 /// structure holding the value for a given parameter
124
125 /// keeps logic about default, derived and user-defined settings (with increasing priority),
126 /// as well as comments for the user (e.g. a recommended range for a given parameter).
127 ///
128 /// might be extended to hold allowed values for certain parameters, e.g. localization procedures.
129 ///
130 /// all values are stored as strings and must be converted to their respective types by the
131 /// QCCalculationParametersBase class (see below)
132 struct QCParameter {
133 public:
135
136 QCParameter(const std::string v, const std::string t, const std::string comment = "",
137 const std::vector<std::string> allowed_values1 = {})
138 : default_value(v), type(t), comment(comment), allowed_values(allowed_values1) {
139 static int i = 0;
140 print_order = i++;
141 set_all();
142 }
143
144 void set_derived_value(const std::string val) {
145 precedence = std::max(derived, precedence);
146 derived_value = val;
147 set_all();
148 }
149
150 void set_user_defined_value(const std::string val) {
151 precedence = std::max(defined, precedence);
152 user_defined_value = val;
153 set_all();
154 }
155
156 bool is_user_defined() const {
157 return (precedence == defined);
158 }
159
160 std::string get_value() const { return value; }
161 std::string get_type() const { return type; }
162 std::string get_comment() const { return comment; }
163
164 std::string print_precedence() const {
165 if (precedence == def) return "default";
166 if (precedence == derived) return "derived";
167 if (precedence == defined) return "defined";
168 std::stringstream sprecedence;
169 sprecedence << precedence;
170 throw std::runtime_error("unknown precedence in QCParameter" + sprecedence.str());
171 return "darn";
172 }
173
174 int get_print_order() const { return print_order; }
175
176 std::string print_line(const std::string& key) const {
177 auto fill_left = [](const int size, const std::string word) {
178 int nspaces = std::max(int(0), size - int(word.length()));
179 return std::string(nspaces, ' ') + word;
180 };
181 auto fill_right = [](const int size, const std::string word) {
182 int nspaces = std::max(int(0), size - int(word.length()));
183 return word + std::string(nspaces, ' ');
184 };
185
186 // key-value block
187 std::string keyval = fill_left(20, key) + " " + fill_right(10, get_value()) + " # " + fill_right(
188 10, print_precedence());
189 std::string empty_keyval(keyval.size(), ' ');
190 empty_keyval[33] = '#';
191
192 std::string allowed_val;
193 if (allowed_values.size() > 0) {
194 using madness::operators::operator<<;
195 std::stringstream ss;
196 ss << allowed_values;
197 allowed_val += ss.str();
198 }
199
200 // split comment into several lines: split onto words and add linebreak
201 bool leave_space_for_allowed_values = (allowed_val.size() > 0);
202
203 // first line breaks after 80 characters, all other lines after 120 (leave space f
204 long keyvalsize = keyval.size(); // length of key, value, precedence
205 std::string comment1 = get_comment();
206 auto commentwords = commandlineparser::split(comment1, " ");
207 std::vector<std::string> commentlines(1);
208 long nchar = 0;
209 for (auto word : commentwords) {
210 bool is_first_line = commentlines.size() == 1;
211 long thislinebreak = 120;
212 if (is_first_line and leave_space_for_allowed_values) thislinebreak = 80;
213 long commentsize = thislinebreak - keyvalsize;
214
215 nchar += word.size() + 1;
216 if (nchar > commentsize) { // start newline
217 commentlines.push_back("");
218 nchar = word.size() + 1;
219 }
220 commentlines.back() += word + " ";
221 }
222
223 std::string result;
224 for (size_t i = 0; i < commentlines.size(); ++i) {
225 if (i == 0) result = keyval + fill_right(40, commentlines[i]) + allowed_val;
226 else result += "\n" + empty_keyval + commentlines[i];
227 }
228
229 // trim result
230 std::size_t last = result.find_last_not_of(' ');
231 return result.substr(0, last + 1);
232 }
233
234 template <typename Archive>
239
241
242 bool operator==(const QCParameter& other) const {
243 return (value == other.value and default_value == other.default_value and
245 type == other.type and null == other.null and comment == other.comment and
247 }
248
249 hashT hash() const {
250 return hash_value(value);
251 }
252
253 private:
254 void set_all() {
258 if (not check_allowed()) throw std::invalid_argument(not_allowed_errmsg());
259 }
260
262 if (allowed_values.size() == 0) return true;
263 auto it = std::find(allowed_values.begin(), allowed_values.end(), value);
264 return (it != allowed_values.end());
265 }
266
267 std::string not_allowed_errmsg() const {
268 using madness::operators::operator<<;
269 std::stringstream ss;
270 ss << allowed_values;
271 std::string errmsg = "\ntrying to assign a value that's not allowed\n\n";
272 errmsg += "\tuser-defined value: " + value + "\n";
273 errmsg += "\tallowed values: " + ss.str() + "\n\n";
274 return errmsg;
275 }
276
277
278 std::string value;
279 std::string default_value = "";
280 std::string derived_value = "";
281 std::string user_defined_value = "";
282 std::string type = "";
283 std::string null = "";
284 std::string comment = "";
285 std::vector<std::string> allowed_values = std::vector<std::string>();
286 int print_order = 0; // use this for printing the parameters in the same order as they are defined
287 };
288
289 /// class for holding the parameters for calculation
290
291 /// Actual parameter classes will be derived from this class with a simple constructor
292 /// (see test_QCCalculationParametersBase.cc for an example) and convenience
293 /// getters for the parameters of each parameter class.
294 /// Having the base class will allow consistent parameter input/output handling
295 /// for all madness programs and reuse of the parsing methods.
296 /// Even if the same parameter is used in different programs, default might differ
297 /// (i.e. econv for 3D/6D calculations). The parameter class will effectively serve as
298 /// a factory for the calculation classes (SCF, nemo, mp2, etc)
299 ///
300 /// parameters are kept in a map with key (string) and value (QCParameter),
301 /// types are converted whenever a parameter is accessed (i.e. should not be
302 /// done too frequently in an inner loop)
304 public:
305 /// print all parameters
306 void print(const std::string header = "", const std::string footer = "") const;
307
308 virtual std::string get_tag() const = 0;
309
310 std::string print_to_string(const std::list<std::string> precedences={"all"}) const;
311
312 template <typename T>
313 T get(const std::string key) const {
314 const QCParameter& parameter = get_parameter(key);
315 MADNESS_ASSERT(check_type<T>(key,parameter));
316 if (std::is_same<T, std::string>::value) {
317 return fromstring<T>(add_quotes(parameter.get_value()));
318 }
319 return fromstring<T>(parameter.get_value());
320 }
321
322 bool is_user_defined(std::string key) const {
323 return get_parameter(key).is_user_defined();
324 }
325
326 template <typename Archive>
327 void serialize(Archive& ar) {
328 ar & parameters & print_debug;
329 }
330
331 hashT hash() const {
332 return hash_range(parameters.begin(), parameters.end());
333 }
334
335 protected:
336 typedef std::map<std::string, QCParameter> ParameterContainerT;
338
340 const commandlineparser& parser,
341 const std::string tag) {
342 // check that user-defined input files actually exist
343 bool file_ok = true;
344 if (parser.key_exists("user_defined_input_file")) file_ok = file_exists(world, parser.value("input"));
345 if (not file_ok) {
346 std::string msg = "could not find user-defined input file: " + parser.value("input") + "\n";
347 throw std::invalid_argument(msg);
348 }
349 // Errors from read_input propagate. They used to be printed and then
350 // swallowed, which turned a rejected keyval into a silent fallback to
351 // the default -- a deck asking for a DFT functional the parser choked
352 // on computed Hartree-Fock instead, and said so only in one line of
353 // output above thousands. A missing data group is not an error and
354 // does not throw (see read_input), so decks that only set some of the
355 // groups are unaffected.
356 read_input(world, parser.value("input"), tag);
357 read_commandline_options(world, parser, tag);
358 }
359
360 public:
361 bool file_exists(World& world, std::string filename) const;
362
363 /// Apply `--<tag>=key=val` command-line overrides on top of the current
364 /// values. Public so ParameterManager::initFromJson can layer CLI
365 /// overrides after from_json (the text path gets them via the ctor's
366 /// read_input_and_commandline_options; JSON decks otherwise ignored them).
367 void read_commandline_options(World& world, const commandlineparser& parser, const std::string tag);
368
369 private:
370 /// read the parameters from file
371
372 /// only world.rank()==0 reads the input file and broadcasts to all other nodes,
373 /// so we don't need to serialize the ParameterMap
374 void read_input(World& world, const std::string filename, const std::string tag);
375
376 protected:
377 bool print_debug = false;
381
382 /// ctor for testing
384
385 /// copy ctor
389
390 /// destructor
392
393 template <typename T>
394 void initialize(const std::string& key, const T& value, const std::string comment = "",
395 const std::vector<T> allowed_values = {}) {
396 if (parameters.find(key) != parameters.end()) {
397 madness::print("you cannot initialize a parameter twice: ", key);
398 throw std::runtime_error("initialization error");
399 }
400
401 std::string svalue = tostring(value);
402 std::string type = std::type_index(typeid(T)).name();
403
404 // transform everything to lower case
405 std::string key_lower = key;
406 std::transform(key_lower.begin(), key_lower.end(), key_lower.begin(), ::tolower);
407 std::transform(svalue.begin(), svalue.end(), svalue.begin(), ::tolower);
408 std::vector<std::string> av_lower_vec;
409 for (const T& av : allowed_values) {
410 std::string av_lower = tostring(av);
411 std::transform(av_lower.begin(), av_lower.end(), av_lower.begin(), ::tolower);
412 av_lower_vec.push_back(av_lower);
413 }
414
415 parameters.insert(std::make_pair<std::string, QCParameter>
416 (std::string(key_lower), QCParameter(svalue, type, comment, av_lower_vec)));
417 }
418
419 public:
420 /// keys whose string values must NOT be case-folded
421
422 /// String parameter values are lowercased on the way in so that enum-like
423 /// knobs match their lowercased \c allowed_values (`xc=HF`, `units=Bohr`).
424 /// That is wrong for free-form values such as paths and filenames, which
425 /// are case-sensitive on the filesystem. Derived classes list those keys
426 /// here and they are then stored verbatim -- the parameter-store analogue
427 /// of \c commandlineparser::set_keyval_keep_case.
428 virtual std::set<std::string> case_sensitive_keys() const { return {}; }
429
430 bool keeps_case(const std::string& key) const {
431 const auto keys = case_sensitive_keys();
432 return keys.find(key) != keys.end();
433 }
434
435 template <typename T>
436 void set_derived_value(const std::string& key, const T& value) {
437 QCParameter& parameter = get_parameter(key);
438 if (not check_type_silent<T>(parameter)) {
439 throw std::runtime_error("type error in set_derived_value for key " + key);
440 }
441 parameter.set_derived_value(to_stored_string(key, value));
442 }
443
447
448 protected:
449 /// helper function for try_setting_user_defined_value
450 template <typename Tuple, std::size_t... I>
451 bool try_setting_any_impl(const std::string& key, const std::string& value, Tuple, std::index_sequence<I...>) {
452 bool success = false;
453 (void)std::initializer_list<int>{
454 (success = try_setting_user_defined_value<std::tuple_element_t<I, Tuple>>(key, value) || success, 0)...
455 };
456 return success;
457 }
458
459 /// helper function for try_setting_user_defined_value
460 template <typename Tuple>
461 bool try_setting_any(const std::string& key, const std::string& value) {
462 return try_setting_any_impl(key, value, Tuple{}, std::make_index_sequence<std::tuple_size<Tuple>::value>{});
463 }
464
465 /// helper function for try_setting_user_defined_value
466 template <typename T>
467 bool try_setting_user_defined_value(const std::string& key, const std::string& val) {
468 if (not check_type_silent<T>(get_parameter(key))) return false;
469
470 if (print_debug) ::madness::print("key:", key, "will set type", std::type_index(typeid(T)).name());
471 T value = fromstring<T>(val);
472 set_user_defined_value<T>(key, value);
473 return true;
474 }
475
476 public:
477
478 template <typename... Types>
479 bool try_set_from_json(QCParameter& parameter, const nlohmann::json& value) {
480 bool success = false;
481 (void)std::initializer_list<int>{
482 (parameter.get_type() == std::type_index(typeid(Types)).name()
483 ? (parameter.set_user_defined_value(QCCalculationParametersBase::tostring(value.get<Types>())), success = true, 0)
484 : 0)...
485 };
486 return success;
487 }
488
489 void from_json(const json& j) {
490 for (const auto& [key, value1] : j.items()) {
491 const auto& value = value1; // avoid shadowing
492 QCParameter& parameter = get_parameter(key);
493 using all_types = all_parameter_types;
494 bool ok = false;
495 std::apply([&](auto&&... args) {
496 ok = try_set_from_json<std::decay_t<decltype(args)>...>(parameter, value);
497 }, all_types{});
498 if (!ok) {
499 throw std::runtime_error("Unsupported parameter type for key: " + key);
500 }
501 }
502 }
503 // Helper to forward tuple types to qcparameter_to_json
504 template <typename... Types>
505 void qcparameter_to_json(json& j, const std::pair<std::string, QCParameter>& p,
506 const std::tuple<Types...>&) const {
507 (void)std::initializer_list<int>{
508 (check_type_silent<Types>(p.second) ? (j[p.first] = get<Types>(p.first), 0) : 0)...
509 };
510 }
511
512 // Helper to forward tuple types to qcparameter_to_json
513 template <typename Tuple>
514 void qcparameter_to_json_from_tuple(json& j, const std::pair<std::string, QCParameter>& p, const Tuple&) const {
515 std::apply([&](auto&&... args) {
516 qcparameter_to_json(j, p, std::tuple<std::decay_t<decltype(args)>...>{});
517 }, Tuple{});
518 }
519
520 /// convert all parameters to a json object
521 [[nodiscard]] json to_json() const {
522 json j_params = {};
523 to_json(j_params);
524 return j_params;
525 }
526
527 /// convert all parameters to a json object
528 void to_json(json& j) const {
529 json j_params = {};
530 for (auto& p : parameters) {
532 }
533 j["parameters"] = j_params;
534 }
535
536 /// convert all parameters to a json object, but only those with a given precedence
538 const std::string& precedence) const {
539 json j_params = {};
540 for (auto& p : parameters) {
541 if (p.second.print_precedence() == precedence) {
543 }
544 }
545 return j_params;
546 }
547
548 template <typename T>
549 void set_user_defined_value(const std::string& key, const T& value) {
550 QCParameter& parameter = get_parameter(key);
551 if (not check_type_silent<T>(parameter)) {
552 throw std::runtime_error("type error in set_user_defined_value");
553 }
554
555 // Name the key in the allowed-values message. QCParameter does not
556 // know its own key, so an out-of-range value used to report only the
557 // value and the list of alternatives, leaving the reader to guess
558 // which keyval it came from -- an input may set several that have
559 // allowed values.
560 try {
561 parameter.set_user_defined_value(to_stored_string(key, value));
562 } catch (const std::invalid_argument& e) {
563 throw std::invalid_argument("in keyword `" + key + "`: " + e.what());
564 }
565 }
566
567 /// stringify \p value for storage, honoring case_sensitive_keys()
568 template <typename T>
569 std::string to_stored_string(const std::string& key, const T& value) const {
570 if constexpr (std::is_same<T, std::string>::value) {
571 if (keeps_case(key)) return value;
572 }
573 return tostring(value);
574 }
575
576 friend bool operator==(const QCCalculationParametersBase& p1,
578
579 protected:
580 const QCParameter& get_parameter(const std::string& key) const {
581 if (not parameter_exists(key)) {
582 throw std::runtime_error("could not find parameter for key " + key);
583 }
584 const QCParameter& parameter = parameters.find(key)->second;
585 return parameter;
586 }
587
588 public:
589 QCParameter& get_parameter(const std::string key) {
590 if (not parameter_exists(key)) {
591 madness::print("\ncould not find parameter for key", key, "\n");
592 throw std::runtime_error("could not find parameter for key " + key);
593 }
594 QCParameter& parameter = parameters.find(key)->second;
595 return parameter;
596 }
597
598 bool parameter_exists(const std::string& key) const {
599 return (parameters.find(key) != parameters.end());
600 }
601
602 template <typename T>
603 static bool check_type(const std::string key, const QCParameter& parameter) {
604 if (check_type_silent<T>(parameter))
605 return true;
606
608 "trying to get the wrong type in QCCalculationParametersBase");
609 madness::print("key ", key);
610 madness::print("parameter type ", parameter.get_type());
611 madness::print("setting type ", std::type_index(typeid(T)).name());
612 madness::print("value ", parameter.get_value());
613 return false;
614 }
615
616 template <typename T>
617 static bool check_type_silent(const QCParameter& parameter) {
618 return (parameter.get_type() == std::type_index(typeid(T)).name());
619 }
620
621 /// read the stream, starting from tag
622
623 /// only parameters that are defined in the constructor will be processed,
624 /// all others will be discarded.
625 virtual void read_internal(World& world, std::string& filecontents,
626 std::string tag);
627
628 static std::string tostring(const bool& arg) {
629 std::ostringstream ss;
630 ss << std::boolalpha << arg;
631 return ss.str();
632 }
633
634 template <typename T>
635 static std::string tostring(const T& arg) {
636 using madness::operators::operator<<;
637 std::ostringstream ss;
638 static_assert(not std::is_same<T, bool>::value, "you need to specialize tostring for this type");
639
640 ss << std::scientific << std::setprecision(4) << arg;
641 std::string str = ss.str();
642 std::transform(str.begin(), str.end(), str.begin(), ::tolower);
643
644 overwrite_if_inf(str, arg);
645 return str;
646 }
647
648 template <typename T>
649 static typename std::enable_if<std::is_floating_point<T>::value, void>::type
650 overwrite_if_inf(std::string& str, const T& arg) {
651 MADNESS_PRAGMA_CLANG(diagnostic push)
652 MADNESS_PRAGMA_CLANG(diagnostic ignored "-Wtautological-constant-compare")
653 if (std::isinf(arg)) {
654 std::stringstream ss;
655 ss << std::numeric_limits<T>::infinity();
656 str = ss.str();
657 }
658 MADNESS_PRAGMA_CLANG(diagnostic pop)
659 }
660
661 template <typename T>
662 static typename std::enable_if<!std::is_floating_point<T>::value, void>::type
663 overwrite_if_inf(std::string& str, const T& arg) {
664 return;
665 }
666
667 template <typename T>
668 static typename std::enable_if<!std::is_same<T, bool>::value, T>::type
669 fromstring(const std::string& arg) {
670 std::stringstream ssvalue(arg);
671
672 // if argument is std::string read the everything between possible double quotes
673 T result = read_quotes<T>(ssvalue);
674
675 bool type_conversion_failed = ssvalue.fail();
676
677 // check for infinity in floating point conversions -- and only clear
678 // the failure when the value really was an infinity. Clearing it
679 // unconditionally accepted any malformed float (`econv 1.e-4a`) and
680 // stored whatever the failed extraction had left behind.
681 if (type_conversion_failed and (std::is_floating_point<T>::value)) {
682 const static T inf = std::numeric_limits<T>::infinity();
683 std::string sinf = tostring(inf); // repeat type conversion from above
684 if (sinf == arg) {
685 result = inf;
686 type_conversion_failed = false;
687 }
688 }
689
690 if (type_conversion_failed) {
691 std::string errmsg = "error in type conversion for argument >> " + arg +
692 " << to type " + std::type_index(typeid(T)).name();
693 throw std::runtime_error(errmsg);
694 }
695
696 // check for trailing characters
697 std::string word;
698 while (ssvalue >> word) {
699 std::string errmsg = "trailing characters in arguement >> " + arg + " <<";
700 throw std::runtime_error(errmsg);
701 }
702 return result;
703 }
704
705 template <typename T>
706 static typename std::enable_if<std::is_same<T, std::string>::value, T>::type
707 read_quotes(std::stringstream& ssvalue) {
708 T arg = ssvalue.str();
709 T result;
710
711 if (arg.find("\"") == std::string::npos) { // no double quotes found
712 // take the whole (blank-trimmed) remainder, not just the first
713 // word: free-form string values legitimately contain blanks
714 // (`xc GGA_X_PBE 0.75 GGA_C_PBE 1.0 HF_X 0.25`,
715 // `freeze_pairs 0 1 2 3`, ...). Reading one word only and then
716 // tripping the trailing-characters check in fromstring() made
717 // those values quote-mandatory. Consume the stream so
718 // fromstring() sees no leftovers.
719 result = trim_blanks(arg);
720 ssvalue.str("");
721 ssvalue.clear();
722 // a key with no value at all stays an error, as before -- an
723 // empty string can never be stored anyway (QCParameter::null)
724 if (result.empty()) ssvalue.setstate(std::ios::failbit);
725 }
726 else { // found double quotes
727 int counter = 0;
728 while (counter < 2) {
729 T tmp;
730 ssvalue >> tmp;
731 if (ssvalue.fail()) {
732 std::string errmsg = "missing closing double quote in line >> " + arg;
733 throw std::runtime_error(errmsg);
734 }
735 result += " " + tmp;
736 counter = std::count(result.begin(), result.end(), '"');
737 }
738
739 // use only the text between the double quotes
740 result = trim_blanks(trim_quotes(result));
741 }
742 return result;
743 }
744
745 static std::string trim_blanks(const std::string arg) {
746 std::size_t first = arg.find_first_not_of(' ');
747 if (first == std::string::npos) return ""; // empty or all blanks
748 std::size_t last = arg.find_last_not_of(' ');
749 return arg.substr(first, last - first + 1);
750 }
751
752 static std::string trim_quotes(const std::string arg) {
753 std::size_t first = arg.find_first_of('"');
754 std::size_t last = arg.find_last_of('"');
755 return arg.substr(first + 1, last - first - 1);
756 }
757
758 static std::string add_quotes(const std::string arg) {
759 return "\"" + arg + "\"";
760 }
761
762 template <typename T>
763 static typename std::enable_if<!std::is_same<T, std::string>::value, T>::type
764 read_quotes(std::stringstream& ssvalue) {
765 T result;
766 ssvalue >> result;
767 return result;
768 }
769
770 template <typename T>
771 static typename std::enable_if<std::is_same<T, bool>::value, T>::type
772 fromstring(const std::string& arg) {
773 std::string str = arg;
774 std::transform(str.begin(), str.end(), str.begin(), ::tolower);
775 if (str == "true" or str == "1" or str == "yes")
776 return true;
777 if (str == "false" or str == "0" or str == "no")
778 return false;
779 std::string errmsg = "error in type conversion for argument >> " + arg +
780 " << to type " + std::type_index(typeid(T)).name();
781 throw std::runtime_error(errmsg);
782 return 0;
783 }
784
785
786 // a templated list of all acceptable parameter types for looping in a parameter pack
787 using all_parameter_types = std::tuple<
788 double, int, unsigned int, long, std::size_t, bool, std::string,
789 std::vector<double>, std::vector<int>, std::vector<std::size_t>,
790 std::vector<std::string>, std::pair<std::string, double>>;
791 };
792
795} /* namespace madness */
796
797#endif /* SRC_APPS_CHEM_QCCALCULATIONPARAMETERSBASE_H_ */
Interface templates for the archives (serialization).
class for holding the parameters for calculation
Definition chem/QCCalculationParametersBase.h:303
static bool check_type_silent(const QCParameter &parameter)
Definition chem/QCCalculationParametersBase.h:617
std::tuple< double, int, unsigned int, long, std::size_t, bool, std::string, std::vector< double >, std::vector< int >, std::vector< std::size_t >, std::vector< std::string >, std::pair< std::string, double > > all_parameter_types
Definition chem/QCCalculationParametersBase.h:790
static std::enable_if< std::is_same< T, std::string >::value, T >::type read_quotes(std::stringstream &ssvalue)
Definition chem/QCCalculationParametersBase.h:707
void read_input_and_commandline_options(World &world, const commandlineparser &parser, const std::string tag)
Definition chem/QCCalculationParametersBase.h:339
ParameterContainerT get_all_parameters() const
Definition chem/QCCalculationParametersBase.h:444
static std::string tostring(const T &arg)
Definition chem/QCCalculationParametersBase.h:635
bool keeps_case(const std::string &key) const
Definition chem/QCCalculationParametersBase.h:430
hashT hash() const
Definition chem/QCCalculationParametersBase.h:331
friend bool operator==(const QCCalculationParametersBase &p1, const QCCalculationParametersBase &p2)
Definition QCCalculationParametersBase.cc:237
std::string to_stored_string(const std::string &key, const T &value) const
stringify value for storage, honoring case_sensitive_keys()
Definition chem/QCCalculationParametersBase.h:569
static std::enable_if< std::is_floating_point< T >::value, void >::type overwrite_if_inf(std::string &str, const T &arg)
Definition chem/QCCalculationParametersBase.h:650
static std::enable_if<!std::is_floating_point< T >::value, void >::type overwrite_if_inf(std::string &str, const T &arg)
Definition chem/QCCalculationParametersBase.h:663
void qcparameter_to_json(json &j, const std::pair< std::string, QCParameter > &p, const std::tuple< Types... > &) const
Definition chem/QCCalculationParametersBase.h:505
bool throw_if_datagroup_not_found
Definition chem/QCCalculationParametersBase.h:380
bool try_setting_any_impl(const std::string &key, const std::string &value, Tuple, std::index_sequence< I... >)
helper function for try_setting_user_defined_value
Definition chem/QCCalculationParametersBase.h:451
void set_user_defined_value(const std::string &key, const T &value)
Definition chem/QCCalculationParametersBase.h:549
virtual std::set< std::string > case_sensitive_keys() const
keys whose string values must NOT be case-folded
Definition chem/QCCalculationParametersBase.h:428
bool print_debug
Definition chem/QCCalculationParametersBase.h:377
const QCParameter & get_parameter(const std::string &key) const
Definition chem/QCCalculationParametersBase.h:580
json to_json() const
convert all parameters to a json object
Definition chem/QCCalculationParametersBase.h:521
void to_json(json &j) const
convert all parameters to a json object
Definition chem/QCCalculationParametersBase.h:528
void qcparameter_to_json_from_tuple(json &j, const std::pair< std::string, QCParameter > &p, const Tuple &) const
Definition chem/QCCalculationParametersBase.h:514
virtual void read_internal(World &world, std::string &filecontents, std::string tag)
read the stream, starting from tag
Definition QCCalculationParametersBase.cc:155
void read_input(World &world, const std::string filename, const std::string tag)
read the parameters from file
Definition QCCalculationParametersBase.cc:84
std::string print_to_string(const std::list< std::string > precedences={"all"}) const
Definition QCCalculationParametersBase.cc:41
void read_commandline_options(World &world, const commandlineparser &parser, const std::string tag)
read the parameters from the command line and broadcast
Definition QCCalculationParametersBase.cc:133
bool parameter_exists(const std::string &key) const
Definition chem/QCCalculationParametersBase.h:598
T get(const std::string key) const
Definition chem/QCCalculationParametersBase.h:313
bool try_set_from_json(QCParameter &parameter, const nlohmann::json &value)
Definition chem/QCCalculationParametersBase.h:479
void initialize(const std::string &key, const T &value, const std::string comment="", const std::vector< T > allowed_values={})
Definition chem/QCCalculationParametersBase.h:394
void print(const std::string header="", const std::string footer="") const
print all parameters
Definition QCCalculationParametersBase.cc:32
void from_json(const json &j)
Definition chem/QCCalculationParametersBase.h:489
bool ignore_unknown_keys
Definition chem/QCCalculationParametersBase.h:378
bool file_exists(World &world, std::string filename) const
Definition QCCalculationParametersBase.cc:72
static std::string tostring(const bool &arg)
Definition chem/QCCalculationParametersBase.h:628
QCCalculationParametersBase(const QCCalculationParametersBase &other)
copy ctor
Definition chem/QCCalculationParametersBase.h:386
static std::enable_if<!std::is_same< T, std::string >::value, T >::type read_quotes(std::stringstream &ssvalue)
Definition chem/QCCalculationParametersBase.h:764
bool ignore_unknown_keys_silently
Definition chem/QCCalculationParametersBase.h:379
QCParameter & get_parameter(const std::string key)
Definition chem/QCCalculationParametersBase.h:589
bool is_user_defined(std::string key) const
Definition chem/QCCalculationParametersBase.h:322
void serialize(Archive &ar)
Definition chem/QCCalculationParametersBase.h:327
bool try_setting_user_defined_value(const std::string &key, const std::string &val)
helper function for try_setting_user_defined_value
Definition chem/QCCalculationParametersBase.h:467
json to_json_if_precedence(const std::string &precedence) const
convert all parameters to a json object, but only those with a given precedence
Definition chem/QCCalculationParametersBase.h:537
bool try_setting_any(const std::string &key, const std::string &value)
helper function for try_setting_user_defined_value
Definition chem/QCCalculationParametersBase.h:461
static std::string trim_blanks(const std::string arg)
Definition chem/QCCalculationParametersBase.h:745
ParameterContainerT parameters
Definition chem/QCCalculationParametersBase.h:337
std::map< std::string, QCParameter > ParameterContainerT
Definition chem/QCCalculationParametersBase.h:336
static bool check_type(const std::string key, const QCParameter &parameter)
Definition chem/QCCalculationParametersBase.h:603
static std::string add_quotes(const std::string arg)
Definition chem/QCCalculationParametersBase.h:758
static std::enable_if< std::is_same< T, bool >::value, T >::type fromstring(const std::string &arg)
Definition chem/QCCalculationParametersBase.h:772
static std::enable_if<!std::is_same< T, bool >::value, T >::type fromstring(const std::string &arg)
Definition chem/QCCalculationParametersBase.h:669
virtual ~QCCalculationParametersBase()
destructor
Definition chem/QCCalculationParametersBase.h:391
static std::string trim_quotes(const std::string arg)
Definition chem/QCCalculationParametersBase.h:752
void set_derived_value(const std::string &key, const T &value)
Definition chem/QCCalculationParametersBase.h:436
QCCalculationParametersBase()
ctor for testing
Definition chem/QCCalculationParametersBase.h:383
virtual std::string get_tag() const =0
A parallel world class.
Definition world.h:134
char * p(char *buf, const char *name, int k, int initial_level, double thresh, int order)
Definition derivatives.cc:72
Tensor< typename Tensor< T >::scalar_type > arg(const Tensor< T > &t)
Return a new tensor holding the argument of each element of t (complex types only)
Definition tensor.h:2757
static const double v
Definition hatom_sf_dirac.cc:20
Macros and tools pertaining to the configuration of MADNESS.
#define MADNESS_PRAGMA_CLANG(x)
Definition madness_config.h:200
#define MADNESS_ASSERT(condition)
Assert a condition that should be free of side-effects since in release builds this might be a no-op.
Definition madness_exception.h:134
Header to declare stuff which has not yet found a home.
Namespace for all elements and tools of MADNESS.
Definition DFConvergence.h:9
void hash_range(hashT &seed, It first, It last)
Definition worldhash.h:281
static const char * filename
Definition legendre.cc:96
static std::enable_if< std::is_floating_point< T >::value, void >::type check_for_inf(const std::string &str, T &arg)
Definition chem/QCCalculationParametersBase.h:34
bool operator!=(const QCCalculationParametersBase &p1, const QCCalculationParametersBase &p2)
Definition QCCalculationParametersBase.cc:248
static double pop(std::vector< double > &v)
Definition SCF.cc:118
nlohmann::json json
Definition chem/QCCalculationParametersBase.h:30
std::istream & operator>>(std::istream &is, PairType &en)
Definition PNOParameters.cpp:24
std::size_t hashT
The hash value type.
Definition worldhash.h:146
void print(const T &t, Ts &&... ts)
Print items to std::cout (items separated by spaces) and terminate with a new line.
Definition print.h:232
std::string type(const PairType &n)
Definition PNOParameters.h:18
std::string name(const FuncType &type, const int ex=-1)
Definition ccpairfunction.h:28
madness::hashT hash_value(const std::array< T, N > &a)
Hash std::array with madness hash.
Definition array_addons.h:78
double Q(double a)
Definition relops.cc:20
static const double c
Definition relops.cc:10
structure holding the value for a given parameter
Definition chem/QCCalculationParametersBase.h:132
int print_order
Definition chem/QCCalculationParametersBase.h:286
bool operator==(const QCParameter &other) const
Definition chem/QCCalculationParametersBase.h:242
std::string print_line(const std::string &key) const
Definition chem/QCCalculationParametersBase.h:176
QCParameter()
Definition chem/QCCalculationParametersBase.h:134
enum madness::QCParameter::@0 precedence
QCParameter(const std::string v, const std::string t, const std::string comment="", const std::vector< std::string > allowed_values1={})
Definition chem/QCCalculationParametersBase.h:136
int get_print_order() const
Definition chem/QCCalculationParametersBase.h:174
std::string default_value
Definition chem/QCCalculationParametersBase.h:279
std::string not_allowed_errmsg() const
Definition chem/QCCalculationParametersBase.h:267
void serialize(Archive &ar)
Definition chem/QCCalculationParametersBase.h:235
std::string user_defined_value
Definition chem/QCCalculationParametersBase.h:281
void set_all()
Definition chem/QCCalculationParametersBase.h:254
bool check_allowed()
Definition chem/QCCalculationParametersBase.h:261
@ derived
Definition chem/QCCalculationParametersBase.h:240
@ defined
Definition chem/QCCalculationParametersBase.h:240
@ def
Definition chem/QCCalculationParametersBase.h:240
std::vector< std::string > allowed_values
Definition chem/QCCalculationParametersBase.h:285
std::string get_comment() const
Definition chem/QCCalculationParametersBase.h:162
void set_user_defined_value(const std::string val)
Definition chem/QCCalculationParametersBase.h:150
std::string type
Definition chem/QCCalculationParametersBase.h:282
std::string print_precedence() const
Definition chem/QCCalculationParametersBase.h:164
std::string value
Definition chem/QCCalculationParametersBase.h:278
std::string derived_value
Definition chem/QCCalculationParametersBase.h:280
std::string get_type() const
Definition chem/QCCalculationParametersBase.h:161
std::string comment
Definition chem/QCCalculationParametersBase.h:284
bool is_user_defined() const
Definition chem/QCCalculationParametersBase.h:156
std::string null
Definition chem/QCCalculationParametersBase.h:283
std::string get_value() const
Definition chem/QCCalculationParametersBase.h:160
void set_derived_value(const std::string val)
Definition chem/QCCalculationParametersBase.h:144
hashT hash() const
Definition chem/QCCalculationParametersBase.h:249
very simple command line parser
Definition commandlineparser.h:28
std::string value(const std::string key) const
Definition commandlineparser.h:84
bool key_exists(std::string key) const
Definition commandlineparser.h:80
static std::vector< std::string > split(std::string s, const std::string delimiter)
split a string s into a vector of strings, using delimiter
Definition commandlineparser.h:136
static const double_complex I
Definition tdse1d.cc:164
std::string ok(const bool b)
Definition test6.cc:43
void errmsg(const char *msg, int status)
Definition test_hashthreaded.cc:54
void e()
Definition test_sig.cc:75
Declares the World class for the parallel runtime environment.