33 template <
int spacedim,
class Value>
41 "String, array of strings, or matrix of strings with formulas for individual "
42 "entries of scalar, vector, or tensor value respectively.\n"
43 "For vector values, you can use just one string to enter homogeneous vector.\n"
44 "For square (($N\\times N$))-matrix values, you can use:\n\n"
45 " - array of strings of size (($N$)) to enter diagonal matrix\n"
46 " - array of strings of size (($\\frac12N(N+1)$)) to enter symmetric matrix (upper triangle, row by row)\n"
47 " - just one string to enter (spatially variable) multiple of the unit matrix.\n"
48 "Formula can contain variables ```x,y,z,t,d``` and usual operators and functions." )
52 "The vector used to project evaluation point onto the surface.")
54 "The name of region set considered as the surface. You have to set surface region if you "
55 "want to use formula variable ```d```.")
62 template <
int spacedim,
class Value>
64 Input::register_class< FieldFormula<spacedim, Value>,
unsigned int >(
"FieldFormula") +
69 template <
int spacedim,
class Value>
72 formula_matrix_(this->value_.n_rows(), this->value_.n_cols()),
77 for(
unsigned int row=0; row < this->
value_.n_rows(); row++) {
84 template <
int spacedim,
class Value>
86 this->init_unit_conversion_coefficient(rec, init_data);
94 template <
int spacedim,
class Value>
98 bool any_parser_changed =
false;
99 std::string value_input_address = in_rec_.address_string();
100 has_depth_var_ =
false;
101 this->is_constant_in_space_ =
true;
104 std::string vars = string(
"x,y,z").substr(0, 2*spacedim-1);
105 std::vector<bool> time_dependent(this->value_.n_rows() * this->value_.n_cols(),
false);
107 for(
unsigned int row=0; row < this->value_.n_rows(); row++)
108 for(
unsigned int col=0; col < this->value_.n_cols(); col++) {
112 FunctionParser tmp_parser;
113 tmp_parser.AddConstant(
"Pi", 3.14159265358979323846);
114 tmp_parser.AddConstant(
"E", 2.71828182845904523536);
117 #pragma GCC diagnostic push
118 #pragma GCC diagnostic ignored "-Wunused-variable"
120 int err=tmp_parser.ParseAndDeduceVariables(formula_matrix_.at(row,col), var_list);
121 ASSERT(err != FunctionParser::FP_NO_ERROR)(tmp_parser.ErrorMsg()).error(
"ParseAndDeduceVariables error\n");
123 #pragma GCC diagnostic pop
125 for(std::string &var_name : var_list ) {
126 if (var_name == std::string(
"t") ) time_dependent[row*this->value_.n_rows()+col]=
true;
127 else if (var_name == std::string(
"d") ) {
128 this->is_constant_in_space_ =
false;
132 WarningOut().fmt(
"Unset surface region. Variable '{}' in the FieldFormula[{}][{}] == '{}' will be set to zero\n at the input address:\n {} \n",
133 var_name, row, col, formula_matrix_.at(row,col), value_input_address );
135 else if (var_name ==
"x" || var_name ==
"y" || var_name ==
"z") {
136 this->is_constant_in_space_ =
false;
140 WarningOut().fmt(
"Unknown variable '{}' in the FieldFormula[{}][{}] == '{}'\n at the input address:\n {} \n",
141 var_name, row, col, formula_matrix_.at(row,col), value_input_address );
145 parser_matrix_[row][col].AddConstant(
"Pi", 3.14159265358979323846);
146 parser_matrix_[row][col].AddConstant(
"E", 2.71828182845904523536);
147 if (time_dependent[row*this->value_.n_rows()+col]) {
148 parser_matrix_[row][col].AddConstant(
"t", time.
end());
153 vars += string(
",d");
156 for(
unsigned int row=0; row < this->value_.n_rows(); row++)
157 for(
unsigned int col=0; col < this->value_.n_cols(); col++) {
162 if (time_dependent[row*this->value_.n_rows()+col] || first_time_set_ ) {
163 parser_matrix_[row][col].Parse(formula_matrix_.at(row,col), vars);
165 if ( parser_matrix_[row][col].GetParseErrorType() != FunctionParser::FP_NO_ERROR ) {
166 xprintf(
UsrErr,
"ParserError: %s\n in the FieldFormula[%d][%d] == '%s'\n at the input address:\n %s \n",
167 parser_matrix_[row][col].ErrorMsg(),
168 row,col,formula_matrix_.at(row,col).c_str(),
169 value_input_address.c_str());
172 parser_matrix_[row][col].Optimize();
173 any_parser_changed =
true;
179 first_time_set_ =
false;
181 return any_parser_changed;
185 template <
int spacedim,
class Value>
188 std::string surface_region;
189 if ( in_rec_.opt_val(
"surface_region", surface_region) ) {
190 surface_depth_ = std::make_shared<SurfaceDepth>(mesh, surface_region, in_rec_.val<std::string>(
"surface_direction"));
198 template <
int spacedim,
class Value>
202 auto p_depth = this->eval_depth_var(p);
203 for(
unsigned int row=0; row < this->value_.n_rows(); row++)
204 for(
unsigned int col=0; col < this->value_.n_cols(); col++) {
205 this->value_(row,col) = this->unit_conversion_coefficient_ * parser_matrix_[row][col].Eval(p_depth.memptr());
207 return this->r_value_;
214 template <
int spacedim,
class Value>
218 ASSERT_EQ( point_list.size(), value_list.size() );
219 for(
unsigned int i=0; i< point_list.size(); i++) {
220 Value envelope(value_list[i]);
221 ASSERT_EQ( envelope.n_rows(), this->value_.n_rows() )(i)(envelope.n_rows())(this->value_.n_rows())
222 .error(
"value_list['i'] has wrong number of rows\n");
223 auto p_depth = this->eval_depth_var(point_list[i]);
225 for(
unsigned int row=0; row < this->value_.n_rows(); row++)
226 for(
unsigned int col=0; col < this->value_.n_cols(); col++) {
227 envelope(row,col) = this->unit_conversion_coefficient_ * parser_matrix_[row][col].Eval(p_depth.memptr());
233 template <
int spacedim,
class Value>
236 if (surface_depth_ && has_depth_var_) {
238 arma::vec p_depth(spacedim+1);
239 p_depth.subvec(0,spacedim-1) = p;
241 p_depth(spacedim) = surface_depth_->compute_distance(p);
242 }
catch (SurfaceDepth::ExcTooLargeSnapDistance &e) {
243 e << SurfaceDepth::EI_FieldTime(this->time_.end());
244 e << in_rec_.ei_address();
254 template <
int spacedim,
class Value>