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>
ArrayMatSet set(uint index)
Auxiliary data class holds number of elements in cache and allow to set this value explicitly (e....
static unsigned int get()
Return number of stored elements.
Directing class of FieldValueCache.
unsigned int region_chunk_end(unsigned int region_patch_idx) const
Return end position of region chunk in FieldValueCache.
unsigned int region_chunk_begin(unsigned int region_patch_idx) const
Return begin position of region chunk in FieldValueCache.
unsigned int simd_size_double
bool is_constant_in_space_
Flag detects that field is only dependent on time.
Space< spacedim >::Point Point
Container for various descendants of FieldCommonBase.
void set_surface_depth(std::shared_ptr< SurfaceDepth > surface_depth)
Set surface depth object to "d" field.
FieldCommon * field(const std::string &field_name) const
Representation of one time step..
#define INSTANCE_ALL(field)
#define FLOW123D_FORCE_LINK_IN_CHILD(x)
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Helper struct stores data for initizalize descentants of FieldAlgorithmBase.