11 #include <boost/foreach.hpp>
22 template<
int spacedim,
class Value>
28 shared_->n_comp_ = (Value::NRows_ ? 0 : 1);
29 this->
add_factory( std::make_shared<FactoryBase>() );
35 template<
int spacedim,
class Value>
42 shared_->n_comp_ = (Value::NRows_ ? 0 : 1);
45 this->
add_factory( std::make_shared<FactoryBase>() );
51 template<
int spacedim,
class Value>
55 factories_(other.factories_)
68 template<
int spacedim,
class Value>
72 ASSERT(other.
shared_->mesh_,
"Must call set_mesh before assign to other field.\n");
74 "Assignment between fields with different meshes.\n");
77 if (&other ==
this)
return *
this;
80 shared_->is_fully_initialized_ =
false;
100 template<
int spacedim,
class Value>
110 if (is_enum_valued) {
111 ar_list.push_back(make_input_tree());
112 return ar_list.back();
114 return FieldBaseType::input_type;
120 template<
int spacedim,
class Value>
122 ASSERT(
false,
"This method can't be used for Field");
131 template <
class FieldBaseType>
135 "NULL pointer to selection in Field::get_input_type(), while Value==FieldEnum.\n");
136 return FieldBaseType::get_input_type(sel);
140 template <
class FieldBaseType>
143 return FieldBaseType::get_input_type(
nullptr);
150 template<
int spacedim,
class Value>
153 "Can not use make_input_tree() for non-enum valued fields, use get_inout_type() instead.\n" );
154 return get_input_type_resolution<FieldBaseType>(
155 shared_->input_element_selection_ ,
156 boost::is_same<typename Value::element_type, FieldEnum>());
161 template<
int spacedim,
class Value>
166 no_check_control_field_=std::make_shared<ControlField>(control_field);
167 shared_->no_check_values_=value_list;
171 template<
int spacedim,
class Value>
176 THROW(ExcFieldMeshDifference() << EI_Field(
name()) );
182 region_fields_.resize(
mesh()->region_db().
size() );
184 data_->region_history_.resize(
mesh()->region_db().
size(), init_history );
186 if (no_check_control_field_) no_check_control_field_->set_mesh(in_mesh);
201 template <
int spacedim,
class Value>
209 template<
int spacedim,
class Value>
215 ASSERT(field,
"Null field pointer.\n");
217 ASSERT(
mesh(),
"Null mesh pointer, set_mesh() has to be called before set_field().\n");
218 if (domain.size() == 0)
return;
224 for(
const Region ®: domain) {
225 RegionHistory ®ion_history = data_->region_history_[reg.idx()];
227 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",
228 hp.first, region_history[0].first );
229 region_history.push_front(hp);
236 template<
int spacedim,
class Value>
242 set_field(domain, FieldBaseType::function_factory(a_rec,
n_comp()), time);
248 template<
int spacedim,
class Value>
251 ASSERT(
mesh() ,
"NULL mesh pointer of field '%s'. set_mesh must be called before.\n",
name().c_str());
259 if (no_check_control_field_) {
260 no_check_control_field_->set_limit_side(
limit_side_);
261 no_check_control_field_->set_time(time);
267 update_history(time);
268 check_initialized_region_fields_();
272 for(
const Region ®:
mesh()->region_db().get_region_set(
"ALL") ) {
273 auto rh = data_->region_history_[reg.idx()];
277 if (reg.is_boundary() ==
is_bc() && !rh.empty() ) {
278 double last_time_in_history = rh.front().first;
279 unsigned int history_size=rh.size();
280 unsigned int i_history;
282 if ( time.
gt(last_time_in_history) ) {
293 i_history=min(i_history, history_size - 1);
294 ASSERT(i_history >= 0,
"Empty field history.");
296 auto new_ptr = rh.at(i_history).second;
297 if (new_ptr != region_fields_[reg.idx()]) {
298 region_fields_[reg.idx()]=new_ptr;
311 template<
int spacedim,
class Value>
314 other.
name().c_str(), this->
name().c_str());
315 if (
typeid(other) ==
typeid(*this)) {
317 this->operator=(other_field);
323 template<
int spacedim,
class Value>
333 template<
int spacedim,
class Value>
335 auto f = region_fields_[elm.
region().
idx()];
336 if (f)
return f->field_result();
342 template<
int spacedim,
class Value>
344 ASSERT(
mesh(),
"Null mesh pointer, set_mesh() has to be called before.\n");
348 if (
shared_->input_list_.size() != 0) {
350 && time.
ge( input_time =
shared_->list_it_->val<
double>(
"time") ) ) {
354 std::string domain_name;
356 if (
shared_->list_it_->opt_val(
"r_set", domain_name)) {
358 if (domain.size() == 0) {
359 THROW( RegionDB::ExcUnknownSetOperand()
360 << RegionDB::EI_Label(domain_name) <<
shared_->list_it_->ei_address() );
363 }
else if (
shared_->list_it_->opt_val(
"region", domain_name)) {
367 domain.push_back(region);
369 xprintf(
Warn,
"Unknown region with label: '%s'\n", domain_name.c_str());
371 }
else if (
shared_->list_it_->opt_val(
"rid",
id)) {
375 domain.push_back(region);
377 xprintf(
Warn,
"Unknown region with id: '%d'\n",
id);
378 }
catch (RegionDB::ExcUniqueRegionId &e) {
379 e <<
shared_->input_list_.ei_address();
383 THROW(ExcMissingDomain()
384 <<
shared_->list_it_->ei_address() );
387 ASSERT(domain.size(),
"Region set with name %s is empty or not exists.\n", domain_name.c_str());
390 for(
auto rit = factories_.rbegin() ; rit != factories_.rend(); ++rit) {
396 field_instance->set_mesh(
mesh() ,
is_bc() );
397 for(
const Region ®: domain) {
398 data_->region_history_[reg.idx()].push_front(
411 template<
int spacedim,
class Value>
414 if (
shared_->is_fully_initialized_)
return;
419 for(
const Region ® :
mesh()->region_db().get_region_set(
"ALL") )
420 if (reg.is_boundary() ==
is_bc()) {
422 if ( rh.empty() || ! rh[0].second)
425 if (no_check_control_field_ && no_check_control_field_->is_constant(reg) ) {
428 FieldEnum value = no_check_control_field_->value(elm.centre(),elm);
430 if ( std::find(
shared_->no_check_values_.begin(),
shared_->no_check_values_.end(), value)
431 !=
shared_->no_check_values_.end() )
434 if (
shared_->input_default_ !=
"") {
435 regions_to_init.push_back( reg );
437 xprintf(
UsrErr,
"Missing value of the input field '%s' ('%s') on region ID: %d label: %s.\n",
438 input_name().c_str(),
name().c_str(), reg.id(), reg.label().c_str() );
444 if ( regions_to_init.size() ) {
445 std::string region_list;
452 auto field_ptr = FieldBaseType::function_factory( a_rec ,
n_comp() );
454 for(
const Region ®: regions_to_init) {
455 data_->region_history_[reg.idx()]
457 region_list+=
" "+reg.label();
459 xprintf(
Warn,
"Using default value '%s' for part of the input field '%s' ('%s').\n"
464 shared_->is_fully_initialized_;
468 template<
int spacedim,
class Value>
470 factories_.push_back( factory );
474 template<
int spacedim,
class Value>
void check_initialized_region_fields_()
Common abstract parent of all Field<...> classes.
pair< double, FieldBasePtr > HistoryPoint
Pair: time, pointer to FieldBase instance.
bool set_time(const TimeStep &time) override
void output(OutputTime *stream) override
unsigned int size() const
Number of subfields that compose the multi-field.
IT::AbstractRecord make_input_tree()
-------— end helper function template
Class template representing a field with values dependent on: point, element, and region...
IT::Record & get_multifield_input_type() override
void register_data(const DiscreteSpace type, MultiField< spacedim, Value > &multi_field)
Generic method for registering output data stored in MultiField.
RegionSet get_region_set(const string &set_name) const
void update_history(const TimeStep &time)
const std::string & input_default() const
const RegionDB & region_db() const
virtual FieldBasePtr create_field(Input::Record rec, const FieldCommon &field)
std::shared_ptr< SharedData > data_
FieldResult field_result(ElementAccessor< spacedim > &elm) const
IT::AbstractRecord & get_input_type() override
std::shared_ptr< SharedData > shared_
OutputTime::DiscreteSpace output_type() const
const std::string & name() const
bool ge(double other_time) const
static constexpr Mask input_copy
A field that is input of its equation and can not read from input, thus must be set by copy...
#define ASSERT_EQUAL(a, b)
FieldFlag::Flags & flags()
Region find_id(unsigned int id, unsigned int dim) const
#define ASSERT_LESS(a, b)
std::shared_ptr< ControlField > no_check_control_field_
static std::shared_ptr< FieldAlgorithmBase< spacedim, Value > > function_factory(const Input::AbstractRecord &rec, unsigned int n_comp=0)
IT::AbstractRecord & get_input_type() override
The class for outputting 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
std::vector< std::shared_ptr< FactoryBase > > factories_
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 add_factory(std::shared_ptr< FactoryBase > factory)
void set_field(const RegionSet &domain, FieldBasePtr field, double time=0.0)
bool gt(double other_time) const
const Mesh * mesh() const
FieldCommon & name(const string &name)
unsigned int n_comp() const
void set_mesh(const Mesh &mesh) override
void set_history_changed()
Region find_label(const std::string &label) const
bool is_valid() const
Returns false if the region has undefined/invalid value.
const std::string & input_name() const
void copy_from(const FieldCommon &other) override
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Representation of one time step.
TimeStatus set_time_result_
Status of history.
void set_mesh(const Mesh &mesh) override
Field & operator=(const Field &other)
static const unsigned int history_length_limit_
unsigned int idx() const
Returns a global index of the region.