11 #include <boost/foreach.hpp>
22 template<
int spacedim,
class Value>
24 : read_field_descriptor_hook( &read_field_descriptor ),
30 shared_->n_comp_ = (Value::NRows_ ? 0 : 1);
34 template<
int spacedim,
class Value>
36 : read_field_descriptor_hook( &read_field_descriptor ),
42 shared_->n_comp_ = (Value::NRows_ ? 0 : 1);
49 template<
int spacedim,
class Value>
52 read_field_descriptor_hook( other.read_field_descriptor_hook ),
65 template<
int spacedim,
class Value>
68 ASSERT( flags().match(
FieldFlag::input_copy ) ,
"Try to assign to non-copy field '%s' from the field '%s'.", this->name().c_str(), other.
name().c_str());
69 ASSERT(other.
shared_->mesh_,
"Must call set_mesh before assign to other field.\n");
70 ASSERT( !shared_->mesh_ || (shared_->mesh_==other.
shared_->mesh_),
71 "Assignment between fields with different meshes.\n");
74 if (&other ==
this)
return *
this;
77 shared_->is_fully_initialized_ =
false;
89 this->set_mesh( *(shared_->mesh_) );
97 template<
int spacedim,
class Value>
107 if (is_enum_valued) {
108 ar_list.push_back(make_input_tree());
109 return ar_list.back();
111 return FieldBaseType::input_type;
118 template <
class FieldBaseType>
122 "NULL pointer to selection in Field::get_input_type(), while Value==FieldEnum.\n");
123 return FieldBaseType::get_input_type(sel);
127 template <
class FieldBaseType>
130 return FieldBaseType::get_input_type(
nullptr);
137 template<
int spacedim,
class Value>
140 "Can not use make_input_tree() for non-enum valued fields, use get_inout_type() instead.\n" );
141 return get_input_type_resolution<FieldBaseType>(
142 shared_->input_element_selection_ ,
143 boost::is_same<typename Value::element_type, FieldEnum>());
148 template<
int spacedim,
class Value>
153 no_check_control_field_=std::make_shared<ControlField>(control_field);
154 shared_->no_check_values_=value_list;
158 template<
int spacedim,
class Value>
162 if (shared_->mesh_ && shared_->mesh_ != &in_mesh) {
163 THROW(ExcFieldMeshDifference() << EI_Field(name()) );
166 shared_->mesh_ = &in_mesh;
169 region_fields_.resize( mesh()->region_db().size() );
171 data_->region_history_.resize( mesh()->region_db().size(), init_history );
173 if (no_check_control_field_) no_check_control_field_->set_mesh(in_mesh);
188 template <
int spacedim,
class Value>
196 template<
int spacedim,
class Value>
202 ASSERT(field,
"Null field pointer.\n");
204 ASSERT( mesh(),
"Null mesh pointer, set_mesh() has to be called before set_field().\n");
205 if (domain.size() == 0)
return;
208 field->set_mesh( mesh() , is_bc() );
211 for(
const Region ®: domain) {
212 RegionHistory ®ion_history = data_->region_history_[reg.idx()];
214 ASSERT( region_history.size() == 0 || region_history[0].first < hp.first,
"Can not insert smaller time %g then last time %g in field's history.\n",
215 hp.first, region_history[0].first );
216 region_history.push_front(hp);
218 set_history_changed();
223 template<
int spacedim,
class Value>
229 set_field(domain, FieldBaseType::function_factory(a_rec, n_comp()), time);
234 template<
int spacedim,
class Value>
238 if (rec.opt_val(field.input_name(), field_record))
239 return FieldBaseType::function_factory(field_record, field.n_comp() );
247 template<
int spacedim,
class Value>
250 ASSERT( mesh() ,
"NULL mesh pointer of field '%s'. set_mesh must be called before.\n",name().c_str());
251 ASSERT( limit_side_ !=
LimitSide::unknown,
"Must set limit side on field '%s' before calling set_time.\n",name().c_str());
254 if (time.
t() == last_time_)
return changed();
258 if (no_check_control_field_) {
259 no_check_control_field_->set_limit_side(limit_side_);
260 no_check_control_field_->set_time(time);
263 set_time_result_ = TimeStatus::constant;
266 update_history(time);
267 check_initialized_region_fields_();
271 for(
const Region ®: mesh()->region_db().get_region_set(
"ALL") ) {
272 auto rh = data_->region_history_[reg.idx()];
276 if (reg.is_boundary() == is_bc() && !rh.empty() ) {
277 double last_time_in_history = rh.front().first;
278 unsigned int history_size=rh.size();
279 unsigned int i_history;
281 if ( time.
gt(last_time_in_history) ) {
292 i_history=min(i_history, history_size - 1);
293 ASSERT(i_history >= 0,
"Empty field history.");
295 auto new_ptr = rh.at(i_history).second;
296 if (new_ptr != region_fields_[reg.idx()]) {
297 region_fields_[reg.idx()]=new_ptr;
298 set_time_result_ = TimeStatus::changed;
301 if ( new_ptr->set_time(time.
t()) ) set_time_result_ = TimeStatus::changed;
310 template<
int spacedim,
class Value>
313 other.
name().c_str(), this->name().c_str());
314 if (
typeid(other) ==
typeid(*this)) {
316 this->operator=(other_field);
322 template<
int spacedim,
class Value>
332 template<
int spacedim,
class Value>
334 auto f = region_fields_[elm.
region().
idx()];
335 if (f)
return f->field_result();
341 template<
int spacedim,
class Value>
343 ASSERT( mesh(),
"Null mesh pointer, set_mesh() has to be called before.\n");
347 if (shared_->input_list_.size() != 0) {
348 while( shared_->list_it_ != shared_->input_list_.end()
349 && time.
ge( input_time = shared_->list_it_->val<
double>(
"time") ) ) {
353 std::string domain_name;
355 if (shared_->list_it_->opt_val(
"r_set", domain_name)) {
356 domain = mesh()->region_db().get_region_set(domain_name);
358 }
else if (shared_->list_it_->opt_val(
"region", domain_name)) {
360 Region region = mesh()->region_db().find_label(domain_name);
362 domain.push_back(region);
364 xprintf(
Warn,
"Unknown region with label: '%s'\n", domain_name.c_str());
366 }
else if (shared_->list_it_->opt_val(
"rid",
id)) {
368 Region region = mesh()->region_db().find_id(
id);
370 domain.push_back(region);
372 xprintf(
Warn,
"Unknown region with id: '%d'\n",
id);
373 }
catch (RegionDB::ExcUniqueRegionId &e) {
374 e << shared_->input_list_.ei_address();
378 THROW(ExcMissingDomain()
379 << shared_->list_it_->ei_address() );
382 if (domain.size() == 0) {
387 FieldBasePtr field_instance = read_field_descriptor_hook(*(shared_->list_it_), *
this);
392 field_instance->set_mesh( mesh() , is_bc() );
393 for(
const Region ®: domain) {
394 data_->region_history_[reg.idx()].push_front(
404 template<
int spacedim,
class Value>
406 ASSERT(mesh(),
"Null mesh pointer.");
407 if (shared_->is_fully_initialized_)
return;
412 for(
const Region ® : mesh()->region_db().get_region_set(
"ALL") )
413 if (reg.is_boundary() == is_bc()) {
415 if ( rh.empty() || ! rh[0].second)
418 if (no_check_control_field_ && no_check_control_field_->is_constant(reg) ) {
421 FieldEnum value = no_check_control_field_->value(elm.centre(),elm);
423 if ( std::find(shared_->no_check_values_.begin(), shared_->no_check_values_.end(), value)
424 != shared_->no_check_values_.end() )
427 if (shared_->input_default_ !=
"") {
428 regions_to_init.push_back( reg );
430 xprintf(
UsrErr,
"Missing value of the input field '%s' ('%s') on region ID: %d label: %s.\n",
431 input_name().c_str(), name().c_str(), reg.id(), reg.label().c_str() );
437 if ( regions_to_init.size() ) {
438 xprintf(
Warn,
"Using default value '%s' for part of the input field '%s' ('%s').\n",
439 input_default().c_str(), input_name().c_str(), name().c_str());
442 string default_input=input_default();
443 auto input_type = get_input_type();
447 auto field_ptr = FieldBaseType::function_factory( a_rec , n_comp() );
448 field_ptr->set_mesh( mesh(), is_bc() );
449 for(
const Region ®: regions_to_init) {
450 data_->region_history_[reg.idx()]
454 shared_->is_fully_initialized_;
465 template<
int spacedim,
class Value>
472 template<
int spacedim,
class Value>
474 sub_fields_.resize( names.size() );
476 for(
unsigned int i_comp=0; i_comp < size(); i_comp++)
478 sub_fields_[i_comp].units( units() );
480 if (sub_names_[i_comp].length() == 0)
481 sub_fields_[i_comp].name( name() );
483 sub_fields_[i_comp].name( sub_names_[i_comp] +
"_" + name());
489 #pragma GCC diagnostic push
490 #pragma GCC diagnostic ignored "-Wreturn-type"
491 template<
int spacedim,
class Value>
494 #pragma GCC diagnostic pop
497 template<
int spacedim,
class Value>
501 field.set_limit_side(side);
505 template<
int spacedim,
class Value>
511 if (field.set_time(time))
519 template<
int spacedim,
class Value>
521 shared_->mesh_ = &mesh;
522 for(
unsigned int i_comp=0; i_comp < size(); i_comp++)
523 sub_fields_[i_comp].set_mesh(mesh);
527 template<
int spacedim,
class Value>
529 if (
typeid(other) ==
typeid(*
this)) {
531 this->operator=(other_field);
533 auto const &other_field =
dynamic_cast< SubFieldType const &
>(other);
534 sub_fields_.resize(1);
535 sub_fields_[0] = other_field;
541 template<
int spacedim,
class Value>
553 template<
int spacedim,
class Value>
555 bool const_all=
false;
556 for(
auto field : sub_fields_) const_all = const_all || field.is_constant(reg);
void check_initialized_region_fields_()
Common abstract parent of all Field<...> classes.
pair< double, FieldBasePtr > HistoryPoint
Pair: time, pointer to FieldBase instance.
void init(const vector< string > &names)
void output(OutputTime *stream) override
void set_limit_side(LimitSide side) override
void update_history(const TimeGovernor &time)
FieldBasePtr(* read_field_descriptor_hook)(Input::Record rec, const FieldCommon &field)
IT::AbstractRecord make_input_tree()
-------— end helper function template
void copy_from(const FieldCommon &other) override
Class template representing a field with values dependent on: point, element, and region...
void register_data(const DiscreteSpace type, MultiField< spacedim, Value > &multi_field)
Generic method for registering output data stored in MultiField.
bool ge(double other_time) const
Basic time management functionality for unsteady (and steady) solvers (class Equation).
std::shared_ptr< SharedData > data_
FieldResult field_result(ElementAccessor< spacedim > &elm) const
IT::AbstractRecord & get_input_type() override
std::shared_ptr< SharedData > shared_
const std::string & name() const
static constexpr Mask input_copy
A field that is input of its equation and cna not read from input, thus muzt be set by copy...
#define ASSERT_EQUAL(a, b)
#define ASSERT_LESS(a, b)
std::shared_ptr< ControlField > no_check_control_field_
IT::AbstractRecord & get_input_type() override
The class for outputing data during time.
IT::AbstractRecord get_input_type_resolution(const Input::Type::Selection *sel, const boost::true_type &)
-------— Helper function template for make_input_tree method
FieldResult
Result type have sense only for larger Value types like vectors and tensors.
std::shared_ptr< FieldBaseType > FieldBasePtr
bool is_constant(Region reg) override
auto disable_where(const Field< spacedim, typename FieldValue< spacedim >::Enum > &control_field, const vector< FieldEnum > &value_list) -> Field &
boost::circular_buffer< HistoryPoint > RegionHistory
Nearest history of one region.
bool is_constant(Region reg) override
void set_field(const RegionSet &domain, FieldBasePtr field, double time=0.0)
bool set_time(const TimeGovernor &time) override
bool set_time(const TimeGovernor &time) override
FieldCommon & name(const string &name)
void set_mesh(const Mesh &mesh) override
static FieldBasePtr read_field_descriptor(Input::Record rec, const FieldCommon &field)
void output(OutputTime *stream) override
Class for representation of a vector of fields of the same physical quantity.
bool is_valid() const
Returns false if the region has undefined/invalid value.
void copy_from(const FieldCommon &other) override
bool gt(double other_time) const
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
void set_mesh(const Mesh &mesh) override
Field & operator=(const Field &other)
unsigned int idx() const
Returns a global index of the region.