18 {
"Point",
"Segment",
"Triangle",
"Square",
"Tetrahedron",
"Cube" };
21 { 1.0, 1.0, 0.5, 1.0, 1./6, 1.0 };
115 GeomCenter[
POINT].
x = 0.0;
116 GeomCenter[
POINT].
y = 0.0;
117 GeomCenter[
POINT].
z = 0.0;
135 GeomCenter[
CUBE].
x = 0.5;
136 GeomCenter[
CUBE].
y = 0.5;
137 GeomCenter[
CUBE].
z = 0.5;
139 GeomToPerfGeomJac[
POINT] = NULL;
146 PerfGeomToGeomJac[
POINT] = NULL;
147 PerfGeomToGeomJac[
SEGMENT] = NULL;
149 PerfGeomToGeomJac[
SQUARE] = NULL;
151 PerfGeomToGeomJac[
CUBE] = NULL;
175 GeomToPerfGeomJac[
CUBE]->
Diag(1.0, 3);
180 for (
int i = 0; i <
NumGeom; i++)
182 delete PerfGeomToGeomJac[i];
183 delete GeomToPerfGeomJac[i];
214 ip.
x = double(rand()) / RAND_MAX;
217 ip.
x = double(rand()) / RAND_MAX;
218 ip.
y = double(rand()) / RAND_MAX;
219 if (ip.
x + ip.
y > 1.0)
226 ip.
x = double(rand()) / RAND_MAX;
227 ip.
y = double(rand()) / RAND_MAX;
230 ip.
x = double(rand()) / RAND_MAX;
231 ip.
y = double(rand()) / RAND_MAX;
232 ip.
z = double(rand()) / RAND_MAX;
235 if (ip.
x + ip.
y > 1.0)
242 if (ip.
x + ip.
z > 1.0)
245 ip.
x = ip.
x + ip.
z - 1.0;
250 else if (ip.
x + ip.
y + ip.
z > 1.0)
254 ip.
x = 1.0 - x - ip.
z;
255 ip.
y = 1.0 - x - ip.
y;
261 ip.
x = double(rand()) / RAND_MAX;
262 ip.
y = double(rand()) / RAND_MAX;
263 ip.
z = double(rand()) / RAND_MAX;
266 MFEM_ABORT(
"Unknown type of reference element!");
275 inline bool NearlyEqual(
double x,
double y,
double eps)
277 return std::abs(x-y) <= eps;
282 inline bool FuzzyGT(
double x,
double y,
double eps)
284 return (x > y + eps);
289 inline bool FuzzyLT(
double x,
double y,
double eps)
291 return (x < y - eps);
302 if (ip.
x != 0.0) {
return false; }
305 if (ip.
x < 0.0 || ip.
x > 1.0) {
return false; }
308 if (ip.
x < 0.0 || ip.
y < 0.0 || ip.
x+ip.
y > 1.0) {
return false; }
311 if (ip.
x < 0.0 || ip.
x > 1.0 || ip.
y < 0.0 || ip.
y > 1.0)
315 if (ip.
x < 0.0 || ip.
y < 0.0 || ip.
z < 0.0 ||
316 ip.
x+ip.
y+ip.
z > 1.0) {
return false; }
319 if (ip.
x < 0.0 || ip.
x > 1.0 || ip.
y < 0.0 || ip.
y > 1.0 ||
320 ip.
z < 0.0 || ip.
z > 1.0) {
return false; }
323 MFEM_ABORT(
"Unknown type of reference element!");
333 if (! internal::NearlyEqual(ip.
x, 0.0, eps))
339 if ( internal::FuzzyLT(ip.
x, 0.0, eps)
340 || internal::FuzzyGT(ip.
x, 1.0, eps) )
346 if ( internal::FuzzyLT(ip.
x, 0.0, eps)
347 || internal::FuzzyLT(ip.
y, 0.0, eps)
348 || internal::FuzzyGT(ip.
x+ip.
y, 1.0, eps) )
354 if ( internal::FuzzyLT(ip.
x, 0.0, eps)
355 || internal::FuzzyGT(ip.
x, 1.0, eps)
356 || internal::FuzzyLT(ip.
y, 0.0, eps)
357 || internal::FuzzyGT(ip.
y, 1.0, eps) )
363 if ( internal::FuzzyLT(ip.
x, 0.0, eps)
364 || internal::FuzzyLT(ip.
y, 0.0, eps)
365 || internal::FuzzyLT(ip.
z, 0.0, eps)
366 || internal::FuzzyGT(ip.
x+ip.
y+ip.
z, 1.0, eps) )
372 if ( internal::FuzzyLT(ip.
x, 0.0, eps)
373 || internal::FuzzyGT(ip.
x, 1.0, eps)
374 || internal::FuzzyLT(ip.
y, 0.0, eps)
375 || internal::FuzzyGT(ip.
y, 1.0, eps)
376 || internal::FuzzyLT(ip.
z, 0.0, eps)
377 || internal::FuzzyGT(ip.
z, 1.0, eps) )
383 MFEM_ABORT(
"Unknown type of reference element!");
392 template <
int N,
int dim>
393 inline bool IntersectSegment(
double lbeg[N],
double lend[N],
398 for (
int i = 0; i < N; i++)
400 lbeg[i] = std::max(lbeg[i], 0.0);
404 t = std::min(t, lbeg[i]/(lbeg[i]-lend[i]));
409 if (
dim >= 1) { end.
x = t*lend[0] + (1.0-t)*lbeg[0]; }
410 if (
dim >= 2) { end.
y = t*lend[1] + (1.0-t)*lbeg[1]; }
411 if (
dim >= 3) { end.
z = t*lend[2] + (1.0-t)*lbeg[2]; }
417 inline bool ProjectTriangle(
double &x,
double &y)
422 if (y < 0.0) { y = 0.0; }
423 else if (y > 1.0) { y = 1.0; }
428 if (x > 1.0) { x = 1.0; }
432 const double l3 = 1.0-x-y;
435 if (y - x > 1.0) { x = 0.0; y = 1.0; }
436 else if (y - x < -1.0) { x = 1.0; y = 0.0; }
437 else { x += l3/2; y += l3/2; }
453 if (end.
x != 0.0) { end.
x = 0.0;
return false; }
458 if (end.
x < 0.0) { end.
x = 0.0;
return false; }
459 if (end.
x > 1.0) { end.
x = 1.0;
return false; }
464 double lend[3] = { end.
x, end.
y, 1-end.
x-end.
y };
465 double lbeg[3] = { beg.
x, beg.
y, 1-beg.
x-beg.
y };
466 return internal::IntersectSegment<3,2>(lbeg, lend, end);
470 double lend[4] = { end.
x, end.
y, 1-end.
x, 1.0-end.
y };
471 double lbeg[4] = { beg.
x, beg.
y, 1-beg.
x, 1.0-beg.
y };
472 return internal::IntersectSegment<4,2>(lbeg, lend, end);
476 double lend[4] = { end.
x, end.
y, end.
z, 1.0-end.
x-end.
y-end.
z };
477 double lbeg[4] = { beg.
x, beg.
y, beg.
z, 1.0-beg.
x-beg.
y-beg.
z };
478 return internal::IntersectSegment<4,3>(lbeg, lend, end);
482 double lend[6] = { end.
x, end.
y, end.
z,
483 1.0-end.
x, 1.0-end.
y, 1.0-end.
z
485 double lbeg[6] = { beg.
x, beg.
y, beg.
z,
486 1.0-beg.
x, 1.0-beg.
y, 1.0-beg.
z
488 return internal::IntersectSegment<6,3>(lbeg, lend, end);
491 MFEM_ABORT(
"Unknown type of reference element!");
507 if (ip.
x < 0.0) { ip.
x = 0.0;
return false; }
508 else if (ip.
x > 1.0) { ip.
x = 1.0;
return false; }
514 return internal::ProjectTriangle(ip.
x, ip.
y);
520 if (ip.
x < 0.0) { in_x =
false; ip.
x = 0.0; }
521 else if (ip.
x > 1.0) { in_x =
false; ip.
x = 1.0; }
522 else { in_x =
true; }
523 if (ip.
y < 0.0) { in_y =
false; ip.
y = 0.0; }
524 else if (ip.
y > 1.0) { in_y =
false; ip.
y = 1.0; }
525 else { in_y =
true; }
534 internal::ProjectTriangle(ip.
x, ip.
y);
540 internal::ProjectTriangle(ip.
x, ip.
z);
546 internal::ProjectTriangle(ip.
y, ip.
z);
549 const double l4 = 1.0-ip.
x-ip.
y-ip.
z;
552 const double l4_3 = l4/3;
555 internal::ProjectTriangle(ip.
x, ip.
y);
556 ip.
z = 1.0-ip.
x-ip.
y;
564 bool in_x, in_y, in_z;
565 if (ip.
x < 0.0) { in_x =
false; ip.
x = 0.0; }
566 else if (ip.
x > 1.0) { in_x =
false; ip.
x = 1.0; }
567 else { in_x =
true; }
568 if (ip.
y < 0.0) { in_y =
false; ip.
y = 0.0; }
569 else if (ip.
y > 1.0) { in_y =
false; ip.
y = 1.0; }
570 else { in_y =
true; }
571 if (ip.
z < 0.0) { in_z =
false; ip.
z = 0.0; }
572 else if (ip.
z > 1.0) { in_z =
false; ip.
z = 1.0; }
573 else { in_z =
true; }
574 return in_x && in_y && in_z;
578 MFEM_ABORT(
"Reference element type is not supported!");
598 pm(0,0) = 0.0; pm(1,0) = 0.0;
599 pm(0,1) = 1.0; pm(1,1) = 0.0;
600 pm(0,2) = 0.5; pm(1,2) = 0.86602540378443864676;
607 pm(0,0) = 0.0; pm(1,0) = 0.0;
608 pm(0,1) = 1.0; pm(1,1) = 0.0;
609 pm(0,2) = 1.0; pm(1,2) = 1.0;
610 pm(0,3) = 0.0; pm(1,3) = 1.0;
617 pm(0,0) = 0.0; pm(1,0) = 0.0; pm(2,0) = 0.0;
618 pm(0,1) = 1.0; pm(1,1) = 0.0; pm(2,1) = 0.0;
619 pm(0,2) = 0.5; pm(1,2) = 0.86602540378443864676; pm(2,2) = 0.0;
620 pm(0,3) = 0.5; pm(1,3) = 0.28867513459481288225;
621 pm(2,3) = 0.81649658092772603273;
628 pm(0,0) = 0.0; pm(1,0) = 0.0; pm(2,0) = 0.0;
629 pm(0,1) = 1.0; pm(1,1) = 0.0; pm(2,1) = 0.0;
630 pm(0,2) = 1.0; pm(1,2) = 1.0; pm(2,2) = 0.0;
631 pm(0,3) = 0.0; pm(1,3) = 1.0; pm(2,3) = 0.0;
632 pm(0,4) = 0.0; pm(1,4) = 0.0; pm(2,4) = 1.0;
633 pm(0,5) = 1.0; pm(1,5) = 0.0; pm(2,5) = 1.0;
634 pm(0,6) = 1.0; pm(1,6) = 1.0; pm(2,6) = 1.0;
635 pm(0,7) = 0.0; pm(1,7) = 1.0; pm(2,7) = 1.0;
640 mfem_error (
"Geometry::GetPerfPointMat (...)");
647 if (PerfGeomToGeomJac[GeomType])
649 Mult(J, *PerfGeomToGeomJac[GeomType], PJ);
686 {0, 1, 2}, {1, 0, 2}, {2, 0, 1},
687 {2, 1, 0}, {1, 2, 0}, {0, 2, 1}
698 {{1, 0}, {3, -4}, {2, 1}, {3, 2}};
704 {0, 1, 2, 3}, {0, 3, 2, 1}, {1, 2, 3, 0}, {1, 0, 3, 2},
705 {2, 3, 0, 1}, {2, 1, 0, 3}, {3, 0, 1, 2}, {3, 2, 1, 0}
712 {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
721 {{1, 2, 3}, {0, 3, 2}, {0, 1, 3}, {0, 2, 1}};
726 {{1, 0}, {2, 1}, {3, 2}, {2, 3}, {3, 4}, {3, 5}};
731 {0, 1}, {1, 2}, {3, 2}, {0, 3}, {4, 5}, {5, 6},
732 {7, 6}, {4, 7}, {0, 4}, {1, 5}, {2, 6}, {3, 7}
743 {3, 2, 1, 0}, {0, 1, 5, 4}, {1, 2, 6, 5},
744 {2, 3, 7, 6}, {3, 0, 4, 7}, {4, 5, 6, 7}
751 {1, 0}, {3, 3}, {4, 8},
772 for (
int j = 0; j < RGeom[i].Size(); j++) {
delete RGeom[i][j]; }
773 for (
int j = 0; j < IntPts[i].Size(); j++) {
delete IntPts[i][j]; }
777 RefinedGeometry *GeometryRefiner::FindInRGeom(
int Geom,
int Times,
int ETimes,
781 for (
int i = 0; i < RGA.
Size(); i++)
792 IntegrationRule *GeometryRefiner::FindInIntPts(
int Geom,
int NPts)
794 Array<IntegrationRule *> &IPA = IntPts[Geom];
795 for (
int i = 0; i < IPA.Size(); i++)
797 IntegrationRule &ir = *IPA[i];
798 if (ir.GetNPoints() == NPts) {
return &ir; }
807 Times = std::max(Times, 1);
808 ETimes = std::max(ETimes, 1);
812 if (RG) {
return RG; }
835 for (i = 0; i <= Times; i++)
841 for (i = 0; i < Times; i++)
854 3*Times*(ETimes+1), 3*Times);
858 for (k = j = 0; j <= Times; j++)
859 for (i = 0; i <= Times-j; i++, k++)
862 ip.
x = cp[i]/(cp[i] + cp[j] + cp[Times-i-j]);
863 ip.
y = cp[j]/(cp[i] + cp[j] + cp[Times-i-j]);
866 for (l = k = j = 0; j < Times; j++, k++)
867 for (i = 0; i < Times-j; i++, k++)
871 G[l++] = k+Times-j+1;
875 G[l++] = k+Times-j+2;
876 G[l++] = k+Times-j+1;
882 for (k = 0; k < Times; k += Times/ETimes)
884 int < = (k == 0) ? lb : li;
885 j = k*(Times+1)-((k-1)*k)/2;
886 for (i = 0; i < Times-k; i++)
893 for (k = Times; k > 0; k -= Times/ETimes)
895 int < = (k == Times) ? lb : li;
897 for (i = 0; i < k; i++)
899 E[lt++] = j; j += Times-i;
904 for (k = 0; k < Times; k += Times/ETimes)
906 int < = (k == 0) ? lb : li;
908 for (i = 0; i < Times-k; i++)
910 E[lt++] = j; j += Times-i+1;
922 4*(ETimes+1)*Times, 4*Times);
926 for (k = j = 0; j <= Times; j++)
927 for (i = 0; i <= Times; i++, k++)
934 for (l = k = j = 0; j < Times; j++, k++)
935 for (i = 0; i < Times; i++, k++)
945 for (k = 0; k <= Times; k += Times/ETimes)
947 int < = (k == 0 || k == Times) ? lb : li;
948 for (i = 0, j = k*(Times+1); i < Times; i++)
955 for (k = Times; k >= 0; k -= Times/ETimes)
957 int < = (k == Times || k == 0) ? lb : li;
958 for (i = 0, j = k; i < Times; i++)
960 E[lt++] = j; j += Times+1;
972 8*Times*Times*Times, 0);
976 for (l = k = 0; k <= Times; k++)
977 for (j = 0; j <= Times; j++)
978 for (i = 0; i <= Times; i++, l++)
986 for (l = k = 0; k < Times; k++)
987 for (j = 0; j < Times; j++)
988 for (i = 0; i < Times; i++)
990 G[l++] = i+0 + (j+0 + (k+0) * (Times+1)) * (Times+1);
991 G[l++] = i+1 + (j+0 + (k+0) * (Times+1)) * (Times+1);
992 G[l++] = i+1 + (j+1 + (k+0) * (Times+1)) * (Times+1);
993 G[l++] = i+0 + (j+1 + (k+0) * (Times+1)) * (Times+1);
994 G[l++] = i+0 + (j+0 + (k+1) * (Times+1)) * (Times+1);
995 G[l++] = i+1 + (j+0 + (k+1) * (Times+1)) * (Times+1);
996 G[l++] = i+1 + (j+1 + (k+1) * (Times+1)) * (Times+1);
997 G[l++] = i+0 + (j+1 + (k+1) * (Times+1)) * (Times+1);
1019 const int n = Times;
1028 for (k = 0; k <= n; k++)
1029 for (j = 0; j <= k; j++)
1030 for (i = 0; i <= j; i++)
1038 double w = cp[k-j] + cp[i] + cp[j-i] + cp[Times-k];
1042 l = i + (j + k * (n+1)) * (n+1);
1046 if (m != (n+3)*(n+2)*(n+1)/6)
1048 mfem_error(
"GeometryRefiner::Refine() for TETRAHEDRON #1");
1053 for (k = 0; k < n; k++)
1054 for (j = 0; j <= k; j++)
1055 for (i = 0; i <= j; i++)
1065 G[m++] = vi[i+0 + (j+0 + (k+0) * (n+1)) * (n+1)];
1066 G[m++] = vi[i+0 + (j+0 + (k+1) * (n+1)) * (n+1)];
1067 G[m++] = vi[i+1 + (j+1 + (k+1) * (n+1)) * (n+1)];
1068 G[m++] = vi[i+0 + (j+1 + (k+1) * (n+1)) * (n+1)];
1072 G[m++] = vi[i+0 + (j+0 + (k+0) * (n+1)) * (n+1)];
1073 G[m++] = vi[i+1 + (j+1 + (k+1) * (n+1)) * (n+1)];
1074 G[m++] = vi[i+0 + (j+1 + (k+0) * (n+1)) * (n+1)];
1075 G[m++] = vi[i+0 + (j+1 + (k+1) * (n+1)) * (n+1)];
1077 G[m++] = vi[i+0 + (j+0 + (k+0) * (n+1)) * (n+1)];
1078 G[m++] = vi[i+0 + (j+1 + (k+0) * (n+1)) * (n+1)];
1079 G[m++] = vi[i+1 + (j+1 + (k+1) * (n+1)) * (n+1)];
1080 G[m++] = vi[i+1 + (j+1 + (k+0) * (n+1)) * (n+1)];
1085 G[m++] = vi[i+0 + (j+0 + (k+0) * (n+1)) * (n+1)];
1086 G[m++] = vi[i+1 + (j+0 + (k+0) * (n+1)) * (n+1)];
1087 G[m++] = vi[i+1 + (j+1 + (k+1) * (n+1)) * (n+1)];
1088 G[m++] = vi[i+1 + (j+0 + (k+1) * (n+1)) * (n+1)];
1092 G[m++] = vi[i+0 + (j+0 + (k+0) * (n+1)) * (n+1)];
1093 G[m++] = vi[i+1 + (j+1 + (k+1) * (n+1)) * (n+1)];
1094 G[m++] = vi[i+1 + (j+0 + (k+0) * (n+1)) * (n+1)];
1095 G[m++] = vi[i+1 + (j+1 + (k+0) * (n+1)) * (n+1)];
1098 G[m++] = vi[i+0 + (j+0 + (k+0) * (n+1)) * (n+1)];
1099 G[m++] = vi[i+1 + (j+1 + (k+1) * (n+1)) * (n+1)];
1100 G[m++] = vi[i+0 + (j+0 + (k+1) * (n+1)) * (n+1)];
1101 G[m++] = vi[i+1 + (j+0 + (k+1) * (n+1)) * (n+1)];
1106 mfem_error(
"GeometryRefiner::Refine() for TETRAHEDRON #2");
1108 for (i = 0; i < m; i++)
1111 mfem_error(
"GeometryRefiner::Refine() for TETRAHEDRON #3");
1136 ir = FindInIntPts(Geom, Times-1);
1140 for (
int i = 1; i < Times; i++)
1143 ip.
x = double(i) / Times;
1156 ir = FindInIntPts(Geom, ((Times-1)*(Times-2))/2);
1160 for (
int k = 0, j = 1; j < Times-1; j++)
1161 for (
int i = 1; i < Times-j; i++, k++)
1164 ip.
x = double(i) / Times;
1165 ip.
y = double(j) / Times;
1178 ir = FindInIntPts(Geom, (Times-1)*(Times-1));
1182 for (
int k = 0, j = 1; j < Times; j++)
1183 for (
int i = 1; i < Times; i++, k++)
1186 ip.
x = double(i) / Times;
1187 ip.
y = double(j) / Times;
1195 mfem_error(
"GeometryRefiner::RefineInterior(...)");
1198 if (ir) { IntPts[Geom].Append(ir); }
int Size() const
Logical size of the array.
static const int InvOrient[NumOrient]
Class for an integration rule - an Array of IntegrationPoint.
static const int I[NumVert]
static const int J[NumEdges][2]
static int GetNodalBasis(int qpt_type)
Return the nodal BasisType corresponding to the Quadrature1D type.
void JacToPerfJac(int GeomType, const DenseMatrix &J, DenseMatrix &PJ) const
static void GetRandomPoint(int GeomType, IntegrationPoint &ip)
Get a random point in the reference element specified by GeomType.
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
static const int J[NumEdges][2]
static const int FaceVert[NumFaces][MaxFaceVert]
RefinedGeometry * Refine(int Geom, int Times, int ETimes=1)
Data type dense matrix using column-major storage.
static const double Volume[NumGeom]
static const int I[NumVert]
static const int NumEdges[NumGeom]
const IntegrationRule * GetVertices(int GeomType)
Return an IntegrationRule consisting of all vertices of the given Geometry::Type, GeomType...
const double * GetPoints(const int p, const int btype)
Get the coordinates of the points of the given BasisType, btype.
static const int NumFaces[NumGeom]
static const int InvOrient[NumOrient]
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
static const int Edges[NumEdges][2]
static const int Dimension[NumGeom]
const IntegrationRule * RefineInterior(int Geom, int Times)
static const int FaceTypes[NumFaces]
void mfem_error(const char *msg)
Function called when an error is encountered. Used by the macros MFEM_ABORT, MFEM_ASSERT, MFEM_VERIFY.
static const int NumVerts[NumGeom]
static const int Edges[NumEdges][2]
GeometryRefiner GlobGeometryRefiner
Class for linear FE on tetrahedron.
static const int NumBdrArray[NumGeom]
Class for linear FE on triangle.
static const int InvOrient[NumOrient]
static const int Orient[NumOrient][NumVert]
static const int Edges[NumEdges][2]
static const char * Name[NumGeom]
static const int I[NumVert]
void CalcInverse(const DenseMatrix &a, DenseMatrix &inva)
static const int InvOrient[NumOrient]
static const int Edges[NumEdges][2]
static bool ProjectPoint(int GeomType, const IntegrationPoint &beg, IntegrationPoint &end)
Project a point end, onto the given Geometry::Type, GeomType.
void GetPerfPointMat(int GeomType, DenseMatrix &pm)
static const int FaceVert[NumFaces][MaxFaceVert]
static const int J[NumEdges][2]
static const int I[NumVert]
static const int FaceVert[NumFaces][NumVert]
Class for integration point with weight.
void Diag(double c, int n)
Creates n x n diagonal matrix with diagonal elements c.
static const int FaceTypes[NumFaces]
static const int FaceVert[NumFaces][NumVert]
static const int Orient[NumOrient][NumVert]
static const int Edges[NumEdges][2]
static const int Orient[NumOrient][NumVert]
static bool CheckPoint(int GeomType, const IntegrationPoint &ip)
Check if the given point is inside the given reference element.
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
static const int Orient[NumOrient][NumVert]
static const int J[NumEdges][2]