MFEM  v3.3
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
geom.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 #include "fem.hpp"
13 
14 namespace mfem
15 {
16 
17 const char *Geometry::Name[NumGeom] =
18 { "Point", "Segment", "Triangle", "Square", "Tetrahedron", "Cube" };
19 
20 const double Geometry::Volume[NumGeom] =
21 { 1.0, 1.0, 0.5, 1.0, 1./6, 1.0 };
22 
24 {
25  // Vertices for Geometry::POINT
26  GeomVert[0] = NULL; // No vertices, dimension is 0
27 
28  // Vertices for Geometry::SEGMENT
29  GeomVert[1] = new IntegrationRule(2);
30 
31  GeomVert[1]->IntPoint(0).x = 0.0;
32  GeomVert[1]->IntPoint(1).x = 1.0;
33 
34  // Vertices for Geometry::TRIANGLE
35  GeomVert[2] = new IntegrationRule(3);
36 
37  GeomVert[2]->IntPoint(0).x = 0.0;
38  GeomVert[2]->IntPoint(0).y = 0.0;
39 
40  GeomVert[2]->IntPoint(1).x = 1.0;
41  GeomVert[2]->IntPoint(1).y = 0.0;
42 
43  GeomVert[2]->IntPoint(2).x = 0.0;
44  GeomVert[2]->IntPoint(2).y = 1.0;
45 
46  // Vertices for Geometry::SQUARE
47  GeomVert[3] = new IntegrationRule(4);
48 
49  GeomVert[3]->IntPoint(0).x = 0.0;
50  GeomVert[3]->IntPoint(0).y = 0.0;
51 
52  GeomVert[3]->IntPoint(1).x = 1.0;
53  GeomVert[3]->IntPoint(1).y = 0.0;
54 
55  GeomVert[3]->IntPoint(2).x = 1.0;
56  GeomVert[3]->IntPoint(2).y = 1.0;
57 
58  GeomVert[3]->IntPoint(3).x = 0.0;
59  GeomVert[3]->IntPoint(3).y = 1.0;
60 
61  // Vertices for Geometry::TETRAHEDRON
62  GeomVert[4] = new IntegrationRule(4);
63  GeomVert[4]->IntPoint(0).x = 0.0;
64  GeomVert[4]->IntPoint(0).y = 0.0;
65  GeomVert[4]->IntPoint(0).z = 0.0;
66 
67  GeomVert[4]->IntPoint(1).x = 1.0;
68  GeomVert[4]->IntPoint(1).y = 0.0;
69  GeomVert[4]->IntPoint(1).z = 0.0;
70 
71  GeomVert[4]->IntPoint(2).x = 0.0;
72  GeomVert[4]->IntPoint(2).y = 1.0;
73  GeomVert[4]->IntPoint(2).z = 0.0;
74 
75  GeomVert[4]->IntPoint(3).x = 0.0;
76  GeomVert[4]->IntPoint(3).y = 0.0;
77  GeomVert[4]->IntPoint(3).z = 1.0;
78 
79  // Vertices for Geometry::CUBE
80  GeomVert[5] = new IntegrationRule(8);
81 
82  GeomVert[5]->IntPoint(0).x = 0.0;
83  GeomVert[5]->IntPoint(0).y = 0.0;
84  GeomVert[5]->IntPoint(0).z = 0.0;
85 
86  GeomVert[5]->IntPoint(1).x = 1.0;
87  GeomVert[5]->IntPoint(1).y = 0.0;
88  GeomVert[5]->IntPoint(1).z = 0.0;
89 
90  GeomVert[5]->IntPoint(2).x = 1.0;
91  GeomVert[5]->IntPoint(2).y = 1.0;
92  GeomVert[5]->IntPoint(2).z = 0.0;
93 
94  GeomVert[5]->IntPoint(3).x = 0.0;
95  GeomVert[5]->IntPoint(3).y = 1.0;
96  GeomVert[5]->IntPoint(3).z = 0.0;
97 
98  GeomVert[5]->IntPoint(4).x = 0.0;
99  GeomVert[5]->IntPoint(4).y = 0.0;
100  GeomVert[5]->IntPoint(4).z = 1.0;
101 
102  GeomVert[5]->IntPoint(5).x = 1.0;
103  GeomVert[5]->IntPoint(5).y = 0.0;
104  GeomVert[5]->IntPoint(5).z = 1.0;
105 
106  GeomVert[5]->IntPoint(6).x = 1.0;
107  GeomVert[5]->IntPoint(6).y = 1.0;
108  GeomVert[5]->IntPoint(6).z = 1.0;
109 
110  GeomVert[5]->IntPoint(7).x = 0.0;
111  GeomVert[5]->IntPoint(7).y = 1.0;
112  GeomVert[5]->IntPoint(7).z = 1.0;
113 
114  GeomCenter[POINT].x = 0.0;
115  GeomCenter[POINT].y = 0.0;
116  GeomCenter[POINT].z = 0.0;
117 
118  GeomCenter[SEGMENT].x = 0.5;
119  GeomCenter[SEGMENT].y = 0.0;
120  GeomCenter[SEGMENT].z = 0.0;
121 
122  GeomCenter[TRIANGLE].x = 1.0 / 3.0;
123  GeomCenter[TRIANGLE].y = 1.0 / 3.0;
124  GeomCenter[TRIANGLE].z = 0.0;
125 
126  GeomCenter[SQUARE].x = 0.5;
127  GeomCenter[SQUARE].y = 0.5;
128  GeomCenter[SQUARE].z = 0.0;
129 
130  GeomCenter[TETRAHEDRON].x = 0.25;
131  GeomCenter[TETRAHEDRON].y = 0.25;
132  GeomCenter[TETRAHEDRON].z = 0.25;
133 
134  GeomCenter[CUBE].x = 0.5;
135  GeomCenter[CUBE].y = 0.5;
136  GeomCenter[CUBE].z = 0.5;
137 
138  PerfGeomToGeomJac[POINT] = NULL;
139  PerfGeomToGeomJac[SEGMENT] = NULL;
140  PerfGeomToGeomJac[TRIANGLE] = new DenseMatrix(2);
141  PerfGeomToGeomJac[SQUARE] = NULL;
142  PerfGeomToGeomJac[TETRAHEDRON] = new DenseMatrix(3);
143  PerfGeomToGeomJac[CUBE] = NULL;
144 
145  {
146  Linear2DFiniteElement TriFE;
148  tri_T.SetFE(&TriFE);
150  tri_T.SetIntPoint(&GeomCenter[TRIANGLE]);
151  CalcInverse(tri_T.Jacobian(), *PerfGeomToGeomJac[TRIANGLE]);
152  }
153  {
154  Linear3DFiniteElement TetFE;
156  tet_T.SetFE(&TetFE);
158  tet_T.SetIntPoint(&GeomCenter[TETRAHEDRON]);
159  CalcInverse(tet_T.Jacobian(), *PerfGeomToGeomJac[TETRAHEDRON]);
160  }
161 }
162 
164 {
165  for (int i = 0; i < NumGeom; i++)
166  {
167  delete PerfGeomToGeomJac[i];
168  delete GeomVert[i];
169  }
170 }
171 
173 {
174  switch (GeomType)
175  {
176  case Geometry::POINT: return GeomVert[0];
177  case Geometry::SEGMENT: return GeomVert[1];
178  case Geometry::TRIANGLE: return GeomVert[2];
179  case Geometry::SQUARE: return GeomVert[3];
180  case Geometry::TETRAHEDRON: return GeomVert[4];
181  case Geometry::CUBE: return GeomVert[5];
182  default:
183  mfem_error ("Geometry::GetVertices(...)");
184  }
185  // make some compilers happy.
186  return GeomVert[0];
187 }
188 
189 // static method
191 {
192  switch (GeomType)
193  {
194  case Geometry::POINT:
195  ip.x = 0.0;
196  break;
197  case Geometry::SEGMENT:
198  ip.x = double(rand()) / RAND_MAX;
199  break;
200  case Geometry::TRIANGLE:
201  ip.x = double(rand()) / RAND_MAX;
202  ip.y = double(rand()) / RAND_MAX;
203  if (ip.x + ip.y > 1.0)
204  {
205  ip.x = 1.0 - ip.x;
206  ip.y = 1.0 - ip.y;
207  }
208  break;
209  case Geometry::SQUARE:
210  ip.x = double(rand()) / RAND_MAX;
211  ip.y = double(rand()) / RAND_MAX;
212  break;
214  ip.x = double(rand()) / RAND_MAX;
215  ip.y = double(rand()) / RAND_MAX;
216  ip.z = double(rand()) / RAND_MAX;
217  // map to the triangular prism obtained by extruding the reference
218  // triangle in z direction
219  if (ip.x + ip.y > 1.0)
220  {
221  ip.x = 1.0 - ip.x;
222  ip.y = 1.0 - ip.y;
223  }
224  // split the prism into 3 parts: 1 is the reference tet, and the
225  // other two tets (as given below) are mapped to the reference tet
226  if (ip.x + ip.z > 1.0)
227  {
228  // tet with vertices: (0,0,1),(1,0,1),(0,1,1),(1,0,0)
229  ip.x = ip.x + ip.z - 1.0;
230  // ip.y = ip.y;
231  ip.z = 1.0 - ip.z;
232  // mapped to: (0,0,0),(1,0,0),(0,1,0),(0,0,1)
233  }
234  else if (ip.x + ip.y + ip.z > 1.0)
235  {
236  // tet with vertices: (0,1,1),(0,1,0),(0,0,1),(1,0,0)
237  double x = ip.x;
238  ip.x = 1.0 - x - ip.z;
239  ip.y = 1.0 - x - ip.y;
240  ip.z = x;
241  // mapped to: (0,0,0),(1,0,0),(0,1,0),(0,0,1)
242  }
243  break;
244  case Geometry::CUBE:
245  ip.x = double(rand()) / RAND_MAX;
246  ip.y = double(rand()) / RAND_MAX;
247  ip.z = double(rand()) / RAND_MAX;
248  break;
249  default:
250  MFEM_ABORT("Unknown type of reference element!");
251  }
252 }
253 
254 // static method
255 bool Geometry::CheckPoint(int GeomType, const IntegrationPoint &ip)
256 {
257  switch (GeomType)
258  {
259  case Geometry::POINT:
260  if (ip.x != 0.0) { return false; }
261  break;
262  case Geometry::SEGMENT:
263  if (ip.x < 0.0 || ip.x > 1.0) { return false; }
264  break;
265  case Geometry::TRIANGLE:
266  if (ip.x < 0.0 || ip.y < 0.0 || ip.x+ip.y > 1.0) { return false; }
267  break;
268  case Geometry::SQUARE:
269  if (ip.x < 0.0 || ip.x > 1.0 || ip.y < 0.0 || ip.y > 1.0)
270  { return false; }
271  break;
273  if (ip.x < 0.0 || ip.y < 0.0 || ip.z < 0.0 ||
274  ip.x+ip.y+ip.z > 1.0) { return false; }
275  break;
276  case Geometry::CUBE:
277  if (ip.x < 0.0 || ip.x > 1.0 || ip.y < 0.0 || ip.y > 1.0 ||
278  ip.z < 0.0 || ip.z > 1.0) { return false; }
279  break;
280  default:
281  MFEM_ABORT("Unknown type of reference element!");
282  }
283  return true;
284 }
285 
286 namespace internal
287 {
288 
289 template <int N, int dim>
290 inline bool IntersectSegment(double lbeg[N], double lend[N],
291  IntegrationPoint &end)
292 {
293  double t = 1.0;
294  bool out = false;
295  for (int i = 0; i < N; i++)
296  {
297  lbeg[i] = std::max(lbeg[i], 0.0); // remove round-off
298  if (lend[i] < 0.0)
299  {
300  out = true;
301  t = std::min(t, lbeg[i]/(lbeg[i]-lend[i]));
302  }
303  }
304  if (out)
305  {
306  if (dim >= 1) { end.x = t*lend[0] + (1.0-t)*lbeg[0]; }
307  if (dim >= 2) { end.y = t*lend[1] + (1.0-t)*lbeg[1]; }
308  if (dim >= 3) { end.z = t*lend[2] + (1.0-t)*lbeg[2]; }
309  return false;
310  }
311  return true;
312 }
313 
314 }
315 
316 // static method
317 bool Geometry::ProjectPoint(int GeomType, const IntegrationPoint &beg,
318  IntegrationPoint &end)
319 {
320  switch (GeomType)
321  {
322  case Geometry::POINT:
323  {
324  if (end.x != 0.0) { end.x = 0.0; return false; }
325  break;
326  }
327  case Geometry::SEGMENT:
328  {
329  if (end.x < 0.0) { end.x = 0.0; return false; }
330  if (end.x > 1.0) { end.x = 1.0; return false; }
331  break;
332  }
333  case Geometry::TRIANGLE:
334  {
335  double lend[3] = { end.x, end.y, 1-end.x-end.y };
336  double lbeg[3] = { beg.x, beg.y, 1-beg.x-beg.y };
337  return internal::IntersectSegment<3,2>(lbeg, lend, end);
338  }
339  case Geometry::SQUARE:
340  {
341  double lend[4] = { end.x, end.y, 1-end.x, 1.0-end.y };
342  double lbeg[4] = { beg.x, beg.y, 1-beg.x, 1.0-beg.y };
343  return internal::IntersectSegment<4,2>(lbeg, lend, end);
344  }
346  {
347  double lend[4] = { end.x, end.y, end.z, 1.0-end.x-end.y-end.z };
348  double lbeg[4] = { beg.x, beg.y, beg.z, 1.0-beg.x-beg.y-beg.z };
349  return internal::IntersectSegment<4,3>(lbeg, lend, end);
350  }
351  case Geometry::CUBE:
352  {
353  double lend[6] = { end.x, end.y, end.z,
354  1.0-end.x, 1.0-end.y, 1.0-end.z
355  };
356  double lbeg[6] = { beg.x, beg.y, beg.z,
357  1.0-beg.x, 1.0-beg.y, 1.0-beg.z
358  };
359  return internal::IntersectSegment<6,3>(lbeg, lend, end);
360  }
361  default:
362  MFEM_ABORT("Unknown type of reference element!");
363  }
364  return true;
365 }
366 
367 void Geometry::GetPerfPointMat(int GeomType, DenseMatrix &pm)
368 {
369  switch (GeomType)
370  {
371  case Geometry::SEGMENT:
372  {
373  pm.SetSize (1, 2);
374  pm(0,0) = 0.0;
375  pm(0,1) = 1.0;
376  }
377  break;
378 
379  case Geometry::TRIANGLE:
380  {
381  pm.SetSize (2, 3);
382  pm(0,0) = 0.0; pm(1,0) = 0.0;
383  pm(0,1) = 1.0; pm(1,1) = 0.0;
384  pm(0,2) = 0.5; pm(1,2) = 0.86602540378443864676;
385  }
386  break;
387 
388  case Geometry::SQUARE:
389  {
390  pm.SetSize (2, 4);
391  pm(0,0) = 0.0; pm(1,0) = 0.0;
392  pm(0,1) = 1.0; pm(1,1) = 0.0;
393  pm(0,2) = 1.0; pm(1,2) = 1.0;
394  pm(0,3) = 0.0; pm(1,3) = 1.0;
395  }
396  break;
397 
399  {
400  pm.SetSize (3, 4);
401  pm(0,0) = 0.0; pm(1,0) = 0.0; pm(2,0) = 0.0;
402  pm(0,1) = 1.0; pm(1,1) = 0.0; pm(2,1) = 0.0;
403  pm(0,2) = 0.5; pm(1,2) = 0.86602540378443864676; pm(2,2) = 0.0;
404  pm(0,3) = 0.5; pm(1,3) = 0.28867513459481288225;
405  pm(2,3) = 0.81649658092772603273;
406  }
407  break;
408 
409  case Geometry::CUBE:
410  {
411  pm.SetSize (3, 8);
412  pm(0,0) = 0.0; pm(1,0) = 0.0; pm(2,0) = 0.0;
413  pm(0,1) = 1.0; pm(1,1) = 0.0; pm(2,1) = 0.0;
414  pm(0,2) = 1.0; pm(1,2) = 1.0; pm(2,2) = 0.0;
415  pm(0,3) = 0.0; pm(1,3) = 1.0; pm(2,3) = 0.0;
416  pm(0,4) = 0.0; pm(1,4) = 0.0; pm(2,4) = 1.0;
417  pm(0,5) = 1.0; pm(1,5) = 0.0; pm(2,5) = 1.0;
418  pm(0,6) = 1.0; pm(1,6) = 1.0; pm(2,6) = 1.0;
419  pm(0,7) = 0.0; pm(1,7) = 1.0; pm(2,7) = 1.0;
420  }
421  break;
422 
423  default:
424  mfem_error ("Geometry::GetPerfPointMat (...)");
425  }
426 }
427 
428 void Geometry::JacToPerfJac(int GeomType, const DenseMatrix &J,
429  DenseMatrix &PJ) const
430 {
431  if (PerfGeomToGeomJac[GeomType])
432  {
433  Mult(J, *PerfGeomToGeomJac[GeomType], PJ);
434  }
435  else
436  {
437  PJ = J;
438  }
439 }
440 
441 const int Geometry::NumBdrArray[] = { 0, 2, 3, 4, 4, 6 };
442 const int Geometry::Dimension[NumGeom] = { 0, 1, 2, 2, 3, 3 };
443 const int Geometry::NumVerts[NumGeom] = { 1, 2, 3, 4, 4, 8 };
444 const int Geometry::NumEdges[NumGeom] = { 0, 1, 3, 4, 6, 12 };
445 const int Geometry::NumFaces[NumGeom] = { 0, 0, 1, 1, 4, 6 };
446 
447 const int Geometry::
449 const int Geometry::
451 
452 const int Geometry::
453 Constants<Geometry::SEGMENT>::Edges[1][2] = { {0, 1} };
454 const int Geometry::
455 Constants<Geometry::SEGMENT>::Orient[2][2] = { {0, 1}, {1, 0} };
456 const int Geometry::
458 
459 const int Geometry::
460 Constants<Geometry::TRIANGLE>::Edges[3][2] = {{0, 1}, {1, 2}, {2, 0}};
461 const int Geometry::
463 const int Geometry::
464 Constants<Geometry::TRIANGLE>::VertToVert::J[3][2] = {{1, 0}, {2, -3}, {2, 1}};
465 const int Geometry::
466 Constants<Geometry::TRIANGLE>::FaceVert[1][3] = {{0, 1, 2}};
467 const int Geometry::
469 {
470  {0, 1, 2}, {1, 0, 2}, {2, 0, 1},
471  {2, 1, 0}, {1, 2, 0}, {0, 2, 1}
472 };
473 const int Geometry::
474 Constants<Geometry::TRIANGLE>::InvOrient[6] = { 0, 1, 4, 3, 2, 5 };
475 
476 const int Geometry::
477 Constants<Geometry::SQUARE>::Edges[4][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 0}};
478 const int Geometry::
480 const int Geometry::
482 {{1, 0}, {3, -4}, {2, 1}, {3, 2}};
483 const int Geometry::
484 Constants<Geometry::SQUARE>::FaceVert[1][4] = {{0, 1, 2, 3}};
485 const int Geometry::
487 {
488  {0, 1, 2, 3}, {0, 3, 2, 1}, {1, 2, 3, 0}, {1, 0, 3, 2},
489  {2, 3, 0, 1}, {2, 1, 0, 3}, {3, 0, 1, 2}, {3, 2, 1, 0}
490 };
491 const int Geometry::
492 Constants<Geometry::SQUARE>::InvOrient[8] = { 0, 1, 6, 3, 4, 5, 2, 7 };
493 
494 const int Geometry::
496 {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
497 const int Geometry::
499 {
501  Geometry::TRIANGLE, Geometry::TRIANGLE
502 };
503 const int Geometry::
505 {{1, 2, 3}, {0, 3, 2}, {0, 1, 3}, {0, 2, 1}};
506 const int Geometry::
508 const int Geometry::
510 {{1, 0}, {2, 1}, {3, 2}, {2, 3}, {3, 4}, {3, 5}};
511 
512 const int Geometry::
514 {
515  {0, 1}, {1, 2}, {3, 2}, {0, 3}, {4, 5}, {5, 6},
516  {7, 6}, {4, 7}, {0, 4}, {1, 5}, {2, 6}, {3, 7}
517 };
518 const int Geometry::
520 {
522  Geometry::SQUARE, Geometry::SQUARE, Geometry::SQUARE
523 };
524 const int Geometry::
526 {
527  {3, 2, 1, 0}, {0, 1, 5, 4}, {1, 2, 6, 5},
528  {2, 3, 7, 6}, {3, 0, 4, 7}, {4, 5, 6, 7}
529 };
530 const int Geometry::
531 Constants<Geometry::CUBE>::VertToVert::I[8] = {0, 3, 5, 7, 8, 10, 11, 12};
532 const int Geometry::
534 {
535  {1, 0}, {3, 3}, {4, 8}, // 0,1:0 0,3:3 0,4:8
536  {2, 1}, {5, 9}, // 1,2:1 1,5:9
537  {3,-3}, {6,10}, // 2,3:-3 2,6:10
538  {7,11}, // 3,7:11
539  {5, 4}, {7, 7}, // 4,5:4 4,7:7
540  {6, 5}, // 5,6:5
541  {7,-7} // 6,7:-7
542 };
543 
545 
546 
548 {
549  type = 0;
550  for (int i = 0; i < Geometry::NumGeom; i++)
551  {
552  RGeom[i] = NULL;
553  IntPts[i] = NULL;
554  }
555 }
556 
558 {
559  for (int i = 0; i < Geometry::NumGeom; i++)
560  {
561  delete RGeom[i];
562  delete IntPts[i];
563  }
564 }
565 
566 RefinedGeometry * GeometryRefiner::Refine (int Geom, int Times, int ETimes)
567 {
568  int i, j, k, l;
569 
570  const double *cp = NULL;
571  if (type)
572  {
573  cp = poly1d.ClosedPoints(Times);
574  }
575 
576  switch (Geom)
577  {
578  case Geometry::SEGMENT:
579  {
580  const int g = Geometry::SEGMENT;
581  if (RGeom[g] != NULL && RGeom[g]->Times == Times)
582  {
583  return RGeom[g];
584  }
585  delete RGeom[g];
586  RGeom[g] = new RefinedGeometry(Times+1, 2*Times, 0);
587  RGeom[g]->Times = Times;
588  RGeom[g]->ETimes = 0;
589  for (i = 0; i <= Times; i++)
590  {
591  IntegrationPoint &ip = RGeom[g]->RefPts.IntPoint(i);
592  ip.x = (type == 0) ? double(i) / Times : cp[i];
593  }
594  Array<int> &G = RGeom[g]->RefGeoms;
595  for (i = 0; i < Times; i++)
596  {
597  G[2*i+0] = i;
598  G[2*i+1] = i+1;
599  }
600 
601  return RGeom[g];
602  }
603 
604  case Geometry::TRIANGLE:
605  {
606  if (RGeom[2] != NULL && RGeom[2]->Times == Times &&
607  RGeom[2]->ETimes == ETimes)
608  {
609  return RGeom[2];
610  }
611 
612  if (RGeom[2] != NULL)
613  {
614  delete RGeom[2];
615  }
616  RGeom[2] = new RefinedGeometry((Times+1)*(Times+2)/2, 3*Times*Times,
617  3*Times*(ETimes+1), 3*Times);
618  RGeom[2]->Times = Times;
619  RGeom[2]->ETimes = ETimes;
620  for (k = j = 0; j <= Times; j++)
621  for (i = 0; i <= Times-j; i++, k++)
622  {
623  IntegrationPoint &ip = RGeom[2]->RefPts.IntPoint(k);
624  if (type == 0)
625  {
626  ip.x = double(i) / Times;
627  ip.y = double(j) / Times;
628  }
629  else
630  {
631  ip.x = cp[i]/(cp[i] + cp[j] + cp[Times-i-j]);
632  ip.y = cp[j]/(cp[i] + cp[j] + cp[Times-i-j]);
633  }
634  }
635  Array<int> &G = RGeom[2]->RefGeoms;
636  for (l = k = j = 0; j < Times; j++, k++)
637  for (i = 0; i < Times-j; i++, k++)
638  {
639  G[l++] = k;
640  G[l++] = k+1;
641  G[l++] = k+Times-j+1;
642  if (i+j+1 < Times)
643  {
644  G[l++] = k+1;
645  G[l++] = k+Times-j+2;
646  G[l++] = k+Times-j+1;
647  }
648  }
649  Array<int> &E = RGeom[2]->RefEdges;
650  int lb = 0, li = 2*RGeom[2]->NumBdrEdges;
651  // horizontal edges
652  for (k = 0; k < Times; k += Times/ETimes)
653  {
654  int &lt = (k == 0) ? lb : li;
655  j = k*(Times+1)-((k-1)*k)/2;
656  for (i = 0; i < Times-k; i++)
657  {
658  E[lt++] = j; j++;
659  E[lt++] = j;
660  }
661  }
662  // diagonal edges
663  for (k = Times; k > 0; k -= Times/ETimes)
664  {
665  int &lt = (k == Times) ? lb : li;
666  j = k;
667  for (i = 0; i < k; i++)
668  {
669  E[lt++] = j; j += Times-i;
670  E[lt++] = j;
671  }
672  }
673  // vertical edges
674  for (k = 0; k < Times; k += Times/ETimes)
675  {
676  int &lt = (k == 0) ? lb : li;
677  j = k;
678  for (i = 0; i < Times-k; i++)
679  {
680  E[lt++] = j; j += Times-i+1;
681  E[lt++] = j;
682  }
683  }
684 
685  return RGeom[2];
686  }
687 
688  case Geometry::SQUARE:
689  {
690  if (RGeom[3] != NULL && RGeom[3]->Times == Times &&
691  RGeom[3]->ETimes == ETimes)
692  {
693  return RGeom[3];
694  }
695 
696  if (RGeom[3] != NULL)
697  {
698  delete RGeom[3];
699  }
700  RGeom[3] = new RefinedGeometry((Times+1)*(Times+1), 4*Times*Times,
701  4*(ETimes+1)*Times, 4*Times);
702  RGeom[3]->Times = Times;
703  RGeom[3]->ETimes = ETimes;
704  for (k = j = 0; j <= Times; j++)
705  for (i = 0; i <= Times; i++, k++)
706  {
707  IntegrationPoint &ip = RGeom[3]->RefPts.IntPoint(k);
708  if (type == 0)
709  {
710  ip.x = double(i) / Times;
711  ip.y = double(j) / Times;
712  }
713  else
714  {
715  ip.x = cp[i];
716  ip.y = cp[j];
717  }
718  }
719  Array<int> &G = RGeom[3]->RefGeoms;
720  for (l = k = j = 0; j < Times; j++, k++)
721  for (i = 0; i < Times; i++, k++)
722  {
723  G[l++] = k;
724  G[l++] = k+1;
725  G[l++] = k+Times+2;
726  G[l++] = k+Times+1;
727  }
728  Array<int> &E = RGeom[3]->RefEdges;
729  int lb = 0, li = 2*RGeom[3]->NumBdrEdges;
730  // horizontal edges
731  for (k = 0; k <= Times; k += Times/ETimes)
732  {
733  int &lt = (k == 0 || k == Times) ? lb : li;
734  for (i = 0, j = k*(Times+1); i < Times; i++)
735  {
736  E[lt++] = j; j++;
737  E[lt++] = j;
738  }
739  }
740  // vertical edges (in right-to-left order)
741  for (k = Times; k >= 0; k -= Times/ETimes)
742  {
743  int &lt = (k == Times || k == 0) ? lb : li;
744  for (i = 0, j = k; i < Times; i++)
745  {
746  E[lt++] = j; j += Times+1;
747  E[lt++] = j;
748  }
749  }
750 
751  return RGeom[3];
752  }
753 
754  case Geometry::CUBE:
755  {
756  const int g = Geometry::CUBE;
757  if (RGeom[g] != NULL && RGeom[g]->Times == Times &&
758  RGeom[g]->ETimes == ETimes)
759  {
760  return RGeom[g];
761  }
762 
763  if (RGeom[g] != NULL)
764  {
765  delete RGeom[g];
766  }
767  RGeom[g] = new RefinedGeometry ((Times+1)*(Times+1)*(Times+1),
768  8*Times*Times*Times, 0);
769  RGeom[g]->Times = Times;
770  RGeom[g]->ETimes = ETimes;
771  for (l = k = 0; k <= Times; k++)
772  for (j = 0; j <= Times; j++)
773  for (i = 0; i <= Times; i++, l++)
774  {
775  IntegrationPoint &ip = RGeom[g]->RefPts.IntPoint(l);
776  if (type == 0)
777  {
778  ip.x = double(i) / Times;
779  ip.y = double(j) / Times;
780  ip.z = double(k) / Times;
781  }
782  else
783  {
784  ip.x = cp[i];
785  ip.y = cp[j];
786  ip.z = cp[k];
787  }
788  }
789  Array<int> &G = RGeom[g]->RefGeoms;
790  for (l = k = 0; k < Times; k++)
791  for (j = 0; j < Times; j++)
792  for (i = 0; i < Times; i++)
793  {
794  G[l++] = i+0 + (j+0 + (k+0) * (Times+1)) * (Times+1);
795  G[l++] = i+1 + (j+0 + (k+0) * (Times+1)) * (Times+1);
796  G[l++] = i+1 + (j+1 + (k+0) * (Times+1)) * (Times+1);
797  G[l++] = i+0 + (j+1 + (k+0) * (Times+1)) * (Times+1);
798  G[l++] = i+0 + (j+0 + (k+1) * (Times+1)) * (Times+1);
799  G[l++] = i+1 + (j+0 + (k+1) * (Times+1)) * (Times+1);
800  G[l++] = i+1 + (j+1 + (k+1) * (Times+1)) * (Times+1);
801  G[l++] = i+0 + (j+1 + (k+1) * (Times+1)) * (Times+1);
802  }
803 
804  return RGeom[g];
805  }
806 
808  {
809  const int g = Geometry::TETRAHEDRON;
810  if (RGeom[g] != NULL && RGeom[g]->Times == Times &&
811  RGeom[g]->ETimes == ETimes)
812  {
813  return RGeom[g];
814  }
815 
816  if (RGeom[g] != NULL)
817  {
818  delete RGeom[g];
819  }
820 
821  // subdivide the tetrahedron with vertices
822  // (0,0,0), (0,0,1), (1,1,1), (0,1,1)
823 
824  // vertices: 0 <= i <= j <= k <= Times
825  // (3-combination with repetitions)
826  // number of vertices: (n+3)*(n+2)*(n+1)/6, n = Times
827 
828  // elements: the vertices are: v1=(i,j,k), v2=v1+u1, v3=v2+u2, v4=v3+u3
829  // where 0 <= i <= j <= k <= n-1 and
830  // u1,u2,u3 is a permutation of (1,0,0),(0,1,0),(0,0,1)
831  // such that all v2,v3,v4 have non-decreasing components
832  // number of elements: n^3
833 
834  const int n = Times;
835  RGeom[g] = new RefinedGeometry((n+3)*(n+2)*(n+1)/6, 4*n*n*n, 0);
836  // enumerate and define the vertices
837  Array<int> vi((n+1)*(n+1)*(n+1));
838  vi = -1;
839  int m = 0;
840  for (k = 0; k <= n; k++)
841  for (j = 0; j <= k; j++)
842  for (i = 0; i <= j; i++)
843  {
844  IntegrationPoint &ip = RGeom[g]->RefPts.IntPoint(m);
845  // map the coordinates to the reference tetrahedron
846  // (0,0,0) -> (0,0,0)
847  // (0,0,1) -> (1,0,0)
848  // (1,1,1) -> (0,1,0)
849  // (0,1,1) -> (0,0,1)
850  if (type == 0)
851  {
852  ip.x = double(k - j) / n;
853  ip.y = double(i) / n;
854  ip.z = double(j - i) / n;
855  }
856  else
857  {
858  double w = cp[k-j] + cp[i] + cp[j-i] + cp[Times-k];
859  ip.x = cp[k-j]/w;
860  ip.y = cp[i]/w;
861  ip.z = cp[j-i]/w;
862  }
863  l = i + (j + k * (n+1)) * (n+1);
864  vi[l] = m;
865  m++;
866  }
867  if (m != (n+3)*(n+2)*(n+1)/6)
868  {
869  mfem_error("GeometryRefiner::Refine() for TETRAHEDRON #1");
870  }
871  // elements
872  Array<int> &G = RGeom[g]->RefGeoms;
873  m = 0;
874  for (k = 0; k < n; k++)
875  for (j = 0; j <= k; j++)
876  for (i = 0; i <= j; i++)
877  {
878  // the ordering of the vertices is chosen to ensure:
879  // 1) correct orientation
880  // 2) the x,y,z edges are in the set of edges
881  // {(0,1),(2,3), (0,2),(1,3)}
882  // (goal is to ensure that subsequent refinement using
883  // this procedure preserves the six tetrahedral shapes)
884 
885  // zyx: (i,j,k)-(i,j,k+1)-(i+1,j+1,k+1)-(i,j+1,k+1)
886  G[m++] = vi[i+0 + (j+0 + (k+0) * (n+1)) * (n+1)];
887  G[m++] = vi[i+0 + (j+0 + (k+1) * (n+1)) * (n+1)];
888  G[m++] = vi[i+1 + (j+1 + (k+1) * (n+1)) * (n+1)];
889  G[m++] = vi[i+0 + (j+1 + (k+1) * (n+1)) * (n+1)];
890  if (j < k)
891  {
892  // yzx: (i,j,k)-(i+1,j+1,k+1)-(i,j+1,k)-(i,j+1,k+1)
893  G[m++] = vi[i+0 + (j+0 + (k+0) * (n+1)) * (n+1)];
894  G[m++] = vi[i+1 + (j+1 + (k+1) * (n+1)) * (n+1)];
895  G[m++] = vi[i+0 + (j+1 + (k+0) * (n+1)) * (n+1)];
896  G[m++] = vi[i+0 + (j+1 + (k+1) * (n+1)) * (n+1)];
897  // yxz: (i,j,k)-(i,j+1,k)-(i+1,j+1,k+1)-(i+1,j+1,k)
898  G[m++] = vi[i+0 + (j+0 + (k+0) * (n+1)) * (n+1)];
899  G[m++] = vi[i+0 + (j+1 + (k+0) * (n+1)) * (n+1)];
900  G[m++] = vi[i+1 + (j+1 + (k+1) * (n+1)) * (n+1)];
901  G[m++] = vi[i+1 + (j+1 + (k+0) * (n+1)) * (n+1)];
902  }
903  if (i < j)
904  {
905  // xzy: (i,j,k)-(i+1,j,k)-(i+1,j+1,k+1)-(i+1,j,k+1)
906  G[m++] = vi[i+0 + (j+0 + (k+0) * (n+1)) * (n+1)];
907  G[m++] = vi[i+1 + (j+0 + (k+0) * (n+1)) * (n+1)];
908  G[m++] = vi[i+1 + (j+1 + (k+1) * (n+1)) * (n+1)];
909  G[m++] = vi[i+1 + (j+0 + (k+1) * (n+1)) * (n+1)];
910  if (j < k)
911  {
912  // xyz: (i,j,k)-(i+1,j+1,k+1)-(i+1,j,k)-(i+1,j+1,k)
913  G[m++] = vi[i+0 + (j+0 + (k+0) * (n+1)) * (n+1)];
914  G[m++] = vi[i+1 + (j+1 + (k+1) * (n+1)) * (n+1)];
915  G[m++] = vi[i+1 + (j+0 + (k+0) * (n+1)) * (n+1)];
916  G[m++] = vi[i+1 + (j+1 + (k+0) * (n+1)) * (n+1)];
917  }
918  // zxy: (i,j,k)-(i+1,j+1,k+1)-(i,j,k+1)-(i+1,j,k+1)
919  G[m++] = vi[i+0 + (j+0 + (k+0) * (n+1)) * (n+1)];
920  G[m++] = vi[i+1 + (j+1 + (k+1) * (n+1)) * (n+1)];
921  G[m++] = vi[i+0 + (j+0 + (k+1) * (n+1)) * (n+1)];
922  G[m++] = vi[i+1 + (j+0 + (k+1) * (n+1)) * (n+1)];
923  }
924  }
925  if (m != 4*n*n*n)
926  {
927  mfem_error("GeometryRefiner::Refine() for TETRAHEDRON #2");
928  }
929  for (i = 0; i < m; i++)
930  if (G[i] < 0)
931  {
932  mfem_error("GeometryRefiner::Refine() for TETRAHEDRON #3");
933  }
934 
935  return RGeom[g];
936  }
937 
938  default:
939 
940  return RGeom[0];
941  }
942 }
943 
945 {
946  int g = Geom;
947 
948  switch (g)
949  {
950  case Geometry::SEGMENT:
951  {
952  if (Times < 2)
953  {
954  return NULL;
955  }
956  if (IntPts[g] == NULL || IntPts[g]->GetNPoints() != Times-1)
957  {
958  delete IntPts[g];
959  IntPts[g] = new IntegrationRule(Times-1);
960  for (int i = 1; i < Times; i++)
961  {
962  IntegrationPoint &ip = IntPts[g]->IntPoint(i-1);
963  ip.x = double(i) / Times;
964  ip.y = ip.z = 0.0;
965  }
966  }
967  }
968  break;
969 
970  case Geometry::TRIANGLE:
971  {
972  if (Times < 3)
973  {
974  return NULL;
975  }
976  if (IntPts[g] == NULL ||
977  IntPts[g]->GetNPoints() != ((Times-1)*(Times-2))/2)
978  {
979  delete IntPts[g];
980  IntPts[g] = new IntegrationRule(((Times-1)*(Times-2))/2);
981  for (int k = 0, j = 1; j < Times-1; j++)
982  for (int i = 1; i < Times-j; i++, k++)
983  {
984  IntegrationPoint &ip = IntPts[g]->IntPoint(k);
985  ip.x = double(i) / Times;
986  ip.y = double(j) / Times;
987  ip.z = 0.0;
988  }
989  }
990  }
991  break;
992 
993  case Geometry::SQUARE:
994  {
995  if (Times < 2)
996  {
997  return NULL;
998  }
999  if (IntPts[g] == NULL || IntPts[g]->GetNPoints() != (Times-1)*(Times-1))
1000  {
1001  delete IntPts[g];
1002  IntPts[g] = new IntegrationRule((Times-1)*(Times-1));
1003  for (int k = 0, j = 1; j < Times; j++)
1004  for (int i = 1; i < Times; i++, k++)
1005  {
1006  IntegrationPoint &ip = IntPts[g]->IntPoint(k);
1007  ip.x = double(i) / Times;
1008  ip.y = double(j) / Times;
1009  ip.z = 0.0;
1010  }
1011  }
1012  }
1013  break;
1014 
1015  default:
1016  mfem_error("GeometryRefiner::RefineInterior(...)");
1017  }
1018 
1019  return IntPts[g];
1020 }
1021 
1023 
1024 }
static const int InvOrient[NumOrient]
Definition: geom.hpp:87
Class for an integration rule - an Array of IntegrationPoint.
Definition: intrules.hpp:83
DenseMatrix & GetPointMat()
Read and write access to the underlying point matrix describing the transformation.
Definition: eltrans.hpp:122
static const int NumGeom
Definition: geom.hpp:34
void JacToPerfJac(int GeomType, const DenseMatrix &J, DenseMatrix &PJ) const
Definition: geom.cpp:428
static void GetRandomPoint(int GeomType, IntegrationPoint &ip)
Definition: geom.cpp:190
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
Definition: table.cpp:468
static const int FaceVert[NumFaces][MaxFaceVert]
Definition: geom.hpp:157
void SetIntPoint(const IntegrationPoint *ip)
Definition: eltrans.hpp:51
RefinedGeometry * Refine(int Geom, int Times, int ETimes=1)
Definition: geom.cpp:566
Data type dense matrix using column-major storage.
Definition: densemat.hpp:22
static const double Volume[NumGeom]
Definition: geom.hpp:37
static const int NumBdrArray[]
Definition: geom.hpp:35
static const int NumEdges[NumGeom]
Definition: geom.hpp:40
Array< int > RefEdges
Definition: geom.hpp:191
const IntegrationRule * GetVertices(int GeomType)
Definition: geom.cpp:172
static const int NumFaces[NumGeom]
Definition: geom.hpp:41
static const int InvOrient[NumOrient]
Definition: geom.hpp:125
Geometry Geometries
Definition: geom.cpp:544
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
Definition: intrules.hpp:225
static const int Edges[NumEdges][2]
Definition: geom.hpp:107
int dim
Definition: ex3.cpp:47
static const int Dimension[NumGeom]
Definition: geom.hpp:38
const IntegrationRule * RefineInterior(int Geom, int Times)
Definition: geom.cpp:944
static const int FaceTypes[NumFaces]
Definition: geom.hpp:173
const DenseMatrix & Jacobian()
Definition: eltrans.hpp:64
static const int NumVerts[NumGeom]
Definition: geom.hpp:39
static const int Edges[NumEdges][2]
Definition: geom.hpp:95
GeometryRefiner GlobGeometryRefiner
Definition: geom.cpp:1022
Class for linear FE on tetrahedron.
Definition: fe.hpp:778
IntegrationRule RefPts
Definition: geom.hpp:190
Class for linear FE on triangle.
Definition: fe.hpp:498
static const int InvOrient[NumOrient]
Definition: geom.hpp:145
static const int Orient[NumOrient][NumVert]
Definition: geom.hpp:98
static const int Edges[NumEdges][2]
Definition: geom.hpp:153
static const char * Name[NumGeom]
Definition: geom.hpp:36
void CalcInverse(const DenseMatrix &a, DenseMatrix &inva)
Definition: densemat.cpp:3010
static const int InvOrient[NumOrient]
Definition: geom.hpp:99
static const int Edges[NumEdges][2]
Definition: geom.hpp:133
static bool ProjectPoint(int GeomType, const IntegrationPoint &beg, IntegrationPoint &end)
Definition: geom.cpp:317
void GetPerfPointMat(int GeomType, DenseMatrix &pm)
Definition: geom.cpp:367
void mfem_error(const char *msg)
Definition: error.cpp:106
static const int FaceVert[NumFaces][MaxFaceVert]
Definition: geom.hpp:175
static const int FaceVert[NumFaces][NumVert]
Definition: geom.hpp:115
Class for integration point with weight.
Definition: intrules.hpp:25
static const int FaceVert[NumFaces][NumVert]
Definition: geom.hpp:141
static const int Orient[NumOrient][NumVert]
Definition: geom.hpp:144
void SetFE(const FiniteElement *FE)
Definition: eltrans.hpp:108
static const int Edges[NumEdges][2]
Definition: geom.hpp:171
const double * ClosedPoints(const int p, const int type=Quadrature1D::GaussLobatto)
Definition: fe.hpp:1392
static const int Orient[NumOrient][NumVert]
Definition: geom.hpp:86
static bool CheckPoint(int GeomType, const IntegrationPoint &ip)
Check if the given point is inside the given reference element.
Definition: geom.cpp:255
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
Definition: densemat.hpp:82
Array< int > RefGeoms
Definition: geom.hpp:191
static const int Orient[NumOrient][NumVert]
Definition: geom.hpp:123
Poly_1D poly1d
Definition: fe.cpp:6535