www.mooseframework.org
ExpressionBuilder.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #include "ExpressionBuilder.h"
11 
14 {
15  return {larg, rarg};
16 }
17 
20 {
21  ExpressionBuilder::EBTermList list = {larg};
22  list.insert(list.end(), rargs.begin(), rargs.end());
23  return list;
24 }
25 
28 {
29  ExpressionBuilder::EBTermList list = largs;
30  list.push_back(rarg);
31  return list;
32 }
33 
34 std::ostream &
35 operator<<(std::ostream & os, const ExpressionBuilder::EBTerm & term)
36 {
37  if (term._root != NULL)
38  return os << *term._root;
39  else
40  return os << "[NULL]";
41 }
42 
43 std::string
45 {
46  return _symbol;
47 }
48 
49 std::string
51 {
52  std::ostringstream s;
53  s << '[' << _id << ']';
54  return s.str();
55 }
56 
57 std::string
59 {
60  const char * name[] = {"sin", "cos", "tan", "abs", "log", "log2", "log10", "exp", "sinh", "cosh"};
61  std::ostringstream s;
62  s << name[_type] << '(' << *_subnode << ')';
63  return s.str();
64 }
65 
66 std::string
68 {
69  const char * name[] = {"-", "!"};
70  std::ostringstream s;
71 
72  s << name[_type];
73 
74  if (_subnode->precedence() > precedence())
75  s << '(' << *_subnode << ')';
76  else
77  s << *_subnode;
78 
79  return s.str();
80 }
81 
82 std::string
84 {
85  const char * name[] = {"min", "max", "atan2", "hypot", "plog"};
86  std::ostringstream s;
87  s << name[_type] << '(' << *_left << ',' << *_right << ')';
88  return s.str();
89 }
90 
91 std::string
93 {
94  const char * name[] = {"+", "-", "*", "/", "%", "^", "<", ">", "<=", ">=", "=", "!="};
95  std::ostringstream s;
96 
97  if (_left->precedence() > precedence())
98  s << '(' << *_left << ')';
99  else
100  s << *_left;
101 
102  s << name[_type];
103 
104  // these operators are left associative at equal precedence
105  // (this matters for -,/,&,^ but not for + and *)
106  if (_right->precedence() > precedence() ||
107  (_right->precedence() == precedence() &&
108  (_type == SUB || _type == DIV || _type == MOD || _type == POW)))
109  s << '(' << *_right << ')';
110  else
111  s << *_right;
112 
113  return s.str();
114 }
115 
116 int
118 {
119  switch (_type)
120  {
121  case ADD:
122  case SUB:
123  return 6;
124  case MUL:
125  case DIV:
126  case MOD:
127  return 5;
128  case POW:
129  return 2;
130  case LESS:
131  case GREATER:
132  case LESSEQ:
133  case GREATEREQ:
134  return 8;
135  case EQ:
136  case NOTEQ:
137  return 9;
138  }
139 
140  mooseError("Unknown type.");
141 }
142 
143 std::string
145 {
146  const char * name[] = {"if"};
147  std::ostringstream s;
148  s << name[_type] << '(' << *_left << ',' << *_middle << ',' << *_right << ')';
149  return s.str();
150 }
151 
154 {
155  this->_eval_arguments = {arg};
156  return *this;
157 }
158 
161 {
162  this->_eval_arguments = EBTermList(args);
163  return *this;
164 }
165 
168 {
169  this->_arguments = this->_eval_arguments;
170  this->_term = term;
171  return *this;
172 }
173 
176 {
177  this->_arguments = this->_eval_arguments;
178  this->_term = EBTerm(func);
179  return *this;
180 }
181 
182 ExpressionBuilder::EBFunction::operator ExpressionBuilder::EBTerm() const
183 {
184  unsigned int narg = _arguments.size();
185  if (narg != _eval_arguments.size())
186  mooseError("EBFunction is used wth a different number of arguments than it was defined with.");
187 
188  // prepare a copy of the function term to perform the substitution on
189  EBTerm result(_term);
190 
191  // prepare a rule list for the substitutions
193  for (unsigned i = 0; i < narg; ++i)
194  rules.push_back(new EBTermSubstitution(_arguments[i], _eval_arguments[i]));
195 
196  // perform substitution
197  result.substitute(rules);
198 
199  // discard rule set
200  for (unsigned i = 0; i < narg; ++i)
201  delete rules[i];
202 
203  return result;
204 }
205 
206 ExpressionBuilder::EBFunction::operator std::string() const
207 {
208  EBTerm eval;
209  eval = *this; // typecast EBFunction -> EBTerm performs a parameter substitution
210  std::ostringstream s;
211  s << eval;
212  return s.str();
213 }
214 
215 std::string
217 {
218  unsigned int narg = _arguments.size();
219  if (narg < 1)
220  return "";
221 
222  std::ostringstream s;
223  s << _arguments[0];
224  for (unsigned int i = 1; i < narg; ++i)
225  s << ',' << _arguments[i];
226 
227  return s.str();
228 }
229 
230 unsigned int
232 {
233  return _term.substitute(rule);
234 }
235 
236 unsigned int
238 {
239  return _term.substitute(rules);
240 }
241 
242 #define UNARY_FUNC_IMPLEMENT(op, OP) \
243  ExpressionBuilder::EBTerm op(const ExpressionBuilder::EBTerm & term) \
244  { \
245  mooseAssert(term._root != NULL, "Empty term provided as argument of function " #op "()"); \
246  return ExpressionBuilder::EBTerm(new ExpressionBuilder::EBUnaryFuncTermNode( \
247  term.cloneRoot(), ExpressionBuilder::EBUnaryFuncTermNode::OP)); \
248  }
250 UNARY_FUNC_IMPLEMENT(cos, COS)
251 UNARY_FUNC_IMPLEMENT(tan, TAN)
252 UNARY_FUNC_IMPLEMENT(abs, ABS)
254 UNARY_FUNC_IMPLEMENT(log2, LOG2)
255 UNARY_FUNC_IMPLEMENT(log10, LOG10)
257 UNARY_FUNC_IMPLEMENT(sinh, SINH)
258 UNARY_FUNC_IMPLEMENT(cosh, COSH)
259 
260 #define BINARY_FUNC_IMPLEMENT(op, OP) \
261  ExpressionBuilder::EBTerm op(const ExpressionBuilder::EBTerm & left, \
262  const ExpressionBuilder::EBTerm & right) \
263  { \
264  mooseAssert(left._root != NULL, \
265  "Empty term provided as first argument of function " #op "()"); \
266  mooseAssert(right._root != NULL, \
267  "Empty term provided as second argument of function " #op "()"); \
268  return ExpressionBuilder::EBTerm(new ExpressionBuilder::EBBinaryFuncTermNode( \
269  left.cloneRoot(), right.cloneRoot(), ExpressionBuilder::EBBinaryFuncTermNode::OP)); \
270  }
272 BINARY_FUNC_IMPLEMENT(max, MAX)
273 BINARY_FUNC_IMPLEMENT(atan2, ATAN2)
274 BINARY_FUNC_IMPLEMENT(hypot, HYPOT)
275 BINARY_FUNC_IMPLEMENT(plog, PLOG)
276 
277 // this is a function in ExpressionBuilder (pow) but an operator in FParser (^)
279 pow(const ExpressionBuilder::EBTerm & left, const ExpressionBuilder::EBTerm & right)
280 {
281  mooseAssert(left._root != NULL, "Empty term for base of pow()");
282  mooseAssert(right._root != NULL, "Empty term for exponent of pow()");
285 }
286 
287 #define TERNARY_FUNC_IMPLEMENT(op, OP) \
288  ExpressionBuilder::EBTerm op(const ExpressionBuilder::EBTerm & left, \
289  const ExpressionBuilder::EBTerm & middle, \
290  const ExpressionBuilder::EBTerm & right) \
291  { \
292  mooseAssert(left._root != NULL, \
293  "Empty term provided as first argument of the ternary function " #op "()"); \
294  mooseAssert(middle._root != NULL, \
295  "Empty term provided as second argument of the ternary function " #op "()"); \
296  mooseAssert(right._root != NULL, \
297  "Empty term provided as third argument of the ternary function " #op "()"); \
298  return ExpressionBuilder::EBTerm(new ExpressionBuilder::EBTernaryFuncTermNode( \
299  left.cloneRoot(), \
300  middle.cloneRoot(), \
301  right.cloneRoot(), \
302  ExpressionBuilder::EBTernaryFuncTermNode::OP)); \
303  }
304 TERNARY_FUNC_IMPLEMENT(conditional, CONDITIONAL)
305 
306 unsigned int
308 {
309  unsigned int nrule = rules.size();
310 
311  for (unsigned int i = 0; i < nrule; ++i)
312  {
313  EBTermNode * replace = rules[i]->apply(_subnode);
314  if (replace != NULL)
315  {
316  delete _subnode;
317  _subnode = replace;
318  return 1;
319  }
320  }
321 
322  return _subnode->substitute(rules);
323 }
324 
325 unsigned int
327 {
328  unsigned int nrule = rules.size();
329  unsigned int success = 0;
330 
331  for (unsigned int i = 0; i < nrule; ++i)
332  {
333  EBTermNode * replace = rules[i]->apply(_left);
334  if (replace != NULL)
335  {
336  delete _left;
337  _left = replace;
338  success = 1;
339  break;
340  }
341  }
342 
343  if (success == 0)
344  success += _left->substitute(rules);
345 
346  for (unsigned int i = 0; i < nrule; ++i)
347  {
348  EBTermNode * replace = rules[i]->apply(_right);
349  if (replace != NULL)
350  {
351  delete _right;
352  _right = replace;
353  return success + 1;
354  }
355  }
356 
357  return success + _right->substitute(rules);
358 }
359 
360 unsigned int
362 {
363  unsigned int nrule = rules.size();
364  bool left_success = false, middle_success = false, right_success = false;
365  EBTermNode * replace;
366 
367  for (unsigned int i = 0; i < nrule; ++i)
368  {
369  replace = rules[i]->apply(_left);
370  if (replace)
371  {
372  delete _left;
373  _left = replace;
374  left_success = true;
375  break;
376  }
377  }
378 
379  for (unsigned int i = 0; i < nrule; ++i)
380  {
381  replace = rules[i]->apply(_middle);
382  if (replace)
383  {
384  delete _middle;
385  _middle = replace;
386  middle_success = true;
387  break;
388  }
389  }
390 
391  for (unsigned int i = 0; i < nrule; ++i)
392  {
393  replace = rules[i]->apply(_right);
394  if (replace)
395  {
396  delete _right;
397  _right = replace;
398  right_success = true;
399  break;
400  }
401  }
402 
403  if (!left_success)
404  left_success = _left->substitute(rules);
405  if (!middle_success)
406  middle_success = _middle->substitute(rules);
407  if (!right_success)
408  right_success = _right->substitute(rules);
409 
410  return left_success + middle_success + right_success;
411 }
412 
413 unsigned int
415 {
416  EBSubstitutionRuleList rules(1);
417  rules[0] = &rule;
418  return substitute(rules);
419 }
420 
421 unsigned int
423 {
424  unsigned int nrule = rules.size();
425 
426  if (_root == NULL)
427  return 0;
428 
429  for (unsigned int i = 0; i < nrule; ++i)
430  {
431  EBTermNode * replace = rules[i]->apply(_root);
432  if (replace != NULL)
433  {
434  delete _root;
435  _root = replace;
436  return 1;
437  }
438  }
439 
440  return _root->substitute(rules);
441 }
442 
444  const EBTerm & replace)
445 {
446  // the expression we want to substitute (has to be a symbol node)
447  const EBSymbolNode * find_root = dynamic_cast<const EBSymbolNode *>(find.getRoot());
448  if (find_root == NULL)
449  mooseError("Function arguments must be pure symbols.");
450  _find = find_root->stringify();
451 
452  // the term we want to substitute with
453  if (replace.getRoot() != NULL)
454  _replace = replace.cloneRoot();
455  else
456  mooseError("Trying to substitute in an empty term for ", _find);
457 }
458 
461 {
462  if (node.stringify() == _find)
463  return _replace->clone();
464  else
465  return NULL;
466 }
467 
470 {
471  if (node._type == EBUnaryFuncTermNode::LOG)
472  return new EBBinaryFuncTermNode(
473  node.getSubnode()->clone(), _epsilon->clone(), EBBinaryFuncTermNode::PLOG);
474  else
475  return NULL;
476 }
ExpressionBuilder::EBFunction
User facing host object for a function. This combines a term with an argument list.
Definition: ExpressionBuilder.h:520
ExpressionBuilder::EBFunction::operator()
EBFunction & operator()(const EBTerm &arg)
Definition: ExpressionBuilder.C:153
ExpressionBuilder::EBBinaryOpTermNode::precedence
virtual int precedence() const
Definition: ExpressionBuilder.C:117
ExpressionBuilder::EBLogPlogSubstitution::substitute
virtual EBTermNode * substitute(const EBUnaryFuncTermNode &) const
Definition: ExpressionBuilder.C:469
ExpressionBuilder::EBBinaryOpTermNode::stringify
virtual std::string stringify() const
Definition: ExpressionBuilder.C:92
ExpressionBuilder::EBBinaryOpTermNode
Node representing a binary operator.
Definition: ExpressionBuilder.h:203
pow
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
Definition: ExpressionBuilder.h:673
ExpressionBuilder::EBTerm::getRoot
const EBTermNode * getRoot() const
Definition: ExpressionBuilder.h:403
ExpressionBuilder::EBTermNode
Base class for nodes in the expression tree.
Definition: ExpressionBuilder.h:62
ExpressionBuilder.h
ROMInputTransform::EXP
ExpressionBuilder::EBUnaryOpTermNode::stringify
virtual std::string stringify() const
Definition: ExpressionBuilder.C:67
TERNARY_FUNC_IMPLEMENT
TERNARY_FUNC_IMPLEMENT(conditional, CONDITIONAL)
Definition: ExpressionBuilder.C:304
ExpressionBuilder::EBUnaryFuncTermNode::LOG
Definition: ExpressionBuilder.h:144
ExpressionBuilder::EBFunction::operator=
EBFunction & operator=(const EBTerm &)
Definition: ExpressionBuilder.C:167
ExpressionBuilder::EBTernaryTermNode::substitute
virtual unsigned int substitute(const EBSubstitutionRuleList &rule)
Definition: ExpressionBuilder.C:361
ExpressionBuilder::EBTermList
std::vector< EBTerm > EBTermList
Definition: ExpressionBuilder.h:56
operator<<
std::ostream & operator<<(std::ostream &os, const ExpressionBuilder::EBTerm &term)
Definition: ExpressionBuilder.C:35
ExpressionBuilder::EBFunction::substitute
unsigned int substitute(const EBSubstitutionRule &rule)
Definition: ExpressionBuilder.C:231
ExpressionBuilder::EBTernaryFuncTermNode::stringify
virtual std::string stringify() const
Definition: ExpressionBuilder.C:144
ExpressionBuilder::EBUnaryFuncTermNode::_type
enum ExpressionBuilder::EBUnaryFuncTermNode::NodeType _type
ExpressionBuilder::EBTerm::_root
EBTermNode * _root
Definition: ExpressionBuilder.h:407
ExpressionBuilder::EBSymbolNode::stringify
virtual std::string stringify() const
Definition: ExpressionBuilder.C:44
ExpressionBuilder::EBTerm::substitute
unsigned int substitute(const EBSubstitutionRule &rule)
Definition: ExpressionBuilder.C:414
ExpressionBuilder::EBUnaryFuncTermNode::stringify
virtual std::string stringify() const
Definition: ExpressionBuilder.C:58
ExpressionBuilder::EBTermNode::clone
virtual EBTermNode * clone() const =0
ExpressionBuilder::EBTerm::cloneRoot
EBTermNode * cloneRoot() const
Definition: ExpressionBuilder.h:404
ExpressionBuilder::EBUnaryTermNode::substitute
virtual unsigned int substitute(const EBSubstitutionRuleList &rule)
ExpressionBuilder::EBBinaryFuncTermNode::PLOG
Definition: ExpressionBuilder.h:246
ExpressionBuilder::EBSymbolNode::_symbol
std::string _symbol
Definition: ExpressionBuilder.h:94
ExpressionBuilder::EBSymbolNode
Template class for leaf nodes holding symbols (i.e. variables) in the expression tree.
Definition: ExpressionBuilder.h:92
ROMInputTransform::LOG
ExpressionBuilder::EBSubstitutionRuleList
std::vector< const EBSubstitutionRule * > EBSubstitutionRuleList
Definition: ExpressionBuilder.h:59
name
const std::string name
Definition: Setup.h:21
ExpressionBuilder::EBFunction::args
std::string args()
get the list of arguments and check if they are all symbols
Definition: ExpressionBuilder.C:216
ExpressionBuilder::EBUnaryFuncTermNode
Node representing a function with two arguments.
Definition: ExpressionBuilder.h:135
ExpressionBuilder::EBTermNode::substitute
virtual unsigned int substitute(const EBSubstitutionRuleList &)
Definition: ExpressionBuilder.h:69
ExpressionBuilder::EBTermSubstitution::substitute
virtual EBTermNode * substitute(const EBSymbolNode &) const
Definition: ExpressionBuilder.C:460
operator,
ExpressionBuilder::EBTermList operator,(const ExpressionBuilder::EBTerm &larg, const ExpressionBuilder::EBTerm &rarg)
Definition: ExpressionBuilder.C:13
UNARY_FUNC_IMPLEMENT
UNARY_FUNC_IMPLEMENT(sin, SIN)
Definition: ExpressionBuilder.C:249
ExpressionBuilder::EBTermSubstitution
Generic Substitution rule to replace all occurences of a given symbol node term with a user defined t...
Definition: ExpressionBuilder.h:323
ExpressionBuilder::EBTempIDNode::stringify
virtual std::string stringify() const
Definition: ExpressionBuilder.C:50
ExpressionBuilder::EBSubstitutionRule
Substitution rule functor base class to perform flexible term substitutions.
Definition: ExpressionBuilder.h:297
ExpressionBuilder::EBTermSubstitution::EBTermSubstitution
EBTermSubstitution(const EBTerm &find, const EBTerm &replace)
Definition: ExpressionBuilder.C:443
ExpressionBuilder::EBBinaryFuncTermNode::stringify
virtual std::string stringify() const
Definition: ExpressionBuilder.C:83
ExpressionBuilder::EBBinaryFuncTermNode
Node representing a function with two arguments.
Definition: ExpressionBuilder.h:237
ExpressionBuilder::EBUnaryTermNode::getSubnode
const EBTermNode * getSubnode() const
Definition: ExpressionBuilder.h:128
BINARY_FUNC_IMPLEMENT
BINARY_FUNC_IMPLEMENT(min, MIN)
Definition: ExpressionBuilder.C:271
ExpressionBuilder::EBBinaryOpTermNode::POW
Definition: ExpressionBuilder.h:213
ExpressionBuilder::EBBinaryTermNode::substitute
virtual unsigned int substitute(const EBSubstitutionRuleList &rule)
Definition: ExpressionBuilder.C:326
ExpressionBuilder::EBTerm
User facing host object for an expression tree.
Definition: ExpressionBuilder.h:357