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