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() );
214 RegionHistory init_history(history_length_limit_);
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) {
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>
#define ASSERT_PERMANENT(expr)
Allow use shorter versions of macro names if these names is not used with external library.
#define ASSERT_LT(a, b)
Definition of comparative assert macro (Less Than) only for debug mode.
#define ASSERT_EQ(a, b)
Definition of comparative assert macro (EQual) only for debug mode.
#define ASSERT_PTR(ptr)
Definition of assert macro checking non-null pointer (PTR) only for debug mode.
Base point accessor class.
const ElementCacheMap * elm_cache_map() const
unsigned int elem_patch_idx() const
unsigned int eval_point_idx() const
Return index in EvalPoints object.
static unsigned int get()
Return number of stored elements.
Directing class of FieldValueCache.
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...
unsigned int region_idx_from_chunk_position(unsigned int chunk_pos) const
Return begin position of region chunk specified by position in map.
static std::shared_ptr< FieldAlgorithmBase< spacedim, Value > > function_factory(const Input::AbstractRecord &rec, const struct FieldAlgoBaseInitData &init_data)
Common abstract parent of all Field<...> classes.
std::shared_ptr< SharedData > shared_
TimeStatus set_time_result_
unsigned int component_index_
const std::string & input_name() const
const std::string & name() const
LimitSide last_limit_side_
std::vector< uint > shape_
FieldCommon & name(const string &name)
std::pair< double, double > limits() const
FieldFlag::Flags get_flags() const
void set_component_index(unsigned int idx)
FieldFlag::Flags & flags()
void set_shape(uint n_rows, uint n_cols)
static std::vector< MessageData > messages_data_
Vector of data of initialization messages.
const Mesh * mesh() const
FieldCommon & units(const UnitSI &units)
Set basic units of the field.
unsigned int n_comp() const
static constexpr Mask declare_input
The field can be set from input. The key in input field descriptor is declared. (default on)
static constexpr Mask equation_input
The field is data parameter of the owning equation. (default on)
virtual bool is_active_field_descriptor(const Input::Record &in_rec, const std::string &input_name)
virtual FieldBasePtr create_field(Input::Record rec, const FieldCommon &field)
Class template representing a field with values dependent on: point, element, and region.
FieldValueCache< typename Value::element_type > value_cache_
void set_input_list(const Input::Array &list, const TimeGovernor &tg) override
std::string get_value_attribute() const override
pair< double, FieldBasePtr > HistoryPoint
Pair: time, pointer to FieldBase instance.
auto disable_where(const Field< spacedim, typename FieldValue< spacedim >::Enum > &control_field, const vector< FieldEnum > &value_list) -> Field &
bool is_constant(Region reg) override
boost::circular_buffer< HistoryPoint > RegionHistory
Nearest history of one region.
void fill_data_value(const std::vector< int > &offsets) override
Implements FieldCommon::fill_data_value.
void cache_reallocate(const ElementCacheMap &cache_map, unsigned int region_idx) const override
Implements FieldCommon::cache_allocate.
void cache_update(ElementCacheMap &cache_map, unsigned int region_patch_idx) const override
Implements FieldCommon::cache_update.
bool set_time(const TimeStep &time, LimitSide limit_side) override
void fill_observe_value(std::shared_ptr< ElementDataCacheBase > output_cache_base, const std::vector< int > &offsets) override
Implements FieldCommon::fill_observe_value.
Value::return_type operator()(BulkPoint &p)
Return appropriate value to BulkPoint in FieldValueCache.
Value::return_type operator[](unsigned int i_cache_point) const
Return item of value_cache_ given by i_cache_point.
void copy_from(const FieldCommon &other) override
FieldResult field_result(RegionSet region_set) const override
Indicates special field states.
void set(FieldBasePtr field, double time, std::vector< std::string > region_set_names={"ALL"})
void update_history(const TimeStep &time)
IT::Instance get_input_type() override
void field_output(std::shared_ptr< OutputTime > stream, OutputTime::DiscreteSpace type) override
std::vector< const FieldCommon * > set_dependency(unsigned int i_reg) const override
std::shared_ptr< ElementDataCache< typename Value::element_type > > output_data_cache_
ElementDataCache used during field output, object is shared with OutputTime.
std::shared_ptr< SharedData > data_
void check_initialized_region_fields_()
void add_factory(std::shared_ptr< FactoryBase > factory)
std::shared_ptr< ControlField > no_check_control_field_
Field & operator=(const Field &other)
IT::Array get_multifield_input_type() override
std::vector< std::shared_ptr< FactoryBase > > factories_
std::shared_ptr< FieldBaseType > FieldBasePtr
std::shared_ptr< FieldFE< spacedim, Value > > get_field_fe()
FieldValueCache< double > * value_cache() override
Implements FieldCommon::value_cache.
void compute_field_data(OutputTime::DiscreteSpace space_type, std::shared_ptr< OutputTime > stream)
void set_mesh(const Mesh &mesh) override
std::vector< FieldBasePtr > region_fields_
void set_output_data_cache(OutputTime::DiscreteSpace space_type, std::shared_ptr< OutputTime > stream) override
const RegionDB & region_db() const
static const unsigned int N_DISCRETE_SPACES
unsigned int bulk_size() const
unsigned int idx() const
Returns a global index of the region.
bool is_valid() const
Returns false if the region has undefined/invalid value.
unsigned int id() const
Returns id of the region (using RegionDB)
std::string label() const
Returns label of the region (using RegionDB)
General point a+ side_begin_ + ccessor allow iterate over quadrature points of given side defined in ...
unsigned int eval_point_idx() const
Return index in EvalPoints object.
Basic time management functionality for unsteady (and steady) solvers (class Equation).
double read_time(Input::Iterator< Input::Tuple > time_it, double default_time=std::numeric_limits< double >::quiet_NaN()) const
Representation of one time step..
double read_time(Input::Iterator< Input::Tuple > time_it, double default_time=std::numeric_limits< double >::quiet_NaN()) const
bool ge(double other_time) const
bool gt(double other_time) const
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
static constexpr bool value
#define WarningOut()
Macro defining 'warning' record of log.
std::string format(CStringRef format_str, ArgList args)
Class OutputElement and its iterator OutputElementIterator on the output mesh.
Classes for auxiliary output mesh.
Helper struct stores data for initizalize descentants of FieldAlgorithmBase.
Store data of one initialization message.