Flow123d  release_1.8.2-1603-g0109a2b
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 "input/input_exception.hh"
25 
26 namespace it = Input::Type;
27 
28 /******************************************************************************************
29  * Implementation of MultiField<...>
30  */
31 
32 template<int spacedim, class Value>
34 : FieldCommon(),
35  no_check_control_field_(nullptr)
36 {
37  static_assert(Value::NRows_ == 1 && Value::NCols_ == 1, "");
38  this->multifield_ = true;
39  this->shared_->bc_ = bc;
40 }
41 
42 
43 
44 template<int spacedim, class Value>
46 : FieldCommon(other),
47  sub_fields_(other.sub_fields_),
50 {
51  this->multifield_ = true;
52 }
53 
54 
55 
56 template<int spacedim, class Value>
58 {
59  OLD_ASSERT( flags().match( FieldFlag::input_copy ) , "Try to assign to non-copy field '%s' from the field '%s'.", this->name().c_str(), other.name().c_str());
60  OLD_ASSERT(other.shared_->mesh_, "Must call set_mesh before assign to other field.\n");
61  OLD_ASSERT( !shared_->mesh_ || (shared_->mesh_==other.shared_->mesh_),
62  "Assignment between multi fields with different meshes.\n");
63  OLD_ASSERT( shared_->comp_names_.size(), "Vector of component names can't be empty!\n");
64  OLD_ASSERT( shared_->comp_names_.size()==other.shared_->comp_names_.size(),
65  "Both multi fields must have same size of vectors of component names.\n");
66 
67  // check for self assignement
68  if (&other == this) return *this;
69 
70  // class members derived from FieldCommon
71  std::vector< std::string > comp_names = shared_->comp_names_; // keep component names
72  shared_ = other.shared_;
73  shared_->comp_names_ = comp_names;
74  shared_->is_fully_initialized_ = false;
76  last_time_ = other.last_time_;
80  this->multifield_ = true;
81 
82  // class members of Field class
83  if ( size() == 0 ) {
84  // move subfields from other, set correct names
85  sub_fields_.clear();
86  sub_fields_.reserve( other.size() );
87  for (unsigned int i=0; i<other.size(); ++i) {
88  sub_fields_.push_back( other.sub_fields_[i] );
89  if (this->shared_->comp_names_[i].length() == 0)
90  THROW( Input::ExcInputMessage() << EI_Message("The field " + this->input_name()
91  + " has set empty name of component.") );
92  else {
93  sub_fields_[i].name_ = this->shared_->comp_names_[i] + "_" + name();
94  }
95  }
96  } else {
97  THROW( ExcMessage() << EI_Message("Internal error. Assignment operator can't be used after call setup_component() method.") );
98  }
101 
102  return *this;
103 }
104 
105 
106 
107 template<int spacedim, class Value>
109  OLD_ASSERT(false, "This method can't be used for MultiField");
110 
111  it::Abstract abstract = it::Abstract();
113  return inst;
114 }
115 
116 
117 template<int spacedim, class Value>
119  it::Array type = it::Array( SubFieldBaseType::get_input_type_instance(shared_->input_element_selection_), 1);
120  return type;
121 }
122 
123 
124 template<int spacedim, class Value>
126  const MultiField<spacedim, typename FieldValue<spacedim>::Enum > &control_field,
128 {
129  no_check_control_field_=&control_field;
130  shared_->no_check_values_=value_list;
131  return *this;
132 }
133 
134 
135 template<int spacedim, class Value>
137  const TimeStep &time, LimitSide limit_side)
138 {
139  // initialization of Multifield for first call
140  if (sub_fields_.size() == 0) {
142  }
143 
144  // set time for sub fields
146  is_jump_time_=false;
147  for( SubFieldType &field : sub_fields_) {
148  if (field.set_time(time, limit_side))
150  is_jump_time_ = is_jump_time_ || field.is_jump_time();
151  }
153 }
154 
155 
156 
157 template<int spacedim, class Value>
159  // test if mesh is not set
160  if (shared_->mesh_ && shared_->mesh_ != &mesh) {
161  THROW(ExcFieldMeshDifference() << EI_Field(name()) );
162  }
163 
164  shared_->mesh_ = &mesh;
165 }
166 
167 
168 template<int spacedim, class Value>
170  if (typeid(other) == typeid(*this)) {
171  auto const &other_field = dynamic_cast< MultiField<spacedim, Value> const &>(other);
172  this->operator=(other_field);
173  } else if (typeid(other) == typeid(SubFieldType)) {
174  auto const &other_field = dynamic_cast< SubFieldType const &>(other);
175  sub_fields_.resize(1);
176  sub_fields_[0] = other_field;
177  }
178 }
179 
180 
181 
182 template<int spacedim, class Value>
183 void MultiField<spacedim, Value>::output(std::shared_ptr<OutputTime> stream)
184 {
185  // currently we cannot output boundary fields
186  if (!is_bc())
187  stream->register_data(this->output_type(), *this);
188 }
189 
190 
191 
192 
193 
194 template<int spacedim, class Value>
196  bool const_all=true;
197  for(auto &field : sub_fields_) const_all = const_all && field.is_constant(reg);
198  return const_all;
199 }
200 
201 
202 
203 template<int spacedim, class Value>
205  unsigned int comp_size = this->shared_->comp_names_.size();
206  string full_name;
207  OLD_ASSERT(comp_size, "Vector of component names is empty!\n");
208  OLD_ASSERT(this->shared_->mesh_, "Mesh is not set!\n");
209 
210  sub_fields_.reserve( comp_size );
211  for(unsigned int i_comp=0; i_comp < comp_size; i_comp++)
212  {
213  if (this->shared_->comp_names_[i_comp].length() == 0)
214  full_name = name();
215  else {
216  full_name = this->shared_->comp_names_[i_comp] + "_" + name();
217  }
218 
219  sub_fields_.push_back( SubFieldType(i_comp, name(), full_name, is_bc()) );
220  sub_fields_[i_comp].units( units() );
221  if (no_check_control_field_ != nullptr && no_check_control_field_->size() == sub_fields_.size())
222  sub_fields_[i_comp].disable_where((*no_check_control_field_)[i_comp], shared_->no_check_values_);
223  sub_fields_[i_comp].set_mesh( *(shared_->mesh_) );
224 // sub_fields_[i_comp].set_limit_side(this->limit_side_);
225  sub_fields_[i_comp].input_selection(shared_->input_element_selection_);
226  sub_fields_[i_comp].add_factory( std::make_shared<MultiFieldFactory>(i_comp) );
227 
228  if (this->shared_->input_default_!="") {
229  sub_fields_[i_comp].shared_->input_default_ = this->shared_->input_default_;
230  }
231 
232  sub_fields_[i_comp].flags_ = this->flags_;
233  sub_fields_[i_comp].set_input_list(this->full_input_list_);
234  }
235 }
236 
237 
238 
239 template<int spacedim, class Value>
241  if (! flags().match(FieldFlag::declare_input)) return;
242 
243  // Check sizes of Arrays defined MultiField in field descriptors
245  it != list.end();
246  ++it) {
247  Input::Array mf_array;
248  if ( it->opt_val(this->input_name(), mf_array) ) {
249  unsigned int comp_size = this->shared_->comp_names_.size();
250  if (mf_array.size() != 1 && mf_array.size() != comp_size)
251  THROW( Exc_InvalidMultiFieldSize() << EI_MultiFieldName(this->input_name())
252  << EI_Size(mf_array.size()) << EI_ExpectedSize(comp_size) << list.ei_address() );
253  }
254  }
255 
256  this->full_input_list_ = list;
257 
258  // Save the full array for future use in FieldCommon::mark_input_times().
259  list.copy_to(shared_->input_list_);
260 }
261 
262 
263 template<int spacedim, class Value>
265  typename MultiFieldValue::return_type ret(size(), 1);
266  for (unsigned int i_comp=0; i_comp < size(); i_comp++) {
267  ret(i_comp, 0) = sub_fields_[i_comp].value(p,elm);
268  }
269 
270  return ret;
271 }
272 
273 
274 
275 template<int spacedim, class Value>
278  OLD_ASSERT_EQUAL( point_list.size(), value_list.size() );
279  for(unsigned int i=0; i< point_list.size(); i++) {
280  value_list[i]=this->value(point_list[i], elm);
281  }
282 }
283 
284 
285 
286 template<int spacedim, class Value>
288  Input::Array multifield_arr;
289  if (descriptor_rec.opt_val(field.input_name(), multifield_arr))
290  {
291  //OLD_ASSERT(multifield_arr.size() == 1 || multifield_arr.size() == field.n_comp(),
292  // "Invalid size of Array defined for MultiField '%s'!\n", field.input_name().c_str());
293  unsigned int position = 0;
294  auto it = multifield_arr.begin<Input::AbstractRecord>();
295  if (multifield_arr.size() > 1)
296  while (index_ != position) {
297  ++it; ++position;
298  }
299 
301  field_algo_base->set_component_idx(index_);
302  return field_algo_base;
303  }
304 
305  return NULL;
306 }
307 
308 
309 
310 template<int spacedim, class Value>
312  return in_rec.find<Input::Array>(input_name);
313 }
314 
315 
316 
317 #endif /* MULTI_FIELD_IMPL_HH_ */
void set_input_list(const Input::Array &list) override
IT::Instance get_input_type() override
Iterator< ValueType > begin() const
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
EI_Address ei_address() const
Definition: accessors.cc:329
auto disable_where(const MultiField< spacedim, typename FieldValue< spacedim >::Enum > &control_field, const vector< FieldEnum > &value_list) -> MultiField &
unsigned int size() const
Number of subfields that compose the multi-field.
Definition: multi_field.hh:156
bool is_active_field_descriptor(const Input::Record &in_rec, const std::string &input_name) override
void copy_from(const FieldCommon &other) override
Class template representing a field with values dependent on: point, element, and region...
Definition: field.hh:62
unsigned int component_index_
Field< spacedim, Value > SubFieldType
Definition: multi_field.hh:58
Definition: mesh.h:99
const MultiField< spacedim, typename FieldValue< spacedim >::Enum > * no_check_control_field_
Definition: multi_field.hh:214
Iterator< Ret > find(const string &key) const
Helper class that stores data of generic types.
Definition: type_generic.hh:88
internal::ReturnType< NRows, NCols, ET >::return_type return_type
double last_time_
void output(std::shared_ptr< OutputTime > stream) override
MultiField & operator=(const MultiField &other)
Input::Array full_input_list_
Full list of input field descriptors from which the subfields of MultiField are set.
Definition: multi_field.hh:205
Class for declaration of inputs sequences.
Definition: type_base.hh:316
static const Input::Type::Instance & get_input_type_instance(const Input::Type::Selection *value_selection=NULL)
std::shared_ptr< SharedData > shared_
IteratorBase end() const
OutputTime::DiscreteSpace output_type() const
#define OLD_ASSERT(...)
Definition: global_defs.h:128
void setup_components()
bool opt_val(const string &key, Ret &value) const
double time() const
const std::string & name() const
std::vector< SubFieldType > sub_fields_
Subfields (items) of MultiField.
Definition: multi_field.hh:202
static constexpr Mask input_copy
A field that is input of its equation and can not read from input, thus must be set by copy...
Definition: field_flag.hh:39
FieldFlag::Flags & flags()
virtual Field< spacedim, Value >::FieldBasePtr create_field(Input::Record rec, const FieldCommon &field)
const UnitSI & units() const
FieldFlag::Flags flags_
Field flags. Default setting is "an equation input field, that can read from user input...
Accessor to the data with type Type::Record.
Definition: accessors.hh:277
static std::shared_ptr< FieldAlgorithmBase< spacedim, Value > > function_factory(const Input::AbstractRecord &rec, unsigned int n_comp=0)
bool set_time(const TimeStep &time, LimitSide limit_side) override
LimitSide last_limit_side_
MultiField(bool bc=false)
Class for declaration of polymorphic Record.
Accessor to the polymorphic input data of a type given by an AbstracRecord object.
Definition: accessors.hh:444
FieldAlgorithmBase< spacedim, Value >::Point Point
Definition: multi_field.hh:60
std::shared_ptr< FieldBaseType > FieldBasePtr
Definition: field.hh:66
void copy_to(Container &out) const
bool is_constant(Region reg) override
virtual MultiFieldValue::return_type value(const Point &p, const ElementAccessor< spacedim > &elm) const
IT::Array get_multifield_input_type() override
const Mesh * mesh() const
FieldCommon & name(const string &name)
Definition: field_common.hh:83
unsigned int n_comp() const
#define OLD_ASSERT_EQUAL(a, b)
Definition: global_defs.h:130
unsigned int size() const
Class for representation of a vector of fields of the same physical quantity.
Definition: multi_field.hh:55
const std::string & input_name() const
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_
void set_mesh(const Mesh &mesh) override
LimitSide
Definition: field_common.hh:44
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
virtual void value_list(const std::vector< Point > &point_list, const ElementAccessor< spacedim > &elm, std::vector< typename MultiFieldValue::return_type > &value_list) const