Exemplo n.º 1
0
void
EBPoissonOp::
applyOpRegularAllDirs(Box * a_loBox,
                      Box * a_hiBox,
                      int * a_hasLo,
                      int * a_hasHi,
                      Box & a_curDblBox,
                      Box & a_curPhiBox,
                      int a_nComps,
                      BaseFab<Real> & a_curOpPhiFAB,
                      const BaseFab<Real> & a_curPhiFAB,
                      bool a_homogeneousPhysBC,
                      const DataIndex& a_dit,
                      const Real& a_beta)
{
  CH_TIME("EBPoissonOp::applyOpRegularAllDirs");
  CH_assert(m_domainBC != NULL);

  //need to monkey with the ghost cells to account for boundary conditions
  BaseFab<Real>& phiFAB = (BaseFab<Real>&) a_curPhiFAB;
  applyDomainFlux(a_loBox, a_hiBox, a_hasLo, a_hasHi,
                  a_curDblBox, a_nComps, phiFAB,
                  a_homogeneousPhysBC, a_dit,m_beta);

  for (int comp = 0; comp<a_nComps; comp++)
    {

      FORT_REGGET1DLAPLACIAN_INPLACE(CHF_FRA1(a_curOpPhiFAB,comp),
                                     CHF_CONST_FRA1(a_curPhiFAB,comp),
                                     CHF_CONST_REAL(a_beta),
                                     CHF_CONST_REALVECT(m_dx),
                                     CHF_BOX(a_curDblBox));
    }
}
Exemplo n.º 2
0
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));
        }
    }
}
Exemplo n.º 3
0
// ------------------------------------------------------------
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));
    }

}
Exemplo n.º 4
0
void
EBMGAverage::averageFAB(EBCellFAB&       a_coar,
                        const Box&       a_boxCoar,
                        const EBCellFAB& a_refCoar,
                        const DataIndex& a_datInd,
                        const Interval&  a_variables) const
{
  CH_TIMERS("EBMGAverage::average");
  CH_TIMER("regular_average", t1);
  CH_TIMER("irregular_average", t2);
  CH_assert(isDefined());

  const Box& coarBox = a_boxCoar;

  //do all cells as if they were regular
  Box refBox(IntVect::Zero, IntVect::Zero);
  refBox.refine(m_refRat);
  int numFinePerCoar = refBox.numPts();

  BaseFab<Real>& coarRegFAB =             a_coar.getSingleValuedFAB();
  const BaseFab<Real>& refCoarRegFAB = a_refCoar.getSingleValuedFAB();

  //set to zero because the fortran is a bit simpleminded
  //and does stuff additively
  a_coar.setVal(0.);
  CH_START(t1);
  for (int comp = a_variables.begin();  comp <= a_variables.end(); comp++)
    {
      FORT_REGAVERAGE(CHF_FRA1(coarRegFAB,comp),
                      CHF_CONST_FRA1(refCoarRegFAB,comp),
                      CHF_BOX(coarBox),
                      CHF_BOX(refBox),
                      CHF_CONST_INT(numFinePerCoar),
                      CHF_CONST_INT(m_refRat));
    }
  CH_STOP(t1);

  //this is really volume-weighted averaging even though it does
  //not look that way.

  //so (in the traditional sense) we want to preserve
  //rhoc * volc = sum(rhof * volf)
  //this translates to
  //volfrac_C * rhoC = (1/numFinePerCoar)(sum(volFrac_F * rhoF))
  //but the data input to this routine is all kappa weigthed so
  //the volumefractions have already been multiplied
  //which means
  // rhoC = (1/numFinePerCoar)(sum(rhoF))
  //which is what this does

  CH_START(t2);
  for (int comp = a_variables.begin();  comp <= a_variables.end(); comp++)
    {
      m_averageEBStencil[a_datInd]->apply(a_coar, a_refCoar, false, comp);
    }
  CH_STOP(t2);

}
Exemplo n.º 5
0
void EdgeToCell(const FluxBox& a_edgeData, const int a_edgeComp,
                FArrayBox& a_cellData, const int a_cellComp,
                const Box& a_cellBox, const int a_dir)
{

  FORT_EDGETOCELL(CHF_CONST_FRA1(a_edgeData[a_dir],a_edgeComp),
                  CHF_FRA1(a_cellData, a_cellComp),
                  CHF_BOX(a_cellBox),
                  CHF_CONST_INT(a_dir));
}
Exemplo n.º 6
0
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));
}
Exemplo n.º 7
0
void EBPoissonOp::
GSColorAllRegular(LevelData<EBCellFAB>&        a_phi,
                  const LevelData<EBCellFAB>&  a_rhs,
                  const IntVect&               a_color,
                  const Real&                  a_weight,
                  const bool&                  a_homogeneousPhysBC)
{
  CH_TIME("EBPoissonOp::GSColorAllRegular");
  CH_assert(a_rhs.ghostVect() == m_ghostCellsRHS);
  CH_assert(a_phi.ghostVect() == m_ghostCellsPhi);

  int nComps = a_phi.nComp();
  for (DataIterator dit = a_phi.dataIterator(); dit.ok(); ++dit)
    {
      Box dblBox(m_eblg.getDBL().get(dit()));
      BaseFab<Real>& phiFAB       = (a_phi[dit()] ).getSingleValuedFAB();
      const BaseFab<Real>& rhsFAB = (a_rhs[dit()] ).getSingleValuedFAB();

      Box loBox[SpaceDim],hiBox[SpaceDim];
      int hasLo[SpaceDim],hasHi[SpaceDim];

      applyDomainFlux(loBox, hiBox, hasLo, hasHi,
                      dblBox, nComps, phiFAB,
                      a_homogeneousPhysBC, dit(),m_beta);

      IntVect loIV = dblBox.smallEnd();
      IntVect hiIV = dblBox.bigEnd();

      for (int idir = 0; idir < SpaceDim; idir++)
        {
          if (loIV[idir] % 2 != a_color[idir])
            {
              loIV[idir]++;
            }
        }

      if (loIV <= hiIV)
        {
          Box coloredBox(loIV, hiIV);

          for (int comp=0; comp<a_phi.nComp(); comp++)
            {
              FORT_DOALLREGULARMULTICOLOR(CHF_FRA1(phiFAB,comp),
                                          CHF_CONST_FRA1(rhsFAB,comp),
                                          CHF_CONST_REAL(a_weight),
                                          CHF_CONST_REAL(m_alpha),
                                          CHF_CONST_REAL(m_beta),
                                          CHF_CONST_REALVECT(m_dx),
                                          CHF_BOX(coloredBox));
            }
        }
    }
}
Exemplo n.º 8
0
// Compute the speed of sound
void PolytropicPhysics::soundSpeed(FArrayBox& a_speed,
                                   const FArrayBox& a_U,
                                   const Box&       a_box)
{
    CH_assert(isDefined());
    CH_assert(a_U.contains(a_box));
    CH_assert(a_speed.contains(a_box));

    FORT_SOUNDSPEEDF(CHF_CONST_FRA1(a_speed, 0),
                     CHF_CONST_FRA(a_U),
                     CHF_BOX(a_box));
}
Exemplo n.º 9
0
// ------------------------------------------------------------
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));
}
Exemplo n.º 10
0
void
EBMGInterp::pwcInterpFAB(EBCellFAB&       a_refCoar,
                         const Box&       a_coarBox,
                         const EBCellFAB& a_coar,
                         const DataIndex& a_datInd,
                         const Interval&  a_variables) const
{
  CH_TIMERS("EBMGInterp::interp");
  CH_TIMER("regular_interp", t1);
  CH_TIMER("irregular_interp", t2);
  CH_assert(isDefined());

  const Box& coarBox = a_coarBox;

  for (int ivar = a_variables.begin();  ivar <= a_variables.end(); ivar++)
    {
      m_interpEBStencil[a_datInd]->cache(a_refCoar, ivar);

      //do all cells as if they were regular
      Box refBox(IntVect::Zero, IntVect::Zero);
      refBox.refine(m_refRat);

      const BaseFab<Real>& coarRegFAB =    a_coar.getSingleValuedFAB();
      BaseFab<Real>& refCoarRegFAB    = a_refCoar.getSingleValuedFAB();

      CH_START(t1);

      FORT_REGPROLONG(CHF_FRA1(refCoarRegFAB,ivar),
                      CHF_CONST_FRA1(coarRegFAB,ivar),
                      CHF_BOX(coarBox),
                      CHF_BOX(refBox),
                      CHF_CONST_INT(m_refRat));

      CH_STOP(t1);

      m_interpEBStencil[a_datInd]->uncache(a_refCoar, ivar);

      CH_START(t2);
      m_interpEBStencil[a_datInd]->apply(a_refCoar, a_coar, true, ivar);
      CH_STOP(t2);
    }
}
Exemplo n.º 11
0
// ----------------------------------------------------------------
void EdgeToCell(const FluxBox& a_edgeData,
                FArrayBox& a_cellData)
{
  // loop over components -- assumption is that in cell-centered
  // data, direction changes faster than component.
  for (int comp = 0; comp<a_edgeData.nComp(); comp++)
    {
      // loop over directions
      for (int dir = 0; dir < SpaceDim; dir++)
        {
          Box cellBox = a_cellData.box();
          cellBox &= a_edgeData.box();
          int cellcomp = SpaceDim*comp + dir;
          FORT_EDGETOCELL(CHF_CONST_FRA1(a_edgeData[dir],comp),
                          CHF_FRA1(a_cellData, cellcomp),
                          CHF_BOX(cellBox),
                          CHF_CONST_INT(dir));
        } // end loop over directions
    } // end loop over components
}
Exemplo n.º 12
0
void NewPoissonOp::
levelRelaxColor(FArrayBox&       a_phi,
                const FArrayBox& a_rhs,
                const IntVect&   a_color,
                const Real&      a_weight,
                const bool&      a_homogeneousPhysBC)
{
  CH_assert(a_phi.nComp() == 1);

  Box dblBox = a_rhs.box();

  //apply domain boundary condtions
  m_bc(a_phi, m_domain.domainBox(), m_domain, m_dx[0], a_homogeneousPhysBC);

  //find box over which we are iterating
  IntVect loIV = dblBox.smallEnd();
  IntVect hiIV = dblBox.bigEnd();

  for (int idir = 0; idir < SpaceDim; idir++)
    {
      if (loIV[idir] % 2 != a_color[idir])
        {
          loIV[idir]++;
        }
    }

  if (loIV <= hiIV)
    {
      Box coloredBox(loIV, hiIV);
      int comp = 0;
      Real alpha = 0;
      Real beta = 1.;
      FORT_AMRPMULTICOLOR(CHF_FRA1(a_phi,comp),
                          CHF_CONST_FRA1(a_rhs,comp),
                          CHF_CONST_REAL(a_weight),
                          CHF_CONST_REAL(alpha),
                          CHF_CONST_REAL(beta),
                          CHF_CONST_REALVECT(m_dx),
                          CHF_BOX(coloredBox));
    }
}
Exemplo n.º 13
0
/// Set boundary primitive values.
void RSIBC::primBC(FArrayBox&            a_WGdnv,
    const FArrayBox&      a_WShiftInside,
    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_isFortranCommonLESet == true);
    CH_assert(m_isDefined == true);

    Box boundaryBox;
    getBoundaryFaces(boundaryBox, a_WGdnv.box(), a_dir, a_side);

    // 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);
            }

            if(lohisign == -1 && a_dir == 1)
            {
                if(m_tmpBdryDataSet)
                {
                    FORT_RSFAULTBCF(CHF_FRA(a_WGdnv),
                        CHF_CONST_FRA(a_WShiftInside),
                        CHF_CONST_FRA(a_W),
                        CHF_CONST_FRA1((*m_tmpBdryData),RX_PSI),
                        CHF_CONST_INT(lohisign),
                        CHF_CONST_REAL(m_dx),
                        CHF_CONST_REAL(a_time),
                        CHF_CONST_INT(a_dir),
                        CHF_BOX(boundaryBox));
                }
                else
                {
                    FORT_RSFAULTBCF(CHF_FRA(a_WGdnv),
                        CHF_CONST_FRA(a_WShiftInside),
                        CHF_CONST_FRA(a_W),
                        CHF_CONST_FRA1((*m_bdryData),RX_PSI),
                        CHF_CONST_INT(lohisign),
                        CHF_CONST_REAL(m_dx),
                        CHF_CONST_REAL(a_time),
                        CHF_CONST_INT(a_dir),
                        CHF_BOX(boundaryBox));
                }
            }
            else if(m_boundaryType[a_dir*2 + (lohisign+1)/2] == 0)
            {
                FORT_LINELASTOUTBCF(CHF_FRA(a_WGdnv),
                    CHF_CONST_FRA(a_WShiftInside),
                    CHF_CONST_FRA(a_W),
                    CHF_CONST_INT(lohisign),
                    CHF_CONST_REAL(m_dx),
                    CHF_CONST_INT(a_dir),
                    CHF_BOX(boundaryBox));
            }
            else if(m_boundaryType[a_dir*2 + (lohisign+1)/2] == 1)
            {
                FORT_LINELASTFREEBCF(CHF_FRA(a_WGdnv),
                    CHF_CONST_FRA(a_WShiftInside),
                    CHF_CONST_FRA(a_W),
                    CHF_CONST_INT(lohisign),
                    CHF_CONST_REAL(m_dx),
                    CHF_CONST_INT(a_dir),
                    CHF_BOX(boundaryBox));
            }
            else
            {
                MayDay::Error("Invalid Boundary Type");
            }
        }
    }
}
Exemplo n.º 14
0
void TraceState(/// state at time t+dt/2 on edges in direction dir
                FArrayBox& a_stateHalf,
                /// cell-centered state at time t
                const FArrayBox& a_state,
                /// cell-centered velocity at time t
                const FArrayBox& a_cellVel,
                /// edge-centered advection velocity at time t+dt/2
                const FluxBox& a_advectionVel,
                /// cell-centered source
                const FArrayBox& a_source,
                /// Physical domain
                const ProblemDomain& a_dProblem,
                /// interior of grid patch
                const Box& a_gridBox,
                /// timeStep
                const Real a_dt,
                /// cell-spacing
                const Real a_dx,
                /// direction in which to perform tracing
                const int a_dir,
                /// which components to trace
                const Interval& a_srcComps,
                ///  where to put traced components in a_stateHalf,
                const Interval& a_destComps)

