50 #ifndef Intrepid2_CellGeometryDef_h
51 #define Intrepid2_CellGeometryDef_h
60 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
63 using BasisPtr = Teuchos::RCP<Intrepid2::Basis<DeviceType,PointScalar,PointScalar> >;
67 static std::map<const CellGeometryType *, shards::CellTopology> cellTopology_;
68 static std::map<const CellGeometryType *, BasisPtr> basisForNodes_;
71 static void constructorCalled(
const CellGeometryType *cellGeometry,
const shards::CellTopology &cellTopo, BasisPtr basisForNodes)
73 cellTopology_[cellGeometry] = cellTopo;
74 basisForNodes_[cellGeometry] = basisForNodes;
79 cellTopology_.erase(cellGeometry);
80 basisForNodes_.erase(cellGeometry);
85 return basisForNodes_[cellGeometry];
88 static const shards::CellTopology & getCellTopology(
const CellGeometryType *cellGeometry)
90 return cellTopology_[cellGeometry];
101 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
104 Kokkos::View<PointScalar**, DeviceType> cellMeasures_;
105 Kokkos::View<PointScalar**, DeviceType> detData_;
111 cellMeasures_(cellMeasures),
113 cubatureWeights_(cubatureWeights)
116 KOKKOS_INLINE_FUNCTION
void
117 operator () (
const ordinal_type cellOrdinal,
const ordinal_type pointOrdinal)
const
119 cellMeasures_(cellOrdinal,pointOrdinal) = detData_(cellOrdinal,pointOrdinal) * cubatureWeights_(pointOrdinal);
124 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
125 KOKKOS_INLINE_FUNCTION
128 nodeOrdering_(cellGeometry.nodeOrdering_),
129 cellGeometryType_(cellGeometry.cellGeometryType_),
130 subdivisionStrategy_(cellGeometry.subdivisionStrategy_),
131 affine_(cellGeometry.affine_),
132 orientations_(cellGeometry.orientations_),
133 origin_(cellGeometry.origin_),
134 domainExtents_(cellGeometry.domainExtents_),
135 gridCellCounts_(cellGeometry.gridCellCounts_),
136 tensorVertices_(cellGeometry.tensorVertices_),
137 cellToNodes_(cellGeometry.cellToNodes_),
138 nodes_(cellGeometry.nodes_),
139 numCells_(cellGeometry.numCells_),
140 numNodesPerCell_(cellGeometry.numNodesPerCell_)
143 #ifndef INTREPID2_COMPILE_DEVICE_CODE
144 shards::CellTopology cellTopo = cellGeometry.
cellTopology();
147 HostMemberLookup::constructorCalled(
this, cellTopo, basisForNodes);
151 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
152 KOKKOS_INLINE_FUNCTION
156 #ifndef INTREPID2_COMPILE_DEVICE_CODE
158 HostMemberLookup::destructorCalled(
this);
162 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
163 KOKKOS_INLINE_FUNCTION
166 switch (subdivisionStrategy) {
169 case TWO_TRIANGLES_LEFT:
170 case TWO_TRIANGLES_RIGHT:
174 case FIVE_TETRAHEDRA:
183 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
187 ScalarView<PointScalar,DeviceType> data;
189 const int CELL_DIM = 0;
190 const int POINT_DIM = 1;
191 const int D1_DIM = 2;
192 const int D2_DIM = 3;
194 const int numCellsWorkset = (endCell == -1) ? (numCells_ - startCell) : (endCell - startCell);
196 Kokkos::Array<int,7> extents { numCellsWorkset, pointsPerCell, spaceDim, spaceDim, 1, 1, 1 };
197 Kokkos::Array<DataVariationType,7> variationType { CONSTANT, CONSTANT, CONSTANT, CONSTANT, CONSTANT, CONSTANT, CONSTANT };
199 int blockPlusDiagonalLastNonDiagonal = -1;
201 if (cellGeometryType_ == UNIFORM_GRID)
203 if (uniformJacobianModulus() != 1)
205 variationType[CELL_DIM] = MODULAR;
206 variationType[POINT_DIM] = CONSTANT;
207 variationType[D1_DIM] = GENERAL;
208 variationType[D2_DIM] = GENERAL;
210 int cellTypeModulus = uniformJacobianModulus();
212 data = getMatchingViewWithLabel(pointComponentView,
"CellGeometryProvider: Jacobian data", cellTypeModulus, spaceDim, spaceDim);
217 variationType[D1_DIM] = BLOCK_PLUS_DIAGONAL;
218 variationType[D2_DIM] = BLOCK_PLUS_DIAGONAL;
219 blockPlusDiagonalLastNonDiagonal = -1;
221 data = getMatchingViewWithLabel(pointComponentView,
"CellGeometryProvider: Jacobian data", spaceDim);
224 else if (cellGeometryType_ == TENSOR_GRID)
228 else if (cellGeometryType_ == FIRST_ORDER)
230 const bool simplex = (spaceDim + 1 == cellToNodes_.extent_int(1));
233 variationType[CELL_DIM] = GENERAL;
234 variationType[POINT_DIM] = CONSTANT;
235 variationType[D1_DIM] = GENERAL;
236 variationType[D2_DIM] = GENERAL;
238 data = getMatchingViewWithLabel(data,
"CellGeometryProvider: Jacobian data", numCells_, spaceDim, spaceDim);
242 variationType[CELL_DIM] = GENERAL;
243 variationType[D1_DIM] = GENERAL;
244 variationType[D2_DIM] = GENERAL;
248 variationType[POINT_DIM] = CONSTANT;
249 data = getMatchingViewWithLabel(data,
"CellGeometryProvider: Jacobian data", numCellsWorkset, spaceDim, spaceDim);
253 variationType[POINT_DIM] = GENERAL;
254 data = getMatchingViewWithLabel(data,
"CellGeometryProvider: Jacobian data", numCellsWorkset, pointsPerCell, spaceDim, spaceDim);
258 else if (cellGeometryType_ == HIGHER_ORDER)
261 variationType[CELL_DIM] = GENERAL;
262 variationType[POINT_DIM] = GENERAL;
263 variationType[D1_DIM] = GENERAL;
264 variationType[D2_DIM] = GENERAL;
265 data = getMatchingViewWithLabel(data,
"CellGeometryProvider: Jacobian data", numCellsWorkset, pointsPerCell, spaceDim, spaceDim);
276 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
279 const int startCell,
const int endCell)
const
281 const int numCellsWorkset = (endCell == -1) ? (numCells_ - startCell) : (endCell - startCell);
283 if (cellGeometryType_ == UNIFORM_GRID)
285 if (uniformJacobianModulus() != 1)
287 int cellTypeModulus = uniformJacobianModulus();
290 auto dataHost = Kokkos::create_mirror_view(dataView3);
292 const int startCellType = startCell % cellTypeModulus;
293 const int endCellType = (numCellsWorkset >= cellTypeModulus) ? startCellType + cellTypeModulus : startCellType + numCellsWorkset;
294 const int gridCellOrdinal = 0;
295 for (
int cellType=startCellType; cellType<endCellType; cellType++)
297 const int subdivisionOrdinal = cellType % cellTypeModulus;
298 const int nodeZero = 0;
300 for (
int i=0; i<spaceDim; i++)
302 for (
int j=0; j<spaceDim; j++)
304 const int node = j+1;
306 const auto J_ij = subdivisionCoordinate(gridCellOrdinal, subdivisionOrdinal, node, i) - subdivisionCoordinate(gridCellOrdinal, subdivisionOrdinal, nodeZero, i);
307 dataHost(cellType,i,j) = J_ij;
312 Kokkos::deep_copy(dataView3,dataHost);
318 const auto domainExtents = domainExtents_;
319 const auto gridCellCounts = gridCellCounts_;
321 using ExecutionSpace =
typename DeviceType::execution_space;
322 auto policy = Kokkos::RangePolicy<>(ExecutionSpace(),0,spaceDim);
323 Kokkos::parallel_for(
"fill jacobian", policy, KOKKOS_LAMBDA(
const int d1)
326 const double REF_SPACE_EXTENT = 2.0;
327 dataView1(d1) = (domainExtents[d1] / REF_SPACE_EXTENT) / gridCellCounts[d1];
329 ExecutionSpace().fence();
332 else if (cellGeometryType_ == TENSOR_GRID)
336 else if ((cellGeometryType_ == FIRST_ORDER) || (cellGeometryType_ == HIGHER_ORDER))
338 const bool simplex = (spaceDim + 1 == cellToNodes_.extent_int(1));
344 auto cellToNodes = cellToNodes_;
347 using ExecutionSpace =
typename DeviceType::execution_space;
348 auto policy = Kokkos::MDRangePolicy<ExecutionSpace,Kokkos::Rank<3>>({startCell,0,0},{numCellsWorkset,spaceDim,spaceDim});
350 Kokkos::parallel_for(
"compute first-order simplex Jacobians", policy,
351 KOKKOS_LAMBDA (
const int &cellOrdinal,
const int &d1,
const int &d2) {
352 const int nodeZero = 0;
353 const int node = d2+1;
354 const auto & nodeCoord = nodes(cellToNodes(cellOrdinal,node), d1);
355 const auto & nodeZeroCoord = nodes(cellToNodes(cellOrdinal,nodeZero), d1);
356 const PointScalar J_ij = nodeCoord - nodeZeroCoord;
357 dataView3(cellOrdinal,d1,d2) = (spaceDim != 1) ? J_ij : J_ij * 0.5;
363 auto basisForNodes = this->basisForNodes();
371 const int onePoint = 1;
372 auto testPointView = getMatchingViewWithLabel(dataView3,
"CellGeometryProvider: test point", onePoint, spaceDim);
373 auto tempData = getMatchingViewWithLabel(dataView3,
"CellGeometryProvider: temporary Jacobian data", numCellsWorkset, onePoint, spaceDim, spaceDim);
375 Kokkos::deep_copy(testPointView, 0.0);
379 auto tempDataSubview = Kokkos::subview(tempData, Kokkos::ALL(), 0, Kokkos::ALL(), Kokkos::ALL());
380 Kokkos::deep_copy(dataView3, tempDataSubview);
385 TEUCHOS_TEST_FOR_EXCEPTION(basisForNodes == Teuchos::null, std::invalid_argument,
"basisForNodes must not be null");
386 TEUCHOS_TEST_FOR_EXCEPTION(dataView.size() == 0, std::invalid_argument,
"underlying view is not valid");
391 if (refData.
rank() == 3)
417 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
419 const Kokkos::Array<PointScalar,spaceDim> &domainExtents,
420 const Kokkos::Array<int,spaceDim> &gridCellCounts,
424 nodeOrdering_(nodeOrdering),
425 cellGeometryType_(UNIFORM_GRID),
426 subdivisionStrategy_(subdivisionStrategy),
429 domainExtents_(domainExtents),
430 gridCellCounts_(gridCellCounts)
433 for (
int d=0; d<spaceDim; d++)
435 numCells_ *= gridCellCounts_[d];
439 shards::CellTopology cellTopo;
443 numNodesPerCell_ = 1 << spaceDim;
447 cellTopo = shards::CellTopology(shards::getCellTopologyData<shards::Line<> >());
449 else if (spaceDim == 2)
451 cellTopo = shards::CellTopology(shards::getCellTopologyData<shards::Quadrilateral<> >());
453 else if (spaceDim == 3)
455 cellTopo = shards::CellTopology(shards::getCellTopologyData<shards::Hexahedron<> >());
465 numNodesPerCell_ = spaceDim + 1;
468 cellTopo = shards::CellTopology(shards::getCellTopologyData<shards::Triangle<> >());
470 else if (spaceDim == 3)
472 cellTopo = shards::CellTopology(shards::getCellTopologyData<shards::Tetrahedron<> >());
481 const int linearPolyOrder = 1;
482 BasisPtr
basisForNodes = getBasis<BasisFamily>(cellTopo, FUNCTION_SPACE_HGRAD, linearPolyOrder);
488 if (cellTopo.getKey() == shards::Quadrilateral<>::key)
492 else if (cellTopo.getKey() == shards::Hexahedron<>::key)
499 HostMemberLookup::constructorCalled(
this, cellTopo, basisForNodes);
505 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
507 ScalarView<int,DeviceType> cellToNodes,
508 ScalarView<PointScalar,DeviceType> nodes,
509 const bool claimAffine,
512 nodeOrdering_(nodeOrdering),
513 cellGeometryType_(FIRST_ORDER),
514 cellToNodes_(cellToNodes),
517 if(cellToNodes.is_allocated())
519 numCells_ = cellToNodes.extent_int(0);
520 numNodesPerCell_ = cellToNodes.extent_int(1);
525 numCells_ = nodes.extent_int(0);
526 numNodesPerCell_ = nodes.extent_int(1);
534 const bool simplicialTopo = (cellTopo.getNodeCount() == cellTopo.getDimension() + 1);
535 affine_ = simplicialTopo;
543 const int linearPolyOrder = 1;
544 BasisPtr
basisForNodes = getBasis<BasisFamily>(cellTopo, FUNCTION_SPACE_HGRAD, linearPolyOrder);
550 if (cellTopo.getKey() == shards::Quadrilateral<>::key)
554 else if (cellTopo.getKey() == shards::Hexahedron<>::key)
561 HostMemberLookup::constructorCalled(
this, cellTopo, basisForNodes);
565 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
567 ScalarView<PointScalar,DeviceType> cellNodes)
569 nodeOrdering_(HYPERCUBE_NODE_ORDER_TENSOR),
570 cellGeometryType_(HIGHER_ORDER),
573 numCells_ = cellNodes.extent_int(0);
574 numNodesPerCell_ = cellNodes.extent_int(1);
577 const bool firstOrderGeometry = (
basisForNodes->getDegree() == 1);
580 shards::CellTopology cellTopo =
basisForNodes->getBaseCellTopology();
582 if (firstOrderGeometry && (cellTopo.getNodeCount() == spaceDim + 1))
591 HostMemberLookup::constructorCalled(
this, cellTopo,
basisForNodes);
594 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
595 KOKKOS_INLINE_FUNCTION
601 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
610 INTREPID2_TEST_FOR_EXCEPTION(cubatureWeights.
rank() != 1, std::invalid_argument,
"cubatureWeights container must have shape (P)");
613 std::vector< Data<PointScalar,DeviceType> > tensorComponents(numTensorComponents);
617 const int cellExtent = jacobianDet.
extent_int(0);
618 Kokkos::Array<DataVariationType,7> cellVariationTypes {jacobianDet.
getVariationTypes()[0], CONSTANT, CONSTANT, CONSTANT, CONSTANT, CONSTANT, CONSTANT};
620 Kokkos::Array<int,7> cellExtents{cellExtent,1,1,1,1,1,1};
622 ScalarView<PointScalar,DeviceType> detDataView (
"cell relative volumes", cellDataDim);
625 for (
int cubTensorComponent=0; cubTensorComponent<numTensorComponents-1; cubTensorComponent++)
628 const auto cubatureExtents = cubatureComponent.getExtents();
629 const auto cubatureVariationTypes = cubatureComponent.getVariationTypes();
630 const int numPoints = cubatureComponent.getDataExtent(0);
631 ScalarView<PointScalar,DeviceType> cubatureWeightView (
"cubature component weights", numPoints);
632 const int pointComponentRank = 1;
633 tensorComponents[cubTensorComponent+1] =
Data<PointScalar,DeviceType>(cubatureWeightView,pointComponentRank,cubatureExtents,cubatureVariationTypes);
638 const int cellExtent = jacobianDet.
extent_int(0);
639 Kokkos::Array<DataVariationType,7> variationTypes {jacobianDet.
getVariationTypes()[0], GENERAL, CONSTANT, CONSTANT, CONSTANT, CONSTANT, CONSTANT};
642 const int numPoints = cubatureWeights.
extent_int(0);
643 Kokkos::Array<int,7> extents{cellExtent,numPoints,1,1,1,1,1};
645 ScalarView<PointScalar,DeviceType> cubatureWeightView;
646 if (variationTypes[0] != CONSTANT)
648 cubatureWeightView = ScalarView<PointScalar,DeviceType>(
"cell measure", cellDataDim, numPoints);
652 cubatureWeightView = ScalarView<PointScalar,DeviceType>(
"cell measure", numPoints);
654 const int cellMeasureRank = 2;
657 const bool separateFirstComponent = (numTensorComponents > 1);
661 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
671 "cellMeasure must either have a tensor component count of 1 or a tensor component count that is one higher than that of cubatureWeights");
673 INTREPID2_TEST_FOR_EXCEPTION(cubatureWeights.
rank() != 1, std::invalid_argument,
"cubatureWeights container must have shape (P)");
680 for (
int i=1; i<numTensorDimensions+1; i++)
689 const bool detCellVaries = detVaries[0] != CONSTANT;
690 const bool detPointVaries = detVaries[1] != CONSTANT;
692 if (detCellVaries && detPointVaries)
696 const int numCells = detData.extent_int(0);
697 const int numPoints = detData.extent_int(1);
698 INTREPID2_TEST_FOR_EXCEPTION(numCells != cellMeasureData.extent_int(0), std::invalid_argument,
"cellMeasureData doesn't match jacobianDet in cell dimension");
699 INTREPID2_TEST_FOR_EXCEPTION(numPoints != cellMeasureData.extent_int(1), std::invalid_argument,
"cellMeasureData doesn't match jacobianDet in point dimension");
704 using ExecutionSpace =
typename DeviceType::execution_space;
705 Kokkos::MDRangePolicy<ExecutionSpace,Kokkos::Rank<2>> rangePolicy({0,0},{numCells,numPoints});
706 Kokkos::parallel_for(rangePolicy, cellMeasureFunctor);
708 else if (detCellVaries && !detPointVaries)
712 using ExecutionSpace =
typename DeviceType::execution_space;
713 Kokkos::parallel_for(
714 Kokkos::MDRangePolicy<ExecutionSpace,Kokkos::Rank<2>>({0,0},{detData.extent_int(0),cubatureWeights.
extent_int(0)}),
715 KOKKOS_LAMBDA (
int cellOrdinal,
int pointOrdinal) {
716 cellMeasureData(cellOrdinal,pointOrdinal) = detData(cellOrdinal) * cubatureWeights(pointOrdinal);
725 using ExecutionSpace =
typename DeviceType::execution_space;
726 Kokkos::parallel_for(Kokkos::RangePolicy<ExecutionSpace>(0,cellMeasureData.extent_int(0)),
727 KOKKOS_LAMBDA (
const int &pointOrdinal) {
728 cellMeasureData(pointOrdinal) = detData(0) * cubatureWeights(pointOrdinal);
734 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
735 typename CellGeometry<PointScalar,spaceDim,DeviceType>::BasisPtr
739 return HostMemberLookup::getBasis(
this);
742 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
746 return HostMemberLookup::getCellTopology(
this);
749 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
750 KOKKOS_INLINE_FUNCTION
753 if (cellToNodes_.is_allocated())
755 return cellToNodes_(cell,node);
757 else if (cellGeometryType_ == UNIFORM_GRID)
759 const ordinal_type numSubdivisions = numCellsPerGridCell(subdivisionStrategy_);
760 const ordinal_type gridCell = cell / numSubdivisions;
761 const ordinal_type subdivisionOrdinal = cell % numSubdivisions;
763 Kokkos::Array<ordinal_type,spaceDim> gridCellCoords;
764 ordinal_type gridCellDivided = gridCell;
765 ordinal_type numGridNodes = 1;
766 ordinal_type numGridCells = 1;
767 for (
int d=0; d<spaceDim; d++)
769 gridCellCoords[d] = gridCellDivided % gridCellCounts_[d];
770 gridCellDivided = gridCellDivided / gridCellCounts_[d];
771 numGridCells *= gridCellCounts_[d];
772 numGridNodes *= (gridCellCounts_[d] + 1);
775 const ordinal_type gridCellNode = gridCellNodeForSubdivisionNode(gridCell, subdivisionOrdinal, node);
779 const ordinal_type numInteriorNodes = ((subdivisionStrategy_ == FOUR_TRIANGLES) || (subdivisionStrategy_ == SIX_PYRAMIDS)) ? 1 : 0;
782 const ordinal_type gridNodeNumberingOffset = numInteriorNodes * numGridCells;
784 const ordinal_type numNodesPerGridCell = 1 << spaceDim;
785 if (gridCellNode >= numNodesPerGridCell)
787 const ordinal_type interiorGridNodeOffset = gridCellNode - numNodesPerGridCell;
788 return numNodesPerGridCell * gridCell + interiorGridNodeOffset;
794 ordinal_type d_index_stride = 1;
795 ordinal_type cartesianNodeNumber = 0;
796 for (
int d=0; d<spaceDim; d++)
798 const ordinal_type d_index = gridCellCoords[d] + hypercubeComponentNodeNumber(gridCellNode,d);
799 cartesianNodeNumber += d_index * d_index_stride;
800 d_index_stride *= (gridCellCounts_[d] + 1);
802 return cartesianNodeNumber + gridNodeNumberingOffset;
812 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
813 KOKKOS_INLINE_FUNCTION
816 if (cellGeometryType_ == UNIFORM_GRID)
818 const int numSubdivisions = numCellsPerGridCell(subdivisionStrategy_);
819 if (numSubdivisions == 1)
831 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
835 if (cellGeometryType_ == UNIFORM_GRID)
840 else if (cellGeometryType_ == TENSOR_GRID)
845 else if ((cellGeometryType_ == FIRST_ORDER) || (cellGeometryType_ == HIGHER_ORDER))
847 const bool simplex = (spaceDim + 1 == cellToNodes_.extent_int(1));
855 auto basisForNodes = this->basisForNodes();
866 if (points.rank() == 2)
869 return getJacobianRefData(tensorPoints);
873 const int numCells = points.extent_int(0);
874 const int numPoints = points.extent_int(1);
875 const int numFields = basisForNodes->getCardinality();
877 auto cellBasisGradientsView = getMatchingViewWithLabel(points,
"CellGeometryProvider: cellBasisGradients", numCells, numFields, numPoints, spaceDim);
878 auto basisGradientsView = getMatchingViewWithLabel(points,
"CellGeometryProvider: basisGradients", numFields, numPoints, spaceDim);
880 for (
int cellOrdinal=0; cellOrdinal<numCells; cellOrdinal++)
882 auto refPointsForCell = Kokkos::subview(points, cellOrdinal, Kokkos::ALL(), Kokkos::ALL());
883 basisForNodes->getValues(basisGradientsView, refPointsForCell, OPERATOR_GRAD);
890 using ExecutionSpace =
typename DeviceType::execution_space;
891 auto policy = Kokkos::MDRangePolicy<ExecutionSpace,Kokkos::Rank<3>>({0,0,0},{numFields,numPoints,spaceDim});
893 Kokkos::parallel_for(
"copy basis gradients", policy,
894 KOKKOS_LAMBDA (
const int &fieldOrdinal,
const int &pointOrdinal,
const int &d) {
895 cellBasisGradientsView(cellOrdinal,fieldOrdinal,pointOrdinal,d) = basisGradientsView(fieldOrdinal,pointOrdinal,d);
897 ExecutionSpace().fence();
915 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
919 if (cellGeometryType_ == UNIFORM_GRID)
924 else if (cellGeometryType_ == TENSOR_GRID)
929 else if ((cellGeometryType_ == FIRST_ORDER) || (cellGeometryType_ == HIGHER_ORDER))
931 const bool simplex = (spaceDim + 1 == cellToNodes_.extent_int(1));
939 auto basisForNodes = this->basisForNodes();
948 auto basisGradients = basisForNodes->allocateBasisValues(points, OPERATOR_GRAD);
949 basisForNodes->getValues(basisGradients, points, OPERATOR_GRAD);
952 int numFields = basisForNodes->getCardinality();
960 auto basisGradientsView = getMatchingViewWithLabel(firstPointComponentView,
"CellGeometryProvider: temporary basisGradients", numFields, numPoints, spaceDim);
962 using ExecutionSpace =
typename DeviceType::execution_space;
963 auto policy = Kokkos::MDRangePolicy<ExecutionSpace,Kokkos::Rank<3>>({0,0,0},{numFields,numPoints,spaceDim});
965 Kokkos::parallel_for(
"copy basis gradients", policy,
966 KOKKOS_LAMBDA (
const int &fieldOrdinal,
const int &pointOrdinal,
const int &d) {
967 basisGradientsView(fieldOrdinal,pointOrdinal,d) = basisGradients(fieldOrdinal,pointOrdinal,d);
969 ExecutionSpace().fence();
984 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
985 KOKKOS_INLINE_FUNCTION
988 if (nodeOrdering_ == HYPERCUBE_NODE_ORDER_CLASSIC_SHARDS)
994 if ((hypercubeNodeNumber % 4 == 1) || (hypercubeNodeNumber % 4 == 2))
1001 if ((hypercubeNodeNumber % 4 == 2) || (hypercubeNodeNumber % 4 == 3))
1008 const int nodesForPriorDimensions = 1 << d;
1009 if ((hypercubeNodeNumber / nodesForPriorDimensions) % 2 == 1)
1015 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1018 using HostExecSpace = Kokkos::DefaultHostExecutionSpace;
1020 const bool isGridType = (cellGeometryType_ == TENSOR_GRID) || (cellGeometryType_ == UNIFORM_GRID);
1021 const int numOrientations = isGridType ? numCellsPerGridCell(subdivisionStrategy_) : numCells();
1023 const int nodesPerCell = numNodesPerCell();
1025 ScalarView<Orientation, DeviceType> orientationsView(
"orientations", numOrientations);
1026 auto orientationsHost = Kokkos::create_mirror_view(
typename HostExecSpace::memory_space(), orientationsView);
1028 DataVariationType cellVariationType;
1034 const int numSubdivisions = numCellsPerGridCell(subdivisionStrategy_);
1035 ScalarView<PointScalar, HostExecSpace> cellNodesHost(
"cellNodesHost",numOrientations,nodesPerCell);
1037 #if defined(INTREPID2_COMPILE_DEVICE_CODE)
1040 const int gridCellOrdinal = 0;
1041 auto hostPolicy = Kokkos::MDRangePolicy<HostExecSpace,Kokkos::Rank<2>>({0,0},{numSubdivisions,nodesPerCell});
1042 Kokkos::parallel_for(
"fill cellNodesHost", hostPolicy,
1043 [
this,gridCellOrdinal,cellNodesHost] (
const int &subdivisionOrdinal,
const int &nodeInCell) {
1044 auto node = this->gridCellNodeForSubdivisionNode(gridCellOrdinal, subdivisionOrdinal, nodeInCell);
1045 cellNodesHost(subdivisionOrdinal,nodeInCell) = node;
1048 cellVariationType = (numSubdivisions == 1) ? CONSTANT : MODULAR;
1053 cellVariationType = GENERAL;
1054 auto cellNodesHost = Kokkos::create_mirror_view_and_copy(
typename HostExecSpace::memory_space(), cellToNodes_);
1057 Kokkos::deep_copy(orientationsView,orientationsHost);
1059 const int orientationsRank = 1;
1060 const Kokkos::Array<int,7> orientationExtents {
static_cast<int>(numCells_),1,1,1,1,1,1};
1061 const Kokkos::Array<DataVariationType,7> orientationVariationTypes { cellVariationType, CONSTANT, CONSTANT, CONSTANT, CONSTANT, CONSTANT, CONSTANT};
1065 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1066 KOKKOS_INLINE_FUNCTION
1074 return numNodesPerCell_;
1086 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1087 template <
typename iType>
1088 KOKKOS_INLINE_FUNCTION
1089 typename std::enable_if<std::is_integral<iType>::value,
int>::type
1092 return static_cast<int>(extent(r));
1095 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1096 KOKKOS_INLINE_FUNCTION
1100 return nodeOrdering_;
1103 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1104 KOKKOS_INLINE_FUNCTION
1110 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1111 KOKKOS_INLINE_FUNCTION
1114 if (cellGeometryType_ == UNIFORM_GRID)
1116 return gridCellCounts_[dim];
1118 else if (cellGeometryType_ == TENSOR_GRID)
1120 return tensorVertices_.extent_int(dim);
1128 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1129 KOKKOS_INLINE_FUNCTION
1132 return numNodesPerCell_;
1135 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1136 KOKKOS_INLINE_FUNCTION
1140 return orientations_(cellNumber);
1143 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1146 if (!orientations_.isValid())
1148 initializeOrientations();
1150 return orientations_;
1153 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1154 KOKKOS_INLINE_FUNCTION
1157 const int componentNode = hypercubeComponentNodeNumber(localNodeNumber, dim);
1158 int cellCountForPriorDimensions = 1;
1159 for (
int d=0; d<dim; d++)
1161 cellCountForPriorDimensions *= numCellsInDimension(d);
1163 const int componentGridCellOrdinal = (gridCellOrdinal / cellCountForPriorDimensions) % numCellsInDimension(dim);
1164 const int vertexOrdinal = componentGridCellOrdinal + componentNode;
1165 if (cellGeometryType_ == UNIFORM_GRID)
1167 return origin_[dim] + (vertexOrdinal * domainExtents_[dim]) / gridCellCounts_[dim];
1169 else if (cellGeometryType_ == TENSOR_GRID)
1171 Kokkos::Array<int,spaceDim> pointOrdinalComponents;
1172 for (
int d=0; d<spaceDim; d++)
1174 pointOrdinalComponents[d] = 0;
1176 pointOrdinalComponents[dim] = vertexOrdinal;
1177 return tensorVertices_(pointOrdinalComponents,dim);
1186 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1187 KOKKOS_INLINE_FUNCTION
1193 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1194 KOKKOS_INLINE_FUNCTION
1196 const int &subdivisionNodeNumber)
const
1199 switch (subdivisionStrategy_)
1201 case NO_SUBDIVISION:
1202 return subdivisionNodeNumber;
1203 case TWO_TRIANGLES_RIGHT:
1204 case TWO_TRIANGLES_LEFT:
1205 case FOUR_TRIANGLES:
1207 Kokkos::Array<int,3> nodeLookup;
1208 if (subdivisionStrategy_ == TWO_TRIANGLES_RIGHT)
1210 if (subdivisionOrdinal == 0)
1213 nodeLookup = {0,1,2};
1215 else if (subdivisionOrdinal == 1)
1220 nodeLookup = {2,3,0};
1227 else if (subdivisionStrategy_ == TWO_TRIANGLES_LEFT)
1229 if (subdivisionOrdinal == 0)
1235 nodeLookup = {3,0,1};
1237 else if (subdivisionOrdinal == 1)
1242 nodeLookup = {2,3,0};
1258 if (subdivisionNodeNumber == 1)
1265 nodeLookup = {(subdivisionOrdinal + 1) % 4, -1, subdivisionOrdinal};
1268 const int gridCellNodeNumber = nodeLookup[subdivisionNodeNumber];
1269 return gridCellNodeNumber;
1271 case FIVE_TETRAHEDRA:
1272 case SIX_TETRAHEDRA:
1274 Kokkos::Array<int,4> nodeLookup;
1275 if (subdivisionStrategy_ == FIVE_TETRAHEDRA)
1305 switch (subdivisionOrdinal) {
1307 nodeLookup = {1,3,4,6};
1310 nodeLookup = {0,1,3,4};
1313 nodeLookup = {1,2,3,6};
1316 nodeLookup = {1,4,5,6};
1319 nodeLookup = {3,4,6,7};
1326 else if (subdivisionStrategy_ == SIX_TETRAHEDRA)
1330 const int gridCellNodeNumber = nodeLookup[subdivisionNodeNumber];
1331 return gridCellNodeNumber;
1335 Kokkos::Array<int,5> nodeLookup;
1337 if (nodeOrdering_ == HYPERCUBE_NODE_ORDER_CLASSIC_SHARDS)
1339 switch (subdivisionOrdinal)
1342 nodeLookup = {0,1,2,3,8};
1345 nodeLookup = {4,5,6,7,8};
1348 nodeLookup = {0,1,5,4,8};
1351 nodeLookup = {3,2,6,7,8};
1354 nodeLookup = {1,2,6,5,8};
1357 nodeLookup = {0,3,7,4,8};
1365 switch (subdivisionOrdinal)
1368 nodeLookup = {0,1,3,2,8};
1371 nodeLookup = {4,5,7,6,8};
1374 nodeLookup = {0,1,5,4,8};
1377 nodeLookup = {2,3,7,6,8};
1380 nodeLookup = {1,3,7,5,8};
1383 nodeLookup = {0,2,6,4,8};
1389 const int gridCellNodeNumber = nodeLookup[subdivisionNodeNumber];
1390 return gridCellNodeNumber;
1399 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1400 KOKKOS_INLINE_FUNCTION
1402 const int &subdivisionNodeNumber,
const int &d)
const
1404 int gridCellNode = gridCellNodeForSubdivisionNode(gridCellOrdinal, subdivisionOrdinal, subdivisionNodeNumber);
1406 if (subdivisionStrategy_ == FOUR_TRIANGLES)
1409 if (gridCellNode == 4)
1413 const int gridVertex0 = 0;
1414 const int gridVertex1 = (d == 0) ? 1 : 3;
1415 return 0.5 * (gridCellCoordinate(gridCellOrdinal, gridVertex0, d) + gridCellCoordinate(gridCellOrdinal, gridVertex1, d));
1418 else if (subdivisionStrategy_ == SIX_PYRAMIDS)
1421 if (gridCellNode == 8)
1425 const int gridVertex0 = 0;
1426 const int gridVertex1 = (nodeOrdering_ == HYPERCUBE_NODE_ORDER_CLASSIC_SHARDS) ? 6 : 7;
1427 return 0.5 * (gridCellCoordinate(gridCellOrdinal, gridVertex0, d) + gridCellCoordinate(gridCellOrdinal, gridVertex1, d));
1430 return gridCellCoordinate(gridCellOrdinal, gridCellNode, d);
1433 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1434 KOKKOS_INLINE_FUNCTION
1437 if ((cellGeometryType_ == UNIFORM_GRID) || (cellGeometryType_ == TENSOR_GRID))
1439 const int numSubdivisions = numCellsPerGridCell(subdivisionStrategy_);
1440 if (numSubdivisions == 1)
1443 return gridCellCoordinate(cell, node, dim);
1447 const int subdivisionOrdinal = cell % numSubdivisions;
1448 const int gridCellOrdinal = cell / numSubdivisions;
1449 return subdivisionCoordinate(gridCellOrdinal, subdivisionOrdinal, node, dim);
1454 #ifdef HAVE_INTREPID2_DEBUG
1462 if (cellToNodes_.is_allocated())
1464 const int nodeNumber = cellToNodes_(cell,node);
1465 return nodes_(nodeNumber,dim);
1469 return nodes_(cell,node,dim);
1474 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1477 auto orientationsData = getOrientations();
1478 const int numCellsWorkset = (endCell == -1) ? (numCells_ - startCell) : (endCell - startCell);
1480 using ExecutionSpace =
typename DeviceType::execution_space;
1481 auto policy = Kokkos::RangePolicy<ExecutionSpace>(ExecutionSpace(),0,numCellsWorkset);
1482 Kokkos::parallel_for(
"copy orientations", policy, KOKKOS_LAMBDA(
const int cellOrdinal)
1484 orientationsView(cellOrdinal) = orientationsData(cellOrdinal);
1486 ExecutionSpace().fence();
1489 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1490 KOKKOS_INLINE_FUNCTION
1493 if (cellGeometryType_ == UNIFORM_GRID)
1495 return numCellsPerGridCell(subdivisionStrategy_);
1503 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1506 const int pointsPerCell = points.
extent_int(0);
1507 return allocateJacobianDataPrivate(points.
getTensorComponent(0),pointsPerCell,startCell,endCell);
1510 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1514 const int pointDimension = (points.rank() == 3) ? 1 : 0;
1515 const int pointsPerCell = points.extent_int(pointDimension);
1516 return allocateJacobianDataPrivate(points,pointsPerCell,startCell,endCell);
1519 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1524 ScalarView<PointScalar,DeviceType> emptyPoints;
1525 return allocateJacobianDataPrivate(emptyPoints,numPoints,startCell,endCell);
1528 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1532 const int pointsPerCell = points.
extent_int(0);
1533 setJacobianDataPrivate(jacobianData,pointsPerCell,refData,startCell,endCell);
1536 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1541 const int pointDimension = (points.rank() == 3) ? 1 : 0;
1542 const int pointsPerCell = points.extent_int(pointDimension);
1543 setJacobianDataPrivate(jacobianData,pointsPerCell,refData,startCell,endCell);
1546 template<
class Po
intScalar,
int spaceDim,
typename DeviceType>
1552 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.