All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Matheval.cpp
Go to the documentation of this file.
1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2  Copyright (c) 2013 The plumed team
3  (see the PEOPLE file at the root of the distribution for a list of names)
4 
5  See http://www.plumed-code.org for more information.
6 
7  This file is part of plumed, version 2.0.
8 
9  plumed is free software: you can redistribute it and/or modify
10  it under the terms of the GNU Lesser General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  (at your option) any later version.
13 
14  plumed is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public License
20  along with plumed. If not, see <http://www.gnu.org/licenses/>.
21 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
22 #include "ActionRegister.h"
23 #include "Function.h"
24 
25 #ifdef __PLUMED_HAS_MATHEVAL
26 #include <matheval.h>
27 #endif
28 
29 using namespace std;
30 
31 namespace PLMD{
32 namespace function{
33 
34 
35 //+PLUMEDOC FUNCTION MATHEVAL
36 /*
37 Calculate a combination of variables using a matheval expression.
38 
39 If you are using a time dependent expression you can get the time using
40 \subpage TIME
41 
42 \par Examples
43 The following input tells plumed to print the angle between vectors
44 identified by atoms 1,2 and atoms 2,3
45 its square (as computed from the x,y,z components) and the distance
46 again as computed from the square root of the square.
47 \verbatim
48 DISTANCE LABEL=d1 ATOMS=1,2 COMPONENTS
49 DISTANCE LABEL=d2 ATOMS=2,3 COMPONENTS
50 MATHEVAL ...
51  LABEL=theta
52  ARG=d1.x,d1.y,d1.z,d2.x,d2.y,d2.z
53  VAR=ax,ay,az,bx,by,bz
54  FUNC=acos((ax*bx+ay*by+az*bz)/sqrt((ax*ax+ay*ay+az*az)*(bx*bx+by*by+bz*bz))
55  PERIODIC=NO
56 ... MATHEVAL
57 PRINT ARG=theta
58 \endverbatim
59 (See also \ref PRINT and \ref DISTANCE).
60 
61 \attention
62 The MATHEVAL object only works if libmatheval is installed on the system and
63 PLUMED has been linked to it
64 
65 */
66 //+ENDPLUMEDOC
67 
68 
69 class Matheval :
70  public Function
71 {
72  void* evaluator;
73  vector<void*> evaluator_deriv;
74  vector<string> var;
75  string func;
76  vector<double> values;
77  vector<char*> names;
78 public:
79  Matheval(const ActionOptions&);
80  ~Matheval();
81  void calculate();
82  static void registerKeywords(Keywords& keys);
83 };
84 
85 #ifdef __PLUMED_HAS_MATHEVAL
86 PLUMED_REGISTER_ACTION(Matheval,"MATHEVAL")
87 
88 void Matheval::registerKeywords(Keywords& keys){
89  Function::registerKeywords(keys);
90  keys.use("ARG"); keys.use("PERIODIC");
91  keys.add("compulsory","FUNC","the function you wish to evaluate");
92  keys.add("optional","VAR","the names to give each of the arguments in the function. If you have up to three arguments in your function you can use x, y and z to refer to them. Otherwise you must use this flag to give your variables names.");
93 }
94 
95 Matheval::Matheval(const ActionOptions&ao):
96 Action(ao),
97 Function(ao),
98 evaluator_deriv(getNumberOfArguments()),
99 values(getNumberOfArguments()),
100 names(getNumberOfArguments())
101 {
102  parseVector("VAR",var);
103  if(var.size()==0){
104  var.resize(getNumberOfArguments());
105  if(getNumberOfArguments()>3)
106  error("Using more than 3 arguments you should explicitly write their names with VAR");
107  if(var.size()>0) var[0]="x";
108  if(var.size()>1) var[1]="y";
109  if(var.size()>2) var[2]="z";
110  }
111  if(var.size()!=getNumberOfArguments())
112  error("Size of VAR array should be the same as number of arguments");
113  parse("FUNC",func);
115  checkRead();
116 
117  evaluator=evaluator_create(const_cast<char*>(func.c_str()));
118 
119  if(!evaluator) error("There was some problem in parsing matheval formula "+func);
120 
121  char **check_names;
122  int check_count;
123  evaluator_get_variables(evaluator,&check_names,&check_count);
124  if(check_count!=int(getNumberOfArguments())){
125  string sc;
126  Tools::convert(check_count,sc);
127  error("Your function string contains "+sc+" arguments. This should be equal to the number of ARGs");
128  }
129  for(unsigned i=0;i<getNumberOfArguments();i++){
130  bool found=false;
131  for(unsigned j=0;j<getNumberOfArguments();j++){
132  if(var[i]==check_names[j])found=true;
133  }
134  if(!found)
135  error("Variable "+var[i]+" cannot be found in your function string");
136  }
137 
138  for(unsigned i=0;i<getNumberOfArguments();i++)
139  evaluator_deriv[i]=evaluator_derivative(evaluator,const_cast<char*>(var[i].c_str()));
140 
141 
142  log.printf(" with function : %s\n",func.c_str());
143  log.printf(" with variables :");
144  for(unsigned i=0;i<var.size();i++) log.printf(" %s",var[i].c_str());
145  log.printf("\n");
146 }
147 
148 void Matheval::calculate(){
149  for(unsigned i=0;i<getNumberOfArguments();i++) values[i]=getArgument(i);
150  for(unsigned i=0;i<getNumberOfArguments();i++) names[i]=const_cast<char*>(var[i].c_str());
151  setValue(evaluator_evaluate(evaluator,names.size(),&names[0],&values[0]));
152 
153  for(unsigned i=0;i<getNumberOfArguments();i++){
154  setDerivative(i,evaluator_evaluate(evaluator_deriv[i],names.size(),&names[0],&values[0]));
155  }
156 }
157 
159  evaluator_destroy(evaluator);
160  for(unsigned i=0;i<evaluator_deriv.size();i++)evaluator_destroy(evaluator_deriv[i]);
161 }
162 
163 #endif
164 
165 }
166 }
167 
168 
Log & log
Reference to the log stream.
Definition: Action.h:93
static bool convert(const std::string &str, double &t)
Convert a string to a double, reading it.
Definition: Tools.cpp:74
void error(const std::string &msg) const
Crash calculation and print documentation.
Definition: Action.cpp:195
void checkRead()
Check if Action was properly read.
Definition: Action.cpp:161
STL namespace.
void parse(const std::string &key, T &t)
Parse one keyword as generic type.
Definition: Action.h:273
This class holds the keywords and their documentation.
Definition: Keywords.h:36
This class is used to bring the relevant information to the Action constructor.
Definition: Action.h:41
int printf(const char *fmt,...)
Formatted output with explicit format - a la printf.
Definition: OFile.cpp:82
Base class for all the input Actions.
Definition: Action.h:60
void parseVector(const std::string &key, std::vector< T > &t)
Parse one keyword as std::vector.
Definition: Action.h:311
void setValue(const double &d)
Set the default value (the one without name)
vector< char * > names
Definition: Matheval.cpp:77
double getArgument(const unsigned n) const
Returns the value of an argument.
vector< void * > evaluator_deriv
Definition: Matheval.cpp:73
Provides the keyword MATHEVAL
Definition: Matheval.cpp:69
This is the abstract base class to use for implementing new CV function, within it there is informati...
Definition: Function.h:37
vector< string > var
Definition: Matheval.cpp:74
vector< double > values
Definition: Matheval.cpp:76
void calculate()
Calculate an Action.
unsigned getNumberOfArguments() const
Returns the number of arguments.
void setDerivative(int, double)
Definition: Function.h:59