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);
394 template<
int spacedim,
class Value>
397 typedef typename Value::element_type ElemType;
399 if (observe->point_ds()->size() == 0)
return;
402 (
unsigned int)Value::NRows_, (
unsigned int)Value::NCols_);
404 unsigned int loc_point_time_index, ele_index;
406 loc_point_time_index = op_acc.loc_point_time_index();
407 ele_index = op_acc.observe_point().element_idx();
408 const Value &obs_value =
409 Value(
const_cast<typename Value::return_type &
>(
410 this->
value(op_acc.observe_point().global_coords(),
412 ASSERT_EQ(output_data.
n_comp(), obs_value.n_rows()*obs_value.n_cols()).error();
413 output_data.
store_value(loc_point_time_index, obs_value.mem_ptr());
419 template<
int spacedim,
class Value>
423 for(
Region ® : region_set) {
424 auto f = region_fields_[reg.idx()];
429 else if (fr != result_all)
442 template<
int spacedim,
class Value>
445 int nrows = Value::NRows_;
446 int ncols = Value::NCols_;
447 string type =
"Integer";
451 return fmt::format(
"{{ \"shape\": [ {}, {} ], \"type\": \"{}\", \"limit\": [ {}, {} ] }}",
452 nrows, ncols, type, this->limits().first, this->limits().second);
456 template<
int spacedim,
class Value>
458 ASSERT_PTR( mesh() ).error(
"Null mesh pointer, set_mesh() has to be called before.\n");
462 if (shared_->input_list_.size() != 0) {
463 while( shared_->list_idx_ < shared_->input_list_.size()
464 && time.
ge( input_time = time.
read_time( shared_->input_list_[shared_->list_idx_].find<
Input::Tuple>(
"time") ) ) ) {
466 const Input::Record & actual_list_item = shared_->input_list_[shared_->list_idx_];
471 if (actual_list_item.
opt_val(
"region", domain_name_array)) {
472 std::vector<string> domain_names = mesh()->region_db().get_and_check_operands(domain_name_array);
473 domain = mesh()->region_db().union_set(domain_names);
475 }
else if (actual_list_item.
opt_val(
"rid",
id)) {
478 region = mesh()->region_db().find_id(
id);
479 }
catch (RegionDB::ExcUniqueRegionId &e) {
484 domain.push_back(region);
486 THROW(RegionDB::ExcUnknownRegion() << RegionDB::EI_ID(
id) );
488 THROW(ExcMissingDomain()
493 for(
auto rit = factories_.rbegin() ; rit != factories_.rend(); ++rit) {
494 FieldBasePtr field_instance = (*rit)->create_field(actual_list_item, *
this);
498 ASSERT_EQ( field_instance->n_comp() , shared_->n_comp_);
499 field_instance->set_mesh( mesh() , is_bc() );
500 for(
const Region ®: domain) {
505 if( data_->region_history_[reg.idx()].size() == 0
506 || data_->region_history_[reg.idx()].back().first < input_time)
508 data_->region_history_[reg.idx()].push_front(
514 data_->region_history_[reg.idx()].back() =
522 ++shared_->list_idx_;
527 template<
int spacedim,
class Value>
529 ASSERT_PTR(mesh()).error(
"Null mesh pointer.");
535 for(
const Region ® : mesh()->region_db().get_region_set(
"ALL") )
536 if (reg.is_boundary() == is_bc()) {
538 if ( rh.empty() || ! rh[0].second)
541 if (no_check_control_field_ && no_check_control_field_->is_constant(reg) ) {
544 FieldEnum value = no_check_control_field_->value(elm.centre(),elm);
546 if ( std::find(shared_->no_check_values_.begin(), shared_->no_check_values_.end(),
value)
547 != shared_->no_check_values_.end() )
550 if (shared_->input_default_ !=
"") {
551 regions_to_init.push_back( reg );
553 THROW( ExcMissingFieldValue() << EI_FieldInputName(input_name()) << EI_FieldName(name())
554 << EI_RegId(reg.id()) << EI_RegLabel(reg.label()) );
560 if ( regions_to_init.size() ) {
561 std::string region_list;
563 string default_input=input_default();
564 auto input_type = get_input_type().make_instance().first;
569 auto field_ptr = FieldBaseType::function_factory( a_rec , init_data );
570 field_ptr->set_mesh( mesh(), is_bc() );
571 for(
const Region ®: regions_to_init) {
572 data_->region_history_[reg.idx()]
574 region_list+=
" "+reg.label();
583 template<
int spacedim,
class Value>
585 factories_.push_back( factory );
589 template<
int spacedim,
class Value>
601 template<
int spacedim,
class Value>
609 template<
int spacedim,
class Value>
614 double time,last_time=0.0;
620 if ( (*rit)->is_active_field_descriptor( (*
it), this->input_name() ) ) {
623 if (
time < last_time) {
624 THROW( ExcNonascendingTime()
627 <<
it->ei_address());
640 template<
int spacedim,
class Value>
642 typedef typename Value::element_type ElemType;
644 auto output_cache_base = stream->prepare_compute_data<ElemType>(this->
name(), space_type,
645 (
unsigned int)Value::NRows_, (
unsigned int)Value::NCols_);
646 output_data_cache_ = std::dynamic_pointer_cast<ElementDataCache<ElemType>>(output_cache_base);
650 template<
int spacedim,
class Value>
652 std::shared_ptr<OutputMeshBase> output_mesh = stream->get_output_mesh_ptr();
658 std::shared_ptr< FieldFE<spacedim, Value> > field_fe_ptr = this->
get_field_fe();
661 auto native_output_data_base = stream->prepare_compute_data<
double>(this->
name(), space_type,
662 (
unsigned int)Value::NRows_, (
unsigned int)Value::NCols_,
663 typeid(field_fe_ptr->get_dofhandler()->ds()->fe()[0_d].get()).
name(),
665 field_fe_ptr->get_dofhandler()->max_elem_dofs());
667 auto native_output_data = std::dynamic_pointer_cast<ElementDataCache<double>>(native_output_data_base);
668 field_fe_ptr->native_data_to_cache(*native_output_data);
670 WarningOut().fmt(
"Field '{}' of native data space type is not of type FieldFE. Output will be skipped.\n", this->
name());
674 stream->update_time(this->
time());
679 template<
int spacedim,
class Value>
682 for (
unsigned int i=0; i<offsets.size(); ++i) {
683 if (offsets[i] == -1)
continue;
684 auto ret_value = Value::get_from_array(this->
value_cache_, i);
691 template<
int spacedim,
class Value>
694 ASSERT(!this->
shared_->bc_).error(
"FieldFE output of native data is supported only for bulk fields!");
696 std::shared_ptr< FieldFE<spacedim, Value> > field_fe_ptr;
706 field_fe_ptr = std::dynamic_pointer_cast< FieldFE<spacedim, Value> >(
region_fields_[1] );
713 template<
int spacedim,
class Value>
721 template<
int spacedim,
class Value>
729 template<
int spacedim,
class Value>
736 template<
int spacedim,
class Value>
753 template<
int spacedim,
class Value>