Flow123d  JS_before_hm-1003-g4e68d2c
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  ElementAccessor<3> elm_acc = this->elm();
116  return dof_handler_->ds_->fe(elm_acc)[Dim<dim>{}];
117  }
118 
119  /// Check validity of accessor (see default constructor)
120  inline bool is_valid() const {
121  return dof_handler_ != NULL;
122  }
123 
124  /// Getter of elm_cache_index_.
125  inline unsigned int element_cache_index() const {
126  return elm_cache_index_;
127  }
128 
129  /// Setter of elm_cache_index_.
130  inline void set_element_cache_index(unsigned int idx) const {
131  elm_cache_index_ = idx;
132  }
133 
134  /// Returns range of cell sides
136 
137  /// Returns range of neighbour cell of lower dimension corresponding to cell of higher dimension
139 
140  /// Return true if accessor represents own element (false for ghost element)
141  inline bool is_own() const {
142  return (loc_ele_idx_ < dof_handler_->el_ds_->lsize());
143  }
144 
145  /// Create new accessor with same local idx and given DOF handler. Actual and given DOF handler must be create on same Mesh.
147  ASSERT( (dh->mesh()->n_nodes() == dof_handler_->mesh()->n_nodes()) && (dh->mesh()->n_elements() == dof_handler_->mesh()->n_elements()) )
148  .error("Incompatible DOF handlers!");
149  return DHCellAccessor(dh, loc_ele_idx_);
150  }
151 
152  /// Iterates to next local element.
153  inline void inc() {
154  loc_ele_idx_++;
155  }
156 
157  /// Comparison of accessors.
158  bool operator==(const DHCellAccessor& other) const {
159  return (loc_ele_idx_ == other.loc_ele_idx_);
160  }
161 
162  /// Comparison of accessors.
163  bool operator!=(const DHCellAccessor& other) const {
164  return (loc_ele_idx_ != other.loc_ele_idx_);
165  }
166 
167 
168 private:
169  /// Pointer to the DOF handler owning the element.
171  /// Index into DOFHandler::el_4_loc array.
172  unsigned int loc_ele_idx_;
173 
174  /// Optional member used in field evaluation, holds index of cell in field data cache.
175  mutable unsigned int elm_cache_index_;
176 
177  friend class DHCellSide;
178  friend class DHEdgeSide;
179  friend class DHNeighbSide;
180 };
181 
182 
183 /**
184  * @brief Side accessor allows to iterate over sides of DOF handler cell.
185  *
186  * Iterator is defined by:
187  * - DOF handler cell
188  * - index of Side in DOF cell (iterated value)
189  */
190 class DHCellSide {
191 public:
192 
193  /**
194  * @brief Default invalid accessor.
195  *
196  * Create invalid \p dh_cell_accessor_.
197  */
199 
200  /**
201  * DOF cell side accessor.
202  */
203  DHCellSide(const DHCellAccessor &dh_cell_accessor, unsigned int side_idx)
204  : dh_cell_accessor_(dh_cell_accessor), side_idx_(side_idx) {}
205 
206  /// Check validity of accessor (see default constructor)
207  inline virtual bool is_valid() const {
208  return dh_cell_accessor_.is_valid();
209  }
210 
211  /// Return Side of given cell and side_idx.
212  inline Side side() const {
213  ASSERT( this->is_valid() );
214  return Side(dh_cell_accessor_.dof_handler_->mesh(), dh_cell_accessor_.elm_idx(), side_idx_ );
215  }
216 
217  /// Return DHCellAccessor appropriate to the side.
218  inline const DHCellAccessor &cell() const {
219  return dh_cell_accessor_;
220  }
221 
222  /// Return DHCellAccessor appropriate to the side.
223  inline DHCellAccessor &cell() {
224  return dh_cell_accessor_;
225  }
226 
227  /// Return dimension of element appropriate to the side.
228  inline unsigned int dim() const {
229  return cell().dim();
230  }
231 
232  /// Side centre.
233  inline arma::vec3 centre() const {
234  return side().centre();
235  }
236 
237  inline ElementAccessor<3> element() const {
238  return side().element();
239  }
240 
241  inline unsigned int elem_idx() const {
242  return side().elem_idx();
243  }
244 
245  inline Boundary cond() const {
246  return side().cond();
247  }
248 
249  inline unsigned int side_idx() const {
250  return side_idx_;
251  }
252 
253  inline double measure() const {
254  return side().measure();
255  }
256 
257  inline double diameter() const {
258  return side().diameter();
259  }
260 
261 
262  /// Returns range of all sides looped over common Edge.
263  RangeConvert<DHEdgeSide, DHCellSide> edge_sides() const;
264 
265  /**
266  * Returns total number of sides appropriate to Edge that owns actual cell side.
267  *
268  * return empty range if no element connected to Edge is local
269  */
270  unsigned int n_edge_sides() const;
271 
272  /// Iterates to next local element.
273  inline virtual void inc() {
274  side_idx_++;
275  }
276 
277  /// Comparison of accessors.
278  inline bool operator ==(const DHCellSide &other) {
279  return this->elem_idx() == other.elem_idx() && side_idx_ == other.side_idx_;
280  }
281 
282  inline bool operator !=(const DHCellSide &other) const {
283  return this->elem_idx() != other.elem_idx() || side_idx_ != other.side_idx_;
284  }
285 
286 private:
287  /// Appropriate DHCellAccessor.
289  /// Index of side.
290  unsigned int side_idx_;
291 
292  friend class DHEdgeSide;
293 };
294 
295 
296 /**
297  * @brief Class allows to iterate over sides of edge.
298  *
299  * Iterator is defined by:
300  * - DOF handler
301  * - global index of Edge (constant value)
302  * - index of Side in Edge (iterated value)
303  *
304  * Note: Class is used only internally. Appropriate range method (DHCellSide::edge_sides) uses convertible iterators
305  * and returns corresponding DHCellSide.
306  */
307 class DHEdgeSide {
308 public:
309  /// Default invalid accessor.
310  DHEdgeSide() : dof_handler_(nullptr), edge_idx_(0) {}
311 
312  /**
313  * Valid accessor allows iterate over sides.
314  */
315  DHEdgeSide(const DHCellSide &cell_side, unsigned int side_idx)
316  : dof_handler_(cell_side.dh_cell_accessor_.dof_handler_),
317  edge_idx_(cell_side.dh_cell_accessor_.elm()->edge_idx(cell_side.side_idx_)),
318  side_idx_(side_idx)
319  {}
320 
321  /// Check validity of accessor (see default constructor)
322  inline bool is_valid() const {
323  return (dof_handler_!=nullptr);
324  }
325 
326  /// Iterates to next edge side.
327  inline void inc() {
328  side_idx_++;
329  }
330 
331  /// Comparison of accessors.
332  bool operator==(const DHEdgeSide& other) {
333  return (edge_idx_ == other.edge_idx_) && (side_idx_ == other.side_idx_);
334  }
335 
336  /// This class is implicitly convertible to DHCellSide.
337  operator DHCellSide() const {
338  SideIter side = dof_handler_->mesh()->edge(edge_idx_).side(side_idx_);
340  return DHCellSide(cell, side->side_idx());
341  }
342 
343 private:
344  /// Pointer to the DOF handler owning the element.
346  /// Global index of Edge.
347  unsigned int edge_idx_;
348  /// Index of side owned by Edge.
349  unsigned int side_idx_;
350 };
351 
352 
353 /**
354  * @brief Class allows to iterate over sides of neighbour.
355  *
356  * Class returns only local cells (owns + ghosts), non-local cells are skipped.
357  *
358  * Iterator is defined by:
359  * - DOF handler cell accessor
360  * - index of Neighbour on cell (iterated value)
361  * - maximal index of Neighbour (allow to skip non-local cells)
362  *
363  * Note: Class is used only internally. Appropriate range method (DHCellAccessor::neighb_sides) uses convertible
364  * iterators and returns corresponding DHCellSide.
365  */
367 public:
368  /// Default invalid accessor.
370 
371  /**
372  * @brief Valid accessor allows iterate over neighbor sides.
373  *
374  * @param dh_cell Element of lower dim.
375  * @param neighb_idx Index of neighbour.
376  * @param max_idx Maximal index of neighbour, method inc() doesn't set neighb_idx_ on higher value.
377  */
378  DHNeighbSide(const DHCellAccessor &dh_cell, unsigned int neighb_idx, unsigned int max_idx)
379  : dh_cell_(dh_cell), neighb_idx_(neighb_idx), max_idx_(max_idx)
380  {
381  // Skip non-local cells
382  while ( (neighb_idx_<max_idx_) && not_local_cell() ) {
383  neighb_idx_++;
384  }
385  }
386 
387  /// Check validity of accessor (see default constructor of DHCellAccessor)
388  inline bool is_valid() const {
389  return dh_cell_.is_valid();
390  }
391 
392  /// Iterates to next neighbour side.
393  inline void inc() {
394  // Skip non-local cells
395  do {
396  neighb_idx_++;
397  if (neighb_idx_>=max_idx_) break; //stop condition at the end item of range
398  } while ( not_local_cell() );
399  }
400 
401  /// Comparison of accessors.
402  bool operator==(const DHNeighbSide& other) {
403  return (neighb_idx_ == other.neighb_idx_);
404  }
405 
406  /// This class is implicitly convertible to DHCellSide.
407  operator DHCellSide() const {
408  SideIter side = dh_cell_.elm()->neigh_vb[neighb_idx_]->side();
410  return DHCellSide(cell, side->side_idx());
411  }
412 
413 private:
414  /// Check if cell side of neighbour is not local (allow skip invalid accessors).
415  inline bool not_local_cell() {
416  return ( dh_cell_.dof_handler_->global_to_local_el_idx_.end() ==
417  dh_cell_.dof_handler_->global_to_local_el_idx_.find((LongIdx)dh_cell_.elm()->neigh_vb[neighb_idx_]->side()->elem_idx()) );
418  }
419 
420  /// Appropriate cell accessor.
422  /// Index into neigh_vb array
423  unsigned int neighb_idx_;
424  /// Maximal index into neigh_vb array
425  unsigned int max_idx_;
426 };
427 
428 
429 /*************************************************************************************
430  * Implementation of inlined methods.
431  */
432 
433 
434 inline unsigned int DHCellAccessor::n_dofs() const
435 {
436  switch (this->dim()) {
437  case 1:
438  return fe<1>()->n_dofs();
439  break;
440  case 2:
441  return fe<2>()->n_dofs();
442  break;
443  case 3:
444  return fe<3>()->n_dofs();
445  break;
446  }
447  return 0; // only fix compiler warning
448 }
449 
450 
451 inline const Dof &DHCellAccessor::cell_dof(unsigned int idof) const
452 {
453  switch (this->dim())
454  {
455  case 1:
456  return fe<1>()->dof(idof);
457  break;
458  case 2:
459  return fe<2>()->dof(idof);
460  break;
461  case 3:
462  return fe<3>()->dof(idof);
463  break;
464  }
465 
466  ASSERT(0)(this->dim()).error("Unsupported FE dimension.");
467  // cannot be reached:
468  return fe<1>()->dof(idof);;
469 }
470 
471 
473  auto bgn_it = make_iter<DHCellSide>( DHCellSide(*this, 0) );
474  auto end_it = make_iter<DHCellSide>( DHCellSide(*this, dim()+1) );
475  return Range<DHCellSide>(bgn_it, end_it);
476 }
477 
478 
480  unsigned int upper_bound = this->elm()->n_neighs_vb();
481  auto bgn_it = make_iter<DHNeighbSide, DHCellSide>( DHNeighbSide(*this, 0, upper_bound) );
482  auto end_it = make_iter<DHNeighbSide, DHCellSide>( DHNeighbSide(*this, upper_bound, upper_bound) );
483  return RangeConvert<DHNeighbSide, DHCellSide>(bgn_it, end_it);
484 }
485 
486 
488  return RangeConvert<DHEdgeSide, DHCellSide>(make_iter<DHEdgeSide, DHCellSide>( DHEdgeSide( *this, 0) ),
489  make_iter<DHEdgeSide, DHCellSide>( DHEdgeSide( *this, n_edge_sides()) ));
490 }
491 
492 
493 inline unsigned int DHCellSide::n_edge_sides() const {
494  unsigned int edge_idx = dh_cell_accessor_.elm()->edge_idx(side_idx_);
495  Edge edg = dh_cell_accessor_.dof_handler_->mesh()->edge(edge_idx);
496  for (uint sid=0; sid<edg.n_sides(); sid++)
497  if ( dh_cell_accessor_.dof_handler_->el_is_local(edg.side(sid)->element().idx()) ) return edg.n_sides();
498  return 0;
499 }
500 
501 
502 
503 #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 elm_cache_index_
Optional member used in field evaluation, holds index of cell in field data cache.
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
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).
unsigned int element_cache_index() const
Getter of elm_cache_index_.
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:126
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:839
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.
void set_element_cache_index(unsigned int idx) const
Setter of elm_cache_index_.
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
virtual unsigned int n_elements(bool boundary=false) const
Returns count of boundary or bulk elements.
Definition: mesh.h:344
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:254
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:160
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.