MFEM  v3.3.2
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
tetrahedron.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
2 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
3 // reserved. See file COPYRIGHT for details.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability see http://mfem.org.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the GNU Lesser General Public License (as published by the Free
10 // Software Foundation) version 2.1 dated February 1999.
11 
12 // Implementation of class Tetrahedron
13 
14 #include "mesh_headers.hpp"
15 
16 namespace mfem
17 {
18 
19 Tetrahedron::Tetrahedron(const int *ind, int attr)
20  : Element(Geometry::TETRAHEDRON)
21 {
22  attribute = attr;
23  for (int i = 0; i < 4; i++)
24  {
25  indices[i] = ind[i];
26  }
27  refinement_flag = 0;
28  transform = 0;
29 }
30 
31 Tetrahedron::Tetrahedron(int ind1, int ind2, int ind3, int ind4, int attr)
32  : Element(Geometry::TETRAHEDRON)
33 {
34  attribute = attr;
35  indices[0] = ind1;
36  indices[1] = ind2;
37  indices[2] = ind3;
38  indices[3] = ind4;
39  refinement_flag = 0;
40  transform = 0;
41 }
42 
43 void Tetrahedron::ParseRefinementFlag(int refinement_edges[2], int &type,
44  int &flag)
45 {
46  int i, f = refinement_flag;
47 
48  MFEM_VERIFY(f != 0, "tetrahedron is not marked");
49 
50  for (i = 0; i < 2; i++)
51  {
52  refinement_edges[i] = f & 7;
53  f = f >> 3;
54  }
55  type = f & 7;
56  flag = (f >> 3);
57 }
58 
59 void Tetrahedron::CreateRefinementFlag(int refinement_edges[2], int type,
60  int flag)
61 {
62  // Check for correct type
63 #ifdef MFEM_DEBUG
64  int e1, e2;
65  e1 = refinement_edges[0];
66  e2 = refinement_edges[1];
67  // if (e1 > e2) e1 = e2, e2 = refinement_edges[0];
68  switch (type)
69  {
71  if (e1 == 2 && e2 == 1) { break; }
72  // if (e1 == 3 && e2 == 4) break;
73  mfem_error("Error in Tetrahedron::CreateRefinementFlag(...) #1");
74  break;
76  if (e1 == 3 && e2 == 1) { break; }
77  if (e1 == 2 && e2 == 4) { break; }
78  // if (flag == 0) // flag is assumed to be the generation
79  // if (e2 == 5)
80  // if (e1 >= 1 && e1 <= 5) break; // type is actually O or M
81  // // ==> ok for generation = 0
82  mfem_error("Error in Tetrahedron::CreateRefinementFlag(...) #2");
83  break;
85  if (flag > 0) // PF is ok only for generation > 0
86  {
87  if (e1 == 2 && e2 == 1) { break; }
88  // if (e1 == 3 && e2 == 4) break;
89  }
90  mfem_error("Error in Tetrahedron::CreateRefinementFlag(...) #3");
91  break;
93  if (flag == 0 && e1 == 5 && e2 == 5)
94  {
95  break;
96  }
97  mfem_error("Error in Tetrahedron::CreateRefinementFlag(...) #4");
98  break;
100  if (flag == 0)
101  {
102  if (e1 == 5 && e2 == 1) { break; }
103  if (e1 == 2 && e2 == 5) { break; }
104  }
105  mfem_error("Error in Tetrahedron::CreateRefinementFlag(...) #5");
106  break;
107  default:
108  mfem_error("Error in Tetrahedron::CreateRefinementFlag(...) #6");
109  break;
110  }
111 #endif
112 
113  refinement_flag = flag;
114  refinement_flag <<= 3;
115 
116  refinement_flag |= type;
117  refinement_flag <<= 3;
118 
119  refinement_flag |= refinement_edges[1];
120  refinement_flag <<= 3;
121 
122  refinement_flag |= refinement_edges[0];
123 }
124 
125 void Tetrahedron::GetMarkedFace(const int face, int *fv)
126 {
127  int re[2], type, flag, *tv = this->indices;
128  ParseRefinementFlag(re, type, flag);
129  switch (face)
130  {
131  case 0:
132  switch (re[1])
133  {
134  case 1: fv[0] = tv[1]; fv[1] = tv[2]; fv[2] = tv[3]; break;
135  case 4: fv[0] = tv[3]; fv[1] = tv[1]; fv[2] = tv[2]; break;
136  case 5: fv[0] = tv[2]; fv[1] = tv[3]; fv[2] = tv[1]; break;
137  }
138  break;
139  case 1:
140  switch (re[0])
141  {
142  case 2: fv[0] = tv[2]; fv[1] = tv[0]; fv[2] = tv[3]; break;
143  case 3: fv[0] = tv[0]; fv[1] = tv[3]; fv[2] = tv[2]; break;
144  case 5: fv[0] = tv[3]; fv[1] = tv[2]; fv[2] = tv[0]; break;
145  }
146  break;
147  case 2:
148  fv[0] = tv[0]; fv[1] = tv[1]; fv[2] = tv[3];
149  break;
150  case 3:
151  fv[0] = tv[1]; fv[1] = tv[0]; fv[2] = tv[2];
152  break;
153  }
154 }
155 
156 int Tetrahedron::NeedRefinement(DSTable &v_to_v, int *middle) const
157 {
158  int m;
159 
160  if ((m = v_to_v(indices[0], indices[1])) != -1)
161  if (middle[m] != -1) { return 1; }
162  if ((m = v_to_v(indices[1], indices[2])) != -1)
163  if (middle[m] != -1) { return 1; }
164  if ((m = v_to_v(indices[2], indices[0])) != -1)
165  if (middle[m] != -1) { return 1; }
166  if ((m = v_to_v(indices[0], indices[3])) != -1)
167  if (middle[m] != -1) { return 1; }
168  if ((m = v_to_v(indices[1], indices[3])) != -1)
169  if (middle[m] != -1) { return 1; }
170  if ((m = v_to_v(indices[2], indices[3])) != -1)
171  if (middle[m] != -1) { return 1; }
172  return 0;
173 }
174 
175 void Tetrahedron::SetVertices(const int *ind)
176 {
177  for (int i = 0; i < 4; i++)
178  {
179  indices[i] = ind[i];
180  }
181 }
182 
183 void Tetrahedron::MarkEdge(const DSTable &v_to_v, const int *length)
184 {
185  int ind[4], i, j, l, L, type;
186 
187  // determine the longest edge
188  L = length[v_to_v(indices[0], indices[1])]; j = 0;
189  if ((l = length[v_to_v(indices[1], indices[2])]) > L) { L = l; j = 1; }
190  if ((l = length[v_to_v(indices[2], indices[0])]) > L) { L = l; j = 2; }
191  if ((l = length[v_to_v(indices[0], indices[3])]) > L) { L = l; j = 3; }
192  if ((l = length[v_to_v(indices[1], indices[3])]) > L) { L = l; j = 4; }
193  if ((l = length[v_to_v(indices[2], indices[3])]) > L) { L = l; j = 5; }
194 
195  for (i = 0; i < 4; i++)
196  {
197  ind[i] = indices[i];
198  }
199 
200  switch (j)
201  {
202  case 1:
203  indices[0] = ind[1]; indices[1] = ind[2];
204  indices[2] = ind[0]; indices[3] = ind[3];
205  break;
206  case 2:
207  indices[0] = ind[2]; indices[1] = ind[0];
208  indices[2] = ind[1]; indices[3] = ind[3];
209  break;
210  case 3:
211  indices[0] = ind[3]; indices[1] = ind[0];
212  indices[2] = ind[2]; indices[3] = ind[1];
213  break;
214  case 4:
215  indices[0] = ind[1]; indices[1] = ind[3];
216  indices[2] = ind[2]; indices[3] = ind[0];
217  break;
218  case 5:
219  indices[0] = ind[2]; indices[1] = ind[3];
220  indices[2] = ind[0]; indices[3] = ind[1];
221  break;
222  }
223 
224  // Determine the two longest edges for the other two faces and
225  // store them in ind[0] and ind[1]
226  ind[0] = 2; ind[1] = 1;
227  L = length[v_to_v(indices[0], indices[2])];
228  if ((l = length[v_to_v(indices[0], indices[3])]) > L) { L = l; ind[0] = 3; }
229  if ((l = length[v_to_v(indices[2], indices[3])]) > L) { L = l; ind[0] = 5; }
230 
231  L = length[v_to_v(indices[1], indices[2])];
232  if ((l = length[v_to_v(indices[1], indices[3])]) > L) { L = l; ind[1] = 4; }
233  if ((l = length[v_to_v(indices[2], indices[3])]) > L) { L = l; ind[1] = 5; }
234 
235  j = 0;
236  switch (ind[0])
237  {
238  case 2:
239  switch (ind[1])
240  {
241  case 1: type = Tetrahedron::TYPE_PU; break;
242  case 4: type = Tetrahedron::TYPE_A; break;
243  case 5:
244  default: type = Tetrahedron::TYPE_M;
245  }
246  break;
247  case 3:
248  switch (ind[1])
249  {
250  case 1: type = Tetrahedron::TYPE_A; break;
251  case 4: type = Tetrahedron::TYPE_PU;
252  j = 1; ind[0] = 2; ind[1] = 1; break;
253  case 5:
254  default: type = Tetrahedron::TYPE_M;
255  j = 1; ind[0] = 5; ind[1] = 1;
256  }
257  break;
258  case 5:
259  default:
260  switch (ind[1])
261  {
262  case 1: type = Tetrahedron::TYPE_M; break;
263  case 4: type = Tetrahedron::TYPE_M;
264  j = 1; ind[0] = 2; ind[1] = 5; break;
265  case 5:
266  default: type = Tetrahedron::TYPE_O;
267  }
268  }
269 
270  if (j)
271  {
272  j = indices[0]; indices[0] = indices[1]; indices[1] = j;
273  j = indices[2]; indices[2] = indices[3]; indices[3] = j;
274  }
275 
276  CreateRefinementFlag(ind, type);
277 }
278 
279 // static method
280 void Tetrahedron::GetPointMatrix(unsigned transform, DenseMatrix &pm)
281 {
282  double *a = &pm(0,0), *b = &pm(0,1), *c = &pm(0,2), *d = &pm(0,3);
283 
284  // initialize to identity
285  a[0] = 0.0, a[1] = 0.0, a[2] = 0.0;
286  b[0] = 1.0, b[1] = 0.0, b[2] = 0.0;
287  c[0] = 0.0, c[1] = 1.0, c[2] = 0.0;
288  d[0] = 0.0, d[1] = 0.0, d[2] = 1.0;
289 
290  int chain[12], n = 0;
291  while (transform)
292  {
293  chain[n++] = (transform & 7) - 1;
294  transform >>= 3;
295  }
296 
297  /* The transformations and orientations here match the six cases in
298  Mesh::Bisection for tetrahedra. */
299  while (n)
300  {
301 #define ASGN(a, b) (a[0] = b[0], a[1] = b[1], a[2] = b[2])
302 #define SWAP(a, b) for (int i = 0; i < 3; i++) { std::swap(a[i], b[i]); }
303 #define AVG(a, b, c) for (int i = 0; i < 3; i++) { a[i] = (b[i]+c[i])*0.5; }
304 
305  double e[3];
306  AVG(e, a, b);
307  switch (chain[--n])
308  {
309  case 0: ASGN(b, c); ASGN(c, d); break;
310  case 1: ASGN(a, c); ASGN(c, d); break;
311  case 2: ASGN(b, a); ASGN(a, d); break;
312  case 3: ASGN(a, b); ASGN(b, d); break;
313  case 4: SWAP(a, c); ASGN(b, d); break;
314  case 5: SWAP(b, c); ASGN(a, d); break;
315  default:
316  MFEM_ABORT("Invalid transform.");
317  }
318  ASGN(d, e);
319  }
320 }
321 
323 {
324  v.SetSize(4);
325  for (int i = 0; i < 4; i++)
326  {
327  v[i] = indices[i];
328  }
329 }
330 
332 {
333 #ifdef MFEM_USE_MEMALLOC
334  Tetrahedron *tet = m->TetMemory.Alloc();
335 #else
336  Tetrahedron *tet = new Tetrahedron;
337 #endif
338  tet->SetVertices(indices);
339  tet->SetAttribute(attribute);
341  return tet;
342 }
343 
345 
346 }
Data type dense matrix using column-major storage.
Definition: densemat.hpp:23
virtual void SetVertices(const int *ind)
Set the vertices according to the given input.
virtual Element * Duplicate(Mesh *m) const
void CreateRefinementFlag(int refinement_edges[2], int type, int flag=0)
Definition: tetrahedron.cpp:59
Class for linear FE on tetrahedron.
Definition: fe.hpp:800
Data type tetrahedron element.
Definition: tetrahedron.hpp:22
int attribute
Element&#39;s attribute (specifying material property, etc).
Definition: element.hpp:32
void mfem_error(const char *msg)
Definition: error.cpp:107
void SetSize(int nsize)
Change logical size of the array, keep existing entries.
Definition: array.hpp:503
virtual void MarkEdge(DenseMatrix &pmat)
Mark the longest edge by assuming/changing the order of the vertices.
Definition: tetrahedron.hpp:73
Linear3DFiniteElement TetrahedronFE
virtual int * GetVertices()
Definition: tetrahedron.hpp:93
virtual int NeedRefinement(DSTable &v_to_v, int *middle) const
Return 1 if the element needs refinement in order to get conforming mesh.
static void GetPointMatrix(unsigned transform, DenseMatrix &pm)
Calculate point matrix corresponding to a chain of transformations.
void SetAttribute(const int attr)
Set element&#39;s attribute.
Definition: element.hpp:53
void GetMarkedFace(const int face, int *fv)
MemAlloc< Tetrahedron, 1024 > TetMemory
Definition: mesh.hpp:157
void SetRefinementFlag(int rf)
Definition: tetrahedron.hpp:64
void ParseRefinementFlag(int refinement_edges[2], int &type, int &flag)
Definition: tetrahedron.cpp:43
Abstract data type element.
Definition: element.hpp:27