Flow123d  JS_before_hm-1709-g5393e92e3
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 field.impl.hh
15  * @brief
16  */
17 
18 #ifndef FIELD_IMPL_HH_
19 #define FIELD_IMPL_HH_
20 
21 #include "field.hh"
22 #include "field_algo_base.impl.hh"
23 #include "field_fe.hh"
24 #include "fields/eval_subset.hh"
25 #include "fields/eval_points.hh"
27 #include "fields/field_set.hh"
28 #include "mesh/region.hh"
30 #include "input/accessors.hh"
31 #include "io/observe.hh"
32 #include "io/output_mesh.hh"
33 #include "io/output_element.hh"
34 
35 
36 /******************************************************************************************
37  * Implementation of Field<...>
38  */
39 
40 template<int spacedim, class Value>
42 : data_(std::make_shared<SharedData>()),
43  value_cache_( FieldValueCache<typename Value::element_type>(Value::NRows_, Value::NCols_) )
44 {
45  // n_comp is nonzero only for variable size vectors Vector, VectorEnum, ..
46  // this invariant is kept also by n_comp setter
47  shared_->n_comp_ = (Value::NRows_ ? 0 : 1);
48  this->add_factory( std::make_shared<FactoryBase>() );
49 
50  unsigned int cache_size = 1.1 * CacheMapElementNumber::get();
51  value_cache_.reinit(cache_size);
52  value_cache_.resize(cache_size);
53 
54  this->multifield_ = false;
55  this->set_shape( Value::NRows_, Value::NCols_ );
56 }
57 
58 
59 template<int spacedim, class Value>
60 Field<spacedim,Value>::Field(const string &name, bool bc)
61 : data_(std::make_shared<SharedData>()),
62  value_cache_( FieldValueCache<typename Value::element_type>(Value::NRows_, Value::NCols_) )
63 {
64  // n_comp is nonzero only for variable size vectors Vector, VectorEnum, ..
65  // this invariant is kept also by n_comp setter
66  shared_->n_comp_ = (Value::NRows_ ? 0 : 1);
67  shared_->bc_=bc;
68  this->name( name );
69  this->add_factory( std::make_shared<FactoryBase>() );
70  unsigned int cache_size = 1.1 * CacheMapElementNumber::get();
71  value_cache_.reinit(cache_size);
72  value_cache_.resize(cache_size);
73 
74  this->multifield_ = false;
75  this->set_shape( Value::NRows_, Value::NCols_ );
76 }
77 
78 
79 
80 template<int spacedim, class Value>
81 Field<spacedim,Value>::Field(unsigned int component_index, string input_name, string name, bool bc)
82 : data_(std::make_shared<SharedData>()),
83  value_cache_( FieldValueCache<typename Value::element_type>(Value::NRows_, Value::NCols_) )
84 {
85  // n_comp is nonzero only for variable size vectors Vector, VectorEnum, ..
86  // this invariant is kept also by n_comp setter
87  shared_->n_comp_ = (Value::NRows_ ? 0 : 1);
88  this->set_component_index(component_index);
89  this->name_ = (name=="") ? input_name : name;
90  this->shared_->input_name_ = input_name;
91  shared_->bc_ = bc;
92 
93  unsigned int cache_size = 1.1 * CacheMapElementNumber::get();
94  value_cache_.reinit(cache_size);
95  value_cache_.resize(cache_size);
96 
97  this->multifield_ = false;
98  this->set_shape( Value::NRows_, Value::NCols_ );
99 }
100 
101 
102 template<int spacedim, class Value>
104 : FieldCommon(other),
105  data_(other.data_),
106  region_fields_(other.region_fields_),
107  factories_(other.factories_),
108  value_cache_(other.value_cache_)
109 {
110  if (other.no_check_control_field_)
111  no_check_control_field_ = make_shared<ControlField>(*other.no_check_control_field_);
112 
113  this->multifield_ = false;
114  this->set_shape( Value::NRows_, Value::NCols_ );
115 }
116 
117 
118 template<int spacedim, class Value>
120 {
121  //ASSERT( flags().match(FieldFlag::input_copy) )(this->name())(other.name()).error("Try to assign to non-copy field from the field.");
122  ASSERT(other.shared_->mesh_).error("Must call set_mesh before assign to other field.\n");
123  ASSERT( !shared_->mesh_ || (shared_->mesh_==other.shared_->mesh_) ).error("Assignment between fields with different meshes.\n");
124 
125  // check for self assignement
126  if (&other == this) return *this;
127 
128  // class members derived from FieldCommon
129  shared_ = other.shared_;
130  shared_->is_fully_initialized_ = false;
131  set_time_result_ = other.set_time_result_;
132  last_time_ = other.last_time_;
133  last_limit_side_ = other.last_limit_side_;
134  is_jump_time_ = other.is_jump_time_;
135  component_index_ = other.component_index_;
136  this->multifield_ = false;
137 
138  // class members of Field class
139  data_ = other.data_;
140  factories_ = other.factories_;
141  region_fields_ = other.region_fields_;
142  value_cache_ = other.value_cache_;
143  this->shape_ = other.shape_;
144 
145  if (other.no_check_control_field_) {
146  no_check_control_field_ = make_shared<ControlField>(*other.no_check_control_field_);
147  }
148 
149  return *this;
150 }
151 
152 
153 
154 template<int spacedim, class Value>
155 typename Value::return_type Field<spacedim,Value>::operator() (BulkPoint &p) {
156  return p.elm_cache_map()->get_value<Value>(value_cache_, p.elem_patch_idx(), p.eval_point_idx());
157 }
158 
159 
160 
161 template<int spacedim, class Value>
162 typename Value::return_type Field<spacedim,Value>::operator() (EdgePoint &p) {
163  return p.elm_cache_map()->get_value<Value>(value_cache_, p.elem_patch_idx(), p.eval_point_idx());
164 }
165 
166 
167 
168 template<int spacedim, class Value>
169 typename Value::return_type Field<spacedim,Value>::operator() (CouplingPoint &p) {
170  return p.elm_cache_map()->get_value<Value>(value_cache_, p.elem_patch_idx(), p.eval_point_idx());
171 }
172 
173 
174 
175 template<int spacedim, class Value>
176 typename Value::return_type Field<spacedim,Value>::operator() (BoundaryPoint &p) {
177  return p.elm_cache_map()->get_value<Value>(value_cache_, p.elem_patch_idx(), p.eval_point_idx());
178 }
179 
180 
181 
182 template<int spacedim, class Value>
183 typename Value::return_type
184 Field<spacedim,Value>::operator[] (unsigned int i_cache_point) const
185 {
186  return Value::get_from_array( this->value_cache_, i_cache_point );
187 }
188 
189 
190 
191 template<int spacedim, class Value>
193  return FieldBaseType::get_input_type_instance(shared_->input_element_selection_);
194 }
195 
196 
197 
198 template<int spacedim, class Value>
200  ASSERT(false).error("This method can't be used for Field");
201 
202  it::Array arr = it::Array( it::Integer() );
203  return arr;
204 }
205 
206 
207 
208 template<int spacedim, class Value>
210  const Field<spacedim, typename FieldValue<spacedim>::Enum > &control_field,
211  const vector<FieldEnum> &value_list) -> Field &
212 {
213  no_check_control_field_=std::make_shared<ControlField>(control_field);
214  shared_->no_check_values_=value_list;
215  return *this;
216 }
217 
218 template<int spacedim, class Value>
219 void Field<spacedim,Value>::set_mesh(const Mesh &in_mesh) {
220  // since we allow copy of fields before set_mesh is called
221  // we have to check that all copies set the same mesh
222  if (shared_->mesh_ && shared_->mesh_ != &in_mesh) {
223  THROW(ExcFieldMeshDifference() << EI_Field(name()) );
224  }
225 
226  shared_->mesh_ = &in_mesh;
227 
228  // initialize table if it is empty, we assume that the RegionDB is closed at this moment
229  region_fields_.resize( mesh()->region_db().size() );
230  RegionHistory init_history(history_length_limit_); // capacity
231  data_->region_history_.resize( mesh()->region_db().size(), init_history );
232 
233  if (no_check_control_field_) no_check_control_field_->set_mesh(in_mesh);
234 }
235 
236 
237 /*
238 template<int spacedim, class Value>
239 std::shared_ptr< typename Field<spacedim,Value>::FieldBaseType >
240 Field<spacedim,Value>::operator[] (Region reg)
241 {
242  ASSERT_LT(reg.idx(), this->region_fields_.size());
243  return this->region_fields_[reg.idx()];
244 }
245 */
246 
247 
248 template <int spacedim, class Value>
250  ASSERT(this->set_time_result_ != TimeStatus::unknown).error("Unknown time status.\n");
251  ASSERT_LT(reg.idx(), this->region_fields_.size());
252  FieldBasePtr region_field = this->region_fields_[reg.idx()];
253  return ( region_field && region_field->is_constant_in_space() );
254 }
255 
256 
257 template<int spacedim, class Value>
259  FieldBasePtr field,
260  double time,
261  std::vector<std::string> region_set_names)
262 {
263  ASSERT_PTR(field).error("Null field pointer.\n");
264 
265  ASSERT_PTR( mesh() ).error("Null mesh pointer, set_mesh() has to be called before set().\n");
266  ASSERT_EQ( field->n_comp() , shared_->n_comp_);
267  field->set_mesh( mesh() , is_bc() );
268 
269  for (auto set_name : region_set_names) {
270  RegionSet domain = mesh()->region_db().get_region_set(set_name);
271  if (domain.size() == 0) continue;
272 
273  HistoryPoint hp = HistoryPoint(time, field);
274  for(const Region &reg: domain) {
275  RegionHistory &region_history = data_->region_history_[reg.idx()];
276  // insert hp into descending time sequence
277  ASSERT( region_history.size() == 0 || region_history[0].first < hp.first)(hp.first)(region_history[0].first)
278  .error("Can not insert smaller time then last time in field's history.\n");
279  region_history.push_front(hp);
280  }
281  }
282  set_history_changed();
283 }
284 
285 
286 
287 template<int spacedim, class Value>
289  const Input::AbstractRecord &a_rec,
290  double time,
291  std::vector<std::string> region_set_names)
292 {
293  FieldAlgoBaseInitData init_data(input_name(), n_comp(), units(), limits(), flags());
294  set(FieldBaseType::function_factory(a_rec, init_data), time, region_set_names);
295 }
296 
297 
298 
299 template<int spacedim, class Value>
300 bool Field<spacedim, Value>::set_time(const TimeStep &time_step, LimitSide limit_side)
301 {
302  ASSERT_PTR( mesh() )( name() ).error("NULL mesh pointer of field with given name. set_mesh must be called before.\n");
303 
304  // Skip setting time if the new time is equal to current time of the field
305  // and if either the field is continuous in that time or the current limit side is same as the new one.
306  if (time_step.end() == last_time_) {
307  if ( ! is_jump_time() ||
308  limit_side == last_limit_side_) {
309  last_limit_side_ = limit_side;
310  return changed();
311  }
312  }
313 
314  last_time_=time_step.end();
315  last_limit_side_ = limit_side;
316 
317  // possibly update our control field
318  if (no_check_control_field_) {
319  no_check_control_field_->set_time(time_step, limit_side);
320  }
321 
322  set_time_result_ = TimeStatus::constant;
323 
324  // read all descriptors satisfying time.ge(input_time)
325  update_history(time_step);
326  check_initialized_region_fields_();
327 
328  //
329  is_jump_time_=false;
330  // set time_step on all regions
331  // for regions that match type of the field domain
332  for(const Region &reg: mesh()->region_db().get_region_set("ALL") ) {
333  auto rh = data_->region_history_[reg.idx()];
334 
335  // skip regions with no matching BC flag
336  if (reg.is_boundary() != is_bc()) continue;
337 
338  // Check regions with empty history, possibly set default.
339  if ( rh.empty()) continue;
340 
341  double last_time_in_history = rh.front().first;
342  unsigned int history_size=rh.size();
343  unsigned int i_history;
344  ASSERT( time_step.ge(last_time_in_history) ).error("Setting field time back in history not fully supported yet!");
345 
346  // set history index
347  if ( time_step.gt(last_time_in_history) ) {
348  // in smooth time_step
349  i_history=0;
350  } else {
351  // time_step .eq. input_time; i.e. jump time
352  is_jump_time_=true;
353  if (limit_side == LimitSide::right) {
354  i_history=0;
355  } else {
356  i_history=1;
357  }
358  }
359  i_history=min(i_history, history_size - 1);
360  ASSERT(i_history >= 0).error("Empty field history.");
361  // possibly update field pointer
362 
363  auto new_ptr = rh.at(i_history).second;
364  if (new_ptr != region_fields_[reg.idx()]) {
365  region_fields_[reg.idx()]=new_ptr;
366  set_time_result_ = TimeStatus::changed;
367  }
368  // let FieldBase implementation set the time
369  if ( new_ptr->set_time(time_step) ) set_time_result_ = TimeStatus::changed;
370 
371  }
372 
373  return changed();
374 }
375 
376 
377 template<int spacedim, class Value>
379  ASSERT( flags().match(FieldFlag::equation_input))(other.name().c_str())(this->name().c_str())
380  .error("Can not copy to the non-input field.");
381 
382  // do not use copy if the field have its own input
383  if ( flags().match(FieldFlag::declare_input)
384  && this->shared_->input_list_.size() != 0 ) return;
385 
386  if (typeid(other) == typeid(*this)) {
387  auto const &other_field = dynamic_cast< Field<spacedim, Value> const &>(other);
388  this->operator=(other_field);
389  }
390 }
391 
392 
393 
394 template<int spacedim, class Value>
395 void Field<spacedim, Value>::field_output(std::shared_ptr<OutputTime> stream, OutputTime::DiscreteSpaceFlags type)
396 {
397  // currently we cannot output boundary fields
398  if (!is_bc()) {
400  this->compute_field_data( type, stream);
401  }
402 }
403 
404 
405 template<int spacedim, class Value>
406 void Field<spacedim, Value>::observe_output(std::shared_ptr<Observe> observe)
407 {
408  typedef typename Value::element_type ElemType;
409 
410  if (observe->point_ds()->size() == 0) return;
411 
412  ElementDataCache<ElemType> &output_data = observe->prepare_compute_data<ElemType>(this->name(), this->time(),
413  (unsigned int)Value::NRows_, (unsigned int)Value::NCols_);
414 
415  unsigned int loc_point_time_index, ele_index;
416  for(ObservePointAccessor op_acc : observe->local_range()) {
417  loc_point_time_index = op_acc.loc_point_time_index();
418  ele_index = op_acc.observe_point().element_idx();
419  const Value &obs_value =
420  Value( const_cast<typename Value::return_type &>(
421  this->value(op_acc.observe_point().global_coords(),
422  ElementAccessor<spacedim>(this->mesh(), ele_index)) ));
423  ASSERT_EQ(output_data.n_comp(), obs_value.n_rows()*obs_value.n_cols()).error();
424  output_data.store_value(loc_point_time_index, obs_value.mem_ptr());
425  }
426 }
427 
428 
429 
430 template<int spacedim, class Value>
432 
433  FieldResult result_all = result_none;
434  for(Region &reg : region_set) {
435  auto f = region_fields_[reg.idx()];
436  if (f) {
437  FieldResult fr = f->field_result();
438  if (result_all == result_none) // first region
439  result_all = fr;
440  else if (fr != result_all)
441  result_all = result_other; // if results from individual regions are different
442  } else return result_none; // if field is undefined on any region of the region set
443  }
444 
445  if (result_all == result_constant && region_set.size() > 1)
446  return result_other; // constant result for individual regions could be non-constant on the whole region set
447 
448  return result_all;
449 
450 }
451 
452 
453 template<int spacedim, class Value>
455 {
456  int nrows = Value::NRows_;
457  int ncols = Value::NCols_;
458  string type = "Integer";
460  type = "Double";
461 
462  return fmt::format("{{ \"shape\": [ {}, {} ], \"type\": \"{}\", \"limit\": [ {}, {} ] }}",
463  nrows, ncols, type, this->limits().first, this->limits().second);
464 }
465 
466 
467 template<int spacedim, class Value>
469  ASSERT_PTR( mesh() ).error("Null mesh pointer, set_mesh() has to be called before.\n");
470 
471  // read input up to given time
472  double input_time;
473  if (shared_->input_list_.size() != 0) {
474  while( shared_->list_idx_ < shared_->input_list_.size()
475  && time.ge( input_time = time.read_time( shared_->input_list_[shared_->list_idx_].find<Input::Tuple>("time") ) ) ) {
476 
477  const Input::Record & actual_list_item = shared_->input_list_[shared_->list_idx_];
478  // get domain specification
479  RegionSet domain;
480  Input::Array domain_name_array;
481  unsigned int id;
482  if (actual_list_item.opt_val("region", domain_name_array)) {
483  std::vector<string> domain_names = mesh()->region_db().get_and_check_operands(domain_name_array);
484  domain = mesh()->region_db().union_set(domain_names);
485 
486  } else if (actual_list_item.opt_val("rid", id)) {
487  Region region;
488  try {
489  region = mesh()->region_db().find_id(id);
490  } catch (RegionDB::ExcUniqueRegionId &e) {
491  e << actual_list_item.ei_address();
492  throw;
493  }
494  if (region.is_valid())
495  domain.push_back(region);
496  else
497  THROW(RegionDB::ExcUnknownRegion() << RegionDB::EI_ID(id) );
498  } else {
499  THROW(ExcMissingDomain()
500  << actual_list_item.ei_address() );
501  }
502 
503  // get field instance
504  for(auto rit = factories_.rbegin() ; rit != factories_.rend(); ++rit) {
505  FieldBasePtr field_instance = (*rit)->create_field(actual_list_item, *this);
506  if (field_instance) // skip descriptors without related keys
507  {
508  // add to history
509  ASSERT_EQ( field_instance->n_comp() , shared_->n_comp_);
510  field_instance->set_mesh( mesh() , is_bc() );
511  for(const Region &reg: domain) {
512  // if region history is empty, add new field
513  // or if region history is not empty and the input_time is higher, add new field
514  // otherwise (region history is not empty and the input_time is the same),
515  // rewrite the region field
516  if( data_->region_history_[reg.idx()].size() == 0
517  || data_->region_history_[reg.idx()].back().first < input_time)
518  {
519  data_->region_history_[reg.idx()].push_front(
520  HistoryPoint(input_time, field_instance));
521  //DebugOut() << "Update history" << print_var(this->name()) << print_var(reg.label()) << print_var(input_time);
522  }
523  else
524  {
525  data_->region_history_[reg.idx()].back() =
526  HistoryPoint(input_time, field_instance);
527  }
528  }
529  break;
530  }
531  }
532 
533  ++shared_->list_idx_;
534  }
535  }
536 }
537 
538 template<int spacedim, class Value>
540  ASSERT_PTR(mesh()).error("Null mesh pointer.");
541  //if (shared_->is_fully_initialized_) return;
542 
543  // check there are no empty field pointers, collect regions to be initialized from default value
544  RegionSet regions_to_init; // empty vector
545 
546  for(const Region &reg : mesh()->region_db().get_region_set("ALL") )
547  if (reg.is_boundary() == is_bc()) { // for regions that match type of the field domain
548  RegionHistory &rh = data_->region_history_[reg.idx()];
549  if ( rh.empty() || ! rh[0].second) // empty region history
550  {
551  // test if check is turned on and control field is FieldConst
552  if (no_check_control_field_ && no_check_control_field_->is_constant(reg) ) {
553  // get constant enum value
554  auto elm = ElementAccessor<spacedim>(mesh(), reg);
555  FieldEnum value = no_check_control_field_->value(elm.centre(),elm);
556  // check that the value is in the disable list
557  if ( std::find(shared_->no_check_values_.begin(), shared_->no_check_values_.end(), value)
558  != shared_->no_check_values_.end() )
559  continue; // the field is not needed on this region
560  }
561  if (shared_->input_default_ != "") { // try to use default
562  regions_to_init.push_back( reg );
563  } else {
564  THROW( ExcMissingFieldValue() << EI_FieldInputName(input_name()) << EI_FieldName(name())
565  << EI_RegId(reg.id()) << EI_RegLabel(reg.label()) );
566  }
567  }
568  }
569 
570  // possibly set from default value
571  if ( regions_to_init.size() ) {
572  std::string region_list;
573  // has to deal with fact that reader can not deal with input consisting of simple values
574  string default_input=input_default();
575  auto input_type = get_input_type().make_instance().first;
576  Input::ReaderToStorage reader( default_input, *input_type, Input::FileFormat::format_JSON );
577 
578  auto a_rec = reader.get_root_interface<Input::AbstractRecord>();
579  FieldAlgoBaseInitData init_data(input_name(), n_comp(), units(), limits(), flags());
580  auto field_ptr = FieldBaseType::function_factory( a_rec , init_data );
581  field_ptr->set_mesh( mesh(), is_bc() );
582  for(const Region &reg: regions_to_init) {
583  data_->region_history_[reg.idx()]
584  .push_front(HistoryPoint( 0.0, field_ptr) );
585  region_list+=" "+reg.label();
586  }
587  FieldCommon::messages_data_.push_back( MessageData(input_default(), name(), region_list) );
588 
589  }
590  //shared_->is_fully_initialized_ = true;
591 }
592 
593 
594 template<int spacedim, class Value>
595 void Field<spacedim,Value>::add_factory(const std::shared_ptr<FactoryBase> factory) {
596  factories_.push_back( factory );
597 }
598 
599 
600 template<int spacedim, class Value>
602  Input::AbstractRecord field_record;
603  if (rec.opt_val(field.input_name(), field_record)) {
604  FieldAlgoBaseInitData init_data(field.input_name(), field.n_comp(), field.units(), field.limits(), field.get_flags());
605  return FieldBaseType::function_factory(field_record, init_data );
606  }
607  else
608  return FieldBasePtr();
609 }
610 
611 
612 template<int spacedim, class Value>
614  return in_rec.find<Input::AbstractRecord>(input_name);
615 }
616 
617 
618 
619 
620 template<int spacedim, class Value>
622  if (! flags().match(FieldFlag::declare_input)) return;
623 
624  // check that times forms ascending sequence
625  double time,last_time=0.0;
626 
628  it != list.end();
629  ++it) {
630  for(auto rit = factories_.rbegin() ; rit != factories_.rend(); ++rit) {
631  if ( (*rit)->is_active_field_descriptor( (*it), this->input_name() ) ) {
632  shared_->input_list_.push_back( Input::Record( *it ) );
633  time = tg.read_time( it->find<Input::Tuple>("time") );
634  if (time < last_time) {
635  THROW( ExcNonascendingTime()
636  << EI_Time(time)
637  << EI_Field(input_name())
638  << it->ei_address());
639  }
640  last_time = time;
641 
642  break;
643  }
644  }
645  }
646 
647 }
648 
649 
650 
651 template<int spacedim, class Value>
652 void Field<spacedim,Value>::compute_field_data(OutputTime::DiscreteSpaceFlags space_type, std::shared_ptr<OutputTime> stream) {
653  typedef typename Value::element_type ElemType;
654  for (uint i=0; i<OutputTime::N_DISCRETE_SPACES; ++i)
655  if (space_type[i]) {
657 
658  OutputTime::OutputDataPtr output_data_base = stream->prepare_compute_data<ElemType>(this->name(), type,
659  (unsigned int)Value::NRows_, (unsigned int)Value::NCols_);
660 
661  try{
662  // try casting actual ElementDataCache
663  if( ! output_data_base->is_dummy()){
664  auto output_data = std::dynamic_pointer_cast<ElementDataCache<ElemType>>(output_data_base);
665  fill_data_cache(type, stream, output_data);
666  }
667 
668  } catch(const std::bad_cast& e){
669  // skip
670  }
671  }
672 
673  /* Set the last time */
674  stream->update_time(this->time());
675 
676 }
677 
678 template<int spacedim, class Value>
680  std::shared_ptr<OutputTime> stream,
681  std::shared_ptr<ElementDataCache<typename Value::element_type>> data_cache)
682 {
683  std::shared_ptr<OutputMeshBase> output_mesh = stream->get_output_mesh_ptr();
684  ASSERT(output_mesh);
685 
686  /* Copy data to array */
687  switch(space_type) {
690  unsigned int node_index = 0;
691  for(const auto & ele : *output_mesh )
692  {
693  std::vector<Space<3>::Point> vertices = ele.vertex_list();
694  for(unsigned int i=0; i < ele.n_nodes(); i++)
695  {
696  const Value &node_value =
697  Value( const_cast<typename Value::return_type &>(
698  this->value(vertices[i],
699  ElementAccessor<spacedim>(ele.orig_mesh(), ele.orig_element_idx()) ))
700  );
701  ASSERT_EQ(data_cache->n_comp(), node_value.n_rows()*node_value.n_cols()).error();
702  data_cache->store_value(node_index, node_value.mem_ptr() );
703  ++node_index;
704  }
705  }
706  }
707  break;
708  case OutputTime::ELEM_DATA: {
709  for(const auto & ele : *output_mesh )
710  {
711  unsigned int ele_index = ele.idx();
712  const Value &ele_value =
713  Value( const_cast<typename Value::return_type &>(
714  this->value(ele.centre(),
715  ElementAccessor<spacedim>(ele.orig_mesh(), ele.orig_element_idx()))
716  )
717  );
718  ASSERT_EQ(data_cache->n_comp(), ele_value.n_rows()*ele_value.n_cols()).error();
719  data_cache->store_value(ele_index, ele_value.mem_ptr() );
720  }
721  }
722  break;
724  std::shared_ptr< FieldFE<spacedim, Value> > field_fe_ptr = this->get_field_fe();
725 
726  if (field_fe_ptr) {
727  auto native_output_data_base = stream->prepare_compute_data<double>(this->name(), space_type,
728  (unsigned int)Value::NRows_, (unsigned int)Value::NCols_,
729  typeid(field_fe_ptr->get_dofhandler()->ds()->fe()[0_d].get()).name(), // should be used better solution of fe_type setting
730  // e.g. method 'name()' of FiniteElement and descendants
731  field_fe_ptr->get_dofhandler()->max_elem_dofs());
732  // try casting actual ElementDataCache
733  auto native_output_data = std::dynamic_pointer_cast<ElementDataCache<double>>(native_output_data_base);
734  field_fe_ptr->native_data_to_cache(*native_output_data);
735  } else {
736  WarningOut().fmt("Field '{}' of native data space type is not of type FieldFE. Output will be skipped.\n", this->name());
737  }
738  }
739  break;
742  //should not happen
743  break;
744  }
745 }
746 
747 template<int spacedim, class Value>
748 std::shared_ptr< FieldFE<spacedim, Value> > Field<spacedim,Value>::get_field_fe() {
749  ASSERT_EQ_DBG(this->mesh()->region_db().size(), region_fields_.size()).error();
750  ASSERT(!this->shared_->bc_).error("FieldFE output of native data is supported only for bulk fields!");
751 
752  std::shared_ptr< FieldFE<spacedim, Value> > field_fe_ptr;
753 
754  bool is_fe = (region_fields_.size()>0); // indicate if FieldFE is defined on all bulk regions
755  is_fe = is_fe && region_fields_[1] && (typeid(*region_fields_[1]) == typeid(FieldFE<spacedim, Value>));
756  for (unsigned int i=3; i<2*this->mesh()->region_db().bulk_size(); i+=2)
757  if (!region_fields_[i] || (region_fields_[i] != region_fields_[1])) {
758  is_fe = false;
759  break;
760  }
761  if (is_fe) {
762  field_fe_ptr = std::dynamic_pointer_cast< FieldFE<spacedim, Value> >( region_fields_[1] );
763  }
764 
765  return field_fe_ptr;
766 }
767 
768 
769 template<int spacedim, class Value>
770 void Field<spacedim, Value>::cache_reallocate(const ElementCacheMap &cache_map, unsigned int region_idx) const {
771  // Call cache_reinit of FieldAlgoBase descendant on appropriate region
772  if (region_fields_[region_idx] != nullptr)
773  region_fields_[region_idx]->cache_reinit(cache_map);
774 }
775 
776 
777 template<int spacedim, class Value>
778 void Field<spacedim, Value>::cache_update(ElementCacheMap &cache_map, unsigned int region_patch_idx) const {
779  unsigned int region_idx = cache_map.region_idx_from_chunk_position(region_patch_idx);
780  if (region_fields_[region_idx] != nullptr) // skips bounadry regions for bulk fields and vice versa
781  region_fields_[region_idx]->cache_update(value_cache_, cache_map, region_patch_idx);
782 }
783 
784 
785 template<int spacedim, class Value>
787  if (region_fields_[i_reg] != nullptr) return region_fields_[i_reg]->set_dependency(field_set);
788  else return std::vector<const FieldCommon *>();
789 }
790 
791 
792 template<int spacedim, class Value>
794  return &value_cache_;
795 }
796 
797 
798 template<>
800  return nullptr;
801 }
802 
803 template<>
805  return nullptr;
806 }
807 
808 
809 template<int spacedim, class Value>
811  return &value_cache_;
812 }
813 
814 
815 template<>
817  return nullptr;
818 }
819 
820 template<>
822  return nullptr;
823 }
824 
825 
826 
827 
828 #endif /* FIELD_IMPL_HH_ */
FieldCommon::units
FieldCommon & units(const UnitSI &units)
Set basic units of the field.
Definition: field_common.hh:150
result_none
@ result_none
Definition: field_algo_base.hh:71
LimitSide::right
@ right
FieldCommon::shared_
std::shared_ptr< SharedData > shared_
Definition: field_common.hh:630
Field::cache_reallocate
void cache_reallocate(const ElementCacheMap &cache_map, unsigned int region_idx) const override
Implements FieldCommon::cache_allocate.
Definition: field.impl.hh:770
CacheMapElementNumber::get
static unsigned int get()
Return number of stored elements.
Definition: field_value_cache.hh:101
reader_to_storage.hh
FieldCommon::last_limit_side_
LimitSide last_limit_side_
Definition: field_common.hh:653
Field::value_cache
FieldValueCache< double > * value_cache() override
Implements FieldCommon::value_cache.
Definition: field.impl.hh:793
eval_subset.hh
CouplingPoint
Point accessor allow iterate over quadrature points of given side defined in local element coordinate...
Definition: eval_subset.hh:184
Input::ReaderToStorage
Reader for (slightly) modified input files.
Definition: reader_to_storage.hh:96
Field< 3, FieldValue< 3 >::TensorFixed >::HistoryPoint
pair< double, FieldBasePtr > HistoryPoint
Pair: time, pointer to FieldBase instance.
Definition: field.hh:387
FieldCommon::last_time_
double last_time_
Definition: field_common.hh:652
Field::set_time
bool set_time(const TimeStep &time, LimitSide limit_side) override
Definition: field.impl.hh:300
PointBase::elem_patch_idx
unsigned int elem_patch_idx() const
Definition: eval_subset.hh:65
FieldCommon::flags
FieldFlag::Flags & flags()
Definition: field_common.hh:275
Field::value_cache_
FieldValueCache< typename Value::element_type > value_cache_
Definition: field.hh:429
ElementDataCache
Definition: element_data_cache.hh:44
ASSERT
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library.
Definition: asserts.hh:347
FieldCommon::set_shape
void set_shape(uint n_rows, uint n_cols)
Definition: field_common.hh:530
FieldCommon::messages_data_
static std::vector< MessageData > messages_data_
Vector of data of initialization messages.
Definition: field_common.hh:686
Field::check_initialized_region_fields_
void check_initialized_region_fields_()
Definition: field.impl.hh:539
FieldCommon::set_component_index
void set_component_index(unsigned int idx)
Definition: field_common.hh:443
Input::Type::Integer
Class for declaration of the integral input data.
Definition: type_base.hh:483
Field::Field
Field()
Definition: field.impl.hh:41
Field::set_dependency
std::vector< const FieldCommon * > set_dependency(FieldSet &field_set, unsigned int i_reg) const override
Definition: field.impl.hh:786
ElementCacheMap
Directing class of FieldValueCache.
Definition: field_value_cache.hh:141
FieldEnum
unsigned int FieldEnum
Definition: field_values.hh:56
eval_points.hh
value
static constexpr bool value
Definition: json.hpp:87
Field::observe_output
void observe_output(std::shared_ptr< Observe > observe) override
Definition: field.impl.hh:406
ElementDataCacheBase::n_comp
unsigned int n_comp() const
Definition: element_data_cache_base.hh:145
RegionIdx::is_valid
bool is_valid() const
Returns false if the region has undefined/invalid value.
Definition: region.hh:78
FieldResult
FieldResult
Definition: field_algo_base.hh:70
field_set.hh
FieldCommon::mesh
const Mesh * mesh() const
Definition: field_common.hh:272
BulkPoint
Point accessor allow iterate over bulk quadrature points defined in local element coordinates.
Definition: eval_subset.hh:96
result_other
@ result_other
Definition: field_algo_base.hh:72
THROW
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
std::vector< FieldEnum >
ElementAccessor
Definition: dh_cell_accessor.hh:32
TimeStep::gt
bool gt(double other_time) const
Definition: time_governor.hh:167
OutputTime::ELEM_DATA
@ ELEM_DATA
Definition: output_time.hh:111
ASSERT_EQ_DBG
#define ASSERT_EQ_DBG(a, b)
Definition of comparative assert macro (EQual) only for debug mode.
Definition: asserts.hh:332
OutputTime::discrete_flags_defined
static bool discrete_flags_defined(DiscreteSpaceFlags &dsf)
Check if at least one of discrete space flag is set to true.
Definition: output_time.hh:125
EdgePoint
Point accessor allow iterate over quadrature points of given side defined in local element coordinate...
Definition: eval_subset.hh:154
Field::get_input_type
IT::Instance get_input_type() override
Definition: field.impl.hh:192
field_fe.hh
uint
unsigned int uint
Definition: mh_dofhandler.hh:101
RegionIdx::idx
unsigned int idx() const
Returns a global index of the region.
Definition: region.hh:82
Field::get_field_fe
std::shared_ptr< FieldFE< spacedim, Value > > get_field_fe()
Definition: field.impl.hh:748
BoundaryPoint::eval_point_idx
unsigned int eval_point_idx() const
Return index in EvalPoints object.
Definition: eval_subset.hh:471
TimeStep::read_time
double read_time(Input::Iterator< Input::Tuple > time_it, double default_time=std::numeric_limits< double >::quiet_NaN()) const
Definition: time_governor.cc:259
fmt::format
std::string format(CStringRef format_str, ArgList args)
Definition: format.h:3141
Field::get_value_attribute
std::string get_value_attribute() const override
Definition: field.impl.hh:454
Field::fill_data_cache
void fill_data_cache(OutputTime::DiscreteSpace space_type, std::shared_ptr< OutputTime > stream, std::shared_ptr< ElementDataCache< typename Value::element_type >> data_cache)
Fills acutally the data cache with field values, used in compute_field_data.
Definition: field.impl.hh:679
Field::cache_update
void cache_update(ElementCacheMap &cache_map, unsigned int region_patch_idx) const override
Implements FieldCommon::cache_update.
Definition: field.impl.hh:778
ASSERT_LT
#define ASSERT_LT(a, b)
Definition of comparative assert macro (Less Than)
Definition: asserts.hh:296
result_constant
@ result_constant
Definition: field_algo_base.hh:73
FieldCommon::shape_
std::vector< uint > shape_
Definition: field_common.hh:505
Region
Definition: region.hh:146
OutputTime::DiscreteSpaceFlags
std::array< bool, 4 > DiscreteSpaceFlags
Definition: output_time.hh:122
Input::Iterator
Definition: accessors.hh:143
Field::update_history
void update_history(const TimeStep &time)
Definition: field.impl.hh:468
TimeStep::end
double end() const
Definition: time_governor.hh:161
ObservePointAccessor
Point accessor allow iterate over local Observe points.
Definition: observe.hh:325
Input::Record
Accessor to the data with type Type::Record.
Definition: accessors.hh:291
FieldCommon::multifield_
bool multifield_
Definition: field_common.hh:675
OutputTime::MESH_DEFINITION
@ MESH_DEFINITION
Definition: output_time.hh:113
RegionDB::bulk_size
unsigned int bulk_size() const
Definition: region.cc:268
FieldAlgoBaseInitData
Helper struct stores data for initizalize descentants of FieldAlgorithmBase.
Definition: field_algo_base.hh:81
CouplingPoint::eval_point_idx
unsigned int eval_point_idx() const
Return index in EvalPoints object.
Definition: eval_subset.hh:459
Field::operator[]
Value::return_type operator[](unsigned int i_cache_point) const
Return item of value_cache_ given by i_cache_point.
Definition: field.impl.hh:184
accessors.hh
Field::set
void set(FieldBasePtr field, double time, std::vector< std::string > region_set_names={"ALL"})
Definition: field.impl.hh:258
TimeStep
Representation of one time step..
Definition: time_governor.hh:123
TimeGovernor
Basic time management functionality for unsteady (and steady) solvers (class Equation).
Definition: time_governor.hh:310
Field::field_result
FieldResult field_result(RegionSet region_set) const override
Indicates special field states.
Definition: field.impl.hh:431
Input::AbstractRecord
Accessor to the polymorphic input data of a type given by an AbstracRecord object.
Definition: accessors.hh:458
FieldCommon
Common abstract parent of all Field<...> classes.
Definition: field_common.hh:74
Field::data_
std::shared_ptr< SharedData > data_
Definition: field.hh:401
Input::Record::ei_address
EI_Address ei_address() const
Definition: accessors.cc:178
Mesh::region_db
const RegionDB & region_db() const
Definition: mesh.h:160
ASSERT_EQ
#define ASSERT_EQ(a, b)
Definition of comparative assert macro (EQual)
Definition: asserts.hh:328
Field::factories_
std::vector< std::shared_ptr< FactoryBase > > factories_
Definition: field.hh:418
Input::Record::opt_val
bool opt_val(const string &key, Ret &value) const
Definition: accessors_impl.hh:107
Input::format_JSON
@ format_JSON
Definition: reader_to_storage.hh:60
Input::Type::Instance
Helper class that stores data of generic types.
Definition: type_generic.hh:89
Input::ReaderToStorage::get_root_interface
T get_root_interface() const
Returns the root accessor.
Definition: reader_to_storage.cc:150
LimitSide
LimitSide
Definition: field_common.hh:61
Field::get_multifield_input_type
IT::Array get_multifield_input_type() override
Definition: field.impl.hh:199
Field::region_fields_
std::vector< FieldBasePtr > region_fields_
Definition: field.hh:416
FieldSet
Container for various descendants of FieldCommonBase.
Definition: field_set.hh:159
BulkPoint::eval_point_idx
unsigned int eval_point_idx() const
Return index in EvalPoints object.
Definition: eval_subset.hh:114
field_algo_base.impl.hh
Field< 3, FieldValue< 3 >::TensorFixed >::RegionHistory
boost::circular_buffer< HistoryPoint > RegionHistory
Nearest history of one region.
Definition: field.hh:389
Input::Record::find
Iterator< Ret > find(const string &key) const
Definition: accessors_impl.hh:91
FieldValue_
Definition: field_values.hh:248
Field::add_factory
void add_factory(std::shared_ptr< FactoryBase > factory)
Definition: field.impl.hh:595
Input::Type
Definition: balance.hh:41
Field::value
virtual const Value::return_type & value(const Point &p, const ElementAccessor< spacedim > &elm) const
Definition: field.hh:452
Value
@ Value
Definition: finite_element.hh:43
observe.hh
Field< 3, FieldValue< 3 >::TensorFixed >::FieldBasePtr
std::shared_ptr< FieldBaseType > FieldBasePtr
Definition: field.hh:99
OutputTime::UNDEFINED
@ UNDEFINED
Definition: output_time.hh:114
FieldFE
Definition: field.hh:63
EdgePoint::eval_point_idx
unsigned int eval_point_idx() const
Return index in EvalPoints object.
Definition: eval_subset.hh:450
Mesh
Definition: mesh.h:77
OutputTime::NODE_DATA
@ NODE_DATA
Definition: output_time.hh:109
BoundaryPoint
Point accessor allow iterate over quadrature points of given side defined in local element coordinate...
Definition: eval_subset.hh:213
Field::no_check_control_field_
std::shared_ptr< ControlField > no_check_control_field_
Definition: field.hh:411
TimeGovernor::read_time
double read_time(Input::Iterator< Input::Tuple > time_it, double default_time=std::numeric_limits< double >::quiet_NaN()) const
Definition: time_governor.cc:790
Input::Type::Array
Class for declaration of inputs sequences.
Definition: type_base.hh:339
Field::set_mesh
void set_mesh(const Mesh &mesh) override
Definition: field.impl.hh:219
ElementCacheMap::region_idx_from_chunk_position
unsigned int region_idx_from_chunk_position(unsigned int chunk_pos) const
Return begin position of region chunk specified by position in map.
Definition: field_value_cache.hh:252
Input::Array
Accessor to input data conforming to declared Array.
Definition: accessors.hh:566
OutputTime::OutputDataPtr
std::shared_ptr< ElementDataCacheBase > OutputDataPtr
Definition: output_time.hh:144
WarningOut
#define WarningOut()
Macro defining 'warning' record of log.
Definition: logger.hh:270
Input::Tuple
Accessor to the data with type Type::Tuple.
Definition: accessors.hh:411
std
Definition: doxy_dummy_defs.hh:5
PointBase::elm_cache_map
const ElementCacheMap * elm_cache_map() const
Definition: eval_subset.hh:60
field_value_cache.hh
FieldFlag::equation_input
static constexpr Mask equation_input
The field is data parameter of the owning equation. (default on)
Definition: field_flag.hh:33
OutputTime::CORNER_DATA
@ CORNER_DATA
Definition: output_time.hh:110
FieldCommon::get_flags
FieldFlag::Flags get_flags() const
Definition: field_common.hh:278
output_mesh.hh
Classes for auxiliary output mesh.
Field::FactoryBase::is_active_field_descriptor
virtual bool is_active_field_descriptor(const Input::Record &in_rec, const std::string &input_name)
Definition: field.impl.hh:613
region.hh
Armor::Array
Definition: armor.hh:597
FieldFlag::declare_input
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
Field::compute_field_data
void compute_field_data(OutputTime::DiscreteSpaceFlags space_type, std::shared_ptr< OutputTime > stream)
Definition: field.impl.hh:652
FieldCommon::SharedData
Definition: field_common.hh:544
Field::set_input_list
void set_input_list(const Input::Array &list, const TimeGovernor &tg) override
Definition: field.impl.hh:621
FieldCommon::name
const std::string & name() const
Definition: field_common.hh:243
FieldCommon::n_comp
unsigned int n_comp() const
Definition: field_common.hh:269
Field::is_constant
bool is_constant(Region reg) override
Definition: field.impl.hh:249
OutputTime::DiscreteSpace
DiscreteSpace
Definition: output_time.hh:108
FieldCommon::is_jump_time_
bool is_jump_time_
Definition: field_common.hh:659
FieldCommon::input_name
const std::string & input_name() const
Definition: field_common.hh:240
FieldCommon::limits
std::pair< double, double > limits() const
Definition: field_common.hh:258
Field
Class template representing a field with values dependent on: point, element, and region.
Definition: field.hh:95
std::list
Definition: doxy_dummy_defs.hh:9
TimeStep::ge
bool ge(double other_time) const
Definition: time_governor.hh:173
Field::disable_where
auto disable_where(const Field< spacedim, typename FieldValue< spacedim >::Enum > &control_field, const vector< FieldEnum > &value_list) -> Field &
Definition: field.impl.hh:209
ASSERT_PTR
#define ASSERT_PTR(ptr)
Definition of assert macro checking non-null pointer (PTR)
Definition: asserts.hh:336
Field::FactoryBase::create_field
virtual FieldBasePtr create_field(Input::Record rec, const FieldCommon &field)
Definition: field.impl.hh:601
OutputTime::N_DISCRETE_SPACES
static const unsigned int N_DISCRETE_SPACES
Definition: output_time.hh:107
output_element.hh
Class OutputElement and its iterator OutputElementIterator on the output mesh.
Field::operator()
Value::return_type operator()(BulkPoint &p)
Return appropriate value to BulkPoint in FieldValueCache.
Definition: field.impl.hh:155
Field::copy_from
void copy_from(const FieldCommon &other) override
Definition: field.impl.hh:378
FieldCommon::time
double time() const
Definition: field_common.hh:285
ElementCacheMap::get_value
Value::return_type get_value(const FieldValueCache< typename Value::element_type > &field_cache, unsigned int elem_patch_idx, unsigned int eval_points_idx) const
Return value of evaluation point given by idx of element in patch and local point idx in EvalPoints f...
Definition: field_value_cache.hh:263
ElementDataCache::store_value
void store_value(unsigned int idx, const T *value)
Definition: element_data_cache.cc:222
FieldAlgorithmBase::function_factory
static std::shared_ptr< FieldAlgorithmBase< spacedim, Value > > function_factory(const Input::AbstractRecord &rec, const struct FieldAlgoBaseInitData &init_data)
Definition: field_algo_base.impl.hh:101
field.hh
FieldCommon::MessageData
Store data of one initialization message.
Definition: field_common.hh:96
Field::field_output
void field_output(std::shared_ptr< OutputTime > stream, OutputTime::DiscreteSpaceFlags type) override
Definition: field.impl.hh:395
FieldCommon::set_time_result_
TimeStatus set_time_result_
Definition: field_common.hh:646
FieldCommon::name_
std::string name_
Definition: field_common.hh:625
OutputTime::NATIVE_DATA
@ NATIVE_DATA
Definition: output_time.hh:112
FieldCommon::component_index_
unsigned int component_index_
Definition: field_common.hh:669
FieldCommon::name
FieldCommon & name(const string &name)
Definition: field_common.hh:118
Field::operator=
Field & operator=(const Field &other)
Definition: field.impl.hh:119