void EBCompositeMACProjector:: correctTangentialVelocity(EBFaceFAB& a_velocity, const EBFaceFAB& a_gradient, const Box& a_grid, const EBISBox& a_ebisBox, const IntVectSet& a_cfivs) { CH_TIME("EBCompositeMACProjector::correctTangentialVelocity"); int velDir = a_velocity.direction(); int gradDir = a_gradient.direction(); //veldir is the face on which the velocity lives //graddir is the direction of the component //and the face on which the mac gradient lives CH_assert(velDir != gradDir); CH_assert(a_velocity.nComp() == 1); CH_assert(a_gradient.nComp() == 1); //updating in place in fortran so we have to save a acopy EBFaceFAB velSave(a_ebisBox, a_velocity.getCellRegion(), velDir, 1); velSave.copy(a_velocity); //interior box is the box where all of the stencil can be reached //without going out of the domain ProblemDomain domainBox = a_ebisBox.getDomain(); Box interiorBox = a_grid; interiorBox.grow(1); interiorBox &= domainBox; interiorBox.grow(-1); Box interiorFaceBox = surroundingNodes(interiorBox, velDir); if (!interiorBox.isEmpty()) { BaseFab<Real>& regVel = a_velocity.getSingleValuedFAB(); const BaseFab<Real>& regGrad = a_gradient.getSingleValuedFAB(); FORT_REGCORRECTTANVEL(CHF_FRA1(regVel,0), CHF_CONST_FRA1(regGrad,0), CHF_BOX(interiorFaceBox), CHF_INT(velDir), CHF_INT(gradDir)); } //do only irregular and boundary cells pointwise IntVectSet ivsIrreg = a_ebisBox.getIrregIVS(a_grid); IntVectSet ivsGrid(a_grid); ivsGrid -= interiorBox; ivsGrid |= ivsIrreg; FaceIterator faceit(ivsGrid, a_ebisBox.getEBGraph(), velDir, FaceStop::SurroundingWithBoundary); for (faceit.reset(); faceit.ok(); ++faceit) { //average neighboring grads in grad dir direction int numGrads = 0; Real gradAve = 0.0; const FaceIndex& velFace = faceit(); for (SideIterator sitVel; sitVel.ok(); ++sitVel) { const VolIndex& vofSide = velFace.getVoF(sitVel()); const IntVect& ivSide = vofSide.gridIndex(); //do not include stuff over coarse-fine interface and inside the domain //cfivs includes cells just outside domain if (!a_cfivs.contains(ivSide) && domainBox.contains(ivSide)) { for (SideIterator sitGrad; sitGrad.ok(); ++sitGrad) { Vector<FaceIndex> gradFaces = a_ebisBox.getFaces(vofSide, gradDir, sitGrad()); for (int iface = 0; iface < gradFaces.size(); iface++) { if (!gradFaces[iface].isBoundary()) { numGrads++; gradAve += a_gradient(gradFaces[iface], 0); } } }//end loop over gradient sides }//end cfivs check else { // inside coarse/fine interface or at domain boundary. extrapolate from neighboring vofs to get the gradient const Side::LoHiSide inSide = flip(sitVel()); const VolIndex& inSideVof = velFace.getVoF(inSide); const IntVect& inSideIV = inSideVof.gridIndex(); IntVect inSideFarIV = inSideIV; inSideFarIV[velDir] += sign(inSide); if (domainBox.contains(inSideIV) && domainBox.contains(inSideFarIV)) { Vector<VolIndex> farVofs = a_ebisBox.getVoFs(inSideFarIV); if (farVofs.size() == 1) { const VolIndex& inSideFarVof = farVofs[0]; for (SideIterator sitGrad; sitGrad.ok(); ++sitGrad) { //get the grad for the face adjoining inSideVof on the sitGrad side, in the gradDir direction Vector<FaceIndex> gradFaces = a_ebisBox.getFaces(inSideVof , gradDir, sitGrad()); Vector<FaceIndex> gradFarFaces = a_ebisBox.getFaces(inSideFarVof, gradDir, sitGrad()); if ( (gradFaces.size() == 1) && (gradFarFaces.size() == 1) ) { // if ( (!gradFaces[0].isBoundary()) && (!gradFarFaces[0].isBoundary()) ) // { const Real& inSideGrad = a_gradient(gradFaces[0], 0); const Real& inSideFarGrad = a_gradient(gradFarFaces[0], 0); Real extrapGrad = 2.0*inSideGrad - inSideFarGrad; gradAve += extrapGrad; numGrads++; // } } } } } }//end cfivs check }//end loop over sides of velocity face if (numGrads > 1) { gradAve /= Real(numGrads); } //remember that the fortran updated the velocity in place so //we have to use the saved velocity a_velocity(velFace, 0) = velSave(velFace, 0) - gradAve; } }
void EBGradDivFilter:: faceDivergence(EBFaceFAB& a_divVel, const EBCellFAB& a_gradVel, const EBCellFAB& a_vel, const EBFluxFAB& a_fluxVel, const Box& a_grid, const EBISBox& a_ebisBox, const int& a_faceDir) { CH_TIME("EBGradDivFilter::faceDivergence"); CH_assert(a_divVel.nComp() == 1); CH_assert(a_vel.nComp() == SpaceDim); a_divVel.setVal(0.0); BaseFab<Real>& regDivVel = a_divVel.getSingleValuedFAB(); const BaseFab<Real>& regVel = a_vel.getSingleValuedFAB(); const BaseFab<Real>& regGradVel= a_gradVel.getSingleValuedFAB(); Box interiorFaceBox = a_grid; interiorFaceBox.grow(a_faceDir, 1); interiorFaceBox &= m_domainFine; interiorFaceBox.grow(a_faceDir, -1); interiorFaceBox.surroundingNodes(a_faceDir); for (int divDir = 0; divDir < SpaceDim; divDir++) { FORT_EBGDFFACEDIVINCR(CHF_FRA1(regDivVel, 0), CHF_FRA(regVel), CHF_FRA(regGradVel), CHF_BOX(interiorFaceBox), CHF_REAL(m_dxFine[divDir]), CHF_INT(a_faceDir), CHF_INT(divDir)); } IntVectSet irregIVS = a_ebisBox.getIrregIVS(a_grid); FaceStop::WhichFaces stopCrit; if (m_domainFine.isPeriodic(a_faceDir)) { stopCrit = FaceStop::SurroundingWithBoundary; } else { stopCrit = FaceStop::SurroundingNoBoundary; } for (FaceIterator faceit(irregIVS, a_ebisBox.getEBGraph(), a_faceDir, stopCrit); faceit.ok(); ++faceit) { Real divVal = 0.0; for (int divDir=0; divDir<SpaceDim; divDir++) { if (divDir == a_faceDir) { divVal += (a_vel(faceit().getVoF(Side::Hi), a_faceDir) - a_vel(faceit().getVoF(Side::Lo), a_faceDir))/m_dxFine[divDir]; } else { // take average of cell-centered tangential derivatives // and increment div //so this is partial (vel_divdir)/partial (x_divdir) int velcomp = divDir; int gradcomp = getGradComp(velcomp, divDir); divVal += 0.5*(a_gradVel(faceit().getVoF(Side::Hi), gradcomp) + a_gradVel(faceit().getVoF(Side::Lo), gradcomp)); } } a_divVel(faceit(), 0) = divVal; } // end loop over interior irregular faces if (!m_domainFine.isPeriodic(a_faceDir)) { //set the boundary face divergence to an extrapolation of the neighboring face divergences for (SideIterator sit; sit.ok(); ++sit) { Box bndryBox = adjCellBox(a_grid, a_faceDir, sit(), 1); int ishift = -sign(sit()); bndryBox.shift(a_faceDir, ishift); IntVectSet bndryIVS(bndryBox); for (FaceIterator faceit(bndryIVS, a_ebisBox.getEBGraph(), a_faceDir, FaceStop::AllBoundaryOnly); faceit.ok(); ++faceit) { Real faceDiv = getDomainDivergence(a_gradVel, a_vel, a_fluxVel, a_grid, a_ebisBox, a_faceDir, faceit(), sit()); a_divVel(faceit(), 0) = faceDiv; } } } }