12#ifndef DUMUX_COMMON_FUNCTION_FROM_STRING_EXPRESSION_HH
13#define DUMUX_COMMON_FUNCTION_FROM_STRING_EXPRESSION_HH
22#include <dune/common/exceptions.hh>
23#include <dune/common/fvector.hh>
26#include <dumux/io/expression/exprtk.hpp>
56template<std::
size_t numVars,
class Scalar =
double>
59 using SymbolTable = exprtk::symbol_table<Scalar>;
60 using Expression = exprtk::expression<Scalar>;
61 using Parser = exprtk::parser<Scalar>;
68 { initialize_(expression, variableNames); }
75 template<
class S, std::enable_if_t<std::is_convertible_v<Scalar, S>,
int> = 0>
76 Scalar
operator() (
const std::array<S, numVars>& params)
const
77 {
return evalRandomAcessImpl_(params); }
79 template<
class S, std::enable_if_t<std::is_convertible_v<Scalar, S>,
int> = 0>
80 Scalar
operator() (
const Dune::FieldVector<S, numVars>& params)
const
81 {
return evalRandomAcessImpl_(params); }
83 template<
class ...Params, std::enable_if_t<(
sizeof...(Params) == numVars) && (std::is_convertible_v<Scalar, std::decay_t<Params>> && ...),
int> = 0>
85 {
return evalRandomAcessImpl_(std::array<Scalar, numVars>{ std::forward<Params>(params)... }); }
91 template<
class RandomAccessContainer>
92 Scalar evalRandomAcessImpl_(
const RandomAccessContainer& params)
const
94 if constexpr (numVars > 0)
96 std::lock_guard lock(evalMutex_);
97 for (std::size_t i = 0; i < numVars; ++i)
98 variables_[i] = params[i];
99 return expression_.value();
102 return expression_.value();
105 template<std::size_t... I>
106 std::array<std::string, numVars> extractVariableNames_(std::string_view names, std::index_sequence<I...>)
const
108 static_assert(numVars ==
sizeof...(I),
"Number of variables has to match size of index set.");
109 if (names.size() != numVars)
110 DUNE_THROW(Dune::IOError,
"Number of variables in '"
111 << names <<
"' does not match number of function arguments: " << numVars);
112 return { std::string(1, names.at(I))... };
116 void initialize_(
const std::string& expression,
const std::array<std::string, numVars>& variableNames)
118 for (std::size_t i = 0; i < numVars; ++i)
119 symbolTable_.add_variable(std::string{variableNames[i]}, variables_[i]);
120 symbolTable_.add_constants();
121 expression_.register_symbol_table(symbolTable_);
123 if (!parser_.compile(expression, expression_))
125 std::stringstream ss;
126 ss << Fmt::format(
"Parsing expression '{}' failed.\n", expression);
130 for (std::size_t i = 0; i < parser_.error_count(); ++i)
132 const auto error = parser_.get_error(i);
135 "-- error (position: {:02d}, type: {}): {}\n",
136 static_cast<unsigned int>(error.token.position),
137 exprtk::parser_error::to_str(error.mode).c_str(),
138 error.diagnostic.c_str()
143 DUNE_THROW(Dune::IOError, ss.str());
145 else if (verbosity_ >= 2)
147 std::cout << Fmt::format(
148 "Successfully parsed math expression '{}'\n",
154 unsigned int verbosity_ = 2;
155 SymbolTable symbolTable_;
156 Expression expression_;
158 mutable std::array<Scalar, numVars> variables_;
159 mutable std::mutex evalMutex_;
167template<
class Scalar =
double>
Evaluating string math expressions containing named variables.
Definition: functionfromstringexpression.hh:58
void setVerbosity(unsigned int v)
Definition: functionfromstringexpression.hh:87
Scalar operator()(const std::array< S, numVars > ¶ms) const
Definition: functionfromstringexpression.hh:76
static constexpr std::size_t numVariables
Definition: functionfromstringexpression.hh:64
FunctionFromStringExpression(const std::string &expression, std::string_view variableNames)
Delegating constructor using all characters of a string as variables.
Definition: functionfromstringexpression.hh:72
FunctionFromStringExpression(const std::string &expression, const std::array< std::string, numVars > &variableNames)
Constructor from math expression and array of variable names.
Definition: functionfromstringexpression.hh:67
Scalar evalStringExpression(const std::string &expression, int verbosity=0)
Evaluating simple string math expressions.
Definition: functionfromstringexpression.hh:168