forked from ufz/ogs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFunctionParameter.h
123 lines (106 loc) · 3.66 KB
/
FunctionParameter.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/**
* \file
* \copyright
* Copyright (c) 2012-2020, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
*/
#pragma once
#include <utility>
#include <vector>
#include <exprtk.hpp>
#include "MeshLib/Elements/Element.h"
#include "MeshLib/Node.h"
#include "Parameter.h"
#include "Utils.h"
namespace ParameterLib
{
/// A parameter class evaluating functions defined by
/// user-provided mathematical expressions.
///
/// Currently, x, y, and z are supported as variables
/// of the functions.
template <typename T>
struct FunctionParameter final : public Parameter<T>
{
using symbol_table_t = exprtk::symbol_table<T>;
using expression_t = exprtk::expression<T>;
using parser_t = exprtk::parser<T>;
using error_t = exprtk::parser_error::type;
/**
* Constructing from a vector of expressions
*
* @param name the parameter's name
* @param mesh the parameter's domain of definition.
* @param vec_expression_str a vector of mathematical expressions
* The vector size specifies the number of components of the parameter.
*/
FunctionParameter(std::string const& name,
MeshLib::Mesh const& mesh,
std::vector<std::string> const& vec_expression_str)
: Parameter<T>(name, &mesh), _vec_expression_str(vec_expression_str)
{
_symbol_table.add_constants();
_symbol_table.create_variable("x");
_symbol_table.create_variable("y");
_symbol_table.create_variable("z");
_vec_expression.resize(_vec_expression_str.size());
for (unsigned i = 0; i < _vec_expression_str.size(); i++)
{
_vec_expression[i].register_symbol_table(_symbol_table);
parser_t parser;
if (!parser.compile(_vec_expression_str[i], _vec_expression[i]))
{
OGS_FATAL("Error: %s\tExpression: %s\n", parser.error().c_str(),
_vec_expression_str[i].c_str());
}
}
}
bool isTimeDependent() const override { return false; }
int getNumberOfComponents() const override
{
return _vec_expression.size();
}
std::vector<T> operator()(double const /*t*/,
SpatialPosition const& pos) const override
{
std::vector<T> cache(getNumberOfComponents());
auto& x = _symbol_table.get_variable("x")->ref();
auto& y = _symbol_table.get_variable("y")->ref();
auto& z = _symbol_table.get_variable("z")->ref();
if (pos.getCoordinates())
{
auto const coords = pos.getCoordinates().get();
x = coords[0];
y = coords[1];
z = coords[2];
}
else if (pos.getNodeID())
{
auto const& node =
*ParameterBase::_mesh->getNode(pos.getNodeID().get());
x = node[0];
y = node[1];
z = node[2];
}
for (unsigned i = 0; i < _vec_expression.size(); i++)
{
cache[i] = _vec_expression[i].value();
}
if (!this->_coordinate_system)
{
return cache;
}
return this->rotateWithCoordinateSystem(cache, pos);
}
private:
std::vector<std::string> const _vec_expression_str;
symbol_table_t _symbol_table;
std::vector<expression_t> _vec_expression;
};
std::unique_ptr<ParameterBase> createFunctionParameter(
std::string const& name, BaseLib::ConfigTree const& config,
MeshLib::Mesh const& mesh);
} // namespace ParameterLib