void EBCoarseAverage::average(LevelData<EBFluxFAB>& a_coarData, const LevelData<EBFluxFAB>& a_fineData, const Interval& a_variables) { CH_TIME("EBCoarseAverage::average(LD<EBFluxFAB>)"); LevelData<EBFluxFAB> coarFiData; LevelData<EBFluxFAB> fineBuffer; CH_assert(isDefined()); { CH_TIME("buffer allocation"); EBFluxFactory factCoFi(m_eblgCoFi.getEBISL()); coarFiData.define( m_eblgCoFi.getDBL(), m_nComp, IntVect::Zero, factCoFi); if (m_useFineBuffer) { EBFluxFactory factFine(m_eblgFine.getEBISL()); fineBuffer.define(m_eblgFine.getDBL(), m_nComp, IntVect::Zero, factFine); } } if (m_useFineBuffer) { CH_TIME("fine_copy"); a_fineData.copyTo(a_variables, fineBuffer, a_variables); } { CH_TIME("averaging"); for (DataIterator dit = m_eblgFine.getDBL().dataIterator(); dit.ok(); ++dit) { const EBFluxFAB* fineFABPtr = NULL; if (m_useFineBuffer) { fineFABPtr = &fineBuffer[dit()]; } else { fineFABPtr = &a_fineData[dit()]; } EBFluxFAB& cofiFAB = coarFiData[dit()]; const EBFluxFAB& fineFAB = *fineFABPtr; for (int idir = 0; idir < SpaceDim; idir++) { averageFAB(cofiFAB[idir], fineFAB[idir], dit(), a_variables, idir); } } } { CH_TIME("copy_coar"); coarFiData.copyTo(a_variables, a_coarData, a_variables); } }
void EBCoarseAverage::average(LevelData<BaseIVFAB<Real> >& a_coarData, const LevelData<BaseIVFAB<Real> >& a_fineData, const Interval& a_variables) { CH_TIME("EBCoarseAverage::average(LD<BaseIVFAB>)"); LevelData<BaseIVFAB<Real> > coarFiData; LevelData<BaseIVFAB<Real> > fineBuffer; CH_assert(isDefined()); { CH_TIME("buffer allocation"); BaseIVFactory<Real> factCoFi(m_eblgCoFi.getEBISL(), m_irregSetsCoFi); coarFiData.define(m_eblgCoFi.getDBL(), m_nComp, IntVect::Zero, factCoFi); if (m_useFineBuffer) { BaseIVFactory<Real> factFine(m_eblgFine.getEBISL(), m_irregSetsFine); coarFiData.define(m_eblgFine.getDBL(), m_nComp, IntVect::Zero, factFine); } } if (m_useFineBuffer) { CH_TIME("fine_copy"); a_fineData.copyTo(a_variables, fineBuffer, a_variables); } { CH_TIME("averaging"); int ifnerg = 0; for (DataIterator dit = m_eblgFine.getDBL().dataIterator(); dit.ok(); ++dit) { const BaseIVFAB<Real>* fineFABPtr = NULL; if (m_useFineBuffer) { fineFABPtr = &fineBuffer[dit()]; } else { fineFABPtr = &a_fineData[dit()]; } BaseIVFAB<Real>& cofiFAB = coarFiData[dit()]; const BaseIVFAB<Real>& fineFAB = *fineFABPtr; averageFAB(cofiFAB, fineFAB, dit(), a_variables); ifnerg++; } } { CH_TIME("copy_coar"); coarFiData.copyTo(a_variables, a_coarData, a_variables); } }
void EBCoarseAverage::average(LevelData<EBCellFAB>& a_coarData, const LevelData<EBCellFAB>& a_fineData, const Interval& a_variables) { CH_TIME("EBCoarseAverage::average(LD<EBCellFAB>)"); LevelData<EBCellFAB> coarFiData; LevelData<EBCellFAB> fineBuffer; CH_assert(isDefined()); { CH_TIME("buffer allocation"); EBCellFactory factCoFi(m_eblgCoFi.getEBISL()); coarFiData.define( m_eblgCoFi.getDBL(), m_nComp, IntVect::Zero, factCoFi); if (m_useFineBuffer) { EBCellFactory factFine(m_eblgFine.getEBISL()); fineBuffer.define(m_eblgFine.getDBL(), m_nComp, IntVect::Zero, factFine); } } if (m_useFineBuffer) { CH_TIME("copy_fine"); a_fineData.copyTo(a_variables, fineBuffer, a_variables); } { CH_TIME("averaging"); for (DataIterator dit = m_eblgFine.getDBL().dataIterator(); dit.ok(); ++dit) { const EBCellFAB* fineFAB = NULL; if (m_useFineBuffer) { fineFAB = &fineBuffer[dit()]; } else { fineFAB = &a_fineData[dit()]; } averageFAB(coarFiData[dit()], *fineFAB, dit(), a_variables); } } { CH_TIME("copy_coar"); coarFiData.copyTo(a_variables, a_coarData, a_variables); } }
void EBPoissonOp:: create(LevelData<EBCellFAB>& a_lhs, const LevelData<EBCellFAB>& a_rhs) { int ncomp = a_rhs.nComp(); EBCellFactory ebcellfact(m_eblg.getEBISL()); a_lhs.define(m_eblg.getDBL(), ncomp, a_rhs.ghostVect(), ebcellfact); }
void makeLevelData(const Vector<Box>& boxes, LevelData<FArrayBox>& levelFab) { Vector<int> procIDs(boxes.size()); LoadBalance(procIDs, boxes); DisjointBoxLayout dbl1(boxes, procIDs); levelFab.define(dbl1, 1); }
//----------------------------------------------------------------------- void EBConsBackwardEulerIntegrator:: computeDiffusion(LevelData<EBCellFAB>& a_diffusionTerm, const LevelData<EBCellFAB>& a_oldTemperature, Real a_specificHeat, const LevelData<EBCellFAB>& a_oldDensity, const LevelData<EBCellFAB>& a_newDensity, const LevelData<EBCellFAB>& a_source, Real a_time, Real a_timeStep, bool a_zeroTemp) { // Allocate storage for the new temperature. LevelData<EBCellFAB> newTemp; EBCellFactory fact(m_eblg.getEBISL()); newTemp.define(m_eblg.getDBL(), 1, 4*IntVect::Unit, fact); EBLevelDataOps::setVal(newTemp, 0.0); // n+1 // Compute T. updateSolution(newTemp, a_oldTemperature, a_specificHeat, a_oldDensity, a_newDensity, a_source, a_time, a_timeStep, a_zeroTemp); // n+1 n // ([rho Cv T] - [rho Cv T] ) // ----------------------------- - a_source -> a_diffusionTerm. // dt a_oldTemperature.copyTo(a_diffusionTerm); for (DataIterator dit = m_eblg.getDBL().dataIterator(); dit.ok(); ++dit) { EBCellFAB& diff = a_diffusionTerm[dit()]; // n // [rho Cv T] -> diff diff *= a_oldDensity[dit()]; diff *= a_specificHeat; // n+1 // [rho Cv T] -> newRhoCvT EBCellFAB& newRhoCvT = newTemp[dit()]; newRhoCvT *= a_newDensity[dit()]; newRhoCvT *= a_specificHeat; // Subtract newRhoCvT from diff, and divide by -dt. diff -= newRhoCvT; diff /= -a_timeStep; // Subtract off the source. diff -= a_source[dit()]; } }
void EBPoissonOp:: createCoarser(LevelData<EBCellFAB>& a_coar, const LevelData<EBCellFAB>& a_fine, bool a_ghosted) { CH_assert(a_fine.nComp() == 1); const DisjointBoxLayout& dbl = m_eblgCoarMG.getDBL(); ProblemDomain coarDom = coarsen(m_eblg.getDomain(), 2); int nghost = a_fine.ghostVect()[0]; EBISLayout coarEBISL; const EBIndexSpace* const ebisPtr = Chombo_EBIS::instance(); ebisPtr->fillEBISLayout(coarEBISL, dbl, coarDom, nghost); EBCellFactory ebcellfact(coarEBISL); a_coar.define(dbl, 1,a_fine.ghostVect(),ebcellfact); }
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; } }
// --------------------------------------------------------------- // tag cells for regridding void AMRNavierStokes::tagCells(IntVectSet & a_tags) { if (s_verbosity >= 3) { pout () << "AMRNavierStokes::tagCells " << m_level << endl; } IntVectSet local_tags; // create tags based on something or other // for now, don't do anything const DisjointBoxLayout& level_domain = newVel().getBoxes(); if (s_tag_vorticity) { LevelData<FArrayBox> vorticity; LevelData<FArrayBox> mag_vorticity; if (SpaceDim == 2) { vorticity.define(level_domain,1); } else if (SpaceDim == 3) { vorticity.define(level_domain,SpaceDim); mag_vorticity.define(level_domain,1); } computeVorticity(vorticity); Interval vortInterval(0,0); if (SpaceDim == 3) { vortInterval = Interval(0,SpaceDim-1); } Real tagLevel = norm(vorticity, vortInterval, 0); // Real tagLevel = 1.0; //tagLevel *= s_vort_factor/m_dx; // actually tag where vort*dx > s_vort_factor*max(vort) tagLevel = s_vort_factor/m_dx; if (tagLevel > 0) { // now tag where vorticity magnitude is greater than or equal // to tagLevel DataIterator dit = vorticity.dataIterator(); for (dit.reset(); dit.ok(); ++dit) { FArrayBox& vortFab = vorticity[dit]; // this only needs to be done in 3d... if (SpaceDim==3) { FArrayBox& magVortFab = mag_vorticity[dit]; FORT_MAGVECT(CHF_FRA1(magVortFab,0), CHF_CONST_FRA(vortFab), CHF_BOX(level_domain[dit])); } BoxIterator bit(vortFab.box()); for (bit.begin(); bit.ok(); ++bit) { const IntVect& iv = bit(); if (SpaceDim == 2) { if (abs(vortFab(iv)) >= tagLevel) { local_tags |= iv; } } else if (SpaceDim == 3) { FArrayBox& magVortFab = mag_vorticity[dit]; if (abs(magVortFab(iv)) >= tagLevel) { local_tags |= iv; } } // end if DIM=3 } // end loop over interior of box } // loop over grids } // if taglevel > 0 } // if tagging on vorticity a_tags = local_tags; }
// --------------------------------------------------------- int main(int argc, char* argv[]) { int status = 0; // number of errors detected. // Do nothing if DIM > 3. #if (CH_SPACEDIM <= 3) #ifdef CH_MPI MPI_Init (&argc, &argv); #endif //scoping trick { // test parameters const int testOrder = 4; // expected order of convergence // A test is considered as a failure // if its convergence rate is smaller than below. Real targetConvergeRate = testOrder*0.9; #ifdef CH_USE_FLOAT targetConvergeRate = testOrder*0.89; #endif // number of ghost cells being interpolated int numGhost = 5; // refinement ratio between coarse and fine levels int refRatio = 4; Vector<Interval> fixedDimsAll; if (SpaceDim == 3) { fixedDimsAll.push_back(Interval(SpaceDim-1, SpaceDim-1)); } // Always include empty interval, meaning NO fixed dimensions. fixedDimsAll.push_back(Interval()); // real domain has length 1. in every dimension RealVect physLength = RealVect::Unit; for (int ifixed = 0; ifixed < fixedDimsAll.size(); ifixed++) { const Interval& fixedDims = fixedDimsAll[ifixed]; int nfixed = fixedDims.size(); IntVect interpUnit = IntVect::Unit; IntVect refineVect = refRatio * IntVect::Unit; for (int dirf = fixedDims.begin(); dirf <= fixedDims.end(); dirf++) { interpUnit[dirf] = 0; refineVect[dirf] = 1; } // No ghost cells in fixed dimensions. IntVect ghostVect = numGhost * interpUnit; #ifdef CH_USE_FLOAT // Single precision doesn't get us very far. #if (CH_SPACEDIM == 1) int domainLengthMin = 16; int domainLengthMax = 32; #else int domainLengthMin = 32; int domainLengthMax = 64; #endif #endif #ifdef CH_USE_DOUBLE int domainLengthMin = 32; #if CH_SPACEDIM >= 3 int domainLengthMax = 64; if (nfixed > 0) domainLengthMax = 128; #else int domainLengthMax = 512; #endif #endif Vector<int> domainLengths; int len = domainLengthMin; while (len <= domainLengthMax) { domainLengths.push_back(len); len *= 2; } int nGrids = domainLengths.size(); if (nGrids > 0) { pout() << endl << "Testing FourthOrderFillPatch DIM=" << SpaceDim; if (nfixed > 0) { pout() << " fixing " << fixedDims.begin() << ":" << fixedDims.end(); } pout() << endl; pout() << "size " << "max diff rate"; pout() << endl; } Real diffMaxCoarser; for (int iGrid = 0; iGrid < nGrids; iGrid++) { int domainLength = domainLengths[iGrid]; IntVect lenCoarse = domainLength * IntVect::Unit; RealVect dxCoarseVect = physLength / RealVect(lenCoarse); RealVect dxFineVect = dxCoarseVect / RealVect(refineVect); Box coarDomain, fineDomain; Vector<Box> coarBoxes, fineBoxes; setHierarchy(lenCoarse, refineVect, coarBoxes, fineBoxes, coarDomain, fineDomain); mortonOrdering(coarBoxes); mortonOrdering(fineBoxes); Vector<int> procCoar(coarBoxes.size()); Vector<int> procFine(fineBoxes.size()); LoadBalance(procCoar, coarBoxes); LoadBalance(procFine, fineBoxes); DisjointBoxLayout dblCoar(coarBoxes, procCoar); DisjointBoxLayout dblFine(fineBoxes, procFine); ProblemDomain probCoar(coarDomain); ProblemDomain probFine(fineDomain); FourthOrderFillPatch interpolator; int ncomp = 1; // Set coarseGhostsFill = ceil(numGhosts / refRatio). // int coarseGhostsFill = numGhost / refRatio; // if (coarseGhostsFill * refRatio < numGhost) coarseGhostsFill++; bool fixedTime = true; interpolator.define(dblFine, dblCoar, ncomp, probCoar, refRatio, numGhost, fixedTime, fixedDims); LevelData<FArrayBox> exactCoarse(dblCoar, ncomp); // Set exact value of function on coarse level. for (DataIterator dit = exactCoarse.dataIterator(); dit.ok(); ++dit) { CH_TIME("computing exactCoarse on FAB"); FArrayBox& exactCoarseFab = exactCoarse[dit]; const Box& bx = exactCoarseFab.box(); // Get average of function on each cell. for (BoxIterator bit(bx); bit.ok(); ++bit) { const IntVect& iv = bit(); RealVect cellLo = RealVect(iv) * dxCoarseVect; RealVect cellHi = cellLo + dxCoarseVect; exactCoarseFab(iv, 0) = avgFunVal(cellLo, cellHi, physLength); } } /* Define data holders on fine level. */ Interval intvlExact(0, ncomp-1); Interval intvlCalc(ncomp, 2*ncomp-1); Interval intvlDiff(2*ncomp, 3*ncomp-1); LevelData<FArrayBox> allFine; LevelData<FArrayBox> exactFine, calcFine, diffFine; { CH_TIME("allocate allFine"); allFine.define(dblFine, 3*ncomp, ghostVect); aliasLevelData(exactFine, &allFine, intvlExact); aliasLevelData(calcFine, &allFine, intvlCalc); aliasLevelData(diffFine, &allFine, intvlDiff); } /* Fill in data holders on fine level. */ // Set exact value of function on fine level. Real exactMax = 0.; for (DataIterator dit = exactFine.dataIterator(); dit.ok(); ++dit) { CH_TIME("computing exactFine on FAB"); FArrayBox& exactFineFab = exactFine[dit]; const Box& bx = exactFineFab.box(); // Get average of function on each cell. for (BoxIterator bit(bx); bit.ok(); ++bit) { const IntVect& iv = bit(); RealVect cellLo = RealVect(iv) * dxFineVect; RealVect cellHi = cellLo + dxFineVect; exactFineFab(iv, 0) = avgFunVal(cellLo, cellHi, physLength); } Real exactFabMax = exactFineFab.norm(0); if (exactFabMax > exactMax) exactMax = exactFabMax; } #ifdef CH_MPI reduceReal(exactMax, MPI_MAX); #endif // Fill in valid cells of calcFine by copying from exact. for (DataIterator dit = dblFine.dataIterator(); dit.ok(); ++dit) { const FArrayBox& exactFineFab = exactFine[dit]; FArrayBox& calcFineFab = calcFine[dit]; const Box& bx = dblFine[dit]; calcFineFab.copy(exactFineFab, bx); } // Fill in ghost cells of calcFine by copying where possible. calcFine.exchange(); // Fill in ghost cells of calcFine by interpolation where necessary. interpolator.fillInterp(calcFine, exactCoarse, 0, 0, ncomp); /* Got results. Now take differences, diffFine = calcFine - exactFine. */ Real diffMax = 0.; for (DataIterator dit = diffFine.dataIterator(); dit.ok(); ++dit) { CH_TIME("calculating diffFine"); FArrayBox& diffFineFab = diffFine[dit]; const FArrayBox& exactFineFab = exactFine[dit]; const FArrayBox& calcFineFab = calcFine[dit]; Box bxWithin(diffFineFab.box()); bxWithin &= probFine; diffFineFab.setVal(0.); diffFineFab.copy(exactFineFab, bxWithin); diffFineFab.minus(calcFineFab, bxWithin, 0, 0, ncomp); Real diffFabMax = diffFineFab.norm(0); if (diffFabMax > diffMax) diffMax = diffFabMax; // dummy statement in order to get around gdb bug int dummy_unused = 0; dummy_unused = 0; } #ifdef CH_MPI reduceReal(diffMax, MPI_MAX); #endif pout() << setw(4) << domainLength; pout() << " " << scientific << setprecision(4) << diffMax; if (iGrid > 0) { Real ratio = diffMaxCoarser / diffMax; Real rate = log(ratio) / log(2.0); pout () << " " << fixed << setprecision(2) << rate; if (rate < targetConvergeRate) { status += 1; } } pout() << endl; diffMaxCoarser = diffMax; } // end loop over grid sizes } // end loop over which dimensions are fixed if (status==0) { pout() << "All tests passed!\n"; } else { pout() << status << " tests failed!\n"; } } // end scoping trick #ifdef CH_MPI CH_TIMER_REPORT(); MPI_Finalize(); #endif #endif return status; }
void EBPoissonOp:: restrictResidual(LevelData<EBCellFAB>& a_resCoar, LevelData<EBCellFAB>& a_phiThisLevel, const LevelData<EBCellFAB>& a_rhsThisLevel) { CH_TIME("EBPoissonOp::restrictResidual"); CH_assert(a_resCoar.nComp() == 1); CH_assert(a_phiThisLevel.nComp() == 1); CH_assert(a_rhsThisLevel.nComp() == 1); LevelData<EBCellFAB> resThisLevel; bool homogeneous = true; EBCellFactory ebcellfactTL(m_eblg.getEBISL()); IntVect ghostVec = a_rhsThisLevel.ghostVect(); resThisLevel.define(m_eblg.getDBL(), 1, ghostVec, ebcellfactTL); // Get the residual on the fine grid residual(resThisLevel,a_phiThisLevel,a_rhsThisLevel,homogeneous); // now use our nifty averaging operator Interval variables(0, 0); CH_assert(m_hasMGObjects); m_ebAverageMG.average(a_resCoar, resThisLevel, variables); #ifdef DO_EB_RHS_CORRECTION // Apply error-correction modification to restricted RHS // Right now this only works with Dirichlet BC's, and only makes sense for the EB int correctionType = 0; // Change this to activate RHS correction if (correctionType != 0) { for (DataIterator dit = a_resCoar.disjointBoxLayout().dataIterator(); dit.ok(); ++dit) { EBCellFAB& resFAB = a_resCoar[dit()]; // Extract the FAB for this box const EBISBox& ebis = resFAB.getEBISBox(); // Get the set of all IntVect indices // Iterate over the parts of the RHS corresponding to the irregular cells, // correcting the RHS in each cell VoFIterator ebvofit(ebis.getIrregIVS(ebis.getRegion()), ebis.getEBGraph()); for (ebvofit.reset(); ebvofit.ok(); ++ebvofit) { for (int icomp = 0; icomp < resFAB.nComp(); ++icomp) // For each component of the residual on this VoF { if (correctionType == 1) { // Setting the residual to zero on the irregular cells gives convergence, // though the rate isn't as good as the full correction resFAB(ebvofit(), icomp) = 0.0; } else if (correctionType == 2) { // Kludge valid only for pseudo-1D test case. May not work for you. Real kappa = ebis.volFrac(ebvofit()); kappa = (kappa > 0.5 ? kappa : 0.5); // Floor on kappa to prevent dividing by a tiny number Real rhoCoeff = (kappa + 0.5)/(2.0*kappa); resFAB(ebvofit(), icomp) *= (1.0 - rhoCoeff); } // else silently do nothing } } } } #endif }