Flow123d  release_2.2.0-23-g01927c6
field.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.hh
15  * @brief
16  */
17 
18 #ifndef FIELD_HH_
19 #define FIELD_HH_
20 
21 #include <memory>
22 using namespace std;
23 
24 #include <boost/circular_buffer.hpp>
25 
26 #include "system/exceptions.hh"
28 #include "tools/time_marks.hh"
29 #include "tools/time_governor.hh"
30 
31 #include "fields/field_common.hh"
33 #include "fields/field_flag.hh"
34 //#include "io/output_time.hh"
35 
36 class OutputTime;
37 
38 namespace IT=Input::Type;
39 
40 /**
41  * @brief Class template representing a field with values dependent on: point, element, and region.
42  *
43  * By "field" we mean a mapping of a a pair (Point, Time) to a @p Value, where
44  * Point is from @p spacedim dimensional ambient space, Time is real number (set by @p set_time method),
45  * and @p Value type representing range of the field, which can be: real scalar, integer scalar (a discrete value),
46  * real vector of fixed (compile time) size, real vector of runtime size, or a matrix of fixed dimensions.
47  * Extensions to vectors or matrices of integers, or to variable tensors are possible. For vector and matrix values
48  * we use classes provided by Armadillo library for linear algebra.
49  * The @p Value template parameter should FieldValue<> template, usual choices are:
50  * FieldValue<spacedim>::Scalar, FieldValue<spacedim>::Integer, FieldValue<spacedim>::Enum,
51  * FieldValue<spacedim>::VectorFixed, FieldValue<spacedim>::TensorFixed.
52  *
53  * 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
54  * region index (very same functionality, but for boundary regions is provided by @p BCField class). This class has interface very similar to FiledBase, however
55  * key methods @p value, and @p value_list are not virtual in this class by contrast these methods are inlined to minimize overhead for
56  * simplest fields like FieldConstant.
57  *
58  * TODO: currently it works only for spacedim==3 since we have only mesh in 3D ambient space.
59  *
60  */
61 template<int spacedim, class Value>
62 class Field : public FieldCommon {
63 public:
64 
66  typedef std::shared_ptr< FieldBaseType > FieldBasePtr;
68  typedef Value ValueType;
69 
70  static const unsigned int space_dim = spacedim;
71 
72 
73  /**
74  * Factory class that creates an instance of FieldBase for field
75  * with name @p field_name based on data in field descriptor @p rec.
76  *
77  * Default implementation in method @p create_field just reads key given by
78  * @p field_name and creates instance using @p FieldBase<...>::function_factory.
79  * Function should return empty SharedField (that is shared_ptr to FieldBase).
80  *
81  * Implementation of these descendants is necessary:
82  * 1) for backward compatibility with old BCD input files
83  * 2) for setting pressure values are piezometric head values
84  */
85  /**
86  * Note for future:
87  * We pass through parameter @p field information about field that holds the factory which are necessary
88  * for interpreting user input and create particular field instance. It would be clearer to pass these information
89  * when the factory is assigned to a field. Moreover some information may not be set to field at all but directly passed
90  * to the factory.
91  */
92  class FactoryBase {
93  public:
94  /**
95  * Default method that creates an instance of FieldBase for field.
96  *
97  * Reads key given by @p field_name and creates the field instance using
98  * @p FieldBase<...>::function_factory.
99  */
100  virtual FieldBasePtr create_field(Input::Record rec, const FieldCommon &field);
101 
102  /**
103  * Check if Input::Record accessor contains data of field given by input_name.
104  *
105  * Returns true when ever the method create_field returns non-null pointer, otherwise returns false.
106  */
107  virtual bool is_active_field_descriptor(const Input::Record &in_rec, const std::string &input_name);
108  };
109 
110  /**
111  * Default constructor.
112  *
113  */
114  Field();
115 
116  Field(const string &name, bool bc = false);
117 
118  /**
119  * Constructor that must be used for create of MultiField components.
120  *
121  * Set parameters @p component_index_, @p shared_->input_name_ and @p name_.
122  * Parameter name_ of Field is consisted of component name and MultiField name.
123  */
124  Field(unsigned int component_index, string input_name, string name = "", bool bc = false);
125 
126  /**
127  * Copy constructor. Keeps shared history, declaration data, mesh.
128  */
129  Field(const Field &other);
130 
131  /**
132  * Assignment operator. Same properties as copy constructor, but class member name_ is not copied.
133  *
134  * Question: do we really need this, isn't copy constructor enough?
135  * Answer: It is necessary in (usual) case when Field instance is created as the class member
136  * but is filled later by assignment possibly from other class.
137  * TODO: operator can be merged with copy constructor, but we must provide to set correct value
138  * of name in method copy_from
139  */
140  Field &operator=(const Field &other);
141 
142 
143  /**
144  * Returns reference to input type of particular field instance, this is static member @p input_type of the corresponding FieldBase class
145  * (i.e. with same template parameters). However, for fields returning "Enum" we have to create whole unique Input::Type hierarchy using following method
146  * @p meka_input_tree.
147  * every instance since every such field use different Selection for initialization, even if all returns just unsigned int.
148  */
149  IT::Instance get_input_type() override;
150 
151  IT::Array get_multifield_input_type() override;
152 
153 
154  /**
155  * 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
156  * FieldConstant and has value in given @p value_list. We check this in the set_time method. Through this mechanism we
157  * can switch of e.g. boundary data fields according to the type of the boundary condition.
158  */
159  auto disable_where(
160  const Field<spacedim, typename FieldValue<spacedim>::Enum > &control_field,
161  const vector<FieldEnum> &value_list) -> Field &;
162 
163 
164 
165  /**
166  * Set mesh pointer and resize region arrays.
167  *
168  * Implements abstract method.
169  */
170  void set_mesh(const Mesh &mesh) override;
171 
172 
173  /**
174  * Direct read access to the table of Field pointers on regions.
175  */
176  //std::shared_ptr< FieldBaseType > operator[] (Region reg);
177 
178  /**
179  * Implementation of @p FieldCommonBase::is_constant().
180  * See also Field<>::field_result which provide better information about special field values.
181  */
182  bool is_constant(Region reg) override;
183 
184  /**
185  * Assigns given @p field to all regions in given region set @p domain.
186  * Field is added to the history with given time and possibly used in the next call of the set_time method.
187  * Caller is responsible for correct construction of given field.
188  *
189  * Use this method only if necessary.
190  *
191  * Default time simplify setting steady fields.
192  */
193  void set_field(const RegionSet &domain, FieldBasePtr field, double time=0.0);
194 
195  /**
196  * Same as before but the field is first created using FieldBase::function_factory(), from
197  * given abstract record accessor @p a_rec.
198  */
199  void set_field(const RegionSet &domain, const Input::AbstractRecord &a_rec, double time=0.0);
200 
201  /**
202  * Check that whole field list is set, possibly use default values for unset regions
203  * and call set_time for every field in the field list.
204  *
205  * Returns true if the field has been changed.
206  */
207  bool set_time(const TimeStep &time, LimitSide limit_side) override;
208 
209  /**
210  * Check that other has same type and assign from it.
211  */
212  void copy_from(const FieldCommon & other) override;
213 
214  /**
215  * Implementation of FieldCommonBase::output().
216  */
217  void field_output(std::shared_ptr<OutputTime> stream) override;
218 
219  /**
220  * Implementation of FieldCommonBase::observe_output().
221  */
222  void observe_output(std::shared_ptr<Observe> observe) override;
223 
224  /**
225  * Returns true, if field is currently set to a time in which it is discontinuous.
226  */
227  //bool is_jump_time();
228 
229 
230  /**
231  * @brief Indicates special field states.
232  *
233  * Return possible values from the enum @p FieldResult, see description there.
234  * The initial state is @p field_none, if the field is correctly set on all regions of the @p region_set given as parameter
235  * we return state @p field_other
236  * - Special field values spatially constant. Could allow optimization of tensor multiplication and
237  * tensor or vector addition. field_result_ should be set in constructor and in set_time method of particular Field implementation.
238  * We return value @p result_none, if the field is not initialized on the region of the given element accessor @p elm.
239  * Other possible results are: result_zeros, result_eye, result_ones, result_constant, result_other
240  * see @p FieldResult for explanation.
241  */
242  FieldResult field_result( RegionSet region_set) const override;
243 
244  /**
245  * Return value of input type attribute 'field_value_shape' that is appended to the
246  * input type of this field in FieldSet::make_field_descriptor_type and also to the output field selection
247  * created in EquationOutput::make_output_type.
248  * This attribute is used by GeoMop to have semantics of the input and output field data.
249  *
250  * Attribute value is a valid JSON (and/or flow style YAML) with keys:
251  * 'subfields' - value True for multifields, False or not presented for single value fields
252  * 'shape' - [ NRows, Ncols] ... given by FieldValue
253  * 'type' - <element type> (Double or Integer) ... given by FieldValue
254  * 'limit' - bounds of the field values.
255  *
256  */
257  std::string get_value_attribute() const override;
258 
259  /**
260  * Returns one value in one given point @p on an element given by ElementAccessor @p elm.
261  * It returns reference to he actual value in order to avoid temporaries for vector and tensor values.
262  */
263  virtual typename Value::return_type const &value(const Point &p, const ElementAccessor<spacedim> &elm) const;
264 
265  /**
266  * Returns std::vector of scalar values in several points at once. The base class implements
267  * trivial implementation using the @p value(,,) method. This is not optimal as it involves lot of virtual calls,
268  * but this overhead can be negligible for more complex fields as Python of Formula.
269  */
270  virtual void value_list(const std::vector< Point > &point_list, const ElementAccessor<spacedim> &elm,
271  std::vector<typename Value::return_type> &value_list) const;
272 
273  /**
274  * Add a new factory for creating Field algorithms on individual regions.
275  * The last factory is tried first, the last one is always the default implementation
276  * Field<...>::FactoryBase.
277  *
278  * The Field<...> object keeps a list of such factories. When the instance of a new field algorithm
279  * has to be created from the input field descriptor, we pass through the list of factories backward
280  * and let factories to create the field algorithm instance from the actual input field descriptor.
281  * The first instance (non-null pointer) is used.
282  */
283  void add_factory(std::shared_ptr<FactoryBase> factory);
284 
285  void set_input_list(const Input::Array &list) override;
286 
287  /**
288  * Interpolate given field into output discrete @p space_type and store the values
289  * into storage of output time @p stream for postponed output.
290  */
291  void compute_field_data(OutputTime::DiscreteSpace space_type, std::shared_ptr<OutputTime> stream);
292 
293 protected:
294 
295  /**
296  * Read input into @p regions_history_ possibly pop some old values from the
297  * history queue to keep its size less then @p history_length_limit_.
298  */
299  void update_history(const TimeStep &time);
300 
301 
302 
303  /**
304  * Check that whole field list (@p region_fields_) is set, possibly use default values for unset regions.
305  */
306  void check_initialized_region_fields_();
307 
308  /**************** Shared data **************/
309 
310  /// Pair: time, pointer to FieldBase instance
311  typedef pair<double, FieldBasePtr> HistoryPoint;
312  /// Nearest history of one region.
313  typedef boost::circular_buffer<HistoryPoint> RegionHistory;
314 
315  struct SharedData {
316 
317  /**
318  * History for every region. Shared among copies.
319  */
321  };
322 
323  /**************** Data per copy **************/
324 
325  std::shared_ptr<SharedData> data_;
326 
327  /**
328  * If this pointer is set, turn off check of initialization in the
329  * @p set_time method on the regions where the method @p get_constant_enum_value
330  * of the control field returns value from @p no_check_values_. This
331  * field is private copy, its set_time method is called from the
332  * set_Time method of actual object.
333  */
335  std::shared_ptr<ControlField> no_check_control_field_;
336 
337  /**
338  * Table with pointers to fields on individual regions.
339  */
341 
343 
344 
345 
346  template<int dim, class Val>
347  friend class MultiField;
348 
349 };
350 
351 
352 
353 
354 
355 
356 
357 /****************************************************************************************
358  * Inlined methods of Field< ... >
359  */
360 
361 template<int spacedim, class Value>
362 inline typename Value::return_type const & Field<spacedim,Value>::value(const Point &p, const ElementAccessor<spacedim> &elm) const
363 {
364 
365  ASSERT(this->set_time_result_ != TimeStatus::unknown)(this->name()).error("Unknown time status.\n");
366  OLD_ASSERT(elm.region_idx().idx() < region_fields_.size(), "Region idx %u out of range %lu, field: %s\n",
367  elm.region_idx().idx(), (unsigned long int) region_fields_.size(), name().c_str());
368  OLD_ASSERT( region_fields_[elm.region_idx().idx()] ,
369  "Null field ptr on region id: %d, idx: %d, field: %s\n", elm.region().id(), elm.region_idx().idx(), name().c_str());
370  return region_fields_[elm.region_idx().idx()]->value(p,elm);
371 }
372 
373 
374 
375 template<int spacedim, class Value>
378 {
379  ASSERT(this->set_time_result_ != TimeStatus::unknown)(this->name()).error("Unknown time status.\n");
380  OLD_ASSERT(elm.region_idx().idx() < region_fields_.size(), "Region idx %u out of range %lu, field: %s\n",
381  elm.region_idx().idx(), (unsigned long int) region_fields_.size(), name().c_str());
382  OLD_ASSERT( region_fields_[elm.region_idx().idx()] ,
383  "Null field ptr on region id: %d, field: %s\n", elm.region().id(), name().c_str());
384 
385  region_fields_[elm.region_idx().idx()]->value_list(point_list,elm, value_list);
386 }
387 
388 
389 
390 
391 
392 
393 
394 #endif /* FIELD_HH_ */
Common abstract parent of all Field<...> classes.
Definition: field_common.hh:60
pair< double, FieldBasePtr > HistoryPoint
Pair: time, pointer to FieldBase instance.
Definition: field.hh:311
Accessor to input data conforming to declared Array.
Definition: accessors.hh:567
Class template representing a field with values dependent on: point, element, and region...
Definition: field.hh:62
Definition: mesh.h:97
Helper class that stores data of generic types.
Definition: type_generic.hh:89
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:346
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:376
Basic time management class.
Class for declaration of inputs sequences.
Definition: type_base.hh:345
std::shared_ptr< SharedData > data_
Definition: field.hh:325
static constexpr bool value
Definition: json.hpp:87
#define OLD_ASSERT(...)
Definition: global_defs.h:131
const std::string & name() const
Accessor to the data with type Type::Record.
Definition: accessors.hh:292
FieldAlgorithmBase< spacedim, Value >::Point Point
Definition: field.hh:67
std::shared_ptr< ControlField > no_check_control_field_
Definition: field.hh:335
virtual Value::return_type const & value(const Point &p, const ElementAccessor< spacedim > &elm) const
Definition: field.hh:362
The class for outputting data during time.
Definition: output_time.hh:44
Space< spacedim >::Point Point
std::vector< FieldBasePtr > region_fields_
Definition: field.hh:340
Value ValueType
Definition: field.hh:68
Accessor to the polymorphic input data of a type given by an AbstracRecord object.
Definition: accessors.hh:459
Region region() const
Definition: accessors.hh:98
FieldResult
std::shared_ptr< FieldBaseType > FieldBasePtr
Definition: field.hh:66
FieldAlgorithmBase< spacedim, Value > FieldBaseType
Definition: field.hh:65
std::vector< std::shared_ptr< FactoryBase > > factories_
Definition: field.hh:342
boost::circular_buffer< HistoryPoint > RegionHistory
Nearest history of one region.
Definition: field.hh:313
RegionIdx region_idx() const
Definition: accessors.hh:101
Field< spacedim, typename FieldValue< spacedim >::Enum > ControlField
Definition: field.hh:334
Class for representation of a vector of fields of the same physical quantity.
Definition: multi_field.hh:55
Representation of one time step..
TimeStatus set_time_result_
LimitSide
Definition: field_common.hh:47
unsigned int id() const
Returns id of the region (using RegionDB)
Definition: region.cc:38
unsigned int idx() const
Returns a global index of the region.
Definition: region.hh:81
std::vector< RegionHistory > region_history_
Definition: field.hh:320