Alamo
ParmParse.H
Go to the documentation of this file.
1//
2// This is a thin wrapper to the amrex::ParmParse class
3// This class exists to add some additional parsing capability,
4// e.g. parsing Set::Matrix and Set::Vector data types.
5//
6// :ref:`IO::ParmParse` uses static :code:`Parse()` functions to
7// perform cascading class-based input parsing.
8// See the :ref:`autodoc` section for instructions on adding documentation.
9//
10// :bdg-warning-line:`This is standard infrastructure code; make sure you know what you ard doing before you change it.`
11//
12// .. _query-directives:
13//
14// **Query directives**
15//
16// Alamo uses different query directives to standardize reading inputs and automatic documentation.
17// The type of query that is used (query vs query_required, etc) triggers different handlers and different
18// automatic documentation procedures.
19// For instance, the use of a :code:`query_default` causes a default value to be set and added to the metadata
20// file, and it also serves as a flag for the autodoc system to document that a default value is available.
21// The following table is a reference for the different kinds of query directives.
22//
23//
24// .. table::
25// :widths: 1 99
26//
27// +---------------------------------+-----------------------------------------------------------------+
28// | BC Type | Description |
29// +=================================+=================================================================+
30// | :bdg-warning:`query` | Standard IO for bool, string, Set::Scalarthat does not enforce |
31// | | defaults or required values. Not recommended for general use. |
32// +---------------------------------+-----------------------------------------------------------------+
33// | :bdg-success:`query_required` | Similar to query, but will abort if no value is specified. |
34// | | Required values are indicated by :bdg-danger-line:`required`. |
35// +---------------------------------+-----------------------------------------------------------------+
36// | :bdg-success:`query_default` | Similar to query, but will fill with default value if no value |
37// | | is provided. Will also add default value to metadata. |
38// | | Default values are indicated by green badge values, e.g. |
39// | | :bdg-success:`0.0`. |
40// +---------------------------------+-----------------------------------------------------------------+
41// | :bdg-success:`query_validate` | For strings, read in a value and enforce that the value is one |
42// | | of a supplied number of values. Optionally make required, or |
43// | | set the default value to the first supplied value. |
44// | | Acceptable options are indicated by blue badge values, e.g. |
45// | | :bdg-primary:`1.0`, :bdg-primary:`2.0`. If a default value is |
46// | | available, it is indicated by a green badge, e.g. |
47// | | :bdg-success:`1.0`. |
48// +---------------------------------+-----------------------------------------------------------------+
49// | :bdg-success:`query_file` | Read in a string that defines a file name. |
50// | | Check to make sure that the file exists and is a regular file, |
51// | | and print an informative error message if not (this can be |
52// | | disabled). |
53// | | Also, copy the file to the output directory, with the full path |
54// | | preserved by replacing / with _. |
55// | | (This can also be disabled, but doing so is discouraged.) |
56// | | Default values are not allowed. |
57// | | File paths are indicated by :bdg-secondary-line:`file path`. |
58// +---------------------------------+-----------------------------------------------------------------+
59// | :bdg-primary:`queryarr` | Read in an array of numbers into either a standard vector or |
60// | | into a :code:`Set::Vector` or :code:`Set::Scalar`. |
61// | | No defaults or existence checking is performed. |
62// +---------------------------------+-----------------------------------------------------------------+
63// | :bdg-primary:`queryclass` | Read a class object with a specified prefix. |
64// | | How that class is read in is determined by its :code:`Parse` |
65// | | function. |
66// +---------------------------------+-----------------------------------------------------------------+
67//
68// .. _query_locator_macros:
69//
70// **Query macros**
71//
72// A set of preprocessor macros are defined so that you can call a query function using :code:`pp_` instead
73// of :code:`pp.`.
74// For instance, the following two can be used interchangeably:
75//
76// .. code-block:: cpp
77//
78// pp.query_required("myvar",myvar); /* function version */
79// pp_query_required("myvar",myvar); /* preprocessor macro version - preferred*/
80//
81// Using the preprocessor macros enables code location information to be passed to the parser, so that
82// more informative error messages will be printed out.
83// Note that **the ParmParse object must always be called** :code:`pp` **for this to work**.
84//
85//
86
87#ifndef IO_PARMPARSE
88#define IO_PARMPARSE
89
90#include <filesystem>
91#include <exception>
92#include <list>
93
94#include "Util/Util.H"
95#include "Set/Set.H"
96#include "AMReX_ParmParse.H"
97
98
99#define pp_query_required(...) pp.query_required(__VA_ARGS__,INFO)
100#define pp_query_default(...) pp.query_default(__VA_ARGS__,INFO)
101#define pp_query_validate(...) pp.query_validate(__VA_ARGS__,INFO)
102#define pp_query_file(...) pp.query_file(__VA_ARGS__,INFO)
103#define pp_queryarr(...) pp.queryarr(__VA_ARGS__,INFO)
104#define pp_queryarr_required(...) pp.queryarr_required(__VA_ARGS__,INFO)
105#define pp_queryarr_default(...) pp.queryarr_default(__VA_ARGS__,INFO)
106#define pp_query(...) pp.query(__VA_ARGS__)
107#define pp_queryclass(...) pp.queryclass(__VA_ARGS__,INFO)
108#define pp_forbid(...) pp.forbid(__VA_ARGS__,INFO)
109
110
111namespace IO
112{
113class ParmParse : public amrex::ParmParse
114{
115private:
116 void Define()
117 {
118 if (checked_for_input_files) return;
119 int k = 0;
120 std::string inputfile = "";
121 while (this->querykth("input",k,inputfile))
122 {
123 Util::Message(INFO,"Including inputs from "+inputfile);
124 this->addfile(inputfile);
125 k++;
126 }
128 }
130
131public:
132 ParmParse(std::string arg) : amrex::ParmParse::ParmParse(arg) {Define();} ;
133 ParmParse() : amrex::ParmParse::ParmParse() {Define();} ;
134 std::string getPrefix() const {return m_prefix;};
135 void ignore(std::string name)
136 {
137 (void)amrex::ParmParse::contains(name.c_str());
138 }
139
140 void pushPrefix(const std::string prefix)
141 {
142 if (m_prefix.length())
143 m_prefix = m_prefix + "." + prefix;
144 else
145 m_prefix = prefix;
146 }
147
149 {
150 size_t pos = m_prefix.rfind('.');
151 if (pos == std::string::npos)
152 m_prefix = "";
153 else
154 m_prefix = m_prefix.substr(0, pos);
155 }
156
157
158 void forbid(std::string name, std::string explanation,
159 std::string file = "", std::string func = "", int line = -1)
160 {
161 if (amrex::ParmParse::contains(full(name).c_str()))
162 {
163 Util::ParmParseException(INFO,file,func,line,full(name),full(name)," forbidden: ", explanation);
164 }
165 std::set<std::string> subs = amrex::ParmParse::getEntries(full(name));
166 if (subs.size())
167 {
168 Util::ParmParseException(INFO,file,func,line,full(name),full(name)," forbidden: ", explanation);
169 }
170 }
171
172 bool contains(std::string name)
173 {
174 if (amrex::ParmParse::contains(name.c_str()))
175 return true;
176 if (amrex::ParmParse::contains(full(name).c_str()))
177 return true;
178 {
179 std::set<std::string> subs = amrex::ParmParse::getEntries(name.c_str());
180 if (subs.size())
181 return true;
182 }
183 {
184 std::set<std::string> subs = amrex::ParmParse::getEntries(full(name).c_str());
185 if (subs.size())
186 return true;
187 }
188 return false;
189 }
190
191 template<typename T>
192 int query_required( std::string name, T & value,
193 std::string file = "", std::string func = "", int line = -1)
194 {
195 if (!contains(name.c_str()))
196 {
197 Util::ParmParseException(INFO,file,func,line,full(name),"required value for ",full(name)," missing");
198 }
199 return query(name.c_str(),value);
200 }
201
202 template<typename T>
203 int query_default( std::string name, T & value, T defaultvalue,
204 std::string = "", std::string = "", int = -1)
205 {
206 if (!contains(name.c_str()))
207 {
208 add(name.c_str(),defaultvalue);
209 }
210 return query(name.c_str(),value);
211 }
212
213 int query_validate( std::string name, int & value, std::vector<int> possibleintvals,
214 std::string file = "", std::string func = "", int line = -1)
215 {
216 // First value is accepted by default...
217
218 // set default value
219 value = possibleintvals[0];
220
221 // get the read value (if it exists)
222 int retval = query(name.c_str(),value);
223
224 // check to make sure the read value matches one of the inpus
225 bool ok = false;
226 for (unsigned int i = 0; i < possibleintvals.size(); i++)
227 {
228 if (value == possibleintvals[i]) ok = true;
229 }
230
231 if (ok) return retval;
232
233 std::stringstream ss;
234 ss << possibleintvals[0];
235 for (unsigned int i = 1; i < possibleintvals.size(); i++)
236 ss << "," << possibleintvals[i];
237
238 Util::ParmParseException(INFO,file,func,line,full(name),"' expected [", ss.str(), "] but got ", value);
239
240 return -1;
241 }
242
243
244 int query_validate( std::string name, std::string & value, std::vector<const char *> possiblecharvals, bool firstbydefault,
245 std::string file = "", std::string func = "", int line = -1)
246 {
247 // if not using default values, then the input must be specified
248 if (!firstbydefault)
249 {
250 if (!contains(name.c_str()))
251 {
252 Util::ParmParseException(INFO,file,func,line,full(name),"required value for ",full(name)," missing");
253 }
254 }
255
256 // set default value
257 value = std::string(possiblecharvals[0]);
258
259 // get the read value (if it exists)
260 int retval = query(name.c_str(),value);
261
262 // check to make sure the read value matches one of the inpus
263 bool ok = false;
264 for (unsigned int i = 0; i < possiblecharvals.size(); i++)
265 {
266 if (value == std::string(possiblecharvals[i])) ok = true;
267 }
268
269 if (ok) return retval;
270
271 std::stringstream ss;
272 ss << possiblecharvals[0];
273 for (unsigned int i = 1; i < possiblecharvals.size(); i++)
274 ss << "," << possiblecharvals[i];
275
276 Util::ParmParseException(INFO,file,func,line,full(name),"' expected [", ss.str(), "] but got ", value);
277
278 return -1;
279 }
280
281 int query_validate( std::string name, std::string & value, std::vector<const char *> possiblecharvals,
282 std::string file = "", std::string func = "", int line = -1)
283 {
284 return query_validate(name,value,possiblecharvals,true,file,func,line);
285 }
286
287
288 // special case for strings
289 int query_default( std::string name, std::string & value, const char *defaultvalue,
290 std::string file = "", std::string func = "", int line = -1)
291 {
292 return query_default(name, value, std::string(defaultvalue), file, func, line);
293 }
294 // special case for bools
295 int query_default( std::string name, int & value, bool defaultvalue,
296 std::string file = "", std::string func = "query_default", int line = -1)
297 {
298 int defaultint = 0;
299 if (defaultvalue) defaultint = 1;
300 return query_default(name, value, defaultint, file, func, line);
301 }
302
303
304
305 // validate filenames
306 int query_file( std::string name, std::string & value, bool copyfile, bool checkfile,
307 std::string file = "", std::string func = "query_file", int line = -1)
308 {
309 try
310 {
311 if (!contains(name.c_str()))
312 {
313 Util::ParmParseException(INFO,file,func,line,full(name),full(name)," must be specified");
314 }
315
316 int retval = query(name.c_str(),value);
317
318 if (amrex::ParallelDescriptor::IOProcessor())
319 {
320 if ( checkfile && ! std::filesystem::exists(value))
321 {
322 Util::ParmParseException(INFO,file,func,line,full(name),full(name)," does not exist");
323 }
324 if ( checkfile && !std::filesystem::is_regular_file(value))
325 {
326 Util::ParmParseException(INFO,file,func,line,full(name),full(name)," is not a regular file");
327 }
328 if ( copyfile )
329 {
330 Util::CopyFileToOutputDir(value, true, full(name));
331 }
332 }
333 return retval;
334 }
335 catch (...)
336 {
337 Util::ParmParseException(INFO,file,func,line,full(name));
338 }
339 return -1;
340 }
341 int query_file( std::string name, std::string & value, bool copyfile,
342 std::string file = "", std::string func = "query_file", int line = -1)
343 {
344 return query_file(name,value,copyfile,true,file,func,line);
345 }
346 int query_file( std::string name, std::string & value,
347 std::string file = "", std::string func = "query_file", int line = -1)
348 {
349 return query_file(name,value,true,true,file,func,line);
350 }
351
352
353 template<typename T>
354 int queryarr( std::string name, std::vector<T> & value,
355 std::string /*file*/, std::string /*func*/, int /*line*/)
356 {
357 return amrex::ParmParse::queryarr(name.c_str(),value);
358 }
359 int queryarr( std::string name, Set::Vector & value,
360 std::string file = "", std::string func = "queryarr", int line = -1)
361 {
362 std::vector<Set::Scalar> vals;
363 amrex::ParmParse::queryarr(name.c_str(), vals);
364 if (vals.size() < AMREX_SPACEDIM)
365 {
366 Util::ParmParseException(INFO,file,func,line,full(name),full(name)," requires at least ", AMREX_SPACEDIM, " arguments, got ",vals.size());
367 }
368 for (int i = 0; i < AMREX_SPACEDIM; i++) value(i) = vals[i];
369 return 0;
370 }
371 int queryarr( std::string name, Set::Matrix & value,
372 std::string file = "", std::string func = "queryarr", int line = -1)
373 {
374 std::vector<Set::Scalar> vals;
375 amrex::ParmParse::queryarr(name.c_str(), vals);
376 if (vals.size() == 9)
377 {
378#if AMREX_SPACEDIM==2
379 Util::Warning(file,func,line,"Reading a 3D matrix (",full(name),")into a 2D code - some values will be ignored.");
380 value(0,0) = vals[0]; value(0,1)= vals[1];
381 value(1,0) = vals[3]; value(1,1)= vals[4];
382#endif
383#if AMREX_SPACEDIM==3
384 value(0,0) = vals[0]; value(0,1)= vals[1]; value(0,2)= vals[2];
385 value(1,0) = vals[3]; value(1,1)= vals[4]; value(1,2)= vals[5];
386 value(2,0) = vals[6]; value(2,1)= vals[7]; value(2,2)= vals[8];
387#endif
388 }
389 else if (vals.size() == 4)
390 {
391#if AMREX_SPACEDIM==2
392 value(0,0) = vals[0]; value(0,1)= vals[1];
393 value(1,0) = vals[2]; value(1,1)= vals[3];
394#endif
395#if AMREX_SPACEDIM==3
396 Util::Warning(file,func,line,"Reading a 2D matrix (",full(name),")into a 3D code - remaining values will be set to zero.");
397 value(0,0) = vals[0]; value(0,1)= vals[1]; value(0,2)= 0.0;
398 value(1,0) = vals[2]; value(1,1)= vals[3]; value(1,2)= 0.0;
399 value(2,0) = 0.0; value(2,1)= 0.0; value(2,2)= 0.0;
400#endif
401 }
402 else
403 {
404 Util::ParmParseException(INFO,file,func,line,full(name),full(name)," needs either 4 or 9 components, but got ",vals.size());
405 }
406 return 0;
407 }
408 template<typename T>
409 int queryarr_required( std::string name, std::vector<T> & value,
410 std::string file, std::string func, int line)
411 {
412 if (!contains(name.c_str()))
413 {
414 Util::ParmParseException(INFO,file,func,line,full(name),"required value for ",full(name)," missing");
415 }
416 return queryarr(name,value,file,func,line);
417 }
418
419
420 int queryarr_default( std::string name, std::vector<std::string> & value, std::string defaultvalue,
421 std::string = "", std::string = "", int = -1)
422 {
423 if (!contains(name.c_str()))
424 {
425 add(name.c_str(),defaultvalue);
426 }
427 return queryarr(name.c_str(),value);
428 }
429
430
431
432 template <typename T>
433 int
434 queryclass_enumerate(std::string a_name, std::vector<T> &value, int number = 1,
435 std::string file = "", std::string func = "", int line = __LINE__)
436 {
437 value.clear();
438
439 //
440 // If only one is present with no subscript, then read
441 // it only and return.
442 //
443 std::string name = a_name;
444 if (this->contains(name))
445 {
446 for (int n = 0; n < number; n++)
447 {
448 T tmp;
449 this->queryclass<T>(name, tmp, file, func, line);
450 value.push_back(tmp);
451 }
452 return 0;
453 }
454
455 //
456 // Some logic to determine whether we are starting with zero
457 // (model0, model1, model2, ...)
458 // or one
459 // (model1, model2, model3, ...)
460 // since both are supported
461 //
462 int start = -1;
463 std::string name0 = a_name + std::to_string(0);
464 std::string name1 = a_name + std::to_string(1);
465 if (this->contains(name0.c_str()))
466 {
467 start = 0;
468 name = name0;
469 }
470 else if (this->contains(name1.c_str()))
471 {
472 start = 1;
473 name = name1;
474 }
475 else
476 {
477 Util::Exception(INFO,"Enumerations must begin with 0 or 1");
478 }
479
480 //
481 // Iterate over items called (model0), model1, model2, etc
482 // until no more are found then exit.
483 //
484 for (int cntr = start; this->contains(name.c_str()); cntr++)
485 {
486 if (this->contains(name.c_str()))
487 {
488 T tmp;
489 this->queryclass<T>(name, tmp, file, func, line);
490 value.push_back(tmp);
491 }
492 name = a_name + std::to_string(cntr+1);
493 }
494
495 return 0;
496 }
497
498
499 template <typename T>
500 int
501 query_enumerate(std::string a_name, std::vector<T> &value, int number = 1,
502 std::string file = "", std::string func = "", int line = __LINE__)
503 {
504 value.clear();
505
506 //
507 // If only one is present with no subscript, then read
508 // it only and return.
509 //
510 std::string name = a_name;
511 if (this->contains(name))
512 {
513 for (int n = 0; n < number; n++)
514 {
515 T tmp;
516 this->query_required(name, tmp, file, func, line);
517 value.push_back(tmp);
518 }
519 return 0;
520 }
521
522 //
523 // Some logic to determine whether we are starting with zero
524 // (model0, model1, model2, ...)
525 // or one
526 // (model1, model2, model3, ...)
527 // since both are supported
528 //
529 int start = -1;
530 std::string name0 = a_name + std::to_string(0);
531 std::string name1 = a_name + std::to_string(1);
532 if (this->contains(name0.c_str()))
533 {
534 start = 0;
535 name = name0;
536 }
537 else if (this->contains(name1.c_str()))
538 {
539 start = 1;
540 name = name1;
541 }
542 else
543 {
544 Util::Exception(INFO,"Enumerations must begin with 0 or 1");
545 }
546
547 //
548 // Iterate over items called (model0), model1, model2, etc
549 // until no more are found then exit.
550 //
551 for (int cntr = start; this->contains(name.c_str()); cntr++)
552 {
553 if (this->contains(name.c_str()))
554 {
555 T tmp;
556 this->query_required(name, tmp, file, func, line);
557 value.push_back(tmp);
558 }
559 name = a_name + std::to_string(cntr+1);
560 }
561
562 return 0;
563 }
564
565
566
567 int AnyUnusedInputs(bool inscopeonly = true, bool verbose = false)
568 {
569 int cnt = 0;
570 for (auto li = m_table->begin(), End = m_table->end(); li != End; ++li)
571 {
572 if (!li->second.m_count)
573 {
574 if (inscopeonly && getPrefix() != "")
575 {
576 if (li->first.rfind(getPrefix()+".",0) != std::string::npos)
577 {
578 if (verbose) Util::Warning(INFO,li->first);
579 cnt++;
580 }
581 }
582 else
583 {
584 if (verbose) Util::Warning(INFO,li->first);
585 cnt++;
586 }
587 }
588 }
589 return cnt;
590 }
591
592 std::vector<std::string> GetUnusedInputs()
593 {
594 std::vector<std::string> ret;
595 for (auto li = m_table->begin(), End = m_table->end(); li != End; ++li)
596 {
597 if (!li->second.m_count && li->first.rfind(getPrefix()+".",0) != std::string::npos)
598 {
599 ret.push_back(li->first);
600 }
601 }
602 return ret;
603 }
604
605 static int AllUnusedInputs()
606 {
607 ParmParse pp;
608 int cnt = 0;
609 for (auto li = pp.m_table->begin(), End = pp.m_table->end(); li != End; ++li)
610 {
611 if (!li->second.m_count)
612 {
613 Util::Warning(INFO,li->first);
614 cnt++;
615 }
616 }
617 return cnt;
618 }
619 std::string prefix ()
620 {
621 return getPrefix();
622 }
623 std::string full (std::string name)
624 {
625 std::string prefix = getPrefix();
626 if (prefix != "") return getPrefix() + "." + name;
627 else return name;
628 }
629
630
631 using amrex::ParmParse::queryarr;
632 template<class T>
633 void queryclass(std::string name, T * value,
634 std::string file = "", std::string func = "", int line = -1)
635 {
636 auto old_prefix = m_prefix;
637 try
638 {
639 if (old_prefix.empty()) m_prefix = name;
640 else m_prefix.append(".").append(name);
641 T::Parse(*value, *this);
642 std::vector<std::string> unused_inputs = GetUnusedInputs();
643 if (unused_inputs.size())
644 {
645 std::stringstream ss;
646 for (unsigned int i=0; i < unused_inputs.size(); i++)
647 ss << "\n\t" << unused_inputs[i];
648 Util::ParmParseException(INFO,file,func,line,name,"The following inputs were specified but not used",ss.str());
649 }
650 }
651 catch (...)
652 {
653 m_prefix = old_prefix;
654 Util::ParmParseException(INFO,file,func,line,full(name));
655 }
656 m_prefix = old_prefix;
657 }
658 template<class T>
659 void queryclass(std::string name, T & value,
660 std::string file = "", std::string func = "", int line = __LINE__)
661 {
662 auto old_prefix = m_prefix;
663 try
664 {
665 if (old_prefix.empty()) m_prefix = name;
666 else m_prefix.append(".").append(name);
667 T::Parse(value, *this);
668 std::vector<std::string> unused_inputs = GetUnusedInputs();
669 if (unused_inputs.size())
670 {
671 std::stringstream ss;
672 for (unsigned int i=0; i < unused_inputs.size(); i++)
673 ss << "\n\t" << unused_inputs[i];
674 Util::ParmParseException(INFO,file,func,line,name,"The following inputs were specified but not used",ss.str());
675 }
676 }
677 catch (...)
678 {
679 m_prefix = old_prefix;
680 Util::ParmParseException(INFO,file,func,line,full(name));
681 }
682 m_prefix = old_prefix;
683 }
684
685 template<class T>
686 void queryclass(T * value,
687 std::string file = "", std::string func = "", int line = __LINE__)
688 {
689 try
690 {
691 T::Parse(*value, *this);
692 }
693 catch (...)
694 {
695 Util::ParmParseException(INFO,file,func,line,getPrefix());
696 }
697 }
698 template<class T>
699 void queryclass(T & value,
700 std::string file = "", std::string func = "", int line = __LINE__)
701 {
702 try
703 {
704 T::Parse(value, *this);
705 }
706 catch (...)
707 {
708 Util::ParmParseException(INFO,file,func,line,getPrefix());
709 }
710 }
711
712 //
713 // Variadic template parsing operator to assign a pointer to
714 // one of a set of possible class objects, then call that method's
715 // Parse function.
716 //
717 // If there is more than one instantiating class, then type must be set.
718 // Otherwise, no type is necessary.
719 //
720 template<typename... IC, typename... Args, typename PTRTYPE>
721 void select (std::string name, PTRTYPE *& ic_eta, Args&&... args)
722 {
723 // if there is only one IC arg provided, we don't need to check the type - assume that
724 // it is the default.
725 if constexpr (sizeof...(IC) == 0)
726 {
727 using first_IC = std::tuple_element_t<0, std::tuple<IC...>>;
728 ic_eta = new first_IC(std::forward<Args>(args)..., (*this), name + "." + std::string(first_IC::name));
729 }
730 // otherwise, check the type.
731 else
732 {
733 std::string type = "";
734 this->query_required(name + ".type", type);
735 bool matched = (( type == IC::name
736 ? (ic_eta = new IC(std::forward<Args>(args)..., (*this), name + "." + std::string(IC::name))),
737 true
738 : false) || ...);
739 if (!matched)
740 Util::Exception(INFO, type, " not a valid type for ", name);
741 }
742 }
743
744 //
745 // Identical to the above, except sets the type automatically to the
746 // firs specified
747 //
748 template<typename FirstIC, typename... IC, typename... Args, typename PTRTYPE>
749 void select_default (std::string name, PTRTYPE *& ic_eta, Args&&... args)
750 {
751 std::string type = "";
752
753 this->query_default(name + ".type", type, FirstIC::name);
754
755 bool matched =
756 (( type == FirstIC::name
757 ? (ic_eta = new FirstIC(std::forward<Args>(args)..., (*this), name + "." + std::string(FirstIC::name))),
758 true : false))
759 ||
760 (( type == IC::name
761 ? (ic_eta = new IC(std::forward<Args>(args)..., (*this), name + "." + std::string(IC::name))),
762 true : false) || ...);
763
764
765 if (!matched)
766 Util::Exception(INFO,type," not a valid type for ",name);
767 }
768
769
770 //
771 //
772 template<typename... IC, typename... Args, typename PTRTYPE>
773 void select_enumerate (std::string a_name, std::vector<PTRTYPE*> & value, Args&&... args)
774 {
775
776 value.clear();
777
778 //
779 // If only one is present with no subscript, then read
780 // it only and return.
781 //
782 std::string name = a_name;
783 if (this->contains(name))
784 {
785 PTRTYPE *tmp;
786 this->select<IC...>(a_name, tmp, args...);
787 value.push_back(tmp);
788 return;
789 }
790
791 //
792 // Some logic to determine whether we are starting with zero
793 // (model0, model1, model2, ...)
794 // or one
795 // (model1, model2, model3, ...)
796 // since both are supported
797 //
798 int start = -1;
799 std::string name0 = a_name + std::to_string(0);
800 std::string name1 = a_name + std::to_string(1);
801 if (this->contains(name0.c_str()))
802 {
803 start = 0;
804 name = name0;
805 }
806 else if (this->contains(name1.c_str()))
807 {
808 start = 1;
809 name = name1;
810 }
811 else
812 {
813 Util::Exception(INFO,"Enumerations must begin with 0 or 1");
814 }
815
816 //
817 // Iterate over items called (model0), model1, model2, etc
818 // until no more are found then exit.
819 //
820 for (int cntr = start; this->contains(name.c_str()); cntr++)
821 {
822 if (this->contains(name.c_str()))
823 {
824 PTRTYPE *tmp;
825 this->select<IC...>(name, tmp, args...);
826 value.push_back(tmp);
827 }
828 name = a_name + std::to_string(cntr+1);
829 }
830 }
831
832
833
834 //
835 // Similar to select but specialized for main functions
836 //
837 template<typename... INTEGRATOR, typename... Args, typename PTRTYPE>
838 void select_main (PTRTYPE *& ic_eta, Args&&... args)
839 {
840 std::string type = "";
841
842 this->query_required("alamo.program", type);
843
844 bool matched = ((type == INTEGRATOR::name
845 ? (ic_eta = new INTEGRATOR(std::forward<Args>(args)..., (*this))),
846 true
847 : false) || ...);
848 if (!matched)
849 Util::Exception(INFO,type," not a valid type for ",type);
850 }
851
852 //
853 // Similar to select_main but works for one function only
854 // and doesn't require a type specifier.
855 //
856
857 // with variadic arguments
858 template<typename INTEGRATOR, typename Args, typename PTRTYPE>
859 void select_only (PTRTYPE *& ic_eta, Args&& args)
860 {
861 ic_eta = new INTEGRATOR(std::forward<Args>(args), (*this));
862 }
863 // without variadic arguments
864 template<typename INTEGRATOR, typename PTRTYPE>
865 void select_only (PTRTYPE *& ic_eta)
866 {
867 ic_eta = new INTEGRATOR((*this));
868 }
869
870
871 //
872 // functionally simlar to other kinds of select, execpt works on
873 // template-based static dispatch.
874 //
875
876 template <typename... OBJ, typename CLASS>
877 void select(std::string name, CLASS& value)
878 {
879 pushPrefix(name);
880 static_polymorphism_parser<CLASS, 0, OBJ...>(value);
881 popPrefix();
882 }
883
884private:
885 //
886 // This function is a virtual "swtich / case" block for static
887 // dispatch. It works on a faux-virtual class "CLASS" that must
888 // contain a tuple of "obj" with each "obj" being a derived type.
889 // Recursion is used to unroll the list, identify the correct class
890 // based on "name/type", set the "selected" index, then call the
891 // appropriate class' Parse function.
892 //
893 // This is only for use by the "select" functions.
894 //
895 template <typename CLASS, int N, typename... OBJ>
896 void static_polymorphism_parser(CLASS& value)
897 {
898 if constexpr (N == 0)
899 {
900 std::string type;
901 query_default("type",type,value.names[0]);
902
903 for (unsigned int i = 0; i < sizeof...(OBJ); i++)
904 if (type == value.names[i])
905 value.selected = i;
906
907 if (value.selected < 0)
909 "Error reading " + getPrefix() +
910 ", invalid type " + type);
911
912
913 pushPrefix(type);
914 }
915
916 if constexpr (N < sizeof...(OBJ))
917 {
918 if (value.selected == N)
919 {
920 std::get<N>(value.obj).Parse(std::get<N>(value.obj), *this);
921 popPrefix();
922 return;
923 }
924 else
925 return static_polymorphism_parser<CLASS, N+1, OBJ...>(value);
926 }
927 else Util::Abort(INFO);
928 }
929
930public:
931
932 template <int N>
933 void query_exactly(std::vector<std::string> names, std::pair<std::string, Set::Scalar> values[N])
934 {
935 int cnt = 0;
936 std::vector<std::string> read;
937 for (unsigned int n = 0; n < names.size(); n++)
938 {
939 if (amrex::ParmParse::contains(names[n].c_str()))
940 {
941 read.push_back(names[n]);
942 cnt++;
943 }
944 }
945 Util::AssertException( INFO, TEST(cnt == N), "incorrect number of values specified: only ", N,
946 " values are allowed, but received ",Util::String::Join(read));
947
948
949 cnt = 0;
950 for (unsigned int n = 0; n < names.size(); n++)
951 {
952 if (amrex::ParmParse::contains(names[n].c_str()))
953 {
954 values[cnt].first = names[n];
955 query_required(names[n],values[cnt].second);
956 cnt++;
957 }
958 }
959 }
960
961
962
963
964};
965}
966#endif
#define TEST(x)
Definition Util.H:21
#define INFO
Definition Util.H:20
int query_file(std::string name, std::string &value, bool copyfile, std::string file="", std::string func="query_file", int line=-1)
Definition ParmParse.H:341
void forbid(std::string name, std::string explanation, std::string file="", std::string func="", int line=-1)
Definition ParmParse.H:158
bool contains(std::string name)
Definition ParmParse.H:172
int queryarr(std::string name, Set::Matrix &value, std::string file="", std::string func="queryarr", int line=-1)
Definition ParmParse.H:371
void select(std::string name, CLASS &value)
Definition ParmParse.H:877
void pushPrefix(const std::string prefix)
Definition ParmParse.H:140
void query_exactly(std::vector< std::string > names, std::pair< std::string, Set::Scalar > values[N])
Definition ParmParse.H:933
int query_default(std::string name, std::string &value, const char *defaultvalue, std::string file="", std::string func="", int line=-1)
Definition ParmParse.H:289
int queryarr_required(std::string name, std::vector< T > &value, std::string file, std::string func, int line)
Definition ParmParse.H:409
int AnyUnusedInputs(bool inscopeonly=true, bool verbose=false)
Definition ParmParse.H:567
std::vector< std::string > GetUnusedInputs()
Definition ParmParse.H:592
std::string getPrefix() const
Definition ParmParse.H:134
static bool checked_for_input_files
Definition ParmParse.H:129
int query_required(std::string name, T &value, std::string file="", std::string func="", int line=-1)
Definition ParmParse.H:192
void queryclass(std::string name, T *value, std::string file="", std::string func="", int line=-1)
Definition ParmParse.H:633
std::string prefix()
Definition ParmParse.H:619
void select(std::string name, PTRTYPE *&ic_eta, Args &&... args)
Definition ParmParse.H:721
void Define()
Definition ParmParse.H:116
void select_default(std::string name, PTRTYPE *&ic_eta, Args &&... args)
Definition ParmParse.H:749
int query_validate(std::string name, std::string &value, std::vector< const char * > possiblecharvals, std::string file="", std::string func="", int line=-1)
Definition ParmParse.H:281
int query_default(std::string name, T &value, T defaultvalue, std::string="", std::string="", int=-1)
Definition ParmParse.H:203
int queryclass_enumerate(std::string a_name, std::vector< T > &value, int number=1, std::string file="", std::string func="", int line=__LINE__)
Definition ParmParse.H:434
int queryarr(std::string name, Set::Vector &value, std::string file="", std::string func="queryarr", int line=-1)
Definition ParmParse.H:359
void select_enumerate(std::string a_name, std::vector< PTRTYPE * > &value, Args &&... args)
Definition ParmParse.H:773
static int AllUnusedInputs()
Definition ParmParse.H:605
void queryclass(std::string name, T &value, std::string file="", std::string func="", int line=__LINE__)
Definition ParmParse.H:659
int query_file(std::string name, std::string &value, std::string file="", std::string func="query_file", int line=-1)
Definition ParmParse.H:346
int query_default(std::string name, int &value, bool defaultvalue, std::string file="", std::string func="query_default", int line=-1)
Definition ParmParse.H:295
void queryclass(T &value, std::string file="", std::string func="", int line=__LINE__)
Definition ParmParse.H:699
void popPrefix()
Definition ParmParse.H:148
int queryarr(std::string name, std::vector< T > &value, std::string, std::string, int)
Definition ParmParse.H:354
int query_file(std::string name, std::string &value, bool copyfile, bool checkfile, std::string file="", std::string func="query_file", int line=-1)
Definition ParmParse.H:306
void static_polymorphism_parser(CLASS &value)
Definition ParmParse.H:896
void select_only(PTRTYPE *&ic_eta, Args &&args)
Definition ParmParse.H:859
void select_main(PTRTYPE *&ic_eta, Args &&... args)
Definition ParmParse.H:838
void queryclass(T *value, std::string file="", std::string func="", int line=__LINE__)
Definition ParmParse.H:686
void select_only(PTRTYPE *&ic_eta)
Definition ParmParse.H:865
void ignore(std::string name)
Definition ParmParse.H:135
std::string full(std::string name)
Definition ParmParse.H:623
int query_validate(std::string name, std::string &value, std::vector< const char * > possiblecharvals, bool firstbydefault, std::string file="", std::string func="", int line=-1)
Definition ParmParse.H:244
int query_enumerate(std::string a_name, std::vector< T > &value, int number=1, std::string file="", std::string func="", int line=__LINE__)
Definition ParmParse.H:501
int queryarr_default(std::string name, std::vector< std::string > &value, std::string defaultvalue, std::string="", std::string="", int=-1)
Definition ParmParse.H:420
int query_validate(std::string name, int &value, std::vector< int > possibleintvals, std::string file="", std::string func="", int line=-1)
Definition ParmParse.H:213
ParmParse(std::string arg)
Definition ParmParse.H:132
Initialize a spherical inclusion.
Definition BMP.H:19
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, 1 > Vector
Definition Base.H:20
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, AMREX_SPACEDIM > Matrix
Definition Base.H:23
std::string Join(std::vector< std::string > &vec, char separator)
Definition Util.cpp:248
AMREX_FORCE_INLINE void AssertException(std::string file, std::string func, int line, std::string smt, bool pass, Args const &... args)
Definition Util.H:233
void Abort(const char *msg)
Definition Util.cpp:170
void ParmParseException(std::string file, std::string func, int line, std::string file2, std::string, int line2, std::string fullname, Args const &... args)
Definition Util.H:263
void CopyFileToOutputDir(std::string a_path, bool fullpath, std::string prefix)
Definition Util.cpp:52
void Warning(std::string file, std::string func, int line, Args const &... args)
Definition Util.H:181
void Message(std::string file, std::string func, int line, Args const &... args)
Definition Util.H:141
void Exception(std::string file, std::string func, int line, Args const &... args)
Definition Util.H:205