Flow123d  last_with_con_2.0.0-4-g42e6930
field_values.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_values.hh
15  * @brief
16  */
17 
18 #ifndef FIELD_VALUES_HH_
19 #define FIELD_VALUES_HH_
20 
21 #include <armadillo>
22 #include <boost/format.hpp>
23 #include <system/exceptions.hh>
24 #include "input/input_type.hh"
25 #include "input/accessors.hh"
26 #include <ostream>
27 #include <cmath>
28 
29 namespace IT=Input::Type;
30 
31 /**
32  * @file
33  *
34  * This file contains various dispatch classes to simplify implementation of Fields. Essential is class template
35  * @p FieldValues_ which provides unified access and initialization to scalar, vector and matrix type object in Armadillo library
36  */
37 
38 TYPEDEF_ERR_INFO( EI_InputMsg, const string );
39 DECLARE_INPUT_EXCEPTION( ExcFV_Input, << "Wrong field value input: " << EI_InputMsg::val );
40 
41 typedef unsigned int FieldEnum;
42 
43 
44 
45 namespace internal {
46 
47 // Helper functions to get scalar type name
48 std::string type_name_(double);
49 std::string type_name_(int);
50 std::string type_name_(FieldEnum);
51 
52 
53 /**
54  * InputType dispatch from elementary type @p ET of FieldValues_ to elementary Input::Type, i.e. descendant of Input::Type::Scalar.
55  */
56 template <class ET>
57 struct InputType { typedef Input::Type::Double type; };
58 
59 template <>
60 struct InputType<int> { typedef Input::Type::Integer type; };
61 
62 template <>
64 
65 
66 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
67 // resolution of Value::return_type
68 
69 // general element type
70 template<int NRows, int NCols, class ET>
71 struct ReturnType { typedef typename arma::Mat<ET>::template fixed<NRows, NCols> return_type; };
72 
73 template<class ET>
74 struct ReturnType<1,1,ET> { typedef ET return_type; };
75 
76 template <class ET>
77 struct ReturnType<0,1,ET> { typedef arma::Col<ET> return_type; };
78 
79 template <int NRows, class ET>
80 struct ReturnType<NRows,1,ET> { typedef typename arma::Col<ET>::template fixed<NRows> return_type; };
81 
82 
83 // FiledEnum element type - this just returns types with ET=unsigned int, however input should be different
84 template<int NRows, int NCols>
85 struct ReturnType<NRows, NCols, FieldEnum> { typedef typename arma::Mat<unsigned int>::template fixed<NRows, NCols> return_type; };
86 
87 template<>
88 struct ReturnType<1,1, FieldEnum> { typedef unsigned int return_type; };
89 
90 template <>
91 struct ReturnType<0,1, FieldEnum> { typedef arma::Col<unsigned int> return_type; };
92 
93 template <int NRows>
94 struct ReturnType<NRows,1, FieldEnum> { typedef typename arma::Col<unsigned int>::template fixed<NRows> return_type; };
95 
96 
97 // Resolution of helper functions for raw constructor
98 template <class RT> inline RT & set_raw_scalar(RT &val, double *raw_data) { return *raw_data;}
99 template <class RT> inline RT & set_raw_scalar(RT &val, int *raw_data) { return *raw_data;}
100 template <class RT> inline RT & set_raw_scalar(RT &val, FieldEnum *raw_data) { return *raw_data;}
101 
102 template <class RT> inline RT & set_raw_vec(RT &val, double *raw_data) { arma::access::rw(val.mem) = raw_data; return val;}
103 template <class RT> inline RT & set_raw_vec(RT &val, int *raw_data) { arma::access::rw(val.mem) = raw_data; return val;}
104 template <class RT> inline RT & set_raw_vec(RT &val, FieldEnum *raw_data) { arma::access::rw(val.mem) = raw_data; return val;}
105 
106 template <class RT> inline RT & set_raw_fix(RT &val, double *raw_data) { val = RT(raw_data); return val;}
107 template <class RT> inline RT & set_raw_fix(RT &val, int *raw_data) { val = RT(raw_data); return val;}
108 template <class RT> inline RT & set_raw_fix(RT &val, FieldEnum *raw_data) { val = RT(raw_data); return val;}
109 
110 
111 
112 // Resolution of input accessor for vector values of enums,
113 template <class ET>
114 struct AccessTypeDispatch { typedef ET type;};
115 template <>
116 struct AccessTypeDispatch<unsigned int> { typedef Input::Enum type; };
117 
118 
119 
120 
121 /**
122  * Initialize an Armadillo matrix from the input.
123  * Since only limited methods are used we can use this template to initialize StringTensor as well.
124  * Used methodas are: at(row,col), zeros()
125  */
126 template<class MatrixType>
127 void init_matrix_from_input( MatrixType &value, Input::Array rec ) {
128  typedef typename MatrixType::elem_type ET;
129  unsigned int nrows = value.n_rows;
130  unsigned int ncols = value.n_cols;
131 
133  if (it->size() == 1 && nrows == ncols) {
134  // square tensor
135  // input = 3 expands to [ [ 3 ] ]; init to 3 * (identity matrix)
136  // input = [1, 2, 3] expands to [[1], [2], [3]]; init to diag. matrix
137  // input = [1, 2, 3, .. , (N+1)*N/2], .... ; init to symmetric matrix [ [1 ,2 ,3], [2, 4, 5], [ 3, 5, 6] ]
138  if (rec.size() == 1) {// scalar times identity
139  value.zeros();
140  ET scalar=*(it->begin<ET>());
141  for(unsigned int i=0; i< nrows; i++) value.at(i,i)=scalar;
142  } else if (rec.size() == nrows) { // diagonal vector
143  value.zeros();
144  for(unsigned int i=0; i< nrows; i++, ++it) value.at(i,i)=*(it->begin<ET>());
145  } else if (rec.size() == (nrows+1)*nrows/2) { // symmetric part
146  for( unsigned int row=0; row<nrows; row++)
147  for( unsigned int col=0; col<ncols; col++)
148  if (row <= col) {
149  value.at(row,col) = *(it->begin<ET>());
150  ++it;
151  } else value.at(row,col) = value.at(col,row);
152  } else {
153  THROW( ExcFV_Input()
154  << EI_InputMsg(
155  boost::str(boost::format("Initializing symmetric matrix %dx%d by vector of wrong size %d, should be 1, %d, or %d.")
156  % nrows % ncols % rec.size() % nrows % ((nrows+1)*nrows/2)))
157  << rec.ei_address()
158 
159  );
160  }
161 
162  } else {
163  // accept only full tensor
164  if (rec.size() == nrows && it->size() == ncols) {
165 
166  for (unsigned int row = 0; row < nrows; row++, ++it) {
167  if (it->size() != ncols)
168  THROW( ExcFV_Input() << EI_InputMsg("Wrong number of columns.")
169  << rec.ei_address());
170  Input::Iterator<ET> col_it = it->begin<ET>();
171  for (unsigned int col = 0; col < ncols; col++, ++col_it)
172  value.at(row, col) = *col_it;
173  }
174  } else {
175  THROW( ExcFV_Input()
176  << EI_InputMsg(
177  boost::str(boost::format("Initializing matrix %dx%d by matrix of wrong size %dx%d.")
178  % nrows % ncols % rec.size() % it->size() ))
179  << rec.ei_address()
180  );
181  }
182  }
183 }
184 
185 /**
186  * Initialize an Armadillo vector from the input.
187  * Since only limited methods are used we can use this template to initialize StringTensor as well.
188  * Used methodas are: at(row,col), zeros()
189  */
190 template<class VectorType>
191 void init_vector_from_input( VectorType &value, Input::Array rec ) {
192  typedef typename VectorType::elem_type ET;
193  unsigned int nrows = value.n_rows;
194 
195  typedef typename AccessTypeDispatch<ET>::type InnerType;
196  Input::Iterator<InnerType> it = rec.begin<InnerType>();
197 
198  if ( rec.size() == 1 ) {
199  for(unsigned int i=0; i< nrows; i++)
200  value.at(i)=ET(*it);
201  } else if ( rec.size() == nrows ) {
202  for(unsigned int i=0; i< nrows; i++, ++it) {
203  value.at(i)=ET(*it);
204  }
205  } else {
206  THROW( ExcFV_Input()
207  << EI_InputMsg(
208  boost::str(boost::format("Initializing vector of size %d by vector of size %d.")
209  % nrows % rec.size() ))
210  << rec.ei_address()
211  );
212  }
213 }
214 
215 
216 
217 } // namespace internal
218 
219 
220 
221 /**
222  * Template for class representing all possible Filed values. It is just common interface to
223  * scalar (double, int) values, vector and tensor values with fixed size and vector/tensor values with variable size.
224  *
225  * ET is type of elements, n_cols and n_rows gives fixed dimensions of the tensor value (nx1 is vector, 1x1 is scalar,
226  * 0x1 is variable size vector, 0x0 is variable size tensor (not implemented yet) )
227  *
228  *
229  */
230 template <int NRows, int NCols, class ET>
231 class FieldValue_ {
232 public:
233  typedef ET element_type;
237  const static int NRows_ = NRows;
238  const static int NCols_ = NCols;
239 
240  static std::string type_name() { return boost::str(boost::format("R[%d,%d]") % NRows % NCols); }
242  if (NRows == NCols) {
243  // for square tensors allow initialization by diagonal vector, etc.
244  return IT::Array( IT::Array( IT::Parameter("element_input_type"), 1), 1 );
245  }
246  else {
247  return IT::Array( IT::Array( IT::Parameter("element_input_type"), NCols, NCols), NRows, NRows );
248  }
249 
250  }
251 
252 
253  inline FieldValue_(return_type &val) : value_(val) {}
254  inline static const return_type &from_raw(return_type &val, ET *raw_data) {return internal::set_raw_fix(val, raw_data);}
255  const ET * mem_ptr() { return value_.memptr(); }
256 
257  void init_from_input( AccessType rec ) {
259  }
260 
261  void set_n_comp(unsigned int) {};
262  inline unsigned int n_cols() const
263  { return NCols; }
264  inline unsigned int n_rows() const
265  { return NRows; }
266  inline ET &operator() ( unsigned int i, unsigned int j)
267  { return value_.at(i,j); }
268  inline ET operator() ( unsigned int i, unsigned int j) const
269  { return value_.at(i,j); }
270  inline operator return_type() const
271  { return value_;}
272 
273  // Set value to matrix of zeros.
274  void zeros() {
275  value_.zeros();
276  }
277  // Set value to identity matrix.
278  void eye() {
279  value_.eye();
280  }
281  // Set value to matrix of ones.
282  void ones() {
283  value_.ones();
284  }
285  // Elementwise equivalence.
286  bool equal_to(const return_type &other) {
287  return arma::max(arma::max(arma::abs(value_ - other))) < 4*std::numeric_limits<ET>::epsilon();
288  }
289 
290 private:
291  return_type &value_;
292 };
293 
294 
295 
296 
297 
298 /// **********************************************************************
299 /// Specialization for scalars
300 template <class ET>
301 class FieldValue_<1,1,ET> {
302 public:
303  typedef ET element_type;
307  const static int NRows_ = 1;
308  const static int NCols_ = 1;
309 
310  static std::string type_name() { return "R"; }
312  {
313  return IT::Parameter("element_input_type");
314  }
315 
316  inline FieldValue_(return_type &val) : value_(val) {}
317 
318  /**
319  * Returns reference to the return_type (i.e. double, or arma::vec or arma::mat); with data provided by the parameter @p raw_data.
320  * A reference to a work space @p val has to be provided for efficient work with vector and matrix values.
321  */
322  inline static const return_type &from_raw(return_type &val, ET *raw_data) {return internal::set_raw_scalar(val, raw_data);}
323  const ET * mem_ptr() { return &(value_); }
324 
325  void init_from_input( AccessType val ) { value_ = return_type(val); }
326 
327  void set_n_comp(unsigned int) {};
328  inline unsigned int n_cols() const
329  { return 1; }
330  inline unsigned int n_rows() const
331  { return 1; }
332  inline ET &operator() ( unsigned int, unsigned int )
333  { return value_; }
334  inline ET operator() ( unsigned int i, unsigned int j) const
335  { return value_; }
336  inline operator return_type() const
337  { return value_;}
338 
339  // Set value to matrix of zeros.
340  void zeros() {
341  value_=0;
342  }
343  // Set value to identity matrix.
344  void eye() {
345  value_=1;
346  }
347  // Set value to matrix of ones.
348  void ones() {
349  value_=1;
350  }
351  bool equal_to(const return_type &other) {
352  return std::abs(value_ - other) < 4*std::numeric_limits<ET>::epsilon();
353  }
354 
355 private:
356  return_type &value_;
357 };
358 
359 
360 
361 
362 /// **********************************************************************
363 /// Specialization for variable size vectors
364 template <class ET>
365 class FieldValue_<0,1,ET> {
366 public:
367  typedef ET element_type;
371  const static int NRows_ = 0;
372  const static int NCols_ = 1;
373 
374 
375  static std::string type_name() { return "R[n]"; }
377  return IT::Array( IT::Parameter("element_input_type"), 1);
378  }
379  inline static const return_type &from_raw(return_type &val, ET *raw_data) {return internal::set_raw_vec(val, raw_data);}
380  const ET * mem_ptr() { return value_.memptr(); }
381 
382  inline FieldValue_(return_type &val) : value_(val) {}
383 
384 
385  void init_from_input( AccessType rec ) {
387  }
388 
389  void set_n_comp(unsigned int n_comp) { value_ = return_type(n_comp,1); };
390  inline unsigned int n_cols() const
391  { return 1; }
392  inline unsigned int n_rows() const
393  { return value_.n_rows; }
394  inline ET &operator() ( unsigned int i, unsigned int )
395  { return value_.at(i); }
396  inline ET operator() ( unsigned int i, unsigned int j) const
397  { return value_.at(i); }
398 
399  inline operator return_type() const
400  { return value_;}
401 
402  // Set value to matrix of zeros.
403  void zeros() {
404  value_.zeros();
405  }
406  // Set value to identity matrix.
407  void eye() {
408  value_.ones();
409  }
410  // Set value to matrix of ones.
411  void ones() {
412  value_.ones();
413  }
414  // Elementwise equivalence.
415  bool equal_to(const return_type &other) {
416  return arma::max(arma::abs(value_ - other)) < 4*std::numeric_limits<ET>::epsilon();
417  }
418 
419 
420 private:
421  return_type &value_;
422 };
423 
424 /// **********************************************************************
425 /// Specialization for fixed size vectors
426 template <int NRows, class ET>
427 class FieldValue_<NRows,1,ET> {
428 public:
429  typedef ET element_type;
433  const static int NRows_ = NRows;
434  const static int NCols_ = 1;
435 
436 
437  static std::string type_name() { return boost::str(boost::format("R[%d]") % NRows ); }
439  return IT::Array( IT::Parameter("element_input_type"), 1, NRows);
440  }
441 
442  inline FieldValue_(return_type &val) : value_(val) {}
443  inline static const return_type &from_raw(return_type &val, ET *raw_data) {return internal::set_raw_fix(val, raw_data);}
444  const ET * mem_ptr() { return value_.memptr(); }
445 
446  void init_from_input( AccessType rec ) {
448  }
449 
450  void set_n_comp(unsigned int) {};
451  inline unsigned int n_cols() const
452  { return 1; }
453  inline unsigned int n_rows() const
454  { return NRows; }
455  inline ET &operator() ( unsigned int i, unsigned int )
456  { return value_.at(i); }
457  inline ET operator() ( unsigned int i, unsigned int j) const
458  { return value_.at(i); }
459 
460  inline operator return_type() const
461  { return value_;}
462 
463  // Set value to matrix of zeros.
464  void zeros() {
465  value_.zeros();
466  }
467  // Set value to identity matrix.
468  void eye() {
469  value_.ones();
470  }
471  // Set value to matrix of ones.
472  void ones() {
473  value_.ones();
474  }
475  // Elementwise equivalence.
476  bool equal_to(const return_type &other) {
477  return arma::max(arma::abs(value_ - other)) < 4*std::numeric_limits<ET>::epsilon();
478  }
479 
480 private:
481  return_type &value_;
482 };
483 
484 
485 
486 //****************************************************************************
487 // string tensor (for FieldFormula)
488 
489 
490 /**
491  * Mimics arma::mat<std::string>. Used in FieldFormula
492  */
494 public:
495  typedef std::string elem_type;
496 
497  StringTensor( unsigned int n_rows, unsigned int n_cols )
498  : n_rows(n_rows),n_cols(n_cols), values_(n_rows*n_cols) {}
499 
500  std::string & at(unsigned int row) { return at(row,0); }
501  std::string & at(unsigned int row, unsigned int col) { return values_[col*n_rows+row]; }
502 
503  void zeros() {
504  for( auto &elem: values_) elem = "0.0";
505  }
506  unsigned int n_rows;
507  unsigned int n_cols;
508 private:
510 
511 };
512 
513 
514 template<int NRows, int NCols>
516 {
519  if (NRows == NCols) {
520  // for square tensors allow initialization by diagonal vector, etc.
521  return IT::Array( IT::Array( IT::String(), 1), 1 );
522  }
523  else {
524  return IT::Array( IT::Array( IT::String(), NCols, NCols), NRows, NRows );
525  }
526 
527  }
528 
529  static void init_from_input(StringTensor &tensor, AccessType input) {
530  internal::init_matrix_from_input(tensor, input);
531  }
532 };
533 
534 template<>
535 struct StringTensorInput<1,1> {
536  typedef std::string AccessType;
537  static IT::String get_input_type() { return IT::String(); }
538  static void init_from_input(StringTensor &tensor, AccessType input) {
539  tensor.at(0,0) = input;
540  }
541 };
542 
543 template<int Nrows>
544 struct StringTensorInput<Nrows,1> {
547  return IT::Array( IT::String(), 1);
548  }
549  static void init_from_input(StringTensor &tensor, AccessType input) {
550  internal::init_vector_from_input(tensor, input);
551  }
552 };
553 
554 
555 
556 
557 /**
558  * Class that provides common template-less interface to all templated Field structes.
559  *
560  * Maybe we can delete this since common interface will be given by "Quantity".
561  */
562 
563 template <int spacedim>
564 struct FieldValue {
565  // typedefs for possible field values
574 };
575 
576 
577 
578 
579 
580 
581 
582 
583 
584 
585 #endif /* FIELD_VALUES_HH_ */
void init_from_input(AccessType val)
internal::ReturnType< 1, 1, ET >::return_type return_type
Iterator< ValueType > begin() const
internal::InputType< ET >::type ElementInputType
Accessor to input data conforming to declared Array.
Definition: accessors.hh:552
static const return_type & from_raw(return_type &val, ET *raw_data)
static IT::Array get_input_type()
EI_Address ei_address() const
Definition: accessors.cc:306
void set_n_comp(unsigned int)
arma::Col< unsigned int > return_type
Definition: field_values.hh:91
std::vector< std::string > values_
static void init_from_input(StringTensor &tensor, AccessType input)
internal::InputType< ET >::type ElementInputType
static void init_from_input(StringTensor &tensor, AccessType input)
bool equal_to(const return_type &other)
FieldValue_< 0, 1, int > IntVector
static const return_type & from_raw(return_type &val, ET *raw_data)
void set_n_comp(unsigned int n_comp)
std::string format(CStringRef format_str, ArgList args)
Definition: format.h:3141
void set_n_comp(unsigned int)
void init_from_input(AccessType rec)
Class for representing parametric types in IST.
Definition: type_generic.hh:52
static std::string type_name()
RT & set_raw_vec(RT &val, double *raw_data)
void set_n_comp(unsigned int)
unsigned int n_cols() const
const ET * mem_ptr()
internal::ReturnType< NRows, NCols, ET >::return_type return_type
FieldValue_(return_type &val)
void init_from_input(AccessType rec)
Input::Type::Selection type
Definition: field_values.hh:63
FieldValue_< 1, 1, FieldEnum > Enum
Class for declaration of the integral input data.
Definition: type_base.hh:465
void init_matrix_from_input(MatrixType &value, Input::Array rec)
void init_from_input(AccessType rec)
Class for declaration of inputs sequences.
Definition: type_base.hh:321
arma::Col< unsigned int >::template fixed< NRows > return_type
Definition: field_values.hh:94
StringTensor(unsigned int n_rows, unsigned int n_cols)
internal::InputType< ET >::type ElementInputType
static IT::Array get_input_type()
Class for declaration of the input data that are floating point numbers.
Definition: type_base.hh:518
static std::string type_name()
FieldValue_< 0, 1, FieldEnum > EnumVector
std::string elem_type
unsigned int FieldEnum
Definition: field_values.hh:41
unsigned int n_rows
internal::InputType< ET >::type ElementInputType
internal::ReturnType< NRows, 1, ET >::return_type return_type
bool equal_to(const return_type &other)
return_type & value_
std::string & at(unsigned int row, unsigned int col)
FieldValue_< spacedim, 1, double > VectorFixed
bool equal_to(const return_type &other)
static IT::Array get_input_type()
void init_vector_from_input(VectorType &value, Input::Array rec)
static std::string type_name()
unsigned int n_rows() const
RT & set_raw_fix(RT &val, double *raw_data)
arma::Mat< ET >::template fixed< NRows, NCols > return_type
Definition: field_values.hh:71
static void init_from_input(StringTensor &tensor, AccessType input)
internal::ReturnType< 0, 1, ET >::return_type return_type
TYPEDEF_ERR_INFO(EI_InputMsg, const string)
std::string & at(unsigned int row)
const double epsilon
Definition: mathfce.h:23
unsigned int n_cols() const
static IT::Array get_input_type()
unsigned int n_rows() const
Input::Type::Integer type
Definition: field_values.hh:60
arma::Mat< unsigned int >::template fixed< NRows, NCols > return_type
Definition: field_values.hh:85
unsigned int n_cols() const
Input::Type::Double type
Definition: field_values.hh:57
unsigned int n_cols
FieldValue_< 1, 1, int > Integer
FieldValue_(return_type &val)
FieldValue_< 0, 1, double > Vector
internal::AccessTypeDispatch< ET >::type AccessType
static std::string type_name()
DECLARE_INPUT_EXCEPTION(ExcFV_Input,<< "Wrong field value input: "<< EI_InputMsg::val)
static const return_type & from_raw(return_type &val, ET *raw_data)
FieldValue_(return_type &val)
static IT::Array get_input_type()
unsigned int size() const
Input::Array AccessType
static const return_type & from_raw(return_type &val, ET *raw_data)
FieldValue_< spacedim, spacedim, double > TensorFixed
unsigned int n_rows() const
Input::Array AccessType
unsigned int n_cols() const
arma::Col< ET >::template fixed< NRows > return_type
Definition: field_values.hh:80
RT & set_raw_scalar(RT &val, double *raw_data)
Definition: field_values.hh:98
Class for declaration of the input data that are in string format.
Definition: type_base.hh:568
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:45
static IT::Parameter get_input_type()
Template for classes storing finite set of named values.
static IT::String get_input_type()
std::string type_name_(double)
Definition: field_values.cc:22
FieldValue_< 1, 1, double > Scalar
bool equal_to(const return_type &other)
FieldValue_(return_type &val)
unsigned int n_rows() const