Flow123d  DF_patch_fe_data_tables-dc76198
ref_element.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 ref_element.hh
15  * @brief Class RefElement defines numbering of vertices, sides, calculation of normal vectors etc.
16  * @author Jan Stebel
17  * @todo
18  *
19  * TODO: reconsider following whether it is actual...
20  * - design interface in such a way, that we can change numbering
21  * - design numbering and orientations on ref element that is consistent (orientation and numbering od 2d el. match sides of 3d),
22  * and possibly allows permute vertices of elements so that sides sharing an edge match numbering and orientation (we dos'nt need permute faces)
23  *
24  * Proposal(prefers combinatoric order) :
25  * 1D - orientation V0 -> V1
26  *
27  * 2D - edges: E0: V0 -> V1,
28  * E1: V0 -> V2
29  * E2: V1 -> V2
30  * This maximize number of edge orientations achievable by edge permutations
31  * edge numbering edge orientation( in original numbering)
32  * 0 1 2 + + +
33  * 0 2 1 - + +
34  * 1 0 2 + + -
35  * 1 2 0 - - +
36  * 2 0 1 + - -
37  * 2 1 0 - - -
38  *
39  * vertices edges normal (out = +)
40  * 3D - sides: S0: 0 1 2 E0 E1 E3 -
41  * S1: 0 1 3 E0 E2 E4 +
42  * S2: 0 2 3 E1 E2 E5 -
43  * S3: 1 2 3 E3 E4 E5 -
44  *
45  * edges: E0: V0 -> V1 x direction
46  * E1: V0 -> V2 y direction
47  * E2: V0 -> V3 z direction
48  * E3: V1 -> V2
49  * E4: V1 -> V3
50  * E5: V2 -> V3
51 
52  *
53  * - functions from DEAL.ii:
54  * bool is_inside_unit_cell( point )
55  * line_to_cell_vertices(line, vertex) vertex index on line to index on whole element
56  * face_to_cell_vertices(face, vertex, Orientation), Orientation should be some class describing permutation of shared face to element's face/side
57  * face_to_cel_lines
58  * standard_to_real_face_vertex(vertex, Orientation), maps vertex to permuted face
59  * real_to_standard_face_vertex - inverse
60  * ... same for line; we should need also something like standard_to_real_line_vertex; Deal dosn;t support Orientation changes for 2D element faces
61  * Point unit_cell_vertex(vertex) - coordinates
62  * project_to_unit_cell
63  * distance_to_unit_cell
64  * d_linear_shape_function
65  *
66  * - can not change numbering of element sides due to DarcyFlow, which use hardwired side numbering in construction of basis functions
67  * - any change of side numbering requires also change in flow/old_bcd.cc
68  *
69  *
70  */
71 
72 #ifndef REF_ELEMENT_HH_
73 #define REF_ELEMENT_HH_
74 
75 #include <vector> // for vector
76 #include <array>
77 #include <armadillo>
78 #include "system/armor.hh"
79 #include "system/asserts.hh"
80 #include <Eigen/Core>
81 #include <Eigen/Dense>
82 
83 template<class T> class ArenaVec;
84 
85 
86 /*
87  * Ordering of nodes and sides in reference elements
88  * =================================================
89  *
90  * TODO we want the following (22.10.):
91  *
92  * 1D element (line segment) 2D element (triangle) 3D element (tetrahedron)
93  *
94  * z
95  * .
96  * ,/
97  * /
98  * 3
99  * y ,/|`\
100  * ^ ,/ | `\
101  * | ,/ '. `\
102  * 2 ,/ | `\
103  * |`\ ,/ | `\
104  * | `\ 0-----------'.--------1 --> x
105  * | `\ `\. | ,/
106  * | `\ `\. | ,/
107  * | `\ `\. '. ,/
108  * 0----------1 --> x 0----------1 --> x `\. |/
109  * `2
110  * `\.
111  * `y
112  *
113  * side id node ids side id node ids side id node ids normal
114  * 0 0 0 0,1 0 0,1,2 OUT
115  * 1 1 1 0,2 1 0,1,3 IN
116  * 2 1,2 2 0,2,3 OUT
117  * 3 1,2,3 IN
118  *
119  *
120  * nodes coordinates:
121  * 0 [0] 0 [0,0] 0 [0,0,0]
122  * 1 [1] 1 [1,0] 1 [1,0,0]
123  * 2 [0,1] 2 [0,1,0]
124  * 3 [0,0,1]
125  *
126  * barycentric coordinates of nodes:
127  * 0 [1,0] 0 [1,0,0] 0 [1,0,0,0]
128  * 1 [0,1] 1 [0,1,0] 1 [0,1,0,0]
129  * 2 [0,0,1] 2 [0,0,1,0]
130  * 3 [0,0,0,1]
131  *
132  *
133  *
134  * Element node permutation for matching sides
135  *
136  * 1. 2D case: Can add mesh elements in "layers" so that at most toe edges are prescribed and one is free.
137  * possible cases, two edges A and B considered counter clockwise around a node:
138  * A out, B out : vertex 0 to node, regular orientation (normal up)
139  * A out, B in : vertex 1 to node, regular orientation
140  * A in , B out : vertex 1 to node, inverted orientation (normal down)
141  * A in , B in : vertex 2 to node regular orientation
142  *
143  * Result: can be matched using two element orientations, element inversion in 1/3 of cases
144  *
145  * 2. 3d elements around an oriented edge
146  * a. possible face configurations
147  * U: side 0 attached to the edge, positive; face vertices: 0 (edge 0), 1 (edge 1), 2
148  * V: side 1 attached to the edge, negative; face vertices: 0 (edge 0), 2 (edge 1), 1
149  * W: side 2 attached to the edge, positive; face vertices: 1 (edge 0), 2 (edge 1), 0
150  *
151  * b. faces of the element edges, configuration of faces attached to the element edge; edge pointing up, looking from outside position, face A on right, face B on left
152  * E0: A (side 0) in U, B (side 1) in U
153  * E1: A (side 2) in U, B (side 0) in V
154  * E2: A (side 1) in V, B (side 2) in V
155  * E3. A (side 0) in W, B (side 3) in U
156  * E4: A (side 3) in V, B (side 1) in W
157  * E5: A (side 2) in W, B (side 3) in W
158  * not presented combination:
159  * A in U, B in W = E3 inverted
160  * A in V, B in U = E1 inverted
161  * A in W, b in V = E4 inverted
162  *
163  * Result can permute element veritices to arrange elements around an edge, possibly element inversion in 1/3 of cases
164  *
165  * 3. 3d elements around a node, up to 3 given faces, one free face
166  * denote V0, V1, V2 vertices of the free face, V3 common vertex of given faces
167  * Denote edges of this element ABCDEF with +- orientation
168  * a. orientation of edges of the vertices
169  * V0: E0+ >V1, E1+ >V2, E2+ >V3 +++
170  * V1: E0- >V0, E3+ >V2, E4+ >V3 -++
171  * V2: E1- >V0, E3- >V1, E5+ >V3 --+
172  * V3: E2- >V0, E4- >V1, E5- >V2 ---
173  *
174 * vertices edges normal (out = +)
175  * 3D - sides: S0: 0 1 2 E0 E1 E3 -
176  * S1: 0 1 3 E0 E2 E4 +
177  * S2: 0 2 3 E1 E2 E5 -
178  * S3: 1 2 3 E3 E4 E5 -
179  *
180  * edges: A E0: V0 -> V1 x direction
181  * B E1: V0 -> V2 y direction
182  * C E2: V0 -> V3 z direction
183  * D E3: V1 -> V2
184  * E E4: V1 -> V3
185  * F E5: V2 -> V3
186 
187  CE -> A
188  EF -> D
189  FC -> B
190  *
191  * with edges DEF, other three edges ABC
192  * configuration given by orientation of edges ABC and possibly by orientation of edges DEF
193  * ABC orientation + down, - up; DEF orientation positive if match side 0, i.e. D (AB), E (AC), F (BC)
194  * faces denoted fD,fE,fF, their configurations considered with respect to the edges DEF respectively
195  * front face denoted: ff
196  * vertices V0, V1, V2 top vertices with edges D (V0V1) E (V0V2) F (V1V2); V3 bottom
197  * invalid = corner case, can not continue must either modify one of the faces, or introduce unmatching face
198  * impossible = combination of edges that can not happen
199  * edge cases arranged for the vertex 3
200  *
201  * CEF ABD face config: fD fE fF ff
202  * +++ +++ U U U
203  * +++ ++- U U U-
204  * +++ +-+ invalid
205  * +++ +-- U U U
206  * +++ -++ U U U
207  * +++ -+- invalid U U U-
208  * +++ --+
209  * +++ --- U U U
210  *
211  * ++- +++ impossible U U U
212  * ++- ++- impossible U U U-
213  * ++- +-+ impossible
214  * ++- +-- U U U
215  * ++- -++ impossible U U U
216  * ++- -+- impossible U U U-
217  * ++- --+ impossible
218  * ++- --- U U U
219 
220  * +-+ +++ impossible U U U
221  * +-+ ++- impossible U U U-
222  * +-+ +-+ impossible
223  * +-+ +-- U U U
224  * +-+ -++ impossible U U U
225  * +-+ -+- impossible U U U-
226  * +-+ --+ impossible
227  * +-+ --- U U U
228 
229  * +-- +++ impossible U U U
230  * +-- ++- impossible U U U-
231  * +-- +-+ impossible
232  * +-- +-- U U U
233  * +-- -++ impossible U U U
234  * +-- -+- impossible U U U-
235  * +-- --+ impossible
236  * +-- --- U U U
237 
238  * -++ +++ impossible U U U
239  * -++ ++- impossible U U U-
240  * -++ +-+ impossible
241  * -++ +-- U U U
242  * -++ -++ impossible U U U
243  * -++ -+- impossible U U U-
244  * -++ --+ impossible
245  * -++ --- U U U
246 
247  * -+- +++ impossible U U U
248  * -+- ++- impossible U U U-
249  * -+- +-+ impossible
250  * -+- +-- U U U
251  * -+- -++ impossible U U U
252  * -+- -+- impossible U U U-
253  * -+- --+ impossible
254  * -+- --- U U U
255 
256  * --+ +++ impossible U U U
257  * --+ ++- impossible U U U-
258  * --+ +-+ impossible
259  * --+ +-- U U U
260  * --+ -++ impossible U U U
261  * --+ -+- impossible U U U-
262  * --+ --+ impossible
263  * --+ --- U U U
264 
265  * --- +++ U U U
266  * --- ++- U U U-
267  * --- +-+ invalid
268  * --- +-- U U U
269  * --- -++ U U U
270  * --- -+- invalid U U U-
271  * --- --+
272  * --- --- U U U
273  *
274  *
275  *
276  */
277 
278 
279 template<std::size_t Size>
280 using IdxVector = std::array<unsigned int, Size>;
281 
282 
283 /** Auxilliary structure that is used to pass template arguments into interact function of RefElement:
284  * RefElement<dim>::interact( Interaction<OutDim,InDim>(i) )
285  *
286  * This enables automatic deduction of dimensional template arguments.
287  * @see @p RefElement<dim>::interact
288  */
289 template <unsigned int OutDim, unsigned int InDim>
290 struct Interaction {
291  Interaction(unsigned int i) : i_(i) {}
292  unsigned int i_;
293 };
294 
295 
296 
298 public:
299  // Order clockwise, faces opposite to the lines from node_lines.
300  // !! dependes on S3 inversion
301  static constexpr IdxVector<3> S3_node_sides [2][4]
302  = { { { 2, 1, 0 },
303  { 3, 0, 1 },
304  { 3, 2, 0 },
305  { 3, 1, 2 }},
306  { { 2, 0, 1 },
307  { 3, 1, 0 },
308  { 3, 0, 2 },
309  { 3, 2, 1 }}};
310 
311  // faces adjecent to given edge, first is the right face when looking form outside with the edge pointing up.
312  // !! dependes on S3 inversion
313  static constexpr IdxVector<2> S3_line_sides [2][6]
314  = { { {0,1},
315  {2,0},
316  {1,2},
317  {0,3},
318  {3,1},
319  {2,3}},
320  { {1,0},
321  {0,2},
322  {2,1},
323  {3,0},
324  {1,3},
325  {3,2}}};
326 
327  // Order clockwise looking over the vertex to center; smallest index first
328  // !! dependes on S3 inversion
329  static constexpr IdxVector<3> S3_node_lines [2][4]
330  = { { {0,1,2},
331  {0,4,3},
332  {1,3,5},
333  {2,5,4}},
334  { {0,2,1},
335  {0,3,4},
336  {1,5,3},
337  {2,4,5}}};
338 
339 };
340 
341 
342 template<unsigned int dim>
344 {
345 public:
346  typedef arma::vec::fixed<dim> LocalPoint;
347  /**
348  * Barycentric coordinates.
349  *
350  * e.g. coordinates (a,b,c) on triangle with vertices X, Y, Z
351  * represents a point: a*X+b*Y+c*Z
352  */
355 
356  //// For computing vectorized normal_vector
357  typedef Eigen::Array<double,Eigen::Dynamic,1> ArrayDbl;
358 
359  DECLARE_EXCEPTION( ExcInvalidPermutation, << "Side permutation not found.\n" );
360 
361  /**
362  * Return coordinates of given node.
363  * @see the class documentation @p RefElement
364  * @param nid Node number.
365  * NOTE: Implementation is dependent on current node and side numbering.
366  */
367  static LocalPoint node_coords(unsigned int nid);
368 
369  /**
370  * Compute normal vector to a given side.
371  * @param sid Side number.
372  */
373  static LocalPoint normal_vector(unsigned int sid);
374 
375 
376  /**
377  * Returns array of reference normal vectors
378  *
379  * @param loc_side_idx_vec Vector of local side idx
380  */
381  static Eigen::Matrix<ArenaVec<double>, dim, 1> normal_vector_array(ArenaVec<uint> loc_side_idx_vec);
382 
383 
384  /**
385  * If the given barycentric coordinate is in the ref. element, return unchanged.
386  * If the given barycentric coordinate is out of the ref. element,
387  * project it on the surface of the ref. element.
388  */
389  static BaryPoint clip(const BaryPoint &barycentric);
390 
391  /** Returns orientation of the normal of side @p sid. 0 -> OUT, 1 -> IN.
392  * NOTE: Implementation is dependent on current node and side numbering.
393  */
394  static unsigned int normal_orientation(unsigned int sid);
395 
396  static double side_measure(unsigned int sid);
397 
398  /**
399  * Returns index of the node that is oposite to side of given index @p sid.
400  * Note: It is dependent on current node and side numbering.
401  * @param sid Side number.
402  * NOTE: Implementation is dependent on current node and side numbering.
403  */
404  static unsigned int oposite_node(unsigned int sid);
405 
406  /**
407  * Return index of 1D line, shared by two faces @p f1 and @p f2 of the reference tetrahedron.
408  * Implemented only for @p dim == 3.
409  */
410  static unsigned int line_between_faces(unsigned int f1, unsigned int f2);
411 
412 
413  static const unsigned int n_sides = dim + 1; ///< Number of sides.
414  static const unsigned int n_nodes = dim + 1; ///< Number of nodes.
415  static const unsigned int n_nodes_per_side = dim; ///< Number of nodes on one side.
416  static const unsigned int n_lines_per_node = dim; ///< Number of lines with one common node.
417  static const unsigned int n_nodes_per_line = 2; ///< Number of nodes in one line.
418  static const unsigned int n_sides_per_line = 2; ///< Number of sides with one common line. @p dim == 3.
419  static const unsigned int n_sides_per_node = dim; ///< Number of sides with one common line.
420 
421  /// Number of lines on boundary of one side.
422  static const unsigned int n_lines_per_side = (unsigned int)((dim * (dim - 1)) / 2);//( dim == 3 ? 3 : 0);// Kombinační číslo dim nad dvěma
423 
424  /// Number of lines, i.e. @p object of dimension @p dim-2 on the boundary of the reference element.
425  static const unsigned int n_lines = (unsigned int)((dim * (dim + 1)) / 2); //( dim == 3 ? 6 : dim == 2 ? 3 : dim == 1 ? 1 : 0); součet posloupnosti
426 
427 
429 
430 
431  /** @brief Converts from local to barycentric coordinates.
432  * @param lp point in local coordinates (x,y)
433  * @return point in barycentric coordinates (1-x-y, x, y)
434  */
435  static BaryPoint local_to_bary(const LocalPoint& lp);
436 
437  /** @brief Converts from barycentric to local coordinates.
438  * @param bp point in barycentric coordinates
439  * @return point in local coordinates
440  */
441  static LocalPoint bary_to_local(const BaryPoint& bp);
442 
444 
445  /**
446  * Used in the clip method.
447  */
449 
450  /**
451  * For given barycentric coordinates on the ref element returns barycentric coordinates
452  * on the ref. element of given face. Assumes that the input point is on the face.
453  * Barycentric order: (complanatory, local_coords )
454  */
455  static FaceBaryPoint barycentric_on_face(const BaryPoint &barycentric, unsigned int i_face);
456 
457 
459  static CentersList centers_of_subelements(unsigned int sub_dim);
460 
461  /**
462  * Return (1) number of zeros and (2) positions of zeros in barycentric coordinates.
463  * @p tolerance serves for testing zero values of @p barycentric coordinates.
464  */
465  static std::pair<unsigned int, unsigned int> zeros_positions(const BaryPoint &barycentric,
466  double tolerance = std::numeric_limits<double>::epsilon()*2);
467 
468  /**
469  * According to positions of zeros in barycentric coordinates, it gives the index of subdim-simplex
470  * in the reference element. Number of zeros must be equal to (3-subdim).
471  * e.g.:
472  * if 1 zeros, return index of side (subdim 2)
473  * if 2 zeros, return index of edge (subdim 1)
474  * if 3 zeros, return index of vertex (subdim 0)
475  */
476  template<unsigned int subdim> static unsigned int topology_idx(unsigned int zeros_positions);
477 
478  /** Function returns number of subdim-simplices inside dim-simplex.
479  * The aim is covering all the n_**** members with a single function.
480  * TODO: think of generalization for n_****_per_**** members, like function @p interact:
481  * template<unsigned int subdimA, unsigned int subdimB> static unsigned int count();
482  */
483  template<unsigned int subdim> static unsigned int count();
484 
485  /**
486  * @param sid - index of a sub-simplex in a simplex
487  * return an array of barycentric coordinates on <dim> simplex from <subdim> simplex
488  * for example: simplex<3> - ABCD and its subsubsimplex<1> AD (line index: 3)
489  * AD has barycoords for A (1,0), for D (0,1), but A in ABCD is (1,0,0,0) and D is (0,0,0,1)
490  * this method creates array ((1,0,0,0),(0,0,0,1))
491  */
492  template<unsigned int subdim> static arma::mat::fixed<dim+1,subdim+1> bary_coords(unsigned int sid);
493 
494  /** Interpolate barycentric coords to a higher dimension of a simplex.
495  * @param coord - barycentric coords of a point on a sub-simplex
496  * @param sub_simplex_idx - id of sub-simplex on a simplex
497  */
498  template<unsigned int subdim> static BaryPoint interpolate(arma::vec::fixed<subdim+1> coord, int sub_simplex_idx);
499 
500 
501  /**
502  * Basic line interpolation.
503  */
505  BaryPoint second_coords,
506  double first_theta, double second_theta, double theta);
507 
508  /**
509  * Usage:
510  * RefElement<3>::interact(Interaction<2,0>(1))
511  * (means: In tetrahedron <3>, give indices of sides <2>, connected by node <0> with index 1)
512  * RefElement<3>::interact(Interaction<2,0>(1))[1]
513  * (as above, but give only the side with index 1)
514  *
515  * Template usage: RefElement<dim>::interact(Interaction<OutDim, InDim>(i))[j]
516  * (means: on dim-dimensional reference element, go on InDim-dimensional subelement with index i,
517  * which connects OutDim-dimnesional subelements and select the one with index j)
518  *
519  * This method serves as an interface to topology information of the reference element.
520  * It returns indices of OutDim-dimensional object
521  * of InDim-dimnesional object of given index
522  * in dim-dimnesional reference element.
523  * @tparam interaction - auxilliary object carying the index and the template arguments OutDim and InDim
524  * @tparam OutDim - output dimension (give me node-0, line-1, side-2), <= dim
525  * @tparam InDim - input dimension (for node-0, line-1, side-2), <= dim
526  * @return vector of indices of OutDim-dimensional subelements represented by @p IdxVector object.
527  *
528  * possible calls:
529  * dim OutDim InDim return
530  * 1,2,3 0 1 InDim+1 - give me indices of nodes of line of given index
531  * 3 0 2 InDim+1 - give me indices of nodes of a side (triangle) of given index
532  * 3 1 2 InDim+1 - give me indices of lines of side (triangle) of given index
533  *
534  * 1,2,3 1 0 dim-InDim - give me indices of lines with common node of given index
535  * 3 2 0 dim-InDim - give me indices of sides (triangles) with common node of given index
536  * 3 2 1 dim-InDim - give me indices of sides (triangles) with common line of given index
537  *
538  */
539  template < template <unsigned int OutDim, unsigned int InDim> class TInteraction, unsigned int OutDim, unsigned int InDim>
540  static const IdxVector< (InDim>OutDim ? InDim+1 : dim-InDim) > interact( TInteraction<OutDim,InDim> interaction, bool inv = false );
541 
542 
543 private:
544  /// Internal part of the interact function.
545  template<unsigned int OutDim, unsigned int InDim>
546  static const IdxVector< (InDim>OutDim ? InDim+1 : dim-InDim) > interact_(unsigned int index, bool inv = false);
547 
548  static const std::vector<IdxVector<n_nodes_per_line>> line_nodes_; ///< [n_lines] For given line, returns its nodes indices.
549  static const std::vector<IdxVector<n_lines_per_node>> node_lines_; ///< [n_nodes] For given node, returns lines indices.
550  static const std::vector<IdxVector<n_nodes_per_side>> side_nodes_; ///< [n_sides] For given side, returns nodes indices. For @p dim == 3.
551  static const std::vector<IdxVector<n_sides_per_node>> node_sides_; ///< [n_nodes] For given node, returns sides indices. For @p dim == 3.
552  static const std::vector<IdxVector<n_sides_per_line>> line_sides_; ///< [n_lines] For given line, returns sides indices. For @p dim == 3.
553  static const std::vector<IdxVector<n_lines_per_side>> side_lines_; ///< [n_sides] For given side, returns lines indices. For @p dim == 3.
554 
555  //TODO: implement for 1d and 2d
556  /**
557  * Consider an n-face (node, edge, face, bulk) with dimension `subdim` and
558  * index within subdimension `idx`. Barycentric coordinates of all points
559  * on the n-face have unique pattern of zero coordinates.
560  *
561  * topology_zeros_[subdim][idx] is a bitfield with '1' where the pattern have zeros.
562  */
563  static const IdxVector<(n_lines > n_nodes) ? n_lines : n_nodes> topology_zeros_[dim+1];
564 };
565 
566 
567 // Declarations of explicit specialization of static memebers.
568 
573 
574 
580 
586 
587 
592 
593 
594 
595 
596 
597 
598 // 0: nodes of nodes
599 // 1: nodes of lines
600 // 2: nodes of sides
601 // 3: nodes of tetrahedron
606 
607 
608 
609 
610 
611 
612 
613 
614 
615 /************************* template implementation ****************************/
616 
617 template<unsigned int dim>
618 template<unsigned int subdim> inline
619 arma::mat::fixed<dim+1,subdim+1> RefElement<dim>::bary_coords(unsigned int sid){
620  ASSERT_LT(subdim, dim).error("Dimension mismatch!");
621  arma::mat::fixed<dim+1,subdim+1> bary_c;
622 
623  for(unsigned int i = 0; i < subdim+1; i++){
624  unsigned int nid = interact_<0,subdim>(sid)[i];
625  bary_c.col(i).zeros();
626  bary_c.col(i)(nid) = 1;
627  }
628 
629  return bary_c;
630 }
631 
632 
633 template<unsigned int dim> inline
634 arma::vec::fixed<dim> RefElement<dim>::node_coords(unsigned int nid)
635 {
636  ASSERT_LT(nid, n_nodes).error("Node number is out of range!");
637 
638  arma::vec::fixed<dim> p;
639  p.zeros();
640 
641  if (nid > 0)
642  p(nid-1) = 1;
643 
644  return p;
645 }
646 
647 
648 template<unsigned int dim>
649 template<unsigned int subdim>
650 auto RefElement<dim>::interpolate(arma::vec::fixed<subdim+1> coord, int sub_simplex_idx) -> BaryPoint
651 {
652  return RefElement<dim>::bary_coords<subdim>(sub_simplex_idx)*coord;
653 }
654 
655 
656 template<> template<> inline unsigned int RefElement<3>::count<0>()
657 { return n_nodes; }
658 template<> template<> inline unsigned int RefElement<3>::count<1>()
659 { return n_lines; }
660 template<> template<> inline unsigned int RefElement<3>::count<2>()
661 { return n_sides; }
662 template<> template<> inline unsigned int RefElement<3>::count<3>()
663 { return 1; }
664 template<> template<> inline unsigned int RefElement<2>::count<0>()
665 { return n_nodes; }
666 template<> template<> inline unsigned int RefElement<2>::count<1>()
667 { return n_lines; }
668 template<> template<> inline unsigned int RefElement<2>::count<2>()
669 { return 1; }
670 template<> template<> inline unsigned int RefElement<2>::count<3>()
671 { return 0; }
672 template<> template<> inline unsigned int RefElement<1>::count<0>()
673 { return n_nodes; }
674 template<> template<> inline unsigned int RefElement<1>::count<1>()
675 { return 1; }
676 template<> template<> inline unsigned int RefElement<1>::count<2>()
677 { return 0; }
678 template<> template<> inline unsigned int RefElement<1>::count<3>()
679 { return 0; }
680 template<> template<> inline unsigned int RefElement<0>::count<0>()
681 { return 1; }
682 template<> template<> inline unsigned int RefElement<0>::count<1>()
683 { return 0; }
684 template<> template<> inline unsigned int RefElement<0>::count<2>()
685 { return 0; }
686 template<> template<> inline unsigned int RefElement<0>::count<3>()
687 { return 0; }
688 
689 template<unsigned int dim>
690 template<unsigned int subdim>
691 unsigned int RefElement<dim>::topology_idx(unsigned int zeros_positions)
692 {
693  for(unsigned int i=0; i < RefElement<dim>::count<subdim>(); i++){
694  if(zeros_positions == topology_zeros_[subdim][i]) return i;
695  }
696  ASSERT_PERMANENT(0).error("Undefined zero pattern.");
697  return -1;
698 }
699 
700 
701 /// This function is for "side_nodes" - for given side, give me nodes (0->0, 1->1).
702 template<> template<> inline const IdxVector<1> RefElement<1>::interact_<0,0>(unsigned int i, bool inv)
703 { ASSERT_LT(i, RefElement<1>::n_nodes)(inv).error("Index out of bounds.");
704  return IdxVector<1>({i});}
705 
706 /// For line i {0}, give me indices of its nodes.
707 template<> template<> inline const IdxVector<2> RefElement<1>::interact_<0,1>(unsigned int i, bool inv)
708 { ASSERT_LT(i, RefElement<1>::n_lines)(inv).error("Index out of bounds.");
709  return line_nodes_[i];}
710 
711 /// For line i {0,1,2}, give me indices of its nodes.
712 template<> template<> inline const IdxVector<2> RefElement<2>::interact_<0,1>(unsigned int i, bool inv)
713 { ASSERT_LT(i, RefElement<2>::n_lines)(inv).error("Index out of bounds.");
714  return line_nodes_[i];}
715 
716 /// For line i {0,1,2,3,4,5}, give me indices of its nodes.
717 template<> template<> inline const IdxVector<2> RefElement<3>::interact_<0,1>(unsigned int i, bool inv)
718 { ASSERT_LT(i, RefElement<3>::n_lines)(inv).error("Index out of bounds.");
719  return line_nodes_[i];}
720 
721 /// For node i {0,1}, give me indices of lines.
722 template<> template<> inline const IdxVector<1> RefElement<1>::interact_<1,0>(unsigned int i, bool inv)
723 { ASSERT_LT(i, RefElement<1>::n_nodes)(inv).error("Index out of bounds.");
724  return node_lines_[i];}
725 
726 /// For node i {0,1,2}, give me indices of lines.
727 template<> template<> inline const IdxVector<2> RefElement<2>::interact_<1,0>(unsigned int i, bool inv)
728 { ASSERT_LT(i, RefElement<2>::n_nodes)(inv).error("Index out of bounds.");
729  return node_lines_[i];}
730 
731 /// For node i {0,1,2,3}, give me indices of lines.
732 template<> template<> inline const IdxVector<3> RefElement<3>::interact_<1,0>(unsigned int i, bool inv)
733 { ASSERT_LT(i, RefElement<3>::n_nodes).error("Index out of bounds.");
734  return _AuxInteract::S3_node_lines[inv][i];}
735 
736 /// For side i {0,1,2}, give me indices of its nodes.
737 template<> template<> inline const IdxVector<3> RefElement<3>::interact_<0,2>(unsigned int i, bool inv)
738 { ASSERT_LT(i, RefElement<3>::n_sides)(inv).error("Index out of bounds.");
739  return side_nodes_[i];}
740 
741 /// For node i {0,1,2,3}, give me indices of sides.
742 template<> template<> inline const IdxVector<3> RefElement<3>::interact_<2,0>(unsigned int i, bool inv)
743 { ASSERT_LT(i, RefElement<3>::n_sides).error("Index out of bounds.");
744  return _AuxInteract::S3_node_sides[inv][i];}
745 
746 /// For line i {0,1,2,3}, give me indices of sides.
747 template<> template<> inline const IdxVector<2> RefElement<3>::interact_<2,1>(unsigned int i, bool inv)
748 { ASSERT_LT(i, RefElement<3>::n_lines).error("Index out of bounds.");
749  return _AuxInteract::S3_line_sides[inv][i];}
750 
751 /// For side i {0,1,2}, give me indices of its lines.
752 template<> template<> inline const IdxVector<3> RefElement<3>::interact_<1,2>(unsigned int i, bool inv)
753 { ASSERT_LT(i, RefElement<3>::n_sides)(inv).error("Index out of bounds.");
754  return side_lines_[i];}
755 
756 template<unsigned int dim> template<unsigned int OutDim, unsigned int InDim>
757 inline const IdxVector< (InDim>OutDim ? InDim+1 : dim-InDim) > RefElement<dim>::interact_(unsigned int i, bool inv)
758 {
759  ASSERT_PERMANENT(false)(dim)(OutDim)(InDim)(i)(inv).error("Not implemented.");
760  //ASSERT_LT(OutDim, dim);
761  //ASSERT_LT(InDim, dim);
762  return IdxVector< (InDim>OutDim ? InDim+1 : dim-InDim) >(); // just to avoid warning for missing return
763 }
764 
765 
766 template<unsigned int dim>
767 template < template <unsigned int OutDim, unsigned int InDim> class TInteraction, unsigned int OutDim, unsigned int InDim>
768 inline const IdxVector< (InDim>OutDim ? InDim+1 : dim-InDim) > RefElement<dim>::interact( TInteraction<OutDim,InDim> interaction , bool inv)
769 {
770  return interact_<OutDim,InDim>(interaction.i_, inv);
771 }
772 
773 #endif /* REF_ELEMENT_HH_ */
Definitions of ASSERTS.
#define ASSERT_PERMANENT(expr)
Allow use shorter versions of macro names if these names is not used with external library.
Definition: asserts.hh:348
#define ASSERT_LT(a, b)
Definition of comparative assert macro (Less Than) only for debug mode.
Definition: asserts.hh:301
static const std::vector< IdxVector< n_lines_per_side > > side_lines_
[n_sides] For given side, returns lines indices. For dim == 3.
Definition: ref_element.hh:553
static CentersList centers_of_subelements(unsigned int sub_dim)
Definition: ref_element.cc:393
static const std::vector< IdxVector< n_nodes_per_line > > line_nodes_
[n_lines] For given line, returns its nodes indices.
Definition: ref_element.hh:548
static LocalPoint bary_to_local(const BaryPoint &bp)
Converts from barycentric to local coordinates.
Definition: ref_element.cc:202
static unsigned int normal_orientation(unsigned int sid)
Definition: ref_element.cc:217
static const unsigned int n_lines_per_node
Number of lines with one common node.
Definition: ref_element.hh:416
Armor::ArmaVec< double, dim > FaceBaryPoint
Definition: ref_element.hh:354
Armor::ArmaVec< double, dim+1 > BaryPoint
Definition: ref_element.hh:353
static FaceBaryPoint barycentric_on_face(const BaryPoint &barycentric, unsigned int i_face)
Definition: ref_element.cc:306
const std::vector< LocalPoint > & CentersList
Definition: ref_element.hh:458
std::vector< BaryPoint > BarycentricUnitVec
Definition: ref_element.hh:443
static BaryPoint line_barycentric_interpolation(BaryPoint first_coords, BaryPoint second_coords, double first_theta, double second_theta, double theta)
Definition: ref_element.cc:464
static const unsigned int n_sides
Number of sides.
Definition: ref_element.hh:413
static const std::vector< IdxVector< n_sides_per_line > > line_sides_
[n_lines] For given line, returns sides indices. For dim == 3.
Definition: ref_element.hh:552
static const IdxVector<(n_lines > n_nodes) ? n_lines :n_nodes > topology_zeros_[dim+1]
Definition: ref_element.hh:563
Eigen::Array< double, Eigen::Dynamic, 1 > ArrayDbl
Definition: ref_element.hh:357
static const std::vector< IdxVector< n_lines_per_node > > node_lines_
[n_nodes] For given node, returns lines indices.
Definition: ref_element.hh:549
arma::vec::fixed< dim > LocalPoint
Definition: ref_element.hh:346
static BaryPoint local_to_bary(const LocalPoint &lp)
Converts from local to barycentric coordinates.
Definition: ref_element.cc:188
static const unsigned int n_lines_per_side
Number of lines on boundary of one side.
Definition: ref_element.hh:422
static BarycentricUnitVec make_bary_unit_vec()
Definition: ref_element.cc:345
static std::pair< unsigned int, unsigned int > zeros_positions(const BaryPoint &barycentric, double tolerance=std::numeric_limits< double >::epsilon() *2)
Definition: ref_element.cc:321
static const unsigned int n_nodes
Number of nodes.
Definition: ref_element.hh:414
DECLARE_EXCEPTION(ExcInvalidPermutation,<< "Side permutation not found.\n")
static const unsigned int n_nodes_per_side
Number of nodes on one side.
Definition: ref_element.hh:415
static const IdxVector<(InDim >OutDim ? InDim+1 :dim-InDim) > interact_(unsigned int index, bool inv=false)
Internal part of the interact function.
static arma::mat::fixed< dim+1, subdim+1 > bary_coords(unsigned int sid)
Definition: ref_element.hh:619
static const unsigned int n_sides_per_node
Number of sides with one common line.
Definition: ref_element.hh:419
static const unsigned int n_nodes_per_line
Number of nodes in one line.
Definition: ref_element.hh:417
static unsigned int line_between_faces(unsigned int f1, unsigned int f2)
static unsigned int topology_idx(unsigned int zeros_positions)
Definition: ref_element.hh:691
static const std::vector< IdxVector< n_sides_per_node > > node_sides_
[n_nodes] For given node, returns sides indices. For dim == 3.
Definition: ref_element.hh:551
static const unsigned int n_sides_per_line
Number of sides with one common line. dim == 3.
Definition: ref_element.hh:418
static BaryPoint interpolate(arma::vec::fixed< subdim+1 > coord, int sub_simplex_idx)
static LocalPoint node_coords(unsigned int nid)
Definition: ref_element.hh:634
static BaryPoint clip(const BaryPoint &barycentric)
Definition: ref_element.cc:359
static double side_measure(unsigned int sid)
static const unsigned int n_lines
Number of lines, i.e. object of dimension dim-2 on the boundary of the reference element.
Definition: ref_element.hh:425
static unsigned int count()
static LocalPoint normal_vector(unsigned int sid)
static const IdxVector<(InDim >OutDim ? InDim+1 :dim-InDim) > interact(TInteraction< OutDim, InDim > interaction, bool inv=false)
static unsigned int oposite_node(unsigned int sid)
Definition: ref_element.cc:210
static const std::vector< std::vector< std::vector< unsigned int > > > nodes_of_subelements
Definition: ref_element.hh:428
static Eigen::Matrix< ArenaVec< double >, dim, 1 > normal_vector_array(ArenaVec< uint > loc_side_idx_vec)
Definition: ref_element.cc:280
static const std::vector< IdxVector< n_nodes_per_side > > side_nodes_
[n_sides] For given side, returns nodes indices. For dim == 3.
Definition: ref_element.hh:550
static constexpr IdxVector< 3 > S3_node_sides[2][4]
Definition: ref_element.hh:302
static constexpr IdxVector< 3 > S3_node_lines[2][4]
Definition: ref_element.hh:330
static constexpr IdxVector< 2 > S3_line_sides[2][6]
Definition: ref_element.hh:314
typename arma::Col< Type >::template fixed< nr > ArmaVec
Definition: armor.hh:505
std::array< unsigned int, Size > IdxVector
Definition: ref_element.hh:280
Interaction(unsigned int i)
Definition: ref_element.hh:291
unsigned int i_
Definition: ref_element.hh:292