Skip to content

Commit

Permalink
Use parser for input parameters of type long (#2506)
Browse files Browse the repository at this point in the history
* Use parser for input parameters of type long

* Revert "Use parser for input parameters of type long"

This reverts commit 9573bb3.

* Use parser for inputs of type long

* add safeCasttoLong function

* Fix typo in comment
  • Loading branch information
NeilZaim committed Oct 2, 2022
1 parent 45ec9e3 commit a1ade2b
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 24 deletions.
2 changes: 1 addition & 1 deletion Source/Diagnostics/ReducedDiags/FieldProbe.cpp
Expand Up @@ -151,7 +151,7 @@ FieldProbe::FieldProbe (std::string rd_name)
}
pp_rd_name.query("integrate", m_field_probe_integrate);
pp_rd_name.query("raw_fields", raw_fields);
pp_rd_name.query("interp_order", interp_order);
queryWithParser(pp_rd_name, "interp_order", interp_order);
pp_rd_name.query("do_moving_window_FP", do_moving_window_FP);

if (WarpX::gamma_boost > 1.0_rt)
Expand Down
2 changes: 1 addition & 1 deletion Source/Initialization/PlasmaInjector.cpp
Expand Up @@ -220,7 +220,7 @@ PlasmaInjector::PlasmaInjector (int ispecies, const std::string& name)
queryWithParser(pp_species_name, "y_cut", y_cut);
queryWithParser(pp_species_name, "z_cut", z_cut);
getWithParser(pp_species_name, "q_tot", q_tot);
pp_species_name.get("npart", npart);
getWithParser(pp_species_name, "npart", npart);
pp_species_name.query("do_symmetrize", do_symmetrize);
gaussian_beam = true;
parseMomentum(pp_species_name);
Expand Down
2 changes: 1 addition & 1 deletion Source/Particles/LaserParticleContainer.cpp
Expand Up @@ -122,7 +122,7 @@ LaserParticleContainer::LaserParticleContainer (AmrCore* amr_core, int ispecies,
);

pp_laser_name.query("do_continuous_injection", do_continuous_injection);
pp_laser_name.query("min_particles_per_mode", m_min_particles_per_mode);
queryWithParser(pp_laser_name, "min_particles_per_mode", m_min_particles_per_mode);

