Flow123d  release_3.0.0-968-gc87a28e79
field_elementwise.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file field_elementwise.cc
15  * @brief
16  */
17 
18 
19 #include <boost/type_traits/is_floating_point.hpp>
21 #include "fields/field_instances.hh" // for instantiation macros
22 #include "tools/unit_si.hh"
23 #include "system/file_path.hh"
24 #include "system/exceptions.hh"
25 #include "input/input_type.hh"
26 #include "io/msh_gmshreader.h"
27 #include "io/reader_cache.hh"
28 
29 /// Implementation.
30 
31 namespace IT = Input::Type;
32 
33 FLOW123D_FORCE_LINK_IN_CHILD(field_elementwise)
34 
35 
36 template <int spacedim, class Value>
38 {
39  return IT::Record("FieldElementwise", FieldAlgorithmBase<spacedim,Value>::template_name()+" Field piecewise constant on mesh elements.")
43  "Input file with ASCII GMSH file format.")
45  "The values of the Field are read from the ```$ElementData``` section with field name given by this key.")
46  //.declare_key("unit", FieldAlgorithmBase<spacedim, Value>::get_input_type_unit_si(), IT::Default::optional(),
47  // "Definition of unit.")
48  .declare_key("default_value", IT::Double(), IT::Default::optional(),
49  "Allow set default value of elements that have not listed values in mesh data file.")
50  .declare_key("time_unit", IT::String(), IT::Default::read_time("Common unit of TimeGovernor."),
51  "Definition of unit of all times defined in mesh data file.")
52  .declare_key("read_time_shift", TimeGovernor::get_input_time_type(), IT::Default("0.0"),
53  "Allow set time shift of field data read from the mesh data file. For time 't', field descriptor with time 'T', "
54  "time shift 'S' and if 't > T', we read time frame 't + S'.")
55  .close();
56 }
57 
58 
59 template <int spacedim, class Value>
61  Input::register_class< FieldElementwise<spacedim, Value>, unsigned int >("FieldElementwise") +
63 
64 
65 
66 template <int spacedim, class Value>
68 : FieldAlgorithmBase<spacedim, Value>(n_comp),
69  internal_raw_data(true), mesh_(NULL), unit_si_( UnitSI::dimensionless() )
70 
71 {
72  n_components_ = this->value_.n_rows() * this->value_.n_cols();
73  this->is_constant_in_space_ = false;
74 }
75 
76 
77 
78 template <int spacedim, class Value>
80  unsigned int n_components)
81 : FieldAlgorithmBase<spacedim, Value>(n_components),
82 internal_raw_data(false), mesh_(NULL), unit_si_( UnitSI::dimensionless() )
83 {
84  n_components_ = this->value_.n_rows() * this->value_.n_cols();
85  data_ = data;
86  //this->scale_and_check_limits();
87 }
88 
89 
90 
91 
92 template <int spacedim, class Value>
94  this->init_unit_conversion_coefficient(rec, init_data);
95  this->in_rec_ = rec;
96  this->unit_si_ = init_data.unit_si_;
97  this->limits_ = init_data.limits_;
98 
99  DebugOut() << "Reader file: " << string(reader_file_);
100  ASSERT(internal_raw_data).error("Trying to initialize internal FieldElementwise from input.");
101  ASSERT(reader_file_ == FilePath()).error("Multiple call of init_from_input.");
102  reader_file_ = FilePath( rec.val<FilePath>("mesh_data_file") );
103 
104  field_name_ = rec.val<std::string>("field_name");
105  if (!in_rec_.opt_val("default_value", default_value_) ) {
106  default_value_ = numeric_limits<double>::signaling_NaN();
107  }
108 }
109 
110 
111 
112 /*template <int spacedim, class Value>
113 void FieldElementwise<spacedim, Value>::set_data_row(unsigned int boundary_idx, typename Value::return_type &value) {
114  Value ref(value);
115  OLD_ASSERT( this->value_.n_cols() == ref.n_cols(), "Size of variable vectors do not match.\n" );
116  OLD_ASSERT( mesh_, "Null mesh pointer of elementwise field: %s, did you call set_mesh()?\n", field_name_.c_str());
117  OLD_ASSERT( boundary_domain_ , "Method set_data_row can be used only for boundary fields.");
118  unsigned int vec_pos = boundary_idx * n_components_;
119  std::vector<typename Value::element_type> &vec = *( data_.get() );
120  for(unsigned int row=0; row < ref.n_rows(); row++)
121  for(unsigned int col=0; col < ref.n_cols(); col++, vec_pos++)
122  vec[vec_pos] = ref(row,col);
123 
124 }*/
125 
126 
127 template <int spacedim, class Value>
129  OLD_ASSERT(mesh_, "Null mesh pointer of elementwise field: %s, did you call set_mesh()?\n", field_name_.c_str());
130  if ( reader_file_ == FilePath() ) return false;
131 
132  //walkaround for the steady time governor - there is no data to be read in time==infinity
133  //TODO: is it possible to check this before calling set_time?
134  //if (time.end() == numeric_limits< double >::infinity()) return false;
135 
136  double time_unit_coef = time.read_coef(in_rec_.find<string>("time_unit"));
137  double time_shift = time.read_time( in_rec_.find<Input::Tuple>("read_time_shift") );
138  double read_time = (time.end()+time_shift) / time_unit_coef;
139  BaseMeshReader::HeaderQuery header_query(field_name_, read_time, OutputTime::DiscreteSpace::ELEM_DATA);
140  ReaderCache::get_reader(reader_file_)->find_header(header_query);
141  data_ = ReaderCache::get_reader(reader_file_)-> template get_element_data<typename Value::element_type>(
142  n_entities_, n_components_, boundary_domain_, this->component_idx_);
143  CheckResult checked_data = ReaderCache::get_reader(reader_file_)->scale_and_check_limits(field_name_,
144  this->unit_conversion_coefficient_, default_value_, limits_.first, limits_.second);
145 
146  if (checked_data == CheckResult::not_a_number) {
147  THROW( ExcUndefElementValue() << EI_Field(field_name_) );
148  } else if (checked_data == CheckResult::out_of_limits) {
149  WarningOut().fmt("Values of some elements of FieldElementwise '{}' at address '{}' is out of limits: <{}, {}>\n"
150  "Unit of the Field: [{}]\n",
151  field_name_, in_rec_.address_string(), limits_.first, limits_.second, unit_si_.format_text() );
152  }
153 
154  return true;
155 }
156 
157 
158 
159 template <int spacedim, class Value>
160 void FieldElementwise<spacedim, Value>::set_mesh(const Mesh *mesh, bool boundary_domain) {
161  // set mesh only once or to same value
162  OLD_ASSERT(mesh_ == nullptr || mesh_ == mesh, "Trying to change mesh of the FieldElementwise.");
163  boundary_domain_ = boundary_domain;
164 
165  mesh_=mesh;
166  n_entities_=mesh_->n_elements(boundary_domain_);
167 
168  // allocate
169  if (!data_) {
170  data_ = std::make_shared<std::vector<typename Value::element_type>>();
171  data_->resize(n_entities_ * n_components_);
172  }
173 
174  if ( reader_file_ == FilePath() ) return;
175  ReaderCache::get_reader(reader_file_)->check_compatible_mesh( const_cast<Mesh &>(*mesh) );
176 }
177 
178 
179 
180 /**
181  * Returns one value in one given point. ResultType can be used to avoid some costly calculation if the result is trivial.
182  */
183 template <int spacedim, class Value>
184 typename Value::return_type const & FieldElementwise<spacedim, Value>::value(const Point &p, const ElementAccessor<spacedim> &elm)
185 {
186  OLD_ASSERT( elm.is_elemental(), "FieldElementwise works only for 'elemental' ElementAccessors.\n");
187  OLD_ASSERT( elm.is_boundary() == boundary_domain_, "Trying to get value of FieldElementwise '%s' for wrong ElementAccessor type (boundary/bulk).\n", field_name_.c_str() );
188 
189  unsigned int idx = n_components_ * elm.idx();
190  std::vector<typename Value::element_type> &vec = *( data_.get() );
191 
192  return Value::from_raw(this->r_value_, (typename Value::element_type *)(&vec[idx]));
193 }
194 
195 
196 
197 /**
198  * Returns std::vector of scalar values in several points at once.
199  */
200 template <int spacedim, class Value>
203 {
204  OLD_ASSERT( elm.is_elemental(), "FieldElementwise works only for 'elemental' ElementAccessors.\n");
205  OLD_ASSERT( elm.is_boundary() == boundary_domain_, "Trying to get value of FieldElementwise '%s' for wrong ElementAccessor type (boundary/bulk).\n", field_name_.c_str() );
206  OLD_ASSERT_EQUAL( point_list.size(), value_list.size() );
208  unsigned int idx = n_components_ * elm.idx();
209  std::vector<typename Value::element_type> &vec = *( data_.get() );
210 
211  typename Value::return_type const &ref = Value::from_raw(this->r_value_, (typename Value::element_type *)(&vec[idx]));
212  for(unsigned int i=0; i< value_list.size(); i++) {
213  OLD_ASSERT( Value(value_list[i]).n_rows()==this->value_.n_rows(),
214  "value_list[%d] has wrong number of rows: %d; should match number of components: %d\n",
215  i, Value(value_list[i]).n_rows(),this->value_.n_rows());
216 
217  value_list[i] = ref;
218  }
219  } else {
220  xprintf(UsrErr, "FieldElementwise is not implemented for discrete return types.\n");
221  }
222 }
223 
224 
225 
226 template <int spacedim, class Value>
228 
229 
230 // Instantiations of FieldElementwise
OLD_ASSERT_EQUAL
#define OLD_ASSERT_EQUAL(a, b)
Definition: global_defs.h:133
FieldElementwise::~FieldElementwise
virtual ~FieldElementwise()
Definition: field_elementwise.cc:227
UsrErr
@ UsrErr
Definition: system.hh:64
FieldElementwise::data_
std::shared_ptr< std::vector< typename Value::element_type > > data_
Raw buffer of n_entities rows each containing Value::size() doubles.
Definition: field_elementwise.hh:126
ASSERT
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library.
Definition: asserts.hh:346
file_path.hh
Input::Record::val
const Ret val(const string &key) const
Definition: accessors_impl.hh:31
value
static constexpr bool value
Definition: json.hpp:87
FilePath
Dedicated class for storing path to input and output files.
Definition: file_path.hh:54
Input::Type::Double
Class for declaration of the input data that are floating point numbers.
Definition: type_base.hh:534
FieldAlgoBaseInitData::unit_si_
const UnitSI & unit_si_
Definition: field_algo_base.hh:91
FLOW123D_FORCE_LINK_IN_CHILD
#define FLOW123D_FORCE_LINK_IN_CHILD(x)
Definition: global_defs.h:180
THROW
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
FieldAlgorithmBase::is_constant_in_space_
bool is_constant_in_space_
Flag detects that field is only dependent on time.
Definition: field_algo_base.hh:271
std::vector
Definition: doxy_dummy_defs.hh:7
Input::Type::Default::read_time
static Default read_time(const std::string &description)
The factory function to make an default value that will be specified at the time when a key will be r...
Definition: type_record.hh:97
ElementAccessor
Definition: fe_value_handler.hh:29
FieldElementwise::value
const Value::return_type & value(const Point &p, const ElementAccessor< spacedim > &elm) override
Definition: field_elementwise.cc:184
FieldElementwise::set_time
bool set_time(const TimeStep &time) override
Definition: field_elementwise.cc:128
reader_cache.hh
ElementAccessor::is_elemental
bool is_elemental() const
Definition: accessors.hh:79
TimeStep::read_time
double read_time(Input::Iterator< Input::Tuple > time_it, double default_time=std::numeric_limits< double >::quiet_NaN()) const
Definition: time_governor.cc:238
FieldAlgorithmBase::Point
Space< spacedim >::Point Point
Definition: field_algo_base.hh:113
msh_gmshreader.h
exceptions.hh
FieldElementwise::init_from_input
virtual void init_from_input(const Input::Record &rec, const struct FieldAlgoBaseInitData &init_data) override
Definition: field_elementwise.cc:93
Input::Type::Default
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:61
Input::Type::Record::derive_from
virtual Record & derive_from(Abstract &parent)
Method to derive new Record from an AbstractRecord parent.
Definition: type_record.cc:195
ElementAccessor::is_boundary
bool is_boundary() const
We need this method after replacing Region by RegionIdx, and movinf RegionDB instance into particular...
Definition: accessors.hh:106
TimeStep::end
double end() const
Definition: time_governor.hh:151
Input::Record
Accessor to the data with type Type::Record.
Definition: accessors.hh:291
FieldElementwise::n_components_
unsigned int n_components_
Size of Value.
Definition: field_elementwise.hh:130
FieldAlgoBaseInitData::limits_
std::pair< double, double > limits_
Definition: field_algo_base.hh:92
FieldAlgoBaseInitData
Helper struct stores data for initizalize descentants of FieldAlgorithmBase.
Definition: field_algo_base.hh:79
xprintf
#define xprintf(...)
Definition: system.hh:92
TimeStep
Representation of one time step..
Definition: time_governor.hh:113
CheckResult
CheckResult
Return type of method that checked data stored in ElementDataCache (NaN values, limits)
Definition: element_data_cache.hh:36
FieldAlgorithmBase::value_
Value value_
Last value, prevents passing large values (vectors) by value.
Definition: field_algo_base.hh:262
Input::Type::Default::obligatory
static Default obligatory()
The factory function to make an empty default value which is obligatory.
Definition: type_record.hh:110
UnitSI
Class for representation SI units of Fields.
Definition: unit_si.hh:40
Input::Type::Record::declare_key
Record & declare_key(const string &key, std::shared_ptr< TypeBase > type, const Default &default_value, const string &description, TypeBase::attribute_map key_attributes=TypeBase::attribute_map())
Declares a new key of the Record.
Definition: type_record.cc:501
field_elementwise.hh
Input::Type::FileName::input
static FileName input()
The factory function for declaring type FileName for input files.
Definition: type_base.cc:525
Input::Type::Record::close
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:303
Input::Type
Definition: balance.hh:38
Input::Type::Record
Record type proxy class.
Definition: type_record.hh:182
FieldElementwise::get_input_type
static const Input::Type::Record & get_input_type()
Implementation.
Definition: field_elementwise.cc:37
Value
@ Value
Definition: finite_element.hh:47
not_a_number
@ not_a_number
Some value(s) is set to NaN.
Definition: element_data_cache.hh:39
input_type.hh
Mesh
Definition: mesh.h:80
Input::Type::Record::copy_keys
Record & copy_keys(const Record &other)
Copy keys from other record.
Definition: type_record.cc:215
FieldAlgorithmBase
Definition: field_algo_base.hh:110
OLD_ASSERT
#define OLD_ASSERT(...)
Definition: global_defs.h:131
Input::Type::String
Class for declaration of the input data that are in string format.
Definition: type_base.hh:582
FieldElementwise
Definition: field_elementwise.hh:66
unit_si.hh
WarningOut
#define WarningOut()
Macro defining 'warning' record of log.
Definition: logger.hh:246
INSTANCE_ALL
#define INSTANCE_ALL(field)
Definition: field_instances.hh:43
Input::Tuple
Accessor to the data with type Type::Tuple.
Definition: accessors.hh:411
field_instances.hh
out_of_limits
@ out_of_limits
Some value(s) is out of limits.
Definition: element_data_cache.hh:38
ElementAccessor::idx
unsigned int idx() const
Return local idx of element in boundary / bulk part of element vector.
Definition: accessors.hh:111
ReaderCache::get_reader
static std::shared_ptr< BaseMeshReader > get_reader(const FilePath &file_path)
Definition: reader_cache.cc:36
TimeGovernor::get_input_time_type
static const Input::Type::Tuple & get_input_time_type(double lower_bound=-std::numeric_limits< double >::max(), double upper_bound=std::numeric_limits< double >::max())
Definition: time_governor.cc:46
FieldElementwise::set_mesh
void set_mesh(const Mesh *mesh, bool boundary_domain) override
Definition: field_elementwise.cc:160
FieldElementwise::value_list
void value_list(const std::vector< Point > &point_list, const ElementAccessor< spacedim > &elm, std::vector< typename Value::return_type > &value_list) override
Definition: field_elementwise.cc:201
FieldElementwise::FieldElementwise
FieldElementwise(unsigned int n_comp=0)
Definition: field_elementwise.cc:67
Mesh::n_elements
virtual unsigned int n_elements(bool boundary=false) const
Returns count of boundary or bulk elements.
Definition: mesh.h:355
DebugOut
#define DebugOut()
Macro defining 'debug' record of log.
Definition: logger.hh:252
Input::Type::Default::optional
static Default optional()
The factory function to make an empty default value which is optional.
Definition: type_record.hh:124
BaseMeshReader::HeaderQuery
Definition: msh_basereader.hh:132
TimeStep::read_coef
double read_coef(Input::Iterator< std::string > unit_it) const
Definition: time_governor.cc:244