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 std::lock_guard lock(evalMutex_);
95 for (std::size_t i = 0; i < numVars; ++i)
96 variables_[i] = params[i];
97 return expression_.value();
100 template<std::size_t... I>
101 std::array<std::string, numVars> extractVariableNames_(std::string_view names, std::index_sequence<I...>)
const
103 static_assert(numVars ==
sizeof...(I),
"Number of variables has to match size of index set.");
104 if (names.size() != numVars)
105 DUNE_THROW(Dune::IOError,
"Number of variables in '"
106 << names <<
"' does not match number of function arguments: " << numVars);
107 return { std::string(1, names.at(I))... };
111 void initialize_(
const std::string& expression,
const std::array<std::string, numVars>& variableNames)
113 for (std::size_t i = 0; i < numVars; ++i)
114 symbolTable_.add_variable(std::string{variableNames[i]}, variables_[i]);
115 symbolTable_.add_constants();
116 expression_.register_symbol_table(symbolTable_);
118 if (!parser_.compile(expression, expression_))
120 std::stringstream ss;
121 ss << Fmt::format(
"Parsing expression '{}' failed.\n", expression);
125 for (std::size_t i = 0; i < parser_.error_count(); ++i)
127 const auto error = parser_.get_error(i);
130 "-- error (position: {:02d}, type: {}): {}\n",
131 static_cast<unsigned int>(error.token.position),
132 exprtk::parser_error::to_str(error.mode).c_str(),
133 error.diagnostic.c_str()
138 DUNE_THROW(Dune::IOError, ss.str());
140 else if (verbosity_ >= 2)
142 std::cout << Fmt::format(
143 "Successfully parsed math expression '{}'\n",
149 unsigned int verbosity_ = 2;
150 SymbolTable symbolTable_;
151 Expression expression_;
153 mutable std::array<Scalar, numVars> variables_;
154 mutable std::mutex evalMutex_;
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