void EBPoissonOp:: getOpVoFStencil(VoFStencil& a_stencil, const int& a_idir, const Vector<VolIndex>& a_allMonotoneVoFs, const EBISBox& a_ebisbox, const VolIndex& a_VoF, const bool& a_lowOrder) { for (SideIterator sit; sit.ok(); ++sit) { Side::LoHiSide side = sit(); Vector<FaceIndex> faces; faces = a_ebisbox.getFaces(a_VoF,a_idir,side); for (int iface = 0; iface < faces.size(); iface++) { FaceIndex face = faces[iface]; VoFStencil faceStencil; getOpFaceStencil(faceStencil,a_allMonotoneVoFs,a_ebisbox,a_VoF, a_idir,side,face,a_lowOrder); a_stencil += faceStencil; } } }
// ----------------------------------------------------------------------------- // Interpolate ghosts at CF interface using zeros on coarser grids. // ----------------------------------------------------------------------------- void homogeneousCFInterp (LevelData<FArrayBox>& a_phif, const RealVect& a_fineDx, const RealVect& a_crseDx, const CFRegion& a_cfRegion, const IntVect& a_applyDirs) { CH_TIME("homogeneousCFInterp (full level)"); // Loop over grids, directions, and sides and call the worker function. DataIterator dit = a_phif.dataIterator(); for (dit.begin(); dit.ok(); ++dit) { if (a_phif[dit].box().isEmpty()) continue; for (int dir = 0; dir < SpaceDim; ++dir) { if (a_applyDirs[dir] == 0) continue; SideIterator sit; for (sit.begin(); sit.ok(); sit.next()) { homogeneousCFInterp(a_phif, dit(), dir, sit(), a_fineDx[dir], a_crseDx[dir], a_cfRegion); } } } }
void CompGridVTOBC::operator()( FArrayBox& a_state, const Box& a_valid, const ProblemDomain& a_domain, Real a_dx, bool a_homogeneous) { const Box& domainBox = a_domain.domainBox(); for (int idir = 0; idir < SpaceDim; idir++) { if (!a_domain.isPeriodic(idir)) { for (SideIterator sit; sit.ok(); ++sit) { Side::LoHiSide side = sit(); if (a_valid.sideEnd(side)[idir] == domainBox.sideEnd(side)[idir]) { // Dirichlet BC int isign = sign(side); Box toRegion = adjCellBox(a_valid, idir, side, 1); // include corner cells if possible by growing toRegion in transverse direction toRegion.grow(1); toRegion.grow(idir, -1); toRegion &= a_state.box(); for (BoxIterator bit(toRegion); bit.ok(); ++bit) { IntVect ivTo = bit(); IntVect ivClose = ivTo - isign*BASISV(idir); for (int ighost=0;ighost<m_nGhosts[0];ighost++,ivTo += isign*BASISV(idir)) { //for (int icomp = 0; icomp < a_state.nComp(); icomp++) a_state(ivTo, icomp) = 0.0; IntVect ivFrom = ivClose; // hardwire to linear BCs for now for (int icomp = 0; icomp < a_state.nComp() ; icomp++) { if (m_bcDiri[idir][side][icomp]) { a_state(ivTo, icomp) = (-1.0)*a_state(ivFrom, icomp); } else { a_state(ivTo, icomp) = (1.0)*a_state(ivFrom, icomp); } } } } // end loop over cells } // if ends match } // end loop over sides } // if not periodic in this direction } // end loop over directions }
void NodeNeumBC(NodeFArrayBox& a_state, const Box& a_valid, Real a_dx, bool a_homogeneous, BCValueHolder a_value) { for (int idir = 0; idir < SpaceDim; idir++) { for (SideIterator sit; sit.ok(); ++sit) { NodeNeumBC(a_state, a_valid, a_dx, a_homogeneous, a_value, idir,sit()); } } }
void EBCompositeMACProjector:: correctVelocityComponent(Vector<LayoutData< Vector< BaseIVFAB<Real> * > >* > & a_coveredVelLo, Vector<LayoutData< Vector< BaseIVFAB<Real> * > >* > & a_coveredVelHi, const Vector< LayoutData< Vector< Vector<VolIndex> > >* >& a_coveredFaceLo, const Vector< LayoutData< Vector< Vector<VolIndex> > >* >& a_coveredFaceHi, const Vector< LayoutData< Vector< IntVectSet > >* > & a_coveredSetsLo, const Vector< LayoutData< Vector< IntVectSet > >* > & a_coveredSetsHi, const Vector<LevelData<EBFluxFAB>* > & a_macGradient, int a_coveredFaceDir, int a_velComp) { CH_TIME("EBCompositeMACProjector::correctVelocityComponent"); for (int ilev = 0; ilev < m_numLevels; ilev++) { for (SideIterator sit; sit.ok(); ++sit) { LayoutData<Vector<BaseIVFAB<Real>* > >* velPtr = NULL; const LayoutData<Vector<Vector<VolIndex> > >* facePtr = NULL; const LayoutData<Vector<IntVectSet> >* setsPtr = NULL; if (sit() == Side::Lo) { velPtr = a_coveredVelLo[ilev]; facePtr = a_coveredFaceLo[ilev]; setsPtr = a_coveredSetsLo[ilev]; } else { velPtr = a_coveredVelHi[ilev]; facePtr = a_coveredFaceHi[ilev]; setsPtr = a_coveredSetsHi[ilev]; } const LevelData<EBFluxFAB>& macGradient = *a_macGradient[ilev]; for (DataIterator dit = m_eblg[ilev].getDBL().dataIterator(); dit.ok(); ++dit) { const EBFluxFAB & macGradFAB = macGradient[dit()]; const Vector<VolIndex>& coveredFace = (*facePtr)[dit()][a_coveredFaceDir]; const IntVectSet & coveredSets = (*setsPtr)[dit()][a_coveredFaceDir]; BaseIVFAB<Real> & coveredVel = *((*velPtr)[dit()][a_coveredFaceDir]); const EBISBox& ebisBox = m_eblg[ilev].getEBISL()[dit()]; correctVelocityComponent(coveredVel, coveredFace, coveredSets, macGradFAB, ebisBox, a_coveredFaceDir, sit(), a_velComp); } } } }
void LevelFluxRegisterEdge::incrementFine( FArrayBox& a_fineFlux, Real a_scale, const DataIndex& a_fineDataIndex, const Interval& a_srcInterval, const Interval& a_dstInterval) { CH_assert(isDefined()); CH_assert(!a_fineFlux.box().isEmpty()); CH_assert(a_srcInterval.size() == a_dstInterval.size()); CH_assert(a_srcInterval.begin() >= 0); CH_assert(a_srcInterval.end() < a_fineFlux.nComp()); CH_assert(a_dstInterval.begin() >= 0); CH_assert(a_dstInterval.end() < m_nComp); int edgeDir = -1; for (int sideDir = 0; sideDir<SpaceDim; sideDir++) { if (a_fineFlux.box().type(sideDir) == IndexType::CELL) { edgeDir = sideDir; } } CH_assert(edgeDir >= 0); CH_assert(edgeDir < SpaceDim); for (int faceDir=0; faceDir<SpaceDim; faceDir++) { if (faceDir != edgeDir) { SideIterator sit; for (sit.begin(); sit.ok(); ++sit) { incrementFine(a_fineFlux, a_scale, a_fineDataIndex, a_srcInterval, a_dstInterval, faceDir, sit()); } } } }
void setBorkedFlux(EBFluxFAB& a_flux, const EBISBox& a_ebisBox, const Box& a_box, const RealVect& a_fluxVal, const BaseFab<int>& a_map) { for (int idir = 0; idir < SpaceDim; idir++) { Real bogval = 0; //the bogus value will be zero so it will not //do to have the correct value be zero if (Abs(a_fluxVal[idir]) < 1.0e-3) bogval = 1.0; a_flux[idir].setVal(a_fluxVal[idir]); //if i am in a 1d box and the box next to me //is 2d, set the border flux to for (SideIterator sit; sit.ok(); ++sit) { Box borderBox; if (sit() == Side::Lo) { borderBox = adjCellLo(a_box, idir, -1); } else { borderBox = adjCellHi(a_box, idir, -1); } for (BoxIterator bit(borderBox); bit.ok(); ++bit) { const IntVect& thisIV = bit(); IntVect thatIV = thisIV + sign(sit())*BASISV(idir); if ((a_map(thisIV, 0) == 1) && (a_map(thatIV, 0) == 2)) { Vector<FaceIndex> faces = a_ebisBox.getAllFaces(thisIV, idir, sit()); for (int iface = 0; iface < faces.size(); iface++) { a_flux[idir](faces[iface],0) = bogval; } } } } } }
void EBFluxRegister:: incrementCoarseIrregular(const BaseIFFAB<Real>& a_coarFlux, const Real& a_scale, const DataIndex& a_coarDatInd, const Interval& a_variables, const int& a_dir) { if (m_hasEBCF) { EBFaceFAB facefab; bool hasCells = copyBIFFToEBFF(facefab, a_coarFlux, m_eblgCoar.getDBL()[a_coarDatInd], m_eblgCoar.getEBISL()[a_coarDatInd]); if (hasCells) { for (SideIterator sit; sit.ok(); ++sit) { incrementCoarIrreg(facefab, a_scale, a_coarDatInd, a_variables, a_dir, sit()); } } } }
void LevelFluxRegisterEdge::setToZero() { for (DataIterator dit = m_regCoarse.dataIterator(); dit.ok(); ++dit) m_regCoarse[dit()].setVal(0.0); SideIterator side; for (int idir=0 ; idir<SpaceDim; ++idir) { for (side.begin(); side.ok(); ++side) { LevelData<FluxBox>& fineReg = m_fabFine[index(idir, side())]; for (DataIterator dit = fineReg.dataIterator(); dit.ok(); ++dit) fineReg[dit()].setVal(0.0); } } }
Real divergence(const EBFluxFAB& a_func, const RealVect& a_bndryFlux, const EBISBox& a_ebisBox, const VolIndex& a_vof, const Real& a_dx) { Real retval = 0; Real bndryArea = a_ebisBox.bndryArea(a_vof); RealVect normal = a_ebisBox.normal(a_vof); for (int idir = 0; idir < SpaceDim; idir++) { Real bndryFlux = a_bndryFlux[idir]; //normal already dealt with Real bndryContrib = -bndryFlux*bndryArea*normal[idir]; Real openContrib = 0; if (bndryArea > 1.0e-3) { openContrib = 0; } for (SideIterator sit; sit.ok(); ++sit) { int isign = sign(sit()); Real rsign = isign; Vector<FaceIndex> faces = a_ebisBox.getFaces(a_vof, idir, sit()); for (int iface = 0; iface < faces.size(); ++iface) { Real areaFrac = a_ebisBox.areaFrac(faces[iface]); Real faceFlux = a_func[idir](faces[iface], 0); openContrib += rsign*faceFlux*areaFrac; } } retval += openContrib + bndryContrib; } retval /= a_dx; return retval; }
void kappaDivergence(EBCellFAB& a_divF, const EBFluxFAB& a_flux, const EBISBox& a_ebisBox, const Box& a_box, const Real& a_dx) { //set the divergence initially to zero //then loop through directions and increment the divergence //with each directions flux difference. a_divF.setVal(0.0); BaseFab<Real>& regDivF = a_divF.getSingleValuedFAB(); regDivF.setVal(0.); for (int idir = 0; idir < SpaceDim; idir++) { //update for the regular vofs in the nonconservative //case works for all single valued vofs. /* do the regular vofs */ /**/ const EBFaceFAB& fluxDir = a_flux[idir]; const BaseFab<Real>& regFluxDir = fluxDir.getSingleValuedFAB(); int ncons = 1; FORT_DIVERGEF( CHF_BOX(a_box), CHF_FRA(regDivF), CHF_CONST_FRA(regFluxDir), CHF_CONST_INT(idir), CHF_CONST_INT(ncons), CHF_CONST_REAL(a_dx)); /**/ } //update the irregular vofs using conservative diff IntVectSet ivsIrreg = a_ebisBox.getIrregIVS(a_box); for (VoFIterator vofit(ivsIrreg, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit) { const VolIndex& vof = vofit(); //divergence was set in regular update. we reset it // to zero and recalc. Real update = 0.; for ( int idir = 0; idir < SpaceDim; idir++) { const EBFaceFAB& fluxDir = a_flux[idir]; for (SideIterator sit; sit.ok(); ++sit) { int isign = sign(sit()); Vector<FaceIndex> faces = a_ebisBox.getFaces(vof, idir, sit()); for (int iface = 0; iface < faces.size(); iface++) { const FaceIndex& face = faces[iface]; Real areaFrac = a_ebisBox.areaFrac(face); Real faceFlux =fluxDir(face, 0); update += isign*areaFrac*faceFlux; } } } //add EB boundary condtions in divergence const IntVect& iv = vof.gridIndex(); Real bndryArea = a_ebisBox.bndryArea(vof); RealVect bndryCent = a_ebisBox.bndryCentroid(vof); RealVect normal = a_ebisBox.normal(vof); RealVect bndryLoc; RealVect exactF; for (int idir = 0; idir < SpaceDim; idir++) { bndryLoc[idir] = a_dx*(iv[idir] + 0.5 + bndryCent[idir]); } for (int idir = 0; idir < SpaceDim; idir++) { exactF[idir] = exactFlux(bndryLoc, idir); } Real bndryFlux = PolyGeom::dot(exactF, normal); update -= bndryFlux*bndryArea; update /= a_dx; //note NOT divided by volfrac a_divF(vof, 0) = update; } }
// 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 EBLevelTGA:: setSourceGhostCells(LevelData<EBCellFAB>& a_src, const DisjointBoxLayout& a_grids, int a_lev) { int ncomp = a_src.nComp(); for (DataIterator dit = a_grids.dataIterator(); dit.ok(); ++dit) { const Box& grid = a_grids.get(dit()); const Box& srcBox = a_src[dit()].box(); for (int idir = 0; idir < SpaceDim; idir++) { for (SideIterator sit; sit.ok(); ++sit) { int iside = sign(sit()); Box bc_box = adjCellBox(grid, idir, sit(), 1); for (int jdir = 0; jdir < SpaceDim; jdir++) { //want corners too if (jdir != idir) { bc_box.grow(jdir, 1); } } //if fails might not have a ghost cell. bc_box &= m_eblg[a_lev].getDomain().domainBox(); CH_assert(srcBox.contains(bc_box)); if (grid.size(idir) >= 4) { FORT_HORESGHOSTBC(CHF_FRA(a_src[dit()].getSingleValuedFAB()), CHF_BOX(bc_box), CHF_CONST_INT(idir), CHF_CONST_INT(iside), CHF_CONST_INT(ncomp)); } else { // valid region not wide enough to apply HOExtrap -- drop // to linear extrap FORT_RESGHOSTBC(CHF_FRA(a_src[dit()].getSingleValuedFAB()), CHF_BOX(bc_box), CHF_CONST_INT(idir), CHF_CONST_INT(iside), CHF_CONST_INT(ncomp)); } IntVectSet ivs = m_eblg[a_lev].getEBISL()[dit()].getIrregIVS(bc_box); for (VoFIterator vofit(ivs, m_eblg[a_lev].getEBISL()[dit()].getEBGraph()); vofit.ok(); ++vofit) { for (int icomp = 0; icomp < ncomp; icomp++) { Real valNeigh = 0; Vector<FaceIndex> faces = m_eblg[a_lev].getEBISL()[dit()].getFaces(vofit(), idir, flip(sit())); for (int iface = 0; iface < faces.size(); iface++) { VolIndex vofNeigh = faces[iface].getVoF(flip(sit())); valNeigh += a_src[dit()](vofNeigh, icomp); } if (faces.size() > 1) valNeigh /= faces.size(); a_src[dit()](vofit(), icomp) = valNeigh; } } } } } }
void EBCompositeMACProjector:: kappaDivergence(Vector<LevelData<EBCellFAB>* >& a_divu, Vector<LevelData<EBFluxFAB>* >& a_velo, const Vector<LevelData<BaseIVFAB<Real> >* >* a_boundaryVelo) { CH_TIME("EBCompositeMACProjector::kappaDivergence"); for (int ilev = 0; ilev < m_numLevels; ilev++) { EBLevelMACProjector::setCurLevel(ilev); EBFluxFactory fluxfact(m_eblg[ilev].getEBISL()); //need one ghost cell so that exchange is meaningful LevelData<EBFluxFAB> centroidVelocity(m_eblg[ilev].getDBL(), 1, IntVect::Unit, fluxfact); Interval interv(0, 0); LevelData<EBFluxFAB>& velExch = (LevelData<EBFluxFAB>&)(*a_velo[ilev]); velExch.exchange(interv); //interpolate velocity to face centroids EBArith::interpolateFluxToCentroids(centroidVelocity, *a_velo[ilev], m_eblg[ilev].getDBL(), m_eblg[ilev].getEBISL(), m_eblg[ilev].getDomain()); centroidVelocity.exchange(interv); LevelData<BaseIVFAB<Real> >* levelBoundaryVel = NULL; if (a_boundaryVelo != NULL) { levelBoundaryVel = (*a_boundaryVelo)[ilev]; } //compute the divergence igoring other levels macKappaDivergence(*a_divu[ilev], centroidVelocity, m_eblg[ilev].getDBL(), m_eblg[ilev].getEBISL(), m_eblg[ilev].getDomain(), m_dx[ilev], levelBoundaryVel); //use flux registers to correct divergence //at coarse-fine interface with velocity from finer //level if (ilev < (m_numLevels-1)) { Real incrScale = 1.0; m_fluxReg[ilev]->setToZero(); //increment with coarse values for (DataIterator dit = m_eblg[ilev].getDBL().dataIterator();dit.ok(); ++dit) { const EBFluxFAB& veloFlux = (*a_velo[ilev])[dit()]; for (int idir = 0; idir < SpaceDim; idir++) { // This assumes that embedded boundaries and coarse-fine boundaries do not cross. // To remove this assumption use incrementCoarseBoth. m_fluxReg[ilev]->incrementCoarseRegular(veloFlux[idir], incrScale, dit(), interv, idir); } } //increment with fine velocities for (DataIterator dit = m_eblg[ilev+1].getDBL().dataIterator();dit.ok(); ++dit) { const EBFluxFAB& veloFlux = (*a_velo[ilev+1])[dit()]; for (int idir = 0; idir < SpaceDim; idir++) { for (SideIterator sit; sit.ok(); ++sit) { // This assumes that embedded boundaries and coarse-fine boundaries do not cross. // To remove this assumption use incrementFineBoth. m_fluxReg[ilev]->incrementFineRegular(veloFlux[idir], incrScale, dit(), interv, idir, sit()); } } } //reflux Real reflScale = 1.0/m_dx[ilev][0]; m_fluxReg[ilev]->reflux(*a_divu[ilev], interv, reflScale); } } }
void EBFluxRegister:: incrementRedistRegister(EBCoarToCoarRedist& a_register, const Interval& a_variables, const Real& a_scale) { if (m_hasEBCF) { LevelData<BaseIVFAB<Real> >& registerMass = a_register.m_regsCoar; LayoutData<IntVectSet>& registerSets = a_register.m_setsCoar; //reflux into an empty LevelData<EBCellFAB> //Multiply this by (kappa)(1-kappa) //add result into register mass EBCellFactory ebcfCoar(m_eblgCoar.getEBISL()); LevelData<EBCellFAB> increment(m_eblgCoar.getDBL(), m_nComp, m_saveCoar.ghostVect(), ebcfCoar); EBLevelDataOps::clone (increment, m_saveCoar); EBLevelDataOps::setVal(increment, 0.0); reflux(increment, a_variables, a_scale, true); for (DataIterator dit = m_eblgCoar.getDBL().dataIterator(); dit.ok(); ++dit) { for (int idir = 0; idir < SpaceDim; idir++) { for (SideIterator sit; sit.ok(); ++sit) { int iindex = index(idir, sit()); Vector<IntVectSet> setsCoar = (m_setsCoar[iindex])[dit()]; for (int iset = 0; iset < setsCoar.size(); iset++) { const IntVectSet& setCoa = registerSets[dit()]; const IntVectSet& setReg = setsCoar[iset]; IntVectSet set = setCoa; set &= setReg; const EBISBox& ebisBox =m_eblgCoar.getEBISL()[dit()]; for (VoFIterator vofit(set, ebisBox.getEBGraph()); vofit.ok(); ++vofit) { const VolIndex& vof = vofit(); int ibleck = 0; if ((vof.gridIndex() == ivdebugfr) && EBFastFR::s_verbose) { ibleck = 1; pout() << setprecision(10) << setiosflags(ios::showpoint) << setiosflags(ios::scientific); pout() << "incrcotoco:" << endl; } for (int icomp = a_variables.begin(); icomp <= a_variables.end(); icomp++) { Real extraMass = increment[dit()](vofit(), icomp); Real oldMass = registerMass[dit()](vofit(), icomp); Real newMass = oldMass + extraMass; Real diff = extraMass; if (ibleck == 1) { pout() << "( " << oldMass << ", " << newMass << ", " << diff << ")"; } registerMass[dit()](vofit(), icomp) += extraMass; //set increment to zero in case it gets //hit twice (more than one direction or //whatever increment[dit()](vof, icomp) = 0; } //loop over comps if (ibleck == 1) { ibleck = 0; pout() << endl; } }//loop over vofs in the set }//loop over sets in this coarse box } //loop over sides } //loop over directions } //dataiterator loop } //You are using Bonetti's defense against me, uh? } //I thought it fitting, considering the rocky terrain.
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 EBFluxRegister:: incrementRedistRegister(EBCoarToFineRedist& a_register, const Interval& a_variables, const Real& a_scale) { if (m_hasEBCF) { LevelData<BaseIVFAB<Real> >& registerMass = a_register.m_regsCoar; LayoutData<IntVectSet>& registerSets = a_register.m_setsCoar; //reflux into an empty LevelData<EBCellFAB> //Multiply this by (kappa)(1-kappa) //add result into register mass EBCellFactory ebcfCoar(m_eblgCoar.getEBISL()); LevelData<EBCellFAB> increment(m_eblgCoar.getDBL(), m_nComp, m_saveCoar.ghostVect(), ebcfCoar); EBLevelDataOps::clone(increment, m_saveCoar); EBLevelDataOps::setVal(increment, 0.0); reflux(increment, a_variables, a_scale, true); for (DataIterator dit = m_eblgCoar.getDBL().dataIterator(); dit.ok(); ++dit) { for (int idir = 0; idir < SpaceDim; idir++) { for (SideIterator sit; sit.ok(); ++sit) { int iindex = index(idir, sit()); Vector<IntVectSet> setsCoar = (m_setsCoar[iindex])[dit()]; for (int iset = 0; iset < setsCoar.size(); iset++) { const IntVectSet& setCoa = registerSets[dit()]; const IntVectSet& setReg = setsCoar[iset]; IntVectSet set = setCoa; set &= setReg; const EBISBox& ebisBox =m_eblgCoar.getEBISL()[dit()]; for (VoFIterator vofit(set, ebisBox.getEBGraph()); vofit.ok(); ++vofit) { const VolIndex vof = vofit(); int ibleck = 0; if ((vof.gridIndex() == ivdebugfr) && EBFastFR::s_verbose) { ibleck = 1; pout() << setprecision(10) << setiosflags(ios::showpoint) << setiosflags(ios::scientific); pout() << "incrcotofi:" << endl; } for (int icomp = a_variables.begin(); icomp <= a_variables.end(); icomp++) { Real extraMass = increment[dit()](vofit(), icomp); if ((ibleck == 1) && icomp == 0) { //incrredist Real soluOld = registerMass[dit()](vof, icomp); Real soluNew = soluOld + extraMass; Real fluxDif = -extraMass; pout() << "(" << extraMass << ", " << soluOld << ", " << soluNew << ", " << fluxDif << ") " ; } registerMass[dit()](vof, icomp) += extraMass; //set increment to zero in case it gets //hit twice (more than one direction or //whatever increment[dit()](vof, icomp) = 0; } if (ibleck == 1) { pout() << endl; ibleck = 0; } } } } } } } }
// new define void LevelFluxRegisterEdge::define( const DisjointBoxLayout& a_dbl, const DisjointBoxLayout& a_dblCoarse, const ProblemDomain& a_dProblem, int a_nRefine, int a_nComp) { m_isDefined = true; CH_assert(a_nRefine > 0); CH_assert(a_nComp > 0); CH_assert(!a_dProblem.isEmpty()); m_nComp = a_nComp; m_nRefine = a_nRefine; m_domainCoarse = coarsen(a_dProblem, a_nRefine); CH_assert (a_dblCoarse.checkPeriodic(m_domainCoarse)); // allocate copiers m_crseCopiers.resize(SpaceDim*2); SideIterator side; // create a Vector<Box> of the fine boxes which also includes periodic images, // since we don't really care about the processor layouts, etc Vector<Box> periodicFineBoxes; CFStencil::buildPeriodicVector(periodicFineBoxes, a_dProblem, a_dbl); // now coarsen these boxes... for (int i=0; i<periodicFineBoxes.size(); i++) { periodicFineBoxes[i].coarsen(m_nRefine); } for (int idir=0 ; idir<SpaceDim; ++idir) { for (side.begin(); side.ok(); ++side) { // step one, build fineBoxes, flux register boxes // indexed by the fine level but in the coarse index // space DisjointBoxLayout fineBoxes,tmp; // first create coarsened dbl, then compute flux register boxes // adjacent to coarsened fine boxes coarsen(tmp, a_dbl, m_nRefine); if (side() == Side::Lo) { adjCellLo(fineBoxes, tmp, idir,1); } else { adjCellHi(fineBoxes, tmp, idir,1); } // now define the FluxBoxes of fabFine on this DisjointBoxLayout m_fabFine[index(idir, side())].define(fineBoxes, a_nComp); LayoutData<Vector<Vector<IntVectSet> > >& ivsetsVect = m_refluxLocations[index(idir, side())]; ivsetsVect.define(a_dblCoarse); LayoutData<Vector<DataIndex> >& mapsV = m_coarToCoarMap[index(idir, side())]; mapsV.define(a_dblCoarse); DisjointBoxLayout coarseBoxes = a_dblCoarse; DataIterator dit = a_dblCoarse.dataIterator(); for (dit.begin(); dit.ok(); ++dit) { unsigned int thisproc = a_dblCoarse.procID(dit()); if (thisproc == procID()) { ivsetsVect[DataIndex(dit())].resize(SpaceDim); } const Box& coarseBox = a_dblCoarse[dit()]; int count = 0; for (int i=0; i<periodicFineBoxes.size(); i++) { Box regBox; if (side() == Side::Lo) { regBox = adjCellLo(periodicFineBoxes[i], idir, 1); } else { regBox = adjCellHi(periodicFineBoxes[i], idir, 1); } // do this little dance in order to ensure that // we catch corner cells which might be in different // boxes. Box testBox(regBox); testBox.grow(1); testBox.grow(idir,-1); if (testBox.intersectsNotEmpty(coarseBox)) { testBox &= coarseBox; ++count; unsigned int proc = a_dblCoarse.procID(dit()); const DataIndex index = DataIndex(dit()); if (proc == procID()) { mapsV[DataIndex(dit())].push_back(index); // loop over face directions here for (int faceDir=0; faceDir<SpaceDim; faceDir++) { // do nothing in normal direction if (faceDir != idir) { // this should give us the face indices for the // faceDir-centered faces adjacent to the coarse-fine // interface which are contained in the current // coarse box Box intersectBox(regBox); Box coarseEdgeBox(coarseBox); coarseEdgeBox.surroundingNodes(faceDir); intersectBox.surroundingNodes(faceDir); intersectBox &= coarseEdgeBox; intersectBox.shiftHalf(faceDir,1); IntVectSet localIV(intersectBox); ivsetsVect[DataIndex(dit())][faceDir].push_back(localIV); } } } } } // end loop over boxes on coarse level } m_regCoarse.define(coarseBoxes, a_nComp, IntVect::Unit); // last thing to do is to define copiers m_crseCopiers[index(idir, side())].define(fineBoxes, coarseBoxes, IntVect::Unit); } } }
void EBLevelTransport:: doRegularUpdate(LevelData<EBCellFAB>& a_divF, LevelData<EBCellFAB>& a_cons, const LevelData<EBCellFAB>& a_normalVel, const LevelData<EBFluxFAB>& a_advVel, const LayoutData< Vector <BaseIVFAB<Real> * > >& a_coveredAdvVelMinu, const LayoutData< Vector <BaseIVFAB<Real> * > >& a_coveredAdvVelPlus, EBFluxRegister& a_fineFluxRegister, EBFluxRegister& a_coarFluxRegister, const LevelData<EBCellFAB>& a_source, Real a_time, Real a_dt) { bool verbose = false; int ibox = 0; Interval consInterv(0, m_nCons-1); Interval fluxInterv(0, m_nFlux-1); for (DataIterator dit = m_thisGrids.dataIterator(); dit.ok(); ++dit, ibox++) { const Box& cellBox = m_thisGrids.get(dit()); const EBISBox& ebisBox = m_thisEBISL[dit()]; if(!ebisBox.isAllCovered()) { const IntVectSet& cfivs = m_cfIVS[dit()]; EBCellFAB& consState = a_cons[dit()]; m_ebPatchGodunov->setValidBox(cellBox, ebisBox, cfivs, a_time, a_dt); //begin debug //int here = 0; //if(cellBox.contains(EBPatchGodunov::s_debugIV) && (EBPatchGodunov::s_whichLev==1)) // { // here = 1; // } //end debug const EBCellFAB& source = a_source[dit()]; const EBCellFAB& normalVel = a_normalVel[dit()]; const EBFluxFAB& advVel = a_advVel[dit()]; const Vector<BaseIVFAB <Real>* >& coveredAdvVelMinu = a_coveredAdvVelMinu[dit()]; const Vector<BaseIVFAB <Real>* >& coveredAdvVelPlus = a_coveredAdvVelPlus[dit()]; m_ebPatchGodunov->setVelocities(normalVel, advVel, coveredAdvVelMinu, coveredAdvVelPlus); EBFluxFAB flux(ebisBox, cellBox, m_nFlux); BaseIVFAB<Real>& nonConsDiv = m_nonConsDivergence[dit()]; BaseIVFAB<Real>& ebIrregFlux = m_ebIrregFaceFlux[dit()]; flux.setVal(7.89); ebIrregFlux.setVal(7.89); const IntVectSet& ivsIrreg = m_irregSetsSmall[dit()]; const EBCellFAB& flatteningFAB = m_flattening[dit()]; BaseIVFAB<Real> coveredPrimMinu[SpaceDim]; BaseIVFAB<Real> coveredPrimPlus[SpaceDim]; Vector<VolIndex> coveredFaceMinu[SpaceDim]; Vector<VolIndex> coveredFacePlus[SpaceDim]; EBFluxFAB facePrim; EBCellFAB& divFFAB = a_divF[dit()]; // EBPatchTransport& patchTrans = (EBPatchTransport&) (*m_ebPatchGodunov); EBPatchGodunov::setCurComp(0); EBPatchGodunov::setDoingVel(0); EBPatchGodunov::setDoingAdvVel(0); m_ebPatchGodunov->primitivesAndDivergences(divFFAB, consState, facePrim, coveredPrimMinu, coveredPrimPlus, coveredFaceMinu, coveredFacePlus, flux, ebIrregFlux, nonConsDiv,flatteningFAB, source, cellBox, ivsIrreg, dit(),verbose); //do fluxregister cha-cha /* Coarse flux register is flux register with the coarse level. Fine flux register is the flux register with the fine level. To the finer level FR, this level is the coarse level. To the coarser level FR, this level is the fine level. */ for(int idir = 0; idir < SpaceDim; idir++) { Real scale = a_dt; EBFaceFAB fluxRegFlux; if(m_hasFiner) { a_fineFluxRegister.incrementCoarseRegular(flux[idir], scale,dit(), consInterv, idir); } if(m_hasCoarser) { for(SideIterator sit; sit.ok(); ++sit) { a_coarFluxRegister.incrementFineRegular(flux[idir],scale, dit(), consInterv, idir,sit()); } } } //copy fluxes into sparse interpolant for(int faceDir = 0; faceDir < SpaceDim; faceDir++) { IntVectSet ivsIrregGrown = m_irregSetsGrown[faceDir][dit()]; ivsIrregGrown &= cellBox; FaceStop::WhichFaces stopCrit = FaceStop::SurroundingWithBoundary; BaseIFFAB<Real>& interpol = m_fluxInterpolants[faceDir][dit()]; interpol.setVal(7.7777e7); EBFaceFAB& fluxDir = flux[faceDir]; for(FaceIterator faceit(ivsIrregGrown, ebisBox.getEBGraph(), faceDir, stopCrit); faceit.ok(); ++faceit) { for(int ivar = 0; ivar < m_nFlux; ivar++) { interpol(faceit(), ivar) = fluxDir(faceit(), ivar); } } } } } for(int faceDir = 0; faceDir < SpaceDim; faceDir++) { m_fluxInterpolants[faceDir].exchange(fluxInterv); } }
void EBLevelTransport:: doIrregularUpdate(LevelData<EBCellFAB>& a_divergeF, LevelData<EBCellFAB>& a_cons, EBFluxRegister& a_fineFluxRegister, EBFluxRegister& a_coarFluxRegister, LevelData<BaseIVFAB<Real> >& a_massDiff, Real a_time, Real a_dt) { //now do the irregular update int ibox = 0; Interval consInterv(0, m_nCons-1); Interval fluxInterv(0, m_nFlux-1); for (DataIterator dit = m_thisGrids.dataIterator(); dit.ok(); ++dit, ibox++) { const Box& cellBox = m_thisGrids.get(dit()); const EBISBox& ebisBox = m_thisEBISL[dit()]; if(!ebisBox.isAllCovered()) { const IntVectSet& cfivs = m_cfIVS[dit()]; EBCellFAB& consState = a_cons[dit()]; BaseIVFAB<Real>& redMass = a_massDiff[dit()]; m_ebPatchGodunov->setValidBox(cellBox, ebisBox, cfivs, a_time, a_dt); //begin debug //int here = 0; //if(cellBox.contains(EBPatchGodunov::s_debugIV) && (EBPatchGodunov::s_whichLev==1)) // { // here = 1; // } //end debug BaseIFFAB<Real> centroidFlux[SpaceDim]; const BaseIFFAB<Real>* interpolantGrid[SpaceDim]; const IntVectSet& ivsIrregSmall = m_irregSetsSmall[dit()]; for(int idir = 0; idir < SpaceDim; idir++) { const BaseIFFAB<Real>& interpol = m_fluxInterpolants[idir][dit()]; interpolantGrid[idir] = &interpol; BaseIFFAB<Real>& fluxDir= centroidFlux[idir]; fluxDir.define(ivsIrregSmall, ebisBox.getEBGraph(), idir, m_nFlux); } m_ebPatchGodunov->interpolateFluxToCentroids(centroidFlux, interpolantGrid, ivsIrregSmall); //update the state and interpolate the flux const BaseIVFAB<Real>& nonConsDiv = m_nonConsDivergence[dit()]; const BaseIVFAB<Real>& ebIrregFlux = m_ebIrregFaceFlux[dit()]; m_ebPatchGodunov->hybridDivergence(a_divergeF[dit()], consState, redMass, centroidFlux, ebIrregFlux, nonConsDiv, cellBox, ivsIrregSmall); //do fluxregister mambo /* Coarse flux register is flux register with the coarse level. Fine flux register is the flux register with the fine level. To the finer level FR, this level is the coarse level. To the coarser level FR, this level is the fine level. */ for(int idir = 0; idir < SpaceDim; idir++) { Real scale = a_dt; BaseIFFAB<Real> fluxRegFlux; if(m_hasFiner) { a_fineFluxRegister.incrementCoarseIrregular(centroidFlux[idir], scale,dit(), consInterv, idir); } if(m_hasCoarser) { for(SideIterator sit; sit.ok(); ++sit) { a_coarFluxRegister.incrementFineIrregular(centroidFlux[idir], scale, dit(), consInterv, idir,sit()); } } } } }// end of loop over grids. }
void LevelFluxRegisterEdge::refluxCurl(LevelData<FluxBox>& a_uCoarse, Real a_scale) { CH_assert(isDefined()); CH_assert(a_uCoarse.nComp() == m_nComp); SideIterator side; // idir is the normal direction to the coarse-fine interface for (int idir=0 ; idir<SpaceDim; ++idir) { for (side.begin(); side.ok(); ++side) { LevelData<FluxBox>& fineReg = m_fabFine[index(idir, side())]; // first, create temp LevelData<FluxBox> to hold "coarse flux" const DisjointBoxLayout coarseBoxes = m_regCoarse.getBoxes(); // this fills the place of what used to be m_fabCoarse in the old // implementation LevelData<FluxBox> coarReg(coarseBoxes, m_nComp, IntVect::Unit); // now fill the coarReg with the curl of the stored coarse-level // edge-centered flux DataIterator crseDit = coarseBoxes.dataIterator(); for (crseDit.begin(); crseDit.ok(); ++crseDit) { FluxBox& thisCoarReg = coarReg[crseDit]; thisCoarReg.setVal(0.0); EdgeDataBox& thisEdgeData = m_regCoarse[crseDit]; for (int edgeDir=0; edgeDir<SpaceDim; edgeDir++) { if (idir != edgeDir) { FArrayBox& crseEdgeDataDir = thisEdgeData[edgeDir]; for (int faceDir = 0; faceDir<SpaceDim; faceDir++) { if (faceDir != edgeDir) { FArrayBox& faceData = thisCoarReg[faceDir]; int shiftDir = -1; for (int i=0; i<SpaceDim; i++) { if ((i != faceDir) && (i != edgeDir) ) { shiftDir = i; } } CH_assert(shiftDir >= 0); crseEdgeDataDir.shiftHalf(shiftDir, sign(side())); // scaling already taken care of in incrementCrse Real scale = 1.0; faceData.plus(crseEdgeDataDir, scale, 0, 0, faceData.nComp()); crseEdgeDataDir.shiftHalf(shiftDir, -sign(side())); } // end if not normal direction } // end loop over face directions } // end if edgeDir != idir } // end loop over edge directions } // end loop over crse boxes // first, we need to create a temp LevelData<FluxBox> // to make a local copy in the coarse layout space of // the fine register increments LevelData<FluxBox> fineRegLocal(coarReg.getBoxes(), m_nComp, IntVect::Unit); fineReg.copyTo(fineReg.interval(), fineRegLocal, fineRegLocal.interval(), m_crseCopiers[index(idir,side())]); for (DataIterator it = a_uCoarse.dataIterator(); it.ok(); ++it) { // loop over flux components here for (int fluxComp=0; fluxComp < SpaceDim; fluxComp++) { // we don't do anything in the normal direction if (fluxComp != idir) { // fluxDir is the direction of the face-centered flux FArrayBox& U = a_uCoarse[it()][fluxComp]; // set up IntVectSet to avoid double counting of updates Box coarseGridBox = U.box(); // transfer to Cell-centered, then create IVS coarseGridBox.shiftHalf(fluxComp,1); IntVectSet nonUpdatedEdges(coarseGridBox); // remember, we want to take the curl here // also recall that fluxComp is the component // of the face-centered curl (not the edge-centered // vector field that we're refluxing, which is why // the sign may seem like it's the opposite of what // you might expect! Real local_scale = -sign(side())*a_scale; //int testDir = (fluxComp+1)%(SpaceDim); if (((fluxComp+1)%(SpaceDim)) == idir) local_scale *= -1; Vector<IntVectSet>& ivsV = m_refluxLocations[index(idir, side())][it()][fluxComp]; Vector<DataIndex>& indexV = m_coarToCoarMap[index(idir, side())][it()]; IVSIterator iv; for (int i=0; i<ivsV.size(); ++i) { iv.define(ivsV[i]); const FArrayBox& coar = coarReg[indexV[i]][fluxComp]; const FArrayBox& fine = fineRegLocal[indexV[i]][fluxComp]; for (iv.begin(); iv.ok(); ++iv) { IntVect thisIV = iv(); if (nonUpdatedEdges.contains(thisIV)) { for (int comp=0; comp <m_nComp; ++comp) { //Real coarVal = coar(thisIV, comp); //Real fineVal = fine(thisIV, comp); U(thisIV, comp) -= local_scale*(coar(thisIV, comp) +fine(thisIV, comp)); } nonUpdatedEdges -= thisIV; } } } } // end if not normal face } // end loop over fluxbox directions } // end loop over coarse boxes } // end loop over sides } // end loop over directions }
void ConstBCFunction::operator()(FArrayBox& a_state, const Box& a_valid, const ProblemDomain& a_domain, Real a_dx, bool a_homogeneous) { const Box& domainBox = a_domain.domainBox(); for (int idir = 0; idir < SpaceDim; idir++) { if (!a_domain.isPeriodic(idir)) { for (SideIterator sit; sit.ok(); ++sit) { Side::LoHiSide side = sit(); if (a_valid.sideEnd(side)[idir] == domainBox.sideEnd(side)[idir]) { int bcType; Real bcValue; if (side == Side::Lo) { bcType = m_loSideType [idir]; bcValue = m_loSideValue[idir]; } else { bcType = m_hiSideType [idir]; bcValue = m_hiSideValue[idir]; } if (bcType == 0) { // Neumann BC int isign = sign(side); Box toRegion = adjCellBox(a_valid, idir, side, 1); toRegion &= a_state.box(); Box fromRegion = toRegion; fromRegion.shift(idir, -isign); a_state.copy(a_state, fromRegion, 0, toRegion, 0, a_state.nComp()); if (!a_homogeneous) { for (BoxIterator bit(toRegion); bit.ok(); ++bit) { const IntVect& ivTo = bit(); // IntVect ivClose = ivTo - isign*BASISV(idir); for (int icomp = 0; icomp < a_state.nComp(); icomp++) { a_state(ivTo, icomp) += Real(isign)*a_dx*bcValue; } } } } else if (bcType == 1) { // Dirichlet BC int isign = sign(side); Box toRegion = adjCellBox(a_valid, idir, side, 1); toRegion &= a_state.box(); for (BoxIterator bit(toRegion); bit.ok(); ++bit) { const IntVect& ivTo = bit(); IntVect ivClose = ivTo - isign*BASISV(idir); // IntVect ivFar = ivTo - 2*isign*BASISV(idir); Real inhomogVal = 0.0; if (!a_homogeneous) { inhomogVal = bcValue; } for (int icomp = 0; icomp < a_state.nComp(); icomp++) { Real nearVal = a_state(ivClose, icomp); // Real farVal = a_state(ivFar, icomp); Real ghostVal = linearInterp(inhomogVal, nearVal); a_state(ivTo, icomp) = ghostVal; } } } else { MayDay::Abort("ConstBCFunction::operator() - unknown BC type"); } } // if ends match } // end loop over sides } // if not periodic in this direction } // end loop over directions }
void EBPlanarShockIBC:: setBndrySlopes(EBCellFAB& a_deltaPrim, const EBCellFAB& a_primState, const EBISBox& a_ebisBox, const Box& a_box, const int& a_dir) { // don't want to deal with the periodic case CH_assert(!m_domain.isPeriodic(a_dir)); CH_assert(m_isDefined); CH_assert(m_isFortranCommonSet); Box loBox,hiBox,centerBox,domain; int hasLo,hasHi; Box slopeBox = a_deltaPrim.getRegion()&m_domain; int numSlop = a_deltaPrim.nComp(); // Generate the domain boundary boxes, loBox and hiBox, if there are // domain boundarys there eblohicenter(loBox,hasLo,hiBox,hasHi,centerBox,domain, slopeBox,m_domain,a_dir); // Set the boundary slopes if necessary if ((hasLo != 0) || (hasHi != 0)) { BaseFab<Real>& regDeltaPrim = a_deltaPrim.getSingleValuedFAB(); const BaseFab<Real>& regPrimState = a_primState.getSingleValuedFAB(); /**/ FORT_SLOPEBCS(CHF_FRA(regDeltaPrim), CHF_CONST_FRA(regPrimState), CHF_CONST_REAL(m_dx), CHF_CONST_INT(a_dir), CHF_BOX(loBox), CHF_CONST_INT(hasLo), CHF_BOX(hiBox), CHF_CONST_INT(hasHi)); /**/ } for(SideIterator sit; sit.ok(); ++sit) { bool doThisSide; Box thisBox; if(sit() == Side::Lo) { doThisSide = (hasLo != 0); thisBox = loBox; } else { doThisSide = (hasHi != 0); thisBox = hiBox; } if(doThisSide) { // the cells for which the regular calculation //are incorrect are the grown set of the multivalued //cells intersected with the appropriate bndry box //and added to the irregular cells on the boundary. Box boxGrown = thisBox; boxGrown.grow(a_dir, 1); boxGrown &= m_domain; IntVectSet ivs = a_ebisBox.getMultiCells(boxGrown); ivs &= loBox; IntVectSet ivsIrreg = a_ebisBox.getIrregIVS(thisBox); ivs |= ivsIrreg; for(VoFIterator vofit(ivs, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit) { const VolIndex& vof = vofit(); //all slopes at boundary get set to zero //except normal velocity. just following the //fortran here int inormVelVar = a_dir + QVELX; for(int ivar = 0; ivar < numSlop; ivar++) { if(ivar != inormVelVar) { a_deltaPrim(vof, ivar) = 0.0; } } //for normal velocity //do strangely limited slope //just lifted from the fortran. Side::LoHiSide otherSide = flip(sit()); Vector<FaceIndex> faces = a_ebisBox.getFaces(vof, a_dir, otherSide); Real thisVel = a_primState(vof, inormVelVar); Real otherVel = 0.; for(int iface = 0; iface < faces.size(); iface++) { VolIndex otherVoF = faces[iface].getVoF(otherSide); otherVel += a_primState(otherVoF,inormVelVar); } if(faces.size() > 0) { otherVel /= Real(faces.size()); Real slope; if(sit() == Side::Lo) { slope = otherVel - thisVel; } else { slope = thisVel - otherVel; } //trick to make sure state will not change sign if(slope*thisVel < 0) { a_deltaPrim(vof, inormVelVar) = 0.0; } else { //slope and vel same sign Real rsign = 1.0; if(thisVel < 0.0) rsign = -1.0; //told you this was odd. Real dvmin = Min(Abs(slope), Abs((Real)2.*thisVel)); a_deltaPrim(vof, inormVelVar) = rsign*dvmin; } } else //no faces on high side of low boundary vof { a_deltaPrim(vof, inormVelVar) = 0.0; } } //end loop over irregular vofs at boundary } } //end loop over boundary sides }
// // 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); }
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; }
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); }
void EBCompositeMACProjector:: correctTangentialVelocity(EBFaceFAB& a_velocity, const EBFaceFAB& a_gradient, const Box& a_grid, const EBISBox& a_ebisBox, const IntVectSet& a_cfivs) { CH_TIME("EBCompositeMACProjector::correctTangentialVelocity"); int velDir = a_velocity.direction(); int gradDir = a_gradient.direction(); //veldir is the face on which the velocity lives //graddir is the direction of the component //and the face on which the mac gradient lives CH_assert(velDir != gradDir); CH_assert(a_velocity.nComp() == 1); CH_assert(a_gradient.nComp() == 1); //updating in place in fortran so we have to save a acopy EBFaceFAB velSave(a_ebisBox, a_velocity.getCellRegion(), velDir, 1); velSave.copy(a_velocity); //interior box is the box where all of the stencil can be reached //without going out of the domain ProblemDomain domainBox = a_ebisBox.getDomain(); Box interiorBox = a_grid; interiorBox.grow(1); interiorBox &= domainBox; interiorBox.grow(-1); Box interiorFaceBox = surroundingNodes(interiorBox, velDir); if (!interiorBox.isEmpty()) { BaseFab<Real>& regVel = a_velocity.getSingleValuedFAB(); const BaseFab<Real>& regGrad = a_gradient.getSingleValuedFAB(); FORT_REGCORRECTTANVEL(CHF_FRA1(regVel,0), CHF_CONST_FRA1(regGrad,0), CHF_BOX(interiorFaceBox), CHF_INT(velDir), CHF_INT(gradDir)); } //do only irregular and boundary cells pointwise IntVectSet ivsIrreg = a_ebisBox.getIrregIVS(a_grid); IntVectSet ivsGrid(a_grid); ivsGrid -= interiorBox; ivsGrid |= ivsIrreg; FaceIterator faceit(ivsGrid, a_ebisBox.getEBGraph(), velDir, FaceStop::SurroundingWithBoundary); for (faceit.reset(); faceit.ok(); ++faceit) { //average neighboring grads in grad dir direction int numGrads = 0; Real gradAve = 0.0; const FaceIndex& velFace = faceit(); for (SideIterator sitVel; sitVel.ok(); ++sitVel) { const VolIndex& vofSide = velFace.getVoF(sitVel()); const IntVect& ivSide = vofSide.gridIndex(); //do not include stuff over coarse-fine interface and inside the domain //cfivs includes cells just outside domain if (!a_cfivs.contains(ivSide) && domainBox.contains(ivSide)) { for (SideIterator sitGrad; sitGrad.ok(); ++sitGrad) { Vector<FaceIndex> gradFaces = a_ebisBox.getFaces(vofSide, gradDir, sitGrad()); for (int iface = 0; iface < gradFaces.size(); iface++) { if (!gradFaces[iface].isBoundary()) { numGrads++; gradAve += a_gradient(gradFaces[iface], 0); } } }//end loop over gradient sides }//end cfivs check else { // inside coarse/fine interface or at domain boundary. extrapolate from neighboring vofs to get the gradient const Side::LoHiSide inSide = flip(sitVel()); const VolIndex& inSideVof = velFace.getVoF(inSide); const IntVect& inSideIV = inSideVof.gridIndex(); IntVect inSideFarIV = inSideIV; inSideFarIV[velDir] += sign(inSide); if (domainBox.contains(inSideIV) && domainBox.contains(inSideFarIV)) { Vector<VolIndex> farVofs = a_ebisBox.getVoFs(inSideFarIV); if (farVofs.size() == 1) { const VolIndex& inSideFarVof = farVofs[0]; for (SideIterator sitGrad; sitGrad.ok(); ++sitGrad) { //get the grad for the face adjoining inSideVof on the sitGrad side, in the gradDir direction Vector<FaceIndex> gradFaces = a_ebisBox.getFaces(inSideVof , gradDir, sitGrad()); Vector<FaceIndex> gradFarFaces = a_ebisBox.getFaces(inSideFarVof, gradDir, sitGrad()); if ( (gradFaces.size() == 1) && (gradFarFaces.size() == 1) ) { // if ( (!gradFaces[0].isBoundary()) && (!gradFarFaces[0].isBoundary()) ) // { const Real& inSideGrad = a_gradient(gradFaces[0], 0); const Real& inSideFarGrad = a_gradient(gradFarFaces[0], 0); Real extrapGrad = 2.0*inSideGrad - inSideFarGrad; gradAve += extrapGrad; numGrads++; // } } } } } }//end cfivs check }//end loop over sides of velocity face if (numGrads > 1) { gradAve /= Real(numGrads); } //remember that the fortran updated the velocity in place so //we have to use the saved velocity a_velocity(velFace, 0) = velSave(velFace, 0) - gradAve; } }
void EBMGInterp::fillGhostCellsPWC(LevelData<EBCellFAB>& a_data, const EBISLayout& a_ebisl, const ProblemDomain& a_dom) { for (int idir = 0; idir < SpaceDim; idir++) { if (m_ghost[idir] < 1) { MayDay::Error("EBMGInterp:I need a ghost cell for linear interpolation"); } } //extrapolate to every ghost cell const DisjointBoxLayout& dbl = a_data.disjointBoxLayout(); for (DataIterator dit = dbl.dataIterator(); dit.ok(); ++dit) { const Box& grid = dbl.get(dit()); const EBGraph& ebgraph = a_ebisl[dit()].getEBGraph(); for (int idir = 0; idir < SpaceDim; idir++) { for (SideIterator sit; sit.ok(); ++sit) { Side::LoHiSide flipSide = flip(sit()); Box ghostBox = adjCellBox(grid, idir, sit(), 1); for (BoxIterator boxit(ghostBox); boxit.ok(); ++boxit) { if (a_dom.contains(boxit())) { Vector<VolIndex> vofs = ebgraph.getVoFs(boxit()); for (int ivof = 0; ivof < vofs.size(); ivof++) { Real extrapVal = 0; Vector<FaceIndex> faces = ebgraph.getFaces(vofs[ivof], idir, flipSide); for (int ivar = 0; ivar < a_data.nComp(); ivar++) { for (int iface = 0; iface < faces.size(); iface++) { const VolIndex& flipVoF = faces[iface].getVoF(flipSide); extrapVal += a_data[dit()](flipVoF, ivar); } if (faces.size() > 1) extrapVal /= faces.size(); a_data[dit()](vofs[ivof], ivar) = extrapVal; } } } else { //just put in the single valued part of the data holder something sensible //if not inside domain int isign = sign(flipSide); BaseFab<Real>& bfdata = a_data[dit()].getSingleValuedFAB(); IntVect otherIV = boxit() + isign*BASISV(idir); for (int ivar = 0; ivar < a_data.nComp(); ivar++) { bfdata(boxit(), ivar) = bfdata(otherIV, ivar); } } } } } } //do exchange to overwrite ghost cells where there exists real data a_data.exchange(); }
void SlabService::fillGraph(BaseFab<int>& a_regIrregCovered, Vector<IrregNode>& a_nodes, const Box& a_validRegion, const Box& a_ghostRegion, const ProblemDomain& a_domain, const RealVect& a_origin, const Real& a_dx) const { Box grownCovBox = grow(m_coveredRegion, 1); grownCovBox &= a_ghostRegion; IntVectSet ivsIrreg(grownCovBox); ivsIrreg -= m_coveredRegion; ivsIrreg &= a_domain; //set regirregcoverred flags CH_assert(a_regIrregCovered.box().contains(a_ghostRegion)); //set every cell to regular a_regIrregCovered.setVal(1); for (BoxIterator bit(a_ghostRegion); bit.ok(); ++bit) { if (m_coveredRegion.contains(bit())) { //set covered cells to -1 a_regIrregCovered(bit(), 0) = -1; } else if (ivsIrreg.contains(bit())) { //set irreg cells to 0 a_regIrregCovered(bit(), 0) = 0; } } //now loop through irreg cells and make Nodes for them a_nodes.resize(0); for (IVSIterator ivsit(ivsIrreg); ivsit.ok(); ++ivsit) { const IntVect& iv = ivsit(); if (a_validRegion.contains(iv)) { IrregNode node; //first the obvious node.m_cell = iv; node.m_volFrac = 1.0; node.m_cellIndex = 0; node.m_volCentroid = RealVect::Zero; //any time the next cell over is in the covered //region, there is no face. If there is a cell //but it is outside the domain, the arc=-1 to signify //a boundary face. Otherwise, the arc is -2 if it //is to a regular cell and 0 if it is to an irregular cell for (int idir = 0; idir < SpaceDim; idir++) { for (SideIterator sit; sit.ok(); ++sit) { int arcIndex = node.index(idir, sit()); Vector<int>& arcs = node.m_arc[arcIndex]; Vector<Real>& areaFracs= node.m_areaFrac[arcIndex]; Vector<RealVect>& faceCents= node.m_faceCentroid[arcIndex]; IntVect otherIV = iv + sign(sit())*BASISV(idir); if (m_coveredRegion.contains(otherIV)) { //do nothing, covered face. leave the vector empty } else { int otherCellIndex; if (ivsIrreg.contains(otherIV)) { //arc irregular cell inside the domain otherCellIndex = 0; } else if (!a_domain.contains(otherIV)) { //boundary face otherCellIndex = -1; } else { //arc to regular cell otherCellIndex = -2; } arcs.push_back(otherCellIndex); Real areaFrac = 1.0; RealVect faceCent = RealVect::Zero; areaFracs.push_back(areaFrac); faceCents.push_back(faceCent); } //end otherIV not covered } } //the boundary centroid and normal //depend on which side is covered for (int idir = 0; idir < SpaceDim; idir++) { for (SideIterator sit; sit.ok(); ++sit) { int arcIndex = node.index(idir, sit()); Vector<int>& arcs = node.m_arc[arcIndex]; if (arcs.size() == 0) { int isign = sign(sit()); node.m_bndryCentroid[idir] = Real(isign)*0.5; } } } a_nodes.push_back(node); } } }
void EBFineToCoarRedist:: define(const DisjointBoxLayout& a_dblFine, const DisjointBoxLayout& a_dblCoar, const EBISLayout& a_ebislFine, const EBISLayout& a_ebislCoar, const Box& a_domainCoar, const int& a_nref, const int& a_nvar, int a_redistRad, const EBIndexSpace* const a_ebisPtr) { CH_TIME("EBFineToCoarRedist::stardard_define"); m_isDefined = true; m_nComp = a_nvar; m_refRat = a_nref; m_domainCoar = a_domainCoar; m_gridsFine = a_dblFine; m_gridsCoar = a_dblCoar; m_ebislFine = a_ebislFine; m_ebislCoar = a_ebislCoar; m_redistRad = a_redistRad; //created the coarsened fine layout m_gridsRefCoar = DisjointBoxLayout(); refine(m_gridsRefCoar, m_gridsCoar, m_refRat); CH_assert(a_ebisPtr->isDefined()); int nghost = 3*m_redistRad; Box domainFine = refine(m_domainCoar, m_refRat); a_ebisPtr->fillEBISLayout(m_ebislRefCoar, m_gridsRefCoar, domainFine, nghost); m_ebislRefCoar.setMaxCoarseningRatio(m_refRat,a_ebisPtr); //define the intvectsets over which the objects live m_setsFine.define(m_gridsFine); m_setsRefCoar.define(m_gridsCoar); //make sets //global set consists of redistrad on the fine side of the coarse-fine //interface //the fine set is that within one fine box. //the refcoar set is that set within one refined coarse box. { CH_TIME("make_fine_sets"); for (DataIterator dit = m_gridsFine.dataIterator(); dit.ok(); ++dit) { const Box& fineBox = m_gridsFine.get(dit()); IntVectSet& fineSet = m_setsFine[dit()]; //add entire fine box fineSet = IntVectSet(fineBox); IntVectSet irregIVS = m_ebislFine[dit()].getIrregIVS(fineBox); fineSet &= irregIVS; //subtract fine box shrunk by the redistribution radius fineSet -= grow(fineBox, -m_redistRad); //subtract all other the fine boxes shifted in all //directions for (LayoutIterator lit = m_gridsFine.layoutIterator(); lit.ok(); ++lit) { const Box& otherBox = m_gridsFine.get(lit()); if (otherBox != fineBox) { for (int idir = 0; idir < SpaceDim; idir++) { for (SideIterator sit; sit.ok(); ++sit) { Box shiftBox = otherBox; shiftBox.shift(idir, sign(sit())*m_redistRad); fineSet -= shiftBox; } } } } } } { CH_TIME("make_coar_sets"); for (DataIterator dit = m_gridsCoar.dataIterator(); dit.ok(); ++dit) { Box grownBox = grow(m_gridsRefCoar.get(dit()), m_redistRad); grownBox &= domainFine; //find the complement of what we really want IntVectSet ivsComplement(grownBox); for (LayoutIterator litFine = m_gridsFine.layoutIterator(); litFine.ok(); ++litFine) { const Box& fineBox = m_gridsFine.get(litFine()); IntVectSet fineSet(fineBox); //add entire fine box fineSet = IntVectSet(fineBox); Box interiorBox = grow(fineBox, -m_redistRad); //subtract fine box shrunk by the redistribution radius fineSet -= interiorBox; //subtract all other the fine boxes shifted in all //directions for (LayoutIterator lit = m_gridsFine.layoutIterator(); lit.ok(); ++lit) { const Box& otherBox = m_gridsFine.get(lit()); if (otherBox != fineBox) { for (int idir = 0; idir < SpaceDim; idir++) { for (SideIterator sit; sit.ok(); ++sit) { Box shiftBox = otherBox; shiftBox.shift(idir, sign(sit())*m_redistRad); fineSet -= shiftBox; } } } } //subtract the fine set from the complement ivsComplement -= fineSet; } //now the set we want is the grownbox - complement IntVectSet& refCoarSet = m_setsRefCoar[dit()]; refCoarSet = IntVectSet(grownBox); refCoarSet -= ivsComplement; IntVectSet irregIVS = m_ebislRefCoar[dit()].getIrregIVS(grownBox); refCoarSet &= irregIVS; } } defineDataHolders(); setToZero(); }