diff --git a/.github/workflows/gcc.yml b/.github/workflows/gcc.yml index 26ad6eaf52..94f625e93f 100644 --- a/.github/workflows/gcc.yml +++ b/.github/workflows/gcc.yml @@ -295,7 +295,7 @@ jobs: run: | export CCACHE_COMPRESS=1 export CCACHE_COMPRESSLEVEL=10 - export CCACHE_MAXSIZE=40M + export CCACHE_MAXSIZE=100M export CCACHE_EXTRAFILES=${{ github.workspace }}/.clang-tidy export CCACHE_LOGFILE=${{ github.workspace }}/ccache.log.txt ccache -z @@ -360,7 +360,7 @@ jobs: run: | export CCACHE_COMPRESS=1 export CCACHE_COMPRESSLEVEL=10 - export CCACHE_MAXSIZE=315M + export CCACHE_MAXSIZE=400M export CCACHE_EXTRAFILES=${{ github.workspace }}/.clang-tidy export CCACHE_LOGFILE=${{ github.workspace }}/ccache.log.txt ccache -z @@ -616,7 +616,7 @@ jobs: run: | export CCACHE_COMPRESS=1 export CCACHE_COMPRESSLEVEL=10 - export CCACHE_MAXSIZE=30M + export CCACHE_MAXSIZE=100M export CCACHE_EXTRAFILES=${{ github.workspace }}/.clang-tidy export CCACHE_LOGFILE=${{ github.workspace }}/ccache.log.txt ccache -z diff --git a/.github/workflows/hip.yml b/.github/workflows/hip.yml index a38c1f6547..345d7c468b 100644 --- a/.github/workflows/hip.yml +++ b/.github/workflows/hip.yml @@ -32,7 +32,7 @@ jobs: run: | export CCACHE_COMPRESS=1 export CCACHE_COMPRESSLEVEL=10 - export CCACHE_MAXSIZE=100M + export CCACHE_MAXSIZE=150M ccache -z source /etc/profile.d/rocm.sh @@ -90,7 +90,7 @@ jobs: run: | export CCACHE_COMPRESS=1 export CCACHE_COMPRESSLEVEL=10 - export CCACHE_MAXSIZE=40M + export CCACHE_MAXSIZE=100M ccache -z source /etc/profile.d/rocm.sh @@ -142,7 +142,7 @@ jobs: run: | export CCACHE_COMPRESS=1 export CCACHE_COMPRESSLEVEL=10 - export CCACHE_MAXSIZE=60M + export CCACHE_MAXSIZE=100M ccache -z ./configure --dim 2 --with-hip yes --enable-eb yes --enable-xsdk-defaults yes --with-mpi no --with-omp no --single-precision yes --single-precision-particles yes diff --git a/.github/workflows/intel.yml b/.github/workflows/intel.yml index 36fc674ecd..227b0f9738 100644 --- a/.github/workflows/intel.yml +++ b/.github/workflows/intel.yml @@ -32,7 +32,7 @@ jobs: run: | export CCACHE_COMPRESS=1 export CCACHE_COMPRESSLEVEL=10 - export CCACHE_MAXSIZE=45M + export CCACHE_MAXSIZE=100M export CCACHE_DEPEND=1 ccache -z @@ -80,7 +80,7 @@ jobs: run: | export CCACHE_COMPRESS=1 export CCACHE_COMPRESSLEVEL=10 - export CCACHE_MAXSIZE=55M + export CCACHE_MAXSIZE=150M export CCACHE_DEPEND=1 ccache -z @@ -126,7 +126,7 @@ jobs: run: | export CCACHE_COMPRESS=1 export CCACHE_COMPRESSLEVEL=10 - export CCACHE_MAXSIZE=55M + export CCACHE_MAXSIZE=100M export CCACHE_DEPEND=1 ccache -z @@ -175,7 +175,7 @@ jobs: run: | export CCACHE_COMPRESS=1 export CCACHE_COMPRESSLEVEL=10 - export CCACHE_MAXSIZE=55M + export CCACHE_MAXSIZE=100M export CCACHE_DEPEND=1 ccache -z @@ -221,7 +221,7 @@ jobs: run: | export CCACHE_COMPRESS=1 export CCACHE_COMPRESSLEVEL=10 - export CCACHE_MAXSIZE=40M + export CCACHE_MAXSIZE=100M ccache -z set +e diff --git a/.github/workflows/smoke.yml b/.github/workflows/smoke.yml index 650ef144e8..d56e52c63e 100644 --- a/.github/workflows/smoke.yml +++ b/.github/workflows/smoke.yml @@ -29,7 +29,7 @@ jobs: run: | export CCACHE_COMPRESS=1 export CCACHE_COMPRESSLEVEL=10 - export CCACHE_MAXSIZE=40M + export CCACHE_MAXSIZE=100M export CCACHE_EXTRAFILES=${{ github.workspace }}/.clang-tidy export CCACHE_LOGFILE=${{ github.workspace }}/ccache.log.txt ccache -z diff --git a/Src/Base/AMReX_CoordSys.cpp b/Src/Base/AMReX_CoordSys.cpp index 757af532cc..a958d33a5b 100644 --- a/Src/Base/AMReX_CoordSys.cpp +++ b/Src/Base/AMReX_CoordSys.cpp @@ -164,7 +164,7 @@ CoordSys::UpperIndex(const Real* point) const noexcept IntVect ix; for (int k = 0; k < AMREX_SPACEDIM; k++) { - ix[k] = (int) ((point[k]-offset[k])/dx[k]); + ix[k] = (int) ((point[k]-offset[k])/dx[k]) + 1; } return ix; } @@ -330,6 +330,8 @@ CoordSys::GetEdgeVolCoord (Vector& vc, GetEdgeLoc(vc,region,dir); // // In R direction of RZ, vol coord = (r^2)/2 + // In R direction of SPHERICAL, vol coord = (r^3)/3 + // In theta direction of SPHERICAL, vol coord = -cos(theta) // #if (AMREX_SPACEDIM == 2) if (dir == 0 && c_sys == RZ) @@ -342,6 +344,29 @@ CoordSys::GetEdgeVolCoord (Vector& vc, vc[i] = 0.5_rt*r*r; } } + else if (c_sys == SPHERICAL) + { + if (dir == 0) + { + int len = static_cast(vc.size()); + AMREX_PRAGMA_SIMD + for (int i = 0; i < len; i++) + { + Real r = vc[i]; + vc[i] = r*r*r/3.0_rt; + } + } + else + { + int len = static_cast(vc.size()); + AMREX_PRAGMA_SIMD + for (int i = 0; i < len; i++) + { + Real theta = vc[i]; + vc[i] = -std::cos(theta); + } + } + } #elif (AMREX_SPACEDIM == 1) if (c_sys == SPHERICAL) { @@ -365,8 +390,11 @@ CoordSys::GetCellVolCoord (Vector& vc, // are identical to physical distance from axis. // GetCellLoc(vc,region,dir); + // - // In R direction of RZ, vol coord = (r^2)/2. + // In R direction of RZ, vol coord = (r^2)/2 + // In R direction of SPHERICAL, vol coord = (r^3)/3 + // In theta direction of SPHERICAL, vol coord = -cos(theta) // #if (AMREX_SPACEDIM == 2) if (dir == 0 && c_sys == RZ) @@ -379,6 +407,29 @@ CoordSys::GetCellVolCoord (Vector& vc, vc[i] = 0.5_rt*r*r; } } + else if (c_sys == SPHERICAL) + { + if (dir == 0) + { + int len = static_cast(vc.size()); + AMREX_PRAGMA_SIMD + for (int i = 0; i < len; i++) + { + Real r = vc[i]; + vc[i] = r*r*r/3.0_rt; + } + } + else + { + int len = static_cast(vc.size()); + AMREX_PRAGMA_SIMD + for (int i = 0; i < len; i++) + { + Real theta = vc[i]; + vc[i] = -std::cos(theta); + } + } + } #elif (AMREX_SPACEDIM == 1) if (c_sys == SPHERICAL) { int len = static_cast(vc.size()); @@ -462,6 +513,9 @@ CoordSys::Volume (const Real xlo[AMREX_SPACEDIM], #if (AMREX_SPACEDIM==2) case RZ: return static_cast(0.5*TWOPI)*(xhi[1]-xlo[1])*(xhi[0]*xhi[0]-xlo[0]*xlo[0]); + case SPHERICAL: + return static_cast(TWOPI/3.)*(std::cos(xlo[1])-std::cos(xhi[1])) * + (xhi[0]-xlo[0])*(xhi[0]*xhi[0]+xhi[0]*xlo[0]+xlo[0]*xlo[0]); #endif default: AMREX_ASSERT(0); @@ -496,6 +550,16 @@ CoordSys::AreaLo (const IntVect& point, int dir) const noexcept // NOLINT(readab AMREX_ASSERT(0); } return 0._rt; // to silent compiler warning + case SPHERICAL: + LoNode(point,xlo); + switch (dir) + { + case 0: return Real(TWOPI)*xlo[0]*xlo[0]*(std::cos(xlo[1]) - std::cos(xlo[1]+dx[1])); + case 1: return (xlo[0]+xlo[0]+dx[0])*dx[0]*std::sin(xlo[1])*static_cast(0.5*TWOPI); + default: + AMREX_ASSERT(0); + } + return 0._rt; // to silent compiler warning default: AMREX_ASSERT(0); } @@ -540,6 +604,16 @@ CoordSys::AreaHi (const IntVect& point, int dir) const noexcept // NOLINT(readab AMREX_ASSERT(0); } return 0._rt; // to silent compiler warning + case SPHERICAL: + HiNode(point,xhi); + switch (dir) + { + case 0: return Real(TWOPI)*xhi[0]*xhi[0]*(std::cos(xhi[1]-dx[1]) - std::cos(xhi[1])); + case 1: return (xhi[0]+xhi[0]-dx[0])*dx[0]*std::sin(xhi[1])*static_cast(0.5*TWOPI); + default: + AMREX_ASSERT(0); + } + return 0._rt; // to silent compiler warning default: AMREX_ASSERT(0); } diff --git a/Src/Base/AMReX_Geometry.H b/Src/Base/AMReX_Geometry.H index 6231fbd1f9..1b7bae1a7d 100644 --- a/Src/Base/AMReX_Geometry.H +++ b/Src/Base/AMReX_Geometry.H @@ -264,7 +264,7 @@ public: vol = dx[0] * dx[1]; } - else { + else if (coord == CoordSys::RZ) { // Cylindrical Real r_l = geomdata.ProbLo()[0] + static_cast(point[0]) * dx[0]; @@ -273,6 +273,19 @@ public: constexpr Real pi = Real(3.1415926535897932); vol = pi * (r_l + r_r) * dx[0] * dx[1]; } + else { + // Spherical + + Real r_l = geomdata.ProbLo()[0] + static_cast(point[0]) * dx[0]; + Real r_r = geomdata.ProbLo()[0] + static_cast(point[0]+1) * dx[0]; + + Real theta_l = geomdata.ProbLo()[1] + static_cast(point[1]) * dx[1]; + Real theta_r = geomdata.ProbLo()[1] + static_cast(point[1]+1) * dx[1]; + + constexpr Real twoThirdsPi = static_cast(2.0 * 3.1415926535897932 / 3.0); + vol = twoThirdsPi * (std::cos(theta_l) - std::cos(theta_r)) * dx[0] * + (r_r*r_r + r_r*r_l + r_l*r_l); + } #else diff --git a/Src/Base/AMReX_ParmParse.H b/Src/Base/AMReX_ParmParse.H index c7ed675580..dc4fa07fb4 100644 --- a/Src/Base/AMReX_ParmParse.H +++ b/Src/Base/AMReX_ParmParse.H @@ -11,10 +11,11 @@ #include #include -#include +#include #include #include #include +#include #include namespace amrex { @@ -27,6 +28,32 @@ class IntVectND; using IntVect = IntVectND; class RealVect; +namespace ppdetail { + template + struct ArithmeticOptional_TT : std::false_type {}; + + template + struct ArithmeticOptional_TT>> + : std::true_type + { + using value_type = T; + }; + + template + struct ArithmeticOptional_TT, + std::enable_if_t>> + : std::true_type + { + using value_type = T; + }; + + template + inline constexpr bool IsArithmeticOptional_v = ArithmeticOptional_TT::value; + + template + using underlying_type_t = typename ArithmeticOptional_TT::value_type; +} + // // ParmParse class implements a simple database for the storage and // retrieval of command-line and input-file arguments. The entries are @@ -1428,6 +1455,100 @@ public: } } + /** + * \brief Query T with Parser, but treat the number as double precision + * during parsing. + * + * The final result is cast to T. It may result in a runtime error if + * the conversion is not safe. T is either arithmetic type or + * std::optional of arithmetic type. + */ + template , int> = 0> + int queryAsDouble (const char* name, T& ref) const + { + using value_type = ppdetail::underlying_type_t; + double dref; + int exist = queryWithParser(name, dref); + if (exist) { + if (std::is_integral_v) { + dref = std::round(dref); + } + auto vref = static_cast(dref); + if constexpr (std::is_integral_v && !std::is_same_v) { + if (static_cast(vref) != dref) { + amrex::Abort("ParmParse:: queryAsDouble is not safe"); + } + } + ref = vref; + } + return exist; + } + + /** + * \brief Query T array with Parser, but treat the number as double + * precision during parsing. + * + * The final result is cast to T's. It may result in a runtime error if + * the conversion is not safe. T is either arithmetic type or + * std::optional of arithmetic type. + */ + template , int> = 0> + int queryarrAsDouble (const char* name, int nvals, T* ref) const + { + using value_type = ppdetail::underlying_type_t; + std::vector dref(nvals); + int exist = queryarrWithParser(name, nvals, dref.data()); + if (exist) { + for (int i = 0; i < nvals; ++i) { + if (std::is_integral_v) { + dref[i] = std::round(dref[i]); + } + auto vref = static_cast(dref[i]); + if constexpr (std::is_integral_v && !std::is_same_v) { + if (static_cast(vref) != dref[i]) { + amrex::Abort("ParmParse:: queryarrAsDouble is not safe"); + } + } + ref[i] = vref; + } + } + return exist; + } + + /** + * \brief Get T with Parser, but treat the number as double precision + * during parsing. + * + * The final result is cast to T. It may result in a runtime error if + * the conversion is not safe. T is either arithmetic type or + * std::optional of arithmetic type. + */ + template , int> = 0> + void getAsDouble (const char* name, T& ref) const + { + int exist = this->queryAsDouble(name, ref); + if (!exist) { + amrex::Error(std::string("ParmParse::getAsDouble: failed to get ")+name); + } + } + + /** + * \brief Get T array with Parser, but treat the number as double + * precision during parsing. + * + * The final result is cast to T's. It may result in a runtime error if + * the conversion is not safe. T is either arithmetic type or + * std::optional of arithmetic type. + */ + template , int> = 0> + void getarrAsDouble (const char* name, int nvals, T* ref) const + { + int exist = this->queryarrAsDouble(name, nvals, ref); + if (!exist) { + amrex::Error(std::string("ParmParse::getarrAsDouble: failed to get ")+name); + } + } + //! Remove given name from the table. int remove (const char* name); diff --git a/Src/Base/AMReX_ParmParse.cpp b/Src/Base/AMReX_ParmParse.cpp index 767bd2a4d0..9d61fad89f 100644 --- a/Src/Base/AMReX_ParmParse.cpp +++ b/Src/Base/AMReX_ParmParse.cpp @@ -991,20 +991,34 @@ pp_make_parser (std::string const& func, Vector const& vars, symbols.erase(var); } + bool recursive = false; + auto& recursive_symbols = g_parser_recursive_symbols[OpenMP::get_thread_num()]; + for (auto const& s : symbols) { value_t v = 0; bool r = false; for (auto const& pf : prefixes) { + std::string pfs = pf + s; + if (auto found = recursive_symbols.find(pfs); found != recursive_symbols.end()) { + recursive = true; + continue; + } if (use_querywithparser) { - r = squeryWithParser(table, parser_prefix, pf+s, v); + r = squeryWithParser(table, parser_prefix, pfs, v); } else { - r = squeryval(table, parser_prefix, pf+s, v, + r = squeryval(table, parser_prefix, pfs, v, ParmParse::FIRST, ParmParse::LAST); } if (r) { break; } } if (r == false) { - amrex::Error("ParmParse: failed to parse " + func); + std::string msg("ParmParse: failed to parse "+func); + if (recursive) { + msg.append(" due to recursive symbol ").append(s); + } else { + msg.append(" due to unknown symbol ").append(s); + } + amrex::Error(msg); } parser.setConstant(s, v); } diff --git a/Src/Base/AMReX_TinyProfiler.cpp b/Src/Base/AMReX_TinyProfiler.cpp index 22bcaa6173..32b35bf770 100644 --- a/Src/Base/AMReX_TinyProfiler.cpp +++ b/Src/Base/AMReX_TinyProfiler.cpp @@ -881,6 +881,7 @@ TinyProfiler::PrintMemStats (std::map& memstats, if (allstatsstr.size() == 1 || !os) { return; } IOFormatSaver iofmtsaver(*os); + *os << std::setfill(' '); int lenhline = 0; for (auto i : maxlen) { diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 29489e8d4f..a5ec9e1cf4 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -122,7 +122,7 @@ else() # List of subdirectories to search for CMakeLists. # set( AMREX_TESTS_SUBDIRS Amr AsyncOut CLZ CTOParFor DeviceGlobal Enum - MultiBlock MultiPeriod Parser Parser2 Reinit + MultiBlock MultiPeriod ParmParse Parser Parser2 Reinit RoundoffDomain) if (AMReX_PARTICLES) diff --git a/Tests/ParmParse/CMakeLists.txt b/Tests/ParmParse/CMakeLists.txt new file mode 100644 index 0000000000..9c0e7f321d --- /dev/null +++ b/Tests/ParmParse/CMakeLists.txt @@ -0,0 +1,9 @@ +foreach(D IN LISTS AMReX_SPACEDIM) + set(_sources main.cpp) + set(_input_files inputs) + + setup_test(${D} _sources _input_files) + + unset(_sources) + unset(_input_files) +endforeach() diff --git a/Tests/ParmParse/GNUmakefile b/Tests/ParmParse/GNUmakefile new file mode 100644 index 0000000000..cacc297050 --- /dev/null +++ b/Tests/ParmParse/GNUmakefile @@ -0,0 +1,24 @@ +AMREX_HOME ?= ../../amrex + +DEBUG = TRUE + +DIM = 3 + +COMP = gcc + +USE_MPI = FALSE +USE_OMP = FALSE +USE_CUDA = FALSE +USE_HIP = FALSE +USE_SYCL = FALSE + +BL_NO_FORT = TRUE + +TINY_PROFILE = FALSE + +include $(AMREX_HOME)/Tools/GNUMake/Make.defs + +include ./Make.package +include $(AMREX_HOME)/Src/Base/Make.package + +include $(AMREX_HOME)/Tools/GNUMake/Make.rules diff --git a/Tests/ParmParse/Make.package b/Tests/ParmParse/Make.package new file mode 100644 index 0000000000..6b4b865e8f --- /dev/null +++ b/Tests/ParmParse/Make.package @@ -0,0 +1 @@ +CEXE_sources += main.cpp diff --git a/Tests/ParmParse/inputs b/Tests/ParmParse/inputs new file mode 100644 index 0000000000..ab876ad9ef --- /dev/null +++ b/Tests/ParmParse/inputs @@ -0,0 +1,64 @@ + +amrex.signal_handling = 0 +amrex.throw_exception = 1 +amrex.v = 0 + +name = "I am w" \ + "line 2" + +b = ((1, 2, 3) (7, 8,9) (1,0, 1)) + +# three numbers. whitespaces inside `""` are okay. +f = 3+4 99 "5 + 6" + +# two numbers. `\` is for continuation +g = 3.1+4.1 \ + 5.0+6.6 + +# two numbers unless using [query|get]WithParser +w = 1 -2 + +my_constants.alpha = 5. +amrex.c = c + +# must use [query|get]WithParser +amrex.foo = sin( pi/2 ) + alpha + -amrex.c**2.5/c^2 + +# either [query|get] or [query|get]WithParser is okay +amrex.bar = sin(pi/2)+alpha+-amrex.c**2.5/c^2 + +# one string across multiple lines +amrex.bar2 = "sin(pi/2)+alpha+ + -amrex.c**2.5/c^2" + +geom.prob_lo = -2*sin(pi/4)/sqrt(2) -sin(pi/2)-cos(pi/2) (sin(pi*3/2)+cos(pi*3/2)) + +# three numbers. `\` is for continuation +geom.prob_hi = "2*sin(pi/4)/sqrt(2)" \ + "sin(pi/2) + cos(pi/2)" \ + -(sin(pi*3/2)+cos(pi*3/2)) + +long_int_1 = 123456789012345 +long_int_2 = 123'456'789'012'345 +long_int_3 = 1.23456789012345e14 + +# recursion like this is not allowed +code.a = code.b +code.b = code.c +code.c = code.d +code.d = code.a + +# Recursion like this is allowed, if my_constants is added as parser prefix. +# It's same as max_steps = my_constants.max_steps +my_constants.max_steps = 40 +max_steps = max_steps +warpx.max_steps = max_steps + +# query int as double +my_constants.lx = 40.e-6 +my_constants.dx = 6.25e-7 +my_constants.nx = lx/dx +n_cell = nx nx nx +ny = nx + +do_this = 1 diff --git a/Tests/ParmParse/main.cpp b/Tests/ParmParse/main.cpp new file mode 100644 index 0000000000..68612e82ea --- /dev/null +++ b/Tests/ParmParse/main.cpp @@ -0,0 +1,143 @@ +#include +#include +#include +#include +#include + +using namespace amrex; + +int main(int argc, char* argv[]) +{ + amrex::Initialize(argc,argv); + { + ParmParse::SetParserPrefix("physical_constants"); + ParmParse pp("physical_constants"); + pp.add("c", 299792458.); + pp.add("pi", 3.14159265358979323846); + } + { + ParmParse pp; + + std::string name; + pp.query("name", name); + AMREX_ALWAYS_ASSERT(name == "I am w"); + pp.query("name", name, 1); + AMREX_ALWAYS_ASSERT(name == "line 2"); + + Box box; + pp.query("b", box); + AMREX_ALWAYS_ASSERT(box == Box(IntVect(AMREX_D_DECL(1,2,3)), + IntVect(AMREX_D_DECL(7,8,9)), + IntVect(AMREX_D_DECL(1,0,1)))); + + double f0 = -1; + pp.query("f", f0); + AMREX_ALWAYS_ASSERT(f0 == 7); + + std::vector f; + pp.queryarr("f", f); + AMREX_ALWAYS_ASSERT(f[0] == 7 && f[1] == 99 && f[2] == 11); + + std::vector g; + pp.queryarr("g", g); + AMREX_ALWAYS_ASSERT(amrex::almostEqual(g[0], 7.2) && + amrex::almostEqual(g[1], 11.6)); + + double w; + pp.query("w", w); + AMREX_ALWAYS_ASSERT(w == 1); + pp.queryWithParser("w", w); + AMREX_ALWAYS_ASSERT(w == -1); + } + { + ParmParse pp("amrex", "my_constants"); + double foo = -1, bar = -2, bar2 = -3; + pp.getWithParser("foo", foo); + AMREX_ALWAYS_ASSERT(amrex::almostEqual(foo, 6.0-std::sqrt(299792458.))); + pp.get("bar", bar); + AMREX_ALWAYS_ASSERT(foo == bar); + pp.get("bar2", bar2); + AMREX_ALWAYS_ASSERT(bar == bar2); + } + { + ParmParse pp; + std::array prob_lo, prob_hi; + pp.get("geom.prob_lo", prob_lo); + pp.get("geom.prob_hi", prob_hi); + AMREX_ALWAYS_ASSERT(amrex::almostEqual(prob_lo[0], -1.0) && + amrex::almostEqual(prob_lo[1], -1.0) && + amrex::almostEqual(prob_lo[2], -1.0) && + amrex::almostEqual(prob_hi[0], 1.0) && + amrex::almostEqual(prob_hi[1], 1.0) && + amrex::almostEqual(prob_hi[2], 1.0)); + } + { + ParmParse pp; + auto parser = pp.makeParser("pi*x+c*y", {"x","y"}); + auto exe = parser.compile<2>(); + AMREX_ALWAYS_ASSERT(amrex::almostEqual(3.14159265358979323846+299792458., + exe(1.0,1.0)) && + amrex::almostEqual(3.14159265358979323846, exe(1.0,0.0)) && + amrex::almostEqual(299792458., exe(0.0, 1.0))); + } + { + ParmParse pp; + long long int i = 123456789012345; + long long int j = 0; + pp.get("long_int_1", j); + AMREX_ALWAYS_ASSERT(i==j); + pp.get("long_int_2", j); + AMREX_ALWAYS_ASSERT(i==j); + pp.get("long_int_3", j); + AMREX_ALWAYS_ASSERT(i==j); + } + try + { + ParmParse pp("code"); + int a = 0; + pp.query("a",a); + amrex::Abort("Should not get here, because query should raise an exception"); + } catch (std::runtime_error const& e) { + // Runtime error as expected + amrex::ignore_unused(e); + } + { + int max_steps = -1; + ParmParse pp("", "my_constants"); + pp.query("max_steps", max_steps); + AMREX_ALWAYS_ASSERT(max_steps == 40); + int warpx_max_steps = -1; + pp.query("warpx.max_steps", warpx_max_steps); + AMREX_ALWAYS_ASSERT(max_steps == 40); + } + { + ParmParse::SetParserPrefix("my_constants"); + ParmParse pp; + + int ny = 0; + pp.queryAsDouble("ny", ny); + AMREX_ALWAYS_ASSERT(ny == 64); + + Array n_cell{0,0,0}; + pp.queryarrAsDouble("n_cell", 3, n_cell.data()); + AMREX_ALWAYS_ASSERT(n_cell[0] == 64 && n_cell[1] == 64 && n_cell[2] == 64); + } + { + ParmParse pp; + bool b_do_this = false; + pp.queryAsDouble("do_this", b_do_this); + AMREX_ALWAYS_ASSERT(b_do_this); + + std::optional o_do_this; + pp.queryAsDouble("do_this", o_do_this); + AMREX_ALWAYS_ASSERT(o_do_this.has_value() && o_do_this.value()); + + std::optional o_do_that; + pp.queryAsDouble("do_that", o_do_that); + AMREX_ALWAYS_ASSERT(!o_do_that.has_value()); + } + { + amrex::Print() << "SUCCESS\n"; + } + amrex::Finalize(); +}