From b5531ffa53df199898c00f5e9661884e8a07c7a9 Mon Sep 17 00:00:00 2001
From: Giovanni Bussi <giovanni.bussi@gmail.com>
Date: Tue, 20 Jun 2017 08:07:52 +0200
Subject: [PATCH] cleanup MATHEVAL

---
 src/function/Matheval.cpp | 71 +++++++++++++++++----------------------
 1 file changed, 30 insertions(+), 41 deletions(-)

diff --git a/src/function/Matheval.cpp b/src/function/Matheval.cpp
index eea59315d..8a7fd382a 100644
--- a/src/function/Matheval.cpp
+++ b/src/function/Matheval.cpp
@@ -189,6 +189,8 @@ class Matheval :
   public Function
 {
   const bool use_lepton;
+  lepton::CompiledExpression expression;
+  std::vector<lepton::CompiledExpression> expression_deriv;
   void* evaluator;
   vector<void*> evaluator_deriv;
   vector<string> var;
@@ -215,7 +217,9 @@ Matheval::Matheval(const ActionOptions&ao):
   Action(ao),
   Function(ao),
   use_lepton(std::getenv("PLUMED_USE_LEPTON")),
-  evaluator_deriv(getNumberOfArguments()),
+  expression_deriv(getNumberOfArguments()),
+  evaluator(NULL),
+  evaluator_deriv(getNumberOfArguments(),NULL),
   values(getNumberOfArguments()),
   names(getNumberOfArguments())
 {
@@ -234,26 +238,31 @@ Matheval::Matheval(const ActionOptions&ao):
   addValueWithDerivatives();
   checkRead();
 
+  log.printf("  with function : %s\n",func.c_str());
+  log.printf("  with variables :");
+  for(unsigned i=0; i<var.size(); i++) log.printf(" %s",var[i].c_str());
+  log.printf("\n");
+
   if(use_lepton) {
-    func=func;
     log<<"  WARNING: you are using lepton as a replacement for libmatheval\n";
-    evaluator=new lepton::CompiledExpression(lepton::Parser::parse(func).optimize(leptonConstants).createCompiledExpression());
+    lepton::ParsedExpression pe=lepton::Parser::parse(func).optimize(leptonConstants);
+    log<<"  function as parsed by lepton: "<<pe<<"\n";
+    expression=pe.createCompiledExpression();
+    for(auto &p: expression.getVariables()) {
+      if(std::find(var.begin(),var.end(),p)==var.end()) {
+        error("variable " + p + " is not defined");
+      }
+    }
+    log<<"  derivatives as computed by lepton:\n";
+    for(unsigned i=0; i<getNumberOfArguments(); i++) {
+      lepton::ParsedExpression pe=lepton::Parser::parse(func).differentiate(var[i]).optimize(leptonConstants);
+      log<<"    "<<pe<<"\n";
+      expression_deriv[i]=pe.createCompiledExpression();
+    }
   } else {
 #ifdef __PLUMED_HAS_MATHEVAL
     evaluator=evaluator_create(const_cast<char*>(func.c_str()));
-#else
-    error("MATHEVAL not available, please export PLUMED_USE_LEPTON=yes");
-#endif
-  }
-
-  if(!evaluator) error("There was some problem in parsing matheval formula "+func);
-
-  if(use_lepton) {
-    for(unsigned i=0; i<getNumberOfArguments(); i++)
-      evaluator_deriv[i]=new
-      lepton::CompiledExpression(lepton::Parser::parse(func).differentiate(var[i]).optimize(leptonConstants).createCompiledExpression());
-  } else {
-#ifdef __PLUMED_HAS_MATHEVAL
+    if(!evaluator) error("There was some problem in parsing matheval formula "+func);
     char **check_names;
     int    check_count;
     evaluator_get_variables(evaluator,&check_names,&check_count);
@@ -272,21 +281,6 @@ Matheval::Matheval(const ActionOptions&ao):
     }
     for(unsigned i=0; i<getNumberOfArguments(); i++)
       evaluator_deriv[i]=evaluator_derivative(evaluator,const_cast<char*>(var[i].c_str()));
-#else
-    error("MATHEVAL not available, please export PLUMED_USE_LEPTON=yes");
-#endif
-  }
-
-  log.printf("  with function : %s\n",func.c_str());
-  log.printf("  with variables :");
-  for(unsigned i=0; i<var.size(); i++) log.printf(" %s",var[i].c_str());
-  log.printf("\n");
-  if(use_lepton) {
-    log<<"  function as parsed by lepton: "<<lepton::Parser::parse(func).optimize(leptonConstants)<<"\n";
-    log<<"  derivatives as computed by lepton:\n";
-    for(unsigned i=0; i<var.size(); i++) log<<"    "<<lepton::Parser::parse(func).differentiate(var[i]).optimize(leptonConstants)<<"\n";
-  } else {
-#ifdef __PLUMED_HAS_MATHEVAL
     log.printf("  function as parsed by matheval: %s\n", evaluator_get_string(evaluator));
     log.printf("  derivatives as computed by matheval:\n");
     for(unsigned i=0; i<var.size(); i++) log.printf("    %s\n",evaluator_get_string(evaluator_deriv[i]));
@@ -300,23 +294,23 @@ void Matheval::calculate() {
   if(use_lepton) {
     for(unsigned i=0; i<getNumberOfArguments(); i++) {
       try {
-        static_cast<lepton::CompiledExpression*>(evaluator)->getVariableReference(var[i])=getArgument(i);
+        expression.getVariableReference(var[i])=getArgument(i);
       } 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
       }
     }
-    setValue(static_cast<lepton::CompiledExpression*>(evaluator)->evaluate());
+    setValue(expression.evaluate());
     for(unsigned i=0; i<getNumberOfArguments(); i++) {
       for(unsigned j=0; j<getNumberOfArguments(); j++) {
         try {
-          static_cast<lepton::CompiledExpression*>(evaluator_deriv[i])->getVariableReference(var[j])=getArgument(j);
+          expression_deriv[i].getVariableReference(var[j])=getArgument(j);
         } 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
         }
       }
-      setDerivative(i,static_cast<lepton::CompiledExpression*>(evaluator_deriv[i])->evaluate());
+      setDerivative(i,expression_deriv[i].evaluate());
     }
   } else {
 #ifdef __PLUMED_HAS_MATHEVAL
@@ -333,12 +327,7 @@ void Matheval::calculate() {
 }
 
 Matheval::~Matheval() {
-  if(use_lepton) {
-    for(unsigned i=0; i<evaluator_deriv.size(); i++) {
-      delete static_cast<lepton::CompiledExpression*>(evaluator_deriv[i]);
-    }
-    delete static_cast<lepton::CompiledExpression*>(evaluator);
-  } else {
+  if(evaluator){
 #ifdef __PLUMED_HAS_MATHEVAL
     evaluator_destroy(evaluator);
     for(unsigned i=0; i<evaluator_deriv.size(); i++)evaluator_destroy(evaluator_deriv[i]);
-- 
GitLab