MFEM  v3.2
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));
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  // horizontal edges
651  for (l = k = 0; k < Times; k += Times/ETimes)
652  {
653  j = k*(Times+1)-((k-1)*k)/2;
654  for (i = 0; i < Times-k; i++)
655  {
656  E[l++] = j; j++;
657  E[l++] = j;
658  }
659  }
660  // diagonal edges
661  for (k = Times; k > 0; k -= Times/ETimes)
662  {
663  j = k;
664  for (i = 0; i < k; i++)
665  {
666  E[l++] = j; j += Times-i;
667  E[l++] = j;
668  }
669  }
670  // vertical edges
671  for (k = 0; k < Times; k += Times/ETimes)
672  {
673  j = k;
674  for (i = 0; i < Times-k; i++)
675  {
676  E[l++] = j; j += Times-i+1;
677  E[l++] = j;
678  }
679  }
680 
681  return RGeom[2];
682  }
683 
684  case Geometry::SQUARE:
685  {
686  if (RGeom[3] != NULL && RGeom[3]->Times == Times &&
687  RGeom[3]->ETimes == ETimes)
688  {
689  return RGeom[3];
690  }
691 
692  if (RGeom[3] != NULL)
693  {
694  delete RGeom[3];
695  }
696  RGeom[3] = new RefinedGeometry ((Times+1)*(Times+1), 4*Times*Times,
697  4*(ETimes+1)*Times);
698  RGeom[3]->Times = Times;
699  RGeom[3]->ETimes = ETimes;
700  for (k = j = 0; j <= Times; j++)
701  for (i = 0; i <= Times; i++, k++)
702  {
703  IntegrationPoint &ip = RGeom[3]->RefPts.IntPoint(k);
704  if (type == 0)
705  {
706  ip.x = double(i) / Times;
707  ip.y = double(j) / Times;
708  }
709  else
710  {
711  ip.x = cp[i];
712  ip.y = cp[j];
713  }
714  }
715  Array<int> &G = RGeom[3]->RefGeoms;
716  for (l = k = j = 0; j < Times; j++, k++)
717  for (i = 0; i < Times; i++, k++)
718  {
719  G[l++] = k;
720  G[l++] = k+1;
721  G[l++] = k+Times+2;
722  G[l++] = k+Times+1;
723  }
724  Array<int> &E = RGeom[3]->RefEdges;
725  // horizontal edges
726  for (l = k = 0; k <= Times; k += Times/ETimes)
727  {
728  for (i = 0, j = k*(Times+1); i < Times; i++)
729  {
730  E[l++] = j; j++;
731  E[l++] = j;
732  }
733  }
734  // vertical edges (in right-to-left order)
735  for (k = Times; k >= 0; k -= Times/ETimes)
736  {
737  for (i = 0, j = k; i < Times; i++)
738  {
739  E[l++] = j; j += Times+1;
740  E[l++] = j;
741  }
742  }
743 
744  return RGeom[3];
745  }
746 
747  case Geometry::CUBE:
748  {
749  const int g = Geometry::CUBE;
750  if (RGeom[g] != NULL && RGeom[g]->Times == Times &&
751  RGeom[g]->ETimes == ETimes)
752  {
753  return RGeom[g];
754  }
755 
756  if (RGeom[g] != NULL)
757  {
758  delete RGeom[g];
759  }
760  RGeom[g] = new RefinedGeometry ((Times+1)*(Times+1)*(Times+1),
761  8*Times*Times*Times, 0);
762  RGeom[g]->Times = Times;
763  RGeom[g]->ETimes = ETimes;
764  for (l = k = 0; k <= Times; k++)
765  for (j = 0; j <= Times; j++)
766  for (i = 0; i <= Times; i++, l++)
767  {
768  IntegrationPoint &ip = RGeom[g]->RefPts.IntPoint(l);
769  if (type == 0)
770  {
771  ip.x = double(i) / Times;
772  ip.y = double(j) / Times;
773  ip.z = double(k) / Times;
774  }
775  else
776  {
777  ip.x = cp[i];
778  ip.y = cp[j];
779  ip.z = cp[k];
780  }
781  }
782  Array<int> &G = RGeom[g]->RefGeoms;
783  for (l = k = 0; k < Times; k++)
784  for (j = 0; j < Times; j++)
785  for (i = 0; i < Times; i++)
786  {
787  G[l++] = i+0 + (j+0 + (k+0) * (Times+1)) * (Times+1);
788  G[l++] = i+1 + (j+0 + (k+0) * (Times+1)) * (Times+1);
789  G[l++] = i+1 + (j+1 + (k+0) * (Times+1)) * (Times+1);
790  G[l++] = i+0 + (j+1 + (k+0) * (Times+1)) * (Times+1);
791  G[l++] = i+0 + (j+0 + (k+1) * (Times+1)) * (Times+1);
792  G[l++] = i+1 + (j+0 + (k+1) * (Times+1)) * (Times+1);
793  G[l++] = i+1 + (j+1 + (k+1) * (Times+1)) * (Times+1);
794  G[l++] = i+0 + (j+1 + (k+1) * (Times+1)) * (Times+1);
795  }
796 
797  return RGeom[g];
798  }
799 
801  {
802  const int g = Geometry::TETRAHEDRON;
803  if (RGeom[g] != NULL && RGeom[g]->Times == Times &&
804  RGeom[g]->ETimes == ETimes)
805  {
806  return RGeom[g];
807  }
808 
809  if (RGeom[g] != NULL)
810  {
811  delete RGeom[g];
812  }
813 
814  // subdivide the tetrahedron with vertices
815  // (0,0,0), (0,0,1), (1,1,1), (0,1,1)
816 
817  // vertices: 0 <= i <= j <= k <= Times
818  // (3-combination with repetitions)
819  // number of vertices: (n+3)*(n+2)*(n+1)/6, n = Times
820 
821  // elements: the vertices are: v1=(i,j,k), v2=v1+u1, v3=v2+u2, v4=v3+u3
822  // where 0 <= i <= j <= k <= n-1 and
823  // u1,u2,u3 is a permutation of (1,0,0),(0,1,0),(0,0,1)
824  // such that all v2,v3,v4 have non-decreasing components
825  // number of elements: n^3
826 
827  const int n = Times;
828  RGeom[g] = new RefinedGeometry((n+3)*(n+2)*(n+1)/6, 4*n*n*n, 0);
829  // enumerate and define the vertices
830  Array<int> vi((n+1)*(n+1)*(n+1));
831  vi = -1;
832  int m = 0;
833  for (k = 0; k <= n; k++)
834  for (j = 0; j <= k; j++)
835  for (i = 0; i <= j; i++)
836  {
837  IntegrationPoint &ip = RGeom[g]->RefPts.IntPoint(m);
838  // map the coordinates to the reference tetrahedron
839  // (0,0,0) -> (0,0,0)
840  // (0,0,1) -> (1,0,0)
841  // (1,1,1) -> (0,1,0)
842  // (0,1,1) -> (0,0,1)
843  if (type == 0)
844  {
845  ip.x = double(k - j) / n;
846  ip.y = double(i) / n;
847  ip.z = double(j - i) / n;
848  }
849  else
850  {
851  double w = cp[k-j] + cp[i] + cp[j-i] + cp[Times-k];
852  ip.x = cp[k-j]/w;
853  ip.y = cp[i]/w;
854  ip.z = cp[j-i]/w;
855  }
856  l = i + (j + k * (n+1)) * (n+1);
857  vi[l] = m;
858  m++;
859  }
860  if (m != (n+3)*(n+2)*(n+1)/6)
861  {
862  mfem_error("GeometryRefiner::Refine() for TETRAHEDRON #1");
863  }
864  // elements
865  Array<int> &G = RGeom[g]->RefGeoms;
866  m = 0;
867  for (k = 0; k < n; k++)
868  for (j = 0; j <= k; j++)
869  for (i = 0; i <= j; i++)
870  {
871  // the ordering of the vertices is chosen to ensure:
872  // 1) correct orientation
873  // 2) the x,y,z edges are in the set of edges
874  // {(0,1),(2,3), (0,2),(1,3)}
875  // (goal is to ensure that subsequent refinement using
876  // this procedure preserves the six tetrahedral shapes)
877 
878  // zyx: (i,j,k)-(i,j,k+1)-(i+1,j+1,k+1)-(i,j+1,k+1)
879  G[m++] = vi[i+0 + (j+0 + (k+0) * (n+1)) * (n+1)];
880  G[m++] = vi[i+0 + (j+0 + (k+1) * (n+1)) * (n+1)];
881  G[m++] = vi[i+1 + (j+1 + (k+1) * (n+1)) * (n+1)];
882  G[m++] = vi[i+0 + (j+1 + (k+1) * (n+1)) * (n+1)];
883  if (j < k)
884  {
885  // yzx: (i,j,k)-(i+1,j+1,k+1)-(i,j+1,k)-(i,j+1,k+1)
886  G[m++] = vi[i+0 + (j+0 + (k+0) * (n+1)) * (n+1)];
887  G[m++] = vi[i+1 + (j+1 + (k+1) * (n+1)) * (n+1)];
888  G[m++] = vi[i+0 + (j+1 + (k+0) * (n+1)) * (n+1)];
889  G[m++] = vi[i+0 + (j+1 + (k+1) * (n+1)) * (n+1)];
890  // yxz: (i,j,k)-(i,j+1,k)-(i+1,j+1,k+1)-(i+1,j+1,k)
891  G[m++] = vi[i+0 + (j+0 + (k+0) * (n+1)) * (n+1)];
892  G[m++] = vi[i+0 + (j+1 + (k+0) * (n+1)) * (n+1)];
893  G[m++] = vi[i+1 + (j+1 + (k+1) * (n+1)) * (n+1)];
894  G[m++] = vi[i+1 + (j+1 + (k+0) * (n+1)) * (n+1)];
895  }
896  if (i < j)
897  {
898  // xzy: (i,j,k)-(i+1,j,k)-(i+1,j+1,k+1)-(i+1,j,k+1)
899  G[m++] = vi[i+0 + (j+0 + (k+0) * (n+1)) * (n+1)];
900  G[m++] = vi[i+1 + (j+0 + (k+0) * (n+1)) * (n+1)];
901  G[m++] = vi[i+1 + (j+1 + (k+1) * (n+1)) * (n+1)];
902  G[m++] = vi[i+1 + (j+0 + (k+1) * (n+1)) * (n+1)];
903  if (j < k)
904  {
905  // xyz: (i,j,k)-(i+1,j+1,k+1)-(i+1,j,k)-(i+1,j+1,k)
906  G[m++] = vi[i+0 + (j+0 + (k+0) * (n+1)) * (n+1)];
907  G[m++] = vi[i+1 + (j+1 + (k+1) * (n+1)) * (n+1)];
908  G[m++] = vi[i+1 + (j+0 + (k+0) * (n+1)) * (n+1)];
909  G[m++] = vi[i+1 + (j+1 + (k+0) * (n+1)) * (n+1)];
910  }
911  // zxy: (i,j,k)-(i+1,j+1,k+1)-(i,j,k+1)-(i+1,j,k+1)
912  G[m++] = vi[i+0 + (j+0 + (k+0) * (n+1)) * (n+1)];
913  G[m++] = vi[i+1 + (j+1 + (k+1) * (n+1)) * (n+1)];
914  G[m++] = vi[i+0 + (j+0 + (k+1) * (n+1)) * (n+1)];
915  G[m++] = vi[i+1 + (j+0 + (k+1) * (n+1)) * (n+1)];
916  }
917  }
918  if (m != 4*n*n*n)
919  {
920  mfem_error("GeometryRefiner::Refine() for TETRAHEDRON #2");
921  }
922  for (i = 0; i < m; i++)
923  if (G[i] < 0)
924  {
925  mfem_error("GeometryRefiner::Refine() for TETRAHEDRON #3");
926  }
927 
928  return RGeom[g];
929  }
930 
931  default:
932 
933  return RGeom[0];
934  }
935 }
936 
938 {
939  int g = Geom;
940 
941  switch (g)
942  {
943  case Geometry::SEGMENT:
944  {
945  if (Times < 2)
946  {
947  return NULL;
948  }
949  if (IntPts[g] == NULL || IntPts[g]->GetNPoints() != Times-1)
950  {
951  delete IntPts[g];
952  IntPts[g] = new IntegrationRule(Times-1);
953  for (int i = 1; i < Times; i++)
954  {
955  IntegrationPoint &ip = IntPts[g]->IntPoint(i-1);
956  ip.x = double(i) / Times;
957  ip.y = ip.z = 0.0;
958  }
959  }
960  }
961  break;
962 
963  case Geometry::TRIANGLE:
964  {
965  if (Times < 3)
966  {
967  return NULL;
968  }
969  if (IntPts[g] == NULL ||
970  IntPts[g]->GetNPoints() != ((Times-1)*(Times-2))/2)
971  {
972  delete IntPts[g];
973  IntPts[g] = new IntegrationRule(((Times-1)*(Times-2))/2);
974  for (int k = 0, j = 1; j < Times-1; j++)
975  for (int i = 1; i < Times-j; i++, k++)
976  {
977  IntegrationPoint &ip = IntPts[g]->IntPoint(k);
978  ip.x = double(i) / Times;
979  ip.y = double(j) / Times;
980  ip.z = 0.0;
981  }
982  }
983  }
984  break;
985 
986  case Geometry::SQUARE:
987  {
988  if (Times < 2)
989  {
990  return NULL;
991  }
992  if (IntPts[g] == NULL || IntPts[g]->GetNPoints() != (Times-1)*(Times-1))
993  {
994  delete IntPts[g];
995  IntPts[g] = new IntegrationRule((Times-1)*(Times-1));
996  for (int k = 0, j = 1; j < Times; j++)
997  for (int i = 1; i < Times; i++, k++)
998  {
999  IntegrationPoint &ip = IntPts[g]->IntPoint(k);
1000  ip.x = double(i) / Times;
1001  ip.y = double(j) / Times;
1002  ip.z = 0.0;
1003  }
1004  }
1005  }
1006  break;
1007 
1008  default:
1009  mfem_error("GeometryRefiner::RefineInterior(...)");
1010  }
1011 
1012  return IntPts[g];
1013 }
1014 
1016 
1017 }
static const int InvOrient[NumOrient]
Definition: geom.hpp:87
Class for integration rule.
Definition: intrules.hpp:83
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:451
static const int FaceVert[NumFaces][MaxFaceVert]
Definition: geom.hpp:157
void SetIntPoint(const IntegrationPoint *ip)
Definition: eltrans.hpp:35
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
const double * ClosedPoints(const int p)
Definition: fe.cpp:6523
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:231
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:937
static const int FaceTypes[NumFaces]
Definition: geom.hpp:173
static const int NumVerts[NumGeom]
Definition: geom.hpp:39
static const int Edges[NumEdges][2]
Definition: geom.hpp:95
GeometryRefiner GlobGeometryRefiner
Definition: geom.cpp:1015
Class for linear FE on tetrahedron.
Definition: fe.hpp:654
IntegrationRule RefPts
Definition: geom.hpp:190
Class for linear FE on triangle.
Definition: fe.hpp:374
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
virtual const DenseMatrix & Jacobian()
Definition: eltrans.cpp:52
void CalcInverse(const DenseMatrix &a, DenseMatrix &inva)
Definition: densemat.cpp:3012
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:23
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:81
static const int Edges[NumEdges][2]
Definition: geom.hpp:171
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:71
Array< int > RefGeoms
Definition: geom.hpp:191
static const int Orient[NumOrient][NumVert]
Definition: geom.hpp:123
Poly_1D poly1d
Definition: fe.cpp:6614