Flow123d  release_3.0.0-1264-g45bfb2a
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/dofhandler.hh"
26 
27 class DHCellSide;
28 class DHNeighbSide;
29 class DHEdgeSide;
30 template <int spacedim> class ElementAccessor;
31 
32 /**
33  * @brief Cell accessor allow iterate over DOF handler cells.
34  *
35  * Iterating is possible over different ranges of local and ghost elements.
36  *
37  * Iterator is defined by:
38  * - DOF handler
39  * - local index of DOF cell (iterated value)
40  */
42 public:
43  /// Default invalid accessor.
45  : dof_handler_(NULL)
46  {}
47 
48  /**
49  * DOF cell accessor.
50  */
51  DHCellAccessor(const DOFHandlerMultiDim *dof_handler, unsigned int loc_idx)
52  : dof_handler_(dof_handler), loc_ele_idx_(loc_idx)
53  {}
54 
55  /// Return local index to element (index of DOF handler).
56  inline unsigned int local_idx() const {
57  ASSERT_LT_DBG(loc_ele_idx_, dof_handler_->global_to_local_el_idx_.size()).error("Local element index is out of range!\n");
58  return loc_ele_idx_;
59  }
60 
61  /// Return serial idx to element of loc_ele_idx_.
62  inline unsigned int elm_idx() const {
63  unsigned int ds_lsize = dof_handler_->el_ds_->lsize();
64  if (local_idx()<ds_lsize) return dof_handler_->mesh()->get_el_4_loc()[loc_ele_idx_]; //own elements
65  else return dof_handler_->ghost_4_loc[loc_ele_idx_-ds_lsize]; //ghost elements
66  }
67 
68  /// Return ElementAccessor to element of loc_ele_idx_.
69  inline const ElementAccessor<3> elm() const {
70  return dof_handler_->mesh()->element_accessor( elm_idx() );
71  }
72 
73  /**
74  * @brief Fill vector of the global indices of dofs associated to the cell.
75  *
76  * @param indices Vector of dof indices on the cell.
77  */
78  unsigned int get_dof_indices(std::vector<int> &indices) const
79  { return dof_handler_->get_dof_indices( *this, indices ); }
80 
81  /**
82  * @brief Returns the indices of dofs associated to the cell on the local process.
83  *
84  * @param indices Array of dof indices on the cell.
85  */
86  unsigned int get_loc_dof_indices(std::vector<LongIdx> &indices) const
87  { return dof_handler_->get_loc_dof_indices( *this, indices ); }
88 
89  /// Return number of dofs on given cell.
90  unsigned int n_dofs() const;
91 
92  /**
93  * @brief Return dof on a given cell.
94  * @param idof Number of dof on the cell.
95  */
96  const Dof &cell_dof(unsigned int idof) const;
97 
98  /// Return dimension of element appropriate to cell.
99  inline unsigned int dim() const {
100  return elm().dim();
101  }
102 
103  /**
104  * @brief Returns finite element object for given space dimension.
105  */
106  template<unsigned int dim>
108  ElementAccessor<3> elm_acc = this->elm();
109  return dof_handler_->ds_->fe<dim>(elm_acc);
110  }
111 
112  /// Check validity of accessor (see default constructor)
113  inline bool is_valid() const {
114  return dof_handler_ != NULL;
115  }
116 
117  /// Returns range of cell sides
119 
120  /// Returns range of neighbour cell of lower dimension corresponding to cell of higher dimension
122 
123  /// Return true if accessor represents own element (false for ghost element)
124  inline bool is_own() const {
125  return (loc_ele_idx_ < dof_handler_->el_ds_->lsize());
126  }
127 
128  /// Iterates to next local element.
129  inline void inc() {
130  loc_ele_idx_++;
131  }
132 
133  /// Comparison of accessors.
134  bool operator==(const DHCellAccessor& other) {
135  return (loc_ele_idx_ == other.loc_ele_idx_);
136  }
137 
138 private:
139  /// Pointer to the DOF handler owning the element.
141  /// Index into DOFHandler::el_4_loc array.
142  unsigned int loc_ele_idx_;
143 
144  friend class DHCellSide;
145  friend class DHEdgeSide;
146  friend class DHNeighbSide;
147 };
148 
149 
150 /**
151  * @brief Side accessor allows to iterate over sides of DOF handler cell.
152  *
153  * Iterator is defined by:
154  * - DOF handler cell
155  * - index of Side in DOF cell (iterated value)
156  */
157 class DHCellSide {
158 public:
159 
160  /**
161  * @brief Default invalid accessor.
162  *
163  * Create invalid \p dh_cell_accessor_.
164  */
166 
167  /**
168  * DOF cell side accessor.
169  */
170  DHCellSide(const DHCellAccessor &dh_cell_accessor, unsigned int side_idx)
171  : dh_cell_accessor_(dh_cell_accessor), side_idx_(side_idx) {}
172 
173  /// Check validity of accessor (see default constructor)
174  inline virtual bool is_valid() const {
175  return dh_cell_accessor_.is_valid();
176  }
177 
178  /// Return Side of given cell and side_idx.
179  inline Side side() const {
180  ASSERT( this->is_valid() );
181  return Side(dh_cell_accessor_.dof_handler_->mesh(), dh_cell_accessor_.elm_idx(), side_idx_ );
182  }
183 
184  /// Return DHCellAccessor appropriate to the side.
185  inline const DHCellAccessor cell() const {
186  return dh_cell_accessor_;
187  }
188 
189  /// Return dimension of element appropriate to the side.
190  inline unsigned int dim() const {
191  return cell().dim();
192  }
193 
194  /// Side centre.
195  inline arma::vec3 centre() const {
196  return side().centre();
197  }
198 
199  inline ElementAccessor<3> element() const {
200  return side().element();
201  }
202 
203  inline unsigned int elem_idx() const {
204  return side().elem_idx();
205  }
206 
207  inline Boundary cond() const {
208  return side().cond();
209  }
210 
211  inline unsigned int side_idx() const {
212  return side_idx_;
213  }
214 
215  inline double measure() const {
216  return side().measure();
217  }
218 
219  inline double diameter() const {
220  return side().diameter();
221  }
222 
223 
224  /// Returns range of all sides looped over common Edge.
225  RangeConvert<DHEdgeSide, DHCellSide> edge_sides() const;
226 
227  /**
228  * Returns total number of sides appropriate to Edge that owns actual cell side.
229  *
230  * return empty range if no element connected to Edge is local
231  */
232  unsigned int n_edge_sides() const;
233 
234  /// Iterates to next local element.
235  inline virtual void inc() {
236  side_idx_++;
237  }
238 
239  /// Comparison of accessors.
240  inline bool operator ==(const DHCellSide &other) {
241  return this->elem_idx() == other.elem_idx() && side_idx_ == other.side_idx_;
242  }
243 
244  inline bool operator !=(const DHCellSide &other) {
245  return this->elem_idx() != other.elem_idx() || side_idx_ != other.side_idx_;
246  }
247 
248 private:
249  /// Appropriate DHCellAccessor.
251  /// Index of side.
252  unsigned int side_idx_;
253 
254  friend class DHEdgeSide;
255 };
256 
257 
258 /**
259  * @brief Class allows to iterate over sides of edge.
260  *
261  * Iterator is defined by:
262  * - DOF handler
263  * - global index of Edge (constant value)
264  * - index of Side in Edge (iterated value)
265  *
266  * Note: Class is used only internally. Appropriate range method (DHCellSide::edge_sides) uses convertible iterators
267  * and returns corresponding DHCellSide.
268  */
269 class DHEdgeSide {
270 public:
271  /// Default invalid accessor.
272  DHEdgeSide() : dof_handler_(nullptr), edge_idx_(0) {}
273 
274  /**
275  * Valid accessor allows iterate over sides.
276  */
277  DHEdgeSide(const DHCellSide &cell_side, unsigned int side_idx)
278  : dof_handler_(cell_side.dh_cell_accessor_.dof_handler_),
279  edge_idx_(cell_side.dh_cell_accessor_.elm()->edge_idx(cell_side.side_idx_)),
280  side_idx_(side_idx)
281  {}
282 
283  /// Check validity of accessor (see default constructor)
284  inline bool is_valid() const {
285  return (dof_handler_!=nullptr);
286  }
287 
288  /// Iterates to next edge side.
289  inline void inc() {
290  side_idx_++;
291  }
292 
293  /// Comparison of accessors.
294  bool operator==(const DHEdgeSide& other) {
295  return (edge_idx_ == other.edge_idx_) && (side_idx_ == other.side_idx_);
296  }
297 
298  /// This class is implicitly convertible to DHCellSide.
299  operator DHCellSide() const {
300  SideIter side = dof_handler_->mesh()->edge(edge_idx_).side(side_idx_);
302  return DHCellSide(cell, side->side_idx());
303  }
304 
305 private:
306  /// Pointer to the DOF handler owning the element.
308  /// Global index of Edge.
309  unsigned int edge_idx_;
310  /// Index of side owned by Edge.
311  unsigned int side_idx_;
312 };
313 
314 
315 /**
316  * @brief Class allows to iterate over sides of neighbour.
317  *
318  * Class returns only local cells (owns + ghosts), non-local cells are skipped.
319  *
320  * Iterator is defined by:
321  * - DOF handler cell accessor
322  * - index of Neighbour on cell (iterated value)
323  * - maximal index of Neighbour (allow to skip non-local cells)
324  *
325  * Note: Class is used only internally. Appropriate range method (DHCellAccessor::neighb_sides) uses convertible
326  * iterators and returns corresponding DHCellSide.
327  */
329 public:
330  /// Default invalid accessor.
332 
333  /**
334  * @brief Valid accessor allows iterate over neighbor sides.
335  *
336  * @param dh_cell Element of lower dim.
337  * @param neighb_idx Index of neighbour.
338  * @param max_idx Maximal index of neighbour, method inc() doesn't set neighb_idx_ on higher value.
339  */
340  DHNeighbSide(const DHCellAccessor &dh_cell, unsigned int neighb_idx, unsigned int max_idx)
341  : dh_cell_(dh_cell), neighb_idx_(neighb_idx), max_idx_(max_idx)
342  {
343  // Skip non-local cells
344  while ( (neighb_idx_<max_idx_) && not_local_cell() ) {
345  neighb_idx_++;
346  }
347  }
348 
349  /// Check validity of accessor (see default constructor of DHCellAccessor)
350  inline bool is_valid() const {
351  return dh_cell_.is_valid();
352  }
353 
354  /// Iterates to next neighbour side.
355  inline void inc() {
356  // Skip non-local cells
357  do {
358  neighb_idx_++;
359  if (neighb_idx_>=max_idx_) break; //stop condition at the end item of range
360  } while ( not_local_cell() );
361  }
362 
363  /// Comparison of accessors.
364  bool operator==(const DHNeighbSide& other) {
365  return (neighb_idx_ == other.neighb_idx_);
366  }
367 
368  /// This class is implicitly convertible to DHCellSide.
369  operator DHCellSide() const {
370  SideIter side = dh_cell_.elm()->neigh_vb[neighb_idx_]->side();
372  return DHCellSide(cell, side->side_idx());
373  }
374 
375 private:
376  /// Check if cell side of neighbour is not local (allow skip invalid accessors).
377  inline bool not_local_cell() {
378  return ( dh_cell_.dof_handler_->global_to_local_el_idx_.end() ==
379  dh_cell_.dof_handler_->global_to_local_el_idx_.find((LongIdx)dh_cell_.elm()->neigh_vb[neighb_idx_]->side()->elem_idx()) );
380  }
381 
382  /// Appropriate cell accessor.
384  /// Index into neigh_vb array
385  unsigned int neighb_idx_;
386  /// Maximal index into neigh_vb array
387  unsigned int max_idx_;
388 };
389 
390 
391 /*************************************************************************************
392  * Implementation of inlined methods.
393  */
394 
395 
396 inline unsigned int DHCellAccessor::n_dofs() const
397 {
398  switch (this->dim()) {
399  case 1:
400  return fe<1>()->n_dofs();
401  break;
402  case 2:
403  return fe<2>()->n_dofs();
404  break;
405  case 3:
406  return fe<3>()->n_dofs();
407  break;
408  }
409  return 0; // only fix compiler warning
410 }
411 
412 
413 inline const Dof &DHCellAccessor::cell_dof(unsigned int idof) const
414 {
415  switch (this->dim())
416  {
417  case 1:
418  return fe<1>()->dof(idof);
419  break;
420  case 2:
421  return fe<2>()->dof(idof);
422  break;
423  case 3:
424  return fe<3>()->dof(idof);
425  break;
426  }
427 
428  ASSERT(0)(this->dim()).error("Unsupported FE dimension.");
429  // cannot be reached:
430  return fe<1>()->dof(idof);;
431 }
432 
433 
435  auto bgn_it = make_iter<DHCellSide>( DHCellSide(*this, 0) );
436  auto end_it = make_iter<DHCellSide>( DHCellSide(*this, dim()+1) );
437  return Range<DHCellSide>(bgn_it, end_it);
438 }
439 
440 
442  unsigned int upper_bound = this->elm()->n_neighs_vb();
443  auto bgn_it = make_iter<DHNeighbSide, DHCellSide>( DHNeighbSide(*this, 0, upper_bound) );
444  auto end_it = make_iter<DHNeighbSide, DHCellSide>( DHNeighbSide(*this, upper_bound, upper_bound) );
445  return RangeConvert<DHNeighbSide, DHCellSide>(bgn_it, end_it);
446 }
447 
448 
450  return RangeConvert<DHEdgeSide, DHCellSide>(make_iter<DHEdgeSide, DHCellSide>( DHEdgeSide( *this, 0) ),
451  make_iter<DHEdgeSide, DHCellSide>( DHEdgeSide( *this, n_edge_sides()) ));
452 }
453 
454 
455 inline unsigned int DHCellSide::n_edge_sides() const {
456  unsigned int edge_idx = dh_cell_accessor_.elm()->edge_idx(side_idx_);
457  Edge edg = dh_cell_accessor_.dof_handler_->mesh()->edge(edge_idx);
458  for (uint sid=0; sid<edg.n_sides(); sid++)
459  if ( dh_cell_accessor_.dof_handler_->el_is_local(edg.side(sid)->element().idx()) ) return edg.n_sides();
460  return 0;
461 }
462 
463 
464 
465 #endif /* DH_CELL_ACCESSOR_HH_ */
int LongIdx
Define type that represents indices of large arrays (elements, nodes, dofs etc.)
Definition: long_idx.hh:22
double diameter() const
unsigned int n_sides() const
Returns number of sides aligned with the edge.
Definition: accessors.hh:298
const Element * element() const
Definition: accessors.hh:159
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.
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...
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:689
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:413
DHCellAccessor dh_cell_accessor_
Appropriate DHCellAccessor.
unsigned int elem_idx() const
unsigned int get_loc_dof_indices(std::vector< LongIdx > &indices) const
Returns the indices of dofs associated to the cell on the local process.
Distribution * el_ds_
Distribution of elements.
Definition: dofhandler.hh:421
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).
FiniteElement< dim > * fe() const
Returns finite element object for given space dimension.
Cell accessor allow iterate over DOF handler cells.
bool is_valid() const
Check validity of accessor (see default constructor of DHCellAccessor)
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
bool is_valid() const
Check validity of accessor (see default constructor)
Mesh * mesh() const
Returns the mesh.
Definition: dofhandler.hh:77
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:739
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:430
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:418
friend class DHCellSide
unsigned int edge_idx_
Global index of Edge.
DHEdgeSide()
Default invalid accessor.
const DHCellAccessor cell() const
Return DHCellAccessor appropriate to the side.
void inc()
Iterates to next edge side.
bool operator==(const DHNeighbSide &other)
Comparison of accessors.
unsigned int get_loc_dof_indices(const DHCellAccessor &cell, std::vector< LongIdx > &indices) const override
Returns the indices of dofs associated to the cell on the local process.
Definition: dofhandler.cc:556
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:371
Edge edge(uint edge_idx) const
Definition: mesh.cc:248
unsigned int elem_idx() const
Returns index of element in Mesh::element_vec_.
Definition: accessors.hh:417
unsigned int side_idx_
Index of side.
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 the description of a general finite element on a reference simplex in dim dimensio...
unsigned int dim() const
Definition: accessors.hh:156
friend class DHEdgeSide
bool operator==(const DHEdgeSide &other)
Comparison of accessors.
unsigned int n_neighs_vb() const
Return number of neighbours.
Definition: elements.h:69
bool operator==(const DHCellAccessor &other)
Comparison of accessors.
unsigned int idx() const
Return local idx of element in boundary / bulk part of element vector.
Definition: accessors.hh:180
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)
unsigned int get_dof_indices(std::vector< int > &indices) const
Fill vector of the global indices of dofs associated to the cell.
LongIdx * get_el_4_loc() const
Definition: mesh.h:168
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.
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.