{

  int ncomp = a_srcComps.size();
  CH_assert (ncomp == a_destComps.size());
  int offset = a_destComps.begin() - a_srcComps.begin();
  Box edgeBox = a_gridBox;
  edgeBox.surroundingNodes(a_dir);

#ifdef SIMPLEUPWIND
  // simple cell-to-edge averaging may be causing us problems --
  // instead do simple upwinding

  for (int comp=a_srcComps.begin(); comp <= a_srcComps.end(); comp++)
  {
    int destcomp = comp+offset;
    FORT_UPWINDCELLTOEDGE(CHF_FRA1(a_stateHalf, destComp),
                          CHF_CONST_FRA1(a_state,comp),
                          CHF_CONST_FRA(a_advectionVel[a_dir]),
                          CHF_BOX(edgeBox),
                          CHF_CONST_INT(a_dir));
  }

#else


  // first compute slopes
  Box slopesBox = grow(a_gridBox,1);

  // these are debugging changes to sync with old code
#ifdef MATCH_OLDCODE
  FluxBox tempEdgeVel(slopesBox,1);
  tempEdgeVel.setVal(0.0);

  FArrayBox tempCellVel(slopesBox,SpaceDim);
  tempCellVel.setVal(0.0);


  CellToEdge(a_cellVel, tempEdgeVel);
  EdgeToCell(tempEdgeVel, tempCellVel);
  tempEdgeVel.clear(); // done with this, so reclaim memory
  EdgeToCell(a_advectionVel, tempCellVel);
#endif

  FArrayBox delS(slopesBox,1);
  FArrayBox sHat(slopesBox,1);
  FArrayBox sTilde(a_state.box(),1);

  for (int comp=a_srcComps.begin(); comp<=a_srcComps.end(); comp++)
  {
    int destComp = comp+offset;

#ifdef SET_BOGUS_VALUES
    delS.setVal(BOGUS_VALUE);
    sHat.setVal(BOGUS_VALUE);
    sTilde.setVal(BOGUS_VALUE);
#endif

    // compute van leer limited slopes in the normal direction
    // for now, always limit slopes, although might want to make
    // this a parameter
    int limitSlopes = 1;
    FORT_SLOPES(CHF_FRA1(delS,0),
                CHF_CONST_FRA1(a_state,comp),
                CHF_BOX(slopesBox),
                CHF_CONST_INT(a_dir),
                CHF_CONST_INT(limitSlopes));

    // this is a way to incorporate the minion correction --
    // stateTilde = state + (dt/2)*source
    sTilde.copy(a_source,comp,0,1);
    Real sourceFactor = a_dt/2.0;
    sTilde *= sourceFactor;
    sTilde.plus(a_state, comp,0,1);
    sHat.copy(sTilde,slopesBox);

    // now loop over directions, adding transverse components
    for (int localDir=0; localDir < SpaceDim; localDir++)
    {
      if (localDir != a_dir)
      {
        // add simple transverse components
        FORT_TRANSVERSE(CHF_FRA1(sHat,0),
                        CHF_CONST_FRA1(sTilde,0),
#ifdef MATCH_OLDCODE
                        CHF_CONST_FRA1(tempCellVel, localDir),
#else
                        CHF_CONST_FRA1(a_cellVel,localDir),
#endif
                        CHF_BOX(slopesBox),
                        CHF_CONST_REAL(a_dt),
                        CHF_CONST_REAL(a_dx),
                        CHF_CONST_INT(localDir));
                        //CHF_FRA1(temp,0));  // not used in function

      }
      else if (SpaceDim == 3)
      {
        // only add cross derivative transverse piece if we're in 3D
        // note that we need both components of velocity for this one
        FORT_TRANSVERSECROSS(CHF_FRA1(sHat,0),
                             CHF_CONST_FRA1(sTilde,0),
                             CHF_CONST_FRA(a_cellVel),
                             CHF_BOX(slopesBox),
                             CHF_CONST_REAL(a_dt),
                             CHF_CONST_REAL(a_dx),
                             CHF_CONST_INT(localDir));
      }
    } // end loop over directions

    // now compute left and right states and resolve the Reimann
    // problem to get single set of edge-centered values
    FORT_PREDICT(CHF_FRA1(a_stateHalf,destComp),
                 CHF_CONST_FRA1(sHat,0),
                 CHF_CONST_FRA1(delS,0),
                 CHF_CONST_FRA1(a_cellVel,a_dir),
                 CHF_CONST_FRA1(a_advectionVel[a_dir],0),
                 CHF_BOX(edgeBox),
                 CHF_CONST_REAL(a_dt),
                 CHF_CONST_REAL(a_dx),
                 CHF_CONST_INT(a_dir));
  } // end loop over components

#endif


}
Exemplo n.º 15
0
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;
        }
    }
}
Exemplo n.º 16
0
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;
    }
}
Exemplo n.º 17
0
void
EBCoarseAverage::averageFAB(EBCellFAB&       a_coar,
                            const EBCellFAB& a_fine,
                            const DataIndex& a_datInd,
                            const Interval&  a_variables) const
{
  CH_TIME("EBCoarseAverage::averageFAB(EBCellFAB)");
  CH_assert(isDefined());
  //do all cells as if they were regular
  BaseFab<Real>& coarRegFAB =  a_coar.getSingleValuedFAB();
  const BaseFab<Real>& fineRegFAB = a_fine.getSingleValuedFAB();
  Box refbox(IntVect::Zero, (m_refRat-1)*IntVect::Unit);

  const Box& coarBox = m_eblgCoFi.getDBL().get(a_datInd);

#ifndef NDEBUG
  Box fineBox = refine(coarBox, m_refRat);
  CH_assert(coarRegFAB.box().contains(coarBox));
  CH_assert(fineRegFAB.box().contains(fineBox));
#endif

  for (int ivar = a_variables.begin();
      ivar <= a_variables.end(); ivar++)
    {
      FORT_EBAVERAGE(CHF_FRA1(coarRegFAB,ivar),
                     CHF_CONST_FRA1(fineRegFAB,ivar),
                     CHF_BOX(coarBox),
                     CHF_CONST_INT(m_refRat),
                     CHF_BOX(refbox));
    }

  //overwrite irregular cells

  //recall that datInd is from the fine layout.
  const EBISBox& ebisBoxCoar = m_eblgCoFi.getEBISL()[a_datInd];
  const EBISBox& ebisBoxFine = m_eblgFine.getEBISL()[a_datInd];
  IntVectSet coarIrregIVS = ebisBoxCoar.getIrregIVS(coarBox);

  //fine cell volume is normalized to one.
  //compute coarse volume
  Real dxCoar = Real(m_refRat);
  Real cellVolCoar = 1.0;
  for (int idir = 0; idir < SpaceDim; idir++)
    cellVolCoar *= dxCoar;

  for (VoFIterator vofitCoar(coarIrregIVS, ebisBoxCoar.getEBGraph());
      vofitCoar.ok(); ++vofitCoar)
    {
      const VolIndex& coarVoF = vofitCoar();
      Vector<VolIndex> fineVoFs =
        m_eblgCoFi.getEBISL().refine(coarVoF, m_refRat, a_datInd);

      Real volCoar = cellVolCoar*ebisBoxCoar.volFrac(coarVoF);
      for (int ivar = a_variables.begin();
          ivar <= a_variables.end(); ivar++)
        {
          Real dataVal = 0.0;
          if (volCoar > 0.)
            {
              for (int ifine = 0; ifine < fineVoFs.size(); ifine++)
                {
                  const VolIndex& fineVoF = fineVoFs[ifine];
                  //fine cell volume is normalized to one...
                  Real volFine  = ebisBoxFine.volFrac(fineVoF);
                  Real fineVal =  a_fine(fineVoF, ivar);
                  if (volFine > 0.)
                    {
                      dataVal += fineVal*volFine;
                    }
                }
              dataVal /= volCoar;
            }
          else
            {
              //if there is no real volume, just take the ave
              //of fine values
              for (int ifine = 0; ifine < fineVoFs.size(); ifine++)
                {
                  const VolIndex& fineVoF = fineVoFs[ifine];
                  Real fineVal =  a_fine(fineVoF, ivar);
                  dataVal += fineVal;
                }
              if (fineVoFs.size() > 0)
                {
                  dataVal /= Real(fineVoFs.size());
                }
            }
          a_coar(coarVoF, ivar) = dataVal;
        }
    }
}
Exemplo n.º 18
0
// 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);
    }
}
Exemplo n.º 19
0
void
EBCoarsen::coarsenFAB(EBCellFAB&       a_coar,
                      const EBCellFAB& a_fine,
                      const DataIndex& a_datInd,
                      const Interval&  a_variables)
{
  CH_assert(isDefined());
  //do all cells as if they were regular
  BaseFab<Real>& coarRegFAB =  a_coar.getSingleValuedFAB();
  const BaseFab<Real>& fineRegFAB = a_fine.getSingleValuedFAB();

  //this is how much we need to grow a coarse box to get a fine box that
  // only has the fine iv's that are neighbors of the coarse iv
  const int fac = 1 - m_refRat/2;//NOTE: fac = 0 for refRat==2...
  Box refbox(IntVect::Zero,
             (m_refRat-1)*IntVect::Unit);
  refbox.grow(fac);

  Box coarBox = m_coarsenedFineGrids.get(a_datInd);

  Box fineBox = refine(coarBox, m_refRat);
  CH_assert(coarRegFAB.box().contains(coarBox));
  CH_assert(fineRegFAB.box().contains(fineBox));

  for (int ivar = a_variables.begin();
      ivar <= a_variables.end(); ivar++)
    {
      BaseFab<Real> laplFine(fineBox, 1);
      laplFine.setVal(0.);
      for (int idir = 0; idir < SpaceDim; idir++)
        {
          Box loBox, hiBox, centerBox;
          int hasLo, hasHi;
          EBArith::loHiCenter(loBox, hasLo,
                              hiBox, hasHi,
                              centerBox, m_domainFine,
                              fineBox, idir, &((*m_cfivsPtr)[a_datInd]));

          FORT_H2LAPL1DADDITIVE(CHF_FRA1(laplFine, 0),
                                CHF_FRA1(fineRegFAB, ivar),
                                CHF_CONST_INT(idir),
                                CHF_BOX(loBox),
                                CHF_CONST_INT(hasLo),
                                CHF_BOX(hiBox),
                                CHF_CONST_INT(hasHi),
                                CHF_BOX(centerBox));
        }

      FORT_EBCOARSEN(CHF_FRA1(coarRegFAB,ivar),
                     CHF_CONST_FRA1(fineRegFAB,ivar),
                     CHF_CONST_FRA1(laplFine, 0),
                     CHF_BOX(coarBox),
                     CHF_CONST_INT(m_refRat),
                     CHF_BOX(refbox));
    }

  //overwrite irregular vofs and coarse vofs next to the cfivs if refRat<4,
  //  for these vofs we coarsen based on
  //  taylor expansions from fine vofs to the coarse cell center
  coarsenIrreg(a_coar,a_fine,a_datInd,a_variables);
}
Exemplo n.º 20
0
void
EBMGInterp::pwlInterpFAB(EBCellFAB&       a_refCoar,
                         const Box&       a_coarBox,
                         const EBCellFAB& a_coar,
                         const DataIndex& a_datInd,
                         const Interval&  a_variables) const
{
  CH_TIMERS("EBMGInterp::pwlinterpfab");
  CH_TIMER("regular_interp", t1);
  CH_TIMER("irregular_interp", t2);
  CH_assert(isDefined());


  //first interpolate piecewise constant.
  pwcInterpFAB(a_refCoar,
               a_coarBox,
               a_coar,
               a_datInd,
               a_variables);

  //then add in slope*distance.
  const Box& coarBox = a_coarBox;

  for (int ivar = a_variables.begin();  ivar <= a_variables.end(); ivar++)
    {
      //save stuff at irreg cells because fortran result will be garbage
      //and this is an incremental process
      m_linearEBStencil[a_datInd]->cache(a_refCoar, ivar);

      //do all cells as if they were regular
      Box refBox(IntVect::Zero, IntVect::Zero);
      refBox.refine(m_refRat);

      const BaseFab<Real>& coarRegFAB =    a_coar.getSingleValuedFAB();
      BaseFab<Real>& refCoarRegFAB    = a_refCoar.getSingleValuedFAB();

      CH_START(t1);

      Real dxf = 1.0/m_coarDomain.size(0);
      Real dxc = 2.0*dxf;

      //do every cell as regular
      for (int idir = 0; idir < SpaceDim; idir++)
        {
          FORT_PROLONGADDSLOPE(CHF_FRA1(refCoarRegFAB,ivar),
                               CHF_CONST_FRA1(coarRegFAB,ivar),
                               CHF_BOX(coarBox),
                               CHF_BOX(refBox),
                               CHF_INT(idir),
                               CHF_REAL(dxf),
                               CHF_REAL(dxc),
                               CHF_CONST_INT(m_refRat));
        }
      CH_STOP(t1);

      //replace garbage fortran put in with original values (at irregular cells)
      m_linearEBStencil[a_datInd]->uncache(a_refCoar, ivar);

      CH_START(t2);
      //do what fortran should have done at irregular cells.
      m_linearEBStencil[a_datInd]->apply(a_refCoar, a_coar, true, ivar);
      CH_STOP(t2);
    }
}
Exemplo n.º 21
0
void
EBCoarseAverage::averageFAB(EBFaceFAB&       a_coar,
                            const EBFaceFAB& a_fine,
                            const DataIndex& a_datInd,
                            const Interval&  a_variables,
                            const int&       a_dir) const
{
  CH_TIME("EBCoarseAverage::averageFAB(EBFaceFAB)");
  CH_assert(isDefined());

  //do all cells as if they were regular
  BaseFab<Real>& coarRegFAB =  a_coar.getSingleValuedFAB();
  const BaseFab<Real>& fineRegFAB = a_fine.getSingleValuedFAB();
  Box refbox(IntVect::Zero,
             (m_refRat-1)*IntVect::Unit);
  refbox.surroundingNodes(a_dir);
  const Box& coarDBLBox = m_eblgCoFi.getDBL().get(a_datInd);
  Box coarFaceBox = coarDBLBox;
  coarFaceBox.surroundingNodes(a_dir);

#ifndef NDEBUG
  Box fineBox = refine(coarFaceBox, m_refRat);
  CH_assert(coarRegFAB.box().contains(coarFaceBox));
  CH_assert(fineRegFAB.box().contains(fineBox));
#endif

  for (int ivar = a_variables.begin();
      ivar <= a_variables.end(); ivar++)
    {
      FORT_EBAVERAGEFACE(CHF_FRA1(coarRegFAB,ivar),
                         CHF_CONST_FRA1(fineRegFAB,ivar),
                         CHF_BOX(coarFaceBox),
                         CHF_CONST_INT(m_refRat),
                         CHF_BOX(refbox),
                         CHF_CONST_INT(a_dir));
    }

  //overwrite irregular cells

  //recall that datInd is from the fine layout.
  const EBISBox& ebisBoxCoar = m_eblgCoFi.getEBISL()[a_datInd];
  const EBISBox& ebisBoxFine = m_eblgFine.getEBISL()[a_datInd];
  IntVectSet coarIrregIVS = ebisBoxCoar.getIrregIVS(coarDBLBox);

  //fine face area is normalized to one.
  //compute coarse volume
  Real dxCoar = Real(m_refRat);
  Real faceAreaCoar = 1.0;
  for (int idir = 0; idir < (SpaceDim - 1); idir++)
    faceAreaCoar *= dxCoar;

  for (FaceIterator faceitCoar(coarIrregIVS, ebisBoxCoar.getEBGraph(),a_dir,
                              FaceStop::SurroundingWithBoundary);
      faceitCoar.ok(); ++faceitCoar)
    {
      const FaceIndex& coarFace = faceitCoar();
      Vector<FaceIndex> fineFaces = m_eblgCoFi.getEBISL().refine(coarFace,m_refRat,a_datInd);

      Real areaCoar = faceAreaCoar*ebisBoxCoar.areaFrac(coarFace);
      for (int ivar = a_variables.begin();
          ivar <= a_variables.end(); ivar++)
        {
          Real dataVal = 0.0;
          if (areaCoar > 0.)
            {
              for (int ifine = 0; ifine < fineFaces.size(); ifine++)
                {
                  const FaceIndex& fineFace = fineFaces[ifine];
                  //fine face area is normalized to one...
                  Real areaFine  = ebisBoxFine.areaFrac(fineFace);
                  Real fineVal =  a_fine(fineFace, ivar);
                  if (areaFine > 0.)
                    {
                      dataVal += fineVal*areaFine;
                    }
                }
              dataVal /= areaCoar;
            }
          else
            {
              //if there is no real area, just take the ave
              //of fine values
              for (int ifine = 0; ifine < fineFaces.size(); ifine++)
                {
                  const FaceIndex& fineFace = fineFaces[ifine];
                  Real fineVal =  a_fine(fineFace, ivar);
                  dataVal += fineVal;
                }
              if (fineFaces.size() > 0)
                {
                  dataVal /= Real(fineFaces.size());
                }
            }

          a_coar(coarFace, ivar) = dataVal;
        }
    }
}
Exemplo n.º 22
0
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));
            }

        }
    }
}
Exemplo n.º 23
0
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;
            }
        }
    }
}