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#include <stdexcept>
94
95#include "Util/Util.H"
96#include "Unit/Unit.H"
97#include "Set/Base.H"
98#include "AMReX_ParmParse.H"
99
100
101#define pp_query_required(...) pp.query_required(__VA_ARGS__)
102#define pp_query_default(...) pp.query_default(__VA_ARGS__)
103#define pp_query_validate(...) pp.query_validate(__VA_ARGS__)
104#define pp_query_file(...) pp.query_file(__VA_ARGS__)
105#define pp_queryarr(...) pp.queryarr(__VA_ARGS__)
106#define pp_queryarr_required(...) pp.queryarr_required(__VA_ARGS__)
107#define pp_queryarr_default(...) pp.queryarr_default(__VA_ARGS__)
108#define pp_query(...) pp.query(__VA_ARGS__)
109#define pp_queryclass(...) pp.queryclass(__VA_ARGS__)
110#define pp_forbid(...) pp.forbid(__VA_ARGS__)
111
112
113namespace IO
114{
115class ParmParse : public amrex::ParmParse
116{
117private:
118 void Define()
119 {
120 if (checked_for_input_files) return;
121 int k = 0;
122 std::string inputfile = "";
123 while (this->querykth("input",k,inputfile))
124 {
125 Util::Message(INFO,"Including inputs from "+inputfile);
126 this->addfile(inputfile);
127 k++;
128 }
130 }
132
133public:
134 ParmParse(std::string arg) : amrex::ParmParse::ParmParse(arg) {Define();} ;
135 ParmParse() : amrex::ParmParse::ParmParse() {Define();} ;
136 std::string getPrefix() const {return m_prefix;};
137 void ignore(std::string name)
138 {
139 (void)amrex::ParmParse::contains(name.c_str());
140 }
141
142 void pushPrefix(const std::string prefix)
143 {
144 if (m_prefix.length())
145 m_prefix = m_prefix + "." + prefix;
146 else
147 m_prefix = prefix;
148 }
149
151 {
152 size_t pos = m_prefix.rfind('.');
153 if (pos == std::string::npos)
154 m_prefix = "";
155 else
156 m_prefix = m_prefix.substr(0, pos);
157 }
158
159
160 void forbid(std::string name, std::string explanation)
161 {
162 if (amrex::ParmParse::contains(full(name).c_str()))
163 {
164 Util::ParmParseException(INFO,full(name),full(name)," forbidden: ", explanation);
165 }
166 std::set<std::string> subs = amrex::ParmParse::getEntries(full(name));
167 if (subs.size())
168 {
169 Util::ParmParseException(INFO,full(name),full(name)," forbidden: ", explanation);
170 }
171 }
172
173 bool contains(std::string name)
174 {
175 if (amrex::ParmParse::contains(name.c_str()))
176 return true;
177 if (amrex::ParmParse::contains(full(name).c_str()))
178 return true;
179 {
180 std::set<std::string> subs = amrex::ParmParse::getEntries(name.c_str());
181 if (subs.size())
182 return true;
183 }
184 {
185 std::set<std::string> subs = amrex::ParmParse::getEntries(full(name).c_str());
186 if (subs.size())
187 return true;
188 }
189 return false;
190 }
191
192 int queryunit (std::string name, Unit &value)
193 {
194 try
195 {
196 std::string strvalue;
197 int retval = amrex::ParmParse::query(name.c_str(),strvalue);
198 value = Unit::Parse(strvalue);
199 Util::DebugMessage(INFO,full(name),": ",strvalue," ==> ",value);
200 return retval;
201 }
202 catch (std::runtime_error & e)
203 {
204 Util::ParmParseException(INFO,full(name), e.what());
205 }
206 catch (...)
207 {
209 }
210 return -1;
211 }
212
213 int queryunit (std::string name, Unit &value, const Unit type)
214 {
215 try
216 {
217 int retval = queryunit(name,value);
218 if (!value.isType(type) && !value.isType(Unit::Less()))
219 {
221 "value requiested had wrong units:", value.normalized_unitstring(),
222 ", units requested are of SI type ",type.normalized_unitstring());
223 }
224 return retval;
225 }
226 catch (...)
227 {
229 }
230 return -1;
231 }
232 int queryunit (std::string name, Set::Scalar &value, const Unit type)
233 {
234 try
235 {
236 Unit read;
237 int retval = queryunit(name,read,type);
238 value = read.normalized_value();
239 return retval;
240 }
241 catch (std::runtime_error &e)
242 {
243 Util::ParmParseException(INFO,full(name), e.what());
244 }
245 return -1;
246 }
247
248 template<typename T>
249 int query_required( std::string name, T & value)
250 {
251 try
252 {
253 if (!contains(name.c_str()))
254 {
255 Util::ParmParseException(INFO,full(name),"required value for ",full(name)," missing");
256 }
257 return query(name.c_str(),value);
258 }
259 catch (std::runtime_error & e)
260 {
261 Util::ParmParseException(INFO,full(name),e.what());
262 }
263 catch (...)
264 {
266 }
267 return -1;
268 }
269
270 template<typename T>
271 int query_required( std::string name, T & value, const Unit type)
272 {
273 try
274 {
275 if (!contains(name.c_str()))
276 {
277 Util::ParmParseException(INFO,full(name),"required value for ",full(name)," missing");
278 }
279 return queryunit(name.c_str(), value, type);
280 }
281 catch (std::runtime_error & e)
282 {
283 Util::ParmParseException(INFO,full(name),e.what());
284 }
285 catch (...)
286 {
288 }
289 return -1;
290 }
291
292 template<typename T>
293 int query_default( std::string name, T & value, T defaultvalue)
294 {
295 try
296 {
297 if (!contains(name.c_str()))
298 {
299 add(name.c_str(),defaultvalue);
300 }
301 return query(name.c_str(),value);
302 }
303 catch (std::runtime_error & e)
304 {
305 Util::ParmParseException(INFO,full(name),e.what());
306 }
307 catch (...)
308 {
310 }
311 return -1;
312 }
313
314 template<typename T>
315 int query_default( std::string name, T & value, std::string defaultvalue, const Unit type)
316 {
317 try
318 {
319 if (!contains(name.c_str()))
320 {
321 add(name.c_str(),defaultvalue);
322 }
323 return queryunit(name.c_str(),value,type);
324 }
325 catch (std::runtime_error & e)
326 {
327 Util::ParmParseException(INFO,full(name),e.what());
328 }
329 catch (...)
330 {
332 }
333 return -1;
334 }
335
336 int query_validate( std::string name, int & value, std::vector<int> possibleintvals)
337 {
338 try
339 {
340 // First value is accepted by default...
341
342 // set default value
343 if (!contains(name.c_str()))
344 {
345 add(name.c_str(), possibleintvals[0]);
346 }
347
348 // get the read value (if it exists)
349 int retval = query(name.c_str(),value);
350
351 // check to make sure the read value matches one of the inpus
352 bool ok = false;
353 for (unsigned int i = 0; i < possibleintvals.size(); i++)
354 {
355 if (value == possibleintvals[i]) ok = true;
356 }
357
358 if (ok) return retval;
359
360 std::stringstream ss;
361 ss << possibleintvals[0];
362 for (unsigned int i = 1; i < possibleintvals.size(); i++)
363 ss << "," << possibleintvals[i];
364
365 Util::ParmParseException(INFO,full(name),"' expected [", ss.str(), "] but got ", value);
366 }
367 catch (std::runtime_error & e)
368 {
369 Util::ParmParseException(INFO,full(name),e.what());
370 }
371 catch (...)
372 {
374 }
375 return -1;
376 }
377
378
379 int query_validate( std::string name, std::string & value, std::vector<const char *> possiblecharvals, bool firstbydefault)
380 {
381 try
382 {
383 // if not using default values, then the input must be specified
384 if (!firstbydefault)
385 {
386 if (!amrex::ParmParse::contains(name.c_str()))
387 {
388 Util::ParmParseException(INFO,full(name),"required value for ",full(name)," missing");
389 }
390 }
391
392 // set default value
393 if (!amrex::ParmParse::contains(name.c_str()))
394 {
395 add(name.c_str(), std::string(possiblecharvals[0]));
396 }
397
398 // get the read value (if it exists)
399 int retval = amrex::ParmParse::query(name.c_str(),value);
400
401 // check to make sure the read value matches one of the inpus
402 bool ok = false;
403 for (unsigned int i = 0; i < possiblecharvals.size(); i++)
404 {
405 if (value == std::string(possiblecharvals[i])) ok = true;
406 }
407
408 if (ok) return retval;
409
410 std::stringstream ss;
411 ss << possiblecharvals[0];
412 for (unsigned int i = 1; i < possiblecharvals.size(); i++)
413 ss << "," << possiblecharvals[i];
414
415 Util::ParmParseException(INFO,full(name),"' expected [", ss.str(), "] but got ", value);
416 }
417 catch (std::runtime_error & e)
418 {
419 Util::ParmParseException(INFO,full(name),e.what());
420 }
421 catch (...)
422 {
424 }
425
426 return -1;
427 }
428
429 int query_validate( std::string name, std::string & value, std::vector<const char *> possiblecharvals)
430 {
431 try
432 {
433 return query_validate(name,value,possiblecharvals,true);
434 }
435 catch (std::runtime_error & e)
436 {
437 Util::ParmParseException(INFO,full(name),e.what());
438 }
439 catch (...)
440 {
442 }
443 return -1;
444 }
445
446
447 // special case for strings
448 int query_default( std::string name, std::string & value, const char *defaultvalue)
449 {
450 try
451 {
452 return query_default(name, value, std::string(defaultvalue));
453 }
454 catch (std::runtime_error & e)
455 {
456 Util::ParmParseException(INFO,full(name),e.what());
457 }
458 catch (...)
459 {
461 }
462 return -1;
463 }
464 // special case for bools
465 int query_default( std::string name, int & value, bool defaultvalue)
466 {
467 try
468 {
469 int defaultint = 0;
470 if (defaultvalue) defaultint = 1;
471 return query_default(name, value, defaultint);
472 }
473 catch (std::runtime_error & e)
474 {
475 Util::ParmParseException(INFO,full(name),e.what());
476 }
477 catch (...)
478 {
480 }
481 return -1;
482 }
483
484
485 // validate filenames
486 int query_file( std::string name, std::string & value, bool copyfile, bool checkfile)
487 {
488 try
489 {
490 if (!contains(name.c_str()))
491 {
492 Util::ParmParseException(INFO,full(name),full(name)," must be specified");
493 }
494
495 int retval = query(name.c_str(),value);
496
497 if (amrex::ParallelDescriptor::IOProcessor())
498 {
499 if ( checkfile && ! std::filesystem::exists(value))
500 {
501 Util::ParmParseException(INFO,full(name),full(name)," does not exist");
502 }
503 if ( checkfile && !std::filesystem::is_regular_file(value))
504 {
505 Util::ParmParseException(INFO,full(name),full(name)," is not a regular file");
506 }
507 if ( copyfile )
508 {
509 Util::CopyFileToOutputDir(value, true, full(name));
510 }
511 }
512 return retval;
513 }
514 catch (std::runtime_error & e)
515 {
516 Util::ParmParseException(INFO,full(name),e.what());
517 }
518 catch (...)
519 {
521 }
522 return -1;
523 }
524 int query_file( std::string name, std::string & value, bool copyfile)
525 {
526 return query_file(name,value,copyfile,true);
527 }
528 int query_file( std::string name, std::string & value)
529 {
530 return query_file(name,value,true,true);
531 }
532
533
534 template<typename T>
535 int queryarr( std::string name, std::vector<T> & value)
536 {
537 try
538 {
539 return amrex::ParmParse::queryarr(name.c_str(),value);
540 }
541 catch (...)
542 {
544 }
545 return -1;
546 }
547 int queryarr( std::string name, std::vector<Set::Scalar> & value, Unit unit = Unit::Less())
548 {
549 try
550 {
551 if (unit.isType(Unit::Less()))
552 {
553 return amrex::ParmParse::queryarr(name.c_str(),value);
554 }
555 else
556 {
557 value.clear();
558 std::vector<std::string> valstrings;
559 int retval = amrex::ParmParse::queryarr(name.c_str(), valstrings);
560 for (unsigned int i = 0; i < valstrings.size(); i++)
561 {
562 Unit unitvalue = Unit::Parse(valstrings[i]);
563 Util::DebugMessage(INFO,full(name),": ",valstrings[i]," ==> ",unitvalue);
564
565 if (!unitvalue.isType(unit) && !unitvalue.isType(Unit::Less()))
566 {
567 Util::Exception(INFO,"value specified had wrong units:", valstrings[i]);
568 }
569 value.push_back(unitvalue.normalized_value());
570 }
571 return retval;
572 }
573 }
574 catch (std::runtime_error &e)
575 {
576 Util::ParmParseException(INFO,full(name), e.what());
577 }
578 catch (...)
579 {
581 }
582 return -1;
583 }
584 int queryarr( std::string name, Set::Vector & value, Unit unit = Unit::Less())
585 {
586 try
587 {
588 std::vector<Set::Scalar> vals;
589 queryarr(name.c_str(), vals, unit);
590 if (vals.size() < AMREX_SPACEDIM)
591 {
593 " requires at least ", AMREX_SPACEDIM,
594 " arguments, got ",vals.size());
595 }
596 for (int i = 0; i < AMREX_SPACEDIM; i++) value(i) = vals[i];
597 return 0;
598 }
599 catch(...)
600 {
602 }
603 return -1;
604 }
605 int queryarr( std::string name, Set::Matrix & value, Unit unit = Unit::Less())
606 {
607 std::vector<Set::Scalar> vals;
608 queryarr(name.c_str(), vals,unit);
609 if (vals.size() == 9)
610 {
611#if AMREX_SPACEDIM==2
612 Util::Warning(INFO, "Reading a 3D matrix (",full(name),")into a 2D code - some values will be ignored.");
613 value(0,0) = vals[0]; value(0,1)= vals[1];
614 value(1,0) = vals[3]; value(1,1)= vals[4];
615#endif
616#if AMREX_SPACEDIM==3
617 value(0,0) = vals[0]; value(0,1)= vals[1]; value(0,2)= vals[2];
618 value(1,0) = vals[3]; value(1,1)= vals[4]; value(1,2)= vals[5];
619 value(2,0) = vals[6]; value(2,1)= vals[7]; value(2,2)= vals[8];
620#endif
621 }
622 else if (vals.size() == 4)
623 {
624#if AMREX_SPACEDIM==2
625 value(0,0) = vals[0]; value(0,1)= vals[1];
626 value(1,0) = vals[2]; value(1,1)= vals[3];
627#endif
628#if AMREX_SPACEDIM==3
629 Util::Warning(INFO,"Reading a 2D matrix (",full(name),")into a 3D code - remaining values will be set to zero.");
630 value(0,0) = vals[0]; value(0,1)= vals[1]; value(0,2)= 0.0;
631 value(1,0) = vals[2]; value(1,1)= vals[3]; value(1,2)= 0.0;
632 value(2,0) = 0.0; value(2,1)= 0.0; value(2,2)= 0.0;
633#endif
634 }
635 else
636 {
637 Util::ParmParseException(INFO,full(name),full(name)," needs either 4 or 9 components, but got ",vals.size());
638 }
639 return 0;
640 }
641
642 template<typename T>
643 int queryarr_required( std::string name, std::vector<T> & value)
644 {
645 if (!contains(name.c_str()))
646 {
647 Util::ParmParseException(INFO,full(name),"required value for ",full(name)," missing");
648 }
649 return queryarr<T>(name,value);
650 }
651
652 int queryarr_required( std::string name, std::vector<Set::Scalar> & value, Unit unit = Unit::Less())
653 {
654 if (!contains(name.c_str()))
655 {
656 Util::ParmParseException(INFO,full(name),"required value for ",full(name)," missing");
657 }
658 return queryarr(name,value,unit);
659 }
660 int queryarr_default( std::string name, std::vector<std::string> & value, std::vector<std::string> defaultvalue)
661 {
662 if (!contains(name.c_str()))
663 {
664 addarr(name.c_str(),defaultvalue);
665 }
666 return amrex::ParmParse::queryarr(name.c_str(),value);
667 }
668
669 int queryarr_default( std::string name, Set::Vector & value, Set::Vector defaultvalue)
670 {
671 try
672 {
673 if (!contains(name.c_str()))
674 {
675 add(name.c_str(),Util::String::Join(defaultvalue));
676 value = defaultvalue;
677 return 0;
678 }
679 return queryarr(name.c_str(),value);
680 }
681 catch (...)
682 {
684 }
685 return -1;
686 }
687
688 int queryarr_default( std::string name, Set::Matrix & value, Set::Matrix defaultvalue)
689 {
690 try
691 {
692 if (!contains(name.c_str()))
693 {
694 add(name.c_str(),Util::String::Join(defaultvalue));
695 value = defaultvalue;
696 return 0;
697 }
698 return queryarr(name.c_str(),value);
699 }
700 catch (...)
701 {
703 }
704 return -1;
705 }
706
707 int queryarr_default( std::string name, std::vector<double> & value, std::vector<double> defaultvalue)
708 {
709 try
710 {
711 if (!contains(name.c_str()))
712 {
713 addarr(name.c_str(),defaultvalue);
714 }
715 return queryarr(name.c_str(),value);
716 }
717 catch (...)
718 {
720 }
721 return -1;
722 }
723
724 int queryarr_default( std::string name, std::vector<double> & value, std::vector<std::string> defaultvalue, Unit unit)
725 {
726 try
727 {
728 if (!contains(name.c_str()))
729 {
730 addarr(name.c_str(),defaultvalue);
731 }
732 return queryarr(name,value, unit);
733 }
734 catch (...)
735 {
737 }
738 return -1;
739 }
740
741
742 template <typename T>
743 int
744 queryclass_enumerate(std::string a_name, std::vector<T> &value, int number = 1)
745 {
746 value.clear();
747
748 //
749 // If only one is present with no subscript, then read
750 // it only and return.
751 //
752 std::string name = a_name;
753 if (this->contains(name))
754 {
755 for (int n = 0; n < number; n++)
756 {
757 T tmp;
758 this->queryclass<T>(name, tmp);
759 value.push_back(tmp);
760 }
761 return 0;
762 }
763
764 //
765 // Some logic to determine whether we are starting with zero
766 // (model0, model1, model2, ...)
767 // or one
768 // (model1, model2, model3, ...)
769 // since both are supported
770 //
771 int start = -1;
772 std::string name0 = a_name + std::to_string(0);
773 std::string name1 = a_name + std::to_string(1);
774 if (this->contains(name0.c_str()))
775 {
776 start = 0;
777 name = name0;
778 }
779 else if (this->contains(name1.c_str()))
780 {
781 start = 1;
782 name = name1;
783 }
784 else
785 {
786 Util::ParmParseException(INFO,full(name), "Enumerations must begin with 0 or 1");
787 }
788
789 //
790 // Iterate over items called (model0), model1, model2, etc
791 // until no more are found then exit.
792 //
793 for (int cntr = start; this->contains(name.c_str()); cntr++)
794 {
795 if (this->contains(name.c_str()))
796 {
797 T tmp;
798 this->queryclass<T>(name, tmp);
799 value.push_back(tmp);
800 }
801 name = a_name + std::to_string(cntr+1);
802 }
803
804 return 0;
805 }
806
807
808 template <typename T>
809 int
810 query_enumerate(std::string a_name, std::vector<T> &value, int number = 1)
811 {
812 value.clear();
813
814 //
815 // If only one is present with no subscript, then read
816 // it only and return.
817 //
818 std::string name = a_name;
819 if (this->contains(name))
820 {
821 for (int n = 0; n < number; n++)
822 {
823 T tmp;
824 this->query_required(name, tmp);
825 value.push_back(tmp);
826 }
827 return 0;
828 }
829
830 //
831 // Some logic to determine whether we are starting with zero
832 // (model0, model1, model2, ...)
833 // or one
834 // (model1, model2, model3, ...)
835 // since both are supported
836 //
837 int start = -1;
838 std::string name0 = a_name + std::to_string(0);
839 std::string name1 = a_name + std::to_string(1);
840 if (this->contains(name0.c_str()))
841 {
842 start = 0;
843 name = name0;
844 }
845 else if (this->contains(name1.c_str()))
846 {
847 start = 1;
848 name = name1;
849 }
850 else
851 {
852 Util::ParmParseException(INFO,full(name), "Enumerations must begin with 0 or 1");
853 }
854
855 //
856 // Iterate over items called (model0), model1, model2, etc
857 // until no more are found then exit.
858 //
859 for (int cntr = start; this->contains(name.c_str()); cntr++)
860 {
861 if (this->contains(name.c_str()))
862 {
863 T tmp;
864 this->query_required(name, tmp);
865 value.push_back(tmp);
866 }
867 name = a_name + std::to_string(cntr+1);
868 }
869
870 return 0;
871 }
872
873
874
875 int AnyUnusedInputs(bool inscopeonly = true, bool verbose = false)
876 {
877 int cnt = 0;
878 for (auto li = m_table->begin(), End = m_table->end(); li != End; ++li)
879 {
880 if (!li->second.m_count)
881 {
882 if (inscopeonly && getPrefix() != "")
883 {
884 if (li->first.rfind(getPrefix()+".",0) != std::string::npos)
885 {
886 if (verbose) Util::Warning(INFO,li->first);
887 cnt++;
888 }
889 }
890 else
891 {
892 if (verbose) Util::Warning(INFO,li->first);
893 cnt++;
894 }
895 }
896 }
897 return cnt;
898 }
899
900 std::vector<std::string> GetUnusedInputs()
901 {
902 std::vector<std::string> ret;
903 for (auto li = m_table->begin(), End = m_table->end(); li != End; ++li)
904 {
905 if (!li->second.m_count && li->first.rfind(getPrefix()+".",0) != std::string::npos)
906 {
907 ret.push_back(li->first);
908 }
909 }
910 return ret;
911 }
912
913 static int AllUnusedInputs()
914 {
915 ParmParse pp;
916 int cnt = 0;
917 for (auto li = pp.m_table->begin(), End = pp.m_table->end(); li != End; ++li)
918 {
919 if (!li->second.m_count)
920 {
921 Util::Warning(INFO,li->first);
922 cnt++;
923 }
924 }
925 return cnt;
926 }
927 std::string prefix ()
928 {
929 return getPrefix();
930 }
931 std::string full (std::string name)
932 {
933 std::string prefix = getPrefix();
934 if (prefix != "") return getPrefix() + "." + name;
935 else return name;
936 }
937
938
939 template<class T>
940 void queryclass(std::string name, T * value)
941 {
942 auto old_prefix = m_prefix;
943 try
944 {
945 if (old_prefix.empty()) m_prefix = name;
946 else m_prefix.append(".").append(name);
947 T::Parse(*value, *this);
948 std::vector<std::string> unused_inputs = GetUnusedInputs();
949 if (unused_inputs.size())
950 {
951 std::stringstream ss;
952 for (unsigned int i=0; i < unused_inputs.size(); i++)
953 ss << "\n\t" << unused_inputs[i];
954 Util::ParmParseException(INFO,name,"The following inputs were specified but not used",ss.str());
955 }
956 }
957 catch (...)
958 {
959 m_prefix = old_prefix;
961 }
962 m_prefix = old_prefix;
963 }
964 template<class T>
965 void queryclass(std::string name, T & value)
966 {
967 auto old_prefix = m_prefix;
968 try
969 {
970 if (old_prefix.empty()) m_prefix = name;
971 else m_prefix.append(".").append(name);
972 T::Parse(value, *this);
973 std::vector<std::string> unused_inputs = GetUnusedInputs();
974 if (unused_inputs.size())
975 {
976 std::stringstream ss;
977 for (unsigned int i=0; i < unused_inputs.size(); i++)
978 ss << "\n\t" << unused_inputs[i];
979 Util::ParmParseException(INFO,name,"The following inputs were specified but not used",ss.str());
980 }
981 }
982 catch (std::runtime_error &e)
983 {
984 Util::ParmParseException(INFO,full(name),e.what());
985 }
986 catch (...)
987 {
988 m_prefix = old_prefix;
990 }
991 m_prefix = old_prefix;
992 }
993
994 template<class T>
995 void queryclass(T * value)
996 {
997 try
998 {
999 T::Parse(*value, *this);
1000 }
1001 catch (std::runtime_error &e)
1002 {
1004 }
1005 catch (...)
1006 {
1008 }
1009 }
1010 template<class T>
1011 void queryclass(T & value)
1012 {
1013 try
1014 {
1015 T::Parse(value, *this);
1016 }
1017 catch (std::runtime_error &e)
1018 {
1020 }
1021 catch (...)
1022 {
1024 }
1025 }
1026
1027 //
1028 // Variadic template parsing operator to assign a pointer to
1029 // one of a set of possible class objects, then call that method's
1030 // Parse function.
1031 //
1032 // If there is more than one instantiating class, then type must be set.
1033 // Otherwise, no type is necessary.
1034 //
1035 template<typename... IC, typename... Args, typename PTRTYPE>
1036 void select (std::string name, PTRTYPE *& ic_eta, Args&&... args)
1037 {
1038 try
1039 {
1040 // if there is only one IC arg provided, we don't need to check the type - assume that
1041 // it is the default.
1042 if constexpr (sizeof...(IC) == 0)
1043 {
1044 using first_IC = std::tuple_element_t<0, std::tuple<IC...>>;
1045 ic_eta = new first_IC(std::forward<Args>(args)..., (*this), name + "." + std::string(first_IC::name));
1046 }
1047 // otherwise, check the type.
1048 else
1049 {
1050 std::string type = "";
1051 this->query_required(name + ".type", type);
1052 bool matched = (( type == IC::name
1053 ? (ic_eta = new IC(std::forward<Args>(args)..., (*this), name + "." + std::string(IC::name))),
1054 true
1055 : false) || ...);
1056 if (!matched)
1057 Util::ParmParseException(INFO,full(name), type, " not a valid type for ", name);
1058 }
1059 }
1060 catch (std::runtime_error &e)
1061 {
1063 }
1064 catch (...)
1065 {
1067 }
1068 }
1069
1070 //
1071 // Identical to the above, except sets the type automatically to the
1072 // firs specified
1073 //
1074 template<typename FirstIC, typename... IC, typename... Args, typename PTRTYPE>
1075 void select_default (std::string name, PTRTYPE *& ic_eta, Args&&... args)
1076 {
1077 std::string type = "";
1078
1079 this->query_default(name + ".type", type, FirstIC::name);
1080
1081 bool matched =
1082 (( type == FirstIC::name
1083 ? (ic_eta = new FirstIC(std::forward<Args>(args)..., (*this), name + "." + std::string(FirstIC::name))),
1084 true : false))
1085 ||
1086 (( type == IC::name
1087 ? (ic_eta = new IC(std::forward<Args>(args)..., (*this), name + "." + std::string(IC::name))),
1088 true : false) || ...);
1089
1090
1091 if (!matched)
1092 Util::ParmParseException(INFO,full(name), type," not a valid type for ",name);
1093 }
1094
1095
1096 //
1097 //
1098 template<typename... IC, typename... Args, typename PTRTYPE>
1099 void select_enumerate (std::string a_name, std::vector<PTRTYPE*> & value, Args&&... args)
1100 {
1101
1102 value.clear();
1103
1104 //
1105 // If only one is present with no subscript, then read
1106 // it only and return.
1107 //
1108 std::string name = a_name;
1109 if (this->contains(name))
1110 {
1111 PTRTYPE *tmp;
1112 this->select<IC...>(a_name, tmp, args...);
1113 value.push_back(tmp);
1114 return;
1115 }
1116
1117 //
1118 // Some logic to determine whether we are starting with zero
1119 // (model0, model1, model2, ...)
1120 // or one
1121 // (model1, model2, model3, ...)
1122 // since both are supported
1123 //
1124 int start = -1;
1125 std::string name0 = a_name + std::to_string(0);
1126 std::string name1 = a_name + std::to_string(1);
1127 if (this->contains(name0.c_str()))
1128 {
1129 start = 0;
1130 name = name0;
1131 }
1132 else if (this->contains(name1.c_str()))
1133 {
1134 start = 1;
1135 name = name1;
1136 }
1137 else
1138 {
1139 Util::ParmParseException(INFO,full(name), "Enumerations must begin with 0 or 1");
1140 }
1141
1142 //
1143 // Iterate over items called (model0), model1, model2, etc
1144 // until no more are found then exit.
1145 //
1146 for (int cntr = start; this->contains(name.c_str()); cntr++)
1147 {
1148 if (this->contains(name.c_str()))
1149 {
1150 PTRTYPE *tmp;
1151 this->select<IC...>(name, tmp, args...);
1152 value.push_back(tmp);
1153 }
1154 name = a_name + std::to_string(cntr+1);
1155 }
1156 }
1157
1158
1159
1160 //
1161 // Similar to select but specialized for main functions
1162 //
1163 template<typename... INTEGRATOR, typename... Args, typename PTRTYPE>
1164 void select_main (PTRTYPE *& ic_eta, Args&&... args)
1165 {
1166 std::string type = "";
1167
1168 this->query_required("alamo.program", type);
1169
1170 bool matched = ((type == INTEGRATOR::name
1171 ? (ic_eta = new INTEGRATOR(std::forward<Args>(args)..., (*this))),
1172 true
1173 : false) || ...);
1174 if (!matched)
1175 Util::ParmParseException(INFO,getPrefix(),type," not a valid type for ",type);
1176 }
1177
1178 //
1179 // Similar to select_main but works for one function only
1180 // and doesn't require a type specifier.
1181 //
1182
1183 // with variadic arguments
1184 template<typename INTEGRATOR, typename Args, typename PTRTYPE>
1185 void select_only (PTRTYPE *& ic_eta, Args&& args)
1186 {
1187 ic_eta = new INTEGRATOR(std::forward<Args>(args), (*this));
1188 }
1189 // without variadic arguments
1190 template<typename INTEGRATOR, typename PTRTYPE>
1191 void select_only (PTRTYPE *& ic_eta)
1192 {
1193 ic_eta = new INTEGRATOR((*this));
1194 }
1195
1196
1197 //
1198 // functionally simlar to other kinds of select, execpt works on
1199 // template-based static dispatch.
1200 //
1201
1202 template <typename... OBJ, typename CLASS>
1203 void select(std::string name, CLASS& value)
1204 {
1205 pushPrefix(name);
1206 static_polymorphism_parser<CLASS, 0, OBJ...>(value);
1207 popPrefix();
1208 }
1209
1210private:
1211 //
1212 // This function is a virtual "swtich / case" block for static
1213 // dispatch. It works on a faux-virtual class "CLASS" that must
1214 // contain a tuple of "obj" with each "obj" being a derived type.
1215 // Recursion is used to unroll the list, identify the correct class
1216 // based on "name/type", set the "selected" index, then call the
1217 // appropriate class' Parse function.
1218 //
1219 // This is only for use by the "select" functions.
1220 //
1221 template <typename CLASS, int N, typename... OBJ>
1223 {
1224 if constexpr (N == 0)
1225 {
1226 std::string type;
1227 query_default("type",type,value.names[0]);
1228
1229 for (unsigned int i = 0; i < sizeof...(OBJ); i++)
1230 if (type == value.names[i])
1231 value.selected = i;
1232
1233 if (value.selected < 0)
1235 "Error reading " + getPrefix() +
1236 ", invalid type " + type);
1237
1238
1239 pushPrefix(type);
1240 }
1241
1242 if constexpr (N < sizeof...(OBJ))
1243 {
1244 if (value.selected == N)
1245 {
1246 std::get<N>(value.obj).Parse(std::get<N>(value.obj), *this);
1247 popPrefix();
1248 return;
1249 }
1250 else
1251 return static_polymorphism_parser<CLASS, N+1, OBJ...>(value);
1252 }
1253 else Util::Abort(INFO);
1254 }
1255
1256public:
1257
1258 template <int N>
1259 void query_exactly( std::vector<std::string> names, std::pair<std::string, Set::Scalar> values[N],
1260 std::vector<Unit> units = std::vector<Unit>())
1261 {
1262 try
1263 {
1264 Util::AssertException( INFO,TEST(units.size() == 0 || units.size() == names.size()),
1265 "# of units must be 0, 1, or ", names.size(), " but got ", units.size());
1266
1267 int cnt = 0;
1268 std::vector<std::string> read;
1269 for (unsigned int n = 0; n < names.size(); n++)
1270 {
1271 if (amrex::ParmParse::contains(names[n].c_str()))
1272 {
1273 read.push_back(names[n]);
1274 cnt++;
1275 }
1276 }
1277 Util::AssertException( INFO, TEST(cnt == N),
1278 " Incorrect number of values specified: only ", N,
1279 " values are allowed, but received ",
1280 Util::String::Join(read,", "));
1281
1282
1283 cnt = 0;
1284 for (unsigned int n = 0; n < names.size(); n++)
1285 {
1286 if (amrex::ParmParse::contains(names[n].c_str()))
1287 {
1288 values[cnt].first = names[n];
1289
1290 if (units.size() == 0)
1291 query_required(names[n],values[cnt].second);
1292 else if (units.size() == 1)
1293 query_required(names[n],values[cnt].second,units[0]);
1294 else
1295 query_required(names[n],values[cnt].second,units[n]);
1296 cnt++;
1297 }
1298 }
1299 }
1300 catch(...)
1301 {
1302 std::string names_str = "[";
1303 for (unsigned int i = 0; i < names.size(); i++)
1304 {
1305 names_str += full(names[i]);
1306 if (i < names.size()-1) names_str += ", ";
1307 }
1308 names_str += "]";
1309 Util::ParmParseException(INFO,names_str);
1310 }
1311 }
1312
1313
1314
1315
1316};
1317}
1318#endif
#define TEST(x)
Definition Util.H:22
#define INFO
Definition Util.H:21
int queryarr_default(std::string name, std::vector< double > &value, std::vector< std::string > defaultvalue, Unit unit)
Definition ParmParse.H:724
bool contains(std::string name)
Definition ParmParse.H:173
int queryunit(std::string name, Unit &value)
Definition ParmParse.H:192
int queryarr_default(std::string name, std::vector< std::string > &value, std::vector< std::string > defaultvalue)
Definition ParmParse.H:660
int queryarr_required(std::string name, std::vector< Set::Scalar > &value, Unit unit=Unit::Less())
Definition ParmParse.H:652
int queryarr(std::string name, std::vector< T > &value)
Definition ParmParse.H:535
void forbid(std::string name, std::string explanation)
Definition ParmParse.H:160
void select(std::string name, CLASS &value)
Definition ParmParse.H:1203
int query_enumerate(std::string a_name, std::vector< T > &value, int number=1)
Definition ParmParse.H:810
int queryarr(std::string name, std::vector< Set::Scalar > &value, Unit unit=Unit::Less())
Definition ParmParse.H:547
void pushPrefix(const std::string prefix)
Definition ParmParse.H:142
int query_validate(std::string name, std::string &value, std::vector< const char * > possiblecharvals, bool firstbydefault)
Definition ParmParse.H:379
int query_file(std::string name, std::string &value)
Definition ParmParse.H:528
int queryarr(std::string name, Set::Vector &value, Unit unit=Unit::Less())
Definition ParmParse.H:584
int query_file(std::string name, std::string &value, bool copyfile, bool checkfile)
Definition ParmParse.H:486
int AnyUnusedInputs(bool inscopeonly=true, bool verbose=false)
Definition ParmParse.H:875
int queryarr(std::string name, Set::Matrix &value, Unit unit=Unit::Less())
Definition ParmParse.H:605
std::vector< std::string > GetUnusedInputs()
Definition ParmParse.H:900
void queryclass(std::string name, T &value)
Definition ParmParse.H:965
std::string getPrefix() const
Definition ParmParse.H:136
static bool checked_for_input_files
Definition ParmParse.H:131
std::string prefix()
Definition ParmParse.H:927
void select(std::string name, PTRTYPE *&ic_eta, Args &&... args)
Definition ParmParse.H:1036
void queryclass(std::string name, T *value)
Definition ParmParse.H:940
int queryclass_enumerate(std::string a_name, std::vector< T > &value, int number=1)
Definition ParmParse.H:744
int query_required(std::string name, T &value)
Definition ParmParse.H:249
int queryarr_default(std::string name, Set::Matrix &value, Set::Matrix defaultvalue)
Definition ParmParse.H:688
int query_default(std::string name, T &value, std::string defaultvalue, const Unit type)
Definition ParmParse.H:315
void Define()
Definition ParmParse.H:118
void select_default(std::string name, PTRTYPE *&ic_eta, Args &&... args)
Definition ParmParse.H:1075
int queryarr_default(std::string name, Set::Vector &value, Set::Vector defaultvalue)
Definition ParmParse.H:669
int queryunit(std::string name, Unit &value, const Unit type)
Definition ParmParse.H:213
int query_default(std::string name, int &value, bool defaultvalue)
Definition ParmParse.H:465
int query_file(std::string name, std::string &value, bool copyfile)
Definition ParmParse.H:524
void select_enumerate(std::string a_name, std::vector< PTRTYPE * > &value, Args &&... args)
Definition ParmParse.H:1099
void queryclass(T &value)
Definition ParmParse.H:1011
static int AllUnusedInputs()
Definition ParmParse.H:913
int query_validate(std::string name, std::string &value, std::vector< const char * > possiblecharvals)
Definition ParmParse.H:429
void queryclass(T *value)
Definition ParmParse.H:995
int queryarr_required(std::string name, std::vector< T > &value)
Definition ParmParse.H:643
int query_required(std::string name, T &value, const Unit type)
Definition ParmParse.H:271
void popPrefix()
Definition ParmParse.H:150
void static_polymorphism_parser(CLASS &value)
Definition ParmParse.H:1222
void select_only(PTRTYPE *&ic_eta, Args &&args)
Definition ParmParse.H:1185
void select_main(PTRTYPE *&ic_eta, Args &&... args)
Definition ParmParse.H:1164
int queryunit(std::string name, Set::Scalar &value, const Unit type)
Definition ParmParse.H:232
int query_default(std::string name, T &value, T defaultvalue)
Definition ParmParse.H:293
void select_only(PTRTYPE *&ic_eta)
Definition ParmParse.H:1191
void ignore(std::string name)
Definition ParmParse.H:137
std::string full(std::string name)
Definition ParmParse.H:931
int query_validate(std::string name, int &value, std::vector< int > possibleintvals)
Definition ParmParse.H:336
int queryarr_default(std::string name, std::vector< double > &value, std::vector< double > defaultvalue)
Definition ParmParse.H:707
void query_exactly(std::vector< std::string > names, std::pair< std::string, Set::Scalar > values[N], std::vector< Unit > units=std::vector< Unit >())
Definition ParmParse.H:1259
int query_default(std::string name, std::string &value, const char *defaultvalue)
Definition ParmParse.H:448
ParmParse(std::string arg)
Definition ParmParse.H:134
Initialize a spherical inclusion.
Definition BMP.H:20
amrex::Real Scalar
Definition Base.H:18
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, 1 > Vector
Definition Base.H:19
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, AMREX_SPACEDIM > Matrix
Definition Base.H:22
AMREX_FORCE_INLINE std::string Join(const std::vector< std::string > &vec, std::string separator="_")
Definition String.H:83
void DebugMessage(std::string, std::string, int, Args const &...)
Definition Util.H:173
AMREX_FORCE_INLINE void AssertException(std::string file, std::string func, int line, std::string smt, bool pass, Args const &... args)
Definition Util.H:251
void Abort(const char *msg)
Definition Util.cpp:240
void CopyFileToOutputDir(std::string a_path, bool fullpath, std::string prefix)
Definition Util.cpp:54
void Warning(std::string file, std::string func, int line, Args const &... args)
Definition Util.H:199
void Message(std::string file, std::string func, int line, Args const &... args)
Definition Util.H:126
void ParmParseException(std::string file, std::string func, int line, std::string fullname, Args const &... args)
Definition Util.H:281
void Exception(std::string file, std::string func, int line, Args const &... args)
Definition Util.H:223
Definition Unit.H:20
bool isType(const Unit &test) const
Definition Unit.H:421
std::string normalized_unitstring() const
Definition Unit.H:478
static Unit Parse(double val, std::string unitstring, bool verbose=false)
Definition Unit.H:266
double normalized_value() const
Definition Unit.H:469
static Unit Less()
Definition Unit.H:193