Flow123d  DF_patch_fe_mechanics-5faa023
patch_fe_values.hh
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 patch_fe_values.hh
15  * @brief Class FEValues calculates finite element data on the actual
16  * cells such as shape function values, gradients, Jacobian of
17  * the mapping from the reference cell etc.
18  * @author Jan Stebel, David Flanderka
19  */
20 
21 #ifndef PATCH_FE_VALUES_HH_
22 #define PATCH_FE_VALUES_HH_
23 
24 
25 #include <string.h> // for memcpy
26 #include <algorithm> // for swap
27 #include <new> // for operator new[]
28 #include <string> // for operator<<
29 #include <vector> // for vector
30 #include "fem/fe_system.hh" // for FESystem
31 #include "fem/eigen_tools.hh"
33 #include "fem/patch_op.hh"
34 #include "fem/op_accessors.hh"
35 #include "mesh/ref_element.hh" // for RefElement
36 #include "mesh/accessors.hh"
38 #include "fem/arena_resource.hh"
39 #include "fem/arena_vec.hh"
40 
41 template<unsigned int dim> class BulkValues;
42 template<unsigned int dim> class SideValues;
43 template<unsigned int dim> class JoinValues;
44 
45 
46 
47 template<unsigned int spacedim = 3>
49 public:
51 
52  /// Struct for pre-computing number of elements, sides, bulk points and side points on each dimension.
53  struct TableSizes {
54  public:
55  /// Constructor
59  }
60 
61  /// Set all values to zero
62  void reset() {
63  std::fill(elem_sizes_[0].begin(), elem_sizes_[0].end(), 0);
64  std::fill(elem_sizes_[1].begin(), elem_sizes_[1].end(), 0);
65  std::fill(point_sizes_[0].begin(), point_sizes_[0].end(), 0);
66  std::fill(point_sizes_[1].begin(), point_sizes_[1].end(), 0);
67  }
68 
69  /// Copy values of other TableSizes instance
70  void copy(const TableSizes &other) {
71  elem_sizes_[0] = other.elem_sizes_[0];
72  elem_sizes_[1] = other.elem_sizes_[1];
73  point_sizes_[0] = other.point_sizes_[0];
74  point_sizes_[1] = other.point_sizes_[1];
75  }
76 
77  /**
78  * Holds number of elements and sides on each dimension
79  * Format:
80  * { {n_elements_1D, n_elements_2D, n_elements_3D },
81  * {n_sides_1D, n_sides_2D, n_sides_3D } }
82  */
84 
85  /**
86  * Holds number of bulk and side points on each dimension
87  * Format:
88  * { {n_bulk_points_1D, n_bulk_points_2D, n_bulk_points_3D },
89  * {n_side_points_1D, n_side_points_2D, n_side_points_3D } }
90  */
92  };
93 
95  : patch_fe_data_(1024 * 1024, 256),
97  {
98  for (uint dim=1; dim<4; ++dim) {
99  patch_point_vals_[0].push_back( PatchPointValues(dim, 0, true, patch_fe_data_) );
100  patch_point_vals_[1].push_back( PatchPointValues(dim, 0, false, patch_fe_data_) );
101  }
102  used_quads_[0] = false; used_quads_[1] = false;
103  }
104 
105  PatchFEValues(unsigned int quad_order, MixedPtr<FiniteElement> fe)
106  : patch_fe_data_(1024 * 1024, 256),
108  fe_(fe)
109  {
110  for (uint dim=1; dim<4; ++dim) {
111  patch_point_vals_[0].push_back( PatchPointValues(dim, quad_order, true, patch_fe_data_) );
112  patch_point_vals_[1].push_back( PatchPointValues(dim, quad_order, false, patch_fe_data_) );
113  }
114  used_quads_[0] = false; used_quads_[1] = false;
115 
116  // TODO move initialization zero_vec_ to patch_fe_data_ constructor when we will create separate ArenaVec of DOshape functions
117  uint zero_vec_size = 300;
118  patch_fe_data_.zero_vec_ = ArenaVec<double>(zero_vec_size, patch_fe_data_.asm_arena_);
119  for (uint i=0; i<zero_vec_size; ++i) patch_fe_data_.zero_vec_(i) = 0.0;
120  }
121 
122 
123  /// Destructor
125  {}
126 
127  /**
128  * @brief Initialize structures and calculates cell-independent data.
129  *
130  * @param _quadrature The quadrature rule for the cell associated
131  * to given finite element or for the cell side.
132  * @param _flags The update flags.
133  */
134  template<unsigned int DIM>
135  void initialize(Quadrature &_quadrature)
136  {
137  if ( _quadrature.dim() == DIM ) {
138  used_quads_[0] = true;
139  patch_point_vals_[0][DIM-1].initialize(); // bulk
140  } else {
141  used_quads_[1] = true;
142  patch_point_vals_[1][DIM-1].initialize(); // side
143  }
144  }
145 
146  /// Finalize initialization, creates child (patch) arena and passes it to PatchPointValue objects
147  void init_finalize() {
148  patch_fe_data_.patch_arena_ = patch_fe_data_.asm_arena_.get_child_arena();
149  }
150 
151  /// Reset PatchpointValues structures
152  void reset()
153  {
154  for (unsigned int i=0; i<spacedim; ++i) {
155  if (used_quads_[0]) patch_point_vals_[0][i].reset();
156  if (used_quads_[1]) patch_point_vals_[1][i].reset();
157  }
158  patch_fe_data_.patch_arena_->reset();
159  }
160 
161  /// Reinit data.
163  {
164  for (auto * op : operations_) {
165  op->eval();
166  }
167  }
168 
169  /**
170  * @brief Returns the number of shape functions.
171  */
172  template<unsigned int dim>
173  inline unsigned int n_dofs() const {
174  ASSERT((dim>=0) && (dim<=3))(dim).error("Dimension must be 0, 1, 2 or 3.");
175  return fe_[Dim<dim>{}]->n_dofs();
176  }
177 
178  /// Getter for bulk quadrature of given dimension
180  ASSERT((dim>0) && (dim<=3))(dim).error("Dimension must be 1, 2 or 3.");
181  return patch_point_vals_[0][dim-1].get_quadrature();
182  }
183 
184  /// Getter for side quadrature of given dimension
186  ASSERT((dim>0) && (dim<=3))(dim).error("Dimension must be 1, 2 or 3.");
187  return patch_point_vals_[1][dim-1].get_quadrature();
188  }
189 
190  /**
191  * @brief Returnd FiniteElement of \p component_idx for FESystem or \p fe for other types
192  */
193  template<unsigned int dim>
194  std::shared_ptr<FiniteElement<dim>> fe_comp(std::shared_ptr< FiniteElement<dim> > fe, uint component_idx) {
195  if (fe->fe_type() == FEMixedSystem) {
196  FESystem<dim> *fe_sys = dynamic_cast<FESystem<dim>*>( fe.get() );
197  return fe_sys->fe()[component_idx];
198  } else {
199  ASSERT_EQ(component_idx, 0).warning("Non-zero component_idx can only be used for FESystem.");
200  return fe;
201  }
202  }
203 
204 
205  /// Return BulkValue object of dimension given by template parameter
206  template<unsigned int dim>
208 
209  /// Return SideValue object of dimension given by template parameter
210  template<unsigned int dim>
212 
213  /// Return JoinValue object of dimension given by template parameter
214  template<unsigned int dim>
216 
217  /** Following methods are used during update of patch. **/
218 
219  /// Resize tables of patch_point_vals_
220  void resize_tables(TableSizes table_sizes) {
221  for (uint i=0; i<spacedim; ++i) {
222  if (used_quads_[0]) patch_point_vals_[0][i].resize_tables(table_sizes.elem_sizes_[0][i], table_sizes.point_sizes_[0][i]);
223  if (used_quads_[1]) patch_point_vals_[1][i].resize_tables(table_sizes.elem_sizes_[1][i], table_sizes.point_sizes_[1][i]);
224  }
225  }
226 
227  /// Register element to patch_point_vals_ table by dimension of element
228  uint register_element(DHCellAccessor cell, uint element_patch_idx) {
230  if (ppv.elements_map_[element_patch_idx] != (uint)-1) {
231  // Return index of element on patch if it is registered repeatedly
232  return ppv.elements_map_[element_patch_idx];
233  }
234 
235  ppv.elements_map_[element_patch_idx] = ppv.i_elem_;
236  ppv.elem_list_.push_back( cell.elm() );
237  return ppv.i_elem_++;
238  }
239 
240  /// Register side to patch_point_vals_ table by dimension of side
242  uint dim = cell_side.dim();
244 
245  ppv.int_table_(3)(ppv.i_elem_) = cell_side.side_idx();
246  ppv.elem_list_.push_back( cell_side.cell().elm() );
247  ppv.side_list_.push_back( cell_side.side() );
248 
249  return ppv.i_elem_++;
250  }
251 
252  /// Register bulk point to patch_point_vals_ table by dimension of element
253  uint register_bulk_point(DHCellAccessor cell, uint elem_table_row, uint value_patch_idx, uint i_point_on_elem) {
254  return patch_point_vals_[0][cell.dim()-1].register_bulk_point(elem_table_row, value_patch_idx, cell.elm_idx(), i_point_on_elem);
255  }
256 
257  /// Register side point to patch_point_vals_ table by dimension of side
258  uint register_side_point(DHCellSide cell_side, uint elem_table_row, uint value_patch_idx, uint i_point_on_side) {
259  return patch_point_vals_[1][cell_side.dim()-1].register_side_point(elem_table_row, value_patch_idx, cell_side.elem_idx(),
260  cell_side.side_idx(), i_point_on_side);
261  }
262 
263  /// return reference to assembly arena
265  return patch_fe_data_.asm_arena_;
266  }
267 
268  /// same as previous but return constant reference
269  inline const AssemblyArena &asm_arena() const {
270  return patch_fe_data_.asm_arena_;
271  }
272 
273  /// return reference to patch arena
274  inline PatchArena &patch_arena() const {
275  return *patch_fe_data_.patch_arena_;
276  }
277 
278  /// Returns operation of given dim and OpType, creates it if doesn't exist
279  template<class OpType, unsigned int dim>
281  std::string op_name = typeid(OpType).name();
282  auto it = op_dependency_.find(op_name);
283  if (it == op_dependency_.end()) {
284  PatchOp<spacedim>* new_op = new OpType(*this);
285  op_dependency_.insert(std::make_pair(op_name, new_op));
286  operations_.push_back(new_op);
287  DebugOut().fmt("Create new operation '{}', dim: {}.\n", op_name, dim);
288  return new_op;
289  } else {
290  return it->second;
291  }
292  }
293 
294  /// Returns operation of given dim and OpType, creates it if doesn't exist
295  template<class OpType, unsigned int dim>
296  PatchOp<spacedim>* get(std::shared_ptr<FiniteElement<dim>> fe) {
297  std::string op_name = typeid(OpType).name();
298  auto it = op_dependency_.find(op_name);
299  if (it == op_dependency_.end()) {
300  PatchOp<spacedim>* new_op = new OpType(*this, fe);
301  op_dependency_.insert(std::make_pair(op_name, new_op));
302  operations_.push_back(new_op);
303  DebugOut().fmt("Create new operation '{}', dim: {}.\n", op_name, dim);
304  return new_op;
305  } else {
306  return it->second;
307  }
308  }
309 
310  /// Print table of all used operations - development method
311  void print_operations(ostream& stream) const {
312  stream << endl << "Table of patch FE operations:" << endl;
313  stream << std::setfill('-') << setw(160) << "" << endl;
314 
315  stream << std::setfill(' ') << " Operation" << std::setw(51) << "" << "Type" << std::setw(5) << "" << "Shape" << std::setw(2) << ""
316  << "n DOFs" << std::setw(2) << "" << "Input operations" << std::endl;
317  for (uint i=0; i<operations_.size(); ++i) {
318  stream << " " << std::left << std::setw(60) << typeid(*operations_[i]).name() << "";
319  stream << operations_[i]->dim_ << "D " << (operations_[i]->domain_ ? "side" : "bulk");
320  stream << " " << std::setw(6) << operations_[i]->format_shape() << "" << " "
321  << std::setw(7) << operations_[i]->n_dofs() << "" << " ";
322  for (auto *i_o : operations_[i]->input_ops_) stream << typeid(*i_o).name() << " ";
323  stream << std::endl;
324  }
325 
326  stream << std::setfill('=') << setw(160) << "" << endl;
327  }
328 
329 private:
331  /// Sub objects of bulk and side data of dimensions 1,2,3
333 
334  MixedPtr<FiniteElement> fe_; ///< Mixed of shared pointers of FiniteElement object
335  bool used_quads_[2]; ///< Pair of flags signs holds info if bulk and side quadratures are used
336 
338  std::unordered_map<std::string, PatchOp<spacedim> *> op_dependency_;
339 
340  friend class PatchOp<spacedim>;
341 };
342 
343 
344 
345 #endif /* PATCH_FE_VALUES_HH_ */
#define ASSERT(expr)
Definition: asserts.hh:351
#define ASSERT_EQ(a, b)
Definition of comparative assert macro (EQual) only for debug mode.
Definition: asserts.hh:333
Cell accessor allow iterate over DOF handler cells.
unsigned int dim() const
Return dimension of element appropriate to cell.
unsigned int elm_idx() const
Return serial idx to element of loc_ele_idx_.
ElementAccessor< 3 > elm() const
Return ElementAccessor to element of loc_ele_idx_.
Side accessor allows to iterate over sides of DOF handler cell.
unsigned int elem_idx() const
Side side() const
Return Side of given cell and side_idx.
const DHCellAccessor & cell() const
Return DHCellAccessor appropriate to the side.
unsigned int dim() const
Return dimension of element appropriate to the side.
unsigned int side_idx() const
Compound finite element on dim dimensional simplex.
Definition: fe_system.hh:102
const std::vector< std::shared_ptr< FiniteElement< dim > > > & fe() const
Definition: fe_system.hh:147
Abstract class for the description of a general finite element on a reference simplex in dim dimensio...
PatchOp< spacedim > * get(std::shared_ptr< FiniteElement< dim >> fe)
Returns operation of given dim and OpType, creates it if doesn't exist.
uint register_element(DHCellAccessor cell, uint element_patch_idx)
Register element to patch_point_vals_ table by dimension of element.
PatchPointValues< spacedim >::PatchFeData PatchFeData
std::vector< PatchOp< spacedim > * > operations_
uint register_bulk_point(DHCellAccessor cell, uint elem_table_row, uint value_patch_idx, uint i_point_on_elem)
Register bulk point to patch_point_vals_ table by dimension of element.
~PatchFEValues()
Destructor.
Quadrature * get_bulk_quadrature(uint dim) const
Getter for bulk quadrature of given dimension.
SideValues< dim > side_values()
Return SideValue object of dimension given by template parameter.
Quadrature * get_side_quadrature(uint dim) const
Getter for side quadrature of given dimension.
uint register_side(DHCellSide cell_side)
Register side to patch_point_vals_ table by dimension of side.
JoinValues< dim > join_values()
Return JoinValue object of dimension given by template parameter.
void init_finalize()
Finalize initialization, creates child (patch) arena and passes it to PatchPointValue objects.
PatchOp< spacedim > * get()
Returns operation of given dim and OpType, creates it if doesn't exist.
BulkValues< dim > bulk_values()
Return BulkValue object of dimension given by template parameter.
const AssemblyArena & asm_arena() const
same as previous but return constant reference
PatchArena & patch_arena() const
return reference to patch arena
uint register_side_point(DHCellSide cell_side, uint elem_table_row, uint value_patch_idx, uint i_point_on_side)
Register side point to patch_point_vals_ table by dimension of side.
void initialize(Quadrature &_quadrature)
Initialize structures and calculates cell-independent data.
void print_operations(ostream &stream) const
Print table of all used operations - development method.
PatchFeData patch_fe_data_
MixedPtr< FiniteElement > fe_
Mixed of shared pointers of FiniteElement object.
void resize_tables(TableSizes table_sizes)
Resize tables of patch_point_vals_.
PatchFEValues(unsigned int quad_order, MixedPtr< FiniteElement > fe)
void reinit_patch()
Reinit data.
bool used_quads_[2]
Pair of flags signs holds info if bulk and side quadratures are used.
unsigned int n_dofs() const
Returns the number of shape functions.
std::unordered_map< std::string, PatchOp< spacedim > * > op_dependency_
AssemblyArena & asm_arena()
return reference to assembly arena
std::vector< std::vector< PatchPointValues< spacedim > > > patch_point_vals_
Sub objects of bulk and side data of dimensions 1,2,3.
std::shared_ptr< FiniteElement< dim > > fe_comp(std::shared_ptr< FiniteElement< dim > > fe, uint component_idx)
Returnd FiniteElement of component_idx for FESystem or fe for other types.
void reset()
Reset PatchpointValues structures.
std::vector< ElementAccessor< spacedim > > elem_list_
List of elements on patch.
uint i_elem_
Index of registered element in table, helper value used during patch creating.
std::vector< uint > elements_map_
Map of element patch indices to PatchOp::result_ and int_table_ tables.
IntTableArena int_table_
std::vector< Side > side_list_
List of sides on patch.
Base class for quadrature rules on simplices in arbitrary dimensions.
Definition: quadrature.hh:48
unsigned int dim() const
Definition: quadrature.hh:72
Store finite element data on the actual patch such as shape function values, gradients,...
Class FESystem for compound finite elements.
@ FEMixedSystem
#define DebugOut()
Macro defining 'debug' record of log.
Definition: logger.hh:284
unsigned int uint
Declares accessors to FE operations.
Base class of FE operations.
Store finite element data on the actual patch such as shape function values, gradients,...
Definitions of particular quadrature rules on simplices.
Class RefElement defines numbering of vertices, sides, calculation of normal vectors etc.
Definition: mixed.hh:25
Struct for pre-computing number of elements, sides, bulk points and side points on each dimension.
std::vector< std::vector< uint > > point_sizes_
void reset()
Set all values to zero.
void copy(const TableSizes &other)
Copy values of other TableSizes instance.
std::vector< std::vector< uint > > elem_sizes_