Flow123d  JS_before_hm-983-gccfd4b3
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 "fields/eval_subset.hh"
25 #include "fields/eval_points.hh"
27 #include "input/input_exception.hh"
28 #include "io/observe.hh"
29 
30 namespace it = Input::Type;
31 
32 /******************************************************************************************
33  * Implementation of MultiField<...>
34  */
35 
36 template<int spacedim, class Value>
38 : FieldCommon(),
39  no_check_control_field_(nullptr)
40 {
41 // static_assert(Value::NRows_ == 1 && Value::NCols_ == 1, "");
42  this->multifield_ = true;
43  this->shared_->bc_ = bc;
44 }
45 
46 
47 
48 template<int spacedim, class Value>
50 : FieldCommon(other),
51  sub_fields_(other.sub_fields_),
54 {
55  this->multifield_ = true;
56 }
57 
58 
59 
60 template<int spacedim, class Value>
62 {
63  //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());
64  OLD_ASSERT(other.shared_->mesh_, "Must call set_mesh before assign to other field.\n");
65  OLD_ASSERT( !shared_->mesh_ || (shared_->mesh_==other.shared_->mesh_),
66  "Assignment between multi fields with different meshes.\n");
67  OLD_ASSERT( shared_->comp_names_.size(), "Vector of component names can't be empty!\n");
68  OLD_ASSERT( shared_->comp_names_.size()==other.shared_->comp_names_.size(),
69  "Both multi fields must have same size of vectors of component names.\n");
70 
71  // check for self assignement
72  if (&other == this) return *this;
73 
74  // class members derived from FieldCommon
75  std::vector< std::string > comp_names = shared_->comp_names_; // keep component names
76  shared_ = other.shared_;
77  shared_->comp_names_ = comp_names;
78  shared_->is_fully_initialized_ = false;
80  last_time_ = other.last_time_;
84  this->multifield_ = true;
85 
86  // class members of Field class
87  if ( size() == 0 ) {
88  // move subfields from other, set correct names
89  sub_fields_.clear();
90  sub_fields_.reserve( other.size() );
91  for (unsigned int i=0; i<other.size(); ++i) {
92  sub_fields_.push_back( other.sub_fields_[i] );
93  if (this->shared_->comp_names_[i].length() == 0)
94  THROW( Input::ExcInputMessage() << EI_Message("The field " + this->input_name()
95  + " has set empty name of component.") );
96  else {
97  sub_fields_[i].name_ = this->shared_->comp_names_[i] + "_" + name();
98  }
99  }
100  } else {
101  THROW( ExcMessage() << EI_Message("Internal error. Assignment operator can't be used after call setup_component() method.") );
102  }
105 
106  return *this;
107 }
108 
109 
110 
111 template<int spacedim, class Value>
113  OLD_ASSERT(false, "This method can't be used for MultiField");
114 
115  it::Abstract abstract = it::Abstract();
117  return inst;
118 }
119 
120 
121 template<int spacedim, class Value>
123  it::Array type = it::Array( SubFieldBaseType::get_input_type_instance(shared_->input_element_selection_), 1);
124  return type;
125 }
126 
127 
128 template<int spacedim, class Value>
130  const MultiField<spacedim, typename FieldValue<spacedim>::Enum > &control_field,
131  const vector<FieldEnum> &value_list) -> MultiField &
132 {
133  no_check_control_field_=&control_field;
134  shared_->no_check_values_=value_list;
135  return *this;
136 }
137 
138 
139 template<int spacedim, class Value>
141  const TimeStep &time, LimitSide limit_side)
142 {
143  // initialization of Multifield for first call
144  if (sub_fields_.size() == 0) {
146  }
147 
148  // set time for sub fields
150  is_jump_time_=false;
151  for( SubFieldType &field : sub_fields_) {
152  if (field.set_time(time, limit_side))
154  is_jump_time_ = is_jump_time_ || field.is_jump_time();
155  }
157 }
158 
159 
160 
161 template<int spacedim, class Value>
163  // test if mesh is not set
164  if (shared_->mesh_ && shared_->mesh_ != &mesh) {
165  THROW(ExcFieldMeshDifference() << EI_Field(name()) );
166  }
167 
168  shared_->mesh_ = &mesh;
169 }
170 
171 
172 template<int spacedim, class Value>
174  ASSERT( flags().match(FieldFlag::equation_input))(other.name().c_str())(this->name().c_str())
175  .error("Can not copy to the non-copy field.");
176 
177  // do not use copy if the field have its own input
179  && this->shared_->input_list_.size() != 0 ) return;
180 
181  if (typeid(other) == typeid(*this)) {
182  auto const &other_field = dynamic_cast< MultiField<spacedim, Value> const &>(other);
183  this->operator=(other_field);
184  } else if (typeid(other) == typeid(SubFieldType)) {
185  auto const &other_field = dynamic_cast< SubFieldType const &>(other);
186  sub_fields_.resize(1);
187  sub_fields_[0] = other_field;
188  }
189 }
190 
191 
192 
193 template<int spacedim, class Value>
194 void MultiField<spacedim, Value>::field_output(std::shared_ptr<OutputTime> stream)
195 {
196  // currently we cannot output boundary fields
197  if (!is_bc()) {
198  const OutputTime::DiscreteSpace type = this->get_output_type();
199 
201 
202  for (unsigned long index=0; index < this->size(); index++) {
203  sub_fields_[index].compute_field_data( type, stream );
204  }
205  }
206 }
207 
208 
209 
210 template<int spacedim, class Value>
211 void MultiField<spacedim, Value>::observe_output(std::shared_ptr<Observe> observe)
212 {
213  for(auto &field : sub_fields_) field.observe_output(observe);
214 }
215 
216 
217 
218 
219 template<int spacedim, class Value>
221  bool const_all=true;
222  for(auto &field : sub_fields_) const_all = const_all && field.is_constant(reg);
223  return const_all;
224 }
225 
226 template<int spacedim, class Value>
228 {
229  ASSERT_DBG(true).error("Not used yet. Test it.");
230 
231  FieldResult result_all = result_none;
232  for(auto &field : sub_fields_) {
233  FieldResult sub_result = field.field_result(region_set);
234  if (sub_result == result_none) return result_none;
235 
236  if (result_all == result_none) // first subfield
237  result_all = sub_result;
238  else if (sub_result == result_other || result_all == result_other)
239  result_all = result_other;
240  else if (sub_result != result_all)
241  result_all = result_constant; // all subfields are (possibly different) constants
242  }
243 
244  return result_all;
245 
246 }
247 
248 
249 template<int spacedim, class Value>
251 {
252  int nrows = Value::NRows_;
253  int ncols = Value::NCols_;
254  string type = "Integer";
256  type = "Double";
257 
258  return fmt::format("{{ \"subfields\": true, \"shape\": [ {}, {} ], \"type\": \"{}\", \"limit\": [ {}, {} ] }}",
259  nrows, ncols, type, this->limits().first, this->limits().second);
260 }
261 
262 
263 template<int spacedim, class Value>
265  unsigned int comp_size = this->shared_->comp_names_.size();
266  string full_name;
267  ASSERT_GT(comp_size, 0).error("Vector of component names is empty!\n");
268  ASSERT_PTR(this->shared_->mesh_).error("Mesh is not set!\n");
269 
270  sub_fields_.reserve( comp_size );
271  for(unsigned int i_comp=0; i_comp < comp_size; i_comp++)
272  {
273  if (this->shared_->comp_names_[i_comp].length() == 0)
274  full_name = name();
275  else {
276  full_name = this->shared_->comp_names_[i_comp] + "_" + name();
277  }
278 
279  sub_fields_.push_back( SubFieldType(i_comp, name(), full_name, is_bc()) );
280  sub_fields_[i_comp].units( units() );
281  if (no_check_control_field_ != nullptr && no_check_control_field_->size() == sub_fields_.size())
282  sub_fields_[i_comp].disable_where((*no_check_control_field_)[i_comp], shared_->no_check_values_);
283  sub_fields_[i_comp].set_mesh( *(shared_->mesh_) );
284 // sub_fields_[i_comp].set_limit_side(this->limit_side_);
285  sub_fields_[i_comp].input_selection(shared_->input_element_selection_);
286  sub_fields_[i_comp].add_factory( std::make_shared<MultiFieldFactory>(i_comp) );
287 
288  if (this->shared_->input_default_!="") {
289  sub_fields_[i_comp].shared_->input_default_ = this->shared_->input_default_;
290  }
291 
292  sub_fields_[i_comp].flags_ = this->flags_;
293  sub_fields_[i_comp].set_input_list(this->full_input_list_, *tg_);
294  }
295 }
296 
297 
298 
299 template<int spacedim, class Value>
301  if (! flags().match(FieldFlag::declare_input)) return;
302 
303  // Check sizes of Arrays defined MultiField in field descriptors
305  it != list.end();
306  ++it) {
307  Input::Array mf_array;
308  if ( it->opt_val(this->input_name(), mf_array) ) {
309  unsigned int comp_size = this->shared_->comp_names_.size();
310  if (mf_array.size() != 1 && mf_array.size() != comp_size)
311  THROW( Exc_InvalidMultiFieldSize() << EI_MultiFieldName(this->input_name())
312  << EI_Size(mf_array.size()) << EI_ExpectedSize(comp_size) << list.ei_address() );
313  }
314  }
315 
316  this->full_input_list_ = list;
317  this->tg_ = &tg;
318 
319  // Save the full array for future use in FieldCommon::mark_input_times().
320  list.copy_to(shared_->input_list_);
321 }
322 
323 
324 // template<int spacedim, class Value>
325 // typename MultiField<spacedim, Value>::MultiFieldValue::return_type MultiField<spacedim, Value>::value(const Point &p, const ElementAccessor<spacedim> &elm) const {
326 // typename MultiFieldValue::return_type ret(size(), 1);
327 // for (unsigned int i_comp=0; i_comp < size(); i_comp++) {
328 // ret(i_comp, 0) = sub_fields_[i_comp].value(p,elm);
329 // }
330 //
331 // return ret;
332 // }
333 //
334 //
335 //
336 // template<int spacedim, class Value>
337 // void MultiField<spacedim, Value>::value_list(const std::vector< Point > &point_list, const ElementAccessor<spacedim> &elm,
338 // std::vector<typename MultiFieldValue::return_type> &value_list) const {
339 // OLD_ASSERT_EQUAL( point_list.size(), value_list.size() );
340 // for(unsigned int i=0; i< point_list.size(); i++) {
341 // value_list[i]=this->value(point_list[i], elm);
342 // }
343 // }
344 
345 
346 
347 template<int spacedim, class Value>
349  Input::Array multifield_arr;
350  if (descriptor_rec.opt_val(field.input_name(), multifield_arr))
351  {
352  //OLD_ASSERT(multifield_arr.size() == 1 || multifield_arr.size() == field.n_comp(),
353  // "Invalid size of Array defined for MultiField '%s'!\n", field.input_name().c_str());
354  unsigned int position = 0;
355  auto it = multifield_arr.begin<Input::AbstractRecord>();
356  if (multifield_arr.size() > 1)
357  while (index_ != position) {
358  ++it; ++position;
359  }
360 
361  FieldAlgoBaseInitData init_data(field.input_name(), field.n_comp(), field.units(), field.limits(), field.get_flags());
363  field_algo_base->set_component_idx(index_);
364  return field_algo_base;
365  }
366 
367  return NULL;
368 }
369 
370 
371 
372 template<int spacedim, class Value>
374  return in_rec.find<Input::Array>(input_name);
375 }
376 
377 
378 
379 template<int spacedim, class Value>
380 void MultiField<spacedim, Value>::cache_allocate(std::shared_ptr<EvalPoints> eval_points) {
381  for(auto &field : sub_fields_) field.cache_allocate(eval_points);
382 }
383 
384 
385 template<int spacedim, class Value>
387  for(auto &field : sub_fields_) field.cache_update(cache_map);
388 }
389 
390 
391 template<int spacedim, class Value>
393  const RegionSet &domain,
395  double time)
396 {
397  unsigned int comp_size = this->shared_->comp_names_.size();
398  ASSERT_GT(comp_size, 0).error("Vector of component names is empty!\n");
399  ASSERT_EQ(comp_size, field_vec.size());
400  ASSERT_PTR(this->shared_->mesh_).error("Mesh is not set!\n");
401 
402  sub_fields_.reserve( comp_size );
403  for(unsigned int i_comp=0; i_comp < comp_size; i_comp++)
404  {
405  sub_fields_.push_back( SubFieldType(i_comp, name(), "", is_bc()) );
406  sub_fields_[i_comp].set_mesh( *(shared_->mesh_) );
407  sub_fields_[i_comp].flags_ = this->flags_;
408  sub_fields_[i_comp].set_field(domain, field_vec[i_comp], time);
409  }
410 }
411 
412 
413 
414 #endif /* MULTI_FIELD_IMPL_HH_ */
IT::Instance get_input_type() override
Iterator< ValueType > begin() const
std::string get_value_attribute() const override
Common abstract parent of all Field<...> classes.
Definition: field_common.hh:73
bool is_jump_time_
Accessor to input data conforming to declared Array.
Definition: accessors.hh:566
EI_Address ei_address() const
Definition: accessors.cc:314
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:206
FieldFlag::Flags get_flags() const
void set_fields(const RegionSet &domain, std::vector< typename Field< spacedim, Value >::FieldBasePtr > field_vec, double time=0.0)
static const Input::Type::Instance & get_input_type_instance(Input::Type::Selection value_selection=Input::Type::Selection())
bool is_active_field_descriptor(const Input::Record &in_rec, const std::string &input_name) override
OutputTime::DiscreteSpace get_output_type() const
void copy_from(const FieldCommon &other) override
Class template representing a field with values dependent on: point, element, and region...
Definition: field.hh:92
std::string format(CStringRef format_str, ArgList args)
Definition: format.h:3141
unsigned int component_index_
std::pair< double, double > limits() const
#define ASSERT_GT(a, b)
Definition of comparative assert macro (Greater Than)
Definition: asserts.hh:312
Directing class of FieldValueCache.
Field< spacedim, Value > SubFieldType
Definition: multi_field.hh:90
Definition: mesh.h:78
const MultiField< spacedim, typename FieldValue< spacedim >::Enum > * no_check_control_field_
Definition: multi_field.hh:277
Iterator< Ret > find(const string &key) const
Helper class that stores data of generic types.
Definition: type_generic.hh:89
Helper struct stores data for initizalize descentants of FieldAlgorithmBase.
double last_time_
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:347
MultiField & operator=(const MultiField &other)
Basic time management functionality for unsteady (and steady) solvers (class Equation).
FieldCommon & units(const UnitSI &units)
Set basic units of the field.
void set_input_list(const Input::Array &list, const TimeGovernor &tg) override
Input::Array full_input_list_
Full list of input field descriptors from which the subfields of MultiField are set.
Definition: multi_field.hh:265
Class for declaration of inputs sequences.
Definition: type_base.hh:339
static constexpr bool value
Definition: json.hpp:87
constexpr bool match(Mask mask) const
Definition: flag_array.hh:163
std::shared_ptr< SharedData > shared_
IteratorBase end() const
#define OLD_ASSERT(...)
Definition: global_defs.h:131
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:262
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:291
static const unsigned int N_DISCRETE_SPACES
Definition: output_time.hh:103
const TimeGovernor * tg_
TimeGovernor is necessary for set input list in setup_components method.
Definition: multi_field.hh:268
bool set_time(const TimeStep &time, LimitSide limit_side) override
LimitSide last_limit_side_
FieldResult field_result(RegionSet region_set) const override
Indicates special field states.
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:458
FieldResult
void field_output(std::shared_ptr< OutputTime > stream) override
static std::shared_ptr< FieldAlgorithmBase< spacedim, Value > > function_factory(const Input::AbstractRecord &rec, const struct FieldAlgoBaseInitData &init_data)
std::shared_ptr< FieldBaseType > FieldBasePtr
Definition: field.hh:96
void copy_to(Container &out) const
bool is_constant(Region reg) override
#define ASSERT_PTR(ptr)
Definition of assert macro checking non-null pointer (PTR)
Definition: asserts.hh:336
IT::Array get_multifield_input_type() override
void cache_update(ElementCacheMap &cache_map) override
Implements FieldCommon::cache_update.
#define ASSERT_LT(a, b)
Definition of comparative assert macro (Less Than)
Definition: asserts.hh:296
#define ASSERT_DBG(expr)
const Mesh * mesh() const
FieldCommon & name(const string &name)
unsigned int n_comp() const
unsigned int size() const
Class for representation of a vector of fields of the same physical quantity.
Definition: multi_field.hh:87
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
void cache_allocate(std::shared_ptr< EvalPoints > eval_points) override
Implements FieldCommon::cache_allocate.
bool is_bc() const
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
Representation of one time step..
TimeStatus set_time_result_
void observe_output(std::shared_ptr< Observe > observe) override
void set_mesh(const Mesh &mesh) override
LimitSide
Definition: field_common.hh:60
#define ASSERT_EQ(a, b)
Definition of comparative assert macro (EQual)
Definition: asserts.hh:328
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