16 #ifndef __INTREPID2_CUBATURE_CONTROLVOLUME_BOUNDARY_DEF_HPP__
17 #define __INTREPID2_CUBATURE_CONTROLVOLUME_BOUNDARY_DEF_HPP__
22 template <
typename DT,
typename PT,
typename WT>
25 const ordinal_type sideIndex) {
28 primaryCellTopo_ = cellTopology;
31 const ordinal_type spaceDim = primaryCellTopo_.getDimension();
34 subcvCellTopo_ = shards::CellTopology(shards::getCellTopologyData<shards::Quadrilateral<4> >());
37 subcvCellTopo_ = shards::CellTopology(shards::getCellTopologyData<shards::Hexahedron<8> >());
44 sideIndex_ = sideIndex;
47 const ordinal_type sideDim = spaceDim - 1;
49 const ordinal_type numPrimarySides = primaryCellTopo_.getSubcellCount(sideDim);
50 const ordinal_type numPrimarySideNodes = primaryCellTopo_.getNodeCount(sideDim, sideIndex_);
52 const ordinal_type numSubcvSideNodes = subcvCellTopo_.getNodeCount(sideDim, 0);
54 boundarySidesHost_ = Kokkos::View<ordinal_type**,Kokkos::HostSpace>(
"CubatureControlVolumeBoundary::boundarySidesHost",
55 numPrimarySides, numSubcvSideNodes);
58 switch (primaryCellTopo_.getKey()) {
59 case shards::Triangle<3>::key:
60 case shards::Quadrilateral<4>::key: {
61 for (ordinal_type i=0;i<numPrimarySides;++i) {
62 boundarySidesHost_(i,0) = 0;
63 boundarySidesHost_(i,1) = 3;
67 case shards::Hexahedron<8>::key: {
69 for (ordinal_type i=0;i<4;++i) {
70 boundarySidesHost_(i,0) = 0;
71 boundarySidesHost_(i,1) = 3;
72 boundarySidesHost_(i,2) = 3;
73 boundarySidesHost_(i,3) = 0;
77 boundarySidesHost_(4,0) = 4;
78 boundarySidesHost_(4,1) = 4;
79 boundarySidesHost_(4,2) = 4;
80 boundarySidesHost_(4,3) = 4;
83 boundarySidesHost_(5,0) = 5;
84 boundarySidesHost_(5,1) = 5;
85 boundarySidesHost_(5,2) = 5;
86 boundarySidesHost_(5,3) = 5;
89 case shards::Tetrahedron<4>::key: {
90 boundarySidesHost_(0,0) = 0;
91 boundarySidesHost_(0,1) = 3;
92 boundarySidesHost_(0,2) = 0;
94 boundarySidesHost_(1,0) = 0;
95 boundarySidesHost_(1,1) = 3;
96 boundarySidesHost_(1,2) = 3;
98 boundarySidesHost_(2,0) = 3;
99 boundarySidesHost_(2,1) = 4;
100 boundarySidesHost_(2,2) = 0;
102 boundarySidesHost_(3,0) = 4;
103 boundarySidesHost_(3,1) = 4;
104 boundarySidesHost_(3,2) = 4;
108 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
109 ">>> ERROR (CubatureControlVolumeBoundary: invalid cell topology.");
113 Kokkos::DynRankView<PT,DT> sideCenterLocal(
"CubatureControlVolumeBoundary::sideCenterLocal",
116 sidePoints_ = Kokkos::DynRankView<PT,DT>(
"CubatureControlVolumeBoundary::sidePoints",
117 numPrimarySideNodes, spaceDim);
119 for (ordinal_type i=0;i<numPrimarySideNodes;++i) {
120 const ordinal_type sideOrd = boundarySidesHost_(sideIndex_,i);
121 const auto sideRange = Kokkos::pair<ordinal_type,ordinal_type>(i, i+1);
122 const auto sidePoint = Kokkos::subdynrankview(sidePoints_, sideRange, Kokkos::ALL());
130 const ordinal_type maxNumNodesPerSide = 10;
131 Kokkos::View<ordinal_type**,Kokkos::HostSpace> sideNodeMapHost(
"CubatureControlVolumeSide::sideNodeMapHost",
132 numPrimarySideNodes, maxNumNodesPerSide);
133 for (ordinal_type i=0;i<numPrimarySideNodes;++i) {
134 const ordinal_type sideOrd = boundarySidesHost_(sideIndex_,i);
135 sideNodeMapHost(i,0) = subcvCellTopo_.getNodeCount(sideDim, sideOrd);
136 for (ordinal_type j=0;j<sideNodeMapHost(i,0);++j)
137 sideNodeMapHost(i,j+1) = subcvCellTopo_.getNodeMap(sideDim, sideOrd, j);
139 sideNodeMap_ = Kokkos::create_mirror_view(
typename DT::memory_space(), sideNodeMapHost);
140 Kokkos::deep_copy(sideNodeMap_, sideNodeMapHost);
143 template <
typename DT,
typename PT,
typename WT>
147 weightViewType cubWeights,
148 PointViewType cellCoords )
const {
149 #ifdef HAVE_INTREPID2_DEBUG
150 INTREPID2_TEST_FOR_EXCEPTION( cubPoints.rank() != 3, std::invalid_argument,
151 ">>> ERROR (CubatureControlVolumeBoundary): cubPoints must have rank 3 (C,P,D).");
152 INTREPID2_TEST_FOR_EXCEPTION( cubWeights.rank() != 2, std::invalid_argument,
153 ">>> ERROR (CubatureControlVolumeBoundary): cubWeights must have rank 2 (C,P).");
154 INTREPID2_TEST_FOR_EXCEPTION( cellCoords.rank() != 3, std::invalid_argument,
155 ">>> ERROR (CubatureControlVolumeBoundary): cellCoords must have rank 3 of (C,P,D).");
157 INTREPID2_TEST_FOR_EXCEPTION( cubPoints.extent(0) != cellCoords.extent(0) ||
158 cubPoints.extent(0) != cubWeights.extent(0), std::invalid_argument,
159 ">>> ERROR (CubatureControlVolume): cubPoints, cubWeights and cellCoords dimension(0) are not consistent, numCells");
162 const ordinal_type spaceDim = cellCoords.extent(2);
163 const ordinal_type sideDim = spaceDim - 1;
164 const size_type numPrimarySideNodes = primaryCellTopo_.getNodeCount(sideDim, sideIndex_);
166 INTREPID2_TEST_FOR_EXCEPTION( cubPoints.extent(1) != numPrimarySideNodes ||
167 cubWeights.extent(1) != numPrimarySideNodes, std::invalid_argument,
168 ">>> ERROR (CubatureControlVolume): cubPoints and cubWeights dimension(1) are not consistent, numPrimarySideNodes");
170 INTREPID2_TEST_FOR_EXCEPTION( cubPoints.extent(2) != cellCoords.extent(2) ||
171 static_cast<ordinal_type
>(cubPoints.extent(2)) != getDimension(), std::invalid_argument,
172 ">>> ERROR (CubatureControlVolume): cubPoints, cellCoords, this->getDimension() are not consistent, spaceDim.");
175 typedef Kokkos::DynRankView<PT,DT> tempPointViewType;
176 typedef Kokkos::DynRankView<PT,Kokkos::LayoutStride,DT> tempPointStrideViewType;
179 const ordinal_type numCells = cellCoords.extent(0);
180 const ordinal_type numNodesPerCell = cellCoords.extent(1);
181 const ordinal_type spaceDim = cellCoords.extent(2);
182 const ordinal_type sideDim = spaceDim - 1;
184 const ordinal_type numNodesPerSubcv = subcvCellTopo_.getNodeCount();
185 tempPointViewType subcvCoords(
"CubatureControlVolumeBoundary::subcvCoords",
186 numCells, numNodesPerCell, numNodesPerSubcv, spaceDim);
192 const ordinal_type numSubcvPoints = 1;
194 tempPointViewType subcvJacobian(
"CubatureControlVolumeBoundary::subcvJacobian",
195 numCells, numSubcvPoints, spaceDim, spaceDim);
197 tempPointViewType subcvJacobianDet(
"CubatureControlVolumeBoundary::subcvJacobianDet",
198 numCells, numSubcvPoints);
200 tempPointViewType weights(
"CubatureControlVolumeBoundary::subcvWeights",
202 Kokkos::deep_copy(weights, spaceDim == 2 ? 2.0 : 4.0);
204 tempPointViewType scratch(
"CubatureControlVolumeBoundary::scratch",
205 numCells*numSubcvPoints*spaceDim*spaceDim);
207 const ordinal_type numPrimarySideNodes = primaryCellTopo_.getNodeCount(sideDim, sideIndex_);
208 for (ordinal_type node=0;node<numPrimarySideNodes;++node) {
209 const auto sideRange = Kokkos::pair<ordinal_type,ordinal_type>(node, node+1);
210 const auto sidePoint = Kokkos::subdynrankview(sidePoints_, sideRange, Kokkos::ALL());
212 const auto idx = primaryCellTopo_.getNodeMap(sideDim, sideIndex_, node);
213 auto subcvCoordsNode = Kokkos::subdynrankview(subcvCoords, Kokkos::ALL(), idx, Kokkos::ALL(), Kokkos::ALL());
223 auto cubPointsNode = Kokkos::subdynrankview(cubPoints, Kokkos::ALL(), node, Kokkos::ALL());
225 typedef Kokkos::View<ordinal_type*,DT> mapViewType;
226 const auto sideNodeMap = Kokkos::subview(sideNodeMap_, node, Kokkos::ALL());
230 const auto loopSize = numCells;
231 Kokkos::RangePolicy<typename DT::execution_space,Kokkos::Schedule<Kokkos::Static> > policy(0, loopSize);
235 Kokkos::parallel_for( policy, FunctorType(cubPointsNode,
240 const auto sideOrd = boundarySidesHost_(sideIndex_, node);
243 auto cubWeightsNode = Kokkos::subdynrankview(cubWeights, Kokkos::ALL(), sideRange);
CubatureControlVolumeBoundary(const shards::CellTopology cellTopology, const ordinal_type sideIndex)
virtual void getCubature(PointViewType cubPoints, weightViewType cubWeights, PointViewType cellCoords) const override
Returns cubature points and weights (return arrays must be pre-sized/pre-allocated).