if (m_e_max == amrex::Real(0.)){
ablastr::warn_manager::WMRecordWarning("Laser",
Expand Down
30 changes: 30 additions & 0 deletions Source/Utils/WarpXUtil.H
Expand Up @@ -197,6 +197,17 @@ void getCellCoordinates (int i, int j, int k,
int
safeCastToInt(amrex::Real x, const std::string& real_name);

/**
* \brief Do a safe cast of a real to a long
* This ensures that the float value is within the range of longs 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
*/
long
safeCastToLong(amrex::Real x, const std::string& real_name);

/**
* \brief Initialize an amrex::Parser object from a string containing a math expression
*
Expand Down Expand Up @@ -265,6 +276,10 @@ int queryWithParser (const amrex::ParmParse& a_pp, char const * const str, T& va

val = safeCastToInt(std::round(parser.compileHost<0>()()), str);
}
else if (std::is_same<T, long>::value) {

val = safeCastToLong(std::round(parser.compileHost<0>()()), str);
}
else {
val = static_cast<T>(parser.compileHost<0>()());
}
Expand All @@ -289,6 +304,9 @@ int queryArrWithParser (const amrex::ParmParse& a_pp, char const * const str, st
if (std::is_same<T, int>::value) {
val[i] = safeCastToInt(std::round(parser.compileHost<0>()()), str);
}
else if (std::is_same<T, long>::value) {
val[i] = safeCastToLong(std::round(parser.compileHost<0>()()), str);
}
else {
val[i] = static_cast<T>(parser.compileHost<0>()());
}
Expand Down Expand Up @@ -330,6 +348,9 @@ int queryArrWithParser (const amrex::ParmParse& a_pp, char const * const str, st
if (std::is_same<T, int>::value) {
val[i] = safeCastToInt(std::round(parser.compileHost<0>()()), str);
}
else if (std::is_same<T, long>::value) {
val[i] = safeCastToLong(std::round(parser.compileHost<0>()()), str);
}
else {
val[i] = static_cast<T>(parser.compileHost<0>()());
}
Expand Down Expand Up @@ -361,6 +382,9 @@ void getWithParser (const amrex::ParmParse& a_pp, char const * const str, T& val
if (std::is_same<T, int>::value) {
val = safeCastToInt(std::round(parser.compileHost<0>()()), str);
}
else if (std::is_same<T, long>::value) {
val = safeCastToLong(std::round(parser.compileHost<0>()()), str);
}
else {
val = static_cast<T>(parser.compileHost<0>()());
}
Expand All @@ -380,6 +404,9 @@ void getArrWithParser (const amrex::ParmParse& a_pp, char const * const str, std
if (std::is_same<T, int>::value) {
val[i] = safeCastToInt(std::round(parser.compileHost<0>()()), str);
}
else if (std::is_same<T, long>::value) {
val[i] = safeCastToLong(std::round(parser.compileHost<0>()()), str);
}
else {
val[i] = static_cast<T>(parser.compileHost<0>()());
}
Expand Down Expand Up @@ -416,6 +443,9 @@ void getArrWithParser (const amrex::ParmParse& a_pp, char const * const str, std
if (std::is_same<T, int>::value) {
val[i] = safeCastToInt(std::round(parser.compileHost<0>()()), str);
}
else if (std::is_same<T, long>::value) {
val[i] = safeCastToLong(std::round(parser.compileHost<0>()()), str);
}
else {
val[i] = static_cast<T>(parser.compileHost<0>()());
}
Expand Down
55 changes: 34 additions & 21 deletions Source/Utils/WarpXUtil.cpp
Expand Up @@ -276,30 +276,43 @@ 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.
using namespace amrex::literals;
constexpr amrex::Real max_range = (2.0_rt*static_cast<amrex::Real>(std::numeric_limits<int>::max()/2+1));
if (x < max_range) {
if (std::ceil(x) >= std::numeric_limits<int>::min()) {
result = static_cast<int>(x);
namespace WarpXUtilSafeCast {
template< typename int_type >
AMREX_FORCE_INLINE
int_type safeCastTo(const amrex::Real x, const std::string& real_name) {
int_type result = int_type(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.
using namespace amrex::literals;
constexpr amrex::Real max_range = (2.0_rt*static_cast<amrex::Real>(std::numeric_limits<int_type>::max()/2+1));
if (x < max_range) {
if (std::ceil(x) >= std::numeric_limits<int_type>::min()) {
result = static_cast<int_type>(x);
} else {
error_detected = true;
assert_msg = "Negative overflow detected when casting " + real_name + " = " +
std::to_string(x) + " to integer type";
}
} else if (x > 0) {
error_detected = true;
assert_msg = "Overflow detected when casting " + real_name + " = " + std::to_string(x) + " to integer type";
} else {
error_detected = true;
assert_msg = "Negative overflow detected when casting " + real_name + " = " + std::to_string(x) + " to int";
assert_msg = "NaN detected when casting " + real_name + " to integer type";
}
} else if (x > 0) {
error_detected = true;
assert_msg = "Overflow detected when casting " + real_name + " = " + std::to_string(x) + " to int";
} else {
error_detected = true;
assert_msg = "NaN detected when casting " + real_name + " to int";
}
WARPX_ALWAYS_ASSERT_WITH_MESSAGE(!error_detected, assert_msg);
return result;
WARPX_ALWAYS_ASSERT_WITH_MESSAGE(!error_detected, assert_msg);
return result;
}
}

int safeCastToInt(const amrex::Real x, const std::string& real_name) {
return WarpXUtilSafeCast::safeCastTo<int> (x, real_name);
}

long safeCastToLong(const amrex::Real x, const std::string& real_name) {
return WarpXUtilSafeCast::safeCastTo<long> (x, real_name);
}

Parser makeParser (std::string const& parse_function, amrex::Vector<std::string> const& varnames)
Expand Down

0 comments on commit a1ade2b

Please sign in to comment.