Panzer Version of the Day
Loading...
Searching...
No Matches
Panzer_ExprEval.cpp
Go to the documentation of this file.
1// @HEADER
2// ***********************************************************************
3//
4// Panzer: A partial differential equation assembly
5// engine for strongly coupled complex multiphysics systems
6// Copyright (2011) Sandia Corporation
7//
8// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9// the U.S. Government retains certain rights in this software.
10//
11// Redistribution and use in source and binary forms, with or without
12// modification, are permitted provided that the following conditions are
13// met:
14//
15// 1. Redistributions of source code must retain the above copyright
16// notice, this list of conditions and the following disclaimer.
17//
18// 2. Redistributions in binary form must reproduce the above copyright
19// notice, this list of conditions and the following disclaimer in the
20// documentation and/or other materials provided with the distribution.
21//
22// 3. Neither the name of the Corporation nor the names of the
23// contributors may be used to endorse or promote products derived from
24// this software without specific prior written permission.
25//
26// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37//
38// Questions? Contact Roger P. Pawlowski (rppawlo@sandia.gov) and
39// Eric C. Cyr (eccyr@sandia.gov)
40// ***********************************************************************
41// @HEADER
42
44
45#include <cstdlib>
46
47#include <Teuchos_MathExpr.hpp>
48
49namespace panzer
50{
51namespace Expr
52{
53
55 : Teuchos::Reader(Teuchos::MathExpr::ask_reader_tables()) {
56}
57
58void EvalBase::set(std::string const& name, Function const& value) {
59 symbol_map[name] = value;
60}
61
62void EvalBase::at_shift(Teuchos::any& result_any, int token, std::string& text) {
63 using std::swap;
64 switch (token) {
65 case Teuchos::MathExpr::TOK_NAME: {
66 std::string& result = Teuchos::make_any_ref<std::string>(result_any);
67 swap(result, text);
68 return;
69 }
70 case Teuchos::MathExpr::TOK_CONST: {
71 this->make_constant(result_any, std::atof(text.c_str()));
72 return;
73 }
74 }
75}
76
77void EvalBase::at_reduce(Teuchos::any& result, int prod, std::vector<Teuchos::any>& rhs) {
78 using std::swap;
79 switch (prod) {
80 case Teuchos::MathExpr::PROD_PROGRAM: {
81 swap(result, rhs.at(1));
82 break;
83 }
84 case Teuchos::MathExpr::PROD_NO_STATEMENTS:
85 case Teuchos::MathExpr::PROD_NO_EXPR:
86 case Teuchos::MathExpr::PROD_NEXT_STATEMENT: {
87 break;
88 }
89 case Teuchos::MathExpr::PROD_ASSIGN: {
90 std::string const& name = Teuchos::any_ref_cast<std::string>(rhs.at(0));
91 swap(symbol_map[name], rhs.at(4));
92 break;
93 }
94 case Teuchos::MathExpr::PROD_YES_EXPR:
95 case Teuchos::MathExpr::PROD_EXPR:
96 case Teuchos::MathExpr::PROD_TERNARY_DECAY:
97 case Teuchos::MathExpr::PROD_OR_DECAY:
98 case Teuchos::MathExpr::PROD_AND_DECAY:
99 case Teuchos::MathExpr::PROD_ADD_SUB_DECAY:
100 case Teuchos::MathExpr::PROD_MUL_DIV_DECAY:
101 case Teuchos::MathExpr::PROD_POW_DECAY:
102 case Teuchos::MathExpr::PROD_NEG_DECAY:
103 case Teuchos::MathExpr::PROD_SOME_ARGS:
104 swap(result, rhs.at(0));
105 break;
106 case Teuchos::MathExpr::PROD_TERNARY:
107 this->ternary_op(result, rhs.at(0), rhs.at(3), rhs.at(6));
108 break;
109 case Teuchos::MathExpr::PROD_OR:
110 this->binary_op(BinaryOpCode::OR, result, rhs.at(0), rhs.at(3));
111 break;
112 case Teuchos::MathExpr::PROD_AND:
113 this->binary_op(BinaryOpCode::AND, result, rhs.at(0), rhs.at(3));
114 break;
115 case Teuchos::MathExpr::PROD_GT:
116 this->binary_op(BinaryOpCode::GT, result, rhs.at(0), rhs.at(3));
117 break;
118 case Teuchos::MathExpr::PROD_LT:
119 this->binary_op(BinaryOpCode::LT, result, rhs.at(0), rhs.at(3));
120 break;
121 case Teuchos::MathExpr::PROD_GEQ:
122 this->binary_op(BinaryOpCode::GEQ, result, rhs.at(0), rhs.at(3));
123 break;
124 case Teuchos::MathExpr::PROD_LEQ:
125 this->binary_op(BinaryOpCode::LEQ, result, rhs.at(0), rhs.at(3));
126 break;
127 case Teuchos::MathExpr::PROD_EQ:
128 this->binary_op(BinaryOpCode::EQ, result, rhs.at(0), rhs.at(3));
129 break;
130 case Teuchos::MathExpr::PROD_BOOL_PARENS:
131 swap(result, rhs.at(2));
132 break;
133 case Teuchos::MathExpr::PROD_ADD:
134 this->binary_op(BinaryOpCode::ADD, result, rhs.at(0), rhs.at(3));
135 break;
136 case Teuchos::MathExpr::PROD_SUB:
137 this->binary_op(BinaryOpCode::SUB, result, rhs.at(0), rhs.at(3));
138 break;
139 case Teuchos::MathExpr::PROD_MUL:
140 this->binary_op(BinaryOpCode::MUL, result, rhs.at(0), rhs.at(3));
141 break;
142 case Teuchos::MathExpr::PROD_DIV:
143 this->binary_op(BinaryOpCode::DIV, result, rhs.at(0), rhs.at(3));
144 break;
145 case Teuchos::MathExpr::PROD_POW:
146 this->binary_op(BinaryOpCode::POW, result, rhs.at(0), rhs.at(3));
147 break;
148 case Teuchos::MathExpr::PROD_CALL: {
149 std::string const& name = Teuchos::any_ref_cast<std::string>(rhs.at(0));
150 auto it = symbol_map.find(name);
151 TEUCHOS_TEST_FOR_EXCEPTION(it == symbol_map.end(), Teuchos::ParserFail,
152 "symbol \"" << name << "\" being called doesn't exist!");
153 Function& func = Teuchos::any_ref_cast<Function>(it->second);
154 std::vector<Teuchos::any>& args = Teuchos::any_ref_cast<std::vector<Teuchos::any>>(rhs.at(4));
155 func(name, result, args);
156 break;
157 }
158 case Teuchos::MathExpr::PROD_NO_ARGS: {
159 result = std::vector<Teuchos::any>{};
160 break;
161 }
162 case Teuchos::MathExpr::PROD_FIRST_ARG: {
163 std::vector<Teuchos::any>& args = Teuchos::make_any_ref<std::vector<Teuchos::any>>(result);
164 args.push_back(Teuchos::any{});
165 swap(args.back(), rhs.at(0));
166 break;
167 }
168 case Teuchos::MathExpr::PROD_NEXT_ARG: {
169 swap(result, rhs.at(0));
170 std::vector<Teuchos::any>& args = Teuchos::any_ref_cast<std::vector<Teuchos::any>>(result);
171 args.push_back(Teuchos::any{});
172 swap(args.back(), rhs.at(3));
173 break;
174 }
175 case Teuchos::MathExpr::PROD_NEG:
176 this->neg_op(result, rhs.at(2));
177 break;
178 case Teuchos::MathExpr::PROD_VAL_PARENS:
179 swap(result, rhs.at(2));
180 break;
181 case Teuchos::MathExpr::PROD_CONST:
182 swap(result, rhs.at(0));
183 break;
184 case Teuchos::MathExpr::PROD_VAR:
185 std::string const& name = Teuchos::any_ref_cast<std::string>(rhs.at(0));
186 auto it = symbol_map.find(name);
187 TEUCHOS_TEST_FOR_EXCEPTION(it == symbol_map.end(), Teuchos::ParserFail,
188 "symbol " << name << " being referenced doesn't exist!");
189 result = it->second;
190 break;
191 }
192}
193
194void EvalBase::ternary_op(Teuchos::any& result, Teuchos::any& cond, Teuchos::any& left, Teuchos::any& right) {
195 bool cond_is_many;
196 bool cond_is_bool;
197 this->inspect_arg(cond, cond_is_many, cond_is_bool);
198 TEUCHOS_TEST_FOR_EXCEPTION(!cond_is_bool, Teuchos::ParserFail,
199 "Ternary condition is not of boolean type!");
200 bool is_many[2];
201 bool is_bool[2];
202 this->inspect_arg(left, is_many[0], is_bool[0]);
203 this->inspect_arg(right, is_many[1], is_bool[1]);
204 TEUCHOS_TEST_FOR_EXCEPTION(is_bool[0], Teuchos::ParserFail,
205 "Boolean values in ternary operator not yet supported");
206 if (!cond_is_many) {
207 auto cond_value = Teuchos::any_cast<Kokkos::View<bool const>>(cond);
208 auto host_cond_value = Kokkos::create_mirror_view(cond_value);
209 Kokkos::deep_copy(host_cond_value, cond_value);
210 if (host_cond_value()) {
211 swap(result, left);
212 } else {
213 swap(result, right);
214 }
215 } else {
216 if (!is_many[0] && !is_many[1]) {
217 this->single_single_ternary_op(result, cond, left, right);
218 } else if (!is_many[0] && is_many[1]) {
219 this->single_many_ternary_op(result, cond, left, right);
220 } else if (is_many[0] && !is_many[1]) {
221 this->many_single_ternary_op(result, cond, left, right);
222 } else if (is_many[0] && is_many[1]) {
223 this->many_many_ternary_op(result, cond, left, right);
224 }
225 }
226}
227
228static const char* get_op_syntax(BinaryOpCode code) {
229 switch (code) {
230 case BinaryOpCode::OR: return "||";
231 case BinaryOpCode::AND: return "&&";
232 case BinaryOpCode::GT: return ">";
233 case BinaryOpCode::LT: return "<";
234 case BinaryOpCode::GEQ: return ">=";
235 case BinaryOpCode::LEQ: return "<=";
236 case BinaryOpCode::EQ: return "==";
237 case BinaryOpCode::ADD: return "+";
238 case BinaryOpCode::SUB: return "-";
239 case BinaryOpCode::MUL: return "*";
240 case BinaryOpCode::DIV: return "/";
241 case BinaryOpCode::POW: return "^";
242 }
243 return "";
244}
245
246void EvalBase::binary_op(BinaryOpCode code, Teuchos::any& result, Teuchos::any& left, Teuchos::any& right) {
247 bool is_many[2];
248 bool is_bool[2];
249 this->inspect_arg(left, is_many[0], is_bool[0]);
250 this->inspect_arg(right, is_many[1], is_bool[1]);
251 bool expect_booleans = (code == BinaryOpCode::AND || code == BinaryOpCode::OR);
252 TEUCHOS_TEST_FOR_EXCEPTION(is_bool[0] != expect_booleans, Teuchos::ParserFail,
253 "Left argument to '" << get_op_syntax(code) << "' is " << (is_bool[0] ? "" : "not") << " boolean!");
254 TEUCHOS_TEST_FOR_EXCEPTION(is_bool[1] != expect_booleans, Teuchos::ParserFail,
255 "Right argument to '" << get_op_syntax(code) << "' is " << (is_bool[0] ? "" : "not") << " boolean!");
256 if (!is_many[0] && !is_many[1]) {
257 this->single_single_binary_op(code, result, left, right);
258 } else if (!is_many[0] && is_many[1]) {
259 this->single_many_binary_op(code, result, left, right);
260 } else if (is_many[0] && !is_many[1]) {
261 this->many_single_binary_op(code, result, left, right);
262 } else if (is_many[0] && is_many[1]) {
263 this->many_many_binary_op(code, result, left, right);
264 }
265}
266
267void EvalBase::neg_op(Teuchos::any& result, Teuchos::any& right) {
268 bool is_many;
269 bool is_bool;
270 this->inspect_arg(right, is_many, is_bool);
271 TEUCHOS_TEST_FOR_EXCEPTION(is_bool, Teuchos::ParserFail,
272 "Can't negate a boolean");
273 if (is_many) {
274 this->many_neg_op(result, right);
275 } else {
276 this->single_neg_op(result, right);
277 }
278}
279
280}} // 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)