// ----------------------------------------------------------------------------- // Adds coarse cell values directly to all overlying fine cells. // ----------------------------------------------------------------------------- void ConstInterpPS::prolongIncrement (LevelData<FArrayBox>& a_phiThisLevel, const LevelData<FArrayBox>& a_correctCoarse) { CH_TIME("ConstInterpPS::prolongIncrement"); // Gather grids, domains, refinement ratios... const DisjointBoxLayout& fineGrids = a_phiThisLevel.getBoxes(); const DisjointBoxLayout& crseGrids = a_correctCoarse.getBoxes(); CH_assert(fineGrids.compatible(crseGrids)); const ProblemDomain& fineDomain = fineGrids.physDomain(); const ProblemDomain& crseDomain = crseGrids.physDomain(); const IntVect mgRefRatio = fineDomain.size() / crseDomain.size(); CH_assert(mgRefRatio.product() > 1); DataIterator dit = fineGrids.dataIterator(); for (dit.reset(); dit.ok(); ++dit) { // Create references for convenience FArrayBox& fineFAB = a_phiThisLevel[dit]; const FArrayBox& crseFAB = a_correctCoarse[dit]; const Box& fineValid = fineGrids[dit]; // To make things easier, we will offset the // coarse and fine data boxes to zero. const IntVect& fiv = fineValid.smallEnd(); const IntVect civ = coarsen(fiv, mgRefRatio); // Correct the fine data FORT_CONSTINTERPPS ( CHF_FRA_SHIFT(fineFAB, fiv), CHF_CONST_FRA_SHIFT(crseFAB, civ), CHF_BOX_SHIFT(fineValid, fiv), CHF_CONST_INTVECT(mgRefRatio)); } }
void MappedLevelFluxRegister::incrementFine(const FArrayBox& a_fineFlux, Real a_scale, const DataIndex& a_fineDataIndex, const Interval& a_srcInterval, const Interval& a_dstInterval, int a_dir, Side::LoHiSide a_sd) { CH_assert(isDefined()); if (!(m_isDefined & FluxRegFineDefined)) return; CH_assert(a_srcInterval.size() == a_dstInterval.size()); CH_TIME("MappedLevelFluxRegister::incrementFine"); // We cast away the constness in a_coarseFlux for the scope of this function. This // should be acceptable, since at the end of the day there is no change to it. -JNJ FArrayBox& fineFlux = const_cast<FArrayBox&>(a_fineFlux); // Muhahaha. fineFlux.shiftHalf(a_dir, sign(a_sd)); Real denom = 1.0; if (m_scaleFineFluxes) { denom = m_nRefine.product() / m_nRefine[a_dir]; } Real scale = sign(a_sd) * a_scale / denom; FArrayBox& cFine = m_fineFlux[a_fineDataIndex]; // FArrayBox cFineFortran(cFine.box(), cFine.nComp()); // cFineFortran.copy(cFine); Box clipBox = m_fineFlux.box(a_fineDataIndex); clipBox.refine(m_nRefine); Box fineBox; if (a_sd == Side::Lo) { fineBox = adjCellLo(clipBox, a_dir, 1); fineBox &= fineFlux.box(); } else { fineBox = adjCellHi(clipBox, a_dir, 1); fineBox &= fineFlux.box(); } #if 0 for (BoxIterator b(fineBox); b.ok(); ++b) { int s = a_srcInterval.begin(); int d = a_dstInterval.begin(); for (; s <= a_srcInterval.end(); ++s, ++d) { cFine(coarsen(b(), m_nRefine), d) += scale * fineFlux(b(), s); } } #else // shifting to ensure fineBox is in the positive quadrant, so IntVect coarening // is just integer division. const Box& box = coarsen(fineBox, m_nRefine); Vector<Real> regbefore(cFine.nComp()); Vector<Real> regafter(cFine.nComp()); if (s_verbose && (a_dir == debugdir) && box.contains(ivdebnoeb)) { for (int ivar = 0; ivar < cFine.nComp(); ivar++) { regbefore[ivar] = cFine(ivdebnoeb, ivar); } } const IntVect& iv = fineBox.smallEnd(); IntVect civ = coarsen(iv, m_nRefine); int srcComp = a_srcInterval.begin(); int destComp = a_dstInterval.begin(); int ncomp = a_srcInterval.size(); FORT_MAPPEDINCREMENTFINE(CHF_CONST_FRA_SHIFT(fineFlux, iv), CHF_FRA_SHIFT(cFine, civ), CHF_BOX_SHIFT(fineBox, iv), CHF_CONST_INTVECT(m_nRefine), CHF_CONST_REAL(scale), CHF_CONST_INT(srcComp), CHF_CONST_INT(destComp), CHF_CONST_INT(ncomp)); if (s_verbose && (a_dir == debugdir) && box.contains(ivdebnoeb)) { for (int ivar = 0; ivar < cFine.nComp(); ivar++) { regafter[ivar] = cFine(ivdebnoeb, ivar); } } if (s_verbose && (a_dir == debugdir) && box.contains(ivdebnoeb)) { pout() << "levelfluxreg::incrementFine: scale = " << scale << endl; Box refbox(ivdebnoeb, ivdebnoeb); refbox.refine(m_nRefine); refbox &= fineBox; if (!refbox.isEmpty()) { pout() << "fine fluxes = " << endl; for (BoxIterator bit(refbox); bit.ok(); ++bit) { for (int ivar = 0; ivar < cFine.nComp(); ivar++) { pout() << "iv = " << bit() << "("; for (int ivar = 0; ivar < cFine.nComp(); ivar++) { pout() << fineFlux(bit(), ivar); } pout() << ")" << endl; } } } for (int ivar = 0; ivar < cFine.nComp(); ivar++) { pout() << " reg before = " << regbefore[ivar] << ", "; pout() << " reg after = " << regafter[ivar] << ", "; } pout() << endl; } //fineBox.shift(-shift); // now, check that cFineFortran and cFine are the same //fineBox.coarsen(m_nRefine); // for (BoxIterator b(fineBox); b.ok(); ++b) // { // if (cFineFortran(b(),0) != cFine(b(),0)) // { // MayDay::Error("Fortran doesn't match C++"); // } // } // need to shift boxes back to where they were on entry. // cFine.shift(-shift/m_nRefine); #endif fineFlux.shiftHalf(a_dir, - sign(a_sd)); }
// ----------------------------------------------------------------------------- // Adds coarse cell values directly to all overlying fine cells, // then removes the average from the fine result. // ----------------------------------------------------------------------------- void ZeroAvgConstInterpPS::prolongIncrement (LevelData<FArrayBox>& a_phiThisLevel, const LevelData<FArrayBox>& a_correctCoarse) { CH_TIME("ZeroAvgConstInterpPS::prolongIncrement"); // Gather grids, domains, refinement ratios... const DisjointBoxLayout& fineGrids = a_phiThisLevel.getBoxes(); const DisjointBoxLayout& crseGrids = a_correctCoarse.getBoxes(); CH_assert(fineGrids.compatible(crseGrids)); const ProblemDomain& fineDomain = fineGrids.physDomain(); const ProblemDomain& crseDomain = crseGrids.physDomain(); const IntVect mgRefRatio = fineDomain.size() / crseDomain.size(); CH_assert(mgRefRatio.product() > 1); // These will accumulate averaging data. Real localSum = 0.0; Real localVol = 0.0; CH_assert(!m_CCJinvPtr.isNull()); CH_assert(m_dxProduct > 0.0); DataIterator dit = fineGrids.dataIterator(); for (dit.reset(); dit.ok(); ++dit) { // Create references for convenience FArrayBox& fineFAB = a_phiThisLevel[dit]; const FArrayBox& crseFAB = a_correctCoarse[dit]; const Box& fineValid = fineGrids[dit]; const FArrayBox& JinvFAB = (*m_CCJinvPtr)[dit]; // To make things easier, we will offset the // coarse and fine data boxes to zero. const IntVect& fiv = fineValid.smallEnd(); const IntVect civ = coarsen(fiv, mgRefRatio); // Correct the fine data FORT_CONSTINTERPWITHAVGPS ( CHF_FRA_SHIFT(fineFAB, fiv), CHF_CONST_FRA_SHIFT(crseFAB, civ), CHF_BOX_SHIFT(fineValid, fiv), CHF_CONST_INTVECT(mgRefRatio), CHF_CONST_FRA1_SHIFT(JinvFAB,0,fiv), CHF_CONST_REAL(m_dxProduct), CHF_REAL(localVol), CHF_REAL(localSum)); } // Compute global sum (this is where the MPI communication happens) #ifdef CH_MPI Real globalSum = 0.0; int result = MPI_Allreduce(&localSum, &globalSum, 1, MPI_CH_REAL, MPI_SUM, Chombo_MPI::comm); if (result != MPI_SUCCESS) { MayDay::Error("Sorry, but I had a communication error in ZeroAvgConstInterpPS::prolongIncrement"); } Real globalVol = 0.0; result = MPI_Allreduce(&localVol, &globalVol, 1, MPI_CH_REAL, MPI_SUM, Chombo_MPI::comm); if (result != MPI_SUCCESS) { MayDay::Error("Sorry, but I had a communication error in ZeroAvgConstInterpPS::prolongIncrement"); } #else Real globalSum = localSum; Real globalVol = localVol; #endif // Remove the average from phi. Real avgPhi = globalSum / globalVol; for (dit.reset(); dit.ok(); ++dit) { a_phiThisLevel[dit] -= avgPhi; } }
void VCAMRPoissonOp2::restrictResidual(LevelData<FArrayBox>& a_resCoarse, LevelData<FArrayBox>& a_phiFine, const LevelData<FArrayBox>& a_rhsFine) { CH_TIME("VCAMRPoissonOp2::restrictResidual"); homogeneousCFInterp(a_phiFine); const DisjointBoxLayout& dblFine = a_phiFine.disjointBoxLayout(); for (DataIterator dit = a_phiFine.dataIterator(); dit.ok(); ++dit) { FArrayBox& phi = a_phiFine[dit]; m_bc(phi, dblFine[dit()], m_domain, m_dx, true); } a_phiFine.exchange(a_phiFine.interval(), m_exchangeCopier); for (DataIterator dit = a_phiFine.dataIterator(); dit.ok(); ++dit) { FArrayBox& phi = a_phiFine[dit]; const FArrayBox& rhs = a_rhsFine[dit]; FArrayBox& res = a_resCoarse[dit]; const FArrayBox& thisACoef = (*m_aCoef)[dit]; const FluxBox& thisBCoef = (*m_bCoef)[dit]; Box region = dblFine.get(dit()); const IntVect& iv = region.smallEnd(); IntVect civ = coarsen(iv, 2); res.setVal(0.0); #if CH_SPACEDIM == 1 FORT_RESTRICTRESVC1D #elif CH_SPACEDIM == 2 FORT_RESTRICTRESVC2D #elif CH_SPACEDIM == 3 FORT_RESTRICTRESVC3D #else This_will_not_compile! #endif (CHF_FRA_SHIFT(res, civ), CHF_CONST_FRA_SHIFT(phi, iv), CHF_CONST_FRA_SHIFT(rhs, iv), CHF_CONST_REAL(m_alpha), CHF_CONST_FRA_SHIFT(thisACoef, iv), CHF_CONST_REAL(m_beta), #if CH_SPACEDIM >= 1 CHF_CONST_FRA_SHIFT(thisBCoef[0], iv), #endif #if CH_SPACEDIM >= 2 CHF_CONST_FRA_SHIFT(thisBCoef[1], iv), #endif #if CH_SPACEDIM >= 3 CHF_CONST_FRA_SHIFT(thisBCoef[2], iv), #endif #if CH_SPACEDIM >= 4 This_will_not_compile! #endif CHF_BOX_SHIFT(region, iv), CHF_CONST_REAL(m_dx)); } }