aboutsummaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/Utils/WarpXUtil.H29
-rw-r--r--Source/Utils/WarpXUtil.cpp103
-rw-r--r--Source/WarpX.cpp72
3 files changed, 165 insertions, 39 deletions
diff --git a/Source/Utils/WarpXUtil.H b/Source/Utils/WarpXUtil.H
index 592eaa5d6..93a1f8e27 100644
--- a/Source/Utils/WarpXUtil.H
+++ b/Source/Utils/WarpXUtil.H
@@ -164,9 +164,21 @@ T trilinear_interp(T x0, T x1,T y0, T y1, T z0, T z1,
}
/**
+* \brief Do a safe cast of a real to an int
+* This ensures that the float value is within the range of ints and if not,
+* raises an exception.
+*
+* \param x Real value to cast
+* \param real_name String, the name of the variable being casted to use in the error message
+*/
+int
+safeCastToInt(amrex::Real x, const std::string& real_name);
+
+/**
* \brief Initialize an amrex::Parser object from a string containing a math expression
*
* \param parse_function String to read to initialize the parser.
+* \param varnames A list of predefined independent variables
*/
amrex::Parser makeParser (std::string const& parse_function, amrex::Vector<std::string> const& varnames);
@@ -186,15 +198,20 @@ amrex::ParserExecutor<N> compileParser (amrex::Parser const* parser)
* amrex::ParmParse::query reads a name and a value from the input file. This function does the
* same, and applies the amrex::Parser to the value, so the user has the choice to specify a value or
* a math expression (including user-defined constants).
- * Only works for amrex::Real numbers, one would need another version for integers etc.
+ * Works for amrex::Real numbers and integers.
*
* \param[in] a_pp amrex::ParmParse object
* \param[in] str name of the parameter to read
- * \param[out] val where the value queried and parsed is stored
+ * \param[out] val where the value queried and parsed is stored, either a scalar or vector
+ * \param[in] start_ix start index in the list of inputs values (optional with arrays)
+ * \param[in] num_val number of input values to use (optional with arrays)
*/
int queryWithParser (const amrex::ParmParse& a_pp, char const * const str, amrex::Real& val);
int queryArrWithParser (const amrex::ParmParse& a_pp, char const * const str, std::vector<amrex::Real>& val,
const int start_ix, const int num_val);
+int queryWithParser (const amrex::ParmParse& a_pp, char const * const str, int& val);
+int queryArrWithParser (const amrex::ParmParse& a_pp, char const * const str, std::vector<int>& val,
+ const int start_ix, const int num_val);
/**
* \brief Similar to amrex::ParmParse::get, but also supports math expressions for the value.
@@ -202,16 +219,22 @@ int queryArrWithParser (const amrex::ParmParse& a_pp, char const * const str, st
* amrex::ParmParse::get reads a name and a value from the input file. This function does the
* same, and applies the Parser to the value, so the user has the choice to specify a value or
* a math expression (including user-defined constants).
- * Only works for amrex::Real numbers, one would need another version for integers etc.
+ * Works for amrex::Real numbers and integers.
*
* \param[in] a_pp amrex::ParmParse object
* \param[in] str name of the parameter to read
* \param[out] val where the value queried and parsed is stored
+ * \param[in] start_ix start index in the list of inputs values (optional with arrays)
+ * \param[in] num_val number of input values to use (optional with arrays)
*/
void getWithParser (const amrex::ParmParse& a_pp, char const * const str, amrex::Real& val);
void getArrWithParser (const amrex::ParmParse& a_pp, char const * const str, std::vector<amrex::Real>& val);
void getArrWithParser (const amrex::ParmParse& a_pp, char const * const str, std::vector<amrex::Real>& val,
const int start_ix, const int num_val);
+void getWithParser (const amrex::ParmParse& a_pp, char const * const str, int& val);
+void getArrWithParser (const amrex::ParmParse& a_pp, char const * const str, std::vector<int>& val);
+void getArrWithParser (const amrex::ParmParse& a_pp, char const * const str, std::vector<int>& val,
+ const int start_ix, const int num_val);
namespace WarpXUtilMsg{
diff --git a/Source/Utils/WarpXUtil.cpp b/Source/Utils/WarpXUtil.cpp
index 03e800e54..6124e8afa 100644
--- a/Source/Utils/WarpXUtil.cpp
+++ b/Source/Utils/WarpXUtil.cpp
@@ -34,11 +34,27 @@
#include <fstream>
#include <set>
#include <string>
+#include <limits>
using namespace amrex;
+void PreparseAMReXInputIntArray(amrex::ParmParse& a_pp, char const * const input_str, const bool replace)
+{
+ const int cnt = a_pp.countval(input_str);
+ if (cnt > 0) {
+ Vector<int> input_array;
+ getArrWithParser(a_pp, input_str, input_array);
+ if (replace) {
+ a_pp.remove(input_str);
+ }
+ a_pp.addarr(input_str, input_array);
+ }
+}
+
void ParseGeometryInput()
{
+ // Parse prob_lo and hi, evaluating any expressions since geometry does not
+ // parse its input
ParmParse pp_geometry("geometry");
Vector<Real> prob_lo(AMREX_SPACEDIM);
@@ -66,6 +82,22 @@ void ParseGeometryInput()
pp_geometry.addarr("prob_lo", prob_lo);
pp_geometry.addarr("prob_hi", prob_hi);
+
+ // Parse amr input, evaluating any expressions since amr does not parse its input
+ ParmParse pp_amr("amr");
+
+ // Note that n_cell is replaced so that only the parsed version is written out to the
+ // warpx_job_info file. This must be done since yt expects to be able to parse
+ // the value of n_cell from that file. For the rest, this doesn't matter.
+ PreparseAMReXInputIntArray(pp_amr, "n_cell", true);
+ PreparseAMReXInputIntArray(pp_amr, "max_grid_size", false);
+ PreparseAMReXInputIntArray(pp_amr, "max_grid_size_x", false);
+ PreparseAMReXInputIntArray(pp_amr, "max_grid_size_y", false);
+ PreparseAMReXInputIntArray(pp_amr, "max_grid_size_z", false);
+ PreparseAMReXInputIntArray(pp_amr, "blocking_factor", false);
+ PreparseAMReXInputIntArray(pp_amr, "blocking_factor_x", false);
+ PreparseAMReXInputIntArray(pp_amr, "blocking_factor_y", false);
+ PreparseAMReXInputIntArray(pp_amr, "blocking_factor_z", false);
}
void ReadBoostedFrameParameters(Real& gamma_boost, Real& beta_boost,
@@ -239,6 +271,30 @@ void Store_parserString(const amrex::ParmParse& pp, std::string query_string,
f.clear();
}
+int safeCastToInt(const amrex::Real x, const std::string& real_name) {
+ int result = 0;
+ bool error_detected = false;
+ std::string assert_msg;
+ // (2.0*(numeric_limits<int>::max()/2+1)) converts numeric_limits<int>::max()+1 to a real ensuring accuracy to all digits
+ // This accepts x = 2**31-1 but rejects 2**31.
+ if (x < (2.0*(std::numeric_limits<int>::max()/2+1))) {
+ if (std::ceil(x) >= std::numeric_limits<int>::min()) {
+ result = static_cast<int>(x);
+ } else {
+ error_detected = true;
+ assert_msg = "Error: Negative overflow detected when casting " + real_name + " = " + std::to_string(x) + " to int";
+ }
+ } else if (x > 0) {
+ error_detected = true;
+ assert_msg = "Error: Overflow detected when casting " + real_name + " = " + std::to_string(x) + " to int";
+ } else {
+ error_detected = true;
+ assert_msg = "Error: NaN detected when casting " + real_name + " to int";
+ }
+ WarpXUtilMsg::AlwaysAssert(!error_detected, assert_msg);
+ return result;
+}
+
Parser makeParser (std::string const& parse_function, amrex::Vector<std::string> const& varnames)
{
// Since queryWithParser recursively calls this routine, keep track of symbols
@@ -391,6 +447,53 @@ getArrWithParser (const amrex::ParmParse& a_pp, char const * const str, std::vec
}
}
+int queryWithParser (const amrex::ParmParse& a_pp, char const * const str, int& val) {
+ amrex::Real rval;
+ const int result = queryWithParser(a_pp, str, rval);
+ if (result) {
+ val = safeCastToInt(std::round(rval), str);
+ }
+ return result;
+}
+
+void getWithParser (const amrex::ParmParse& a_pp, char const * const str, int& val) {
+ amrex::Real rval;
+ getWithParser(a_pp, str, rval);
+ val = safeCastToInt(std::round(rval), str);
+}
+
+int queryArrWithParser (const amrex::ParmParse& a_pp, char const * const str, std::vector<int>& val,
+ const int start_ix, const int num_val) {
+ std::vector<amrex::Real> rval;
+ const int result = queryArrWithParser(a_pp, str, rval, start_ix, num_val);
+ if (result) {
+ val.resize(rval.size());
+ for (unsigned long i = 0 ; i < val.size() ; i++) {
+ val[i] = safeCastToInt(std::round(rval[i]), str);
+ }
+ }
+ return result;
+}
+
+void getArrWithParser (const amrex::ParmParse& a_pp, char const * const str, std::vector<int>& val) {
+ std::vector<amrex::Real> rval;
+ getArrWithParser(a_pp, str, rval);
+ val.resize(rval.size());
+ for (unsigned long i = 0 ; i < val.size() ; i++) {
+ val[i] = safeCastToInt(std::round(rval[i]), str);
+ }
+}
+
+void getArrWithParser (const amrex::ParmParse& a_pp, char const * const str, std::vector<int>& val,
+ const int start_ix, const int num_val) {
+ std::vector<amrex::Real> rval;
+ getArrWithParser(a_pp, str, rval, start_ix, num_val);
+ val.resize(rval.size());
+ for (unsigned long i = 0 ; i < val.size() ; i++) {
+ val[i] = safeCastToInt(std::round(rval[i]), str);
+ }
+}
+
/**
* \brief Ensures that the blocks are setup correctly for the RZ spectral solver
* When using the RZ spectral solver, the Hankel transform cannot be
diff --git a/Source/WarpX.cpp b/Source/WarpX.cpp
index 76d3d5456..680ac150f 100644
--- a/Source/WarpX.cpp
+++ b/Source/WarpX.cpp
@@ -405,7 +405,7 @@ WarpX::ReadParameters ()
{
{
ParmParse pp;// Traditionally, max_step and stop_time do not have prefix.
- pp.query("max_step", max_step);
+ queryWithParser(pp, "max_step", max_step);
queryWithParser(pp, "stop_time", stop_time);
pp.query("authors", authors);
}
@@ -425,7 +425,7 @@ WarpX::ReadParameters ()
ParmParse pp_warpx("warpx");
std::vector<int> numprocs_in;
- pp_warpx.queryarr("numprocs", numprocs_in);
+ queryArrWithParser(pp_warpx, "numprocs", numprocs_in, 0, AMREX_SPACEDIM);
if (not numprocs_in.empty()) {
AMREX_ALWAYS_ASSERT_WITH_MESSAGE
(numprocs_in.size() == AMREX_SPACEDIM,
@@ -460,7 +460,7 @@ WarpX::ReadParameters ()
queryWithParser(pp_warpx, "cfl", cfl);
pp_warpx.query("verbose", verbose);
- pp_warpx.query("regrid_int", regrid_int);
+ queryWithParser(pp_warpx, "regrid_int", regrid_int);
pp_warpx.query("do_subcycling", do_subcycling);
pp_warpx.query("do_multi_J", do_multi_J);
if (do_multi_J)
@@ -489,8 +489,8 @@ WarpX::ReadParameters ()
pp_warpx.query("do_moving_window", do_moving_window);
if (do_moving_window)
{
- pp_warpx.query("start_moving_window_step", start_moving_window_step);
- pp_warpx.query("end_moving_window_step", end_moving_window_step);
+ queryWithParser(pp_warpx, "start_moving_window_step", start_moving_window_step);
+ queryWithParser(pp_warpx, "end_moving_window_step", end_moving_window_step);
std::string s;
pp_warpx.get("moving_window_dir", s);
if (s == "x" || s == "X") {
@@ -531,7 +531,7 @@ WarpX::ReadParameters ()
AMREX_ALWAYS_ASSERT_WITH_MESSAGE( (s == "z" || s == "Z"),
"The boosted frame diagnostic currently only works if the boost is in the z direction.");
- pp_warpx.get("num_snapshots_lab", num_snapshots_lab);
+ queryWithParser(pp_warpx, "num_snapshots_lab", num_snapshots_lab);
// Read either dz_snapshots_lab or dt_snapshots_lab
bool snapshot_interval_is_specified = 0;
@@ -561,7 +561,7 @@ WarpX::ReadParameters ()
if (do_electrostatic == ElectrostaticSolverAlgo::LabFrame) {
queryWithParser(pp_warpx, "self_fields_required_precision", self_fields_required_precision);
- pp_warpx.query("self_fields_max_iters", self_fields_max_iters);
+ queryWithParser(pp_warpx, "self_fields_max_iters", self_fields_max_iters);
pp_warpx.query("self_fields_verbosity", self_fields_verbosity);
// Note that with the relativistic version, these parameters would be
// input for each species.
@@ -580,7 +580,7 @@ WarpX::ReadParameters ()
pp_warpx.query("use_filter", use_filter);
pp_warpx.query("use_filter_compensation", use_filter_compensation);
Vector<int> parse_filter_npass_each_dir(AMREX_SPACEDIM,1);
- pp_warpx.queryarr("filter_npass_each_dir", parse_filter_npass_each_dir);
+ queryArrWithParser(pp_warpx, "filter_npass_each_dir", parse_filter_npass_each_dir, 0, AMREX_SPACEDIM);
filter_npass_each_dir[0] = parse_filter_npass_each_dir[0];
filter_npass_each_dir[1] = parse_filter_npass_each_dir[1];
#if (AMREX_SPACEDIM == 3)
@@ -623,8 +623,8 @@ WarpX::ReadParameters ()
pp_warpx.query("refine_plasma", refine_plasma);
pp_warpx.query("do_dive_cleaning", do_dive_cleaning);
pp_warpx.query("do_divb_cleaning", do_divb_cleaning);
- pp_warpx.query("n_field_gather_buffer", n_field_gather_buffer);
- pp_warpx.query("n_current_deposition_buffer", n_current_deposition_buffer);
+ queryWithParser(pp_warpx, "n_field_gather_buffer", n_field_gather_buffer);
+ queryWithParser(pp_warpx, "n_current_deposition_buffer", n_current_deposition_buffer);
#ifdef AMREX_USE_GPU
std::vector<std::string>sort_intervals_string_vec = {"4"};
#else
@@ -634,7 +634,7 @@ WarpX::ReadParameters ()
sort_intervals = IntervalsParser(sort_intervals_string_vec);
Vector<int> vect_sort_bin_size(AMREX_SPACEDIM,1);
- bool sort_bin_size_is_specified = pp_warpx.queryarr("sort_bin_size", vect_sort_bin_size);
+ bool sort_bin_size_is_specified = queryArrWithParser(pp_warpx, "sort_bin_size", vect_sort_bin_size, 0, AMREX_SPACEDIM);
if (sort_bin_size_is_specified){
for (int i=0; i<AMREX_SPACEDIM; i++)
sort_bin_size[i] = vect_sort_bin_size[i];
@@ -666,8 +666,8 @@ WarpX::ReadParameters ()
}
}
- pp_warpx.query("pml_ncell", pml_ncell);
- pp_warpx.query("pml_delta", pml_delta);
+ queryWithParser(pp_warpx, "pml_ncell", pml_ncell);
+ queryWithParser(pp_warpx, "pml_delta", pml_delta);
pp_warpx.query("pml_has_particles", pml_has_particles);
pp_warpx.query("do_pml_j_damping", do_pml_j_damping);
pp_warpx.query("do_pml_in_domain", do_pml_in_domain);
@@ -758,11 +758,11 @@ WarpX::ReadParameters ()
ParmParse pp_vismf("vismf");
pp_vismf.add("usesingleread", use_single_read);
pp_vismf.add("usesinglewrite", use_single_write);
- pp_warpx.query("mffile_nstreams", mffile_nstreams);
+ queryWithParser(pp_warpx, "mffile_nstreams", mffile_nstreams);
VisMF::SetMFFileInStreams(mffile_nstreams);
- pp_warpx.query("field_io_nfiles", field_io_nfiles);
+ queryWithParser(pp_warpx, "field_io_nfiles", field_io_nfiles);
VisMF::SetNOutFiles(field_io_nfiles);
- pp_warpx.query("particle_io_nfiles", particle_io_nfiles);
+ queryWithParser(pp_warpx, "particle_io_nfiles", particle_io_nfiles);
ParmParse pp_particles("particles");
pp_particles.add("particles_nfiles", particle_io_nfiles);
}
@@ -782,7 +782,7 @@ WarpX::ReadParameters ()
if (do_nodal) galerkin_interpolation = false;
// Only needs to be set with WARPX_DIM_RZ, otherwise defaults to 1
- pp_warpx.query("n_rz_azimuthal_modes", n_rz_azimuthal_modes);
+ queryWithParser(pp_warpx, "n_rz_azimuthal_modes", n_rz_azimuthal_modes);
// If true, the current is deposited on a nodal grid and then interpolated onto a Yee grid
pp_warpx.query("do_current_centering", do_current_centering);
@@ -868,7 +868,7 @@ WarpX::ReadParameters ()
if (!species_names.empty() || !lasers_names.empty()) {
int particle_shape;
- if (pp_algo.query("particle_shape", particle_shape) == false)
+ if (queryWithParser(pp_algo, "particle_shape", particle_shape) == false)
{
amrex::Abort("\nalgo.particle_shape must be set in the input file:"
"\nplease set algo.particle_shape to 1, 2, or 3");
@@ -908,16 +908,16 @@ WarpX::ReadParameters ()
// For momentum-conserving field gathering, read from input the order of
// interpolation from the staggered positions to the grid nodes
if (WarpX::field_gathering_algo == GatheringAlgo::MomentumConserving) {
- pp_interpolation.query("field_centering_nox", field_centering_nox);
- pp_interpolation.query("field_centering_noy", field_centering_noy);
- pp_interpolation.query("field_centering_noz", field_centering_noz);
+ queryWithParser(pp_interpolation, "field_centering_nox", field_centering_nox);
+ queryWithParser(pp_interpolation, "field_centering_noy", field_centering_noy);
+ queryWithParser(pp_interpolation, "field_centering_noz", field_centering_noz);
}
// Read order of finite-order centering of currents (nodal to staggered)
if (WarpX::do_current_centering) {
- pp_interpolation.query("current_centering_nox", current_centering_nox);
- pp_interpolation.query("current_centering_noy", current_centering_noy);
- pp_interpolation.query("current_centering_noz", current_centering_noz);
+ queryWithParser(pp_interpolation, "current_centering_nox", current_centering_nox);
+ queryWithParser(pp_interpolation, "current_centering_noy", current_centering_noy);
+ queryWithParser(pp_interpolation, "current_centering_noz", current_centering_noz);
}
if (maxLevel() > 0)
@@ -964,20 +964,20 @@ WarpX::ReadParameters ()
pp_psatd.query("noy", noy_str);
pp_psatd.query("noz", noz_str);
- if(nox_str == "inf"){
+ if(nox_str == "inf") {
nox_fft = -1;
- } else{
- pp_psatd.query("nox", nox_fft);
+ } else {
+ queryWithParser(pp_psatd, "nox", nox_fft);
}
- if(noy_str == "inf"){
+ if(noy_str == "inf") {
noy_fft = -1;
- } else{
- pp_psatd.query("noy", noy_fft);
+ } else {
+ queryWithParser(pp_psatd, "noy", noy_fft);
}
- if(noz_str == "inf"){
+ if(noz_str == "inf") {
noz_fft = -1;
- } else{
- pp_psatd.query("noz", noz_fft);
+ } else {
+ queryWithParser(pp_psatd, "noz", noz_fft);
}
@@ -1112,8 +1112,8 @@ WarpX::ReadParameters ()
}
queryArrWithParser(pp_slice, "dom_lo", slice_lo, 0, AMREX_SPACEDIM);
queryArrWithParser(pp_slice, "dom_hi", slice_hi, 0, AMREX_SPACEDIM);
- pp_slice.queryarr("coarsening_ratio",slice_crse_ratio,0,AMREX_SPACEDIM);
- pp_slice.query("plot_int",slice_plot_int);
+ queryArrWithParser(pp_slice, "coarsening_ratio",slice_crse_ratio,0,AMREX_SPACEDIM);
+ queryWithParser(pp_slice, "plot_int",slice_plot_int);
slice_realbox.setLo(slice_lo);
slice_realbox.setHi(slice_hi);
slice_cr_ratio = IntVect(AMREX_D_DECL(1,1,1));
@@ -1127,7 +1127,7 @@ WarpX::ReadParameters ()
if (do_back_transformed_diagnostics) {
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(gamma_boost > 1.0,
"gamma_boost must be > 1 to use the boost frame diagnostic");
- pp_slice.query("num_slice_snapshots_lab", num_slice_snapshots_lab);
+ queryWithParser(pp_slice, "num_slice_snapshots_lab", num_slice_snapshots_lab);
if (num_slice_snapshots_lab > 0) {
getWithParser(pp_slice, "dt_slice_snapshots_lab", dt_slice_snapshots_lab );
getWithParser(pp_slice, "particle_slice_width_lab",particle_slice_width_lab);