void PoisselleTube:: initializeVelocity(LevelData<EBCellFAB>& a_velocity, const DisjointBoxLayout& a_grids, const EBISLayout& a_ebisl, const ProblemDomain& a_domain, const RealVect& a_origin, const Real& a_time, const RealVect& a_dx) const { for (DataIterator dit = a_grids.dataIterator(); dit.ok(); ++dit) { IntVectSet ivsBox(a_grids.get(dit())); for (VoFIterator vofit(ivsBox, a_ebisl[dit()].getEBGraph()); vofit.ok(); ++vofit) { RealVect xval = EBArith::getVofLocation(vofit() , a_dx, RealVect::Zero); for (int idir = 0; idir < SpaceDim; idir++) { //bogus values for normal and time because they do not matter Real velComp = m_bcval[idir].value(xval, RealVect::Zero, a_time, idir); a_velocity[dit()](vofit(), idir) = velComp; } } } }
void NoFlowVortex:: initializeVelocity(LevelData<EBCellFAB>& a_velocity, const DisjointBoxLayout& a_grids, const EBISLayout& a_ebisl, const ProblemDomain& a_domain, const RealVect& a_origin, const Real& a_time, const RealVect& a_dx) const { Real pi = 4.0*atan(1.0); for (DataIterator dit = a_grids.dataIterator(); dit.ok(); ++dit) { IntVectSet ivsBox(a_grids.get(dit())); for (VoFIterator vofit(ivsBox, a_ebisl[dit()].getEBGraph()); vofit.ok(); ++vofit) { RealVect xval, velpt; getXVal(xval, a_origin,vofit(), a_dx); getVelPt(velpt, xval, pi); for (int idir = 0; idir < SpaceDim; idir++) { a_velocity[dit()](vofit(), idir) = velpt[idir]; } } } }
void setToExactFluxLD(LevelData<EBFluxFAB>& a_flux, const EBISLayout& a_ebisl, const DisjointBoxLayout& a_dbl, const Real& a_dx) { for (DataIterator dit= a_dbl.dataIterator(); dit.ok(); ++dit) { setToExactFlux(a_flux[dit()], a_ebisl[dit()], a_dbl.get(dit()), a_dx); } }
void setToExactDivFLD(LevelData<EBCellFAB>& a_soln, const EBISLayout& a_ebisl, const DisjointBoxLayout& a_dbl, const Real& a_dx) { for (DataIterator dit= a_dbl.dataIterator(); dit.ok(); ++dit) { setToExactDivF(a_soln[dit()], a_ebisl[dit()], a_dbl.get(dit()), a_dx); } }
// Set up initial conditions void AdvectTestIBC::initialize(LevelData<FArrayBox>& a_U) { DisjointBoxLayout grids = a_U.disjointBoxLayout(); for (DataIterator dit = grids.dataIterator(); dit.ok(); ++dit) { const Box& grid = grids.get(dit()); FORT_ADVECTINITF(CHF_FRA1(a_U[dit()],0), CHF_CONST_REALVECT(m_center), CHF_CONST_REAL(m_size), CHF_CONST_REAL(m_dx), CHF_BOX(grid)); } }
int makeLayout(DisjointBoxLayout& a_dbl, const Box& a_domain) { ParmParse pp; int eekflag= 0; int ipieces; ipieces = Max(ipieces, 1); int maxsize; pp.get("maxboxsize",maxsize); Vector<Box> vbox(1, a_domain); domainSplit(a_domain, vbox, maxsize); if (eekflag != 0) { pout() << "problem in domainsplit" << endl; return eekflag; } Vector<int> procAssign; eekflag = LoadBalance(procAssign,vbox); if (eekflag != 0) { pout() << "problem in loadbalance" << endl; return eekflag; } a_dbl.define(vbox, procAssign); return eekflag; }
void kappaDivergenceLD(LevelData<EBCellFAB>& a_divF, const LevelData<EBFluxFAB>& a_flux, const EBISLayout& a_ebisl, const DisjointBoxLayout& a_dbl, const Real& a_dx) { for (DataIterator dit= a_dbl.dataIterator(); dit.ok(); ++dit) { kappaDivergence(a_divF[dit()], a_flux[dit()], a_ebisl[dit()], a_dbl.get(dit()), a_dx); } }
int makeLayout(DisjointBoxLayout& a_dbl, const Box& a_domainFine) { //set up mesh refine object ParmParse pp; int eekflag= 0; int maxsize; pp.get("maxboxsize",maxsize); int bufferSize = 1; int blockFactor = 2; Real fillrat = 0.75; Box domainCoar = coarsen(a_domainFine, 2); Vector<int> refRat(2,2); BRMeshRefine meshRefObj(domainCoar, refRat, fillrat, blockFactor, bufferSize, maxsize); Vector<Vector<Box> > oldMeshes(2); oldMeshes[0] = Vector<Box>(1, domainCoar); oldMeshes[1] = Vector<Box>(1, a_domainFine); //set up coarse tags int nc = domainCoar.size(0); int nmi = nc/2;//16 int nqu = nc/4;//8 int ntf = (nc*3)/4; //24 int nte = (nc*3)/8; //12 int nfe = (nc*5)/8; //20 #if (CH_SPACEDIM ==2) Box boxf1(IntVect(0, nqu), IntVect(nmi-1,ntf-1)); Box boxf2(IntVect(nmi,nte), IntVect(ntf-1,nfe-1)); Box boxf3(IntVect(nqu,0 ), IntVect(nfe-1,nqu-1)); Box boxf4(IntVect(nfe,nqu), IntVect(nc -1,nte-1)); #else Box boxf1(IntVect(0, nqu,nqu), IntVect(nmi-1,ntf-1,ntf-1)); Box boxf2(IntVect(nmi,nte,nte), IntVect(ntf-1,nfe-1,nfe-1)); Box boxf3(IntVect(nqu,0,0 ), IntVect(nfe-1,nqu-1,nqu-1)); Box boxf4(IntVect(nfe,nqu,nqu), IntVect(nc -1,nte-1,nte-1)); #endif IntVectSet tags; tags |= boxf1; tags |= boxf2; tags |= boxf3; tags |= boxf4; int baseLevel = 0; int topLevel = 0; Vector<Vector<Box> > newMeshes; meshRefObj.regrid(newMeshes, tags, baseLevel, topLevel, oldMeshes); const Vector<Box>& vbox = newMeshes[1]; Vector<int> procAssign; eekflag = LoadBalance(procAssign,vbox); if (eekflag != 0) return eekflag; a_dbl.define(vbox, procAssign); return eekflag; }
int EBAMRTestCommon:: checkForZero(const LevelData<EBCellFAB>& a_errorVelo, const DisjointBoxLayout& a_gridsFine, const EBISLayout& a_ebislFine, const Box& a_domainFine, string a_funcname) { int eekflag = 0; Real eps = 1.0e-8; #ifdef CH_USE_FLOAT eps = 1.0e-3; #endif for (DataIterator dit = a_gridsFine.dataIterator(); dit.ok(); ++dit) { Box grownBox = a_gridsFine.get(dit()); grownBox.grow(1); grownBox &= a_domainFine; IntVectSet ivsBox(grownBox); for (VoFIterator vofit(ivsBox, a_ebislFine[dit()].getEBGraph()); vofit.ok(); ++vofit) { const VolIndex& vof = vofit(); int ihere = 0; if (vof.gridIndex() == EBDebugPoint::s_ivd) { ihere = 1; } for (int ivar = 0; ivar < a_errorVelo.nComp(); ivar++) { Real errorIn = a_errorVelo[dit()](vof, ivar); if (Abs(errorIn) > eps) { pout() << "check for zero error too big for test " << a_funcname << endl; pout() << "ivar = " << ivar << endl; pout() << "vof = " << vof.gridIndex() << " error = " << errorIn << endl; return -1; } } } } return eekflag; }
void CFStencil::buildPeriodicVector(Vector<Box>& a_periodicVector, const ProblemDomain& a_fineDomain, const DisjointBoxLayout& a_fineBoxes) { Box periodicTestBox(a_fineDomain.domainBox()); if (a_fineDomain.isPeriodic()) { for (int idir=0; idir<SpaceDim; idir++) { if (a_fineDomain.isPeriodic(idir)) { periodicTestBox.grow(idir,-1); } } } a_periodicVector.clear(); a_periodicVector.reserve(a_fineBoxes.size()); LayoutIterator lit = a_fineBoxes.layoutIterator(); for (lit.reset(); lit.ok(); ++lit) { const Box& box = a_fineBoxes[lit()]; a_periodicVector.push_back(box); // if periodic, also need to add periodic images // only do this IF we're periodic and box // adjacent to the domain box boundary somewhere if (a_fineDomain.isPeriodic() && !periodicTestBox.contains(box)) { ShiftIterator shiftIt = a_fineDomain.shiftIterator(); IntVect shiftMult(a_fineDomain.domainBox().size()); Box shiftedBox(box); for (shiftIt.begin(); shiftIt.ok(); ++shiftIt) { IntVect shiftVect = shiftMult*shiftIt(); shiftedBox.shift(shiftVect); a_periodicVector.push_back(shiftedBox); shiftedBox.shift(-shiftVect); } // end loop over periodic shift directions } // end if periodic } a_periodicVector.sort(); }
int makeLayoutPart(DisjointBoxLayout& a_dbl, const Box& a_domainCoarsest) { // Vector<int> vecRefRat(2, 2); ParmParse pp; int eekflag= 0; int blockFactor, bufferSize, maxSize; Real fillRat; pp.get("block_factor", blockFactor); pp.get("buffer_size", bufferSize); pp.get("maxboxsize", maxSize); pp.get("fill_ratio", fillRat); int nlevels = 2; Vector<int> vecRefRat(nlevels); pp.getarr("ref_ratio", vecRefRat,0,nlevels); BRMeshRefine mesher(a_domainCoarsest, vecRefRat, fillRat, blockFactor, bufferSize, maxSize); int topLevel = 0; int baseLevel = 0; //tags at base level IntVectSet tags; eekflag = makeTags(tags, a_domainCoarsest); if (eekflag < 0) return eekflag; Vector<Vector<Box> > oldMeshes(nlevels); oldMeshes[0] = Vector<Box>(1, a_domainCoarsest); Box finerDomain = a_domainCoarsest; for (int ilev = 1; ilev < nlevels; ilev++) { finerDomain.refine(vecRefRat[ilev]); oldMeshes[ilev] = Vector<Box>(1, finerDomain); } Vector<Vector<Box> > newMeshes; mesher.regrid(newMeshes, tags, baseLevel, topLevel, oldMeshes); Vector<int> procAssign; eekflag = LoadBalance(procAssign, newMeshes[1]); if (eekflag != 0) return eekflag; a_dbl.define(newMeshes[1], procAssign); int iverbose; pp.get("verbose", iverbose); if (iverbose == 1) { pout() << "the grids coarser domain= " << a_domainCoarsest << " = " << a_dbl << endl; } return eekflag; }
void getError(LevelData<EBCellFAB>& a_error, const EBISLayout& a_ebisl, const DisjointBoxLayout& a_dbl, const Real& a_dx) { EBCellFactory ebcellfact(a_ebisl); EBFluxFactory ebfluxfact(a_ebisl); a_error.define(a_dbl, 1, IntVect::Zero, ebcellfact); LevelData<EBCellFAB> divFCalc(a_dbl, 1, IntVect::Zero, ebcellfact); LevelData<EBCellFAB> divFExac(a_dbl, 1, IntVect::Zero, ebcellfact); LevelData<EBFluxFAB> faceFlux(a_dbl, 1, IntVect::Zero, ebfluxfact); for (DataIterator dit = a_dbl.dataIterator(); dit.ok(); ++dit) { a_error[dit()].setVal(0.); divFCalc[dit()].setVal(0.); divFExac[dit()].setVal(0.); } setToExactDivFLD(divFExac, a_ebisl, a_dbl, a_dx); setToExactFluxLD(faceFlux, a_ebisl, a_dbl, a_dx); Interval interv(0, 0); faceFlux.exchange(interv); kappaDivergenceLD(divFCalc, faceFlux, a_ebisl, a_dbl, a_dx); for (DataIterator dit = a_dbl.dataIterator(); dit.ok(); ++dit) { EBCellFAB& errorFAB = a_error[dit()]; EBCellFAB& exactFAB = divFExac[dit()]; EBCellFAB& calcuFAB = divFCalc[dit()]; errorFAB += calcuFAB; errorFAB -= exactFAB; } }
void NoFlowVortex:: initializeScalar ( LevelData<EBCellFAB>& a_scalar, const DisjointBoxLayout& a_grids, const EBISLayout& a_ebisl, const ProblemDomain& a_domain, const RealVect& a_origin, const Real& a_time, const RealVect& a_dx) const { for (DataIterator dit = a_grids.dataIterator(); dit.ok(); ++dit) { IntVectSet ivsBox(a_grids.get(dit())); for (VoFIterator vofit(ivsBox, a_ebisl[dit()].getEBGraph()); vofit.ok(); ++vofit) { RealVect xval; Real scal; getXVal(xval, a_origin,vofit(), a_dx); getScalarPt(scal, xval); a_scalar[dit()](vofit(), 0) = scal; } } }
void NoFlowVortex:: initializePressure(LevelData<EBCellFAB>& a_pressure, const DisjointBoxLayout& a_grids, const EBISLayout& a_ebisl, const ProblemDomain& a_domain, const RealVect& a_origin, const Real& a_time, const RealVect& a_dx) const { for (DataIterator dit = a_grids.dataIterator(); dit.ok(); ++dit) { IntVectSet ivsBox(a_grids.get(dit())); for (VoFIterator vofit(ivsBox, a_ebisl[dit()].getEBGraph()); vofit.ok(); ++vofit) { RealVect xval, pt; getXVal(xval, a_origin,vofit(), a_dx); for (int idir = 0; idir < SpaceDim; idir++) { a_pressure[dit()](vofit(), idir) = 1.e99; } } } }
int checkCoarseAssortment(const Box& a_domain) { int retval = 0; const EBIndexSpace* const ebisPtr = Chombo_EBIS::instance(); CH_assert(ebisPtr->isDefined()); Box fineDomain = a_domain; int numLevels = ebisPtr->numLevels(); for (int ilev = 1; ilev < numLevels; ilev++) { CH_assert(!fineDomain.isEmpty()); Vector<Box> vbox(1, fineDomain); Vector<int> proc(1, 0); DisjointBoxLayout fineDBL(vbox, proc); EBISLayout fineEBISL; int nghost = 4; ebisPtr->fillEBISLayout(fineEBISL, fineDBL, fineDomain, nghost); Box coarDomain = coarsen(fineDomain, 2); DisjointBoxLayout coarDBL; coarsen(coarDBL, fineDBL, 2); EBISLayout coarEBISL; ebisPtr->fillEBISLayout(coarEBISL, coarDBL, coarDomain, nghost); for (DataIterator dit = fineDBL.dataIterator(); dit.ok(); ++dit) { retval = checkEBISBox(coarDBL.get(dit()), coarEBISL[dit()], fineEBISL[dit()]); if (retval != 0) { pout() << "problem in coarsening " << fineDomain << " to " << coarDomain << endl; return retval; } } fineDomain.coarsen(2); } return retval; }
// --------------------------------------------------------- void NodeCoarseAverage::define(const DisjointBoxLayout& a_gridsFine, const DisjointBoxLayout& a_gridsCoarse, int a_numcomps, int a_refRatio, const ProblemDomain& a_domainFine) { m_refRatio = a_refRatio; m_numcomps = a_numcomps; m_domainCoarse = coarsen(a_domainFine, m_refRatio); // DisjointBoxLayout::coarsen() coarsen(m_coarsenedGrids, a_gridsFine, m_refRatio); m_coarsenedFine.define(m_coarsenedGrids, m_numcomps); IntVect extent = (a_refRatio/2) * IntVect::Unit; m_refbox = Box(-extent, extent); m_weights.define(m_refbox, 1); FORT_NODEAVERAGE_GETWEIGHTS(CHF_FRA(m_weights), CHF_CONST_INT(m_refRatio)); if (m_verbose) cout << "IBN NodeCoarseAverage on " << m_domainCoarse.domainBox().size() << ", from " << m_coarsenedGrids.size() << " coarsened grids to " << a_gridsCoarse.size() << " coarser-level grids on " << m_domainCoarse.domainBox().size() << endl; interiorBoundaryNodes(m_IVSV, a_gridsCoarse, m_coarsenedGrids, m_domainCoarse); if (m_verbose) cout << "IBN NodeCoarseAverage on " << m_domainCoarse.domainBox().size() << ", from " << m_coarsenedGrids.size() << " coarsened grids to selves on " << m_domainCoarse.domainBox().size() << endl; interiorBoundaryNodes(m_IVSVsame, m_coarsenedGrids, m_domainCoarse); // m_IVSVfull added by petermc, 21 Jul 2003 fullIntVectSets(m_IVSVfull, m_IVSVsame); m_sameGrids = false; is_defined = true; }
// ------------------------------------------------------------ // version of 27 March 2003 Real norm(const LevelData<NodeFArrayBox>& a_phi, const ProblemDomain& a_domain, const DisjointBoxLayout& a_finerGridsCoarsened, const LayoutData< Vector<Box> >& a_IVSVext, const LayoutData< Vector<Box> >& a_IVSVintFinerCoarsened, const int a_nRefFine, const Real a_dx, const Interval& a_comps, const int a_p, bool a_verbose) { // Idea: copy a_phi to temp, then zero out temp on: // - exterior nodes of grids at this level; // - projections of interior nodes of the finer grids. int ncomps = a_comps.size(); const DisjointBoxLayout& grids = a_phi.getBoxes(); LevelData<NodeFArrayBox> temp(grids, ncomps); // Copy a_phi to temp. Interval newcomps(0, ncomps-1); for (DataIterator dit(grids.dataIterator()); dit.ok(); ++dit) { const NodeFArrayBox& nfab = a_phi[dit()]; const Box& bx = grids.get(dit()); temp[dit()].copy(bx, newcomps, bx, nfab, a_comps); } // Zero out temp on exterior nodes. zeroBoundaryNodes(temp, a_IVSVext); // Define zeroCoarsened to be all zero on the coarsened finer grids. LevelData<NodeFArrayBox> zeroCoarsened(a_finerGridsCoarsened, ncomps, IntVect::Zero); for (DataIterator dit(a_finerGridsCoarsened.dataIterator()); dit.ok(); ++dit) zeroCoarsened[dit()].getFab().setVal(0.); // Set temp to zero on interior nodes of coarsened finer grids. copyInteriorNodes(temp, zeroCoarsened, a_IVSVintFinerCoarsened); Real normLevel = norm(temp, a_dx, a_p, newcomps, a_verbose); return normLevel; }
int makeLayout(DisjointBoxLayout& a_dbl, const Box& a_domainFine) { //set up mesh refine object ParmParse pp; int eekflag= 0; int maxsize; pp.get("maxboxsize",maxsize); int bufferSize = 2; int blockFactor = 8; Real fillrat = 0.7; Box domainCoar = coarsen(a_domainFine, 2); Vector<int> refRat(2,2); BRMeshRefine meshRefObj(domainCoar, refRat, fillrat, blockFactor, bufferSize, maxsize); Vector<Vector<Box> > oldMeshes(2); oldMeshes[0] = Vector<Box>(1, domainCoar); oldMeshes[1] = Vector<Box>(1, a_domainFine); //set up coarse tags int nc = domainCoar.size(0); Box halfBox = domainCoar; halfBox.growHi(0, -nc/2); IntVectSet tags(halfBox); int baseLevel = 0; int topLevel = 0; Vector<Vector<Box> > newMeshes; meshRefObj.regrid(newMeshes, tags, baseLevel, topLevel, oldMeshes); const Vector<Box>& vbox = newMeshes[1]; Vector<int> procAssign; eekflag = LoadBalance(procAssign,vbox); if (eekflag != 0) return eekflag; a_dbl.define(vbox, procAssign); return eekflag; }
int main(int argc ,char *argv[] ) { #ifdef CH_MPI MPI_Init(&argc, &argv); #endif int status = 0; // Make this test pass automatically if DIM > 3, to avoid FAIL message. if (SpaceDim <= 3) { parseTestOptions(argc, argv); // establish periodic domain -- first multiply periodic in all directions int baseDomainSize = 8; int numGhost = 2; IntVect ghostVect(numGhost*IntVect::Unit); Box baseDomBox(IntVect::Zero, (baseDomainSize-1)*IntVect::Unit); ProblemDomain baseDomain(baseDomBox); // set periodic in all directions for (int dir=0; dir<SpaceDim; dir++) { baseDomain.setPeriodic(dir, true); } { // QuadCFInterp test int nRef = 2; ProblemDomain fineDomain(baseDomain); fineDomain.refine(nRef); const Box domainBox = baseDomain.domainBox(); Vector<Box> crseBoxes(1, domainBox); Vector<int> crseProcAssign(1,0); DisjointBoxLayout crseGrids(crseBoxes, crseProcAssign, baseDomain); // note the lack of ghost cells on the base level LevelData<FArrayBox> crseData(crseGrids, 1, IntVect::Zero); Real dxCrse = 1.0/(baseDomainSize); Real dxFine = dxCrse/nRef; initData(crseData, dxCrse); #if (CH_SPACEDIM == 1) Vector<Box> fineBoxes(2); Vector<int> fineProcAssign(2); fineBoxes[0] = Box(IntVect::Zero, 5*IntVect::Unit); fineBoxes[1] = Box(IntVect(D_DECL6(6,10,10,6,10,0)), IntVect(D_DECL6(11,15,15,11,15,15))); #else // try multiple boxes for fine level Vector<Box> fineBoxes(4); Vector<int> fineProcAssign(4); fineBoxes[0] = Box(IntVect::Zero, 9*IntVect::Unit); fineBoxes[1] = Box(IntVect(D_DECL6(6,10,10,6,10,0)), IntVect(D_DECL6(11,15,15,11,15,15))); // this box should fail the disjointness test //fineBoxes[1] = Box(IntVect(D_DECL(7,10,10)), 17*IntVect::Unit); fineBoxes[2] = Box(IntVect(D_DECL6(12,2,0,12,2,0)), IntVect(D_DECL6(15,7,7,15,7,7))); fineBoxes[3] = Box(IntVect(D_DECL6(12,12,0,12,12,0)), 15*IntVect::Unit); #endif int loadbalancestatus = LoadBalance(fineProcAssign, fineBoxes); CH_assert (loadbalancestatus == 0); DisjointBoxLayout fineGrids; fineGrids.define(fineBoxes, fineProcAssign, fineDomain); LevelData<FArrayBox> fineData(fineGrids, 1, ghostVect); // set these to a bogus value to start with DataIterator fineDit = fineData.dataIterator(); for (fineDit.begin(); fineDit.ok(); ++fineDit) { fineData[fineDit()].setVal(1.0e9); } FineInterp interpolator(fineGrids, 1, nRef, fineDomain); // turn on fine-data averaging even though it's unnecessary // since this is a test (so we'd like to know if it's broken) bool averageFineData = true; interpolator.interpToFine(fineData, crseData, averageFineData); // now fill in ghost cells QuadCFInterp filler(fineGrids, &crseGrids, dxFine, nRef, 1, fineDomain); filler.coarseFineInterp(fineData, crseData); } { // fineInterp near boundary test int numLev = 3; Vector<int> nRefVect(numLev); nRefVect[0] = 4; nRefVect[1] = 2; nRefVect[2] = -1; Vector<Real> dxVect(numLev); Vector<ProblemDomain> levelDomains(numLev); levelDomains[0] = Box(IntVect::Zero, 15*IntVect::Unit); dxVect[0] = 1.0/(levelDomains[0].domainBox().size(0)); for (int lev=1; lev<numLev; lev++) { levelDomains[lev] = levelDomains[lev-1]; levelDomains[lev].refine(nRefVect[lev-1]); dxVect[lev] = dxVect[lev-1]/nRefVect[lev-1]; } Vector<DisjointBoxLayout> levelGrids(numLev); Vector<LevelData<FArrayBox>* > levelData(numLev, NULL); const Box domainBox = levelDomains[0].domainBox(); Vector<Box> crseBoxes(1, domainBox); Vector<int> crseProcAssign(1,0); DisjointBoxLayout level0Grids(crseBoxes, crseProcAssign, levelDomains[0]); levelGrids[0] = level0Grids; // note the lack of ghost cells on the base level levelData[0] = new LevelData<FArrayBox>(level0Grids, 1, IntVect::Zero); initData(*levelData[0], dxVect[0]); Vector<Box> level1Boxes(1, levelDomains[1].domainBox()); int loadbalancestatus = LoadBalance(crseProcAssign, level1Boxes); CH_assert (loadbalancestatus == 0); IntVect newGhostVect(4*IntVect::Unit); DisjointBoxLayout fineGrids; fineGrids.define(level1Boxes, crseProcAssign, levelDomains[1]); levelGrids[1] = fineGrids; levelData[1] = new LevelData<FArrayBox>(fineGrids, 1, newGhostVect); Vector<Box> level2Boxes(1); //level2Boxes[0] = Box(20*IntVect::Unit, 119*IntVect::Unit); level2Boxes[0] = Box(100*IntVect::Unit, 127*IntVect::Unit); DisjointBoxLayout finestGrids(level2Boxes, crseProcAssign, levelDomains[2]); levelGrids[2] = finestGrids; levelData[2] = new LevelData<FArrayBox>(finestGrids, 1, newGhostVect); for (int lev=1; lev<numLev; lev++) { LevelData<FArrayBox>& fineData = *levelData[lev]; LevelData<FArrayBox>& crseData = *levelData[lev-1]; // set these to a bogus value to start with DataIterator fineDit = fineData.dataIterator(); for (fineDit.begin(); fineDit.ok(); ++fineDit) { fineData[fineDit()].setVal(1.0e9); } FineInterp interpolator(levelGrids[lev], 1, nRefVect[lev-1], levelDomains[lev]); // turn on fine-data averaging even though it's unnecessary // since this is a test (so we'd like to know if it's broken) bool averageFineData = true; interpolator.interpToFine(fineData, crseData, averageFineData); pout() << "grids at level = " << lev << endl; dumpDBL(&levelGrids[lev]); pout() << "grids at level = " << lev-1 << endl; dumpDBL(&levelGrids[lev-1]); // now fill in ghost cells QuadCFInterp filler(levelGrids[lev], &levelGrids[lev-1], dxVect[lev], nRefVect[lev-1], 1, levelDomains[lev]); filler.coarseFineInterp(fineData, crseData); } #ifdef CH_USE_HDF5 // dump data if (writePlots) { string fname = "interp.hdf5"; Vector<string> varNames(1,"phi"); Real dt = 0.0; Real time= 0.0; WriteAMRHierarchyHDF5(fname, levelGrids, levelData, varNames, levelDomains[0].domainBox(), dxVect[0], dt, time, nRefVect, numLev); } #endif // clean up memory for (int lev=0; lev<levelData.size(); lev++) { if (levelData[lev] != NULL) { delete levelData[lev]; levelData[lev] = NULL; } } } // now test partially periodic case (also coarsen back to original domain // no such thing as "partially periodic" for 1D; for 1D, test moving // fine-grid boxes from low-end of domain to high-end of domain { baseDomain.setPeriodic(0,false); // try similar tests to the previous case int nRef = 2; ProblemDomain fineDomain(baseDomain); fineDomain.refine(nRef); const Box domainBox = baseDomain.domainBox(); Vector<Box> crseBoxes(1, domainBox); Vector<int> crseProcAssign(1,0); DisjointBoxLayout crseGrids(crseBoxes, crseProcAssign, baseDomain); // note the lack of ghost cells on the base level LevelData<FArrayBox> crseData(crseGrids, 1, IntVect::Zero); Real dxCrse = 1.0/(baseDomainSize); Real dxFine = dxCrse/nRef; initData(crseData, dxCrse); #if (CH_SPACEDIM == 1) Vector<Box> fineBoxes(2); Vector<int> fineProcAssign(2); fineBoxes[0] = Box(12*IntVect::Unit, 15*IntVect::Unit); fineBoxes[1] = Box(IntVect(D_DECL6(6,10,10,6,10,10)), IntVect(D_DECL6(11,15,15,11,15,15))); #else // try multiple boxes for fine level // note grids are different in this case to allow for all periodic checking Vector<Box> fineBoxes(3); Vector<int> fineProcAssign(3); fineBoxes[0] = Box(IntVect::Zero, 9*IntVect::Unit); fineBoxes[1] = Box(IntVect(D_DECL6(6,10,10,6,10,10)), IntVect(D_DECL6(11,15,15,11,15,15))); // this box should fail the disjointness test //fineBoxes[1] = Box(IntVect(D_DECL(7,10,10)), 17*IntVect::Unit); fineBoxes[2] = Box(IntVect(D_DECL6(12,2,0,12,2,0)), IntVect(D_DECL6(15,7,7,15,7,7))); //fineBoxes[3] = Box(IntVect(D_DECL(12,12,0)), 15*IntVect::Unit); #endif int loadbalancestatus = LoadBalance(fineProcAssign, fineBoxes); CH_assert (loadbalancestatus == 0); DisjointBoxLayout fineGrids; fineGrids.define(fineBoxes, fineProcAssign, fineDomain); LevelData<FArrayBox> fineData(fineGrids, 1, ghostVect); // set these to a bogus value to start with DataIterator fineDit = fineData.dataIterator(); for (fineDit.begin(); fineDit.ok(); ++fineDit) { fineData[fineDit()].setVal(1.0e9); } FineInterp interpolator(fineGrids, 1, nRef, fineDomain); // turn on fine-data averaging even though it's unnecessary // since this is a test (so we'd like to know if it's broken) bool averageFineData = true; interpolator.interpToFine(fineData, crseData, averageFineData); // now fill in first layer of ghost cells QuadCFInterp filler(fineGrids, &crseGrids, dxFine, nRef, 1, fineDomain); filler.coarseFineInterp(fineData, crseData); // now fill in remaining ghost cell with extrapolation Interval extrapInterval(1,1); ExtrapFillPatch extrapFiller(fineGrids, fineDomain, extrapInterval); for (int dir=0; dir<SpaceDim; dir++) { extrapFiller.fillExtrap(fineData,dir,0,1); } fineData.exchange(fineData.interval()); } } // if (SpaceDim <= 3) pout() << indent << pgmname << ": " << ( (status == 0) ? "passed all tests" : "failed at least one test,") << endl; #ifdef CH_MPI MPI_Finalize(); #endif return status ; }
void CFStencil::define( const ProblemDomain& a_fineDomain, const Box& a_grid, const DisjointBoxLayout& a_fineBoxes, const DisjointBoxLayout& a_coarBoxes, int a_refRatio, int a_direction, Side::LoHiSide a_hiorlo) { m_isDefined = true; CH_assert(a_refRatio >= 1); CH_assert(a_direction >= 0); CH_assert(a_direction < SpaceDim); CH_assert((a_hiorlo == Side::Lo) || (a_hiorlo == Side::Hi)); CH_assert(!a_fineDomain.isEmpty()); //set internal vars. most of these are kept around //just to keep the class from having an identity crisis. m_direction = a_direction; m_hiorlo = a_hiorlo; Box finebox = a_grid; //compute intvectset of all points on fine grid that //need to be interpolated //shift direction int hilo = sign(a_hiorlo); //create fine stencil Box edgebox; CH_assert((hilo ==1) || (hilo == -1)); if (hilo == -1) { edgebox = adjCellLo(finebox,m_direction,1); } else { edgebox = adjCellHi(finebox,m_direction,1); } edgebox = a_fineDomain & edgebox; if (!edgebox.isEmpty()) { Box periodicTestBox(a_fineDomain.domainBox()); if (a_fineDomain.isPeriodic()) { for (int idir=0; idir<SpaceDim; idir++) { if (a_fineDomain.isPeriodic(idir)) { periodicTestBox.grow(idir,-1); } } } m_fineIVS.define(edgebox); LayoutIterator lit = a_fineBoxes.layoutIterator(); for (lit.reset(); lit.ok(); ++lit) { m_fineIVS -= a_fineBoxes[lit()]; // if periodic, also need to subtract periodic images // only do this IF we're periodic _and_ both boxes // adjoin the domain box boundary somewhere if (a_fineDomain.isPeriodic() && !periodicTestBox.contains(edgebox) && !periodicTestBox.contains(a_fineBoxes[lit()])) { ShiftIterator shiftIt = a_fineDomain.shiftIterator(); IntVect shiftMult(a_fineDomain.domainBox().size()); Box shiftedBox(a_fineBoxes[lit()]); for (shiftIt.begin(); shiftIt.ok(); ++shiftIt) { IntVect shiftVect = shiftMult*shiftIt(); shiftedBox.shift(shiftVect); m_fineIVS -= shiftedBox; shiftedBox.shift(-shiftVect); } // end loop over periodic shift directions } // end if periodic } } //ivs where all coarse slopes are defined //== coarsened fine ivs m_coarIVS.define(m_fineIVS); m_coarIVS.coarsen(a_refRatio); // this is a trick to get around the lack of a IntVectSet intersection // operator which works with a ProblemDomain ProblemDomain coardom= coarsen(a_fineDomain, a_refRatio); Box domainIntersectBox = m_coarIVS.minBox(); domainIntersectBox = coardom & domainIntersectBox; m_coarIVS &= domainIntersectBox; m_packedBox = m_fineIVS.minBox(); if (m_fineIVS.numPts() == m_packedBox.numPts()) { m_isPacked = true; } else { m_isPacked = false; m_packedBox = Box(); } }
int checkEBISL(const EBISLayout& a_ebisl, const DisjointBoxLayout& a_grids, const Box& a_domain, const Real& a_dx, const RealVect& a_origin, const int& a_upDir, const int& a_indepVar, const Real& a_startPt, const Real& a_slope) { //check to see that the sum of the volume fractions //comes to close to exactly the total volume int eekflag = 0; #ifdef CH_USE_FLOAT Real tolerance = 60 * PolyGeom::getTolerance(); #else Real tolerance = PolyGeom::getTolerance(); #endif const IntVect& ivSize= a_domain.size(); RealVect hiCorn; RealVect domLen; Real cellVolume = 1.0; Real totalVolume = 1.0; for (int idir = 0; idir < SpaceDim; idir++) { hiCorn[idir] = a_origin[idir] + a_dx*Real(ivSize[idir]); cellVolume *= a_dx; domLen[idir] = hiCorn[idir] - a_origin[idir]; totalVolume *= domLen[idir]; } //find normal and alpha in the space where the length of //the domain in all directions is unity int iy = a_upDir; int ix = a_indepVar; RealVect normal = RealVect::Zero; normal[iy] = domLen[iy]; normal[ix] = -a_slope*domLen[ix]; Real alpha = a_slope*(a_origin[ix]-a_startPt)-a_origin[iy]; Real volExact = totalVolume*PolyGeom::computeVolume(alpha, normal); RealVect correctNorm = RealVect::Zero; Real sumSquare; correctNorm[a_upDir] = 1.0; correctNorm[a_indepVar] = -a_slope; PolyGeom::unifyVector(correctNorm, sumSquare); // //voltot = sum(cellVolume*volFrac) = numerical domain volume. Real voltot = 0; for (DataIterator dit = a_grids.dataIterator(); dit.ok(); ++dit) { const EBISBox& ebisBox = a_ebisl[dit()]; for (BoxIterator bit(a_grids.get(dit())); bit.ok(); ++bit) { const IntVect& iv = bit(); Vector<VolIndex> vofs = ebisBox.getVoFs(iv); if (vofs.size() > 1) { eekflag = 2; return eekflag; } for (int ivof = 0; ivof < vofs.size(); ivof++) { Real volFrac = ebisBox.volFrac(vofs[ivof]); voltot += volFrac*cellVolume; if (volFrac > tolerance && volFrac < 1.0-tolerance) { if (!ebisBox.isIrregular(iv)) { eekflag = 4; return eekflag; } RealVect normal= ebisBox.normal(vofs[ivof]); for (int idir = 0; idir < SpaceDim; idir++) { if (Abs(normal[idir] - correctNorm[idir]) > tolerance) { eekflag = 5; return eekflag; } } RealVect centroid= ebisBox.centroid(vofs[ivof]); for (int idir = 0; idir < SpaceDim; idir++) { if (Abs(centroid[idir]) > 0.5) { eekflag = 6; return eekflag; } } } } } } #ifdef CH_MPI Real t=voltot; MPI_Allreduce ( &t, &voltot, 1, MPI_CH_REAL, MPI_SUM, Chombo_MPI::comm); #endif if (Abs(voltot -volExact) > tolerance) { pout() << Abs(voltot - volExact) << " > " << tolerance << endl; eekflag = 3; return eekflag; } return eekflag; }
int testIFFAB(const DisjointBoxLayout& a_dbl, const EBISLayout & a_ebisl, const Box & a_domain, const Real & a_dx ) { int faceDir = 0; int nFlux = 1; LayoutData<IntVectSet> irregSetsGrown; LevelData< BaseIFFAB<Real> > fluxInterpolant; EBArith::defineFluxInterpolant(fluxInterpolant, irregSetsGrown, a_dbl, a_ebisl, a_domain, nFlux, faceDir); //set source fab to right ans over set only on grids interior cells int ibox = 0; for (DataIterator dit = a_dbl.dataIterator(); dit.ok(); ++dit) { BaseIFFAB<Real>& srcFab = fluxInterpolant[dit()]; srcFab.setVal(-1.0); IntVectSet ivsSmall = irregSetsGrown[dit()]; const Box& grid = a_dbl.get(dit()); ivsSmall &= grid; for (FaceIterator faceit(ivsSmall, a_ebisl[dit()].getEBGraph(), faceDir, FaceStop::SurroundingWithBoundary); faceit.ok(); ++faceit) { srcFab(faceit(), 0) = rightAns(faceit()); } ibox++; } //diagnostics if (g_diagnosticMode) { pout() << " diagnostics for processor " << procID() << endl; for (DataIterator dit = a_dbl.dataIterator(); dit.ok(); ++dit) { const IntVectSet& ivsGrown = irregSetsGrown[dit()]; const Box& grid = a_dbl.get(dit()); pout() << "============" << endl; pout() << " box = " << grid; pout() << ", full ivs = " ; dumpIVS(&ivsGrown); pout() << "============" << endl; for (LayoutIterator lit = a_dbl.layoutIterator(); lit.ok(); ++lit) { const Box& grid2 = a_dbl.get(lit()); IntVectSet ivsIntersect = ivsGrown; ivsIntersect &= grid2; pout() << "intersection with box " << grid2 << " = "; dumpIVS(&ivsIntersect); pout() << "============" << endl; } } } BaseIFFAB<Real>::setVerbose(true); //do the evil exchange Interval interv(0, nFlux-1); fluxInterpolant.exchange(interv); ibox = 0; //check the answer over grown set Real tolerance = 0.001; for (DataIterator dit = a_dbl.dataIterator(); dit.ok(); ++dit) { const BaseIFFAB<Real>& srcFab = fluxInterpolant[dit()]; const IntVectSet& ivsGrown = irregSetsGrown[dit()]; for (FaceIterator faceit(ivsGrown, a_ebisl[dit()].getEBGraph(), faceDir, FaceStop::SurroundingWithBoundary); faceit.ok(); ++faceit) { Real correct = rightAns(faceit()); Real fabAns = srcFab(faceit(), 0); if (Abs(correct - fabAns) > tolerance) { pout() << "iffab test failed at face " << faceit().gridIndex(Side::Lo) << faceit().gridIndex(Side::Hi) << endl; pout() << " right ans = " << correct << endl; pout() << " data holds= " << fabAns << endl; int eekflag = -3; return eekflag; } } ibox++; } return 0; }
int checkEBISL(const EBISLayout& a_ebisl, const DisjointBoxLayout& a_grids, const Box& a_domain, const Real& a_dx, const RealVect& a_origin, const Real& a_radius, const RealVect& a_center, const bool& a_insideRegular) { //check to see that the sum of the volume fractions //comes to close to exactly the total volume int eekflag = 0; //First: calculate volume of domain const IntVect& ivSize = a_domain.size(); RealVect hiCorn; RealVect domLen; Real cellVolume = 1.0; Real totalVolume = 1.0; for (int idir = 0; idir < SpaceDim; idir++) { hiCorn[idir] = a_origin[idir] + a_dx*Real(ivSize[idir]); cellVolume *= a_dx; domLen[idir] = hiCorn[idir] - a_origin[idir]; totalVolume *= domLen[idir]; } // Calculate the exact volume of the regular region Real volExact; Real volError; Real bndryExact; Real bndryError; if (SpaceDim == 2) { volExact = acos(-1.0) * a_radius*a_radius; volError = 0.0001851; bndryExact = 2*acos(-1.0) * a_radius; bndryError = 0.000047; } if (SpaceDim == 3) { volExact = 4.0/3.0 * acos(-1.0) * a_radius*a_radius*a_radius; volError = 0.000585; bndryExact = 4.0 * acos(-1.0) * a_radius*a_radius; bndryError = 0.000287; } if (a_insideRegular == false) { volExact = totalVolume - volExact; } // Now calculate the volume of approximate sphere Real tolerance = 0.001; Real volTotal = 0.0; Real bndryTotal = 0.0; for (DataIterator dit = a_grids.dataIterator(); dit.ok(); ++dit) { const EBISBox& ebisBox = a_ebisl[dit()]; for (BoxIterator bit(a_grids.get(dit())); bit.ok(); ++bit) { const IntVect& iv = bit(); Vector<VolIndex> vofs = ebisBox.getVoFs(iv); if (vofs.size() > 1) { eekflag = 2; return eekflag; } for (int ivof = 0; ivof < vofs.size(); ivof++) { Real volFrac = ebisBox.volFrac(vofs[ivof]); if (ebisBox.isIrregular(iv)) { pout() << "iv = " << iv << ", volFrac = " << volFrac << endl; } volTotal += volFrac * cellVolume; Real bndryArea = ebisBox.bndryArea(vofs[ivof]); bndryTotal += bndryArea * cellVolume / a_dx; if (volFrac > tolerance && volFrac < 1.0 - tolerance) { if (!ebisBox.isIrregular(iv)) { eekflag = 4; return eekflag; } } } } } #ifdef CH_MPI Real t=volTotal; MPI_Allreduce ( &t, &volTotal, 1, MPI_CH_REAL, MPI_SUM, Chombo_MPI::comm); t=bndryTotal; MPI_Allreduce ( &t, &bndryTotal, 1, MPI_CH_REAL, MPI_SUM, Chombo_MPI::comm); #endif //check how close is the answer pout() << endl; Real error; error = volTotal - volExact; if (Abs(error/volExact) > volError) { eekflag = 5; } pout() << "volTotal = " << volTotal << endl; pout() << "volExact = " << volExact << endl; pout() << "error = " << error << endl; pout() << "relError = " << Abs(error/volExact) << endl; pout() << "tolerance = " << volError << endl; pout() << endl; error = bndryTotal - bndryExact; if (Abs(error/bndryExact) > bndryError) { eekflag = 6; } pout() << "bndryTotal = " << bndryTotal << endl; pout() << "bndryExact = " << bndryExact << endl; pout() << "error = " << error << endl; pout() << "relError = " << Abs(error/bndryExact) << endl; pout() << "tolerance = " << bndryError << endl; pout() << endl; return eekflag; }
// --------------------------------------------------------- void NodeQCFI::define(const DisjointBoxLayout& a_grids, Real a_dx, const ProblemDomain& a_domain, const LayoutData<NodeCFIVS>* const a_loCFIVS, const LayoutData<NodeCFIVS>* const a_hiCFIVS, int a_refToCoarse, NodeBCFunc a_bc, int a_interpolationDegree, int a_ncomp, bool a_verbose) { CH_assert(a_refToCoarse >= 2); m_bc = a_bc; m_grids = a_grids; m_dx = a_dx; m_verbose = a_verbose; // m_coarsenings == log2(a_refToCoarse); m_coarsenings = 0; for (int interRatio = a_refToCoarse; interRatio >= 2; interRatio /= 2) m_coarsenings++; m_qcfi2.resize(m_coarsenings); m_inter.resize(m_coarsenings-1); m_loCFIVScoarser.resize(m_coarsenings-1); m_hiCFIVScoarser.resize(m_coarsenings-1); // for i=1:m_c-2, m_qcfi2[i] interpolates m_inter[i] from m_inter[i-1]. if (m_coarsenings == 1) { m_qcfi2[0] = new NodeQuadCFInterp2(a_grids, a_domain, a_loCFIVS, a_hiCFIVS, false, a_interpolationDegree, a_ncomp); } else { // if m_coarsenings == 2: // m_qcfi2[1] = new NodeQuadCFInterp2(a_grids, true); // m_qcfi2[0] = new NodeQuadCFInterp2(a_grids.coarsen(2), false); // m_inter[0] = new LevelData(a_grids.coarsen(2)); ProblemDomain domainLevel(a_domain); Real dxLevel = m_dx; DisjointBoxLayout gridsInterFine(a_grids); DisjointBoxLayout gridsInterCoarse; // m_qcfi2[m_coarsenings-1] interpolates from a 2-coarsening of // the fine grids onto the fine grids (a_grids). // Interpolation is from the interface only. m_qcfi2[m_coarsenings-1] = new NodeQuadCFInterp2(a_grids, domainLevel, a_loCFIVS, a_hiCFIVS, true, a_interpolationDegree, a_ncomp); for (int interlev = m_coarsenings - 2; interlev >= 0; interlev--) { // m_coarsenings >= 2, so this will be executed at least once. coarsen(gridsInterCoarse, gridsInterFine, 2); domainLevel.coarsen(2); dxLevel *= 2.; bool interfaceOnly = (interlev > 0); // m_qcfi2[interlev] interpolates from some coarsening of // the fine grids onto gridsInterCoarse. // Except for the first time (interlev == 0), // interpolation is from the interface only. // Define objects containing the nodes of the coarse/fine interfaces. m_loCFIVScoarser[interlev] = new LayoutData<NodeCFIVS>[SpaceDim]; m_hiCFIVScoarser[interlev] = new LayoutData<NodeCFIVS>[SpaceDim]; for (int idir = 0; idir < SpaceDim; idir++) { LayoutData<NodeCFIVS>& loCFIVS = m_loCFIVScoarser[interlev][idir]; LayoutData<NodeCFIVS>& hiCFIVS = m_hiCFIVScoarser[interlev][idir]; loCFIVS.define(gridsInterCoarse); hiCFIVS.define(gridsInterCoarse); for (DataIterator dit = gridsInterCoarse.dataIterator(); dit.ok(); ++dit) { const Box& bx = gridsInterCoarse.get(dit()); loCFIVS[dit()].define(domainLevel, bx, gridsInterCoarse, idir, Side::Lo); hiCFIVS[dit()].define(domainLevel, bx, gridsInterCoarse, idir, Side::Hi); } } m_qcfi2[interlev] = new NodeQuadCFInterp2(gridsInterCoarse, domainLevel, m_loCFIVScoarser[interlev], m_hiCFIVScoarser[interlev], interfaceOnly, a_interpolationDegree, a_ncomp); m_inter[interlev] = new LevelData<NodeFArrayBox>(gridsInterCoarse, a_ncomp, IntVect::Zero); gridsInterFine = gridsInterCoarse; } m_domainPenultimate = domainLevel; m_dxPenultimate = dxLevel; } m_ncomp = a_ncomp; m_isDefined = true; }
int makeLayouts(DisjointBoxLayout& a_dblCoar, DisjointBoxLayout& a_dblFine, const Box& a_domainCoar, const Box& a_domainFine) { //set up mesh refine object int eekflag= 0; Vector<Box> vboxCoar; Vector<Box> vboxFine; #if 1 ParmParse pp; int maxsize; pp.get("maxboxsize",maxsize); int bufferSize = 1; int blockFactor = 2; Real fillrat = 0.75; Vector<int> refRat(2,2); BRMeshRefine meshRefObj(a_domainCoar, refRat, fillrat, blockFactor, bufferSize, maxsize); Vector<Vector<Box> > oldMeshes(2); oldMeshes[0] = Vector<Box>(1, a_domainCoar); oldMeshes[1] = Vector<Box>(1, a_domainFine); //set up coarse tags int nc = a_domainCoar.size(0); int nmi = nc/2;//16 int nqu = nc/4;//8 int ntf = (nc*3)/4; //24 int nte = (nc*3)/8; //12 int nfe = (nc*5)/8; //20 #if (CH_SPACEDIM ==2) Box boxf1(IntVect(0, nqu), IntVect(nmi-1,ntf-1)); Box boxf2(IntVect(nmi,nte), IntVect(ntf-1,nfe-1)); Box boxf3(IntVect(nqu,0 ), IntVect(nfe-1,nqu-1)); Box boxf4(IntVect(nfe,nqu), IntVect(nc -1,nte-1)); // Box boxf5(IntVect(nqu,nqu), IntVect(ntf-1,ntf-1)); #else Box boxf1(IntVect(0, nqu,nqu), IntVect(nmi-1,ntf-1,ntf-1)); Box boxf2(IntVect(nmi,nte,nte), IntVect(ntf-1,nfe-1,nfe-1)); Box boxf3(IntVect(nqu,0,0 ), IntVect(nfe-1,nqu-1,nqu-1)); Box boxf4(IntVect(nfe,nqu,nqu), IntVect(nc -1,nte-1,nte-1)); // Box boxf5(IntVect(nqu,nqu), IntVect(ntf-1,ntf-1)) #endif IntVectSet tags; tags |= boxf1; tags |= boxf2; tags |= boxf3; tags |= boxf4; // tags |= boxf5; int baseLevel = 0; int topLevel = 0; Vector<Vector<Box> > newMeshes; meshRefObj.regrid(newMeshes, tags, baseLevel, topLevel, oldMeshes); vboxCoar = newMeshes[0]; vboxFine = newMeshes[1]; #else vboxCoar = Vector<Box>(1, a_domainCoar); Box shrunkFine = a_domainFine; int nc = Max(a_domainCoar.size(0)/4, 2); shrunkFine.grow(-nc); vboxFine = Vector<Box>(1, shrunkFine); #endif Vector<int> procAssignFine, procAssignCoar; eekflag = LoadBalance(procAssignFine,vboxFine); if (eekflag != 0) return eekflag; eekflag = LoadBalance(procAssignCoar,vboxCoar); if (eekflag != 0) return eekflag; a_dblFine.define(vboxFine, procAssignFine); a_dblCoar.define(vboxCoar, procAssignCoar); return eekflag; }
void MappedLevelFluxRegister::define(const DisjointBoxLayout& a_dbl, const DisjointBoxLayout& a_dblCoarse, const ProblemDomain& a_dProblem, const IntVect& a_nRefine, int a_nComp, bool a_scaleFineFluxes) { CH_TIME("MappedLevelFluxRegister::define"); m_isDefined = FluxRegDefined; // Basically, define was called m_nRefine = a_nRefine; m_scaleFineFluxes = a_scaleFineFluxes; DisjointBoxLayout coarsenedFine; coarsen(coarsenedFine, a_dbl, a_nRefine); #ifndef DISABLE_TEMPORARY_FLUX_REGISTER_OPTIMIZATION // This doesn't work for multi-block calculations, which are // not properly nested. -JNJ //begin temporary optimization. bvs int numPts = 0; for (LayoutIterator lit = a_dblCoarse.layoutIterator(); lit.ok(); ++lit) { numPts += a_dblCoarse[lit].numPts(); } for (LayoutIterator lit = coarsenedFine.layoutIterator(); lit.ok(); ++lit) { numPts -= coarsenedFine[lit].numPts(); } if (numPts == 0) { m_coarFlux.clear(); // OK, fine region completely covers coarse region. no registers. return; } #endif //end temporary optimization. bvs m_coarFlux.define( a_dblCoarse, a_nComp); m_isDefined |= FluxRegCoarseDefined; m_domain = a_dProblem; ProblemDomain coarsenedDomain; coarsen(coarsenedDomain, a_dProblem, a_nRefine); m_fineFlux.define( coarsenedFine, a_nComp, IntVect::Unit); m_isDefined |= FluxRegFineDefined; m_reverseCopier.ghostDefine(coarsenedFine, a_dblCoarse, coarsenedDomain, IntVect::Unit); for (int i = 0; i < CH_SPACEDIM; i++) { m_coarseLocations[i].define(a_dblCoarse); m_coarseLocations[i + CH_SPACEDIM].define(a_dblCoarse); } DataIterator dC = a_dblCoarse.dataIterator(); LayoutIterator dF = coarsenedFine.layoutIterator(); for (dC.begin(); dC.ok(); ++dC) { const Box& cBox = a_dblCoarse.get(dC); for (dF.begin(); dF.ok(); ++dF) { const Box& fBox = coarsenedFine.get(dF); if (fBox.bigEnd(0) + 1 < cBox.smallEnd(0)) { //can skip this box since they cannot intersect, due to sorting } else if (fBox.smallEnd(0) - 1 > cBox.bigEnd(0)) { //skip to end, since all the rest of boxes will not intersect either dF.end(); } else { for (int i = 0; i < CH_SPACEDIM; i++) { Vector<Box>& lo = m_coarseLocations[i][dC]; Vector<Box>& hi = m_coarseLocations[i + CH_SPACEDIM][dC]; Box loBox = adjCellLo(fBox, i, 1); Box hiBox = adjCellHi(fBox, i, 1); if (cBox.intersectsNotEmpty(loBox)) lo.push_back(loBox & cBox); if (cBox.intersectsNotEmpty(hiBox)) hi.push_back(hiBox & cBox); } } } } Box domainBox = coarsenedDomain.domainBox(); if (a_dProblem.isPeriodic()) { Vector<Box> periodicBoxes[2 * CH_SPACEDIM]; for (dF.begin(); dF.ok(); ++dF) { const Box& fBox = coarsenedFine.get(dF); for (int i = 0; i < CH_SPACEDIM; i++) { if (a_dProblem.isPeriodic(i)) { if (fBox.smallEnd(i) == domainBox.smallEnd(i)) periodicBoxes[i].push_back(adjCellLo(fBox, i, 1)); if (fBox.bigEnd(i) == domainBox.bigEnd(i)) periodicBoxes[i + CH_SPACEDIM].push_back(adjCellHi(fBox, i, 1)); } } } for (int i = 0; i < CH_SPACEDIM; i++) { Vector<Box>& loV = periodicBoxes[i]; Vector<Box>& hiV = periodicBoxes[i + CH_SPACEDIM]; int size = domainBox.size(i); for (int j = 0; j < loV.size(); j++) loV[j].shift(i, size); for (int j = 0; j < hiV.size(); j++) hiV[j].shift(i, -size); } for (dC.begin(); dC.ok(); ++dC) { const Box& cBox = a_dblCoarse.get(dC); for (int i = 0; i < CH_SPACEDIM; i++) if (a_dProblem.isPeriodic(i)) { Vector<Box>& loV = periodicBoxes[i]; Vector<Box>& hiV = periodicBoxes[i + CH_SPACEDIM]; if (cBox.smallEnd(i) == domainBox.smallEnd(i) ) { Vector<Box>& hi = m_coarseLocations[i + CH_SPACEDIM][dC]; for (int j = 0; j < hiV.size(); j++) { if (cBox.intersectsNotEmpty(hiV[j])) hi.push_back(cBox & hiV[j]); } } if (cBox.bigEnd(i) == domainBox.bigEnd(i) ) { Vector<Box>& lo = m_coarseLocations[i][dC]; for (int j = 0; j < loV.size(); j++) { if (cBox.intersectsNotEmpty(loV[j])) lo.push_back(cBox & loV[j]); } } } } } }
void LevelFluxRegisterEdge::refluxCurl(LevelData<FluxBox>& a_uCoarse, Real a_scale) { CH_assert(isDefined()); CH_assert(a_uCoarse.nComp() == m_nComp); SideIterator side; // idir is the normal direction to the coarse-fine interface for (int idir=0 ; idir<SpaceDim; ++idir) { for (side.begin(); side.ok(); ++side) { LevelData<FluxBox>& fineReg = m_fabFine[index(idir, side())]; // first, create temp LevelData<FluxBox> to hold "coarse flux" const DisjointBoxLayout coarseBoxes = m_regCoarse.getBoxes(); // this fills the place of what used to be m_fabCoarse in the old // implementation LevelData<FluxBox> coarReg(coarseBoxes, m_nComp, IntVect::Unit); // now fill the coarReg with the curl of the stored coarse-level // edge-centered flux DataIterator crseDit = coarseBoxes.dataIterator(); for (crseDit.begin(); crseDit.ok(); ++crseDit) { FluxBox& thisCoarReg = coarReg[crseDit]; thisCoarReg.setVal(0.0); EdgeDataBox& thisEdgeData = m_regCoarse[crseDit]; for (int edgeDir=0; edgeDir<SpaceDim; edgeDir++) { if (idir != edgeDir) { FArrayBox& crseEdgeDataDir = thisEdgeData[edgeDir]; for (int faceDir = 0; faceDir<SpaceDim; faceDir++) { if (faceDir != edgeDir) { FArrayBox& faceData = thisCoarReg[faceDir]; int shiftDir = -1; for (int i=0; i<SpaceDim; i++) { if ((i != faceDir) && (i != edgeDir) ) { shiftDir = i; } } CH_assert(shiftDir >= 0); crseEdgeDataDir.shiftHalf(shiftDir, sign(side())); // scaling already taken care of in incrementCrse Real scale = 1.0; faceData.plus(crseEdgeDataDir, scale, 0, 0, faceData.nComp()); crseEdgeDataDir.shiftHalf(shiftDir, -sign(side())); } // end if not normal direction } // end loop over face directions } // end if edgeDir != idir } // end loop over edge directions } // end loop over crse boxes // first, we need to create a temp LevelData<FluxBox> // to make a local copy in the coarse layout space of // the fine register increments LevelData<FluxBox> fineRegLocal(coarReg.getBoxes(), m_nComp, IntVect::Unit); fineReg.copyTo(fineReg.interval(), fineRegLocal, fineRegLocal.interval(), m_crseCopiers[index(idir,side())]); for (DataIterator it = a_uCoarse.dataIterator(); it.ok(); ++it) { // loop over flux components here for (int fluxComp=0; fluxComp < SpaceDim; fluxComp++) { // we don't do anything in the normal direction if (fluxComp != idir) { // fluxDir is the direction of the face-centered flux FArrayBox& U = a_uCoarse[it()][fluxComp]; // set up IntVectSet to avoid double counting of updates Box coarseGridBox = U.box(); // transfer to Cell-centered, then create IVS coarseGridBox.shiftHalf(fluxComp,1); IntVectSet nonUpdatedEdges(coarseGridBox); // remember, we want to take the curl here // also recall that fluxComp is the component // of the face-centered curl (not the edge-centered // vector field that we're refluxing, which is why // the sign may seem like it's the opposite of what // you might expect! Real local_scale = -sign(side())*a_scale; //int testDir = (fluxComp+1)%(SpaceDim); if (((fluxComp+1)%(SpaceDim)) == idir) local_scale *= -1; Vector<IntVectSet>& ivsV = m_refluxLocations[index(idir, side())][it()][fluxComp]; Vector<DataIndex>& indexV = m_coarToCoarMap[index(idir, side())][it()]; IVSIterator iv; for (int i=0; i<ivsV.size(); ++i) { iv.define(ivsV[i]); const FArrayBox& coar = coarReg[indexV[i]][fluxComp]; const FArrayBox& fine = fineRegLocal[indexV[i]][fluxComp]; for (iv.begin(); iv.ok(); ++iv) { IntVect thisIV = iv(); if (nonUpdatedEdges.contains(thisIV)) { for (int comp=0; comp <m_nComp; ++comp) { //Real coarVal = coar(thisIV, comp); //Real fineVal = fine(thisIV, comp); U(thisIV, comp) -= local_scale*(coar(thisIV, comp) +fine(thisIV, comp)); } nonUpdatedEdges -= thisIV; } } } } // end if not normal face } // end loop over fluxbox directions } // end loop over coarse boxes } // end loop over sides } // end loop over directions }
// new define void LevelFluxRegisterEdge::define( const DisjointBoxLayout& a_dbl, const DisjointBoxLayout& a_dblCoarse, const ProblemDomain& a_dProblem, int a_nRefine, int a_nComp) { m_isDefined = true; CH_assert(a_nRefine > 0); CH_assert(a_nComp > 0); CH_assert(!a_dProblem.isEmpty()); m_nComp = a_nComp; m_nRefine = a_nRefine; m_domainCoarse = coarsen(a_dProblem, a_nRefine); CH_assert (a_dblCoarse.checkPeriodic(m_domainCoarse)); // allocate copiers m_crseCopiers.resize(SpaceDim*2); SideIterator side; // create a Vector<Box> of the fine boxes which also includes periodic images, // since we don't really care about the processor layouts, etc Vector<Box> periodicFineBoxes; CFStencil::buildPeriodicVector(periodicFineBoxes, a_dProblem, a_dbl); // now coarsen these boxes... for (int i=0; i<periodicFineBoxes.size(); i++) { periodicFineBoxes[i].coarsen(m_nRefine); } for (int idir=0 ; idir<SpaceDim; ++idir) { for (side.begin(); side.ok(); ++side) { // step one, build fineBoxes, flux register boxes // indexed by the fine level but in the coarse index // space DisjointBoxLayout fineBoxes,tmp; // first create coarsened dbl, then compute flux register boxes // adjacent to coarsened fine boxes coarsen(tmp, a_dbl, m_nRefine); if (side() == Side::Lo) { adjCellLo(fineBoxes, tmp, idir,1); } else { adjCellHi(fineBoxes, tmp, idir,1); } // now define the FluxBoxes of fabFine on this DisjointBoxLayout m_fabFine[index(idir, side())].define(fineBoxes, a_nComp); LayoutData<Vector<Vector<IntVectSet> > >& ivsetsVect = m_refluxLocations[index(idir, side())]; ivsetsVect.define(a_dblCoarse); LayoutData<Vector<DataIndex> >& mapsV = m_coarToCoarMap[index(idir, side())]; mapsV.define(a_dblCoarse); DisjointBoxLayout coarseBoxes = a_dblCoarse; DataIterator dit = a_dblCoarse.dataIterator(); for (dit.begin(); dit.ok(); ++dit) { unsigned int thisproc = a_dblCoarse.procID(dit()); if (thisproc == procID()) { ivsetsVect[DataIndex(dit())].resize(SpaceDim); } const Box& coarseBox = a_dblCoarse[dit()]; int count = 0; for (int i=0; i<periodicFineBoxes.size(); i++) { Box regBox; if (side() == Side::Lo) { regBox = adjCellLo(periodicFineBoxes[i], idir, 1); } else { regBox = adjCellHi(periodicFineBoxes[i], idir, 1); } // do this little dance in order to ensure that // we catch corner cells which might be in different // boxes. Box testBox(regBox); testBox.grow(1); testBox.grow(idir,-1); if (testBox.intersectsNotEmpty(coarseBox)) { testBox &= coarseBox; ++count; unsigned int proc = a_dblCoarse.procID(dit()); const DataIndex index = DataIndex(dit()); if (proc == procID()) { mapsV[DataIndex(dit())].push_back(index); // loop over face directions here for (int faceDir=0; faceDir<SpaceDim; faceDir++) { // do nothing in normal direction if (faceDir != idir) { // this should give us the face indices for the // faceDir-centered faces adjacent to the coarse-fine // interface which are contained in the current // coarse box Box intersectBox(regBox); Box coarseEdgeBox(coarseBox); coarseEdgeBox.surroundingNodes(faceDir); intersectBox.surroundingNodes(faceDir); intersectBox &= coarseEdgeBox; intersectBox.shiftHalf(faceDir,1); IntVectSet localIV(intersectBox); ivsetsVect[DataIndex(dit())][faceDir].push_back(localIV); } } } } } // end loop over boxes on coarse level } m_regCoarse.define(coarseBoxes, a_nComp, IntVect::Unit); // last thing to do is to define copiers m_crseCopiers[index(idir, side())].define(fineBoxes, coarseBoxes, IntVect::Unit); } } }
// this function averages down the fine solution to the valid // regions of the computed solution, then subtracts ir from // the computed solution. (error is exact-computed) void computeAMRError(Vector<LevelData<FArrayBox>* >& a_error, const Vector<string>& a_errorVars, const Vector<LevelData<FArrayBox>* >& a_computedSoln, const Vector<string>& a_computedVars, const Vector<DisjointBoxLayout>& a_computedGrids, const Real a_computedDx, const Vector<int>& a_computedRefRatio, const Vector<LevelData<FArrayBox>* >& a_exactSoln, const Vector<string>& a_exactVars, const Real a_exactDx, Real a_bogus_value, bool a_HOaverage, bool a_computeRelativeError) { int numLevels = a_computedSoln.size(); CH_assert(a_exactSoln.size() == 1); CH_assert(a_error.size() == numLevels); CH_assert(a_exactDx <= a_computedDx); CH_assert(a_computedRefRatio.size() >= numLevels - 1); if (a_exactDx == a_computedDx) { cerr << "Exact dx and computed dx are equal." << endl; } // check whether input file selects "sum all variables" bool sumAll = false; ParmParse pp; pp.query("sumAll",sumAll); // const DisjointBoxLayout& exactGrids = a_exactSoln[0]->getBoxes(); Real dxLevel = a_computedDx; // do a bit of sleight-of-hand in the case where there are no // ghost cells in the exact solution -- allocate a temporary which // _has_ ghost cells, and do a copyTo LevelData<FArrayBox>* exactSolnPtr = NULL; bool allocatedMemory = false; if (a_exactSoln[0]->ghostVect() == IntVect::Zero) { exactSolnPtr = new LevelData<FArrayBox>(a_exactSoln[0]->getBoxes(), a_exactSoln[0]->nComp(), IntVect::Unit); a_exactSoln[0]->copyTo(*exactSolnPtr); allocatedMemory = true; } else { // if there are ghost cells, we can use the exactSoln as-is exactSolnPtr = a_exactSoln[0]; } LevelData<FArrayBox>& exactSolnRef = *exactSolnPtr; // first need to set boundary conditions on exactsoln // this is for the Laplacian which is needed in AverageHO DataIterator ditFine = exactSolnRef.dataIterator(); DomainGhostBC exactBC; Interval exactComps(0, a_exactVars.size() - 1); for (int dir = 0; dir < SpaceDim; dir++) { SideIterator sit; for (sit.reset(); sit.ok(); ++sit) { // use HO extrapolation at physical boundaries HOExtrapBC thisBC(dir, sit(), exactComps); exactBC.setBoxGhostBC(thisBC); } } for (ditFine.begin(); ditFine.ok(); ++ditFine) { FArrayBox& thisFineSoln = exactSolnRef[ditFine()]; const Box& fineBox = exactSolnRef.getBoxes()[ditFine()]; exactBC.applyInhomogeneousBCs(thisFineSoln, fineBox, a_exactDx); } exactSolnRef.exchange(exactComps); // outer loop is over levels for (int level = 0; level < numLevels; level++) { LevelData<FArrayBox>& thisLevelError = *a_error[level]; LevelData<FArrayBox>& thisLevelComputed = *a_computedSoln[level]; // compute refinement ratio between solution at this level // and exact solution Real nRefTemp = (dxLevel / a_exactDx); int nRefExact = (int) nRefTemp; // this is to do rounding properly if necessary if (nRefTemp - nRefExact > 0.5) nRefExact += 1; // make sure it's not zero if (nRefExact == 0) nRefExact =1; const DisjointBoxLayout levelGrids = a_error[level]->getBoxes(); const DisjointBoxLayout fineGrids = a_exactSoln[0]->getBoxes(); DisjointBoxLayout coarsenedFineGrids; // petermc, 14 Jan 2014: Replace this because fineGrids might // not be coarsenable by nRefExact. // coarsen(coarsenedFineGrids, fineGrids, nRefExact); int nCoarsenExact = nRefExact; while ( !fineGrids.coarsenable(nCoarsenExact) && (nCoarsenExact > 0) ) { // Divide nCoarsenExact by 2 until fineGrids is coarsenable by it. nCoarsenExact /= 2; } if (nCoarsenExact == 0) { nCoarsenExact = 1; } coarsen(coarsenedFineGrids, fineGrids, nCoarsenExact); int numExact = a_exactVars.size(); LevelData<FArrayBox> averagedExact(coarsenedFineGrids, numExact); Box fineRefBox(IntVect::Zero, (nCoarsenExact-1)*IntVect::Unit); // average fine solution down to coarsened-fine level // loop over grids and do HO averaging down //DataIterator crseExactDit = coarsenedFineGrids.dataIterator(); for (ditFine.reset(); ditFine.ok(); ++ditFine) { const Box fineBox = exactSolnRef.getBoxes()[ditFine()]; FArrayBox fineTemp(fineBox, 1); Box coarsenedFineBox(fineBox); coarsenedFineBox.coarsen(nCoarsenExact); if (a_exactDx < a_computedDx) { // loop over components for (int comp = 0; comp < numExact; comp++) { Box coarseBox(coarsenedFineGrids.get(ditFine())); coarseBox &= coarsenedFineBox; if (!coarseBox.isEmpty()) { // for now, this is a quick and dirty way to avoid // stepping out of bounds if there are no ghost cells. // LapBox will be the box over which we are // able to compute the Laplacian. Box LapBox = exactSolnRef[ditFine()].box(); LapBox.grow(-1); LapBox &= fineBox; fineTemp.setVal(0.0); int doHO = 0; if (a_HOaverage) { doHO = 1; } // average by default int doAverage = 1; if (sumAll || sumVar(a_exactVars[comp])) { doAverage = 0; } // average or sum, based on booleans FORT_AVERAGEHO(CHF_FRA1(averagedExact[ditFine], comp), CHF_CONST_FRA1(exactSolnRef[ditFine], comp), CHF_FRA1(fineTemp, 0), CHF_BOX(coarseBox), CHF_BOX(LapBox), CHF_CONST_INT(nCoarsenExact), CHF_BOX(fineRefBox), CHF_INT(doHO), CHF_INT(doAverage)); } // end if crseBox not empty } // end loop over comps } else { // if cell sizes are the same, then copy averagedExact[ditFine].copy(exactSolnRef[ditFine]); } } // end loop over exact solution boxes int nRefineComputed = nRefExact / nCoarsenExact; LevelData<FArrayBox>* thisLevelComputedRefinedPtr = &thisLevelComputed; LevelData<FArrayBox>* thisLevelErrorRefinedPtr = &thisLevelError; if (nRefineComputed > 1) { // Do piecewise constant interpolation (replication) by nRefineComputed // on thisLevelComputed. DisjointBoxLayout levelRefinedGrids; refine(levelRefinedGrids, levelGrids, nRefineComputed); int nCompComputed = thisLevelComputed.nComp(); IntVect ghostVectComputed = nRefineComputed * thisLevelComputed.ghostVect(); thisLevelComputedRefinedPtr = new LevelData<FArrayBox>(levelRefinedGrids, nCompComputed, ghostVectComputed); ProblemDomain levelDomain = levelRefinedGrids.physDomain(); FineInterp interpolator(levelRefinedGrids, nCompComputed, nRefineComputed, levelDomain); interpolator.pwcinterpToFine(*thisLevelComputedRefinedPtr, thisLevelComputed); int nCompErr = thisLevelError.nComp(); IntVect ghostVectErr = nRefineComputed * thisLevelError.ghostVect(); thisLevelErrorRefinedPtr = new LevelData<FArrayBox>(levelRefinedGrids, nCompErr, ghostVectErr); } // initialize error to 0 // also initialize error to a bogus value DataIterator levelDit = thisLevelError.dataIterator(); for (levelDit.begin(); levelDit.ok(); ++levelDit) { (*thisLevelErrorRefinedPtr)[levelDit].setVal(a_bogus_value); } Box refComputedBox(IntVect::Zero, (nRefineComputed-1)*IntVect::Unit); // loop over variables for (int nErr = 0; nErr < a_errorVars.size(); nErr++) { string thisErrVar = a_errorVars[nErr]; bool done = false; // first loop over exact variables for (int exactComp = 0; exactComp < a_exactVars.size(); exactComp++) { string thisExactVar = a_exactVars[exactComp]; // check if this exact variable is "the one" if ((thisExactVar == thisErrVar) || nonAverageVar(thisErrVar)) { int computedComp = 0; // now loop over computed variables while (!done && (computedComp < a_computedVars.size())) { if (a_computedVars[computedComp] == thisErrVar) { if (!nonAverageVar(thisErrVar)) { // copy averaged exact solution -> error // and then subtract computed solution Interval exactInterval(exactComp, exactComp); Interval errorInterval(nErr, nErr); averagedExact.copyTo(exactInterval, *thisLevelErrorRefinedPtr, errorInterval); } DataIterator levelDit = thisLevelError.dataIterator(); for (levelDit.reset(); levelDit.ok(); ++levelDit) { FArrayBox& thisComputedRefined = (*thisLevelComputedRefinedPtr)[levelDit]; FArrayBox& thisErrorRefined = (*thisLevelErrorRefinedPtr)[levelDit]; if (a_computeRelativeError) { // do this a little strangely -- relative // error is one - computed/exact. thisErrorRefined.divide(thisComputedRefined, computedComp, nErr, 1); thisErrorRefined.invert(-1.0, nErr, 1); thisErrorRefined.plus(1.0, nErr, 1); } else { thisErrorRefined.minus(thisComputedRefined, computedComp, nErr, 1); } if (nRefineComputed > 1) { FArrayBox& thisError = thisLevelError[levelDit]; Box coarseBox = thisError.box(); // Average thisErrorRefined to thisError. int doHO = 0; if (a_HOaverage) { doHO = 1; } CH_assert(doHO == 0); // for now, this is a quick and dirty way to avoid // stepping out of bounds if there are no ghost cells. // LapBox will be the box over which we are // able to compute the Laplacian. Box LapBox = thisErrorRefined.box(); LapBox.grow(-1); // LapBox &= fineBox; FArrayBox fineTemp(thisErrorRefined.box(), 1); fineTemp.setVal(0.0); // average by default int doAverage = 1; // average or sum, based on booleans FORT_AVERAGEHO(CHF_FRA1(thisError, nErr), CHF_CONST_FRA1(thisErrorRefined, nErr), CHF_FRA1(fineTemp, 0), CHF_BOX(coarseBox), CHF_BOX(LapBox), CHF_CONST_INT(nRefineComputed), CHF_BOX(refComputedBox), CHF_INT(doHO), CHF_INT(doAverage)); } } // end loop over coarse grids done = true; } // if computedVar is a_errorVar computedComp += 1; } // end loop over a_computedVars if (!done) { pout() << "Variable " << thisErrVar << " not found!!!" << endl; MayDay::Error(); } } // end if this exactVar is correct } // end loop over exact variables } // end loop over errors if (nRefineComputed > 1) { delete thisLevelComputedRefinedPtr; delete thisLevelErrorRefinedPtr; } // now need to set covered regions to 0 if (level < numLevels - 1) { // will need to loop over all boxes in finer level, not just // those on this processor... const BoxLayout& finerGrids = a_computedSoln[level + 1]->boxLayout(); LayoutIterator fineLit = finerGrids.layoutIterator(); // outer loop over this level's grids, since there are fewer of them DataIterator levelDit = thisLevelError.dataIterator(); for (levelDit.reset(); levelDit.ok(); ++levelDit) { const Box& coarseBox = levelGrids[levelDit()]; FArrayBox& thisError = thisLevelError[levelDit()]; int numError = thisError.nComp(); for (fineLit.reset(); fineLit.ok(); ++fineLit) { Box fineBox(finerGrids[fineLit()]); // now coarsen box down to this level fineBox.coarsen(a_computedRefRatio[level]); // if coarsened fine box intersects error's box, set // overlap to 0 fineBox &= coarseBox; if (!fineBox.isEmpty()) { thisError.setVal(0.0, fineBox, 0, numError); } } // end loop over finer-level grids } // end loop over this-level grids // this is a good place to update dx as well dxLevel = dxLevel / a_computedRefRatio[level]; } // end if there is a finer level thisLevelError.exchange(); } // end loop over levels // clean up if we need to if (allocatedMemory) { delete exactSolnPtr; exactSolnPtr = NULL; } }
// this function works on two solutions on equivalent grids. // It subtracts the computed solution from the exact solution // if a_doGhostCells == true, then does box-by-box comparison, // including ghost cells (boxes must be the same for each). // Otherwise, only does this for valid cells, but boxes don't // need to be the same. void computeSameSizeError(Vector<LevelData<FArrayBox>* >& a_error, const Vector<string>& a_errorVars, const Vector<LevelData<FArrayBox>* >& a_computedSoln, const Vector<string>& a_computedVars, const Vector<DisjointBoxLayout>& a_computedGrids, const Real a_dx, const Vector<int>& a_refRatio, const Vector<LevelData<FArrayBox>* >& a_exactSoln, const Vector<string>& a_exactVars, Real a_bogus_value, bool a_computeRelativeError, bool a_doGhostCells) { int numLevels = a_computedSoln.size(); CH_assert(a_exactSoln.size() == numLevels); CH_assert(a_error.size() == numLevels); CH_assert(a_refRatio.size() >= numLevels - 1); Real dxLevel = a_dx; // outer loop is over levels for (int level = 0; level < numLevels; level++) { LevelData<FArrayBox>& thisLevelError = *a_error[level]; LevelData<FArrayBox>& thisLevelComputed = *a_computedSoln[level]; LevelData<FArrayBox>& thisLevelExact = *a_exactSoln[level]; const DisjointBoxLayout levelGrids = thisLevelComputed.getBoxes(); const DisjointBoxLayout exactGrids = thisLevelExact.getBoxes(); DataIterator levelDit = levelGrids.dataIterator(); for (levelDit.begin(); levelDit.ok(); ++levelDit) { // initialize error to a bogus value thisLevelError[levelDit()].setVal(a_bogus_value); } // loop over variables for (int nErr = 0; nErr < a_errorVars.size(); nErr++) { string thisErrVar = a_errorVars[nErr]; bool done = false; // this is where things differ between the ghost-cell // and non-ghost-cell approach. if (a_doGhostCells) { // this is the older approach to things -- // do everything grid-by-grid // first loop over exact variables for (int exactComp = 0; exactComp < a_exactVars.size(); exactComp++) { string thisExactVar = a_exactVars[exactComp]; // check if this exact variable is "the one" if (thisExactVar == thisErrVar) { int computedComp = 0; // now loop over computed variables while (!done && (computedComp < a_computedVars.size())) { if (a_computedVars[computedComp] == thisErrVar) { // copy exact solution -> error // and then subtract computed solution DataIterator exactDit = thisLevelExact.dataIterator(); for (levelDit.reset(); levelDit.ok(); ++levelDit) { FArrayBox& thisComputed = thisLevelComputed[levelDit()]; FArrayBox& thisError = thisLevelError[levelDit()]; const Box& thisBox = levelGrids[levelDit()]; for (exactDit.begin(); exactDit.ok(); ++exactDit) { if (thisBox.contains(exactGrids[exactDit()])) { thisError.copy(thisLevelExact[exactDit()], exactComp, nErr, 1); } // end if exact and computed boxes match } // end loop over exact grids if (a_computeRelativeError) { // do this a little strangely -- relative // error is one - computed/exact. thisError.divide(thisComputed, computedComp, nErr, 1); thisError.invert(-1.0, nErr, 1); thisError.plus(1.0, nErr, 1); } else { thisError.minus(thisComputed, computedComp, nErr, 1); } } // end loop over grids done = true; } // if a_computedVar is a_errorVar computedComp += 1; } // end loop over a_computedVars if (!done) { pout() << "Variable " << thisErrVar << " not found!!!" << endl; MayDay::Error(); } } // end if this exactVar is correct } // end loop over exact variables } else // non-ghost cell case; this is simpler: { // first loop over exact variables and copy into error for (int exactComp=0; exactComp<a_exactVars.size(); ++exactComp) { string thisExactVar = a_exactVars[exactComp]; // check if this exact variable is "the one" if (thisExactVar == thisErrVar) { // copy exact solution -> error Interval exactInterval(exactComp, exactComp); Interval errInterval(nErr, nErr); thisLevelExact.copyTo(exactInterval, thisLevelError, errInterval); done = true; } // end if this exact var is the error var } // end loop over exact comps if (!done) { pout() << "Variable " << thisErrVar << " not found in exact solution!!!" << endl; MayDay::Error(); } done = false; int computedComp = 0; // now loop over computed variables and subtract computed solution while (!done && (computedComp < a_computedVars.size())) { if (a_computedVars[computedComp] == thisErrVar) { for (levelDit.reset(); levelDit.ok(); ++levelDit) { FArrayBox& thisComputed = thisLevelComputed[levelDit()]; FArrayBox& thisError = thisLevelError[levelDit()]; thisError.minus(thisComputed, computedComp, nErr, 1); } // end loop over computed/error grids done = true; } // if a_computedVar is a_errorVar computedComp += 1; } // end loop over a_computedVars if (!done) { pout() << "Variable " << thisErrVar << " not found!!!" << endl; MayDay::Error(); } } // end non-ghost-cell case } // end loop over errors // now need to set covered regions to 0 if (level < numLevels - 1) { // will need to loop over all boxes in finer level, not just // those on this processor... const BoxLayout& finerGrids = a_computedSoln[level + 1]->boxLayout(); LayoutIterator fineLit = finerGrids.layoutIterator(); // outer loop over this level's grids, since there are fewer of them DataIterator levelDit = thisLevelError.dataIterator(); for (levelDit.reset(); levelDit.ok(); ++levelDit) { const Box& coarseBox = levelGrids[levelDit()]; FArrayBox& thisError = thisLevelError[levelDit()]; int numError = thisError.nComp(); for (fineLit.reset(); fineLit.ok(); ++fineLit) { Box fineBox(finerGrids[fineLit()]); // now coarsen box down to this level fineBox.coarsen(a_refRatio[level]); // if coarsened fine box intersects error's box, set // overlap to 0 fineBox &= coarseBox; if (!fineBox.isEmpty()) { thisError.setVal(0.0, fineBox, 0, numError); } } // end loop over finer-level grids } // end loop over this-level grids // this is a good place to update dx as well dxLevel = dxLevel / a_refRatio[level]; } // end if there is a finer level // finally, if we're not doing ghost cells, do an exchange just // to "prettify" the output if (!a_doGhostCells) { thisLevelError.exchange(thisLevelError.interval()); } } // end loop over levels }