diff options
author | 2022-10-10 20:36:14 +0200 | |
---|---|---|
committer | 2022-10-10 11:36:14 -0700 | |
commit | e9cc65ffeb0684a97618b67c2164d95ea497226c (patch) | |
tree | ed65f7ac86cc4e8945021dc36a79c8bc246c150d /Source/Utils/Parser/ParserUtils.H | |
parent | 56e04c1b911f9399662c4ff9ecf6630d686cc220 (diff) | |
download | WarpX-e9cc65ffeb0684a97618b67c2164d95ea497226c.tar.gz WarpX-e9cc65ffeb0684a97618b67c2164d95ea497226c.tar.zst WarpX-e9cc65ffeb0684a97618b67c2164d95ea497226c.zip |
Partial refactoring of the utils directory (#3404)
* initial work to clean WarpX Utils
* remove AMRCore from Ionization tables
* progress
* refactoring of a part of the utils directory
* fix bug
* fixed bug
* fixed bug
* remove debug line accidentally slipped into the code
* remove debug line accidentally slipped into the code
* remove debug line accidentally slipped into the code
* cleaning
* fixed bug
Diffstat (limited to 'Source/Utils/Parser/ParserUtils.H')
-rw-r--r-- | Source/Utils/Parser/ParserUtils.H | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/Source/Utils/Parser/ParserUtils.H b/Source/Utils/Parser/ParserUtils.H new file mode 100644 index 000000000..4195bed1a --- /dev/null +++ b/Source/Utils/Parser/ParserUtils.H @@ -0,0 +1,298 @@ +/* Copyright 2022 Andrew Myers, Burlen Loring, Luca Fedeli + * Maxence Thevenet, Remi Lehe, Revathi Jambunathan + * + * This file is part of WarpX. + * + * License: BSD-3-Clause-LBNL + */ + +#ifndef WARPX_UTILS_PARSER_PARSERUTILS_H_ +#define WARPX_UTILS_PARSER_PARSERUTILS_H_ + +#include <AMReX_ParmParse.H> +#include <AMReX_Parser.H> +#include <AMReX_REAL.H> +#include <AMReX_Vector.H> + +#include <cmath> +#include <string> +#include <type_traits> + +namespace utils::parser +{ + /** + * \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 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 + * + * \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); + + + /** + * \brief Parse a string (typically a mathematical expression) from the + * input file and store it into a variable. + * + * \param pp used to read the query_string `pp.<function>=string` + * \param query_string ParmParse.query will look for this string + * \param stored_string variable in which the string to parse is stored + */ + void Store_parserString( + const amrex::ParmParse &pp, + std::string query_string, + std::string& stored_string); + + + /** Parse a string and return as a double precision floating point number + * + * In case the string cannot be interpreted as a double, + * this function ... <throws an exception? aborts with error message?> + * + * \param str The string to be parsed + * \return representation as a double + */ + double parseStringtoDouble(const std::string& str); + + + /** Parse a string and return an int + * + * In case the string cannot be interpreted as Real, + * this function ... <throws an exception? aborts with error message?> + * + * \param str The string to be parsed + * \param name For integers, the name, to be used in error messages + * \return rounded closest integer + */ + int parseStringtoInt(const std::string& str, const std::string& name); + + + template <int N> + amrex::ParserExecutor<N> compileParser (amrex::Parser const* parser) + { + if (parser) { + return parser->compile<N>(); + } else { + return amrex::ParserExecutor<N>{}; + } + } + + + /** Similar to amrex::ParmParse::query, but also supports math expressions for the value. + * + * 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). + * 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, either a scalar or vector + */ + template <typename T> + int queryWithParser (const amrex::ParmParse& a_pp, char const * const str, T& val) + { + // call amrex::ParmParse::query, check if the user specified str. + std::string tmp_str; + int is_specified = a_pp.query(str, tmp_str); + if (is_specified) + { + // If so, create a parser object and apply it to the value provided by the user. + std::string str_val; + Store_parserString(a_pp, str, str_val); + + auto parser = makeParser(str_val, {}); + + if (std::is_same<T, int>::value) { + + val = safeCastToInt(std::round(parser.compileHost<0>()()), str); + } + else { + val = static_cast<T>(parser.compileHost<0>()()); + } + } + // return the same output as amrex::ParmParse::query + return is_specified; + } + + + template <typename T> + int queryArrWithParser (const amrex::ParmParse& a_pp, char const * const str, std::vector<T>& val) + { + // call amrex::ParmParse::query, check if the user specified str. + std::vector<std::string> tmp_str_arr; + int is_specified = a_pp.queryarr(str, tmp_str_arr); + if (is_specified) + { + // If so, create parser objects and apply them to the values provided by the user. + int const n = static_cast<int>(tmp_str_arr.size()); + val.resize(n); + for (int i=0 ; i < n ; i++) { + auto parser = makeParser(tmp_str_arr[i], {}); + if (std::is_same<T, int>::value) { + val[i] = safeCastToInt(std::round(parser.compileHost<0>()()), str); + } + else { + val[i] = static_cast<T>(parser.compileHost<0>()()); + } + } + } + // return the same output as amrex::ParmParse::query + return is_specified; + } + + + /** Similar to amrex::ParmParse::query, but also supports math expressions for the value. + * + * 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). + * 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, either a scalar or vector + * \param[in] start_ix start index in the list of inputs values (optional with arrays, default is + * amrex::ParmParse::FIRST for starting with the first input value) + * \param[in] num_val number of input values to use (optional with arrays, default is + * amrex::ParmParse::LAST for reading until the last input value) + */ + template <typename T> + int queryArrWithParser (const amrex::ParmParse& a_pp, char const * const str, std::vector<T>& val, + const int start_ix, const int num_val) + { + // call amrex::ParmParse::query, check if the user specified str. + std::vector<std::string> tmp_str_arr; + int is_specified = a_pp.queryarr(str, tmp_str_arr, start_ix, num_val); + if (is_specified) + { + // If so, create parser objects and apply them to the values provided by the user. + int const n = static_cast<int>(tmp_str_arr.size()); + val.resize(n); + for (int i=0 ; i < n ; i++) { + auto parser = makeParser(tmp_str_arr[i], {}); + if (std::is_same<T, int>::value) { + val[i] = safeCastToInt(std::round(parser.compileHost<0>()()), str); + } + else { + val[i] = static_cast<T>(parser.compileHost<0>()()); + } + } + } + // return the same output as amrex::ParmParse::query + return is_specified; + } + + + /** Similar to amrex::ParmParse::get, but also supports math expressions for the value. + * + * 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). + * 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 + */ + template <typename T> + void getWithParser (const amrex::ParmParse& a_pp, char const * const str, T& val) + { + // If so, create a parser object and apply it to the value provided by the user. + std::string str_val; + Store_parserString(a_pp, str, str_val); + + auto parser = makeParser(str_val, {}); + if (std::is_same<T, int>::value) { + val = safeCastToInt(std::round(parser.compileHost<0>()()), str); + } + else { + val = static_cast<T>(parser.compileHost<0>()()); + } + } + + template <typename T> + void getArrWithParser (const amrex::ParmParse& a_pp, char const * const str, std::vector<T>& val) + { + // Create parser objects and apply them to the values provided by the user. + std::vector<std::string> tmp_str_arr; + a_pp.getarr(str, tmp_str_arr); + + int const n = static_cast<int>(tmp_str_arr.size()); + val.resize(n); + for (int i=0 ; i < n ; i++) { + auto parser = makeParser(tmp_str_arr[i], {}); + if (std::is_same<T, int>::value) { + val[i] = safeCastToInt(std::round(parser.compileHost<0>()()), str); + } + else { + val[i] = static_cast<T>(parser.compileHost<0>()()); + } + } + } + + + /** Similar to amrex::ParmParse::get, but also supports math expressions for the value. + * + * 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). + * 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, default is + * amrex::ParmParse::FIRST for starting with the first input value) + * \param[in] num_val number of input values to use (optional with arrays, default is + * amrex::ParmParse::LAST for reading until the last input value) + */ + template <typename T> + void getArrWithParser (const amrex::ParmParse& a_pp, char const * const str, std::vector<T>& val, + const int start_ix, const int num_val) + { + // Create parser objects and apply them to the values provided by the user. + std::vector<std::string> tmp_str_arr; + a_pp.getarr(str, tmp_str_arr, start_ix, num_val); + + int const n = static_cast<int>(tmp_str_arr.size()); + val.resize(n); + for (int i=0 ; i < n ; i++) { + auto parser = makeParser(tmp_str_arr[i], {}); + if (std::is_same<T, int>::value) { + val[i] = safeCastToInt(std::round(parser.compileHost<0>()()), str); + } + else { + val[i] = static_cast<T>(parser.compileHost<0>()()); + } + } + } + +} + +#endif // WARPX_UTILS_PARSER_PARSERUTILS_H_ |