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);
69 this->
add_factory( std::make_shared<FactoryBase>() );
75 this->
set_shape( Value::NRows_, Value::NCols_ );
80 template<
int spacedim,
class Value>
87 shared_->n_comp_ = (Value::NRows_ ? 0 : 1);
98 this->
set_shape( Value::NRows_, Value::NCols_ );
102 template<
int spacedim,
class Value>
106 region_fields_(other.region_fields_),
107 factories_(other.factories_),
108 value_cache_(other.value_cache_)
114 this->
set_shape( Value::NRows_, Value::NCols_ );
118 template<
int spacedim,
class Value>
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");
126 if (&other ==
this)
return *
this;
130 shared_->is_fully_initialized_ =
false;
136 this->multifield_ =
false;
143 this->shape_ = other.
shape_;
154 template<
int spacedim,
class Value>
161 template<
int spacedim,
class Value>
168 template<
int spacedim,
class Value>
169 typename Value::return_type
172 return Value::get_from_array( this->value_cache_, i_cache_point );
177 template<
int spacedim,
class Value>
179 return FieldBaseType::get_input_type_instance(shared_->input_element_selection_);
184 template<
int spacedim,
class Value>
194 template<
int spacedim,
class Value>
199 no_check_control_field_=std::make_shared<ControlField>(control_field);
200 shared_->no_check_values_=value_list;
204 template<
int spacedim,
class Value>
208 if (shared_->mesh_ && shared_->mesh_ != &in_mesh) {
209 THROW(ExcFieldMeshDifference() << EI_Field(name()) );
212 shared_->mesh_ = &in_mesh;
215 region_fields_.resize( mesh()->region_db().size() );
217 data_->region_history_.resize( mesh()->region_db().size(), init_history );
219 if (no_check_control_field_) no_check_control_field_->set_mesh(in_mesh);
234 template <
int spacedim,
class Value>
236 ASSERT(this->set_time_result_ != TimeStatus::unknown).error(
"Unknown time status.\n");
239 return ( region_field && region_field->is_constant_in_space() );
243 template<
int spacedim,
class Value>
249 ASSERT_PTR(field).error(
"Null field pointer.\n");
251 ASSERT_PTR( mesh() ).error(
"Null mesh pointer, set_mesh() has to be called before set().\n");
252 ASSERT_EQ( field->n_comp() , shared_->n_comp_);
253 field->set_mesh( mesh() , is_bc() );
255 for (
auto set_name : region_set_names) {
256 RegionSet domain = mesh()->region_db().get_region_set(set_name);
257 if (domain.size() == 0)
continue;
260 for(
const Region ®: domain) {
261 RegionHistory ®ion_history = data_->region_history_[reg.idx()];
263 ASSERT( region_history.size() == 0 || region_history[0].first < hp.first)(hp.first)(region_history[0].first)
264 .error(
"Can not insert smaller time then last time in field's history.\n");
265 region_history.push_front(hp);
268 set_history_changed();
273 template<
int spacedim,
class Value>
280 set(FieldBaseType::function_factory(a_rec, init_data), time, region_set_names);
285 template<
int spacedim,
class Value>
288 ASSERT_PTR( mesh() )( name() ).error(
"NULL mesh pointer of field with given name. set_mesh must be called before.\n");
292 if (time_step.
end() == last_time_) {
293 if ( ! is_jump_time() ||
294 limit_side == last_limit_side_) {
295 last_limit_side_ = limit_side;
300 last_time_=time_step.
end();
301 last_limit_side_ = limit_side;
304 if (no_check_control_field_) {
305 no_check_control_field_->set_time(time_step, limit_side);
308 if(set_time_result_ == TimeStatus::changed_forced)
309 set_time_result_ = TimeStatus::changed;
311 set_time_result_ = TimeStatus::constant;
314 update_history(time_step);
315 check_initialized_region_fields_();
321 for(
const Region ®: mesh()->region_db().get_region_set(
"ALL") ) {
322 auto rh = data_->region_history_[reg.idx()];
325 if (reg.is_boundary() != is_bc())
continue;
328 if ( rh.empty())
continue;
330 double last_time_in_history = rh.front().first;
331 unsigned int history_size=rh.size();
332 unsigned int i_history;
333 ASSERT( time_step.
ge(last_time_in_history) ).error(
"Setting field time back in history not fully supported yet!");
336 if ( time_step.
gt(last_time_in_history) ) {
348 i_history=min(i_history, history_size - 1);
349 ASSERT(i_history >= 0).error(
"Empty field history.");
352 auto new_ptr = rh.at(i_history).second;
353 if (new_ptr != region_fields_[reg.idx()]) {
354 region_fields_[reg.idx()]=new_ptr;
355 set_time_result_ = TimeStatus::changed;
358 if ( new_ptr->set_time(time_step) ) set_time_result_ = TimeStatus::changed;
366 template<
int spacedim,
class Value>
369 .error(
"Can not copy to the non-input field.");
373 && this->shared_->input_list_.size() != 0 )
return;
375 if (
typeid(other) ==
typeid(*this)) {
377 this->operator=(other_field);
383 template<
int spacedim,
class Value>
389 this->compute_field_data( type, stream);
395 template<
int spacedim,
class Value>
399 for(
Region ® : region_set) {
400 auto f = region_fields_[reg.idx()];
405 else if (fr != result_all)
418 template<
int spacedim,
class Value>
421 int nrows = Value::NRows_;
422 int ncols = Value::NCols_;
423 string type =
"Integer";
427 return fmt::format(
"{{ \"shape\": [ {}, {} ], \"type\": \"{}\", \"limit\": [ {}, {} ] }}",
428 nrows, ncols, type, this->limits().first, this->limits().second);
432 template<
int spacedim,
class Value>
434 ASSERT_PTR( mesh() ).error(
"Null mesh pointer, set_mesh() has to be called before.\n");
438 if (shared_->input_list_.size() != 0) {
439 while( shared_->list_idx_ < shared_->input_list_.size()
440 && time.
ge( input_time = time.
read_time( shared_->input_list_[shared_->list_idx_].find<
Input::Tuple>(
"time") ) ) ) {
442 const Input::Record & actual_list_item = shared_->input_list_[shared_->list_idx_];
447 if (actual_list_item.
opt_val(
"region", domain_name_array)) {
448 std::vector<string> domain_names = mesh()->region_db().get_and_check_operands(domain_name_array);
449 domain = mesh()->region_db().union_set(domain_names);
451 }
else if (actual_list_item.
opt_val(
"rid",
id)) {
454 region = mesh()->region_db().find_id(
id);
455 }
catch (RegionDB::ExcUniqueRegionId &e) {
460 domain.push_back(region);
462 THROW(RegionDB::ExcUnknownRegion() << RegionDB::EI_ID(
id) );
464 THROW(ExcMissingDomain()
469 for(
auto rit = factories_.rbegin() ; rit != factories_.rend(); ++rit) {
470 FieldBasePtr field_instance = (*rit)->create_field(actual_list_item, *
this);
474 ASSERT_EQ( field_instance->n_comp() , shared_->n_comp_);
475 field_instance->set_mesh( mesh() , is_bc() );
476 for(
const Region ®: domain) {
481 if( data_->region_history_[reg.idx()].size() == 0
482 || data_->region_history_[reg.idx()].back().first < input_time)
484 data_->region_history_[reg.idx()].push_front(
490 data_->region_history_[reg.idx()].back() =
498 ++shared_->list_idx_;
503 template<
int spacedim,
class Value>
505 ASSERT_PTR(mesh()).error(
"Null mesh pointer.");
511 for(
const Region ® : mesh()->region_db().get_region_set(
"ALL") )
512 if (reg.is_boundary() == is_bc()) {
514 if ( rh.empty() || ! rh[0].second)
526 if (shared_->input_default_ !=
"") {
527 regions_to_init.push_back( reg );
529 THROW( ExcMissingFieldValue() << EI_FieldInputName(input_name()) << EI_FieldName(name())
530 << EI_RegId(reg.id()) << EI_RegLabel(reg.label()) );
536 if ( regions_to_init.size() ) {
537 std::string region_list;
539 string default_input=input_default();
540 auto input_type = get_input_type().make_instance().first;
545 auto field_ptr = FieldBaseType::function_factory( a_rec , init_data );
546 field_ptr->set_mesh( mesh(), is_bc() );
547 for(
const Region ®: regions_to_init) {
548 data_->region_history_[reg.idx()]
550 region_list+=
" "+reg.label();
559 template<
int spacedim,
class Value>
561 factories_.push_back( factory );
565 template<
int spacedim,
class Value>
577 template<
int spacedim,
class Value>
585 template<
int spacedim,
class Value>
590 double time,last_time=0.0;
596 if ( (*rit)->is_active_field_descriptor( (*
it), this->input_name() ) ) {
599 if (
time < last_time) {
600 THROW( ExcNonascendingTime()
603 <<
it->ei_address());
616 template<
int spacedim,
class Value>
618 typedef typename Value::element_type ElemType;
620 auto output_cache_base = stream->prepare_compute_data<ElemType>(this->
name(), space_type,
621 (
unsigned int)Value::NRows_, (
unsigned int)Value::NCols_);
622 output_data_cache_ = std::dynamic_pointer_cast<ElementDataCache<ElemType>>(output_cache_base);
626 template<
int spacedim,
class Value>
628 std::shared_ptr<OutputMeshBase> output_mesh = stream->get_output_mesh_ptr();
634 std::shared_ptr< FieldFE<spacedim, Value> > field_fe_ptr = this->
get_field_fe();
637 auto native_output_data_base = stream->prepare_compute_data<
double>(this->
name(), space_type,
638 (
unsigned int)Value::NRows_, (
unsigned int)Value::NCols_,
639 typeid(field_fe_ptr->get_dofhandler()->ds()->fe()[0_d].get()).
name(),
641 field_fe_ptr->get_dofhandler()->max_elem_dofs());
643 auto native_output_data = std::dynamic_pointer_cast<ElementDataCache<double>>(native_output_data_base);
644 field_fe_ptr->native_data_to_cache(*native_output_data);
646 WarningOut().fmt(
"Field '{}' of native data space type is not of type FieldFE. Output will be skipped.\n", this->
name());
650 stream->update_time(this->
time());
655 template<
int spacedim,
class Value>
658 for (
unsigned int i=0; i<offsets.size(); ++i) {
659 if (offsets[i] == -1)
continue;
660 auto ret_value = Value::get_from_array(this->
value_cache_, i);
667 template<
int spacedim,
class Value>
670 typedef typename Value::element_type ElemType;
672 std::shared_ptr<ElementDataCache<ElemType>> observe_data_cache =
673 std::dynamic_pointer_cast<ElementDataCache<ElemType>>(output_cache_base);
675 for (
unsigned int i=0; i<offsets.size(); ++i) {
676 if (offsets[i] == -1)
continue;
677 auto ret_value = Value::get_from_array(this->
value_cache_, i);
679 observe_data_cache->store_value(offsets[i], ele_value.mem_ptr() );
684 template<
int spacedim,
class Value>
687 ASSERT(!this->
shared_->bc_).error(
"FieldFE output of native data is supported only for bulk fields!");
689 std::shared_ptr< FieldFE<spacedim, Value> > field_fe_ptr;
699 field_fe_ptr = std::dynamic_pointer_cast< FieldFE<spacedim, Value> >(
region_fields_[1] );
706 template<
int spacedim,
class Value>
714 template<
int spacedim,
class Value>
722 template<
int spacedim,
class Value>
729 template<
int spacedim,
class Value>
746 template<
int spacedim,
class Value>