void CubatureControlVolumeSide<Scalar,ArrayPoint,ArrayWeight>::getCubature(ArrayPoint& cubPoints, ArrayWeight& cubWeights, ArrayPoint& cellCoords) const { // get array dimensions index_type numCells = static_cast<index_type>(cellCoords.dimension(0)); index_type numNodesPerCell = static_cast<index_type>(cellCoords.dimension(1)); index_type spaceDim = static_cast<index_type>(cellCoords.dimension(2)); int numNodesPerSubCV = subCVCellTopo_->getNodeCount(); // get sub-control volume coordinates (one sub-control volume per node of primary cell) Intrepid2::FieldContainer<Scalar> subCVCoords(numCells,numNodesPerCell,numNodesPerSubCV,spaceDim); Intrepid2::CellTools<Scalar>::getSubCVCoords(subCVCoords,cellCoords,*(primaryCellTopo_)); // num edges per primary cell int numEdgesPerCell = primaryCellTopo_->getEdgeCount(); // Loop over cells for (index_type icell = 0; icell < numCells; icell++){ // Get subcontrol volume side midpoints and normals int iside = 1; int numNodesPerSide = subCVCellTopo_->getNodeCount(spaceDim-1,iside); Intrepid2::FieldContainer<int> sideNodes(numNodesPerSide); for (int i=0; i<numNodesPerSide; i++){ sideNodes(i) = subCVCellTopo_->getNodeMap(spaceDim-1,iside,i); } // Loop over primary cell nodes and get side midpoints // In each primary cell the number of control volume side integration // points is equal to the number of primary cell edges. In 2d the // number of edges = number of nodes and this loop defines all side // points. In 3d this loop computes the side points for all // subcontrol volume sides for iside = 1. Additional code below // computes the remaining points for particular 3d topologies. for (index_type inode=0; inode < numNodesPerCell; inode++){ for(index_type idim=0; idim < spaceDim; idim++){ Scalar midpt = 0.0; for (int i=0; i<numNodesPerSide; i++){ midpt += subCVCoords(icell,inode,sideNodes(i),idim); } cubPoints(icell,inode,idim) = midpt/numNodesPerSide; } } // Map side center to reference subcell //Intrepid2::FieldContainer<Scalar> sideCenterLocal(1,spaceDim-1); Intrepid2::FieldContainer<double> sideCenterLocal(1,spaceDim-1); for (index_type idim = 0; idim < spaceDim-1; idim++){ sideCenterLocal(0,idim) = 0.0; } Intrepid2::FieldContainer<Scalar> refSidePoints(1,spaceDim); iside = 1; Intrepid2::CellTools<Scalar>::mapToReferenceSubcell(refSidePoints, sideCenterLocal, spaceDim-1, iside, *(subCVCellTopo_)); // Array of cell control volume coordinates Intrepid2::FieldContainer<Scalar> cellCVCoords(numNodesPerCell, numNodesPerSubCV, spaceDim); for (index_type isubcv = 0; isubcv < numNodesPerCell; isubcv++) { for (int inode = 0; inode < numNodesPerSubCV; inode++){ for (int idim = 0; idim < spaceDim; idim++){ cellCVCoords(isubcv,inode,idim) = subCVCoords(icell,isubcv,inode,idim); } } } // calculate Jacobian at side centers Intrepid2::FieldContainer<Scalar> subCVsideJacobian(numNodesPerCell, 1, spaceDim, spaceDim); Intrepid2::CellTools<Scalar>::setJacobian(subCVsideJacobian, refSidePoints, cellCVCoords, *(subCVCellTopo_)); // Get subcontrol volume side normals Intrepid2::FieldContainer<Scalar> normals(numNodesPerCell, 1, spaceDim); Intrepid2::CellTools<Scalar>::getPhysicalSideNormals(normals,subCVsideJacobian,iside,*(subCVCellTopo_)); for (index_type inode = 0; inode < numNodesPerCell; inode++) { for (index_type idim = 0; idim < spaceDim; idim++){ cubWeights(icell,inode,idim) = normals(inode,0,idim)*pow(2,spaceDim-1); } } if (primaryCellTopo_->getKey()==shards::Hexahedron<8>::key) { // first set of side midpoints and normals (above) associated with // primary cell edges 0-7 are obtained from side 1 of the // eight control volumes // second set of side midpoints and normals associated with // primary cell edges 8-11 are obtained from side 5 of the // first four control volumes. iside = 5; for (int i=0; i<numNodesPerSide; i++){ sideNodes(i) = subCVCellTopo_->getNodeMap(spaceDim-1,iside,i); } int numExtraSides = numEdgesPerCell - numNodesPerCell; for (int icount=0; icount < numExtraSides; icount++){ int iedge = icount + numNodesPerCell; for(index_type idim=0; idim < spaceDim; idim++){ Scalar midpt = 0.0; for (int i=0; i<numNodesPerSide; i++){ midpt += subCVCoords(icell,icount,sideNodes(i),idim)/numNodesPerSide; } cubPoints(icell,iedge,idim) = midpt; } } // Map side center to reference subcell iside = 5; Intrepid2::CellTools<Scalar>::mapToReferenceSubcell(refSidePoints, sideCenterLocal, spaceDim-1, iside, *(subCVCellTopo_)); // calculate Jacobian at side centers Intrepid2::CellTools<Scalar>::setJacobian(subCVsideJacobian, refSidePoints, cellCVCoords, *(subCVCellTopo_)); // Get subcontrol volume side normals Intrepid2::CellTools<Scalar>::getPhysicalSideNormals(normals,subCVsideJacobian,iside,*(subCVCellTopo_)); for (int icount = 0; icount < numExtraSides; icount++) { int iedge = icount + numNodesPerCell; for (index_type idim = 0; idim < spaceDim; idim++){ cubWeights(icell,iedge,idim) = normals(icount,0,idim)*pow(2,spaceDim-1); } } } // end if Hex if (primaryCellTopo_->getKey()==shards::Tetrahedron<4>::key) { // first set of side midpoints and normals associated with // primary cell edges 0-2 are obtained from side 1 of the // eight control volumes (above) // second set of side midpoints and normals associated with // primary cell edges 3-5 are obtained from side 5 of the // first three control volumes. iside = 5; for (int i=0; i<numNodesPerSide; i++){ sideNodes(i) = subCVCellTopo_->getNodeMap(spaceDim-1,iside,i); } for (int icount=0; icount < 3; icount++){ int iedge = icount + 3; for(index_type idim=0; idim < spaceDim; idim++){ Scalar midpt = 0.0; for (int i=0; i<numNodesPerSide; i++){ midpt += subCVCoords(icell,icount,sideNodes(i),idim)/numNodesPerSide; } cubPoints(icell,iedge,idim) = midpt; } } // Map side center to reference subcell iside = 5; Intrepid2::CellTools<Scalar>::mapToReferenceSubcell(refSidePoints, sideCenterLocal, spaceDim-1, iside, *(subCVCellTopo_)); // calculate Jacobian at side centers Intrepid2::CellTools<Scalar>::setJacobian(subCVsideJacobian, refSidePoints, cellCVCoords, *(subCVCellTopo_)); // Get subcontrol volume side normals Intrepid2::CellTools<Scalar>::getPhysicalSideNormals(normals,subCVsideJacobian,iside,*(subCVCellTopo_)); for (int icount = 0; icount < 3; icount++) { int iedge = icount + 3; for (index_type idim = 0; idim < spaceDim; idim++){ cubWeights(icell,iedge,idim) = normals(icount,0,idim)*pow(2,spaceDim-1); } } }// if tetrahedron } // end loop over cells } // end getCubature
void CubatureControlVolume<Scalar,ArrayPoint,ArrayWeight>::getCubature(ArrayPoint& cubPoints, ArrayWeight& cubWeights, ArrayPoint& cellCoords) const { // get array dimensions int numCells = cellCoords.dimension(0); int numNodesPerCell = cellCoords.dimension(1); int spaceDim = cellCoords.dimension(2); int numNodesPerSubCV = subCVCellTopo_->getNodeCount(); // get sub-control volume coordinates (one sub-control volume per node of primary cell) Intrepid2::FieldContainer<Scalar> subCVCoords(numCells,numNodesPerCell,numNodesPerSubCV,spaceDim); Intrepid2::CellTools<Scalar>::getSubCVCoords(subCVCoords,cellCoords,*(primaryCellTopo_)); // Integration points and weights for calculating sub-control volumes Intrepid2::DefaultCubatureFactory<double> subCVCubFactory; int subcvCubDegree = 2; Teuchos::RCP<Intrepid2::Cubature<double,Intrepid2::FieldContainer<double> > > subCVCubature; subCVCubature = subCVCubFactory.create(*(subCVCellTopo_), subcvCubDegree); int subcvCubDim = subCVCubature -> getDimension(); int numSubcvCubPoints = subCVCubature -> getNumPoints(); // Get numerical integration points and weights Intrepid2::FieldContainer<double> subcvCubPoints (numSubcvCubPoints, subcvCubDim); Intrepid2::FieldContainer<double> subcvCubWeights(numSubcvCubPoints); subCVCubature -> getCubature(subcvCubPoints, subcvCubWeights); // Loop over cells for (std::size_t icell = 0; icell < numCells; icell++){ // get sub-control volume centers (integration points) Intrepid2::FieldContainer<Scalar> subCVCenter(numNodesPerCell,1,spaceDim); Intrepid2::FieldContainer<Scalar> cellCVCoords(numNodesPerCell,numNodesPerSubCV,spaceDim); for (int isubcv = 0; isubcv < numNodesPerCell; isubcv++){ for (int idim = 0; idim < spaceDim; idim++){ for (int inode = 0; inode < numNodesPerSubCV; inode++){ subCVCenter(isubcv,0,idim) += subCVCoords(icell,isubcv,inode,idim)/numNodesPerSubCV; cellCVCoords(isubcv,inode,idim) = subCVCoords(icell,isubcv,inode,idim); } cubPoints(icell,isubcv,idim) = subCVCenter(isubcv,0,idim); } } // calculate Jacobian and determinant for each subCV quadrature point Intrepid2::FieldContainer<Scalar> subCVJacobian(numNodesPerCell, numSubcvCubPoints, spaceDim, spaceDim); Intrepid2::FieldContainer<Scalar> subCVJacobDet(numNodesPerCell, numSubcvCubPoints); Intrepid2::CellTools<Scalar>::setJacobian(subCVJacobian, subcvCubPoints, cellCVCoords, *(subCVCellTopo_)); Intrepid2::CellTools<Scalar>::setJacobianDet(subCVJacobDet, subCVJacobian ); // fill array with sub control volumes (the sub control volume cell measure) for (int inode = 0; inode < numNodesPerCell; inode++){ Scalar vol = 0; for (int ipt = 0; ipt < numSubcvCubPoints; ipt++){ vol += subcvCubWeights(ipt)*subCVJacobDet(inode,ipt); } cubWeights(icell,inode) = vol; } } // end cell loop } // end getCubature