void MappedLevelFluxRegister::incrementFine(const FArrayBox& a_fineFlux, Real a_scale, const DataIndex& a_fineDataIndex, const Interval& a_srcInterval, const Interval& a_dstInterval, int a_dir, Side::LoHiSide a_sd) { CH_assert(isDefined()); if (!(m_isDefined & FluxRegFineDefined)) return; CH_assert(a_srcInterval.size() == a_dstInterval.size()); CH_TIME("MappedLevelFluxRegister::incrementFine"); // We cast away the constness in a_coarseFlux for the scope of this function. This // should be acceptable, since at the end of the day there is no change to it. -JNJ FArrayBox& fineFlux = const_cast<FArrayBox&>(a_fineFlux); // Muhahaha. fineFlux.shiftHalf(a_dir, sign(a_sd)); Real denom = 1.0; if (m_scaleFineFluxes) { denom = m_nRefine.product() / m_nRefine[a_dir]; } Real scale = sign(a_sd) * a_scale / denom; FArrayBox& cFine = m_fineFlux[a_fineDataIndex]; // FArrayBox cFineFortran(cFine.box(), cFine.nComp()); // cFineFortran.copy(cFine); Box clipBox = m_fineFlux.box(a_fineDataIndex); clipBox.refine(m_nRefine); Box fineBox; if (a_sd == Side::Lo) { fineBox = adjCellLo(clipBox, a_dir, 1); fineBox &= fineFlux.box(); } else { fineBox = adjCellHi(clipBox, a_dir, 1); fineBox &= fineFlux.box(); } #if 0 for (BoxIterator b(fineBox); b.ok(); ++b) { int s = a_srcInterval.begin(); int d = a_dstInterval.begin(); for (; s <= a_srcInterval.end(); ++s, ++d) { cFine(coarsen(b(), m_nRefine), d) += scale * fineFlux(b(), s); } } #else // shifting to ensure fineBox is in the positive quadrant, so IntVect coarening // is just integer division. const Box& box = coarsen(fineBox, m_nRefine); Vector<Real> regbefore(cFine.nComp()); Vector<Real> regafter(cFine.nComp()); if (s_verbose && (a_dir == debugdir) && box.contains(ivdebnoeb)) { for (int ivar = 0; ivar < cFine.nComp(); ivar++) { regbefore[ivar] = cFine(ivdebnoeb, ivar); } } const IntVect& iv = fineBox.smallEnd(); IntVect civ = coarsen(iv, m_nRefine); int srcComp = a_srcInterval.begin(); int destComp = a_dstInterval.begin(); int ncomp = a_srcInterval.size(); FORT_MAPPEDINCREMENTFINE(CHF_CONST_FRA_SHIFT(fineFlux, iv), CHF_FRA_SHIFT(cFine, civ), CHF_BOX_SHIFT(fineBox, iv), CHF_CONST_INTVECT(m_nRefine), CHF_CONST_REAL(scale), CHF_CONST_INT(srcComp), CHF_CONST_INT(destComp), CHF_CONST_INT(ncomp)); if (s_verbose && (a_dir == debugdir) && box.contains(ivdebnoeb)) { for (int ivar = 0; ivar < cFine.nComp(); ivar++) { regafter[ivar] = cFine(ivdebnoeb, ivar); } } if (s_verbose && (a_dir == debugdir) && box.contains(ivdebnoeb)) { pout() << "levelfluxreg::incrementFine: scale = " << scale << endl; Box refbox(ivdebnoeb, ivdebnoeb); refbox.refine(m_nRefine); refbox &= fineBox; if (!refbox.isEmpty()) { pout() << "fine fluxes = " << endl; for (BoxIterator bit(refbox); bit.ok(); ++bit) { for (int ivar = 0; ivar < cFine.nComp(); ivar++) { pout() << "iv = " << bit() << "("; for (int ivar = 0; ivar < cFine.nComp(); ivar++) { pout() << fineFlux(bit(), ivar); } pout() << ")" << endl; } } } for (int ivar = 0; ivar < cFine.nComp(); ivar++) { pout() << " reg before = " << regbefore[ivar] << ", "; pout() << " reg after = " << regafter[ivar] << ", "; } pout() << endl; } //fineBox.shift(-shift); // now, check that cFineFortran and cFine are the same //fineBox.coarsen(m_nRefine); // for (BoxIterator b(fineBox); b.ok(); ++b) // { // if (cFineFortran(b(),0) != cFine(b(),0)) // { // MayDay::Error("Fortran doesn't match C++"); // } // } // need to shift boxes back to where they were on entry. // cFine.shift(-shift/m_nRefine); #endif fineFlux.shiftHalf(a_dir, - sign(a_sd)); }
EBCellFAB& EBCellFAB::axby(const EBCellFAB& a_X, const EBCellFAB& a_Y, const Real& a_A, const Real& a_B) { CH_assert(isDefined()); CH_assert(a_X.isDefined()); CH_assert(a_Y.isDefined()); // Dan G. feels strongly that the assert below should NOT be commented out // Brian feels that a weaker version of the CH_assert (if possible) is needed // Terry is just trying to get his code to work //CH_assert(m_ebisBox == a_X.m_ebisBox); CH_assert(a_X.m_nComp == m_nComp); CH_assert(a_Y.m_nComp == m_nComp); bool sameRegBox = (a_X.m_regFAB.box() == a_Y.m_regFAB.box()) && (a_X.m_regFAB.box() == m_regFAB.box()); Box locRegion = a_X.m_region & m_region & a_Y.m_region; if (!locRegion.isEmpty()) { int srccomp = 0; int destcomp = 0; FORT_AXBYFAB(CHF_FRA(m_regFAB), CHF_CONST_FRA(a_X.m_regFAB), CHF_CONST_FRA(a_Y.m_regFAB), CHF_CONST_REAL(a_A), CHF_CONST_REAL(a_B), CHF_BOX(locRegion), CHF_INT(srccomp), CHF_INT(destcomp), CHF_INT(m_nComp)); bool nvofTest = false; bool regionTest = false; //CP: we do a thorough test here to see if all VoFs are the same, just being cautious const Vector<VolIndex>& vofs = m_irrFAB.getVoFs(); const Vector<VolIndex>& vofs_x = a_X.m_irrFAB.getVoFs(); const Vector<VolIndex>& vofs_y = a_Y.m_irrFAB.getVoFs(); if (vofs.size() == vofs_x.size() && vofs.size()==vofs_y.size()) { nvofTest = true; for (int i=0; i<vofs.size(); i++) { if (vofs[i] != vofs_x[i] || vofs[i] != vofs_y[i]) { nvofTest = false; break; } } } if (locRegion == a_X.m_region && locRegion == a_Y.m_region && locRegion == m_region) regionTest = true; if (sameRegBox && regionTest && nvofTest) { const Real* l = a_X.m_irrFAB.dataPtr(destcomp); const Real* r = a_Y.m_irrFAB.dataPtr(destcomp); Real* c = m_irrFAB.dataPtr(destcomp); int nvof = a_X.m_irrFAB.numVoFs(); for (int i=0; i<m_nComp*nvof; i++) c[i] = l[i] * a_A + r[i] * a_B; } else { IntVectSet ivsMulti = a_X.getMultiCells(); ivsMulti &= a_Y.getMultiCells(); ivsMulti &= getMultiCells(); // opt might be to take this out ivsMulti &= locRegion; IVSIterator ivsit(ivsMulti); for (ivsit.reset(); ivsit.ok(); ++ivsit) { const IntVect& iv = ivsit(); Vector<VolIndex> vofs = m_ebisBox.getVoFs(iv); for (int ivof = 0; ivof < vofs.size(); ivof++) { const VolIndex& vof = vofs[ivof]; for (int icomp = 0; icomp < m_nComp; ++icomp) { m_irrFAB(vof, icomp) = a_X.m_irrFAB(vof, icomp) * a_A + a_Y.m_irrFAB(vof, icomp) * a_B; } } } } } return *this; }
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 }
// ----------------------------------------------------------------------------- // Adds coarse cell values directly to all overlying fine cells, // then removes the average from the fine result. // ----------------------------------------------------------------------------- void ZeroAvgConstInterpPS::prolongIncrement (LevelData<FArrayBox>& a_phiThisLevel, const LevelData<FArrayBox>& a_correctCoarse) { CH_TIME("ZeroAvgConstInterpPS::prolongIncrement"); // Gather grids, domains, refinement ratios... const DisjointBoxLayout& fineGrids = a_phiThisLevel.getBoxes(); const DisjointBoxLayout& crseGrids = a_correctCoarse.getBoxes(); CH_assert(fineGrids.compatible(crseGrids)); const ProblemDomain& fineDomain = fineGrids.physDomain(); const ProblemDomain& crseDomain = crseGrids.physDomain(); const IntVect mgRefRatio = fineDomain.size() / crseDomain.size(); CH_assert(mgRefRatio.product() > 1); // These will accumulate averaging data. Real localSum = 0.0; Real localVol = 0.0; CH_assert(!m_CCJinvPtr.isNull()); CH_assert(m_dxProduct > 0.0); DataIterator dit = fineGrids.dataIterator(); for (dit.reset(); dit.ok(); ++dit) { // Create references for convenience FArrayBox& fineFAB = a_phiThisLevel[dit]; const FArrayBox& crseFAB = a_correctCoarse[dit]; const Box& fineValid = fineGrids[dit]; const FArrayBox& JinvFAB = (*m_CCJinvPtr)[dit]; // To make things easier, we will offset the // coarse and fine data boxes to zero. const IntVect& fiv = fineValid.smallEnd(); const IntVect civ = coarsen(fiv, mgRefRatio); // Correct the fine data FORT_CONSTINTERPWITHAVGPS ( CHF_FRA_SHIFT(fineFAB, fiv), CHF_CONST_FRA_SHIFT(crseFAB, civ), CHF_BOX_SHIFT(fineValid, fiv), CHF_CONST_INTVECT(mgRefRatio), CHF_CONST_FRA1_SHIFT(JinvFAB,0,fiv), CHF_CONST_REAL(m_dxProduct), CHF_REAL(localVol), CHF_REAL(localSum)); } // Compute global sum (this is where the MPI communication happens) #ifdef CH_MPI Real globalSum = 0.0; int result = MPI_Allreduce(&localSum, &globalSum, 1, MPI_CH_REAL, MPI_SUM, Chombo_MPI::comm); if (result != MPI_SUCCESS) { MayDay::Error("Sorry, but I had a communication error in ZeroAvgConstInterpPS::prolongIncrement"); } Real globalVol = 0.0; result = MPI_Allreduce(&localVol, &globalVol, 1, MPI_CH_REAL, MPI_SUM, Chombo_MPI::comm); if (result != MPI_SUCCESS) { MayDay::Error("Sorry, but I had a communication error in ZeroAvgConstInterpPS::prolongIncrement"); } #else Real globalSum = localSum; Real globalVol = localVol; #endif // Remove the average from phi. Real avgPhi = globalSum / globalVol; for (dit.reset(); dit.ok(); ++dit) { a_phiThisLevel[dit] -= avgPhi; } }
void 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; } }
void EBPlanarShockIBC:: fluxBC(EBFluxFAB& a_flux, const EBCellFAB& a_primCenter, const EBCellFAB& a_primExtrap, const Side::LoHiSide& a_side, const Real& a_time, const EBISBox& a_ebisBox, const DataIndex& a_dit, const Box& a_box, const Box& a_faceBox, const int& a_dir) { CH_assert(m_isDefined); CH_assert(m_isFortranCommonSet); CH_assert(!m_domain.isPeriodic(a_dir)); Box FBox = a_flux[a_dir].getSingleValuedFAB().box(); Box cellBox = FBox; int numFlux = a_flux[a_dir].nComp(); // Determine which side and thus shifting directions int isign = sign(a_side); cellBox.shiftHalf(a_dir,isign); // Is there a domain boundary next to this grid if (!m_domain.contains(cellBox)) { cellBox &= m_domain; // Find the strip of cells next to the domain boundary Box boundaryBox = bdryBox(cellBox, a_dir, a_side, 1); // Shift things to all line up correctly boundaryBox.shiftHalf(a_dir,-isign); BaseFab<Real>& regFlux = a_flux[a_dir].getSingleValuedFAB(); const BaseFab<Real>& regPrimExtrap = a_primExtrap.getSingleValuedFAB(); // Set the boundary fluxes bool inbackofshock = (!m_shockbackward && a_side == Side::Lo) || ( m_shockbackward && a_side == Side::Hi); if(a_dir == m_shocknorm && inbackofshock) { regFlux.shiftHalf(a_dir,-isign); // Set the boundary fluxes /**/ FORT_EXTRAPBC(CHF_FRA(regFlux), CHF_CONST_FRA(regPrimExtrap), CHF_CONST_REAL(m_dx), CHF_CONST_INT(a_dir), CHF_BOX(boundaryBox)); /**/ // Shift returned fluxes to be face centered regFlux.shiftHalf(a_dir,isign); //now for the multivalued cells. Since it is pointwise, //the regular calc is correct for all single-valued cells. IntVectSet ivs = a_ebisBox.getMultiCells(boundaryBox); for(VoFIterator vofit(ivs, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit) { const VolIndex& vof = vofit(); Vector<Real> qgdnv(QNUM); Vector<Real> fluxv(FNUM); for(int ivar = 0; ivar < QNUM; ivar++) { qgdnv[ivar] = a_primExtrap(vof, ivar); } Vector<FaceIndex> bndryFaces = a_ebisBox.getFaces(vof, a_dir, a_side); for(int iface= 0; iface < bndryFaces.size(); iface++) { /**/ FORT_POINTGETFLUX(CHF_VR(fluxv), CHF_VR(qgdnv), CHF_CONST_INT(a_dir)); /**/ const FaceIndex& face = bndryFaces[iface]; for(int ivar = 0; ivar < FNUM; ivar++) { a_flux[a_dir](face, ivar) = fluxv[ivar]; } } } } //end if on the back side of the shock else { regFlux.shiftHalf(a_dir,-isign); //solid wall bcs FORT_SLIPWALLSOLIDBC(CHF_FRA(regFlux), CHF_CONST_FRA(regPrimExtrap), CHF_CONST_INT(isign), CHF_CONST_REAL(m_dx), CHF_CONST_INT(a_dir), CHF_BOX(boundaryBox)); // Shift returned fluxes to be face centered regFlux.shiftHalf(a_dir,isign); int inormMomVar = CMOMX + a_dir; int inormVelVar = QVELX + a_dir; //now for the multivalued cells. Since it is pointwise, //the regular calc is correct for all single-valued cells. IntVectSet ivs = a_ebisBox.getMultiCells(boundaryBox); for(VoFIterator vofit(ivs, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit) { const VolIndex& vof = vofit(); //set all fluxes except normal momentum to zero. //set normal momemtum flux to sign(normal)*pressure Vector<FaceIndex> bndryFaces = a_ebisBox.getFaces(vof, a_dir, a_side); for(int iface= 0; iface < bndryFaces.size(); iface++) { const FaceIndex& face = bndryFaces[iface]; //set all fluxes to zero then fix normal momentum for(int ivar = 0; ivar < numFlux; ivar++) { a_flux[a_dir](face, ivar) = 0; } Real press = a_primExtrap(vof, QPRES); Real dense = a_primExtrap(vof, QRHO); Real unorm = a_primExtrap(vof, inormVelVar); Real speed = sqrt(m_gamma*press/dense); a_flux[a_dir](face, inormMomVar) = press + isign*dense*unorm*speed; } } } } }
void VCAMRPoissonOp2::looseGSRB(LevelData<FArrayBox>& a_phi, const LevelData<FArrayBox>& a_rhs) { CH_TIME("VCAMRPoissonOp2::looseGSRB"); #if 1 MayDay::Abort("VCAMRPoissonOp2::looseGSRB - Not implemented"); #else // This implementation converges at half the rate of "levelGSRB" in // multigrid solves CH_assert(a_phi.isDefined()); CH_assert(a_rhs.isDefined()); CH_assert(a_phi.ghostVect() >= IntVect::Unit); CH_assert(a_phi.nComp() == a_rhs.nComp()); // Recompute the relaxation coefficient if needed. resetLambda(); const DisjointBoxLayout& dbl = a_phi.disjointBoxLayout(); DataIterator dit = a_phi.dataIterator(); // fill in intersection of ghostcells and a_phi's boxes { CH_TIME("VCAMRPoissonOp2::looseGSRB::homogeneousCFInterp"); homogeneousCFInterp(a_phi); } { CH_TIME("VCAMRPoissonOp2::looseGSRB::exchange"); a_phi.exchange(a_phi.interval(), m_exchangeCopier); } // now step through grids... for (dit.begin(); dit.ok(); ++dit) { // invoke physical BC's where necessary { CH_TIME("VCAMRPoissonOp2::looseGSRB::BCs"); m_bc(a_phi[dit], dbl[dit()], m_domain, m_dx, true); } const Box& region = dbl.get(dit()); const FluxBox& thisBCoef = (*m_bCoef)[dit]; int whichPass = 0; #if CH_SPACEDIM == 1 FORT_GSRBHELMHOLTZVC1D #elif CH_SPACEDIM == 2 FORT_GSRBHELMHOLTZVC2D #elif CH_SPACEDIM == 3 FORT_GSRBHELMHOLTZVC3D #else This_will_not_compile! #endif (CHF_FRA(a_phi[dit]), CHF_CONST_FRA(a_rhs[dit]), CHF_BOX(region), CHF_CONST_REAL(m_dx), CHF_CONST_REAL(m_alpha), CHF_CONST_FRA((*m_aCoef)[dit]), CHF_CONST_REAL(m_beta), #if CH_SPACEDIM >= 1 CHF_CONST_FRA(thisBCoef[0]), #endif #if CH_SPACEDIM >= 2 CHF_CONST_FRA(thisBCoef[1]), #endif #if CH_SPACEDIM >= 3 CHF_CONST_FRA(thisBCoef[2]), #endif #if CH_SPACEDIM >= 4 This_will_not_compile! #endif CHF_CONST_FRA(m_lambda[dit]), CHF_CONST_INT(whichPass)); whichPass = 1; #if CH_SPACEDIM == 1 FORT_GSRBHELMHOLTZVC1D #elif CH_SPACEDIM == 2 FORT_GSRBHELMHOLTZVC2D #elif CH_SPACEDIM == 3 FORT_GSRBHELMHOLTZVC3D #else This_will_not_compile! #endif (CHF_FRA(a_phi[dit]), CHF_CONST_FRA(a_rhs[dit]), CHF_BOX(region), CHF_CONST_REAL(m_dx), CHF_CONST_REAL(m_alpha), CHF_CONST_FRA((*m_aCoef)[dit]), CHF_CONST_REAL(m_beta), #if CH_SPACEDIM >= 1 CHF_CONST_FRA(thisBCoef[0]), #endif #if CH_SPACEDIM >= 2 CHF_CONST_FRA(thisBCoef[1]), #endif #if CH_SPACEDIM >= 3 CHF_CONST_FRA(thisBCoef[2]), #endif #if CH_SPACEDIM >= 4 This_will_not_compile! #endif CHF_CONST_FRA(m_lambda[dit]), CHF_CONST_INT(whichPass)); } // end loop through grids #endif }
// Set boundary fluxes void VelIBC::primBC(FArrayBox& a_WGdnv, const FArrayBox& a_Wextrap, const FArrayBox& a_W, const int& a_dir, const Side::LoHiSide& a_side, const Real& a_time) { CH_assert(m_isDefined == true); // In periodic case, this doesn't do anything if (!m_domain.isPeriodic(a_dir)) { // This needs to be fixed // CH_assert(m_isBCvalSet); int lohisign; Box tmp = a_WGdnv.box() & m_domain; Real bcVal; // Determine which side and thus shifting directions if (a_side == Side::Lo) { lohisign = -1; bcVal = m_bcVal[a_dir][0]; } else { lohisign = 1; bcVal = m_bcVal[a_dir][1]; } tmp.shiftHalf(a_dir,lohisign); // Is there a domain boundary next to this grid if (!m_domain.contains(tmp)) { tmp &= m_domain; Box boundaryBox; // Find the strip of cells next to the domain boundary if (a_side == Side::Lo) { boundaryBox = bdryLo(tmp,a_dir); } else { boundaryBox = bdryHi(tmp,a_dir); } // Set the boundary fluxes FORT_SOLIDVELBCF(CHF_FRA(a_WGdnv), CHF_CONST_FRA(a_Wextrap), CHF_CONST_REAL(bcVal), CHF_CONST_INT(lohisign), CHF_CONST_REAL(m_dx), CHF_CONST_INT(a_dir), CHF_BOX(boundaryBox)); } } }
// ----------------------------------------------------------------------------- // Interpolate ghosts at CF interface using zeros on coarser grids. // Only do one face. // ----------------------------------------------------------------------------- void homogeneousCFInterp (LevelData<FArrayBox>& a_phif, const DataIndex& a_index, const int a_dir, const Side::LoHiSide a_side, const Real a_fineDxDir, const Real a_crseDxDir, const CFRegion& a_cfRegion) { CH_TIME("homogeneousCFInterp (single grid)"); // Sanity checks CH_assert((a_dir >= 0) && (a_dir < SpaceDim)); CH_assert(a_phif.ghostVect()[a_dir] >= 1); // Get the C/F region const CFIVS* cfivs_ptr = NULL; if (a_side == Side::Lo) { CFRegion& castCFRegion = (CFRegion&)a_cfRegion; cfivs_ptr = &(castCFRegion.loCFIVS(a_index, a_dir)); } else { CFRegion& castCFRegion = (CFRegion&)a_cfRegion; cfivs_ptr = &(castCFRegion.hiCFIVS(a_index, a_dir)); } if (cfivs_ptr->isPacked()) { // The C/F region is a box. // Iterate over the box and interpolate. int ihiorlo = sign(a_side); FArrayBox& phiFab = a_phif[a_index]; const Box region = cfivs_ptr->packedBox(); CH_assert(a_crseDxDir > 0.0 || region.isEmpty()); if (phiFab.box().size(a_dir) == 3) { // Linear interpolation of fine ghosts assuming // all zeros on coarser level. FORTNT_INTERPHOMOLINEAR( CHF_FRA(phiFab), CHF_BOX(region), CHF_CONST_REAL(a_fineDxDir), CHF_CONST_REAL(a_crseDxDir), CHF_CONST_INT(a_dir), CHF_CONST_INT(ihiorlo)); } else { // Quadratic interpolation of fine ghosts assuming // all zeros on coarser level. FORTNT_INTERPHOMO( CHF_FRA(phiFab), CHF_BOX(region), CHF_CONST_REAL(a_fineDxDir), CHF_CONST_REAL(a_crseDxDir), CHF_CONST_INT(a_dir), CHF_CONST_INT(ihiorlo)); } } else { // The C/F region is sparse. // Iterate over the IVS and interpolate. const IntVectSet& interp_ivs = cfivs_ptr->getFineIVS(); if (!interp_ivs.isEmpty()) { CH_assert(a_crseDxDir > 0.0); interpOnIVSHomo(a_phif, a_index, a_dir, a_side, interp_ivs, a_fineDxDir, a_crseDxDir); } } }
void VCAMRPoissonOp2::restrictResidual(LevelData<FArrayBox>& a_resCoarse, LevelData<FArrayBox>& a_phiFine, const LevelData<FArrayBox>& a_rhsFine) { CH_TIME("VCAMRPoissonOp2::restrictResidual"); homogeneousCFInterp(a_phiFine); const DisjointBoxLayout& dblFine = a_phiFine.disjointBoxLayout(); for (DataIterator dit = a_phiFine.dataIterator(); dit.ok(); ++dit) { FArrayBox& phi = a_phiFine[dit]; m_bc(phi, dblFine[dit()], m_domain, m_dx, true); } a_phiFine.exchange(a_phiFine.interval(), m_exchangeCopier); for (DataIterator dit = a_phiFine.dataIterator(); dit.ok(); ++dit) { FArrayBox& phi = a_phiFine[dit]; const FArrayBox& rhs = a_rhsFine[dit]; FArrayBox& res = a_resCoarse[dit]; const FArrayBox& thisACoef = (*m_aCoef)[dit]; const FluxBox& thisBCoef = (*m_bCoef)[dit]; Box region = dblFine.get(dit()); const IntVect& iv = region.smallEnd(); IntVect civ = coarsen(iv, 2); res.setVal(0.0); #if CH_SPACEDIM == 1 FORT_RESTRICTRESVC1D #elif CH_SPACEDIM == 2 FORT_RESTRICTRESVC2D #elif CH_SPACEDIM == 3 FORT_RESTRICTRESVC3D #else This_will_not_compile! #endif (CHF_FRA_SHIFT(res, civ), CHF_CONST_FRA_SHIFT(phi, iv), CHF_CONST_FRA_SHIFT(rhs, iv), CHF_CONST_REAL(m_alpha), CHF_CONST_FRA_SHIFT(thisACoef, iv), CHF_CONST_REAL(m_beta), #if CH_SPACEDIM >= 1 CHF_CONST_FRA_SHIFT(thisBCoef[0], iv), #endif #if CH_SPACEDIM >= 2 CHF_CONST_FRA_SHIFT(thisBCoef[1], iv), #endif #if CH_SPACEDIM >= 3 CHF_CONST_FRA_SHIFT(thisBCoef[2], iv), #endif #if CH_SPACEDIM >= 4 This_will_not_compile! #endif CHF_BOX_SHIFT(region, iv), CHF_CONST_REAL(m_dx)); } }
void EBPoissonOp:: applyDomainFlux(Box * a_loBox, Box * a_hiBox, int * a_hasLo, int * a_hasHi, Box & a_dblBox, int a_nComps, BaseFab<Real> & a_phiFAB, bool a_homogeneousPhysBC, const DataIndex& a_dit, const Real& a_beta) { CH_TIME("EBPoissonOp::applyDomainFlux"); CH_assert(m_domainBC != NULL); for (int idir=0; idir<SpaceDim; idir++) { EBArith::loHi(a_loBox[idir], a_hasLo[idir], a_hiBox[idir], a_hasHi[idir], m_eblg.getDomain(), a_dblBox, idir); for (int comp = 0; comp<a_nComps; comp++) { if (a_hasLo[idir] == 1) { Box lbox=a_loBox[idir]; lbox.shift(idir,-1); BaseFab<Real> loFaceFlux(a_loBox[idir],a_nComps); int side = -1; m_domainBC->getFaceFlux(loFaceFlux,a_phiFAB,m_origin,m_dx,idir,Side::Lo,a_dit,m_time,a_homogeneousPhysBC); FORT_REGAPPLYDOMAINFLUX_INPLACE(CHF_FRA1(a_phiFAB,comp), CHF_CONST_FRA1(loFaceFlux,comp), CHF_CONST_REAL(m_dx[idir]), CHF_CONST_INT(side), CHF_CONST_INT(idir), CHF_BOX(lbox)); } if (a_hasHi[idir] == 1) { Box hbox=a_hiBox[idir]; hbox.shift(idir,1); BaseFab<Real> hiFaceFlux(a_hiBox[idir],a_nComps); int side = 1; m_domainBC->getFaceFlux(hiFaceFlux,a_phiFAB,m_origin,m_dx,idir,Side::Hi,a_dit,m_time,a_homogeneousPhysBC); FORT_REGAPPLYDOMAINFLUX_INPLACE(CHF_FRA1(a_phiFAB,comp), CHF_CONST_FRA1(hiFaceFlux,comp), CHF_CONST_REAL(m_dx[idir]), CHF_CONST_INT(side), CHF_CONST_INT(idir), CHF_BOX(hbox)); } } } }
// --------------------------------------------------------- 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 }
// Adjust boundary fluxes to account for artificial viscosity void RampIBC::artViscBC(FArrayBox& a_F, const FArrayBox& a_U, const FArrayBox& a_divVel, const int& a_dir, const Real& a_time) { CH_assert(m_isFortranCommonSet == true); CH_assert(m_isDefined == true); FArrayBox &divVel = (FArrayBox &)a_divVel; Box fluxBox = divVel.box(); fluxBox.enclosedCells(a_dir); fluxBox.grow(a_dir,1); Box loBox,hiBox,centerBox,entireBox; int hasLo,hasHi; loHiCenterFace(loBox,hasLo,hiBox,hasHi,centerBox,entireBox, fluxBox,m_domain,a_dir); if (hasLo == 1) { loBox.shiftHalf(a_dir,1); divVel.shiftHalf(a_dir,1); a_F.shiftHalf(a_dir,1); int loHiSide = -1; FORT_RAMPARTVISCF(CHF_FRA(a_F), CHF_CONST_FRA(a_U), CHF_CONST_FRA1(divVel,0), CHF_CONST_INT(loHiSide), CHF_CONST_REAL(m_dx), CHF_CONST_INT(a_dir), CHF_BOX(loBox)); loBox.shiftHalf(a_dir,-1); divVel.shiftHalf(a_dir,-1); a_F.shiftHalf(a_dir,-1); } if (hasHi == 1) { hiBox.shiftHalf(a_dir,-1); divVel.shiftHalf(a_dir,-1); a_F.shiftHalf(a_dir,-1); int loHiSide = 1; FORT_RAMPARTVISCF(CHF_FRA(a_F), CHF_CONST_FRA(a_U), CHF_CONST_FRA1(divVel,0), CHF_CONST_INT(loHiSide), CHF_CONST_REAL(m_dx), CHF_CONST_INT(a_dir), CHF_BOX(hiBox)); hiBox.shiftHalf(a_dir,1); divVel.shiftHalf(a_dir,1); a_F.shiftHalf(a_dir,1); } }
void EBGradDivFilter:: cellGradient(EBCellFAB& a_gradDiv, const EBCellFAB& a_gradVel, const EBCellFAB& a_vel, const EBFluxFAB& a_fluxVel, const EBFluxFAB& a_div, const Box& a_grid, const EBISBox& a_ebisBox, const DataIndex& a_dataIndex, bool a_multiplyByLambda, bool a_noExtrapToCovered) { CH_TIME("EBGradDivFilter::cellGradient"); int icomp = 0; EBCellFAB& lambdaFAB = m_lambda[a_dataIndex]; IntVectSet irregIVS = a_ebisBox.getIrregIVS(a_grid); for (int faceDir = 0; faceDir < SpaceDim; faceDir++) { const EBFaceFAB& faceDiv = a_div[faceDir]; const BaseFab<Real>& regFaceDiv = faceDiv.getSingleValuedFAB(); const BaseFab<Real>& regLambda = lambdaFAB.getSingleValuedFAB(); BaseFab<Real>& regGradDiv = a_gradDiv.getSingleValuedFAB(); int imultByLambda = 0; if (a_multiplyByLambda) { imultByLambda = 1; } FORT_EBGDFCELLGRAD(CHF_FRA1(regGradDiv, faceDir), CHF_CONST_FRA1(regFaceDiv, icomp), CHF_CONST_FRA1(regLambda, icomp), CHF_BOX(a_grid), CHF_CONST_REAL(m_dxFine[faceDir]), CHF_CONST_INT(faceDir), CHF_CONST_INT(imultByLambda)); //nonconservative gradient for (VoFIterator vofit(irregIVS, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit) { const VolIndex& vof = vofit(); Real gradVal = 0.0; Vector<FaceIndex> facesHi = a_ebisBox.getFaces(vof, faceDir, Side::Hi); Vector<FaceIndex> facesLo = a_ebisBox.getFaces(vof, faceDir, Side::Lo); bool zeroGrad = a_noExtrapToCovered && ((facesHi.size() == 0) || (facesLo.size() == 0)); if (zeroGrad) { gradVal = 0; } else { Real valHi= 0; if (facesHi.size() > 0) { for (int iface = 0; iface < facesHi.size(); iface++) { valHi += faceDiv(facesHi[iface], icomp); } valHi /= facesHi.size(); } else { valHi = ccpGetCoveredExtrapValue(vof, faceDir, Side::Hi, faceDiv, a_ebisBox, a_grid, m_domainFine, m_dxFine, icomp); } Real valLo= 0; if (facesLo.size() > 0) { for (int iface = 0; iface < facesLo.size(); iface++) { valLo += faceDiv(facesLo[iface], 0); } valLo /= facesLo.size(); } else { valLo = ccpGetCoveredExtrapValue(vof, faceDir, Side::Lo , faceDiv, a_ebisBox, a_grid, m_domainFine, m_dxFine, icomp); } gradVal = (valHi-valLo)/(m_dxFine[faceDir]); //multiply the lambda in since we have the area fractions lying about if (a_multiplyByLambda) { Real lambda = lambdaFAB(vof, 0); gradVal *= lambda; } } a_gradDiv(vof, faceDir) = gradVal; } } }
void EBGradDivFilter:: gradVel(EBCellFAB& a_gradVel, const EBCellFAB& a_vel, const Box& a_grid, const EBISBox& a_ebisBox, bool a_lowOrderOneSide) { CH_TIME("EBGradDivFilter::gradVel"); CH_assert(a_gradVel.nComp() == SpaceDim*SpaceDim); CH_assert(a_vel.nComp() == SpaceDim); int iLowOrderOneSide = 0; if (a_lowOrderOneSide) { iLowOrderOneSide = 1; } for (int derivDir = 0; derivDir < SpaceDim; derivDir++) { Box loBox, hiBox, centerBox; int hasLo, hasHi; EBArith::loHiCenter(loBox, hasLo, hiBox, hasHi, centerBox, m_domainFine, a_grid, derivDir); for (int velDir = 0; velDir < SpaceDim; velDir++) { BaseFab<Real>& regGradVel = a_gradVel.getSingleValuedFAB(); const BaseFab<Real>& regVel = a_vel.getSingleValuedFAB(); int gradcomp = getGradComp(velDir, derivDir); FORT_EBGDFGRADVEL(CHF_FRA1(regGradVel, gradcomp), CHF_CONST_FRA1(regVel, velDir), CHF_BOX(loBox), CHF_INT(hasLo), CHF_BOX(hiBox), CHF_INT(hasHi), CHF_BOX(centerBox), CHF_CONST_REAL(m_dxFine[derivDir]), CHF_CONST_INT(derivDir), CHF_CONST_INT(iLowOrderOneSide)); IntVectSet ivsIrreg = a_ebisBox.getIrregIVS(a_grid); if (!a_lowOrderOneSide) { ivsIrreg.grow(1); ivsIrreg &= a_grid; } for (VoFIterator vofit(ivsIrreg, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit) { const VolIndex& vof = vofit(); bool hasHi, hasLo; VolIndex vofHi, vofLo; Vector<FaceIndex> facesHi = a_ebisBox.getFaces(vof, derivDir, Side::Hi); Vector<FaceIndex> facesLo = a_ebisBox.getFaces(vof, derivDir, Side::Lo); hasHi = (facesHi.size() == 1) && (!facesHi[0].isBoundary()); hasLo = (facesLo.size() == 1) && (!facesLo[0].isBoundary()); if (hasLo) { vofLo = facesLo[0].getVoF(Side::Lo); } if (hasHi) { vofHi = facesHi[0].getVoF(Side::Hi); } Real gradVal; if (hasHi && hasLo) { gradVal = (a_vel(vofHi, velDir) - a_vel(vofLo, velDir))/(2.*m_dxFine[derivDir]); } else if (hasHi || hasLo) { //do one-sided diff CH_assert(!(hasHi && hasLo)); Side::LoHiSide side; VolIndex vofNear; if (hasLo) { side = Side::Lo; vofNear = vofLo; } else { side = Side::Hi; vofNear = vofHi; } int isign = sign(side); Vector<FaceIndex> facesFar = a_ebisBox.getFaces(vofNear, derivDir, side); bool hasVoFFar = (facesFar.size()==1) && (!facesFar[0].isBoundary()); Real valStart = a_vel(vof, velDir); Real valNear = a_vel(vofNear, velDir); if (hasVoFFar && !a_lowOrderOneSide) { VolIndex vofFar = facesFar[0].getVoF(side); Real valFar = a_vel(vofFar, velDir); gradVal = (4*(valNear - valStart)- (valFar-valStart))/(2.*isign*m_dxFine[derivDir]); } else { //do not have another point for stencil or specified low order one-sided. //drop order of derivative gradVal = (valNear - valStart)/(isign*m_dxFine[derivDir]); } } else { //only have one point, can only set gradient to zero gradVal = 0.0; } a_gradVel(vof, gradcomp) = gradVal; } } } }