void EBMGInterp::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, const IntVect& a_ghostCellsPhi, const bool& a_layoutChanged, const bool& a_doLinear) { CH_TIMERS("EBMGInterp::define"); CH_TIMER("fillEBISLayout", t1); m_isDefined = true; m_doLinear = a_doLinear; m_ghost = a_ghostCellsPhi; m_nComp = a_nvar; m_coarGrids = a_dblCoar; m_fineGrids = a_dblFine; m_coarEBISL = a_ebislCoar; m_fineEBISL = a_ebislFine; m_coarDomain = a_domainCoar; m_refRat = a_nref; m_fineDomain = refine(m_coarDomain, m_refRat); m_layoutChanged = a_layoutChanged; m_coarsenable = a_dblFine.coarsenable(m_refRat); //only define ebislbuf and gridbuf if we are changing layouts if (m_layoutChanged) { ProblemDomain domebisl; if (m_coarsenable) { coarsen(m_buffGrids, m_fineGrids, m_refRat); domebisl = m_coarDomain; } else { refine(m_buffGrids, m_coarGrids, m_refRat); m_copierRCtoF.define(m_buffGrids, m_fineGrids, a_ghostCellsPhi); m_copierFtoRC.define(m_fineGrids, m_buffGrids, a_ghostCellsPhi); domebisl = m_fineDomain; } CH_START(t1); int nghost = 4; ebisPtr->fillEBISLayout(m_buffEBISL, m_buffGrids, domebisl, nghost); if (m_refRat > 2) { if (m_coarsenable) { m_buffEBISL.setMaxRefinementRatio(m_refRat, ebisPtr); } else { m_buffEBISL.setMaxCoarseningRatio(m_refRat, ebisPtr); } } CH_STOP(t1); } defineStencils(); }
// 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 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); }