Flow123d  release_2.1.0-87-gfbc1563
field_common.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_common.hh
15  * @brief
16  */
17 
18 #ifndef FIELD_COMMON_HH_
19 #define FIELD_COMMON_HH_
20 
21 #include <vector>
22 using namespace std;
23 
24 #include "system/exceptions.hh"
25 #include "fields/field_values.hh"
26 #include "input/accessors.hh"
27 #include "input/type_generic.hh"
28 #include "tools/time_marks.hh"
29 #include "tools/time_governor.hh"
30 
32 #include "fields/field_flag.hh"
33 #include "fields/unit_si.hh"
34 #include "io/output_time.hh"
35 
36 
37 class Mesh;
38 class Region;
39 class Observe;
40 
41 namespace IT=Input::Type;
42 
43 /**
44  * Left and right time limit, used in the @p set_time() method.
45  * Assigned values allow to index an array.
46  */
47 enum class LimitSide {
48  left=0,
49  right=1
50 };
51 
52 
53 
54 /**
55  * @brief Common abstract parent of all Field<...> classes.
56  *
57  * We need common ancestor in order to keep a list of all fields in one EqData object and allow
58  * collective operations like @p set_time or @p init_from_input.
59  */
60 class FieldCommon {
61 
62 public:
63  TYPEDEF_ERR_INFO(EI_Time, double);
64  TYPEDEF_ERR_INFO(EI_Field, std::string);
65  DECLARE_INPUT_EXCEPTION(ExcNonascendingTime,
66  << "Non-ascending time: " << EI_Time::val << " for field " << EI_Field::qval << ".\n");
67  DECLARE_INPUT_EXCEPTION(ExcMissingDomain,
68  << "Missing domain specification (region or r_id) in the field descriptor:");
69  DECLARE_EXCEPTION(ExcFieldMeshDifference,
70  << "Two copies of the field " << EI_Field::qval << "call set_mesh with different arguments.\n");
71 
72 
73 
74  /**
75  * Set name of the field. In fact there are two attributes set by this method.
76  *
77  * The first is name used to identify the field as part of a FieldSet or MultiField objects.
78  * This name is permanent and can be set only by this method. Can be accessed by @p name() method.
79  * This name is also used at output.
80  *
81  * The second is @p input_name_ that determines appropriate key name in the input field descriptor.
82  * This name is also set by this method, but is stored in the internal shared space which
83  * is overwritten during call of copy_from method or assignment operator. Can be accessed by @p input_name() mathod.
84  *
85  */
86  FieldCommon &name(const string & name)
87  { name_=shared_->input_name_ = name;
88  return *this;
89  }
90  /**
91  * Set description of the field, used for description of corresponding key in documentation.
92  */
93  FieldCommon & description(const string & description)
94  { shared_->input_description_ = description; return *this;}
95  /**
96  * Set default value for the field's key from which the default constant valued field will be constructed.
97  *
98  * During the first call of the @p set_time method, we check that the field is defined on all regions.
99  * On regions where it is not set yet, we use given @p dflt string to get particular instance of
100  * FieldBase<> (see @p check_initialized_region_fields_).
101  * The default string is interpreted in the same way as if it appears in the input file
102  * as the value of the field. In particular it can be whole record with @p TYPE of the field etc.
103  * Most common choice is however mere constant.
104  */
105  FieldCommon & input_default(const string &input_default)
106  { shared_->input_default_ = input_default; return *this;}
107  /**
108  * @brief Set basic units of the field.
109  *
110  * Currently, we use it only during output and we represents units just by a string.
111  *
112  * TODO:
113  * Particular class for representing and conversion of various units would be more appropriate.
114  * This can allow specification of the units on the inptu, automatic conversion and the same on the output.
115  * Possibly this allow using Boost::Units library, however, it seems to introduce lot of boilerplate code.
116  * But can increase correctness of the calculations.
117  */
118  FieldCommon & units(const UnitSI & units)
119  { shared_->units_ = units; return *this;}
120 
121  /**
122  * Set limits of value of the field.
123  */
124  FieldCommon & set_limits(double min, double max = std::numeric_limits<double>::max())
125  {
126  ASSERT(min < max)(min)(max).error("Invalid field limits!");
127  shared_->limits_ = std::make_pair(min, max);
128  return *this;
129  }
130 
131  /**
132  * For the fields returning "Enum", we have to pass the Input::Type::Selection object to
133  * the field implementations.
134  *
135  * We must save raw pointer since selection may not be yet initialized (during static initialization phase).
136  */
138  {
139  shared_->input_element_selection_=element_selection;
140  return *this;
141  }
142 
143  /**
144  * Output discrete space used in the output() method. Can be different for different field copies.
145  * one can choose between:
146  * data constant on elements, linear data given in nodes, and discontinuous linear data.
147  *
148  * If not set explicitly by this method, the default value is OutputTime::ELEM_DATA
149  */
151  { type_of_output_data_ = rt; return *this; }
152 
153  /**
154  * Set given mask to the field flags, ignoring default setting.
155  * Default setting is declare_input & equation_input & allow_output.
156  */
157  FieldCommon & flags(FieldFlag::Flags::Mask mask)
158  { flags_ = FieldFlag::Flags(mask); return *this; }
159 
160  /**
161  * Add given mask to the field flags.
162  */
163  FieldCommon & flags_add(FieldFlag::Flags::Mask mask)
164  { flags().add(mask); return *this; }
165 
166  /**
167  * Set vector of component names.
168  * Set number of components for run-time sized vectors. This is used latter when we construct
169  * objects derived from FieldBase<...>.
170  *
171  * n_comp_ is constant zero for fixed values, this zero is set by Field<...> constructors
172  */
173  void set_components(const std::vector<string> &names) {
174  // Test of unique values in names vector for MultiField
175  if (multifield_) {
176  std::vector<string> cpy = names;
177  std::sort( cpy.begin(), cpy.end() );
178  cpy.erase( std::unique( cpy.begin(), cpy.end() ), cpy.end() );
179  if (names.size() != cpy.size()) {
180  THROW( Input::ExcInputMessage() << EI_Message("The field " + this->input_name()
181  + " has set non-unique names of components.") );
182  }
183  }
184 
185  shared_->comp_names_ = names;
186  shared_->n_comp_ = (shared_->n_comp_ ? names.size() : 0);
187  }
188 
189 
190  /**
191  * Set internal mesh pointer.
192  */
193  virtual void set_mesh(const Mesh &mesh) {};
194  /**
195  * Set the data list from which field will read its input. It is list of "field descriptors".
196  * When reading from the input list we consider only field descriptors containing key of
197  * named by the field name. These field descriptors has to have times forming ascending sequence.
198  *
199  * The list is used by set_time method to set field on individual regions to actual FieldBase descendants.
200  */
201  virtual void set_input_list(const Input::Array &list) =0;
202 
203  /**
204  * Getters.
205  */
206  const std::string &input_name() const
207  { return shared_->input_name_;}
208 
209  const std::string &name() const
210  { return name_;}
211 
212  const std::string description() const
213  {return shared_->input_description_;}
214 
215  const std::string &input_default() const
216  { return shared_->input_default_;}
217 
218  const UnitSI &units() const
219  {
220  ASSERT(shared_->units_.is_def())(name()).error("Getting undefined unit.\n");
221  return shared_->units_;
222  }
223 
224  std::pair<double, double> limits() const
225  {
226  return shared_->limits_;
227  }
228 
230  { return type_of_output_data_; }
231 
232  bool is_bc() const
233  { return shared_->bc_;}
234 
235  unsigned int n_comp() const
236  { return shared_->n_comp_;}
237 
238  const Mesh * mesh() const
239  { return shared_->mesh_;}
240 
242  { return flags_; }
243 
244  /**
245  * Returns time set by last call of set_time method.
246  * Can be different for different field copies.
247  */
248  double time() const
249  { return last_time_; }
250 
251  /**
252  * Returns true if the field change algorithm for the current time set through the @p set_time method.
253  * This happen for all times in the field descriptors on the input of this particular field.
254  */
255  bool is_jump_time() {
256  return is_jump_time_;
257  }
258 
259  /**
260  * Returns number of field descriptors containing the field.
261  */
262  unsigned int input_list_size() const {
263  return shared_->input_list_.size();
264  }
265 
266  /**
267  * If the field on given region @p reg exists and is of type FieldConstant<...> the method method returns true
268  * otherwise it returns false.
269  * Then one can call ElementAccessor<spacedim>(mesh(), reg ) to construct an ElementAccessor @p elm
270  * pointing to "virtual" element on which Field::value returns constant value.
271  * Unlike the Field<>::field_result method, this one provides no value, so it have common header (arguments, return type) and
272  * could be part of FieldCommon and FieldSet which is useful in some applications.
273  *
274  * TODO:Current implementation use virtual functions and can be prohibitively slow if called for every element. If this
275  * becomes necessary it is possible to incorporate such test into set_time method and in this method just return precomputed result.
276  */
277  virtual bool is_constant(Region reg) =0;
278 
279 
280  /**
281  * @brief Indicates special field states.
282  *
283  * Extension of the previous method. Return possible values from the enum @p FieldResult, see description there.
284  * The initial state is @p field_none, if the field is correctly set on all regions of the @p region_set given as parameter
285  * we return state @p field_other or even more particular result.
286  *
287  * Special field values spatially constant. Could allow optimization of tensor multiplication and
288  * tensor or vector addition. field_result_ should be set in constructor and in set_time method of particular Field implementation.
289  * We return value @p result_none, if the field is not initialized on the region of the given element accessor @p elm.
290  * Other possible results are: result_zeros, result_eye, result_ones, result_constant, result_other
291  * see @p FieldResult for explanation.
292  *
293  * Multifield return most particular value that holds for all its subfields.
294  *
295  *
296  */
297  virtual FieldResult field_result( RegionSet region_set) const =0;
298 
299  /**
300  * Return specification of the field value type in form of the string:
301  * [ <element type>, NRows, NCols]
302  *
303  * Result is valid JSON (and/or flow style YAML).
304  * For multifields not implemented.
305  */
306  virtual std::string get_value_attribute() const =0;
307 
308  /**
309  * Returns true if set_time_result_ is not @p TimeStatus::constant.
310  * Returns the same value as last set_time method.
311  */
312  bool changed() const
313  {
314  ASSERT( set_time_result_ != TimeStatus::unknown ).error("Invalid time status.");
315  return ( (set_time_result_ == TimeStatus::changed) );
316  }
317 
318  /**
319  * Common part of the field descriptor. To get finished record
320  * one has to add keys for individual fields. This is done automatically
321  * using FieldSet::get_input_type().
322  */
323  static IT::Record field_descriptor_record(const string& record_name);
324 
325  /**
326  * Create description of field descriptor record.
327  */
328  static const std::string field_descriptor_record_description(const string& record_name);
329 
330  /**
331  * Returns input type for particular field instance, this is reference to a static member input_type of the corresponding @p FieldBase
332  * class (i.e. with the same template parameters). This is used in FieldSet::make_field_descriptor_type.
333  */
334  virtual IT::Instance get_input_type() =0;
335 
336  /**
337  * Returns input type for MultiField instance.
338  * TODO: temporary solution, see @p multifield_
339  */
340  virtual IT::Array get_multifield_input_type() =0;
341 
342  /**
343  * Pass through the input array @p input_list_, collect all times where the field could change and
344  * put appropriate time marks into global TimeMarks object.
345  * Introduced time marks have both given @p mark_type and @p type_input() type.
346  *
347  * Further development:
348  * - we have to distinguish "jump" times and "smooth" times
349  */
350  void mark_input_times(const TimeGovernor &tg);
351 
352  /**
353  * Abstract method to update field to the new time level.
354  * Implemented by in class template Field<...>.
355  *
356  * Return true if the value of the field was changed on some region.
357  * The returned value is also stored in @p changed_during_set_time data member.
358  *
359  * Default values helps when creating steady field. Note that default TimeGovernor constructor
360  * set time to 0.0.
361  *
362  * Different field copies can be set to different times.
363  *
364  * TODO: update following:
365  * Set side of limit when calling @p set_time
366  * with jump time, i.e. time where the field change implementation on some region.
367  * Wee assume that implementations prescribe only smooth fields.
368  * This method invalidate result of
369  * @p changed() so it should be called just before @p set_time.
370  * Can be different for different field copies.
371  */
372  virtual bool set_time(const TimeStep &time, LimitSide limit_side) =0;
373 
374  /**
375  * Check that @p other is instance of the same Field<..> class and
376  * perform assignment. Polymorphic copy.
377  *
378  * The copy is performed only if *this have set flag 'input_copy'.
379  * If *this have set also the flag 'decare_input' the copy is performed only if the
380  * input_list is empty.
381  */
382  virtual void copy_from(const FieldCommon & other) =0;
383 
384  /**
385  * Output the field.
386  * The parameter @p output_fields is checked for value named by the field name. If the key exists,
387  * then the output of the field is performed. If the key do not appear in the input, no output is done.
388  */
389  virtual void output(std::shared_ptr<OutputTime> stream) =0;
390 
391  /**
392  * Perform the observe output of the field.
393  * The Observe object passed by the parameter is called with the particular Field<> as the parameter
394  * to evaluate the field in observation points and store the values in the OutputData arrays.
395  */
396  virtual void observe_output(std::shared_ptr<Observe> observe) =0;
397 
398 
399  /**
400  * Sets @p component_index_
401  */
402  void set_component_index(unsigned int idx)
403  {
404  this->component_index_ = idx;
405  }
406 
407  /**
408  * Return @p multifield_ flag.
409  * TODO: temporary solution
410  */
411  inline bool is_multifield() const
412  {
413  return this->multifield_;
414  }
415 
416  /**
417  * Virtual destructor.
418  */
419  virtual ~FieldCommon();
420 
421 
422 protected:
423  /**
424  * Private default constructor. Should be used only through
425  * Field<...>
426  */
427  FieldCommon();
428 
429  /**
430  * Private copy constructor. Should be used only through
431  * Field<...>
432  */
433  FieldCommon(const FieldCommon & other);
434 
435  /**
436  * Invalidate last time in order to force set_time method
437  * update region_fields_.
438  */
440  {
441  last_time_ = -numeric_limits<double>::infinity();
442  }
443 
444  /**
445  * Setters for essential field properties.
446  */
447  /**
448  * Data shared among copies of the same field.
449  *
450  * This allow field copies in different equations with different time setting, but
451  * sharing common input field descriptor array and common history.
452  */
453  struct SharedData {
454  /**
455  * Empty constructor.
456  */
458  : list_idx_(0), limits_(std::make_pair(-std::numeric_limits<double>::max(), std::numeric_limits<double>::max())) {};
459 
460  /**
461  * True for boundary fields.
462  */
463  bool bc_;
464  /**
465  * Number of components for fields that return variable size vectors. Zero in other cases.
466  */
467  unsigned int n_comp_;
468  /**
469  * Names of field components.
470  */
472  /**
473  * Name of the particular field. Used to name the key in the Field list Record.
474  */
475  std::string input_name_;
476  /**
477  * Description of corresponding key in the Field list Record.
478  */
479  std::string input_description_;
480  /**
481  * Units of the field values. Currently just a string description.
482  */
484  /**
485  * For Enum valued fields this is the input type selection that should be used
486  * to read possible values of the field (e.g. for FieldConstant the key 'value' has this selection input type).
487  *
488  * Is empty selection for for non-enum values fields.
489  */
491  /**
492  * Possible default value of the field.
493  */
495  /**
496  * Pointer to the mesh on which the field lives.
497  */
498  const Mesh *mesh_;
499 
500  /**
501  * Vector of input field descriptors from which the field is set.
502  */
504 
505  /**
506  * Index to current position of input field descriptor.
507  */
508  unsigned int list_idx_;
509 
510  /**
511  * True after check_initialized_region_fields_ is called. That happen at first call of the set_time method.
512  */
514 
515  /**
516  * For which values of an enum valued field we do not
517  * check the field. User is responsible, that the value will not be called
518  * on such regions.
519  */
521 
522  /**
523  * Allow set minimal and maximal limit value of Field.
524  */
525  std::pair<double, double> limits_;
526 
527 
528  };
529 
530  /**
531  * Name that identifies the field in the field_set. By default this is same as
532  * shared_->input_name_.
533  */
534  std::string name_;
535 
536  /**
537  * Data shared among copies of the same input field.
538  */
539  std::shared_ptr<SharedData> shared_;
540 
541  /**
542  * Result of last set time method
543  */
544  enum class TimeStatus {
545  changed, //< Field changed during last set time call.
546  constant, //< Field doesn't change.
547  unknown //< Before first call of set_time.
548  };
549 
550  // TODO: Merge time information: set_time_result_, last_time_, last_limit_side_, is_jump_time into
551  // a single structure with single getter.
552  /**
553  * Status of @p history.
554  */
556 
557  /**
558  * Last set time. Can be different for different field copies.
559  * Store also time limit, since the field may be discontinuous.
560  */
561  double last_time_ = -numeric_limits<double>::infinity();
562  LimitSide last_limit_side_ = LimitSide::left;
563 
564  /**
565  * Set to true by the @p set_time method the field algorithm change on any region.
566  * Accessible through the @p is_jump_time method.
567  */
569 
570  /**
571  * Output data type used in the output() method. Can be different for different field copies.
572  */
574 
575  /**
576  * Specify if the field is part of a MultiField and which component it is
577  */
578  unsigned int component_index_;
579 
580  /**
581  * Flag determining if object is Multifield or Field.
582  * TODO: temporary solution, goal is to make these two classes to behave similarly
583  */
585 
586  /**
587  * Maximum number of FieldBase objects we store per one region.
588  */
589  static const unsigned int history_length_limit_=3;
590 
591  /// Field flags. Default setting is "an equation input field, that can read from user input, and can be written to output"
593 
594  /**
595  * Stream output operator
596  */
597  friend std::ostream &operator<<(std::ostream &stream, const FieldCommon &field) {
598 
599  vector<string> limit_side_str = {"left", "right"};
600 
601  stream
602  << "field name:" << field.name()
603  << " n. comp.:" << field.n_comp()
604  << " last time:" << field.last_time_
605  << " last limit side:" << limit_side_str[(unsigned int) field.last_limit_side_];
606  return stream;
607  }
608 };
609 
610 
611 
612 
613 
614 
615 
616 #endif /* FIELD_COMMON_HH_ */
virtual void set_mesh(const Mesh &mesh)
std::string input_description_
Common abstract parent of all Field<...> classes.
Definition: field_common.hh:60
std::pair< double, double > limits_
bool is_jump_time_
Accessor to input data conforming to declared Array.
Definition: accessors.hh:561
FieldCommon & input_selection(Input::Type::Selection element_selection)
static constexpr Mask allow_output
The field can output. Is part of generated output selection. (default on)
Definition: field_flag.hh:37
FieldCommon & flags_add(FieldFlag::Flags::Mask mask)
std::string name_
#define DECLARE_EXCEPTION(ExcName, Format)
Macro for simple definition of exceptions.
Definition: exceptions.hh:150
unsigned int component_index_
std::pair< double, double > limits() const
vector< Input::Record > input_list_
Definition: mesh.h:95
Helper class that stores data of generic types.
Definition: type_generic.hh:88
double last_time_
const std::string & input_default() const
#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).
FieldCommon & units(const UnitSI &units)
Set basic units of the field.
const std::string description() const
Basic time management class.
Class for declaration of inputs sequences.
Definition: type_base.hh:339
std::shared_ptr< SharedData > shared_
OutputTime::DiscreteSpace output_type() const
double time() const
friend std::ostream & operator<<(std::ostream &stream, const FieldCommon &field)
const std::string & name() const
FieldFlag::Flags & flags()
FieldCommon & input_default(const string &input_default)
const UnitSI & units() const
unsigned int input_list_size() const
bool is_multifield() const
LimitSide last_limit_side_
#define TYPEDEF_ERR_INFO(EI_Type, Type)
Macro to simplify declaration of error_info types.
Definition: exceptions.hh:186
std::vector< FieldEnum > no_check_values_
FieldResult
bool is_jump_time()
#define DECLARE_INPUT_EXCEPTION(ExcName, Format)
Macro for simple definition of input exceptions.
FieldCommon & description(const string &description)
Definition: field_common.hh:93
void set_component_index(unsigned int idx)
IT::Selection input_element_selection_
const Mesh * mesh() const
FieldCommon & name(const string &name)
Definition: field_common.hh:86
unsigned int n_comp() const
bool changed() const
void set_components(const std::vector< string > &names)
Record type proxy class.
Definition: type_record.hh:177
void set_history_changed()
FieldCommon & set_limits(double min, double max=std::numeric_limits< double >::max())
FlagArray< FieldFlag > Flags
Definition: field_flag.hh:26
FieldCommon & flags(FieldFlag::Flags::Mask mask)
const std::string & input_name() const
static constexpr Mask equation_input
The field is data parameter of the owning equation. (default on)
Definition: field_flag.hh:33
Class for representation SI units of Fields.
Definition: unit_si.hh:40
bool is_bc() const
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:45
Representation of one time step..
TimeStatus set_time_result_
Template for classes storing finite set of named values.
LimitSide
Definition: field_common.hh:47
FieldCommon & output_type(OutputTime::DiscreteSpace rt)
static constexpr Mask declare_input
The field can be set from input. The key in input field descriptor is declared. (default on) ...
Definition: field_flag.hh:35
std::vector< std::string > comp_names_