void EBMGAverage::averageFAB(EBCellFAB& a_coar, const Box& a_boxCoar, const EBCellFAB& a_refCoar, const DataIndex& a_datInd, const Interval& a_variables) const { CH_TIMERS("EBMGAverage::average"); CH_TIMER("regular_average", t1); CH_TIMER("irregular_average", t2); CH_assert(isDefined()); const Box& coarBox = a_boxCoar; //do all cells as if they were regular Box refBox(IntVect::Zero, IntVect::Zero); refBox.refine(m_refRat); int numFinePerCoar = refBox.numPts(); BaseFab<Real>& coarRegFAB = a_coar.getSingleValuedFAB(); const BaseFab<Real>& refCoarRegFAB = a_refCoar.getSingleValuedFAB(); //set to zero because the fortran is a bit simpleminded //and does stuff additively a_coar.setVal(0.); CH_START(t1); for (int comp = a_variables.begin(); comp <= a_variables.end(); comp++) { FORT_REGAVERAGE(CHF_FRA1(coarRegFAB,comp), CHF_CONST_FRA1(refCoarRegFAB,comp), CHF_BOX(coarBox), CHF_BOX(refBox), CHF_CONST_INT(numFinePerCoar), CHF_CONST_INT(m_refRat)); } CH_STOP(t1); //this is really volume-weighted averaging even though it does //not look that way. //so (in the traditional sense) we want to preserve //rhoc * volc = sum(rhof * volf) //this translates to //volfrac_C * rhoC = (1/numFinePerCoar)(sum(volFrac_F * rhoF)) //but the data input to this routine is all kappa weigthed so //the volumefractions have already been multiplied //which means // rhoC = (1/numFinePerCoar)(sum(rhoF)) //which is what this does CH_START(t2); for (int comp = a_variables.begin(); comp <= a_variables.end(); comp++) { m_averageEBStencil[a_datInd]->apply(a_coar, a_refCoar, false, comp); } CH_STOP(t2); }
void EBMGInterp::pwcInterpFAB(EBCellFAB& a_refCoar, const Box& a_coarBox, const EBCellFAB& a_coar, const DataIndex& a_datInd, const Interval& a_variables) const { CH_TIMERS("EBMGInterp::interp"); CH_TIMER("regular_interp", t1); CH_TIMER("irregular_interp", t2); CH_assert(isDefined()); const Box& coarBox = a_coarBox; for (int ivar = a_variables.begin(); ivar <= a_variables.end(); ivar++) { m_interpEBStencil[a_datInd]->cache(a_refCoar, ivar); //do all cells as if they were regular Box refBox(IntVect::Zero, IntVect::Zero); refBox.refine(m_refRat); const BaseFab<Real>& coarRegFAB = a_coar.getSingleValuedFAB(); BaseFab<Real>& refCoarRegFAB = a_refCoar.getSingleValuedFAB(); CH_START(t1); FORT_REGPROLONG(CHF_FRA1(refCoarRegFAB,ivar), CHF_CONST_FRA1(coarRegFAB,ivar), CHF_BOX(coarBox), CHF_BOX(refBox), CHF_CONST_INT(m_refRat)); CH_STOP(t1); m_interpEBStencil[a_datInd]->uncache(a_refCoar, ivar); CH_START(t2); m_interpEBStencil[a_datInd]->apply(a_refCoar, a_coar, true, ivar); CH_STOP(t2); } }
void EBStenVarCoef:: cache(const EBCellFAB& a_phi, int a_ivar) { CH_assert(a_phi.getSingleValuedFAB().box() == m_grownBox); const Real* singleValuedPtrPhi = a_phi.getSingleValuedFAB().dataPtr(a_ivar); const Real* multiValuedPtrPhi = a_phi.getMultiValuedFAB().dataPtr(a_ivar); for (int isrc = 0; isrc < m_sourTerms.size(); isrc++) { //debugging hook //const VolIndex& srcVoF = m_srcVoFs[isrc]; if (m_sourTerms[isrc].multiValued) { m_cache[isrc] = *(multiValuedPtrPhi + m_sourTerms[isrc].offset); } else { m_cache[isrc] = *(singleValuedPtrPhi + m_sourTerms[isrc].offset); } } }
void EBStenVarCoef:: uncache(EBCellFAB& a_phi, int a_ivar) const { CH_assert(a_phi.getSingleValuedFAB().box() == m_grownBox); Real* singleValuedPtrPhi = a_phi.getSingleValuedFAB().dataPtr(a_ivar); Real* multiValuedPtrPhi = a_phi.getMultiValuedFAB().dataPtr(a_ivar); Real* phiPtr = NULL; for (int isrc = 0; isrc < m_sourTerms.size(); isrc++) { if (m_sourTerms[isrc].multiValued) { phiPtr = multiValuedPtrPhi + m_sourTerms[isrc].offset; } else { phiPtr = singleValuedPtrPhi + m_sourTerms[isrc].offset; } *phiPtr = m_cache[isrc]; } }
void EBStenVarCoef:: apply(EBCellFAB& a_lofphi, const EBCellFAB& a_phi, const EBCellFAB& a_alphaWeight, const Real& a_alpha, const EBCellFAB& a_betaWeight, const Real& a_beta) { CH_TIME("EBStenVarCoef::apply"); CH_assert(a_lofphi.getSingleValuedFAB().box() == m_grownBox); CH_assert(a_phi.getSingleValuedFAB().box() == m_grownBox); CH_assert(a_alphaWeight.getSingleValuedFAB().box() == m_grownBox); CH_assert(a_betaWeight.getSingleValuedFAB().box() == m_grownBox); const Real* singleValuedPtrPhi = a_phi.getSingleValuedFAB().dataPtr(0); const Real* multiValuedPtrPhi = a_phi. getMultiValuedFAB().dataPtr(0); const Real* singleValuedPtrAlp = a_alphaWeight.getSingleValuedFAB().dataPtr(0); const Real* multiValuedPtrAlp = a_alphaWeight. getMultiValuedFAB().dataPtr(0); const Real* singleValuedPtrBet = a_betaWeight.getSingleValuedFAB().dataPtr(0); const Real* multiValuedPtrBet = a_betaWeight. getMultiValuedFAB().dataPtr(0); Real* multiValuedPtrLph = a_lofphi. getMultiValuedFAB().dataPtr(m_destVar); Real* singleValuedPtrLph = a_lofphi.getSingleValuedFAB().dataPtr(m_destVar); //plo is different from phi because of destvar //phi is for stencil evaluation. plo is for the local value at this variable const Real* multiValuedPtrPlo = a_phi. getMultiValuedFAB().dataPtr(m_destVar); const Real* singleValuedPtrPlo = a_phi.getSingleValuedFAB().dataPtr(m_destVar); for (int isrc = 0; isrc < m_stencil.size(); isrc++) { //debugging hook //const VolIndex& srcVoF = m_srcVoFs[isrc]; Real* lphPtr = NULL; const Real* phiPtr = NULL; const Real* alpPtr = NULL; const Real* betPtr = NULL; if (m_sourTerms[isrc].multiValued) { lphPtr = multiValuedPtrLph + m_sourTerms[isrc].offset; phiPtr = multiValuedPtrPlo + m_sourTerms[isrc].offset; alpPtr = multiValuedPtrAlp + m_sourTerms[isrc].offset; betPtr = multiValuedPtrBet + m_sourTerms[isrc].offset; } else { lphPtr = singleValuedPtrLph + m_sourTerms[isrc].offset; phiPtr = singleValuedPtrPlo + m_sourTerms[isrc].offset; alpPtr = singleValuedPtrAlp + m_sourTerms[isrc].offset; betPtr = singleValuedPtrBet + m_sourTerms[isrc].offset; } Real& lph = *lphPtr; const Real& phi = *phiPtr; const Real& alphaWeight = *alpPtr; const Real& betaWeight = *betPtr; lph = 0.; const varcsten_t& stenpt = m_stencil[isrc]; //single-valued for (int isingle = 0; isingle < stenpt.single.size(); isingle++) { const int & offset = stenpt.single[isingle].offset; const Real& phiVal = *(singleValuedPtrPhi + offset); const Real& weight = stenpt.single[isingle].weight; lph += phiVal*weight; } //multi-valued for (int imulti = 0; imulti < stenpt.multi.size(); imulti++) { const int & offset = stenpt.multi[imulti].offset; const Real& phiVal = *(multiValuedPtrPhi + offset); const Real& weight = stenpt.multi[imulti].weight; lph += phiVal*weight; } //at this point lph holds divF. add in identity terms //and multiply by factors lph = a_alpha*alphaWeight*phi + a_beta*betaWeight*lph; } }
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 EBCoarsen::coarsenFAB(EBCellFAB& a_coar, const EBCellFAB& a_fine, const DataIndex& a_datInd, const Interval& a_variables) { CH_assert(isDefined()); //do all cells as if they were regular BaseFab<Real>& coarRegFAB = a_coar.getSingleValuedFAB(); const BaseFab<Real>& fineRegFAB = a_fine.getSingleValuedFAB(); //this is how much we need to grow a coarse box to get a fine box that // only has the fine iv's that are neighbors of the coarse iv const int fac = 1 - m_refRat/2;//NOTE: fac = 0 for refRat==2... Box refbox(IntVect::Zero, (m_refRat-1)*IntVect::Unit); refbox.grow(fac); Box coarBox = m_coarsenedFineGrids.get(a_datInd); Box fineBox = refine(coarBox, m_refRat); CH_assert(coarRegFAB.box().contains(coarBox)); CH_assert(fineRegFAB.box().contains(fineBox)); for (int ivar = a_variables.begin(); ivar <= a_variables.end(); ivar++) { BaseFab<Real> laplFine(fineBox, 1); laplFine.setVal(0.); for (int idir = 0; idir < SpaceDim; idir++) { Box loBox, hiBox, centerBox; int hasLo, hasHi; EBArith::loHiCenter(loBox, hasLo, hiBox, hasHi, centerBox, m_domainFine, fineBox, idir, &((*m_cfivsPtr)[a_datInd])); FORT_H2LAPL1DADDITIVE(CHF_FRA1(laplFine, 0), CHF_FRA1(fineRegFAB, ivar), CHF_CONST_INT(idir), CHF_BOX(loBox), CHF_CONST_INT(hasLo), CHF_BOX(hiBox), CHF_CONST_INT(hasHi), CHF_BOX(centerBox)); } FORT_EBCOARSEN(CHF_FRA1(coarRegFAB,ivar), CHF_CONST_FRA1(fineRegFAB,ivar), CHF_CONST_FRA1(laplFine, 0), CHF_BOX(coarBox), CHF_CONST_INT(m_refRat), CHF_BOX(refbox)); } //overwrite irregular vofs and coarse vofs next to the cfivs if refRat<4, // for these vofs we coarsen based on // taylor expansions from fine vofs to the coarse cell center coarsenIrreg(a_coar,a_fine,a_datInd,a_variables); }
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 EBMGInterp::pwlInterpFAB(EBCellFAB& a_refCoar, const Box& a_coarBox, const EBCellFAB& a_coar, const DataIndex& a_datInd, const Interval& a_variables) const { CH_TIMERS("EBMGInterp::pwlinterpfab"); CH_TIMER("regular_interp", t1); CH_TIMER("irregular_interp", t2); CH_assert(isDefined()); //first interpolate piecewise constant. pwcInterpFAB(a_refCoar, a_coarBox, a_coar, a_datInd, a_variables); //then add in slope*distance. const Box& coarBox = a_coarBox; for (int ivar = a_variables.begin(); ivar <= a_variables.end(); ivar++) { //save stuff at irreg cells because fortran result will be garbage //and this is an incremental process m_linearEBStencil[a_datInd]->cache(a_refCoar, ivar); //do all cells as if they were regular Box refBox(IntVect::Zero, IntVect::Zero); refBox.refine(m_refRat); const BaseFab<Real>& coarRegFAB = a_coar.getSingleValuedFAB(); BaseFab<Real>& refCoarRegFAB = a_refCoar.getSingleValuedFAB(); CH_START(t1); Real dxf = 1.0/m_coarDomain.size(0); Real dxc = 2.0*dxf; //do every cell as regular for (int idir = 0; idir < SpaceDim; idir++) { FORT_PROLONGADDSLOPE(CHF_FRA1(refCoarRegFAB,ivar), CHF_CONST_FRA1(coarRegFAB,ivar), CHF_BOX(coarBox), CHF_BOX(refBox), CHF_INT(idir), CHF_REAL(dxf), CHF_REAL(dxc), CHF_CONST_INT(m_refRat)); } CH_STOP(t1); //replace garbage fortran put in with original values (at irregular cells) m_linearEBStencil[a_datInd]->uncache(a_refCoar, ivar); CH_START(t2); //do what fortran should have done at irregular cells. m_linearEBStencil[a_datInd]->apply(a_refCoar, a_coar, true, ivar); CH_STOP(t2); } }
void EBCoarseAverage::averageFAB(EBCellFAB& a_coar, const EBCellFAB& a_fine, const DataIndex& a_datInd, const Interval& a_variables) const { CH_TIME("EBCoarseAverage::averageFAB(EBCellFAB)"); CH_assert(isDefined()); //do all cells as if they were regular BaseFab<Real>& coarRegFAB = a_coar.getSingleValuedFAB(); const BaseFab<Real>& fineRegFAB = a_fine.getSingleValuedFAB(); Box refbox(IntVect::Zero, (m_refRat-1)*IntVect::Unit); const Box& coarBox = m_eblgCoFi.getDBL().get(a_datInd); #ifndef NDEBUG Box fineBox = refine(coarBox, m_refRat); CH_assert(coarRegFAB.box().contains(coarBox)); CH_assert(fineRegFAB.box().contains(fineBox)); #endif for (int ivar = a_variables.begin(); ivar <= a_variables.end(); ivar++) { FORT_EBAVERAGE(CHF_FRA1(coarRegFAB,ivar), CHF_CONST_FRA1(fineRegFAB,ivar), CHF_BOX(coarBox), CHF_CONST_INT(m_refRat), CHF_BOX(refbox)); } //overwrite irregular cells //recall that datInd is from the fine layout. const EBISBox& ebisBoxCoar = m_eblgCoFi.getEBISL()[a_datInd]; const EBISBox& ebisBoxFine = m_eblgFine.getEBISL()[a_datInd]; IntVectSet coarIrregIVS = ebisBoxCoar.getIrregIVS(coarBox); //fine cell volume is normalized to one. //compute coarse volume Real dxCoar = Real(m_refRat); Real cellVolCoar = 1.0; for (int idir = 0; idir < SpaceDim; idir++) cellVolCoar *= dxCoar; for (VoFIterator vofitCoar(coarIrregIVS, ebisBoxCoar.getEBGraph()); vofitCoar.ok(); ++vofitCoar) { const VolIndex& coarVoF = vofitCoar(); Vector<VolIndex> fineVoFs = m_eblgCoFi.getEBISL().refine(coarVoF, m_refRat, a_datInd); Real volCoar = cellVolCoar*ebisBoxCoar.volFrac(coarVoF); for (int ivar = a_variables.begin(); ivar <= a_variables.end(); ivar++) { Real dataVal = 0.0; if (volCoar > 0.) { for (int ifine = 0; ifine < fineVoFs.size(); ifine++) { const VolIndex& fineVoF = fineVoFs[ifine]; //fine cell volume is normalized to one... Real volFine = ebisBoxFine.volFrac(fineVoF); Real fineVal = a_fine(fineVoF, ivar); if (volFine > 0.) { dataVal += fineVal*volFine; } } dataVal /= volCoar; } else { //if there is no real volume, just take the ave //of fine values for (int ifine = 0; ifine < fineVoFs.size(); ifine++) { const VolIndex& fineVoF = fineVoFs[ifine]; Real fineVal = a_fine(fineVoF, ivar); dataVal += fineVal; } if (fineVoFs.size() > 0) { dataVal /= Real(fineVoFs.size()); } } a_coar(coarVoF, ivar) = dataVal; } } }
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 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 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; } } } }