Flow123d  last_with_con_2.0.0-4-g42e6930
field_formula.impl.hh
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file field_formula.impl.hh
15  * @brief
16  */
17 
18 #ifndef FIELD_FORMULA_IMPL_HH_
19 #define FIELD_FORMULA_IMPL_HH_
20 
21 
22 #include "fields/field_formula.hh"
23 #include "fparser.hh"
24 #include "input/input_type.hh"
25 #include <boost/foreach.hpp>
26 
27 /// Implementation.
28 
29 namespace it = Input::Type;
30 
31 FLOW123D_FORCE_LINK_IN_CHILD(field_formula)
32 
33 
34 template <int spacedim, class Value>
35 const Input::Type::Record & FieldFormula<spacedim, Value>::get_input_type()
36 {
37 
38  return it::Record("FieldFormula", FieldAlgorithmBase<spacedim,Value>::template_name()+" Field given by runtime interpreted formula.")
40  .declare_key("value", STI::get_input_type() , it::Default::obligatory(),
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``` and usual operators and functions." )
49  .close();
50 }
51 
52 
53 
54 template <int spacedim, class Value>
56  Input::register_class< FieldFormula<spacedim, Value>, unsigned int >("FieldFormula") +
58 
59 
60 
61 template <int spacedim, class Value>
63 : FieldAlgorithmBase<spacedim, Value>(n_comp),
64  formula_matrix_(this->value_.n_rows(), this->value_.n_cols())
65 {
66  parser_matrix_.resize(this->value_.n_rows());
67  for(unsigned int row=0; row < this->value_.n_rows(); row++) {
68  parser_matrix_[row].resize(this->value_.n_cols());
69  }
70 }
71 
72 
73 
74 template <int spacedim, class Value>
76  // read formulas form input
77  STI::init_from_input( formula_matrix_, rec.val<typename STI::AccessType>("value") );
79 }
80 
81 
82 template <int spacedim, class Value>
84 
85 
86  bool any_parser_changed = false;
87 
88 
89  std::string vars = string("x,y,z").substr(0, 2*spacedim-1);
90  // update parsers
91  for(unsigned int row=0; row < this->value_.n_rows(); row++)
92  for(unsigned int col=0; col < this->value_.n_cols(); col++) {
93  // get all variable names from the formula
94  std::vector<std::string> var_list;
95 
96  FunctionParser tmp_parser;
97  tmp_parser.AddConstant("Pi", 3.14159265358979323846);
98  tmp_parser.AddConstant("E", 2.71828182845904523536);
99 
100 
101 #pragma GCC diagnostic push
102 #pragma GCC diagnostic ignored "-Wunused-variable"
103  {
104  int err=tmp_parser.ParseAndDeduceVariables(formula_matrix_.at(row,col), var_list);
105  OLD_ASSERT( err != FunctionParser::FP_NO_ERROR, "ParseAndDeduceVariables error: %s\n", tmp_parser.ErrorMsg() );
106  }
107 #pragma GCC diagnostic pop
108 
109  bool time_dependent = false;
110  BOOST_FOREACH(std::string &var_name, var_list ) {
111  if (var_name == std::string("t") ) time_dependent=true;
112  else if (var_name == "x" || var_name == "y" || var_name == "z") continue;
113  else
114  WarningOut().fmt("Unknown variable '{}' in the FieldFormula[{}][{}] == '{}'\n at the input address:\n {} \n",
115  var_name, row, col, formula_matrix_.at(row,col), value_input_address_ );
116  }
117 
118  // Seems that we can not just add 't' constant to tmp_parser, since it was already Parsed.
119  parser_matrix_[row][col].AddConstant("Pi", 3.14159265358979323846);
120  parser_matrix_[row][col].AddConstant("E", 2.71828182845904523536);
121  if (time_dependent) {
122  parser_matrix_[row][col].AddConstant("t", time.end());
123  }
124 
125  // TODO:
126  // - possibly add user defined constants and units here ...
127  // - optimization; possibly parse only if time_dependent || formula_matrix[][] has changed ...
128  //parser_matrix_[row][col] = tmp_parser;
129  if (time_dependent || this->time_ == TimeStep() ) {
130  parser_matrix_[row][col].Parse(formula_matrix_.at(row,col), vars);
131 
132  if ( parser_matrix_[row][col].GetParseErrorType() != FunctionParser::FP_NO_ERROR ) {
133  xprintf(UsrErr, "ParserError: %s\n in the FieldFormula[%d][%d] == '%s'\n at the input address:\n %s \n",
134  parser_matrix_[row][col].ErrorMsg(),
135  row,col,formula_matrix_.at(row,col).c_str(),
136  value_input_address_.c_str());
137  }
138 
139  parser_matrix_[row][col].Optimize();
140  any_parser_changed = true;
141  }
142 
143 
144  }
145 
146  this->time_=time;
147  return any_parser_changed;
148 }
149 
150 
151 /**
152  * Returns one value in one given point. ResultType can be used to avoid some costly calculation if the result is trivial.
153  */
154 template <int spacedim, class Value>
155 typename Value::return_type const & FieldFormula<spacedim, Value>::value(const Point &p, const ElementAccessor<spacedim> &elm)
156 {
157  for(unsigned int row=0; row < this->value_.n_rows(); row++)
158  for(unsigned int col=0; col < this->value_.n_cols(); col++) {
159  this->value_(row,col) = parser_matrix_[row][col].Eval(p.memptr());
160  }
161  return this->r_value_;
162 }
163 
164 
165 /**
166  * Returns std::vector of scalar values in several points at once.
167  */
168 template <int spacedim, class Value>
171 {
172  OLD_ASSERT_EQUAL( point_list.size(), value_list.size() );
173  for(unsigned int i=0; i< point_list.size(); i++) {
174  Value envelope(value_list[i]);
175  OLD_ASSERT( envelope.n_rows()==this->value_.n_rows(),
176  "value_list[%d] has wrong number of rows: %d; should match number of components: %d\n",
177  i, envelope.n_rows(),this->value_.n_rows());
178 
179  for(unsigned int row=0; row < this->value_.n_rows(); row++)
180  for(unsigned int col=0; col < this->value_.n_cols(); col++) {
181  envelope(row,col) = parser_matrix_[row][col].Eval(point_list[i].memptr());
182  }
183  }
184 }
185 
186 
187 template <int spacedim, class Value>
189 }
190 
191 
192 #endif /* FIELD_FORMULA_IMPL_HH_ */
TimeStep time_
Actual time level; initial value is -infinity.
std::string value_input_address_
Accessor to input data conforming to declared Array.
Definition: accessors.hh:552
static void init_from_input(StringTensor &tensor, AccessType input)
virtual ~FieldFormula()
FieldFormula(unsigned int n_comp=0)
static Default obligatory()
The factory function to make an empty default value which is obligatory.
Definition: type_record.hh:99
StringTensor formula_matrix_
Value::return_type r_value_
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:286
bool set_time(const TimeStep &time) override
virtual Record & derive_from(Abstract &parent)
Method to derive new Record from an AbstractRecord parent.
Definition: type_record.cc:195
#define OLD_ASSERT(...)
Definition: global_defs.h:131
virtual void init_from_input(const Input::Record &rec)
Accessor to the data with type Type::Record.
Definition: accessors.hh:277
const Ret val(const string &key) const
#define xprintf(...)
Definition: system.hh:87
Record & declare_key(const string &key, std::shared_ptr< TypeBase > type, const Default &default_value, const string &description, TypeBase::attribute_map key_attributes=TypeBase::attribute_map())
Declares a new key of the Record.
Definition: type_record.cc:468
double end() const
Space< spacedim >::Point Point
Definition: system.hh:59
std::string & at(unsigned int row)
Value value_
Last value, prevents passing large values (vectors) by value.
virtual Value::return_type const & value(const Point &p, const ElementAccessor< spacedim > &elm)
#define WarningOut()
Macro defining &#39;warning&#39; record of log.
Definition: logger.hh:234
#define OLD_ASSERT_EQUAL(a, b)
Definition: global_defs.h:133
std::vector< std::vector< FunctionParser > > parser_matrix_
Record type proxy class.
Definition: type_record.hh:171
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)
#define FLOW123D_FORCE_LINK_IN_CHILD(x)
Definition: global_defs.h:180
string address_string() const
Definition: accessors.cc:176