void EBGradDivFilter:: gradVel(EBCellFAB& a_gradVel, const EBCellFAB& a_vel, const Box& a_grid, const EBISBox& a_ebisBox, bool a_lowOrderOneSide) { CH_TIME("EBGradDivFilter::gradVel"); CH_assert(a_gradVel.nComp() == SpaceDim*SpaceDim); CH_assert(a_vel.nComp() == SpaceDim); int iLowOrderOneSide = 0; if (a_lowOrderOneSide) { iLowOrderOneSide = 1; } for (int derivDir = 0; derivDir < SpaceDim; derivDir++) { Box loBox, hiBox, centerBox; int hasLo, hasHi; EBArith::loHiCenter(loBox, hasLo, hiBox, hasHi, centerBox, m_domainFine, a_grid, derivDir); for (int velDir = 0; velDir < SpaceDim; velDir++) { BaseFab<Real>& regGradVel = a_gradVel.getSingleValuedFAB(); const BaseFab<Real>& regVel = a_vel.getSingleValuedFAB(); int gradcomp = getGradComp(velDir, derivDir); FORT_EBGDFGRADVEL(CHF_FRA1(regGradVel, gradcomp), CHF_CONST_FRA1(regVel, velDir), CHF_BOX(loBox), CHF_INT(hasLo), CHF_BOX(hiBox), CHF_INT(hasHi), CHF_BOX(centerBox), CHF_CONST_REAL(m_dxFine[derivDir]), CHF_CONST_INT(derivDir), CHF_CONST_INT(iLowOrderOneSide)); IntVectSet ivsIrreg = a_ebisBox.getIrregIVS(a_grid); if (!a_lowOrderOneSide) { ivsIrreg.grow(1); ivsIrreg &= a_grid; } for (VoFIterator vofit(ivsIrreg, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit) { const VolIndex& vof = vofit(); bool hasHi, hasLo; VolIndex vofHi, vofLo; Vector<FaceIndex> facesHi = a_ebisBox.getFaces(vof, derivDir, Side::Hi); Vector<FaceIndex> facesLo = a_ebisBox.getFaces(vof, derivDir, Side::Lo); hasHi = (facesHi.size() == 1) && (!facesHi[0].isBoundary()); hasLo = (facesLo.size() == 1) && (!facesLo[0].isBoundary()); if (hasLo) { vofLo = facesLo[0].getVoF(Side::Lo); } if (hasHi) { vofHi = facesHi[0].getVoF(Side::Hi); } Real gradVal; if (hasHi && hasLo) { gradVal = (a_vel(vofHi, velDir) - a_vel(vofLo, velDir))/(2.*m_dxFine[derivDir]); } else if (hasHi || hasLo) { //do one-sided diff CH_assert(!(hasHi && hasLo)); Side::LoHiSide side; VolIndex vofNear; if (hasLo) { side = Side::Lo; vofNear = vofLo; } else { side = Side::Hi; vofNear = vofHi; } int isign = sign(side); Vector<FaceIndex> facesFar = a_ebisBox.getFaces(vofNear, derivDir, side); bool hasVoFFar = (facesFar.size()==1) && (!facesFar[0].isBoundary()); Real valStart = a_vel(vof, velDir); Real valNear = a_vel(vofNear, velDir); if (hasVoFFar && !a_lowOrderOneSide) { VolIndex vofFar = facesFar[0].getVoF(side); Real valFar = a_vel(vofFar, velDir); gradVal = (4*(valNear - valStart)- (valFar-valStart))/(2.*isign*m_dxFine[derivDir]); } else { //do not have another point for stencil or specified low order one-sided. //drop order of derivative gradVal = (valNear - valStart)/(isign*m_dxFine[derivDir]); } } else { //only have one point, can only set gradient to zero gradVal = 0.0; } a_gradVel(vof, gradcomp) = gradVal; } } } }
void EBPlanarShockIBC:: setBndrySlopes(EBCellFAB& a_deltaPrim, const EBCellFAB& a_primState, const EBISBox& a_ebisBox, const Box& a_box, const int& a_dir) { // don't want to deal with the periodic case CH_assert(!m_domain.isPeriodic(a_dir)); CH_assert(m_isDefined); CH_assert(m_isFortranCommonSet); Box loBox,hiBox,centerBox,domain; int hasLo,hasHi; Box slopeBox = a_deltaPrim.getRegion()&m_domain; int numSlop = a_deltaPrim.nComp(); // Generate the domain boundary boxes, loBox and hiBox, if there are // domain boundarys there eblohicenter(loBox,hasLo,hiBox,hasHi,centerBox,domain, slopeBox,m_domain,a_dir); // Set the boundary slopes if necessary if ((hasLo != 0) || (hasHi != 0)) { BaseFab<Real>& regDeltaPrim = a_deltaPrim.getSingleValuedFAB(); const BaseFab<Real>& regPrimState = a_primState.getSingleValuedFAB(); /**/ FORT_SLOPEBCS(CHF_FRA(regDeltaPrim), CHF_CONST_FRA(regPrimState), CHF_CONST_REAL(m_dx), CHF_CONST_INT(a_dir), CHF_BOX(loBox), CHF_CONST_INT(hasLo), CHF_BOX(hiBox), CHF_CONST_INT(hasHi)); /**/ } for(SideIterator sit; sit.ok(); ++sit) { bool doThisSide; Box thisBox; if(sit() == Side::Lo) { doThisSide = (hasLo != 0); thisBox = loBox; } else { doThisSide = (hasHi != 0); thisBox = hiBox; } if(doThisSide) { // the cells for which the regular calculation //are incorrect are the grown set of the multivalued //cells intersected with the appropriate bndry box //and added to the irregular cells on the boundary. Box boxGrown = thisBox; boxGrown.grow(a_dir, 1); boxGrown &= m_domain; IntVectSet ivs = a_ebisBox.getMultiCells(boxGrown); ivs &= loBox; IntVectSet ivsIrreg = a_ebisBox.getIrregIVS(thisBox); ivs |= ivsIrreg; for(VoFIterator vofit(ivs, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit) { const VolIndex& vof = vofit(); //all slopes at boundary get set to zero //except normal velocity. just following the //fortran here int inormVelVar = a_dir + QVELX; for(int ivar = 0; ivar < numSlop; ivar++) { if(ivar != inormVelVar) { a_deltaPrim(vof, ivar) = 0.0; } } //for normal velocity //do strangely limited slope //just lifted from the fortran. Side::LoHiSide otherSide = flip(sit()); Vector<FaceIndex> faces = a_ebisBox.getFaces(vof, a_dir, otherSide); Real thisVel = a_primState(vof, inormVelVar); Real otherVel = 0.; for(int iface = 0; iface < faces.size(); iface++) { VolIndex otherVoF = faces[iface].getVoF(otherSide); otherVel += a_primState(otherVoF,inormVelVar); } if(faces.size() > 0) { otherVel /= Real(faces.size()); Real slope; if(sit() == Side::Lo) { slope = otherVel - thisVel; } else { slope = thisVel - otherVel; } //trick to make sure state will not change sign if(slope*thisVel < 0) { a_deltaPrim(vof, inormVelVar) = 0.0; } else { //slope and vel same sign Real rsign = 1.0; if(thisVel < 0.0) rsign = -1.0; //told you this was odd. Real dvmin = Min(Abs(slope), Abs((Real)2.*thisVel)); a_deltaPrim(vof, inormVelVar) = rsign*dvmin; } } else //no faces on high side of low boundary vof { a_deltaPrim(vof, inormVelVar) = 0.0; } } //end loop over irregular vofs at boundary } } //end loop over boundary sides }
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; } } } }