18 #ifndef FIELD_IMPL_HH_
19 #define FIELD_IMPL_HH_
40 template<
int spacedim,
class Value>
47 shared_->n_comp_ = (Value::NRows_ ? 0 : 1);
48 this->
add_factory( std::make_shared<FactoryBase>() );
55 this->
set_shape( Value::NRows_, Value::NCols_ );
59 template<
int spacedim,
class Value>
66 shared_->n_comp_ = (Value::NRows_ ? 0 : 1);
68 this->
add_factory( std::make_shared<FactoryBase>() );
74 this->
set_shape( Value::NRows_, Value::NCols_ );
79 template<
int spacedim,
class Value>
86 shared_->n_comp_ = (Value::NRows_ ? 0 : 1);
96 this->
set_shape( Value::NRows_, Value::NCols_ );
100 template<
int spacedim,
class Value>
104 region_fields_(other.region_fields_),
105 factories_(other.factories_),
106 value_cache_(other.value_cache_)
112 this->
set_shape( Value::NRows_, Value::NCols_ );
116 template<
int spacedim,
class Value>
120 ASSERT(other.
shared_->mesh_).error(
"Must call set_mesh before assign to other field.\n");
121 ASSERT( !shared_->mesh_ || (shared_->mesh_==other.
shared_->mesh_) ).error(
"Assignment between fields with different meshes.\n");
124 if (&other ==
this)
return *
this;
128 shared_->is_fully_initialized_ =
false;
134 this->multifield_ =
false;
141 this->shape_ = other.
shape_;
152 template<
int spacedim,
class Value>
159 template<
int spacedim,
class Value>
166 template<
int spacedim,
class Value>
167 typename Value::return_type
170 return Value::get_from_array( this->value_cache_, i_cache_point );
175 template<
int spacedim,
class Value>
177 return FieldBaseType::get_input_type_instance(shared_->input_element_selection_);
182 template<
int spacedim,
class Value>
192 template<
int spacedim,
class Value>
197 no_check_control_field_=std::make_shared<ControlField>(control_field);
198 shared_->no_check_values_=value_list;
202 template<
int spacedim,
class Value>
206 if (shared_->mesh_ && shared_->mesh_ != &in_mesh) {
207 THROW(ExcFieldMeshDifference() << EI_Field(name()) );
210 shared_->mesh_ = &in_mesh;
213 region_fields_.resize( mesh()->region_db().size() );
215 data_->region_history_.resize( mesh()->region_db().size(), init_history );
217 if (no_check_control_field_) no_check_control_field_->set_mesh(in_mesh);
232 template <
int spacedim,
class Value>
234 ASSERT(this->set_time_result_ != TimeStatus::unknown).error(
"Unknown time status.\n");
237 return ( region_field && region_field->is_constant_in_space() );
241 template<
int spacedim,
class Value>
247 ASSERT_PTR(field).error(
"Null field pointer.\n");
249 ASSERT_PTR( mesh() ).error(
"Null mesh pointer, set_mesh() has to be called before set().\n");
250 ASSERT_EQ( field->n_comp() , shared_->n_comp_);
251 field->set_mesh( mesh() );
253 for (
auto set_name : region_set_names) {
254 RegionSet domain = mesh()->region_db().get_region_set(set_name);
255 if (domain.size() == 0)
continue;
258 for(
const Region ®: domain) {
259 RegionHistory ®ion_history = data_->region_history_[reg.idx()];
261 ASSERT( region_history.size() == 0 || region_history[0].first < hp.first)(hp.first)(region_history[0].first)
262 .error(
"Can not insert smaller time then last time in field's history.\n");
263 region_history.push_front(hp);
266 set_history_changed();
271 template<
int spacedim,
class Value>
278 set(FieldBaseType::function_factory(a_rec, init_data), time, region_set_names);
283 template<
int spacedim,
class Value>
286 ASSERT_PTR( mesh() )( name() ).error(
"NULL mesh pointer of field with given name. set_mesh must be called before.\n");
290 if (time_step.
end() == last_time_) {
291 if ( ! is_jump_time() ||
292 limit_side == last_limit_side_) {
293 last_limit_side_ = limit_side;
298 last_time_=time_step.
end();
299 last_limit_side_ = limit_side;
302 if (no_check_control_field_) {
303 no_check_control_field_->set_time(time_step, limit_side);
306 if(set_time_result_ == TimeStatus::changed_forced)
307 set_time_result_ = TimeStatus::changed;
309 set_time_result_ = TimeStatus::constant;
312 update_history(time_step);
313 check_initialized_region_fields_();
319 for(
const Region ®: mesh()->region_db().get_region_set(
"ALL") ) {
320 auto rh = data_->region_history_[reg.idx()];
323 if ( rh.empty())
continue;
325 double last_time_in_history = rh.front().first;
326 unsigned int history_size=rh.size();
327 unsigned int i_history;
328 ASSERT( time_step.
ge(last_time_in_history) ).error(
"Setting field time back in history not fully supported yet!");
331 if ( time_step.
gt(last_time_in_history) ) {
343 i_history=min(i_history, history_size - 1);
344 ASSERT(i_history >= 0).error(
"Empty field history.");
347 auto new_ptr = rh.at(i_history).second;
348 if (new_ptr != region_fields_[reg.idx()]) {
349 region_fields_[reg.idx()]=new_ptr;
350 set_time_result_ = TimeStatus::changed;
353 if ( new_ptr->set_time(time_step) ) set_time_result_ = TimeStatus::changed;
361 template<
int spacedim,
class Value>
364 .error(
"Can not copy to the non-input field.");
368 && this->shared_->input_list_.size() != 0 )
return;
370 if (
typeid(other) ==
typeid(*this)) {
372 this->operator=(other_field);
378 template<
int spacedim,
class Value>
383 this->compute_field_data( type, stream);
388 template<
int spacedim,
class Value>
392 for(
Region ® : region_set) {
393 auto f = region_fields_[reg.idx()];
398 else if (fr != result_all)
411 template<
int spacedim,
class Value>
414 int nrows = Value::NRows_;
415 int ncols = Value::NCols_;
416 string type =
"Integer";
420 return fmt::format(
"{{ \"shape\": [ {}, {} ], \"type\": \"{}\", \"limit\": [ {}, {} ] }}",
421 nrows, ncols, type, this->limits().first, this->limits().second);
425 template<
int spacedim,
class Value>
427 ASSERT_PTR( mesh() ).error(
"Null mesh pointer, set_mesh() has to be called before.\n");
431 if (shared_->input_list_.size() != 0) {
432 while( shared_->list_idx_ < shared_->input_list_.size()
433 && time.
ge( input_time = time.
read_time( shared_->input_list_[shared_->list_idx_].find<
Input::Tuple>(
"time") ) ) ) {
435 const Input::Record & actual_list_item = shared_->input_list_[shared_->list_idx_];
440 if (actual_list_item.
opt_val(
"region", domain_name_array)) {
441 std::vector<string> domain_names = mesh()->region_db().get_and_check_operands(domain_name_array);
442 domain = mesh()->region_db().union_set(domain_names);
444 }
else if (actual_list_item.
opt_val(
"rid",
id)) {
447 region = mesh()->region_db().find_id(
id);
448 }
catch (RegionDB::ExcUniqueRegionId &e) {
453 domain.push_back(region);
455 THROW(RegionDB::ExcUnknownRegion() << RegionDB::EI_ID(
id) );
457 THROW(ExcMissingDomain()
462 for(
auto rit = factories_.rbegin() ; rit != factories_.rend(); ++rit) {
463 FieldBasePtr field_instance = (*rit)->create_field(actual_list_item, *
this);
467 ASSERT_EQ( field_instance->n_comp() , shared_->n_comp_);
468 field_instance->set_mesh( mesh() );
469 for(
const Region ®: domain) {
474 if( data_->region_history_[reg.idx()].size() == 0
475 || data_->region_history_[reg.idx()].back().first < input_time)
477 data_->region_history_[reg.idx()].push_front(
483 data_->region_history_[reg.idx()].back() =
491 ++shared_->list_idx_;
496 template<
int spacedim,
class Value>
498 ASSERT_PTR(mesh()).error(
"Null mesh pointer.");
504 for(
const Region ® : mesh()->region_db().get_region_set(
"ALL") ) {
506 if ( rh.empty() || ! rh[0].second)
518 if (shared_->input_default_ !=
"") {
519 regions_to_init.push_back( reg );
521 THROW( ExcMissingFieldValue() << EI_FieldInputName(input_name()) << EI_FieldName(name())
522 << EI_RegId(reg.id()) << EI_RegLabel(reg.label()) );
528 if ( regions_to_init.size() ) {
529 std::string region_list;
531 string default_input=input_default();
532 auto input_type = get_input_type().make_instance().first;
537 auto field_ptr = FieldBaseType::function_factory( a_rec , init_data );
538 field_ptr->set_mesh( mesh() );
539 for(
const Region ®: regions_to_init) {
540 data_->region_history_[reg.idx()]
542 region_list+=
" "+reg.label();
551 template<
int spacedim,
class Value>
553 factories_.push_back( factory );
557 template<
int spacedim,
class Value>
569 template<
int spacedim,
class Value>
577 template<
int spacedim,
class Value>
582 double time,last_time=0.0;
588 if ( (*rit)->is_active_field_descriptor( (*
it), this->input_name() ) ) {
591 if (
time < last_time) {
592 THROW( ExcNonascendingTime()
595 <<
it->ei_address());
608 template<
int spacedim,
class Value>
610 typedef typename Value::element_type ElemType;
612 auto output_cache_base = stream->prepare_compute_data<ElemType>(this->
name(), space_type,
613 (
unsigned int)Value::NRows_, (
unsigned int)Value::NCols_);
614 output_data_cache_ = std::dynamic_pointer_cast<ElementDataCache<ElemType>>(output_cache_base);
618 template<
int spacedim,
class Value>
620 std::shared_ptr<OutputMeshBase> output_mesh = stream->get_output_mesh_ptr();
626 std::shared_ptr< FieldFE<spacedim, Value> > field_fe_ptr = this->
get_field_fe();
629 auto native_output_data_base = stream->prepare_compute_data<
double>(this->
name(), space_type,
630 (
unsigned int)Value::NRows_, (
unsigned int)Value::NCols_,
631 typeid(field_fe_ptr->get_dofhandler()->ds()->fe()[0_d].get()).
name(),
633 field_fe_ptr->get_dofhandler()->max_elem_dofs());
635 auto native_output_data = std::dynamic_pointer_cast<ElementDataCache<double>>(native_output_data_base);
636 field_fe_ptr->native_data_to_cache(*native_output_data);
638 WarningOut().fmt(
"Field '{}' of native data space type is not of type FieldFE. Output will be skipped.\n", this->
name());
642 stream->update_time(this->
time());
647 template<
int spacedim,
class Value>
650 for (
unsigned int i=0; i<offsets.size(); ++i) {
651 if (offsets[i] == -1)
continue;
652 auto ret_value = Value::get_from_array(this->
value_cache_, i);
659 template<
int spacedim,
class Value>
662 typedef typename Value::element_type ElemType;
664 std::shared_ptr<ElementDataCache<ElemType>> observe_data_cache =
665 std::dynamic_pointer_cast<ElementDataCache<ElemType>>(output_cache_base);
667 for (
unsigned int i=0; i<offsets.size(); ++i) {
668 if (offsets[i] == -1)
continue;
669 auto ret_value = Value::get_from_array(this->
value_cache_, i);
671 observe_data_cache->store_value(offsets[i], ele_value.mem_ptr() );
676 template<
int spacedim,
class Value>
681 std::shared_ptr< FieldFE<spacedim, Value> > field_fe_ptr;
691 field_fe_ptr = std::dynamic_pointer_cast< FieldFE<spacedim, Value> >(
region_fields_[1] );
698 template<
int spacedim,
class Value>
706 template<
int spacedim,
class Value>
714 template<
int spacedim,
class Value>
721 template<
int spacedim,
class Value>
738 template<
int spacedim,
class Value>