// ------------------------------------------------------------ void CellToEdge(const FArrayBox& a_cellData, FArrayBox& a_edgeData, const int a_dir) { Box edgeBox = surroundingNodes(a_cellData.box(), a_dir); edgeBox.grow(a_dir,-1); edgeBox &= a_edgeData.box(); int cellComp; for (int comp = 0; comp < a_edgeData.nComp(); comp++) { if (a_cellData.nComp() == a_edgeData.nComp()) { // straightforward cell->edge averaging cellComp = comp; } else { // each cell comp represents a different spatial direction cellComp = SpaceDim*comp + a_dir; } FORT_CELLTOEDGE(CHF_CONST_FRA1(a_cellData, cellComp), CHF_FRA1(a_edgeData, comp), CHF_BOX(edgeBox), CHF_CONST_INT(a_dir)); } }
// Compute the primitive variables from the conserved variables void PolytropicPhysics::consToPrim(FArrayBox& a_W, const FArrayBox& a_U, const Box& a_box) { CH_assert(isDefined()); CH_assert(a_U.box().contains(a_box)); CH_assert(a_W.box().contains(a_box)); FORT_CONSTOPRIMF(CHF_FRA(a_W), CHF_CONST_FRA(a_U), CHF_BOX(a_box)); }
void CellBilinear::interp (const FArrayBox& crse, int crse_comp, FArrayBox& fine, int fine_comp, int ncomp, const Box& fine_region, const IntVect & ratio, const Geometry& /*crse_geom*/, const Geometry& /*fine_geom*/, Array<BCRec>& /*bcr*/, int actual_comp, int actual_state) { BL_PROFILE("CellBilinear::interp()"); #if (BL_SPACEDIM == 3) BoxLib::Error("interp: not implemented"); #endif // // Set up to call FORTRAN. // const int* clo = crse.box().loVect(); const int* chi = crse.box().hiVect(); const int* flo = fine.loVect(); const int* fhi = fine.hiVect(); const int* lo = fine_region.loVect(); const int* hi = fine_region.hiVect(); int num_slope = D_TERM(2,*2,*2)-1; int len0 = crse.box().length(0); int slp_len = num_slope*len0; Array<Real> slope(slp_len); int strp_len = len0*ratio[0]; Array<Real> strip(strp_len); int strip_lo = ratio[0] * clo[0]; int strip_hi = ratio[0] * chi[0]; const Real* cdat = crse.dataPtr(crse_comp); Real* fdat = fine.dataPtr(fine_comp); const int* ratioV = ratio.getVect(); FORT_CBINTERP (cdat,ARLIM(clo),ARLIM(chi),ARLIM(clo),ARLIM(chi), fdat,ARLIM(flo),ARLIM(fhi),ARLIM(lo),ARLIM(hi), D_DECL(&ratioV[0],&ratioV[1],&ratioV[2]),&ncomp, slope.dataPtr(),&num_slope,strip.dataPtr(),&strip_lo,&strip_hi, &actual_comp,&actual_state); }
void VCAMRPoissonOp2::getFlux(FArrayBox& a_flux, const FArrayBox& a_data, const FluxBox& a_bCoef, const Box& a_facebox, int a_dir, int a_ref) const { CH_TIME("VCAMRPoissonOp2::getFlux"); CH_assert(a_dir >= 0); CH_assert(a_dir < SpaceDim); CH_assert(!a_data.box().isEmpty()); CH_assert(!a_facebox.isEmpty()); // probably the simplest way to test centering // a_box needs to be face-centered in the a_dir Box faceTestBox(IntVect::Zero, IntVect::Unit); faceTestBox.surroundingNodes(a_dir); CH_assert(a_facebox.type() == faceTestBox.type()); const FArrayBox& bCoefDir = a_bCoef[a_dir]; // reality check for bCoef CH_assert(bCoefDir.box().contains(a_facebox)); a_flux.resize(a_facebox, a_data.nComp()); BoxIterator bit(a_facebox); Real scale = m_beta * a_ref / m_dx; for ( bit.begin(); bit.ok(); bit.next()) { IntVect iv = bit(); IntVect shiftiv = BASISV(a_dir); IntVect ivlo = iv - shiftiv; IntVect ivhi = iv; CH_assert(a_data.box().contains(ivlo)); CH_assert(a_data.box().contains(ivhi)); for (int ivar = 0; ivar < a_data.nComp(); ivar++) { Real phihi = a_data(ivhi,ivar); Real philo = a_data(ivlo,ivar); Real gradphi = (phihi - philo ) * scale; a_flux(iv,ivar) = -bCoefDir(iv, ivar) * gradphi; } } }
void LinElastPhysics::consToPrim(FArrayBox& a_W, const FArrayBox& a_U, const Box& a_box) { //JK Our primitives are our conserved variables //JK pout() << "LinElastPhysics::consToPrim" << endl; CH_assert(isDefined()); CH_assert(a_U.box().contains(a_box)); CH_assert(a_W.box().contains(a_box)); FORT_COPYF(CHF_FRA(a_W), CHF_CONST_FRA(a_U), CHF_BOX(a_box)); }
// ------------------------------------------------------------ void CellToEdge(const FArrayBox& a_cellData, const int a_cellComp, FArrayBox& a_edgeData, const int a_edgeComp, const int a_dir) { Box edgeBox = surroundingNodes(a_cellData.box(),a_dir); edgeBox.grow(a_dir, -1); edgeBox &= a_edgeData.box(); FORT_CELLTOEDGE(CHF_CONST_FRA1(a_cellData,a_cellComp), CHF_FRA1(a_edgeData,a_edgeComp), CHF_BOX(edgeBox), CHF_CONST_INT(a_dir)); }
void NewPoissonOp:: levelGSRB(FArrayBox& a_phi, const FArrayBox& a_rhs) { CH_assert(a_phi.nComp() == a_rhs.nComp()); Real dx = m_dx[0]; // do first red, then black passes for (int whichPass =0; whichPass <= 1; whichPass++) { m_bc(a_phi, m_domain.domainBox(), m_domain, dx, true); // now step through grids... //fill in intersection of ghostcells and a_phi's boxes // dfm -- for a 5 point stencil, this should not be necessary //a_phi.exchange(a_phi.interval(), m_exchangeCopier); // invoke physical BC's where necessary //m_bc(a_phi, m_domain, dx, true); //new approach to help with checker #ifndef NDEBUG #endif FORT_GSRBLAPLACIAN(CHF_FRA(a_phi), CHF_CONST_FRA(a_rhs), CHF_BOX(a_rhs.box()), CHF_CONST_REAL(dx), CHF_CONST_INT(whichPass)); } // end loop through red-black }
// Set boundary slopes: // The boundary slopes in a_dW are already set to one sided difference // approximations. If this function doesn't change them they will be // used for the slopes at the boundaries. void ExplosionIBC::setBdrySlopes(FArrayBox& a_dW, const FArrayBox& a_W, const int& a_dir, const Real& a_time) { CH_assert(m_isFortranCommonSet == true); CH_assert(m_isDefined == true); // In periodic case, this doesn't do anything if (!m_domain.isPeriodic(a_dir)) { Box loBox,hiBox,centerBox,domain; int hasLo,hasHi; Box slopeBox = a_dW.box(); slopeBox.grow(a_dir,1); // Generate the domain boundary boxes, loBox and hiBox, if there are // domain boundarys there loHiCenter(loBox,hasLo,hiBox,hasHi,centerBox,domain, slopeBox,m_domain,a_dir); // Set the boundary slopes if necessary if ((hasLo != 0) || (hasHi != 0)) { FORT_SLOPEBCSF(CHF_FRA(a_dW), CHF_CONST_FRA(a_W), CHF_CONST_INT(a_dir), CHF_BOX(loBox), CHF_CONST_INT(hasLo), CHF_BOX(hiBox), CHF_CONST_INT(hasHi)); } } }
void PatchGodunov::updateState(FArrayBox& a_U, FluxBox& a_F, Real& a_maxWaveSpeed, const FArrayBox& a_S, const Real& a_dt, const Box& a_box) { CH_assert(isDefined()); CH_assert(a_box == m_currentBox); int numPrim = m_gdnvPhysics->numPrimitives(); int numFlux = m_gdnvPhysics->numFluxes(); FluxBox whalf(a_box,numPrim); whalf.setVal(0.0); a_F.resize(a_box,numFlux); a_F.setVal(0.0); computeWHalf(whalf, a_U, a_S, a_dt, a_box); FArrayBox dU(a_U.box(),a_U.nComp()); computeUpdate(dU, a_F, a_U, whalf, a_dt, a_box); a_U += dU; // Get and return the maximum wave speed on this patch/grid a_maxWaveSpeed = m_gdnvPhysics->getMaxWaveSpeed(a_U, m_currentBox); }
// Set boundary fluxes void RampIBC::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_isFortranCommonSet == true); CH_assert(m_isDefined == true); // Neither the x or y direction can be periodic if ((a_dir == 0 || a_dir == 1) && m_domain.isPeriodic(a_dir)) { MayDay::Error("RampIBC::primBC: Neither the x or y boundaries can be periodic"); } Box boundaryBox; getBoundaryFaces(boundaryBox, a_WGdnv.box(), a_dir, a_side); if (! boundaryBox.isEmpty() ) { // Set the boundary fluxes int lohisign = sign(a_side); FORT_RAMPBCF(CHF_FRA(a_WGdnv), CHF_CONST_FRA(a_Wextrap), CHF_CONST_FRA(a_W), CHF_CONST_REAL(a_time), CHF_CONST_INT(lohisign), CHF_CONST_REAL(m_dx), CHF_CONST_INT(a_dir), CHF_BOX(boundaryBox)); } }
void CellToEdge(const FArrayBox& a_cellData, FluxBox& a_edgeData) { // loop over components -- assumption is that in cell-centered // data, direction changes faster than component int cellcomp; for (int comp = 0; comp < a_edgeData.nComp(); comp++) { // loop over directions for (int dir = 0; dir < SpaceDim; dir++) { // define faces over which we can do averaging Box edgeBox = surroundingNodes(a_cellData.box(), dir); edgeBox.grow(dir,-1); edgeBox &= a_edgeData[dir].box(); if (a_cellData.nComp() == a_edgeData.nComp()) { // straightforward cell->edge averaging cellcomp = comp; } else { // each cell comp represents a different spatial direction cellcomp = SpaceDim*comp + dir; } FORT_CELLTOEDGE(CHF_CONST_FRA1(a_cellData, cellcomp), CHF_FRA1(a_edgeData[dir], comp), CHF_BOX(edgeBox), CHF_CONST_INT(dir)); } } }
/** Given input left and right states in a direction, a_dir, compute a Riemann problem and generate fluxes at the faces within a_box. */ void LinElastPhysics::riemann(/// face-centered solution to Riemann problem FArrayBox& a_WStar, /// left state, on cells to left of each face const FArrayBox& a_WLeft, /// right state, on cells to right of each face const FArrayBox& a_WRight, /// state on cells, used to set boundary conditions const FArrayBox& a_W, /// current time const Real& a_time, /// direction of faces const int& a_dir, /// face-centered box on which to set a_WStar const Box& a_box) { //JK pout() << "LinElastPhysics::riemann" << endl; CH_assert(isDefined()); CH_assert(a_WStar.box().contains(a_box)); // Get the numbers of relevant variables int numPrim = numPrimitives(); CH_assert(a_WStar .nComp() == numPrim); CH_assert(a_WLeft .nComp() == numPrim); CH_assert(a_WRight.nComp() == numPrim); // Cast away "const" inputs so their boxes can be shifted left or right // 1/2 cell and then back again (no net change is made!) FArrayBox& shiftWLeft = (FArrayBox&)a_WLeft; FArrayBox& shiftWRight = (FArrayBox&)a_WRight; // Solution to the Riemann problem // Shift the left and right primitive variable boxes 1/2 cell so they are // face centered shiftWLeft .shiftHalf(a_dir, 1); shiftWRight.shiftHalf(a_dir,-1); CH_assert(shiftWLeft .box().contains(a_box)); CH_assert(shiftWRight.box().contains(a_box)); // Riemann solver computes Wgdnv all edges that are not on the physical // boundary. FORT_RIEMANNF(CHF_FRA(a_WStar), CHF_CONST_FRA(shiftWLeft), CHF_CONST_FRA(shiftWRight), CHF_CONST_INT(a_dir), CHF_BOX(a_box)); // Call boundary Riemann solver (note: periodic BC's are handled there). m_bc->primBC(a_WStar,shiftWLeft ,a_W,a_dir,Side::Hi,a_time); m_bc->primBC(a_WStar,shiftWRight,a_W,a_dir,Side::Lo,a_time); // Shift the left and right primitive variable boxes back to their original // position. shiftWLeft .shiftHalf(a_dir,-1); shiftWRight.shiftHalf(a_dir, 1); }
void ABec4::bCoefficients (const FArrayBox& _b, int gridno) { BL_ASSERT(_b.box().contains((bcoefs[0])->boxArray()[gridno])); invalidate_b_to_level(0); (*bcoefs[0])[gridno].copy(_b,0,0,bcoefs[0]->nComp()); }
void GodunovPhysics::artVisc(FArrayBox& a_F, const FArrayBox& a_U, const Real& a_artificialViscosity, const Real& a_currentTime, const int& a_dir, const Box& a_box) { CH_assert(a_U.box().contains(a_box)); // a_box: valid cells // Take the cell-centered box, a_box, and derive a face-centered box in // direction a_dir. // faceBox consists of all a_dir-faces of valid cells. Box faceBox = a_box; faceBox &= m_domain; faceBox.surroundingNodes(a_dir); CH_assert(a_F.box().contains(faceBox)); // Derive a cell-centered box where the primitive variables are needed. // wBox consists of valid cells grown by 1, intersected with m_domain. Box wBox = faceBox; wBox.enclosedCells(a_dir); wBox.grow(1); wBox &= m_domain; // Get the primitive variables from the conserved variables (as needed). int numPrim = numPrimitives(); FArrayBox W(wBox, numPrim); consToPrim(W, a_U, wBox); // W on valid cells + 1 layer of ghosts // Compute the divergence of the velocity FArrayBox divu(faceBox, 1); Interval velInt = velocityInterval(); m_util.divVel(divu, W, velInt, a_dir, faceBox); // If using fourth-order artificial viscosity, apply the nonlinear operator to // divu. if (m_useFourthOrderArtificialViscosity) m_util.divVelHO(divu, W, a_dir, faceBox, this); // Change fluxes due to artificial viscosity on the interior faces m_util.artificialViscosity(a_F, a_U, divu, a_artificialViscosity, a_dir, faceBox); // Change fluxes due to artificial viscosity on the boundary faces m_bc->artViscBC(a_F, a_U, divu, a_dir, a_currentTime); }
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 NewPoissonOp:: createCoarsened(FArrayBox& a_lhs, const FArrayBox& a_rhs, const int & a_refRat) { int ncomp = a_rhs.nComp(); //fill ebislayout Box coarsenedBox = coarsen(a_rhs.box(), a_refRat); a_lhs.define(coarsenedBox, ncomp); }
void LevelFluxRegisterEdge::incrementCoarse(FArrayBox& a_coarseFlux, Real a_scale, const DataIndex& a_coarseDataIndex, const Interval& a_srcInterval, const Interval& a_dstInterval) { CH_assert(isDefined()); CH_assert(!a_coarseFlux.box().isEmpty()); CH_assert(a_srcInterval.size() == a_dstInterval.size()); CH_assert(a_srcInterval.begin() >= 0); CH_assert(a_srcInterval.end() < a_coarseFlux.nComp()); CH_assert(a_dstInterval.begin() >= 0); CH_assert(a_dstInterval.end() < m_nComp); // get edge-centering of coarseFlux const Box& edgeBox = a_coarseFlux.box(); int edgeDir = -1; for (int dir=0; dir<SpaceDim; dir++) { if (edgeBox.type(dir) == IndexType::CELL) { if (edgeDir == -1) { edgeDir = dir; } else { // already found a cell-centered direction (should only be // one for edge-centering) MayDay::Error("LevelFluxRegisterEdge::incrementCoarse -- e-field not edge-centered"); } } } // end loop over directions CH_assert(edgeDir != -1); FArrayBox& thisCrseReg = m_regCoarse[a_coarseDataIndex][edgeDir]; thisCrseReg.plus(a_coarseFlux, -a_scale, a_srcInterval.begin(), a_dstInterval.begin(), a_srcInterval.size()); }
void RSIBC::updateBoundary(const FArrayBox& a_WHalf,int a_dir,const Real& a_dt,const Real& a_dx,const Real& a_time,const bool a_final) { if(a_dir == 1 && bdryLo(m_domain,a_dir).contains(bdryLo(a_WHalf.box(),a_dir))) { if(a_final) { FORT_RSSETBND( CHF_FRA((*m_bdryData)), CHF_BOX(bdryLo(a_WHalf.box(),a_dir)), CHF_CONST_FRA((*m_bdryData)), CHF_CONST_FRA(a_WHalf), CHF_CONST_REAL(a_dt), CHF_CONST_REAL(a_dx), CHF_CONST_REAL(a_time)); } // THIS MAY BE NECESSARY IN 3-D, NOT SURE!!! // else if(m_tmpBdryDataSet) // { // FORT_RSSETBND( // CHF_FRA((*m_tmpBdryData)), // CHF_BOX(bdryLo(a_WHalf.box(),a_dir)), // CHF_CONST_FRA((*m_tmpBdryData)), // CHF_CONST_FRA(a_WHalf), // CHF_CONST_REAL(a_dt), // CHF_CONST_REAL(a_dx), // CHF_CONST_REAL(a_time)); // } else { // m_tmpBdryData = new FArrayBox(m_bdryData->box(), m_numBdryVars); FORT_RSSETBND( CHF_FRA((*m_tmpBdryData)), CHF_BOX(bdryLo(a_WHalf.box(),a_dir)), CHF_CONST_FRA((*m_bdryData)), CHF_CONST_FRA(a_WHalf), CHF_CONST_REAL(a_dt), CHF_CONST_REAL(a_dx), CHF_CONST_REAL(a_time)); m_tmpBdryDataSet = true; } } }
void NewPoissonOp::prolongIncrement(FArrayBox& a_phiThisLevel, const FArrayBox& a_correctCoarse) { FArrayBox& phi = a_phiThisLevel; const FArrayBox& coarse = a_correctCoarse; //FArrayBox& c = (FArrayBox&)coarse; Box region = a_phiThisLevel.box(); region.grow(-1); Box cBox = a_correctCoarse.box(); cBox.grow(-1); CH_assert(cBox == coarsen(region, 2)); int r = 2; FORT_PROLONG(CHF_FRA(phi), CHF_CONST_FRA(coarse), CHF_BOX(region), CHF_CONST_INT(r)); }
void EdgeToCellMax(const FluxBox& a_edgeData, const int a_edgeComp, FArrayBox& a_cellData, const int a_cellComp, const int a_dir) { const Box& cellBox = a_cellData.box(); FORT_EDGETOCELLMAX(CHF_CONST_FRA1(a_edgeData[a_dir],a_edgeComp), CHF_FRA1(a_cellData, a_cellComp), CHF_BOX(cellBox), CHF_CONST_INT(a_dir)); }
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 NewPoissonOp::createCoarser(FArrayBox& a_coarse, const FArrayBox& a_fine, bool ghosted) { Box c = a_fine.box(); if (ghosted) { c.grow(-1); } c.coarsen(2); c.refine(2); if (ghosted) c.grow(1); CH_assert(c == a_fine.box()); if (ghosted) c.grow(-1); c.coarsen(2); if (ghosted) { c.grow(1); } a_coarse.define(c, a_fine.nComp()); }
void NodeBilinear::interp (const FArrayBox& crse, int crse_comp, FArrayBox& fine, int fine_comp, int ncomp, const Box& fine_region, const IntVect& ratio, const Geometry& /*crse_geom */, const Geometry& /*fine_geom */, Array<BCRec>& /*bcr*/, int actual_comp, int actual_state) { BL_PROFILE("NodeBilinear::interp()"); // // Set up to call FORTRAN. // const int* clo = crse.box().loVect(); const int* chi = crse.box().hiVect(); const int* flo = fine.loVect(); const int* fhi = fine.hiVect(); const int* lo = fine_region.loVect(); const int* hi = fine_region.hiVect(); int num_slope = D_TERM(2,*2,*2)-1; int len0 = crse.box().length(0); int slp_len = num_slope*len0; Array<Real> strip(slp_len); const Real* cdat = crse.dataPtr(crse_comp); Real* fdat = fine.dataPtr(fine_comp); const int* ratioV = ratio.getVect(); FORT_NBINTERP (cdat,ARLIM(clo),ARLIM(chi),ARLIM(clo),ARLIM(chi), fdat,ARLIM(flo),ARLIM(fhi),ARLIM(lo),ARLIM(hi), D_DECL(&ratioV[0],&ratioV[1],&ratioV[2]),&ncomp, strip.dataPtr(),&num_slope,&actual_comp,&actual_state); }
// Compute a Riemann problem and generate fluxes at the faces. void PolytropicPhysics::riemann(FArrayBox& a_WGdnv, const FArrayBox& a_WLeft, const FArrayBox& a_WRight, const FArrayBox& a_W, const Real& a_time, const int& a_dir, const Box& a_box) { CH_assert(isDefined()); CH_assert(a_WGdnv.box().contains(a_box)); // Get the numbers of relevant variables int numPrim = numPrimitives(); CH_assert(a_WGdnv .nComp() == numPrim); CH_assert(a_WLeft .nComp() == numPrim); CH_assert(a_WRight.nComp() == numPrim); // Cast away "const" inputs so their boxes can be shifted left or right // 1/2 cell and then back again (no net change is made!) FArrayBox& shiftWLeft = (FArrayBox&)a_WLeft; FArrayBox& shiftWRight = (FArrayBox&)a_WRight; // Solution to the Riemann problem // Shift the left and right primitive variable boxes 1/2 cell so they are // face centered shiftWLeft .shiftHalf(a_dir, 1); shiftWRight.shiftHalf(a_dir,-1); CH_assert(shiftWLeft .box().contains(a_box)); CH_assert(shiftWRight.box().contains(a_box)); // Riemann solver computes Wgdnv all edges that are not on the physical // boundary. FORT_RIEMANNF(CHF_FRA(a_WGdnv), CHF_CONST_FRA(shiftWLeft), CHF_CONST_FRA(shiftWRight), CHF_CONST_INT(a_dir), CHF_BOX(a_box)); // Call boundary Riemann solver (note: periodic BC's are handled there). m_bc->primBC(a_WGdnv,shiftWLeft ,a_W,a_dir,Side::Hi,a_time); m_bc->primBC(a_WGdnv,shiftWRight,a_W,a_dir,Side::Lo,a_time); // Shift the left and right primitive variable boxes back to their original // position. shiftWLeft .shiftHalf(a_dir,-1); shiftWRight.shiftHalf(a_dir, 1); }
void LinElastPhysics::artVisc(FArrayBox& a_F, const FArrayBox& a_U, const Real& a_artificialViscosity, const Real& a_currentTime, const int& a_dir, const Box& a_box) { MayDay::Error("artVisc needs to be thought through more!"); CH_assert(a_U.box().contains(a_box)); // Take the cell centered box, a_box, and derive a face centered box in // direction a_dir Box faceBox = a_box; faceBox &= m_domain; faceBox.surroundingNodes(a_dir); CH_assert(a_F.box().contains(faceBox)); // Note: a_box is face centered in the a_dir direction and is set up for // updating a_F // Remove any boundary faces in direction a_dir from a_box Box noBoundaryBox = faceBox; noBoundaryBox.enclosedCells(a_dir); noBoundaryBox.grow(a_dir,1); noBoundaryBox &= m_domain; noBoundaryBox.grow(a_dir,-1); noBoundaryBox.surroundingNodes(a_dir); FORT_ARTDISP(CHF_FRA(a_F), CHF_CONST_FRA(a_U), CHF_CONST_REAL(a_artificialViscosity), CHF_CONST_INT(a_dir), CHF_BOX(noBoundaryBox)); // Change fluxes due to artificial viscosity on the boundary faces // m_bc->artViscBC(a_F,a_U,divu,a_dir,a_currentTime); }
bool RSIBC::tagCellsInit(FArrayBox& markFAB,const Real& threshold) { // If grid spacing > R0 refine otherwise only refine the nucleation patch if(m_dx > m_R0) { // pout() << m_dx << " " << m_R0 << endl; markFAB.setVal(1,bdryLo(m_domain.domainBox(),1,1) & markFAB.box(),0); } else { IntVect nucSm; IntVect nucBg; if(SpaceDim > 0) { nucSm.setVal(0,floor(m_x0/m_dx)); nucBg.setVal(0, ceil(m_x0/m_dx)); } if(SpaceDim > 1) { nucSm.setVal(1,0); nucBg.setVal(1,0); } if(SpaceDim > 2) { nucSm.setVal(2,floor(m_x0/m_dx)); nucBg.setVal(2, ceil(m_x0/m_dx)); } markFAB.setVal(1,Box(nucSm,nucBg)& markFAB.box(),0); } // pout() << m_domain << endl; // FORT_ALLBOUNDREFINE( // CHF_FRA1(markFAB,0), // CHF_CONST_REAL(threshold), // CHF_BOX(markFAB.box())); return true; }
// this preconditioner first initializes phihat to (IA)phihat = rhshat // (diagonization of L -- A is the matrix version of L) // then smooths with a couple of passes of levelGSRB void NewPoissonOp::preCond( FArrayBox& a_phi, const FArrayBox& a_rhs) { // diagonal term of this operator is 4/h/h in 2D, 6/h/h in 3D, // so inverse of this is our initial multiplier Real mult = -m_dx[0]*m_dx[0]/(2.0*SpaceDim); Interval comps = a_phi.interval(); CH_assert(a_phi.nComp() == a_rhs.nComp()); a_phi.copy(a_rhs.box(), comps, a_rhs.box(), a_rhs, comps); a_phi *= mult; relax(a_phi, a_rhs, 2); }
// Set boundary fluxes void ExplosionIBC::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_isFortranCommonSet == true); CH_assert(m_isDefined == true); // In periodic case, this doesn't do anything if (!m_domain.isPeriodic(a_dir)) { int lohisign; Box tmp = a_WGdnv.box(); // Determine which side and thus shifting directions lohisign = sign(a_side); 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_SOLIDBCF(CHF_FRA(a_WGdnv), CHF_CONST_FRA(a_Wextrap), CHF_CONST_FRA(a_W), CHF_CONST_INT(lohisign), CHF_CONST_INT(a_dir), CHF_BOX(boundaryBox)); } } }
// Compute increment of primitive variables. void PolytropicPhysics::quasilinearUpdate(FArrayBox& a_dWdx, const FArrayBox& a_WHalf, const FArrayBox& a_W, const Real& a_scale, const int& a_dir, const Box& a_box) { CH_assert(isDefined()); CH_assert(a_dWdx.box().contains(a_box)); FORT_GETADWDXF(CHF_FRA(a_dWdx), CHF_CONST_FRA(a_WHalf), CHF_CONST_FRA(a_W), CHF_CONST_REAL(a_scale), CHF_CONST_INT(a_dir), CHF_BOX(a_box)); }
/** Compute dU = dt*dUdt, the change in the conserved variables over the time step. The fluxes are returned are suitable for use in refluxing. This has a default implementation but can be redefined as needed. */ void LinElastPhysics::computeUpdate(FArrayBox& a_dU, FluxBox& a_F, const FArrayBox& a_U, const FluxBox& a_WHalf, const bool& a_useArtificialViscosity, const Real& a_artificialViscosity, const Real& a_currentTime, const Real& a_dx, const Real& a_dt, const Box& a_box) { CH_assert(isDefined()); a_dU.setVal(0.0); for (int idir = 0; idir < SpaceDim; idir++) { // Get flux from WHalf getFlux(a_F[idir],a_WHalf[idir],idir,a_F[idir].box()); if (a_useArtificialViscosity) { artVisc(a_F[idir],a_U, a_artificialViscosity,a_currentTime, idir,a_box); } // Compute flux difference fHi-fLo FArrayBox diff(a_dU.box(), a_dU.nComp()); diff.setVal(0.0); FORT_FLUXDIFFF(CHF_FRA(diff), CHF_CONST_FRA(a_F[idir]), CHF_CONST_INT(idir), CHF_BOX(a_box)); // Add flux difference to dU a_dU += diff; ((LEPhysIBC*)m_bc)->updateBoundary(a_WHalf[idir],idir,a_dt,a_dx,a_currentTime+a_dt,true); } // Multiply dU by dt/dx because that is what the output expects a_dU *= -a_dt / a_dx; }