Flow123d  master-1cc3435
multi_field.impl.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 multi_field.impl.hh
15  * @brief
16  */
17 
18 #ifndef MULTI_FIELD_IMPL_HH_
19 #define MULTI_FIELD_IMPL_HH_
20 
21 
22 #include "multi_field.hh"
24 #include "fem/integral_acc.hh"
25 #include "fem/eval_points.hh"
26 #include "fem/element_cache_map.hh"
27 #include "fields/field_set.hh"
28 #include "input/input_exception.hh"
29 #include "io/observe.hh"
30 
31 struct AssemblyInternals;
32 
33 namespace it = Input::Type;
34 
35 /******************************************************************************************
36  * Implementation of MultiField<...>
37  */
38 
39 template<int spacedim, class Value>
41 : FieldCommon(),
42  no_check_control_field_(nullptr)
43 {
44 // static_assert(Value::NRows_ == 1 && Value::NCols_ == 1, "");
45  this->multifield_ = true;
46  this->set_shape( Value::NRows_, Value::NCols_ );
47 }
48 
49 
50 
51 template<int spacedim, class Value>
53 : FieldCommon(other),
54  sub_fields_(other.sub_fields_),
55  full_input_list_(other.full_input_list_),
56  no_check_control_field_(other.no_check_control_field_)
57 {
58  this->multifield_ = true;
59  this->set_shape( Value::NRows_, Value::NCols_ );
60 }
61 
62 
63 
64 template<int spacedim, class Value>
66 {
67  //ASSERT( flags().match( FieldFlag::input_copy )(this->name())(other.name()).error("Try to assign to non-copy field.");
68  ASSERT_PTR(other.shared_->mesh_).error("Must call set_mesh before assign to other field.\n");
69  ASSERT( !shared_->mesh_ || (shared_->mesh_==other.shared_->mesh_))
70  .error("Assignment between multi fields with different meshes.\n");
71  ASSERT_GT( shared_->comp_names_.size(), 0).error("Vector of component names can't be empty!\n");
72  ASSERT_EQ( shared_->comp_names_.size(), other.shared_->comp_names_.size())
73  .error("Both multi fields must have same size of vectors of component names.\n");
74 
75  // check for self assignement
76  if (&other == this) return *this;
77 
78  // class members derived from FieldCommon
79  std::vector< std::string > comp_names = shared_->comp_names_; // keep component names
80  shared_ = other.shared_;
81  shared_->comp_names_ = comp_names;
82  shared_->is_fully_initialized_ = false;
83  set_time_result_ = other.set_time_result_;
84  last_time_ = other.last_time_;
85  last_limit_side_ = other.last_limit_side_;
86  is_jump_time_ = other.is_jump_time_;
87  component_index_ = other.component_index_;
88  this->multifield_ = true;
89  this->shape_ = other.shape_;
90 
91  // class members of Field class
92  if ( size() == 0 ) {
93  // move subfields from other, set correct names
94  sub_fields_.clear();
95  sub_fields_.reserve( other.size() );
96  for (unsigned int i=0; i<other.size(); ++i) {
97  sub_fields_.push_back( other.sub_fields_[i] );
98  if (this->shared_->comp_names_[i].length() == 0)
99  THROW( Input::ExcInputMessage() << EI_Message("The field " + this->input_name()
100  + " has set empty name of component.") );
101  else {
102  sub_fields_[i].name_ = this->shared_->comp_names_[i] + "_" + name();
103  }
104  }
105  } else {
106  THROW( ExcMessage() << EI_Message("Internal error. Assignment operator can't be used after call setup_component() method.") );
107  }
108  full_input_list_ = other.full_input_list_;
109  no_check_control_field_ = other.no_check_control_field_;
110 
111  return *this;
112 }
113 
114 
115 
116 template<int spacedim, class Value>
118  ASSERT_PERMANENT(false).error("This method can't be used for MultiField");
119 
120  it::Abstract abstract = it::Abstract();
122  return inst;
123 }
124 
125 
126 template<int spacedim, class Value>
128  it::Array type = it::Array( SubFieldBaseType::get_input_type_instance(shared_->input_element_selection_), 1);
129  return type;
130 }
131 
132 
133 template<int spacedim, class Value>
135  const MultiField<spacedim, typename FieldValue<spacedim>::Enum > &control_field,
136  const vector<FieldEnum> &value_list) -> MultiField &
137 {
138  no_check_control_field_=&control_field;
139  shared_->no_check_values_=value_list;
140  return *this;
141 }
142 
143 
144 template<int spacedim, class Value>
146  const TimeStep &time, LimitSide limit_side)
147 {
148  // initialization of Multifield for first call
149  if (sub_fields_.size() == 0) {
150  setup_components();
151  }
152 
153  // set time for sub fields
154  set_time_result_ = TimeStatus::constant;
155  is_jump_time_=false;
156  for( SubFieldType &field : sub_fields_) {
157  if (field.set_time(time, limit_side))
158  set_time_result_ = TimeStatus::changed;
159  is_jump_time_ = is_jump_time_ || field.is_jump_time();
160  }
161  return (set_time_result_ == TimeStatus::changed);
162 }
163 
164 
165 
166 template<int spacedim, class Value>
168  // test if mesh is not set
169  if (shared_->mesh_ && shared_->mesh_ != &mesh) {
170  THROW(ExcFieldMeshDifference() << EI_Field(name()) );
171  }
172 
173  shared_->mesh_ = &mesh;
174 }
175 
176 
177 template<int spacedim, class Value>
179  ASSERT( flags().match(FieldFlag::equation_input))(other.name())(this->name())
180  .error("Can not copy to the non-copy field.");
181 
182  // do not use copy if the field have its own input
183  if ( flags().match(FieldFlag::declare_input)
184  && this->shared_->input_list_.size() != 0 ) return;
185 
186  if (typeid(other) == typeid(*this)) {
187  auto const &other_field = dynamic_cast< MultiField<spacedim, Value> const &>(other);
188  this->operator=(other_field);
189  } else if (typeid(other) == typeid(SubFieldType)) {
190  auto const &other_field = dynamic_cast< SubFieldType const &>(other);
191  sub_fields_.resize(1);
192  sub_fields_[0] = other_field;
193  }
194 }
195 
196 
197 
198 template<int spacedim, class Value>
199 void MultiField<spacedim, Value>::field_output(std::shared_ptr<OutputTime> stream, OutputTime::DiscreteSpace type)
200 {
201  ASSERT_LT( type, OutputTime::N_DISCRETE_SPACES ).error();
202 
203  for (unsigned long index=0; index < this->size(); index++) {
204  sub_fields_[index].compute_field_data( type, stream );
205  }
206 }
207 
208 
209 
210 
211 template<int spacedim, class Value>
213  bool const_all=true;
214  for(auto &field : sub_fields_) const_all = const_all && field.is_constant(reg);
215  return const_all;
216 }
217 
218 template<int spacedim, class Value>
220 {
221  ASSERT(true).error("Not used yet. Test it.");
222 
223  FieldResult result_all = result_none;
224  for(auto &field : sub_fields_) {
225  FieldResult sub_result = field.field_result(region_set);
226  if (sub_result == result_none) return result_none;
227 
228  if (result_all == result_none) // first subfield
229  result_all = sub_result;
230  else if (sub_result == result_other || result_all == result_other)
231  result_all = result_other;
232  else if (sub_result != result_all)
233  result_all = result_constant; // all subfields are (possibly different) constants
234  }
235 
236  return result_all;
237 
238 }
239 
240 
241 template<int spacedim, class Value>
243 {
244  int nrows = Value::NRows_;
245  int ncols = Value::NCols_;
246  string type = "Integer";
248  type = "Double";
249 
250  return fmt::format("{{ \"subfields\": true, \"shape\": [ {}, {} ], \"type\": \"{}\", \"limit\": [ {}, {} ] }}",
251  nrows, ncols, type, this->limits().first, this->limits().second);
252 }
253 
254 
255 template<int spacedim, class Value>
257  unsigned int comp_size = this->shared_->comp_names_.size();
258  ASSERT_GT(comp_size, 0).error("Vector of component names is empty!\n");
259  ASSERT_PTR(this->shared_->mesh_).error("Mesh is not set!\n");
260 
261  sub_fields_.reserve( comp_size );
262  for(unsigned int i_comp=0; i_comp < comp_size; i_comp++)
263  {
264  sub_fields_.push_back( SubFieldType(i_comp, name(), this->full_comp_name(i_comp)) );
265  sub_fields_[i_comp].units( units() );
266  if (no_check_control_field_ != nullptr && no_check_control_field_->size() == sub_fields_.size())
267  sub_fields_[i_comp].disable_where((*no_check_control_field_)[i_comp], shared_->no_check_values_);
268  sub_fields_[i_comp].set_mesh( *(shared_->mesh_) );
269 // sub_fields_[i_comp].set_limit_side(this->limit_side_);
270  sub_fields_[i_comp].input_selection(shared_->input_element_selection_);
271  sub_fields_[i_comp].add_factory( std::make_shared<MultiFieldFactory>(i_comp) );
272 
273  if (this->shared_->input_default_!="") {
274  sub_fields_[i_comp].shared_->input_default_ = this->shared_->input_default_;
275  }
276 
277  sub_fields_[i_comp].flags_ = this->flags_;
278  sub_fields_[i_comp].set_input_list(this->full_input_list_, *tg_);
279  sub_fields_[i_comp].set_default_fieldset( *(this->shared_->default_fieldset_) );
280  }
281 }
282 
283 
284 
285 template<int spacedim, class Value>
287  if (! flags().match(FieldFlag::declare_input)) return;
288 
289  // Check sizes of Arrays defined MultiField in field descriptors
291  it != list.end();
292  ++it) {
293  Input::Array mf_array;
294  if ( it->opt_val(this->input_name(), mf_array) ) {
295  unsigned int comp_size = this->shared_->comp_names_.size();
296  if (mf_array.size() != 1 && mf_array.size() != comp_size)
297  THROW( Exc_InvalidMultiFieldSize() << EI_MultiFieldName(this->input_name())
298  << EI_Size(mf_array.size()) << EI_ExpectedSize(comp_size) << list.ei_address() );
299  }
300  }
301 
302  this->full_input_list_ = list;
303  this->tg_ = &tg;
304 
305  // Save the full array for future use in FieldCommon::mark_input_times().
306  list.copy_to(shared_->input_list_);
307 }
308 
309 
310 
311 template<int spacedim, class Value>
313  Input::Array multifield_arr;
314  if (descriptor_rec.opt_val(field.input_name(), multifield_arr))
315  {
316  //ASSERT_PERMANENT(multifield_arr.size() == 1 || multifield_arr.size() == field.n_comp() )(field.input_name())
317  // .error("Invalid size of Array defined for MultiField!\n";
318  unsigned int position = 0;
319  auto it = multifield_arr.begin<Input::AbstractRecord>();
320  if (multifield_arr.size() > 1)
321  while (index_ != position) {
322  ++it; ++position;
323  }
324 
325  FieldAlgoBaseInitData init_data(field.input_name(), field.n_comp(), field.units(), field.limits(), field.get_flags());
327  field_algo_base->set_component_idx(index_);
328  return field_algo_base;
329  }
330 
331  return NULL;
332 }
333 
334 
335 
336 template<int spacedim, class Value>
338  return in_rec.find<Input::Array>(input_name);
339 }
340 
341 
342 template<int spacedim, class Value>
344  ASSERT_PERMANENT(false).error("Set dependency of MultiField should be performed by individual components!\n");
346 }
347 
348 
349 
350 template<int spacedim, class Value>
351 void MultiField<spacedim, Value>::cache_reallocate(FMT_UNUSED AssemblyInternals &asm_internals, FMT_UNUSED unsigned int region_idx) const {
352  //for(auto &field : sub_fields_) field.cache_reallocate(cache_map);
353  ASSERT_PERMANENT(false).error("Cache reallocate of MultiField should be performed by individual components!\n");
354 }
355 
356 
357 template<int spacedim, class Value>
359  FMT_UNUSED unsigned int region_patch_idx) const {
360  ASSERT_PERMANENT(false).error("Cache update of MultiField should be performed by individual components!\n");
361 }
362 
363 
364 template<int spacedim, class Value>
367  double time,
368  std::vector<std::string> region_set_names)
369 {
370  unsigned int comp_size = this->shared_->comp_names_.size();
371  ASSERT_GT(comp_size, 0).error("Vector of component names is empty!\n");
372  ASSERT_EQ(comp_size, field_vec.size());
373  ASSERT_PTR(this->shared_->mesh_).error("Mesh is not set!\n");
374 
375  sub_fields_.reserve( comp_size );
376  for(unsigned int i_comp=0; i_comp < comp_size; i_comp++)
377  {
378  sub_fields_.push_back( SubFieldType(i_comp, name(), "") );
379  sub_fields_[i_comp].set_mesh( *(shared_->mesh_) );
380  sub_fields_[i_comp].flags_ = this->flags_;
381  sub_fields_[i_comp].set(field_vec[i_comp], time, region_set_names);
382  }
383 }
384 
385 
386 template<int spacedim, class Value>
389  double time,
390  std::vector<std::string> region_set_names)
391 {
392  ASSERT_EQ(this->shared_->comp_names_.size(), 1).error("Size of component names vector must be 1!\n");
393  ASSERT_PTR(this->shared_->mesh_).error("Mesh is not set!\n");
394 
395  sub_fields_.reserve(1);
396  sub_fields_.push_back( SubFieldType(0, name(), "") );
397  sub_fields_[0].set_mesh( *(shared_->mesh_) );
398  sub_fields_[0].flags_ = this->flags_;
399  sub_fields_[0].set(field, time, region_set_names);
400 }
401 
402 
403 
404 #endif /* MULTI_FIELD_IMPL_HH_ */
#define ASSERT(expr)
Definition: asserts.hh:351
#define ASSERT_PERMANENT(expr)
Allow use shorter versions of macro names if these names is not used with external library.
Definition: asserts.hh:348
#define ASSERT_LT(a, b)
Definition of comparative assert macro (Less Than) only for debug mode.
Definition: asserts.hh:301
#define ASSERT_EQ(a, b)
Definition of comparative assert macro (EQual) only for debug mode.
Definition: asserts.hh:333
#define ASSERT_GT(a, b)
Definition of comparative assert macro (Greater Than) only for debug mode.
Definition: asserts.hh:317
#define ASSERT_PTR(ptr)
Definition of assert macro checking non-null pointer (PTR) only for debug mode.
Definition: asserts.hh:341
Directing class of FieldValueCache.
static std::shared_ptr< FieldAlgorithmBase< spacedim, Value > > function_factory(const Input::AbstractRecord &rec, const struct FieldAlgoBaseInitData &init_data)
Common abstract parent of all Field<...> classes.
Definition: field_common.hh:78
std::shared_ptr< SharedData > shared_
TimeStatus set_time_result_
unsigned int component_index_
const std::string & input_name() const
FieldFlag::Flags flags_
Field flags. Default setting is "an equation input field, that can read from user input,...
const std::string & name() const
LimitSide last_limit_side_
std::vector< uint > shape_
double last_time_
FieldCommon & name(const string &name)
std::pair< double, double > limits() const
FieldFlag::Flags get_flags() const
double time() const
void set_shape(uint n_rows, uint n_cols)
bool is_jump_time_
FieldCommon & units(const UnitSI &units)
Set basic units of the field.
unsigned int n_comp() const
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
static constexpr Mask equation_input
The field is data parameter of the owning equation. (default on)
Definition: field_flag.hh:33
Class template representing a field with values dependent on: point, element, and region.
Definition: field.hh:93
std::shared_ptr< FieldBaseType > FieldBasePtr
Definition: field.hh:97
Accessor to the polymorphic input data of a type given by an AbstracRecord object.
Definition: accessors.hh:458
Accessor to input data conforming to declared Array.
Definition: accessors.hh:566
Iterator< ValueType > begin() const
unsigned int size() const
Accessor to the data with type Type::Record.
Definition: accessors.hh:291
bool opt_val(const string &key, Ret &value) const
Iterator< Ret > find(const string &key) const
Class for declaration of polymorphic Record.
Class for declaration of inputs sequences.
Definition: type_base.hh:339
Helper class that stores data of generic types.
Definition: type_generic.hh:89
Definition: mesh.h:362
virtual Field< spacedim, Value >::FieldBasePtr create_field(Input::Record rec, const FieldCommon &field)
bool is_active_field_descriptor(const Input::Record &in_rec, const std::string &input_name) override
Class for representation of a vector of fields of the same physical quantity.
Definition: multi_field.hh:88
std::string get_value_attribute() const override
Input::Array full_input_list_
Full list of input field descriptors from which the subfields of MultiField are set.
Definition: multi_field.hh:284
void copy_from(const FieldCommon &other) override
std::vector< const FieldCommon * > set_dependency(unsigned int i_reg) const override
void field_output(std::shared_ptr< OutputTime > stream, OutputTime::DiscreteSpace type) override
bool set_time(const TimeStep &time, LimitSide limit_side) override
void setup_components()
MultiField & operator=(const MultiField &other)
void cache_update(ElementCacheMap &cache_map, unsigned int region_patch_idx) const override
Implements FieldCommon::cache_update.
unsigned int size() const
Number of subfields that compose the multi-field.
Definition: multi_field.hh:201
IT::Instance get_input_type() override
auto disable_where(const MultiField< spacedim, typename FieldValue< spacedim >::Enum > &control_field, const vector< FieldEnum > &value_list) -> MultiField &
void cache_reallocate(AssemblyInternals &asm_internals, unsigned int region_idx) const override
Implements FieldCommon::cache_reallocate.
std::vector< SubFieldType > sub_fields_
Subfields (items) of MultiField.
Definition: multi_field.hh:281
Field< spacedim, Value > SubFieldType
Definition: multi_field.hh:91
void set_input_list(const Input::Array &list, const TimeGovernor &tg) override
IT::Array get_multifield_input_type() override
void set_mesh(const Mesh &mesh) override
const MultiField< spacedim, typename FieldValue< spacedim >::Enum > * no_check_control_field_
Definition: multi_field.hh:296
void set(std::vector< typename Field< spacedim, Value >::FieldBasePtr > field_vec, double time, std::vector< std::string > region_set_names={"ALL"})
FieldResult field_result(RegionSet region_set) const override
Indicates special field states.
bool is_constant(Region reg) override
static const unsigned int N_DISCRETE_SPACES
Definition: output_time.hh:107
Basic time management functionality for unsteady (and steady) solvers (class Equation).
Representation of one time step..
FieldResult
@ result_other
@ result_constant
@ result_none
LimitSide
Definition: field_common.hh:65
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
static constexpr bool value
Definition: json.hpp:87
std::string format(CStringRef format_str, ArgList args)
Definition: format.h:3141
#define FMT_UNUSED
Definition: posix.h:75
Holds common data shared between GenericAssemblz and Assembly<dim> classes.
Helper struct stores data for initizalize descentants of FieldAlgorithmBase.