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