Flow123d  release_2.2.0-914-gf1a3a4f
field_fe.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_fe.cc
15  * @brief
16  */
17 
18 
19 #include <limits>
20 
21 #include "fields/field_fe.hh"
22 #include "fields/field_instances.hh" // for instantiation macros
23 #include "input/input_type.hh"
24 #include "fem/fe_p.hh"
25 #include "io/reader_cache.hh"
26 #include "io/msh_gmshreader.h"
27 
28 
29 
30 
31 /// Implementation.
32 
33 namespace it = Input::Type;
34 
35 
36 
37 
39 
40 
41 template <int spacedim, class Value>
42 const Input::Type::Record & FieldFE<spacedim, Value>::get_input_type()
43 {
44  return it::Record("FieldFE", FieldAlgorithmBase<spacedim,Value>::template_name()+" Field given by finite element approximation.")
48  "GMSH mesh with data. Can be different from actual computational mesh.")
50  "Section where to find the field, some sections are specific to file format \n"
51  "point_data/node_data, cell_data/element_data, -/element_node_data, native/-.\n"
52  "If not given by user we try to find the field in all sections, but report error \n"
53  "if it is found in more the one section.")
55  "The values of the Field are read from the ```$ElementData``` section with field name given by this key.")
56  .close();
57 }
58 
59 template <int spacedim, class Value>
61 {
62  return it::Selection("FE_discretization",
63  "Specify the section in mesh input file where field data is listed.\nSome sections are specific to file format.")
64  .add_value(OutputTime::DiscreteSpace::NODE_DATA, "node_data", "point_data (VTK) / node_data (GMSH)")
65  .add_value(OutputTime::DiscreteSpace::ELEM_DATA, "element_data", "cell_data (VTK) / element_data (GMSH)")
66  .add_value(OutputTime::DiscreteSpace::CORNER_DATA, "element_node_data", "element_node_data (only for GMSH)")
67  .add_value(OutputTime::DiscreteSpace::NATIVE_DATA, "native_data", "native_data (only for VTK)")
68  .close();
69 }
70 
71 template <int spacedim, class Value>
73  Input::register_class< FieldFE<spacedim, Value>, unsigned int >("FieldFE") +
75 
76 
77 
78 template <int spacedim, class Value>
79 FieldFE<spacedim, Value>::FieldFE( unsigned int n_comp)
80 : FieldAlgorithmBase<spacedim, Value>(n_comp),
81  data_vec_(nullptr),
82  field_name_("")
83 {}
84 
85 
86 template <int spacedim, class Value>
87 void FieldFE<spacedim, Value>::set_fe_data(std::shared_ptr<DOFHandlerMultiDim> dh,
88  MappingP1<1,3> *map1,
89  MappingP1<2,3> *map2,
90  MappingP1<3,3> *map3,
91  VectorSeqDouble *data)
92 {
93  dh_ = dh;
94  data_vec_ = data;
95 
96  unsigned int ndofs = dh_->max_elem_dofs();
97  dof_indices_.resize(ndofs);
98 
99  // initialization data of value handlers
100  FEValueInitData init_data;
101  init_data.dh = dh_;
102  init_data.data_vec = data_vec_;
103  init_data.ndofs = ndofs;
104  init_data.n_comp = this->n_comp();
105 
106  // initialize value handler objects
107  value_handler1_.initialize(init_data, map1);
108  value_handler2_.initialize(init_data, map2);
109  value_handler3_.initialize(init_data, map3);
110 
111  // set discretization
112  discretization_ = OutputTime::DiscreteSpace::UNDEFINED;
113 }
114 
115 
116 
117 /**
118  * Returns one value in one given point. ResultType can be used to avoid some costly calculation if the result is trivial.
119  */
120 template <int spacedim, class Value>
121 typename Value::return_type const & FieldFE<spacedim, Value>::value(const Point &p, const ElementAccessor<spacedim> &elm)
122 {
123  switch (elm.dim()) {
124  case 1:
125  return value_handler1_.value(p, elm);
126  case 2:
127  return value_handler2_.value(p, elm);
128  case 3:
129  return value_handler3_.value(p, elm);
130  default:
131  ASSERT(false).error("Invalid element dimension!");
132  }
133 
134  return this->r_value_;
135 }
136 
137 
138 
139 /**
140  * Returns std::vector of scalar values in several points at once.
141  */
142 template <int spacedim, class Value>
145 {
146  ASSERT_EQ( point_list.size(), value_list.size() ).error();
147 
148  switch (elm.dim()) {
149  case 1:
150  value_handler1_.value_list(point_list, elm, value_list);
151  break;
152  case 2:
153  value_handler2_.value_list(point_list, elm, value_list);
154  break;
155  case 3:
156  value_handler3_.value_list(point_list, elm, value_list);
157  break;
158  default:
159  ASSERT(false).error("Invalid element dimension!");
160  }
161 }
162 
163 
164 
165 template <int spacedim, class Value>
167  this->init_unit_conversion_coefficient(rec, init_data);
168  flags_ = init_data.flags_;
169 
170 
171  // read data from input record
172  reader_file_ = FilePath( rec.val<FilePath>("mesh_data_file") );
173  field_name_ = rec.val<std::string>("field_name");
174  if (! rec.opt_val<OutputTime::DiscreteSpace>("input_discretization", discretization_) ) {
175  discretization_ = OutputTime::DiscreteSpace::UNDEFINED;
176  }
177 }
178 
179 
180 
181 template <int spacedim, class Value>
182 void FieldFE<spacedim, Value>::set_mesh(const Mesh *mesh, bool boundary_domain) {
183  // Mesh can be set only for field initialized from input.
185  ASSERT(field_name_ != "").error("Uninitialized FieldFE, did you call init_from_input()?\n");
186  this->make_dof_handler(mesh);
187  ReaderCache::get_reader(reader_file_)->check_compatible_mesh( *(dh_->mesh()) );
188  }
189 }
190 
191 
192 
193 template <int spacedim, class Value>
195  // temporary solution - these objects will be set through FieldCommon
196  fe1_ = new FE_P_disc<1,3>(0);
197  fe2_ = new FE_P_disc<2,3>(0);
198  fe3_ = new FE_P_disc<3,3>(0);
199 
200  dh_ = std::make_shared<DOFHandlerMultiDim>( const_cast<Mesh &>(*mesh) );
201  dh_->distribute_dofs(*fe1_, *fe2_, *fe3_);
202  unsigned int ndofs = dh_->max_elem_dofs();
203  dof_indices_.resize(ndofs);
204 
205  // allocate data_vec_
206  unsigned int data_size = dh_->n_global_dofs();
207  data_vec_ = new VectorSeqDouble();
208  data_vec_->resize(data_size);
209 
210  // initialization data of value handlers
211  FEValueInitData init_data;
212  init_data.dh = dh_;
213  init_data.data_vec = data_vec_;
214  init_data.ndofs = ndofs;
215  init_data.n_comp = this->n_comp();
216 
217  // initialize value handler objects
218  value_handler1_.initialize(init_data);
219  value_handler2_.initialize(init_data);
220  value_handler3_.initialize(init_data);
221 }
222 
223 
224 
225 template <int spacedim, class Value>
227  // Time can be set only for field initialized from input.
229  ASSERT(field_name_ != "").error("Uninitialized FieldFE, did you call init_from_input()?\n");
230  ASSERT_PTR(dh_)(field_name_).error("Null target mesh pointer of finite element field, did you call set_mesh()?\n");
231  if ( reader_file_ == FilePath() ) return false;
232 
233  unsigned int n_components = this->value_.n_rows() * this->value_.n_cols();
234  bool boundary_domain = false;
235  BaseMeshReader::HeaderQuery header_query(field_name_, time.end(), this->discretization_, dh_->hash());
236  ReaderCache::get_reader(reader_file_)->find_header(header_query);
237 
238  if (header_query.discretization == OutputTime::DiscreteSpace::NATIVE_DATA) {
239  auto data_vec = ReaderCache::get_reader(reader_file_)->template get_element_data<double>(dh_->mesh()->element.size(),
240  n_components, boundary_domain, this->component_idx_);
241  this->calculate_native_values(data_vec);
242  } else {
243  std::shared_ptr<Mesh> source_mesh = ReaderCache::get_mesh(reader_file_);
244  auto data_vec = ReaderCache::get_reader(reader_file_)->template get_element_data<double>(source_mesh->element.size(),
245  n_components, boundary_domain, this->component_idx_);
246  this->interpolate(data_vec);
247  }
248 
249  return true;
250  } else return false;
251 
252 }
253 
254 
255 template <int spacedim, class Value>
257 {
258  std::shared_ptr<Mesh> source_mesh = ReaderCache::get_mesh(reader_file_);
259  std::vector<double> sum_val(4);
260  std::vector<unsigned int> elem_count(4);
261  std::vector<unsigned int> searched_elements; // stored suspect elements in calculating the intersection
262 
263  FOR_ELEMENTS( dh_->mesh(), ele ) {
264  searched_elements.clear();
265  source_mesh->get_bih_tree().find_point(ele->centre(), searched_elements);
266  std::fill(sum_val.begin(), sum_val.end(), 0.0);
267  std::fill(elem_count.begin(), elem_count.end(), 0);
268  for (std::vector<unsigned int>::iterator it = searched_elements.begin(); it!=searched_elements.end(); it++) {
269  ElementFullIter elm = source_mesh->element( *it );
270  bool contains=false;
271  switch (elm->dim()) {
272  case 1:
273  contains = value_handler1_.contains_point(ele->centre(), *elm);
274  break;
275  case 2:
276  contains = value_handler2_.contains_point(ele->centre(), *elm);
277  break;
278  case 3:
279  contains = value_handler3_.contains_point(ele->centre(), *elm);
280  break;
281  default:
282  ASSERT(false).error("Invalid element dimension!");
283  }
284  if (contains) {
285  // projection point in element
286  sum_val[elm->dim()] += (*data_vec)[*it];
287  ++elem_count[elm->dim()];
288  }
289  }
290  unsigned int dim = ele->dim();
291  double elem_value = 0.0;
292  do {
293  if (elem_count[dim] > 0) {
294  elem_value = sum_val[dim] / elem_count[dim];
295  break;
296  }
297  ++dim;
298  } while (dim<4);
299 
300  dh_->get_dof_indices( ele, dof_indices_);
302  (*data_vec_)[dof_indices_[0]] = elem_value * this->unit_conversion_coefficient_;
303  }
304 }
305 
306 
307 template <int spacedim, class Value>
309 {
310  // Same algorithm as in output of Node_data. Possibly code reuse.
311  unsigned int dof_size, data_vec_i;
312  std::vector<unsigned int> count_vector(data_vec_->size(), 0);
313  data_vec_->fill(0.0);
315 
316  // iterate through elements, assembly global vector and count number of writes
317  FOR_ELEMENTS( dh_->mesh(), ele ) {
318  dof_size = dh_->get_dof_indices( ele, dof_indices_ );
319  data_vec_i = ele.index() * dof_indices_.size();
320  for (unsigned int i=0; i<dof_size; ++i, ++data_vec_i) {
321  (*data_vector)[ dof_indices_[i] ] += (*data_cache)[data_vec_i];
322  ++count_vector[ dof_indices_[i] ];
323  }
324  }
325 
326  // compute averages of values
327  for (unsigned int i=0; i<data_vec_->size(); ++i) {
328  if (count_vector[i]>0) (*data_vector)[i] /= count_vector[i];
329  }
330 }
331 
332 
333 template <int spacedim, class Value>
335  ASSERT_EQ(output_data_cache.n_values() * output_data_cache.n_elem(), dh_->n_global_dofs()).error();
336  ASSERT_EQ(output_data_cache.n_elem(), dof_indices_.size()).error();
337  double loc_values[output_data_cache.n_elem()];
338  unsigned int i, dof_filled_size;
339 
341  FOR_ELEMENTS( dh_->mesh(), ele ) {
342  dof_filled_size = dh_->get_dof_indices( ele, dof_indices_);
343  for (i=0; i<dof_filled_size; ++i) loc_values[i] = (*data_vec)[ dof_indices_[0] ];
344  for ( ; i<output_data_cache.n_elem(); ++i) loc_values[i] = numeric_limits<double>::signaling_NaN();
345  output_data_cache.store_value( ele.index(), loc_values );
346  }
347 
348  output_data_cache.set_dof_handler_hash( dh_->hash() );
349 }
350 
351 
352 
353 template <int spacedim, class Value>
355 {}
356 
357 
358 // Instantiations of FieldFE
virtual ~FieldFE()
Destructor.
Definition: field_fe.cc:354
void init_unit_conversion_coefficient(const Input::Record &rec, const struct FieldAlgoBaseInitData &init_data)
Init value of unit_conversion_coefficient_ from input.
virtual void value_list(const std::vector< Point > &point_list, const ElementAccessor< spacedim > &elm, std::vector< typename Value::return_type > &value_list)
Definition: field_fe.cc:143
void set_dof_handler_hash(std::size_t hash)
std::shared_ptr< std::vector< T > > ComponentDataPtr
std::vector< IdxInt > dof_indices_
Array of indexes to data_vec_, used for get/set values.
Definition: field_fe.hh:139
void interpolate(ElementDataCache< double >::ComponentDataPtr data_vec)
Interpolate data over all elements of target mesh.
Definition: field_fe.cc:256
VectorSeqDouble * data_vec_
Store data of Field.
Definition: field_fe.hh:137
unsigned int component_idx_
Specify if the field is part of a MultiField and which component it is.
void initialize(FEValueInitData init_data, MappingP1< elemdim, 3 > *map=nullptr)
Initialize data members.
void fill(double value)
Fill all values of data vector with given value.
#define FOR_ELEMENTS(_mesh_, __i)
Definition: mesh.h:480
std::string field_name_
field name read from input
Definition: field_fe.hh:163
void fill_data_to_cache(ElementDataCache< double > &output_data_cache)
Definition: field_fe.cc:334
Abstract linear system class.
Definition: equation.hh:37
FieldFlag::Flags flags_
FEValueHandler< 2, spacedim, Value > value_handler2_
Value handler that allows get value of 2D elements.
Definition: field_fe.hh:144
void store_value(unsigned int idx, const T *value)
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
Definition: field_fe.hh:160
std::shared_ptr< std::vector< double > > VectorSeq
#define INSTANCE_ALL(field)
Definition: mesh.h:99
Helper struct stores data for initizalize descentants of FieldAlgorithmBase.
void set_mesh(const Mesh *mesh, bool boundary_domain) override
Definition: field_fe.cc:182
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:346
FEValueHandler< 3, spacedim, Value > value_handler3_
Value handler that allows get value of 3D elements.
Definition: field_fe.hh:146
bool set_time(const TimeStep &time) override
Definition: field_fe.cc:226
Value::return_type const & value(const Point &p, const ElementAccessor< spacedim > &elm)
Returns one value in one given point.
Value::return_type r_value_
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:303
unsigned int size()
Getter for shared pointer of output data.
unsigned int data_size() const
Definition: field_fe.hh:116
constexpr bool match(Mask mask) const
Definition: flag_array.hh:163
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:195
static Default optional()
The factory function to make an empty default value which is optional.
Definition: type_record.hh:124
bool opt_val(const string &key, Ret &value) const
OutputTime::DiscreteSpace discretization_
Specify section where to find the field data in input mesh file.
Definition: field_fe.hh:166
std::shared_ptr< DOFHandlerMultiDim > dh_
DOF handler object.
Definition: field_fe.hh:135
FiniteElement< 2, 3 > * fe2_
Same as previous, but represents 2D element.
Definition: field_fe.hh:155
void value_list(const std::vector< Point > &point_list, const ElementAccessor< spacedim > &elm, std::vector< typename Value::return_type > &value_list)
Returns std::vector of scalar values in several points at once.
VectorSeqDouble * data_vec
Store data of Field.
Definitions of basic Lagrangean finite elements with polynomial shape functions.
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
void resize(unsigned int size)
Create shared pointer and PETSC vector with given size.
Selection & add_value(const int value, const std::string &key, const std::string &description="", TypeBase::attribute_map attributes=TypeBase::attribute_map())
Adds one new value with name given by key to the Selection.
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:490
virtual Value::return_type const & value(const Point &p, const ElementAccessor< spacedim > &elm)
Definition: field_fe.cc:121
double end() const
unsigned int ndofs
number of dofs
Space< spacedim >::Point Point
std::shared_ptr< DOFHandlerMultiDim > dh
DOF handler object.
void set_fe_data(std::shared_ptr< DOFHandlerMultiDim > dh, MappingP1< 1, 3 > *map1, MappingP1< 2, 3 > *map2, MappingP1< 3, 3 > *map3, VectorSeqDouble *data)
Definition: field_fe.cc:87
FEValueHandler< 1, spacedim, Value > value_handler1_
Value handler that allows get value of 1D elements.
Definition: field_fe.hh:142
Record & copy_keys(const Record &other)
Copy keys from other record.
Definition: type_record.cc:215
Dedicated class for storing path to input and output files.
Definition: file_path.hh:54
static const Input::Type::Selection & get_disc_selection_input_type()
Definition: field_fe.cc:60
Value value_
Last value, prevents passing large values (vectors) by value.
#define ASSERT_PTR(ptr)
Definition of assert macro checking non-null pointer (PTR)
Definition: asserts.hh:335
const Selection & close() const
Close the Selection, no more values can be added.
FieldFE(unsigned int n_comp=0)
Definition: field_fe.cc:79
bool contains_point(arma::vec point, Element &elm)
Test if element contains given point.
virtual void init_from_input(const Input::Record &rec, const struct FieldAlgoBaseInitData &init_data)
Definition: field_fe.cc:166
static std::shared_ptr< Mesh > get_mesh(const FilePath &file_path)
Definition: reader_cache.cc:38
VectorSeq get_data_ptr()
Getter for shared pointer of output data.
Record type proxy class.
Definition: type_record.hh:182
static constexpr Mask equation_input
The field is data parameter of the owning equation. (default on)
Definition: field_flag.hh:33
unsigned int dim() const
Definition: accessors.hh:83
static std::shared_ptr< BaseMeshReader > get_reader(const FilePath &file_path)
Definition: reader_cache.cc:34
FiniteElement< 1, 3 > * fe1_
Definition: field_fe.hh:153
unsigned int n_comp
number of components
void calculate_native_values(ElementDataCache< double >::ComponentDataPtr data_cache)
Calculate native data over all elements of target mesh.
Definition: field_fe.cc:308
FieldFlag::Flags flags_
Field flags.
Definition: field_fe.hh:169
Initialization structure of FEValueHandler class.
FiniteElement< 3, 3 > * fe3_
Same as previous, but represents 3D element.
Definition: field_fe.hh:157
Class for declaration of the input data that are in string format.
Definition: type_base.hh:588
Representation of one time step..
Template for classes storing finite set of named values.
void make_dof_handler(const Mesh *mesh)
Create DofHandler object.
Definition: field_fe.cc:194
#define FLOW123D_FORCE_LINK_IN_CHILD(x)
Definition: global_defs.h:180
#define ASSERT_EQ(a, b)
Definition of comparative assert macro (EQual)
Definition: asserts.hh:327
static constexpr Mask declare_input
The field can be set from input. The key in input field descriptor is declared. (default on) ...
Definition: field_flag.hh:35
Definition: field.hh:37
unsigned int n_comp() const
#define ASSERT_LT_DBG(a, b)
Definition of comparative assert macro (Less Than) only for debug mode.
Definition: asserts.hh:299