diff --git a/MathEval/parser.y b/MathEval/parser.y new file mode 100644 index 0000000000000000000000000000000000000000..7c3d250b11ac510474b1de58d6b73bf4a6e9cfe5 --- /dev/null +++ b/MathEval/parser.y @@ -0,0 +1,119 @@ +%{ +/* + * Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of GNU libmatheval + * + * GNU libmatheval is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU libmatheval is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with program; see the file COPYING. If not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* This file was modified for inclusion in Gmsh */ + +#include "common.h" +#include "node.h" + +/* Variables used to communicate with code using parser. */ +extern Node* matheval_root; /* Root of tree representation of function. */ +extern int matheval_ok; /* Flag representing success of parsing. */ + +/* Report parsing error. */ +int yyerror (char *s); + +/* Function used to tokenize string representing function (this function + is generated by scanner generator). */ +int yylex (void); +%} + +/* Parser semantic values type. */ +%union { + Node *node; + Record *record; +} + +/* Grammar terminal symbols. */ +%token <node> NUMBER VARIABLE +%token <record> FUNCTION + +/* Grammar non-terminal symbols. */ +%type <node> expression + +%left '-' '+' +%left '*' '/' +%left NEG +%left '^' + +/* Grammar start non-terminal. */ +%start input + +%% + +input +: expression '\n' { + matheval_root = $1; + yyerrok; + return 1; +} +; + +expression +: NUMBER { + $$ = $1; +} +| VARIABLE { + $$ = $1; +} +| expression '+' expression { + /* Create addition binary operator node. */ + $$ = node_create ('b', '+', $1, $3); +} +| expression '-' expression { + /* Create subtraction binary operator node. */ + $$ = node_create ('b', '-', $1, $3); +} +| expression '*' expression { + /* Create multiplication binary operator node. */ + $$ = node_create ('b', '*', $1, $3); +} +| expression '/' expression { + /* Create division binary operator node. */ + $$ = node_create ('b', '/', $1, $3); +} +| '-' expression %prec NEG { + /* Create minus unary operator node. */ + $$ = node_create ('u', '-', $2); +} +| expression '^' expression { + /* Create exponentiation unary operator node. */ + $$ = node_create ('b', '^', $1, $3); +} +| FUNCTION '(' expression ')' { + /* Create function node. */ + $$ = node_create ('f', $1, $3); +} +| '(' expression ')' { + $$ = $2; +} +; + +%% + +int yyerror(char* s) +{ + /* Indicate parsing error through appropriate flag and stop + parsing. */ + matheval_ok = 0; + return 0; +} diff --git a/MathEval/scanner.l b/MathEval/scanner.l new file mode 100644 index 0000000000000000000000000000000000000000..8c6977fd41b83d043d1f58c0cdcd7b3ceacae71c --- /dev/null +++ b/MathEval/scanner.l @@ -0,0 +1,126 @@ +%{ +/* + * Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of GNU libmatheval + * + * GNU libmatheval is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU libmatheval is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with program; see the file COPYING. If not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* This file was modified for inclusion in Gmsh */ + +#include "common.h" +#include "node.h" +#include "parser.h" +#include "symbol_table.h" + +/* Redefine macro to redirect scanner input from string instead of + standard input. */ +#define YY_INPUT( buffer, result, max_size ) \ +{ result = input_from_string (buffer, max_size); } + +/* Variables used to communicate with code using scanner. */ +extern SymbolTable *matheval_symbol_table; /* Evaluator symbol table. */ +extern char *matheval_input_string; /* String representing function. */ + +/* Read next max_size character from string into buffer. */ +static int input_from_string (char *buffer, int max_size); +%} + +/* Token definitions. */ +whitespace [\ \t]+ +digit [0-9] +number ({digit}+|{digit}+"."{digit}*|{digit}*"."{digit}+)([Ee][-+]?{digit}+)? +function "Exp"|"Log"|"Sqrt"|"Sin"|"Cos"|"Tan"|"Ctan"|"Asin"|"Acos"|"Atan"|"Actan"|"Sinh"|"Cosh"|"Tanh"|"Ctanh"|"Asinh"|"Acosh"|"Atanh"|"Actanh"|"Fabs" +identifier [a-zA-Z\_][a-zA-Z0-9\_]* + +%% + +{whitespace} + +{number} { + /* Create node representing constant with appropriate value. */ + melval.node = node_create ('c', atof (metext)); + return NUMBER; +} + +{function} { + /* Find symbol table record corresponding to function name. */ + melval.record = symbol_table_lookup (matheval_symbol_table, metext); + return FUNCTION; +} + +{identifier} { + Record *record; /* Symbol table record. */ + /* Inserty variable into symbol table. */ + record = symbol_table_insert (matheval_symbol_table, metext, 'v'); + melval.node = node_create ('v', record); + return VARIABLE; +} + +"+" { + return '+'; +} + +"-" { + return '-'; +} + +"*" { + return '*'; +} + +"/" { + return '/'; +} + +"^" { + return '^'; +} + +"(" { + return '('; +} + +")" { + return ')'; +} + +"\n" { + return '\n'; +} + +%% + +#undef mewrap + +int mewrap() {return 1;} + +static int input_from_string (char *buffer, int max_size) +{ + int count; /* Count of characters to copy from input string to buffer. */ + + /* Calculate count of characters to copy. */ + count = strlen (matheval_input_string); + if (count > max_size) + count = max_size; + + /* Perform copy operation and update input string. */ + memcpy(buffer, matheval_input_string, count); + matheval_input_string += count; + + return count; +} diff --git a/Plugin/Evaluate.cpp b/Plugin/Evaluate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..336a3c0386754c2c76972b04f98f3f23f02748c8 --- /dev/null +++ b/Plugin/Evaluate.cpp @@ -0,0 +1,209 @@ +// $Id: Evaluate.cpp,v 1.1 2004-05-12 03:23:31 geuzaine Exp $ +// +// Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems to <gmsh@geuz.org>. + +#include "Plugin.h" +#include "Evaluate.h" +#include "List.h" +#include "Views.h" +#include "Context.h" +#include "Numeric.h" + +#if defined(HAVE_MATH_EVAL) +#include "matheval.h" +#endif + +extern Context_T CTX; + +StringXNumber EvaluateOptions_Number[] = { + {GMSH_FULLRC, "TimeStep", NULL, 0.}, + {GMSH_FULLRC, "iView", NULL, -1.} +}; + +StringXString EvaluateOptions_String[] = { + {GMSH_FULLRC, "Expression", NULL, "Sin(v) * Sqrt(x^2+y^2)"} +}; + +extern "C" +{ + GMSH_Plugin *GMSH_RegisterEvaluatePlugin() + { + return new GMSH_EvaluatePlugin(); + } +} + + +GMSH_EvaluatePlugin::GMSH_EvaluatePlugin() +{ + ; +} + +void GMSH_EvaluatePlugin::getName(char *name) const +{ + strcpy(name, "Evaluate"); +} + +void GMSH_EvaluatePlugin::getInfos(char *author, char *copyright, + char *help_text) const +{ + strcpy(author, "C. Geuzaine (geuz@geuz.org)"); + strcpy(copyright, "DGR (www.multiphysics.com)"); + strcpy(help_text, + "Plugin(Evaluate) sets the values associated with\n" + "the `TimeStep'-th time step in the view `iView'\n" + "to the expression `Expression'. In addition to\n" + "the usual mathematical functions, `Expression' can\n" + "contain the symbols x, y, z and v, which represent\n" + "the three spatial coordinates and the value of the\n" + "field, respectively.\n" + "\n" + "Plugin(Evaluate) is executed in-place.\n"); +} + +int GMSH_EvaluatePlugin::getNbOptions() const +{ + return sizeof(EvaluateOptions_Number) / sizeof(StringXNumber); +} + +StringXNumber *GMSH_EvaluatePlugin::getOption(int iopt) +{ + return &EvaluateOptions_Number[iopt]; +} + +int GMSH_EvaluatePlugin::getNbOptionsStr() const +{ + return sizeof(EvaluateOptions_String) / sizeof(StringXString); +} + +StringXString *GMSH_EvaluatePlugin::getOptionStr(int iopt) +{ + return &EvaluateOptions_String[iopt]; +} + +void GMSH_EvaluatePlugin::catchErrorMessage(char *errorMessage) const +{ + strcpy(errorMessage, "Evaluate failed..."); +} + +static void evaluateList(Post_View * v, List_T * list, int nbElm, + int nbNod, int timeStep, char *expression) +{ +#if !defined(HAVE_MATH_EVAL) + + Msg(GERROR, "MathEval is not compiled in this version of Gmsh"); + +#else + + double *x, *y, *z, *val; + int nb, i, j; + + if(!nbElm) + return; + + v->Changed = 1; + + if(timeStep < 0 || timeStep > v->NbTimeStep - 1){ + Msg(WARNING, "Invalid TimeStep (%d) in View[%d]: choosing TimeStep 0", + timeStep, v->Index); + timeStep = 0; + } + + void *f = evaluator_create(expression); + + if(!f){ + Msg(GERROR, "Invalid expression '%s'", expression); + return; + } + + double min = VAL_INF; + double max = -VAL_INF; + + nb = List_Nbr(list) / nbElm; + for(i = 0; i < List_Nbr(list); i += nb) { + x = (double *)List_Pointer_Fast(list, i); + y = (double *)List_Pointer_Fast(list, i + nbNod); + z = (double *)List_Pointer_Fast(list, i + 2 * nbNod); + val = (double *)List_Pointer_Fast(list, i + 3 * nbNod); + for(j = 0; j < nbNod; j++) { + + double xx = x[j]; + double yy = y[j]; + double zz = z[j]; + double vv = val[nbNod * timeStep + j]; + + char *names[] = { "x", "y" , "z", "v" }; + double values[] = { xx , yy, zz, vv }; + double res = evaluator_evaluate(f, sizeof(names)/sizeof(names[0]), names, values); + + val[nbNod * timeStep + j] = res; + if(res < min) min = res; + if(res > max) max = res; + } + } + + evaluator_destroy(f); + + v->TimeStepMin[timeStep] = min; + v->TimeStepMax[timeStep] = max; + v->Min = v->TimeStepMin[0]; + v->Max = v->TimeStepMax[0]; + for(int i = 1; i < v->NbTimeStep; i++){ + if(v->TimeStepMin[i] < v->Min) v->Min = v->TimeStepMin[i]; + if(v->TimeStepMax[i] > v->Max) v->Max = v->TimeStepMax[i]; + } + +#endif +} + +static void evaluate(Post_View * v, int timeStep, char *expression) +{ + evaluateList(v, v->SP, v->NbSP, 1, timeStep, expression); + evaluateList(v, v->SL, v->NbSL, 2, timeStep, expression); + evaluateList(v, v->ST, v->NbST, 3, timeStep, expression); + evaluateList(v, v->SQ, v->NbSQ, 4, timeStep, expression); + evaluateList(v, v->SS, v->NbSS, 4, timeStep, expression); + evaluateList(v, v->SH, v->NbSH, 8, timeStep, expression); + evaluateList(v, v->SI, v->NbSI, 6, timeStep, expression); + evaluateList(v, v->SY, v->NbSY, 5, timeStep, expression); +} + +Post_View *GMSH_EvaluatePlugin::execute(Post_View * v) +{ + Post_View *vv; + + int timeStep = (int)EvaluateOptions_Number[0].def; + int iView = (int)EvaluateOptions_Number[1].def; + char *expr = EvaluateOptions_String[0].def; + + if(v && iView < 0) + vv = v; + else { + if(!v && iView < 0) + iView = 0; + if(!(vv = (Post_View *) List_Pointer_Test(CTX.post.list, iView))) { + Msg(WARNING, "View[%d] does not exist", iView); + return 0; + } + } + + evaluate(vv, timeStep, expr); + return vv; +} + diff --git a/Plugin/Evaluate.h b/Plugin/Evaluate.h new file mode 100644 index 0000000000000000000000000000000000000000..73564af9477962cd49f8b5c5ba5afd387e517571 --- /dev/null +++ b/Plugin/Evaluate.h @@ -0,0 +1,44 @@ +#ifndef _EVALUATE_H_ +#define _EVALUATE_H + +// Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems to <gmsh@geuz.org>. + +#include "Plugin.h" + +extern "C" +{ + GMSH_Plugin *GMSH_RegisterEvaluatePlugin(); +} + +class GMSH_EvaluatePlugin : public GMSH_Post_Plugin +{ +public: + GMSH_EvaluatePlugin(); + void getName(char *name) const; + void getInfos(char *author, char *copyright, char *helpText) const; + void catchErrorMessage(char *errorMessage) const; + int getNbOptions() const; + StringXNumber* getOption(int iopt); + int getNbOptionsStr() const; + StringXString* getOptionStr(int iopt); + Post_View *execute(Post_View *); +}; + +#endif