Flow123d  JS_before_hm-1598-g3b021b4
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_DBG(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() );
200  return Side(dh_cell_accessor_.dof_handler_->mesh(), dh_cell_accessor_.elm_idx(), side_idx_ );
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.
249  RangeConvert<DHEdgeSide, DHCellSide> edge_sides() const;
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 {
324  SideIter side = dof_handler_->mesh()->edge(edge_idx_).side(side_idx_);
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 {
394  SideIter side = dh_cell_.elm()->neigh_vb[neighb_idx_]->side();
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() {
402  return ( dh_cell_.dof_handler_->global_to_local_el_idx_.end() ==
403  dh_cell_.dof_handler_->global_to_local_el_idx_.find((LongIdx)dh_cell_.elm()->neigh_vb[neighb_idx_]->side()->elem_idx()) );
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 1:
424  return fe<1>()->n_dofs();
425  break;
426  case 2:
427  return fe<2>()->n_dofs();
428  break;
429  case 3:
430  return fe<3>()->n_dofs();
431  break;
432  }
433  return 0; // only fix compiler warning
434 }
435 
436 
437 inline const Dof &DHCellAccessor::cell_dof(unsigned int idof) const
438 {
439  switch (this->dim())
440  {
441  case 1:
442  return fe<1>()->dof(idof);
443  break;
444  case 2:
445  return fe<2>()->dof(idof);
446  break;
447  case 3:
448  return fe<3>()->dof(idof);
449  break;
450  }
451 
452  ASSERT(0)(this->dim()).error("Unsupported FE dimension.");
453  // cannot be reached:
454  return fe<1>()->dof(idof);;
455 }
456 
457 
459  auto bgn_it = make_iter<DHCellSide>( DHCellSide(*this, 0) );
460  auto end_it = make_iter<DHCellSide>( DHCellSide(*this, dim()+1) );
461  return Range<DHCellSide>(bgn_it, end_it);
462 }
463 
464 
466  unsigned int upper_bound = this->elm()->n_neighs_vb();
467  auto bgn_it = make_iter<DHNeighbSide, DHCellSide>( DHNeighbSide(*this, 0, upper_bound) );
468  auto end_it = make_iter<DHNeighbSide, DHCellSide>( DHNeighbSide(*this, upper_bound, upper_bound) );
469  return RangeConvert<DHNeighbSide, DHCellSide>(bgn_it, end_it);
470 }
471 
472 
474  return RangeConvert<DHEdgeSide, DHCellSide>(make_iter<DHEdgeSide, DHCellSide>( DHEdgeSide( *this, 0) ),
475  make_iter<DHEdgeSide, DHCellSide>( DHEdgeSide( *this, n_edge_sides()) ));
476 }
477 
478 
479 inline unsigned int DHCellSide::n_edge_sides() const {
480  unsigned int edge_idx = dh_cell_accessor_.elm()->edge_idx(side_idx_);
481  Edge edg = dh_cell_accessor_.dof_handler_->mesh()->edge(edge_idx);
482  for (uint sid=0; sid<edg.n_sides(); sid++)
483  if ( dh_cell_accessor_.dof_handler_->el_is_local(edg.side(sid)->element().idx()) ) return edg.n_sides();
484  return 0;
485 }
486 
487 
488 
489 #endif /* DH_CELL_ACCESSOR_HH_ */
double diameter() const
unsigned int n_sides() const
Returns number of sides aligned with the edge.
Definition: accessors.hh:300
const Element * element() const
Definition: accessors.hh:160
virtual bool is_valid() const
Check validity of accessor (see default constructor)
const Dof & cell_dof(unsigned int idof) const
Return dof on a given cell.
Definition: mixed.hh:25
Range< DHCellSide > side_range() const
Returns range of cell sides.
Declaration of class which handles the ordering of degrees of freedom (dof) and mappings between loca...
bool operator!=(const DHCellAccessor &other) const
Comparison of accessors.
Class allows to iterate over sides of neighbour.
const DOFHandlerMultiDim * dof_handler_
Pointer to the DOF handler owning the element.
unsigned int elm_idx() const
Return serial idx to element of loc_ele_idx_.
const DHCellAccessor cell_accessor_from_element(unsigned int elm_idx) const
Return DHCellAccessor appropriate to ElementAccessor of given idx.
Definition: dofhandler.cc:678
arma::Col< IntIdx > LocDofVec
Definition: index_types.hh:28
unsigned int uint
void inc()
Iterates to next local element.
unsigned int dim() const
Return dimension of element appropriate to the side.
unsigned int side_idx() const
Returns local index of the side on the element.
Definition: accessors.hh:415
DHCellAccessor dh_cell_accessor_
Appropriate DHCellAccessor.
unsigned int get_dof_indices(std::vector< LongIdx > &indices) const
Fill vector of the global indices of dofs associated to the cell.
unsigned int elem_idx() const
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:364
virtual unsigned int n_elements() const
Returns count of boundary or bulk elements.
Definition: mesh.h:343
Range helper class.
Distribution * el_ds_
Distribution of elements.
Definition: dofhandler.hh:443
unsigned int dim() const
Return dimension of element appropriate to cell.
unsigned int local_idx() const
Return local index to element (index of DOF handler).
Cell accessor allow iterate over DOF handler cells.
bool is_valid() const
Check validity of accessor (see default constructor of DHCellAccessor)
LocDofVec get_loc_dof_indices() const
Returns the local indices of dofs associated to the cell on the local process.
double measure() const
const DOFHandlerMultiDim * dof_handler_
Pointer to the DOF handler owning the element.
unsigned int side_idx_
Index of side owned by Edge.
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:347
virtual unsigned int n_nodes() const
Definition: mesh.h:125
bool is_valid() const
Check validity of accessor (see default constructor)
Mesh * mesh() const
Returns the mesh.
Definition: dofhandler.hh:78
unsigned int max_idx_
Maximal index into neigh_vb array.
unsigned int side_idx() const
bool is_own() const
Return true if accessor represents own element (false for ghost element)
unsigned int n_dofs() const
Return number of dofs on given cell.
ElementAccessor< 3 > element() const
Returns iterator to the element of the side.
Side side() const
Return Side of given cell and side_idx.
virtual ElementAccessor< 3 > element_accessor(unsigned int idx) const
Create and return ElementAccessor to element of given idx.
Definition: mesh.cc:925
DHNeighbSide(const DHCellAccessor &dh_cell, unsigned int neighb_idx, unsigned int max_idx)
Valid accessor allows iterate over neighbor sides.
bool is_valid() const
Check validity of accessor (see default constructor)
const ElementAccessor< 3 > elm() const
Return ElementAccessor to element of loc_ele_idx_.
unsigned int neighb_idx_
Index into neigh_vb array.
DHNeighbSide()
Default invalid accessor.
RangeConvert< DHEdgeSide, DHCellSide > edge_sides() const
Returns range of all sides looped over common Edge.
void inc()
Iterates to next neighbour side.
Range helper class.
ElementAccessor< 3 > element() const
DHCellAccessor()
Default invalid accessor.
RangeConvert< DHNeighbSide, DHCellSide > neighb_sides() const
Returns range of neighbour cell of lower dimension corresponding to cell of higher dimension...
Boundary cond() const
Provides the numbering of the finite element degrees of freedom on the computational mesh...
Definition: dofhandler.hh:151
DHCellAccessor(const DOFHandlerMultiDim *dof_handler, unsigned int loc_idx)
vector< LongIdx > ghost_4_loc
Indices of ghost cells (neighbouring with local elements).
Definition: dofhandler.hh:452
unsigned int n_edge_sides() const
std::unordered_map< LongIdx, LongIdx > global_to_local_el_idx_
Maps global element index into local/ghost index (obsolete).
Definition: dofhandler.hh:440
friend class DHCellSide
unsigned int edge_idx_
Global index of Edge.
const DOFHandlerMultiDim * dh() const
Return DOF handler.
DHEdgeSide()
Default invalid accessor.
std::shared_ptr< FiniteElement< dim >> FEPtr
const DHCellAccessor & cell() const
Return DHCellAccessor appropriate to the side.
void inc()
Iterates to next edge side.
DHCellAccessor & cell()
Return DHCellAccessor appropriate to the side.
int LongIdx
Define type that represents indices of large arrays (elements, nodes, dofs etc.)
Definition: index_types.hh:24
bool operator==(const DHNeighbSide &other)
Comparison of accessors.
DHCellSide()
Default invalid accessor.
virtual void inc()
Iterates to next local element.
friend class DHNeighbSide
DHEdgeSide(const DHCellSide &cell_side, unsigned int side_idx)
DHCellAccessor dh_cell_
Appropriate cell accessor.
std::shared_ptr< DiscreteSpace > ds_
Pointer to the discrete space for which the handler distributes dofs.
Definition: dofhandler.hh:393
Edge edge(uint edge_idx) const
Definition: mesh.cc:257
unsigned int elem_idx() const
Returns index of element in Mesh::element_vec_.
Definition: accessors.hh:419
unsigned int side_idx_
Index of side.
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...
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:544
Abstract class for description of finite elements.
unsigned int dim() const
Definition: accessors.hh:157
friend class DHEdgeSide
bool operator==(const DHEdgeSide &other)
Comparison of accessors.
unsigned int n_neighs_vb() const
Return number of neighbours.
Definition: elements.h:67
unsigned int idx() const
Return local idx of element in boundary / bulk part of element vector.
Definition: accessors.hh:181
bool not_local_cell()
Check if cell side of neighbour is not local (allow skip invalid accessors).
DHCellSide(const DHCellAccessor &dh_cell_accessor, unsigned int side_idx)
LongIdx * get_el_4_loc() const
Definition: mesh.h:159
SideIter side(const unsigned int i) const
Gets side iterator of the i -th side.
unsigned int loc_ele_idx_
Index into DOFHandler::el_4_loc array.
Side accessor allows to iterate over sides of DOF handler cell.
bool operator==(const DHCellAccessor &other) const
Comparison of accessors.
FEPtr< dim > fe() const
Returns finite element object for given space dimension.
Class allows to iterate over sides of edge.
#define ASSERT_LT_DBG(a, b)
Definition of comparative assert macro (Less Than) only for debug mode.
Definition: asserts.hh:300
unsigned int lsize(int proc) const
get local size
arma::vec3 centre() const
Side centre.