16 #ifndef Intrepid2_CellGeometryDef_h
17 #define Intrepid2_CellGeometryDef_h
26 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
29 using BasisPtr = Teuchos::RCP<Intrepid2::Basis<DeviceType,PointScalar,PointScalar> >;
33 static std::map<const CellGeometryType *, shards::CellTopology> cellTopology_;
34 static std::map<const CellGeometryType *, BasisPtr> basisForNodes_;
37 static void constructorCalled(
const CellGeometryType *cellGeometry,
const shards::CellTopology &cellTopo, BasisPtr basisForNodes)
39 cellTopology_[cellGeometry] = cellTopo;
40 basisForNodes_[cellGeometry] = basisForNodes;
45 cellTopology_.erase(cellGeometry);
46 basisForNodes_.erase(cellGeometry);
51 return basisForNodes_[cellGeometry];
54 static const shards::CellTopology & getCellTopology(
const CellGeometryType *cellGeometry)
56 return cellTopology_[cellGeometry];
67 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
70 Kokkos::View<PointScalar**, DeviceType> cellMeasures_;
71 Kokkos::View<PointScalar**, DeviceType> detData_;
77 cellMeasures_(cellMeasures),
79 cubatureWeights_(cubatureWeights)
82 KOKKOS_INLINE_FUNCTION
void
83 operator () (
const ordinal_type cellOrdinal,
const ordinal_type pointOrdinal)
const
85 cellMeasures_(cellOrdinal,pointOrdinal) = detData_(cellOrdinal,pointOrdinal) * cubatureWeights_(pointOrdinal);
90 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
91 KOKKOS_INLINE_FUNCTION
94 nodeOrdering_(cellGeometry.nodeOrdering_),
95 cellGeometryType_(cellGeometry.cellGeometryType_),
96 subdivisionStrategy_(cellGeometry.subdivisionStrategy_),
97 affine_(cellGeometry.affine_),
98 orientations_(cellGeometry.orientations_),
99 origin_(cellGeometry.origin_),
100 domainExtents_(cellGeometry.domainExtents_),
101 gridCellCounts_(cellGeometry.gridCellCounts_),
102 tensorVertices_(cellGeometry.tensorVertices_),
103 cellToNodes_(cellGeometry.cellToNodes_),
104 nodes_(cellGeometry.nodes_),
105 numCells_(cellGeometry.numCells_),
106 numNodesPerCell_(cellGeometry.numNodesPerCell_)
109 #ifndef INTREPID2_COMPILE_DEVICE_CODE
110 shards::CellTopology cellTopo = cellGeometry.
cellTopology();
113 HostMemberLookup::constructorCalled(
this, cellTopo, basisForNodes);
117 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
118 KOKKOS_INLINE_FUNCTION
122 #ifndef INTREPID2_COMPILE_DEVICE_CODE
124 HostMemberLookup::destructorCalled(
this);
128 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
129 KOKKOS_INLINE_FUNCTION
132 switch (subdivisionStrategy) {
135 case TWO_TRIANGLES_LEFT:
136 case TWO_TRIANGLES_RIGHT:
140 case FIVE_TETRAHEDRA:
149 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
153 ScalarView<PointScalar,DeviceType> data;
155 const int CELL_DIM = 0;
156 const int POINT_DIM = 1;
157 const int D1_DIM = 2;
158 const int D2_DIM = 3;
160 const int numCellsWorkset = (endCell == -1) ? (numCells_ - startCell) : (endCell - startCell);
162 Kokkos::Array<int,7> extents { numCellsWorkset, pointsPerCell, spaceDim, spaceDim, 1, 1, 1 };
163 Kokkos::Array<DataVariationType,7> variationType { CONSTANT, CONSTANT, CONSTANT, CONSTANT, CONSTANT, CONSTANT, CONSTANT };
165 int blockPlusDiagonalLastNonDiagonal = -1;
167 if (cellGeometryType_ == UNIFORM_GRID)
169 if (uniformJacobianModulus() != 1)
171 variationType[CELL_DIM] = MODULAR;
172 variationType[POINT_DIM] = CONSTANT;
173 variationType[D1_DIM] = GENERAL;
174 variationType[D2_DIM] = GENERAL;
176 int cellTypeModulus = uniformJacobianModulus();
178 data = getMatchingViewWithLabel(pointComponentView,
"CellGeometryProvider: Jacobian data", cellTypeModulus, spaceDim, spaceDim);
183 variationType[D1_DIM] = BLOCK_PLUS_DIAGONAL;
184 variationType[D2_DIM] = BLOCK_PLUS_DIAGONAL;
185 blockPlusDiagonalLastNonDiagonal = -1;
187 data = getMatchingViewWithLabel(pointComponentView,
"CellGeometryProvider: Jacobian data", spaceDim);
190 else if (cellGeometryType_ == TENSOR_GRID)
194 else if (cellGeometryType_ == FIRST_ORDER)
196 const bool simplex = (spaceDim + 1 == cellToNodes_.extent_int(1));
199 variationType[CELL_DIM] = GENERAL;
200 variationType[POINT_DIM] = CONSTANT;
201 variationType[D1_DIM] = GENERAL;
202 variationType[D2_DIM] = GENERAL;
204 data = getMatchingViewWithLabel(data,
"CellGeometryProvider: Jacobian data", numCells_, spaceDim, spaceDim);
208 variationType[CELL_DIM] = GENERAL;
209 variationType[D1_DIM] = GENERAL;
210 variationType[D2_DIM] = GENERAL;
214 variationType[POINT_DIM] = CONSTANT;
215 data = getMatchingViewWithLabel(data,
"CellGeometryProvider: Jacobian data", numCellsWorkset, spaceDim, spaceDim);
219 variationType[POINT_DIM] = GENERAL;
220 data = getMatchingViewWithLabel(data,
"CellGeometryProvider: Jacobian data", numCellsWorkset, pointsPerCell, spaceDim, spaceDim);
224 else if (cellGeometryType_ == HIGHER_ORDER)
227 variationType[CELL_DIM] = GENERAL;
228 variationType[POINT_DIM] = GENERAL;
229 variationType[D1_DIM] = GENERAL;
230 variationType[D2_DIM] = GENERAL;
231 data = getMatchingViewWithLabel(data,
"CellGeometryProvider: Jacobian data", numCellsWorkset, pointsPerCell, spaceDim, spaceDim);
242 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
245 const int startCell,
const int endCell)
const
247 const int numCellsWorkset = (endCell == -1) ? (numCells_ - startCell) : (endCell - startCell);
249 if (cellGeometryType_ == UNIFORM_GRID)
251 if (uniformJacobianModulus() != 1)
253 int cellTypeModulus = uniformJacobianModulus();
256 auto dataHost = Kokkos::create_mirror_view(dataView3);
258 const int startCellType = startCell % cellTypeModulus;
259 const int endCellType = (numCellsWorkset >= cellTypeModulus) ? startCellType + cellTypeModulus : startCellType + numCellsWorkset;
260 const int gridCellOrdinal = 0;
261 for (
int cellType=startCellType; cellType<endCellType; cellType++)
263 const int subdivisionOrdinal = cellType % cellTypeModulus;
264 const int nodeZero = 0;
266 for (
int i=0; i<spaceDim; i++)
268 for (
int j=0; j<spaceDim; j++)
270 const int node = j+1;
272 const auto J_ij = subdivisionCoordinate(gridCellOrdinal, subdivisionOrdinal, node, i) - subdivisionCoordinate(gridCellOrdinal, subdivisionOrdinal, nodeZero, i);
273 dataHost(cellType,i,j) = J_ij;
278 Kokkos::deep_copy(dataView3,dataHost);
284 const auto domainExtents = domainExtents_;
285 const auto gridCellCounts = gridCellCounts_;
287 using ExecutionSpace =
typename DeviceType::execution_space;
288 auto policy = Kokkos::RangePolicy<>(ExecutionSpace(),0,spaceDim);
289 Kokkos::parallel_for(
"fill jacobian", policy, KOKKOS_LAMBDA(
const int d1)
292 const double REF_SPACE_EXTENT = 2.0;
293 dataView1(d1) = (domainExtents[d1] / REF_SPACE_EXTENT) / gridCellCounts[d1];
295 ExecutionSpace().fence();
298 else if (cellGeometryType_ == TENSOR_GRID)
302 else if ((cellGeometryType_ == FIRST_ORDER) || (cellGeometryType_ == HIGHER_ORDER))
304 const bool simplex = (spaceDim + 1 == cellToNodes_.extent_int(1));
310 auto cellToNodes = cellToNodes_;
313 using ExecutionSpace =
typename DeviceType::execution_space;
314 auto policy = Kokkos::MDRangePolicy<ExecutionSpace,Kokkos::Rank<3>>({startCell,0,0},{numCellsWorkset,spaceDim,spaceDim});
316 Kokkos::parallel_for(
"compute first-order simplex Jacobians", policy,
317 KOKKOS_LAMBDA (
const int &cellOrdinal,
const int &d1,
const int &d2) {
318 const int nodeZero = 0;
319 const int node = d2+1;
320 const auto & nodeCoord = nodes(cellToNodes(cellOrdinal,node), d1);
321 const auto & nodeZeroCoord = nodes(cellToNodes(cellOrdinal,nodeZero), d1);
322 const PointScalar J_ij = nodeCoord - nodeZeroCoord;
323 dataView3(cellOrdinal,d1,d2) = (spaceDim != 1) ? J_ij : J_ij * 0.5;
329 auto basisForNodes = this->basisForNodes();
337 const int onePoint = 1;
338 auto testPointView = getMatchingViewWithLabel(dataView3,
"CellGeometryProvider: test point", onePoint, spaceDim);
339 auto tempData = getMatchingViewWithLabel(dataView3,
"CellGeometryProvider: temporary Jacobian data", numCellsWorkset, onePoint, spaceDim, spaceDim);
341 Kokkos::deep_copy(testPointView, 0.0);
345 auto tempDataSubview = Kokkos::subview(tempData, Kokkos::ALL(), 0, Kokkos::ALL(), Kokkos::ALL());
346 Kokkos::deep_copy(dataView3, tempDataSubview);
351 TEUCHOS_TEST_FOR_EXCEPTION(basisForNodes == Teuchos::null, std::invalid_argument,
"basisForNodes must not be null");
352 TEUCHOS_TEST_FOR_EXCEPTION(dataView.size() == 0, std::invalid_argument,
"underlying view is not valid");
357 if (refData.
rank() == 3)
383 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
385 const Kokkos::Array<PointScalar,spaceDim> &domainExtents,
386 const Kokkos::Array<int,spaceDim> &gridCellCounts,
390 nodeOrdering_(nodeOrdering),
391 cellGeometryType_(UNIFORM_GRID),
392 subdivisionStrategy_(subdivisionStrategy),
395 domainExtents_(domainExtents),
396 gridCellCounts_(gridCellCounts)
399 for (
int d=0; d<spaceDim; d++)
401 numCells_ *= gridCellCounts_[d];
405 shards::CellTopology cellTopo;
409 numNodesPerCell_ = 1 << spaceDim;
413 cellTopo = shards::CellTopology(shards::getCellTopologyData<shards::Line<> >());
415 else if (spaceDim == 2)
417 cellTopo = shards::CellTopology(shards::getCellTopologyData<shards::Quadrilateral<> >());
419 else if (spaceDim == 3)
421 cellTopo = shards::CellTopology(shards::getCellTopologyData<shards::Hexahedron<> >());
431 numNodesPerCell_ = spaceDim + 1;
434 cellTopo = shards::CellTopology(shards::getCellTopologyData<shards::Triangle<> >());
436 else if (spaceDim == 3)
438 cellTopo = shards::CellTopology(shards::getCellTopologyData<shards::Tetrahedron<> >());
447 const int linearPolyOrder = 1;
448 BasisPtr
basisForNodes = getBasis<BasisFamily>(cellTopo, FUNCTION_SPACE_HGRAD, linearPolyOrder);
454 if (cellTopo.getKey() == shards::Quadrilateral<>::key)
458 else if (cellTopo.getKey() == shards::Hexahedron<>::key)
465 HostMemberLookup::constructorCalled(
this, cellTopo, basisForNodes);
471 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
473 ScalarView<int,DeviceType> cellToNodes,
474 ScalarView<PointScalar,DeviceType> nodes,
475 const bool claimAffine,
478 nodeOrdering_(nodeOrdering),
479 cellGeometryType_(FIRST_ORDER),
480 cellToNodes_(cellToNodes),
483 if(cellToNodes.is_allocated())
485 numCells_ = cellToNodes.extent_int(0);
486 numNodesPerCell_ = cellToNodes.extent_int(1);
491 numCells_ = nodes.extent_int(0);
492 numNodesPerCell_ = nodes.extent_int(1);
500 const bool simplicialTopo = (cellTopo.getNodeCount() == cellTopo.getDimension() + 1);
501 affine_ = simplicialTopo;
509 const int linearPolyOrder = 1;
510 BasisPtr
basisForNodes = getBasis<BasisFamily>(cellTopo, FUNCTION_SPACE_HGRAD, linearPolyOrder);
516 if (cellTopo.getKey() == shards::Quadrilateral<>::key)
520 else if (cellTopo.getKey() == shards::Hexahedron<>::key)
527 HostMemberLookup::constructorCalled(
this, cellTopo, basisForNodes);
531 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
533 ScalarView<PointScalar,DeviceType> cellNodes)
535 nodeOrdering_(HYPERCUBE_NODE_ORDER_TENSOR),
536 cellGeometryType_(HIGHER_ORDER),
539 numCells_ = cellNodes.extent_int(0);
540 numNodesPerCell_ = cellNodes.extent_int(1);
543 const bool firstOrderGeometry = (
basisForNodes->getDegree() == 1);
546 shards::CellTopology cellTopo =
basisForNodes->getBaseCellTopology();
548 if (firstOrderGeometry && (cellTopo.getNodeCount() == spaceDim + 1))
557 HostMemberLookup::constructorCalled(
this, cellTopo,
basisForNodes);
560 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
561 KOKKOS_INLINE_FUNCTION
567 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
576 INTREPID2_TEST_FOR_EXCEPTION(cubatureWeights.
rank() != 1, std::invalid_argument,
"cubatureWeights container must have shape (P)");
579 std::vector< Data<PointScalar,DeviceType> > tensorComponents(numTensorComponents);
583 const int cellExtent = jacobianDet.
extent_int(0);
584 Kokkos::Array<DataVariationType,7> cellVariationTypes {jacobianDet.
getVariationTypes()[0], CONSTANT, CONSTANT, CONSTANT, CONSTANT, CONSTANT, CONSTANT};
586 Kokkos::Array<int,7> cellExtents{cellExtent,1,1,1,1,1,1};
588 ScalarView<PointScalar,DeviceType> detDataView (
"cell relative volumes", cellDataDim);
591 for (
int cubTensorComponent=0; cubTensorComponent<numTensorComponents-1; cubTensorComponent++)
594 const auto cubatureExtents = cubatureComponent.getExtents();
595 const auto cubatureVariationTypes = cubatureComponent.getVariationTypes();
596 const int numPoints = cubatureComponent.getDataExtent(0);
597 ScalarView<PointScalar,DeviceType> cubatureWeightView (
"cubature component weights", numPoints);
598 const int pointComponentRank = 1;
599 tensorComponents[cubTensorComponent+1] =
Data<PointScalar,DeviceType>(cubatureWeightView,pointComponentRank,cubatureExtents,cubatureVariationTypes);
604 const int cellExtent = jacobianDet.
extent_int(0);
605 Kokkos::Array<DataVariationType,7> variationTypes {jacobianDet.
getVariationTypes()[0], GENERAL, CONSTANT, CONSTANT, CONSTANT, CONSTANT, CONSTANT};
608 const int numPoints = cubatureWeights.
extent_int(0);
609 Kokkos::Array<int,7> extents{cellExtent,numPoints,1,1,1,1,1};
611 ScalarView<PointScalar,DeviceType> cubatureWeightView;
612 if (variationTypes[0] != CONSTANT)
614 cubatureWeightView = ScalarView<PointScalar,DeviceType>(
"cell measure", cellDataDim, numPoints);
618 cubatureWeightView = ScalarView<PointScalar,DeviceType>(
"cell measure", numPoints);
620 const int cellMeasureRank = 2;
623 const bool separateFirstComponent = (numTensorComponents > 1);
627 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
637 "cellMeasure must either have a tensor component count of 1 or a tensor component count that is one higher than that of cubatureWeights");
639 INTREPID2_TEST_FOR_EXCEPTION(cubatureWeights.
rank() != 1, std::invalid_argument,
"cubatureWeights container must have shape (P)");
646 for (
int i=1; i<numTensorDimensions+1; i++)
655 const bool detCellVaries = detVaries[0] != CONSTANT;
656 const bool detPointVaries = detVaries[1] != CONSTANT;
658 if (detCellVaries && detPointVaries)
662 const int numCells = detData.extent_int(0);
663 const int numPoints = detData.extent_int(1);
664 INTREPID2_TEST_FOR_EXCEPTION(numCells != cellMeasureData.extent_int(0), std::invalid_argument,
"cellMeasureData doesn't match jacobianDet in cell dimension");
665 INTREPID2_TEST_FOR_EXCEPTION(numPoints != cellMeasureData.extent_int(1), std::invalid_argument,
"cellMeasureData doesn't match jacobianDet in point dimension");
670 using ExecutionSpace =
typename DeviceType::execution_space;
671 Kokkos::MDRangePolicy<ExecutionSpace,Kokkos::Rank<2>> rangePolicy({0,0},{numCells,numPoints});
672 Kokkos::parallel_for(rangePolicy, cellMeasureFunctor);
674 else if (detCellVaries && !detPointVaries)
678 using ExecutionSpace =
typename DeviceType::execution_space;
679 Kokkos::parallel_for(
680 Kokkos::MDRangePolicy<ExecutionSpace,Kokkos::Rank<2>>({0,0},{detData.extent_int(0),cubatureWeights.
extent_int(0)}),
681 KOKKOS_LAMBDA (
int cellOrdinal,
int pointOrdinal) {
682 cellMeasureData(cellOrdinal,pointOrdinal) = detData(cellOrdinal) * cubatureWeights(pointOrdinal);
691 using ExecutionSpace =
typename DeviceType::execution_space;
692 Kokkos::parallel_for(Kokkos::RangePolicy<ExecutionSpace>(0,cellMeasureData.extent_int(0)),
693 KOKKOS_LAMBDA (
const int &pointOrdinal) {
694 cellMeasureData(pointOrdinal) = detData(0) * cubatureWeights(pointOrdinal);
700 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
701 typename CellGeometry<PointScalar,spaceDim,DeviceType>::BasisPtr
705 return HostMemberLookup::getBasis(
this);
708 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
712 return HostMemberLookup::getCellTopology(
this);
715 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
716 KOKKOS_INLINE_FUNCTION
719 if (cellToNodes_.is_allocated())
721 return cellToNodes_(cell,node);
723 else if (cellGeometryType_ == UNIFORM_GRID)
725 const ordinal_type numSubdivisions = numCellsPerGridCell(subdivisionStrategy_);
726 const ordinal_type gridCell = cell / numSubdivisions;
727 const ordinal_type subdivisionOrdinal = cell % numSubdivisions;
729 Kokkos::Array<ordinal_type,spaceDim> gridCellCoords;
730 ordinal_type gridCellDivided = gridCell;
731 ordinal_type numGridNodes = 1;
732 ordinal_type numGridCells = 1;
733 for (
int d=0; d<spaceDim; d++)
735 gridCellCoords[d] = gridCellDivided % gridCellCounts_[d];
736 gridCellDivided = gridCellDivided / gridCellCounts_[d];
737 numGridCells *= gridCellCounts_[d];
738 numGridNodes *= (gridCellCounts_[d] + 1);
741 const ordinal_type gridCellNode = gridCellNodeForSubdivisionNode(gridCell, subdivisionOrdinal, node);
745 const ordinal_type numInteriorNodes = ((subdivisionStrategy_ == FOUR_TRIANGLES) || (subdivisionStrategy_ == SIX_PYRAMIDS)) ? 1 : 0;
748 const ordinal_type gridNodeNumberingOffset = numInteriorNodes * numGridCells;
750 const ordinal_type numNodesPerGridCell = 1 << spaceDim;
751 if (gridCellNode >= numNodesPerGridCell)
753 const ordinal_type interiorGridNodeOffset = gridCellNode - numNodesPerGridCell;
754 return numNodesPerGridCell * gridCell + interiorGridNodeOffset;
760 ordinal_type d_index_stride = 1;
761 ordinal_type cartesianNodeNumber = 0;
762 for (
int d=0; d<spaceDim; d++)
764 const ordinal_type d_index = gridCellCoords[d] + hypercubeComponentNodeNumber(gridCellNode,d);
765 cartesianNodeNumber += d_index * d_index_stride;
766 d_index_stride *= (gridCellCounts_[d] + 1);
768 return cartesianNodeNumber + gridNodeNumberingOffset;
778 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
779 KOKKOS_INLINE_FUNCTION
782 if (cellGeometryType_ == UNIFORM_GRID)
784 const int numSubdivisions = numCellsPerGridCell(subdivisionStrategy_);
785 if (numSubdivisions == 1)
797 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
801 if (cellGeometryType_ == UNIFORM_GRID)
806 else if (cellGeometryType_ == TENSOR_GRID)
811 else if ((cellGeometryType_ == FIRST_ORDER) || (cellGeometryType_ == HIGHER_ORDER))
813 const bool simplex = (spaceDim + 1 == cellToNodes_.extent_int(1));
821 auto basisForNodes = this->basisForNodes();
832 if (points.rank() == 2)
835 return getJacobianRefData(tensorPoints);
839 const int numCells = points.extent_int(0);
840 const int numPoints = points.extent_int(1);
841 const int numFields = basisForNodes->getCardinality();
843 auto cellBasisGradientsView = getMatchingViewWithLabel(points,
"CellGeometryProvider: cellBasisGradients", numCells, numFields, numPoints, spaceDim);
844 auto basisGradientsView = getMatchingViewWithLabel(points,
"CellGeometryProvider: basisGradients", numFields, numPoints, spaceDim);
846 for (
int cellOrdinal=0; cellOrdinal<numCells; cellOrdinal++)
848 auto refPointsForCell = Kokkos::subview(points, cellOrdinal, Kokkos::ALL(), Kokkos::ALL());
849 basisForNodes->getValues(basisGradientsView, refPointsForCell, OPERATOR_GRAD);
856 using ExecutionSpace =
typename DeviceType::execution_space;
857 auto policy = Kokkos::MDRangePolicy<ExecutionSpace,Kokkos::Rank<3>>({0,0,0},{numFields,numPoints,spaceDim});
859 Kokkos::parallel_for(
"copy basis gradients", policy,
860 KOKKOS_LAMBDA (
const int &fieldOrdinal,
const int &pointOrdinal,
const int &d) {
861 cellBasisGradientsView(cellOrdinal,fieldOrdinal,pointOrdinal,d) = basisGradientsView(fieldOrdinal,pointOrdinal,d);
863 ExecutionSpace().fence();
881 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
885 if (cellGeometryType_ == UNIFORM_GRID)
890 else if (cellGeometryType_ == TENSOR_GRID)
895 else if ((cellGeometryType_ == FIRST_ORDER) || (cellGeometryType_ == HIGHER_ORDER))
897 const bool simplex = (spaceDim + 1 == cellToNodes_.extent_int(1));
905 auto basisForNodes = this->basisForNodes();
914 auto basisGradients = basisForNodes->allocateBasisValues(points, OPERATOR_GRAD);
915 basisForNodes->getValues(basisGradients, points, OPERATOR_GRAD);
918 int numFields = basisForNodes->getCardinality();
926 auto basisGradientsView = getMatchingViewWithLabel(firstPointComponentView,
"CellGeometryProvider: temporary basisGradients", numFields, numPoints, spaceDim);
928 using ExecutionSpace =
typename DeviceType::execution_space;
929 auto policy = Kokkos::MDRangePolicy<ExecutionSpace,Kokkos::Rank<3>>({0,0,0},{numFields,numPoints,spaceDim});
931 Kokkos::parallel_for(
"copy basis gradients", policy,
932 KOKKOS_LAMBDA (
const int &fieldOrdinal,
const int &pointOrdinal,
const int &d) {
933 basisGradientsView(fieldOrdinal,pointOrdinal,d) = basisGradients(fieldOrdinal,pointOrdinal,d);
935 ExecutionSpace().fence();
950 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
951 KOKKOS_INLINE_FUNCTION
954 if (nodeOrdering_ == HYPERCUBE_NODE_ORDER_CLASSIC_SHARDS)
960 if ((hypercubeNodeNumber % 4 == 1) || (hypercubeNodeNumber % 4 == 2))
967 if ((hypercubeNodeNumber % 4 == 2) || (hypercubeNodeNumber % 4 == 3))
974 const int nodesForPriorDimensions = 1 << d;
975 if ((hypercubeNodeNumber / nodesForPriorDimensions) % 2 == 1)
981 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
984 using HostExecSpace = Kokkos::DefaultHostExecutionSpace;
986 const bool isGridType = (cellGeometryType_ == TENSOR_GRID) || (cellGeometryType_ == UNIFORM_GRID);
987 const int numOrientations = isGridType ? numCellsPerGridCell(subdivisionStrategy_) : numCells();
989 const int nodesPerCell = numNodesPerCell();
991 ScalarView<Orientation, DeviceType> orientationsView(
"orientations", numOrientations);
992 auto orientationsHost = Kokkos::create_mirror_view(
typename HostExecSpace::memory_space(), orientationsView);
994 DataVariationType cellVariationType;
1000 const int numSubdivisions = numCellsPerGridCell(subdivisionStrategy_);
1001 ScalarView<PointScalar, HostExecSpace> cellNodesHost(
"cellNodesHost",numOrientations,nodesPerCell);
1003 #if defined(INTREPID2_COMPILE_DEVICE_CODE)
1006 const int gridCellOrdinal = 0;
1007 auto hostPolicy = Kokkos::MDRangePolicy<HostExecSpace,Kokkos::Rank<2>>({0,0},{numSubdivisions,nodesPerCell});
1008 Kokkos::parallel_for(
"fill cellNodesHost", hostPolicy,
1009 [
this,gridCellOrdinal,cellNodesHost] (
const int &subdivisionOrdinal,
const int &nodeInCell) {
1010 auto node = this->gridCellNodeForSubdivisionNode(gridCellOrdinal, subdivisionOrdinal, nodeInCell);
1011 cellNodesHost(subdivisionOrdinal,nodeInCell) = node;
1014 cellVariationType = (numSubdivisions == 1) ? CONSTANT : MODULAR;
1019 cellVariationType = GENERAL;
1020 auto cellNodesHost = Kokkos::create_mirror_view_and_copy(
typename HostExecSpace::memory_space(), cellToNodes_);
1023 Kokkos::deep_copy(orientationsView,orientationsHost);
1025 const int orientationsRank = 1;
1026 const Kokkos::Array<int,7> orientationExtents {
static_cast<int>(numCells_),1,1,1,1,1,1};
1027 const Kokkos::Array<DataVariationType,7> orientationVariationTypes { cellVariationType, CONSTANT, CONSTANT, CONSTANT, CONSTANT, CONSTANT, CONSTANT};
1031 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1032 KOKKOS_INLINE_FUNCTION
1040 return numNodesPerCell_;
1052 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1053 template <
typename iType>
1054 KOKKOS_INLINE_FUNCTION
1055 typename std::enable_if<std::is_integral<iType>::value,
int>::type
1058 return static_cast<int>(extent(r));
1061 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1062 KOKKOS_INLINE_FUNCTION
1066 return nodeOrdering_;
1069 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1070 KOKKOS_INLINE_FUNCTION
1076 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1077 KOKKOS_INLINE_FUNCTION
1080 if (cellGeometryType_ == UNIFORM_GRID)
1082 return gridCellCounts_[dim];
1084 else if (cellGeometryType_ == TENSOR_GRID)
1086 return tensorVertices_.extent_int(dim);
1094 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1095 KOKKOS_INLINE_FUNCTION
1098 return numNodesPerCell_;
1101 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1102 KOKKOS_INLINE_FUNCTION
1106 return orientations_(cellNumber);
1109 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1112 if (!orientations_.isValid())
1114 initializeOrientations();
1116 return orientations_;
1119 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1120 KOKKOS_INLINE_FUNCTION
1123 const int componentNode = hypercubeComponentNodeNumber(localNodeNumber, dim);
1124 int cellCountForPriorDimensions = 1;
1125 for (
int d=0; d<dim; d++)
1127 cellCountForPriorDimensions *= numCellsInDimension(d);
1129 const int componentGridCellOrdinal = (gridCellOrdinal / cellCountForPriorDimensions) % numCellsInDimension(dim);
1130 const int vertexOrdinal = componentGridCellOrdinal + componentNode;
1131 if (cellGeometryType_ == UNIFORM_GRID)
1133 return origin_[dim] + (vertexOrdinal * domainExtents_[dim]) / gridCellCounts_[dim];
1135 else if (cellGeometryType_ == TENSOR_GRID)
1137 Kokkos::Array<int,spaceDim> pointOrdinalComponents;
1138 for (
int d=0; d<spaceDim; d++)
1140 pointOrdinalComponents[d] = 0;
1142 pointOrdinalComponents[dim] = vertexOrdinal;
1143 return tensorVertices_(pointOrdinalComponents,dim);
1152 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1153 KOKKOS_INLINE_FUNCTION
1159 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1160 KOKKOS_INLINE_FUNCTION
1162 const int &subdivisionNodeNumber)
const
1165 switch (subdivisionStrategy_)
1167 case NO_SUBDIVISION:
1168 return subdivisionNodeNumber;
1169 case TWO_TRIANGLES_RIGHT:
1170 case TWO_TRIANGLES_LEFT:
1171 case FOUR_TRIANGLES:
1173 Kokkos::Array<int,3> nodeLookup;
1174 if (subdivisionStrategy_ == TWO_TRIANGLES_RIGHT)
1176 if (subdivisionOrdinal == 0)
1179 nodeLookup = {0,1,2};
1181 else if (subdivisionOrdinal == 1)
1186 nodeLookup = {2,3,0};
1193 else if (subdivisionStrategy_ == TWO_TRIANGLES_LEFT)
1195 if (subdivisionOrdinal == 0)
1201 nodeLookup = {3,0,1};
1203 else if (subdivisionOrdinal == 1)
1208 nodeLookup = {2,3,0};
1224 if (subdivisionNodeNumber == 1)
1231 nodeLookup = {(subdivisionOrdinal + 1) % 4, -1, subdivisionOrdinal};
1234 const int gridCellNodeNumber = nodeLookup[subdivisionNodeNumber];
1235 return gridCellNodeNumber;
1237 case FIVE_TETRAHEDRA:
1238 case SIX_TETRAHEDRA:
1240 Kokkos::Array<int,4> nodeLookup;
1241 if (subdivisionStrategy_ == FIVE_TETRAHEDRA)
1271 switch (subdivisionOrdinal) {
1273 nodeLookup = {1,3,4,6};
1276 nodeLookup = {0,1,3,4};
1279 nodeLookup = {1,2,3,6};
1282 nodeLookup = {1,4,5,6};
1285 nodeLookup = {3,4,6,7};
1292 else if (subdivisionStrategy_ == SIX_TETRAHEDRA)
1296 const int gridCellNodeNumber = nodeLookup[subdivisionNodeNumber];
1297 return gridCellNodeNumber;
1301 Kokkos::Array<int,5> nodeLookup;
1303 if (nodeOrdering_ == HYPERCUBE_NODE_ORDER_CLASSIC_SHARDS)
1305 switch (subdivisionOrdinal)
1308 nodeLookup = {0,1,2,3,8};
1311 nodeLookup = {4,5,6,7,8};
1314 nodeLookup = {0,1,5,4,8};
1317 nodeLookup = {3,2,6,7,8};
1320 nodeLookup = {1,2,6,5,8};
1323 nodeLookup = {0,3,7,4,8};
1331 switch (subdivisionOrdinal)
1334 nodeLookup = {0,1,3,2,8};
1337 nodeLookup = {4,5,7,6,8};
1340 nodeLookup = {0,1,5,4,8};
1343 nodeLookup = {2,3,7,6,8};
1346 nodeLookup = {1,3,7,5,8};
1349 nodeLookup = {0,2,6,4,8};
1355 const int gridCellNodeNumber = nodeLookup[subdivisionNodeNumber];
1356 return gridCellNodeNumber;
1365 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1366 KOKKOS_INLINE_FUNCTION
1368 const int &subdivisionNodeNumber,
const int &d)
const
1370 int gridCellNode = gridCellNodeForSubdivisionNode(gridCellOrdinal, subdivisionOrdinal, subdivisionNodeNumber);
1372 if (subdivisionStrategy_ == FOUR_TRIANGLES)
1375 if (gridCellNode == 4)
1379 const int gridVertex0 = 0;
1380 const int gridVertex1 = (d == 0) ? 1 : 3;
1381 return 0.5 * (gridCellCoordinate(gridCellOrdinal, gridVertex0, d) + gridCellCoordinate(gridCellOrdinal, gridVertex1, d));
1384 else if (subdivisionStrategy_ == SIX_PYRAMIDS)
1387 if (gridCellNode == 8)
1391 const int gridVertex0 = 0;
1392 const int gridVertex1 = (nodeOrdering_ == HYPERCUBE_NODE_ORDER_CLASSIC_SHARDS) ? 6 : 7;
1393 return 0.5 * (gridCellCoordinate(gridCellOrdinal, gridVertex0, d) + gridCellCoordinate(gridCellOrdinal, gridVertex1, d));
1396 return gridCellCoordinate(gridCellOrdinal, gridCellNode, d);
1399 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1400 KOKKOS_INLINE_FUNCTION
1403 if ((cellGeometryType_ == UNIFORM_GRID) || (cellGeometryType_ == TENSOR_GRID))
1405 const int numSubdivisions = numCellsPerGridCell(subdivisionStrategy_);
1406 if (numSubdivisions == 1)
1409 return gridCellCoordinate(cell, node, dim);
1413 const int subdivisionOrdinal = cell % numSubdivisions;
1414 const int gridCellOrdinal = cell / numSubdivisions;
1415 return subdivisionCoordinate(gridCellOrdinal, subdivisionOrdinal, node, dim);
1420 #ifdef HAVE_INTREPID2_DEBUG
1428 if (cellToNodes_.is_allocated())
1430 const int nodeNumber = cellToNodes_(cell,node);
1431 return nodes_(nodeNumber,dim);
1435 return nodes_(cell,node,dim);
1440 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1443 auto orientationsData = getOrientations();
1444 const int numCellsWorkset = (endCell == -1) ? (numCells_ - startCell) : (endCell - startCell);
1446 using ExecutionSpace =
typename DeviceType::execution_space;
1447 auto policy = Kokkos::RangePolicy<ExecutionSpace>(ExecutionSpace(),0,numCellsWorkset);
1448 Kokkos::parallel_for(
"copy orientations", policy, KOKKOS_LAMBDA(
const int cellOrdinal)
1450 orientationsView(cellOrdinal) = orientationsData(cellOrdinal);
1452 ExecutionSpace().fence();
1455 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1456 KOKKOS_INLINE_FUNCTION
1459 if (cellGeometryType_ == UNIFORM_GRID)
1461 return numCellsPerGridCell(subdivisionStrategy_);
1469 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1472 const int pointsPerCell = points.
extent_int(0);
1473 return allocateJacobianDataPrivate(points.
getTensorComponent(0),pointsPerCell,startCell,endCell);
1476 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1480 const int pointDimension = (points.rank() == 3) ? 1 : 0;
1481 const int pointsPerCell = points.extent_int(pointDimension);
1482 return allocateJacobianDataPrivate(points,pointsPerCell,startCell,endCell);
1485 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1490 ScalarView<PointScalar,DeviceType> emptyPoints;
1491 return allocateJacobianDataPrivate(emptyPoints,numPoints,startCell,endCell);
1494 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1498 const int pointsPerCell = points.
extent_int(0);
1499 setJacobianDataPrivate(jacobianData,pointsPerCell,refData,startCell,endCell);
1502 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1507 const int pointDimension = (points.rank() == 3) ? 1 : 0;
1508 const int pointsPerCell = points.extent_int(pointDimension);
1509 setJacobianDataPrivate(jacobianData,pointsPerCell,refData,startCell,endCell);
1512 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1518 setJacobianDataPrivate(jacobianData,numPoints,emptyRefData,startCell,endCell);
void setJacobianDataPrivate(Data< PointScalar, DeviceType > &jacobianData, const int &pointsPerCell, const Data< PointScalar, DeviceType > &refData, const int startCell, const int endCell) const
Notionally-private method that provides a common interface for multiple public-facing setJacobianData...
Implementation of the default H(grad)-compatible FEM basis of degree 1 on Quadrilateral cell...
geometry expressible in terms of vertices of the cell
BasisPtr basisForNodes() const
H^1 Basis used in the reference-to-physical transformation. Linear for straight-edged geometry; highe...
KOKKOS_INLINE_FUNCTION int numCellsPerGridCell(SubdivisionStrategy subdivisionStrategy) const
Helper method that returns the number of cells into which each grid cell will be subdivided based on ...
Data< PointScalar, DeviceType > allocateJacobianDataPrivate(const ScalarView< PointScalar, DeviceType > &pointComponentView, const int &pointsPerCell, const int startCell, const int endCell) const
Notionally-private method that provides a common interface for multiple public-facing allocateJacobia...
KOKKOS_INLINE_FUNCTION PointScalar subdivisionCoordinate(const int &gridCellOrdinal, const int &subdivisionOrdinal, const int &subdivisionNodeNumber, const int &d) const
returns coordinate in dimension d for the indicated subdivision of the indicated grid cell ...
CellGeometry provides the nodes for a set of cells; has options that support efficient definition of ...
Functor for full (C,P) Jacobian determinant container. CUDA compiler issues led us to avoid lambdas f...
View-like interface to tensor points; point components are stored separately; the appropriate coordin...
#define INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(test, x, msg)
const shards::CellTopology & cellTopology() const
The shards CellTopology for each cell within the CellGeometry object. Note that this is always a lowe...
KOKKOS_INLINE_FUNCTION ordinal_type cellToNode(ordinal_type cellIndex, ordinal_type cellNodeNumber) const
Returns a global node number corresponding to the specified (cell, node) combination. If uniform grid (possibly subdivided), this number is computed dynamically; for more general meshes, this simply returns the result of a lookup in the cellToNodes container provided at construction.
KOKKOS_INLINE_FUNCTION PointScalar operator()(const int &cell, const int &node, const int &dim) const
Return the coordinate (weight) of the specified node. For straight-edged geometry, this is simply the physical coordinate of the vertex. For all geometries, this can be understood as a weight on the corresponding H^1 basis function used in the reference-to-physical map.
An abstract base class that defines interface for concrete basis implementations for Finite Element (...
void orientations(ScalarView< Orientation, DeviceType > orientationsView, const int &startCell=0, const int &endCell=-1)
Fills the provided container with the orientations for the specified cell range. Calls getOrientation...
CellGeometry(const Kokkos::Array< PointScalar, spaceDim > &origin, const Kokkos::Array< PointScalar, spaceDim > &domainExtents, const Kokkos::Array< int, spaceDim > &gridCellCounts, SubdivisionStrategy subdivisionStrategy=NO_SUBDIVISION, HypercubeNodeOrdering nodeOrdering=HYPERCUBE_NODE_ORDER_TENSOR)
Uniform grid constructor, with optional subdivision into simplices.
KOKKOS_INLINE_FUNCTION const Kokkos::View< DataScalar *, DeviceType > & getUnderlyingView1() const
returns the View that stores the unique data. For rank-1 underlying containers.
KOKKOS_INLINE_FUNCTION unsigned rank() const
Returns the logical rank of this container. This is always 3.
KOKKOS_INLINE_FUNCTION const Kokkos::Array< DataVariationType, 7 > & getVariationTypes() const
Returns an array with the variation types in each logical dimension.
KOKKOS_INLINE_FUNCTION int hypercubeComponentNodeNumber(int hypercubeNodeNumber, int d) const
For hypercube vertex number hypercubeNodeNumber, returns the component node number in specified dimen...
Data< PointScalar, DeviceType > allocateJacobianData(const TensorPoints< PointScalar, DeviceType > &points, const int startCell=0, const int endCell=-1) const
Allocate a container into which Jacobians of the reference-to-physical mapping can be placed...
KOKKOS_INLINE_FUNCTION enable_if_t< rank==1, const Kokkos::View< typename RankExpander< DataScalar, rank >::value_type, DeviceType > & > getUnderlyingView() const
Returns the underlying view. Throws an exception if the underlying view is not rank 1...
KOKKOS_INLINE_FUNCTION bool affine() const
Returns true if Jacobian is constant within each cell.
Wrapper around a Kokkos::View that allows data that is constant or repeating in various logical dimen...
KOKKOS_INLINE_FUNCTION const Data< Scalar, DeviceType > & getTensorComponent(const ordinal_type &r) const
Returns the requested tensor component.
KOKKOS_INLINE_FUNCTION HypercubeNodeOrdering nodeOrderingForHypercubes() const
Returns the node ordering used for hypercubes.
KOKKOS_INLINE_FUNCTION int gridCellNodeForSubdivisionNode(const int &gridCellOrdinal, const int &subdivisionOrdinal, const int &subdivisionNodeNumber) const
returns coordinate in dimension d for the indicated subdivision of the indicated grid cell ...
TensorData< PointScalar, DeviceType > allocateCellMeasure(const Data< PointScalar, DeviceType > &jacobianDet, const TensorData< PointScalar, DeviceType > &cubatureWeights) const
Allocate a TensorData object appropriate for passing to computeCellMeasure().
KOKKOS_INLINE_FUNCTION ordinal_type rank() const
Returns the rank of the container.
KOKKOS_INLINE_FUNCTION PointScalar gridCellCoordinate(const int &gridCellOrdinal, const int &localNodeNumber, const int &dim) const
returns coordinate in dimension dim of the indicated node in the indicated grid cell ...
KOKKOS_INLINE_FUNCTION std::enable_if< std::is_integral< iType >::value, int >::type extent_int(const iType &r) const
Returns the logical extent of the container in the specified dimension as an int; the shape of CellGe...
KOKKOS_INLINE_FUNCTION const Kokkos::View< DataScalar ***, DeviceType > & getUnderlyingView3() const
returns the View that stores the unique data. For rank-3 underlying containers.
KOKKOS_INLINE_FUNCTION constexpr bool isValid() const
returns true for containers that have data; false for those that don't (namely, those that have been ...
KOKKOS_INLINE_FUNCTION int uniformJacobianModulus() const
Returns an integer indicating the number of distinct cell types vis-a-vis Jacobians.
Data< PointScalar, DeviceType > getJacobianRefData(const ScalarView< PointScalar, DeviceType > &points) const
Computes reference-space data for the specified points, to be used in setJacobian().
Orientation encoding and decoding.
Store host-only "members" of CellGeometry using a static map indexed on the CellGeometry pointer...
geometry expressible in terms of a higher-order basis (must be specified)
void initializeOrientations()
Initialize the internal orientations_ member with the orientations of each member cell...
Data< Orientation, DeviceType > getOrientations()
Returns the orientations for all cells. Calls initializeOrientations() if it has not previously been ...
KOKKOS_INLINE_FUNCTION Orientation getOrientation(int &cellNumber) const
Returns the orientation for the specified cell. Requires that initializeOrientations() has been calle...
KOKKOS_INLINE_FUNCTION DataVariationType cellVariationType() const
A family of nodal basis functions which is related to, but not identical with, the Lagrangian basis f...
KOKKOS_INLINE_FUNCTION int numNodesPerCell() const
Returns the number of nodes per cell; may be more than the number of vertices in the corresponding Ce...
KOKKOS_INLINE_FUNCTION int numCellsInDimension(const int &dim) const
For uniform grid and tensor grid CellGeometry, returns the number of cells in the specified component...
void setJacobian(Data< PointScalar, DeviceType > &jacobianData, const TensorPoints< PointScalar, DeviceType > &points, const Data< PointScalar, DeviceType > &refData, const int startCell=0, const int endCell=-1) const
Compute Jacobian values for the reference-to-physical transformation, and place them in the provided ...
KOKKOS_INLINE_FUNCTION unsigned rank() const
Returns the logical rank of the Data container.
KOKKOS_INLINE_FUNCTION int extent_int(const int &r) const
Returns the logical extent in the specified dimension.
KOKKOS_INLINE_FUNCTION int getDataExtent(const ordinal_type &d) const
returns the true extent of the data corresponding to the logical dimension provided; if the data does...
KOKKOS_INLINE_FUNCTION std::enable_if< std::is_integral< iType >::value, ordinal_type >::type extent_int(const iType &d) const
Returns the logical extent in the requested dimension.
KOKKOS_INLINE_FUNCTION int numCells() const
Returns the number of cells.
KOKKOS_INLINE_FUNCTION ~CellGeometry()
Destructor.
KOKKOS_INLINE_FUNCTION const Kokkos::View< DataScalar **, DeviceType > & getUnderlyingView2() const
returns the View that stores the unique data. For rank-2 underlying containers.
Implementation of the default H(grad)-compatible FEM basis of degree 1 on Hexahedron cell...
KOKKOS_INLINE_FUNCTION size_t extent(const int &r) const
Returns the logical extent of the container in the specified dimension; the shape of CellGeometry is ...
KOKKOS_INLINE_FUNCTION ordinal_type numTensorComponents() const
Return the number of tensorial components.
KOKKOS_INLINE_FUNCTION ScalarView< PointScalar, DeviceType > getTensorComponent(const ordinal_type &r) const
Returns the requested tensor component.
KOKKOS_INLINE_FUNCTION std::enable_if< std::is_integral< iType >::value, int >::type extent_int(const iType &r) const
Returns the logical extent in the requested dimension.
void computeCellMeasure(TensorData< PointScalar, DeviceType > &cellMeasure, const Data< PointScalar, DeviceType > &jacobianDet, const TensorData< PointScalar, DeviceType > &cubatureWeights) const
Compute cell measures that correspond to provided Jacobian determinants and.