Flow123d  jenkins-Flow123d-linux-release-multijob-282
field_formula.impl.hh
Go to the documentation of this file.
1  /*
2  * field_formula.impl.hh
3  *
4  * Created on: Jan 2, 2013
5  * Author: jb
6  */
7 
8 #ifndef FIELD_FORMULA_IMPL_HH_
9 #define FIELD_FORMULA_IMPL_HH_
10 
11 
12 #include "fields/field_formula.hh"
13 #include "fparser.hh"
14 #include "input/input_type.hh"
15 #include <boost/foreach.hpp>
16 
17 /// Implementation.
18 
19 namespace it = Input::Type;
20 
21 template <int spacedim, class Value>
23 
24 template <int spacedim, class Value>
26  Input::Type::AbstractRecord &a_type, const typename Value::ElementInputType *eit
27  )
28 {
29  it::Record type
30  = it::Record("FieldFormula", FieldAlgorithmBase<spacedim,Value>::template_name()+" Field given by runtime interpreted formula.")
31  .derive_from(a_type)
32  .declare_key("value", StringValue::get_input_type(NULL), it::Default::obligatory(),
33  "String, array of strings, or matrix of strings with formulas for individual "
34  "entries of scalar, vector, or tensor value respectively.\n"
35  "For vector values, you can use just one string to enter homogeneous vector.\n"
36  "For square NxN-matrix values, you can use:\n"
37  "* array of strings of size N to enter diagonal matrix\n"
38  "* array of strings of size (N+1)*N/2 to enter symmetric matrix (upper triangle, row by row)\n"
39  "* just one string to enter (spatially variable) multiple of the unit matrix.\n"
40  "Formula can contain variables x,y,z,t and usual operators and functions." );
41 
42  return type;
43 }
44 
45 
46 
47 
48 template <int spacedim, class Value>
50 : FieldAlgorithmBase<spacedim, Value>(n_comp),
51  formula_matrix_(this->value_.n_rows(), this->value_.n_cols()),
52  formula_matrix_helper_(formula_matrix_), parser_matrix_(this->value_.n_rows())
53 {
54  for(unsigned int row=0; row < this->value_.n_rows(); row++) {
55  parser_matrix_[row].resize(this->value_.n_cols());
56  }
57 }
58 
59 
60 
61 template <int spacedim, class Value>
63  // read formulas form input
64  formula_matrix_helper_.init_from_input( rec.val<typename StringValue::AccessType>("value") );
65  value_input_address_ = rec.address_string();
66 }
67 
68 
69 template <int spacedim, class Value>
71 
72 
73  bool any_parser_changed = false;
74 
75 
76  std::string vars = string("x,y,z").substr(0, 2*spacedim-1);
77  // update parsers
78  for(unsigned int row=0; row < this->value_.n_rows(); row++)
79  for(unsigned int col=0; col < this->value_.n_cols(); col++) {
80  // get all variable names from the formula
81  std::vector<std::string> var_list;
82 
83  FunctionParser tmp_parser;
84 #pragma GCC diagnostic push
85 #pragma GCC diagnostic ignored "-Wunused-variable"
86  {
87  int err=tmp_parser.ParseAndDeduceVariables(formula_matrix_.at(row,col), var_list);
88  ASSERT( err != FunctionParser::FP_NO_ERROR, "ParseAndDeduceVariables error: %s\n", tmp_parser.ErrorMsg() );
89  }
90 #pragma GCC diagnostic pop
91 
92  bool time_dependent = false;
93  BOOST_FOREACH(std::string &var_name, var_list ) {
94  if (var_name == std::string("t") ) time_dependent=true;
95  else if (var_name == "x" || var_name == "y" || var_name == "z") continue;
96  else
97  xprintf(Warn, "Unknown variable '%s' in the FieldFormula[%d][%d] == '%s'\n at the input address:\n %s \n",
98  var_name.c_str(), row, col, formula_matrix_.at(row,col).c_str(),
99  value_input_address_.c_str() );
100  }
101  if (time_dependent) {
102  parser_matrix_[row][col].AddConstant("t", time.end());
103  }
104 
105  // TODO:
106  // - possibly add user defined constants and units here ...
107  // - optimization; possibly parse only if time_dependent || formula_matrix[][] has changed ...
108 
109  if (time_dependent || this->time_ == TimeStep() ) {
110  parser_matrix_[row][col].Parse(formula_matrix_.at(row,col), vars);
111 
112  if ( parser_matrix_[row][col].GetParseErrorType() != FunctionParser::FP_NO_ERROR ) {
113  xprintf(UsrErr, "ParserError: %s\n in the FieldFormula[%d][%d] == '%s'\n at the input address:\n %s \n",
114  parser_matrix_[row][col].ErrorMsg(),
115  row,col,formula_matrix_.at(row,col).c_str(),
116  value_input_address_.c_str());
117  }
118 
119  parser_matrix_[row][col].Optimize();
120  any_parser_changed = true;
121  }
122 
123 
124  }
125 
126  this->time_=time;
127  return any_parser_changed;
128 }
129 
130 
131 /**
132  * Returns one value in one given point. ResultType can be used to avoid some costly calculation if the result is trivial.
133  */
134 template <int spacedim, class Value>
135 typename Value::return_type const & FieldFormula<spacedim, Value>::value(const Point &p, const ElementAccessor<spacedim> &elm)
136 {
137  for(unsigned int row=0; row < this->value_.n_rows(); row++)
138  for(unsigned int col=0; col < this->value_.n_cols(); col++) {
139  this->value_(row,col) = parser_matrix_[row][col].Eval(p.memptr());
140  }
141  return this->r_value_;
142 }
143 
144 
145 /**
146  * Returns std::vector of scalar values in several points at once.
147  */
148 template <int spacedim, class Value>
151 {
152  ASSERT_EQUAL( point_list.size(), value_list.size() );
153  for(unsigned int i=0; i< point_list.size(); i++) {
154  Value envelope(value_list[i]);
155  ASSERT( envelope.n_rows()==this->value_.n_rows(),
156  "value_list[%d] has wrong number of rows: %d; should match number of components: %d\n",
157  i, envelope.n_rows(),this->value_.n_rows());
158 
159  for(unsigned int row=0; row < this->value_.n_rows(); row++)
160  for(unsigned int col=0; col < this->value_.n_cols(); col++) {
161  envelope(row,col) = parser_matrix_[row][col].Eval(point_list[i].memptr());
162  }
163  }
164 }
165 
166 
167 template <int spacedim, class Value>
169 }
170 
171 
172 #endif /* FIELD_FORMULA_IMPL_HH_ */
Accessor to input data conforming to declared Array.
Definition: accessors.hh:558
virtual ~FieldFormula()
FieldFormula(unsigned int n_comp=0)
static Default obligatory()
Definition: type_record.hh:89
Record & derive_from(AbstractRecord &parent)
Definition: type_record.cc:197
static Input::Type::Record get_input_type(Input::Type::AbstractRecord &a_type, const typename Value::ElementInputType *eit)
bool set_time(const TimeStep &time) override
#define ASSERT(...)
Definition: global_defs.h:121
Definition: system.hh:72
virtual void init_from_input(const Input::Record &rec)
#define ASSERT_EQUAL(a, b)
Definition: global_defs.h:136
Accessor to the data with type Type::Record.
Definition: accessors.hh:327
const Ret val(const string &key) const
#define xprintf(...)
Definition: system.hh:100
Class for declaration of polymorphic Record.
Definition: type_record.hh:487
double end() const
Space< spacedim >::Point Point
Definition: system.hh:72
Value value_
Last value, prevents passing large values (vectors) by value.
virtual Value::return_type const & value(const Point &p, const ElementAccessor< spacedim > &elm)
std::vector< std::vector< FunctionParser > > parser_matrix_
Record type proxy class.
Definition: type_record.hh:169
Representation of one time step.
virtual void value_list(const std::vector< Point > &point_list, const ElementAccessor< spacedim > &elm, std::vector< typename Value::return_type > &value_list)
string address_string() const
Definition: accessors.cc:193
Record & declare_key(const string &key, const KeyType &type, const Default &default_value, const string &description)
Definition: type_record.cc:430