Flow123d  release_3.0.0-1165-gffc6a5f
field_interpolated_p0.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_interpolated_p0.cc
15  * @brief
16  */
17 
18 
19 #include "field_interpolated_p0.hh"
20 #include "fields/field_instances.hh" // for instantiation macros
21 #include "system/system.hh"
22 #include "io/msh_gmshreader.h"
23 #include "mesh/bih_tree.hh"
24 #include "mesh/accessors.hh"
25 #include "io/reader_cache.hh"
26 #include "system/sys_profiler.hh"
27 
28 #include "fem/mapping_p1.hh"
29 
33 
34 namespace it = Input::Type;
35 
36 FLOW123D_FORCE_LINK_IN_CHILD(field_interpolated)
37 
38 
39 
40 template <int spacedim, class Value>
41 const Input::Type::Record & FieldInterpolatedP0<spacedim, Value>::get_input_type()
42 {
43  return it::Record("FieldInterpolatedP0", FieldAlgorithmBase<spacedim,Value>::template_name()+" Field interpolated from external mesh data and piecewise constant on mesh elements.")
47  "Input file with ASCII GMSH file format.")
49  "The values of the Field are read from the ```$ElementData``` section with field name given by this key.")
50  //.declare_key("unit", FieldAlgorithmBase<spacedim, Value>::get_input_type_unit_si(), it::Default::optional(),
51  // "Definition of unit.")
52  .declare_key("default_value", IT::Double(), IT::Default::optional(),
53  "Allow set default value of elements that have not listed values in mesh data file.")
54  .declare_key("time_unit", IT::String(), IT::Default::read_time("Common unit of TimeGovernor."),
55  "Definition of unit of all times defined in mesh data file.")
56  .declare_key("read_time_shift", TimeGovernor::get_input_time_type(), IT::Default("0.0"),
57  "Allow set time shift of field data read from the mesh data file. For time 't', field descriptor with time 'T', "
58  "time shift 'S' and if 't > T', we read time frame 't + S'.")
59  .close();
60 }
61 
62 
63 
64 template <int spacedim, class Value>
66  Input::register_class< FieldInterpolatedP0<spacedim, Value>, unsigned int >("FieldInterpolatedP0") +
68 
69 
70 template <int spacedim, class Value>
72 : FieldAlgorithmBase<spacedim, Value>(n_comp)
73 {
74  this->is_constant_in_space_ = false;
75 }
76 
77 
78 
79 template <int spacedim, class Value>
81  this->init_unit_conversion_coefficient(rec, init_data);
82  this->in_rec_ = rec;
83 
84 
85  // read mesh, create tree
86  {
87  reader_file_ = FilePath( rec.val<FilePath>("mesh_data_file") );
89  //source_mesh_->setup_topology();
91  }
92  bih_tree_ = new BIHTree();
93  bih_tree_->add_boxes( source_mesh_->get_element_boxes() );
95 
96  // allocate data_
97  unsigned int data_size = source_mesh_->n_elements() * (this->value_.n_rows() * this->value_.n_cols());
98  data_ = std::make_shared<std::vector<typename Value::element_type>>();
99  data_->resize(data_size);
100 
101  field_name_ = rec.val<std::string>("field_name");
102  if (!rec.opt_val("default_value", default_value_) ) {
103  default_value_ = numeric_limits<double>::signaling_NaN();
104  }
105 }
106 
107 
108 
109 
110 template <int spacedim, class Value>
112  OLD_ASSERT(source_mesh_, "Null mesh pointer of elementwise field: %s, did you call init_from_input(Input::Record)?\n", field_name_.c_str());
113  if ( reader_file_ == FilePath() ) return false;
114 
115  //walkaround for the steady time governor - there is no data to be read in time==infinity
116  //TODO: is it possible to check this before calling set_time?
117  //if (time == numeric_limits< double >::infinity()) return false;
118 
119  // value of last computed element must be recalculated if time is changed
120  computed_elm_idx_ = numeric_limits<unsigned int>::max();
121 
122  bool boundary_domain_ = false;
123  double time_unit_coef = time.read_coef(in_rec_.find<string>("time_unit"));
124  double time_shift = time.read_time( in_rec_.find<Input::Tuple>("read_time_shift") );
125  double read_time = (time.end()+time_shift) / time_unit_coef;
126  BaseMeshReader::HeaderQuery header_query(field_name_, read_time, OutputTime::DiscreteSpace::ELEM_DATA);
127  ReaderCache::get_reader(reader_file_ )->find_header(header_query);
128  data_ = ReaderCache::get_reader(reader_file_ )->template get_element_data<typename Value::element_type>(
129  source_mesh_->n_elements(), this->value_.n_rows() * this->value_.n_cols(), boundary_domain_, this->component_idx_);
130  CheckResult checked_data = ReaderCache::get_reader(reader_file_)->scale_and_check_limits(field_name_,
132 
133  if (checked_data == CheckResult::not_a_number) {
134  THROW( ExcUndefElementValue() << EI_Field(field_name_) );
135  }
136 
137  return true;
138 }
139 
140 
141 
142 template <int spacedim, class Value>
143 typename Value::return_type const &FieldInterpolatedP0<spacedim, Value>::value(const Point &p, const ElementAccessor<spacedim> &elm)
144 {
145  OLD_ASSERT( elm.is_elemental(), "FieldInterpolatedP0 works only for 'elemental' ElementAccessors.\n");
146  if (elm.idx() != computed_elm_idx_ || elm.is_boundary() != computed_elm_boundary_) {
147  computed_elm_idx_ = elm.idx();
149 
150  if (elm.dim() == 3) {
151  xprintf(Err, "Dimension of element in target mesh must be 0, 1 or 2! elm.idx() = %d\n", elm.idx());
152  }
153 
154  double epsilon = 4* numeric_limits<double>::epsilon() * elm.measure();
155 
156  // gets suspect elements
157  if (elm.dim() == 0) {
158  searched_elements_.clear();
159  ((BIHTree *)bih_tree_)->find_point(elm.node(0)->point(), searched_elements_);
160  } else {
161  BoundingBox bb = elm.bounding_box();
162  searched_elements_.clear();
163  ((BIHTree *)bih_tree_)->find_bounding_box(bb, searched_elements_);
164  }
165 
166  // set zero values of value_ object
167  for (unsigned int i=0; i < this->value_.n_rows(); i++) {
168  for (unsigned int j=0; j < this->value_.n_cols(); j++) {
169  this->value_(i,j) = 0.0;
170  }
171  }
172 
173  double total_measure=0.0, measure;
174 
175  START_TIMER("compute_pressure");
177 
178 
179  MappingP1<3,3> mapping;
180 
182  {
183  ElementAccessor<3> ele = source_mesh_->element_accessor(*it);
184  if (ele->dim() == 3) {
185  // get intersection (set measure = 0 if intersection doesn't exist)
186  switch (elm.dim()) {
187  case 0: {
188  arma::vec::fixed<3> real_point = elm.node(0)->point();
189  arma::mat::fixed<3, 4> elm_map = mapping.element_map(ele);
190  arma::vec::fixed<4> unit_point = mapping.project_real_to_unit(real_point, elm_map);
191 
192  measure = (std::fabs(arma::sum( unit_point )-1) <= 1e-14
193  && arma::min( unit_point ) >= 0)
194  ? 1.0 : 0.0;
195  break;
196  }
197  case 1: {
199  ComputeIntersection<1,3> CI(elm, ele, source_mesh_.get());
200  CI.init();
201  CI.compute(is);
202 
203  IntersectionLocal<1,3> ilc(is);
204  measure = ilc.compute_measure() * elm.measure();
205  break;
206  }
207  case 2: {
209  ComputeIntersection<2,3> CI(elm, ele, source_mesh_.get());
210  CI.init();
211  CI.compute(is);
212 
213  IntersectionLocal<2,3> ilc(is);
214  measure = 2 * ilc.compute_measure() * elm.measure();
215  break;
216  }
217  }
218 
219  //adds values to value_ object if intersection exists
220  if (measure > epsilon) {
221  unsigned int index = this->value_.n_rows() * this->value_.n_cols() * (*it);
223  typename Value::return_type & ret_type_value = const_cast<typename Value::return_type &>( Value::from_raw(this->r_value_, (typename Value::element_type *)(&vec[index])) );
224  Value tmp_value = Value( ret_type_value );
225 
226  for (unsigned int i=0; i < this->value_.n_rows(); i++) {
227  for (unsigned int j=0; j < this->value_.n_cols(); j++) {
228  this->value_(i,j) += tmp_value(i,j) * measure;
229  }
230  }
231  total_measure += measure;
232  }
233  }
234  }
235 
236  // computes weighted average
237  if (total_measure > epsilon) {
238  for (unsigned int i=0; i < this->value_.n_rows(); i++) {
239  for (unsigned int j=0; j < this->value_.n_cols(); j++) {
240  this->value_(i,j) /= total_measure;
241  }
242  }
243  } else {
244  WarningOut().fmt("Processed element with idx {} is out of source mesh!\n", elm.idx());
245  }
246  END_TIMER("compute_pressure");
247 
248  }
249  return this->r_value_;
250 }
251 
252 
253 
254 template <int spacedim, class Value>
257 {
258  OLD_ASSERT( elm.is_elemental(), "FieldInterpolatedP0 works only for 'elemental' ElementAccessors.\n");
259  FieldAlgorithmBase<spacedim, Value>::value_list(point_list, elm, value_list);
260 }
261 
262 
263 
264 // Instantiations of FieldInterpolatedP0
unsigned int computed_elm_boundary_
stored flag if last computed element is boundary
double default_value_
Default value of element if not set in mesh data file.
Class MappingP1 implements the affine transformation of the unit cell onto the actual cell...
void init_unit_conversion_coefficient(const Input::Record &rec, const struct FieldAlgoBaseInitData &init_data)
Init value of unit_conversion_coefficient_ from input.
Bounding box in 3d ambient space.
Definition: bounding_box.hh:54
double read_coef(Input::Iterator< std::string > unit_it) const
Classes with algorithms for computation of intersections of meshes.
Some value(s) is set to NaN.
bool set_time(const TimeStep &time) override
unsigned int component_idx_
Specify if the field is part of a MultiField and which component it is.
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:61
double compute_measure() const override
Computes the relative measure of intersection object.
bool is_boundary() const
We need this method after replacing Region by RegionIdx, and movinf RegionDB instance into particular...
Definition: accessors.hh:106
Abstract linear system class.
Definition: balance.hh:37
virtual void value_list(const std::vector< Point > &point_list, const ElementAccessor< spacedim > &elm, std::vector< typename Value::return_type > &value_list)=0
Fundamental simplicial intersections.
static Default obligatory()
The factory function to make an empty default value which is obligatory.
Definition: type_record.hh:110
FilePath reader_file_
mesh reader file
virtual void init_from_input(const Input::Record &rec, const struct FieldAlgoBaseInitData &init_data)
virtual Value::return_type const & value(const Point &p, const ElementAccessor< spacedim > &elm)
#define INSTANCE_ALL(field)
void init()
Initializes lower dimensional objects. Sets correctly the pointers to Plucker coordinates and product...
Iterator< Ret > find(const string &key) const
Helper struct stores data for initizalize descentants of FieldAlgorithmBase.
Mat< double, N, 1 > vec
Definition: armor.hh:211
unsigned int computed_elm_idx_
stored index to last computed element
#define ADD_CALLS(n_calls)
Increase number of calls in actual timer.
Value::return_type r_value_
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:304
void init()
Initializes lower dimensional objects. Sets correctly the pointers to Plucker coordinates and product...
double unit_conversion_coefficient_
Coeficient of conversion of user-defined unit.
virtual Record & derive_from(Abstract &parent)
Method to derive new Record from an AbstractRecord parent.
Definition: type_record.cc:196
unsigned int dim() const
Definition: elements.h:124
static Default optional()
The factory function to make an empty default value which is optional.
Definition: type_record.hh:124
#define OLD_ASSERT(...)
Definition: global_defs.h:131
bool opt_val(const string &key, Ret &value) const
virtual void value_list(const std::vector< Point > &point_list, const ElementAccessor< spacedim > &elm, std::vector< typename Value::return_type > &value_list)
bool is_elemental() const
Definition: accessors.hh:79
Class for declaration of the input data that are floating point numbers.
Definition: type_base.hh:541
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())
static FileName input()
The factory function for declaring type FileName for input files.
Definition: type_base.cc:526
Accessor to the data with type Type::Record.
Definition: accessors.hh:292
const Ret val(const string &key) const
#define xprintf(...)
Definition: system.hh:92
FieldInterpolatedP0(unsigned int n_comp=0)
#define START_TIMER(tag)
Starts a timer with specified tag.
Input::Record in_rec_
Accessor to Input::Record.
Class for O(log N) lookup for intersections with a set of bounding boxes.
Definition: bih_tree.hh:38
std::shared_ptr< Mesh > source_mesh_
mesh, which is interpolated
BoundingBox bounding_box() const
Definition: accessors.hh:157
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:503
static bool check_compatible_mesh(const FilePath &file_path, Mesh &mesh)
Definition: reader_cache.cc:73
double measure() const
Computes the measure of the element.
Definition: accessors.hh:254
double end() const
Space< spacedim >::Point Point
CheckResult
Return type of method that checked data stored in ElementDataCache (NaN values, limits) ...
BIHTree * bih_tree_
tree of mesh elements
double read_time(Input::Iterator< Input::Tuple > time_it, double default_time=std::numeric_limits< double >::quiet_NaN()) const
Record & copy_keys(const Record &other)
Copy keys from other record.
Definition: type_record.cc:216
Dedicated class for storing path to input and output files.
Definition: file_path.hh:54
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
bool is_constant_in_space_
Flag detects that field is only dependent on time.
Value value_
Last value, prevents passing large values (vectors) by value.
std::vector< unsigned int > searched_elements_
vector stored suspect elements in calculating the intersection
Class for 2D-2D intersections.
#define WarningOut()
Macro defining &#39;warning&#39; record of log.
Definition: logger.hh:246
#define END_TIMER(tag)
Ends a timer with specified tag.
Definition: system.hh:64
static std::shared_ptr< Mesh > get_mesh(const FilePath &file_path)
Definition: reader_cache.cc:40
Record type proxy class.
Definition: type_record.hh:182
Accessor to the data with type Type::Tuple.
Definition: accessors.hh:412
unsigned int dim() const
Definition: accessors.hh:87
Internal auxiliary class representing intersection object of simplex<dimA> and simplex<dimB>.
static std::shared_ptr< BaseMeshReader > get_reader(const FilePath &file_path)
Definition: reader_cache.cc:36
std::string field_name_
field name read from input
void construct()
Definition: bih_tree.cc:55
arma::vec3 & point()
Definition: nodes.hh:67
unsigned int idx() const
Return local idx of element in boundary / bulk part of element vector.
Definition: accessors.hh:111
std::shared_ptr< std::vector< typename Value::element_type > > data_
Raw buffer of n_entities rows each containing Value::size() doubles.
Class for declaration of the input data that are in string format.
Definition: type_base.hh:589
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
Representation of one time step..
void add_boxes(const std::vector< BoundingBox > &boxes)
Definition: bih_tree.cc:43
#define FLOW123D_FORCE_LINK_IN_CHILD(x)
Definition: global_defs.h:180
Internal class representing intersection object.
const Node * node(unsigned int ni) const
Definition: accessors.hh:145