// ---------------------------------------------------------
void
AMRNavierStokes::computeLapScal(LevelData<FArrayBox>& a_lapScal,
                                LevelData<FArrayBox>& a_scal,
                                const BCHolder& a_physBC,
                                const LevelData<FArrayBox>* a_crseScalPtr)
{
  m_scalarsAMRPoissonOp.setBC(a_physBC);
  bool isHomogeneous = false;
  if (a_crseScalPtr != NULL)
    {
      m_scalarsAMRPoissonOp.AMROperatorNF(a_lapScal, a_scal, *a_crseScalPtr,
                                          isHomogeneous);
    }
  else
    {
      m_scalarsAMRPoissonOp.applyOpI(a_lapScal, a_scal,
                                     isHomogeneous);
    }

  BCHolder viscBC = m_physBCPtr->viscousFuncBC();

  DataIterator dit = a_lapScal.dataIterator();
  const DisjointBoxLayout& grids = a_lapScal.getBoxes();
  for (dit.reset(); dit.ok(); ++dit)
    {
      viscBC(a_lapScal[dit],
             grids[dit],
             m_problem_domain, m_dx,
             false); // not homogeneous
    }

  // finally, do exchange
  a_lapScal.exchange(a_lapScal.interval());
}
// 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 VCAMRPoissonOp2::preCond(LevelData<FArrayBox>&       a_phi,
                              const LevelData<FArrayBox>& a_rhs)
{
  CH_TIME("VCAMRPoissonOp2::preCond");

  // diagonal term of this operator in:
  //
  //       alpha * a(i)
  //     + beta  * sum_over_dir (b(i-1/2*e_dir) + b(i+1/2*e_dir)) / (dx*dx)
  //
  // The inverse of this is our initial multiplier.

  int ncomp = a_phi.nComp();

  CH_assert(m_lambda.isDefined());
  CH_assert(a_rhs.nComp()    == ncomp);
  CH_assert(m_bCoef->nComp() == ncomp);

  // Recompute the relaxation coefficient if needed.
  resetLambda();

  // don't need to use a Copier -- plain copy will do
  DataIterator dit = a_phi.dataIterator();
  for (dit.begin(); dit.ok(); ++dit)
    {
      // also need to average and sum face-centered bCoefs to cell-centers
      Box gridBox = a_rhs[dit].box();

      // approximate inverse
      a_phi[dit].copy(a_rhs[dit]);
      a_phi[dit].mult(m_lambda[dit], gridBox, 0, 0, ncomp);
    }

  relax(a_phi, a_rhs, 2);
}
Exemple #3
0
void
initData(LevelData<FArrayBox>& a_data, const Real a_dx)
{

  DataIterator dit = a_data.dataIterator();
  const DisjointBoxLayout& interiorBoxes = a_data.getBoxes();

  for (dit.begin(); dit.ok(); ++dit)
    {
      // first set to a bogus value which will persist in ghost cells
      // after initialization
      a_data[dit()].setVal(1.0e9);

      // this will be slow, but who cares?
      FArrayBox& localData = a_data[dit()];
      BoxIterator boxIt(interiorBoxes[dit()]);
      Real localVal;
      for (boxIt.begin(); boxIt.ok(); ++boxIt)
        {
          const IntVect& loc = boxIt();
          for (int comp=0; comp<localData.nComp(); comp++)
            {
              localVal = dataVal(loc, comp);
              localData(loc, comp) = localVal;
            }
        }

    }
}
Exemple #4
0
// ---------------------------------------------------------
void levelDivergenceMAC(LevelData<FArrayBox>& a_div,
                        const LevelData<FluxBox>& a_uEdge,
                        const Real a_dx)
{

  // silly way to do this until i figure out a better
  // way to make this dimensionally-independent
  CH_assert (a_uEdge.nComp() >= a_div.nComp());


  DataIterator dit = a_div.dataIterator();
  for (dit.reset(); dit.ok(); ++dit)
  {
    a_div[dit()].setVal(0.0);

    const FluxBox& thisFluxBox = a_uEdge[dit()];
    Box cellBox(thisFluxBox.box());
    // just to be sure we don't accidentally trash memory...
    cellBox &= a_div[dit()].box();

    // now loop over coordinate directions and add to divergence
    for (int dir=0; dir<SpaceDim; dir++)
    {
      const FArrayBox& uEdgeDir = thisFluxBox[dir];

      FORT_DIVERGENCE(CHF_CONST_FRA(uEdgeDir),
                      CHF_FRA(a_div[dit()]),
                      CHF_BOX(cellBox),
                      CHF_CONST_REAL(a_dx),
                      CHF_INT(dir));
    }

  }

}
Exemple #5
0
/// Set up initial conditions
void SWIBC::initializeBdry(LevelData<FArrayBox>& a_B)
{
    const Real tmpVal  =  0.0;
    const Real tmpVal2 = 100;
    for (DataIterator dit = a_B.dataIterator(); dit.ok(); ++dit)
    {
        // Storage for current grid
        FArrayBox& B = a_B[dit()];

        // Box of current grid
        Box bBox = B.box();
        bBox &= m_domain;

        // Set up initial condition in this grid
        FORT_LINELASTSETFAB(CHF_FRA1(B,4),
            CHF_BOX(bBox),
            CHF_CONST_REAL(tmpVal));
        FORT_LINELASTSETFAB(CHF_FRA1(B,5),
            CHF_BOX(bBox),
            CHF_CONST_REAL(tmpVal));
        FORT_LINELASTSETFAB(CHF_FRA1(B,6),
            CHF_BOX(bBox),
            CHF_CONST_REAL(tmpVal2));
    }
}
// -----------------------------------------------------------------------------
// Interpolate ghosts at CF interface using zeros on coarser grids.
// -----------------------------------------------------------------------------
void homogeneousCFInterp (LevelData<FArrayBox>& a_phif,
                          const RealVect&       a_fineDx,
                          const RealVect&       a_crseDx,
                          const CFRegion&       a_cfRegion,
                          const IntVect&        a_applyDirs)
{
    CH_TIME("homogeneousCFInterp (full level)");

    // Loop over grids, directions, and sides and call the worker function.
    DataIterator dit = a_phif.dataIterator();
    for (dit.begin(); dit.ok(); ++dit) {
        if (a_phif[dit].box().isEmpty()) continue;

        for (int dir = 0; dir < SpaceDim; ++dir) {
            if (a_applyDirs[dir] == 0) continue;

            SideIterator sit;
            for (sit.begin(); sit.ok(); sit.next()) {
                homogeneousCFInterp(a_phif,
                                    dit(),
                                    dir,
                                    sit(),
                                    a_fineDx[dir],
                                    a_crseDx[dir],
                                    a_cfRegion);
            }
        }
    }
}
// ---------------------------------------------------------
void
AMRNavierStokes::computeLapVel(LevelData<FArrayBox>& a_lapVel,
                               LevelData<FArrayBox>& a_vel,
                               const LevelData<FArrayBox>* a_crseVelPtr)
{
  // set BC's
  VelBCHolder velBC(m_physBCPtr->viscousVelFuncBC());
  bool isHomogeneous = false;
  m_velocityAMRPoissonOp.applyOp(a_lapVel, a_vel, a_crseVelPtr,
                                 isHomogeneous, velBC);

  // may need to extend lapVel to cover ghost cells as well
  {
    BCHolder viscBC = m_physBCPtr->viscousFuncBC();
    const DisjointBoxLayout& grids = a_lapVel.getBoxes();
    DataIterator dit = a_lapVel.dataIterator();
    for (dit.reset(); dit.ok(); ++dit)
      {
        viscBC(a_lapVel[dit], grids[dit],
               m_problem_domain, m_dx,
               false); // not homogeneous
      }
  }

  // finally, do exchange
  a_lapVel.exchange(a_lapVel.interval());
}
Exemple #8
0
// ----------------------------------------------------------------
void EdgeToCell(const LevelData<FluxBox>& a_edgeData,
                LevelData<FArrayBox>& a_cellData)
{
  // this is just a wrapper around the single-grid version
  DataIterator dit = a_edgeData.dataIterator();
  for (dit.reset(); dit.ok(); ++dit)
    {
      EdgeToCell(a_edgeData[dit()], a_cellData[dit()]);
    }
}
Exemple #9
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));
            }
        }
    }
}
Exemple #10
0
void EBPoissonOp::
GSColorAllIrregular(LevelData<EBCellFAB>&        a_phi,
                    const LevelData<EBCellFAB>&  a_rhs,
                    const IntVect&               a_color,
                    const bool&                  a_homogeneousPhysBC,
                    int icolor)
{
  CH_TIME("EBPoissonOp::GSColorAllIrregular");


  for (DataIterator dit = a_phi.dataIterator(); dit.ok(); ++dit)
    {
      EBCellFAB& phifab = a_phi[dit()];
      const EBCellFAB& rhsfab = a_rhs[dit()];

      //phi = (I-lambda*L)phiOld
      m_colorEBStencil[icolor][dit()]->apply(phifab, phifab, false);

      //apply EB bcs to (I-lambda*L)phi (already done in colorStencil += fluxStencil, and hom only here))
      int comp = 0;
      const BaseIVFAB<Real>& curAlphaWeight = m_alphaDiagWeight[dit()];
      const BaseIVFAB<Real>& curBetaWeight  = m_betaDiagWeight[dit()];
      //apply domain bcs to (I-lambda*L)phi
      for (int idir = 0; idir < SpaceDim; idir++)
        {
          for (m_vofItIrregColorDomLo[icolor][idir][dit()].reset(); m_vofItIrregColorDomLo[icolor][idir][dit()].ok();  ++m_vofItIrregColorDomLo[icolor][idir][dit()])
            {
              Real flux;
              const VolIndex& vof = m_vofItIrregColorDomLo[icolor][idir][dit()]();
              Real weightIrreg = m_alpha*curAlphaWeight(vof,0) + m_beta*curBetaWeight(vof,0);
              m_domainBC->getFaceFlux(flux,vof,comp,a_phi[dit()],
                                      m_origin,m_dx,idir,Side::Lo, dit(), m_time,
                                      a_homogeneousPhysBC);

              phifab(vof,comp) -= -(1./weightIrreg) * flux * m_beta*m_invDx[idir];
            }
          for (m_vofItIrregColorDomHi[icolor][idir][dit()].reset(); m_vofItIrregColorDomHi[icolor][idir][dit()].ok();  ++m_vofItIrregColorDomHi[icolor][idir][dit()])
            {
              Real flux;
              const VolIndex& vof = m_vofItIrregColorDomHi[icolor][idir][dit()]();
              Real weightIrreg = m_alpha*curAlphaWeight(vof,0) + m_beta*curBetaWeight(vof,0);
              m_domainBC->getFaceFlux(flux,vof,comp,a_phi[dit()],
                                      m_origin,m_dx,idir,Side::Hi,dit(), m_time,
                                      a_homogeneousPhysBC);

              phifab(vof,comp) += -(1./weightIrreg) * flux * m_beta*m_invDx[idir];
            }
        }

      //phi += lambda*rhsfab
      m_rhsColorEBStencil[icolor][dit()]->apply(phifab, rhsfab, true);
    }
}
Exemple #11
0
void EBPoissonOp::
colorGS(LevelData<EBCellFAB>&       a_phi,
        const LevelData<EBCellFAB>& a_rhs,
        const IntVect& a_color,
        int icolor)
{
  CH_TIME("EBPoissonOp::colorGS");

  //this is a multigrid operator so only homogeneous CF BC and null coar level
  CH_assert(a_rhs.ghostVect()    == m_ghostCellsRHS);
  CH_assert(a_phi.ghostVect()    == m_ghostCellsPhi);

  a_phi.exchange();


  Real weight = m_alpha;
  for (int idir = 0; idir < SpaceDim; idir++)
    {
      weight += -2.0 * m_beta * m_invDx2[idir];
    }
  weight = 1.0 / weight;


  for (DataIterator dit = a_phi.dataIterator(); dit.ok(); ++dit)
    {
      EBCellFAB& phifab = a_phi[dit()];
      m_colorEBStencil[icolor][dit()]->cache(phifab);
    }

  GSColorAllRegular(  a_phi, a_rhs, a_color, weight, true);

  for (DataIterator dit = a_phi.dataIterator(); dit.ok(); ++dit)
    {
      EBCellFAB& phifab = a_phi[dit()];
      m_colorEBStencil[icolor][dit()]->uncache(phifab);
    }

  GSColorAllIrregular(a_phi, a_rhs, a_color, true, icolor);
}
Exemple #12
0
void
initData(LevelData<FArrayBox>& a_data,
         Real a_dx)
{
  // for now, set phi to 1 everywhere
  Real phiVal = 1.0;

  DataIterator dit = a_data.dataIterator();
  for (dit.begin(); dit.ok(); ++dit)
    {
      a_data[dit].setVal(phiVal);
    }
}
Exemple #13
0
void
EBPlanarShockIBC::
initialize(LevelData<EBCellFAB>& a_conState,
           const EBISLayout& a_ebisl) const
{
 CH_assert(m_isDefined);
 CH_assert(m_isFortranCommonSet);

  // Iterator of all grids in this level
  for(DataIterator dit = a_conState.dataIterator(); dit.ok(); ++dit)
    {
      const EBISBox& ebisBox = a_ebisl[dit()];
      // Storage for current grid
      EBCellFAB& conFAB = a_conState[dit()];

      BaseFab<Real>& regConFAB = conFAB.getSingleValuedFAB();
      // Box of current grid
      Box uBox = regConFAB.box();
      uBox &= m_domain;
      // Set up initial condition in this grid
      /**/
      FORT_PLANARSHOCKINIT(CHF_CONST_FRA(regConFAB),
                           CHF_CONST_REAL(m_dx),
                           CHF_BOX(uBox));
      /**/

      //now for the multivalued cells.  Since it is pointwise,
      //the regular calc is correct for all single-valued cells.
      IntVectSet ivs = ebisBox.getMultiCells(uBox);
      for(VoFIterator vofit(ivs, ebisBox.getEBGraph()); vofit.ok(); ++vofit)
        {
          const VolIndex& vof = vofit();
          const IntVect& iv = vof.gridIndex();
          RealVect momentum;
          Real energy, density;
          /**/
          FORT_POINTPLANARSHOCKINIT(CHF_REAL(density),
                                    CHF_REALVECT(momentum),
                                    CHF_REAL(energy),
                                    CHF_CONST_INTVECT(iv),
                                    CHF_CONST_REAL(m_dx));
          /**/
          conFAB(vof, CRHO) = density;
          conFAB(vof, CENG) = energy;
          for(int idir = 0; idir < SpaceDim; idir++)
            {
              conFAB(vof, CMOMX+idir) = momentum[idir];
            }
        }//end loop over multivalued cells
    } //end loop over boxes
}
Exemple #14
0
/// Set up initial conditions
void RSIBC::initializeBdry(LevelData<FArrayBox>& a_B)
{
    const Real tmpVal  =  0.0;
    const Real tmpVal2 = 1e10;
    for (DataIterator dit = a_B.dataIterator(); dit.ok(); ++dit)
    {
        // Storage for current grid
        FArrayBox& B = a_B[dit()];

        // Box of current grid
        Box bBox = B.box();
        bBox &= m_domain;

        // Set up initial condition in this grid
        FORT_LINELASTSETFAB(CHF_FRA1(B,RX_VX),
            CHF_BOX(bBox),
            CHF_CONST_REAL(tmpVal));
        FORT_LINELASTSETFAB(CHF_FRA1(B,RX_VZ),
            CHF_BOX(bBox),
            CHF_CONST_REAL(tmpVal));
        FORT_LINELASTSETFAB(CHF_FRA1(B,RX_SXY),
            CHF_BOX(bBox),
            CHF_CONST_REAL(tmpVal));
        FORT_LINELASTSETFAB(CHF_FRA1(B,RX_SYZ),
            CHF_BOX(bBox),
            CHF_CONST_REAL(tmpVal));
        FORT_LINELASTSETFAB(CHF_FRA1(B,RX_V),
            CHF_BOX(bBox),
            CHF_CONST_REAL(tmpVal));
        FORT_LINELASTSETFAB(CHF_FRA1(B,RX_DX),
            CHF_BOX(bBox),
            CHF_CONST_REAL(tmpVal));
        FORT_LINELASTSETFAB(CHF_FRA1(B,RX_DZ),
            CHF_BOX(bBox),
            CHF_CONST_REAL(tmpVal));
        FORT_LINELASTSETFAB(CHF_FRA1(B,RX_DT),
            CHF_BOX(bBox),
            CHF_CONST_REAL(tmpVal));
        FORT_LINELASTSETFAB(CHF_FRA1(B,RX_RT),
            CHF_BOX(bBox),
            CHF_CONST_REAL(tmpVal2));
        FORT_LINELASTSETFAB(CHF_FRA1(B,RX_SYY),
            CHF_BOX(bBox),
            CHF_CONST_REAL(tmpVal));
        FORT_LINELASTSETFAB(CHF_FRA1(B,RX_PSI),
            CHF_BOX(bBox),
            CHF_CONST_REAL(m_psi));
    }
}
// ---------------------------------------------------------
void
AMRNavierStokes::computeKineticEnergy(LevelData<FArrayBox>& a_energy) const
{
  // this is simple since no BC's need to be set.
  const LevelData<FArrayBox>& levelVel = *m_vel_new_ptr;
  const DisjointBoxLayout& levelGrids = levelVel.getBoxes();

  DataIterator dit = a_energy.dataIterator();
  for (dit.begin(); dit.ok(); ++dit)
    {
      FORT_KINETICENERGY(CHF_FRA1(a_energy[dit],0),
                         CHF_CONST_FRA(levelVel[dit]),
                         CHF_BOX(levelGrids[dit]));
    }
}
Exemple #16
0
// -------------------------------------------------------------
void
Mask::buildMasks(LevelData<BaseFab<int> >& a_masks,
                 const ProblemDomain& a_dProblem,
                 const BoxLayout& a_grids, const BoxLayout* a_fineGridsPtr,
                 int a_nRefFine)
{
  // simply iterate over boxes and call single-basefab function
  DataIterator dit = a_masks.dataIterator();

  for (dit.reset(); dit.ok(); ++dit)
    {
      buildMask(a_masks[dit()], a_dProblem, a_grids, a_fineGridsPtr,
                a_nRefFine);
    }
}
Exemple #17
0
void EBPoissonOp::
residual(LevelData<EBCellFAB>&       a_residual,
         const LevelData<EBCellFAB>& a_phi,
         const LevelData<EBCellFAB>& a_rhs,
         bool                        a_homogeneousPhysBC)
{
  CH_TIME("EBPoissonOp::residual");
  //this is a multigrid operator so only homogeneous CF BC
  //and null coar level
  CH_assert(a_residual.ghostVect() == m_ghostCellsRHS);
  CH_assert(a_phi.ghostVect() == m_ghostCellsPhi);
  DataIterator dit = a_residual.dataIterator();
  applyOp(a_residual,a_phi, a_homogeneousPhysBC, dit );
  axby(a_residual,a_residual,a_rhs,-1.0, 1.0);
}
Exemple #18
0
// ----------------------------------------------------------
// this function is shamelessly based on the ANAG CoarseAverage
// (cell-centered) version
void
CoarseAverageEdge::averageToCoarse(LevelData<FluxBox>& a_coarseData,
                                   const LevelData<FluxBox>& a_fineData)
{
  CH_assert(isDefined());

  DataIterator dit = a_fineData.dataIterator();
  for (dit.reset(); dit.ok(); ++dit)
    {
      FluxBox& coarsenedFine = m_coarsenedFineData[dit()];
      const FluxBox& fine = a_fineData[dit()];

      // coarsen from the entire fine grid onto the entire coarse grid
      averageGridData(coarsenedFine, fine);
    }

  m_coarsenedFineData.copyTo(m_coarsenedFineData.interval(),
                             a_coarseData, a_coarseData.interval());
}
Exemple #19
0
void setValue(LevelData<EBCellFAB>& phase, const BaseBCValue& value,
              const Box& domain,
              const RealVect& dx, const RealVect& origin,
              bool useKappa)
{
    RealVect loc;
    IntVect  originIV = domain.smallEnd();
    DataIterator dit = phase.dataIterator();
    for (dit.begin(); dit.ok(); ++dit)
    {
        EBCellFAB& efab = phase[dit];

        FArrayBox& fab  = efab.getFArrayBox();
        ForAllX(Real, fab)
        {
            D_EXPR(loc[0]=iR+nR-nR+originIV[0], loc[1]=jR+originIV[1], loc[2]=kR+originIV[2]);
            loc+=0.5;
            loc*=dx;
            loc+=origin;
            fabR = value.value(loc, RealVect::Zero, 1.e99,0);
        }
        EndFor ;
        if (useKappa)
        {
            const EBISBox& ebox = efab.getEBISBox();
            IntVectSet ivs = ebox.getIrregIVS(efab.getRegion());
            IVSIterator it(ivs);
            for (; it.ok(); ++it)
            {
                const IntVect iv = it();
                VolIndex vi(iv,0);
                if (ebox.bndryArea(vi) != 0)
                {
                    loc = iv;
                    loc+=0.5;
                    loc+= ebox.centroid(vi);
                    loc*=dx;
                    loc+=origin;
                    efab(vi, 0) = value.value(loc, RealVect::Zero, 1.e99,0)*ebox.volFrac(vi);
                }
            }
        }
    }
void TimeInterpolatorRK4::interpolate(/// interpolated solution on this level coarsened
                                      LevelData<FArrayBox>&   a_U,
                                      /// time interpolation coefficient in range [0:1]
                                      const Real&             a_timeInterpCoeff,
                                      /// interval of a_U to fill in
                                      const Interval&         a_intvl)
{
  CH_assert(m_defined);
  CH_assert(m_gotFullTaylorPoly);
  CH_assert(a_U.nComp() == m_numStates);

  LevelData<FArrayBox> UComp;
  aliasLevelData(UComp, &a_U, a_intvl);

  // For i in 0:m_numCoeffs-1,
  // coeffFirst[i] is index of first component of m_taylorCoeffs
  // that corresponds to a coefficient of t^i.
  Vector<int> coeffFirst(m_numCoeffs);
  int intervalLength = a_intvl.size();
  for (int i = 0; i < m_numCoeffs; i++)
    {
      coeffFirst[i] = a_intvl.begin() + i * m_numStates;
    }

  DataIterator dit = UComp.dataIterator();
  for (dit.begin(); dit.ok(); ++dit)
    {
      FArrayBox& UFab = UComp[dit];
      const FArrayBox& taylorFab = m_taylorCoeffs[dit];

      // Evaluate a0 + a1*t + a2*t^2 + a3*t^3
      // as a0 + t * (a1 + t * (a2 + t * a3)).
      UFab.copy(taylorFab, coeffFirst[m_numCoeffs-1], 0, intervalLength);
      for (int ind = m_numCoeffs - 2; ind >=0; ind--)
        {
          UFab *= a_timeInterpCoeff;
          UFab.plus(taylorFab, coeffFirst[ind], 0, intervalLength);
        }
    }
  // dummy statement in order to get around gdb bug
  int dummy_unused = 0; dummy_unused = 0;
}
Exemple #21
0
// Set up initial conditions
void RampIBC::initialize(LevelData<FArrayBox>& a_U)
{
  CH_assert(m_isFortranCommonSet == true);
  CH_assert(m_isDefined == true);

  // Iterator of all grids in this level
  for (DataIterator dit = a_U.dataIterator(); dit.ok(); ++dit)
    {
      // Storage for current grid
      FArrayBox& U = a_U[dit];

      // Box of current grid
      Box uBox = U.box();
      uBox &= m_domain;

      // Set up initial condition in this grid
      FORT_RAMPINITF(CHF_FRA(U),
                     CHF_CONST_REAL(m_dx),
                     CHF_BOX(uBox));
    }
}
Exemple #22
0
void
initData(LevelData<FArrayBox>& a_data, const Real a_dx)
{

  DataIterator dit = a_data.dataIterator();
  const DisjointBoxLayout& interiorBoxes = a_data.getBoxes();

  for (dit.begin(); dit.ok(); ++dit)
    {
      // first set to a bogus value which will persist in ghost cells
      // after initialization
      a_data[dit()].setVal(1.0e9);

      // this will be slow, but who cares?
      FArrayBox& localData = a_data[dit()];
      BoxIterator boxIt(interiorBoxes[dit()]);
      Real localVal;
      for (boxIt.begin(); boxIt.ok(); ++boxIt)
        {
          const IntVect& loc = boxIt();
          // linear profile
          //localVal = a_dx*(D_TERM(loc[0]+0.5,
          //                      + loc[1]+0.5,
          //                      + loc[2]+0.5));

          // quadratic profile
          localVal = a_dx*a_dx*(D_TERM6((loc[0]+0.5)*(loc[0]+0.5),
                                        + (loc[1]+0.5)*(loc[1]+0.5),
                                        + (loc[2]+0.5)*(loc[2]+0.5),
                                        + (loc[3]+0.5)*(loc[3]+0.5),
                                        + (loc[4]+0.5)*(loc[4]+0.5),
                                        + (loc[5]+0.5)*(loc[5]+0.5)));
          localData(loc) = localVal;
        }

    }
}
void TimeInterpolatorRK4::intermediate(/// intermediate RK4 solution on this level coarsened
                                       LevelData<FArrayBox>&   a_U,
                                       /// time interpolation coefficient in range [0:1]
                                       const Real&             a_timeInterpCoeff,
                                       /// which RK4 stage:  0, 1, 2, 3
                                       const int&              a_stage,
                                       /// interval of a_U to fill in
                                       const Interval&         a_intvl) const
{
  CH_assert(m_defined);
  CH_assert(m_gotFullTaylorPoly);
  CH_assert(a_U.nComp() == m_numStates);
  CH_assert(a_stage >= 0);
  CH_assert(a_stage < 4);

  Real rinv = 1. / Real(m_refineCoarse);
  Vector<Real> intermCoeffs(4);
  // 0 is coefficient of m_taylorCoeffs[0] = Ucoarse(0)
  // 1 is coefficient of m_taylorCoeffs[1] =           K1
  // 2 is coefficient of m_taylorCoeffs[2] = 1/2 * (-3*K1 + 2*K2 + 2*K3 - K4)
  // 3 is coefficient of m_taylorCoeffs[3] = 2/3 * (   K1 -   K2 -   K3 + K4)
  Real diff12Coeffs;
  // coefficient of m_diff12               =              -   K2 +   K3
  switch (a_stage)
    {
    case 0:
      intermCoeffs[0] = 1.;
      intermCoeffs[1] = a_timeInterpCoeff;
      intermCoeffs[2] = a_timeInterpCoeff * a_timeInterpCoeff;
      intermCoeffs[3] = a_timeInterpCoeff * a_timeInterpCoeff  * a_timeInterpCoeff;
      diff12Coeffs = 0.;
      break;
    case 1:
      intermCoeffs[0] = 1.;
      intermCoeffs[1] = 0.5*rinv + a_timeInterpCoeff;
      intermCoeffs[2] = a_timeInterpCoeff * (rinv + a_timeInterpCoeff);
      intermCoeffs[3] = a_timeInterpCoeff * a_timeInterpCoeff * (1.5*rinv + a_timeInterpCoeff);
      diff12Coeffs = 0.;
      break;
    case 2:
      intermCoeffs[0] = 1.;
      intermCoeffs[1] = 0.5*rinv + a_timeInterpCoeff;
      intermCoeffs[2] = 0.5*rinv*rinv + a_timeInterpCoeff * (rinv + a_timeInterpCoeff);
      intermCoeffs[3] = 0.375*rinv*rinv*rinv + a_timeInterpCoeff * (1.5*rinv*rinv + a_timeInterpCoeff * (1.5*rinv + a_timeInterpCoeff));
      diff12Coeffs = -0.25 * rinv * rinv;
      break;
    case 3:
      intermCoeffs[0] = 1.;
      intermCoeffs[1] = rinv + a_timeInterpCoeff;
      intermCoeffs[2] = rinv*rinv + a_timeInterpCoeff * (2.*rinv + a_timeInterpCoeff);
      intermCoeffs[3] = 0.75*rinv*rinv*rinv + a_timeInterpCoeff * (3.*rinv*rinv + a_timeInterpCoeff * (3.*rinv + a_timeInterpCoeff));
      diff12Coeffs = 0.5 * rinv * rinv;
      break;
    default:
      MayDay::Error("TimeInterpolatorRK4::intermediate must have a_stage in range 0:3");
    }
  LevelData<FArrayBox> UComp;
  aliasLevelData(UComp, &a_U, a_intvl);

  // For i in 0:m_numCoeffs-1,
  // coeffFirst[i] is index of first component of m_taylorCoeffs
  // that corresponds to a coefficient of t^i.
  Vector<int> coeffFirst(m_numCoeffs);
  int intervalLength = a_intvl.size();
  for (int i = 0; i < m_numCoeffs; i++)
    {
      coeffFirst[i] = a_intvl.begin() + i * m_numStates;
    }

  DataIterator dit = UComp.dataIterator();
  for (dit.begin(); dit.ok(); ++dit)
    {
      FArrayBox& UFab = UComp[dit];
      const FArrayBox& taylorFab = m_taylorCoeffs[dit];

      // WAS:  Evaluate a0 + a1*t + a2*t^2 + a3*t^3
      // as a0 + t * (a1 + t * (a2 + t * a3)):
      // that is, set UFab to
      // a3, t*a3 + a2, t*(t*a3 + a2) + a1, t*(t*(t*a3 + a2) + a1) * a0.

      // NEW:  Evaluate a0*c0 + a1*c1 + a2*c2 + a3*c3,
      // where c0, c1, c2, c3 are scalars,
      // and c0 = intermCoeffs[0] = 1.
      UFab.copy(taylorFab, coeffFirst[0], 0, intervalLength);
      for (int ind = 1; ind < 4; ind++)
        {
          UFab.plus(taylorFab, intermCoeffs[ind],
                    coeffFirst[ind], 0, intervalLength);
        }
      const FArrayBox& diff12Fab = m_diff12[dit];
      UFab.plus(diff12Fab, diff12Coeffs, 0, 0, intervalLength);
    }
  // dummy statement in order to get around gdb bug
  int dummy_unused = 0; dummy_unused = 0;
}
Exemple #24
0
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));
    }
}
Exemple #25
0
//
// VCAMRPoissonOp2::reflux()
//   There are currently the new version (first) and the old version (second)
//   in this file.  Brian asked to preserve the old version in this way for
//   now. - TJL (12/10/2007)
//
void VCAMRPoissonOp2::reflux(const LevelData<FArrayBox>&        a_phiFine,
                            const LevelData<FArrayBox>&        a_phi,
                            LevelData<FArrayBox>&              a_residual,
                            AMRLevelOp<LevelData<FArrayBox> >* a_finerOp)
{
  CH_TIMERS("VCAMRPoissonOp2::reflux");

  m_levfluxreg.setToZero();
  Interval interv(0,a_phi.nComp()-1);

  CH_TIMER("VCAMRPoissonOp2::reflux::incrementCoarse", t2);
  CH_START(t2);

  DataIterator dit = a_phi.dataIterator();
  for (dit.reset(); dit.ok(); ++dit)
  {
    const FArrayBox& coarfab   = a_phi[dit];
    const FluxBox&   coarBCoef = (*m_bCoef)[dit];
    const Box&       gridBox   = a_phi.getBoxes()[dit];

    if (m_levfluxreg.hasCF(dit()))
    {
      for (int idir = 0; idir < SpaceDim; idir++)
      {
        FArrayBox coarflux;
        Box faceBox = surroundingNodes(gridBox, idir);

        getFlux(coarflux, coarfab, coarBCoef, faceBox, idir);

        Real scale = 1.0;
        m_levfluxreg.incrementCoarse(coarflux, scale,dit(),
            interv, interv, idir);
      }
    }
  }

  CH_STOP(t2);

  // const cast:  OK because we're changing ghost cells only
  LevelData<FArrayBox>& phiFineRef = ( LevelData<FArrayBox>&)a_phiFine;

  VCAMRPoissonOp2* finerAMRPOp = (VCAMRPoissonOp2*) a_finerOp;
  QuadCFInterp& quadCFI = finerAMRPOp->m_interpWithCoarser;

  quadCFI.coarseFineInterp(phiFineRef, a_phi);
  // I'm pretty sure this is not necessary. bvs -- flux calculations use
  // outer ghost cells, but not inner ones
  // phiFineRef.exchange(a_phiFine.interval());
  IntVect phiGhost = phiFineRef.ghostVect();
  int ncomps = a_phiFine.nComp();

  CH_TIMER("VCAMRPoissonOp2::reflux::incrementFine", t3);
  CH_START(t3);

  DataIterator ditf = a_phiFine.dataIterator();
  const DisjointBoxLayout& dblFine = a_phiFine.disjointBoxLayout();
  for (ditf.reset(); ditf.ok(); ++ditf)
    {
      const FArrayBox& phifFab   = a_phiFine[ditf];
      const FluxBox&   fineBCoef = (*(finerAMRPOp->m_bCoef))[ditf];
      const Box&       gridbox   = dblFine.get(ditf());

      for (int idir = 0; idir < SpaceDim; idir++)
        {
          //int normalGhost = phiGhost[idir];
          SideIterator sit;
          for (sit.begin(); sit.ok(); sit.next())
            {
              if (m_levfluxreg.hasCF(ditf(), sit()))
                {
                  Side::LoHiSide hiorlo = sit();
                  Box fluxBox = bdryBox(gridbox,idir,hiorlo,1);

                  FArrayBox fineflux(fluxBox,ncomps);
                  getFlux(fineflux, phifFab, fineBCoef, fluxBox, idir,
                          m_refToFiner);

                  Real scale = 1.0;
                  m_levfluxreg.incrementFine(fineflux, scale, ditf(),
                                             interv, interv, idir, hiorlo);
                }
            }
        }
    }

  CH_STOP(t3);

  Real scale = 1.0/m_dx;
  m_levfluxreg.reflux(a_residual, scale);
}
Exemple #26
0
void VCAMRPoissonOp2::reflux(const LevelData<FArrayBox>&        a_phiFine,
                            const LevelData<FArrayBox>&        a_phi,
                            LevelData<FArrayBox>&              a_residual,
                            AMRLevelOp<LevelData<FArrayBox> >* a_finerOp)
{
  CH_TIME("VCAMRPoissonOp2::reflux");

  int ncomp = 1;
  ProblemDomain fineDomain = refine(m_domain, m_refToFiner);
  LevelFluxRegister levfluxreg(a_phiFine.disjointBoxLayout(),
                               a_phi.disjointBoxLayout(),
                               fineDomain,
                               m_refToFiner,
                               ncomp);

  levfluxreg.setToZero();
  Interval interv(0,a_phi.nComp()-1);

  DataIterator dit = a_phi.dataIterator();
  for (dit.reset(); dit.ok(); ++dit)
    {
      const FArrayBox& coarfab = a_phi[dit];
      const FluxBox& coarBCoef  = (*m_bCoef)[dit];
      const Box& gridBox = a_phi.getBoxes()[dit];

      for (int idir = 0; idir < SpaceDim; idir++)
        {
          FArrayBox coarflux;
          Box faceBox = surroundingNodes(gridBox, idir);
          getFlux(coarflux, coarfab, coarBCoef , faceBox, idir);

          Real scale = 1.0;
          levfluxreg.incrementCoarse(coarflux, scale,dit(),
                                     interv,interv,idir);
        }
    }
  LevelData<FArrayBox>& p = ( LevelData<FArrayBox>&)a_phiFine;

  // has to be its own object because the finer operator
  // owns an interpolator and we have no way of getting to it
  VCAMRPoissonOp2* finerAMRPOp = (VCAMRPoissonOp2*) a_finerOp;
  QuadCFInterp& quadCFI = finerAMRPOp->m_interpWithCoarser;

  quadCFI.coarseFineInterp(p, a_phi);
  // p.exchange(a_phiFine.interval()); // BVS is pretty sure this is not necesary.
  IntVect phiGhost = p.ghostVect();

  DataIterator ditf = a_phiFine.dataIterator();
  const  DisjointBoxLayout& dblFine = a_phiFine.disjointBoxLayout();
  for (ditf.reset(); ditf.ok(); ++ditf)
    {
      const FArrayBox& phifFab = a_phiFine[ditf];
      const FluxBox& fineBCoef  = (*(finerAMRPOp->m_bCoef))[ditf];
      const Box& gridbox = dblFine.get(ditf());
      for (int idir = 0; idir < SpaceDim; idir++)
        {
          int normalGhost = phiGhost[idir];
          SideIterator sit;
          for (sit.begin(); sit.ok(); sit.next())
            {
              Side::LoHiSide hiorlo = sit();
              Box fabbox;
              Box facebox;

              // assumption here that the stencil required
              // to compute the flux in the normal direction
              // is 2* the number of ghost cells for phi
              // (which is a reasonable assumption, and probably
              // better than just assuming you need one cell on
              // either side of the interface
              // (dfm 8-4-06)
              if (sit() == Side::Lo)
                {
                  fabbox = adjCellLo(gridbox,idir, 2*normalGhost);
                  fabbox.shift(idir, 1);
                  facebox = bdryLo(gridbox, idir,1);
                }
              else
                {
                  fabbox = adjCellHi(gridbox,idir, 2*normalGhost);
                  fabbox.shift(idir, -1);
                  facebox = bdryHi(gridbox, idir, 1);
                }

              // just in case we need ghost cells in the transverse direction
              // (dfm 8-4-06)
              for (int otherDir=0; otherDir<SpaceDim; ++otherDir)
                {
                  if (otherDir != idir)
                    {
                      fabbox.grow(otherDir, phiGhost[otherDir]);
                    }
                }
              CH_assert(!fabbox.isEmpty());

              FArrayBox phifab(fabbox, a_phi.nComp());
              phifab.copy(phifFab);

              FArrayBox fineflux;
              getFlux(fineflux, phifab, fineBCoef, facebox, idir,
                      m_refToFiner);

              Real scale = 1.0;
              levfluxreg.incrementFine(fineflux, scale, ditf(),
                                       interv, interv, idir, hiorlo);
            }
        }
    }

  Real scale =  1.0/m_dx;
  levfluxreg.reflux(a_residual, scale);
}
Exemple #27
0
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
}
// ---------------------------------------------------------------
// tag cells for regridding
void
AMRNavierStokes::tagCells(IntVectSet & a_tags)
{
  if (s_verbosity >= 3)
    {
      pout () << "AMRNavierStokes::tagCells " << m_level << endl;
    }

  IntVectSet local_tags;

  // create tags based on something or other
  // for now, don't do anything
  const DisjointBoxLayout& level_domain = newVel().getBoxes();

  if (s_tag_vorticity)
    {
      LevelData<FArrayBox> vorticity;
      LevelData<FArrayBox> mag_vorticity;
      if (SpaceDim == 2)
        {
          vorticity.define(level_domain,1);
        }
      else if (SpaceDim == 3)
        {
          vorticity.define(level_domain,SpaceDim);
          mag_vorticity.define(level_domain,1);
        }
      computeVorticity(vorticity);

      Interval vortInterval(0,0);
      if (SpaceDim == 3)
        {
          vortInterval = Interval(0,SpaceDim-1);
        }
      Real tagLevel = norm(vorticity, vortInterval, 0);
      // Real tagLevel = 1.0;
      //tagLevel *= s_vort_factor/m_dx;
      // actually tag where vort*dx > s_vort_factor*max(vort)
      tagLevel = s_vort_factor/m_dx;

      if (tagLevel > 0)
        {
          // now tag where vorticity magnitude is greater than or equal
          // to tagLevel
          DataIterator dit = vorticity.dataIterator();
          for (dit.reset(); dit.ok(); ++dit)
            {
              FArrayBox& vortFab = vorticity[dit];

              // this only needs to be done in 3d...
              if (SpaceDim==3)
                {
                  FArrayBox& magVortFab = mag_vorticity[dit];
                  FORT_MAGVECT(CHF_FRA1(magVortFab,0),
                               CHF_CONST_FRA(vortFab),
                               CHF_BOX(level_domain[dit]));
                }

              BoxIterator bit(vortFab.box());
              for (bit.begin(); bit.ok(); ++bit)
                {
                  const IntVect& iv = bit();
                  if (SpaceDim == 2)
                    {
                      if (abs(vortFab(iv)) >= tagLevel)
                        {
                          local_tags |= iv;
                        }
                    }
                  else if (SpaceDim == 3)
                    {
                      FArrayBox& magVortFab = mag_vorticity[dit];
                      if (abs(magVortFab(iv)) >= tagLevel)
                        {
                          local_tags |= iv;
                        }
                    } // end if DIM=3
                } // end loop over interior of box
            } // loop over grids
        } // if taglevel > 0
    } // if tagging on vorticity

  a_tags = local_tags;
}
void
LevelFluxRegisterEdge::refluxCurl(LevelData<FluxBox>& a_uCoarse,
                                  Real a_scale)
{
  CH_assert(isDefined());
  CH_assert(a_uCoarse.nComp() == m_nComp);

  SideIterator side;
  // idir is the normal direction to the coarse-fine interface
  for (int idir=0 ; idir<SpaceDim; ++idir)
  {
    for (side.begin(); side.ok(); ++side)
    {
      LevelData<FluxBox>& fineReg = m_fabFine[index(idir, side())];

      // first, create temp LevelData<FluxBox> to hold "coarse flux"
      const DisjointBoxLayout coarseBoxes = m_regCoarse.getBoxes();

      // this fills the place of what used to be m_fabCoarse in the old
      // implementation
      LevelData<FluxBox> coarReg(coarseBoxes, m_nComp, IntVect::Unit);


      // now fill the coarReg with the curl of the stored coarse-level
      // edge-centered flux
      DataIterator crseDit = coarseBoxes.dataIterator();
      for (crseDit.begin(); crseDit.ok(); ++crseDit)
        {
          FluxBox& thisCoarReg = coarReg[crseDit];
          thisCoarReg.setVal(0.0);

          EdgeDataBox& thisEdgeData = m_regCoarse[crseDit];

          for (int edgeDir=0; edgeDir<SpaceDim; edgeDir++)
            {
              if (idir != edgeDir)
                {
                  FArrayBox& crseEdgeDataDir = thisEdgeData[edgeDir];
                  for (int faceDir = 0; faceDir<SpaceDim; faceDir++)
                    {
                      if (faceDir != edgeDir)
                        {
                          FArrayBox& faceData = thisCoarReg[faceDir];
                          int shiftDir = -1;
                          for (int i=0; i<SpaceDim; i++)
                            {
                              if ((i != faceDir) && (i != edgeDir) )
                                {
                                  shiftDir = i;
                                }
                            }
                          CH_assert(shiftDir >= 0);
                          crseEdgeDataDir.shiftHalf(shiftDir, sign(side()));
                          // scaling already taken care of in incrementCrse
                          Real scale = 1.0;
                          faceData.plus(crseEdgeDataDir, scale, 0, 0, faceData.nComp());
                          crseEdgeDataDir.shiftHalf(shiftDir, -sign(side()));
                        } // end if not normal direction
                    } // end loop over face directions
                } // end if edgeDir != idir
            } // end loop over edge directions
        } // end loop over crse boxes


      // first, we need to create a temp LevelData<FluxBox>
      // to make a local copy in the coarse layout space of
      // the fine register increments

      LevelData<FluxBox> fineRegLocal(coarReg.getBoxes(), m_nComp, IntVect::Unit);

      fineReg.copyTo(fineReg.interval(), fineRegLocal,
                     fineRegLocal.interval(),
                     m_crseCopiers[index(idir,side())]);

      for (DataIterator it = a_uCoarse.dataIterator(); it.ok(); ++it)
        {
          // loop over flux components here
          for (int fluxComp=0; fluxComp < SpaceDim; fluxComp++)
            {
              // we don't do anything in the normal direction
              if (fluxComp != idir)
                {
                  // fluxDir is the direction of the face-centered flux
                  FArrayBox& U = a_uCoarse[it()][fluxComp];
                  // set up IntVectSet to avoid double counting of updates
                  Box coarseGridBox = U.box();
                  // transfer to Cell-centered, then create IVS
                  coarseGridBox.shiftHalf(fluxComp,1);
                  IntVectSet nonUpdatedEdges(coarseGridBox);

                  // remember, we want to take the curl here
                  // also recall that fluxComp is the component
                  // of the face-centered curl (not the edge-centered
                  // vector field that we're refluxing, which is why
                  // the sign may seem like it's the opposite of what
                  // you might expect!
                  Real local_scale = -sign(side())*a_scale;
                  //int testDir = (fluxComp+1)%(SpaceDim);
                  if (((fluxComp+1)%(SpaceDim)) == idir)  local_scale *= -1;
                  Vector<IntVectSet>& ivsV =
                    m_refluxLocations[index(idir, side())][it()][fluxComp];
                  Vector<DataIndex>&  indexV =
                    m_coarToCoarMap[index(idir, side())][it()];
                  IVSIterator iv;

                  for (int i=0; i<ivsV.size(); ++i)
                    {
                      iv.define(ivsV[i]);
                      const FArrayBox& coar = coarReg[indexV[i]][fluxComp];
                      const FArrayBox& fine = fineRegLocal[indexV[i]][fluxComp];
                      for (iv.begin(); iv.ok(); ++iv)
                        {
                          IntVect thisIV = iv();
                          if (nonUpdatedEdges.contains(thisIV))
                          {
                            for (int comp=0; comp <m_nComp; ++comp)
                              {
                                //Real coarVal = coar(thisIV, comp);
                                //Real fineVal = fine(thisIV, comp);
                                U(thisIV, comp) -=
                                local_scale*(coar(thisIV, comp)
                                             +fine(thisIV, comp));
                              }
                            nonUpdatedEdges -= thisIV;
                          }
                        }

                    }
                } // end if not normal face
            } // end loop over fluxbox directions
        } // end loop over coarse boxes
    } // end loop over sides
  } // end loop over directions
}