virtual double
value(const Point<dim> &p, const unsigned int component = 0) const override;
- /**
- * Return all components of a vector-valued function at the given point @p
- * p.
- *
- * <code>values</code> shall have the right size beforehand, i.e.
- * #n_components.
- */
- virtual void
- vector_value(const Point<dim> &p, Vector<double> &values) const override;
-
/**
* Return an array of function expressions (one per component), used to
* initialize this function.
<< ").");
//@}
-
-private:
- /**
- * Initialize fp and vars on the current thread. This function may only be
- * called once per thread. A thread can test whether the function has
- * already been called by testing whether 'fp.get().size()==0' (not
- * initialized) or >0 (already initialized).
- */
- void
- init_muparser() const;
};
#include <deal.II/base/config.h>
+#include <deal.II/base/array_view.h>
+#include <deal.II/base/point.h>
#include <deal.II/base/thread_local_storage.h>
#include <memory>
#include <string>
#include <vector>
-
DEAL_II_NAMESPACE_OPEN
-
-
-#ifdef DEAL_II_WITH_MUPARSER
-
namespace internal
{
namespace FunctionParser
*/
std::vector<std::string>
get_function_names();
+
+ /**
+ * @addtogroup Exceptions
+ * @{
+ */
+ DeclException2(ExcParseError,
+ int,
+ std::string,
+ << "Parsing Error at Column " << arg1
+ << ". The parser said: " << arg2);
+
+ //@}
+
/**
* deal.II uses muParser as a purely internal dependency. To this end, we do
* not include any muParser headers in our own headers (and the bundled
mutable Threads::ThreadLocalStorage<internal::FunctionParser::ParserData>
parser_data;
+ void
+ init_muparser() const;
+
+ Number
+ do_value(const Point<dim> &p,
+ const double time,
+ unsigned int component) const;
+
+ void
+ do_all_values(const Point<dim> & p,
+ const double time,
+ ArrayView<Number> &values) const;
+
/**
* An array to keep track of all the constants, required to initialize fp
* in each thread.
*/
unsigned int n_vars;
};
-
-
} // namespace FunctionParser
-
} // namespace internal
-#endif
-
-
DEAL_II_NAMESPACE_CLOSE
<< ").");
//@}
-
private:
- /**
- * Initialize tfp and vars on the current thread. This function may only be
- * called once per thread. A thread can test whether the function has
- * already been called by testing whether 'tfp.get().size()==0' (not
- * initialized) or >0 (already initialized).
- */
- void
- init_muparser() const;
-
/**
* Number of components is equal dim<sup>rank</sup>.
*/
symbolic_function.inst.in
tensor_function.inst.in
tensor_function_parser.inst.in
+ mu_parser_internal.inst.in
time_stepping.inst.in
)
#include <cmath>
#include <map>
-#ifdef DEAL_II_WITH_MUPARSER
-# include <muParser.h>
-#endif
-
DEAL_II_NAMESPACE_OPEN
// value() and vector_value(). this is not strictly necessary because a user
// may never call these functions on the current thread, but it gets us
// error messages about wrong formulas right away
- init_muparser();
+ this->init_muparser();
// finally set the initialization bit
this->initialized = true;
}
-namespace internal
-{
- namespace FunctionParserImplementation
- {
- namespace
- {
- /**
- * PIMPL for mu::Parser.
- */
- class Parser : public internal::FunctionParser::muParserBase
- {
- public:
- operator mu::Parser &()
- {
- return parser;
- }
-
- operator const mu::Parser &() const
- {
- return parser;
- }
-
- protected:
- mu::Parser parser;
- };
- } // namespace
- } // namespace FunctionParserImplementation
-} // namespace internal
-
-
-template <int dim>
-void
-FunctionParser<dim>::init_muparser() const
-{
- // check that we have not already initialized the parser on the
- // current thread, i.e., that the current function is only called
- // once per thread
- internal::FunctionParser::ParserData &data = this->parser_data.get();
- Assert(data.parsers.size() == 0 && data.vars.size() == 0, ExcInternalError());
-
- // initialize the objects for the current thread
- data.parsers.reserve(this->n_components);
- data.vars.resize(this->var_names.size());
- for (unsigned int component = 0; component < this->n_components; ++component)
- {
- data.parsers.emplace_back(
- new internal::FunctionParserImplementation::Parser());
- mu::Parser &parser =
- dynamic_cast<internal::FunctionParserImplementation::Parser &>(
- *data.parsers.back());
-
- for (const auto &constant : this->constants)
- parser.DefineConst(constant.first, constant.second);
-
- for (unsigned int iv = 0; iv < this->var_names.size(); ++iv)
- parser.DefineVar(this->var_names[iv], &data.vars[iv]);
-
- // define some compatibility functions:
- parser.DefineFun("if", internal::FunctionParser::mu_if, true);
- parser.DefineOprt("|", internal::FunctionParser::mu_or, 1);
- parser.DefineOprt("&", internal::FunctionParser::mu_and, 2);
- parser.DefineFun("int", internal::FunctionParser::mu_int, true);
- parser.DefineFun("ceil", internal::FunctionParser::mu_ceil, true);
- parser.DefineFun("cot", internal::FunctionParser::mu_cot, true);
- parser.DefineFun("csc", internal::FunctionParser::mu_csc, true);
- parser.DefineFun("floor", internal::FunctionParser::mu_floor, true);
- parser.DefineFun("sec", internal::FunctionParser::mu_sec, true);
- parser.DefineFun("log", internal::FunctionParser::mu_log, true);
- parser.DefineFun("pow", internal::FunctionParser::mu_pow, true);
- parser.DefineFun("erf", internal::FunctionParser::mu_erf, true);
- parser.DefineFun("erfc", internal::FunctionParser::mu_erfc, true);
- parser.DefineFun("rand_seed",
- internal::FunctionParser::mu_rand_seed,
- true);
- parser.DefineFun("rand", internal::FunctionParser::mu_rand, true);
-
- try
- {
- // muparser expects that functions have no
- // space between the name of the function and the opening
- // parenthesis. this is awkward because it is not backward
- // compatible to the library we used to use before muparser
- // (the fparser library) but also makes no real sense.
- // consequently, in the expressions we set, remove any space
- // we may find after function names
- std::string transformed_expression = this->expressions[component];
-
- for (const auto ¤t_function_name :
- internal::FunctionParser::get_function_names())
- {
- const unsigned int function_name_length =
- current_function_name.size();
-
- std::string::size_type pos = 0;
- while (true)
- {
- // try to find any occurrences of the function name
- pos = transformed_expression.find(current_function_name, pos);
- if (pos == std::string::npos)
- break;
-
- // replace whitespace until there no longer is any
- while ((pos + function_name_length <
- transformed_expression.size()) &&
- ((transformed_expression[pos + function_name_length] ==
- ' ') ||
- (transformed_expression[pos + function_name_length] ==
- '\t')))
- transformed_expression.erase(
- transformed_expression.begin() + pos +
- function_name_length);
-
- // move the current search position by the size of the
- // actual function name
- pos += function_name_length;
- }
- }
-
- // now use the transformed expression
- parser.SetExpr(transformed_expression);
- }
- catch (mu::ParserError &e)
- {
- std::cerr << "Message: <" << e.GetMsg() << ">\n";
- std::cerr << "Formula: <" << e.GetExpr() << ">\n";
- std::cerr << "Token: <" << e.GetToken() << ">\n";
- std::cerr << "Position: <" << e.GetPos() << ">\n";
- std::cerr << "Errc: <" << e.GetCode() << ">" << std::endl;
- AssertThrow(false, ExcParseError(e.GetCode(), e.GetMsg()));
- }
- }
-}
-
template <int dim>
FunctionParser<dim>::value(const Point<dim> & p,
const unsigned int component) const
{
- Assert(this->initialized == true, ExcNotInitialized());
- AssertIndexRange(component, this->n_components);
-
- // initialize the parser if that hasn't happened yet on the current thread
- internal::FunctionParser::ParserData &data = this->parser_data.get();
- if (data.vars.size() == 0)
- init_muparser();
-
- for (unsigned int i = 0; i < dim; ++i)
- data.vars[i] = p(i);
- if (dim != this->n_vars)
- data.vars[dim] = this->get_time();
-
- try
- {
- Assert(dynamic_cast<internal::FunctionParserImplementation::Parser *>(
- data.parsers[component].get()),
- ExcInternalError());
- // using dynamic_cast in the next line is about 6% slower than
- // static_cast, so use the assertion above for debugging and disable
- // clang-tidy:
- mu::Parser &parser =
- static_cast<internal::FunctionParserImplementation::Parser &>( // NOLINT
- *data.parsers[component]);
- return parser.Eval();
- }
- catch (mu::ParserError &e)
- {
- std::cerr << "Message: <" << e.GetMsg() << ">\n";
- std::cerr << "Formula: <" << e.GetExpr() << ">\n";
- std::cerr << "Token: <" << e.GetToken() << ">\n";
- std::cerr << "Position: <" << e.GetPos() << ">\n";
- std::cerr << "Errc: <" << e.GetCode() << ">" << std::endl;
- AssertThrow(false, ExcParseError(e.GetCode(), e.GetMsg()));
- return 0.0;
- }
-}
-
-
-
-template <int dim>
-void
-FunctionParser<dim>::vector_value(const Point<dim> &p,
- Vector<double> & values) const
-{
- Assert(this->initialized == true, ExcNotInitialized());
- Assert(values.size() == this->n_components,
- ExcDimensionMismatch(values.size(), this->n_components));
-
-
- // initialize the parser if that hasn't happened yet on the current thread
- internal::FunctionParser::ParserData &data = this->parser_data.get();
- if (data.vars.size() == 0)
- init_muparser();
-
- for (unsigned int i = 0; i < dim; ++i)
- data.vars[i] = p(i);
- if (dim != this->n_vars)
- data.vars[dim] = this->get_time();
-
- for (unsigned int component = 0; component < this->n_components; ++component)
- {
- // Same comment in value() applies here too:
- Assert(dynamic_cast<internal::FunctionParserImplementation::Parser *>(
- data.parsers[component].get()),
- ExcInternalError());
- mu::Parser &parser =
- static_cast<internal::FunctionParserImplementation::Parser &>( // NOLINT
- *data.parsers[component]);
-
- values(component) = parser.Eval();
- }
+ return this->do_value(p, this->get_time(), component);
}
#else
#include <random>
#include <vector>
+#ifdef DEAL_II_WITH_MUPARSER
+# include <muParser.h>
+#endif
DEAL_II_NAMESPACE_OPEN
-
-
-#ifdef DEAL_II_WITH_MUPARSER
-
namespace internal
{
namespace FunctionParser
"rand_seed"};
}
- } // namespace FunctionParser
+#ifdef DEAL_II_WITH_MUPARSER
+ /**
+ * PIMPL for mu::Parser.
+ */
+ class Parser : public muParserBase
+ {
+ public:
+ operator mu::Parser &()
+ {
+ return parser;
+ }
+
+ operator const mu::Parser &() const
+ {
+ return parser;
+ }
+
+ protected:
+ mu::Parser parser;
+ };
+#endif
-} // namespace internal
+
+
+ template <int dim, typename Number>
+ void
+ ParserImplementation<dim, Number>::init_muparser() const
+ {
+#ifdef DEAL_II_WITH_MUPARSER
+ // check that we have not already initialized the parser on the
+ // current thread, i.e., that the current function is only called
+ // once per thread
+ ParserData &data = this->parser_data.get();
+ Assert(data.parsers.size() == 0 && data.vars.size() == 0,
+ ExcInternalError());
+ const unsigned int n_components = expressions.size();
+
+ // initialize the objects for the current thread
+ data.parsers.reserve(n_components);
+ data.vars.resize(this->var_names.size());
+ for (unsigned int component = 0; component < n_components; ++component)
+ {
+ data.parsers.emplace_back(std::make_unique<Parser>());
+ mu::Parser &parser = dynamic_cast<Parser &>(*data.parsers.back());
+
+ for (const auto &constant : this->constants)
+ parser.DefineConst(constant.first, constant.second);
+
+ for (unsigned int iv = 0; iv < this->var_names.size(); ++iv)
+ parser.DefineVar(this->var_names[iv], &data.vars[iv]);
+
+ // define some compatibility functions:
+ parser.DefineFun("if", mu_if, true);
+ parser.DefineOprt("|", mu_or, 1);
+ parser.DefineOprt("&", mu_and, 2);
+ parser.DefineFun("int", mu_int, true);
+ parser.DefineFun("ceil", mu_ceil, true);
+ parser.DefineFun("cot", mu_cot, true);
+ parser.DefineFun("csc", mu_csc, true);
+ parser.DefineFun("floor", mu_floor, true);
+ parser.DefineFun("sec", mu_sec, true);
+ parser.DefineFun("log", mu_log, true);
+ parser.DefineFun("pow", mu_pow, true);
+ parser.DefineFun("erfc", mu_erfc, true);
+ parser.DefineFun("rand_seed", mu_rand_seed, true);
+ parser.DefineFun("rand", mu_rand, true);
+
+ try
+ {
+ // muparser expects that functions have no
+ // space between the name of the function and the opening
+ // parenthesis. this is awkward because it is not backward
+ // compatible to the library we used to use before muparser
+ // (the fparser library) but also makes no real sense.
+ // consequently, in the expressions we set, remove any space
+ // we may find after function names
+ std::string transformed_expression = this->expressions[component];
+
+ for (const auto ¤t_function_name : get_function_names())
+ {
+ const unsigned int function_name_length =
+ current_function_name.size();
+
+ std::string::size_type pos = 0;
+ while (true)
+ {
+ // try to find any occurrences of the function name
+ pos =
+ transformed_expression.find(current_function_name, pos);
+ if (pos == std::string::npos)
+ break;
+
+ // replace whitespace until there no longer is any
+ while (
+ (pos + function_name_length <
+ transformed_expression.size()) &&
+ ((transformed_expression[pos + function_name_length] ==
+ ' ') ||
+ (transformed_expression[pos + function_name_length] ==
+ '\t')))
+ transformed_expression.erase(
+ transformed_expression.begin() + pos +
+ function_name_length);
+
+ // move the current search position by the size of the
+ // actual function name
+ pos += function_name_length;
+ }
+ }
+
+ // now use the transformed expression
+ parser.SetExpr(transformed_expression);
+ }
+ catch (mu::ParserError &e)
+ {
+ std::cerr << "Message: <" << e.GetMsg() << ">\n";
+ std::cerr << "Formula: <" << e.GetExpr() << ">\n";
+ std::cerr << "Token: <" << e.GetToken() << ">\n";
+ std::cerr << "Position: <" << e.GetPos() << ">\n";
+ std::cerr << "Errc: <" << e.GetCode() << ">" << std::endl;
+ AssertThrow(false, ExcParseError(e.GetCode(), e.GetMsg()));
+ }
+ }
+#else
+ AssertThrow(false, ExcNeedsFunctionparser());
+#endif
+ }
+
+ template <int dim, typename Number>
+ Number
+ ParserImplementation<dim, Number>::do_value(const Point<dim> &p,
+ const double time,
+ unsigned int component) const
+ {
+#ifdef DEAL_II_WITH_MUPARSER
+ Assert(this->initialized == true, ExcNotInitialized());
+
+ // initialize the parser if that hasn't happened yet on the current
+ // thread
+ internal::FunctionParser::ParserData &data = this->parser_data.get();
+ if (data.vars.size() == 0)
+ init_muparser();
+
+ for (unsigned int i = 0; i < dim; ++i)
+ data.vars[i] = p(i);
+ if (dim != this->n_vars)
+ data.vars[dim] = time;
+
+ try
+ {
+ Assert(dynamic_cast<Parser *>(data.parsers[component].get()),
+ ExcInternalError());
+ // NOLINTNEXTLINE don't warn about using static_cast once we check
+ mu::Parser &parser = static_cast<Parser &>(*data.parsers[component]);
+ return parser.Eval();
+ } // try
+ catch (mu::ParserError &e)
+ {
+ std::cerr << "Message: <" << e.GetMsg() << ">\n";
+ std::cerr << "Formula: <" << e.GetExpr() << ">\n";
+ std::cerr << "Token: <" << e.GetToken() << ">\n";
+ std::cerr << "Position: <" << e.GetPos() << ">\n";
+ std::cerr << "Errc: <" << e.GetCode() << ">" << std::endl;
+ AssertThrow(false, ExcParseError(e.GetCode(), e.GetMsg()));
+ } // catch
+
+#else
+ AssertThrow(false, ExcNeedsFunctionparser());
+#endif
+ return std::numeric_limits<double>::signaling_NaN();
+ }
+
+ template <int dim, typename Number>
+ void
+ ParserImplementation<dim, Number>::do_all_values(
+ const Point<dim> & p,
+ const double time,
+ ArrayView<Number> &values) const
+ {
+#ifdef DEAL_II_WITH_MUPARSER
+ Assert(this->initialized == true, ExcNotInitialized());
+
+ // initialize the parser if that hasn't happened yet on the current
+ // thread
+ internal::FunctionParser::ParserData &data = this->parser_data.get();
+ if (data.vars.size() == 0)
+ init_muparser();
+
+ for (unsigned int i = 0; i < dim; ++i)
+ data.vars[i] = p(i);
+ if (dim != this->n_vars)
+ data.vars[dim] = time;
+
+ AssertDimension(values.size(), data.parsers.size());
+ try
+ {
+ for (unsigned int component = 0; component < data.parsers.size();
+ ++component)
+ {
+ Assert(dynamic_cast<Parser *>(data.parsers[component].get()),
+ ExcInternalError());
+ mu::Parser &parser =
+ // We just checked that the pointer is valid so suppress the
+ // clang-tidy check
+ static_cast<Parser &>(*data.parsers[component]); // NOLINT
+ values[component] = parser.Eval();
+ }
+ } // try
+ catch (mu::ParserError &e)
+ {
+ std::cerr << "Message: <" << e.GetMsg() << ">\n";
+ std::cerr << "Formula: <" << e.GetExpr() << ">\n";
+ std::cerr << "Token: <" << e.GetToken() << ">\n";
+ std::cerr << "Position: <" << e.GetPos() << ">\n";
+ std::cerr << "Errc: <" << e.GetCode() << ">" << std::endl;
+ AssertThrow(false, ExcParseError(e.GetCode(), e.GetMsg()));
+ } // catch
+#else
+ AssertThrow(false, ExcNeedsFunctionparser());
#endif
+ }
+// explicit instantiations
+#include "mu_parser_internal.inst"
+ } // namespace FunctionParser
+} // namespace internal
DEAL_II_NAMESPACE_CLOSE
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2022 - 2022 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+for (S : REAL_SCALARS; dim : SPACE_DIMENSIONS)
+ {
+ template class ParserImplementation<dim, S>;
+ }
+
+for (S : COMPLEX_SCALARS; dim : SPACE_DIMENSIONS)
+ {
+ template class ParserImplementation<dim, S>;
+ }
#include <cmath>
#include <map>
-#ifdef DEAL_II_WITH_MUPARSER
-# include <muParser.h>
-#endif
-
DEAL_II_NAMESPACE_OPEN
// because a user may never call these functions on the current
// thread, but it gets us error messages about wrong formulas right
// away
- init_muparser();
+ this->init_muparser();
// finally set the initialization bit
this->initialized = true;
-namespace internal
-{
- namespace TensorFunctionParserImplementation
- {
- namespace
- {
- /**
- * PIMPL for mu::Parser.
- */
- class Parser : public internal::FunctionParser::muParserBase
- {
- public:
- operator mu::Parser &()
- {
- return parser;
- }
-
- operator const mu::Parser &() const
- {
- return parser;
- }
-
- protected:
- mu::Parser parser;
- };
- } // namespace
- } // namespace TensorFunctionParserImplementation
-} // namespace internal
-
-
-
-template <int rank, int dim, typename Number>
-void
-TensorFunctionParser<rank, dim, Number>::init_muparser() const
-{
- // check that we have not already initialized the parser on the
- // current thread, i.e., that the current function is only called
- // once per thread
- internal::FunctionParser::ParserData &data = this->parser_data.get();
- Assert(data.parsers.size() == 0 && data.vars.size() == 0, ExcInternalError());
-
- // initialize the objects for the current thread
- data.parsers.reserve(this->n_components);
- data.vars.resize(this->var_names.size());
- for (unsigned int component = 0; component < this->n_components; ++component)
- {
- data.parsers.emplace_back(
- std::make_unique<
- internal::TensorFunctionParserImplementation::Parser>());
- mu::Parser &parser =
- dynamic_cast<internal::TensorFunctionParserImplementation::Parser &>(
- *data.parsers.back());
-
- for (const auto &constant : this->constants)
- parser.DefineConst(constant.first, constant.second);
-
- for (unsigned int iv = 0; iv < this->var_names.size(); ++iv)
- parser.DefineVar(this->var_names[iv], &data.vars[iv]);
-
- // define some compatibility functions:
- parser.DefineFun("if", internal::FunctionParser::mu_if, true);
- parser.DefineOprt("|", internal::FunctionParser::mu_or, 1);
- parser.DefineOprt("&", internal::FunctionParser::mu_and, 2);
- parser.DefineFun("int", internal::FunctionParser::mu_int, true);
- parser.DefineFun("ceil", internal::FunctionParser::mu_ceil, true);
- parser.DefineFun("cot", internal::FunctionParser::mu_cot, true);
- parser.DefineFun("csc", internal::FunctionParser::mu_csc, true);
- parser.DefineFun("floor", internal::FunctionParser::mu_floor, true);
- parser.DefineFun("sec", internal::FunctionParser::mu_sec, true);
- parser.DefineFun("log", internal::FunctionParser::mu_log, true);
- parser.DefineFun("pow", internal::FunctionParser::mu_pow, true);
- parser.DefineFun("erfc", internal::FunctionParser::mu_erfc, true);
- parser.DefineFun("rand_seed",
- internal::FunctionParser::mu_rand_seed,
- true);
- parser.DefineFun("rand", internal::FunctionParser::mu_rand, true);
-
- try
- {
- // muparser expects that functions have no
- // space between the name of the function and the opening
- // parenthesis. this is awkward because it is not backward
- // compatible to the library we used to use before muparser
- // (the fparser library) but also makes no real sense.
- // consequently, in the expressions we set, remove any space
- // we may find after function names
- std::string transformed_expression = this->expressions[component];
-
- for (const auto ¤t_function_name :
- internal::FunctionParser::get_function_names())
- {
- const unsigned int function_name_length =
- current_function_name.size();
-
- std::string::size_type pos = 0;
- while (true)
- {
- // try to find any occurrences of the function name
- pos = transformed_expression.find(current_function_name, pos);
- if (pos == std::string::npos)
- break;
-
- // replace whitespace until there no longer is any
- while ((pos + function_name_length <
- transformed_expression.size()) &&
- ((transformed_expression[pos + function_name_length] ==
- ' ') ||
- (transformed_expression[pos + function_name_length] ==
- '\t')))
- transformed_expression.erase(
- transformed_expression.begin() + pos +
- function_name_length);
-
- // move the current search position by the size of the
- // actual function name
- pos += function_name_length;
- }
- }
-
- // now use the transformed expression
- parser.SetExpr(transformed_expression);
- }
- catch (mu::ParserError &e)
- {
- std::cerr << "Message: <" << e.GetMsg() << ">\n";
- std::cerr << "Formula: <" << e.GetExpr() << ">\n";
- std::cerr << "Token: <" << e.GetToken() << ">\n";
- std::cerr << "Position: <" << e.GetPos() << ">\n";
- std::cerr << "Errc: <" << e.GetCode() << ">" << std::endl;
- AssertThrow(false, ExcParseError(e.GetCode(), e.GetMsg()));
- }
- }
-}
-
-
-
template <int rank, int dim, typename Number>
void
TensorFunctionParser<rank, dim, Number>::initialize(
Tensor<rank, dim, Number>
TensorFunctionParser<rank, dim, Number>::value(const Point<dim> &p) const
{
- Assert(this->initialized == true, ExcNotInitialized());
-
- // initialize the parser if that hasn't happened yet on the current thread
- internal::FunctionParser::ParserData &data = this->parser_data.get();
- if (data.vars.size() == 0)
- init_muparser();
-
- for (unsigned int i = 0; i < dim; ++i)
- data.vars[i] = p(i);
- if (dim != this->n_vars)
- data.vars[dim] = this->get_time();
-
std::array<Number, Tensor<rank, dim, Number>::n_independent_components>
- values;
-
- try
- {
- for (unsigned int component = 0; component < values.size(); ++component)
- {
- Assert(dynamic_cast<
- internal::TensorFunctionParserImplementation::Parser *>(
- data.parsers[component].get()),
- ExcInternalError());
- mu::Parser &parser = static_cast< // NOLINT
- internal::TensorFunctionParserImplementation::Parser &>(
- *data.parsers[component]);
- values[component] = parser.Eval();
- } // for
- } // try
- catch (mu::ParserError &e)
- {
- std::cerr << "Message: <" << e.GetMsg() << ">\n";
- std::cerr << "Formula: <" << e.GetExpr() << ">\n";
- std::cerr << "Token: <" << e.GetToken() << ">\n";
- std::cerr << "Position: <" << e.GetPos() << ">\n";
- std::cerr << "Errc: <" << e.GetCode() << ">" << std::endl;
- AssertThrow(false, ExcParseError(e.GetCode(), e.GetMsg()));
-
- return Tensor<rank, dim, Number>();
- } // catch
+ values;
+ auto values_view = make_array_view(values.begin(), values.end());
+ this->do_all_values(p, this->get_time(), values_view);
return Tensor<rank, dim, Number>(
make_array_view(values.begin(), values.end()));