MFEM  v4.0
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::Init(int ind1, int ind2, int ind3, int ind4, int attr)
44 {
45  attribute = attr;
46  indices[0] = ind1;
47  indices[1] = ind2;
48  indices[2] = ind3;
49  indices[3] = ind4;
50 }
51 
52 void Tetrahedron::ParseRefinementFlag(int refinement_edges[2], int &type,
53  int &flag)
54 {
55  int i, f = refinement_flag;
56 
57  MFEM_VERIFY(f != 0, "tetrahedron is not marked");
58 
59  for (i = 0; i < 2; i++)
60  {
61  refinement_edges[i] = f & 7;
62  f = f >> 3;
63  }
64  type = f & 7;
65  flag = (f >> 3);
66 }
67 
68 void Tetrahedron::CreateRefinementFlag(int refinement_edges[2], int type,
69  int flag)
70 {
71  // Check for correct type
72 #ifdef MFEM_DEBUG
73  int e1, e2;
74  e1 = refinement_edges[0];
75  e2 = refinement_edges[1];
76  // if (e1 > e2) e1 = e2, e2 = refinement_edges[0];
77  switch (type)
78  {
80  if (e1 == 2 && e2 == 1) { break; }
81  // if (e1 == 3 && e2 == 4) break;
82  mfem_error("Error in Tetrahedron::CreateRefinementFlag(...) #1");
83  break;
85  if (e1 == 3 && e2 == 1) { break; }
86  if (e1 == 2 && e2 == 4) { break; }
87  // if (flag == 0) // flag is assumed to be the generation
88  // if (e2 == 5)
89  // if (e1 >= 1 && e1 <= 5) break; // type is actually O or M
90  // // ==> ok for generation = 0
91  mfem_error("Error in Tetrahedron::CreateRefinementFlag(...) #2");
92  break;
94  if (flag > 0) // PF is ok only for generation > 0
95  {
96  if (e1 == 2 && e2 == 1) { break; }
97  // if (e1 == 3 && e2 == 4) break;
98  }
99  mfem_error("Error in Tetrahedron::CreateRefinementFlag(...) #3");
100  break;
101  case Tetrahedron::TYPE_O:
102  if (flag == 0 && e1 == 5 && e2 == 5)
103  {
104  break;
105  }
106  mfem_error("Error in Tetrahedron::CreateRefinementFlag(...) #4");
107  break;
108  case Tetrahedron::TYPE_M:
109  if (flag == 0)
110  {
111  if (e1 == 5 && e2 == 1) { break; }
112  if (e1 == 2 && e2 == 5) { break; }
113  }
114  mfem_error("Error in Tetrahedron::CreateRefinementFlag(...) #5");
115  break;
116  default:
117  mfem_error("Error in Tetrahedron::CreateRefinementFlag(...) #6");
118  break;
119  }
120 #endif
121 
122  refinement_flag = flag;
123  refinement_flag <<= 3;
124 
125  refinement_flag |= type;
126  refinement_flag <<= 3;
127 
128  refinement_flag |= refinement_edges[1];
129  refinement_flag <<= 3;
130 
131  refinement_flag |= refinement_edges[0];
132 }
133 
134 void Tetrahedron::GetMarkedFace(const int face, int *fv)
135 {
136  int re[2], type, flag, *tv = this->indices;
137  ParseRefinementFlag(re, type, flag);
138  switch (face)
139  {
140  case 0:
141  switch (re[1])
142  {
143  case 1: fv[0] = tv[1]; fv[1] = tv[2]; fv[2] = tv[3]; break;
144  case 4: fv[0] = tv[3]; fv[1] = tv[1]; fv[2] = tv[2]; break;
145  case 5: fv[0] = tv[2]; fv[1] = tv[3]; fv[2] = tv[1]; break;
146  }
147  break;
148  case 1:
149  switch (re[0])
150  {
151  case 2: fv[0] = tv[2]; fv[1] = tv[0]; fv[2] = tv[3]; break;
152  case 3: fv[0] = tv[0]; fv[1] = tv[3]; fv[2] = tv[2]; break;
153  case 5: fv[0] = tv[3]; fv[1] = tv[2]; fv[2] = tv[0]; break;
154  }
155  break;
156  case 2:
157  fv[0] = tv[0]; fv[1] = tv[1]; fv[2] = tv[3];
158  break;
159  case 3:
160  fv[0] = tv[1]; fv[1] = tv[0]; fv[2] = tv[2];
161  break;
162  }
163 }
164 
166 {
167  if (v_to_v.FindId(indices[0], indices[1]) != -1) { return 1; }
168  if (v_to_v.FindId(indices[1], indices[2]) != -1) { return 1; }
169  if (v_to_v.FindId(indices[2], indices[0]) != -1) { return 1; }
170  if (v_to_v.FindId(indices[0], indices[3]) != -1) { return 1; }
171  if (v_to_v.FindId(indices[1], indices[3]) != -1) { return 1; }
172  if (v_to_v.FindId(indices[2], indices[3]) != -1) { return 1; }
173  return 0;
174 }
175 
176 void Tetrahedron::SetVertices(const int *ind)
177 {
178  for (int i = 0; i < 4; i++)
179  {
180  indices[i] = ind[i];
181  }
182 }
183 
184 void Tetrahedron::MarkEdge(const DSTable &v_to_v, const int *length)
185 {
186  int ind[4], i, j, l, L, type;
187 
188  // determine the longest edge
189  L = length[v_to_v(indices[0], indices[1])]; j = 0;
190  if ((l = length[v_to_v(indices[1], indices[2])]) > L) { L = l; j = 1; }
191  if ((l = length[v_to_v(indices[2], indices[0])]) > L) { L = l; j = 2; }
192  if ((l = length[v_to_v(indices[0], indices[3])]) > L) { L = l; j = 3; }
193  if ((l = length[v_to_v(indices[1], indices[3])]) > L) { L = l; j = 4; }
194  if ((l = length[v_to_v(indices[2], indices[3])]) > L) { j = 5; }
195 
196  for (i = 0; i < 4; i++)
197  {
198  ind[i] = indices[i];
199  }
200 
201  switch (j)
202  {
203  case 1:
204  indices[0] = ind[1]; indices[1] = ind[2];
205  indices[2] = ind[0]; indices[3] = ind[3];
206  break;
207  case 2:
208  indices[0] = ind[2]; indices[1] = ind[0];
209  indices[2] = ind[1]; indices[3] = ind[3];
210  break;
211  case 3:
212  indices[0] = ind[3]; indices[1] = ind[0];
213  indices[2] = ind[2]; indices[3] = ind[1];
214  break;
215  case 4:
216  indices[0] = ind[1]; indices[1] = ind[3];
217  indices[2] = ind[2]; indices[3] = ind[0];
218  break;
219  case 5:
220  indices[0] = ind[2]; indices[1] = ind[3];
221  indices[2] = ind[0]; indices[3] = ind[1];
222  break;
223  }
224 
225  // Determine the two longest edges for the other two faces and
226  // store them in ind[0] and ind[1]
227  ind[0] = 2; ind[1] = 1;
228  L = length[v_to_v(indices[0], indices[2])];
229  if ((l = length[v_to_v(indices[0], indices[3])]) > L) { L = l; ind[0] = 3; }
230  if ((l = length[v_to_v(indices[2], indices[3])]) > L) { ind[0] = 5; }
231 
232  L = length[v_to_v(indices[1], indices[2])];
233  if ((l = length[v_to_v(indices[1], indices[3])]) > L) { L = l; ind[1] = 4; }
234  if ((l = length[v_to_v(indices[2], indices[3])]) > L) { ind[1] = 5; }
235 
236  j = 0;
237  switch (ind[0])
238  {
239  case 2:
240  switch (ind[1])
241  {
242  case 1: type = Tetrahedron::TYPE_PU; break;
243  case 4: type = Tetrahedron::TYPE_A; break;
244  case 5:
245  default: type = Tetrahedron::TYPE_M;
246  }
247  break;
248  case 3:
249  switch (ind[1])
250  {
251  case 1: type = Tetrahedron::TYPE_A; break;
252  case 4: type = Tetrahedron::TYPE_PU;
253  j = 1; ind[0] = 2; ind[1] = 1; break;
254  case 5:
255  default: type = Tetrahedron::TYPE_M;
256  j = 1; ind[0] = 5; ind[1] = 1;
257  }
258  break;
259  case 5:
260  default:
261  switch (ind[1])
262  {
263  case 1: type = Tetrahedron::TYPE_M; break;
264  case 4: type = Tetrahedron::TYPE_M;
265  j = 1; ind[0] = 2; ind[1] = 5; break;
266  case 5:
267  default: type = Tetrahedron::TYPE_O;
268  }
269  }
270 
271  if (j)
272  {
273  mfem::Swap(indices[0], indices[1]);
274  mfem::Swap(indices[2], indices[3]);
275  }
276 
277  CreateRefinementFlag(ind, type);
278 }
279 
280 // static method
281 void Tetrahedron::GetPointMatrix(unsigned transform, DenseMatrix &pm)
282 {
283  double *a = &pm(0,0), *b = &pm(0,1), *c = &pm(0,2), *d = &pm(0,3);
284 
285  // initialize to identity
286  a[0] = 0.0, a[1] = 0.0, a[2] = 0.0;
287  b[0] = 1.0, b[1] = 0.0, b[2] = 0.0;
288  c[0] = 0.0, c[1] = 1.0, c[2] = 0.0;
289  d[0] = 0.0, d[1] = 0.0, d[2] = 1.0;
290 
291  int chain[12], n = 0;
292  while (transform)
293  {
294  chain[n++] = (transform & 7) - 1;
295  transform >>= 3;
296  }
297 
298  /* The transformations and orientations here match the six cases in
299  Mesh::Bisection for tetrahedra. */
300  while (n)
301  {
302 #define ASGN(a, b) (a[0] = b[0], a[1] = b[1], a[2] = b[2])
303 #define SWAP(a, b) for (int i = 0; i < 3; i++) { std::swap(a[i], b[i]); }
304 #define AVG(a, b, c) for (int i = 0; i < 3; i++) { a[i] = (b[i]+c[i])*0.5; }
305 
306  double e[3];
307  AVG(e, a, b);
308  switch (chain[--n])
309  {
310  case 0: ASGN(b, c); ASGN(c, d); break;
311  case 1: ASGN(a, c); ASGN(c, d); break;
312  case 2: ASGN(b, a); ASGN(a, d); break;
313  case 3: ASGN(a, b); ASGN(b, d); break;
314  case 4: SWAP(a, c); ASGN(b, d); break;
315  case 5: SWAP(b, c); ASGN(a, d); break;
316  default:
317  MFEM_ABORT("Invalid transform.");
318  }
319  ASGN(d, e);
320  }
321 }
322 
324 {
325  v.SetSize(4);
326  for (int i = 0; i < 4; i++)
327  {
328  v[i] = indices[i];
329  }
330 }
331 
333 {
334 #ifdef MFEM_USE_MEMALLOC
335  Tetrahedron *tet = m->TetMemory.Alloc();
336 #else
337  Tetrahedron *tet = new Tetrahedron;
338 #endif
339  tet->SetVertices(indices);
340  tet->SetAttribute(attribute);
342  return tet;
343 }
344 
345 }
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 mfem_error(const char *msg)
Function called when an error is encountered. Used by the macros MFEM_ABORT, MFEM_ASSERT, MFEM_VERIFY.
Definition: error.cpp:146
void CreateRefinementFlag(int refinement_edges[2], int type, int flag=0)
Definition: tetrahedron.cpp:68
Data type tetrahedron element.
Definition: tetrahedron.hpp:22
void Swap(Array< T > &, Array< T > &)
Definition: array.hpp:575
int attribute
Element&#39;s attribute (specifying material property, etc).
Definition: element.hpp:33
void SetSize(int nsize)
Change logical size of the array, keep existing entries.
Definition: array.hpp:618
virtual int * GetVertices()
Definition: tetrahedron.hpp:93
virtual int NeedRefinement(HashTable< Hashed2 > &v_to_v) 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 Init(int ind1, int ind2, int ind3, int ind4, int attr=1)
Initialize the vertex indices and the attribute of a Tetrahedron.
Definition: tetrahedron.cpp:43
void SetAttribute(const int attr)
Set element&#39;s attribute.
Definition: element.hpp:58
void GetMarkedFace(const int face, int *fv)
MemAlloc< Tetrahedron, 1024 > TetMemory
Definition: mesh.hpp:163
void SetRefinementFlag(int rf)
Definition: tetrahedron.hpp:67
void ParseRefinementFlag(int refinement_edges[2], int &type, int &flag)
Definition: tetrahedron.cpp:52
int FindId(int p1, int p2) const
Find id of item whose parents are p1, p2... Return -1 if it doesn&#39;t exist.
Definition: hash.hpp:355
virtual void MarkEdge(const DSTable &v_to_v, const int *length)
Abstract data type element.
Definition: element.hpp:28