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 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; } }
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; } }