Flow123d  jenkins-Flow123d-windows-release-multijob-285
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 "tools/time_marks.hh"
19 #include "tools/time_governor.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  * The @p Value template parameter should FieldValue<> template, usual choices are:
39  * FieldValue<spacedim>::Scalar, FieldValue<spacedim>::Integer, FieldValue<spacedim>::Enum,
40  * FieldValue<spacedim>::VectorFixed, FieldValue<spacedim>::TensorFixed
41  * deprecated choices: FieldValue<spacedim>::Vector, FieldValue<spacedim>::VectorEnum.
42  *
43  * 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
44  * region index (very same functionality, but for boundary regions is provided by @p BCField class). This class has interface very similar to FiledBase, however
45  * key methods @p value, and @p value_list are not virtual in this class by contrast these methods are inlined to minimize overhead for
46  * simplest fields like FieldConstant.
47  *
48  * TODO: currently it works only for spacedim==3 since we have only mesh in 3D ambient space.
49  *
50  */
51 template<int spacedim, class Value>
52 class Field : public FieldCommon {
53 public:
54 
56  typedef std::shared_ptr< FieldBaseType > FieldBasePtr;
58 
59  static constexpr bool is_enum_valued = boost::is_same<typename Value::element_type, FieldEnum>::value;
60  static const unsigned int space_dim = spacedim;
61 
62 
63  /**
64  * Factory class that creates an instance of FieldBase for field
65  * with name @p field_name based on data in field descriptor @p rec.
66  *
67  * Default implementation in method @p create_field just reads key given by
68  * @p field_name and creates instance using @p FieldBase<...>::function_factory.
69  * Function should return empty SharedField (that is shared_ptr to FieldBase).
70  *
71  * Implementation of these descendants is necessary:
72  * 1) for backward compatibility with old BCD input files
73  * 2) for setting pressure values are piezometric head values
74  */
75  /**
76  * Note for future:
77  * We pass through parameter @p field information about field that holds the factory which are necessary
78  * for interpreting user input and create particular field instance. It would be clearer to pass these information
79  * when the factory is assigned to a field. Moreover some information may not be set to field at all but directly passed
80  * to the factory.
81  */
82  class FactoryBase {
83  public:
84  /**
85  * Default method that creates an instance of FieldBase for field.
86  *
87  * Reads key given by @p field_name and creates the field instance using
88  * @p FieldBase<...>::function_factory.
89  */
90  virtual FieldBasePtr create_field(Input::Record rec, const FieldCommon &field);
91  };
92 
93  /**
94  * Default constructor.
95  *
96  */
97  Field();
98 
99  Field(const string &name, bool bc = false);
100 
101  /**
102  * Copy constructor. Keeps shared history, declaration data, mesh.
103  */
104  Field(const Field &other);
105 
106  /**
107  * Assignment operator. Same properties as copy constructor.
108  *
109  * Question: do we really need this, isn't copy constructor enough?
110  * Answer: It is necessary in (usual) case when Field instance is created as the class member
111  * but is filled later by assignment possibly from other class.
112  */
113  Field &operator=(const Field &other);
114 
115 
116  /**
117  * Returns reference to input type of particular field instance, this is static member @p input_type of the corresponding FieldBase class
118  * (i.e. with same template parameters). However, for fields returning "Enum" we have to create whole unique Input::Type hierarchy using following method
119  * @p meka_input_tree.
120  * every instance since every such field use different Selection for initialization, even if all returns just unsigned int.
121  */
122  IT::AbstractRecord &get_input_type() override;
123 
124  IT::Record &get_multifield_input_type() override;
125 
126 
127  /**
128  * 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
129  * FieldConstant and has value in given @p value_list. We check this in the set_time method. Through this mechanism we
130  * can switch of e.g. boundary data fields according to the type of the boundary condition.
131  */
132  auto disable_where(
133  const Field<spacedim, typename FieldValue<spacedim>::Enum > &control_field,
134  const vector<FieldEnum> &value_list) -> Field &;
135 
136 
137 
138  /**
139  * Set mesh pointer and resize region arrays.
140  *
141  * Implements abstract method.
142  */
143  void set_mesh(const Mesh &mesh) override;
144 
145 
146  /**
147  * Direct read access to the table of Field pointers on regions.
148  */
149  //boost::shared_ptr< FieldBaseType > operator[] (Region reg);
150 
151  /**
152  * Implementation of @p FieldCommonBase::is_constant().
153  */
154  bool is_constant(Region reg) override;
155 
156 
157  /**
158  * Assigns given @p field to all regions in given region set @p domain.
159  * Field is added to the history with given time and possibly used in the next call of the set_time method.
160  * Caller is responsible for correct construction of given field.
161  *
162  * Use this method only if necessary.
163  *
164  * Default time simplify setting steady fields.
165  */
166  void set_field(const RegionSet &domain, FieldBasePtr field, double time=0.0);
167 
168  /**
169  * Same as before but the field is first created using FieldBase::function_factory(), from
170  * given abstract record accessor @p a_rec.
171  */
172  void set_field(const RegionSet &domain, const Input::AbstractRecord &a_rec, double time=0.0);
173 
174  /**
175  * Check that whole field list is set, possibly use default values for unset regions
176  * and call set_time for every field in the field list.
177  *
178  * Returns true if the field has been changed.
179  */
180  bool set_time(const TimeStep &time) override;
181 
182  /**
183  * Check that other has same type and assign from it.
184  */
185  void copy_from(const FieldCommon & other) override;
186 
187  /**
188  * Implementation of FieldCommonBase::output().
189  */
190  void output(OutputTime *stream) override;
191 
192 
193  /**
194  * Returns true, if field is currently set to a time in which it is discontinuous.
195  */
196  //bool is_jump_time();
197 
198 
199  /**
200  * Special field values spatially constant. Could allow optimization of tensor multiplication and
201  * tensor or vector addition. field_result_ should be set in constructor and in set_time method of particular Field implementation.
202  * We return value @p result_none, if the field is not initialized on the region of the given element accessor @p elm.
203  */
204  inline FieldResult field_result( ElementAccessor<spacedim> &elm) const;
205 
206  /**
207  * Returns one value in one given point @p on an element given by ElementAccessor @p elm.
208  * It returns reference to he actual value in order to avoid temporaries for vector and tensor values.
209  */
210  virtual typename Value::return_type const &value(const Point &p, const ElementAccessor<spacedim> &elm) const;
211 
212  /**
213  * Returns std::vector of scalar values in several points at once. The base class implements
214  * trivial implementation using the @p value(,,) method. This is not optimal as it involves lot of virtual calls,
215  * but this overhead can be negligible for more complex fields as Python of Formula.
216  */
217  virtual void value_list(const std::vector< Point > &point_list, const ElementAccessor<spacedim> &elm,
218  std::vector<typename Value::return_type> &value_list) const;
219 
220  /**
221  * Add a new factory for creating Field algorithms on individual regions.
222  * The last factory is tried first, the last one is always the default implementation
223  * Field<...>::FactoryBase.
224  *
225  * The Field<...> object keeps a list of such factories. When the instance of a new field algorithm
226  * has to be created from the input field descriptor, we pass through the list of factories backward
227  * and let factories to create the field algorithm instance from the actual input field descriptor.
228  * The first instance (non-null pointer) is used.
229  */
230  void add_factory(std::shared_ptr<FactoryBase> factory);
231 
232 protected:
233  /**
234  * For fields returning "enum", i.e. with @p Value == FieldEnum, the input type (meaning whole input_Type tree of the field) depends on the
235  * Input::Type::Selection object that represents particular C enum type. Therefore, we have to create whole tree for the selection
236  * that was set through @p FieldBaseCommon::set_selection() method.
237  */
238  IT::AbstractRecord make_input_tree();
239 
240 
241 
242 
243  /**
244  * Read input into @p regions_history_ possibly pop some old values from the
245  * history queue to keep its size less then @p history_length_limit_.
246  */
247  void update_history(const TimeStep &time);
248 
249 
250 
251  /**
252  * Check that whole field list (@p region_fields_) is set, possibly use default values for unset regions.
253  */
254  void check_initialized_region_fields_();
255 
256  /**************** Shared data **************/
257 
258  /// Pair: time, pointer to FieldBase instance
259  typedef pair<double, FieldBasePtr> HistoryPoint;
260  /// Nearest history of one region.
261  typedef boost::circular_buffer<HistoryPoint> RegionHistory;
262 
263  struct SharedData {
264 
265  /**
266  * History for every region. Shared among copies.
267  */
269  };
270 
271  /**************** Data per copy **************/
272 
273  std::shared_ptr<SharedData> data_;
274 
275  /**
276  * If this pointer is set, turn off check of initialization in the
277  * @p set_time method on the regions where the method @p get_constant_enum_value
278  * of the control field returns value from @p no_check_values_. This
279  * field is private copy, its set_time method is called from the
280  * set_Time method of actual object.
281  */
283  std::shared_ptr<ControlField> no_check_control_field_;
284 
285  /**
286  * Table with pointers to fields on individual regions.
287  */
289 
291 
292 
293 
294  template<int dim, class Val>
295  friend class MultiField;
296 
297 };
298 
299 
300 
301 
302 
303 
304 
305 
306 
307 /****************************************************************************************
308  * Inlined methods of Field< ... >
309  */
310 
311 template<int spacedim, class Value>
312 inline typename Value::return_type const & Field<spacedim,Value>::value(const Point &p, const ElementAccessor<spacedim> &elm) const
313 {
314 
315  ASSERT(this->set_time_result_ != TimeStatus::unknown, "Unknown time status.\n");
316  ASSERT(elm.region_idx().idx() < region_fields_.size(), "Region idx %u out of range %lu, field: %s\n",
317  elm.region_idx().idx(), (unsigned long int) region_fields_.size(), name().c_str());
318  ASSERT( region_fields_[elm.region_idx().idx()] ,
319  "Null field ptr on region id: %d, idx: %d, field: %s\n", elm.region().id(), elm.region_idx().idx(), name().c_str());
320  return region_fields_[elm.region_idx().idx()]->value(p,elm);
321 }
322 
323 
324 
325 template<int spacedim, class Value>
328 {
329  ASSERT(this->set_time_result_ != TimeStatus::unknown, "Unknown time status.\n");
330  ASSERT(elm.region_idx().idx() < region_fields_.size(), "Region idx %u out of range %lu, field: %s\n",
331  elm.region_idx().idx(), (unsigned long int) region_fields_.size(), name().c_str());
332  ASSERT( region_fields_[elm.region_idx().idx()] ,
333  "Null field ptr on region id: %d, field: %s\n", elm.region().id(), name().c_str());
334 
335  region_fields_[elm.region_idx().idx()]->value_list(point_list,elm, value_list);
336 }
337 
338 
339 
340 
341 
342 
343 
344 #endif /* FIELD_HH_ */
Common abstract parent of all Field<...> classes.
Definition: field_common.hh:47
pair< double, FieldBasePtr > HistoryPoint
Pair: time, pointer to FieldBase instance.
Definition: field.hh:259
Class template representing a field with values dependent on: point, element, and region...
Definition: field.hh:52
Definition: mesh.h:109
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:326
Basic time management class.
std::shared_ptr< SharedData > data_
Definition: field.hh:273
#define ASSERT(...)
Definition: global_defs.h:121
const std::string & name() const
Accessor to the data with type Type::Record.
Definition: accessors.hh:327
FieldAlgorithmBase< spacedim, Value >::Point Point
Definition: field.hh:57
std::shared_ptr< ControlField > no_check_control_field_
Definition: field.hh:283
Class for declaration of polymorphic Record.
Definition: type_record.hh:487
virtual Value::return_type const & value(const Point &p, const ElementAccessor< spacedim > &elm) const
Definition: field.hh:312
The class for outputting data during time.
Definition: output_time.hh:32
Space< spacedim >::Point Point
std::vector< FieldBasePtr > region_fields_
Definition: field.hh:288
Accessor to the polymorphic input data of a type given by an AbstracRecord object.
Definition: accessors.hh:448
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:56
FieldAlgorithmBase< spacedim, Value > FieldBaseType
Definition: field.hh:55
std::vector< std::shared_ptr< FactoryBase > > factories_
Definition: field.hh:290
boost::circular_buffer< HistoryPoint > RegionHistory
Nearest history of one region.
Definition: field.hh:261
RegionIdx region_idx() const
Definition: accessors.hh:91
Field< spacedim, typename FieldValue< spacedim >::Enum > ControlField
Definition: field.hh:282
Record type proxy class.
Definition: type_record.hh:169
Class for representation of a vector of fields of the same physical quantity.
Definition: multi_field.hh:45
Representation of one time step.
TimeStatus set_time_result_
Status of history.
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:268