Panzer Version of the Day
Loading...
Searching...
No Matches
Panzer_ExprEval.cpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Panzer: A partial differential equation assembly
4// engine for strongly coupled complex multiphysics systems
5//
6// Copyright 2011 NTESS and the Panzer contributors.
7// SPDX-License-Identifier: BSD-3-Clause
8// *****************************************************************************
9// @HEADER
10
12
13#include <cstdlib>
14
15#include <Teuchos_MathExpr.hpp>
16
17namespace panzer
18{
19namespace Expr
20{
21
23 : Teuchos::Reader(Teuchos::MathExpr::ask_reader_tables()) {
24}
25
26void EvalBase::set(std::string const& name, Function const& value) {
27 symbol_map[name] = value;
28}
29
30void EvalBase::at_shift(Teuchos::any& result_any, int token, std::string& text) {
31 using std::swap;
32 switch (token) {
33 case Teuchos::MathExpr::TOK_NAME: {
34 std::string& result = Teuchos::make_any_ref<std::string>(result_any);
35 swap(result, text);
36 return;
37 }
38 case Teuchos::MathExpr::TOK_CONST: {
39 this->make_constant(result_any, std::atof(text.c_str()));
40 return;
41 }
42 }
43}
44
45void EvalBase::at_reduce(Teuchos::any& result, int prod, std::vector<Teuchos::any>& rhs) {
46 using std::swap;
47 switch (prod) {
48 case Teuchos::MathExpr::PROD_PROGRAM: {
49 swap(result, rhs.at(1));
50 break;
51 }
52 case Teuchos::MathExpr::PROD_NO_STATEMENTS:
53 case Teuchos::MathExpr::PROD_NO_EXPR:
54 case Teuchos::MathExpr::PROD_NEXT_STATEMENT: {
55 break;
56 }
57 case Teuchos::MathExpr::PROD_ASSIGN: {
58 std::string const& name = Teuchos::any_ref_cast<std::string>(rhs.at(0));
59 swap(symbol_map[name], rhs.at(4));
60 break;
61 }
62 case Teuchos::MathExpr::PROD_YES_EXPR:
63 case Teuchos::MathExpr::PROD_EXPR:
64 case Teuchos::MathExpr::PROD_TERNARY_DECAY:
65 case Teuchos::MathExpr::PROD_OR_DECAY:
66 case Teuchos::MathExpr::PROD_AND_DECAY:
67 case Teuchos::MathExpr::PROD_ADD_SUB_DECAY:
68 case Teuchos::MathExpr::PROD_MUL_DIV_DECAY:
69 case Teuchos::MathExpr::PROD_POW_DECAY:
70 case Teuchos::MathExpr::PROD_NEG_DECAY:
71 case Teuchos::MathExpr::PROD_SOME_ARGS:
72 swap(result, rhs.at(0));
73 break;
74 case Teuchos::MathExpr::PROD_TERNARY:
75 this->ternary_op(result, rhs.at(0), rhs.at(3), rhs.at(6));
76 break;
77 case Teuchos::MathExpr::PROD_OR:
78 this->binary_op(BinaryOpCode::OR, result, rhs.at(0), rhs.at(3));
79 break;
80 case Teuchos::MathExpr::PROD_AND:
81 this->binary_op(BinaryOpCode::AND, result, rhs.at(0), rhs.at(3));
82 break;
83 case Teuchos::MathExpr::PROD_GT:
84 this->binary_op(BinaryOpCode::GT, result, rhs.at(0), rhs.at(3));
85 break;
86 case Teuchos::MathExpr::PROD_LT:
87 this->binary_op(BinaryOpCode::LT, result, rhs.at(0), rhs.at(3));
88 break;
89 case Teuchos::MathExpr::PROD_GEQ:
90 this->binary_op(BinaryOpCode::GEQ, result, rhs.at(0), rhs.at(3));
91 break;
92 case Teuchos::MathExpr::PROD_LEQ:
93 this->binary_op(BinaryOpCode::LEQ, result, rhs.at(0), rhs.at(3));
94 break;
95 case Teuchos::MathExpr::PROD_EQ:
96 this->binary_op(BinaryOpCode::EQ, result, rhs.at(0), rhs.at(3));
97 break;
98 case Teuchos::MathExpr::PROD_BOOL_PARENS:
99 swap(result, rhs.at(2));
100 break;
101 case Teuchos::MathExpr::PROD_ADD:
102 this->binary_op(BinaryOpCode::ADD, result, rhs.at(0), rhs.at(3));
103 break;
104 case Teuchos::MathExpr::PROD_SUB:
105 this->binary_op(BinaryOpCode::SUB, result, rhs.at(0), rhs.at(3));
106 break;
107 case Teuchos::MathExpr::PROD_MUL:
108 this->binary_op(BinaryOpCode::MUL, result, rhs.at(0), rhs.at(3));
109 break;
110 case Teuchos::MathExpr::PROD_DIV:
111 this->binary_op(BinaryOpCode::DIV, result, rhs.at(0), rhs.at(3));
112 break;
113 case Teuchos::MathExpr::PROD_POW:
114 this->binary_op(BinaryOpCode::POW, result, rhs.at(0), rhs.at(3));
115 break;
116 case Teuchos::MathExpr::PROD_CALL: {
117 std::string const& name = Teuchos::any_ref_cast<std::string>(rhs.at(0));
118 auto it = symbol_map.find(name);
119 TEUCHOS_TEST_FOR_EXCEPTION(it == symbol_map.end(), Teuchos::ParserFail,
120 "symbol \"" << name << "\" being called doesn't exist!");
121 Function& func = Teuchos::any_ref_cast<Function>(it->second);
122 std::vector<Teuchos::any>& args = Teuchos::any_ref_cast<std::vector<Teuchos::any>>(rhs.at(4));
123 func(name, result, args);
124 break;
125 }
126 case Teuchos::MathExpr::PROD_NO_ARGS: {
127 result = std::vector<Teuchos::any>{};
128 break;
129 }
130 case Teuchos::MathExpr::PROD_FIRST_ARG: {
131 std::vector<Teuchos::any>& args = Teuchos::make_any_ref<std::vector<Teuchos::any>>(result);
132 args.push_back(Teuchos::any{});
133 swap(args.back(), rhs.at(0));
134 break;
135 }
136 case Teuchos::MathExpr::PROD_NEXT_ARG: {
137 swap(result, rhs.at(0));
138 std::vector<Teuchos::any>& args = Teuchos::any_ref_cast<std::vector<Teuchos::any>>(result);
139 args.push_back(Teuchos::any{});
140 swap(args.back(), rhs.at(3));
141 break;
142 }
143 case Teuchos::MathExpr::PROD_NEG:
144 this->neg_op(result, rhs.at(2));
145 break;
146 case Teuchos::MathExpr::PROD_VAL_PARENS:
147 swap(result, rhs.at(2));
148 break;
149 case Teuchos::MathExpr::PROD_CONST:
150 swap(result, rhs.at(0));
151 break;
152 case Teuchos::MathExpr::PROD_VAR:
153 std::string const& name = Teuchos::any_ref_cast<std::string>(rhs.at(0));
154 auto it = symbol_map.find(name);
155 TEUCHOS_TEST_FOR_EXCEPTION(it == symbol_map.end(), Teuchos::ParserFail,
156 "symbol " << name << " being referenced doesn't exist!");
157 result = it->second;
158 break;
159 }
160}
161
162void EvalBase::ternary_op(Teuchos::any& result, Teuchos::any& cond, Teuchos::any& left, Teuchos::any& right) {
163 bool cond_is_many;
164 bool cond_is_bool;
165 this->inspect_arg(cond, cond_is_many, cond_is_bool);
166 TEUCHOS_TEST_FOR_EXCEPTION(!cond_is_bool, Teuchos::ParserFail,
167 "Ternary condition is not of boolean type!");
168 bool is_many[2];
169 bool is_bool[2];
170 this->inspect_arg(left, is_many[0], is_bool[0]);
171 this->inspect_arg(right, is_many[1], is_bool[1]);
172 TEUCHOS_TEST_FOR_EXCEPTION(is_bool[0], Teuchos::ParserFail,
173 "Boolean values in ternary operator not yet supported");
174 if (!cond_is_many) {
175 auto cond_value = Teuchos::any_cast<Kokkos::View<bool const>>(cond);
176 auto host_cond_value = Kokkos::create_mirror_view(cond_value);
177 Kokkos::deep_copy(host_cond_value, cond_value);
178 if (host_cond_value()) {
179 swap(result, left);
180 } else {
181 swap(result, right);
182 }
183 } else {
184 if (!is_many[0] && !is_many[1]) {
185 this->single_single_ternary_op(result, cond, left, right);
186 } else if (!is_many[0] && is_many[1]) {
187 this->single_many_ternary_op(result, cond, left, right);
188 } else if (is_many[0] && !is_many[1]) {
189 this->many_single_ternary_op(result, cond, left, right);
190 } else if (is_many[0] && is_many[1]) {
191 this->many_many_ternary_op(result, cond, left, right);
192 }
193 }
194}
195
196static const char* get_op_syntax(BinaryOpCode code) {
197 switch (code) {
198 case BinaryOpCode::OR: return "||";
199 case BinaryOpCode::AND: return "&&";
200 case BinaryOpCode::GT: return ">";
201 case BinaryOpCode::LT: return "<";
202 case BinaryOpCode::GEQ: return ">=";
203 case BinaryOpCode::LEQ: return "<=";
204 case BinaryOpCode::EQ: return "==";
205 case BinaryOpCode::ADD: return "+";
206 case BinaryOpCode::SUB: return "-";
207 case BinaryOpCode::MUL: return "*";
208 case BinaryOpCode::DIV: return "/";
209 case BinaryOpCode::POW: return "^";
210 }
211 return "";
212}
213
214void EvalBase::binary_op(BinaryOpCode code, Teuchos::any& result, Teuchos::any& left, Teuchos::any& right) {
215 bool is_many[2];
216 bool is_bool[2];
217 this->inspect_arg(left, is_many[0], is_bool[0]);
218 this->inspect_arg(right, is_many[1], is_bool[1]);
219 bool expect_booleans = (code == BinaryOpCode::AND || code == BinaryOpCode::OR);
220 TEUCHOS_TEST_FOR_EXCEPTION(is_bool[0] != expect_booleans, Teuchos::ParserFail,
221 "Left argument to '" << get_op_syntax(code) << "' is " << (is_bool[0] ? "" : "not") << " boolean!");
222 TEUCHOS_TEST_FOR_EXCEPTION(is_bool[1] != expect_booleans, Teuchos::ParserFail,
223 "Right argument to '" << get_op_syntax(code) << "' is " << (is_bool[0] ? "" : "not") << " boolean!");
224 if (!is_many[0] && !is_many[1]) {
225 this->single_single_binary_op(code, result, left, right);
226 } else if (!is_many[0] && is_many[1]) {
227 this->single_many_binary_op(code, result, left, right);
228 } else if (is_many[0] && !is_many[1]) {
229 this->many_single_binary_op(code, result, left, right);
230 } else if (is_many[0] && is_many[1]) {
231 this->many_many_binary_op(code, result, left, right);
232 }
233}
234
235void EvalBase::neg_op(Teuchos::any& result, Teuchos::any& right) {
236 bool is_many;
237 bool is_bool;
238 this->inspect_arg(right, is_many, is_bool);
239 TEUCHOS_TEST_FOR_EXCEPTION(is_bool, Teuchos::ParserFail,
240 "Can't negate a boolean");
241 if (is_many) {
242 this->many_neg_op(result, right);
243 } else {
244 this->single_neg_op(result, right);
245 }
246}
247
248}} // end namespace panzer::Expr
PHX::MDField< ScalarT, panzer::Cell, panzer::IP > result
A field that will be used to build up the result of the integral we're performing.
virtual void single_many_binary_op(BinaryOpCode code, Teuchos::any &result, Teuchos::any &left, Teuchos::any &right)=0
virtual void inspect_arg(Teuchos::any const &arg, bool &is_many, bool &is_bool)=0
void neg_op(Teuchos::any &result, Teuchos::any &right)
Executes the only native unary operator in the math language, numeric negation via a minus sign.
void at_shift(Teuchos::any &result, int token, std::string &text) override
Called at every parsed token in the math language.
void at_reduce(Teuchos::any &result, int prod, std::vector< Teuchos::any > &rhs) override
Called at every reduced production in the math language.
virtual void single_single_ternary_op(Teuchos::any &result, Teuchos::any &cond, Teuchos::any &left, Teuchos::any &right)=0
virtual void single_neg_op(Teuchos::any &result, Teuchos::any &right)=0
virtual void single_many_ternary_op(Teuchos::any &result, Teuchos::any &cond, Teuchos::any &left, Teuchos::any &right)=0
virtual void single_single_binary_op(BinaryOpCode code, Teuchos::any &result, Teuchos::any &left, Teuchos::any &right)=0
virtual void many_many_ternary_op(Teuchos::any &result, Teuchos::any &cond, Teuchos::any &left, Teuchos::any &right)=0
virtual void make_constant(Teuchos::any &result, double const &value)=0
void binary_op(BinaryOpCode code, Teuchos::any &result, Teuchos::any &left, Teuchos::any &right)
Executes a binary operator.
virtual void many_single_ternary_op(Teuchos::any &result, Teuchos::any &cond, Teuchos::any &left, Teuchos::any &right)=0
virtual void many_many_binary_op(BinaryOpCode code, Teuchos::any &result, Teuchos::any &left, Teuchos::any &right)=0
std::function< void(std::string const &name, Teuchos::any &, std::vector< Teuchos::any > &rhs)> Function
The type of user-defined functions which are callable in the math language.
std::map< std::string, Teuchos::any > symbol_map
Stores all current symbols including variables and functions.
void ternary_op(Teuchos::any &result, Teuchos::any &cond, Teuchos::any &left, Teuchos::any &right)
Executes the ternary operator, e.g. (a > b) ? a : b.
virtual void many_single_binary_op(BinaryOpCode code, Teuchos::any &result, Teuchos::any &left, Teuchos::any &right)=0
virtual void many_neg_op(Teuchos::any &result, Teuchos::any &right)=0
void set(std::string const &name, Function const &value)
Registers an EvalBase::Function, binding it to a name and making it callable.
BinaryOpCode
Denotes the native binary operators in the Teuchos::MathExpr language.
static const char * get_op_syntax(BinaryOpCode code)