// --------------------------------------------------------- void AMRNavierStokes::computeLapVel(LevelData<FArrayBox>& a_lapVel, LevelData<FArrayBox>& a_vel, const LevelData<FArrayBox>* a_crseVelPtr) { // set BC's VelBCHolder velBC(m_physBCPtr->viscousVelFuncBC()); bool isHomogeneous = false; m_velocityAMRPoissonOp.applyOp(a_lapVel, a_vel, a_crseVelPtr, isHomogeneous, velBC); // may need to extend lapVel to cover ghost cells as well { BCHolder viscBC = m_physBCPtr->viscousFuncBC(); const DisjointBoxLayout& grids = a_lapVel.getBoxes(); DataIterator dit = a_lapVel.dataIterator(); for (dit.reset(); dit.ok(); ++dit) { viscBC(a_lapVel[dit], grids[dit], m_problem_domain, m_dx, false); // not homogeneous } } // finally, do exchange a_lapVel.exchange(a_lapVel.interval()); }
// --------------------------------------------------------- void levelDivergenceMAC(LevelData<FArrayBox>& a_div, const LevelData<FluxBox>& a_uEdge, const Real a_dx) { // silly way to do this until i figure out a better // way to make this dimensionally-independent CH_assert (a_uEdge.nComp() >= a_div.nComp()); DataIterator dit = a_div.dataIterator(); for (dit.reset(); dit.ok(); ++dit) { a_div[dit()].setVal(0.0); const FluxBox& thisFluxBox = a_uEdge[dit()]; Box cellBox(thisFluxBox.box()); // just to be sure we don't accidentally trash memory... cellBox &= a_div[dit()].box(); // now loop over coordinate directions and add to divergence for (int dir=0; dir<SpaceDim; dir++) { const FArrayBox& uEdgeDir = thisFluxBox[dir]; FORT_DIVERGENCE(CHF_CONST_FRA(uEdgeDir), CHF_FRA(a_div[dit()]), CHF_BOX(cellBox), CHF_CONST_REAL(a_dx), CHF_INT(dir)); } } }
// --------------------------------------------------------- void AMRNavierStokes::computeLapScal(LevelData<FArrayBox>& a_lapScal, LevelData<FArrayBox>& a_scal, const BCHolder& a_physBC, const LevelData<FArrayBox>* a_crseScalPtr) { m_scalarsAMRPoissonOp.setBC(a_physBC); bool isHomogeneous = false; if (a_crseScalPtr != NULL) { m_scalarsAMRPoissonOp.AMROperatorNF(a_lapScal, a_scal, *a_crseScalPtr, isHomogeneous); } else { m_scalarsAMRPoissonOp.applyOpI(a_lapScal, a_scal, isHomogeneous); } BCHolder viscBC = m_physBCPtr->viscousFuncBC(); DataIterator dit = a_lapScal.dataIterator(); const DisjointBoxLayout& grids = a_lapScal.getBoxes(); for (dit.reset(); dit.ok(); ++dit) { viscBC(a_lapScal[dit], grids[dit], m_problem_domain, m_dx, false); // not homogeneous } // finally, do exchange a_lapScal.exchange(a_lapScal.interval()); }
// ----------------------------------------------------------------------------- // Semi-implicitly handles the gravity forcing and projection. // The old* inputs should be the values at t^n. // The new* inputs should be the updated values from the TGA solver. // ----------------------------------------------------------------------------- void AMRNavierStokes::doCCIGProjection (LevelData<FArrayBox>& a_newVel, LevelData<FArrayBox>& a_newB, const LevelData<FArrayBox>& a_oldVel, const LevelData<FArrayBox>& a_oldB, const LevelData<FluxBox>& a_advVel, const Real a_oldTime, const Real a_dt, const bool a_doProj) { CH_TIME("AMRNavierStokes::doCCIGProjection"); const Real halfTime = a_oldTime + 0.5 * a_dt; const Real newTime = a_oldTime + 1.0 * a_dt; const Real dummyTime = -1.0e300; const GeoSourceInterface& geoSource = *(m_levGeoPtr->getGeoSourcePtr()); const RealVect& dx = m_levGeoPtr->getDx(); const DisjointBoxLayout& grids = a_newVel.getBoxes(); DataIterator dit = grids.dataIterator(); // 1. Compute the background buoyancy, N, Dinv, etc... // Fill the FC background buoyancy field. LevelData<FluxBox> bbar(grids, 1, 2*IntVect::Unit); for (dit.reset(); dit.ok(); ++dit) { FluxBox& bbarFB = bbar[dit]; D_TERM(m_physBCPtr->setBackgroundScalar(bbarFB[0], 0, *m_levGeoPtr, dit(), dummyTime);, m_physBCPtr->setBackgroundScalar(bbarFB[1], 0, *m_levGeoPtr, dit(), dummyTime);,
// ---------------------------------------------------------------- void EdgeToCell(const LevelData<FluxBox>& a_edgeData, LevelData<FArrayBox>& a_cellData) { // this is just a wrapper around the single-grid version DataIterator dit = a_edgeData.dataIterator(); for (dit.reset(); dit.ok(); ++dit) { EdgeToCell(a_edgeData[dit()], a_cellData[dit()]); } }
// ------------------------------------------------------------- void Mask::buildMasks(LevelData<BaseFab<int> >& a_masks, const ProblemDomain& a_dProblem, const BoxLayout& a_grids, const BoxLayout* a_fineGridsPtr, int a_nRefFine) { // simply iterate over boxes and call single-basefab function DataIterator dit = a_masks.dataIterator(); for (dit.reset(); dit.ok(); ++dit) { buildMask(a_masks[dit()], a_dProblem, a_grids, a_fineGridsPtr, a_nRefFine); } }
// ---------------------------------------------------------- // this function is shamelessly based on the ANAG CoarseAverage // (cell-centered) version void CoarseAverageEdge::averageToCoarse(LevelData<FluxBox>& a_coarseData, const LevelData<FluxBox>& a_fineData) { CH_assert(isDefined()); DataIterator dit = a_fineData.dataIterator(); for (dit.reset(); dit.ok(); ++dit) { FluxBox& coarsenedFine = m_coarsenedFineData[dit()]; const FluxBox& fine = a_fineData[dit()]; // coarsen from the entire fine grid onto the entire coarse grid averageGridData(coarsenedFine, fine); } m_coarsenedFineData.copyTo(m_coarsenedFineData.interval(), a_coarseData, a_coarseData.interval()); }
// ----------------------------------------------------------------------------- // 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)); } }
// --------------------------------------------------------------- // 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; }
// 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 }
// // VCAMRPoissonOp2::reflux() // There are currently the new version (first) and the old version (second) // in this file. Brian asked to preserve the old version in this way for // now. - TJL (12/10/2007) // void VCAMRPoissonOp2::reflux(const LevelData<FArrayBox>& a_phiFine, const LevelData<FArrayBox>& a_phi, LevelData<FArrayBox>& a_residual, AMRLevelOp<LevelData<FArrayBox> >* a_finerOp) { CH_TIMERS("VCAMRPoissonOp2::reflux"); m_levfluxreg.setToZero(); Interval interv(0,a_phi.nComp()-1); CH_TIMER("VCAMRPoissonOp2::reflux::incrementCoarse", t2); CH_START(t2); DataIterator dit = a_phi.dataIterator(); for (dit.reset(); dit.ok(); ++dit) { const FArrayBox& coarfab = a_phi[dit]; const FluxBox& coarBCoef = (*m_bCoef)[dit]; const Box& gridBox = a_phi.getBoxes()[dit]; if (m_levfluxreg.hasCF(dit())) { for (int idir = 0; idir < SpaceDim; idir++) { FArrayBox coarflux; Box faceBox = surroundingNodes(gridBox, idir); getFlux(coarflux, coarfab, coarBCoef, faceBox, idir); Real scale = 1.0; m_levfluxreg.incrementCoarse(coarflux, scale,dit(), interv, interv, idir); } } } CH_STOP(t2); // const cast: OK because we're changing ghost cells only LevelData<FArrayBox>& phiFineRef = ( LevelData<FArrayBox>&)a_phiFine; VCAMRPoissonOp2* finerAMRPOp = (VCAMRPoissonOp2*) a_finerOp; QuadCFInterp& quadCFI = finerAMRPOp->m_interpWithCoarser; quadCFI.coarseFineInterp(phiFineRef, a_phi); // I'm pretty sure this is not necessary. bvs -- flux calculations use // outer ghost cells, but not inner ones // phiFineRef.exchange(a_phiFine.interval()); IntVect phiGhost = phiFineRef.ghostVect(); int ncomps = a_phiFine.nComp(); CH_TIMER("VCAMRPoissonOp2::reflux::incrementFine", t3); CH_START(t3); DataIterator ditf = a_phiFine.dataIterator(); const DisjointBoxLayout& dblFine = a_phiFine.disjointBoxLayout(); for (ditf.reset(); ditf.ok(); ++ditf) { const FArrayBox& phifFab = a_phiFine[ditf]; const FluxBox& fineBCoef = (*(finerAMRPOp->m_bCoef))[ditf]; const Box& gridbox = dblFine.get(ditf()); for (int idir = 0; idir < SpaceDim; idir++) { //int normalGhost = phiGhost[idir]; SideIterator sit; for (sit.begin(); sit.ok(); sit.next()) { if (m_levfluxreg.hasCF(ditf(), sit())) { Side::LoHiSide hiorlo = sit(); Box fluxBox = bdryBox(gridbox,idir,hiorlo,1); FArrayBox fineflux(fluxBox,ncomps); getFlux(fineflux, phifFab, fineBCoef, fluxBox, idir, m_refToFiner); Real scale = 1.0; m_levfluxreg.incrementFine(fineflux, scale, ditf(), interv, interv, idir, hiorlo); } } } } CH_STOP(t3); Real scale = 1.0/m_dx; m_levfluxreg.reflux(a_residual, scale); }
Real DotProduct(const BoxLayoutData<FArrayBox>& a_dataOne, const BoxLayoutData<FArrayBox>& a_dataTwo, const BoxLayout& a_dblIn, const Interval& a_comps) { Vector<Real> rhodot; rhodot.reserve(10); const int startcomp = a_comps.begin(); const int endcomp = a_comps.end(); //calculate the single-processor dot product DataIterator dit = a_dataOne.dataIterator(); for (dit.reset(); dit.ok(); ++dit) { Box fabbox = a_dblIn.get(dit()); const FArrayBox& onefab = a_dataOne[dit()]; const FArrayBox& twofab = a_dataTwo[dit()]; CH_assert(onefab.box().contains(fabbox)); CH_assert(twofab.box().contains(fabbox)); Real dotgrid = 0; FORT_DOTPRODUCT(CHF_REAL(dotgrid), CHF_CONST_FRA(onefab), CHF_CONST_FRA(twofab), CHF_BOX(fabbox), CHF_CONST_INT(startcomp), CHF_CONST_INT(endcomp)); rhodot.push_back(dotgrid); } // now for the multi-processor fandango //gather all the rhodots onto a vector and add them up int baseProc = 0; Vector<Vector<Real> >dotVec; gather(dotVec, rhodot, baseProc); Real rhodotTot = 0.0; if (procID() == baseProc) { CH_assert(dotVec.size() == numProc()); rhodot.resize(a_dblIn.size()); int index = 0; for (int p = 0; p < dotVec.size(); p++) { Vector<Real>& v = dotVec[p]; for (int i = 0; i < v.size(); i++, index++) { rhodot[index] = v[i]; } } rhodot.sort(); for (int ivec = 0; ivec < rhodot.size(); ivec++) { rhodotTot += rhodot[ivec]; } } //broadcast the sum to all processors. broadcast(rhodotTot, baseProc); //return the total return rhodotTot; }
void EBPoissonOp:: applyOp(LevelData<EBCellFAB>& a_opPhi, const LevelData<EBCellFAB>& a_phi, bool a_homogeneousPhysBC, DataIterator& dit, bool a_do_exchange) { CH_TIMERS("EBPoissonOp::applyOp"); CH_TIMER("regular_apply", t1); CH_TIMER("irregular_apply", t2); CH_TIMER("eb_bcs_apply", t3); CH_TIMER("dom_bcs_apply", t4); CH_TIMER("alpha_apply", t5); CH_assert(a_opPhi.ghostVect() == m_ghostCellsRHS); CH_assert(a_phi.ghostVect() == m_ghostCellsPhi); CH_assert(a_phi.nComp() == a_opPhi.nComp()); LevelData<EBCellFAB>& phi = const_cast<LevelData<EBCellFAB>&>(a_phi); if (a_do_exchange) { phi.exchange(phi.interval()); } int nComps = a_phi.nComp(); for (dit.reset(); dit.ok(); ++dit) { Box dblBox( m_eblg.getDBL().get(dit()) ); const EBCellFAB& phifab = phi[dit()]; Box curPhiBox = phifab.box(); const BaseFab<Real>& curPhiFAB = phifab.getSingleValuedFAB(); EBCellFAB& opphifab = a_opPhi[dit()]; BaseFab<Real>& curOpPhiFAB = opphifab.getSingleValuedFAB(); // Interval interv(0, nComps-1); CH_START(t5); if (m_alpha == 0) { opphifab.setVal(0.0); } else { opphifab.copy(phifab); opphifab.mult(m_alpha); } CH_STOP(t5); Box loBox[SpaceDim],hiBox[SpaceDim]; int hasLo[SpaceDim],hasHi[SpaceDim]; CH_START(t1); applyOpRegularAllDirs( loBox, hiBox, hasLo, hasHi, dblBox, curPhiBox, nComps, curOpPhiFAB, curPhiFAB, a_homogeneousPhysBC, dit(), m_beta); CH_STOP(t1); CH_START(t2); //apply stencil m_opEBStencil[dit()]->apply(opphifab, phifab, false); CH_STOP(t2); //apply inhom boundary conditions CH_START(t3); if (!a_homogeneousPhysBC) { const Real factor = m_dxScale*m_beta; m_ebBC->applyEBFlux(opphifab, phifab, m_vofItIrreg[dit()], (*m_eblg.getCFIVS()), dit(), m_origin, m_dx, factor, a_homogeneousPhysBC, m_time); } CH_STOP(t3); CH_START(t4); int comp = 0; for (int idir = 0; idir < SpaceDim; idir++) { for (m_vofItIrregDomLo[idir][dit()].reset(); m_vofItIrregDomLo[idir][dit()].ok(); ++m_vofItIrregDomLo[idir][dit()]) { Real flux; const VolIndex& vof = m_vofItIrregDomLo[idir][dit()](); m_domainBC->getFaceFlux(flux,vof,comp,a_phi[dit()], m_origin,m_dx,idir,Side::Lo, dit(), m_time, a_homogeneousPhysBC); opphifab(vof,comp) -= flux * m_beta*m_invDx[idir]; } for (m_vofItIrregDomHi[idir][dit()].reset(); m_vofItIrregDomHi[idir][dit()].ok(); ++m_vofItIrregDomHi[idir][dit()]) { Real flux; const VolIndex& vof = m_vofItIrregDomHi[idir][dit()](); m_domainBC->getFaceFlux(flux,vof,comp,a_phi[dit()], m_origin,m_dx,idir,Side::Hi,dit(), m_time, a_homogeneousPhysBC); opphifab(vof,comp) += flux * m_beta*m_invDx[idir]; } } CH_STOP(t4); } }
// --------------------------------------------------------- void AMRNavierStokes::computeVorticity(LevelData<FArrayBox>& a_vorticity) const { // this breaks the "const"-ness of the function, // but is necessary to ensure that boundary // conditions are properly set. LevelData<FArrayBox>& vel = *(const_cast<LevelData<FArrayBox>*>(m_vel_new_ptr)); const DisjointBoxLayout& grids = vel.getBoxes(); if (m_level > 0) { // do quadratic C/F BC's // for now, assume that BC's are with new velocity // (may need to be changed for fine-level regridding) LevelData<FArrayBox>& crseVel = crseNSPtr()->newVel(); const DisjointBoxLayout& crseGrids = crseVel.getBoxes(); int nRefCrse = crseNSPtr()->refRatio(); QuadCFInterp interpolator(grids, &crseGrids, m_dx, nRefCrse, SpaceDim, m_problem_domain); interpolator.coarseFineInterp(vel, crseVel); } Interval velComps(0,SpaceDim-1); vel.exchange(velComps); DataIterator dit = vel.dataIterator(); // at the moment, do extrap at physical boundaries // (same effect as one-sided differencing) BCHolder vortVelBC = m_physBCPtr->extrapFuncBC(1); for (dit.reset(); dit.ok(); ++dit) { // apply physical BC's vortVelBC(vel[dit], grids[dit], m_problem_domain, m_dx, true); // homogeneous if (SpaceDim == 3) { for (int dir=0; dir<SpaceDim; dir++) { // and then compute vorticity FORT_COMPUTEVORT(CHF_FRA1(a_vorticity[dit],dir), CHF_CONST_FRA(vel[dit]), CHF_BOX(grids[dit]), CHF_CONST_REAL(m_dx), CHF_CONST_INT(dir)); } } else if (SpaceDim == 2) { int dir = 2; FORT_COMPUTEVORT(CHF_FRA1(a_vorticity[dit],0), CHF_CONST_FRA(vel[dit]), CHF_BOX(grids[dit]), CHF_CONST_REAL(m_dx), CHF_CONST_INT(dir)); } // end dimensionality choice } // end loop over grids }
// ----------------------------------------------------------------------------- // 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; } }
int fluxRegTest() { #ifdef CH_USE_HDF5 writeLevel(NULL); #endif int retflag = 0; int nref; Vector<Box> fineboxes; Vector<Box> coarboxes; Box domf, domc; //set coarse and fine grid boxes setDefaults(nref, coarboxes, fineboxes, domc, domf); { // first do nonperiodic test Interval interv(0,0); //set up coarse and fine grids DisjointBoxLayout dblFineCell,dblCoarCell; Vector<int> procAssignCoar(coarboxes.size(), 0); Vector<int> procAssignFine(fineboxes.size(), 0); LoadBalance(procAssignCoar, coarboxes); LoadBalance(procAssignFine, fineboxes); dblCoarCell.define(coarboxes, procAssignCoar); dblFineCell.define(fineboxes, procAssignFine); dblCoarCell.close(); dblFineCell.close(); LevelData<FArrayBox> coarData(dblCoarCell, 1); LevelData<FArrayBox> fineData(dblFineCell, 1); DataIterator coarIt = coarData.dataIterator(); DataIterator fineIt = fineData.dataIterator(); LevelFluxRegister fluxReg(dblFineCell, dblCoarCell, domf, nref, 1); //set data and flux registers to zero for (coarIt.reset(); coarIt.ok(); ++coarIt) coarData[coarIt()].setVal(0.); fluxReg.setToZero(); //increment and decrement //flux registers with equal size fluxes Real scale = 1.0; Real fluxVal = 4.77; for (coarIt.reset(); coarIt.ok(); ++coarIt) { const Box& cellBoxCoar = dblCoarCell.get(coarIt()); for (int idir = 0; idir < SpaceDim; idir++) { Box edgeBoxCoar = surroundingNodes(cellBoxCoar, idir); FArrayBox edgeFlux(edgeBoxCoar,1); edgeFlux.setVal(fluxVal); DataIndex dataIndGlo = coarIt(); fluxReg.incrementCoarse(edgeFlux, scale, dataIndGlo, interv, interv, idir); } } for (fineIt.reset(); fineIt.ok(); ++fineIt) { const Box& cellBoxFine = dblFineCell.get(fineIt()); for (int idir = 0; idir < SpaceDim; idir++) { Box edgeBoxFine = surroundingNodes(cellBoxFine, idir); FArrayBox edgeFlux(edgeBoxFine,1); edgeFlux.setVal(fluxVal); SideIterator sit; DataIndex dataIndGlo = fineIt(); for (sit.reset(); sit.ok(); ++sit) { fluxReg.incrementFine(edgeFlux, scale, dataIndGlo, interv, interv, idir, sit()); } } } //reflux what ought to be zero into zero and the result should be zero fluxReg.reflux(coarData, scale); DataIterator datIt = coarData.dataIterator(); for (datIt.reset(); datIt.ok(); ++datIt) { const FArrayBox& data = coarData[datIt()]; Real rmax = Abs(data.max()); Real rmin = Abs(data.min()); if ((rmax > 1.0e-10)||(rmin > 1.0e-10)) { pout() << indent << pgmname << ": fluxRegister failed the nonperiodic conservation test = " << endl; retflag = 1; } } } // end non-periodic test // now do the same thing all over again, this time with a periodic domain { ProblemDomain coarseDomain(domc); ProblemDomain fineDomain(domf); for (int dir=0; dir<SpaceDim; dir++) { coarseDomain.setPeriodic(dir, true); fineDomain.setPeriodic(dir, true); } Interval interv(0,0); //set up coarse and fine grids DisjointBoxLayout dblFineCell,dblCoarCell; Vector<int> procAssignCoar(coarboxes.size(), 0); Vector<int> procAssignFine(fineboxes.size(), 0); LoadBalance(procAssignCoar, coarboxes); LoadBalance(procAssignFine, fineboxes); dblCoarCell.define(coarboxes, procAssignCoar, coarseDomain); dblFineCell.define(fineboxes, procAssignFine, fineDomain); dblCoarCell.close(); dblFineCell.close(); LevelData<FArrayBox> coarData(dblCoarCell, 1); LevelData<FArrayBox> fineData(dblFineCell, 1); DataIterator coarIt = coarData.dataIterator(); DataIterator fineIt = fineData.dataIterator(); LevelFluxRegister fluxReg(dblFineCell, dblCoarCell, fineDomain, nref, 1); //set data and flux registers to zero for (coarIt.reset(); coarIt.ok(); ++coarIt) coarData[coarIt()].setVal(0.); fluxReg.setToZero(); //increment and decrement //flux registers with equal size fluxes Real scale = 1.0; Real fluxVal = 4.77; for (coarIt.reset(); coarIt.ok(); ++coarIt) { const Box& cellBoxCoar = dblCoarCell.get(coarIt()); for (int idir = 0; idir < SpaceDim; idir++) { Box edgeBoxCoar = surroundingNodes(cellBoxCoar, idir); FArrayBox edgeFlux(edgeBoxCoar,1); edgeFlux.setVal(fluxVal); DataIndex dataIndGlo = coarIt(); fluxReg.incrementCoarse(edgeFlux, scale, dataIndGlo, interv, interv, idir); } } for (fineIt.reset(); fineIt.ok(); ++fineIt) { const Box& cellBoxFine = dblFineCell.get(fineIt()); for (int idir = 0; idir < SpaceDim; idir++) { Box edgeBoxFine = surroundingNodes(cellBoxFine, idir); FArrayBox edgeFlux(edgeBoxFine,1); edgeFlux.setVal(fluxVal); SideIterator sit; DataIndex dataIndGlo = fineIt(); for (sit.reset(); sit.ok(); ++sit) { fluxReg.incrementFine(edgeFlux, scale, dataIndGlo, interv, interv, idir, sit()); } } } //reflux what ought to be zero into zero and the result should be zero fluxReg.reflux(coarData, scale); DataIterator datIt = coarData.dataIterator(); for (datIt.reset(); datIt.ok(); ++datIt) { const FArrayBox& data = coarData[datIt()]; Real rmax = Abs(data.max()); Real rmin = Abs(data.min()); if ((rmax > 1.0e-10)||(rmin > 1.0e-10)) { pout() << indent << pgmname << ": fluxRegister failed the periodic conservation test " << endl; retflag += 2; } } } // end periodic test return retflag; }
void VCAMRPoissonOp2::reflux(const LevelData<FArrayBox>& a_phiFine, const LevelData<FArrayBox>& a_phi, LevelData<FArrayBox>& a_residual, AMRLevelOp<LevelData<FArrayBox> >* a_finerOp) { CH_TIME("VCAMRPoissonOp2::reflux"); int ncomp = 1; ProblemDomain fineDomain = refine(m_domain, m_refToFiner); LevelFluxRegister levfluxreg(a_phiFine.disjointBoxLayout(), a_phi.disjointBoxLayout(), fineDomain, m_refToFiner, ncomp); levfluxreg.setToZero(); Interval interv(0,a_phi.nComp()-1); DataIterator dit = a_phi.dataIterator(); for (dit.reset(); dit.ok(); ++dit) { const FArrayBox& coarfab = a_phi[dit]; const FluxBox& coarBCoef = (*m_bCoef)[dit]; const Box& gridBox = a_phi.getBoxes()[dit]; for (int idir = 0; idir < SpaceDim; idir++) { FArrayBox coarflux; Box faceBox = surroundingNodes(gridBox, idir); getFlux(coarflux, coarfab, coarBCoef , faceBox, idir); Real scale = 1.0; levfluxreg.incrementCoarse(coarflux, scale,dit(), interv,interv,idir); } } LevelData<FArrayBox>& p = ( LevelData<FArrayBox>&)a_phiFine; // has to be its own object because the finer operator // owns an interpolator and we have no way of getting to it VCAMRPoissonOp2* finerAMRPOp = (VCAMRPoissonOp2*) a_finerOp; QuadCFInterp& quadCFI = finerAMRPOp->m_interpWithCoarser; quadCFI.coarseFineInterp(p, a_phi); // p.exchange(a_phiFine.interval()); // BVS is pretty sure this is not necesary. IntVect phiGhost = p.ghostVect(); DataIterator ditf = a_phiFine.dataIterator(); const DisjointBoxLayout& dblFine = a_phiFine.disjointBoxLayout(); for (ditf.reset(); ditf.ok(); ++ditf) { const FArrayBox& phifFab = a_phiFine[ditf]; const FluxBox& fineBCoef = (*(finerAMRPOp->m_bCoef))[ditf]; const Box& gridbox = dblFine.get(ditf()); for (int idir = 0; idir < SpaceDim; idir++) { int normalGhost = phiGhost[idir]; SideIterator sit; for (sit.begin(); sit.ok(); sit.next()) { Side::LoHiSide hiorlo = sit(); Box fabbox; Box facebox; // assumption here that the stencil required // to compute the flux in the normal direction // is 2* the number of ghost cells for phi // (which is a reasonable assumption, and probably // better than just assuming you need one cell on // either side of the interface // (dfm 8-4-06) if (sit() == Side::Lo) { fabbox = adjCellLo(gridbox,idir, 2*normalGhost); fabbox.shift(idir, 1); facebox = bdryLo(gridbox, idir,1); } else { fabbox = adjCellHi(gridbox,idir, 2*normalGhost); fabbox.shift(idir, -1); facebox = bdryHi(gridbox, idir, 1); } // just in case we need ghost cells in the transverse direction // (dfm 8-4-06) for (int otherDir=0; otherDir<SpaceDim; ++otherDir) { if (otherDir != idir) { fabbox.grow(otherDir, phiGhost[otherDir]); } } CH_assert(!fabbox.isEmpty()); FArrayBox phifab(fabbox, a_phi.nComp()); phifab.copy(phifFab); FArrayBox fineflux; getFlux(fineflux, phifab, fineBCoef, facebox, idir, m_refToFiner); Real scale = 1.0; levfluxreg.incrementFine(fineflux, scale, ditf(), interv, interv, idir, hiorlo); } } } Real scale = 1.0/m_dx; levfluxreg.reflux(a_residual, scale); }
int fluxRegTest() { int nref = 2; int eekflag = 0; ParmParse pp; Box domainCoar, domainFine; eekflag = makeGeometry(domainFine); if (eekflag != 0) return eekflag; domainCoar = coarsen(domainFine, nref); DisjointBoxLayout dblFine,dblCoar; eekflag = makeLayouts(dblCoar, dblFine, domainCoar, domainFine); Interval interv(0,0); EBISLayout ebislFine, ebislCoar; int nghost = 3; makeEBISL(ebislFine, dblFine, domainFine, nghost); makeEBISL(ebislCoar, dblCoar, domainCoar, nghost); EBCellFactory factFine(ebislFine); EBCellFactory factCoar(ebislCoar); IntVect ivghost = IntVect::Unit; LevelData<EBCellFAB> fineData(dblFine, 1,ivghost, factFine); LevelData<EBCellFAB> coarData(dblCoar, 1,ivghost, factCoar); LevelData<EBCellFAB> extraDense(dblCoar, 1,ivghost, factCoar); //set data and flux registers to zero for (DataIterator coarIt = coarData.dataIterator(); coarIt.ok(); ++coarIt) coarData[coarIt()].setVal(0.); for (DataIterator fineIt = fineData.dataIterator(); fineIt.ok(); ++fineIt) fineData[fineIt()].setVal(0.); { // pout() << "before constructor" << endl; EBFluxRegister fluxReg(dblFine, dblCoar, ebislFine, ebislCoar, domainCoar, nref, 1, Chombo_EBIS::instance()); // pout() << "after constructor" << endl; fluxReg.setToZero(); // pout() << "after settozero" << endl; //loop through directions Real scale = 1.0; Real fluxVal = 4.77; for (int idir = 0; idir < SpaceDim; idir++) { // pout() << "idir = " << idir << endl; // MPI_Barrier(Chombo_MPI::comm); //increment and decrement //flux registers with equal size fluxes for (DataIterator coarIt = coarData.dataIterator(); coarIt.ok(); ++coarIt) { const Box& boxCoar = dblCoar.get(coarIt()); const EBISBox& ebisBox = ebislCoar[coarIt()]; IntVectSet ivsBC(boxCoar); EBFaceFAB edgeFluxReg(ebisBox, boxCoar, idir, 1); BaseIFFAB<Real> edgeFluxIrr(ivsBC, ebisBox.getEBGraph(), idir, 1); edgeFluxReg.setVal(fluxVal); edgeFluxIrr.setVal(fluxVal); fluxReg.incrementCoarseRegular(edgeFluxReg, scale, coarIt(), interv, idir); // pout() << "after increment coar regular"<< endl; fluxReg.incrementCoarseIrregular(edgeFluxIrr, scale, coarIt(), interv, idir); // pout() << "after increment coar irregular"<< endl; } // pout() << "after increment coar"<< endl; // MPI_Barrier(Chombo_MPI::comm); for (DataIterator fineIt = fineData.dataIterator(); fineIt.ok(); ++fineIt) { const Box& boxFine = dblFine.get(fineIt()); const EBISBox& ebisBox = ebislFine[fineIt()]; IntVectSet ivsBF(boxFine); EBFaceFAB edgeFluxReg(ebisBox, boxFine, idir, 1); BaseIFFAB<Real> edgeFluxIrr(ivsBF, ebisBox.getEBGraph(), idir, 1); edgeFluxReg.setVal(fluxVal); edgeFluxIrr.setVal(fluxVal); for (SideIterator sit; sit.ok(); ++sit) { fluxReg.incrementFineRegular(edgeFluxReg, scale, fineIt(), interv, idir, sit()); fluxReg.incrementFineIrregular(edgeFluxIrr, scale, fineIt(), interv, idir, sit()); } } // pout() << "after increment fine"<< endl; // MPI_Barrier(Chombo_MPI::comm); } //reflux what ought to be zero into zero and the result should be zero //except where the coarse-fine boundary gets crossed by the embedded //boundary. That should get fixed by the extramass thing. fluxReg.reflux(coarData, interv, scale); // pout() << "after reflux"<< endl; for (DataIterator coarIt = coarData.dataIterator(); coarIt.ok(); ++coarIt) extraDense[coarIt()].setVal(0.); // now add extra density to soltuion //in the end the solution should return to zero fluxReg.incrementDensityArray(extraDense, interv, scale); } // pout() << "after fluxreg destruction" << endl; // pout() << "after incementDensityArray"<< endl; for (DataIterator coarIt = coarData.dataIterator(); coarIt.ok(); ++coarIt) coarData[coarIt()] += extraDense[coarIt()]; // MPI_Barrier(Chombo_MPI::comm); // pout() << "after += operation "<< endl; DataIterator datIt = coarData.dataIterator(); for (datIt.reset(); datIt.ok(); ++datIt) { const EBCellFAB& data = coarData[datIt()]; IntVectSet ivsBox(dblCoar.get(datIt())); const EBISBox& ebisBox = ebislCoar[datIt()]; Real rmax = 0.; Real rmin = 0.; for (VoFIterator vofit(ivsBox, ebisBox.getEBGraph()); vofit.ok(); ++vofit) { const VolIndex& vof = vofit(); rmax = Max(rmax, Abs(data(vof, 0))); rmin = Min(rmax, Abs(data(vof, 0))); #ifdef CH_USE_FLOAT Real tolerance = 1.0e-6; #else Real tolerance = 1.0e-10; #endif if ((rmax > tolerance)||(rmin > tolerance)) { pout() << "EBFluxRegister failed the test at " << " vof = " << vof << endl; pout() << " rmax: " << rmax << ", or" << " rmin: " << rmin << " >" << " tolerance: " << tolerance << ")" << endl; eekflag = 42; return eekflag; } } } // pout() << "about to return "<< endl; return eekflag; }
int main(int argc, char* argv[]) { #ifdef CH_MPI MPI_Init(&argc, &argv); // setChomboMPIErrorHandler(); MPI_Barrier(Chombo_MPI::comm); // Barrier #1 #endif // ------------------------------------------------ // parse command line and input file // ------------------------------------------------ // infile must be first if (argc < 2) { cerr << " need inputs file" << endl; abort(); } char* in_file = argv[1]; ParmParse pp(argc-2, argv+2, NULL, in_file); #ifdef CH_MPI MPI_Barrier(Chombo_MPI::comm); #endif pout().setf(ios::scientific); pout().precision(4); // set defaults bool isSameSize = false; bool doGhostCells = false; bool doPlots = true; bool isTimeDep = false; bool verbose = false; bool computeRelativeError = false; bool removeMean = false; bool useUnitDomain = false; bool HOaverage = false; // this is the initial value for the error Real bogusValue = 0.0; string exactRoot, computedRoot, errorRoot; Vector<string> errorVars; int numCrseFinish, numCrseStart, crseStep, crseMult, intFieldSize; init(exactRoot, computedRoot, errorRoot, intFieldSize, numCrseStart, errorVars, numCrseFinish, crseStep, crseMult, doPlots, isTimeDep, isSameSize, bogusValue, computeRelativeError, removeMean, doGhostCells, useUnitDomain, HOaverage,verbose); int nStep, exactStep; if (!isTimeDep) { crseStep = 1; numCrseFinish = numCrseStart; } for (nStep = numCrseStart; nStep <= numCrseFinish; nStep += crseStep) { if (verbose) { pout() << "starting step " << nStep << endl; } exactStep = nStep*crseMult; ostrstream exactFile; ostrstream computedFile; ostrstream errorFile; exactFile.fill('0'); computedFile.fill('0'); errorFile.fill('0'); if (isTimeDep) { constructPlotFileName(exactFile, exactRoot, intFieldSize, exactStep); constructPlotFileName(computedFile, computedRoot, intFieldSize, nStep); constructPlotFileName(errorFile, errorRoot, intFieldSize, nStep); } else { // if not time dependent, file roots are really filenames exactFile << exactRoot << ends; computedFile << computedRoot << ends; errorFile << errorRoot << ends; } pout() << "exact Filename = " << exactFile.str() << endl; pout() << "computed Filename = " << computedFile.str() << endl; if (doPlots) { pout() << "error Filename = " << errorFile.str() << endl; } // declare memory Vector<LevelData<FArrayBox>* > exactSoln; Vector<string> exactVars; // exact solution variable names Vector<DisjointBoxLayout> exactGrids; Box exactDomain; Real exactDx, exactDt, exactTime; Vector<int> exactRefRatio; int exactNumLevels; IntVect ghostVect = IntVect::Unit; string exactFileName(exactFile.str()); // get exact solution if (verbose) { pout() << "read exact solution..." << endl; } ReadAMRHierarchyHDF5(exactFileName, exactGrids, exactSoln, exactVars, exactDomain, exactDx, exactDt, exactTime, exactRefRatio, exactNumLevels); if (verbose) { pout () << "done reading exact soln" << endl; } // we assume that exact soln is single-grid if we're doing averaging if (!isSameSize) { CH_assert(exactNumLevels == 1); } Vector<LevelData<FArrayBox>* > computedSoln; Vector<string> computedVars; // computed soln variable names Vector<DisjointBoxLayout> computedGrids; Box computedDomain; Real computedDx, computedDt, computedTime; Vector<int> computedRefRatio; int computedNumLevels; string computedFileName(computedFile.str()); //ghostVect = IntVect::Zero; // now read in computed solution if (verbose) { pout() << "read computed solution..." << endl; } ReadAMRHierarchyHDF5(computedFileName, computedGrids, computedSoln, computedVars, computedDomain, computedDx, computedDt, computedTime, computedRefRatio, computedNumLevels); if (verbose) { pout() << "done reading computed solution" << endl; } // reality check if ((computedDomain != exactDomain) && isSameSize) { MayDay::Error("Incompatible exact and computed domains for sameSize comparison"); } int numExact = exactVars.size(); int numComputed = computedVars.size(); int numError = errorVars.size(); // If no errorVars were specified if (numError == 0) { // Set errorVars to the intersection of exactVars and computedVars // This numVars^2 method should be changed to something more efficient for (int iExact = 0; iExact < numExact; iExact++) { for (int iComp = 0; iComp < numComputed; iComp++) { if (exactVars[iExact] == computedVars[iComp]) { errorVars.push_back(exactVars[iExact]); break; } } } numError = errorVars.size(); } else { // if errorVars were specified, then do a quick check that // they're present in both exactVars and computedVars for (int errVarNo = 0; errVarNo<errorVars.size(); ++errVarNo) { bool foundComputed = false; for (int i=0; i<numComputed; i++) { if (errorVars[errVarNo] == computedVars[i]) { foundComputed = true; } } // end loop over exact variables if (!foundComputed) { pout() << "errorVar " << errorVars[errVarNo] << " not found in computed solution!" << endl; MayDay::Error(); } bool foundExact = false; for (int i=0; i<numExact; i++) { if (errorVars[errVarNo] == exactVars[i]) { foundExact = true; } } // end loop over exact variables if (!foundExact) { pout() << "errorVar " << errorVars[errVarNo] << " not found in exact solution!" << endl; MayDay::Error(); } } // end loop over errorVars } // end if errorVars was specified in the inputs file Vector<string> errorNames; errorNames.resize(numError); constructErrorNames(errorNames, errorVars); Vector<LevelData<FArrayBox>* > error(computedNumLevels); // allocate error -- same domain as computed solution for (int level = 0; level < computedNumLevels; level++) { error[level] = new LevelData<FArrayBox>(computedGrids[level], numError, ghostVect); } if (!isSameSize) { if (verbose) { pout () << "compute AMR error..." << endl; } computeAMRError(error, errorVars, computedSoln, computedVars, computedGrids, computedDx, computedRefRatio, exactSoln, exactVars, exactDx, bogusValue, HOaverage, computeRelativeError); if (verbose) { pout() << "done computing AMR error" << endl; } } else { // first make sure refRatios are the same for (int lev = 0; lev < computedRefRatio.size() - 1; lev++) { CH_assert(computedRefRatio[lev] == exactRefRatio[lev]); } CH_assert(exactDx == computedDx); if (verbose) { pout () << "compute sameSize error..." << endl; } computeSameSizeError(error, errorVars, computedSoln, computedVars, computedGrids, computedDx, computedRefRatio, exactSoln, exactVars, bogusValue, computeRelativeError, doGhostCells); if (verbose) { pout() << "done computing sameSize error" << endl; } } Vector<Real> mean(numError); // remove mean if (removeMean) { int lBase = 0; int numLevels = error.size(); for (int err = 0; err < numError; err++) { Interval errComps(err, err); if (verbose) { pout() << "compute mean for component " << err << endl; } Real volume; mean[err] = computeSum(volume, error, computedRefRatio, computedDx, errComps, lBase); mean[err] /= volume; if (verbose) { pout() << "comp = " << err << ", mean = " << mean << ", vol = " << volume << endl; } for (int level = 0; level < numLevels; level++) { LevelData<FArrayBox>& thisLevelError = *error[level]; const DisjointBoxLayout levelGrids = error[level]->getBoxes(); DataIterator dit = levelGrids.dataIterator(); for (dit.reset(); dit.ok(); ++dit) { const Box thisBox = levelGrids[dit()]; FArrayBox& thisFabError = thisLevelError[dit()]; thisFabError.plus(-mean[err],err); } // end loop over errors thisLevelError.exchange(); } // end loop over levels } // end loop over errors } // now compute norms pout() << "error, step " << nStep << ": L1, L2, Max, sum" << endl; for (int err = 0; err < numError; err++) { Interval errComps(err, err); Real L0, L1, L2, sum; if (verbose) { pout() << "compute error for component " << err << endl; } int lBase = 0; int normType = 0; Real normDx = computedDx; if (useUnitDomain) { normDx = 1.0/computedDomain.size(0); } L0 = computeNorm(error, computedRefRatio, normDx, errComps, normType, lBase); normType = 1; L1 = computeNorm(error, computedRefRatio, normDx, errComps, normType, lBase); normType = 2; L2 = computeNorm(error, computedRefRatio, normDx, errComps, normType, lBase); sum = computeSum(error, computedRefRatio, normDx, errComps, lBase); pout() << errorNames[err] << ": " << L1 << ", " << L2 << ", " << L0 << ", " << sum; if (removeMean) { pout() << " (" << mean[err] << ")"; } pout() << endl; } // end loop over errors if (doPlots) { if (verbose) { pout() << "begin writing hdf5 file..." << endl; } WriteAMRHierarchyHDF5(errorFile.str(), computedGrids, error, errorNames, computedDomain, computedDx, computedDt, computedTime, computedRefRatio, computedNumLevels); if (verbose) { pout() << "done writing hdf5 file" << endl; } } // clean up memory for (int level = 0; level < exactNumLevels; level++) { if (exactSoln[level] != NULL) { delete exactSoln[level]; exactSoln[level] = NULL; } } for (int level = 0; level < computedNumLevels; level++) { if (computedSoln[level] != NULL) { delete computedSoln[level]; computedSoln[level] = NULL; } if (error[level] != NULL) { delete error[level]; error[level] = NULL; } } } // end loop over timesteps #ifdef CH_MPI dumpmemoryatexit(); MPI_Finalize(); #endif } // end main
// --------------------------------------------------------------- void AMRNavierStokes::computeAdvectionVelocities(LevelData<FluxBox>& a_advVel) { if (s_verbosity >= 3) { pout() << "AMRNavierStokes::computeAdvectionVelocities: " << m_level << endl; } bool isViscous = (s_nu > 0.0); const DisjointBoxLayout& levelGrids = newVel().getBoxes(); /// need to build grown grids to get be able to do all of /// tracing properly IntVect advect_grow(D_DECL(ADVECT_GROW, ADVECT_GROW, ADVECT_GROW)); LevelData<FArrayBox> old_vel(levelGrids, SpaceDim, advect_grow); LevelData<FArrayBox> viscousSource(levelGrids, SpaceDim, advect_grow); LevelData<FArrayBox>* crseVelPtr = NULL; if (s_set_bogus_values) { setValLevel(old_vel, s_bogus_value); setValLevel(viscousSource, s_bogus_value); } // m_time contains the time at which the new state is centered Real old_time = m_time - m_dt; fillVelocity(old_vel, old_time); // set physical boundary conditions here // set physical boundary conditions on velocity if (isViscous) { LevelData<FArrayBox> viscousVel(levelGrids, SpaceDim, advect_grow); DataIterator dit = viscousVel.dataIterator(); // rather than resetting BC's on old_vel, and then setting them // back, just copy old_vel to a temporary holder, and set // BCs on that one. for (dit.begin(); dit.ok(); ++dit) { viscousVel[dit].copy(old_vel[dit]); } VelBCHolder velBC(m_physBCPtr->viscousVelFuncBC()); velBC.applyBCs(viscousVel, levelGrids, m_problem_domain, m_dx, false); // inhomogeneous // if crse level exists, fill coarse velocity BC if (m_level > 0) { const DisjointBoxLayout& crseGrids = crseNSPtr()->newVel().getBoxes(); crseVelPtr = new LevelData<FArrayBox>(crseGrids, SpaceDim); crseNSPtr()->fillVelocity(*crseVelPtr, old_time); } computeLapVel(viscousSource, viscousVel, crseVelPtr); for (dit.reset(); dit.ok(); ++dit) { viscousSource[dit].mult(s_nu); } } else { setValLevel(viscousSource, 0.0); } // tracing will use inviscid BC's { VelBCHolder velBC(m_physBCPtr->tracingVelFuncBC()); velBC.applyBCs(old_vel, levelGrids, m_problem_domain, m_dx, false); // inhomogeneous } // call utility function to do tracing traceAdvectionVel(a_advVel, old_vel, viscousSource, m_patchGodVelocity, old_time, m_dt); EdgeVelBCHolder edgeVelBC(m_physBCPtr->advectionVelFuncBC(isViscous)); edgeVelBC.applyBCs(a_advVel, levelGrids, m_problem_domain, m_dx, false); // inhomogeneous // noel levelMacProject is big guy // now MAC project m_projection.levelMacProject(a_advVel, old_time, m_dt); // finally, add volume discrepancy correction if (m_projection.etaLambda() > 0 && s_applyFreestreamCorrection) { LevelData<FluxBox>& grad_e_Lambda = m_projection.grad_eLambda(); DataIterator dit = levelGrids.dataIterator(); for (dit.reset(); dit.ok(); ++dit) { FluxBox& thisGrad_eLambda = grad_e_Lambda[dit]; FluxBox& thisAdvVel = a_advVel[dit]; for (int dir=0; dir<SpaceDim; dir++) { thisAdvVel[dir] += thisGrad_eLambda[dir]; } } } edgeVelBC.applyBCs(a_advVel, levelGrids, m_problem_domain, m_dx, false); // inhomogeneous // clean up storage if (crseVelPtr != NULL) { delete crseVelPtr; crseVelPtr = NULL; } }
// 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; } }