https://mooseframework.inl.gov
Loading...
Searching...
No Matches
KokkosFunctionParser.h
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#pragma once
11
12#include "KokkosTypes.h"
13#include "KokkosVariableValue.h"
16#include "KokkosFunction.h"
17
19
20#include "peglib.h"
21
22namespace Moose::Kokkos
23{
24
25class FunctionBase;
26
31{
32public:
38 PEGParser(const std::string & expression, const ConsoleStream * console = nullptr);
39
44 auto ast() const { return _ast; }
49 const std::string & expression() const { return _expression; }
50
51private:
55 peg::parser _parser;
59 std::shared_ptr<peg::Ast> _ast;
63 const std::string _expression;
64};
65
70{
71public:
77 RPNBuilder(const std::string & expression, const ConsoleStream * console = nullptr)
78 : _parser(expression, console)
79 {
80 }
81
85 enum class Opcode
86 {
87 NUM,
88 VAR,
89 NEG,
90 NOT,
91 // Binary operators
92 ADD,
93 SUB,
94 MUL,
95 DIV,
96 AND,
97 OR,
98 EQ,
99 NEQ,
100 LT,
101 LEQ,
102 GT,
103 GEQ,
104 // Functions
105 ABS,
106 ACOS,
107 ACOSH,
108 ASIN,
109 ASINH,
110 ATAN,
111 ATAN2,
112 ATANH,
113 CBRT,
114 CEIL,
115 COS,
116 COSH,
117 COT,
118 CSC,
119 EXP,
120 EXP2,
121 FLOOR,
122 HYPOT,
123 IF,
124 INT,
125 LOG,
126 LOG2,
127 LOG10,
128 MAX,
129 MIN,
130 POW,
131 SEC,
132 SIN,
133 SINH,
134 SQRT,
135 TAN,
136 TANH,
137 TRUNC
138 };
139
144 {
145 // Opcode
147 // Original string
148 std::string text;
149 // Constant of variable index
151 };
152
156 struct Variable
157 {
158 // Variable index
159 unsigned int idx;
160 // Pointer to a scalar value
161 const Real * scalar = nullptr;
162 // Pointer to a field variable
163 const VariableValue * field = nullptr;
164 // Pointer to a material property
165 const MaterialProperty<Real> * property = nullptr;
166 // Pointer to a function
167 const Function * function = nullptr;
168 // Whether the variable was associated
169 bool associated() const { return scalar || field || property || function; }
170 };
171
177 void build(const peg::Ast & ast);
178 void build() { build(*_parser.ast()); }
180
185 void printRPN(const ConsoleStream & console) const;
190 const std::vector<Instruction> & getRPN() const { return _rpn; }
191
201
207 unsigned int addNumber(Real number);
213 unsigned int addVariable(const std::string & name);
219 void associateScalar(const std::string & name, const Real * scalar);
225 void associateField(const std::string & name, const VariableValue * field);
231 void associateProperty(const std::string & name, const MaterialProperty<Real> * property);
237 void associateFunction(const std::string & name, const Function * function);
238
243 const std::vector<Real> & getNumbers() const { return _numbers; }
248 const std::unordered_map<std::string, Variable> & getVariables() const { return _variables; }
249
253 void finalize() { _finalized = true; }
258 bool finalized() const { return _finalized; }
259
260private:
264 static inline const std::map<std::string, Opcode> _unary_opcode_map = {{"-", Opcode::NEG},
265 {"!", Opcode::NOT}};
266
270 static inline const std::map<std::string, Opcode> _binary_opcode_map = {{"+", Opcode::ADD},
271 {"-", Opcode::SUB},
272 {"*", Opcode::MUL},
273 {"/", Opcode::DIV},
274 {"^", Opcode::POW},
275 {"&", Opcode::AND},
276 {"|", Opcode::OR},
277 {"=", Opcode::EQ},
278 {"!=", Opcode::NEQ},
279 {"<", Opcode::LT},
280 {"<=", Opcode::LEQ},
281 {">", Opcode::GT},
282 {">=", Opcode::GEQ}};
283
287 static inline const std::map<std::string, std::pair<Opcode, unsigned int>> _function_opcode_map =
288 {{"abs", {Opcode::ABS, 1}}, {"acos", {Opcode::ACOS, 1}}, {"acosh", {Opcode::ACOSH, 1}},
289 {"asin", {Opcode::ASIN, 1}}, {"asinh", {Opcode::ASINH, 1}}, {"atan", {Opcode::ATAN, 1}},
290 {"atan2", {Opcode::ATAN2, 2}}, {"atanh", {Opcode::ATANH, 1}}, {"cbrt", {Opcode::CBRT, 1}},
291 {"ceil", {Opcode::CEIL, 1}}, {"cos", {Opcode::COS, 1}}, {"cosh", {Opcode::COSH, 1}},
292 {"cot", {Opcode::COT, 1}}, {"csc", {Opcode::CSC, 1}}, {"exp", {Opcode::EXP, 1}},
293 {"exp2", {Opcode::EXP2, 1}}, {"floor", {Opcode::FLOOR, 1}}, {"hypot", {Opcode::HYPOT, 2}},
294 {"if", {Opcode::IF, 3}}, {"int", {Opcode::INT, 1}}, {"log", {Opcode::LOG, 1}},
295 {"log2", {Opcode::LOG2, 1}}, {"log10", {Opcode::LOG10, 1}}, {"max", {Opcode::MAX, 2}},
296 {"min", {Opcode::MIN, 2}}, {"pow", {Opcode::POW, 2}}, {"sec", {Opcode::SEC, 1}},
297 {"sin", {Opcode::SIN, 1}}, {"sinh", {Opcode::SINH, 1}}, {"sqrt", {Opcode::SQRT, 1}},
298 {"tan", {Opcode::TAN, 1}}, {"tanh", {Opcode::TANH, 1}}, {"trunc", {Opcode::TRUNC, 1}}};
299
307 std::vector<Instruction> _rpn;
311 std::vector<Real> _numbers;
315 std::unordered_map<std::string, Variable> _variables;
323 bool _finalized = false;
324
330 [[noreturn]] void builderError(const peg::Ast & ast, const std::string & message) const;
331
336};
337
342{
344
345public:
349 RPNEvaluator() = default;
353 RPNEvaluator(const RPNEvaluator & evaluator);
354
359 void init(const RPNBuilder & builder);
360
369 KOKKOS_FUNCTION Real eval(const Real t,
370 const Real3 p,
371 const unsigned int qp = 0,
372 Datum * datum = nullptr) const;
373
374private:
379 {
380 // Opcode
382 // Constant of variable index
384 };
388 enum class VariableType
389 {
390 SCALAR,
391 FIELD,
392 MATERIAL,
394 };
395
427 std::vector<const void *> _pointers;
428
432 unsigned int _num_scalars = 0;
436 unsigned int _num_fields = 0;
440 unsigned int _num_properties = 0;
444 unsigned int _num_functions = 0;
445
449 static constexpr unsigned int _stack_size = 10;
453 static constexpr double _epsilon = 1.0e-12;
454};
455
456#define KOKKOS_FPARSER_COMPARE(code, op, epsilon) \
457 case Opcode::code: \
458 stack[head - 2] = stack[head - 2] - stack[head - 1] op epsilon; \
459 --head; \
460 break
461
462#define KOKKOS_FPARSER_BINARY(code, op) \
463 case Opcode::code: \
464 stack[head - 2] = stack[head - 2] op stack[head - 1]; \
465 --head; \
466 break
467
468#define KOKKOS_FPARSER_FUNCTION_1(code, func) \
469 case Opcode::code: \
470 stack[head - 1] = ::Kokkos::func(stack[head - 1]); \
471 break
472
473#define KOKKOS_FPARSER_FUNCTION_2(code, func) \
474 case Opcode::code: \
475 stack[head - 2] = ::Kokkos::func(stack[head - 2], stack[head - 1]); \
476 --head; \
477 break
478
479#define KOKKOS_FPARSER_FUNCTION_INV_1(code, func) \
480 case Opcode::code: \
481 stack[head - 1] = 1.0 / ::Kokkos::func(stack[head - 1]); \
482 break
483
484KOKKOS_FUNCTION inline Real
485RPNEvaluator::eval(const Real t, const Real3 p, const unsigned int qp, Datum * datum) const
486{
487 Real stack[_stack_size];
488
489 // Stack head position
490 unsigned int head = 0;
491
492 for (unsigned int pos = 0; pos < _rpn.size(); ++pos)
493 {
494 KOKKOS_ASSERT(head < _stack_size);
495
496 const auto inst = _rpn[pos];
497
498 switch (_rpn[pos].op)
499 {
500 case Opcode::NUM:
501 stack[head] = _numbers[inst.arg];
502 ++head;
503 break;
504 case Opcode::VAR:
505 if (inst.arg < 3)
506 stack[head] = p(inst.arg);
507 else if (inst.arg == 3)
508 stack[head] = t;
509 else
510 {
511 const auto type = _variables[inst.arg].first;
512 const auto idx = _variables[inst.arg].second;
513
514 switch (type)
515 {
517 stack[head] = _scalars[idx];
518 break;
520 {
521 KOKKOS_ASSERT(datum);
522
523 stack[head] = _fields[idx](*datum, qp);
524 break;
525 }
527 {
528 KOKKOS_ASSERT(datum);
529
530 stack[head] = _properties[idx](*datum, qp);
531 break;
532 }
534 stack[head] = _functions[idx].value(t, p);
535 break;
536 }
537 }
538 ++head;
539 break;
540 case Opcode::NEG:
541 stack[head - 1] = -stack[head - 1];
542 break;
543 case Opcode::NOT:
544 stack[head - 1] = !::Kokkos::round(stack[head - 1]);
545 break;
546 case Opcode::EQ:
547 stack[head - 2] = ::Kokkos::abs(stack[head - 2] - stack[head - 1]) <= _epsilon;
548 --head;
549 break;
550 case Opcode::NEQ:
551 stack[head - 2] = ::Kokkos::abs(stack[head - 2] - stack[head - 1]) > _epsilon;
552 --head;
553 break;
554 case Opcode::AND:
555 stack[head - 2] = ::Kokkos::round(stack[head - 2]) && ::Kokkos::round(stack[head - 1]);
556 --head;
557 break;
558 case Opcode::OR:
559 stack[head - 2] = ::Kokkos::round(stack[head - 2]) || ::Kokkos::round(stack[head - 1]);
560 --head;
561 break;
562 case Opcode::IF:
563 stack[head - 3] = ::Kokkos::round(stack[head - 3]) ? stack[head - 2] : stack[head - 1];
564 head -= 2;
565 break;
566 KOKKOS_FPARSER_COMPARE(LT, <, -_epsilon);
567 KOKKOS_FPARSER_COMPARE(LEQ, <=, _epsilon);
568 KOKKOS_FPARSER_COMPARE(GT, >, _epsilon);
569 KOKKOS_FPARSER_COMPARE(GEQ, >=, -_epsilon);
570 KOKKOS_FPARSER_BINARY(ADD, +);
571 KOKKOS_FPARSER_BINARY(SUB, -);
572 KOKKOS_FPARSER_BINARY(MUL, *);
573 KOKKOS_FPARSER_BINARY(DIV, /);
574 KOKKOS_FPARSER_FUNCTION_1(ABS, abs);
575 KOKKOS_FPARSER_FUNCTION_1(ACOS, acos);
576 KOKKOS_FPARSER_FUNCTION_1(ACOSH, acosh);
577 KOKKOS_FPARSER_FUNCTION_1(ASIN, asin);
578 KOKKOS_FPARSER_FUNCTION_1(ASINH, asinh);
579 KOKKOS_FPARSER_FUNCTION_1(ATAN, atan);
580 KOKKOS_FPARSER_FUNCTION_2(ATAN2, atan2);
581 KOKKOS_FPARSER_FUNCTION_1(ATANH, atanh);
582 KOKKOS_FPARSER_FUNCTION_1(CBRT, cbrt);
583 KOKKOS_FPARSER_FUNCTION_1(CEIL, ceil);
584 KOKKOS_FPARSER_FUNCTION_1(COS, cos);
585 KOKKOS_FPARSER_FUNCTION_1(COSH, cosh);
586 KOKKOS_FPARSER_FUNCTION_INV_1(COT, tan);
587 KOKKOS_FPARSER_FUNCTION_INV_1(CSC, sin);
588 KOKKOS_FPARSER_FUNCTION_1(EXP, exp);
589 KOKKOS_FPARSER_FUNCTION_1(EXP2, exp2);
590 KOKKOS_FPARSER_FUNCTION_1(FLOOR, floor);
591 KOKKOS_FPARSER_FUNCTION_2(HYPOT, hypot);
592 KOKKOS_FPARSER_FUNCTION_1(INT, round);
593 KOKKOS_FPARSER_FUNCTION_1(LOG, log);
594 KOKKOS_FPARSER_FUNCTION_1(LOG2, log2);
595 KOKKOS_FPARSER_FUNCTION_1(LOG10, log10);
596 KOKKOS_FPARSER_FUNCTION_2(MAX, max);
597 KOKKOS_FPARSER_FUNCTION_2(MIN, min);
598 KOKKOS_FPARSER_FUNCTION_2(POW, pow);
599 KOKKOS_FPARSER_FUNCTION_INV_1(SEC, cos);
600 KOKKOS_FPARSER_FUNCTION_1(SIN, sin);
601 KOKKOS_FPARSER_FUNCTION_1(SINH, sinh);
602 KOKKOS_FPARSER_FUNCTION_1(SQRT, sqrt);
603 KOKKOS_FPARSER_FUNCTION_1(TAN, tan);
604 KOKKOS_FPARSER_FUNCTION_1(TANH, tanh);
605 KOKKOS_FPARSER_FUNCTION_1(TRUNC, trunc);
606 }
607 }
608
609 KOKKOS_ASSERT(head == 1);
610
611 return stack[head - 1];
612}
613
614} // namespace Moose::Kokkos
A helper class for re-directing output streams to Console output objects form MooseObjects.
KOKKOS_FUNCTION T & first() const
Get the first element.
The Kokkos array class.
The Kokkos object that holds thread-private data in the parallel operations of any Kokkos object.
The abstract class that provides polymorphic interfaces for a function.
The Kokkos material property class.
Parsing Expression Grammar (PEG)
const std::string _expression
Input expression.
peg::parser _parser
Parser object.
std::shared_ptr< peg::Ast > _ast
Abstract Syntax Tree (AST)
const std::string & expression() const
Get input expression.
PEGParser(const std::string &expression, const ConsoleStream *console=nullptr)
Constructor.
Reverse Polish Notation (RPN) builder.
void build(const peg::Ast &ast)
Build RPN from AST.
void associateField(const std::string &name, const VariableValue *field)
Associate a variable with a field variable.
std::unordered_map< std::string, Variable > _variables
Variables used in the function.
void builderError(const peg::Ast &ast, const std::string &message) const
Print a pretty error showing the position of error.
std::vector< Real > _numbers
Numbers used in the function.
unsigned int addVariable(const std::string &name)
Add a parsed function variable.
unsigned int addNumber(Real number)
Add a parsed function constant.
void checkFinalized()
Error on attempts to update the builder after finalization.
const std::vector< Instruction > & getRPN() const
Get RPN sequence.
void associateScalar(const std::string &name, const Real *scalar)
Associate a variable with a scalar value.
void finalize()
Finalize the builder and prevent further changes.
bool finalized() const
Get whether the builder was finalized.
bool _has_default_variables
Whether default variables were added.
void addDefaultVariables()
Add default variables.
std::vector< Instruction > _rpn
RPN sequence.
const std::vector< Real > & getNumbers() const
Get numbers used in the expression.
static const std::map< std::string, std::pair< Opcode, unsigned int > > _function_opcode_map
Map from functions to opcodes and the expected number of arguments.
void printRPN(const ConsoleStream &console) const
Print RPN sequence for debugging.
bool hasDefaultVariables() const
Get whether default variables were added.
static const std::map< std::string, Opcode > _binary_opcode_map
Map from binary operators to opcodes.
RPNBuilder(const std::string &expression, const ConsoleStream *console=nullptr)
Constructor.
bool _finalized
Whether builder was finalized.
static const std::map< std::string, Opcode > _unary_opcode_map
Map from unary operators to opcodes.
const std::unordered_map< std::string, Variable > & getVariables() const
Get variables used in the expression.
void associateProperty(const std::string &name, const MaterialProperty< Real > *property)
Associate a variable with a material property.
void associateFunction(const std::string &name, const Function *function)
Associate a variable with a function.
Reverse Polish Notation (RPN) evaluator.
Array<::Kokkos::pair< VariableType, unsigned int > > _variables
Types of variables and indices.
Array< Function > _functions
Functions used in the function.
Array< Instruction > _rpn
RPN sequence.
unsigned int _num_functions
Number of functions.
Array< Real > _numbers
Numbers used in the function.
Array< MaterialProperty< Real > > _properties
Material properties used in the function.
RPNEvaluator()=default
Default constructor.
RPNEvaluator(const RPNEvaluator &evaluator)
Copy constructor for parallel dispatch.
Array< VariableValue > _fields
Field variables used in the function.
KOKKOS_FUNCTION Real eval(const Real t, const Real3 p, const unsigned int qp=0, Datum *datum=nullptr) const
Evaluate RPN at point (t,x,y,z)
std::vector< const void * > _pointers
Pointers to the associated quantities of variables.
static constexpr double _epsilon
Epsilon for equality comparison.
unsigned int _num_fields
Number of field variables.
Array< Real > _scalars
Scalar variables used in the function.
void init(const RPNBuilder &builder)
Initialize RPN evaluator from an RPN builder.
unsigned int _num_scalars
Number of scalar variables.
unsigned int _num_properties
Number of material properties.
static constexpr unsigned int _stack_size
Fixed stack size.
The Kokkos wrapper classes for MOOSE-like variable value access.
const unsigned int invalid_uint