Flow123d  JS_before_hm-915-gc632be9
accessors.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 accessors.hh
15  * @brief
16  */
17 
18 #ifndef ACCESSORS_HH_
19 #define ACCESSORS_HH_
20 
21 #include "mesh/bounding_box.hh"
22 #include "mesh/region.hh"
23 #include "mesh/elements.h"
24 #include "mesh/mesh.h"
25 #include "mesh/node_accessor.hh"
26 #include "mesh/ref_element.hh"
27 #include "la/distribution.hh"
28 #include "mesh/point.hh"
29 #include <vector>
30 #include <armadillo>
31 
32 
33 /**
34  * Due to circular dependence of return parameters in mesh accessors,
35  * and the intention to have all methods inlined,
36  * we gathered the accessors into a single file.
37  * This way, it is possible to implement it, see the simple test below.
38  *
39  * Do not include accessors_impl.hh file anywhere but at the end of this file!
40  *
41  * previous include loops:
42  * side -> boundary -> elemen accessor
43  * element accessor <-> side
44  * edge <-> side
45  * boundary -> edge
46  */
47 
48 // Compilable test of class loop dependence of return parameters.
49 // class A;
50 // class B;
51 
52 // class A{
53 // public:
54 // A()
55 // {};
56 
57 // B create_b();
58 // };
59 
60 // class B{
61 // public:
62 // B()
63 // {};
64 
65 // A create_a();
66 // };
67 
68 
69 // B A::create_b()
70 // { return B(); }
71 
72 // A B::create_a()
73 // { return A(); }
74 
75 
76 class Side;
77 class SiderIter;
78 class Edge;
79 class Boundary;
80 
81 /**
82  * Element accessor templated just by dimension of the embedding space, used by Fields.
83  * This should allow algorithms over elements where dimension of particular element is runtime parameter.
84  *
85  * This class suites as interface of Fields to the mesh elements, in particular this accessor knows directly
86  * the region, and also can be used as an accessor that works on the whole region if used by Fields that do not depend on
87  * particular elements as FieldConstant, FiledFormula, and FieldPython.
88  *
89  * TODO:
90  * - make this kind of accessor subclass of FieldCommonBase or at least move it into src/fields
91  * since it has functionality particular for Fields
92  *
93  * Ideas:
94  * need function to calculate intersection (object) of two ElementAccessors, but this definitely should be templated by
95  * dimension of the ref. element (or rather shape of ref. element), here we can have case dispatch
96  *
97  */
98 template <int spacedim>
99 class ElementAccessor {
100 public:
101  /// Default invalid accessor.
102  ElementAccessor();
103 
104  /// Regional accessor.
105  ElementAccessor(const Mesh *mesh, RegionIdx r_idx);
106 
107  /// Element accessor.
108  ElementAccessor(const Mesh *mesh, unsigned int idx);
109 
110  /// Incremental function of the Element iterator.
111  void inc();
112 
113  /// Return list of element vertices.
115 
116  /// Computes the measure of the element.
117  double measure() const;
118 
119  /** Computes the Jacobian of the element.
120  * J = det ( 1 1 1 1 )
121  * x1 x2 x3 x4
122  * y1 y2 y3 y4
123  * z1 z2 z3 z4
124  */
125  double tetrahedron_jacobian() const;
126 
127  /// Computes the barycenter.
128  arma::vec::fixed<spacedim> centre() const;
129 
130  /**
131  * Quality of the element based on the smooth and scale-invariant quality measures proposed in:
132  * J. R. Schewchuk: What is a Good Linear Element?
133  *
134  * We scale the measure so that is gives value 1 for regular elements. Line 1d elements
135  * have always quality 1.
136  */
137  double quality_measure_smooth(SideIter side) const;
138 
139  SideIter side(const unsigned int loc_index);
140 
141  const SideIter side(const unsigned int loc_index) const;
142 
143 
144 
145  bool is_regional() const {
146  return dim_ == undefined_dim_;
147  }
148 
149  bool is_elemental() const {
150  return ( is_valid() && ! is_regional() );
151  }
152 
153  bool is_valid() const {
154  return mesh_ != NULL;
155  }
156 
157  unsigned int dim() const
158  { return dim_; }
159 
160  const Element * element() const {
161  return &(mesh_->element_vec_[element_idx_]);
162  }
163 
164 
165  Region region() const
166  { return Region( r_idx_, mesh_->region_db()); }
167 
169  { return r_idx_; }
170 
171  /// We need this method after replacing Region by RegionIdx, and movinf RegionDB instance into particular mesh
172  //unsigned int region_id() const {
173  // return region().id();
174  //}
175 
176  bool is_boundary() const {
177  return boundary_;
178  }
179 
180  /// Return local idx of element in boundary / bulk part of element vector
181  unsigned int idx() const {
182  if (boundary_) return ( element_idx_ - mesh_->bulk_size_ );
183  else return element_idx_;
184  }
185 
186  /// Return global idx of element in full element vector
187  unsigned int mesh_idx() const {
188  return element_idx_;
189  }
190 
191  unsigned int index() const {
192  return (unsigned int)mesh_->find_elem_id(element_idx_);
193  }
194 
195  unsigned int proc() const {
197  }
198 
199 
200  NodeAccessor<3> node(unsigned int ni) const {
201  return mesh_->node( element()->node_idx(ni) );
202  }
203 
204  /**
205  * Return bounding box of the element.
206  * Simpler code, but need to check performance penelty.
207  */
209  return BoundingBox(this->vertex_list());
210  }
211 
212  bool operator==(const ElementAccessor<spacedim>& other) const {
213  return (element_idx_ == other.element_idx_);
214  }
215 
216  inline bool operator!=(const ElementAccessor<spacedim>& other) const {
217  return (element_idx_ != other.element_idx_);
218  }
219 
220  /**
221  * -> dereference operator
222  *
223  * Allow simplify calling of element() method. Example:
224  @code
225  ElementAccessor<3> elm_ac(mesh, index);
226  arma::vec centre;
227  centre = elm_ac.element()->node_idx(0); // full format of access to element
228  centre = elm_ac->node_idx(0); // short format with dereference operator
229  @endcode
230  */
231  const Element * operator ->() const {
232  return &(mesh_->element_vec_[element_idx_]);
233  }
234 
235 
236 private:
237  /**
238  * When dim_ == undefined_dim_ ; the value of element_idx_ is invalid.
239  * Is used for ElementAccessors for whole region
240  */
241  static const unsigned int undefined_dim_ = 100;
242 
243  /// Dimension of reference element.
244  unsigned int dim_;
245 
246  /// Pointer to the mesh owning the element.
247  const Mesh *mesh_;
248  /// True if the element is boundary
249  bool boundary_;
250 
251  /// Index into Mesh::element_vec_ array.
252  unsigned int element_idx_;
253 
254  /// Region index.
256 };
257 
258 
259 
260 
261 
262 //=============================================================================
263 // Edge class
264 //=============================================================================
265 class Edge
266 {
267 public:
268  /// Default invalid edge accessor constructor.
269  Edge();
270 
271  /// Valid edge accessor constructor.
272  Edge(const Mesh *mesh, unsigned int edge_idx);
273 
274  /// Gets side iterator of the @p i -th side.
275  SideIter side(const unsigned int i) const;
276 
277 
278 
279  bool is_valid() const
280  { return mesh_ != nullptr; }
281 
282  /// Returns edge global index.
283  unsigned int idx() const {
284  ASSERT_DBG(is_valid());
285  return edge_idx_;
286  }
287 
288  /// Incremental function of the Edge iterator.
289  void inc() {
290  ASSERT_DBG(is_valid()).error("Do not call inc() for invalid accessor!");
291  edge_idx_++;
292  }
293 
294  /// Comparison operator of the iterator.
295  bool operator==(const Edge& other) const{
296  return (edge_idx_ == other.edge_idx_);
297  }
298 
299  /// Returns number of sides aligned with the edge.
300  unsigned int n_sides() const
301  { return edge_data()->n_sides;}
302 
303 private:
304  /// Pointer to the mesh owning the node.
305  const Mesh *mesh_;
306  /// Index into Mesh::edges vector.
307  unsigned int edge_idx_;
308 
309  /// Getter for edge data from mesh.
310  const EdgeData* edge_data() const;
311 };
312 
313 
314 
315 
316 
317 //=============================================================================
318 // Boundary class
319 //=============================================================================
320 class Boundary
321 {
322 public:
323  Boundary();
324  Boundary(BoundaryData* boundary_data);
325 
326  Edge edge();
327  ElementAccessor<3> element_accessor();
328  Region region();
329  Element * element();
330 
331  bool is_valid() const {
332  return boundary_data_ != nullptr;
333  }
334 
335  Mesh* mesh() {
336  ASSERT_DBG(is_valid());
337  return boundary_data_->mesh_;
338  }
339 
341  ASSERT_DBG(is_valid());
342  return boundary_data_->edge_idx_;
343  }
344 
346  ASSERT_DBG(is_valid());
347  return boundary_data_->bc_ele_idx_;
348  }
349 
350 private:
352 };
353 
354 
355 
356 
357 
358 //=============================================================================
359 // Side class
360 //=============================================================================
361 class Side {
362 public:
363  /// Default invalid side accessor constructor.
364  Side();
365 
366  /// Valid edge accessor constructor.
367  Side(const Mesh * mesh, unsigned int elem_idx, unsigned int set_lnum);
368 
369  double measure() const; ///< Calculate metrics of the side
370  arma::vec3 centre() const; ///< Centre of side
371  arma::vec3 normal() const; ///< Vector of (generalized) normal
372  double diameter() const; ///< Calculate the side diameter.
373 
374  /// Returns dimension of the side, that is dimension of the element minus one.
375  unsigned int dim() const;
376 
377  /// Returns true for all sides either on boundary or connected to vb neigboring.
378  bool is_external() const;
379 
380  /// Returns true for side on the boundary.
381  bool is_boundary() const;
382 
383  /// Returns node for given local index @p i on the side.
384  NodeAccessor<3> node(unsigned int i) const;
385 
386  /// Returns iterator to the element of the side.
387  ElementAccessor<3> element() const;
388 
389  /// Returns global index of the edge connected to the side.
390  unsigned int edge_idx() const;
391 
392  /// Returns pointer to the edge connected to the side.
393  Edge edge() const;
394 
395  /**
396  * Returns boundary condition prescribed on the side.
397  * Fails on assert if side if not on boundary and no BC is prescribed.
398  */
399  Boundary cond() const;
400 
401  /// Returns global index of the prescribed boundary condition.
402  unsigned int cond_idx() const;
403 
404 
405 
406  /// Returns number of nodes of the side.
407  unsigned int n_nodes() const
408  { return dim()+1; }
409 
410  /// Returns pointer to the mesh.
411  const Mesh * mesh() const
412  { return this->mesh_; }
413 
414  /// Returns local index of the side on the element.
415  unsigned int side_idx() const
416  { return side_idx_; }
417 
418  /// Returns index of element in Mesh::element_vec_.
419  unsigned int elem_idx() const
420  { return elem_idx_; }
421 
422  /// Returns true if the side has assigned element.
423  bool is_valid() const
424  { return mesh_!= nullptr; }
425 
426  /// Iterate over local sides of the element.
427  void inc() {
428  ASSERT_DBG(is_valid()).error("Do not call inc() for invalid accessor!");
429  side_idx_++;
430  }
431 
432  bool operator==(const Side &other) const {
433  return (mesh_ == other.mesh_ ) && ( elem_idx_ == other.elem_idx_ )
434  && ( side_idx_ == other.side_idx_ );
435  }
436 
437  bool operator!=(const Side &other) const {
438  return !( *this == other);
439  }
440 
441  /// This is necessary by current DofHandler, should change this
442  //void *make_ptr() const;
443 private:
444 
445  arma::vec3 normal_point() const;
446  arma::vec3 normal_line() const;
447  arma::vec3 normal_triangle() const;
448 
449  // Topology of the mesh
450 
451  const Mesh * mesh_; ///< Pointer to Mesh to which belonged
452  unsigned int elem_idx_; ///< Index of element in Mesh::element_vec_
453  unsigned int side_idx_; ///< Local # of side in element (to remove it, we heve to remove calc_side_rhs)
454 
455 };
456 
457 
458 /*
459  * Iterator to a side.
460  */
461 class SideIter {
462 public:
464  {}
465 
467  : side_(side)
468  {}
469 
470  bool operator==(const SideIter &other) {
471  return (side_.mesh() == other.side_.mesh() ) && ( side_.elem_idx() == other.side_.elem_idx() )
472  && ( side_.side_idx() == other.side_.side_idx() );
473  }
474 
475 
476  bool operator!=(const SideIter &other) {
477  return !( *this == other);
478  }
479 
480  /// * dereference operator
481  const Side & operator *() const
482  { return side_; }
483 
484  /// -> dereference operator
485  const Side * operator ->() const
486  { return &side_; }
487 
488  /// prefix increment iterate only on local element
489  SideIter &operator ++ () {
490  side_.inc();
491  return (*this);
492  }
493 
494 private:
496 };
497 
498 
499 
500 #include "mesh/accessors_impl.hh"
501 
502 #endif /* ACCESSORS_HH_ */
unsigned int get_proc(unsigned int idx) const
get processor of the given index
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
Bounding box in 3d ambient space.
Definition: bounding_box.hh:54
vector< Element > element_vec_
Definition: mesh.h:510
void inc()
Incremental function of the Edge iterator.
Definition: accessors.hh:289
LongIdx * get_row_4_el() const
Definition: mesh.h:157
unsigned int uint
unsigned int dim_
Dimension of reference element.
Definition: accessors.hh:244
unsigned int side_idx() const
Returns local index of the side on the element.
Definition: accessors.hh:415
bool operator!=(const ElementAccessor< spacedim > &other) const
Definition: accessors.hh:216
unsigned int idx() const
Returns edge global index.
Definition: accessors.hh:283
uint edge_idx()
Definition: accessors.hh:340
bool is_boundary() const
We need this method after replacing Region by RegionIdx, and movinf RegionDB instance into particular...
Definition: accessors.hh:176
bool operator==(const ElementAccessor< spacedim > &other) const
Definition: accessors.hh:212
unsigned int mesh_idx() const
Return global idx of element in full element vector.
Definition: accessors.hh:187
const Mesh * mesh_
Pointer to the mesh owning the node.
Definition: accessors.hh:305
Definition: mesh.h:78
bool operator!=(const Side &other) const
Definition: accessors.hh:437
bool is_valid() const
Definition: accessors.hh:153
const Mesh * mesh_
Pointer to the mesh owning the element.
Definition: accessors.hh:247
uint bc_ele_idx()
Definition: accessors.hh:345
SideIter side(const unsigned int loc_index)
BoundaryData * boundary_data_
Definition: accessors.hh:351
const RegionDB & region_db() const
Definition: mesh.h:143
unsigned int element_idx_
Index into Mesh::element_vec_ array.
Definition: accessors.hh:252
bool operator==(const Side &other) const
Definition: accessors.hh:432
unsigned int proc() const
Definition: accessors.hh:195
NodeAccessor< 3 > node(unsigned int ni) const
Definition: accessors.hh:200
Side side_
Definition: accessors.hh:495
Mesh * mesh()
Definition: accessors.hh:335
UnitSI operator*(const UnitSI &a, const UnitSI &b)
Product of two units.
Definition: unit_si.cc:235
arma::vec::fixed< spacedim > centre() const
Computes the barycenter.
unsigned int elem_idx_
Index of element in Mesh::element_vec_.
Definition: accessors.hh:452
bool operator==(const Edge &other) const
Comparison operator of the iterator.
Definition: accessors.hh:295
static const unsigned int undefined_dim_
Definition: accessors.hh:241
double quality_measure_smooth(SideIter side) const
bool is_elemental() const
Definition: accessors.hh:149
const Mesh * mesh() const
Returns pointer to the mesh.
Definition: accessors.hh:411
int find_elem_id(unsigned int pos) const
Return element id (in GMSH file) of element of given position in element vector.
Definition: mesh.h:352
bool is_valid() const
Definition: accessors.hh:331
unsigned int index() const
Definition: accessors.hh:191
bool is_valid() const
Returns true if the side has assigned element.
Definition: accessors.hh:423
bool operator!=(const SideIter &other)
Definition: accessors.hh:476
void inc()
Incremental function of the Element iterator.
BoundingBox bounding_box() const
Definition: accessors.hh:208
double measure() const
Computes the measure of the element.
NodeAccessor< 3 > node(unsigned int idx) const
Create and return NodeAccessor to node of given idx.
Definition: mesh.cc:845
bool boundary_
True if the element is boundary.
Definition: accessors.hh:249
Distribution * get_el_ds() const
Definition: mesh.h:154
ElementAccessor()
Default invalid accessor.
Region region() const
Definition: accessors.hh:165
const Element * operator->() const
Definition: accessors.hh:231
unsigned int side_idx_
Local # of side in element (to remove it, we heve to remove calc_side_rhs)
Definition: accessors.hh:453
RegionIdx r_idx_
Region index.
Definition: accessors.hh:255
Support classes for parallel programing.
unsigned int edge_idx_
Index into Mesh::edges vector.
Definition: accessors.hh:307
vector< arma::vec3 > vertex_list() const
Return list of element vertices.
const Mesh * mesh_
Pointer to Mesh to which belonged.
Definition: accessors.hh:451
RegionIdx region_idx() const
Definition: accessors.hh:168
#define ASSERT_DBG(expr)
double tetrahedron_jacobian() const
Class RefElement defines numbering of vertices, sides, calculation of normal vectors etc...
unsigned int elem_idx() const
Returns index of element in Mesh::element_vec_.
Definition: accessors.hh:419
void inc()
Iterate over local sides of the element.
Definition: accessors.hh:427
bool operator==(const SideIter &other)
Definition: accessors.hh:470
unsigned int dim() const
Definition: accessors.hh:157
bool is_valid() const
Definition: accessors.hh:279
unsigned int idx() const
Return local idx of element in boundary / bulk part of element vector.
Definition: accessors.hh:181
unsigned int bulk_size_
Count of bulk elements.
Definition: mesh.h:516
unsigned int n_nodes() const
Returns number of nodes of the side.
Definition: accessors.hh:407
SideIter(const Side &side)
Definition: accessors.hh:466
bool is_regional() const
Definition: accessors.hh:145