Flow123d  master-921db77
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 <stdio.h> // for sprintf
22 #include <string.h> // for memcpy
23 #include <algorithm> // for find, min
24 #include <boost/circular_buffer.hpp>
25 #include <memory> // for dynamic_pointe...
26 #include <new> // for operator new[]
27 #include <ostream> // for basic_ostream:...
28 #include <string> // for basic_string
29 #include <utility> // for pair
30 #include <vector> // for vector
31 #include <armadillo>
32 #include "fields/field_algo_base.hh" // for FieldAlgorithm...
33 #include "fields/field_common.hh" // for FieldCommon::T...
34 #include "fields/field_values.hh" // for FieldValue<>::...
35 #include "fem/element_cache_map.hh" // for FieldValueCache
36 #include "input/accessors.hh" // for ExcTypeMismatch
37 #include "input/accessors_impl.hh" // for Record::opt_val
38 #include "input/factory_impl.hh" // for Factory::create
39 #include "input/input_exception.hh" // for FieldCommon::E...
40 #include "input/storage.hh" // for ExcStorageType...
41 #include "input/type_base.hh" // for Array
42 #include "input/type_generic.hh" // for Instance
43 #include "input/type_record.hh" // for Record::ExcRec...
44 #include "input/input_exception.hh" // for Input::Exception
45 #include "io/output_time.hh" // for OutputTime
46 #include "mesh/elements.h" // for Element::dim
47 #include "mesh/region.hh" // for RegionDB::ExcU...
48 #include "system/asserts.hh" // for Assert, ASSERT
49 #include "system/exceptions.hh" // for ExcAssertMsg::...
50 #include "tools/time_governor.hh" // for TimeStep
51 
52 class Mesh;
53 class Observe;
54 class EvalPoints;
55 class BulkPoint;
56 class SidePoint;
57 class FieldSet;
59 struct PatchInternals;
60 template <int spacedim> class ElementAccessor;
61 template <int spacedim, class Value> class FieldFE;
62 namespace detail
63 {
64  template< typename CALLABLE, typename TUPLE, int INDEX >
65  struct model_cache_item;
66 }
67 
68 using namespace std;
69 namespace IT=Input::Type;
70 
71 /**
72  * @brief Class template representing a field with values dependent on: point, element, and region.
73  *
74  * By "field" we mean a mapping of a a pair (Point, Time) to a @p Value, where
75  * Point is from @p spacedim dimensional ambient space, Time is real number (set by @p set_time method),
76  * and @p Value type representing range of the field, which can be: real scalar, integer scalar (a discrete value),
77  * real vector of fixed (compile time) size, real vector of runtime size, or a matrix of fixed dimensions.
78  * Extensions to vectors or matrices of integers, or to variable tensors are possible. For vector and matrix values
79  * we use classes provided by Armadillo library for linear algebra.
80  * The @p Value template parameter should FieldValue<> template, usual choices are:
81  * FieldValue<spacedim>::Scalar, FieldValue<spacedim>::Integer, FieldValue<spacedim>::Enum,
82  * FieldValue<spacedim>::VectorFixed, FieldValue<spacedim>::TensorFixed.
83  *
84  * 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
85  * region index (very same functionality, but for boundary regions is provided by @p BCField class). This class has interface very similar to FiledBase, however
86  * key methods @p value, and @p value_list are not virtual in this class by contrast these methods are inlined to minimize overhead for
87  * simplest fields like FieldConstant.
88  *
89  * TODO: currently it works only for spacedim==3 since we have only mesh in 3D ambient space.
90  *
91  */
92 template<int spacedim, class Value>
93 class Field : public FieldCommon {
94 public:
95 
97  typedef std::shared_ptr< FieldBaseType > FieldBasePtr;
99  typedef Value ValueType;
100 
101  static const unsigned int space_dim = spacedim;
102 
103 
104  /**
105  * Factory class that creates an instance of FieldBase for field
106  * with name @p field_name based on data in field descriptor @p rec.
107  *
108  * Default implementation in method @p create_field just reads key given by
109  * @p field_name and creates instance using @p FieldBase<...>::function_factory.
110  * Function should return empty SharedField (that is shared_ptr to FieldBase).
111  *
112  * Implementation of these descendants is necessary:
113  * 1) for backward compatibility with old BCD input files
114  * 2) for setting pressure values are piezometric head values
115  */
116  /**
117  * Note for future:
118  * We pass through parameter @p field information about field that holds the factory which are necessary
119  * for interpreting user input and create particular field instance. It would be clearer to pass these information
120  * when the factory is assigned to a field. Moreover some information may not be set to field at all but directly passed
121  * to the factory.
122  */
123  class FactoryBase {
124  public:
125  /**
126  * Default method that creates an instance of FieldBase for field.
127  *
128  * Reads key given by @p field_name and creates the field instance using
129  * @p FieldBase<...>::function_factory.
130  */
131  virtual FieldBasePtr create_field(Input::Record rec, const FieldCommon &field);
132 
133  /**
134  * Check if Input::Record accessor contains data of field given by input_name.
135  *
136  * Returns true when ever the method create_field returns non-null pointer, otherwise returns false.
137  */
138  virtual bool is_active_field_descriptor(const Input::Record &in_rec, const std::string &input_name);
139  };
140 
141  /**
142  * Default constructor.
143  *
144  */
145  Field();
146 
147  Field(const string &name);
148 
149  /**
150  * Constructor that must be used for create of MultiField components.
151  *
152  * Set parameters @p component_index_, @p shared_->input_name_ and @p name_.
153  * Parameter name_ of Field is consisted of component name and MultiField name.
154  */
155  Field(unsigned int component_index, string input_name, string name = "");
156 
157  /**
158  * Copy constructor. Keeps shared history, declaration data, mesh.
159  */
160  Field(const Field &other);
161 
162  /**
163  * Assignment operator. Same properties as copy constructor, but class member name_ is not copied.
164  *
165  * Question: do we really need this, isn't copy constructor enough?
166  * Answer: It is necessary in (usual) case when Field instance is created as the class member
167  * but is filled later by assignment possibly from other class.
168  * TODO: operator can be merged with copy constructor, but we must provide to set correct value
169  * of name in method copy_from
170  */
171  Field &operator=(const Field &other);
172 
173 
174  /// Return appropriate value to BulkPoint in FieldValueCache
175  typename Value::return_type operator() (BulkPoint &p);
176 
177 
178  /// Return appropriate value to EdgePoint in FieldValueCache
179  typename Value::return_type operator() (SidePoint &p);
180 
181 
182  /**
183  * Returns reference to input type of particular field instance, this is static member @p input_type of the corresponding FieldBase class
184  * (i.e. with same template parameters). However, for fields returning "Enum" we have to create whole unique Input::Type hierarchy using following method
185  * @p make_input_tree.
186  * every instance since every such field use different Selection for initialization, even if all returns just unsigned int.
187  */
188  IT::Instance get_input_type() override;
189 
190  IT::Array get_multifield_input_type() override;
191 
192 
193  /**
194  * 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
195  * FieldConstant and has value in given @p value_list. We check this in the set_time method. Through this mechanism we
196  * can switch of e.g. boundary data fields according to the type of the boundary condition.
197  */
198  auto disable_where(
199  const Field<spacedim, typename FieldValue<spacedim>::Enum > &control_field,
200  const vector<FieldEnum> &value_list) -> Field &;
201 
202 
203 
204  /**
205  * Set mesh pointer and resize region arrays.
206  *
207  * Implements abstract method.
208  */
209  void set_mesh(const Mesh &mesh) override;
210 
211 
212  /**
213  * Direct read access to the table of Field pointers on regions.
214  */
215  //std::shared_ptr< FieldBaseType > operator[] (Region reg);
216 
217  /**
218  * Implementation of @p FieldCommonBase::is_constant().
219  * See also Field<>::field_result which provide better information about special field values.
220  */
221  bool is_constant(Region reg) override;
222 
223  /**
224  * Assigns given @p field to all regions in region set given by @p region_set_names.
225  * Field is added to the history with given time and possibly used in the next call of the set_time method.
226  * Caller is responsible for correct construction of given field.
227  *
228  * Use this method only if necessary.
229  */
230  void set(FieldBasePtr field, double time, std::vector<std::string> region_set_names = {"ALL"});
231 
232  /**
233  * Same as before but the field is first created using FieldBase::function_factory(), from
234  * given abstract record accessor @p a_rec.
235  */
236  void set(const Input::AbstractRecord &a_rec, double time, std::vector<std::string> region_set_names = {"ALL"});
237 
238  /**
239  * Check that whole field list is set, possibly use default values for unset regions
240  * and call set_time for every field in the field list.
241  *
242  * Returns true if the field has been changed.
243  */
244  bool set_time(const TimeStep &time, LimitSide limit_side) override;
245 
246  /**
247  * Check that other has same type and assign from it.
248  */
249  void copy_from(const FieldCommon & other) override;
250 
251  /**
252  * Implementation of FieldCommonBase::output().
253  */
254  void field_output(std::shared_ptr<OutputTime> stream, OutputTime::DiscreteSpace type) override;
255 
256  /**
257  * Returns true, if field is currently set to a time in which it is discontinuous.
258  */
259  //bool is_jump_time();
260 
261  /**
262  * Check that the field is in fact FieldFE set on all bulk regions, return shared pointer to that FieldFE or NULL
263  * if the Field is not FieldFE.
264  */
265  std::shared_ptr< FieldFE<spacedim, Value> > get_field_fe();
266 
267 
268  /**
269  * @brief Indicates special field states.
270  *
271  * Return possible values from the enum @p FieldResult, see description there.
272  * The initial state is @p field_none, if the field is correctly set on all regions of the @p region_set given as parameter
273  * we return state @p field_other
274  * - Special field values spatially constant. Could allow optimization of tensor multiplication and
275  * tensor or vector addition. field_result_ should be set in constructor and in set_time method of particular Field implementation.
276  * We return value @p result_none, if the field is not initialized on the region of the given element accessor @p elm.
277  * Other possible results are: result_zeros, result_eye, result_ones, result_constant, result_other
278  * see @p FieldResult for explanation.
279  */
280  FieldResult field_result( RegionSet region_set) const override;
281 
282  /**
283  * Return value of input type attribute 'field_value_shape' that is appended to the
284  * input type of this field in FieldSet::make_field_descriptor_type and also to the output field selection
285  * created in EquationOutput::make_output_type.
286  * This attribute is used by GeoMop to have semantics of the input and output field data.
287  *
288  * Attribute value is a valid JSON (and/or flow style YAML) with keys:
289  * 'subfields' - value True for multifields, False or not presented for single value fields
290  * 'shape' - [ NRows, Ncols] ... given by FieldValue
291  * 'type' - <element type> (Double or Integer) ... given by FieldValue
292  * 'limit' - bounds of the field values.
293  *
294  */
295  std::string get_value_attribute() const override;
296 
297  /**
298  * Add a new factory for creating Field algorithms on individual regions.
299  * The last factory is tried first, the last one is always the default implementation
300  * Field<...>::FactoryBase.
301  *
302  * The Field<...> object keeps a list of such factories. When the instance of a new field algorithm
303  * has to be created from the input field descriptor, we pass through the list of factories backward
304  * and let factories to create the field algorithm instance from the actual input field descriptor.
305  * The first instance (non-null pointer) is used.
306  */
307  void add_factory(std::shared_ptr<FactoryBase> factory);
308 
309  void set_input_list(const Input::Array &list, const TimeGovernor &tg) override;
310 
311  /**
312  * Create and return shared_ptr to ElementDataCache appropriate to Field. Data cache is given by discrete @p space_type
313  * and is stored into data structures of output time @p stream for postponed output too.
314  */
315  void set_output_data_cache(OutputTime::DiscreteSpace space_type, std::shared_ptr<OutputTime> stream) override;
316 
317  /**
318  * Interpolate given field into output discrete @p space_type and store the values
319  * into storage of output time @p stream for postponed output.
320  */
321  void compute_field_data(OutputTime::DiscreteSpace space_type, std::shared_ptr<OutputTime> stream);
322 
323  /// Implements FieldCommon::cache_allocate
324  void cache_reallocate(PatchInternals &patch_internals, unsigned int region_idx) const override;
325 
326  /// Implements FieldCommon::cache_update
327  void cache_update(ElementCacheMap &cache_map, unsigned int region_patch_idx) const override;
328 
329  /// Implements FieldCommon::value_cache
330  FieldValueCache<double> * value_cache() override;
331 
332  /// Implements FieldCommon::value_cache
333  const FieldValueCache<double> * value_cache() const override;
334 
335  /**
336  * Implementation of FieldCommon::set_dependency().
337  */
338  std::vector<const FieldCommon *> set_dependency(unsigned int i_reg) const override;
339 
340  /// Implements FieldCommon::fill_data_value
341  void fill_data_value(const std::vector<int> &offsets) override;
342 
343  /// Implements FieldCommon::fill_observe_value
344  void fill_observe_value(std::shared_ptr<ElementDataCacheBase> output_cache_base, const std::vector<int> &offsets) override;
345 
346 protected:
347 
348  /// Return item of @p value_cache_ given by i_cache_point.
349  typename Value::return_type operator[] (unsigned int i_cache_point) const;
350 
351  /**
352  * Read input into @p regions_history_ possibly pop some old values from the
353  * history queue to keep its size less then @p history_length_limit_.
354  */
355  void update_history(const TimeStep &time);
356 
357  /**
358  * Check that whole field list (@p region_fields_) is set, possibly use default values for unset regions.
359  */
360  void check_initialized_region_fields_();
361 
362  /**************** Shared data **************/
363 
364  /// Pair: time, pointer to FieldBase instance
365  typedef pair<double, FieldBasePtr> HistoryPoint;
366  /// Nearest history of one region.
367  typedef boost::circular_buffer<HistoryPoint> RegionHistory;
368 
369  struct SharedData {
370 
371  /**
372  * History for every region. Shared among copies.
373  */
375  };
376 
377  /**************** Data per copy **************/
378 
379  std::shared_ptr<SharedData> data_;
380 
381  /**
382  * If this pointer is set, turn off check of initialization in the
383  * @p set_time method on the regions where the method @p get_constant_enum_value
384  * of the control field returns value from @p no_check_values_. This
385  * field is private copy, its set_time method is called from the
386  * set_Time method of actual object.
387  */
389  std::shared_ptr<ControlField> no_check_control_field_;
390 
391  /**
392  * Table with pointers to fields on individual regions.
393  */
395 
397 
398  /**
399  * Field value data cache
400  *
401  * Data is ordered like three dimensional table. The highest level is determinated by subsets,
402  * those data ranges are holds in subset_starts. Data block size of each subset is determined
403  * by number of eval_points (of subset) and maximal number of stored elements.
404  * The table is allocated to hold all subsets, but only those marked in used_subsets are updated.
405  * Order of subsets is same as in eval_points.
406  */
408 
409  /// ElementDataCache used during field output, object is shared with OutputTime
410  std::shared_ptr<ElementDataCache<typename Value::element_type>> output_data_cache_;
411 
412 
413 
414  template<int dim, class Val>
415  friend class MultiField;
416 
417  template< typename CALLABLE, typename TUPLE, int INDEX >
419 
420 };
421 
422 
423 
424 
425 
426 
427 
428 #endif /* FIELD_HH_ */
Definitions of ASSERTS.
Base point accessor class.
Directing class of FieldValueCache.
Class holds local coordinations of evaluating points (bulk and sides) specified by element dimension.
Definition: eval_points.hh:54
Space< spacedim >::Point Point
Common abstract parent of all Field<...> classes.
Definition: field_common.hh:78
Container for various descendants of FieldCommonBase.
Definition: field_set.hh:161
Class template representing a field with values dependent on: point, element, and region.
Definition: field.hh:93
FieldValueCache< typename Value::element_type > value_cache_
Definition: field.hh:407
FieldAlgorithmBase< spacedim, Value >::Point Point
Definition: field.hh:98
Field< spacedim, typename FieldValue< spacedim >::Enum > ControlField
Definition: field.hh:388
FieldAlgorithmBase< spacedim, Value > FieldBaseType
Definition: field.hh:96
pair< double, FieldBasePtr > HistoryPoint
Pair: time, pointer to FieldBase instance.
Definition: field.hh:365
boost::circular_buffer< HistoryPoint > RegionHistory
Nearest history of one region.
Definition: field.hh:367
Value ValueType
Definition: field.hh:99
std::shared_ptr< ElementDataCache< typename Value::element_type > > output_data_cache_
ElementDataCache used during field output, object is shared with OutputTime.
Definition: field.hh:410
std::shared_ptr< SharedData > data_
Definition: field.hh:379
std::shared_ptr< ControlField > no_check_control_field_
Definition: field.hh:389
std::vector< std::shared_ptr< FactoryBase > > factories_
Definition: field.hh:396
std::shared_ptr< FieldBaseType > FieldBasePtr
Definition: field.hh:97
std::vector< FieldBasePtr > region_fields_
Definition: field.hh:394
Accessor to the polymorphic input data of a type given by an AbstracRecord object.
Definition: accessors.hh:458
Accessor to input data conforming to declared Array.
Definition: accessors.hh:566
Accessor to the data with type Type::Record.
Definition: accessors.hh:291
Class for declaration of inputs sequences.
Definition: type_base.hh:339
Helper class that stores data of generic types.
Definition: type_generic.hh:89
Definition: mesh.h:362
Class for representation of a vector of fields of the same physical quantity.
Definition: multi_field.hh:88
General point a+ side_begin_ + ccessor allow iterate over quadrature points of given side defined in ...
Basic time management functionality for unsteady (and steady) solvers (class Equation).
Representation of one time step..
FieldResult
LimitSide
Definition: field_common.hh:65
@ Value
Definition: field.hh:63
std::vector< RegionHistory > region_history_
Definition: field.hh:374
Holds common data shared between GenericAssemblz and Assembly<dim> classes.
base case for building up arguments for the function call
Definition: field_model.hh:64
Basic time management class.