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