void
EBCompositeCCProjector::
averageVelocityToFaces(Vector<LevelData<EBFluxFAB>* >&  a_macVeloc,
                       Vector<LevelData<EBCellFAB>* >&  a_velocity)
{
  CH_TIME("EBCompositeCCProjector::averageVelocityToFaces");
  //interpolate and then send stuff on through to level function
  // int ncomp = a_velocity[0]->nComp();
  Interval interv(0, SpaceDim-1);
  Vector<LevelData<EBCellFAB> *> amrPhi = m_macProjector->getPhi();
  //  Real time = 0.;
  for (int ilev = 0; ilev < m_numLevels; ilev++)
    {
      if (ilev > 0)
        {
          //so it can be reused quadcfi is a one-variable animal
          //when we have ebalias, we can accomplish this without copies.
          //for now, tough luck
          //use phi for scratch space
          LevelData<EBCellFAB>& phiCoar = *amrPhi[ilev-1];
          LevelData<EBCellFAB>& phiFine = *amrPhi[ilev  ];
          for (int idir = 0; idir < SpaceDim; idir++)
            {
              Interval phiInterv(0, 0);
              Interval velInterv(idir, idir);
              a_velocity[ilev-1]->copyTo(velInterv, phiCoar, phiInterv);
              a_velocity[ilev  ]->copyTo(velInterv, phiFine, phiInterv);
              m_quadCFI[ilev]->interpolate(phiFine,
                                           phiCoar,
                                           phiInterv);
              // m_pwlCFI[ilev]->interpolate(phiFine,
              //                             phiCoar,
              //                             phiCoar,
              //                             time,
              //                             time,
              //                             time,
              //                             phiInterv);

              //on copy back, we need ghost cells, so do the data iterator loop
              for (DataIterator dit = phiFine.dataIterator(); dit.ok(); ++dit)
                {
                  Box region = phiFine[dit()].getRegion(); //includes ghost cells
                  (*a_velocity[ilev])[dit()].copy(region, velInterv, region, phiFine[dit()], phiInterv);
                }

              EBLevelDataOps::setVal(phiFine, 0.0);
              EBLevelDataOps::setVal(phiCoar, 0.0);
            }
        }
      a_velocity[ilev]->exchange(interv);
      ccpAverageVelocityToFaces(*a_macVeloc[ilev],
                                *a_velocity[ilev],
                                m_eblg[ilev].getDBL(),
                                m_eblg[ilev].getEBISL(),
                                m_eblg[ilev].getDomain(),
                                m_dx[ilev],
                                *m_eblg[ilev].getCFIVS());
    }
}
void
EBGradDivFilter::
gradDiv(LevelData<EBCellFAB>&       a_gradDivVel,
        LevelData<EBCellFAB>&       a_velFine,
        const LevelData<EBFluxFAB>& a_fluxVelFine,
        const LevelData<EBCellFAB>* a_velCoar,
        bool a_lowOrderOneSidedGrad,
        bool a_noExtrapToCovered)
{
  CH_TIME("EBGradDivFilter::gradDiv");
  CH_assert(a_velFine.nComp() == SpaceDim);
  Interval velInterv(0, SpaceDim-1);
  //do coarse-fine interpolation if necessary
  if (m_hasCoarser)
    {
      CH_assert(a_velCoar != NULL);
      CH_assert(a_velCoar->nComp() == SpaceDim);
      m_tensorCFI->coarseFineInterp(a_velFine, m_gradVel, *a_velCoar);
    }
  //fill in ghost cells
  a_velFine.exchange(velInterv);
  //compute gradient of velocity for parts NOT in ghost cells
  for (DataIterator dit = m_gridsFine.dataIterator(); dit.ok(); ++dit)
    {
      m_gradVel[dit()].setVal(0.);
      gradVel(m_gradVel[dit()],
              a_velFine[dit()],
              m_gridsFine.get(dit()),
              m_ebislFine[dit()],
              a_lowOrderOneSidedGrad);
    }
  m_gradVel.exchange();

  int ibox = 0;
  for (DataIterator dit = m_gridsFine.dataIterator(); dit.ok(); ++dit)
    {
      EBFluxFAB& fluxVel = m_faceDivCell[dit()];
      for (int idir = 0; idir < SpaceDim; idir++)
        {
          faceDivergence(fluxVel[idir],
                         m_gradVel[dit()],
                         a_velFine[dit()],
                         a_fluxVelFine[dit()],
                         m_gridsFine.get(dit()),
                         m_ebislFine[dit()],
                         idir);
        }
      ibox++;
    }
  m_faceDivCell.exchange();

  for (DataIterator dit = m_gridsFine.dataIterator(); dit.ok(); ++dit)
    {
      //the false tells gradDiv to not premultiply by lambda
      gradDiv(a_gradDivVel[dit()],
              m_gradVel[dit()],
              a_velFine[dit()],
              a_fluxVelFine[dit()],
              m_faceDivCell[dit()],
              m_gridsFine.get(dit()),
              m_ebislFine[dit()],
              dit(),
              false,
              a_noExtrapToCovered);
    }
}
void
EBGradDivFilter::
filter(LevelData<EBCellFAB>&       a_velFine,
       const LevelData<EBFluxFAB>& a_fluxVelFine,
       const LevelData<EBCellFAB>* a_velCoar,
       bool a_lowOrderOneSidedGrad,
       bool a_noExtrapToCovered)
{
  CH_TIME("EBGradDivFilter::filter");
  CH_assert(a_velFine.nComp() == SpaceDim);
  Interval velInterv(0, SpaceDim-1);
  //do coarse-fine interpolation if necessary
  if (m_hasCoarser)
    {
      CH_assert(a_velCoar != NULL);
      CH_assert(a_velCoar->nComp() == SpaceDim);
      m_tensorCFI->coarseFineInterp(a_velFine, m_gradVel, *a_velCoar);
    }

  //fill in ghost cells
  a_velFine.exchange(velInterv);
  //compute gradient of velocity for parts NOT in ghost cells
  for (DataIterator dit = m_gridsFine.dataIterator(); dit.ok(); ++dit)
    {
      gradVel(m_gradVel[dit()],
              a_velFine[dit()],
              m_gridsFine.get(dit()),
              m_ebislFine[dit()],
              a_lowOrderOneSidedGrad);
    }
  m_gradVel.exchange();

  int ibox = 0;
  for (DataIterator dit = m_gridsFine.dataIterator(); dit.ok(); ++dit)
    {
      EBFluxFAB& faceDiv = m_faceDivCell[dit()];
      for (int idir = 0; idir < SpaceDim; idir++)
        {
          faceDivergence(faceDiv[idir],
                         m_gradVel[dit()],
                         a_velFine[dit()],
                         a_fluxVelFine[dit()],
                         m_gridsFine.get(dit()),
                         m_ebislFine[dit()],
                         idir);
        }
      ibox++;
    }
  m_faceDivCell.exchange();

  //apply filter grid by grid
  //the lambda gets multiplied in on the fly
  //(the true tells grad div to do this multiplication)
  for (DataIterator dit = m_gridsFine.dataIterator(); dit.ok(); ++dit)
    {
      EBCellFAB lambdaGradDivVel(m_ebislFine[dit()], m_gridsFine.get(dit()), SpaceDim);
      gradDiv(lambdaGradDivVel,
              m_gradVel[dit()],
              a_velFine[dit()],
              a_fluxVelFine[dit()],
              m_faceDivCell[dit()],
              m_gridsFine.get(dit()),
              m_ebislFine[dit()],
              dit(),
              true,
              a_noExtrapToCovered);
      a_velFine[dit()] += lambdaGradDivVel;
    }
}