From caddb8b65e1d4fc6cef378d663862d627cd76501 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi <giovanni.bussi@gmail.com> Date: Tue, 10 Apr 2018 13:22:55 +0200 Subject: [PATCH] Optimized CUSTOM switching function --- src/tools/SwitchingFunction.cpp | 41 ++++++++++++++++++++++++--------- src/tools/SwitchingFunction.h | 2 ++ 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/tools/SwitchingFunction.cpp b/src/tools/SwitchingFunction.cpp index 0428be4f2..9616320da 100644 --- a/src/tools/SwitchingFunction.cpp +++ b/src/tools/SwitchingFunction.cpp @@ -124,19 +124,22 @@ s(r) = 1 - \tanh\left( \frac{ r - d_0 }{ r_0 } \right) {TANH R_0=\f$r_0\f$ D_0=\f$d_0\f$} </td> <td> </td> </tr> <tr> -<td> MATHEVAL </td> <td> +<td> CUSTOM </td> <td> \f$ s(r) = FUNC \f$ </td> <td> -{MATHEVAL FUNC=1/(1+x^6) R_0=\f$r_0\f$ D_0=\f$d_0\f$} +{CUSTOM FUNC=1/(1+x^6) R_0=\f$r_0\f$ D_0=\f$d_0\f$} </td> <td> </td> </tr> </table> +Notice that for backward compatibility we allow using `MATHEVAL` instead of `CUSTOM`. + \attention -Notice that using MATHEVAL is much slower than using e.g. RATIONAL. -Thus, the MATHEVAL switching function is useful to perform quick +Notice that CUSTOM is slower than other functions +(e.g., it is slower than an equivalent RATIONAL function by approximately a factor 2). +Thus, the CUSTOM switching function is useful to perform quick tests on switching functions with arbitrary form before proceeding to their implementation in C++. @@ -254,9 +257,30 @@ void SwitchingFunction::set(const std::string & definition,std::string& errormsg lepton_func=func; expression.resize(OpenMP::getNumThreads()); for(auto & e : expression) e=pe.createCompiledExpression(); + lepton_ref.resize(expression.size()); + for(unsigned t=0; t<lepton_ref.size(); t++) { + try { + lepton_ref[t]=&const_cast<lepton::CompiledExpression*>(&expression[t])->getVariableReference("x"); + } catch(PLMD::lepton::Exception& exc) { +// this is necessary since in some cases lepton things a variable is not present even though it is present +// e.g. func=0*x + lepton_ref[t]=nullptr; + } + } lepton::ParsedExpression ped=lepton::Parser::parse(func).differentiate("x").optimize(leptonConstants); expression_deriv.resize(OpenMP::getNumThreads()); for(auto & e : expression_deriv) e=ped.createCompiledExpression(); + lepton_ref_deriv.resize(expression_deriv.size()); + for(unsigned t=0; t<lepton_ref_deriv.size(); t++) { + try { + lepton_ref_deriv[t]=&const_cast<lepton::CompiledExpression*>(&expression_deriv[t])->getVariableReference("x"); + } catch(PLMD::lepton::Exception& exc) { +// this is necessary since in some cases lepton things a variable is not present even though it is present +// e.g. func=3*x + lepton_ref_deriv[t]=nullptr; + } + } + } else errormsg="cannot understand switching function type '"+name+"'"; if( !data.empty() ) { @@ -398,13 +422,8 @@ double SwitchingFunction::calculate(double distance,double&dfunc)const { } else if(type==leptontype) { const unsigned t=OpenMP::getThreadNum(); plumed_assert(t<expression.size()); - try { - const_cast<lepton::CompiledExpression*>(&expression[t])->getVariableReference("x")=rdist; - const_cast<lepton::CompiledExpression*>(&expression_deriv[t])->getVariableReference("x")=rdist; - } catch(PLMD::lepton::Exception& exc) { -// this is necessary since in some cases lepton things a variable is not present even though it is present -// e.g. func=0*x - } + if(lepton_ref[t]) *lepton_ref[t]=rdist; + if(lepton_ref_deriv[t]) *lepton_ref_deriv[t]=rdist; result=expression[t].evaluate(); dfunc=expression_deriv[t].evaluate(); } else plumed_merror("Unknown switching function type"); diff --git a/src/tools/SwitchingFunction.h b/src/tools/SwitchingFunction.h index bcb04ad8f..ef4390be3 100644 --- a/src/tools/SwitchingFunction.h +++ b/src/tools/SwitchingFunction.h @@ -81,6 +81,8 @@ class SwitchingFunction { /// Lepton expression for derivative /// \warning Since lepton::CompiledExpression is mutable, a vector is necessary for multithreading! std::vector<lepton::CompiledExpression> expression_deriv; + std::vector<double*> lepton_ref; + std::vector<double*> lepton_ref_deriv; public: static void registerKeywords( Keywords& keys ); /// Set a "rational" switching function. -- GitLab