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