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_switch` | Validate a string against allowed values and run the branch |
50// | | lambda associated with the selected value. |
51// +---------------------------------+-----------------------------------------------------------------+
52// | :bdg-success:`query_if` | Read a Boolean value and run the supplied lambda when enabled. |
53// +---------------------------------+-----------------------------------------------------------------+
54// | :bdg-success:`query_if_else` | Read a Boolean value and run the corresponding supplied lambda. |
55// +---------------------------------+-----------------------------------------------------------------+
56// | :bdg-success:`query_file` | Read in a string that defines a file name. |
57// | | Check to make sure that the file exists and is a regular file, |
58// | | and print an informative error message if not (this can be |
59// | | disabled). |
60// | | Also, copy the file to the output directory, with the full path |
61// | | preserved by replacing / with _. |
62// | | (This can also be disabled, but doing so is discouraged.) |
63// | | Default values are not allowed. |
64// | | File paths are indicated by :bdg-secondary-line:`file path`. |
65// +---------------------------------+-----------------------------------------------------------------+
66// | :bdg-primary:`queryarr` | Read in an array of numbers into either a standard vector or |
67// | | into a :code:`Set::Vector` or :code:`Set::Scalar`. |
68// | | No defaults or existence checking is performed. |
69// +---------------------------------+-----------------------------------------------------------------+
70// | :bdg-primary:`queryclass` | Read a class object with a specified prefix. |
71// | | How that class is read in is determined by its :code:`Parse` |
72// | | function. |
73// +---------------------------------+-----------------------------------------------------------------+
74//
75// .. _query_locator_macros:
76//
77// **Query macros**
78//
79// A set of preprocessor macros are defined so that you can call a query function using :code:`pp_` instead
80// of :code:`pp.`.
81// For instance, the following two can be used interchangeably:
82//
83// .. code-block:: cpp
84//
85// pp.query_required("myvar",myvar); /* function version */
86// pp_query_required("myvar",myvar); /* preprocessor macro version - preferred*/
87//
88// Using the preprocessor macros enables code location information to be passed to the parser, so that
89// more informative error messages will be printed out.
90// Note that **the ParmParse object must always be called** :code:`pp` **for this to work**.
91//
92//
93
94#ifndef IO_PARMPARSE
95#define IO_PARMPARSE
96
97#include <filesystem>
98#include <exception>
99#include <functional>
100#include <iostream>
101#include <list>
102#include <optional>
103#include <source_location>
104#include <sstream>
105#include <stdexcept>
106#include <string>
107#include <tuple>
108#include <type_traits>
109#include <utility>
110#include <vector>
111
112#include "Util/Util.H"
113#include "Unit/Unit.H"
114#include "Set/Base.H"
115#include "IO/InputScraper.H"
116#include "AMReX_ParmParse.H"
117
118
119#define pp_query_required(...) pp.query_required(__VA_ARGS__)
120#define pp_query_default(...) pp.query_default(__VA_ARGS__)
121#define pp_query_validate(...) pp.query_validate(__VA_ARGS__)
122#define pp_query_switch(...) pp.query_switch(__VA_ARGS__)
123#define pp_query_if(...) pp.query_if(__VA_ARGS__)
124#define pp_query_if_else(...) pp.query_if_else(__VA_ARGS__)
125#define pp_query_file(...) pp.query_file(__VA_ARGS__)
126#define pp_queryarr(...) pp.queryarr(__VA_ARGS__)
127#define pp_queryarr_required(...) pp.queryarr_required(__VA_ARGS__)
128#define pp_queryarr_default(...) pp.queryarr_default(__VA_ARGS__)
129#define pp_query(...) pp.query(__VA_ARGS__)
130#define pp_queryclass(...) pp.queryclass(__VA_ARGS__)
131#define pp_forbid(...) pp.forbid(__VA_ARGS__)
132
133
134namespace IO
135{
136class ParmParse : public amrex::ParmParse
137{
138public:
140 template<typename... Args>
142 {
143 std::tuple<Args...> values;
144
145 explicit ForwardArgs(Args... args) : values(std::forward<Args>(args)...) {}
146 };
147
148 template<typename Arg>
149 using ForwardArgStorage = std::conditional_t<
150 std::is_lvalue_reference_v<Arg>, Arg, std::remove_cvref_t<Arg>>;
151
152 template<typename... Args>
154 {
155 return ForwardArgs<ForwardArgStorage<Args>...>(std::forward<Args>(args)...);
156 }
157
158private:
159 friend class InputScraper;
160 void Define()
161 {
162 if (checked_for_input_files) return;
163 int k = 0;
164 std::string inputfile = "";
165 while (this->querykth("input",k,inputfile))
166 {
167 Util::Message(INFO,"Including inputs from "+inputfile);
168 this->addfile(inputfile);
169 k++;
170 }
172 }
174 void RecordInput( std::string name,
175 std::string directive,
176 const std::source_location &location,
177 std::vector<std::string> options = {},
178 std::optional<std::string> default_value = std::nullopt,
179 bool has_unnamed_default = false);
180 void RecordConstraint( std::string kind,
181 int count,
182 std::vector<std::string> members,
183 std::vector<std::string> units,
184 const std::source_location &location);
185 void PrintTraversalBranch(std::string name, const std::string &value);
187 std::string name,
188 const std::source_location &location,
189 std::vector<std::string> options = {},
190 std::optional<std::string> default_value = std::nullopt,
191 bool has_unnamed_default = false,
192 const std::source_location &handler_location = std::source_location::current())
193 {
194 if (InTraversalMode())
195 RecordInput(name, InputScraper::DirectiveName(handler_location), location,
196 std::move(options), std::move(default_value),
197 has_unnamed_default);
198 }
200
201 template<typename T, typename... Args>
202 static T *ConstructSelected(ForwardArgs<Args...> &args, ParmParse &pp, const std::string &name)
203 {
204 return std::apply(
205 [&](auto &...constructor_args) -> T *
206 {
207 return new T(constructor_args..., pp, name);
208 },
209 args.values);
210 }
211
212 template<typename T, typename = void>
213 struct HasSelectName : std::false_type {};
214
215 template<typename T>
216 struct HasSelectName<T, std::void_t<decltype(T::name)>> : std::true_type {};
217
218 template<typename T, typename... Args>
219 static constexpr bool HasSelectedConstructor =
220 std::is_constructible_v<T, std::add_lvalue_reference_t<Args>...,
221 ParmParse &, std::string>;
222
223 template<typename T, typename... Args>
225 {
226 return std::apply(
227 [&](auto &...constructor_args) -> T *
228 {
229 static_assert( std::is_constructible_v<T, decltype(constructor_args)...>,
230 "The unnamed select default cannot be constructed from forward_args");
231 return new T(constructor_args...);
232 },
233 args.values);
234 }
235
236 template<typename T, typename... Args>
237 static void AppendSelectName(std::vector<std::string> &names, ForwardArgs<Args...> &)
238 {
239 if constexpr (HasSelectName<T>::value && HasSelectedConstructor<T, Args...>)
240 names.emplace_back(T::name);
241 }
242
243 template<typename T, typename... Args, typename PTRTYPE>
244 static bool TrySelectNamed( const std::string &type, const std::string &name,
245 PTRTYPE *&value, ForwardArgs<Args...> &args,
246 ParmParse &pp)
247 {
248 if constexpr (HasSelectName<T>::value && HasSelectedConstructor<T, Args...>)
249 {
250 if (type == T::name)
251 {
252 value = ConstructSelected<T>(args, pp, name + "." + std::string(T::name));
253 return true;
254 }
255 }
256 return false;
257 }
258
259public:
260 static void SetTraversalMode(bool enabled);
261 static bool InTraversalMode();
262 static bool ShouldExecute();
263 static const InputNode &InputTree();
264 static void ClearInputTree();
265 static void SetTraversalOutputFile(std::string path);
266 static const std::string &TraversalOutputFile();
267 static void WriteInputTreeJson(std::ostream &os);
268 static void WriteInputTreeJsonFile(const std::string &path);
269 static bool IgnoreInTraversalMode(
270 std::string note = "This input parser is not yet compliant with traversal mode; its inputs are not fully documented.",
271 const std::source_location &location = std::source_location::current());
272
273 ParmParse(std::string arg) : amrex::ParmParse::ParmParse(arg) {Define();} ;
274 ParmParse() : amrex::ParmParse::ParmParse() {Define();} ;
275 std::string getPrefix() const {return m_prefix;};
276 void ignore(std::string name,
277 const std::source_location & location = std::source_location::current())
278 {
279 (void)location;
280 (void)amrex::ParmParse::contains(name.c_str());
281 }
282
283 void pushPrefix(const std::string prefix)
284 {
285 if (m_prefix.length())
286 m_prefix = m_prefix + "." + prefix;
287 else
288 m_prefix = prefix;
289 }
290
292 {
293 size_t pos = m_prefix.rfind('.');
294 if (pos == std::string::npos)
295 m_prefix = "";
296 else
297 m_prefix = m_prefix.substr(0, pos);
298 }
299
300
301 void forbid(std::string name, std::string explanation,
302 const std::source_location & location = std::source_location::current())
303 {
304 (void)location;
305 if (amrex::ParmParse::contains(full(name).c_str()))
306 {
307 if (!InTraversalMode())
308 Util::ParmParseException(INFO,full(name),full(name)," forbidden: ", explanation);
309 }
310 std::set<std::string> subs = amrex::ParmParse::getEntries(full(name));
311 if (subs.size())
312 {
313 if (!InTraversalMode())
314 Util::ParmParseException(INFO,full(name),full(name)," forbidden: ", explanation);
315 }
316 }
317
318 bool contains( std::string name,
319 const std::source_location & location = std::source_location::current())
320 {
321 (void)location;
322 if (amrex::ParmParse::contains(name.c_str()))
323 return true;
324 if (amrex::ParmParse::contains(full(name).c_str()))
325 return true;
326 {
327 std::set<std::string> subs = amrex::ParmParse::getEntries(name.c_str());
328 if (subs.size())
329 return true;
330 }
331 {
332 std::set<std::string> subs = amrex::ParmParse::getEntries(full(name).c_str());
333 if (subs.size())
334 return true;
335 }
336 return false;
337 }
338
339 template<typename T>
340 int query( std::string name, T & value,
341 const std::source_location & location = std::source_location::current())
342 {
343 if constexpr (std::is_same_v<std::remove_cv_t<T>, bool>)
344 RecordInputAndContinue(name, location, {"0", "1"});
345 else
346 RecordInputAndContinue(name, location);
347 if (InTraversalMode() && !contains(name.c_str())) return 0;
348 return amrex::ParmParse::query(name.c_str(), value);
349 }
350
351 int queryunit ( std::string name, Unit &value,
352 const std::source_location & location = std::source_location::current())
353 {
354 RecordInputAndContinue(name, location);
355 if (InTraversalMode() && !contains(name.c_str())) return 0;
356 try
357 {
358 std::string strvalue;
359 int retval = amrex::ParmParse::query(name.c_str(),strvalue);
360 value = Unit::Parse(strvalue);
361 return retval;
362 }
363 catch (std::runtime_error & e)
364 {
365 if (!InTraversalMode())
366 Util::ParmParseException(INFO,full(name), e.what());
367 }
368 catch (...)
369 {
370 if (!InTraversalMode())
372 }
373 return -1;
374 }
375
376 int queryunit ( std::string name, Unit &value, const Unit type,
377 const std::source_location & location = std::source_location::current())
378 {
379 RecordInputAndContinue(name, location);
380 if (InTraversalMode() && !contains(name.c_str())) return 0;
381 try
382 {
383 int retval = queryunit(name,value, location);
384 if (!value.isType(type) && !value.isType(Unit::Less()))
385 {
386 if (!InTraversalMode())
388 "value requiested had wrong units:", value.normalized_unitstring(),
389 ", units requested are of SI type ",type.normalized_unitstring());
390 }
391 return retval;
392 }
393 catch (...)
394 {
395 if (!InTraversalMode())
397 }
398 return -1;
399 }
400 int queryunit ( std::string name, Set::Scalar &value, const Unit type,
401 const std::source_location & location = std::source_location::current())
402 {
403 RecordInputAndContinue(name, location);
404 if (InTraversalMode() && !contains(name.c_str())) return 0;
405 try
406 {
407 Unit read;
408 int retval = queryunit(name,read,type, location);
409 value = read.normalized_value();
410 return retval;
411 }
412 catch (std::runtime_error &e)
413 {
414 if (!InTraversalMode())
415 Util::ParmParseException(INFO,full(name), e.what());
416 }
417 return -1;
418 }
419
420 template<typename T>
421 int query_required( std::string name, T & value,
422 const std::source_location & location = std::source_location::current())
423 {
424 if constexpr (std::is_same_v<std::remove_cv_t<T>, bool>)
425 RecordInputAndContinue(name, location, {"0", "1"});
426 else
427 RecordInputAndContinue(name, location);
428 if (InTraversalMode())
429 {
430 if (!contains(name.c_str())) return 0;
431 return amrex::ParmParse::query(name.c_str(), value);
432 }
433 try
434 {
435 if (!contains(name.c_str()))
436 {
437 if (!InTraversalMode())
438 Util::ParmParseException(INFO,full(name),"required value for ",full(name)," missing");
439 }
440 return query(name.c_str(),value);
441 }
442 catch (std::runtime_error & e)
443 {
444 if (!InTraversalMode())
445 Util::ParmParseException(INFO,full(name),e.what());
446 }
447 catch (...)
448 {
449 if (!InTraversalMode())
451 }
452 return -1;
453 }
454
455 template<typename T>
456 int query_required( std::string name, T & value, const Unit type,
457 const std::source_location & location = std::source_location::current())
458 {
459 RecordInputAndContinue(name, location);
460 if (InTraversalMode())
461 {
462 if (!contains(name.c_str())) return 0;
463 std::string strvalue;
464 int retval = amrex::ParmParse::query(name.c_str(), strvalue);
465 Unit read = Unit::Parse(strvalue);
466 value = read.normalized_value();
467 return retval;
468 }
469 try
470 {
471 if (!contains(name.c_str()))
472 {
473 if (!InTraversalMode())
474 Util::ParmParseException(INFO,full(name),"required value for ",full(name)," missing");
475 }
476 return queryunit(name.c_str(), value, type, location);
477 }
478 catch (std::runtime_error & e)
479 {
480 if (!InTraversalMode())
481 Util::ParmParseException(INFO,full(name),e.what());
482 }
483 catch (...)
484 {
485 if (!InTraversalMode())
487 }
488 return -1;
489 }
490
491 template<typename T>
492 int query_default( std::string name, T & value, T defaultvalue,
493 const std::source_location & location = std::source_location::current())
494 {
495 if constexpr (std::is_same_v<std::remove_cv_t<T>, bool>)
496 RecordInputAndContinue( name, location, {"0", "1"},
497 InputScraper::InputValueString(defaultvalue));
498 else
499 RecordInputAndContinue( name, location, {},
500 InputScraper::InputValueString(defaultvalue));
501 if (InTraversalMode())
502 {
503 if (contains(name.c_str()))
504 return amrex::ParmParse::query(name.c_str(), value);
505 value = defaultvalue;
506 return 0;
507 }
508 try
509 {
510 if (!contains(name.c_str()))
511 {
512 add(name.c_str(),defaultvalue);
513 }
514 return query(name.c_str(),value);
515 }
516 catch (std::runtime_error & e)
517 {
518 if (!InTraversalMode())
519 Util::ParmParseException(INFO,full(name),e.what());
520 }
521 catch (...)
522 {
523 if (!InTraversalMode())
525 }
526 return -1;
527 }
528
529 template<typename T>
530 int query_default( std::string name, T & value, std::string defaultvalue, const Unit type,
531 const std::source_location & location = std::source_location::current())
532 {
533 RecordInputAndContinue(name, location, {}, defaultvalue);
534 if (InTraversalMode())
535 {
536 if (contains(name.c_str()))
537 {
538 std::string strvalue;
539 int retval = amrex::ParmParse::query(name.c_str(), strvalue);
540 Unit read = Unit::Parse(strvalue);
541 value = read.normalized_value();
542 return retval;
543 }
544 Unit read = Unit::Parse(defaultvalue);
545 value = read.normalized_value();
546 return 0;
547 }
548 try
549 {
550 if (!contains(name.c_str()))
551 {
552 add(name.c_str(),defaultvalue);
553 }
554 return queryunit(name.c_str(),value,type, location);
555 }
556 catch (std::runtime_error & e)
557 {
558 if (!InTraversalMode())
559 Util::ParmParseException(INFO,full(name),e.what());
560 }
561 catch (...)
562 {
563 if (!InTraversalMode())
565 }
566 return -1;
567 }
568
569 int query_validate( std::string name, int & value, std::vector<int> possibleintvals,
570 const std::source_location & location = std::source_location::current())
571 {
572 std::vector<std::string> options;
573 for (const auto &possibleval : possibleintvals)
574 options.push_back(std::to_string(possibleval));
575 RecordInputAndContinue(name, location, options);
576 if (InTraversalMode())
577 {
578 if (contains(name.c_str()))
579 return amrex::ParmParse::query(name.c_str(), value);
580 value = possibleintvals[0];
581 return 0;
582 }
583
584 try
585 {
586 // First value is accepted by default...
587
588 // set default value
589 if (!contains(name.c_str()))
590 {
591 add(name.c_str(), possibleintvals[0]);
592 }
593
594 // get the read value (if it exists)
595 int retval = query(name.c_str(),value);
596
597 // check to make sure the read value matches one of the inpus
598 bool ok = false;
599 for (unsigned int i = 0; i < possibleintvals.size(); i++)
600 {
601 if (value == possibleintvals[i]) ok = true;
602 }
603
604 if (ok) return retval;
605
606 std::stringstream ss;
607 ss << possibleintvals[0];
608 for (unsigned int i = 1; i < possibleintvals.size(); i++)
609 ss << "," << possibleintvals[i];
610
611 if (!InTraversalMode())
612 Util::ParmParseException(INFO,full(name),"' expected [", ss.str(), "] but got ", value);
613 }
614 catch (std::runtime_error & e)
615 {
616 if (!InTraversalMode())
617 Util::ParmParseException(INFO,full(name),e.what());
618 }
619 catch (...)
620 {
621 if (!InTraversalMode())
623 }
624 return -1;
625 }
626
627
628 int query_validate( std::string name, std::string & value, std::vector<const char *> possiblecharvals, bool firstbydefault,
629 const std::source_location &location = std::source_location::current())
630 {
631 std::vector<std::string> options;
632 for (const auto &possibleval : possiblecharvals)
633 options.push_back(std::string(possibleval));
634 RecordInputAndContinue(name, location, options);
635 if (InTraversalMode())
636 {
637 if (contains(name.c_str()))
638 return amrex::ParmParse::query(name.c_str(), value);
639 value = std::string(possiblecharvals[0]);
640 return 0;
641 }
642
643 try
644 {
645 // if not using default values, then the input must be specified
646 if (!firstbydefault)
647 {
648 if (!amrex::ParmParse::contains(name.c_str()))
649 {
650 if (!InTraversalMode())
651 Util::ParmParseException(INFO,full(name),"required value for ",full(name)," missing");
652 }
653 }
654
655 // set default value
656 if (!amrex::ParmParse::contains(name.c_str()))
657 {
658 add(name.c_str(), std::string(possiblecharvals[0]));
659 }
660
661 // get the read value (if it exists)
662 int retval = amrex::ParmParse::query(name.c_str(),value);
663
664 // check to make sure the read value matches one of the inpus
665 bool ok = false;
666 for (unsigned int i = 0; i < possiblecharvals.size(); i++)
667 {
668 if (value == std::string(possiblecharvals[i])) ok = true;
669 }
670
671 if (ok) return retval;
672
673 std::stringstream ss;
674 ss << possiblecharvals[0];
675 for (unsigned int i = 1; i < possiblecharvals.size(); i++)
676 ss << "," << possiblecharvals[i];
677
678 Util::ParmParseException(INFO,full(name),"' expected [", ss.str(), "] but got ", value);
679 }
680 catch (std::runtime_error & e)
681 {
682 if (!InTraversalMode())
683 Util::ParmParseException(INFO,full(name),e.what());
684 }
685 catch (...)
686 {
687 if (!InTraversalMode())
689 }
690
691 return -1;
692 }
693
694 int query_validate( std::string name, std::string & value, std::vector<const char *> possiblecharvals,
695 const std::source_location &location = std::source_location::current())
696 {
697 try
698 {
699 return query_validate(name,value,possiblecharvals,true, location);
700 }
701 catch (std::runtime_error & e)
702 {
703 if (!InTraversalMode())
704 Util::ParmParseException(INFO,full(name),e.what());
705 }
706 catch (...)
707 {
708 if (!InTraversalMode())
710 }
711 return -1;
712 }
713
714 int query_switch( std::string name,
715 std::initializer_list<std::pair<std::string, std::function<void()>>> cases,
716 const std::source_location &location = std::source_location::current())
717 {
718 std::string value;
719 std::vector<std::string> possiblevals;
720 possiblevals.reserve(cases.size());
721 for (const auto &entry : cases)
722 possiblevals.push_back(entry.first);
723 {
724 RecordInputAndContinue(name, location, possiblevals);
725 }
726
727 auto set_switch_value = [&](const std::string &switch_value)
728 {
729 this->remove(name.c_str());
730 this->add(name.c_str(), switch_value);
731 };
732
733 auto print_switch_branch = [&](const std::string &switch_value)
734 {
735 PrintTraversalBranch(name, switch_value);
736 };
737
738 auto run_case = [&](const std::string &switch_value, auto &&action)
739 {
740 set_switch_value(switch_value);
741 print_switch_branch(switch_value);
742 TraversalBranchScope branch(*this, name, switch_value);
743 action();
744 };
745
746 if (InTraversalMode())
747 {
748 std::string original_value;
749 bool had_original_value = amrex::ParmParse::contains(name.c_str());
750 if (had_original_value)
751 amrex::ParmParse::query(name.c_str(), original_value);
752
753 for (const auto &entry : cases)
754 run_case(entry.first, entry.second);
755
756 if (had_original_value)
757 set_switch_value(original_value);
758 else
759 this->remove(name.c_str());
760 return 0;
761 }
762
763 int retval = -1;
764 try
765 {
766 if (!amrex::ParmParse::contains(name.c_str()))
767 {
768 add(name.c_str(), possiblevals[0]);
769 }
770
771 retval = amrex::ParmParse::query(name.c_str(),value);
772
773 bool ok = false;
774 for (const auto & possibleval : possiblevals)
775 {
776 if (value == possibleval) ok = true;
777 }
778
779 if (!ok)
780 {
781 std::stringstream ss;
782 ss << possiblevals[0];
783 for (unsigned int i = 1; i < possiblevals.size(); i++)
784 ss << "," << possiblevals[i];
785
786 Util::ParmParseException(INFO,full(name),"' expected [", ss.str(), "] but got ", value);
787 }
788 }
789 catch (std::runtime_error & e)
790 {
791 Util::ParmParseException(INFO,full(name),e.what());
792 }
793 catch (...)
794 {
796 }
797
798 bool matched = false;
799 for (const auto &entry : cases)
800 {
801 if (!matched && value == entry.first)
802 {
803 entry.second();
804 matched = true;
805 }
806 }
807
808 if (!matched)
809 {
810 Util::ParmParseException(INFO,full(name),value," not a valid value for ",full(name));
811 }
812
813 return retval;
814 }
815
816 template <typename Action>
817 int query_if( std::string name, Action &&action,
818 const std::source_location &location = std::source_location::current())
819 {
820 static_assert( std::is_invocable_v<Action &>,
821 "query_if action must be callable without arguments");
822
823 RecordInputAndContinue(name, location, {"0", "1"}, "0");
824
825 auto set_value = [&](const std::string &value)
826 {
827 this->remove(name.c_str());
828 this->add(name.c_str(), value);
829 };
830
831 if (InTraversalMode())
832 {
833 std::string original_value;
834 bool had_original_value = amrex::ParmParse::contains(name.c_str());
835 if (had_original_value)
836 amrex::ParmParse::query(name.c_str(), original_value);
837
838 set_value("1");
839 PrintTraversalBranch(name, "1");
840 {
841 TraversalBranchScope branch(*this, name, "1");
842 action();
843 }
844
845 if (had_original_value)
846 set_value(original_value);
847 else
848 this->remove(name.c_str());
849 return 0;
850 }
851
852 int enabled = 0;
853 int retval = amrex::ParmParse::query(name.c_str(), enabled);
854 if (retval && enabled != 0 && enabled != 1)
855 Util::ParmParseException(INFO, full(name), "expected 0 or 1 but got ", enabled);
856 if (enabled)
857 action();
858 return retval;
859 }
860
861 template <typename TrueAction, typename FalseAction>
862 int query_if_else( std::string name,
863 TrueAction &&true_action,
864 FalseAction &&false_action,
865 const std::source_location &location = std::source_location::current())
866 {
867 static_assert( std::is_invocable_v<TrueAction &>,
868 "query_if_else true action must be callable without arguments");
869 static_assert( std::is_invocable_v<FalseAction &>,
870 "query_if_else false action must be callable without arguments");
871
872 RecordInputAndContinue(name, location, {"0", "1"}, "0");
873
874 auto set_value = [&](const std::string &value)
875 {
876 this->remove(name.c_str());
877 this->add(name.c_str(), value);
878 };
879
880 auto run_action = [&](const std::string &value, auto &&action)
881 {
882 set_value(value);
883 PrintTraversalBranch(name, value);
884 TraversalBranchScope branch(*this, name, value);
885 action();
886 };
887
888 if (InTraversalMode())
889 {
890 std::string original_value;
891 bool had_original_value = amrex::ParmParse::contains(name.c_str());
892 if (had_original_value)
893 amrex::ParmParse::query(name.c_str(), original_value);
894
895 run_action("0", false_action);
896 run_action("1", true_action);
897
898 if (had_original_value)
899 set_value(original_value);
900 else
901 this->remove(name.c_str());
902 return 0;
903 }
904
905 int enabled = 0;
906 int retval = amrex::ParmParse::query(name.c_str(), enabled);
907 if (retval && enabled != 0 && enabled != 1)
908 Util::ParmParseException(INFO, full(name), "expected 0 or 1 but got ", enabled);
909 if (enabled)
910 true_action();
911 else
912 false_action();
913 return retval;
914 }
915
916 // special case for strings
917 int query_default( std::string name, std::string & value, const char *defaultvalue,
918 const std::source_location &location = std::source_location::current())
919 {
920 try
921 {
922 return query_default(name, value, std::string(defaultvalue), location);
923 }
924 catch (std::runtime_error & e)
925 {
926 if (!InTraversalMode())
927 Util::ParmParseException(INFO,full(name),e.what());
928 }
929 catch (...)
930 {
931 if (!InTraversalMode())
933 }
934 return -1;
935 }
936 // special case for bools
937 int query_default( std::string name, int & value, bool defaultvalue,
938 const std::source_location &location = std::source_location::current())
939 {
940 try
941 {
942 int defaultint = 0;
943 if (defaultvalue) defaultint = 1;
944 return query_default(name, value, defaultint, location);
945 }
946 catch (std::runtime_error & e)
947 {
948 if (!InTraversalMode())
949 Util::ParmParseException(INFO,full(name),e.what());
950 }
951 catch (...)
952 {
953 if (!InTraversalMode())
955 }
956 return -1;
957 }
958
959
960 // validate filenames
961 int query_file( std::string name, std::string & value, bool copyfile, bool checkfile,
962 const std::source_location &location = std::source_location::current())
963 {
964 RecordInputAndContinue(name, location);
965 if (InTraversalMode())
966 {
967 if (!contains(name.c_str())) return 0;
968 return amrex::ParmParse::query(name.c_str(), value);
969 }
970 try
971 {
972 if (!contains(name.c_str()))
973 {
974 if (!InTraversalMode())
975 Util::ParmParseException(INFO,full(name),full(name)," must be specified");
976 }
977
978 int retval = query(name.c_str(),value);
979
980 if (ShouldExecute() && amrex::ParallelDescriptor::IOProcessor())
981 {
982 if ( checkfile && ! std::filesystem::exists(value))
983 {
984 if (!InTraversalMode())
985 Util::ParmParseException(INFO,full(name),full(name)," does not exist");
986 }
987 if ( checkfile && !std::filesystem::is_regular_file(value))
988 {
989 if (!InTraversalMode())
990 Util::ParmParseException(INFO,full(name),full(name)," is not a regular file");
991 }
992 if ( copyfile )
993 {
994 if (!InTraversalMode())
995 Util::CopyFileToOutputDir(value, true, full(name));
996 }
997 }
998 return retval;
999 }
1000 catch (std::runtime_error & e)
1001 {
1002 if (!InTraversalMode())
1003 Util::ParmParseException(INFO,full(name),e.what());
1004 }
1005 catch (...)
1006 {
1007 if (!InTraversalMode())
1009 }
1010 return -1;
1011 }
1012 int query_file( std::string name, std::string & value, bool copyfile,
1013 const std::source_location & location = std::source_location::current())
1014 {
1015 return query_file(name,value,copyfile,true, location);
1016 }
1017 int query_file( std::string name, std::string & value,std::source_location loc = std::source_location::current())
1018 {
1019 return query_file(name,value,true,true, loc);
1020 }
1021
1022
1023 template<typename T>
1024 int queryarr( std::string name, std::vector<T> & value,
1025 const std::source_location &location = std::source_location::current())
1026 {
1027 RecordInputAndContinue(name, location);
1028 if (InTraversalMode())
1029 {
1030 if (contains(name.c_str()))
1031 return amrex::ParmParse::queryarr(name.c_str(), value);
1032 value.clear();
1033 return 0;
1034 }
1035 try
1036 {
1037 return amrex::ParmParse::queryarr(name.c_str(),value);
1038 }
1039 catch (...)
1040 {
1041 if (!InTraversalMode())
1043 }
1044 return -1;
1045 }
1046 int queryarr( std::string name, std::vector<Set::Scalar> & value, Unit unit = Unit::Less(),
1047 const std::source_location &location = std::source_location::current())
1048 {
1049 RecordInputAndContinue(name, location);
1050 if (InTraversalMode())
1051 {
1052 if (contains(name.c_str()))
1053 {
1054 if (unit.isType(Unit::Less()))
1055 return amrex::ParmParse::queryarr(name.c_str(), value);
1056
1057 value.clear();
1058 std::vector<std::string> valstrings;
1059 int retval = amrex::ParmParse::queryarr(name.c_str(), valstrings);
1060 for (unsigned int i = 0; i < valstrings.size(); i++)
1061 {
1062 Unit unitvalue = Unit::Parse(valstrings[i]);
1063 value.push_back(unitvalue.normalized_value());
1064 }
1065 return retval;
1066 }
1067 value.clear();
1068 return 0;
1069 }
1070 try
1071 {
1072 if (unit.isType(Unit::Less()))
1073 {
1074 return amrex::ParmParse::queryarr(name.c_str(),value);
1075 }
1076 else
1077 {
1078 value.clear();
1079 std::vector<std::string> valstrings;
1080 int retval = amrex::ParmParse::queryarr(name.c_str(), valstrings);
1081 for (unsigned int i = 0; i < valstrings.size(); i++)
1082 {
1083 Unit unitvalue = Unit::Parse(valstrings[i]);
1084 Util::DebugMessage(INFO,full(name),": ",valstrings[i]," ==> ",unitvalue);
1085
1086 if (!unitvalue.isType(unit) && !unitvalue.isType(Unit::Less()))
1087 {
1088 Util::Exception(INFO,"value specified had wrong units:", valstrings[i]);
1089 }
1090 value.push_back(unitvalue.normalized_value());
1091 }
1092 return retval;
1093 }
1094 }
1095 catch (std::runtime_error &e)
1096 {
1097 if (!InTraversalMode())
1098 Util::ParmParseException(INFO,full(name), e.what());
1099 }
1100 catch (...)
1101 {
1102 if (!InTraversalMode())
1104 }
1105 return -1;
1106 }
1107 int queryarr( std::string name, Set::Vector & value, Unit unit = Unit::Less(),
1108 const std::source_location &location = std::source_location::current())
1109 {
1110 RecordInputAndContinue(name, location);
1111 if (InTraversalMode())
1112 {
1113 if (contains(name.c_str()))
1114 {
1115 std::vector<Set::Scalar> vals;
1116 if (unit.isType(Unit::Less()))
1117 amrex::ParmParse::queryarr(name.c_str(), vals);
1118 else
1119 {
1120 std::vector<std::string> valstrings;
1121 amrex::ParmParse::queryarr(name.c_str(), valstrings);
1122 for (unsigned int i = 0; i < valstrings.size(); i++)
1123 {
1124 Unit unitvalue = Unit::Parse(valstrings[i]);
1125 vals.push_back(unitvalue.normalized_value());
1126 }
1127 }
1128 value = Set::Vector::Zero();
1129 for (int i = 0; i < AMREX_SPACEDIM && i < static_cast<int>(vals.size()); i++)
1130 value(i) = vals[i];
1131 return 0;
1132 }
1133 value = Set::Vector::Zero();
1134 return 0;
1135 }
1136 try
1137 {
1138 std::vector<Set::Scalar> vals;
1139 queryarr(name.c_str(), vals, unit);
1140 if (vals.size() < AMREX_SPACEDIM)
1141 {
1142 if (!InTraversalMode())
1144 " requires at least ", AMREX_SPACEDIM,
1145 " arguments, got ",vals.size());
1146 }
1147 for (int i = 0; i < AMREX_SPACEDIM; i++) value(i) = vals[i];
1148 return 0;
1149 }
1150 catch(...)
1151 {
1152 if (!InTraversalMode())
1154 }
1155 return -1;
1156 }
1157 int queryarr( std::string name, Set::Matrix & value, Unit unit = Unit::Less(),
1158 const std::source_location &location = std::source_location::current())
1159 {
1160 RecordInputAndContinue(name, location);
1161 if (InTraversalMode())
1162 {
1163 if (contains(name.c_str()))
1164 {
1165 std::vector<Set::Scalar> vals;
1166 if (unit.isType(Unit::Less()))
1167 amrex::ParmParse::queryarr(name.c_str(), vals);
1168 else
1169 {
1170 std::vector<std::string> valstrings;
1171 amrex::ParmParse::queryarr(name.c_str(), valstrings);
1172 for (unsigned int i = 0; i < valstrings.size(); i++)
1173 {
1174 Unit unitvalue = Unit::Parse(valstrings[i]);
1175 vals.push_back(unitvalue.normalized_value());
1176 }
1177 }
1178 value = Set::Matrix::Zero();
1179 for (int i = 0; i < AMREX_SPACEDIM * AMREX_SPACEDIM && i < static_cast<int>(vals.size()); i++)
1180 value.data()[i] = vals[i];
1181 return 0;
1182 }
1183 value = Set::Matrix::Zero();
1184 return 0;
1185 }
1186 std::vector<Set::Scalar> vals;
1187 queryarr(name.c_str(), vals,unit);
1188 if (vals.size() == 9)
1189 {
1190#if AMREX_SPACEDIM==2
1191 Util::Warning(INFO, "Reading a 3D matrix (",full(name),")into a 2D code - some values will be ignored.");
1192 value(0,0) = vals[0]; value(0,1)= vals[1];
1193 value(1,0) = vals[3]; value(1,1)= vals[4];
1194#endif
1195#if AMREX_SPACEDIM==3
1196 value(0,0) = vals[0]; value(0,1)= vals[1]; value(0,2)= vals[2];
1197 value(1,0) = vals[3]; value(1,1)= vals[4]; value(1,2)= vals[5];
1198 value(2,0) = vals[6]; value(2,1)= vals[7]; value(2,2)= vals[8];
1199#endif
1200 }
1201 else if (vals.size() == 4)
1202 {
1203#if AMREX_SPACEDIM==2
1204 value(0,0) = vals[0]; value(0,1)= vals[1];
1205 value(1,0) = vals[2]; value(1,1)= vals[3];
1206#endif
1207#if AMREX_SPACEDIM==3
1208 Util::Warning(INFO,"Reading a 2D matrix (",full(name),")into a 3D code - remaining values will be set to zero.");
1209 value(0,0) = vals[0]; value(0,1)= vals[1]; value(0,2)= 0.0;
1210 value(1,0) = vals[2]; value(1,1)= vals[3]; value(1,2)= 0.0;
1211 value(2,0) = 0.0; value(2,1)= 0.0; value(2,2)= 0.0;
1212#endif
1213 }
1214 else
1215 {
1216 if (!InTraversalMode())
1217 Util::ParmParseException(INFO,full(name),full(name)," needs either 4 or 9 components, but got ",vals.size());
1218 }
1219 return 0;
1220 }
1221
1222 template<typename T>
1223 int queryarr_required( std::string name, std::vector<T> & value,
1224 const std::source_location &location = std::source_location::current())
1225 {
1226 RecordInputAndContinue(name, location);
1227 if (InTraversalMode())
1228 {
1229 if (contains(name.c_str()))
1230 return amrex::ParmParse::queryarr(name.c_str(), value);
1231 value.clear();
1232 return 0;
1233 }
1234 if (!contains(name.c_str()))
1235 {
1236 if (!InTraversalMode())
1237 Util::ParmParseException(INFO,full(name),"required value for ",full(name)," missing");
1238 }
1239 return queryarr<T>(name,value);
1240 }
1241
1242 int queryarr_required( std::string name, std::vector<Set::Scalar> & value, Unit unit = Unit::Less(),
1243 const std::source_location &location = std::source_location::current())
1244 {
1245 RecordInputAndContinue(name, location);
1246 if (InTraversalMode())
1247 {
1248 if (contains(name.c_str()))
1249 {
1250 if (unit.isType(Unit::Less()))
1251 return amrex::ParmParse::queryarr(name.c_str(), value);
1252
1253 value.clear();
1254 std::vector<std::string> valstrings;
1255 int retval = amrex::ParmParse::queryarr(name.c_str(), valstrings);
1256 for (unsigned int i = 0; i < valstrings.size(); i++)
1257 {
1258 Unit unitvalue = Unit::Parse(valstrings[i]);
1259 value.push_back(unitvalue.normalized_value());
1260 }
1261 return retval;
1262 }
1263 value.clear();
1264 return 0;
1265 }
1266 if (!contains(name.c_str()))
1267 {
1268 if (!InTraversalMode())
1269 Util::ParmParseException(INFO,full(name),"required value for ",full(name)," missing");
1270 }
1271 return queryarr(name,value,unit);
1272 }
1273 int queryarr_required( std::string name, Set::Vector & value, Unit unit = Unit::Less(),
1274 const std::source_location &location = std::source_location::current())
1275 {
1276 RecordInputAndContinue(name, location);
1277 if (InTraversalMode())
1278 {
1279 if (contains(name.c_str()))
1280 {
1281 std::vector<Set::Scalar> vals;
1282 if (unit.isType(Unit::Less()))
1283 amrex::ParmParse::queryarr(name.c_str(), vals);
1284 else
1285 {
1286 std::vector<std::string> valstrings;
1287 amrex::ParmParse::queryarr(name.c_str(), valstrings);
1288 for (const auto &valstring : valstrings)
1289 vals.push_back(Unit::Parse(valstring).normalized_value());
1290 }
1291 value = Set::Vector::Zero();
1292 for (int i = 0; i < AMREX_SPACEDIM && i < static_cast<int>(vals.size()); i++)
1293 value(i) = vals[i];
1294 return 0;
1295 }
1296 value = Set::Vector::Zero();
1297 return 0;
1298 }
1299 if (!contains(name.c_str()))
1300 Util::ParmParseException(INFO,full(name),"required value for ",full(name)," missing");
1301 return queryarr(name,value,unit);
1302 }
1303 int queryarr_default( std::string name, std::vector<std::string> & value, std::vector<std::string> defaultvalue,
1304 const std::source_location &location = std::source_location::current())
1305 {
1306 RecordInputAndContinue(name, location, {}, InputScraper::InputArrayString(defaultvalue));
1307 if (InTraversalMode())
1308 {
1309 if (contains(name.c_str()))
1310 return amrex::ParmParse::queryarr(name.c_str(), value);
1311 value = defaultvalue;
1312 return 0;
1313 }
1314 if (!contains(name.c_str()))
1315 {
1316 addarr(name.c_str(),defaultvalue);
1317 }
1318 return amrex::ParmParse::queryarr(name.c_str(),value);
1319 }
1320
1321 int queryarr_default( std::string name, Set::Vector & value, std::string defaultvalue, Unit unit,
1322 const std::source_location &location = std::source_location::current())
1323 {
1324 RecordInputAndContinue(name, location, {}, defaultvalue);
1325 if (InTraversalMode())
1326 {
1327 std::vector<std::string> data = Util::String::Split(defaultvalue);
1328 if (contains(name.c_str()))
1329 amrex::ParmParse::queryarr(name.c_str(), data);
1330
1331 value = Set::Vector::Zero();
1332 for (int i = 0; i < AMREX_SPACEDIM && i < static_cast<int>(data.size()); i++)
1333 {
1334 Unit unitvalue = Unit::Parse(data[i]);
1335 value(i) = unitvalue.normalized_value();
1336 }
1337 return 0;
1338 }
1339 try
1340 {
1341 if (!contains(name.c_str()))
1342 {
1343 this->addarr(name.c_str(),Util::String::Split(defaultvalue));
1344 }
1345 return queryarr(name.c_str(),value,unit);
1346 }
1347 catch (std::runtime_error &e)
1348 {
1349 if (!InTraversalMode())
1350 Util::ParmParseException(INFO,full(name), e.what());
1351 }
1352 catch (...)
1353 {
1354 if (!InTraversalMode())
1356 }
1357 return -1;
1358 }
1359 int queryarr_default( std::string name, Set::Vector & value, Set::Vector defaultvalue,
1360 const std::source_location &location = std::source_location::current())
1361 {
1362 RecordInputAndContinue(name, location, {}, InputScraper::InputArrayString(defaultvalue));
1363 if (InTraversalMode())
1364 {
1365 if (contains(name.c_str()))
1366 {
1367 std::vector<Set::Scalar> vals;
1368 amrex::ParmParse::queryarr(name.c_str(), vals);
1369 value = Set::Vector::Zero();
1370 for (int i = 0; i < AMREX_SPACEDIM && i < static_cast<int>(vals.size()); i++)
1371 value(i) = vals[i];
1372 return 0;
1373 }
1374 value = defaultvalue;
1375 return 0;
1376 }
1377 try
1378 {
1379 if (!contains(name.c_str()))
1380 {
1381 std::vector<Set::Scalar> def_data(AMREX_SPACEDIM);
1382 for (unsigned int i = 0; i < def_data.size(); i++)
1383 def_data[i] = defaultvalue[i];
1384
1385 add(name.c_str(),Util::String::Join(def_data));
1386 value = defaultvalue;
1387 return 0;
1388 }
1389 return queryarr(name.c_str(),value);
1390 }
1391 catch (...)
1392 {
1393 if (!InTraversalMode())
1395 }
1396 return -1;
1397 }
1398
1399 int queryarr_default( std::string name, Set::Matrix & value, Set::Matrix def,
1400 const std::source_location &location = std::source_location::current())
1401 {
1403 if (InTraversalMode())
1404 {
1405 if (contains(name.c_str()))
1406 {
1407 std::vector<Set::Scalar> vals;
1408 amrex::ParmParse::queryarr(name.c_str(), vals);
1409 value = Set::Matrix::Zero();
1410 for (int i = 0; i < AMREX_SPACEDIM * AMREX_SPACEDIM && i < static_cast<int>(vals.size()); i++)
1411 value.data()[i] = vals[i];
1412 return 0;
1413 }
1414 value = def;
1415 return 0;
1416 }
1417 try
1418 {
1419 if (!contains(name.c_str()))
1420 {
1421 std::vector<Set::Scalar> def_data(AMREX_SPACEDIM*AMREX_SPACEDIM);
1422 for (unsigned int i = 0; i < def_data.size(); i++)
1423 def_data[i] = def.data()[i];
1424
1425 add(name.c_str(),Util::String::Join(def_data));
1426 value = def;
1427 return 0;
1428 }
1429 return queryarr(name.c_str(),value);
1430 }
1431 catch (...)
1432 {
1433 if (!InTraversalMode())
1435 }
1436 return -1;
1437 }
1438
1439 int queryarr_default( std::string name, std::vector<double> & value, std::vector<double> defaultvalue,
1440 const std::source_location &location = std::source_location::current())
1441 {
1442 RecordInputAndContinue(name, location, {}, InputScraper::InputArrayString(defaultvalue));
1443 if (InTraversalMode())
1444 {
1445 if (contains(name.c_str()))
1446 return amrex::ParmParse::queryarr(name.c_str(), value);
1447 value = defaultvalue;
1448 return 0;
1449 }
1450 try
1451 {
1452 if (!contains(name.c_str()))
1453 {
1454 addarr(name.c_str(),defaultvalue);
1455 }
1456 return queryarr(name.c_str(),value);
1457 }
1458 catch (...)
1459 {
1460 if (!InTraversalMode())
1462 }
1463 return -1;
1464 }
1465
1466 int queryarr_default( std::string name, std::vector<double> & value, std::vector<std::string> defaultvalue, Unit unit,
1467 const std::source_location &location = std::source_location::current())
1468 {
1469 RecordInputAndContinue(name, location, {}, InputScraper::InputArrayString(defaultvalue));
1470 if (InTraversalMode())
1471 {
1472 std::vector<std::string> data = defaultvalue;
1473 if (contains(name.c_str()))
1474 amrex::ParmParse::queryarr(name.c_str(), data);
1475
1476 value.clear();
1477 for (const auto &entry : data)
1478 {
1479 Unit unitvalue = Unit::Parse(entry);
1480 value.push_back(unitvalue.normalized_value());
1481 }
1482 return 0;
1483 }
1484 try
1485 {
1486 if (!contains(name.c_str()))
1487 {
1488 addarr(name.c_str(),defaultvalue);
1489 }
1490 return queryarr(name,value, unit);
1491 }
1492 catch (...)
1493 {
1494 if (!InTraversalMode())
1496 }
1497 return -1;
1498 }
1499
1500
1501 template <typename T>
1502 int
1503 queryclass_enumerate( std::string a_name, std::vector<T> &value, int number = 1,
1504 const std::source_location &location = std::source_location::current())
1505 {
1506 {
1507 RecordInputAndContinue(a_name, location);
1508 }
1509 value.clear();
1510 if (InTraversalMode())
1511 {
1512 const std::string template_name = a_name + "0";
1513 T tmp;
1514 this->queryclass<T>(template_name, tmp);
1515 InputScraper::CaptureSequenceTemplate(*this, a_name, template_name);
1516 return 0;
1517 }
1518
1519 //
1520 // If only one is present with no subscript, then read
1521 // it only and return.
1522 //
1523 std::string name = a_name;
1524 if (this->contains(name))
1525 {
1526 for (int n = 0; n < number; n++)
1527 {
1528 T tmp;
1529 this->queryclass<T>(name, tmp);
1530 value.push_back(tmp);
1531 }
1532 return 0;
1533 }
1534
1535 //
1536 // Some logic to determine whether we are starting with zero
1537 // (model0, model1, model2, ...)
1538 // or one
1539 // (model1, model2, model3, ...)
1540 // since both are supported
1541 //
1542 int start = -1;
1543 std::string name0 = a_name + std::to_string(0);
1544 std::string name1 = a_name + std::to_string(1);
1545 if (this->contains(name0.c_str()))
1546 {
1547 start = 0;
1548 name = name0;
1549 }
1550 else if (this->contains(name1.c_str()))
1551 {
1552 start = 1;
1553 name = name1;
1554 }
1555 else
1556 {
1557 if (!InTraversalMode())
1558 Util::ParmParseException(INFO,full(name), "Enumerations must begin with 0 or 1");
1559 }
1560
1561 //
1562 // Iterate over items called (model0), model1, model2, etc
1563 // until no more are found then exit.
1564 //
1565 for (int cntr = start; this->contains(name.c_str()); cntr++)
1566 {
1567 if (this->contains(name.c_str()))
1568 {
1569 T tmp;
1570 this->queryclass<T>(name, tmp);
1571 value.push_back(tmp);
1572 }
1573 name = a_name + std::to_string(cntr+1);
1574 }
1575
1576 return 0;
1577 }
1578
1579
1580 template <typename T>
1581 int
1582 query_enumerate(std::string a_name, std::vector<T> &value, int number = 1,
1583 const std::source_location &location = std::source_location::current())
1584 {
1585 {
1586 RecordInputAndContinue(a_name, location);
1587 }
1588 value.clear();
1589
1590 //
1591 // If only one is present with no subscript, then read
1592 // it only and return.
1593 //
1594 std::string name = a_name;
1595 if (this->contains(name))
1596 {
1597 for (int n = 0; n < number; n++)
1598 {
1599 T tmp;
1600 this->query_required(name, tmp);
1601 value.push_back(tmp);
1602 }
1603 return 0;
1604 }
1605
1606 //
1607 // Some logic to determine whether we are starting with zero
1608 // (model0, model1, model2, ...)
1609 // or one
1610 // (model1, model2, model3, ...)
1611 // since both are supported
1612 //
1613 int start = -1;
1614 std::string name0 = a_name + std::to_string(0);
1615 std::string name1 = a_name + std::to_string(1);
1616 if (this->contains(name0.c_str()))
1617 {
1618 start = 0;
1619 name = name0;
1620 }
1621 else if (this->contains(name1.c_str()))
1622 {
1623 start = 1;
1624 name = name1;
1625 }
1626 else
1627 {
1628 if (!InTraversalMode())
1629 Util::ParmParseException(INFO,full(name), "Enumerations must begin with 0 or 1");
1630 }
1631
1632 //
1633 // Iterate over items called (model0), model1, model2, etc
1634 // until no more are found then exit.
1635 //
1636 for (int cntr = start; this->contains(name.c_str()); cntr++)
1637 {
1638 if (this->contains(name.c_str()))
1639 {
1640 T tmp;
1641 this->query_required(name, tmp);
1642 value.push_back(tmp);
1643 }
1644 name = a_name + std::to_string(cntr+1);
1645 }
1646
1647 return 0;
1648 }
1649
1650 template <typename T>
1651 int
1652 queryarr_enumerate( std::string a_name, std::vector<std::vector<T>> &value, int number = 1,
1653 const std::source_location &location = std::source_location::current())
1654 {
1655 RecordInputAndContinue(a_name, location);
1656 value.clear();
1657
1658 std::string name = a_name;
1659 if (this->contains(name))
1660 {
1661 for (int n = 0; n < number; n++)
1662 {
1663 std::vector<T> tmp;
1664 this->queryarr_required(name, tmp);
1665 value.push_back(std::move(tmp));
1666 }
1667 return 0;
1668 }
1669
1670 int start = -1;
1671 std::string name0 = a_name + std::to_string(0);
1672 std::string name1 = a_name + std::to_string(1);
1673 if (this->contains(name0.c_str()))
1674 {
1675 start = 0;
1676 name = name0;
1677 }
1678 else if (this->contains(name1.c_str()))
1679 {
1680 start = 1;
1681 name = name1;
1682 }
1683 else
1684 {
1685 if (!InTraversalMode())
1686 Util::ParmParseException(INFO,full(name), "Enumerations must begin with 0 or 1");
1687 }
1688
1689 for (int cntr = start; this->contains(name.c_str()); cntr++)
1690 {
1691 std::vector<T> tmp;
1692 this->queryarr_required(name, tmp);
1693 value.push_back(std::move(tmp));
1694 name = a_name + std::to_string(cntr+1);
1695 }
1696
1697 return 0;
1698 }
1699
1700
1701
1702 int AnyUnusedInputs(bool inscopeonly = true, bool verbose = false)
1703 {
1704 int cnt = 0;
1705 for (auto li = m_table->begin(), End = m_table->end(); li != End; ++li)
1706 {
1707 if (!li->second.m_count)
1708 {
1709 if (inscopeonly && getPrefix() != "")
1710 {
1711 if (li->first.rfind(getPrefix()+".",0) != std::string::npos)
1712 {
1713 if (verbose) Util::Warning(INFO,li->first);
1714 cnt++;
1715 }
1716 }
1717 else
1718 {
1719 if (verbose) Util::Warning(INFO,li->first);
1720 cnt++;
1721 }
1722 }
1723 }
1724 return cnt;
1725 }
1726
1727 std::vector<std::string> GetUnusedInputs()
1728 {
1729 std::vector<std::string> ret;
1730 for (auto li = m_table->begin(), End = m_table->end(); li != End; ++li)
1731 {
1732 if (!li->second.m_count && li->first.rfind(getPrefix()+".",0) != std::string::npos)
1733 {
1734 ret.push_back(li->first);
1735 }
1736 }
1737 return ret;
1738 }
1739
1740 static int AllUnusedInputs()
1741 {
1742 ParmParse pp;
1743 int cnt = 0;
1744 for (auto li = pp.m_table->begin(), End = pp.m_table->end(); li != End; ++li)
1745 {
1746 if (!li->second.m_count)
1747 {
1748 Util::Warning(INFO,li->first);
1749 cnt++;
1750 }
1751 }
1752 return cnt;
1753 }
1754 std::string prefix ()
1755 {
1756 return getPrefix();
1757 }
1758 std::string full (std::string name)
1759 {
1760 std::string prefix = getPrefix();
1761 if (prefix != "") return getPrefix() + "." + name;
1762 else return name;
1763 }
1764
1765
1766 template<class T>
1767 void queryclass(std::string name, T * value,
1768 const std::source_location &location = std::source_location::current())
1769 {
1770 {
1771 RecordInputAndContinue(name, location);
1772 }
1773 auto old_prefix = m_prefix;
1774 try
1775 {
1776 if (old_prefix.empty()) m_prefix = name;
1777 else m_prefix.append(".").append(name);
1778 T::Parse(*value, *this);
1779 std::vector<std::string> unused_inputs = GetUnusedInputs();
1780 if (unused_inputs.size())
1781 {
1782 std::stringstream ss;
1783 for (unsigned int i=0; i < unused_inputs.size(); i++)
1784 ss << "\n\t" << unused_inputs[i];
1785 if (!InTraversalMode())
1786 Util::ParmParseException(INFO,name,"The following inputs were specified but not used",ss.str());
1787 }
1788 }
1789 catch (...)
1790 {
1791 m_prefix = old_prefix;
1792 if (!InTraversalMode())
1794 }
1795 m_prefix = old_prefix;
1796 }
1797 template<class T>
1798 void queryclass(std::string name, T & value,
1799 const std::source_location &location = std::source_location::current())
1800 {
1801 {
1802 RecordInputAndContinue(name, location);
1803 }
1804 auto old_prefix = m_prefix;
1805 try
1806 {
1807 if (old_prefix.empty()) m_prefix = name;
1808 else m_prefix.append(".").append(name);
1809 T::Parse(value, *this);
1810 std::vector<std::string> unused_inputs = GetUnusedInputs();
1811 if (unused_inputs.size())
1812 {
1813 std::stringstream ss;
1814 for (unsigned int i=0; i < unused_inputs.size(); i++)
1815 ss << "\n\t" << unused_inputs[i];
1816 if (!InTraversalMode())
1817 Util::ParmParseException(INFO,name,"The following inputs were specified but not used",ss.str());
1818 }
1819 }
1820 catch (std::runtime_error &e)
1821 {
1822 Util::ParmParseException(INFO,full(name),e.what());
1823 }
1824 catch (...)
1825 {
1826 m_prefix = old_prefix;
1827 if (!InTraversalMode())
1829 }
1830 m_prefix = old_prefix;
1831 }
1832
1833 template<class T>
1834 void queryclass(T * value,
1835 const std::source_location &location = std::source_location::current())
1836 {
1837 (void)location;
1838 try
1839 {
1840 T::Parse(*value, *this);
1841 }
1842 catch (std::runtime_error &e)
1843 {
1844 if (!InTraversalMode())
1846 }
1847 catch (...)
1848 {
1849 if (!InTraversalMode())
1851 }
1852 }
1853 template<class T>
1854 void queryclass(T & value,
1855 const std::source_location &location = std::source_location::current())
1856 {
1857 (void)location;
1858 try
1859 {
1860 T::Parse(value, *this);
1861 }
1862 catch (std::runtime_error &e)
1863 {
1864 if (!InTraversalMode())
1866 }
1867 catch (...)
1868 {
1869 if (!InTraversalMode())
1871 }
1872 }
1873
1874 //
1875 // Variadic template parsing operator to assign a pointer to
1876 // one of a set of possible class objects, then call that method's
1877 // Parse function.
1878 //
1879 // If there is more than one instantiating class, then type must be set.
1880 // Otherwise, no type is necessary.
1881 //
1882 template<typename... IC, typename PTRTYPE>
1883 void select ( std::string name, PTRTYPE *& ic_eta,
1884 const std::source_location &location = std::source_location::current())
1885 {
1886 auto args = forward_args();
1887 select<IC...>(std::move(name), ic_eta, args, location);
1888 }
1889
1890 template<typename... IC, typename... Args, typename PTRTYPE>
1891 void select ( std::string name, PTRTYPE *& ic_eta, ForwardArgs<Args...> args,
1892 const std::source_location &location = std::source_location::current())
1893 {
1894 try
1895 {
1896 std::string type_name = name + ".type";
1897 std::vector<std::string> possiblevals = {std::string(IC::name)...};
1898
1899 if (InTraversalMode())
1900 {
1901 {
1902 RecordInputAndContinue(type_name, location, possiblevals);
1903 }
1904
1905 std::string original_type;
1906 bool had_original_type = this->contains(type_name.c_str());
1907 if (had_original_type)
1908 amrex::ParmParse::query(type_name.c_str(), original_type);
1909
1910 auto set_select_value = [&](const std::string &select_value)
1911 {
1912 this->remove(type_name.c_str());
1913 this->add(type_name.c_str(), select_value);
1914 };
1915
1916 auto restore_select_value = [&]()
1917 {
1918 this->remove(type_name.c_str());
1919 if (had_original_type)
1920 this->add(type_name.c_str(), original_type);
1921 };
1922
1923 auto traverse_one = [&]<typename T>()
1924 {
1925 std::string select_value = T::name;
1926 set_select_value(select_value);
1927 PrintTraversalBranch(type_name, select_value);
1928 TraversalBranchScope branch(*this, type_name, select_value);
1929 PTRTYPE *tmp = ConstructSelected<T>(args, *this, name + "." + select_value);
1930 delete tmp;
1931 };
1932
1933 (traverse_one.template operator()<IC>(), ...);
1934 restore_select_value();
1935 ic_eta = nullptr;
1936 return;
1937 }
1938
1939 // if there is only one IC arg provided, we don't need to check the type - assume that
1940 // it is the default.
1941 if constexpr (sizeof...(IC) == 0)
1942 {
1943 using first_IC = std::tuple_element_t<0, std::tuple<IC...>>;
1944 ic_eta = ConstructSelected<first_IC>(args, *this, name + "." + std::string(first_IC::name));
1945 }
1946 // otherwise, check the type.
1947 else
1948 {
1949 std::string type = "";
1950 this->query_required(type_name, type);
1951 bool matched = (( type == IC::name
1952 ? (ic_eta = ConstructSelected<IC>(args, *this, name + "." + std::string(IC::name))),
1953 true
1954 : false) || ...);
1955 if (!matched)
1956 if (!InTraversalMode())
1957 Util::ParmParseException(INFO,full(name), type, " not a valid type for ", name);
1958 }
1959 }
1960 catch (std::runtime_error &e)
1961 {
1962 if (!InTraversalMode())
1964 }
1965 catch (...)
1966 {
1967 if (!InTraversalMode())
1969 }
1970 }
1971
1972 //
1973 // Identical to the above, except the first class is the default. A first
1974 // class without a ParmParse constructor is constructed directly when
1975 // no type is specified.
1976 //
1977 template<typename FirstIC, typename... IC, typename PTRTYPE>
1978 void select_default ( std::string name, PTRTYPE *& ic_eta,
1979 const std::source_location &location = std::source_location::current())
1980 {
1981 auto args = forward_args();
1982 select_default<FirstIC, IC...>(std::move(name), ic_eta, args, location);
1983 }
1984
1985 template<typename FirstIC, typename... IC, typename... Args, typename PTRTYPE>
1986 void select_default ( std::string name, PTRTYPE *& ic_eta, ForwardArgs<Args...> args,
1987 const std::source_location &location = std::source_location::current())
1988 {
1989 std::string type = "";
1990 std::string type_name = name + ".type";
1991 constexpr bool has_unnamed_default =
1993 HasSelectedConstructor<FirstIC, Args...>);
1994 std::vector<std::string> possiblevals;
1995 AppendSelectName<FirstIC>(possiblevals, args);
1996 (AppendSelectName<IC>(possiblevals, args), ...);
1997
1998 if (InTraversalMode())
1999 {
2000 {
2001 RecordInputAndContinue( type_name, location, possiblevals,
2002 std::nullopt, has_unnamed_default);
2003 }
2004
2005 std::string original_type;
2006 bool had_original_type = this->contains(type_name.c_str());
2007 if (had_original_type)
2008 amrex::ParmParse::query(type_name.c_str(), original_type);
2009
2010 auto set_select_value = [&](const std::string &select_value)
2011 {
2012 this->remove(type_name.c_str());
2013 this->add(type_name.c_str(), select_value);
2014 };
2015
2016 auto restore_select_value = [&]()
2017 {
2018 this->remove(type_name.c_str());
2019 if (had_original_type)
2020 this->add(type_name.c_str(), original_type);
2021 };
2022
2023 auto traverse_one = [&]<typename T>()
2024 {
2025 if constexpr (HasSelectName<T>::value && HasSelectedConstructor<T, Args...>)
2026 {
2027 std::string select_value = T::name;
2028 set_select_value(select_value);
2029 PrintTraversalBranch(type_name, select_value);
2030 TraversalBranchScope branch(*this, type_name, select_value);
2031 PTRTYPE *tmp = ConstructSelected<T>(args, *this, name + "." + select_value);
2032 delete tmp;
2033 }
2034 };
2035
2036 traverse_one.template operator()<FirstIC>();
2037 (traverse_one.template operator()<IC>(), ...);
2038 restore_select_value();
2039 ic_eta = nullptr;
2040 return;
2041 }
2042
2043 if constexpr ( HasSelectName<FirstIC>::value &&
2044 HasSelectedConstructor<FirstIC, Args...>)
2045 {
2046 this->query_default(type_name, type, std::string(FirstIC::name));
2047 }
2048 else
2049 {
2050 if (!this->contains(type_name.c_str()))
2051 {
2052 ic_eta = ConstructSelectDefault<FirstIC>(args);
2053 return;
2054 }
2055 this->query_required(type_name, type);
2056 }
2057
2058 bool matched = TrySelectNamed<FirstIC>(type, name, ic_eta, args, *this);
2059 matched = matched || (TrySelectNamed<IC>(type, name, ic_eta, args, *this) || ...);
2060
2061 if (!matched && !InTraversalMode())
2062 Util::ParmParseException(INFO,full(name), type," not a valid type for ",name);
2063 }
2064
2065
2066 //
2067 //
2068 template<typename... IC, typename PTRTYPE>
2069 void select_enumerate ( std::string a_name, std::vector<PTRTYPE*> & value,
2070 const std::source_location &location = std::source_location::current())
2071 {
2072 auto args = forward_args();
2073 select_enumerate<IC...>(std::move(a_name), value, args, location);
2074 }
2075
2076 template<typename... IC, typename... Args, typename PTRTYPE>
2077 void select_enumerate ( std::string a_name, std::vector<PTRTYPE*> & value, ForwardArgs<Args...> args,
2078 const std::source_location &location = std::source_location::current())
2079 {
2080 RecordInputAndContinue(a_name, location);
2081 value.clear();
2082
2083 if (InTraversalMode())
2084 {
2085 PTRTYPE *tmp = nullptr;
2086 const std::string template_name = a_name + "0";
2087 this->select<IC...>(template_name, tmp, args, location);
2088 InputScraper::CaptureSequenceTemplate(*this, a_name, template_name);
2089 return;
2090 }
2091
2092 //
2093 // If only one is present with no subscript, then read
2094 // it only and return.
2095 //
2096 std::string name = a_name;
2097 if (this->contains(name))
2098 {
2099 PTRTYPE *tmp;
2100 this->select<IC...>(a_name, tmp, args, location);
2101 value.push_back(tmp);
2102 return;
2103 }
2104
2105 //
2106 // Some logic to determine whether we are starting with zero
2107 // (model0, model1, model2, ...)
2108 // or one
2109 // (model1, model2, model3, ...)
2110 // since both are supported
2111 //
2112 int start = -1;
2113 std::string name0 = a_name + std::to_string(0);
2114 std::string name1 = a_name + std::to_string(1);
2115 if (this->contains(name0.c_str()))
2116 {
2117 start = 0;
2118 name = name0;
2119 }
2120 else if (this->contains(name1.c_str()))
2121 {
2122 start = 1;
2123 name = name1;
2124 }
2125 else
2126 {
2127 if (!InTraversalMode())
2128 Util::ParmParseException(INFO,full(name), "Enumerations must begin with 0 or 1");
2129 }
2130
2131 //
2132 // Iterate over items called (model0), model1, model2, etc
2133 // until no more are found then exit.
2134 //
2135 for (int cntr = start; this->contains(name.c_str()); cntr++)
2136 {
2137 if (this->contains(name.c_str()))
2138 {
2139 PTRTYPE *tmp;
2140 this->select<IC...>(name, tmp, args, location);
2141 value.push_back(tmp);
2142 }
2143 name = a_name + std::to_string(cntr+1);
2144 }
2145 }
2146
2147
2148
2149 //
2150 // Similar to select but specialized for main functions
2151 //
2152 template<typename... INTEGRATOR, typename... Args, typename PTRTYPE>
2153 void select_main (PTRTYPE *& ic_eta, Args&&... args)
2154 {
2155 std::string type = "";
2156
2157 this->query_required("alamo.program", type);
2158
2159 bool matched = ((type == INTEGRATOR::name
2160 ? (ic_eta = new INTEGRATOR(std::forward<Args>(args)..., (*this))),
2161 true
2162 : false) || ...);
2163 if (!matched)
2164 if (!InTraversalMode())
2165 Util::ParmParseException(INFO,getPrefix(),type," not a valid type for ",type);
2166 }
2167
2168 //
2169 // Similar to select_main but works for one function only
2170 // and doesn't require a type specifier.
2171 //
2172
2173 // with variadic arguments
2174 template<typename INTEGRATOR, typename Args, typename PTRTYPE>
2175 void select_only (PTRTYPE *& ic_eta, Args&& args)
2176 {
2177 ic_eta = new INTEGRATOR(std::forward<Args>(args), (*this));
2178 }
2179 // without variadic arguments
2180 template<typename INTEGRATOR, typename PTRTYPE>
2181 void select_only (PTRTYPE *& ic_eta)
2182 {
2183 ic_eta = new INTEGRATOR((*this));
2184 }
2185
2186
2187 //
2188 // functionally simlar to other kinds of select, execpt works on
2189 // template-based static dispatch.
2190 //
2191
2192 template <typename... OBJ, typename CLASS>
2193 requires (!std::is_pointer_v<std::remove_reference_t<CLASS>>)
2194 void select(std::string name, CLASS& value,
2195 const std::source_location &location = std::source_location::current())
2196 {
2197#if !AMREX_DEVICE_COMPILE
2198 auto args = forward_args();
2199 select<OBJ...>(std::move(name), value, args, location);
2200#else
2201 Util::IgnoreUnused(name, value, location);
2202#endif
2203 }
2204
2205 template <typename... OBJ, typename CLASS, typename... Args>
2206 requires (!std::is_pointer_v<std::remove_reference_t<CLASS>>)
2207 void select(std::string name, CLASS& value, ForwardArgs<Args...> args,
2208 const std::source_location &location = std::source_location::current())
2209 {
2210#if !AMREX_DEVICE_COMPILE
2211 pushPrefix(name);
2212 if (InTraversalMode())
2213 {
2214 std::vector<std::string> possiblevals = {std::string(OBJ::name)...};
2215 {
2216 RecordInputAndContinue("type", location, possiblevals);
2217 }
2218
2219 std::string original_type;
2220 bool had_original_type = this->contains("type");
2221 if (had_original_type)
2222 amrex::ParmParse::query("type", original_type);
2223 int original_selected = value.selected;
2224
2225 static_polymorphism_traverser<CLASS, 0, OBJ...>(value, args);
2226
2227 this->remove("type");
2228 if (had_original_type)
2229 this->add("type", original_type);
2230 value.selected = original_selected;
2231 }
2232 else
2233 static_polymorphism_parser<CLASS, 0, OBJ...>(value, args);
2234 popPrefix();
2235#else
2236 Util::IgnoreUnused(name, value, args, location);
2237#endif
2238 }
2239
2240private:
2241 //
2242 // This function is a virtual "swtich / case" block for static
2243 // dispatch. It works on a faux-virtual class "CLASS" that must
2244 // contain a tuple of "obj" with each "obj" being a derived type.
2245 // Recursion is used to unroll the list, identify the correct class
2246 // based on "name/type", set the "selected" index, then call the
2247 // appropriate class' Parse function.
2248 //
2249 // This is only for use by the "select" functions.
2250 //
2251 template <typename CLASS, int N, typename... OBJ, typename... Args>
2253 {
2254 if constexpr (N < sizeof...(OBJ))
2255 {
2256 std::string type = value.names[N];
2257 this->remove("type");
2258 this->add("type", type);
2259 value.selected = N;
2260
2261 PrintTraversalBranch("type", type);
2262 {
2263 TraversalBranchScope branch(*this, "type", type);
2264 pushPrefix(type);
2265 std::apply(
2266 [&](auto &...parse_args)
2267 {
2268 std::get<N>(value.obj).Parse(
2269 std::get<N>(value.obj), *this, parse_args...);
2270 },
2271 args.values);
2272 popPrefix();
2273 }
2274
2275 static_polymorphism_traverser<CLASS, N+1, OBJ...>(
2276 value, args);
2277 }
2278 }
2279
2280 template <typename CLASS, int N, typename... OBJ, typename... Args>
2282 {
2283 if constexpr (N == 0)
2284 {
2285 std::string type;
2286 query_default("type",type,value.names[0]);
2287
2288 for (unsigned int i = 0; i < sizeof...(OBJ); i++)
2289 if (type == value.names[i])
2290 value.selected = i;
2291
2292 if (value.selected < 0)
2293 if (!InTraversalMode())
2295 "Error reading " + getPrefix() +
2296 ", invalid type " + type);
2297
2298
2299 pushPrefix(type);
2300 }
2301
2302 if constexpr (N < sizeof...(OBJ))
2303 {
2304 if (value.selected == N)
2305 {
2306 std::apply(
2307 [&](auto &...parse_args)
2308 {
2309 std::get<N>(value.obj).Parse(
2310 std::get<N>(value.obj), *this, parse_args...);
2311 },
2312 args.values);
2313 popPrefix();
2314 return;
2315 }
2316 else
2317 return static_polymorphism_parser<CLASS, N+1, OBJ...>(
2318 value, args);
2319 }
2320 else Util::Abort(INFO);
2321 }
2322
2323public:
2324
2325 template <int N>
2326 void query_exactly( std::vector<std::string> names, std::pair<std::string, Set::Scalar> values[N],
2327 std::vector<Unit> units = std::vector<Unit>(),
2328 const std::source_location &location = std::source_location::current())
2329 {
2330 for (const auto &name : names)
2331 RecordInputAndContinue(name, location, names);
2332 std::vector<std::string> unit_names;
2333 for (const auto &unit : units)
2334 unit_names.push_back(unit.normalized_unitstring());
2335 RecordConstraint("exactly", N, names, unit_names, location);
2336
2337 if (InTraversalMode())
2338 {
2339 int cnt = 0;
2340 for (unsigned int n = 0; n < names.size() && cnt < N; n++)
2341 {
2342 if (!contains(names[n].c_str())) continue;
2343
2344 values[cnt].first = names[n];
2345 if (units.size() == 0)
2346 amrex::ParmParse::query(names[n].c_str(), values[cnt].second);
2347 else
2348 {
2349 std::string strvalue;
2350 amrex::ParmParse::query(names[n].c_str(), strvalue);
2351 Unit read = Unit::Parse(strvalue);
2352 values[cnt].second = read.normalized_value();
2353 }
2354 cnt++;
2355 }
2356 for (unsigned int n = 0; n < names.size() && cnt < N; n++)
2357 {
2358 if (contains(names[n].c_str())) continue;
2359
2360 values[cnt].first = names[n];
2361 values[cnt].second = 1.0;
2362 cnt++;
2363 }
2364 return;
2365 }
2366
2367 try
2368 {
2369 Util::AssertException( INFO,TEST(units.size() == 0 || units.size() == names.size()),
2370 "# of units must be 0, 1, or ", names.size(), " but got ", units.size());
2371
2372 int cnt = 0;
2373 std::vector<std::string> read;
2374 for (unsigned int n = 0; n < names.size(); n++)
2375 {
2376 if (amrex::ParmParse::contains(names[n].c_str()))
2377 {
2378 read.push_back(names[n]);
2379 cnt++;
2380 }
2381 }
2382 Util::AssertException( INFO, TEST(cnt == N),
2383 " Incorrect number of values specified: only ", N,
2384 " values are allowed, but received ",
2385 Util::String::Join(read,", "));
2386
2387
2388 cnt = 0;
2389 for (unsigned int n = 0; n < names.size(); n++)
2390 {
2391 if (amrex::ParmParse::contains(names[n].c_str()))
2392 {
2393 values[cnt].first = names[n];
2394
2395 if (units.size() == 0)
2396 query_required(names[n],values[cnt].second);
2397 else if (units.size() == 1)
2398 query_required(names[n],values[cnt].second,units[0]);
2399 else
2400 query_required(names[n],values[cnt].second,units[n]);
2401 cnt++;
2402 }
2403 }
2404 }
2405 catch(...)
2406 {
2407 std::string names_str = "[";
2408 for (unsigned int i = 0; i < names.size(); i++)
2409 {
2410 names_str += full(names[i]);
2411 if (i < names.size()-1) names_str += ", ";
2412 }
2413 names_str += "]";
2414 if (!InTraversalMode())
2415 Util::ParmParseException(INFO,names_str);
2416 }
2417 }
2418};
2419}
2420#endif
#define TEST(x)
Definition Util.H:25
#define INFO
Definition Util.H:24
static void CaptureSequenceTemplate(ParmParse &pp, const std::string &sequence_name, const std::string &template_name)
static std::string DirectiveName(const std::source_location &location)
static std::string InputValueString(const T &value)
static std::string InputArrayString(const std::vector< T > &values)
void select_default(std::string name, PTRTYPE *&ic_eta, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1978
int queryarr_required(std::string name, Set::Vector &value, Unit unit=Unit::Less(), const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1273
void RecordInputAndContinue(std::string name, const std::source_location &location, std::vector< std::string > options={}, std::optional< std::string > default_value=std::nullopt, bool has_unnamed_default=false, const std::source_location &handler_location=std::source_location::current())
Definition ParmParse.H:186
void queryclass(std::string name, T *value, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1767
static constexpr bool HasSelectedConstructor
Definition ParmParse.H:219
void forbid(std::string name, std::string explanation, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:301
int query_if_else(std::string name, TrueAction &&true_action, FalseAction &&false_action, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:862
static void SetTraversalMode(bool enabled)
Definition ParmParse.cpp:8
int queryarr_default(std::string name, std::vector< double > &value, std::vector< double > defaultvalue, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1439
void select(std::string name, PTRTYPE *&ic_eta, ForwardArgs< Args... > args, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1891
int queryarr(std::string name, Set::Matrix &value, Unit unit=Unit::Less(), const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1157
int query_validate(std::string name, int &value, std::vector< int > possibleintvals, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:569
int queryclass_enumerate(std::string a_name, std::vector< T > &value, int number=1, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1503
void ignore(std::string name, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:276
int queryarr_required(std::string name, std::vector< T > &value, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1223
int queryarr(std::string name, std::vector< T > &value, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1024
int query(std::string name, T &value, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:340
int query_file(std::string name, std::string &value, bool copyfile, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1012
void pushPrefix(const std::string prefix)
Definition ParmParse.H:283
int query_default(std::string name, std::string &value, const char *defaultvalue, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:917
static const InputNode & InputTree()
Definition ParmParse.cpp:26
void PrintTraversalBranch(std::string name, const std::string &value)
Definition ParmParse.cpp:71
int queryarr_default(std::string name, std::vector< double > &value, std::vector< std::string > defaultvalue, Unit unit, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1466
int query_validate(std::string name, std::string &value, std::vector< const char * > possiblecharvals, bool firstbydefault, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:628
int AnyUnusedInputs(bool inscopeonly=true, bool verbose=false)
Definition ParmParse.H:1702
void query_exactly(std::vector< std::string > names, std::pair< std::string, Set::Scalar > values[N], std::vector< Unit > units=std::vector< Unit >(), const std::source_location &location=std::source_location::current())
Definition ParmParse.H:2326
void select(std::string name, CLASS &value, ForwardArgs< Args... > args, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:2207
int queryarr_default(std::string name, Set::Vector &value, Set::Vector defaultvalue, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1359
int queryarr(std::string name, Set::Vector &value, Unit unit=Unit::Less(), const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1107
int queryarr_required(std::string name, std::vector< Set::Scalar > &value, Unit unit=Unit::Less(), const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1242
std::vector< std::string > GetUnusedInputs()
Definition ParmParse.H:1727
int query_required(std::string name, T &value, const Unit type, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:456
int query_default(std::string name, int &value, bool defaultvalue, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:937
static void SetTraversalOutputFile(std::string path)
Definition ParmParse.cpp:38
static void AppendSelectName(std::vector< std::string > &names, ForwardArgs< Args... > &)
Definition ParmParse.H:237
void queryclass(T *value, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1834
std::string getPrefix() const
Definition ParmParse.H:275
static bool checked_for_input_files
Definition ParmParse.H:173
void RecordInput(std::string name, std::string directive, const std::source_location &location, std::vector< std::string > options={}, std::optional< std::string > default_value=std::nullopt, bool has_unnamed_default=false)
Definition ParmParse.cpp:77
void queryclass(std::string name, T &value, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1798
static ForwardArgs< ForwardArgStorage< Args >... > forward_args(Args &&... args)
Definition ParmParse.H:153
std::string prefix()
Definition ParmParse.H:1754
int query_default(std::string name, T &value, T defaultvalue, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:492
void select_enumerate(std::string a_name, std::vector< PTRTYPE * > &value, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:2069
int queryunit(std::string name, Unit &value, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:351
int queryunit(std::string name, Set::Scalar &value, const Unit type, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:400
int query_file(std::string name, std::string &value, bool copyfile, bool checkfile, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:961
void Define()
Definition ParmParse.H:160
void static_polymorphism_parser(CLASS &value, ForwardArgs< Args... > &args)
Definition ParmParse.H:2281
int query_switch(std::string name, std::initializer_list< std::pair< std::string, std::function< void()> > > cases, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:714
static const std::string & TraversalOutputFile()
Definition ParmParse.cpp:44
std::conditional_t< std::is_lvalue_reference_v< Arg >, Arg, std::remove_cvref_t< Arg > > ForwardArgStorage
Definition ParmParse.H:150
int queryarr_default(std::string name, Set::Vector &value, std::string defaultvalue, Unit unit, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1321
int query_enumerate(std::string a_name, std::vector< T > &value, int number=1, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1582
int queryarr_enumerate(std::string a_name, std::vector< std::vector< T > > &value, int number=1, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1652
int query_default(std::string name, T &value, std::string defaultvalue, const Unit type, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:530
int query_file(std::string name, std::string &value, std::source_location loc=std::source_location::current())
Definition ParmParse.H:1017
static void WriteInputTreeJsonFile(const std::string &path)
Definition ParmParse.cpp:56
static int AllUnusedInputs()
Definition ParmParse.H:1740
InputScraper::InputNode InputNode
Definition ParmParse.H:139
static T * ConstructSelectDefault(ForwardArgs< Args... > &args)
Definition ParmParse.H:224
int queryarr(std::string name, std::vector< Set::Scalar > &value, Unit unit=Unit::Less(), const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1046
static bool InTraversalMode()
Definition ParmParse.cpp:14
int query_validate(std::string name, std::string &value, std::vector< const char * > possiblecharvals, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:694
void select_enumerate(std::string a_name, std::vector< PTRTYPE * > &value, ForwardArgs< Args... > args, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:2077
void select_default(std::string name, PTRTYPE *&ic_eta, ForwardArgs< Args... > args, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1986
int queryarr_default(std::string name, std::vector< std::string > &value, std::vector< std::string > defaultvalue, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1303
void popPrefix()
Definition ParmParse.H:291
static bool ShouldExecute()
Definition ParmParse.cpp:20
bool contains(std::string name, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:318
static void ClearInputTree()
Definition ParmParse.cpp:32
void select_only(PTRTYPE *&ic_eta, Args &&args)
Definition ParmParse.H:2175
void select_main(PTRTYPE *&ic_eta, Args &&... args)
Definition ParmParse.H:2153
void queryclass(T &value, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1854
int queryarr_default(std::string name, Set::Matrix &value, Set::Matrix def, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1399
int query_required(std::string name, T &value, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:421
void select_only(PTRTYPE *&ic_eta)
Definition ParmParse.H:2181
void RecordConstraint(std::string kind, int count, std::vector< std::string > members, std::vector< std::string > units, const std::source_location &location)
Definition ParmParse.cpp:90
std::string full(std::string name)
Definition ParmParse.H:1758
int query_if(std::string name, Action &&action, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:817
static bool IgnoreInTraversalMode(std::string note="This input parser is not yet compliant with traversal mode; its inputs are not fully documented.", const std::source_location &location=std::source_location::current())
Definition ParmParse.cpp:62
int queryunit(std::string name, Unit &value, const Unit type, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:376
void static_polymorphism_traverser(CLASS &value, ForwardArgs< Args... > &args)
Definition ParmParse.H:2252
static bool TrySelectNamed(const std::string &type, const std::string &name, PTRTYPE *&value, ForwardArgs< Args... > &args, ParmParse &pp)
Definition ParmParse.H:244
void select(std::string name, CLASS &value, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:2194
static void WriteInputTreeJson(std::ostream &os)
Definition ParmParse.cpp:50
static T * ConstructSelected(ForwardArgs< Args... > &args, ParmParse &pp, const std::string &name)
Definition ParmParse.H:202
void select(std::string name, PTRTYPE *&ic_eta, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1883
ParmParse(std::string arg)
Definition ParmParse.H:273
Initialize a spherical inclusion.
Definition BMP.H:20
amrex::Real Scalar
Definition Base.H:19
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, 1 > Vector
Definition Base.H:21
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, AMREX_SPACEDIM > Matrix
Definition Base.H:24
AMREX_FORCE_INLINE std::string Join(const std::vector< std::string > &vec, std::string separator="_")
Definition String.H:83
AMREX_FORCE_INLINE std::vector< std::string > Split(std::string &str, const char delim=' ')
Definition String.H:138
void DebugMessage(std::string, std::string, int, Args const &...)
Definition Util.H:187
AMREX_FORCE_INLINE void AssertException(std::string file, std::string func, int line, std::string smt, bool pass, Args const &... args)
Definition Util.H:265
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void IgnoreUnused(const Ts &...)
Definition Util.H:442
void CopyFileToOutputDir(std::string a_path, bool fullpath, std::string prefix)
Definition Util.cpp:140
void Warning(std::string file, std::string func, int line, Args const &... args)
Definition Util.H:213
void Message(std::string file, std::string func, int line, Args const &... args)
Definition Util.H:140
AMREX_GPU_HOST_DEVICE void Abort(const char *msg)
Definition Util.cpp:406
void ParmParseException(std::string file, std::string func, int line, std::string fullname, Args const &... args)
Definition Util.H:295
void Exception(std::string file, std::string func, int line, Args const &... args)
Definition Util.H:237
std::tuple< Args... > values
Definition ParmParse.H:143
ForwardArgs(Args... args)
Definition ParmParse.H:145
Definition Unit.H:21
bool isType(const Unit &test) const
Definition Unit.H:425
std::string normalized_unitstring() const
Definition Unit.H:515
static Unit Parse(double val, std::string unitstring, bool verbose=false)
Definition Unit.H:270
double normalized_value() const
Definition Unit.H:506
static Unit Less()
Definition Unit.H:197