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>
175 template<
int spacedim,
class Value>
182 template<
int spacedim,
class Value>
183 typename Value::return_type
186 return Value::get_from_array( this->value_cache_, i_cache_point );
191 template<
int spacedim,
class Value>
193 return FieldBaseType::get_input_type_instance(shared_->input_element_selection_);
198 template<
int spacedim,
class Value>
200 ASSERT(
false).error(
"This method can't be used for Field");
208 template<
int spacedim,
class Value>
213 no_check_control_field_=std::make_shared<ControlField>(control_field);
214 shared_->no_check_values_=value_list;
218 template<
int spacedim,
class Value>
222 if (shared_->mesh_ && shared_->mesh_ != &in_mesh) {
223 THROW(ExcFieldMeshDifference() << EI_Field(name()) );
226 shared_->mesh_ = &in_mesh;
229 region_fields_.resize( mesh()->region_db().size() );
231 data_->region_history_.resize( mesh()->region_db().size(), init_history );
233 if (no_check_control_field_) no_check_control_field_->set_mesh(in_mesh);
248 template <
int spacedim,
class Value>
250 ASSERT(this->set_time_result_ != TimeStatus::unknown).error(
"Unknown time status.\n");
253 return ( region_field && region_field->is_constant_in_space() );
257 template<
int spacedim,
class Value>
263 ASSERT_PTR(field).error(
"Null field pointer.\n");
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() );
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;
274 for(
const Region ®: domain) {
275 RegionHistory ®ion_history = data_->region_history_[reg.idx()];
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);
282 set_history_changed();
287 template<
int spacedim,
class Value>
294 set(FieldBaseType::function_factory(a_rec, init_data), time, region_set_names);
299 template<
int spacedim,
class Value>
302 ASSERT_PTR( mesh() )( name() ).error(
"NULL mesh pointer of field with given name. set_mesh must be called before.\n");
306 if (time_step.
end() == last_time_) {
307 if ( ! is_jump_time() ||
308 limit_side == last_limit_side_) {
309 last_limit_side_ = limit_side;
314 last_time_=time_step.
end();
315 last_limit_side_ = limit_side;
318 if (no_check_control_field_) {
319 no_check_control_field_->set_time(time_step, limit_side);
322 set_time_result_ = TimeStatus::constant;
325 update_history(time_step);
326 check_initialized_region_fields_();
332 for(
const Region ®: mesh()->region_db().get_region_set(
"ALL") ) {
333 auto rh = data_->region_history_[reg.idx()];
336 if (reg.is_boundary() != is_bc())
continue;
339 if ( rh.empty())
continue;
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!");
347 if ( time_step.
gt(last_time_in_history) ) {
359 i_history=min(i_history, history_size - 1);
360 ASSERT(i_history >= 0).error(
"Empty field history.");
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;
369 if ( new_ptr->set_time(time_step) ) set_time_result_ = TimeStatus::changed;
377 template<
int spacedim,
class Value>
380 .error(
"Can not copy to the non-input field.");
384 && this->shared_->input_list_.size() != 0 )
return;
386 if (
typeid(other) ==
typeid(*this)) {
388 this->operator=(other_field);
394 template<
int spacedim,
class Value>
400 this->compute_field_data( type, stream);
405 template<
int spacedim,
class Value>
408 typedef typename Value::element_type ElemType;
410 if (observe->point_ds()->size() == 0)
return;
413 (
unsigned int)Value::NRows_, (
unsigned int)Value::NCols_);
415 unsigned int loc_point_time_index, ele_index;
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(),
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());
430 template<
int spacedim,
class Value>
434 for(
Region ® : region_set) {
435 auto f = region_fields_[reg.idx()];
440 else if (fr != result_all)
453 template<
int spacedim,
class Value>
456 int nrows = Value::NRows_;
457 int ncols = Value::NCols_;
458 string type =
"Integer";
462 return fmt::format(
"{{ \"shape\": [ {}, {} ], \"type\": \"{}\", \"limit\": [ {}, {} ] }}",
463 nrows, ncols, type, this->limits().first, this->limits().second);
467 template<
int spacedim,
class Value>
469 ASSERT_PTR( mesh() ).error(
"Null mesh pointer, set_mesh() has to be called before.\n");
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") ) ) ) {
477 const Input::Record & actual_list_item = shared_->input_list_[shared_->list_idx_];
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);
486 }
else if (actual_list_item.
opt_val(
"rid",
id)) {
489 region = mesh()->region_db().find_id(
id);
490 }
catch (RegionDB::ExcUniqueRegionId &e) {
495 domain.push_back(region);
497 THROW(RegionDB::ExcUnknownRegion() << RegionDB::EI_ID(
id) );
499 THROW(ExcMissingDomain()
504 for(
auto rit = factories_.rbegin() ; rit != factories_.rend(); ++rit) {
505 FieldBasePtr field_instance = (*rit)->create_field(actual_list_item, *
this);
509 ASSERT_EQ( field_instance->n_comp() , shared_->n_comp_);
510 field_instance->set_mesh( mesh() , is_bc() );
511 for(
const Region ®: domain) {
516 if( data_->region_history_[reg.idx()].size() == 0
517 || data_->region_history_[reg.idx()].back().first < input_time)
519 data_->region_history_[reg.idx()].push_front(
525 data_->region_history_[reg.idx()].back() =
533 ++shared_->list_idx_;
538 template<
int spacedim,
class Value>
540 ASSERT_PTR(mesh()).error(
"Null mesh pointer.");
546 for(
const Region ® : mesh()->region_db().get_region_set(
"ALL") )
547 if (reg.is_boundary() == is_bc()) {
549 if ( rh.empty() || ! rh[0].second)
552 if (no_check_control_field_ && no_check_control_field_->is_constant(reg) ) {
555 FieldEnum value = no_check_control_field_->value(elm.centre(),elm);
557 if ( std::find(shared_->no_check_values_.begin(), shared_->no_check_values_.end(),
value)
558 != shared_->no_check_values_.end() )
561 if (shared_->input_default_ !=
"") {
562 regions_to_init.push_back( reg );
564 THROW( ExcMissingFieldValue() << EI_FieldInputName(input_name()) << EI_FieldName(name())
565 << EI_RegId(reg.id()) << EI_RegLabel(reg.label()) );
571 if ( regions_to_init.size() ) {
572 std::string region_list;
574 string default_input=input_default();
575 auto input_type = get_input_type().make_instance().first;
580 auto field_ptr = FieldBaseType::function_factory( a_rec , init_data );
581 field_ptr->set_mesh( mesh(), is_bc() );
582 for(
const Region ®: regions_to_init) {
583 data_->region_history_[reg.idx()]
585 region_list+=
" "+reg.label();
594 template<
int spacedim,
class Value>
596 factories_.push_back( factory );
600 template<
int spacedim,
class Value>
612 template<
int spacedim,
class Value>
620 template<
int spacedim,
class Value>
625 double time,last_time=0.0;
631 if ( (*rit)->is_active_field_descriptor( (*
it), this->input_name() ) ) {
634 if (
time < last_time) {
635 THROW( ExcNonascendingTime()
638 <<
it->ei_address());
651 template<
int spacedim,
class Value>
653 typedef typename Value::element_type ElemType;
659 (
unsigned int)Value::NRows_, (
unsigned int)Value::NCols_);
663 if( ! output_data_base->is_dummy()){
664 auto output_data = std::dynamic_pointer_cast<ElementDataCache<ElemType>>(output_data_base);
668 }
catch(
const std::bad_cast& e){
674 stream->update_time(this->
time());
678 template<
int spacedim,
class Value>
680 std::shared_ptr<OutputTime> stream,
683 std::shared_ptr<OutputMeshBase> output_mesh = stream->get_output_mesh_ptr();
690 unsigned int node_index = 0;
691 for(
const auto & ele : *output_mesh )
694 for(
unsigned int i=0; i < ele.n_nodes(); i++)
696 const Value &node_value =
697 Value(
const_cast<typename Value::return_type &
>(
698 this->
value(vertices[i],
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() );
709 for(
const auto & ele : *output_mesh )
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(),
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() );
724 std::shared_ptr< FieldFE<spacedim, Value> > field_fe_ptr = this->
get_field_fe();
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(),
731 field_fe_ptr->get_dofhandler()->max_elem_dofs());
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);
736 WarningOut().fmt(
"Field '{}' of native data space type is not of type FieldFE. Output will be skipped.\n", this->
name());
747 template<
int spacedim,
class Value>
750 ASSERT(!this->
shared_->bc_).error(
"FieldFE output of native data is supported only for bulk fields!");
752 std::shared_ptr< FieldFE<spacedim, Value> > field_fe_ptr;
762 field_fe_ptr = std::dynamic_pointer_cast< FieldFE<spacedim, Value> >(
region_fields_[1] );
769 template<
int spacedim,
class Value>
777 template<
int spacedim,
class Value>
785 template<
int spacedim,
class Value>
792 template<
int spacedim,
class Value>
809 template<
int spacedim,
class Value>