Flow123d  jenkins-Flow123d-windows32-release-multijob-51
field.hh
Go to the documentation of this file.
1 /*
2  * field.hh
3  *
4  * Created on: Feb 13, 2014
5  * Author: jb
6  */
7 
8 #ifndef FIELD_HH_
9 #define FIELD_HH_
10 
11 #include <memory>
12 using namespace std;
13 
14 #include <boost/circular_buffer.hpp>
15 
16 #include "system/exceptions.hh"
17 #include "input/accessors.hh"
18 #include "coupling/time_marks.hh"
20 
21 #include "fields/field_common.hh"
23 #include "fields/field_flag.hh"
24 #include "io/output_time.hh"
25 
26 
27 namespace IT=Input::Type;
28 
29 /**
30  * @brief Class template representing a field with values dependent on: point, element, and region.
31  *
32  * By "field" we mean a mapping of a a pair (Point, Time) to a @p Value, where
33  * Point is from @p spacedim dimensional ambient space, Time is real number (set by @p set_time method),
34  * and @p Value type representing range of the field, which can be: real scalar, integer scalar (a discrete value),
35  * real vector of fixed (compile time) size, real vector of runtime size, or a matrix of fixed dimensions.
36  * Extensions to vectors or matrices of integers, or to variable tensors are possible. For vector and matrix values
37  * we use classes provided by Armadillo library for linear algebra.
38  *
39  * This class assign particular fields (instances of descendants of FiledBase) to the regions. It keeps a table of pointers to fields for every possible bulk
40  * region index (very same functionality, but for boundary regions is provided by @p BCField class). This class has interface very similar to FiledBase, however
41  * key methods @p value, and @p value_list are not virtual in this class by contrast these methods are inlined to minimize overhead for
42  * simplest fields like FieldConstant.
43  *
44  * TODO: currently it works only for spacedim==3 since we have only mesh in 3D ambient space.
45  *
46  */
47 template<int spacedim, class Value>
48 class Field : public FieldCommon {
49 public:
50 
52  typedef std::shared_ptr< FieldBaseType > FieldBasePtr;
54 
55  static constexpr bool is_enum_valued = boost::is_same<typename Value::element_type, FieldEnum>::value;
56  static const unsigned int space_dim = spacedim;
57 
58 
59  /**
60  * Pointer to function that creates an instance of FieldBase for
61  * field with name @p field_name based on data in field descriptor @p rec.
62  *
63  * Default implementation in method @p read_field_descriptor just reads key given by
64  * @p field_name and creates instance using @p FieldBase<...>::function_factory.
65  * Function should return empty SharedField (that is shared_ptr to FieldBase).
66  *
67  * Hooks are necessary to implement:
68  * 1) backward compatibility with old BCD input files
69  * 2) setting pressure values are piezometric head values
70  */
71  FieldBasePtr (*read_field_descriptor_hook)(Input::Record rec, const FieldCommon &field);
72 
73  /**
74  * Default constructor.
75  *
76  */
77  Field();
78 
79  Field(const string &name, bool bc = false);
80 
81  /**
82  * Copy constructor. Keeps shared history, declaration data, mesh.
83  */
84  Field(const Field &other);
85 
86  /**
87  * Assignment operator. Same properties as copy constructor.
88  *
89  * Question: do we really need this, isn't copy constructor enough?
90  */
91  Field &operator=(const Field &other);
92 
93 
94  /**
95  * Returns reference to input type of particular field instance, this is static member @p input_type of the corresponding FieldBase class
96  * (i.e. with same template parameters). However, for fields returning "Enum" we have to create whole unique Input::Type hierarchy using following method
97  * @p meka_input_tree.
98  * every instance since every such field use different Selection for initialization, even if all returns just unsigned int.
99  */
100  IT::AbstractRecord &get_input_type() override;
101 
102 
103  /**
104  * By this method you can allow that the field need not to be set on regions (and times) where the given @p control_field is
105  * FieldConstant and has value in given @p value_list. We check this in the set_time method. Through this mechanism we
106  * can switch of e.g. boundary data fields according to the type of the boundary condition.
107  */
108  auto disable_where(
109  const Field<spacedim, typename FieldValue<spacedim>::Enum > &control_field,
110  const vector<FieldEnum> &value_list) -> Field &;
111 
112 
113 
114  /**
115  * Set mesh pointer and resize region arrays.
116  *
117  * Implements abstract method.
118  */
119  void set_mesh(const Mesh &mesh) override;
120 
121 
122  /**
123  * Direct read access to the table of Field pointers on regions.
124  */
125  //boost::shared_ptr< FieldBaseType > operator[] (Region reg);
126 
127  /**
128  * Implementation of @p FieldCommonBase::is_constant().
129  */
130  bool is_constant(Region reg) override;
131 
132 
133  /**
134  * Assigns given @p field to all regions in given region set @p domain.
135  * Field is added to the history with given time and possibly used in the next call of the set_time method.
136  * Caller is responsible for correct construction of given field.
137  *
138  * Use this method only if necessary.
139  *
140  * Default time simplify setting steady fields.
141  */
142  void set_field(const RegionSet &domain, FieldBasePtr field, double time=0.0);
143 
144  /**
145  * Same as before but the field is first created using FieldBase::function_factory(), from
146  * given abstract record accessor @p a_rec.
147  */
148  void set_field(const RegionSet &domain, const Input::AbstractRecord &a_rec, double time=0.0);
149 
150  /**
151  * Default implementation of @p read_field_descriptor_hook.
152  *
153  * Reads key given by @p field_name and creates the field instance using
154  * @p FieldBase<...>::function_factory.
155  */
156  static FieldBasePtr read_field_descriptor(Input::Record rec, const FieldCommon &field);
157 
158  void set_limit_side(LimitSide side) override
159  { this->limit_side_=side; }
160 
161  /**
162  * Check that whole field list is set, possibly use default values for unset regions
163  * and call set_time for every field in the field list.
164  *
165  * Returns true if the field has been changed.
166  */
167  bool set_time(const TimeGovernor &time) override;
168 
169  /**
170  * Check that other has same type and assign from it.
171  */
172  void copy_from(const FieldCommon & other) override;
173 
174  /**
175  * Implementation of FieldCommonBase::output().
176  */
177  void output(OutputTime *stream) override;
178 
179 
180  /**
181  * Returns true, if field is currently set to a time in which it is discontinuous.
182  */
183  //bool is_jump_time();
184 
185 
186  /**
187  * Special field values spatially constant. Could allow optimization of tensor multiplication and
188  * tensor or vector addition. field_result_ should be set in constructor and in set_time method of particular Field implementation.
189  * We return value @p result_none, if the field is not initialized on the region of the given element accessor @p elm.
190  */
191  inline FieldResult field_result( ElementAccessor<spacedim> &elm) const;
192 
193  /**
194  * Returns one value in one given point @p on an element given by ElementAccessor @p elm.
195  * It returns reference to he actual value in order to avoid temporaries for vector and tensor values.
196  */
197  virtual typename Value::return_type const &value(const Point &p, const ElementAccessor<spacedim> &elm) const;
198 
199  /**
200  * Returns std::vector of scalar values in several points at once. The base class implements
201  * trivial implementation using the @p value(,,) method. This is not optimal as it involves lot of virtual calls,
202  * but this overhead can be negligible for more complex fields as Python of Formula.
203  */
204  virtual void value_list(const std::vector< Point > &point_list, const ElementAccessor<spacedim> &elm,
205  std::vector<typename Value::return_type> &value_list) const;
206 
207 protected:
208  /**
209  * For fields returning "enum", i.e. with @p Value == FieldEnum, the input type (meaning whole input_Type tree of the field) depends on the
210  * Input::Type::Selection object that represents particular C enum type. Therefore, we have to create whole tree for the selection
211  * that was set through @p FieldBaseCommon::set_selection() method.
212  */
213  IT::AbstractRecord make_input_tree();
214 
215 
216 
217 
218  /**
219  * Read input into @p regions_history_ possibly pop some old values from the
220  * history queue to keep its size less then @p history_length_limit_.
221  */
222  void update_history(const TimeGovernor &time);
223 
224 
225 
226  /**
227  * Check that whole field list (@p region_fields_) is set, possibly use default values for unset regions.
228  */
229  void check_initialized_region_fields_();
230 
231  /**************** Shared data **************/
232 
233  /// Pair: time, pointer to FieldBase instance
234  typedef pair<double, FieldBasePtr> HistoryPoint;
235  /// Nearest history of one region.
236  typedef boost::circular_buffer<HistoryPoint> RegionHistory;
237 
238  struct SharedData {
239 
240  /**
241  * History for every region. Shared among copies.
242  */
244  };
245 
246  /**************** Data per copy **************/
247 
248  std::shared_ptr<SharedData> data_;
249 
250  /**
251  * If this pointer is set, turn off check of initialization in the
252  * @p set_time method on the regions where the method @p get_constant_enum_value
253  * of the control field returns value from @p no_check_values_. This
254  * field is private copy, its set_time method is called from the
255  * set_Time method of actual object.
256  */
258  std::shared_ptr<ControlField> no_check_control_field_;
259 
260  /**
261  * Table with pointers to fields on individual regions.
262  */
264 
265 
266 
267 };
268 
269 
270 
271 
272 
273 /**
274  * Same as Field<...> but for boundary regions.
275  */
276 template<int spacedim, class Value>
277 class BCField : public Field<spacedim, Value> {
278 public:
279  BCField() : Field<spacedim,Value>("anonymous_bc", true) {}
280 };
281 
282 
283 
284 
285 /**
286  * @brief Class for representation of a vector of fields of the same physical quantity.
287  *
288  * When solving a system of same equations with the number of components given at runtime
289  * (as in the case of transport equation for runtime given number of substances) we need means how to work with the whole
290  * vector of fields at once. This is the aim of this class. It provides the interface given by the parent class @p FieldCommonBase,
291  * but principally it is just a vector of Field<Value,dim> objects. The sub-fields or components of a @p MultiField are independent
292  * objects, how ever the setters propagates the values from the MultiFields to the individual fields. The only exception is the
293  * @p set_name method which in conjunction with @p MultiField::set_subfield_names can set unique name to each component.
294  *
295  * Template parameters are used for every subfield.
296  *
297  * TODO:
298  * - general mechanism how to convert a Field< dim, Vector> to MultiField< dim, Value>
299  * - implement set_from_input
300  * - implement set_Time
301  * - implement set_complemented_vector_field
302  *
303  * - problem with "input" methods, since Field works with AbstratRecord, the MultiField - However - should use Array of AbstractRecords
304  * simplest solution - test that in EqDataBase and have more methods in FieldCommonBase, or somehow detach input handling from
305  * Fields
306  *
307  */
308 template<int spacedim, class Value>
309 class MultiField : public FieldCommon {
310 public:
311  //typedef FieldBase<spacedim, Value> SubFieldBaseType;
314 
315  /**
316  * Default constructor.
317  */
318  MultiField();
319 
320  /**
321  * Returns input type of particular field instance, this is usually static member input_type of the corresponding FieldBase class (
322  * with same template parameters), however, for fields returning "Enum" we have to create whole unique Input::Type hierarchy for
323  * every instance since every such field use different Selection for initialization, even if all returns just unsigned int.
324  */
325  IT::AbstractRecord &get_input_type() override;
326 
327  void set_limit_side(LimitSide side) override;
328 
329  /**
330  * Abstract method to update field to the new time level.
331  * Implemented by in class template Field<...>.
332  *
333  * Return true if the value of the field was changed on some region.
334  * The returned value is also stored in @p changed_during_set_time data member.
335  */
336  bool set_time(const TimeGovernor &time) override;
337 
338  /**
339  * We have to override the @p set_mesh method in order to call set_mesh method for subfields.
340  */
341  void set_mesh(const Mesh &mesh) override;
342 
343 
344  /**
345  * Polymorphic copy. Check correct type, allows copy of MultiField or Field.
346  */
347  void copy_from(const FieldCommon & other) override;
348 
349  /**
350  * Implementation of @p FieldCommonBase::output().
351  */
352  void output(OutputTime *stream) override;
353 
354  /**
355  * Implementation of @p FieldCommonBase::is_constant().
356  */
357  bool is_constant(Region reg) override;
358 
359  /**
360  * Virtual destructor.
361  */
362  inline virtual ~MultiField() {}
363 
364  /// Number of subfields that compose the multi-field.
365  inline unsigned int size() const
366  { return sub_fields_.size(); }
367 
368  /**
369  * Initialize MultiField to the number of components given by the size of @p names
370  * and use this vector to name individual components. Should be called after the setters derived from
371  * FieldCommonBase.
372  */
373  void init( const vector<string> &names);
374 
375  /**
376  * Allows set Field<dim, Vector> that can be used for alternative initialization in "transposed" form.
377  */
378  void set_complemented_vector_field( TransposedField &complemented);
379 
380  /**
381  * Returns reference to the sub-field (component) of given index @p idx.
382  */
383  inline SubFieldType &operator[](unsigned int idx)
384  { return sub_fields_[idx]; }
385 
386 private:
389 };
390 
391 
392 
393 
394 /****************************************************************************************
395  * Inlined methods of Field< ... >
396  */
397 
398 template<int spacedim, class Value>
399 inline typename Value::return_type const & Field<spacedim,Value>::value(const Point &p, const ElementAccessor<spacedim> &elm) const
400 {
401 
402  ASSERT(this->set_time_result_ != TimeStatus::unknown, "Unknown time status.\n");
403  ASSERT(elm.region_idx().idx() < region_fields_.size(), "Region idx %u out of range %lu, field: %s\n",
404  elm.region_idx().idx(), (unsigned long int) region_fields_.size(), name().c_str());
405  ASSERT( region_fields_[elm.region_idx().idx()] ,
406  "Null field ptr on region id: %d, idx: %d, field: %s\n", elm.region().id(), elm.region_idx().idx(), name().c_str());
407  return region_fields_[elm.region_idx().idx()]->value(p,elm);
408 }
409 
410 
411 
412 template<int spacedim, class Value>
415 {
416  ASSERT(this->set_time_result_ != TimeStatus::unknown, "Unknown time status.\n");
417  ASSERT(elm.region_idx().idx() < region_fields_.size(), "Region idx %u out of range %lu, field: %s\n",
418  elm.region_idx().idx(), (unsigned long int) region_fields_.size(), name().c_str());
419  ASSERT( region_fields_[elm.region_idx().idx()] ,
420  "Null field ptr on region id: %d, field: %s\n", elm.region().id(), name().c_str());
421 
422  region_fields_[elm.region_idx().idx()]->value_list(point_list,elm, value_list);
423 }
424 
425 
426 
427 
428 
429 
430 
431 #endif /* FIELD_HH_ */
std::vector< std::string > sub_names_
Definition: field.hh:388
Common abstract parent of all Field<...> classes.
Definition: field_common.hh:45
pair< double, FieldBasePtr > HistoryPoint
Pair: time, pointer to FieldBase instance.
Definition: field.hh:234
unsigned int size() const
Number of subfields that compose the multi-field.
Definition: field.hh:365
void set_limit_side(LimitSide side) override
Definition: field.hh:158
Class template representing a field with values dependent on: point, element, and region...
Definition: field.hh:48
Field< spacedim, Value > SubFieldType
Definition: field.hh:312
Definition: mesh.h:108
Basic time management functionality for unsteady (and steady) solvers (class Equation).
virtual void value_list(const std::vector< Point > &point_list, const ElementAccessor< spacedim > &elm, std::vector< typename Value::return_type > &value_list) const
Definition: field.hh:413
Basic time management class.
std::shared_ptr< SharedData > data_
Definition: field.hh:248
#define ASSERT(...)
Definition: global_defs.h:121
std::vector< SubFieldType > sub_fields_
Definition: field.hh:387
Accessor to the data with type Type::Record.
Definition: accessors.hh:308
FieldAlgorithmBase< spacedim, Value >::Point Point
Definition: field.hh:53
std::shared_ptr< ControlField > no_check_control_field_
Definition: field.hh:258
Class for declaration of polymorphic Record.
Definition: type_record.hh:463
virtual Value::return_type const & value(const Point &p, const ElementAccessor< spacedim > &elm) const
Definition: field.hh:399
The class for outputing data during time.
Definition: output_time.hh:37
Space< spacedim >::Point Point
Field< spacedim, typename FieldValue< spacedim >::Vector > TransposedField
Definition: field.hh:313
std::vector< FieldBasePtr > region_fields_
Definition: field.hh:263
Accessor to the polymorphic input data of a type given by an AbstracRecord object.
Definition: accessors.hh:423
Region region() const
Definition: accessors.hh:88
FieldResult
Result type have sense only for larger Value types like vectors and tensors.
std::shared_ptr< FieldBaseType > FieldBasePtr
Definition: field.hh:52
FieldAlgorithmBase< spacedim, Value > FieldBaseType
Definition: field.hh:51
boost::circular_buffer< HistoryPoint > RegionHistory
Nearest history of one region.
Definition: field.hh:236
virtual ~MultiField()
Definition: field.hh:362
RegionIdx region_idx() const
Definition: accessors.hh:91
Field< spacedim, typename FieldValue< spacedim >::Enum > ControlField
Definition: field.hh:257
Class for representation of a vector of fields of the same physical quantity.
Definition: field.hh:309
BCField()
Definition: field.hh:279
SubFieldType & operator[](unsigned int idx)
Definition: field.hh:383
LimitSide
Definition: field_common.hh:31
unsigned int id() const
Returns id of the region (using RegionDB)
Definition: region.cc:28
unsigned int idx() const
Returns a global index of the region.
Definition: region.hh:71
std::vector< RegionHistory > region_history_
Definition: field.hh:243