MOOSE - Multiscale Object Oriented Simulation Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Func.cpp
Go to the documentation of this file.
1 // Func.cpp ---
2 //
3 // Filename: Func.cpp
4 // Description: Implementation of a wrapper around GNU libmatheval to calculate arbitrary functions.
5 // Author: Subhasis Ray
6 // Maintainer: Subhasis Ray
7 // Created: Sat May 25 16:35:17 2013 (+0530)
8 // Version:
9 // Last-Updated: Tue Jun 11 16:49:01 2013 (+0530)
10 // By: subha
11 // Update #: 619
12 // URL:
13 // Keywords:
14 // Compatibility:
15 //
16 //
17 
18 // Commentary:
19 //
20 //
21 //
22 //
23 
24 // Change log:
25 //
26 //
27 //
28 //
29 // This program is free software; you can redistribute it and/or
30 // modify it under the terms of the GNU Lesser General Public License as
31 // published by the Free Software Foundation; either version 3, or
32 // (at your option) any later version.
33 //
34 // This program is distributed in the hope that it will be useful,
35 // but WITHOUT ANY WARRANTY; without even the implied warranty of
36 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
37 // General Public License for more details.
38 //
39 // You should have received a copy of the GNU Lesser General Public License
40 // along with this program; see the file COPYING. If not, write to
41 // the Free Software Foundation, Inc., 51 Franklin Street, Fifth
42 // Floor, Boston, MA 02110-1301, USA.
43 //
44 //
45 
46 // Code:
47 
48 #include "header.h"
49 #include "../utility/utility.h"
50 #include "../utility/numutil.h"
51 #include "Func.h"
52 
54 {
55  static SrcFinfo1<double> valueOut("valueOut",
56  "Evaluated value of the function for the current variable values.");
57  return &valueOut;
58 }
59 
61 {
62  static SrcFinfo1< double > derivativeOut("derivativeOut",
63  "Value of derivative of the function for the current variable values");
64  return &derivativeOut;
65 }
66 
68 {
70  // Value fields
73  "Result of the function evaluation with current variable values.",
75  static ReadOnlyValueFinfo< Func, double > derivative("derivative",
76  "Derivative of the function at given variable values.",
78  static ValueFinfo< Func, unsigned int > mode("mode",
79  "Mode of operation: \n"
80  " 1: only the function value will be calculated\n"
81  " 2: only the derivative will be calculated\n"
82  " 3: both function value and derivative at current variable values will be calculated.",
84  &Func::getMode);
85  static ValueFinfo< Func, string > expr("expr",
86  "Mathematical expression defining the function. The underlying parser\n"
87  "is muParser. In addition to the available functions and operators from\n"
88  "muParser, some more functions are added.\n"
89  "\nFunctions\n"
90  "Name args explanation\n"
91  "sin 1 sine function\n"
92  "cos 1 cosine function\n"
93  "tan 1 tangens function\n"
94  "asin 1 arcus sine function\n"
95  "acos 1 arcus cosine function\n"
96  "atan 1 arcus tangens function\n"
97  "sinh 1 hyperbolic sine function\n"
98  "cosh 1 hyperbolic cosine\n"
99  "tanh 1 hyperbolic tangens function\n"
100  "asinh 1 hyperbolic arcus sine function\n"
101  "acosh 1 hyperbolic arcus tangens function\n"
102  "atanh 1 hyperbolic arcur tangens function\n"
103  "log2 1 logarithm to the base 2\n"
104  "log10 1 logarithm to the base 10\n"
105  "log 1 logarithm to the base 10\n"
106  "ln 1 logarithm to base e (2.71828...)\n"
107  "exp 1 e raised to the power of x\n"
108  "sqrt 1 square root of a value\n"
109  "sign 1 sign function -1 if x<0; 1 if x>0\n"
110  "rint 1 round to nearest integer\n"
111  "abs 1 absolute value\n"
112  "min var. min of all arguments\n"
113  "max var. max of all arguments\n"
114  "sum var. sum of all arguments\n"
115  "avg var. mean value of all arguments\n"
116  "rand 1 rand(seed), random float between 0 and 1, \n"
117  " if seed = -1, then a 'random' seed is created.\n"
118  "rand2 3 rand(a, b, seed), random float between a and b, \n"
119  " if seed = -1, a 'random' seed is created using either\n"
120  " by random_device or by reading system clock\n"
121  "\nOperators\n"
122  "Op meaning prioroty\n"
123  "= assignement -1\n"
124  "&& logical and 1\n"
125  "|| logical or 2\n"
126  "<= less or equal 4\n"
127  ">= greater or equal 4\n"
128  "!= not equal 4\n"
129  "== equal 4\n"
130  "> greater than 4\n"
131  "< less than 4\n"
132  "+ addition 5\n"
133  "- subtraction 5\n"
134  "* multiplication 6\n"
135  "/ division 6\n"
136  "^ raise x to the power of y 7\n"
137  "\n"
138  "?: if then else operator C++ style syntax\n",
139  &Func::setExpr,
140  &Func::getExpr);
142  "Lookup table for variable values.",
143  &Func::setVar,
144  &Func::getVar);
145  static ReadOnlyValueFinfo< Func, vector<string> > vars("vars",
146  "Variable names in the expression",
147  &Func::getVars);
148  static ValueFinfo< Func, double > x("x",
149  "Value for variable named x. This is a shorthand. If the\n"
150  "expression does not have any variable named x, this the first variable\n"
151  "in the sequence `vars`.",
152  &Func::setX,
153  &Func::getX);
154  static ValueFinfo< Func, double > y("y",
155  "Value for variable named y. This is a utility for two/three\n"
156  " variable functions where the y value comes from a source separate\n"
157  " from that of x. This is a shorthand. If the\n"
158  "expression does not have any variable named y, this the second\n"
159  "variable in the sequence `vars`.",
160  &Func::setY,
161  &Func::getY);
162  static ValueFinfo< Func, double > z("z",
163  "Value for variable named z. This is a utility for three\n"
164  " variable functions where the z value comes from a source separate\n"
165  " from that of x or z. This is a shorthand. If the expression does not\n"
166  " have any variable named z, this the third variable in the sequence `vars`.",
167  &Func::setZ,
168  &Func::getZ);
170  // DestFinfos
172  static DestFinfo varIn("varIn",
173  "Handle value for specified variable coming from other objects",
175  static DestFinfo xIn("xIn",
176  "Handle value for variable named x. This is a shorthand. If the\n"
177  "expression does not have any variable named x, this the first variable\n"
178  "in the sequence `vars`.",
180  static DestFinfo yIn("yIn",
181  "Handle value for variable named y. This is a utility for two/three\n"
182  " variable functions where the y value comes from a source separate\n"
183  " from that of x. This is a shorthand. If the\n"
184  "expression does not have any variable named y, this the second\n"
185  "variable in the sequence `vars`.",
187  static DestFinfo zIn("zIn",
188  "Handle value for variable named z. This is a utility for three\n"
189  " variable functions where the z value comes from a source separate\n"
190  " from that of x or y. This is a shorthand. If the expression does not\n"
191  " have any variable named y, this the second variable in the sequence `vars`.",
193  static DestFinfo xyIn("xyIn",
194  "Handle value for variables x and y for two-variable function",
196  static DestFinfo xyzIn("xyzIn",
197  "Handle value for variables x, y and z for three-variable function",
199 
200  static DestFinfo setVars("setVars",
201  "Utility function to assign the variable values of the function.\n"
202  "Takes a list of variable names and a list of corresponding values.",
203  new OpFunc2< Func, vector< string >, vector< double > > (&Func::setVarValues));
204 
205  // TODO - a way to allow connect a source to a specific variable without the source knowing the variable name
206  // simple case of x, [y, [z]] variables
207 
209  // Shared messages
211  static DestFinfo process( "process",
212  "Handles process call, updates internal time stamp.",
214  static DestFinfo reinit( "reinit",
215  "Handles reinit call.",
217  static Finfo* processShared[] =
218  {
219  &process, &reinit
220  };
221 
222  static SharedFinfo proc( "proc",
223  "This is a shared message to receive Process messages "
224  "from the scheduler objects."
225  "The first entry in the shared msg is a MsgDest "
226  "for the Process operation. It has a single argument, "
227  "ProcInfo, which holds lots of information about current "
228  "time, thread, dt and so on. The second entry is a MsgDest "
229  "for the Reinit operation. It also uses ProcInfo. ",
230  processShared, sizeof( processShared ) / sizeof( Finfo* )
231  );
232 
233  static Finfo *funcFinfos[] =
234  {
235  &value,
236  &derivative,
237  &mode,
238  &expr,
239  &var,
240  &vars,
241  &x,
242  &y,
243  &z,
244  &varIn,
245  &xIn,
246  &yIn,
247  &zIn,
248  &xyIn,
249  &xyzIn,
250  &proc,
251  valueOut(),
252  derivativeOut(),
253  };
254 
255  static string doc[] =
256  {
257  "Name", "Func",
258  "Author", "Subhasis Ray",
259  "Description",
260  "Func: general purpose function calculator using real numbers. It can\n"
261  "parse mathematical expression defining a function and evaluate it\n"
262  "and/or its derivative for specified variable values.\n"
263  "The variables can be input from other moose objects. In case of\n"
264  "arbitrary variable names, the source message must have the variable\n"
265  "name as the first argument. For most common cases, input messages to\n"
266  "set x, y, z and xy, xyz are made available without such\n"
267  "requirement. This class handles only real numbers\n"
268  "(C-double). Predefined constants are: pi=3.141592...,\n"
269  "e=2.718281... \n"
270  };
271 
272  static Dinfo< Func > dinfo;
273  static Cinfo funcCinfo("Func",
275  funcFinfos,
276  sizeof(funcFinfos) / sizeof(Finfo*),
277  &dinfo,
278  doc,
279  sizeof(doc)/sizeof(string));
280  return &funcCinfo;
281 
282 }
283 
284 static const Cinfo * funcCinfo = Func::initCinfo();
285 
286 const int Func::VARMAX = 10;
287 
288 Func::Func():_x(NULL), _y(NULL), _z(NULL), _mode(1), _valid(false)
289 {
290  _varbuf.reserve(VARMAX);
291  _parser.SetVarFactory(_addVar, this);
292  // Adding pi and e, the defaults are `_pi` and `_e`
293  _parser.DefineConst(_T("pi"), (mu::value_type)M_PI);
294  _parser.DefineConst(_T("e"), (mu::value_type)M_E);
295 }
296 
297 Func::Func(const Func& rhs): _mode(rhs._mode)
298 {
299  _varbuf.reserve(VARMAX);
300  _parser.SetVarFactory(_addVar, this);
301  // Adding pi and e, the defaults are `_pi` and `_e`
302  _parser.DefineConst(_T("pi"), (mu::value_type)M_PI);
303  _parser.DefineConst(_T("e"), (mu::value_type)M_E);
304  setExpr(rhs.getExpr());
305  vector <string> vars = rhs.getVars();
306  for (unsigned int ii = 0; ii < vars.size(); ++ii)
307  {
308  setVar(vars[ii], rhs.getVar(vars[ii]));
309  }
310 }
311 
313 {
314  _clearBuffer();
315  _mode = rhs._mode;
316  // Adding pi and e, the defaults are `_pi` and `_e`
317  _parser.DefineConst(_T("pi"), (mu::value_type)M_PI);
318  _parser.DefineConst(_T("e"), (mu::value_type)M_E);
319  setExpr(rhs.getExpr());
320  vector <string> vars = rhs.getVars();
321  for (unsigned int ii = 0; ii < vars.size(); ++ii)
322  {
323  setVar(vars[ii], rhs.getVar(vars[ii]));
324  }
325  return *this;
326 }
327 
329 {
330 
331  _clearBuffer();
332 }
333 
335 {
336  _parser.ClearVar();
337  for (unsigned int ii = 0; ii < _varbuf.size(); ++ii)
338  {
339  delete _varbuf[ii];
340  }
341  _varbuf.clear();
342 }
343 
344 void Func::_showError(mu::Parser::exception_type &e) const
345 {
346  cout << "Error occurred in parser.\n"
347  << "Message: " << e.GetMsg() << "\n"
348  << "Formula: " << e.GetExpr() << "\n"
349  << "Token: " << e.GetToken() << "\n"
350  << "Position: " << e.GetPos() << "\n"
351  << "Error code: " << e.GetCode() << endl;
352 }
356 static double * _addVar(const char *name, void *data)
357 {
358  Func* func = reinterpret_cast< Func * >(data);
359  double *ret = new double;
360  *ret = 0.0;
361  func->_varbuf.push_back(ret);
362  return ret;
363 }
364 
365 void Func::setExpr(string expr)
366 {
367  _valid = false;
368  _x = NULL;
369  _y = NULL;
370  _z = NULL;
371  mu::varmap_type vars;
372  try
373  {
374  _parser.SetExpr(expr);
375  vars = _parser.GetUsedVar();
376  }
377  catch (mu::Parser::exception_type &e)
378  {
379  _showError(e);
380  _clearBuffer();
381  return;
382  }
383  mu::varmap_type::iterator v = vars.find("x");
384  if (v != vars.end())
385  {
386  _x = v->second;
387  }
388  else if (vars.size() >= 1)
389  {
390  v = vars.begin();
391  _x = v->second;
392  }
393  v = vars.find("y");
394  if (v != vars.end())
395  {
396  _y = v->second;
397  }
398  else if (vars.size() >= 2)
399  {
400  v = vars.begin();
401  ++v;
402  _y = v->second;
403  }
404  v = vars.find("z");
405  if (v != vars.end())
406  {
407  _z = v->second;
408  }
409  else if (vars.size() >= 3)
410  {
411  v = vars.begin();
412  v++;
413  v++;
414  _z = v->second;
415  }
416  _valid = true;
417 }
418 
419 string Func::getExpr() const
420 {
421  if (!_valid)
422  {
423  cout << "Error: Func::getExpr() - invalid parser state" << endl;
424  return "";
425  }
426  return _parser.GetExpr();
427 }
428 
432 void Func::setVar(string name, double value)
433 {
434  if (!_valid)
435  {
436  cout << "Error: Func::setVar() - invalid parser state" << endl;
437  return;
438  }
439  mu::varmap_type vars;
440  try
441  {
442  vars = _parser.GetVar();
443  }
444  catch (mu::Parser::exception_type &e)
445  {
446  _valid = false;
447  _showError(e);
448  return;
449  }
450  mu::varmap_type::iterator v = vars.find(name);
451  if (v != vars.end())
452  {
453  *v->second = value;
454  }
455  else
456  {
457  cout << "Error: no such variable " << name << endl;
458  }
459 }
460 
464 double Func::getVar(string name) const
465 {
466  if (!_valid)
467  {
468  cout << "Error: Func::getVar() - invalid parser state" << endl;
469  return 0.0;
470  }
471  try
472  {
473  const mu::varmap_type &vars = _parser.GetVar();
474  mu::varmap_type::const_iterator v = vars.find(name);
475  if (v != vars.end())
476  {
477  return *v->second;
478  }
479  else
480  {
481  cout << "Error: no such variable " << name << endl;
482  return 0.0;
483  }
484  }
485  catch (mu::Parser::exception_type &e)
486  {
487  _showError(e);
488  return 0.0;
489  }
490 }
491 
492 void Func::setX(double x)
493 {
494  if (_x != NULL)
495  {
496  *_x = x;
497  }
498 }
499 
500 double Func::getX() const
501 {
502  if (_x != NULL)
503  {
504  return *_x;
505  }
506  return 0.0;
507 }
508 
509 void Func::setY(double y)
510 {
511  if (_y != NULL)
512  {
513  *_y = y;
514  }
515 }
516 
517 double Func::getY() const
518 {
519  if (_y != NULL)
520  {
521  return *_y;
522  }
523  return 0.0;
524 }
525 void Func::setZ(double z)
526 {
527  if (_z != NULL)
528  {
529  *_z = z;
530  }
531 }
532 
533 double Func::getZ() const
534 {
535  if (_z != NULL)
536  {
537  return *_z;
538  }
539  return 0.0;
540 }
541 
542 void Func::setXY(double x, double y)
543 {
544  if (_x != NULL)
545  {
546  *_x = x;
547  }
548  if (_y != NULL)
549  {
550  *_y = y;
551  }
552 }
553 
554 void Func::setXYZ(double x, double y, double z)
555 {
556  if (_x != NULL)
557  {
558  *_x = x;
559  }
560  if (_y != NULL)
561  {
562  *_y = y;
563  }
564  if (_z != NULL)
565  {
566  *_z = z;
567  }
568 }
569 
570 void Func::setMode(unsigned int mode)
571 {
572  _mode = mode;
573 }
574 
575 unsigned int Func::getMode() const
576 {
577  return _mode;
578 }
579 
580 double Func::getValue() const
581 {
582  double value = 0.0;
583  if (!_valid)
584  {
585  cout << "Error: Func::getValue() - invalid state" << endl;
586  return value;
587  }
588  try
589  {
590  value = _parser.Eval();
591  }
592  catch (mu::Parser::exception_type &e)
593  {
594  _showError(e);
595  }
596  return value;
597 }
598 
599 double Func::getDerivative() const
600 {
601  double value = 0.0;
602  if (!_valid)
603  {
604  cout << "Error: Func::getDerivative() - invalid state" << endl;
605  return value;
606  }
607  if (_x != NULL)
608  {
609  try
610  {
611  value = _parser.Diff(_x, *_x);
612  }
613  catch (mu::Parser::exception_type &e)
614  {
615  _showError(e);
616  }
617  }
618  return value;
619 }
620 
621 
622 vector<string> Func::getVars() const
623 {
624  vector< string > ret;
625  if (!_valid)
626  {
627  cout << "Error: Func::getVars() - invalid parser state" << endl;
628  return ret;
629  }
630  mu::varmap_type vars;
631  try
632  {
633  vars = _parser.GetVar();
634  for (mu::varmap_type::iterator ii = vars.begin();
635  ii != vars.end(); ++ii)
636  {
637  ret.push_back(ii->first);
638  }
639  }
640  catch (mu::Parser::exception_type &e)
641  {
642  _showError(e);
643  }
644  return ret;
645 }
646 
647 void Func::setVarValues(vector<string> vars, vector<double> vals)
648 {
649 
650  if (vars.size() > vals.size() || !_valid)
651  {
652  return;
653  }
654  mu::varmap_type varmap = _parser.GetVar();
655  for (unsigned int ii = 0; ii < vars.size(); ++ii)
656  {
657  mu::varmap_type::iterator v = varmap.find(vars[ii]);
658  if ( v != varmap.end())
659  {
660  *v->second = vals[ii];
661  }
662  }
663 }
664 
665 void Func::process(const Eref &e, ProcPtr p)
666 {
667  if (!_valid)
668  {
669  return;
670  }
671  if (_mode & 1)
672  {
673  valueOut()->send(e, getValue());
674  }
675  if (_mode & 2)
676  {
677  derivativeOut()->send(e, getDerivative());
678  }
679 }
680 
681 void Func::reinit(const Eref &e, ProcPtr p)
682 {
683  if (!_valid)
684  {
685  cout << "Error: Func::reinit() - invalid parser state. Will do nothing." << endl;
686  return;
687  }
688  if (moose::trim(_parser.GetExpr(), " \t\n\r").length() == 0)
689  {
690  cout << "Error: no expression set. Will do nothing." << endl;
691  setExpr("0.0");
692  _valid = false;
693  }
694 }
695 //
696 // Func.cpp ends here
void setVarValues(vector< string > vars, vector< double > vals)
Definition: Func.cpp:647
static const int VARMAX
Definition: Func.h:61
uint32_t value
Definition: moosemodule.h:42
void setVar(string name, double value)
Definition: Func.cpp:432
void setY(double value)
Definition: Func.cpp:509
static double * _addVar(const char *name, void *data)
Definition: Func.cpp:356
double * _x
Definition: Func.h:111
static const Cinfo * initCinfo()
Definition: Func.cpp:67
double value_type
double * _y
Definition: Func.h:111
Definition: Dinfo.h:60
Definition: OpFunc.h:56
void _clearBuffer()
Definition: Func.cpp:334
bool _valid
Definition: Func.h:113
vector< string > getVars() const
Definition: Func.cpp:622
void setX(double value)
Definition: Func.cpp:492
void setXYZ(double x, double y, double z)
Definition: Func.cpp:554
double getZ() const
Definition: Func.cpp:533
#define M_PI
Definition: numutil.h:34
double getVar(string name) const
Definition: Func.cpp:464
static SrcFinfo1< double > * derivativeOut()
Definition: Func.cpp:60
void reinit(const Eref &e, ProcPtr p)
Definition: Func.cpp:681
Definition: OpFunc.h:40
double getX() const
Definition: Func.cpp:500
Func()
Definition: Func.cpp:288
double * _z
Definition: Func.h:111
double getValue() const
Definition: Func.cpp:580
void setXY(double x, double y)
Definition: Func.cpp:542
static SrcFinfo1< double > * valueOut()
Definition: Func.cpp:53
void setZ(double value)
Definition: Func.cpp:525
~Func()
Definition: Func.cpp:328
Definition: OpFunc.h:27
Definition: Eref.h:26
Definition: Func.h:58
friend double * _addVar(const char *name, void *data)
Definition: Func.cpp:356
void setMode(unsigned int mode)
Definition: Func.cpp:570
mu::Parser _parser
Definition: Func.h:110
static char name[]
Definition: mfield.cpp:401
double getDerivative() const
Definition: Func.cpp:599
unsigned int _mode
Definition: Func.h:112
void process(const Eref &e, ProcPtr p)
Definition: Func.cpp:665
double getY() const
Definition: Func.cpp:517
#define M_E
Definition: numutil.h:38
static const Cinfo * initCinfo()
Definition: Neutral.cpp:16
string getExpr() const
Definition: Func.cpp:419
std::string trim(const std::string myString, const string &delimiters)
Definition: strutil.cpp:53
void setExpr(string expr)
Definition: Func.cpp:365
static const Cinfo * funcCinfo
Definition: Func.cpp:284
void _showError(mu::Parser::exception_type &e) const
Definition: Func.cpp:344
Definition: Cinfo.h:18
vector< double * > _varbuf
Definition: Func.h:109
unsigned int getMode() const
Definition: Func.cpp:575
Func & operator=(const Func rhs)
Definition: Func.cpp:312
Definition: Finfo.h:12