void EBPoissonOp:: getOpVoFStencil(VoFStencil& a_stencil, const int& a_idir, const Vector<VolIndex>& a_allMonotoneVoFs, const EBISBox& a_ebisbox, const VolIndex& a_VoF, const bool& a_lowOrder) { for (SideIterator sit; sit.ok(); ++sit) { Side::LoHiSide side = sit(); Vector<FaceIndex> faces; faces = a_ebisbox.getFaces(a_VoF,a_idir,side); for (int iface = 0; iface < faces.size(); iface++) { FaceIndex face = faces[iface]; VoFStencil faceStencil; getOpFaceStencil(faceStencil,a_allMonotoneVoFs,a_ebisbox,a_VoF, a_idir,side,face,a_lowOrder); a_stencil += faceStencil; } } }
void setToExactFlux(EBFluxFAB& a_flux, const EBISBox& a_ebisBox, const Box& a_region, const Real& a_dx) { IntVectSet ivsregion(a_region); for (int faceDir = 0; faceDir < SpaceDim; faceDir++) { for (FaceIterator faceit(ivsregion, a_ebisBox.getEBGraph(), faceDir, FaceStop::SurroundingWithBoundary); faceit.ok(); ++faceit) { RealVect xval; IntVect iv = faceit().gridIndex(Side::Hi); RealVect centroid = a_ebisBox.centroid(faceit()); for (int idir = 0; idir < SpaceDim; idir++) { if (idir == faceDir) { xval[idir] = (Real(iv[idir]))*a_dx; } else { xval[idir] = (Real(iv[idir]) + 0.5 + centroid[idir])*a_dx; } } Real fluxDir = exactFlux(xval, faceDir); a_flux[faceDir](faceit(), 0) = fluxDir; } } //end loop over face directions }
void NoFlowAdvectBC:: fluxBC(EBFluxFAB& a_primGdnv, const EBCellFAB& a_primCenter, const EBCellFAB& a_primExtrap, const Side::LoHiSide& a_side, const Real& a_time, const EBISBox& a_ebisBox, const DataIndex& a_dit, const Box& a_box, const Box& a_faceBox, const int& a_dir) { CH_assert(m_isDefined); Box FBox = a_faceBox; Box cellBox = FBox; CH_assert(a_primGdnv[a_dir].nComp()==1); // Determine which side and thus shifting directions int isign = sign(a_side); cellBox.shiftHalf(a_dir,isign); // Is there a domain boundary next to this grid if (!m_domain.contains(cellBox)) { cellBox &= m_domain; // Find the strip of cells next to the domain boundary Box bndryBox = adjCellBox(cellBox, a_dir, a_side, 1); // Shift things to all line up correctly bndryBox.shift(a_dir,-isign); IntVectSet ivs(bndryBox); for (VoFIterator vofit(ivs, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit) { const VolIndex& vof = vofit(); Vector<FaceIndex> bndryFaces = a_ebisBox.getFaces(vof, a_dir, a_side); for (int iface= 0; iface < bndryFaces.size(); iface++) { const FaceIndex& face = bndryFaces[iface]; //set all fluxes to zero then fix momentum flux //solid wall if (a_dir == m_velComp) { a_primGdnv[a_dir](face, 0) = 0.0; } else { a_primGdnv[a_dir](face, 0) = a_primExtrap(vof, 0); } } } } }
bool EBFluxRegister:: copyBIFFToEBFF(EBFaceFAB& a_dst, const BaseIFFAB<Real>& a_src, const Box & a_box, const EBISBox& a_ebisBox) { IntVectSet ivs = a_src.getIVS(); ivs &= a_box; bool hasCells = !(ivs.isEmpty()); if (hasCells) { a_dst.define(a_ebisBox, a_box, a_src.direction(), a_src.nComp()); a_dst.setVal(0.); for (FaceIterator faceit(ivs, a_ebisBox.getEBGraph(), a_src.direction(), FaceStop::SurroundingWithBoundary); faceit.ok(); ++faceit) { for (int icomp = 0; icomp < a_src.nComp(); icomp++) { a_dst(faceit(), icomp) = a_src(faceit(), icomp); } } } return (hasCells); }
int testEBFluxFAB(const EBISBox& a_ebisBox, const Box& a_box) { Interval comps(0,0); IntVectSet ivs(a_box); EBFluxFAB srcFab( a_ebisBox, a_box, 1); EBFluxFAB dstFab( a_ebisBox, a_box, 1); for (int idir = 0; idir < SpaceDim; idir++) { //set source fab to right ans for (FaceIterator faceit(ivs, a_ebisBox.getEBGraph(), idir, FaceStop::SurroundingWithBoundary); faceit.ok(); ++faceit) { srcFab[idir](faceit(), 0) = rightAns(faceit()); } } //linearize the data to dst int sizeFab = srcFab.size(a_box, comps); unsigned char* buf = new unsigned char[sizeFab]; srcFab.linearOut(buf, a_box, comps); dstFab.linearIn( buf, a_box, comps); delete[] buf; //check the answer int eekflag = 0; for (int idir = 0; idir < SpaceDim; idir++) { Real tolerance = 0.001; for (FaceIterator faceit(ivs, a_ebisBox.getEBGraph(), idir, FaceStop::SurroundingWithBoundary); faceit.ok(); ++faceit) { Real correct = rightAns(faceit()); if (Abs(dstFab[idir](faceit(), 0) - correct) > tolerance) { pout() << "ivfab test failed at face " << faceit().gridIndex(Side::Lo) << faceit().gridIndex(Side::Hi) << endl; eekflag = -4; return eekflag; } } } return 0; }
void EBGradDivFilter:: getAreaFracs(Vector<FaceIndex> a_facesLo[SpaceDim], Vector<FaceIndex> a_facesHi[SpaceDim], bool a_hasFacesLo[SpaceDim], bool a_hasFacesHi[SpaceDim], RealVect& a_areaFracLo, RealVect& a_areaFracHi, const VolIndex& a_vof, const EBISBox& a_ebisBox) { for (int idir = 0; idir < SpaceDim; idir++) { Real areaSumLo = 0; Real areaSumHi = 0; a_facesLo[idir] = a_ebisBox.getFaces(a_vof, idir, Side::Lo); a_facesHi[idir] = a_ebisBox.getFaces(a_vof, idir, Side::Hi); a_hasFacesLo[idir] = ( ( a_facesLo[idir].size() > 0) && (!a_facesLo[idir][0].isBoundary())); a_hasFacesHi[idir] = ( ( a_facesHi[idir].size() > 0) && (!a_facesHi[idir][0].isBoundary())); //want boundary faces to look covered if (a_hasFacesLo[idir]) { for (int iface = 0; iface < a_facesLo[idir].size(); iface++) { areaSumLo += a_ebisBox.areaFrac(a_facesLo[idir][iface]); } } //want boundary faces to look covered if (a_hasFacesHi[idir]) { for (int iface = 0; iface < a_facesHi[idir].size(); iface++) { areaSumHi += a_ebisBox.areaFrac(a_facesHi[idir][iface]); } } a_areaFracLo[idir] = areaSumLo; a_areaFracHi[idir] = areaSumHi; } }
void setToExactDivF(EBCellFAB& a_exactDivF, const EBISBox& a_ebisBox, const Box& a_region, const Real& a_dx) { a_exactDivF.setVal(0.); IntVectSet ivsregion(a_region); for (VoFIterator vofit(ivsregion, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit) { const VolIndex& vof = vofit(); RealVect xval; IntVect iv = vof.gridIndex(); for (int idir = 0; idir < SpaceDim; idir++) { xval[idir] = (Real(iv[idir]) + 0.5)*a_dx; } Real solnrv = exactDivergence(xval); Real kappa = a_ebisBox.volFrac(vof); a_exactDivF(vof,0) = kappa*solnrv; } }
int testIVFAB(const EBISBox& a_ebisBox, const Box& a_box) { IntVectSet ivs = a_ebisBox.getIrregIVS(a_box); if (ivs.isEmpty()) return 0; Interval comps(0,0); BaseIVFAB<Real> srcFab(ivs, a_ebisBox.getEBGraph(), 1); BaseIVFAB<Real> dstFab(ivs, a_ebisBox.getEBGraph(), 1); //set source fab to right ans for (VoFIterator vofit(ivs, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit) { srcFab(vofit(), 0) = rightAns(vofit()); } //linearize the data to dst int sizeFab = srcFab.size(a_box, comps); unsigned char* buf = new unsigned char[sizeFab]; srcFab.linearOut(buf, a_box, comps); dstFab.linearIn( buf, a_box, comps); delete[] buf; //check the answer int eekflag = 0; Real tolerance = 0.001; for (VoFIterator vofit(ivs, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit) { Real correct = rightAns(vofit()); if (Abs(dstFab(vofit(), 0) - correct) > tolerance) { pout() << "ivfab test failed at vof " << vofit().gridIndex() << endl; eekflag = -1; return eekflag; } } return 0; }
Real divergence(const EBFluxFAB& a_func, const RealVect& a_bndryFlux, const EBISBox& a_ebisBox, const VolIndex& a_vof, const Real& a_dx) { Real retval = 0; Real bndryArea = a_ebisBox.bndryArea(a_vof); RealVect normal = a_ebisBox.normal(a_vof); for (int idir = 0; idir < SpaceDim; idir++) { Real bndryFlux = a_bndryFlux[idir]; //normal already dealt with Real bndryContrib = -bndryFlux*bndryArea*normal[idir]; Real openContrib = 0; if (bndryArea > 1.0e-3) { openContrib = 0; } for (SideIterator sit; sit.ok(); ++sit) { int isign = sign(sit()); Real rsign = isign; Vector<FaceIndex> faces = a_ebisBox.getFaces(a_vof, idir, sit()); for (int iface = 0; iface < faces.size(); ++iface) { Real areaFrac = a_ebisBox.areaFrac(faces[iface]); Real faceFlux = a_func[idir](faces[iface], 0); openContrib += rsign*faceFlux*areaFrac; } } retval += openContrib + bndryContrib; } retval /= a_dx; return retval; }
void EBLevelAdvect:: advectToFacesBCG(EBFluxFAB& a_extrapState, BaseIVFAB<Real>& a_boundaryPrim, const EBCellFAB & a_consState, const EBCellFAB & a_normalVel, const EBFluxFAB & a_advectionVel, const Box& a_cellBox, const EBISBox& a_ebisBox, const Real& a_dt, const Real& a_time, const EBCellFAB & a_source, const DataIndex& a_dit, bool a_doBoundaryPrim) { CH_TIME("EBLevelAdvect::advectToFacesBCG (fluxfab)"); IntVectSet cfivs; //not used here. only used in flux interpolation m_ebPatchAdvect[a_dit]->setTimeAndDt(a_time, a_dt); // EBCellFAB& primState = m_ebPatchAdvect[a_dit]->getPrimState(); m_ebPatchAdvect[a_dit]->setVelocities(a_normalVel, a_advectionVel); //placeholder (no flattening used here) EBCellFAB flattening; //not reused EBCellFAB slopesPrim[SpaceDim]; EBCellFAB slopesSeco[SpaceDim]; bool verbose = false; m_ebPatchAdvect[a_dit]->extrapolateBCG(a_extrapState, // primState, slopesPrim, slopesSeco, flattening, a_consState, a_source, a_cellBox, a_dit, verbose); if (a_doBoundaryPrim) { IntVectSet irregIVS = a_ebisBox.getIrregIVS(a_cellBox); m_ebPatchAdvect[a_dit]->computeEBIrregFlux(a_boundaryPrim, // primState, a_consState, slopesPrim, irregIVS, a_source); } }
void divergence(EBCellFAB& a_divF, const EBFluxFAB& a_flux, const EBISBox& a_ebisBox, const Box& a_box, const RealVect& a_fluxVal, const Real& a_dx) { IntVectSet ivs(a_box); for (VoFIterator vofit(ivs, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit) { Real divval = divergence(a_flux, a_fluxVal, a_ebisBox, vofit(), a_dx); a_divF(vofit(), 0) = divval; } }
void setBorkedFlux(EBFluxFAB& a_flux, const EBISBox& a_ebisBox, const Box& a_box, const RealVect& a_fluxVal, const BaseFab<int>& a_map) { for (int idir = 0; idir < SpaceDim; idir++) { Real bogval = 0; //the bogus value will be zero so it will not //do to have the correct value be zero if (Abs(a_fluxVal[idir]) < 1.0e-3) bogval = 1.0; a_flux[idir].setVal(a_fluxVal[idir]); //if i am in a 1d box and the box next to me //is 2d, set the border flux to for (SideIterator sit; sit.ok(); ++sit) { Box borderBox; if (sit() == Side::Lo) { borderBox = adjCellLo(a_box, idir, -1); } else { borderBox = adjCellHi(a_box, idir, -1); } for (BoxIterator bit(borderBox); bit.ok(); ++bit) { const IntVect& thisIV = bit(); IntVect thatIV = thisIV + sign(sit())*BASISV(idir); if ((a_map(thisIV, 0) == 1) && (a_map(thatIV, 0) == 2)) { Vector<FaceIndex> faces = a_ebisBox.getAllFaces(thisIV, idir, sit()); for (int iface = 0; iface < faces.size(); iface++) { a_flux[idir](faces[iface],0) = bogval; } } } } } }
void EBCFData:: getEBCFIVSGrid(IntVectSet& a_ebcfivs, const Box& a_grid, const int& a_idir, const Side::LoHiSide& a_side, const IntVect& a_diagGrow, const ProblemDomain& a_domain, const IntVectSet& a_cfivs, const EBISBox& a_ebisBox) { Box gridSide = adjCellBox(a_grid, a_idir, a_side, 1); Box grownBoxSide = gridSide; grownBoxSide &= a_domain; for (int jdir = 0; jdir < SpaceDim; jdir++) { if (jdir != a_idir) { grownBoxSide.grow(jdir, a_diagGrow[jdir]); } } grownBoxSide &= a_domain; a_ebcfivs = a_cfivs; for (int jdir = 0; jdir < SpaceDim; jdir++) { if (jdir != a_idir) { a_ebcfivs.grow(jdir, a_diagGrow[jdir]); } } IntVectSet ivsIrreg = a_ebisBox.getIrregIVS(grownBoxSide); ivsIrreg.grow(3); ivsIrreg &= a_domain; a_ebcfivs &= ivsIrreg; a_ebcfivs &= gridSide; }
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 EBCompositeMACProjector:: correctVelocityComponent(BaseIVFAB<Real> & a_coveredVel, const Vector<VolIndex>& a_coveredFace, const IntVectSet & a_coveredSets, const EBFluxFAB & a_macGradient, const EBISBox & a_ebisBox, int a_coveredFaceDir, Side::LoHiSide a_sd, int a_faceGradComp) { CH_TIME("EBCompositeMACProjector::correctVelocityComponent"); //if a_coveredFaceDir == faceGradComp, just linearly extrapolate gradient and subtract. //if a_coveredFaceDir != faceGradComp, need to average to cell centers then extrapolate and subtract CH_assert(a_coveredVel.nComp() == 1); CH_assert(a_macGradient.nComp() == 1); const EBFaceFAB& macGradFAB = a_macGradient[a_faceGradComp]; for (int ivof = 0; ivof < a_coveredFace.size(); ivof++) { const VolIndex& vof = a_coveredFace[ivof]; Vector<FaceIndex> nearFaces, farFaces; bool hasNearFaces = false; bool hasFarFaces = false; VolIndex nearVoF, farVoF; FaceIndex nearFace, farFace; nearFaces = a_ebisBox.getFaces(vof, a_coveredFaceDir, flip(a_sd)); hasNearFaces = (nearFaces.size()==1) && (!nearFaces[0].isBoundary()); if (hasNearFaces) { nearFace = nearFaces[0]; nearVoF = nearFace.getVoF(flip(a_sd)); farFaces = a_ebisBox.getFaces(nearVoF, a_coveredFaceDir, flip(a_sd)); hasFarFaces = (farFaces.size()==1) && (!farFaces[0].isBoundary()); if (hasFarFaces) { farFace = farFaces[0]; farVoF = farFace.getVoF(flip(a_sd)); } } Real extrapGrad; if (a_coveredFaceDir == a_faceGradComp) { //if a_coveredFaceDir == faceGradComp, just linearly extrapolate gradient and subtract. if (hasNearFaces && hasFarFaces) { Real nearGrad = macGradFAB(nearFace, 0); Real farGrad = macGradFAB(farFace, 0); extrapGrad = 2.0*nearGrad - farGrad; } else if (hasNearFaces) { extrapGrad = macGradFAB(nearFace, 0); } else { extrapGrad = 0.0; } } else { //if a_coveredFaceDir != faceGradComp, need to average to cell centers then extrapolate and subtract Real nearGrad = getAverageFaceGrad(vof, macGradFAB, a_ebisBox, a_faceGradComp); if (hasNearFaces) { Real farGrad = getAverageFaceGrad(nearVoF, macGradFAB, a_ebisBox, a_faceGradComp); extrapGrad = 1.5*nearGrad - 0.5*farGrad; } else { extrapGrad = nearGrad; } } a_coveredVel(vof, 0) -= extrapGrad; } }
Real getAverageFaceGrad(const VolIndex& a_vof, const EBFaceFAB& a_macGradient, const EBISBox& a_ebisBox, int a_faceDir) { CH_TIME("EBCompositeMACProjector::getAverageFaceGrad"); Vector<FaceIndex> hiFaces = a_ebisBox.getFaces(a_vof, a_faceDir, Side::Hi); Vector<FaceIndex> loFaces = a_ebisBox.getFaces(a_vof, a_faceDir, Side::Lo); bool hasHiFaces = (hiFaces.size() > 0); bool hasLoFaces = (loFaces.size() > 0); Real hiVal = 0.0; Real loVal = 0.0; if (hasHiFaces) { for (int iface = 0; iface < hiFaces.size(); iface++) { hiVal += a_macGradient(hiFaces[iface], 0); } hiVal /= hiFaces.size(); } if (hasLoFaces) { for (int iface = 0; iface < loFaces.size(); iface++) { loVal += a_macGradient(loFaces[iface], 0); } loVal /= loFaces.size(); } if (!hasLoFaces && hasHiFaces) { //only want to do the wacky extrapolation thing if not multivalued if ((hiFaces.size() == 1) && (!hiFaces[0].isBoundary())) { const VolIndex& hiVoF = hiFaces[0].getVoF(Side::Hi); Vector<FaceIndex> farFaces = a_ebisBox.getFaces(hiVoF, a_faceDir, Side::Hi); if (farFaces.size() > 0) { Real farVal = 0.0; for (int iface = 0; iface < farFaces.size(); iface++) { farVal += a_macGradient(farFaces[iface], 0); } farVal /= farFaces.size(); loVal = 2*hiVal - farVal; } else { loVal = hiVal; } } else { loVal = hiVal; } } if (!hasHiFaces && hasLoFaces) { //only want to do the wacky extrapolation thing if not multivalued if ((loFaces.size() == 1) && (!loFaces[0].isBoundary())) { const VolIndex& hiVoF = loFaces[0].getVoF(Side::Lo); Vector<FaceIndex> farFaces = a_ebisBox.getFaces(hiVoF, a_faceDir, Side::Lo); if (farFaces.size() > 0) { Real farVal = 0.0; for (int iface = 0; iface < farFaces.size(); iface++) { farVal += a_macGradient(farFaces[iface], 0); } farVal /= farFaces.size(); hiVal = 2*loVal - farVal; } else { hiVal = loVal; } } else { hiVal = loVal; } } Real retval = 0.5*(hiVal + loVal); return retval; }
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 EBPlanarShockIBC:: fluxBC(EBFluxFAB& a_flux, const EBCellFAB& a_primCenter, const EBCellFAB& a_primExtrap, const Side::LoHiSide& a_side, const Real& a_time, const EBISBox& a_ebisBox, const DataIndex& a_dit, const Box& a_box, const Box& a_faceBox, const int& a_dir) { CH_assert(m_isDefined); CH_assert(m_isFortranCommonSet); CH_assert(!m_domain.isPeriodic(a_dir)); Box FBox = a_flux[a_dir].getSingleValuedFAB().box(); Box cellBox = FBox; int numFlux = a_flux[a_dir].nComp(); // Determine which side and thus shifting directions int isign = sign(a_side); cellBox.shiftHalf(a_dir,isign); // Is there a domain boundary next to this grid if (!m_domain.contains(cellBox)) { cellBox &= m_domain; // Find the strip of cells next to the domain boundary Box boundaryBox = bdryBox(cellBox, a_dir, a_side, 1); // Shift things to all line up correctly boundaryBox.shiftHalf(a_dir,-isign); BaseFab<Real>& regFlux = a_flux[a_dir].getSingleValuedFAB(); const BaseFab<Real>& regPrimExtrap = a_primExtrap.getSingleValuedFAB(); // Set the boundary fluxes bool inbackofshock = (!m_shockbackward && a_side == Side::Lo) || ( m_shockbackward && a_side == Side::Hi); if(a_dir == m_shocknorm && inbackofshock) { regFlux.shiftHalf(a_dir,-isign); // Set the boundary fluxes /**/ FORT_EXTRAPBC(CHF_FRA(regFlux), CHF_CONST_FRA(regPrimExtrap), CHF_CONST_REAL(m_dx), CHF_CONST_INT(a_dir), CHF_BOX(boundaryBox)); /**/ // Shift returned fluxes to be face centered regFlux.shiftHalf(a_dir,isign); //now for the multivalued cells. Since it is pointwise, //the regular calc is correct for all single-valued cells. IntVectSet ivs = a_ebisBox.getMultiCells(boundaryBox); for(VoFIterator vofit(ivs, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit) { const VolIndex& vof = vofit(); Vector<Real> qgdnv(QNUM); Vector<Real> fluxv(FNUM); for(int ivar = 0; ivar < QNUM; ivar++) { qgdnv[ivar] = a_primExtrap(vof, ivar); } Vector<FaceIndex> bndryFaces = a_ebisBox.getFaces(vof, a_dir, a_side); for(int iface= 0; iface < bndryFaces.size(); iface++) { /**/ FORT_POINTGETFLUX(CHF_VR(fluxv), CHF_VR(qgdnv), CHF_CONST_INT(a_dir)); /**/ const FaceIndex& face = bndryFaces[iface]; for(int ivar = 0; ivar < FNUM; ivar++) { a_flux[a_dir](face, ivar) = fluxv[ivar]; } } } } //end if on the back side of the shock else { regFlux.shiftHalf(a_dir,-isign); //solid wall bcs FORT_SLIPWALLSOLIDBC(CHF_FRA(regFlux), CHF_CONST_FRA(regPrimExtrap), CHF_CONST_INT(isign), CHF_CONST_REAL(m_dx), CHF_CONST_INT(a_dir), CHF_BOX(boundaryBox)); // Shift returned fluxes to be face centered regFlux.shiftHalf(a_dir,isign); int inormMomVar = CMOMX + a_dir; int inormVelVar = QVELX + a_dir; //now for the multivalued cells. Since it is pointwise, //the regular calc is correct for all single-valued cells. IntVectSet ivs = a_ebisBox.getMultiCells(boundaryBox); for(VoFIterator vofit(ivs, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit) { const VolIndex& vof = vofit(); //set all fluxes except normal momentum to zero. //set normal momemtum flux to sign(normal)*pressure Vector<FaceIndex> bndryFaces = a_ebisBox.getFaces(vof, a_dir, a_side); for(int iface= 0; iface < bndryFaces.size(); iface++) { const FaceIndex& face = bndryFaces[iface]; //set all fluxes to zero then fix normal momentum for(int ivar = 0; ivar < numFlux; ivar++) { a_flux[a_dir](face, ivar) = 0; } Real press = a_primExtrap(vof, QPRES); Real dense = a_primExtrap(vof, QRHO); Real unorm = a_primExtrap(vof, inormVelVar); Real speed = sqrt(m_gamma*press/dense); a_flux[a_dir](face, inormMomVar) = press + isign*dense*unorm*speed; } } } } }
void kappaDivergence(EBCellFAB& a_divF, const EBFluxFAB& a_flux, const EBISBox& a_ebisBox, const Box& a_box, const Real& a_dx) { //set the divergence initially to zero //then loop through directions and increment the divergence //with each directions flux difference. a_divF.setVal(0.0); BaseFab<Real>& regDivF = a_divF.getSingleValuedFAB(); regDivF.setVal(0.); for (int idir = 0; idir < SpaceDim; idir++) { //update for the regular vofs in the nonconservative //case works for all single valued vofs. /* do the regular vofs */ /**/ const EBFaceFAB& fluxDir = a_flux[idir]; const BaseFab<Real>& regFluxDir = fluxDir.getSingleValuedFAB(); int ncons = 1; FORT_DIVERGEF( CHF_BOX(a_box), CHF_FRA(regDivF), CHF_CONST_FRA(regFluxDir), CHF_CONST_INT(idir), CHF_CONST_INT(ncons), CHF_CONST_REAL(a_dx)); /**/ } //update the irregular vofs using conservative diff IntVectSet ivsIrreg = a_ebisBox.getIrregIVS(a_box); for (VoFIterator vofit(ivsIrreg, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit) { const VolIndex& vof = vofit(); //divergence was set in regular update. we reset it // to zero and recalc. Real update = 0.; for ( int idir = 0; idir < SpaceDim; idir++) { const EBFaceFAB& fluxDir = a_flux[idir]; for (SideIterator sit; sit.ok(); ++sit) { int isign = sign(sit()); Vector<FaceIndex> faces = a_ebisBox.getFaces(vof, idir, sit()); for (int iface = 0; iface < faces.size(); iface++) { const FaceIndex& face = faces[iface]; Real areaFrac = a_ebisBox.areaFrac(face); Real faceFlux =fluxDir(face, 0); update += isign*areaFrac*faceFlux; } } } //add EB boundary condtions in divergence const IntVect& iv = vof.gridIndex(); Real bndryArea = a_ebisBox.bndryArea(vof); RealVect bndryCent = a_ebisBox.bndryCentroid(vof); RealVect normal = a_ebisBox.normal(vof); RealVect bndryLoc; RealVect exactF; for (int idir = 0; idir < SpaceDim; idir++) { bndryLoc[idir] = a_dx*(iv[idir] + 0.5 + bndryCent[idir]); } for (int idir = 0; idir < SpaceDim; idir++) { exactF[idir] = exactFlux(bndryLoc, idir); } Real bndryFlux = PolyGeom::dot(exactF, normal); update -= bndryFlux*bndryArea; update /= a_dx; //note NOT divided by volfrac a_divF(vof, 0) = update; } }
void EBGradDivFilter:: cellGradient(EBCellFAB& a_gradDiv, const EBCellFAB& a_gradVel, const EBCellFAB& a_vel, const EBFluxFAB& a_fluxVel, const EBFluxFAB& a_div, const Box& a_grid, const EBISBox& a_ebisBox, const DataIndex& a_dataIndex, bool a_multiplyByLambda, bool a_noExtrapToCovered) { CH_TIME("EBGradDivFilter::cellGradient"); int icomp = 0; EBCellFAB& lambdaFAB = m_lambda[a_dataIndex]; IntVectSet irregIVS = a_ebisBox.getIrregIVS(a_grid); for (int faceDir = 0; faceDir < SpaceDim; faceDir++) { const EBFaceFAB& faceDiv = a_div[faceDir]; const BaseFab<Real>& regFaceDiv = faceDiv.getSingleValuedFAB(); const BaseFab<Real>& regLambda = lambdaFAB.getSingleValuedFAB(); BaseFab<Real>& regGradDiv = a_gradDiv.getSingleValuedFAB(); int imultByLambda = 0; if (a_multiplyByLambda) { imultByLambda = 1; } FORT_EBGDFCELLGRAD(CHF_FRA1(regGradDiv, faceDir), CHF_CONST_FRA1(regFaceDiv, icomp), CHF_CONST_FRA1(regLambda, icomp), CHF_BOX(a_grid), CHF_CONST_REAL(m_dxFine[faceDir]), CHF_CONST_INT(faceDir), CHF_CONST_INT(imultByLambda)); //nonconservative gradient for (VoFIterator vofit(irregIVS, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit) { const VolIndex& vof = vofit(); Real gradVal = 0.0; Vector<FaceIndex> facesHi = a_ebisBox.getFaces(vof, faceDir, Side::Hi); Vector<FaceIndex> facesLo = a_ebisBox.getFaces(vof, faceDir, Side::Lo); bool zeroGrad = a_noExtrapToCovered && ((facesHi.size() == 0) || (facesLo.size() == 0)); if (zeroGrad) { gradVal = 0; } else { Real valHi= 0; if (facesHi.size() > 0) { for (int iface = 0; iface < facesHi.size(); iface++) { valHi += faceDiv(facesHi[iface], icomp); } valHi /= facesHi.size(); } else { valHi = ccpGetCoveredExtrapValue(vof, faceDir, Side::Hi, faceDiv, a_ebisBox, a_grid, m_domainFine, m_dxFine, icomp); } Real valLo= 0; if (facesLo.size() > 0) { for (int iface = 0; iface < facesLo.size(); iface++) { valLo += faceDiv(facesLo[iface], 0); } valLo /= facesLo.size(); } else { valLo = ccpGetCoveredExtrapValue(vof, faceDir, Side::Lo , faceDiv, a_ebisBox, a_grid, m_domainFine, m_dxFine, icomp); } gradVal = (valHi-valLo)/(m_dxFine[faceDir]); //multiply the lambda in since we have the area fractions lying about if (a_multiplyByLambda) { Real lambda = lambdaFAB(vof, 0); gradVal *= lambda; } } a_gradDiv(vof, faceDir) = gradVal; } } }
void EBScalarAdvectBC:: fluxBC(EBFluxFAB& a_facePrim, const EBCellFAB& a_Wcenter, const EBCellFAB& a_Wextrap, const Side::LoHiSide& a_side, const Real& a_time, const EBISBox& a_ebisBox, const DataIndex& a_dit, const Box& a_box, const Box& a_faceBox, const int& a_faceDir) { // a_facePrim.setVal(1.0); CH_assert(m_isDefined); CH_assert(!m_domain.isPeriodic(a_faceDir)); CH_assert(m_injectionBCFunc != NULL); //gets face centered region of data Box FBox = a_facePrim[a_faceDir].getRegion(); Box cellBox = a_faceBox; CH_assert(a_facePrim[a_faceDir].nComp() == 1); // Determine which side and thus shifting directions int isign = sign(a_side); cellBox.shiftHalf(a_faceDir,isign); //figure out if we are on a wall and if its an inflow and the inflow value bool isInflow = ((a_side == Side::Lo) && (a_faceDir==m_inflowDir)); bool isOutflow = ((a_side == Side::Hi) && (a_faceDir==m_inflowDir)); // Is there a domain boundary next to this grid if (!m_domain.contains(cellBox)) { cellBox &= m_domain; // Find the strip of cells next to the domain boundary Box bndryBox = adjCellBox(cellBox, a_faceDir, a_side, 1); // Shift things to all line up correctly bndryBox.shift(a_faceDir,-isign); IntVectSet ivs(bndryBox); Real scalVal, velBC; for (VoFIterator vofit(ivs, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit) { const VolIndex& vof = vofit(); Vector<FaceIndex> bndryFaces = a_ebisBox.getFaces(vof, a_faceDir, a_side); for (int iface= 0; iface < bndryFaces.size(); iface++) { //this all will work for the case of spatially varying inflow //for inhomogeneous other faces, this is wrong. const FaceIndex& face = bndryFaces[iface]; if (isOutflow) // assuming injection is from the outflow face (injectibe into counter flow) { // figure out if you are inside or outside the tube // inside the tube scalar injection val = 1.0; outside, extrap RealVect prob_lo = RealVect::Zero; const RealVect tubeCenter = m_injectionBCFunc->getTubeCenter(); Real tubeRadius = m_injectionBCFunc->getTubeRadius(); bool isInsideTube = false; const RealVect loc = EBArith::getFaceLocation(face, m_dx, prob_lo); CH_assert(loc[m_inflowDir] == tubeCenter[m_inflowDir]); Real radius = m_injectionBCFunc->getRadius(loc); // start hardwire Real wallThickness = 0.075; ParmParse pp; pp.get("wall_thickness",wallThickness); Real bcFactor = 0.5; // % of outflow face to be set to inflow condition tubeRadius += wallThickness * bcFactor /2.0; if (radius <= tubeRadius) { isInsideTube = true; } isInsideTube ? scalVal = m_scalarInflowValue : scalVal = a_Wextrap(vof, 0); } // end if outflow else if (isInflow) { scalVal = 0.0; } else // solid wall { scalVal = 0.0; } a_facePrim[a_faceDir](face,0) = scalVal; } // end face loop } // end vofit loop } }
void InflowOutflowAdvectBC:: fluxBC(EBFluxFAB& a_primGdnv, const EBCellFAB& a_primCenter, const EBCellFAB& a_primExtrap, const Side::LoHiSide& a_side, const Real& a_time, const EBISBox& a_ebisBox, const DataIndex& a_dit, const Box& a_box, const Box& a_faceBox, const int& a_dir) { CH_assert(m_isDefined); CH_assert(!m_domain.isPeriodic(a_dir)); //gets face centered region of data Box FBox = a_primGdnv[a_dir].getRegion(); Box cellBox = a_faceBox; CH_assert(a_primGdnv[a_dir].nComp() == 1); // Determine which side and thus shifting directions int isign = sign(a_side); cellBox.shiftHalf(a_dir,isign); //figure out if we are on a wall and if its an inflow and the inflow value bool isInflow = ((a_side == Side::Lo) && (a_dir==m_flowDir)); bool isOutflow = ((a_side == Side::Hi) && (a_dir==m_flowDir)); // Is there a domain boundary next to this grid if (!m_domain.contains(cellBox)) { cellBox &= m_domain; // Find the strip of cells next to the domain boundary Box bndryBox = adjCellBox(cellBox, a_dir, a_side, 1); // Shift things to all line up correctly bndryBox.shift(a_dir,-isign); IntVectSet ivs(bndryBox); for (VoFIterator vofit(ivs, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit) { const VolIndex& vof = vofit(); Vector<FaceIndex> bndryFaces = a_ebisBox.getFaces(vof, a_dir, a_side); for (int iface= 0; iface < bndryFaces.size(); iface++) { //this all will work for the case of spatially varying inflow //for inhomogeneous other faces, this is wrong. const FaceIndex& face = bndryFaces[iface]; Real velComp = 1.e99; if (isInflow && (m_velComp == m_flowDir)) { if (!m_doJet1PoiseInflow) { velComp = m_jet1inflowVel; } else if (m_doJet1PoiseInflow) { //set coordinates based on slip walls RealVect prob_lo = RealVect::Zero; //assumes inflow boundary is always on lo side of domain const RealVect loc = EBArith::getFaceLocation(face, m_dx, prob_lo); Real radius = m_jet1PoiseInflowFunc->getRadius(loc); velComp = m_jet1PoiseInflowFunc->getVel(radius)[m_flowDir]; } } else if (isInflow && (m_velComp != m_flowDir)) { velComp = 0.0; } else if (isOutflow) { if (!m_doJet2) { velComp = a_primExtrap(vof, 0); } else if (m_doJet2) { RealVect prob_lo = RealVect::Zero; const RealVect tubeCenter = m_jet2PoiseInflowFunc->getTubeCenter(); Real tubeRadius = m_jet2PoiseInflowFunc->getTubeRadius(); bool isInsideTube = false; const RealVect loc = EBArith::getFaceLocation(face, m_dx, prob_lo); CH_assert(loc[m_flowDir] == tubeCenter[m_flowDir]); Real radius = m_jet2PoiseInflowFunc->getRadius(loc); // start hardwire Real wallThickness = 0.075; ParmParse pp; pp.get("wall_thickness",wallThickness); Real bcFactor = 0.5; // % of outflow face to be set to inflow condition tubeRadius += wallThickness * bcFactor /2.0; // end hardwire if (radius <= tubeRadius) { isInsideTube = true; } if (isInsideTube && (m_velComp == m_flowDir)) { if (m_doJet2PoiseInflow) { velComp = m_jet2PoiseInflowFunc->getVel(radius)[m_flowDir]; } else if (!m_doJet2PoiseInflow) { velComp = m_jet2inflowVel; } } else if (isInsideTube && (m_velComp != m_flowDir)) { velComp = 0.0; } else if (!(isInsideTube)) { velComp = a_primExtrap(vof, 0); } } } else //solid wall { if (a_dir == m_velComp) { velComp = 0.0; } else { velComp = a_primExtrap(vof, 0); } } a_primGdnv[a_dir](face, 0) = velComp; } } } }
void EBPoissonOp:: getOpFaceStencil(VoFStencil& a_stencil, const Vector<VolIndex>& a_allMonotoneVoFs, const EBISBox& a_ebisbox, const VolIndex& a_VoF, int a_dir, const Side::LoHiSide& a_side, const FaceIndex& a_face, const bool& a_lowOrder) { a_stencil.clear(); const RealVect& faceCentroid = a_ebisbox.centroid(a_face); const IntVect& origin = a_VoF.gridIndex(); IntVect dirs = IntVect::Zero; for (int idir = 0; idir < SpaceDim; idir++) { if (idir != a_dir) { IntVect ivPlus = origin; ivPlus[idir] += 1; if (faceCentroid[idir] < 0.0) { dirs[idir] = -1; } else if (faceCentroid[idir] > 0.0) { dirs[idir] = 1; } else if (m_eblg.getDomain().contains(ivPlus)) { dirs[idir] = 1; } else { dirs[idir] = -1; } } } bool orderOne = true; if (m_orderEB == 0 || a_lowOrder) { orderOne = false; } else { IntVect loVect = dirs; loVect.min(IntVect::Zero); IntVect hiVect = dirs; hiVect.max(IntVect::Zero); Box fluxBox(loVect,hiVect); IntVectSet fluxIVS(fluxBox); IVSIterator ivsit(fluxIVS); for (ivsit.begin(); ivsit.ok(); ++ivsit) { bool curOkay; IntVect ivDelta = ivsit(); IntVect iv1 = ivDelta; iv1 += origin; VolIndex VoF1; curOkay = EBArith::isVoFHere(VoF1,a_allMonotoneVoFs,iv1); IntVect iv2 = iv1; iv2[a_dir] += sign(a_side); VolIndex VoF2; curOkay = curOkay && EBArith::isVoFHere(VoF2,a_allMonotoneVoFs,iv2); orderOne = orderOne && curOkay; if (curOkay) { VoFStencil curPair; curPair.add(VoF1,-m_invDx2[a_dir]); curPair.add(VoF2, m_invDx2[a_dir]); for (int idir = 0; idir < SpaceDim; idir++) { if (idir != a_dir) { if (ivDelta[idir] == 0) { curPair *= 1 - abs(faceCentroid[idir]); } else { curPair *= abs(faceCentroid[idir]); } } } a_stencil += curPair; } } } if (!orderOne) { VolIndex VoF1 = a_VoF; VolIndex VoF2 = a_face.getVoF(a_side); if (a_ebisbox.getRegion().contains(VoF2.gridIndex())) { a_stencil.clear(); a_stencil.add(VoF1,-m_invDx2[a_dir]); a_stencil.add(VoF2, m_invDx2[a_dir]); } } if (!a_lowOrder) { a_stencil *= a_ebisbox.areaFrac(a_face); } }
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; } } } }
int checkEBISBox(const Box& a_gridCoar, const EBISBox& a_ebisBoxCoar, const EBISBox& a_ebisBoxFine) { IntVectSet ivs = a_ebisBoxCoar.getIrregIVS(a_gridCoar); Real dxCoar = 2; Real dxFine = 1; #if CH_SPACEDIM==2 Real areaFineCell = dxFine; Real areaCoarCell = dxCoar; Real voluFineCell = dxFine*dxFine; Real voluCoarCell = dxCoar*dxCoar; #elif CH_SPACEDIM==3 Real areaFineCell = dxFine*dxFine; Real areaCoarCell = dxCoar*dxCoar; Real voluFineCell = dxFine*dxFine*dxFine; Real voluCoarCell = dxCoar*dxCoar*dxCoar; #else MayDay::Error(); #endif int retval = 0; for (VoFIterator vofit(ivs, a_ebisBoxCoar.getEBGraph()); vofit.ok(); ++vofit) { const VolIndex& vofCoar = vofit(); Vector<VolIndex> vofsFine = a_ebisBoxCoar.refine(vofCoar); //check the easy bits Real volumCoar = a_ebisBoxCoar.volFrac( vofCoar); RealVect areaCritCoar = a_ebisBoxCoar.bndryArea(vofCoar)* a_ebisBoxCoar.normal(vofCoar); Real volumFine = 0; RealVect areaCritFine = RealVect::Zero; for (int ivof = 0; ivof < vofsFine.size(); ivof++) { volumFine += a_ebisBoxFine.volFrac( vofsFine[ivof]); areaCritFine += a_ebisBoxFine.bndryArea(vofsFine[ivof])* a_ebisBoxFine.normal(vofsFine[ivof]); } volumFine *= voluFineCell; areaCritFine *= areaFineCell; volumCoar *= voluCoarCell; areaCritCoar *= areaCoarCell; Real tolerance = 1.0e-10; if (Abs(volumFine -volumCoar) > tolerance*volumCoar) { pout() << "volume problem in coar cell " << vofCoar.gridIndex() << endl; retval = -1; } // Real maxCc = 0.0; // Real maxDev = 0.0; for (int idir=0; idir<SpaceDim; idir++) { if (Abs(areaCritFine[idir]-areaCritCoar[idir]) > tolerance*Abs(areaCritCoar[idir])) { pout() << "bndry area problem in coar cell " << vofCoar.gridIndex() << endl; retval = -2; } } //centroids are a bit uglier to test // RealVect bndryCentroidCoar = a_ebisBoxCoar.bndryCentroid( vofCoar); // RealVect bndryCentroidFine = RealVect::Zero; //the areas are somewhat more painful to test // for (int idir = 0; idir < SpaceDim; idir++) // { // // } } return retval; }
Real EBGradDivFilter:: getDomainDivergence(const EBCellFAB& a_gradVel, const EBCellFAB& a_vel, const EBFluxFAB& a_fluxVel, const Box& a_grid, const EBISBox& a_ebisBox, const int& a_faceDir, const FaceIndex& a_face, const Side::LoHiSide& a_side) { CH_TIME("EBGradDivFilter::getDomainDivergence"); Real divVel; CH_assert(a_fluxVel.nComp() == 1); Real velB = a_fluxVel[a_faceDir](a_face, 0); //compute normal derivative. //need second-order derivative at the boundary so //given u_b, u_i, u_i+1, //ux_b = (9u_i - u_i+1 - 8u_b)/(6 dx) VolIndex vofNear, vofStart; Real valNear=0; Real valStart =0; bool hasVoFNear; vofStart = a_face.getVoF(flip(a_side)); valStart = a_vel(vofStart, a_faceDir); int iflipsign = sign(flip(a_side)); Real rsign = Real(iflipsign); Vector<FaceIndex> facesNear = a_ebisBox.getFaces(vofStart, a_faceDir, flip(a_side)); hasVoFNear = (facesNear.size() == 1); if (hasVoFNear) { vofNear = facesNear[0].getVoF(flip(a_side)); valNear = a_vel(vofNear, a_faceDir); } Real hsign = rsign*m_dxFine[a_faceDir]; if (hasVoFNear) { divVel = (2.25*(valStart-velB) - 0.25*(valNear-velB))/(0.75*hsign); } else { //if there is no farther away value, drop order of derivative divVel = (valStart - velB)/(0.5*hsign); } //now add in tangential derivatives of tangential velocities //using extrapolated gradients for (int tanDir = 0; tanDir< SpaceDim; tanDir++) { if (tanDir != a_faceDir) { Real gradVel = 0.0; int gradcomp = getGradComp(tanDir, tanDir); if (hasVoFNear) { Real gradNear = a_gradVel(vofNear, gradcomp); Real gradStart = a_gradVel(vofStart, gradcomp); gradVel = 1.5*gradStart - 0.5*gradNear; } else { Real gradStart = a_gradVel(vofStart, gradcomp); gradVel = gradStart; } divVel += gradVel; } } return divVel; }
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; } } } }