Intrepid2
Intrepid2_CubatureControlVolumeSideDef.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Intrepid2 Package
4 //
5 // Copyright 2007 NTESS and the Intrepid2 contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
16 #ifndef __INTREPID2_CUBATURE_CONTROLVOLUME_SIDE_DEF_HPP__
17 #define __INTREPID2_CUBATURE_CONTROLVOLUME_SIDE_DEF_HPP__
18 
19 namespace Intrepid2 {
20 
21  template <typename DT, typename PT, typename WT>
23  CubatureControlVolumeSide(const shards::CellTopology cellTopology) {
24 
25  // define primary cell topology with given one
26  primaryCellTopo_ = cellTopology;
27 
28  // subcell is defined either hex or quad according to dimension
29  const auto spaceDim = primaryCellTopo_.getDimension();
30  switch (spaceDim) {
31  case 2:
32  subcvCellTopo_ = shards::CellTopology(shards::getCellTopologyData<shards::Quadrilateral<4> >());
33  break;
34  case 3:
35  subcvCellTopo_ = shards::CellTopology(shards::getCellTopologyData<shards::Hexahedron<8> >());
36  break;
37  }
38 
39  // computation order is always one;
40  degree_ = 1;
41 
42  // precompute reference side points that are repeatedly used in get cubature
43  const auto maxNumNodesPerSide = 10;
44  const auto numSideNodeMaps = (spaceDim == 2 ? 1 : 2);
45 
46  const ordinal_type sideOrd[2] = { 1, 5 };
47  Kokkos::View<ordinal_type**,Kokkos::HostSpace> sideNodeMapHost("CubatureControlVolumeSide::sideNodeMapHost",
48  numSideNodeMaps, maxNumNodesPerSide);
49 
50  const auto sideDim = spaceDim - 1;
51  for (ordinal_type i=0;i<numSideNodeMaps;++i) {
52  const auto side = sideOrd[i];
53  sideNodeMapHost(i,0) = subcvCellTopo_.getNodeCount(sideDim, side);
54  for (ordinal_type j=0;j<sideNodeMapHost(i,0);++j)
55  sideNodeMapHost(i,j+1) = subcvCellTopo_.getNodeMap(sideDim, side, j);
56  }
57  sideNodeMap_ = Kokkos::create_mirror_view(typename DT::memory_space(), sideNodeMapHost);
58  Kokkos::deep_copy(sideNodeMap_, sideNodeMapHost);
59 
60  Kokkos::DynRankView<PT,DT> sideCenterLocal("CubatureControlVolumeSide::sideCenterLocal",
61  1, sideDim);
62 
63  // map to reference subcell function relies on uvm; some utility functions in cell tools still need uvm
64  sidePoints_ = Kokkos::DynRankView<PT,DT>("CubatureControlVolumeSide::sidePoints", numSideNodeMaps, spaceDim);
65  for (ordinal_type i=0;i<numSideNodeMaps;++i) {
66  const auto sideRange = Kokkos::pair<ordinal_type,ordinal_type>(i, i+1);
67  auto sidePoint = Kokkos::subdynrankview(sidePoints_, sideRange, Kokkos::ALL());
69  sideCenterLocal,
70  sideDim,
71  sideOrd[i],
72  subcvCellTopo_);
73  }
74  }
75 
76  template <typename DT, typename PT, typename WT>
77  void
79  getCubature( PointViewType cubPoints,
80  weightViewType cubWeights,
81  PointViewType cellCoords ) const {
82 #ifdef HAVE_INTREPID2_DEBUG
83  INTREPID2_TEST_FOR_EXCEPTION( cubPoints.rank() != 3, std::invalid_argument,
84  ">>> ERROR (CubatureControlVolumeSide): cubPoints must have rank 3 (C,P,D).");
85  INTREPID2_TEST_FOR_EXCEPTION( cubWeights.rank() != 3, std::invalid_argument,
86  ">>> ERROR (CubatureControlVolumeSide): cubWeights must have rank 2 (C,P,D).");
87  INTREPID2_TEST_FOR_EXCEPTION( cellCoords.rank() != 3, std::invalid_argument,
88  ">>> ERROR (CubatureControlVolumeSide): cellCoords must have rank 3 of (C,P,D).");
89 
90  INTREPID2_TEST_FOR_EXCEPTION( cubPoints.extent(0) != cellCoords.extent(0) ||
91  cubPoints.extent(0) != cubWeights.extent(0), std::invalid_argument,
92  ">>> ERROR (CubatureControlVolumeSide): cubPoints, cubWeights and cellCoords dimension(0) are not consistent, numCells");
93 
94  INTREPID2_TEST_FOR_EXCEPTION( cubPoints.extent(2) != cellCoords.extent(2) ||
95  cubPoints.extent(2) != cubWeights.extent(2) ||
96  static_cast<ordinal_type>(cubPoints.extent(2)) != getDimension(), std::invalid_argument,
97  ">>> ERROR (CubatureControlVolumeSide): cubPoints, cellCoords, this->getDimension() are not consistent, spaceDim.");
98 #endif
99  typedef Kokkos::DynRankView<PT,DT> tempPointViewType;
100 
101  // get array dimensions
102  const auto numCells = cellCoords.extent(0);
103  const auto numNodesPerCell = cellCoords.extent(1);
104  const auto spaceDim = cellCoords.extent(2);
105 
106  const auto numNodesPerSubcv = subcvCellTopo_.getNodeCount();
107  tempPointViewType subcvCoords("CubatureControlVolumeSide::subcvCoords",
108  numCells, numNodesPerCell, numNodesPerSubcv, spaceDim);
109  CellTools<DT>::getSubcvCoords(subcvCoords,
110  cellCoords,
111  primaryCellTopo_);
112 
113  const auto numSideNodeMaps = (spaceDim == 2 ? 1 : 2);
114  const ordinal_type sideOrd[2] = { 1, 5 };
115 
116  Kokkos::pair<ordinal_type,ordinal_type> nodeRangePerSide[2]={};
117 
118  // the second rage is cell specific to handle remained sides
119  switch (primaryCellTopo_.getKey()) {
120  case shards::Triangle<3>::key:
121  case shards::Quadrilateral<4>::key:
122  nodeRangePerSide[0].first = 0;
123  nodeRangePerSide[0].second = nodeRangePerSide[0].first + numNodesPerCell;
124  break;
125  case shards::Hexahedron<8>::key:
126  nodeRangePerSide[0].first = 0;
127  nodeRangePerSide[0].second = nodeRangePerSide[0].first + numNodesPerCell;
128  nodeRangePerSide[1].first = numNodesPerCell;
129  nodeRangePerSide[1].second = nodeRangePerSide[1].first + 4;
130  break;
131  case shards::Tetrahedron<4>::key:
132  nodeRangePerSide[0].first = 0;
133  nodeRangePerSide[0].second = nodeRangePerSide[0].first + numNodesPerCell;
134  nodeRangePerSide[1].first = 3;
135  nodeRangePerSide[1].second = nodeRangePerSide[1].first + 3;
136  break;
137  }
138 
139  for (ordinal_type i=0;i<numSideNodeMaps;++i) {
140  const auto numSubcvPoints = 1;
141  const auto numNodesPerThisSide = nodeRangePerSide[i].second - nodeRangePerSide[i].first;
142  tempPointViewType subcvJacobian("CubatureControlVolume::subcvJacobian",
143  numCells, numNodesPerThisSide, numSubcvPoints, spaceDim, spaceDim);
144 
145  tempPointViewType subcvSideNormal("CubatureControlVolume::subcvSideNormal",
146  numCells, numNodesPerThisSide, numSubcvPoints, spaceDim);
147 
148  // numNodesPerCell is maximum 8; this repeated run is necessary because of cell tools input consideration
149  const auto sideRange = Kokkos::pair<ordinal_type,ordinal_type>(i, i+1);
150  const auto sidePoint = Kokkos::subdynrankview(sidePoints_, sideRange, Kokkos::ALL());
151 
152  for (auto node=0;node<numNodesPerThisSide;++node) {
153  auto subcvJacobianNode = Kokkos::subdynrankview(subcvJacobian, Kokkos::ALL(), node, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
154  auto subcvCoordsNode = Kokkos::subdynrankview(subcvCoords, Kokkos::ALL(), node, Kokkos::ALL(), Kokkos::ALL());
155  auto subcvSideNormalNode = Kokkos::subdynrankview(subcvSideNormal, Kokkos::ALL(), node, Kokkos::ALL(), Kokkos::ALL());
156 
157  CellTools<DT>::setJacobian(subcvJacobianNode, // C, P, D, D
158  sidePoint, // P, D
159  subcvCoordsNode, // C, N, D
160  subcvCellTopo_);
161 
162  CellTools<DT>::getPhysicalSideNormals(subcvSideNormalNode, // C, P, D
163  subcvJacobianNode,
164  sideOrd[i],
165  subcvCellTopo_); // C, P, D, D
166  }
167 
168  typedef Kokkos::View<ordinal_type*,DT> mapViewType;
169  const auto sideNodeMap = Kokkos::subview(sideNodeMap_, i, Kokkos::ALL());
170 
171  //typedef typename ExecSpace<typename PointViewType::execution_space,DT>::ExecSpaceType ExecSpaceType;
172 
173  const auto loopSize = numCells;
174  Kokkos::RangePolicy<typename DT::execution_space,Kokkos::Schedule<Kokkos::Static> > policy(0, loopSize);
175 
177 
178  auto cubPointsThisSide = Kokkos::subdynrankview(cubPoints, Kokkos::ALL(), nodeRangePerSide[i], Kokkos::ALL());
179  auto cubWeightsThisSide = Kokkos::subdynrankview(cubWeights, Kokkos::ALL(), nodeRangePerSide[i], Kokkos::ALL());
180 
181  Kokkos::parallel_for( policy, FunctorType(cubPointsThisSide,
182  cubWeightsThisSide,
183  subcvCoords,
184  subcvSideNormal,
185  sideNodeMap) );
186  }
187  }
188 
189 }
190 
191 #endif
192 
static void getPhysicalSideNormals(Kokkos::DynRankView< sideNormalValueType, sideNormalProperties...> sideNormals, const Kokkos::DynRankView< worksetJacobianValueType, worksetJacobianProperties...> worksetJacobians, const ordinal_type worksetSideOrd, const shards::CellTopology parentCell)
Computes non-normalized normal vectors to physical sides in a side workset .
static void setJacobian(JacobianViewType jacobian, const PointViewType points, const WorksetType worksetCell, const Teuchos::RCP< HGradBasisType > basis, const int startCell=0, const int endCell=-1)
Computes the Jacobian matrix DF of the reference-to-physical frame map F.
static void mapToReferenceSubcell(refSubcellViewType refSubcellPoints, const paramPointViewType paramPoints, const ordinal_type subcellDim, const ordinal_type subcellOrd, const shards::CellTopology parentCell)
Computes parameterization maps of 1- and 2-subcells of reference cells.
virtual void getCubature(PointViewType cubPoints, weightViewType cubWeights, PointViewType cellCoords) const override
Returns cubature points and weights (return arrays must be pre-sized/pre-allocated).
static void getSubcvCoords(Kokkos::DynRankView< subcvCoordValueType, subcvCoordProperties...> subcvCoords, const Kokkos::DynRankView< cellCoordValueType, cellCoordProperties...> cellCoords, const shards::CellTopology primaryCell)
Computes coordinates of sub-control volumes in each primary cell.
CubatureControlVolumeSide(const shards::CellTopology cellTopology)