Flow123d  release_1.8.2-1603-g0109a2b
ref_element.cc
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.cc
15  * @brief Class RefElement defines numbering of vertices, sides, calculation of normal vectors etc.
16  * @author Jan Stebel
17  */
18 
19 #include "system/global_defs.h"
20 #include "system/system.hh"
21 #include "mesh/ref_element.hh"
22 
23 using namespace arma;
24 using namespace std;
25 
26 template<> const unsigned int RefElement<1>::side_permutations[][n_nodes_per_side] = { { 0 } };
27 
28 template<> const unsigned int RefElement<2>::side_permutations[][n_nodes_per_side] = { { 0, 1 }, { 1, 0 } };
29 
30 template<> const unsigned int RefElement<3>::side_permutations[][n_nodes_per_side] = {
31  { 0, 1, 2 },
32  { 0, 2, 1 },
33  { 1, 0, 2 },
34  { 1, 2, 0 },
35  { 2, 0, 1 },
36  { 2, 1, 0 }
37 };
38 
39 
40 template<> const unsigned int RefElement<1>::side_nodes[][1] = {
41  { 0 },
42  { 1 }
43 };
44 
45 template<> const unsigned int RefElement<2>::side_nodes[][2] = {
46  { 0, 1},
47  { 0, 2},
48  { 1, 2}
49 };
50 
51 template<> const unsigned int RefElement<3>::side_nodes[][3] = {
52  {0,1,2},
53  {0,1,3},
54  {0,2,3},
55  {1,2,3}
56 };
57 
58 
59 
60 template<> const unsigned int RefElement<3>::side_lines[][3] = {
61  {0,1,2},
62  {0,3,4},
63  {1,3,5},
64  {2,4,5}
65 };
66 
67 
68 
69 template<> const unsigned int RefElement<3>::line_nodes[][2] = {
70  {0,1},
71  {0,2},
72  {1,2},
73  {0,3},
74  {1,3},
75  {2,3}
76 };
77 
78 
79 template<unsigned int dim>
80 vec::fixed<dim> RefElement<dim>::node_coords(unsigned int nid)
81 {
82  OLD_ASSERT(nid < n_nodes, "Vertex number is out of range!");
83 
84  vec::fixed<dim> p;
85  p.zeros();
86 
87  if (nid > 0)
88  p(nid-1) = 1;
89 
90  return p;
91 }
92 
93 
94 template<unsigned int dim>
95 vec::fixed<dim+1> RefElement<dim>::node_barycentric_coords(unsigned int nid)
96 {
97  OLD_ASSERT(nid < n_nodes, "Vertex number is out of range!");
98 
99  vec::fixed<dim+1> p;
100  p.zeros();
101 
102  if (nid == 0)
103  p(dim) = 1;
104  else
105  p(nid-1) = 1;
106 
107  return p;
108 }
109 
110 
111 template<>
112 vec::fixed<1> RefElement<1>::normal_vector(unsigned int sid)
113 {
114  OLD_ASSERT(sid < n_sides, "Side number is out of range!");
115 
116  return node_coords(sid) - node_coords(1-sid);
117 }
118 
119 template<>
120 vec::fixed<2> RefElement<2>::normal_vector(unsigned int sid)
121 {
122  OLD_ASSERT(sid < n_sides, "Side number is out of range!");
123  vec::fixed<2> barycenter, bar_side, n, t;
124 
125  // tangent vector along line
126  t = node_coords(side_nodes[sid][1]) - node_coords(side_nodes[sid][0]);
127  // barycenter coordinates
128  barycenter.fill(1./3);
129  // vector from barycenter to the side
130  bar_side = node_coords(side_nodes[sid][0]) - barycenter;
131  // normal vector to side (modulo sign)
132  n(0) = -t(1);
133  n(1) = t(0);
134  n /= norm(n,2);
135  // check sign of normal vector
136  if (dot(n,bar_side) < 0) n *= -1;
137 
138  return n;
139 }
140 
141 template<>
142 vec::fixed<3> RefElement<3>::normal_vector(unsigned int sid)
143 {
144  OLD_ASSERT(sid < n_sides, "Side number is out of range!");
145  vec::fixed<3> barycenter, bar_side, n, t1, t2;
146 
147  // tangent vectors of side
148  t1 = node_coords(side_nodes[sid][1]) - node_coords(side_nodes[sid][0]);
149  t2 = node_coords(side_nodes[sid][2]) - node_coords(side_nodes[sid][0]);
150  // baryucenter coordinates
151  barycenter.fill(0.25);
152  // vector from barycenter to the side
153  bar_side = node_coords(side_nodes[sid][0]) - barycenter;
154  // normal vector (modulo sign)
155  n = cross(t1,t2);
156  n /= norm(n,2);
157  // check sign of normal vector
158  if (dot(n,bar_side) < 0) n = -n;
159 
160  return n;
161 }
162 
163 
164 template<>
165 double RefElement<1>::side_measure(unsigned int sid)
166 {
167  OLD_ASSERT(sid < n_sides, "Side number is out of range!");
168 
169  return 1;
170 }
171 
172 
173 template<>
174 double RefElement<2>::side_measure(unsigned int sid)
175 {
176  OLD_ASSERT(sid < n_sides, "Side number is out of range!");
177 
178  return norm(node_coords(side_nodes[sid][1]) - node_coords(side_nodes[sid][0]),2);
179 }
180 
181 
182 template<>
183 double RefElement<3>::side_measure(unsigned int sid)
184 {
185  OLD_ASSERT(sid < n_sides, "Side number is out of range!");
186 
187  return 0.5*norm(cross(node_coords(side_nodes[sid][1]) - node_coords(side_nodes[sid][0]),
188  node_coords(side_nodes[sid][2]) - node_coords(side_nodes[sid][0])),2);
189 }
190 
191 
192 
193 template <>
194 unsigned int RefElement<3>::line_between_faces(unsigned int f1, unsigned int f2) {
195  unsigned int i,j;
196  i=j=0;
197  while (side_lines[f1][i] != side_lines[f2][j])
198  if (side_lines[f1][i] < side_lines[f2][j]) i++;
199  else j++;
200  return side_lines[f1][i];
201 }
202 
203 
204 
205 template<unsigned int dim>
206 unsigned int RefElement<dim>::permutation_index(unsigned int p[n_nodes_per_side])
207 {
208  unsigned int index;
209  for (index = 0; index < n_side_permutations; index++)
210  if (equal(p, p + n_nodes_per_side, side_permutations[index]))
211  return index;
212 
213  xprintf(PrgErr, "Side permutation not found.\n");
214 
215  // The following line is present in order to suppress compilers warning
216  // about missing return value.
217  return 0;
218 }
219 
220 
221 template class RefElement<1>;
222 template class RefElement<2>;
223 template class RefElement<3>;
224 
225 
226 
227 
static arma::vec::fixed< dim > normal_vector(unsigned int sid)
static arma::vec::fixed< dim > node_coords(unsigned int nid)
Definition: ref_element.cc:80
static unsigned int permutation_index(unsigned int p[n_nodes_per_side])
Definition: ref_element.cc:206
static unsigned int line_between_faces(unsigned int f1, unsigned int f2)
#define OLD_ASSERT(...)
Definition: global_defs.h:128
Global macros to enhance readability and debugging, general constants.
#define xprintf(...)
Definition: system.hh:87
static double side_measure(unsigned int sid)
Definition: system.hh:59
Class RefElement defines numbering of vertices, sides, calculation of normal vectors etc...
static arma::vec::fixed< dim+1 > node_barycentric_coords(unsigned int nid)
Definition: ref_element.cc:95