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 value = possibleintvals[0];
344
345 // get the read value (if it exists)
346 int retval = query(name.c_str(),value);
347
348 // check to make sure the read value matches one of the inpus
349 bool ok = false;
350 for (unsigned int i = 0; i < possibleintvals.size(); i++)
351 {
352 if (value == possibleintvals[i]) ok = true;
353 }
354
355 if (ok) return retval;
356
357 std::stringstream ss;
358 ss << possibleintvals[0];
359 for (unsigned int i = 1; i < possibleintvals.size(); i++)
360 ss << "," << possibleintvals[i];
361
362 Util::ParmParseException(INFO,full(name),"' expected [", ss.str(), "] but got ", value);
363 }
364 catch (std::runtime_error & e)
365 {
366 Util::ParmParseException(INFO,full(name),e.what());
367 }
368 catch (...)
369 {
371 }
372 return -1;
373 }
374
375
376 int query_validate( std::string name, std::string & value, std::vector<const char *> possiblecharvals, bool firstbydefault)
377 {
378 try
379 {
380 // if not using default values, then the input must be specified
381 if (!firstbydefault)
382 {
383 if (!contains(name.c_str()))
384 {
385 Util::ParmParseException(INFO,full(name),"required value for ",full(name)," missing");
386 }
387 }
388
389 // set default value
390 value = std::string(possiblecharvals[0]);
391
392 // get the read value (if it exists)
393 int retval = amrex::ParmParse::query(name.c_str(),value);
394
395 // check to make sure the read value matches one of the inpus
396 bool ok = false;
397 for (unsigned int i = 0; i < possiblecharvals.size(); i++)
398 {
399 if (value == std::string(possiblecharvals[i])) ok = true;
400 }
401
402 if (ok) return retval;
403
404 std::stringstream ss;
405 ss << possiblecharvals[0];
406 for (unsigned int i = 1; i < possiblecharvals.size(); i++)
407 ss << "," << possiblecharvals[i];
408
409 Util::ParmParseException(INFO,full(name),"' expected [", ss.str(), "] but got ", value);
410 }
411 catch (std::runtime_error & e)
412 {
413 Util::ParmParseException(INFO,full(name),e.what());
414 }
415 catch (...)
416 {
418 }
419
420 return -1;
421 }
422
423 int query_validate( std::string name, std::string & value, std::vector<const char *> possiblecharvals)
424 {
425 try
426 {
427 return query_validate(name,value,possiblecharvals,true);
428 }
429 catch (std::runtime_error & e)
430 {
431 Util::ParmParseException(INFO,full(name),e.what());
432 }
433 catch (...)
434 {
436 }
437 return -1;
438 }
439
440
441 // special case for strings
442 int query_default( std::string name, std::string & value, const char *defaultvalue)
443 {
444 try
445 {
446 return query_default(name, value, std::string(defaultvalue));
447 }
448 catch (std::runtime_error & e)
449 {
450 Util::ParmParseException(INFO,full(name),e.what());
451 }
452 catch (...)
453 {
455 }
456 return -1;
457 }
458 // special case for bools
459 int query_default( std::string name, int & value, bool defaultvalue)
460 {
461 try
462 {
463 int defaultint = 0;
464 if (defaultvalue) defaultint = 1;
465 return query_default(name, value, defaultint);
466 }
467 catch (std::runtime_error & e)
468 {
469 Util::ParmParseException(INFO,full(name),e.what());
470 }
471 catch (...)
472 {
474 }
475 return -1;
476 }
477
478
479 // validate filenames
480 int query_file( std::string name, std::string & value, bool copyfile, bool checkfile)
481 {
482 try
483 {
484 if (!contains(name.c_str()))
485 {
486 Util::ParmParseException(INFO,full(name),full(name)," must be specified");
487 }
488
489 int retval = query(name.c_str(),value);
490
491 if (amrex::ParallelDescriptor::IOProcessor())
492 {
493 if ( checkfile && ! std::filesystem::exists(value))
494 {
495 Util::ParmParseException(INFO,full(name),full(name)," does not exist");
496 }
497 if ( checkfile && !std::filesystem::is_regular_file(value))
498 {
499 Util::ParmParseException(INFO,full(name),full(name)," is not a regular file");
500 }
501 if ( copyfile )
502 {
503 Util::CopyFileToOutputDir(value, true, full(name));
504 }
505 }
506 return retval;
507 }
508 catch (std::runtime_error & e)
509 {
510 Util::ParmParseException(INFO,full(name),e.what());
511 }
512 catch (...)
513 {
515 }
516 return -1;
517 }
518 int query_file( std::string name, std::string & value, bool copyfile)
519 {
520 return query_file(name,value,copyfile,true);
521 }
522 int query_file( std::string name, std::string & value)
523 {
524 return query_file(name,value,true,true);
525 }
526
527
528 template<typename T>
529 int queryarr( std::string name, std::vector<T> & value)
530 {
531 try
532 {
533 return amrex::ParmParse::queryarr(name.c_str(),value);
534 }
535 catch (...)
536 {
538 }
539 return -1;
540 }
541 int queryarr( std::string name, std::vector<Set::Scalar> & value, Unit unit = Unit::Less())
542 {
543 try
544 {
545 if (unit.isType(Unit::Less()))
546 {
547 return amrex::ParmParse::queryarr(name.c_str(),value);
548 }
549 else
550 {
551 value.clear();
552 std::vector<std::string> valstrings;
553 int retval = amrex::ParmParse::queryarr(name.c_str(), valstrings);
554 for (unsigned int i = 0; i < valstrings.size(); i++)
555 {
556 Unit unitvalue = Unit::Parse(valstrings[i]);
557 Util::DebugMessage(INFO,full(name),": ",valstrings[i]," ==> ",unitvalue);
558
559 if (!unitvalue.isType(unit) && !unitvalue.isType(Unit::Less()))
560 {
561 Util::Exception(INFO,"value specified had wrong units:", valstrings[i]);
562 }
563 value.push_back(unitvalue.normalized_value());
564 }
565 return retval;
566 }
567 }
568 catch (std::runtime_error &e)
569 {
570 Util::ParmParseException(INFO,full(name), e.what());
571 }
572 catch (...)
573 {
575 }
576 return -1;
577 }
578 int queryarr( std::string name, Set::Vector & value, Unit unit = Unit::Less())
579 {
580 try
581 {
582 std::vector<Set::Scalar> vals;
583 queryarr(name.c_str(), vals, unit);
584 if (vals.size() < AMREX_SPACEDIM)
585 {
587 " requires at least ", AMREX_SPACEDIM,
588 " arguments, got ",vals.size());
589 }
590 for (int i = 0; i < AMREX_SPACEDIM; i++) value(i) = vals[i];
591 return 0;
592 }
593 catch(...)
594 {
596 }
597 return -1;
598 }
599 int queryarr( std::string name, Set::Matrix & value, Unit unit = Unit::Less())
600 {
601 std::vector<Set::Scalar> vals;
602 queryarr(name.c_str(), vals,unit);
603 if (vals.size() == 9)
604 {
605#if AMREX_SPACEDIM==2
606 Util::Warning(INFO, "Reading a 3D matrix (",full(name),")into a 2D code - some values will be ignored.");
607 value(0,0) = vals[0]; value(0,1)= vals[1];
608 value(1,0) = vals[3]; value(1,1)= vals[4];
609#endif
610#if AMREX_SPACEDIM==3
611 value(0,0) = vals[0]; value(0,1)= vals[1]; value(0,2)= vals[2];
612 value(1,0) = vals[3]; value(1,1)= vals[4]; value(1,2)= vals[5];
613 value(2,0) = vals[6]; value(2,1)= vals[7]; value(2,2)= vals[8];
614#endif
615 }
616 else if (vals.size() == 4)
617 {
618#if AMREX_SPACEDIM==2
619 value(0,0) = vals[0]; value(0,1)= vals[1];
620 value(1,0) = vals[2]; value(1,1)= vals[3];
621#endif
622#if AMREX_SPACEDIM==3
623 Util::Warning(INFO,"Reading a 2D matrix (",full(name),")into a 3D code - remaining values will be set to zero.");
624 value(0,0) = vals[0]; value(0,1)= vals[1]; value(0,2)= 0.0;
625 value(1,0) = vals[2]; value(1,1)= vals[3]; value(1,2)= 0.0;
626 value(2,0) = 0.0; value(2,1)= 0.0; value(2,2)= 0.0;
627#endif
628 }
629 else
630 {
631 Util::ParmParseException(INFO,full(name),full(name)," needs either 4 or 9 components, but got ",vals.size());
632 }
633 return 0;
634 }
635
636 template<typename T>
637 int queryarr_required( std::string name, std::vector<T> & value)
638 {
639 if (!contains(name.c_str()))
640 {
641 Util::ParmParseException(INFO,full(name),"required value for ",full(name)," missing");
642 }
643 return queryarr<T>(name,value);
644 }
645
646 int queryarr_required( std::string name, std::vector<Set::Scalar> & value, Unit unit = Unit::Less())
647 {
648 if (!contains(name.c_str()))
649 {
650 Util::ParmParseException(INFO,full(name),"required value for ",full(name)," missing");
651 }
652 return queryarr(name,value,unit);
653 }
654 int queryarr_default( std::string name, std::vector<std::string> & value, std::vector<std::string> defaultvalue)
655 {
656 if (!contains(name.c_str()))
657 {
658 addarr(name.c_str(),defaultvalue);
659 }
660 return amrex::ParmParse::queryarr(name.c_str(),value);
661 }
662
663 int queryarr_default( std::string name, Set::Vector & value, Set::Vector defaultvalue)
664 {
665 try
666 {
667 if (!contains(name.c_str()))
668 {
669 add(name.c_str(),Util::String::Join(defaultvalue));
670 value = defaultvalue;
671 return 0;
672 }
673 return queryarr(name.c_str(),value);
674 }
675 catch (...)
676 {
678 }
679 return -1;
680 }
681
682 int queryarr_default( std::string name, Set::Matrix & value, Set::Matrix defaultvalue)
683 {
684 try
685 {
686 if (!contains(name.c_str()))
687 {
688 add(name.c_str(),Util::String::Join(defaultvalue));
689 value = defaultvalue;
690 return 0;
691 }
692 return queryarr(name.c_str(),value);
693 }
694 catch (...)
695 {
697 }
698 return -1;
699 }
700
701 int queryarr_default( std::string name, std::vector<double> & value, std::vector<double> defaultvalue)
702 {
703 try
704 {
705 if (!contains(name.c_str()))
706 {
707 addarr(name.c_str(),defaultvalue);
708 }
709 return queryarr(name.c_str(),value);
710 }
711 catch (...)
712 {
714 }
715 return -1;
716 }
717
718 int queryarr_default( std::string name, std::vector<double> & value, std::vector<std::string> defaultvalue, Unit unit)
719 {
720 try
721 {
722 if (!contains(name.c_str()))
723 {
724 addarr(name.c_str(),defaultvalue);
725 }
726 return queryarr(name,value, unit);
727 }
728 catch (...)
729 {
731 }
732 return -1;
733 }
734
735
736 template <typename T>
737 int
738 queryclass_enumerate(std::string a_name, std::vector<T> &value, int number = 1)
739 {
740 value.clear();
741
742 //
743 // If only one is present with no subscript, then read
744 // it only and return.
745 //
746 std::string name = a_name;
747 if (this->contains(name))
748 {
749 for (int n = 0; n < number; n++)
750 {
751 T tmp;
752 this->queryclass<T>(name, tmp);
753 value.push_back(tmp);
754 }
755 return 0;
756 }
757
758 //
759 // Some logic to determine whether we are starting with zero
760 // (model0, model1, model2, ...)
761 // or one
762 // (model1, model2, model3, ...)
763 // since both are supported
764 //
765 int start = -1;
766 std::string name0 = a_name + std::to_string(0);
767 std::string name1 = a_name + std::to_string(1);
768 if (this->contains(name0.c_str()))
769 {
770 start = 0;
771 name = name0;
772 }
773 else if (this->contains(name1.c_str()))
774 {
775 start = 1;
776 name = name1;
777 }
778 else
779 {
780 Util::ParmParseException(INFO,full(name), "Enumerations must begin with 0 or 1");
781 }
782
783 //
784 // Iterate over items called (model0), model1, model2, etc
785 // until no more are found then exit.
786 //
787 for (int cntr = start; this->contains(name.c_str()); cntr++)
788 {
789 if (this->contains(name.c_str()))
790 {
791 T tmp;
792 this->queryclass<T>(name, tmp);
793 value.push_back(tmp);
794 }
795 name = a_name + std::to_string(cntr+1);
796 }
797
798 return 0;
799 }
800
801
802 template <typename T>
803 int
804 query_enumerate(std::string a_name, std::vector<T> &value, int number = 1)
805 {
806 value.clear();
807
808 //
809 // If only one is present with no subscript, then read
810 // it only and return.
811 //
812 std::string name = a_name;
813 if (this->contains(name))
814 {
815 for (int n = 0; n < number; n++)
816 {
817 T tmp;
818 this->query_required(name, tmp);
819 value.push_back(tmp);
820 }
821 return 0;
822 }
823
824 //
825 // Some logic to determine whether we are starting with zero
826 // (model0, model1, model2, ...)
827 // or one
828 // (model1, model2, model3, ...)
829 // since both are supported
830 //
831 int start = -1;
832 std::string name0 = a_name + std::to_string(0);
833 std::string name1 = a_name + std::to_string(1);
834 if (this->contains(name0.c_str()))
835 {
836 start = 0;
837 name = name0;
838 }
839 else if (this->contains(name1.c_str()))
840 {
841 start = 1;
842 name = name1;
843 }
844 else
845 {
846 Util::ParmParseException(INFO,full(name), "Enumerations must begin with 0 or 1");
847 }
848
849 //
850 // Iterate over items called (model0), model1, model2, etc
851 // until no more are found then exit.
852 //
853 for (int cntr = start; this->contains(name.c_str()); cntr++)
854 {
855 if (this->contains(name.c_str()))
856 {
857 T tmp;
858 this->query_required(name, tmp);
859 value.push_back(tmp);
860 }
861 name = a_name + std::to_string(cntr+1);
862 }
863
864 return 0;
865 }
866
867
868
869 int AnyUnusedInputs(bool inscopeonly = true, bool verbose = false)
870 {
871 int cnt = 0;
872 for (auto li = m_table->begin(), End = m_table->end(); li != End; ++li)
873 {
874 if (!li->second.m_count)
875 {
876 if (inscopeonly && getPrefix() != "")
877 {
878 if (li->first.rfind(getPrefix()+".",0) != std::string::npos)
879 {
880 if (verbose) Util::Warning(INFO,li->first);
881 cnt++;
882 }
883 }
884 else
885 {
886 if (verbose) Util::Warning(INFO,li->first);
887 cnt++;
888 }
889 }
890 }
891 return cnt;
892 }
893
894 std::vector<std::string> GetUnusedInputs()
895 {
896 std::vector<std::string> ret;
897 for (auto li = m_table->begin(), End = m_table->end(); li != End; ++li)
898 {
899 if (!li->second.m_count && li->first.rfind(getPrefix()+".",0) != std::string::npos)
900 {
901 ret.push_back(li->first);
902 }
903 }
904 return ret;
905 }
906
907 static int AllUnusedInputs()
908 {
909 ParmParse pp;
910 int cnt = 0;
911 for (auto li = pp.m_table->begin(), End = pp.m_table->end(); li != End; ++li)
912 {
913 if (!li->second.m_count)
914 {
915 Util::Warning(INFO,li->first);
916 cnt++;
917 }
918 }
919 return cnt;
920 }
921 std::string prefix ()
922 {
923 return getPrefix();
924 }
925 std::string full (std::string name)
926 {
927 std::string prefix = getPrefix();
928 if (prefix != "") return getPrefix() + "." + name;
929 else return name;
930 }
931
932
933 template<class T>
934 void queryclass(std::string name, T * value)
935 {
936 auto old_prefix = m_prefix;
937 try
938 {
939 if (old_prefix.empty()) m_prefix = name;
940 else m_prefix.append(".").append(name);
941 T::Parse(*value, *this);
942 std::vector<std::string> unused_inputs = GetUnusedInputs();
943 if (unused_inputs.size())
944 {
945 std::stringstream ss;
946 for (unsigned int i=0; i < unused_inputs.size(); i++)
947 ss << "\n\t" << unused_inputs[i];
948 Util::ParmParseException(INFO,name,"The following inputs were specified but not used",ss.str());
949 }
950 }
951 catch (...)
952 {
953 m_prefix = old_prefix;
955 }
956 m_prefix = old_prefix;
957 }
958 template<class T>
959 void queryclass(std::string name, T & value)
960 {
961 auto old_prefix = m_prefix;
962 try
963 {
964 if (old_prefix.empty()) m_prefix = name;
965 else m_prefix.append(".").append(name);
966 T::Parse(value, *this);
967 std::vector<std::string> unused_inputs = GetUnusedInputs();
968 if (unused_inputs.size())
969 {
970 std::stringstream ss;
971 for (unsigned int i=0; i < unused_inputs.size(); i++)
972 ss << "\n\t" << unused_inputs[i];
973 Util::ParmParseException(INFO,name,"The following inputs were specified but not used",ss.str());
974 }
975 }
976 catch (std::runtime_error &e)
977 {
978 Util::ParmParseException(INFO,full(name),e.what());
979 }
980 catch (...)
981 {
982 m_prefix = old_prefix;
984 }
985 m_prefix = old_prefix;
986 }
987
988 template<class T>
989 void queryclass(T * value)
990 {
991 try
992 {
993 T::Parse(*value, *this);
994 }
995 catch (std::runtime_error &e)
996 {
998 }
999 catch (...)
1000 {
1002 }
1003 }
1004 template<class T>
1005 void queryclass(T & value)
1006 {
1007 try
1008 {
1009 T::Parse(value, *this);
1010 }
1011 catch (std::runtime_error &e)
1012 {
1014 }
1015 catch (...)
1016 {
1018 }
1019 }
1020
1021 //
1022 // Variadic template parsing operator to assign a pointer to
1023 // one of a set of possible class objects, then call that method's
1024 // Parse function.
1025 //
1026 // If there is more than one instantiating class, then type must be set.
1027 // Otherwise, no type is necessary.
1028 //
1029 template<typename... IC, typename... Args, typename PTRTYPE>
1030 void select (std::string name, PTRTYPE *& ic_eta, Args&&... args)
1031 {
1032 try
1033 {
1034 // if there is only one IC arg provided, we don't need to check the type - assume that
1035 // it is the default.
1036 if constexpr (sizeof...(IC) == 0)
1037 {
1038 using first_IC = std::tuple_element_t<0, std::tuple<IC...>>;
1039 ic_eta = new first_IC(std::forward<Args>(args)..., (*this), name + "." + std::string(first_IC::name));
1040 }
1041 // otherwise, check the type.
1042 else
1043 {
1044 std::string type = "";
1045 this->query_required(name + ".type", type);
1046 bool matched = (( type == IC::name
1047 ? (ic_eta = new IC(std::forward<Args>(args)..., (*this), name + "." + std::string(IC::name))),
1048 true
1049 : false) || ...);
1050 if (!matched)
1051 Util::ParmParseException(INFO,full(name), type, " not a valid type for ", name);
1052 }
1053 }
1054 catch (std::runtime_error &e)
1055 {
1057 }
1058 catch (...)
1059 {
1061 }
1062 }
1063
1064 //
1065 // Identical to the above, except sets the type automatically to the
1066 // firs specified
1067 //
1068 template<typename FirstIC, typename... IC, typename... Args, typename PTRTYPE>
1069 void select_default (std::string name, PTRTYPE *& ic_eta, Args&&... args)
1070 {
1071 std::string type = "";
1072
1073 this->query_default(name + ".type", type, FirstIC::name);
1074
1075 bool matched =
1076 (( type == FirstIC::name
1077 ? (ic_eta = new FirstIC(std::forward<Args>(args)..., (*this), name + "." + std::string(FirstIC::name))),
1078 true : false))
1079 ||
1080 (( type == IC::name
1081 ? (ic_eta = new IC(std::forward<Args>(args)..., (*this), name + "." + std::string(IC::name))),
1082 true : false) || ...);
1083
1084
1085 if (!matched)
1086 Util::ParmParseException(INFO,full(name), type," not a valid type for ",name);
1087 }
1088
1089
1090 //
1091 //
1092 template<typename... IC, typename... Args, typename PTRTYPE>
1093 void select_enumerate (std::string a_name, std::vector<PTRTYPE*> & value, Args&&... args)
1094 {
1095
1096 value.clear();
1097
1098 //
1099 // If only one is present with no subscript, then read
1100 // it only and return.
1101 //
1102 std::string name = a_name;
1103 if (this->contains(name))
1104 {
1105 PTRTYPE *tmp;
1106 this->select<IC...>(a_name, tmp, args...);
1107 value.push_back(tmp);
1108 return;
1109 }
1110
1111 //
1112 // Some logic to determine whether we are starting with zero
1113 // (model0, model1, model2, ...)
1114 // or one
1115 // (model1, model2, model3, ...)
1116 // since both are supported
1117 //
1118 int start = -1;
1119 std::string name0 = a_name + std::to_string(0);
1120 std::string name1 = a_name + std::to_string(1);
1121 if (this->contains(name0.c_str()))
1122 {
1123 start = 0;
1124 name = name0;
1125 }
1126 else if (this->contains(name1.c_str()))
1127 {
1128 start = 1;
1129 name = name1;
1130 }
1131 else
1132 {
1133 Util::ParmParseException(INFO,full(name), "Enumerations must begin with 0 or 1");
1134 }
1135
1136 //
1137 // Iterate over items called (model0), model1, model2, etc
1138 // until no more are found then exit.
1139 //
1140 for (int cntr = start; this->contains(name.c_str()); cntr++)
1141 {
1142 if (this->contains(name.c_str()))
1143 {
1144 PTRTYPE *tmp;
1145 this->select<IC...>(name, tmp, args...);
1146 value.push_back(tmp);
1147 }
1148 name = a_name + std::to_string(cntr+1);
1149 }
1150 }
1151
1152
1153
1154 //
1155 // Similar to select but specialized for main functions
1156 //
1157 template<typename... INTEGRATOR, typename... Args, typename PTRTYPE>
1158 void select_main (PTRTYPE *& ic_eta, Args&&... args)
1159 {
1160 std::string type = "";
1161
1162 this->query_required("alamo.program", type);
1163
1164 bool matched = ((type == INTEGRATOR::name
1165 ? (ic_eta = new INTEGRATOR(std::forward<Args>(args)..., (*this))),
1166 true
1167 : false) || ...);
1168 if (!matched)
1169 Util::ParmParseException(INFO,getPrefix(),type," not a valid type for ",type);
1170 }
1171
1172 //
1173 // Similar to select_main but works for one function only
1174 // and doesn't require a type specifier.
1175 //
1176
1177 // with variadic arguments
1178 template<typename INTEGRATOR, typename Args, typename PTRTYPE>
1179 void select_only (PTRTYPE *& ic_eta, Args&& args)
1180 {
1181 ic_eta = new INTEGRATOR(std::forward<Args>(args), (*this));
1182 }
1183 // without variadic arguments
1184 template<typename INTEGRATOR, typename PTRTYPE>
1185 void select_only (PTRTYPE *& ic_eta)
1186 {
1187 ic_eta = new INTEGRATOR((*this));
1188 }
1189
1190
1191 //
1192 // functionally simlar to other kinds of select, execpt works on
1193 // template-based static dispatch.
1194 //
1195
1196 template <typename... OBJ, typename CLASS>
1197 void select(std::string name, CLASS& value)
1198 {
1199 pushPrefix(name);
1200 static_polymorphism_parser<CLASS, 0, OBJ...>(value);
1201 popPrefix();
1202 }
1203
1204private:
1205 //
1206 // This function is a virtual "swtich / case" block for static
1207 // dispatch. It works on a faux-virtual class "CLASS" that must
1208 // contain a tuple of "obj" with each "obj" being a derived type.
1209 // Recursion is used to unroll the list, identify the correct class
1210 // based on "name/type", set the "selected" index, then call the
1211 // appropriate class' Parse function.
1212 //
1213 // This is only for use by the "select" functions.
1214 //
1215 template <typename CLASS, int N, typename... OBJ>
1217 {
1218 if constexpr (N == 0)
1219 {
1220 std::string type;
1221 query_default("type",type,value.names[0]);
1222
1223 for (unsigned int i = 0; i < sizeof...(OBJ); i++)
1224 if (type == value.names[i])
1225 value.selected = i;
1226
1227 if (value.selected < 0)
1229 "Error reading " + getPrefix() +
1230 ", invalid type " + type);
1231
1232
1233 pushPrefix(type);
1234 }
1235
1236 if constexpr (N < sizeof...(OBJ))
1237 {
1238 if (value.selected == N)
1239 {
1240 std::get<N>(value.obj).Parse(std::get<N>(value.obj), *this);
1241 popPrefix();
1242 return;
1243 }
1244 else
1245 return static_polymorphism_parser<CLASS, N+1, OBJ...>(value);
1246 }
1247 else Util::Abort(INFO);
1248 }
1249
1250public:
1251
1252 template <int N>
1253 void query_exactly( std::vector<std::string> names, std::pair<std::string, Set::Scalar> values[N],
1254 std::vector<Unit> units = std::vector<Unit>())
1255 {
1256 try
1257 {
1258 Util::AssertException( INFO,TEST(units.size() == 0 || units.size() == names.size()),
1259 "# of units must be 0, 1, or ", names.size(), " but got ", units.size());
1260
1261 int cnt = 0;
1262 std::vector<std::string> read;
1263 for (unsigned int n = 0; n < names.size(); n++)
1264 {
1265 if (amrex::ParmParse::contains(names[n].c_str()))
1266 {
1267 read.push_back(names[n]);
1268 cnt++;
1269 }
1270 }
1271 Util::AssertException( INFO, TEST(cnt == N),
1272 " Incorrect number of values specified: only ", N,
1273 " values are allowed, but received ",
1274 Util::String::Join(read,", "));
1275
1276
1277 cnt = 0;
1278 for (unsigned int n = 0; n < names.size(); n++)
1279 {
1280 if (amrex::ParmParse::contains(names[n].c_str()))
1281 {
1282 values[cnt].first = names[n];
1283
1284 if (units.size() == 0)
1285 query_required(names[n],values[cnt].second);
1286 else if (units.size() == 1)
1287 query_required(names[n],values[cnt].second,units[0]);
1288 else
1289 query_required(names[n],values[cnt].second,units[n]);
1290 cnt++;
1291 }
1292 }
1293 }
1294 catch(...)
1295 {
1296 std::string names_str = "[";
1297 for (unsigned int i = 0; i < names.size(); i++)
1298 {
1299 names_str += full(names[i]);
1300 if (i < names.size()-1) names_str += ", ";
1301 }
1302 names_str += "]";
1303 Util::ParmParseException(INFO,names_str);
1304 }
1305 }
1306
1307
1308
1309
1310};
1311}
1312#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:718
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:654
int queryarr_required(std::string name, std::vector< Set::Scalar > &value, Unit unit=Unit::Less())
Definition ParmParse.H:646
int queryarr(std::string name, std::vector< T > &value)
Definition ParmParse.H:529
void forbid(std::string name, std::string explanation)
Definition ParmParse.H:160
void select(std::string name, CLASS &value)
Definition ParmParse.H:1197
int query_enumerate(std::string a_name, std::vector< T > &value, int number=1)
Definition ParmParse.H:804
int queryarr(std::string name, std::vector< Set::Scalar > &value, Unit unit=Unit::Less())
Definition ParmParse.H:541
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:376
int query_file(std::string name, std::string &value)
Definition ParmParse.H:522
int queryarr(std::string name, Set::Vector &value, Unit unit=Unit::Less())
Definition ParmParse.H:578
int query_file(std::string name, std::string &value, bool copyfile, bool checkfile)
Definition ParmParse.H:480
int AnyUnusedInputs(bool inscopeonly=true, bool verbose=false)
Definition ParmParse.H:869
int queryarr(std::string name, Set::Matrix &value, Unit unit=Unit::Less())
Definition ParmParse.H:599
std::vector< std::string > GetUnusedInputs()
Definition ParmParse.H:894
void queryclass(std::string name, T &value)
Definition ParmParse.H:959
std::string getPrefix() const
Definition ParmParse.H:136
static bool checked_for_input_files
Definition ParmParse.H:131
std::string prefix()
Definition ParmParse.H:921
void select(std::string name, PTRTYPE *&ic_eta, Args &&... args)
Definition ParmParse.H:1030
void queryclass(std::string name, T *value)
Definition ParmParse.H:934
int queryclass_enumerate(std::string a_name, std::vector< T > &value, int number=1)
Definition ParmParse.H:738
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:682
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:1069
int queryarr_default(std::string name, Set::Vector &value, Set::Vector defaultvalue)
Definition ParmParse.H:663
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:459
int query_file(std::string name, std::string &value, bool copyfile)
Definition ParmParse.H:518
void select_enumerate(std::string a_name, std::vector< PTRTYPE * > &value, Args &&... args)
Definition ParmParse.H:1093
void queryclass(T &value)
Definition ParmParse.H:1005
static int AllUnusedInputs()
Definition ParmParse.H:907
int query_validate(std::string name, std::string &value, std::vector< const char * > possiblecharvals)
Definition ParmParse.H:423
void queryclass(T *value)
Definition ParmParse.H:989
int queryarr_required(std::string name, std::vector< T > &value)
Definition ParmParse.H:637
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:1216
void select_only(PTRTYPE *&ic_eta, Args &&args)
Definition ParmParse.H:1179
void select_main(PTRTYPE *&ic_eta, Args &&... args)
Definition ParmParse.H:1158
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:1185
void ignore(std::string name)
Definition ParmParse.H:137
std::string full(std::string name)
Definition ParmParse.H:925
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:701
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:1253
int query_default(std::string name, std::string &value, const char *defaultvalue)
Definition ParmParse.H:442
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:225
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:353
std::string normalized_unitstring() const
Definition Unit.H:410
double normalized_value() const
Definition Unit.H:401
static Unit Less()
Definition Unit.H:187
static Unit Parse(double val, std::string unitstring)
Definition Unit.H:257