From: heister Date: Thu, 6 Feb 2014 18:55:54 +0000 (+0000) Subject: towards thread-safe muparser X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e15a3fe1f354cfaef110bd94d02834d210096796;p=dealii-svn.git towards thread-safe muparser git-svn-id: https://svn.dealii.org/branches/branch_muparser@32424 0785d39b-7218-0410-832d-ea1e28bc413d --- diff --git a/deal.II/include/deal.II/base/function_parser.h b/deal.II/include/deal.II/base/function_parser.h index a5b6d8f613..3e0a974f3f 100644 --- a/deal.II/include/deal.II/base/function_parser.h +++ b/deal.II/include/deal.II/base/function_parser.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -540,18 +541,28 @@ public: //@} private: +#ifdef DEAL_II_WITH_MUPARSER /** - * A pointer to the actual - * function parsers. The pointer is - * to an array of parsers, not - * just a single one. The length of - * the array equals the number of - * vector components. + * muParser will stores references to these variables. */ -#ifdef DEAL_II_WITH_MUPARSER + + // TODO: document variables + mutable Threads::ThreadLocalStorage > vars; + mutable Threads::ThreadLocalStorage > fp; + mutable Threads::ThreadLocalStorage init_at_version; + + unsigned int version; + + std::map< std::string, double > constants; std::vector var_names; - mu::Parser *fp; + std::vector expressions; + void init_muparser() const; #else + /** + * A pointer to the actual function parsers. The pointer is to an array of + * parsers, not just a single one. The length of the array equals the number + * of vector components. + */ fparser::FunctionParser *fp; #endif /** diff --git a/deal.II/source/base/function_parser.cc b/deal.II/source/base/function_parser.cc index 9c08475d13..6954800be2 100644 --- a/deal.II/source/base/function_parser.cc +++ b/deal.II/source/base/function_parser.cc @@ -49,12 +49,14 @@ template FunctionParser::FunctionParser(const unsigned int n_components, const double initial_time) : - Function(n_components, initial_time), - fp (0) + Function(n_components, initial_time) +#ifdef DEAL_II_WITH_MUPARSER + ,version(0) +#else + ,fp (0) +#endif { - #ifdef DEAL_II_WITH_MUPARSER - fp = new mu::Parser[n_components]; #else fp = new fparser::FunctionParser[n_components]; #endif @@ -65,7 +67,10 @@ FunctionParser::FunctionParser(const unsigned int n_components, template FunctionParser::~FunctionParser() { +#ifdef DEAL_II_WITH_MUPARSER +#else delete[] fp; +#endif } @@ -85,12 +90,45 @@ void FunctionParser::initialize (const std::string &varia use_degrees); } -double constant_eval(double x, double c) +#ifdef DEAL_II_WITH_MUPARSER +template +void FunctionParser:: init_muparser() const { - return x*c; -} + if (version == init_at_version.get()) + return; + + fp.get().resize(this->n_components); + vars.get().resize(var_names.size()); + for (unsigned int i=0; in_components; ++i) + { + std::map< std::string, double >::const_iterator + constant = constants.begin(), + endc = constants.end(); + for (; constant != endc; ++constant) + { + fp.get()[i].DefineConst(constant->first.c_str(), constant->second); + } + for (unsigned int iv=0;iv void FunctionParser::initialize (const std::string &variables, @@ -100,6 +138,18 @@ void FunctionParser::initialize (const std::string &variables, const bool time_dependent, const bool use_degrees) { + +#ifdef DEAL_II_WITH_MUPARSER + version++; + + this->constants = constants; + this->var_names = Utilities::split_string_list(variables, ','); + this->expressions = expressions; + AssertThrow(((time_dependent)?dim+1:dim) == var_names.size(), + ExcMessage("wrong number of variables")); + AssertThrow(!use_degrees, ExcNotImplemented()); +#endif + // We check that the number of // components of this function // matches the number of components @@ -109,11 +159,6 @@ void FunctionParser::initialize (const std::string &variables, ExcInvalidExpressionSize(this->n_components, expressions.size()) ); -#ifdef DEAL_II_WITH_MUPARSER - var_names = Utilities::split_string_list(variables, ','); - AssertThrow(((time_dependent)?dim+1:dim) == var_names.size(), ExcMessage("wrong number of variables")); -#endif - for (unsigned int i=0; in_components; ++i) { @@ -131,7 +176,6 @@ void FunctionParser::initialize (const std::string &variables, // std_cxx1x::bind(&constant_eval, std_cxx1x:_1, unit->second)); AssertThrow(false, ExcNotImplemented()); - #else const bool success = fp[i].AddUnit(unit->first, unit->second); AssertThrow (success, @@ -150,7 +194,6 @@ void FunctionParser::initialize (const std::string &variables, for (; constant != endc; ++constant) { #ifdef DEAL_II_WITH_MUPARSER - fp[i].DefineConst(constant->first.c_str(), constant->second); #else const bool success = fp[i].AddConstant(constant->first, constant->second); AssertThrow (success, ExcMessage("Invalid Constant Name")); @@ -158,9 +201,6 @@ void FunctionParser::initialize (const std::string &variables, } #ifdef DEAL_II_WITH_MUPARSER - AssertThrow(!use_degrees, ExcNotImplemented()); - - fp[i].SetExpr(expressions[i]); #else const int ret_value = fp[i].Parse(expressions[i], variables, @@ -203,6 +243,10 @@ void FunctionParser::initialize (const std::string &variables, ExcDimensionMismatch(n_vars,fp[0].NVars())); */ +#ifdef DEAL_II_WITH_MUPARSER + init_muparser(); +#endif + // Now set the initialization bit. initialized = true; } @@ -255,29 +299,38 @@ double FunctionParser::value (const Point &p, Assert (component < this->n_components, ExcIndexRange(component, 0, this->n_components)); +#ifdef DEAL_II_WITH_MUPARSER + + init_muparser(); + + for (unsigned int i=0; iget_time(); + + try + { + return fp.get()[component].Eval(); + } + catch (mu::ParserError &e) + { + cerr << "Message: " << e.GetMsg() << "\n"; + cerr << "Formula: " << e.GetExpr() << "\n"; + cerr << "Token: " << e.GetToken() << "\n"; + cerr << "Position: " << e.GetPos() << "\n"; + cerr << "Errc: " << e.GetCode() << std::endl; + AssertThrow(false, ExcParseError(e.GetCode(), e.GetMsg().c_str())); + return 0.0; + } +#else // Statically allocate dim+1 // double variables. double vars[dim+1]; - for (unsigned int i=0; iget_time(); -#ifdef DEAL_II_WITH_MUPARSER - for (unsigned int iv=0;iv::vector_value (const Point &p, Assert (values.size() == this->n_components, ExcDimensionMismatch (values.size(), this->n_components)); - // Statically allocates dim+1 - // double variables. - double vars[dim+1]; - for (unsigned int i=0; iget_time(); - -#ifdef DEAL_II_WITH_MUPARSER + vars.get()[dim] = this->get_time(); for (unsigned int component = 0; component < this->n_components; ++component) - { - for (unsigned int iv=0;ivget_time(); for (unsigned int component = 0; component < this->n_components; ++component)