1010
1111namespace MeshField {
1212// directly copied from SCOREC/core @ 7cd76473 apf/apfIntegrate.[h|cc]
13- struct IntegrationPoint {
14- IntegrationPoint (Vector3 const &p, double w) : param(p), weight(w) {}
15- Vector3 param;
13+ template <size_t pointSize> struct IntegrationPoint {
14+ // template parameter pointSize specifies the length of the integration point
15+ // array for one point
16+ IntegrationPoint (Kokkos::Array<Real, pointSize> const &p, double w)
17+ : param(p), weight(w) {}
18+ Kokkos::Array<Real, pointSize> param;
1619 double weight;
1720};
18-
19- class Integration {
21+ template <size_t pointSize> class Integration {
2022public:
2123 virtual ~Integration () {}
2224 virtual int countPoints () const = 0;
23- virtual std::vector<IntegrationPoint> getPoints () const = 0;
25+ virtual std::vector<IntegrationPoint<pointSize> > getPoints () const = 0;
2426 virtual int getAccuracy () const = 0;
2527};
26-
27- class EntityIntegration {
28+ template <size_t pointSize> class EntityIntegration {
2829public:
2930 virtual ~EntityIntegration () {}
30- Integration const *getAccurate (int minimumAccuracy) const {
31+ Integration<pointSize> const *getAccurate (int minimumAccuracy) const {
3132 int n = countIntegrations ();
3233 for (int i = 0 ; i < n; ++i) {
33- Integration const *integration = getIntegration (i);
34+ Integration<pointSize> const *integration = getIntegration (i);
3435 if (integration->getAccuracy () >= minimumAccuracy)
3536 return integration;
3637 }
3738 return NULL ;
3839 }
3940 virtual int countIntegrations () const = 0;
40- virtual Integration const *getIntegration (int i) const = 0;
41+ virtual Integration<pointSize> const *getIntegration (int i) const = 0;
4142};
4243
43- class TriangleIntegration : public EntityIntegration {
44+ class TriangleIntegration : public EntityIntegration < 3 > {
4445public:
45- class N1 : public Integration {
46+ class N1 : public Integration < 3 > {
4647 public:
4748 virtual int countPoints () const { return 1 ; }
48- virtual std::vector<IntegrationPoint> getPoints () const {
49+ virtual std::vector<IntegrationPoint< 3 > > getPoints () const {
4950 return {IntegrationPoint (Vector3{1 . / 3 ., 1 . / 3 ., 1 . / 3 .}, 1.0 / 2.0 )};
5051 }
5152 virtual int getAccuracy () const { return 1 ; }
5253 }; // end N1
53- class N2 : public Integration {
54+ class N2 : public Integration < 3 > {
5455 public:
5556 virtual int countPoints () const { return 3 ; }
56- virtual std::vector<IntegrationPoint> getPoints () const {
57+ virtual std::vector<IntegrationPoint< 3 > > getPoints () const {
5758 return {IntegrationPoint (Vector3{0.666666666666667 , 0.166666666666667 ,
5859 0.166666666666667 },
5960 1 . / 3 . / 2.0 ),
@@ -67,31 +68,69 @@ class TriangleIntegration : public EntityIntegration {
6768 virtual int getAccuracy () const { return 2 ; }
6869 }; // end N2
6970 virtual int countIntegrations () const { return 2 ; }
70- virtual Integration const *getIntegration (int i) const {
71+ virtual Integration< 3 > const *getIntegration (int i) const {
7172 static N1 i1;
7273 static N2 i2;
73- static Integration *integrations[2 ] = {&i1, &i2};
74+ static Integration< 3 > *integrations[2 ] = {&i1, &i2};
7475 return integrations[i];
7576 }
7677};
7778
78- std::shared_ptr<EntityIntegration> const getIntegration (Mesh_Topology topo) {
79- if (topo != Triangle) {
80- fail (" getIntegration only supports triangles (Mesh_Topology::Triangle)\n " );
79+ class TetrahedronIntegration : public EntityIntegration <4 > {
80+ public:
81+ class N1 : public Integration <4 > {
82+ public:
83+ virtual int countPoints () const { return 1 ; }
84+ virtual std::vector<IntegrationPoint<4 >> getPoints () const {
85+ return {IntegrationPoint (Vector4{0.25 , 0.25 , 0.25 , 0.25 }, 1.0 / 6.0 )};
86+ }
87+ virtual int getAccuracy () const { return 1 ; }
88+ };
89+ class N2 : public Integration <4 > {
90+ public:
91+ virtual int countPoints () const { return 4 ; }
92+ virtual std::vector<IntegrationPoint<4 >> getPoints () const {
93+
94+ return {IntegrationPoint (Vector4{0.138196601125011 , 0.138196601125011 ,
95+ 0.138196601125011 , 0.585410196624969 },
96+ 0.25 / 6.0 ),
97+ IntegrationPoint (Vector4{0.585410196624969 , 0.138196601125011 ,
98+ 0.138196601125011 , 0.138196601125011 },
99+ 0.25 / 6.0 ),
100+ IntegrationPoint (Vector4{0.138196601125011 , 0.585410196624969 ,
101+ 0.138196601125011 , 0.138196601125011 },
102+ 0.25 / 6.0 ),
103+ IntegrationPoint (Vector4{0.138196601125011 , 0.138196601125011 ,
104+ 0.585410196624969 , 0.138196601125011 },
105+ 0.25 / 6.0 )};
106+ }
107+ virtual int getAccuracy () const { return 2 ; }
108+ };
109+ virtual int countIntegrations () const { return 2 ; }
110+ virtual Integration<4 > const *getIntegration (int i) const {
111+ static N1 i1;
112+ static N2 i2;
113+ static Integration<4 > *integrations[2 ] = {&i1, &i2};
114+ return integrations[i];
81115 }
82- return std::make_shared<TriangleIntegration>();
116+ };
117+ template <Mesh_Topology topo> auto const getIntegration () {
118+ if constexpr (topo == Triangle) {
119+ return std::make_shared<TriangleIntegration>();
120+ } else if constexpr (topo == Tetrahedron) {
121+ return std::make_shared<TetrahedronIntegration>();
122+ }
123+ fail (" getIntegration does not support given topology\n " );
83124}
84-
85- std::vector<IntegrationPoint> getIntegrationPoints (Mesh_Topology topo,
86- int order) {
87- auto ip = getIntegration (topo)->getAccurate (order)->getPoints ();
125+ template <Mesh_Topology topo> auto getIntegrationPoints (int order) {
126+ auto ip = getIntegration<topo>()->getAccurate (order)->getPoints ();
88127 return ip;
89128}
90129
91130template <typename FieldElement>
92- Kokkos::View<MeshField::Real **>
93- getIntegrationPointLocalCoords ( FieldElement &fes,
94- std::vector<IntegrationPoint> ip) {
131+ Kokkos::View<MeshField::Real **> getIntegrationPointLocalCoords (
132+ FieldElement &fes,
133+ std::vector<IntegrationPoint<FieldElement::MeshEntDim + 1 > > ip) {
95134 const auto numPtsPerElm = ip.size ();
96135 const auto numMeshEnts = fes.numMeshEnts ;
97136 const auto meshEntDim = fes.MeshEntDim ;
@@ -115,9 +154,9 @@ getIntegrationPointLocalCoords(FieldElement &fes,
115154}
116155
117156template <typename FieldElement>
118- Kokkos::View<Real *>
119- getIntegrationPointWeights ( FieldElement &fes,
120- std::vector<IntegrationPoint> ip) {
157+ Kokkos::View<Real *> getIntegrationPointWeights (
158+ FieldElement &fes,
159+ std::vector<IntegrationPoint<FieldElement::MeshEntDim + 1 > > ip) {
121160 const auto numPtsPerElm = ip.size ();
122161 const auto numMeshEnts = fes.numMeshEnts ;
123162 const auto meshEntDim = fes.MeshEntDim ;
@@ -194,13 +233,9 @@ class Integrator {
194233 * FIXME make the sensible
195234 * */
196235 template <typename FieldElement> void process (FieldElement &fes) {
197- const auto topo = fes.elm2dof .getTopology ();
198- if (topo[0 ] != MeshField::Triangle) {
199- throw std::invalid_argument (
200- " Integrator::process only supports triangles." );
201- }
236+ constexpr auto topo = decltype (FieldElement::elm2dof)::getTopology ();
202237 pre ();
203- auto ip = getIntegrationPoints ( topo[0 ], order);
238+ auto ip = getIntegrationPoints< topo[0 ]>( order);
204239 auto localCoords = getIntegrationPointLocalCoords (fes, ip);
205240 auto weights = getIntegrationPointWeights (fes, ip);
206241 auto dV = getJacobianDeterminants (fes, localCoords, ip.size ());
0 commit comments