Flow123d  master-f44eb46
dh_cell_accessor.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 dh_cell_accessor.hh
15  * @brief
16  * @author David Flanderka
17  */
18 
19 #ifndef DH_CELL_ACCESSOR_HH_
20 #define DH_CELL_ACCESSOR_HH_
21 
22 #include <armadillo>
23 #include "mesh/accessors.hh"
24 #include "mesh/neighbours.h"
25 #include "fem/finite_element.hh"
26 #include "fem/dofhandler.hh"
27 #include "system/index_types.hh"
28 
29 class DHCellSide;
30 class DHNeighbSide;
31 class DHEdgeSide;
32 template <int spacedim> class ElementAccessor;
33 
34 /**
35  * @brief Cell accessor allow iterate over DOF handler cells.
36  *
37  * Iterating is possible over different ranges of local and ghost elements.
38  *
39  * Iterator is defined by:
40  * - DOF handler
41  * - local index of DOF cell (iterated value)
42  */
44 public:
45  /// Default invalid accessor.
47  : dof_handler_(NULL)
48  {}
49 
50  /**
51  * DOF cell accessor.
52  */
53  DHCellAccessor(const DOFHandlerMultiDim *dof_handler, unsigned int loc_idx)
54  : dof_handler_(dof_handler), loc_ele_idx_(loc_idx)
55  {}
56 
57  /// Return local index to element (index of DOF handler).
58  inline unsigned int local_idx() const {
59  ASSERT_LT(loc_ele_idx_, dof_handler_->global_to_local_el_idx_.size()).error("Local element index is out of range!\n");
60  return loc_ele_idx_;
61  }
62 
63  /// Return serial idx to element of loc_ele_idx_.
64  inline unsigned int elm_idx() const {
65  unsigned int ds_lsize = dof_handler_->el_ds_->lsize();
66  if (local_idx()<ds_lsize) return dof_handler_->mesh()->get_el_4_loc()[loc_ele_idx_]; //own elements
67  else return dof_handler_->ghost_4_loc[loc_ele_idx_-ds_lsize]; //ghost elements
68  }
69 
70  /// Return ElementAccessor to element of loc_ele_idx_.
71  inline const ElementAccessor<3> elm() const {
72  return dof_handler_->mesh()->element_accessor( elm_idx() );
73  }
74 
75  /**
76  * @brief Fill vector of the global indices of dofs associated to the cell.
77  *
78  * @param indices Vector of dof indices on the cell.
79  */
80  unsigned int get_dof_indices(std::vector<LongIdx> &indices) const
81  { return dof_handler_->get_dof_indices( *this, indices ); }
82 
83  /**
84  * @brief Returns the local indices of dofs associated to the cell on the local process.
85  *
86  * @param indices Array of dof indices on the cell.
87  */
90 
91  /// Return number of dofs on given cell.
92  unsigned int n_dofs() const;
93 
94  /**
95  * @brief Return dof on a given cell.
96  * @param idof Number of dof on the cell.
97  */
98  const Dof &cell_dof(unsigned int idof) const;
99 
100  /// Return dimension of element appropriate to cell.
101  inline unsigned int dim() const {
102  return elm().dim();
103  }
104 
105  /// Return DOF handler
106  inline const DOFHandlerMultiDim *dh() const{
107  return dof_handler_;
108  }
109 
110  /**
111  * @brief Returns finite element object for given space dimension.
112  */
113  template<unsigned int dim>
114  FEPtr<dim> fe() const {
115  return dof_handler_->ds_->fe()[Dim<dim>{}];
116  }
117 
118  /// Check validity of accessor (see default constructor)
119  inline bool is_valid() const {
120  return dof_handler_ != NULL;
121  }
122 
123  /// Returns range of cell sides
125 
126  /// Returns range of neighbour cell of lower dimension corresponding to cell of higher dimension
128 
129  /// Return true if accessor represents own element (false for ghost element)
130  inline bool is_own() const {
131  return (loc_ele_idx_ < dof_handler_->el_ds_->lsize());
132  }
133 
134  /// Create new accessor with same local idx and given DOF handler. Actual and given DOF handler must be create on same Mesh.
136  ASSERT( (dh->mesh()->n_nodes() == dof_handler_->mesh()->n_nodes()) && (dh->mesh()->n_elements() == dof_handler_->mesh()->n_elements()) )
137  .error("Incompatible DOF handlers!");
138  return DHCellAccessor(dh, loc_ele_idx_);
139  }
140 
141  /// Iterates to next local element.
142  inline void inc() {
143  loc_ele_idx_++;
144  }
145 
146  /// Comparison of accessors.
147  bool operator==(const DHCellAccessor& other) const {
148  return (loc_ele_idx_ == other.loc_ele_idx_);
149  }
150 
151  /// Comparison of accessors.
152  bool operator!=(const DHCellAccessor& other) const {
153  return (loc_ele_idx_ != other.loc_ele_idx_);
154  }
155 
156 
157 private:
158  /// Pointer to the DOF handler owning the element.
160  /// Index into DOFHandler::el_4_loc array.
161  unsigned int loc_ele_idx_;
162 
163  friend class DHCellSide;
164  friend class DHEdgeSide;
165  friend class DHNeighbSide;
166 };
167 
168 
169 /**
170  * @brief Side accessor allows to iterate over sides of DOF handler cell.
171  *
172  * Iterator is defined by:
173  * - DOF handler cell
174  * - index of Side in DOF cell (iterated value)
175  */
176 class DHCellSide {
177 public:
178 
179  /**
180  * @brief Default invalid accessor.
181  *
182  * Create invalid \p dh_cell_accessor_.
183  */
185 
186  /**
187  * DOF cell side accessor.
188  */
189  DHCellSide(const DHCellAccessor &dh_cell_accessor, unsigned int side_idx)
190  : dh_cell_accessor_(dh_cell_accessor), side_idx_(side_idx) {}
191 
192  /// Check validity of accessor (see default constructor)
193  inline virtual bool is_valid() const {
194  return dh_cell_accessor_.is_valid();
195  }
196 
197  /// Return Side of given cell and side_idx.
198  inline Side side() const {
199  ASSERT( this->is_valid() );
201  }
202 
203  /// Return DHCellAccessor appropriate to the side.
204  inline const DHCellAccessor &cell() const {
205  return dh_cell_accessor_;
206  }
207 
208  /// Return DHCellAccessor appropriate to the side.
209  inline DHCellAccessor &cell() {
210  return dh_cell_accessor_;
211  }
212 
213  /// Return dimension of element appropriate to the side.
214  inline unsigned int dim() const {
215  return cell().dim();
216  }
217 
218  /// Side centre.
219  inline arma::vec3 centre() const {
220  return side().centre();
221  }
222 
223  inline ElementAccessor<3> element() const {
224  return side().element();
225  }
226 
227  inline unsigned int elem_idx() const {
228  return side().elem_idx();
229  }
230 
231  inline Boundary cond() const {
232  return side().cond();
233  }
234 
235  inline unsigned int side_idx() const {
236  return side_idx_;
237  }
238 
239  inline double measure() const {
240  return side().measure();
241  }
242 
243  inline double diameter() const {
244  return side().diameter();
245  }
246 
247 
248  /// Returns range of all sides looped over common Edge.
250 
251  /**
252  * Returns total number of sides appropriate to Edge that owns actual cell side.
253  *
254  * return empty range if no element connected to Edge is local
255  */
256  unsigned int n_edge_sides() const;
257 
258  /// Iterates to next local element.
259  inline virtual void inc() {
260  side_idx_++;
261  }
262 
263  /// Comparison of accessors.
264  inline bool operator ==(const DHCellSide &other) {
265  return this->elem_idx() == other.elem_idx() && side_idx_ == other.side_idx_;
266  }
267 
268  inline bool operator !=(const DHCellSide &other) const {
269  return this->elem_idx() != other.elem_idx() || side_idx_ != other.side_idx_;
270  }
271 
272 private:
273  /// Appropriate DHCellAccessor.
275  /// Index of side.
276  unsigned int side_idx_;
277 
278  friend class DHEdgeSide;
279 };
280 
281 
282 /**
283  * @brief Class allows to iterate over sides of edge.
284  *
285  * Iterator is defined by:
286  * - DOF handler
287  * - global index of Edge (constant value)
288  * - index of Side in Edge (iterated value)
289  *
290  * Note: Class is used only internally. Appropriate range method (DHCellSide::edge_sides) uses convertible iterators
291  * and returns corresponding DHCellSide.
292  */
293 class DHEdgeSide {
294 public:
295  /// Default invalid accessor.
296  DHEdgeSide() : dof_handler_(nullptr), edge_idx_(0) {}
297 
298  /**
299  * Valid accessor allows iterate over sides.
300  */
301  DHEdgeSide(const DHCellSide &cell_side, unsigned int side_idx)
302  : dof_handler_(cell_side.dh_cell_accessor_.dof_handler_),
303  edge_idx_(cell_side.dh_cell_accessor_.elm()->edge_idx(cell_side.side_idx_)),
304  side_idx_(side_idx)
305  {}
306 
307  /// Check validity of accessor (see default constructor)
308  inline bool is_valid() const {
309  return (dof_handler_!=nullptr);
310  }
311 
312  /// Iterates to next edge side.
313  inline void inc() {
314  side_idx_++;
315  }
316 
317  /// Comparison of accessors.
318  bool operator==(const DHEdgeSide& other) {
319  return (edge_idx_ == other.edge_idx_) && (side_idx_ == other.side_idx_);
320  }
321 
322  /// This class is implicitly convertible to DHCellSide.
323  operator DHCellSide() const {
326  return DHCellSide(cell, side->side_idx());
327  }
328 
329 private:
330  /// Pointer to the DOF handler owning the element.
332  /// Global index of Edge.
333  unsigned int edge_idx_;
334  /// Index of side owned by Edge.
335  unsigned int side_idx_;
336 };
337 
338 
339 /**
340  * @brief Class allows to iterate over sides of neighbour.
341  *
342  * Class returns only local cells (owns + ghosts), non-local cells are skipped.
343  *
344  * Iterator is defined by:
345  * - DOF handler cell accessor
346  * - index of Neighbour on cell (iterated value)
347  * - maximal index of Neighbour (allow to skip non-local cells)
348  *
349  * Note: Class is used only internally. Appropriate range method (DHCellAccessor::neighb_sides) uses convertible
350  * iterators and returns corresponding DHCellSide.
351  */
353 public:
354  /// Default invalid accessor.
356 
357  /**
358  * @brief Valid accessor allows iterate over neighbor sides.
359  *
360  * @param dh_cell Element of lower dim.
361  * @param neighb_idx Index of neighbour.
362  * @param max_idx Maximal index of neighbour, method inc() doesn't set neighb_idx_ on higher value.
363  */
364  DHNeighbSide(const DHCellAccessor &dh_cell, unsigned int neighb_idx, unsigned int max_idx)
365  : dh_cell_(dh_cell), neighb_idx_(neighb_idx), max_idx_(max_idx)
366  {
367  // Skip non-local cells
368  while ( (neighb_idx_<max_idx_) && not_local_cell() ) {
369  neighb_idx_++;
370  }
371  }
372 
373  /// Check validity of accessor (see default constructor of DHCellAccessor)
374  inline bool is_valid() const {
375  return dh_cell_.is_valid();
376  }
377 
378  /// Iterates to next neighbour side.
379  inline void inc() {
380  // Skip non-local cells
381  do {
382  neighb_idx_++;
383  if (neighb_idx_>=max_idx_) break; //stop condition at the end item of range
384  } while ( not_local_cell() );
385  }
386 
387  /// Comparison of accessors.
388  bool operator==(const DHNeighbSide& other) {
389  return (neighb_idx_ == other.neighb_idx_);
390  }
391 
392  /// This class is implicitly convertible to DHCellSide.
393  operator DHCellSide() const {
396  return DHCellSide(cell, side->side_idx());
397  }
398 
399 private:
400  /// Check if cell side of neighbour is not local (allow skip invalid accessors).
401  inline bool not_local_cell() {
404  }
405 
406  /// Appropriate cell accessor.
408  /// Index into neigh_vb array
409  unsigned int neighb_idx_;
410  /// Maximal index into neigh_vb array
411  unsigned int max_idx_;
412 };
413 
414 
415 /*************************************************************************************
416  * Implementation of inlined methods.
417  */
418 
419 
420 inline unsigned int DHCellAccessor::n_dofs() const
421 {
422  switch (this->dim()) {
423  case 0:
424  return fe<0>()->n_dofs();
425  break;
426  case 1:
427  return fe<1>()->n_dofs();
428  break;
429  case 2:
430  return fe<2>()->n_dofs();
431  break;
432  case 3:
433  return fe<3>()->n_dofs();
434  break;
435  }
436  return 0; // only fix compiler warning
437 }
438 
439 
440 inline const Dof &DHCellAccessor::cell_dof(unsigned int idof) const
441 {
442  switch (this->dim())
443  {
444  case 0:
445  return fe<0>()->dof(idof);
446  break;
447  case 1:
448  return fe<1>()->dof(idof);
449  break;
450  case 2:
451  return fe<2>()->dof(idof);
452  break;
453  case 3:
454  return fe<3>()->dof(idof);
455  break;
456  }
457 
458  ASSERT_PERMANENT(0)(this->dim()).error("Unsupported FE dimension.");
459  // cannot be reached:
460  return fe<1>()->dof(idof);
461 }
462 
463 
465  auto bgn_it = make_iter<DHCellSide>( DHCellSide(*this, 0) );
466  auto end_it = make_iter<DHCellSide>( DHCellSide(*this, dim()+1) );
467  return Range<DHCellSide>(bgn_it, end_it);
468 }
469 
470 
472  unsigned int upper_bound = this->elm()->n_neighs_vb();
473  auto bgn_it = make_iter<DHNeighbSide, DHCellSide>( DHNeighbSide(*this, 0, upper_bound) );
474  auto end_it = make_iter<DHNeighbSide, DHCellSide>( DHNeighbSide(*this, upper_bound, upper_bound) );
475  return RangeConvert<DHNeighbSide, DHCellSide>(bgn_it, end_it);
476 }
477 
478 
480  return RangeConvert<DHEdgeSide, DHCellSide>(make_iter<DHEdgeSide, DHCellSide>( DHEdgeSide( *this, 0) ),
481  make_iter<DHEdgeSide, DHCellSide>( DHEdgeSide( *this, n_edge_sides()) ));
482 }
483 
484 
485 inline unsigned int DHCellSide::n_edge_sides() const {
486  unsigned int edge_idx = dh_cell_accessor_.elm()->edge_idx(side_idx_);
487  Edge edg = dh_cell_accessor_.dof_handler_->mesh()->edge(edge_idx);
488  for (uint sid=0; sid<edg.n_sides(); sid++)
489  if ( dh_cell_accessor_.dof_handler_->el_is_local(edg.side(sid)->element().idx()) ) return edg.n_sides();
490  return 0;
491 }
492 
493 
494 
495 #endif /* DH_CELL_ACCESSOR_HH_ */
#define ASSERT(expr)
Definition: asserts.hh:351
#define ASSERT_PERMANENT(expr)
Allow use shorter versions of macro names if these names is not used with external library.
Definition: asserts.hh:348
#define ASSERT_LT(a, b)
Definition of comparative assert macro (Less Than) only for debug mode.
Definition: asserts.hh:301
Cell accessor allow iterate over DOF handler cells.
const ElementAccessor< 3 > elm() const
Return ElementAccessor to element of loc_ele_idx_.
unsigned int n_dofs() const
Return number of dofs on given cell.
RangeConvert< DHNeighbSide, DHCellSide > neighb_sides() const
Returns range of neighbour cell of lower dimension corresponding to cell of higher dimension.
DHCellAccessor(const DOFHandlerMultiDim *dof_handler, unsigned int loc_idx)
bool is_own() const
Return true if accessor represents own element (false for ghost element)
const Dof & cell_dof(unsigned int idof) const
Return dof on a given cell.
void inc()
Iterates to next local element.
LocDofVec get_loc_dof_indices() const
Returns the local indices of dofs associated to the cell on the local process.
bool operator!=(const DHCellAccessor &other) const
Comparison of accessors.
DHCellAccessor cell_with_other_dh(const DOFHandlerMultiDim *dh) const
Create new accessor with same local idx and given DOF handler. Actual and given DOF handler must be c...
friend class DHCellSide
bool operator==(const DHCellAccessor &other) const
Comparison of accessors.
DHCellAccessor()
Default invalid accessor.
unsigned int get_dof_indices(std::vector< LongIdx > &indices) const
Fill vector of the global indices of dofs associated to the cell.
unsigned int loc_ele_idx_
Index into DOFHandler::el_4_loc array.
const DOFHandlerMultiDim * dh() const
Return DOF handler.
unsigned int dim() const
Return dimension of element appropriate to cell.
const DOFHandlerMultiDim * dof_handler_
Pointer to the DOF handler owning the element.
Range< DHCellSide > side_range() const
Returns range of cell sides.
unsigned int elm_idx() const
Return serial idx to element of loc_ele_idx_.
FEPtr< dim > fe() const
Returns finite element object for given space dimension.
friend class DHNeighbSide
bool is_valid() const
Check validity of accessor (see default constructor)
unsigned int local_idx() const
Return local index to element (index of DOF handler).
Side accessor allows to iterate over sides of DOF handler cell.
virtual bool is_valid() const
Check validity of accessor (see default constructor)
unsigned int elem_idx() const
DHCellAccessor & cell()
Return DHCellAccessor appropriate to the side.
DHCellSide(const DHCellAccessor &dh_cell_accessor, unsigned int side_idx)
DHCellAccessor dh_cell_accessor_
Appropriate DHCellAccessor.
DHCellSide()
Default invalid accessor.
bool operator==(const DHCellSide &other)
Comparison of accessors.
unsigned int n_edge_sides() const
double diameter() const
Side side() const
Return Side of given cell and side_idx.
Boundary cond() const
const DHCellAccessor & cell() const
Return DHCellAccessor appropriate to the side.
RangeConvert< DHEdgeSide, DHCellSide > edge_sides() const
Returns range of all sides looped over common Edge.
unsigned int dim() const
Return dimension of element appropriate to the side.
double measure() const
bool operator!=(const DHCellSide &other) const
unsigned int side_idx_
Index of side.
virtual void inc()
Iterates to next local element.
ElementAccessor< 3 > element() const
unsigned int side_idx() const
friend class DHEdgeSide
arma::vec3 centre() const
Side centre.
Class allows to iterate over sides of edge.
DHEdgeSide(const DHCellSide &cell_side, unsigned int side_idx)
bool operator==(const DHEdgeSide &other)
Comparison of accessors.
DHEdgeSide()
Default invalid accessor.
void inc()
Iterates to next edge side.
unsigned int side_idx_
Index of side owned by Edge.
const DOFHandlerMultiDim * dof_handler_
Pointer to the DOF handler owning the element.
bool is_valid() const
Check validity of accessor (see default constructor)
unsigned int edge_idx_
Global index of Edge.
Class allows to iterate over sides of neighbour.
bool is_valid() const
Check validity of accessor (see default constructor of DHCellAccessor)
DHNeighbSide(const DHCellAccessor &dh_cell, unsigned int neighb_idx, unsigned int max_idx)
Valid accessor allows iterate over neighbor sides.
DHCellAccessor dh_cell_
Appropriate cell accessor.
unsigned int max_idx_
Maximal index into neigh_vb array.
bool not_local_cell()
Check if cell side of neighbour is not local (allow skip invalid accessors).
bool operator==(const DHNeighbSide &other)
Comparison of accessors.
void inc()
Iterates to next neighbour side.
DHNeighbSide()
Default invalid accessor.
unsigned int neighb_idx_
Index into neigh_vb array.
MeshBase * mesh() const
Returns the mesh.
Definition: dofhandler.hh:78
Provides the numbering of the finite element degrees of freedom on the computational mesh.
Definition: dofhandler.hh:151
LocDofVec get_loc_dof_indices(unsigned int loc_ele_idx) const override
Returns the indices of dofs associated to the cell on the local process.
Definition: dofhandler.hh:369
Distribution * el_ds_
Distribution of elements.
Definition: dofhandler.hh:448
std::shared_ptr< DiscreteSpace > ds_
Pointer to the discrete space for which the handler distributes dofs.
Definition: dofhandler.hh:398
unsigned int get_dof_indices(const DHCellAccessor &cell, std::vector< LongIdx > &indices) const override
Returns the global indices of dofs associated to the cell.
Definition: dofhandler.cc:567
vector< LongIdx > ghost_4_loc
Indices of ghost cells (neighbouring with local elements).
Definition: dofhandler.hh:457
bool el_is_local(int index) const
Definition: dofhandler.cc:669
const DHCellAccessor cell_accessor_from_element(unsigned int elm_idx) const
Return DHCellAccessor appropriate to ElementAccessor of given idx.
Definition: dofhandler.cc:701
std::unordered_map< LongIdx, LongIdx > global_to_local_el_idx_
Maps global element index into local/ghost index (obsolete).
Definition: dofhandler.hh:445
unsigned int lsize(int proc) const
get local size
unsigned int n_sides() const
Returns number of sides aligned with the edge.
Definition: accessors.hh:329
SideIter side(const unsigned int i) const
Gets side iterator of the i -th side.
unsigned int idx() const
We need this method after replacing Region by RegionIdx, and movinf RegionDB instance into particular...
Definition: accessors.hh:215
unsigned int dim() const
Definition: accessors.hh:188
unsigned int edge_idx(unsigned int edg_idx) const
Return edge_idx of given index.
Definition: elements.h:135
Neighbour ** neigh_vb
Definition: elements.h:83
unsigned int n_neighs_vb() const
Return number of neighbours.
Definition: elements.h:65
LongIdx * get_el_4_loc() const
Definition: mesh.h:122
unsigned int n_nodes() const
Definition: mesh.h:171
unsigned int n_elements() const
Definition: mesh.h:111
Edge edge(uint edge_idx) const
Return edge with given index.
Definition: mesh.cc:131
ElementAccessor< 3 > element_accessor(unsigned int idx) const
Create and return ElementAccessor to element of given idx.
Definition: mesh.cc:866
SideIter side() const
Definition: neighbours.h:147
Range helper class.
Range helper class.
double measure() const
Calculate metrics of the side.
Definition: accessors.cc:27
unsigned int elem_idx() const
Returns index of element in Mesh::element_vec_.
Definition: accessors.hh:448
unsigned int side_idx() const
Returns local index of the side on the element.
Definition: accessors.hh:444
Boundary cond() const
ElementAccessor< 3 > element() const
Returns iterator to the element of the side.
double diameter() const
Calculate the side diameter.
Definition: accessors.cc:132
arma::vec3 centre() const
Centre of side.
Definition: accessors.cc:116
std::shared_ptr< FiniteElement< dim > > FEPtr
Declaration of class which handles the ordering of degrees of freedom (dof) and mappings between loca...
Abstract class for description of finite elements.
arma::Col< IntIdx > LocDofVec
Definition: index_types.hh:28
int LongIdx
Define type that represents indices of large arrays (elements, nodes, dofs etc.)
Definition: index_types.hh:24
unsigned int uint
Definition: mixed.hh:25