25 #include <boost/algorithm/string/replace.hpp>
26 #include <boost/regex.hpp>
37 template <
int spacedim,
class Value>
45 "String, array of strings, or matrix of strings with formulas for individual "
46 "entries of scalar, vector, or tensor value respectively.\n"
47 "For vector values, you can use just one string to enter homogeneous vector.\n"
48 "For square (($N\\times N$))-matrix values, you can use:\n\n"
49 " - array of strings of size (($N$)) to enter diagonal matrix\n"
50 " - array of strings of size (($\\frac12N(N+1)$)) to enter symmetric matrix (upper triangle, row by row)\n"
51 " - just one string to enter (spatially variable) multiple of the unit matrix.\n"
52 "Formula can contain variables ```x,y,z,t,d``` and usual operators and functions." )
56 "The vector used to project evaluation point onto the surface.")
58 "The name of region set considered as the surface. You have to set surface region if you "
59 "want to use formula variable ```d```.")
66 template <
int spacedim,
class Value>
68 Input::register_class< FieldFormula<spacedim, Value>,
unsigned int >(
"FieldFormula") +
73 template <
int spacedim,
class Value>
84 template <
int spacedim,
class Value>
86 this->init_unit_conversion_coefficient(rec, init_data);
89 this->formula_ = rec.
val<std::string>(
"value");
94 template <
int spacedim,
class Value>
98 this->is_constant_in_space_ =
false;
104 template <
int spacedim,
class Value>
107 std::string surface_region;
108 if ( in_rec_.opt_val(
"surface_region", surface_region) ) {
109 surface_depth_ = std::make_shared<SurfaceDepth>(mesh, surface_region, in_rec_.val<std::string>(
"surface_direction"));
114 template <
int spacedim,
class Value>
121 for (
unsigned int i=reg_chunk_begin; i<reg_chunk_end; ++i) {
124 for (
auto it : eval_field_data_) {
127 auto value_cache =
it.first->value_cache();
128 for (
unsigned int i=reg_chunk_begin; i<reg_chunk_end; ++i) {
129 if (
it.first->name() ==
"X") {
130 x_[i] = value_cache->template vec<3>(i)(0);
131 y_[i] = value_cache->template vec<3>(i)(1);
132 z_[i] = value_cache->template vec<3>(i)(2);
134 it.second[i] = value_cache->data_[i];
142 subset_vec.assign(subsets_ + subsets_begin, subsets_ + subsets_end);
144 b_parser_.set_subset(subset_vec);
147 for(
unsigned int row=0; row < this->value_.n_rows(); row++)
148 for(
unsigned int col=0; col < this->value_.n_cols(); col++) {
149 uint comp_shift = (row*this->value_.n_cols()+col) * vec_size;
150 for (
unsigned int i=reg_chunk_begin; i<reg_chunk_end; ++i) {
151 auto cache_val = data_cache.template mat<Value::NRows_, Value::NCols_>(i);
152 cache_val(row, col) = this->unit_conversion_coefficient_ * res_[i + comp_shift];
153 data_cache.
set(i) = cache_val;
159 template <
int spacedim,
class Value>
162 if (surface_depth_ && has_depth_var_) {
165 p_depth.subvec(0,spacedim-1) = p;
167 p_depth(spacedim) = surface_depth_->compute_distance(p);
168 }
catch (SurfaceDepth::ExcTooLargeSnapDistance &e) {
169 e << SurfaceDepth::EI_FieldTime(this->time_.end());
170 e << in_rec_.ei_address();
179 template <
int spacedim,
class Value>
181 required_fields_.clear();
185 b_parser_.parse( formula_ );
186 }
catch (std::exception
const& e) {
187 if (
typeid(e) ==
typeid(bparser::Exception))
188 THROW( ExcParserError() << EI_BParserMsg(e.what()) << EI_Formula(formula_) << Input::EI_Address( in_rec_.address_string() ) );
192 std::sort( variables.begin(), variables.end() );
193 variables.erase( std::unique( variables.begin(), variables.end() ), variables.end() );
197 for (
auto var : variables) {
198 if (var ==
"X" || var ==
"x" || var ==
"y" || var ==
"z") {
199 required_fields_.push_back( field_set.
field(
"X") );
200 sum_shape_sizes_ += spacedim;
202 else if (var ==
"t") has_time_ =
true;
204 auto field_ptr = field_set.
field(var);
205 if (field_ptr !=
nullptr) required_fields_.push_back( field_ptr );
206 else THROW( FieldSet::ExcUnknownField() << FieldCommon::EI_Field(var) << FieldSet::EI_FieldType(
"formula") << Input::EI_Address( in_rec_.address_string() ) );
208 if (field_ptr->value_cache() ==
nullptr)
THROW( ExcNotDoubleField() << EI_Field(var) << Input::EI_Address( in_rec_.address_string() ) );
211 sum_shape_sizes_ += field_ptr->n_shape();
218 return required_fields_;
222 template <
int spacedim,
class Value>
227 if (arena_alloc_!=
nullptr) {
230 eval_field_data_.clear();
234 uint n_subsets = vec_size / cache_map.simd_size_double;
235 uint res_comp = Value::NRows_ * Value::NCols_;
236 uint n_vectors = sum_shape_sizes_ + res_comp;
237 arena_alloc_ =
new bparser::ArenaAlloc(cache_map.simd_size_double, n_vectors * vec_size *
sizeof(
double) + n_subsets *
sizeof(
uint));
238 res_ = arena_alloc_->create_array<
double>(vec_size * res_comp);
239 for (
auto field : required_fields_) {
240 std::string field_name = field->name();
241 eval_field_data_[field] = arena_alloc_->create_array<
double>(field->n_shape() * vec_size);
242 if (field_name ==
"X") {
243 X_ = eval_field_data_[field] + 0;
244 x_ = eval_field_data_[field] + 0;
245 y_ = eval_field_data_[field] + vec_size;
246 z_ = eval_field_data_[field] + 2*vec_size;
249 subsets_ = arena_alloc_->create_array<
uint>(n_subsets);
253 b_parser_.set_constant(
"t", {}, {this->time_.end()});
255 for (
auto field : required_fields_) {
256 std::string field_name = field->name();
257 if (field_name ==
"X") {
258 b_parser_.set_variable(
"X", {3}, X_);
259 b_parser_.set_variable(
"x", {}, x_);
260 b_parser_.set_variable(
"y", {}, y_);
261 b_parser_.set_variable(
"z", {}, z_);
264 if (field->n_shape() > 1) f_shape = field->shape_;
265 b_parser_.set_variable(field_name, f_shape, eval_field_data_[field]);
269 if (Value::NRows_ > 1) shape.push_back(Value::NRows_);
270 if (Value::NCols_ > 1) shape.push_back(Value::NCols_);
271 b_parser_.set_variable(
"_result_", shape, res_);
274 for (
uint i=0; i<n_subsets; ++i)
279 template <
int spacedim,
class Value>