25 #include "include/arena_alloc.hh" 26 #include <boost/algorithm/string/replace.hpp> 36 template <
int spacedim, class
Value>
44 "String, array of strings, or matrix of strings with formulas for individual " 45 "entries of scalar, vector, or tensor value respectively.\n" 46 "For vector values, you can use just one string to enter homogeneous vector.\n" 47 "For square (($N\\times N$))-matrix values, you can use:\n\n" 48 " - array of strings of size (($N$)) to enter diagonal matrix\n" 49 " - array of strings of size (($\\frac12N(N+1)$)) to enter symmetric matrix (upper triangle, row by row)\n" 50 " - just one string to enter (spatially variable) multiple of the unit matrix.\n" 51 "Formula can contain variables ```x,y,z,t,d``` and usual operators and functions." )
55 "The vector used to project evaluation point onto the surface.")
57 "The name of region set considered as the surface. You have to set surface region if you " 58 "want to use formula variable ```d```.")
65 template <
int spacedim,
class Value>
67 Input::register_class< FieldFormula<spacedim, Value>,
unsigned int >(
"FieldFormula") +
72 template <
int spacedim,
class Value>
75 formula_matrix_(this->value_.n_rows(), this->value_.n_cols()),
76 first_time_set_(true), arena_alloc_(nullptr)
80 for(
unsigned int row=0; row < this->
value_.n_rows(); row++) {
84 for(
unsigned int i=0; i < this->
value_.n_rows()*this->
value_.n_cols(); i++) {
91 template <
int spacedim,
class Value>
101 template <
int spacedim,
class Value>
105 bool any_parser_changed =
false;
111 std::string vars = string(
"x,y,z").substr(0, 2*spacedim-1);
114 for(
unsigned int row=0; row < this->
value_.n_rows(); row++)
115 for(
unsigned int col=0; col < this->
value_.n_cols(); col++) {
119 FunctionParser tmp_parser;
120 tmp_parser.AddConstant(
"Pi", 3.14159265358979323846);
121 tmp_parser.AddConstant(
"E", 2.71828182845904523536);
124 #pragma GCC diagnostic push 125 #pragma GCC diagnostic ignored "-Wunused-variable" 127 int err=tmp_parser.ParseAndDeduceVariables(
formula_matrix_.
at(row,col), var_list);
128 ASSERT(err != FunctionParser::FP_NO_ERROR)(tmp_parser.ErrorMsg()).error(
"ParseAndDeduceVariables error\n");
130 #pragma GCC diagnostic pop 132 for(std::string &var_name : var_list ) {
133 if (var_name == std::string(
"t") ) time_dependent[row*this->
value_.n_rows()+col]=
true;
134 else if (var_name == std::string(
"d") ) {
139 WarningOut().fmt(
"Unset surface region. Variable '{}' in the FieldFormula[{}][{}] == '{}' will be set to zero\n at the input address:\n {} \n",
142 else if (var_name ==
"x" || var_name ==
"y" || var_name ==
"z") {
147 WarningOut().fmt(
"Unknown variable '{}' in the FieldFormula[{}][{}] == '{}'\n at the input address:\n {} \n",
152 parser_matrix_[row][col].AddConstant(
"Pi", 3.14159265358979323846);
153 parser_matrix_[row][col].AddConstant(
"E", 2.71828182845904523536);
154 if (time_dependent[row*this->
value_.n_rows()+col]) {
160 vars += string(
",d");
161 vars += string(
",cross_section,const_scalar,scalar_field,unknown_scalar,integer_scalar");
164 for(
unsigned int row=0; row < this->
value_.n_rows(); row++)
165 for(
unsigned int col=0; col < this->
value_.n_cols(); col++) {
173 if (
parser_matrix_[row][col].GetParseErrorType() != FunctionParser::FP_NO_ERROR ) {
174 THROW( ExcFParserError() << EI_FParserMsg(
parser_matrix_[row][col].ErrorMsg()) << EI_Row(row)
179 any_parser_changed =
true;
187 return any_parser_changed;
191 template <
int spacedim,
class Value>
194 std::string surface_region;
196 surface_depth_ = std::make_shared<SurfaceDepth>(mesh, surface_region,
in_rec_.
val<std::string>(
"surface_direction"));
204 template <
int spacedim,
class Value>
209 for(
unsigned int row=0; row < this->
value_.n_rows(); row++)
210 for(
unsigned int col=0; col < this->
value_.n_cols(); col++) {
220 template <
int spacedim,
class Value>
226 for(
unsigned int i=0; i< point_list.
size(); i++) {
227 Value envelope(value_list[i]);
229 .error(
"value_list['i'] has wrong number of rows\n");
232 for(
unsigned int row=0; row < this->
value_.n_rows(); row++)
233 for(
unsigned int col=0; col < this->
value_.n_cols(); col++) {
240 template <
int spacedim,
class Value>
247 for (
unsigned int i=reg_chunk_begin; i<reg_chunk_end; ++i) {
253 auto value_cache =
it.first->value_cache();
254 for (
unsigned int i=reg_chunk_begin; i<reg_chunk_end; ++i) {
255 if (
it.first->name() ==
"X") {
256 x_[i] = value_cache->template vec<3>(i)(0);
257 y_[i] = value_cache->template vec<3>(i)(1);
258 z_[i] = value_cache->template vec<3>(i)(2);
260 it.second[i] = value_cache->data_[i];
270 for(
unsigned int row=0; row < this->
value_.n_rows(); row++)
271 for(
unsigned int col=0; col < this->
value_.n_cols(); col++) {
274 for (
unsigned int i=reg_chunk_begin; i<reg_chunk_end; ++i) {
275 auto cache_val = data_cache.template mat<Value::NRows_, Value::NCols_>(i);
276 cache_val(row, col) =
res_[i];
277 data_cache.
set(i) = cache_val;
283 template <
int spacedim,
class Value>
289 p_depth.subvec(0,spacedim-1) = p;
292 }
catch (SurfaceDepth::ExcTooLargeSnapDistance &e) {
293 e << SurfaceDepth::EI_FieldTime(this->
time_.
end());
305 for (
auto i : shape) r *= i;
310 template <
int spacedim,
class Value>
315 for(
unsigned int row=0; row < this->
value_.n_rows(); row++)
316 for(
unsigned int col=0; col < this->
value_.n_cols(); col++) {
318 unsigned int i_p = row*this->
value_.n_cols()+col;
323 boost::replace_all(expr,
"^",
"**");
324 boost::replace_all(expr,
"max(",
"maximum(");
325 boost::replace_all(expr,
"min(",
"minimum(");
326 boost::replace_all(expr,
"Pi",
"pi");
327 boost::replace_all(expr,
"E",
"e");
329 std::string pref(
"if(");
330 auto res = std::mismatch(pref.begin(), pref.end(), expr.begin());
331 if ( (res.first == pref.end()) && (expr.back() ==
')') ) {
332 std::string subexpr = expr.substr(3, expr.size()-4);
333 std::string delimiter =
",";
334 std::string cond = subexpr.substr(0, subexpr.find(delimiter));
335 subexpr.erase(0, cond.size()+1);
336 std::string if_case = subexpr.substr(0, subexpr.find(delimiter));
337 std::string else_case = subexpr.substr(if_case.size()+1);
338 expr =
"(" + if_case +
" if " + cond +
" else " + else_case +
")";
343 }
catch (std::exception
const& e) {
344 if (
typeid(e) ==
typeid(bparser::Exception))
THROW( ExcParserError() << EI_BParserMsg(e.what()) );
347 variables.insert(variables.end(),
b_parser_[i_p].variables().begin(),
b_parser_[i_p].variables().end());
350 std::sort( variables.begin(), variables.end() );
351 variables.erase( std::unique( variables.begin(), variables.end() ), variables.end() );
354 for (
auto var : variables) {
355 if (var ==
"x" || var ==
"y" || var ==
"z") {
361 auto field_ptr = field_set.
field(var);
363 else THROW( ExcUnknownField() << EI_Field(var) );
365 if (field_ptr->value_cache() ==
nullptr)
THROW( ExcNotDoubleField() << EI_Field(var) );
379 template <
int spacedim,
class Value>
394 std::string field_name = field->name();
396 if (field_name ==
"X") {
404 for(
unsigned int row=0; row < this->
value_.n_rows(); row++)
405 for(
unsigned int col=0; col < this->
value_.n_cols(); col++) {
407 unsigned int i_p = row*this->
value_.n_cols()+col;
411 for (
auto field : required_fields_) {
412 std::string field_name = field->name();
413 if (field_name ==
"X") {
423 for (
uint i=0; i<n_subsets; ++i)
428 template <
int spacedim,
class Value>
unsigned int region_chunk_begin(unsigned int region_patch_idx) const
Return begin position of region chunk in FieldValueCache.
TimeStep time_
Actual time level; initial value is -infinity.
void init_unit_conversion_coefficient(const Input::Record &rec, const struct FieldAlgoBaseInitData &init_data)
Init value of unit_conversion_coefficient_ from input.
Container for various descendants of FieldCommonBase.
unsigned int size() const
static unsigned int get()
Return number of stored elements.
#define INSTANCE_ALL(field)
Directing class of FieldValueCache.
Helper struct stores data for initizalize descentants of FieldAlgorithmBase.
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
ArmaVec< Type, nr > vec(uint mat_index) const
Value::return_type r_value_
double unit_conversion_coefficient_
Coeficient of conversion of user-defined unit.
FieldCommon * field(const std::string &field_name) const
unsigned int region_chunk_end(unsigned int region_patch_idx) const
Return end position of region chunk in FieldValueCache.
ArrayMatSet set(uint index)
Space< spacedim >::Point Point
std::string & at(unsigned int row)
bool is_constant_in_space_
Flag detects that field is only dependent on time.
Value value_
Last value, prevents passing large values (vectors) by value.
void set_surface_depth(std::shared_ptr< SurfaceDepth > surface_depth)
Set surface depth object to "d" field.
#define WarningOut()
Macro defining 'warning' record of log.
static const unsigned int simd_size_double
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Representation of one time step..
#define FLOW123D_FORCE_LINK_IN_CHILD(x)
#define ASSERT_EQ(a, b)
Definition of comparative assert macro (EQual)