Block-Structured AMR Software Framework
AMReX_ParmParse.H
Go to the documentation of this file.
1 #ifndef AMREX_PARMPARSE_H_
2 #define AMREX_PARMPARSE_H_
3 #include <AMReX_Config.H>
4 
5 #include <AMReX_BLassert.H>
6 #include <AMReX_Enum.H>
7 #include <AMReX_INT.H>
8 #include <AMReX_IParser.H>
9 #include <AMReX_Parser.H>
10 #include <AMReX_TypeTraits.H>
11 
12 #include <array>
13 #include <iosfwd>
14 #include <optional>
15 #include <set>
16 #include <string>
17 #include <string_view>
18 #include <unordered_map>
19 #include <vector>
20 
21 namespace amrex {
22 
23 template<int dim>
24 class BoxND;
25 using Box = BoxND<AMREX_SPACEDIM>;
26 template<int dim>
27 class IntVectND;
28 using IntVect = IntVectND<AMREX_SPACEDIM>;
29 class RealVect;
30 
31 namespace ppdetail {
32  template <class T, class Enable = void>
33  struct ArithmeticOptional_TT : std::false_type {};
34 
35  template <class T>
36  struct ArithmeticOptional_TT<T, std::enable_if_t<std::is_arithmetic_v<T>>>
37  : std::true_type
38  {
39  using value_type = T;
40  };
41 
42  template <class T>
43  struct ArithmeticOptional_TT<std::optional<T>,
44  std::enable_if_t<std::is_arithmetic_v<T>>>
45  : std::true_type
46  {
47  using value_type = T;
48  };
49 
50  template <class T>
52 
53  template <class T>
55 }
56 
57 //
58 // ParmParse class implements a simple database for the storage and
59 // retrieval of command-line and input-file arguments. The entries are
60 // stored in a static table in (name,value_list) pairs.
61 //
62 // The format of the input file is a series of DEFINITIONS.
63 //
64 // A DEFINITION is of the form <name> = <value> <value> ...
65 // The equal sign is important since the list of values can span multiple
66 // lines.
67 //
68 // Comments in an input file include all text from a '#' character to the
69 // end of the line. Here is an example input file:
70 /*
71  niter = 100 # niter is an integer
72  title = "Double Wammy" # example of a string with spaces
73  cell_size = 0.5 0.75 # cell spacing in each dimension
74  plot.var = Density 1 10 # a list of values
75  plot.var = Energy 5 12 # another list of values
76  bigarray = 1 2 3 4 5 6 7 8 \
77  9 10 11 12 # continuation of bigarray
78  multi_line_string = "This is a
79  multi-line string."
80  test = apple "boy blue" 10 20 30 40
81  FILE = prob_file # insert contents of this "prob_file" here
82 */
83 // For values spanning multiple lines, one must use '\' at the end of a line
84 // for continuation, otherwise it's a runtime error. Note that there must be
85 // at least one space before the continuation character `\`. Multiple lines
86 // inside a pair of double quotes are considered a single string containing
87 // '\n's. The "FILE = <filename>" definition is special. Rather than just
88 // adding this entry to the database, it reads the contents of <filename>
89 // into the database.
90 // For CI/CD workflows and out-of-source tests, the environment variable
91 // AMREX_INPUTS_FILE_PREFIX can be set to prefix every FILE = <filename>
92 // with a custom path.
93 //
94 // ParmParse stores all entries in a static table which is built the
95 // first time a ParmParse object is constructed (usually in main()).
96 // Subsequent invocations have access to this table.
97 // A ParmParse constructor has an optional "prefix" argument that will
98 // limit the searches to only those entries of the table with this prefix
99 // in name. For example:
100 // ParmParse pp("plot");
101 // will find only those entries with name given by "plot.<string>".
102 //
103 // All values in the table are stored as strings. For example, the
104 // values of "cell_size" in the above input file are stored as the
105 // strings "0.5" and "0.75". These strings can be returned as either
106 // strings or numeric values by the query functions.
107 // Character strings with spaces must be delimited by double quotes
108 // in the input file but the quotes are stripped before they are entered
109 // into the table. For example, 'title' in the above input file has a
110 // single value, the string 'Double Wammy' (without the quotes).
111 // Each value in the list associated with a definition can be referred to
112 // by its index number. The index numbers start at 0 just like an array
113 // in the C programming language. Consider the definition of "test" in
114 // the above input file. The first value 'apple'is a string with index
115 // 0. The second value 'boy blue' is a string with index 1. The
116 // remaining four values are integers indexed 2, 3, 4, and 5.
117 //
118 // For a string value to represent an integer or float it must fit the
119 // following regular expression:
120 // Sign ::= '+' | '-'
121 // Digit ::= '0' | '1' | ... | '9'
122 // Integer ::= [Sign]Digit+
123 // Exp ::= ('e'|'E')Integer
124 // Float ::= ( Integer[.Digit*][Exp] | [Integer].Digit+[Exp] )
125 //
126 // Where '+' indicates one or more occurrences, '*' represents zero or
127 // more occurrences, '|' means one or the other and '[]' represents zero
128 // or one occurrence.
129 //
130 // Note that floats and doubles have the same string representation and
131 // that the FORTRAN "double" exponent format is not supported.
132 // That is, 1.0d+3 is not a valid representation of a floating point
133 // number but that 1.0e+3 is acceptable.
134 //
135 // There are a host of functions allowing the user to query the database
136 // and retrieve values. Here are some general rules about the names of
137 // the member functions:
138 //
139 // * Functions with the string "get" in their names attempt to get a
140 // value or an array of values from the table. They generate a
141 // run-time error if they are not successful.
142 //
143 // * Functions with the string "query" in their names attempt to get a
144 // value or an array of values from the table. They return the value 1
145 // (true) if they are successful and 0 (false) if not.
146 //
147 // * Functions with the string "kth" in their names get values from
148 // the Kth entry with the given name in the database. This is
149 // necessary since there may be multiple definitions with the same
150 // name in the database.
151 //
152 // * Functions without the string "kth" in their names get values from
153 // the last entry with the given name in the database. Note that the
154 // definitions from the command line are appended to the database table
155 // and hence will be the last entries.
156 //
157 // * Functions with the string "arr" in their names get an Array of
158 // values from the given entry in the table. The array argument is
159 // resized (if necessary) to hold all the values requested.
160 //
161 // * Functions without the string "arr" in their names get single
162 // values from the given entry in the table.
163 //
164 // The following is a code sample showing how to use ParmParse:
165 //
166 // main(int argc, char **argv)
167 // {
168 // char* in_file_name = argv[1];
169 // ParmParse::Initialize(argc-2, argv+2, in_file_name);
170 //
171 // // Query table for value of "niter". If not in table
172 // // then set to default value
173 // if (!pp.query("niter",niter)) niter = 20;
174 //
175 // // read array of cell sizes if in table
176 // Vector<float> dx;
177 // if (nx=pp.countval("cell_size")) {
178 // // get nx values starting at index 0 and store in dx.
179 // // dx is automatically resized here.
180 // pp.getarr("cell_size",dx,0,nx);
181 // }
182 // ParmParse::Finalize();
183 // }
184 //
185 // void do_graphics()
186 // {
187 // //
188 // // Will only query entries with the "plot" prefix:
189 // //
190 // ParmParse pp("plot");
191 // //
192 // // Read all variables with "plot.var" keyword.
193 // //
194 // std::string var_name;
195 // Vector<int> range;
196 // int num = pp.countname("var");
197 // for (int k = 0; k < num; k++)
198 // {
199 // //
200 // // Element 0 in list is a string.
201 // //
202 // pp.getkth("var",k,var_name,0);
203 // //
204 // // Elements 1 and 2 are integers.
205 // // Note that "range" will be resized to hold 2 elements.
206 // //
207 // pp.getktharr("var",k,range,1,2);
208 // cout << "variable = " << var_name << "lo, hi = ",
209 // << range[0] << " " << range[1] << endl;
210 // }
211 // }
212 // -----------------------------------------------------------------
213 // ----------------------- END COMMENTS ---------------------------
214 // -----------------------------------------------------------------
215 
216 
320 {
321 public:
322  enum { LAST = -1, FIRST = 0, ALL = -1 };
330  explicit ParmParse (std::string prefix = std::string(),
331  std::string parser_prefix = std::string());
332 
334  [[nodiscard]] bool contains (const char* name) const;
340  [[nodiscard]] int countval (const char* name, int n = LAST) const;
345  [[nodiscard]] int countname (const std::string& name) const;
357  void getkth (const char* name,
358  int k,
359  bool& ref,
360  int ival = FIRST) const;
362  void get (const char* name,
363  bool& ref,
364  int ival = FIRST) const;
372  int querykth (const char* name,
373  int k,
374  bool& ref,
375  int ival = FIRST) const;
377  int query (const char* name,
378  bool& ref,
379  int ival = FIRST) const;
381  void add (const char* name, bool val);
391  void getkth (const char* name,
392  int k,
393  int& ref,
394  int ival = FIRST) const;
395 
397  void get (const char* name,
398  int& ref,
399  int ival = FIRST) const;
407  int querykth (const char* name,
408  int k,
409  int& ref,
410  int ival = FIRST) const;
412  int query (const char* name,
413  int& ref,
414  int ival = FIRST) const;
416  void add (const char* name, int val);
426  void getkth (const char* name,
427  int k,
428  long& ref,
429  int ival = FIRST) const;
431  void get (const char* name,
432  long& ref,
433  int ival = FIRST) const;
441  int querykth (const char* name,
442  int k,
443  long& ref,
444  int ival = FIRST) const;
446  int query (const char* name,
447  long& ref,
448  int ival = FIRST) const;
450  void add (const char* name, long val);
460  void getkth (const char* name,
461  int k,
462  long long& ref,
463  int ival = FIRST) const;
465  void get (const char* name,
466  long long& ref,
467  int ival = FIRST) const;
475  int querykth (const char* name,
476  int k,
477  long long& ref,
478  int ival = FIRST) const;
480  int query (const char* name,
481  long long& ref,
482  int ival = FIRST) const;
484  void add (const char* name, long long val);
494  void getkth (const char* name,
495  int k,
496  float& ref,
497  int ival = FIRST) const;
499  void get (const char* name,
500  float& ref,
501  int ival = FIRST) const;
509  int querykth (const char* name,
510  int k,
511  float& ref,
512  int ival = FIRST) const;
514  int query (const char* name,
515  float& ref,
516  int ival = FIRST) const;
518  void add (const char* name, float val);
528  void getkth (const char* name,
529  int k,
530  double& ref,
531  int ival = FIRST) const;
533  void get (const char* name,
534  double& ref,
535  int ival = FIRST) const;
543  int querykth (const char* name,
544  int k,
545  double& ref,
546  int ival = FIRST) const;
548  int query (const char* name,
549  double& ref,
550  int ival = FIRST) const;
552  void add (const char* name, double val);
562  void getkth (const char* name,
563  int k,
564  std::string& ref,
565  int ival = FIRST) const;
566 
568  void get (const char* name,
569  std::string& ref,
570  int ival = FIRST) const;
578  int querykth (const char* name,
579  int k,
580  std::string& ref,
581  int ival = FIRST) const;
583  int query (const char* name,
584  std::string& ref,
585  int ival = FIRST) const;
587  void add (const char* name, const std::string& val);
588 
598  void getkth (const char* name,
599  int k,
600  IntVect& ref,
601  int ival = FIRST) const;
603  void get (const char* name,
604  IntVect& ref,
605  int ival = FIRST) const;
613  int querykth (const char* name,
614  int k,
615  IntVect& ref,
616  int ival = FIRST) const;
618  int query (const char* name,
619  IntVect& ref,
620  int ival = FIRST) const;
622  void add (const char* name, const IntVect& val);
632  void getkth (const char* name,
633  int k,
634  Box& ref,
635  int ival = FIRST) const;
637  void get (const char* name,
638  Box& ref,
639  int ival = FIRST) const;
647  int querykth (const char* name,
648  int k,
649  Box& ref,
650  int ival = FIRST) const;
652  int query (const char* name,
653  Box& ref,
654  int ival = FIRST) const;
656  void add (const char* name, const Box& val);
669  void getktharr (const char* name,
670  int k,
671  std::vector<int>& ref,
672  int start_ix = FIRST,
673  int num_val = ALL) const;
675  void getarr (const char* name,
676  std::vector<int>& ref,
677  int start_ix = FIRST,
678  int num_val = ALL) const;
680  int queryktharr (const char* name,
681  int k,
682  std::vector<int>& ref,
683  int start_ix = FIRST,
684  int num_val = ALL) const;
686  int queryarr (const char* name,
687  std::vector<int>& ref,
688  int start_ix = FIRST,
689  int num_val = ALL) const;
691  void addarr (const char* name, const std::vector<int>& ref);
692 
705  void getktharr (const char* name,
706  int k,
707  std::vector<long>& ref,
708  int start_ix = FIRST,
709  int num_val = ALL) const;
711  void getarr (const char* name,
712  std::vector<long>& ref,
713  int start_ix = FIRST,
714  int num_val = ALL) const;
716  int queryktharr (const char* name,
717  int k,
718  std::vector<long>& ref,
719  int start_ix = FIRST,
720  int num_val = ALL) const;
722  int queryarr (const char* name,
723  std::vector<long>& ref,
724  int start_ix = FIRST,
725  int num_val = ALL) const;
727  void addarr (const char* name, const std::vector<long>& ref);
728 
741  void getktharr (const char* name,
742  int k,
743  std::vector<long long>& ref,
744  int start_ix = FIRST,
745  int num_val = ALL) const;
747  void getarr (const char* name,
748  std::vector<long long>& ref,
749  int start_ix = FIRST,
750  int num_val = ALL) const;
752  int queryktharr (const char* name,
753  int k,
754  std::vector<long long>& ref,
755  int start_ix = FIRST,
756  int num_val = ALL) const;
758  int queryarr (const char* name,
759  std::vector<long long>& ref,
760  int start_ix = FIRST,
761  int num_val = ALL) const;
763  void addarr (const char* name, const std::vector<long long>& ref);
764 
777  void getktharr (const char* name,
778  int k,
779  std::vector<float>& ref,
780  int start_ix = FIRST,
781  int num_val = ALL) const;
783  void getarr (const char* name,
784  std::vector<float>& ref,
785  int start_ix = FIRST,
786  int num_val = ALL) const;
788  int queryktharr (const char* name,
789  int k,
790  std::vector<float>& ref,
791  int start_ix = FIRST,
792  int num_val = ALL) const;
794  int queryarr (const char* name,
795  std::vector<float>& ref,
796  int start_ix = FIRST,
797  int num_val = ALL) const;
799  void addarr (const char* name, const std::vector<float>& ref);
812  void getktharr (const char* name,
813  int k,
814  std::vector<double>& ref,
815  int start_ix = FIRST,
816  int num_val = ALL) const;
818  void getarr (const char* name,
819  std::vector<double>& ref,
820  int start_ix = FIRST,
821  int num_val = ALL) const;
823  int queryktharr (const char* name,
824  int k,
825  std::vector<double>& ref,
826  int start_ix = FIRST,
827  int num_val = ALL) const;
829  int queryarr (const char* name,
830  std::vector<double>& ref,
831  int start_ix = FIRST,
832  int num_val = ALL) const;
834  void addarr (const char* name, const std::vector<double>& ref);
847  void getktharr (const char* name,
848  int k,
849  std::vector<std::string>& ref,
850  int start_ix = FIRST,
851  int num_val = ALL) const;
853  void getarr (const char* name,
854  std::vector<std::string>& ref,
855  int start_ix = FIRST,
856  int num_val = ALL) const;
858  int queryktharr (const char* name,
859  int k,
860  std::vector<std::string>& ref,
861  int start_ix = FIRST,
862  int num_val = ALL) const;
864  int queryarr (const char* name,
865  std::vector<std::string>& ref,
866  int start_ix = FIRST,
867  int num_val = ALL) const;
869  void addarr (const char* name, const std::vector<std::string>& ref);
882  void getktharr (const char* name,
883  int k,
884  std::vector<IntVect>& ref,
885  int start_ix = FIRST,
886  int num_val = ALL) const;
888  void getarr (const char* name,
889  std::vector<IntVect>& ref,
890  int start_ix = FIRST,
891  int num_val = ALL) const;
893  int queryktharr (const char* name,
894  int k,
895  std::vector<IntVect>& ref,
896  int start_ix = FIRST,
897  int num_val = ALL) const;
899  int queryarr (const char* name,
900  std::vector<IntVect>& ref,
901  int start_ix = FIRST,
902  int num_val = ALL) const;
904  void addarr (const char* name, const std::vector<IntVect>& ref);
917  void getktharr (const char* name,
918  int k,
919  std::vector<Box>& ref,
920  int start_ix = FIRST,
921  int num_val = ALL) const;
923  void getarr (const char* name,
924  std::vector<Box>& ref,
925  int start_ix = FIRST,
926  int num_val = ALL) const;
928  int queryktharr (const char* name,
929  int k,
930  std::vector<Box>& ref,
931  int start_ix = FIRST,
932  int num_val = ALL) const;
934  int queryarr (const char* name,
935  std::vector<Box>& ref,
936  int start_ix = FIRST,
937  int num_val = ALL) const;
939  void addarr (const char* name, const std::vector<Box>& refd);
940 
941  /*
942  * \brief Query IntVect from array
943  *
944  * This reads IntVect from an array (e.g., `8 16 8`), not the format
945  * using parentheses (e.g., `(8,16,8)`).
946  */
947  int queryarr (const char* name, IntVect& ref) const;
948 
949  /*
950  * \brief Get IntVect from array
951  *
952  * This reads IntVect from an array (e.g., `8 16 8`), not the format
953  * using parentheses (e.g., `(8,16,8)`).
954  */
955  void getarr (const char* name, IntVect& ref) const;
956 
958  int queryarr (const char* name, RealVect& ref) const;
959 
961  void getarr (const char* name, RealVect& ref) const;
962 
963  template <typename T, std::size_t N>
964  void get (const char* name, std::array<T,N>& ref) const {
965  std::vector<T> v;
966  this->getarr(name, v);
967  AMREX_ALWAYS_ASSERT(v.size() >= N);
968  for (std::size_t i = 0; i < N; ++i) {
969  ref[i] = v[i];
970  }
971  }
972 
973  template <typename T, std::size_t N>
974  int query (const char* name, std::array<T,N>& ref) const {
975  std::vector<T> v;
976  int exist = this->queryarr(name, v);
977  if (exist) {
978  AMREX_ALWAYS_ASSERT(v.size() >= N);
979  for (std::size_t i = 0; i < N; ++i) {
980  ref[i] = v[i];
981  }
982  }
983  return exist;
984  }
985 
992  template <typename T, std::enable_if_t<!IsStdVector<T>::value, int> = 0>
993  int queryAdd (const char* name, T& ref) {
994  int exist = this->query(name, ref);
995  if (!exist) {
996  this->add(name, ref);
997  }
998  return exist;
999  }
1000 
1001  int queryAdd (const char* name, std::string& ref) {
1002  int exist = this->query(name, ref);
1003  if (!exist && !ref.empty()) {
1004  this->add(name, ref);
1005  }
1006  return exist;
1007  }
1008 
1018  template <typename T>
1019  int queryAdd (const char* name, std::vector<T>& ref) {
1020  std::vector<T> empty;
1021  int exist = this->queryarr(name, empty);
1022  if (exist) {
1023  ref = std::move(empty);
1024  }
1025  if (!exist && !ref.empty()) {
1026  this->addarr(name, ref);
1027  }
1028  return exist;
1029  }
1030 
1037  template <typename T>
1038  int queryAdd (const char* name, std::vector<T>& ref, int num_val) {
1039  int exist = this->queryarr(name, ref, 0, num_val);
1040  if (!exist) {
1041  this->addarr(name, ref);
1042  }
1043  return exist;
1044  }
1045 
1052  template <typename T, std::size_t N>
1053  int queryAdd (const char* name, std::array<T,N>& ref) {
1054  std::vector<T> v;
1055  int exist = this->queryarr(name, v);
1056  if (exist) {
1057  AMREX_ALWAYS_ASSERT(v.size() >= N);
1058  for (std::size_t i = 0; i < N; ++i) {
1059  ref[i] = v[i];
1060  }
1061  } else {
1062  v.resize(N);
1063  for (std::size_t i = 0; i < N; ++i) {
1064  v[i] = ref[i];
1065  }
1066  this->addarr(name, v);
1067  }
1068  return exist;
1069  }
1070 
1077  int queryWithParser (const char* name, int& ref) const;
1078  int queryWithParser (const char* name, long& ref) const;
1079  int queryWithParser (const char* name, long long& ref) const;
1080  int queryWithParser (const char* name, float& ref) const;
1081  int queryWithParser (const char* name, double& ref) const;
1082 
1089  int queryarrWithParser (const char* name, int nvals, int* ref) const;
1090  int queryarrWithParser (const char* name, int nvals, long* ref) const;
1091  int queryarrWithParser (const char* name, int nvals, long long* ref) const;
1092  int queryarrWithParser (const char* name, int nvals, float* ref) const;
1093  int queryarrWithParser (const char* name, int nvals, double* ref) const;
1094  template <typename T, std::enable_if_t<std::is_same_v<T,int> ||
1095  std::is_same_v<T,long> ||
1096  std::is_same_v<T,long long> ||
1097  std::is_same_v<T,float> ||
1098  std::is_same_v<T,double>,int> = 0>
1099  int queryarrWithParser (const char* name, int nvals, std::vector<T>& ref) const
1100  {
1101  if (this->contains(name)) {
1102  if (int(ref.size()) < nvals) { ref.resize(nvals); }
1103  return this->queryarrWithParser(name, nvals, ref.data());
1104  } else {
1105  return 0;
1106  }
1107  }
1108 
1115  template <typename T, std::enable_if_t<std::is_same_v<T,int> ||
1116  std::is_same_v<T,long> ||
1117  std::is_same_v<T,long long> ||
1118  std::is_same_v<T,float> ||
1119  std::is_same_v<T,double>,int> = 0>
1120  int queryAddWithParser (const char* name, T& ref) const
1121  {
1122  int exist = this->queryWithParser(name, ref);
1123  if (!exist) {
1124  this->add(name, ref);
1125  }
1126  return exist;
1127  }
1128 
1134  template <typename T, std::enable_if_t<std::is_same_v<T,int> ||
1135  std::is_same_v<T,long> ||
1136  std::is_same_v<T,long long> ||
1137  std::is_same_v<T,float> ||
1138  std::is_same_v<T,double>,int> = 0>
1139  void getWithParser (const char* name, T& ref) const
1140  {
1141  int exist = this->queryWithParser(name, ref);
1142  if (!exist) {
1143  amrex::Error(std::string("ParmParse::getWithParser: failed to get ")+name);
1144  }
1145  }
1146 
1152  template <typename T, std::enable_if_t<std::is_same_v<T,int> ||
1153  std::is_same_v<T,long> ||
1154  std::is_same_v<T,long long> ||
1155  std::is_same_v<T,float> ||
1156  std::is_same_v<T,double>,int> = 0>
1157  void getarrWithParser (const char* name, int nvals, T* ref) const
1158  {
1159  int exist = this->queryarrWithParser(name, nvals, ref);
1160  if (!exist) {
1161  amrex::Error(std::string("ParmParse::getarrWithParser: failed to get ")+name);
1162  }
1163  }
1164 
1170  template <typename T, std::enable_if_t<std::is_same_v<T,int> ||
1171  std::is_same_v<T,long> ||
1172  std::is_same_v<T,long long> ||
1173  std::is_same_v<T,float> ||
1174  std::is_same_v<T,double>,int> = 0>
1175  void getarrWithParser (const char* name, int nvals, std::vector<T>& ref) const
1176  {
1177  int exist = this->queryarrWithParser(name, nvals, ref);
1178  if (!exist) {
1179  amrex::Error(std::string("ParmParse::getarrWithParser: failed to get ")+name);
1180  }
1181  }
1182 
1183  /*
1184  * \brief Evaluate given string as math expression
1185  *
1186  * For unknown symbols, ParmParse database will be queried.
1187  */
1188  template <typename T, std::enable_if_t<std::is_same_v<T,int> ||
1189  std::is_same_v<T,long> ||
1190  std::is_same_v<T,long long> ||
1191  std::is_same_v<T,float> ||
1192  std::is_same_v<T,double>,int> = 0>
1193  T eval (std::string const& expr) const
1194  {
1195  if constexpr (std::is_integral_v<T>) {
1196  auto const parser = this->makeIParser(expr, {});
1197  auto const exe = parser.compileHost<0>();
1198  return static_cast<T>(exe()); // In the future, we might add safety check.
1199  } else {
1200  auto const parser = this->makeParser(expr, {});
1201  auto const exe = parser.compileHost<0>();
1202  return static_cast<T>(exe());
1203  }
1204  }
1205 
1206  /*
1207  * \brief Query two names.
1208  *
1209  * This function queries with `new_name` first. If it's not found, it
1210  * will try again with `old_name`.
1211  */
1212  template <typename T>
1213  int query (const char* new_name, const char* old_name, T& ref)
1214  {
1215  return (this->query(new_name, ref) ||
1216  this->query(old_name, ref));
1217  }
1218 
1226  template <typename T>
1227  void get (const char* new_name, const char* old_name, T& ref)
1228  {
1229  auto exist = this->query(new_name, old_name, ref);
1230  if (!exist) {
1231  amrex::ErrorStream() << "ParmParse::get failed to find "
1232  << new_name << " and " << old_name << '\n';
1234  amrex::Abort();
1235  }
1236  }
1237 
1246  template <typename T, typename ET = amrex_enum_traits<T>,
1247  std::enable_if_t<ET::value,int> = 0>
1248  int query (const char* name, T& ref, int ival = FIRST) const
1249  {
1250  std::string s;
1251  int exist = this->query(name, s, ival);
1252  if (exist) {
1253  try {
1254  ref = amrex::getEnum<T>(s);
1255  } catch (...) {
1256  if (amrex::Verbose() > 0 ) {
1257  amrex::Print() << "amrex::ParmParse::query (input name: "
1258  << this->prefixedName(name) << "):\n";
1259  }
1260  throw;
1261  }
1262  }
1263  return exist;
1264  }
1265 
1274  template <typename T, typename ET = amrex_enum_traits<T>,
1275  std::enable_if_t<ET::value,int> = 0>
1276  void get (const char* name, T& ref, int ival = FIRST) const
1277  {
1278  std::string s;
1279  this->get(name, s, ival);
1280  try {
1281  ref = amrex::getEnum<T>(s);
1282  } catch (...) {
1283  if (amrex::Verbose() > 0 ) {
1284  amrex::Print() << "amrex::ParmParse::get (input name: "
1285  << this->prefixedName(name) << "):\n";
1286  }
1287  throw;
1288  }
1289  }
1290 
1292  template <typename T, typename ET = amrex_enum_traits<T>,
1293  std::enable_if_t<ET::value,int> = 0>
1294  int queryarr (const char* name,
1295  std::vector<T>& ref,
1296  int start_ix = FIRST,
1297  int num_val = ALL) const
1298  {
1299  std::vector<std::string> s;
1300  int exist = this->queryarr(name, s, start_ix, num_val);
1301  if (exist) {
1302  ref.resize(s.size());
1303  for (std::size_t i = 0; i < s.size(); ++i) {
1304  try {
1305  ref[i] = amrex::getEnum<T>(s[i]);
1306  } catch (...) {
1307  if (amrex::Verbose() > 0 ) {
1308  amrex::Print() << "amrex::ParmParse::queryarr (input name: "
1309  << this->prefixedName(name) << "):\n";
1310  }
1311  throw;
1312  }
1313  }
1314  }
1315  return exist;
1316  }
1317 
1319  template <typename T, typename ET = amrex_enum_traits<T>,
1320  std::enable_if_t<ET::value,int> = 0>
1321  void getarr (const char* name,
1322  std::vector<T>& ref,
1323  int start_ix = FIRST,
1324  int num_val = ALL) const
1325  {
1326  std::vector<std::string> s;
1327  this->getarr(name, s, start_ix, num_val);
1328  ref.resize(s.size());
1329  for (std::size_t i = 0; i < s.size(); ++i) {
1330  try {
1331  ref[i] = amrex::getEnum<T>(s[i]);
1332  } catch (...) {
1333  if (amrex::Verbose() > 0 ) {
1334  amrex::Print() << "amrex::ParmParse::getarr (input name: "
1335  << this->prefixedName(name) << "):\n";
1336  }
1337  throw;
1338  }
1339  }
1340  }
1341 
1352  template <typename T, typename ET = amrex_enum_traits<T>,
1353  std::enable_if_t<ET::value,int> = 0>
1354  int query_enum_case_insensitive (const char* name, T& ref, int ival = FIRST) const
1355  {
1356  std::string s;
1357  int exist = this->query(name, s, ival);
1358  if (exist) {
1359  try {
1360  ref = amrex::getEnumCaseInsensitive<T>(s);
1361  } catch (...) {
1362  if (amrex::Verbose() > 0) {
1363  amrex::Print() << "amrex::ParmParse::query_enum_case_insensitive (input name: "
1364  << this->prefixedName(name) << "):\n";
1365  }
1366  throw;
1367  }
1368  }
1369  return exist;
1370  }
1371 
1382  template <typename T, typename ET = amrex_enum_traits<T>,
1383  std::enable_if_t<ET::value,int> = 0>
1384  void get_enum_case_insensitive (const char* name, T& ref, int ival = FIRST) const
1385  {
1386  int exist = this->query_enum_case_insensitive(name, ref, ival);
1387  if (!exist) {
1388  std::string msg("get_enum_case_insensitive(\"");
1389  msg.append(name).append("\",").append(amrex::getEnumClassName<T>())
1390  .append("&) failed.");
1391  amrex::Abort(msg);
1392  }
1393  }
1394 
1407  template <typename T, typename ET = amrex_enum_traits<T>,
1408  std::enable_if_t<ET::value,int> = 0>
1409  int query_enum_sloppy (const char* name, T& ref, std::string_view const& ignores,
1410  int ival = FIRST) const
1411  {
1412  std::string s;
1413  int exist = this->query(name, s, ival);
1414  if (exist) {
1415  try {
1416  s.erase(std::remove_if(s.begin(), s.end(),
1417  [&] (auto const& c) {
1418  return ignores.find(c) != std::string_view::npos; }),
1419  s.end());
1420  ref = amrex::getEnumCaseInsensitive<T>(s);
1421  } catch (...) {
1422  if (amrex::Verbose() > 0) {
1423  amrex::Print() << "amrex::ParmParse::query_enum_sloppy (input name: "
1424  << this->prefixedName(name) << "):\n";
1425  }
1426  throw;
1427  }
1428  }
1429  return exist;
1430  }
1431 
1444  template <typename T, typename ET = amrex_enum_traits<T>,
1445  std::enable_if_t<ET::value,int> = 0>
1446  void get_enum_sloppy (const char* name, T& ref, std::string_view const& ignores,
1447  int ival = FIRST) const
1448  {
1449  int exist = this->query_enum_sloppy(name, ref, ignores, ival);
1450  if (!exist) {
1451  std::string msg("get_enum_sloppy(\"");
1452  msg.append(name).append("\",").append(amrex::getEnumClassName<T>())
1453  .append("&) failed.");
1454  amrex::Abort(msg);
1455  }
1456  }
1457 
1466  template <typename T, std::enable_if_t<ppdetail::IsArithmeticOptional_v<T>, int> = 0>
1467  int queryAsDouble (const char* name, T& ref) const
1468  {
1469  using value_type = ppdetail::underlying_type_t<T>;
1470  double dref;
1471  int exist = queryWithParser(name, dref);
1472  if (exist) {
1473  if (std::is_integral_v<value_type>) {
1474  dref = std::round(dref);
1475  }
1476  auto vref = static_cast<value_type>(dref);
1477  if constexpr (std::is_integral_v<value_type> && !std::is_same_v<value_type,bool>) {
1478  if (static_cast<double>(vref) != dref) {
1479  amrex::Abort("ParmParse:: queryAsDouble is not safe");
1480  }
1481  }
1482  ref = vref;
1483  }
1484  return exist;
1485  }
1486 
1495  template <typename T, std::enable_if_t<ppdetail::IsArithmeticOptional_v<T>, int> = 0>
1496  int queryarrAsDouble (const char* name, int nvals, T* ref) const
1497  {
1498  using value_type = ppdetail::underlying_type_t<T>;
1499  std::vector<double> dref(nvals);
1500  int exist = queryarrWithParser(name, nvals, dref.data());
1501  if (exist) {
1502  for (int i = 0; i < nvals; ++i) {
1503  if (std::is_integral_v<value_type>) {
1504  dref[i] = std::round(dref[i]);
1505  }
1506  auto vref = static_cast<value_type>(dref[i]);
1507  if constexpr (std::is_integral_v<value_type> && !std::is_same_v<value_type,bool>) {
1508  if (static_cast<double>(vref) != dref[i]) {
1509  amrex::Abort("ParmParse:: queryarrAsDouble is not safe");
1510  }
1511  }
1512  ref[i] = vref;
1513  }
1514  }
1515  return exist;
1516  }
1517 
1526  template <typename T, std::enable_if_t<ppdetail::IsArithmeticOptional_v<T>, int> = 0>
1527  void getAsDouble (const char* name, T& ref) const
1528  {
1529  int exist = this->queryAsDouble(name, ref);
1530  if (!exist) {
1531  amrex::Error(std::string("ParmParse::getAsDouble: failed to get ")+name);
1532  }
1533  }
1534 
1543  template <typename T, std::enable_if_t<ppdetail::IsArithmeticOptional_v<T>, int> = 0>
1544  void getarrAsDouble (const char* name, int nvals, T* ref) const
1545  {
1546  int exist = this->queryarrAsDouble(name, nvals, ref);
1547  if (!exist) {
1548  amrex::Error(std::string("ParmParse::getarrAsDouble: failed to get ")+name);
1549  }
1550  }
1551 
1553  int remove (const char* name);
1554 
1558  [[nodiscard]] Parser makeParser (std::string const& func,
1559  Vector<std::string> const& vars) const;
1560 
1564  [[nodiscard]] IParser makeIParser (std::string const& func,
1565  Vector<std::string> const& vars) const;
1566 
1574  static void Initialize (int argc, char** argv, const char* parfile);
1579  static void Finalize ();
1580 
1582  static void SetParserPrefix (std::string a_prefix);
1583 
1584  static int Verbose ();
1585  static void SetVerbose (int v);
1586 
1588  static void dumpTable (std::ostream& os, bool prettyPrint = false);
1589 
1592  static void prettyPrintTable (std::ostream& os);
1593 
1595  static void addfile (std::string const& filename);
1596 
1597  static bool QueryUnusedInputs ();
1598 
1600  [[nodiscard]] static bool hasUnusedInputs (const std::string& prefix = std::string());
1601 
1603  [[nodiscard]] static std::vector<std::string> getUnusedInputs (const std::string& prefix = std::string());
1604 
1606  [[nodiscard]] static std::set<std::string> getEntries (const std::string& prefix = std::string());
1607 
1608  struct PP_entry {
1609  // There can be multiple occurrences for a given name (e.g.,
1610  // multiple lines starting with `foo =` in inputs. For each
1611  // occurrence, there can be multiple values. Thus, the use of
1612  // vector<vector<std::string>>.
1613  std::vector<std::vector<std::string>> m_vals;
1614  mutable Long m_count = 0;
1615  };
1616  using Table = std::unordered_map<std::string, PP_entry>;
1617 
1618  [[nodiscard]] const Table& table() const {return *m_table;}
1619 
1621  static std::string const FileKeyword;
1622 
1623  static std::string ParserPrefix;
1624 
1625  [[nodiscard]] std::string prefixedName (const std::string_view& str) const;
1626 
1627 protected:
1628 
1629  std::string m_prefix; // Prefix used in keyword search
1630  std::string m_parser_prefix; // Prefix used by Parser
1632 };
1633 
1634 }
1635 
1636 #endif /* AMREX_PARMPARSE_H_ */
#define AMREX_ALWAYS_ASSERT(EX)
Definition: AMReX_BLassert.H:50
Definition: AMReX_IParser.H:58
IParserExecutor< N > compileHost() const
This compiles for CPU only.
Definition: AMReX_IParser.H:110
Parse Parameters From Command Line and Input Files.
Definition: AMReX_ParmParse.H:320
bool contains(const char *name) const
Returns true if name is in table.
Definition: AMReX_ParmParse.cpp:1922
int queryarrWithParser(const char *name, int nvals, int *ref) const
Query with Parser. The return value indicates whether it's found. Note that queryWithParser will be u...
Definition: AMReX_ParmParse.cpp:2016
void getarrWithParser(const char *name, int nvals, std::vector< T > &ref) const
Get with Parser. If name is not found, it's a runtime error. If the number of elements does not equal...
Definition: AMReX_ParmParse.H:1175
void addarr(const char *name, const std::vector< int > &ref)
Add a key 'name' with vector of values 'ref' to the end of the PP table.
Definition: AMReX_ParmParse.cpp:1390
void get(const char *name, bool &ref, int ival=FIRST) const
Same as getkth() but searches for the last occurrence of name.
Definition: AMReX_ParmParse.cpp:1299
void get(const char *name, std::array< T, N > &ref) const
Definition: AMReX_ParmParse.H:964
static void prettyPrintTable(std::ostream &os)
Definition: AMReX_ParmParse.cpp:1252
static void Initialize(int argc, char **argv, const char *parfile)
Construct an initial ParmParse object from the argc and argv passed in to main(). An error will be si...
Definition: AMReX_ParmParse.cpp:1095
int queryarrWithParser(const char *name, int nvals, std::vector< T > &ref) const
Definition: AMReX_ParmParse.H:1099
static void addfile(std::string const &filename)
Add keys and values from a file to the end of the PP table.
Definition: AMReX_ParmParse.cpp:1070
int queryAsDouble(const char *name, T &ref) const
Query T with Parser, but treat the number as double precision during parsing.
Definition: AMReX_ParmParse.H:1467
int query(const char *name, T &ref, int ival=FIRST) const
. Query enum value using given name.
Definition: AMReX_ParmParse.H:1248
static std::string const FileKeyword
keyword for files to load
Definition: AMReX_ParmParse.H:1621
static std::string ParserPrefix
Definition: AMReX_ParmParse.H:1623
static int Verbose()
Definition: AMReX_ParmParse.cpp:1176
void getAsDouble(const char *name, T &ref) const
Get T with Parser, but treat the number as double precision during parsing.
Definition: AMReX_ParmParse.H:1527
static void SetVerbose(int v)
Definition: AMReX_ParmParse.cpp:1189
void get(const char *new_name, const char *old_name, T &ref)
Get using two names.
Definition: AMReX_ParmParse.H:1227
int queryarr(const char *name, std::vector< int > &ref, int start_ix=FIRST, int num_val=ALL) const
Same as queryktharr() but searches for last occurrence of name.
Definition: AMReX_ParmParse.cpp:1383
int query_enum_sloppy(const char *name, T &ref, std::string_view const &ignores, int ival=FIRST) const
. Query enum value using given name.
Definition: AMReX_ParmParse.H:1409
int queryAdd(const char *name, T &ref)
If name is found, the value in the ParmParse database will be stored in the ref argument....
Definition: AMReX_ParmParse.H:993
int queryAdd(const char *name, std::vector< T > &ref, int num_val)
If name is found, the value in the ParmParse database will be stored in the ref argument....
Definition: AMReX_ParmParse.H:1038
void getarr(const char *name, std::vector< int > &ref, int start_ix=FIRST, int num_val=ALL) const
Same as getktharr() but searches for last occurrence of name.
Definition: AMReX_ParmParse.cpp:1369
static bool hasUnusedInputs(const std::string &prefix=std::string())
Any unused [prefix.]* parameters?
Definition: AMReX_ParmParse.cpp:1127
void getWithParser(const char *name, T &ref) const
Get with Parser. If name is found, this uses amrex::Parser to parse the entire list of empty space se...
Definition: AMReX_ParmParse.H:1139
int remove(const char *name)
Remove given name from the table.
Definition: AMReX_ParmParse.cpp:1938
Parser makeParser(std::string const &func, Vector< std::string > const &vars) const
Definition: AMReX_ParmParse.cpp:2046
int query(const char *name, std::array< T, N > &ref) const
Definition: AMReX_ParmParse.H:974
void getkth(const char *name, int k, bool &ref, int ival=FIRST) const
Get the ival'th value of kth occurrence of the requested name. If successful, the value is converted ...
Definition: AMReX_ParmParse.cpp:1290
void getarrAsDouble(const char *name, int nvals, T *ref) const
Get T array with Parser, but treat the number as double precision during parsing.
Definition: AMReX_ParmParse.H:1544
int queryktharr(const char *name, int k, std::vector< int > &ref, int start_ix=FIRST, int num_val=ALL) const
queryktharr() is to querykth() as getktharr() is to getkth().
Definition: AMReX_ParmParse.cpp:1376
int queryAdd(const char *name, std::vector< T > &ref)
If name is found, the value in the ParmParse database will be stored in the ref argument....
Definition: AMReX_ParmParse.H:1019
static bool QueryUnusedInputs()
Definition: AMReX_ParmParse.cpp:1112
void add(const char *name, bool val)
Add a key 'name'with value 'ref' to the end of the PP table.
Definition: AMReX_ParmParse.cpp:1324
T eval(std::string const &expr) const
Definition: AMReX_ParmParse.H:1193
void getktharr(const char *name, int k, std::vector< int > &ref, int start_ix=FIRST, int num_val=ALL) const
Gets an std::vector<int> of num_val values from kth occurrence of given name. If successful,...
Definition: AMReX_ParmParse.cpp:1362
static void Finalize()
The destructor. The internal static table will only be deleted if there are no other ParmParse object...
Definition: AMReX_ParmParse.cpp:1195
std::string m_prefix
Definition: AMReX_ParmParse.H:1629
int countname(const std::string &name) const
Returns the number of times the given name (prepended with prefix) appears in the table.
Definition: AMReX_ParmParse.cpp:1906
std::string prefixedName(const std::string_view &str) const
Definition: AMReX_ParmParse.cpp:1056
static void SetParserPrefix(std::string a_prefix)
Set prefix used by math expression Parser.
Definition: AMReX_ParmParse.cpp:1221
static std::vector< std::string > getUnusedInputs(const std::string &prefix=std::string())
Returns unused [prefix.]* parameters.
Definition: AMReX_ParmParse.cpp:1133
int query(const char *name, bool &ref, int ival=FIRST) const
Same as querykth() but searches for the last occurrence of name.
Definition: AMReX_ParmParse.cpp:1316
@ FIRST
Definition: AMReX_ParmParse.H:322
@ LAST
Definition: AMReX_ParmParse.H:322
@ ALL
Definition: AMReX_ParmParse.H:322
int queryarr(const char *name, std::vector< T > &ref, int start_ix=FIRST, int num_val=ALL) const
Query an array of enum values using given name.
Definition: AMReX_ParmParse.H:1294
int queryWithParser(const char *name, int &ref) const
Query with Parser. If name is found, this uses amrex::Parser to parse the entire list of empty space ...
Definition: AMReX_ParmParse.cpp:1986
const Table & table() const
Definition: AMReX_ParmParse.H:1618
int query(const char *new_name, const char *old_name, T &ref)
Definition: AMReX_ParmParse.H:1213
void get_enum_case_insensitive(const char *name, T &ref, int ival=FIRST) const
. Get enum value using given name.
Definition: AMReX_ParmParse.H:1384
Table * m_table
Definition: AMReX_ParmParse.H:1631
std::string m_parser_prefix
Definition: AMReX_ParmParse.H:1630
int countval(const char *name, int n=LAST) const
Returns the number of values associated with nth occurrence of name (prepended with the prefix) in th...
Definition: AMReX_ParmParse.cpp:1278
int querykth(const char *name, int k, bool &ref, int ival=FIRST) const
Similar to getkth() but returns 0 if there is no kth occurrence of name. If successful,...
Definition: AMReX_ParmParse.cpp:1307
int queryAdd(const char *name, std::string &ref)
Definition: AMReX_ParmParse.H:1001
static void dumpTable(std::ostream &os, bool prettyPrint=false)
Write the contents of the table in ASCII to the ostream.
Definition: AMReX_ParmParse.cpp:1227
int queryarrAsDouble(const char *name, int nvals, T *ref) const
Query T array with Parser, but treat the number as double precision during parsing.
Definition: AMReX_ParmParse.H:1496
void getarrWithParser(const char *name, int nvals, T *ref) const
Get with Parser. If name is not found, it's a runtime error. If the number of elements does not equal...
Definition: AMReX_ParmParse.H:1157
void get(const char *name, T &ref, int ival=FIRST) const
. Get enum value using given name.
Definition: AMReX_ParmParse.H:1276
static std::set< std::string > getEntries(const std::string &prefix=std::string())
Returns [prefix.]* parameters.
Definition: AMReX_ParmParse.cpp:1163
int queryAddWithParser(const char *name, T &ref) const
Query with Parser. If name is found, this uses amrex::Parser to parse the entire list of empty space ...
Definition: AMReX_ParmParse.H:1120
void getarr(const char *name, std::vector< T > &ref, int start_ix=FIRST, int num_val=ALL) const
Get an array of enum values using given name.
Definition: AMReX_ParmParse.H:1321
int query_enum_case_insensitive(const char *name, T &ref, int ival=FIRST) const
. Query enum value using given name.
Definition: AMReX_ParmParse.H:1354
void get_enum_sloppy(const char *name, T &ref, std::string_view const &ignores, int ival=FIRST) const
. Get enum value using given name.
Definition: AMReX_ParmParse.H:1446
ParmParse(std::string prefix=std::string(), std::string parser_prefix=std::string())
Construct an additional ParmParse object sharing the same internal table as any other such objects in...
Definition: AMReX_ParmParse.cpp:40
std::unordered_map< std::string, PP_entry > Table
Definition: AMReX_ParmParse.H:1616
IParser makeIParser(std::string const &func, Vector< std::string > const &vars) const
Definition: AMReX_ParmParse.cpp:2053
int queryAdd(const char *name, std::array< T, N > &ref)
If name is found, the value in the ParmParse database will be stored in the ref argument....
Definition: AMReX_ParmParse.H:1053
Definition: AMReX_Parser.H:68
ParserExecutor< N > compileHost() const
This compiles for CPU only.
Definition: AMReX_Parser.H:123
This class provides the user with a few print options.
Definition: AMReX_Print.H:35
A Real vector in SpaceDim-dimensional space.
Definition: AMReX_RealVect.H:32
typename ArithmeticOptional_TT< T >::value_type underlying_type_t
Definition: AMReX_ParmParse.H:54
constexpr bool IsArithmeticOptional_v
Definition: AMReX_ParmParse.H:51
Definition: AMReX_Amr.cpp:49
std::ostream & ErrorStream()
Definition: AMReX.cpp:870
BoxND< AMREX_SPACEDIM > Box
Definition: AMReX_BaseFwd.H:27
IntVectND< AMREX_SPACEDIM > IntVect
Definition: AMReX_BaseFwd.H:30
AMREX_GPU_HOST_DEVICE IntVectND(const Array< int, dim > &) -> IntVectND< dim >
void Error(const std::string &msg)
Print out message to cerr and exit via amrex::Abort().
Definition: AMReX.cpp:215
int Verbose() noexcept
Definition: AMReX.cpp:160
void Abort(const std::string &msg)
Print out message to cerr and exit via abort().
Definition: AMReX.cpp:221
Definition: AMReX_ParmParse.H:1608
std::vector< std::vector< std::string > > m_vals
Definition: AMReX_ParmParse.H:1613
Long m_count
Definition: AMReX_ParmParse.H:1614
Definition: AMReX_ParmParse.H:33