49 #ifndef __INTREPID2_CUBATURE_CONTROLVOLUME_BOUNDARY_DEF_HPP__
50 #define __INTREPID2_CUBATURE_CONTROLVOLUME_BOUNDARY_DEF_HPP__
55 template <
typename SpT,
typename PT,
typename WT>
58 const ordinal_type sideIndex) {
61 primaryCellTopo_ = cellTopology;
64 const ordinal_type spaceDim = primaryCellTopo_.getDimension();
67 subcvCellTopo_ = shards::CellTopology(shards::getCellTopologyData<shards::Quadrilateral<4> >());
70 subcvCellTopo_ = shards::CellTopology(shards::getCellTopologyData<shards::Hexahedron<8> >());
77 sideIndex_ = sideIndex;
80 const ordinal_type sideDim = spaceDim - 1;
82 const ordinal_type numPrimarySides = primaryCellTopo_.getSubcellCount(sideDim);
83 const ordinal_type numPrimarySideNodes = primaryCellTopo_.getNodeCount(sideDim, sideIndex_);
85 const ordinal_type numSubcvSideNodes = subcvCellTopo_.getNodeCount(sideDim, 0);
87 boundarySidesHost_ = Kokkos::View<ordinal_type**,Kokkos::HostSpace>(
"CubatureControlVolumeBoundary::boundarySidesHost",
88 numPrimarySides, numSubcvSideNodes);
91 switch (primaryCellTopo_.getKey()) {
92 case shards::Triangle<3>::key:
93 case shards::Quadrilateral<4>::key: {
94 for (ordinal_type i=0;i<numPrimarySides;++i) {
95 boundarySidesHost_(i,0) = 0;
96 boundarySidesHost_(i,1) = 3;
100 case shards::Hexahedron<8>::key: {
102 for (ordinal_type i=0;i<4;++i) {
103 boundarySidesHost_(i,0) = 0;
104 boundarySidesHost_(i,1) = 3;
105 boundarySidesHost_(i,2) = 3;
106 boundarySidesHost_(i,3) = 0;
110 boundarySidesHost_(4,0) = 4;
111 boundarySidesHost_(4,1) = 4;
112 boundarySidesHost_(4,2) = 4;
113 boundarySidesHost_(4,3) = 4;
116 boundarySidesHost_(5,0) = 5;
117 boundarySidesHost_(5,1) = 5;
118 boundarySidesHost_(5,2) = 5;
119 boundarySidesHost_(5,3) = 5;
122 case shards::Tetrahedron<4>::key: {
123 boundarySidesHost_(0,0) = 0;
124 boundarySidesHost_(0,1) = 3;
125 boundarySidesHost_(0,2) = 0;
127 boundarySidesHost_(1,0) = 0;
128 boundarySidesHost_(1,1) = 3;
129 boundarySidesHost_(1,2) = 3;
131 boundarySidesHost_(2,0) = 3;
132 boundarySidesHost_(2,1) = 4;
133 boundarySidesHost_(2,2) = 0;
135 boundarySidesHost_(3,0) = 4;
136 boundarySidesHost_(3,1) = 4;
137 boundarySidesHost_(3,2) = 4;
141 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
142 ">>> ERROR (CubatureControlVolumeBoundary: invalid cell topology.");
146 Kokkos::DynRankView<PT,SpT> sideCenterLocal(
"CubatureControlVolumeBoundary::sideCenterLocal",
149 sidePoints_ = Kokkos::DynRankView<PT,SpT>(
"CubatureControlVolumeBoundary::sidePoints",
150 numPrimarySideNodes, spaceDim);
152 for (ordinal_type i=0;i<numPrimarySideNodes;++i) {
153 const ordinal_type sideOrd = boundarySidesHost_(sideIndex_,i);
154 const auto sideRange = Kokkos::pair<ordinal_type,ordinal_type>(i, i+1);
155 const auto sidePoint = Kokkos::subdynrankview(sidePoints_, sideRange, Kokkos::ALL());
163 const ordinal_type maxNumNodesPerSide = 10;
164 Kokkos::View<ordinal_type**,Kokkos::HostSpace> sideNodeMapHost(
"CubatureControlVolumeSide::sideNodeMapHost",
165 numPrimarySideNodes, maxNumNodesPerSide);
166 for (ordinal_type i=0;i<numPrimarySideNodes;++i) {
167 const ordinal_type sideOrd = boundarySidesHost_(sideIndex_,i);
168 sideNodeMapHost(i,0) = subcvCellTopo_.getNodeCount(sideDim, sideOrd);
169 for (ordinal_type j=0;j<sideNodeMapHost(i,0);++j)
170 sideNodeMapHost(i,j+1) = subcvCellTopo_.getNodeMap(sideDim, sideOrd, j);
172 sideNodeMap_ = Kokkos::create_mirror_view(
typename SpT::memory_space(), sideNodeMapHost);
173 Kokkos::deep_copy(sideNodeMap_, sideNodeMapHost);
176 template <
typename SpT,
typename PT,
typename WT>
180 weightViewType cubWeights,
181 PointViewType cellCoords )
const {
182 #ifdef HAVE_INTREPID2_DEBUG
183 INTREPID2_TEST_FOR_EXCEPTION( cubPoints.rank() != 3, std::invalid_argument,
184 ">>> ERROR (CubatureControlVolumeBoundary): cubPoints must have rank 3 (C,P,D).");
185 INTREPID2_TEST_FOR_EXCEPTION( cubWeights.rank() != 2, std::invalid_argument,
186 ">>> ERROR (CubatureControlVolumeBoundary): cubWeights must have rank 2 (C,P).");
187 INTREPID2_TEST_FOR_EXCEPTION( cellCoords.rank() != 3, std::invalid_argument,
188 ">>> ERROR (CubatureControlVolumeBoundary): cellCoords must have rank 3 of (C,P,D).");
190 INTREPID2_TEST_FOR_EXCEPTION( cubPoints.extent(0) != cellCoords.extent(0) ||
191 cubPoints.extent(0) != cubWeights.extent(0), std::invalid_argument,
192 ">>> ERROR (CubatureControlVolume): cubPoints, cubWeights and cellCoords dimension(0) are not consistent, numCells");
195 const ordinal_type spaceDim = cellCoords.extent(2);
196 const ordinal_type sideDim = spaceDim - 1;
197 const size_type numPrimarySideNodes = primaryCellTopo_.getNodeCount(sideDim, sideIndex_);
199 INTREPID2_TEST_FOR_EXCEPTION( cubPoints.extent(1) != numPrimarySideNodes ||
200 cubWeights.extent(1) != numPrimarySideNodes, std::invalid_argument,
201 ">>> ERROR (CubatureControlVolume): cubPoints and cubWeights dimension(1) are not consistent, numPrimarySideNodes");
203 INTREPID2_TEST_FOR_EXCEPTION( cubPoints.extent(2) != cellCoords.extent(2) ||
204 static_cast<ordinal_type
>(cubPoints.extent(2)) != getDimension(), std::invalid_argument,
205 ">>> ERROR (CubatureControlVolume): cubPoints, cellCoords, this->getDimension() are not consistent, spaceDim.");
208 typedef Kokkos::DynRankView<PT,SpT> tempPointViewType;
209 typedef Kokkos::DynRankView<PT,Kokkos::LayoutStride,SpT> tempPointStrideViewType;
212 const ordinal_type numCells = cellCoords.extent(0);
213 const ordinal_type numNodesPerCell = cellCoords.extent(1);
214 const ordinal_type spaceDim = cellCoords.extent(2);
215 const ordinal_type sideDim = spaceDim - 1;
217 const ordinal_type numNodesPerSubcv = subcvCellTopo_.getNodeCount();
218 tempPointViewType subcvCoords(
"CubatureControlVolumeBoundary::subcvCoords",
219 numCells, numNodesPerCell, numNodesPerSubcv, spaceDim);
225 const ordinal_type numSubcvPoints = 1;
227 tempPointViewType subcvJacobian(
"CubatureControlVolumeBoundary::subcvJacobian",
228 numCells, numSubcvPoints, spaceDim, spaceDim);
230 tempPointViewType subcvJacobianDet(
"CubatureControlVolumeBoundary::subcvJacobianDet",
231 numCells, numSubcvPoints);
233 tempPointViewType weights(
"CubatureControlVolumeBoundary::subcvWeights",
235 Kokkos::deep_copy(weights, spaceDim == 2 ? 2.0 : 4.0);
237 tempPointViewType scratch(
"CubatureControlVolumeBoundary::scratch",
238 numCells*numSubcvPoints*spaceDim*spaceDim);
240 const ordinal_type numPrimarySideNodes = primaryCellTopo_.getNodeCount(sideDim, sideIndex_);
241 for (ordinal_type node=0;node<numPrimarySideNodes;++node) {
242 const auto sideRange = Kokkos::pair<ordinal_type,ordinal_type>(node, node+1);
243 const auto sidePoint = Kokkos::subdynrankview(sidePoints_, sideRange, Kokkos::ALL());
245 const auto idx = primaryCellTopo_.getNodeMap(sideDim, sideIndex_, node);
246 auto subcvCoordsNode = Kokkos::subdynrankview(subcvCoords, Kokkos::ALL(), idx, Kokkos::ALL(), Kokkos::ALL());
256 auto cubPointsNode = Kokkos::subdynrankview(cubPoints, Kokkos::ALL(), node, Kokkos::ALL());
258 typedef Kokkos::View<ordinal_type*,SpT> mapViewType;
259 const auto sideNodeMap = Kokkos::subview(sideNodeMap_, node, Kokkos::ALL());
261 typedef typename ExecSpace<typename PointViewType::execution_space,SpT>::ExecSpaceType ExecSpaceType;
263 const auto loopSize = numCells;
264 Kokkos::RangePolicy<ExecSpaceType,Kokkos::Schedule<Kokkos::Static> > policy(0, loopSize);
268 Kokkos::parallel_for( policy, FunctorType(cubPointsNode,
273 const auto sideOrd = boundarySidesHost_(sideIndex_, node);
276 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
Returns cubature points and weights (return arrays must be pre-sized/pre-allocated).