MFEM  v3.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 int Tetrahedron::NeedRefinement(DSTable &v_to_v, int *middle) const
126 {
127  int m;
128 
129  if ((m = v_to_v(indices[0], indices[1])) != -1)
130  if (middle[m] != -1) { return 1; }
131  if ((m = v_to_v(indices[1], indices[2])) != -1)
132  if (middle[m] != -1) { return 1; }
133  if ((m = v_to_v(indices[2], indices[0])) != -1)
134  if (middle[m] != -1) { return 1; }
135  if ((m = v_to_v(indices[0], indices[3])) != -1)
136  if (middle[m] != -1) { return 1; }
137  if ((m = v_to_v(indices[1], indices[3])) != -1)
138  if (middle[m] != -1) { return 1; }
139  if ((m = v_to_v(indices[2], indices[3])) != -1)
140  if (middle[m] != -1) { return 1; }
141  return 0;
142 }
143 
144 void Tetrahedron::SetVertices(const int *ind)
145 {
146  for (int i = 0; i < 4; i++)
147  {
148  indices[i] = ind[i];
149  }
150 }
151 
152 void Tetrahedron::MarkEdge(const DSTable &v_to_v, const int *length)
153 {
154  int ind[4], i, j, l, L, type;
155 
156  // determine the longest edge
157  L = length[v_to_v(indices[0], indices[1])]; j = 0;
158  if ((l = length[v_to_v(indices[1], indices[2])]) > L) { L = l; j = 1; }
159  if ((l = length[v_to_v(indices[2], indices[0])]) > L) { L = l; j = 2; }
160  if ((l = length[v_to_v(indices[0], indices[3])]) > L) { L = l; j = 3; }
161  if ((l = length[v_to_v(indices[1], indices[3])]) > L) { L = l; j = 4; }
162  if ((l = length[v_to_v(indices[2], indices[3])]) > L) { L = l; j = 5; }
163 
164  for (i = 0; i < 4; i++)
165  {
166  ind[i] = indices[i];
167  }
168 
169  switch (j)
170  {
171  case 1:
172  indices[0] = ind[1]; indices[1] = ind[2];
173  indices[2] = ind[0]; indices[3] = ind[3];
174  break;
175  case 2:
176  indices[0] = ind[2]; indices[1] = ind[0];
177  indices[2] = ind[1]; indices[3] = ind[3];
178  break;
179  case 3:
180  indices[0] = ind[3]; indices[1] = ind[0];
181  indices[2] = ind[2]; indices[3] = ind[1];
182  break;
183  case 4:
184  indices[0] = ind[1]; indices[1] = ind[3];
185  indices[2] = ind[2]; indices[3] = ind[0];
186  break;
187  case 5:
188  indices[0] = ind[2]; indices[1] = ind[3];
189  indices[2] = ind[0]; indices[3] = ind[1];
190  break;
191  }
192 
193  // Determine the two longest edges for the other two faces and
194  // store them in ind[0] and ind[1]
195  ind[0] = 2; ind[1] = 1;
196  L = length[v_to_v(indices[0], indices[2])];
197  if ((l = length[v_to_v(indices[0], indices[3])]) > L) { L = l; ind[0] = 3; }
198  if ((l = length[v_to_v(indices[2], indices[3])]) > L) { L = l; ind[0] = 5; }
199 
200  L = length[v_to_v(indices[1], indices[2])];
201  if ((l = length[v_to_v(indices[1], indices[3])]) > L) { L = l; ind[1] = 4; }
202  if ((l = length[v_to_v(indices[2], indices[3])]) > L) { L = l; ind[1] = 5; }
203 
204  j = 0;
205  switch (ind[0])
206  {
207  case 2:
208  switch (ind[1])
209  {
210  case 1: type = Tetrahedron::TYPE_PU; break;
211  case 4: type = Tetrahedron::TYPE_A; break;
212  case 5:
213  default: type = Tetrahedron::TYPE_M;
214  }
215  break;
216  case 3:
217  switch (ind[1])
218  {
219  case 1: type = Tetrahedron::TYPE_A; break;
220  case 4: type = Tetrahedron::TYPE_PU;
221  j = 1; ind[0] = 2; ind[1] = 1; break;
222  case 5:
223  default: type = Tetrahedron::TYPE_M;
224  j = 1; ind[0] = 5; ind[1] = 1;
225  }
226  break;
227  case 5:
228  default:
229  switch (ind[1])
230  {
231  case 1: type = Tetrahedron::TYPE_M; break;
232  case 4: type = Tetrahedron::TYPE_M;
233  j = 1; ind[0] = 2; ind[1] = 5; break;
234  case 5:
235  default: type = Tetrahedron::TYPE_O;
236  }
237  }
238 
239  if (j)
240  {
241  j = indices[0]; indices[0] = indices[1]; indices[1] = j;
242  j = indices[2]; indices[2] = indices[3]; indices[3] = j;
243  }
244 
245  CreateRefinementFlag(ind, type);
246 }
247 
248 // static method
249 void Tetrahedron::GetPointMatrix(unsigned transform, DenseMatrix &pm)
250 {
251  double *a = &pm(0,0), *b = &pm(0,1), *c = &pm(0,2), *d = &pm(0,3);
252 
253  // initialize to identity
254  a[0] = 0.0, a[1] = 0.0, a[2] = 0.0;
255  b[0] = 1.0, b[1] = 0.0, b[2] = 0.0;
256  c[0] = 0.0, c[1] = 1.0, c[2] = 0.0;
257  d[0] = 0.0, d[1] = 0.0, d[2] = 1.0;
258 
259  int chain[12], n = 0;
260  while (transform)
261  {
262  chain[n++] = (transform & 7) - 1;
263  transform >>= 3;
264  }
265 
266  /* The transformations and orientations here match the six cases in
267  Mesh::Bisection for tetrahedra. */
268  while (n)
269  {
270 #define ASGN(a, b) (a[0] = b[0], a[1] = b[1], a[2] = b[2])
271 #define SWAP(a, b) for (int i = 0; i < 3; i++) { std::swap(a[i], b[i]); }
272 #define AVG(a, b, c) for (int i = 0; i < 3; i++) { a[i] = (b[i]+c[i])*0.5; }
273 
274  double e[3];
275  AVG(e, a, b);
276  switch (chain[--n])
277  {
278  case 0: ASGN(b, c); ASGN(c, d); break;
279  case 1: ASGN(a, c); ASGN(c, d); break;
280  case 2: ASGN(b, a); ASGN(a, d); break;
281  case 3: ASGN(a, b); ASGN(b, d); break;
282  case 4: SWAP(a, c); ASGN(b, d); break;
283  case 5: SWAP(b, c); ASGN(a, d); break;
284  default:
285  MFEM_ABORT("Invalid transform.");
286  }
287  ASGN(d, e);
288  }
289 }
290 
292 {
293  v.SetSize(4);
294  for (int i = 0; i < 4; i++)
295  {
296  v[i] = indices[i];
297  }
298 }
299 
301 {
302 #ifdef MFEM_USE_MEMALLOC
303  Tetrahedron *tet = m->TetMemory.Alloc();
304 #else
305  Tetrahedron *tet = new Tetrahedron;
306 #endif
307  tet->SetVertices(indices);
308  tet->SetAttribute(attribute);
310  return tet;
311 }
312 
314 
315 }
Data type dense matrix using column-major storage.
Definition: densemat.hpp:22
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:654
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:23
void SetSize(int nsize)
Change logical size of the array, keep existing entries.
Definition: array.hpp:331
virtual void MarkEdge(DenseMatrix &pmat)
Mark the longest edge by assuming/changing the order of the vertices.
Definition: tetrahedron.hpp:71
Linear3DFiniteElement TetrahedronFE
virtual int * GetVertices()
Definition: tetrahedron.hpp:91
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
MemAlloc< Tetrahedron, 1024 > TetMemory
Definition: mesh.hpp:128
void SetRefinementFlag(int rf)
Definition: tetrahedron.hpp:62
void ParseRefinementFlag(int refinement_edges[2], int &type, int &flag)
Definition: tetrahedron.cpp:43
Abstract data type element.
Definition: element.hpp:27