// Initialize grids void AMRLevelPluto::initialGrid(const Vector<Box>& a_newGrids) { CH_assert(allDefined()); if (s_verbosity >= 3) { pout() << "AMRLevelPluto::initialGrid " << m_level << endl; } // Save original grids and load balance m_level_grids = a_newGrids; m_grids = loadBalance(a_newGrids); if (s_verbosity >= 4) { // Indicate/guarantee that the indexing below is only for reading // otherwise an error/assertion failure occurs const DisjointBoxLayout& constGrids = m_grids; pout() << "new grids: " << endl; for (LayoutIterator lit = constGrids.layoutIterator(); lit.ok(); ++lit) { pout() << constGrids[lit()] << endl; } } // Define old and new state data structures IntVect ivGhost = m_numGhost*IntVect::Unit; m_UNew.define(m_grids,m_numStates,ivGhost); m_UOld.define(m_grids,m_numStates,ivGhost); // Set up data structures levelSetup(); }
// Set up data on this level after regridding void AMRLevelPluto::regrid(const Vector<Box>& a_newGrids) { CH_assert(allDefined()); if (s_verbosity >= 3) { pout() << "AMRLevelPluto::regrid " << m_level << endl; } // Save original grids and load balance m_level_grids = a_newGrids; m_grids = loadBalance(a_newGrids); if (s_verbosity >= 4) { // Indicate/guarantee that the indexing below is only for reading // otherwise an error/assertion failure occurs const DisjointBoxLayout& constGrids = m_grids; pout() << "new grids: " << endl; for (LayoutIterator lit = constGrids.layoutIterator(); lit.ok(); ++lit) { pout() << constGrids[lit()] << endl; } } // Save data for later DataIterator dit = m_UNew.dataIterator(); for(;dit.ok(); ++dit){ m_UOld[dit()].copy(m_UNew[dit()]); } // Reshape state with new grids IntVect ivGhost = m_numGhost*IntVect::Unit; m_UNew.define(m_grids,m_numStates,ivGhost); // Set up data structures levelSetup(); // Interpolate from coarser level if (m_hasCoarser) { AMRLevelPluto* amrGodCoarserPtr = getCoarserLevel(); m_fineInterp.interpToFine(m_UNew,amrGodCoarserPtr->m_UNew); } // Copy from old state m_UOld.copyTo(m_UOld.interval(), m_UNew, m_UNew.interval()); m_UOld.define(m_grids,m_numStates,ivGhost); }
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(); }
void EBLevelGrid:: defineCoveringIVS() { CH_assert(m_isDefined); if (!m_isCoveringIVSDefined) { m_isCoveringIVSDefined = true; //define the covering ivs by first assembling its complement const Box& domBox = m_domain.domainBox(); IntVectSet complementIVS(domBox); for (LayoutIterator lit = m_grids.layoutIterator(); lit.ok(); ++lit) { complementIVS -= m_grids.get(lit()); } m_coveringIVS = IntVectSet(domBox); m_coveringIVS -= complementIVS; } }
// ------------------------------------------------------------- void Mask::buildMask(BaseFab<int>& a_mask, const ProblemDomain& a_dProblem, const BoxLayout& a_grids, const BoxLayout* a_fineGridsPtr, int a_nRefFine) { // first set entire box to Physical BC a_mask.setVal(maskPhysical); // now set all of domain interior to coarse Box domainInterior(a_mask.box()); domainInterior &= a_dProblem; a_mask.setVal(maskCoarse,domainInterior,0); // now loop over this level's boxes and set them to "copy" LayoutIterator lit = a_grids.layoutIterator(); for (lit.reset(); lit.ok(); ++lit) { Box intersectBox = a_grids.get(lit()); intersectBox &= a_mask.box(); if (!intersectBox.isEmpty()) { a_mask.setVal(maskCopy,intersectBox,0); } } // if finer grids exist, set them to "covered" if (a_fineGridsPtr != NULL) { CH_assert (a_nRefFine > 1); LayoutIterator litFine = a_fineGridsPtr->layoutIterator(); for (litFine.reset(); litFine.ok(); ++litFine) { Box coarsenedBox(a_fineGridsPtr->get(litFine())); coarsenedBox.coarsen(a_nRefFine); coarsenedBox &= a_mask.box(); if (!coarsenedBox.isEmpty()) { a_mask.setVal(maskCovered,coarsenedBox,0); } } } }
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 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; }
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]); } } } } } }
// 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 }
// 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; } }
void EBCoarToFineRedist:: define(const DisjointBoxLayout& a_dblFine, const DisjointBoxLayout& a_dblCoar, const EBISLayout& a_ebislFine, const EBISLayout& a_ebislCoar, const Box& a_domainCoar, const int& a_nref, const int& a_nvar, int a_redistRad, const EBIndexSpace* ebisPtr) { CH_TIME("EBCoarToFineRedist::define"); m_isDefined = true; m_nComp = a_nvar; m_refRat = a_nref; m_domainCoar = a_domainCoar; m_gridsFine = a_dblFine; m_gridsCoar = a_dblCoar; m_ebislFine = a_ebislFine; m_ebislCoar = a_ebislCoar; m_redistRad = a_redistRad; //created the coarsened fine layout m_gridsCedFine = DisjointBoxLayout(); coarsen(m_gridsCedFine, m_gridsFine, m_refRat); CH_assert(ebisPtr->isDefined()); int nghost = 3*m_redistRad; ebisPtr->fillEBISLayout(m_ebislCedFine, m_gridsCedFine, m_domainCoar, nghost); m_ebislCedFine.setMaxRefinementRatio(m_refRat, ebisPtr); //define the intvectsets over which the objects live m_setsCoar.define(m_gridsCoar); m_setsCedFine.define(m_gridsCedFine); //the buffers for the fine level are really simple. //grow the coarsened fine grid by the redist radius //and subtract off the coarsened fine grids. //intersect with the irregular cells. //this way get irregular cells range of this grid on coarse //grid. { CH_TIME("coarsened_fine_sets"); for (DataIterator dit = m_gridsCedFine.dataIterator(); dit.ok(); ++dit) { Box grownBox = grow(m_gridsCedFine.get(dit()), m_redistRad); grownBox &= m_domainCoar; IntVectSet localIVS = m_ebislCedFine[dit()].getIrregIVS(grownBox); //subtract off all boxes on fine level so we get stuff at the //coarse-fine interface that will redistribute to this grid for (LayoutIterator lit = m_gridsCedFine.layoutIterator(); lit.ok(); ++lit) { localIVS -= m_gridsCedFine.get(lit()); } m_setsCedFine[dit()] = localIVS; } } //the coarse buffers are more complicated. //Need to intersect irregular cells on this grid // with entire coarse/fine interface of width redist radius { CH_TIME("coarse_sets"); for (DataIterator dit = m_gridsCoar.dataIterator(); dit.ok(); ++dit) { Box coarBox = m_gridsCoar.get(dit()); //make the complement set the whole IntVectSet cfIntComp(coarBox); //subtract the CF Interface from each coarsened fine box //from the complement for (LayoutIterator lit1 = m_gridsCedFine.layoutIterator(); lit1.ok(); ++lit1) { Box grownBox = grow(m_gridsCedFine.get(lit1()), m_redistRad); grownBox &= m_domainCoar; IntVectSet cedCFIVS(grownBox); //subtract off all boxes on fine level so we get stuff at the //coarse-fine interface that will redistribute to this grid for (LayoutIterator lit2 = m_gridsCedFine.layoutIterator(); lit2.ok(); ++lit2) { cedCFIVS -= m_gridsCedFine.get(lit2()); } cfIntComp -=cedCFIVS; } //coarse fine interface is whole box - complement IntVectSet cfInterface(coarBox); cfInterface -= cfIntComp; IntVectSet localIVS = m_ebislCoar[dit()].getIrregIVS(coarBox); //intersect with fat coarse-fine interface localIVS &= cfInterface; m_setsCoar[dit()] = localIVS; } } //define the registers and all that defineDataHolders(); //initialize the buffers to zero setToZero(); }
void EBLevelTransport:: define(const DisjointBoxLayout& a_thisDBL, const DisjointBoxLayout& a_coarDBL, const EBISLayout& a_thisEBISL, const EBISLayout& a_coarEBISL, const ProblemDomain& a_domain, const int& a_nRefine, const RealVect& a_dx, const bool& a_hasCoarser, const bool& a_hasFiner, RefCountedPtr<EBPatchTransport>& a_patchGodunov, const EBIndexSpace* const a_eb) { CH_TIME("EBLevelTransport::define"); CH_assert(a_dx[0] > 0.0); CH_assert(a_nRefine > 0); m_ebPatchGodunov = a_patchGodunov; m_isDefined = true; m_thisGrids = a_thisDBL; m_thisEBISL = a_thisEBISL; m_refRatCrse = a_nRefine; m_dx = a_dx; m_domain = a_domain; m_hasCoarser = a_hasCoarser; m_hasFiner = a_hasFiner; if (m_hasCoarser) { m_coarGrids = a_coarDBL; m_coarEBISL = a_coarEBISL; } m_nVar = m_ebPatchGodunov->numPrimitives(); m_nPrim = m_ebPatchGodunov->numPrimitives(); m_nCons = m_ebPatchGodunov->numConserved(); m_nFlux = m_ebPatchGodunov->numFluxes(); m_irregSetsSmall.define(m_thisGrids); for(DataIterator dit = m_thisGrids.dataIterator(); dit.ok(); ++dit) { const EBISBox& ebisBox = m_thisEBISL[dit()]; if(!ebisBox.isAllCovered()) { const Box& thisBox = m_thisGrids.get(dit()); m_irregSetsSmall[dit()] = ebisBox.getIrregIVS(thisBox); } } m_cfIVS.define(m_thisGrids); for(DataIterator ditOuter = m_thisGrids.dataIterator(); ditOuter.ok(); ++ditOuter) { const EBISBox& ebisBox = m_thisEBISL[ditOuter()]; if(!ebisBox.isAllCovered()) { // make a grown box of the grid and then subtract off each grid in the //domain to make the coarse-fine IVS // CFIVS = grow(b, 1) - sum(bi) Box grownBox = grow(m_thisGrids.get(ditOuter()), 1); grownBox &= m_domain; IntVectSet complementIVS(grownBox); for(LayoutIterator litInner = m_thisGrids.layoutIterator(); litInner.ok(); ++litInner) { Box innerBox = m_thisGrids.get(litInner()); complementIVS -= innerBox; } m_cfIVS[ditOuter()] = complementIVS; } } m_nGhost = a_thisEBISL.getGhost(); if (m_hasCoarser) { CH_TIME("EBLevelTransport::define::fillPatchDefine"); ProblemDomain domainCrse = coarsen(m_domain, m_refRatCrse); //patcher is defined with the number of conserved vars. m_fillPatch.define(m_thisGrids, m_coarGrids, m_thisEBISL, m_coarEBISL, domainCrse, m_refRatCrse, m_nVar, m_nGhost, a_eb); m_fillPatchVel.define(m_thisGrids, m_coarGrids, m_thisEBISL, m_coarEBISL, domainCrse, m_refRatCrse, SpaceDim, m_nGhost, a_eb); } m_irregSetsSmall.define(m_thisGrids); for(DataIterator dit = m_thisGrids.dataIterator(); dit.ok(); ++dit) { const EBISBox& ebisBox = m_thisEBISL[dit()]; if(!ebisBox.isAllCovered()) { const Box& thisBox = m_thisGrids.get(dit()); m_irregSetsSmall[dit()] = ebisBox.getIrregIVS(thisBox); } } for(int faceDir = 0; faceDir < SpaceDim; faceDir++) { EBArith::defineFluxInterpolant(m_fluxInterpolants[faceDir], m_irregSetsGrown [faceDir], m_thisGrids, m_thisEBISL, m_domain, m_nFlux, faceDir); } BaseIVFactory<Real> cellFactorySmall(m_thisEBISL, m_irregSetsSmall); m_nonConsDivergence.define(m_thisGrids, m_nCons, IntVect::Zero, cellFactorySmall); m_ebIrregFaceFlux.define(m_thisGrids, m_nFlux, IntVect::Zero, cellFactorySmall); //create temp data with the correct number of ghost cells IntVect ivGhost = m_nGhost*IntVect::Unit; EBCellFactory factory(m_thisEBISL); IntVect flatGhostIV = 3*IntVect::Unit; m_flattening.define(m_thisGrids, 1, flatGhostIV, factory); }
PetscErrorCode setupGrids( Vector<int> &a_refratios, // out Vector<ProblemDomain> &a_domains, // out Vector<DisjointBoxLayout> &a_grids, // in/out int a_nLevs, Real &a_cdx, // out Vector<RefCountedPtr<LevelData<FArrayBox> > > a_exact, Vector<RefCountedPtr<LevelData<FArrayBox> > > a_phi, Real a_max_norm_error, Vector<IntVectSet> &a_tagVects, bool &a_same // out ) { CH_TIME("setupGrids"); const int new_level=a_nLevs-1; bool isperiodic[3] = {false,false,false}; PetscFunctionBeginUser; a_cdx = 1./s_nCells0; // out a_refratios.resize(a_nLevs-1); a_domains.resize(a_nLevs); a_grids.resize(a_nLevs); if (a_nLevs==1) { Vector<int> procAssign; Vector<Box> boxvector; Box levbox(IntVect::Zero,(s_nCells0-1)*IntVect::Unit), dombox=levbox; pout() << "setupGrids for level " << new_level+1 << "/" << a_nLevs << ". level domain " << levbox << endl; domainSplit(levbox, boxvector, s_maxboxsz, s_blockingfactor); // need blocking factor of 4 for C-F LoadBalance( procAssign, boxvector ); a_grids[new_level].define(boxvector,procAssign); a_domains[new_level].define(dombox,isperiodic); a_same = false; } else { Vector<Vector<Box> > old_grids(a_nLevs-1); int new_finest_level; Real fillRatio = .8; BRMeshRefine refiner; Box curr_dom_box; static double thresh; // refratio a_refratios[new_level-1] = s_refRatio; // make new domain { Box dombox = a_domains[new_level-1].domainBox(); dombox.refine(s_refRatio); a_domains[new_level].define(dombox,isperiodic); } refiner.define(a_domains[0],a_refratios,fillRatio,s_blockingfactor,s_nesting,s_maxboxsz); Real dx = a_cdx; if (a_nLevs==2) { // get max_grad on coarsest level - has the whole domain double max_ = 0.; const DisjointBoxLayout& dbl = a_grids[0]; for (DataIterator dit = dbl.dataIterator(); dit.ok(); ++dit) { FArrayBox& exactFAB = (*a_exact[0])[dit]; FArrayBox& phiFAB = (*a_phi[0])[dit]; Box region = dbl[dit]; for (BoxIterator bit(region); bit.ok(); ++bit) { const IntVect& iv = bit(); Real grad = 0., tt; if (s_amr_type_iserror) { tt = fabs(phiFAB(iv,0)-exactFAB(iv,0)); if (tt>max_) max_ = tt; } else { for (int dir=0; dir<SpaceDim; ++dir) { IntVect liv(iv), riv(iv); liv.shift(dir,-1); riv.shift(dir,1); tt = (exactFAB(riv,0)-exactFAB(liv,0))/(2.*dx); grad += tt*tt; } grad = sqrt(grad); if (grad>max_) max_ = grad; } } } #ifdef CH_MPI MPI_Allreduce( &max_, &thresh, 1, MPI_DOUBLE, MPI_MAX, PETSC_COMM_WORLD ); #else thresh = max_; #endif // set thresh thresh /= 2.; } // make tags curr_dom_box = a_domains[0].domainBox(); // used for hard wired refinement for (int ilev=0;ilev<new_level;ilev++) { const DisjointBoxLayout& dbl = a_grids[ilev]; for (DataIterator dit = dbl.dataIterator(); dit.ok(); ++dit) { FArrayBox& exactFAB = (*a_exact[ilev])[dit]; FArrayBox& phiFAB = (*a_phi[ilev])[dit]; Box region = dbl[dit]; for (BoxIterator bit(region); bit.ok(); ++bit) { const IntVect& iv = bit(); if (s_amr_type_iserror) { Real error = fabs(phiFAB(iv,0)-exactFAB(iv,0)); if (error > thresh) a_tagVects[ilev] |= iv; // real AMR } else // grad { Real grad = 0., tt; for (int dir=0; dir<SpaceDim; ++dir) { IntVect liv(iv), riv(iv); liv.shift(dir,-1); riv.shift(dir,1); tt = (exactFAB(riv,0)-exactFAB(liv,0))/(2.*dx); grad += tt*tt; } grad = sqrt(grad); if (grad > thresh) a_tagVects[ilev] |= iv; // real AMR } } } // grid // hardwire refinement in fake place IntVect se = a_domains[ilev].domainBox().smallEnd(); //se.shift(1,curr_dom_box.size(1)-1); a_tagVects[ilev] |= se; curr_dom_box.refine(s_refRatio); dx /= s_refRatio; thresh *= s_error_thresh; } // make old_grids, need to make all because coarse grids can change after refinement for (int ilev=0;ilev<new_level;ilev++) { const DisjointBoxLayout& dbl = a_grids[ilev]; old_grids[ilev].resize(dbl.size()); LayoutIterator lit = dbl.layoutIterator(); int boxIndex = 0; for (lit.begin(); lit.ok(); ++lit, ++boxIndex) { old_grids[ilev][boxIndex] = dbl[lit()]; } } pout() << "setupGrids for level " << new_level+1 << "/" << a_nLevs << ". level domain " << a_domains[new_level].domainBox() << endl; // want to keep these Vector<IntVectSet> tagVects_copy(a_nLevs-1); for (int ilev=0;ilev<new_level;ilev++) { tagVects_copy[ilev] = a_tagVects[ilev]; } Vector<Vector<Box> > new_grids; new_finest_level = refiner.regrid( new_grids, tagVects_copy, 0, new_level-1, old_grids ); if (new_finest_level == new_level-1) { a_same = true; } else { // test to see if grids have changed, create new DBLs a_same = true; for (int ilev=1; ilev<=new_finest_level; ++ilev) { int numGridsNew = new_grids[ilev].size(); Vector<int> procIDs(numGridsNew); LoadBalance(procIDs, new_grids[ilev]); const DisjointBoxLayout newDBL( new_grids[ilev], procIDs, a_domains[ilev] ); const DisjointBoxLayout oldDBL = a_grids[ilev]; a_same &= oldDBL.sameBoxes(newDBL); a_grids[ilev] = newDBL; } } if (a_same) { pout() << "setupGrids -- grids unchanged" << endl; } } PetscFunctionReturn(0); }
void EBCoarseAverage::define(const DisjointBoxLayout& a_dblFine, const DisjointBoxLayout& a_dblCoar, const EBISLayout& a_ebislFine, const EBISLayout& a_ebislCoar, const ProblemDomain& a_domainCoar, const int& a_nref, const int& a_nvar, const EBIndexSpace* ebisPtr) { CH_TIME("EBCoarseAverage::define"); CH_assert(ebisPtr->isDefined()); ProblemDomain domainFine = a_domainCoar; domainFine.refine(a_nref); EBLevelGrid eblgFine; EBLevelGrid eblgCoar = EBLevelGrid(a_dblCoar, a_ebislCoar, a_domainCoar); EBLevelGrid eblgCoFi; //check to see if the input layout is coarsenable. //if so, proceed with ordinary drill //otherwise, see if the layout covers the domain. //if it does, we can use domainsplit if (a_dblFine.coarsenable(a_nref)) { eblgFine = EBLevelGrid(a_dblFine, a_ebislFine, domainFine); m_useFineBuffer = false; } else { Box fineDomBox = refine(a_domainCoar.domainBox(), a_nref); int numPtsDom = fineDomBox.numPts(); //no need for gathers here because the meta data is global int numPtsLayout = 0; for (LayoutIterator lit = a_dblFine.layoutIterator(); lit.ok(); ++lit) { numPtsLayout += a_dblFine.get(lit()).numPts(); } bool coveringDomain = (numPtsDom == numPtsLayout); if (coveringDomain) { m_useFineBuffer = true; int maxBoxSize = 4*a_nref; Vector<Box> boxes; Vector<int> procs; domainSplit(fineDomBox, boxes, maxBoxSize); mortonOrdering(boxes); LoadBalance(procs, boxes); DisjointBoxLayout dblBufFine(boxes, procs); eblgFine = EBLevelGrid(dblBufFine, domainFine, 2, eblgCoar.getEBIS()); } else { pout() << "EBCoarseAverage::input layout is not coarsenable and does not cover the domain--bailing out" << endl; MayDay::Error(); } } coarsen(eblgCoFi, eblgFine, a_nref); define(eblgFine, eblgCoar, eblgCoFi, a_nref, a_nvar); }
void EBFineToCoarRedist:: define(const DisjointBoxLayout& a_dblFine, const DisjointBoxLayout& a_dblCoar, const EBISLayout& a_ebislFine, const EBISLayout& a_ebislCoar, const Box& a_domainCoar, const int& a_nref, const int& a_nvar, int a_redistRad, const EBIndexSpace* const a_ebisPtr) { CH_TIME("EBFineToCoarRedist::stardard_define"); m_isDefined = true; m_nComp = a_nvar; m_refRat = a_nref; m_domainCoar = a_domainCoar; m_gridsFine = a_dblFine; m_gridsCoar = a_dblCoar; m_ebislFine = a_ebislFine; m_ebislCoar = a_ebislCoar; m_redistRad = a_redistRad; //created the coarsened fine layout m_gridsRefCoar = DisjointBoxLayout(); refine(m_gridsRefCoar, m_gridsCoar, m_refRat); CH_assert(a_ebisPtr->isDefined()); int nghost = 3*m_redistRad; Box domainFine = refine(m_domainCoar, m_refRat); a_ebisPtr->fillEBISLayout(m_ebislRefCoar, m_gridsRefCoar, domainFine, nghost); m_ebislRefCoar.setMaxCoarseningRatio(m_refRat,a_ebisPtr); //define the intvectsets over which the objects live m_setsFine.define(m_gridsFine); m_setsRefCoar.define(m_gridsCoar); //make sets //global set consists of redistrad on the fine side of the coarse-fine //interface //the fine set is that within one fine box. //the refcoar set is that set within one refined coarse box. { CH_TIME("make_fine_sets"); for (DataIterator dit = m_gridsFine.dataIterator(); dit.ok(); ++dit) { const Box& fineBox = m_gridsFine.get(dit()); IntVectSet& fineSet = m_setsFine[dit()]; //add entire fine box fineSet = IntVectSet(fineBox); IntVectSet irregIVS = m_ebislFine[dit()].getIrregIVS(fineBox); fineSet &= irregIVS; //subtract fine box shrunk by the redistribution radius fineSet -= grow(fineBox, -m_redistRad); //subtract all other the fine boxes shifted in all //directions for (LayoutIterator lit = m_gridsFine.layoutIterator(); lit.ok(); ++lit) { const Box& otherBox = m_gridsFine.get(lit()); if (otherBox != fineBox) { for (int idir = 0; idir < SpaceDim; idir++) { for (SideIterator sit; sit.ok(); ++sit) { Box shiftBox = otherBox; shiftBox.shift(idir, sign(sit())*m_redistRad); fineSet -= shiftBox; } } } } } } { CH_TIME("make_coar_sets"); for (DataIterator dit = m_gridsCoar.dataIterator(); dit.ok(); ++dit) { Box grownBox = grow(m_gridsRefCoar.get(dit()), m_redistRad); grownBox &= domainFine; //find the complement of what we really want IntVectSet ivsComplement(grownBox); for (LayoutIterator litFine = m_gridsFine.layoutIterator(); litFine.ok(); ++litFine) { const Box& fineBox = m_gridsFine.get(litFine()); IntVectSet fineSet(fineBox); //add entire fine box fineSet = IntVectSet(fineBox); Box interiorBox = grow(fineBox, -m_redistRad); //subtract fine box shrunk by the redistribution radius fineSet -= interiorBox; //subtract all other the fine boxes shifted in all //directions for (LayoutIterator lit = m_gridsFine.layoutIterator(); lit.ok(); ++lit) { const Box& otherBox = m_gridsFine.get(lit()); if (otherBox != fineBox) { for (int idir = 0; idir < SpaceDim; idir++) { for (SideIterator sit; sit.ok(); ++sit) { Box shiftBox = otherBox; shiftBox.shift(idir, sign(sit())*m_redistRad); fineSet -= shiftBox; } } } } //subtract the fine set from the complement ivsComplement -= fineSet; } //now the set we want is the grownbox - complement IntVectSet& refCoarSet = m_setsRefCoar[dit()]; refCoarSet = IntVectSet(grownBox); refCoarSet -= ivsComplement; IntVectSet irregIVS = m_ebislRefCoar[dit()].getIrregIVS(grownBox); refCoarSet &= irregIVS; } } defineDataHolders(); setToZero(); }