Flow123d
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_base.hh"
22 #include "io/output_time.hh"
23 
24 namespace IT=Input::Type;
25 
26 /**
27  * Left and right time limit, used in the @p set_time() method.
28  * Assigned values allow to index an array.
29  */
30 enum class LimitSide {
31  left=0,
32  right=1,
33  unknown=2 // undefined value
34 };
35 
36 
37 /**
38  * @brief Common abstract parent of all Field<...> classes.
39  *
40  * We need common ancestor in order to keep a list of all fields in one EqData object and allow
41  * collective operations like @p set_time or @p init_from_input.
42  */
44 
45 public:
46  TYPEDEF_ERR_INFO(EI_Time, double);
47  TYPEDEF_ERR_INFO(EI_Field, std::string);
48  DECLARE_INPUT_EXCEPTION(ExcNonascendingTime,
49  << "Non-ascending time: " << EI_Time::val << " for field " << EI_Field::qval << ".\n");
50  DECLARE_INPUT_EXCEPTION(ExcMissingDomain,
51  << "Missing domain specification (region, r_id, or r_set) in fields descriptor:");
52  DECLARE_EXCEPTION(ExcFieldMeshDifference,
53  << "Two copies of the field " << EI_Field::qval << "call set_mesh with different arguments.\n");
54 
55 
56 
57  /**
58  * Set name of the field, used for naming the field's key in EqData record.
59  * It can also be used to name a corresponding output data set, e.g. when outut the field into a VTK file.
60  */
61  FieldCommonBase &name(const string & name)
62  { shared_->name_ = name; return *this;}
63  /**
64  * Mark field to be used only as a copy of other field (do not produce key in record, do not set input list).
65  */
67  {is_copy_=true; return *this;}
68  /**
69  * Set description of the field, used for description of corresponding key in documentation.
70  */
71  FieldCommonBase & desc(const string & desc)
72  { shared_->desc_ = desc; return *this;}
73  /**
74  * Set default value for the field's key from which the default constant valued field will be constructed.
75  *
76  * During the first call of the @p set_time method, we check that the field is defined on all regions.
77  * On regions where it is not set yet, we use given @p dflt string to get particular instance of
78  * FieldBase<> (see @p check_initialized_region_fields_).
79  * The default string is interpreted in the same way as if it appears in the input file
80  * as the value of the field. In particular it can be whole record with @p TYPE of the field etc.
81  * Most common choice is however mere constant.
82  */
83  FieldCommonBase & input_default(const string &dflt)
84  { shared_->default_ = dflt; return *this;}
85  /**
86  * @brief Set basic units of the field.
87  *
88  * Currently, we use it only during output and we represents units just by a string.
89  *
90  * TODO:
91  * Particular class for representing and conversion of various units would be more appropriate.
92  * This can allow specification of the units on the inptu, automatic conversion and the same on the output.
93  * Possibly this allow using Boost::Units library, however, it seems to introduce lot of boilerplate code.
94  * But can increase correctness of the calculations.
95  */
96  FieldCommonBase & units(const string & units)
97  { shared_->units_ = units; return *this;}
98 
99  /**
100  * For the fields returning "Enum", we have to pass the Input::Type::Selection object to
101  * the field implementations.
102  *
103  * We must save raw pointer since selection may not be yet initialized (during static initialization phase).
104  */
106  {
107  shared_->element_selection_=element_selection;
108  return *this;
109  }
110 
111  /**
112  * Output discrete space used in the output() method. Can be different for different field copies.
113  * one can choose between:
114  * data constant on elements, linear data given in nodes, and discontinuous linear data.
115  *
116  * If not set explicitly by this method, the default value is OutputTime::ELEM_DATA
117  */
119  { type_of_output_data_ = rt; return *this; }
120 
121  /**
122  * Set number of components for run-time sized vectors. This is used latter when we construct
123  * objects derived from FieldBase<...>.
124  *
125  * n_comp_ is constant zero for fixed values, this zero is set by Field<...> constructors
126  */
127  void n_comp( unsigned int n_comp)
128  { shared_->n_comp_ = (shared_->n_comp_ ? n_comp : 0);}
129 
130 
131  /**
132  * Set internal mesh pointer.
133  */
134  virtual void set_mesh(const Mesh &mesh) {};
135  /**
136  * Set the data list from which field will read its input. It is list of "field descriptors".
137  * When reading from the input list we consider only field descriptors containing key of
138  * named by the field name. These field descriptors has to have times forming ascending sequence.
139  *
140  * The list is used by set_time method to set field on individual regions to actual FieldBase descendants.
141  */
142  void set_input_list(const Input::Array &list);
143 
144  /**
145  * Set side of limit when calling @p set_time
146  * with jump time. This method invalidate result of
147  * @p changed() so it should be called just before @p set_time.
148  * Can be different for different field copies.
149  */
150  virtual void set_limit_side(LimitSide side) = 0;
151 
152  /**
153  * Getters.
154  */
155  const std::string &name() const
156  { return shared_->name_;}
157 
158  const std::string desc() const
159  {return shared_->desc_;}
160 
161  const std::string &input_default() const
162  { return shared_->default_;}
163 
164  const std::string &units() const
165  { return shared_->units_;}
166 
168  { return type_of_output_data_; }
169 
170  bool is_bc() const
171  { return shared_->bc_;}
172 
173  unsigned int n_comp() const
174  { return shared_->n_comp_;}
175 
176  const Mesh * mesh() const
177  { return shared_->mesh_;}
178 
179  bool is_just_copy() const
180  { return is_copy_;}
181 
182  /**
183  * Returns time set by last call of set_time method.
184  * Can be different for different field copies.
185  */
186  double time() const
187  { return last_time_; }
188 
189 
190  /**
191  * Common part of the field descriptor. To get finished record
192  * one has to add keys for individual fields. This is done automatically
193  * using FieldSet::get_input_type().
194  */
195  static IT::Record field_descriptor_record(const string& record_name);
196 
197  /**
198  * Returns input type for particular field instance, this is reference to a static member input_type of the corresponding @p FieldBase
199  * class (i.e. with the same template parameters). This is used in FieldSet::make_field_descriptor_type.
200  */
201  virtual IT::AbstractRecord &get_input_type() =0;
202 
203  /**
204  * Abstract method for initialization of the field on one region.
205  */
206  //virtual void set_from_input(const RegionSet &domain, const Input::AbstractRecord &rec) =0;
207 
208  /**
209  * Pass through the input array @p input_list_, collect all times where the field could change and
210  * put appropriate time marks into global TimeMarks object.
211  * Introduced time marks have both given @p mark_type and @p type_input() type.
212  *
213  * Further development:
214  * - we have to distinguish "jump" times and "smooth" times
215  */
216  void mark_input_times(TimeMark::Type mark_type);
217 
218  /**
219  * Abstract method to update field to the new time level.
220  * Implemented by in class template Field<...>.
221  *
222  * Return true if the value of the field was changed on some region.
223  * The returned value is also stored in @p changed_during_set_time data member.
224  *
225  * Default values helps when creating steady field. Note that default TimeGovernor constructor
226  * set time to 0.0.
227  *
228  * Different field copies can be set to different times.
229  */
230  virtual bool set_time(const TimeGovernor &time) =0;
231 
232  /**
233  * Check that @p other is instance of the same Field<..> class and
234  * perform assignment. Polymorphic copy.
235  */
236  virtual void copy_from(const FieldCommonBase & other) =0;
237 
238  /**
239  * Output the field.
240  * The parameter @p output_fields is checked for value named by the field name. If the key exists,
241  * then the output of the field is performed. If the key do not appear in the input, no output is done.
242  */
243  virtual void output(OutputTime *stream) =0;
244 
245 
246  /**
247  * If the field on given region @p reg exists and is of type FieldConstant<...> the method method returns true
248  * otherwise it returns false.
249  * Then one call ElementAccessor<spacedim>(mesh(), reg ) to construct an ElementAccessor @p elm
250  * pointing to "virtual" element on which Field::value returns constant value.
251  *
252  * Current implementation use virtual functions and can be prohibitively slow if called for every element. If this
253  * becomes necessary it is possible to incorporate such test into set_time method and in this method just return precomputed result.
254  */
255  virtual bool is_constant(Region reg) =0;
256 
257  /**
258  * Returns true if set_time_result_ is not @p TimeStatus::constant.
259  * Returns the same value as last set_time method.
260  */
261  bool changed() const
262  {
263  ASSERT( set_time_result_ != TimeStatus::unknown, "Invalid time status.\n");
264  return ( (set_time_result_ == TimeStatus::changed) );
265  }
266 
267  /**
268  * Virtual destructor.
269  */
270  virtual ~FieldCommonBase();
271 
272 
273 protected:
274  /**
275  * Private default constructor. Should be used only through
276  * Field<...>
277  */
278  FieldCommonBase();
279 
280  /**
281  * Private copy constructor. Should be used only through
282  * Field<...>
283  */
284  FieldCommonBase(const FieldCommonBase & other);
285 
286  //FieldCommonBase &FieldCommonBase::operator=(const FieldCommonBase &other) delete;
287 
288  /**
289  * Invalidate last time in order to force set_time method
290  * update region_fields_.
291  */
293  {
294  last_time_ = -numeric_limits<double>::infinity();
295  }
296 
297  /**
298  * Setters for essential field properties.
299  */
300  /**
301  * Data shared among copies of the same field.
302  *
303  * This allow field copies in different equations with different time setting, but
304  * sharing common input field descriptor array and common history.
305  */
306  struct SharedData {
307  /**
308  * True for boundary fields.
309  */
310  bool bc_;
311  /**
312  * Number of components for fields that return variable size vectors. Zero in other cases.
313  */
314  unsigned int n_comp_;
315  /**
316  * Name of the particular field. Used to name the key in the Field list Record.
317  */
318  std::string name_;
319  /**
320  * Description of corresponding key in the Field list Record.
321  */
322  std::string desc_;
323  /**
324  * Units of the field values. Currently just a string description.
325  */
326  std::string units_;
327  /**
328  * For Enum valued fields this is the input type selection that should be used
329  * to read possible values of the field (e.g. for FieldConstant the key 'value' has this selection input type).
330  *
331  * Is empty selection for for non-enum values fields.
332  *
333  * In fact we must use raw pointer since selection may not be constructed yet (static variable).
334  */
336  /**
337  * Possible default value of the field.
338  */
339  string default_;
340  /**
341  * Pointer to the mesh on which the field lives.
342  */
343  const Mesh *mesh_;
344 
345  /**
346  * List of input field descriptors from which the field is set.
347  */
349 
350  /**
351  * Iterator to current input field descriptor.
352  */
354 
355  /**
356  * True after check_initialized_region_fields_ is called. That happen at first call of the set_time method.
357  */
359 
360  /**
361  * For which values of an enum valued field we do not
362  * check the field. User is responsible, that the value will not be called
363  * on such regions.
364  */
366 
367 
368  };
369 
370 
371  std::shared_ptr<SharedData> shared_;
372 
373  /**
374  * Which value is returned for times where field is discontinuous.
375  */
377 
378  /**
379  * Result of last set time method
380  */
381  enum class TimeStatus {
382  changed, //< Field changed during last set time call.
383  constant, //< Field doesn't change.
384  unknown //< Before first call of set_time.
385  };
386 
387  /// Status of @p history.
389 
390  /**
391  * Last set time. Can be different for different field copies.
392  */
393  double last_time_ = -numeric_limits<double>::infinity();
394 
395  /**
396  * Output data type used in the output() method. Can be different for different field copies.
397  */
399 
400  /**
401  * Maximum number of FieldBase objects we store per one region.
402  */
403  static const unsigned int history_length_limit_=3;
404 
405  /// Flag field that has to be set as a copy of other field using copy_from method.
406  bool is_copy_=false;
407 
408 };
409 
410 
411 
412 
413 
414 
415 
416 /**
417  * @brief Class template representing a field with values dependent on: point, element, and region.
418  *
419  * By "field" we mean a mapping of a a pair (Point, Time) to a @p Value, where
420  * Point is from @p spacedim dimensional ambient space, Time is real number (set by @p set_time method),
421  * and @p Value type representing range of the field, which can be: real scalar, integer scalar (a discrete value),
422  * real vector of fixed (compile time) size, real vector of runtime size, or a matrix of fixed dimensions.
423  * Extensions to vectors or matrices of integers, or to variable tensors are possible. For vector and matrix values
424  * we use classes provided by Armadillo library for linear algebra.
425  *
426  * 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
427  * region index (very same functionality, but for boundary regions is provided by @p BCField class). This class has interface very similar to FiledBase, however
428  * key methods @p value, and @p value_list are not virtual in this class by contrast these methods are inlined to minimize overhead for
429  * simplest fields like FieldConstant.
430  *
431  * TODO: currently it works only for spacedim==3 since we have only mesh in 3D ambient space.
432  *
433  */
434 template<int spacedim, class Value>
435 class Field : public FieldCommonBase {
436 public:
437 
439  typedef std::shared_ptr< FieldBaseType > FieldBasePtr;
441 
442  static constexpr bool is_enum_valued = boost::is_same<typename Value::element_type, FieldEnum>::value;
443  static const unsigned int space_dim = spacedim;
444 
445 
446  /**
447  * Pointer to function that creates an instance of FieldBase for
448  * field with name @p field_name based on data in field descriptor @p rec.
449  *
450  * Default implementation in method @p read_field_descriptor just reads key given by
451  * @p field_name and creates instance using @p FieldBase<...>::function_factory.
452  * Function should return empty SharedField (that is shared_ptr to FieldBase).
453  *
454  * Hooks are necessary to implement:
455  * 1) backward compatibility with old BCD input files
456  * 2) setting pressure values are piezometric head values
457  */
458  FieldBasePtr (*read_field_descriptor_hook)(Input::Record rec, const FieldCommonBase &field);
459 
460  /**
461  * Default constructor.
462  *
463  */
464  Field();
465 
466  Field(const string &name, bool bc = false);
467 
468  /**
469  * Copy constructor. Keeps shared history, declaration data, mesh.
470  */
471  Field(const Field &other);
472 
473  /**
474  * Assignment operator. Same properties as copy constructor.
475  *
476  * Question: do we really need this, isn't copy constructor enough?
477  */
478  Field &operator=(const Field &other);
479 
480 
481  /**
482  * Returns reference to input type of particular field instance, this is static member @p input_type of the corresponding FieldBase class
483  * (i.e. with same template parameters). However, for fields returning "Enum" we have to create whole unique Input::Type hierarchy using following method
484  * @p meka_input_tree.
485  * every instance since every such field use different Selection for initialization, even if all returns just unsigned int.
486  */
487  IT::AbstractRecord &get_input_type() override;
488 
489 
490  /**
491  * 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
492  * FieldConstant and has value in given @p value_list. We check this in the set_time method. Through this mechanism we
493  * can switch of e.g. boundary data fields according to the type of the boundary condition.
494  */
495  auto disable_where(
496  const Field<spacedim, typename FieldValue<spacedim>::Enum > &control_field,
497  const vector<FieldEnum> &value_list) -> Field &;
498 
499 
500 
501  /**
502  * Set mesh pointer and resize region arrays.
503  *
504  * Implements abstract method.
505  */
506  void set_mesh(const Mesh &mesh) override;
507 
508 
509  /**
510  * Direct read access to the table of Field pointers on regions.
511  */
512  //boost::shared_ptr< FieldBaseType > operator[] (Region reg);
513 
514  /**
515  * Implementation of @p FieldCommonBase::is_constant().
516  */
517  bool is_constant(Region reg) override;
518 
519 
520  /**
521  * Assigns given @p field to all regions in given region set @p domain.
522  * Field is added to the history with given time and possibly used in the next call of the set_time method.
523  * Caller is responsible for correct construction of given field.
524  *
525  * Use this method only if necessary.
526  *
527  * Default time simplify setting steady fields.
528  */
529  void set_field(const RegionSet &domain, FieldBasePtr field, double time=0.0);
530 
531  /**
532  * Same as before but the field is first created using FieldBase::function_factory(), from
533  * given abstract record accessor @p a_rec.
534  */
535  void set_field(const RegionSet &domain, const Input::AbstractRecord &a_rec, double time=0.0);
536 
537  /**
538  * Default implementation of @p read_field_descriptor_hook.
539  *
540  * Reads key given by @p field_name and creates the field instance using
541  * @p FieldBase<...>::function_factory.
542  */
543  static FieldBasePtr read_field_descriptor(Input::Record rec, const FieldCommonBase &field);
544 
545  void set_limit_side(LimitSide side) override
546  { this->limit_side_=side; }
547 
548  /**
549  * Check that whole field list is set, possibly use default values for unset regions
550  * and call set_time for every field in the field list.
551  *
552  * Returns true if the field has been changed.
553  */
554  bool set_time(const TimeGovernor &time) override;
555 
556  /**
557  * Check that other has same type and assign from it.
558  */
559  void copy_from(const FieldCommonBase & other) override;
560 
561  /**
562  * Implementation of FieldCommonBase::output().
563  */
564  void output(OutputTime *stream) override;
565 
566 
567  /**
568  * Returns true, if field is currently set to a time in which it is discontinuous.
569  */
570  //bool is_jump_time();
571 
572 
573  /**
574  * Special field values spatially constant. Could allow optimization of tensor multiplication and
575  * tensor or vector addition. field_result_ should be set in constructor and in set_time method of particular Field implementation.
576  * We return value @p result_none, if the field is not initialized on the region of the given element accessor @p elm.
577  */
578  inline FieldResult field_result( ElementAccessor<spacedim> &elm) const;
579 
580  /**
581  * Returns one value in one given point @p on an element given by ElementAccessor @p elm.
582  * It returns reference to he actual value in order to avoid temporaries for vector and tensor values.
583  */
584  virtual typename Value::return_type const &value(const Point &p, const ElementAccessor<spacedim> &elm) const;
585 
586  /**
587  * Returns std::vector of scalar values in several points at once. The base class implements
588  * trivial implementation using the @p value(,,) method. This is not optimal as it involves lot of virtual calls,
589  * but this overhead can be negligible for more complex fields as Python of Formula.
590  */
591  virtual void value_list(const std::vector< Point > &point_list, const ElementAccessor<spacedim> &elm,
592  std::vector<typename Value::return_type> &value_list) const;
593 
594 protected:
595  /**
596  * For fields returning "enum", i.e. with @p Value == FieldEnum, the input type (meaning whole input_Type tree of the field) depends on the
597  * Input::Type::Selection object that represents particular C enum type. Therefore, we have to create whole tree for the selection
598  * that was set through @p FieldBaseCommon::set_selection() method.
599  */
600  IT::AbstractRecord make_input_tree();
601 
602 
603 
604 
605  /**
606  * Read input into @p regions_history_ possibly pop some old values from the
607  * history queue to keep its size less then @p history_length_limit_.
608  */
609  void update_history(const TimeGovernor &time);
610 
611 
612 
613  /**
614  * Check that whole field list (@p region_fields_) is set, possibly use default values for unset regions.
615  */
616  void check_initialized_region_fields_();
617 
618  /**************** Shared data **************/
619 
620  /// Pair: time, pointer to FieldBase instance
621  typedef pair<double, FieldBasePtr> HistoryPoint;
622  /// Nearest history of one region.
623  typedef boost::circular_buffer<HistoryPoint> RegionHistory;
624 
625  struct SharedData {
626 
627  /**
628  * History for every region. Shared among copies.
629  */
631  };
632 
633  /**************** Data per copy **************/
634 
635  std::shared_ptr<SharedData> data_;
636 
637  /**
638  * If this pointer is set, turn off check of initialization in the
639  * @p set_time method on the regions where the method @p get_constant_enum_value
640  * of the control field returns value from @p no_check_values_. This
641  * field is private copy, its set_time method is called from the
642  * set_Time method of actual object.
643  */
645  std::shared_ptr<ControlField> no_check_control_field_;
646 
647  /**
648  * Table with pointers to fields on individual regions.
649  */
651 
652 
653 
654 };
655 
656 
657 
658 
659 
660 /**
661  * Same as Field<...> but for boundary regions.
662  */
663 template<int spacedim, class Value>
664 class BCField : public Field<spacedim, Value> {
665 public:
666  BCField() : Field<spacedim,Value>("anonymous_bc", true) {}
667 };
668 
669 
670 
671 
672 /**
673  * @brief Class for representation of a vector of fields of the same physical quantity.
674  *
675  * When solving a system of same equations with the number of components given at runtime
676  * (as in the case of transport equation for runtime given number of substances) we need means how to work with the whole
677  * vector of fields at once. This is the aim of this class. It provides the interface given by the parent class @p FieldCommonBase,
678  * but principally it is just a vector of Field<Value,dim> objects. The sub-fields or components of a @p MultiField are independent
679  * objects, how ever the setters propagates the values from the MultiFields to the individual fields. The only exception is the
680  * @p set_name method which in conjunction with @p MultiField::set_subfield_names can set unique name to each component.
681  *
682  * Template parameters are used for every subfield.
683  *
684  * TODO:
685  * - general mechanism how to convert a Field< dim, Vector> to MultiField< dim, Value>
686  * - implement set_from_input
687  * - implement set_Time
688  * - implement set_complemented_vector_field
689  *
690  * - problem with "input" methods, since Field works with AbstratRecord, the MultiField - However - should use Array of AbstractRecords
691  * simplest solution - test that in EqDataBase and have more methods in FieldCommonBase, or somehow detach input handling from
692  * Fields
693  *
694  */
695 template<int spacedim, class Value>
696 class MultiField : public FieldCommonBase {
697 public:
698  //typedef FieldBase<spacedim, Value> SubFieldBaseType;
701 
702  /**
703  * Default constructor.
704  */
705  MultiField();
706 
707  /**
708  * Returns input type of particular field instance, this is usually static member input_type of the corresponding FieldBase class (
709  * with same template parameters), however, for fields returning "Enum" we have to create whole unique Input::Type hierarchy for
710  * every instance since every such field use different Selection for initialization, even if all returns just unsigned int.
711  */
712  IT::AbstractRecord &get_input_type() override;
713 
714  void set_limit_side(LimitSide side) override;
715 
716  /**
717  * Abstract method to update field to the new time level.
718  * Implemented by in class template Field<...>.
719  *
720  * Return true if the value of the field was changed on some region.
721  * The returned value is also stored in @p changed_during_set_time data member.
722  */
723  bool set_time(const TimeGovernor &time) override;
724 
725  /**
726  * We have to override the @p set_mesh method in order to call set_mesh method for subfields.
727  */
728  void set_mesh(const Mesh &mesh) override;
729 
730 
731  /**
732  * Polymorphic copy. Check correct type, allows copy of MultiField or Field.
733  */
734  void copy_from(const FieldCommonBase & other) override;
735 
736  /**
737  * Implementation of @p FieldCommonBase::output().
738  */
739  void output(OutputTime *stream) override;
740 
741  /**
742  * Implementation of @p FieldCommonBase::is_constant().
743  */
744  bool is_constant(Region reg) override;
745 
746  /**
747  * Virtual destructor.
748  */
749  inline virtual ~MultiField() {}
750 
751  /// Number of subfields that compose the multi-field.
752  inline unsigned int size() const
753  { return sub_fields_.size(); }
754 
755  /**
756  * Initialize MultiField to the number of components given by the size of @p names
757  * and use this vector to name individual components. Should be called after the setters derived from
758  * FieldCommonBase.
759  */
760  void init( const vector<string> &names);
761 
762  /**
763  * Allows set Field<dim, Vector> that can be used for alternative initialization in "transposed" form.
764  */
765  void set_complemented_vector_field( TransposedField &complemented);
766 
767  /**
768  * Returns reference to the sub-field (component) of given index @p idx.
769  */
770  inline SubFieldType &operator[](unsigned int idx)
771  { return sub_fields_[idx]; }
772 
773 private:
776 };
777 
778 
779 
780 
781 /****************************************************************************************
782  * Inlined methods of Field< ... >
783  */
784 
785 template<int spacedim, class Value>
786 inline typename Value::return_type const & Field<spacedim,Value>::value(const Point &p, const ElementAccessor<spacedim> &elm) const
787 {
788 
789  ASSERT(this->set_time_result_ != TimeStatus::unknown, "Unknown time status.\n");
790  ASSERT(elm.region_idx().idx() < region_fields_.size(), "Region idx %u out of range %lu, field: %s\n",
791  elm.region_idx().idx(), (unsigned long int) region_fields_.size(), name().c_str());
792  ASSERT( region_fields_[elm.region_idx().idx()] ,
793  "Null field ptr on region id: %d, idx: %d, field: %s\n", elm.region().id(), elm.region_idx().idx(), name().c_str());
794  return region_fields_[elm.region_idx().idx()]->value(p,elm);
795 }
796 
797 
798 
799 template<int spacedim, class Value>
802 {
803  ASSERT(this->set_time_result_ != TimeStatus::unknown, "Unknown time status.\n");
804  ASSERT(elm.region_idx().idx() < region_fields_.size(), "Region idx %u out of range %lu, field: %s\n",
805  elm.region_idx().idx(), (unsigned long int) region_fields_.size(), name().c_str());
806  ASSERT( region_fields_[elm.region_idx().idx()] ,
807  "Null field ptr on region id: %d, field: %s\n", elm.region().id(), name().c_str());
808 
809  region_fields_[elm.region_idx().idx()]->value_list(point_list,elm, value_list);
810 }
811 
812 
813 
814 
815 
816 
817 
818 #endif /* FIELD_HH_ */