예제 #1
0
void VCAMRPoissonOp2::residualI(LevelData<FArrayBox>&       a_lhs,
                               const LevelData<FArrayBox>& a_phi,
                               const LevelData<FArrayBox>& a_rhs,
                               bool                        a_homogeneous)
{
  CH_TIME("VCAMRPoissonOp2::residualI");

  LevelData<FArrayBox>& phi = (LevelData<FArrayBox>&)a_phi;
  Real dx = m_dx;
  const DisjointBoxLayout& dbl = a_lhs.disjointBoxLayout();
  DataIterator dit = phi.dataIterator();
  {
    CH_TIME("VCAMRPoissonOp2::residualIBC");

    for (dit.begin(); dit.ok(); ++dit)
    {
      m_bc(phi[dit], dbl[dit()],m_domain, dx, a_homogeneous);
    }
  }

  phi.exchange(phi.interval(), m_exchangeCopier);

  for (dit.begin(); dit.ok(); ++dit)
    {
      const Box& region = dbl[dit()];
      const FluxBox& thisBCoef = (*m_bCoef)[dit];

#if CH_SPACEDIM == 1
      FORT_VCCOMPUTERES1D
#elif CH_SPACEDIM == 2
      FORT_VCCOMPUTERES2D
#elif CH_SPACEDIM == 3
      FORT_VCCOMPUTERES3D
#else
      This_will_not_compile!
#endif
                         (CHF_FRA(a_lhs[dit]),
                          CHF_CONST_FRA(phi[dit]),
                          CHF_CONST_FRA(a_rhs[dit]),
                          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_BOX(region),
                          CHF_CONST_REAL(m_dx));
    } // end loop over boxes
}
void EBLevelTransport::
divergeF(LevelData<EBCellFAB>&         a_divergeF,
         LevelData<BaseIVFAB<Real> >&  a_massDiff,
         EBFluxRegister&               a_fineFluxRegister,
         EBFluxRegister&               a_coarFluxRegister,
         LevelData<EBCellFAB>&         a_consState,   //not really changed
         LevelData<EBCellFAB>&         a_normalVel,
         const LevelData<EBFluxFAB>&   a_advVel,
         const LayoutData< Vector <BaseIVFAB<Real> * > >& a_coveredAdvVelMinu,
         const LayoutData< Vector <BaseIVFAB<Real> * > >& a_coveredAdvVelPlus,
         const LevelData<EBCellFAB>&   a_source,
         const LevelData<EBCellFAB>&   a_consStateCoarseOld,
         const LevelData<EBCellFAB>&   a_consStateCoarseNew,
         const LevelData<EBCellFAB>&   a_normalVelCoarseOld,
         const LevelData<EBCellFAB>&   a_normalVelCoarseNew,
         const Real&                   a_time,
         const Real&                   a_coarTimeOld,
         const Real&                   a_coarTimeNew,
         const Real&                   a_dt)
{
  Interval consInterv(0, m_nCons-1);
  Interval fluxInterv(0, m_nFlux-1);
  CH_assert(isDefined());

  CH_assert(a_consState.disjointBoxLayout() == m_thisGrids);

  //fill a_consState with data interpolated between constate and coarser data
  fillCons(a_consState, a_normalVel, a_consStateCoarseOld, a_consStateCoarseNew, a_normalVelCoarseOld, a_normalVelCoarseNew, a_time, a_coarTimeOld, a_coarTimeNew); 

  // clear flux registers with fine level
  //remember this level is the coarse level to the fine FR
  if(m_hasFiner)
    {
      a_fineFluxRegister.setToZero();
    }

  //compute flattening coefficients. this saves a ghost cell. woo hoo.
  computeFlattening(a_consState, a_time, a_dt);

  //this includes copying flux into flux interpolant and updating
  //regular grids and incrementing flux registers.

  doRegularUpdate(a_divergeF, a_consState, a_normalVel, a_advVel, a_coveredAdvVelMinu, a_coveredAdvVelPlus, a_fineFluxRegister, a_coarFluxRegister, a_source, a_time, a_dt);

  //this does irregular update and deals with flux registers.
  //also computes the mass increment
  doIrregularUpdate(a_divergeF, a_consState, a_fineFluxRegister, a_coarFluxRegister, a_massDiff, a_time, a_dt);

}
예제 #3
0
// Set up initial conditions
void AdvectTestIBC::initialize(LevelData<FArrayBox>& a_U)
{
  DisjointBoxLayout grids = a_U.disjointBoxLayout();
  for (DataIterator dit = grids.dataIterator(); dit.ok(); ++dit)
    {
      const Box& grid = grids.get(dit());
      FORT_ADVECTINITF(CHF_FRA1(a_U[dit()],0),
                       CHF_CONST_REALVECT(m_center),
                       CHF_CONST_REAL(m_size),
                       CHF_CONST_REAL(m_dx),
                       CHF_BOX(grid));

    }

}
예제 #4
0
void VCAMRPoissonOp2::applyOpNoBoundary(LevelData<FArrayBox>&      a_lhs,
                                        const LevelData<FArrayBox>& a_phi)
{
  CH_TIME("VCAMRPoissonOp2::applyOpNoBoundary");

  LevelData<FArrayBox>& phi = (LevelData<FArrayBox>&)a_phi;

  const DisjointBoxLayout& dbl = a_lhs.disjointBoxLayout();
  DataIterator dit = phi.dataIterator();

  phi.exchange(phi.interval(), m_exchangeCopier);

  for (dit.begin(); dit.ok(); ++dit)
    {
      const Box& region = dbl[dit()];
      const FluxBox& thisBCoef = (*m_bCoef)[dit];

#if CH_SPACEDIM == 1
      FORT_VCCOMPUTEOP1D
#elif CH_SPACEDIM == 2
      FORT_VCCOMPUTEOP2D
#elif CH_SPACEDIM == 3
      FORT_VCCOMPUTEOP3D
#else
      This_will_not_compile!
#endif
                        (CHF_FRA(a_lhs[dit]),
                         CHF_CONST_FRA(phi[dit]),
                         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_BOX(region),
                         CHF_CONST_REAL(m_dx));
    } // end loop over boxes
}
예제 #5
0
void VCAMRPoissonOp2::applyOpI(LevelData<FArrayBox>&      a_lhs,
                             const LevelData<FArrayBox>& a_phi,
                             bool                        a_homogeneous )
{
  CH_TIME("VCAMRPoissonOp2::applyOpI");
  LevelData<FArrayBox>& phi = (LevelData<FArrayBox>&)a_phi;
  Real dx = m_dx;
  const DisjointBoxLayout& dbl = a_lhs.disjointBoxLayout();
  DataIterator dit = phi.dataIterator();

  for (dit.begin(); dit.ok(); ++dit)
    {
      m_bc(phi[dit], dbl[dit()],m_domain, dx, a_homogeneous);
    }

  applyOpNoBoundary(a_lhs, a_phi);
}
예제 #6
0
// Find the maximum wave speed on the current level
Real OldLevelGodunov::getMaxWaveSpeed(const LevelData<FArrayBox>& a_U)
{
  const DisjointBoxLayout& disjointBoxLayout = a_U.disjointBoxLayout();
  DataIterator dit = disjointBoxLayout.dataIterator();

  // Initial maximum wave speed
  Real speed = 0.0;

  // This computation doesn't need involve a time but the time being set
  // is checked by OldPatchGodunov::getMaxWaveSpeed so we have to set it
  // to something...
  m_patchGodunov->setCurrentTime(0.0);

  // Loop over all grids to get the maximum wave speed
  for (dit.begin(); dit.ok(); ++dit)
    {
      const Box& currentBox = disjointBoxLayout.get(dit());

      // Set the current box and get the maximum wave speed on the current grid
      m_patchGodunov->setCurrentBox(currentBox);
      Real speedOverBox = m_patchGodunov->getMaxWaveSpeed(a_U[dit()],
                                                          currentBox);

      // Compute a running maximum
      speed = Max(speed,speedOverBox);
    }

  // Gather maximum wave speeds and broadcast the maximum over these
  Vector<Real> allSpeeds;

  gather(allSpeeds,speed,uniqueProc(SerialTask::compute));

  if (procID() == uniqueProc(SerialTask::compute))
    {
      speed = allSpeeds[0];
      for (int i = 1; i < allSpeeds.size (); ++i)
        {
          speed = Max(speed,allSpeeds[i]);
        }
    }

  broadcast(speed,uniqueProc(SerialTask::compute));

  // Return the maximum wave speed
  return speed;
}
예제 #7
0
void
EBMGInterp::fillGhostCellsPWC(LevelData<EBCellFAB>& a_data,
                              const EBISLayout&     a_ebisl,
                              const ProblemDomain&  a_dom)
{
  for (int idir = 0; idir < SpaceDim; idir++)
    {
      if (m_ghost[idir] < 1)
        {
          MayDay::Error("EBMGInterp:I need a ghost cell for linear interpolation");
        }
    }
  //extrapolate to every ghost cell
  const DisjointBoxLayout& dbl = a_data.disjointBoxLayout();
  for (DataIterator dit = dbl.dataIterator(); dit.ok(); ++dit)
    {
      const Box& grid = dbl.get(dit());
      const EBGraph& ebgraph = a_ebisl[dit()].getEBGraph();
      for (int idir = 0; idir < SpaceDim; idir++)
        {
          for (SideIterator sit; sit.ok(); ++sit)
            {
              Side::LoHiSide flipSide = flip(sit());
              Box ghostBox = adjCellBox(grid, idir, sit(), 1);

              for (BoxIterator boxit(ghostBox); boxit.ok(); ++boxit)
                {
                  if (a_dom.contains(boxit()))
                    {
                      Vector<VolIndex> vofs = ebgraph.getVoFs(boxit());
                      for (int ivof = 0; ivof < vofs.size(); ivof++)
                        {
                          Real extrapVal = 0;
                          Vector<FaceIndex> faces = ebgraph.getFaces(vofs[ivof], idir, flipSide);
                          for (int ivar = 0; ivar < a_data.nComp(); ivar++)
                            {
                              for (int iface = 0; iface < faces.size(); iface++)
                                {
                                  const VolIndex& flipVoF = faces[iface].getVoF(flipSide);
                                  extrapVal += a_data[dit()](flipVoF, ivar);
                                }
                              if (faces.size() > 1) extrapVal /= faces.size();
                              a_data[dit()](vofs[ivof], ivar) = extrapVal;
                            }
                        }

                    }
                  else
                    {
                      //just put in the single valued part of the data holder something sensible
                      //if not inside domain
                      int isign = sign(flipSide);
                      BaseFab<Real>& bfdata = a_data[dit()].getSingleValuedFAB();
                      IntVect otherIV = boxit() + isign*BASISV(idir);
                      for (int ivar = 0; ivar < a_data.nComp(); ivar++)
                        {
                          bfdata(boxit(), ivar) = bfdata(otherIV, ivar);
                        }
                    }
                }
            }
        }
    }
  //do exchange to overwrite ghost cells where there exists real data
  a_data.exchange();
}
예제 #8
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
}
예제 #9
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);
}
예제 #10
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);
}
예제 #11
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));
    }
}
예제 #12
0
void EBPoissonOp::
restrictResidual(LevelData<EBCellFAB>&       a_resCoar,
                 LevelData<EBCellFAB>&       a_phiThisLevel,
                 const LevelData<EBCellFAB>& a_rhsThisLevel)
{
  CH_TIME("EBPoissonOp::restrictResidual");

  CH_assert(a_resCoar.nComp() == 1);
  CH_assert(a_phiThisLevel.nComp() == 1);
  CH_assert(a_rhsThisLevel.nComp() == 1);

  LevelData<EBCellFAB> resThisLevel;
  bool homogeneous = true;

  EBCellFactory ebcellfactTL(m_eblg.getEBISL());
  IntVect ghostVec = a_rhsThisLevel.ghostVect();

  resThisLevel.define(m_eblg.getDBL(), 1, ghostVec, ebcellfactTL);

  // Get the residual on the fine grid
  residual(resThisLevel,a_phiThisLevel,a_rhsThisLevel,homogeneous);

  // now use our nifty averaging operator
  Interval variables(0, 0);
  CH_assert(m_hasMGObjects);
  m_ebAverageMG.average(a_resCoar, resThisLevel, variables);

#ifdef DO_EB_RHS_CORRECTION
  // Apply error-correction modification to restricted RHS
  // Right now this only works with Dirichlet BC's, and only makes sense for the EB

  int correctionType = 0;    // Change this to activate RHS correction

  if (correctionType != 0)
    {
      for (DataIterator dit = a_resCoar.disjointBoxLayout().dataIterator(); dit.ok(); ++dit)
        {
          EBCellFAB&       resFAB = a_resCoar[dit()];                      // Extract the FAB for this box
          const EBISBox&   ebis   = resFAB.getEBISBox();                   // Get the set of all IntVect indices

          // Iterate over the parts of the RHS corresponding to the irregular cells,
          // correcting the RHS in each cell
          VoFIterator ebvofit(ebis.getIrregIVS(ebis.getRegion()), ebis.getEBGraph());
          for (ebvofit.reset(); ebvofit.ok(); ++ebvofit)
            {
              for (int icomp = 0; icomp < resFAB.nComp(); ++icomp)    // For each component of the residual on this VoF
                {
                  if (correctionType == 1)
                    {
                      // Setting the residual to zero on the irregular cells gives convergence,
                      // though the rate isn't as good as the full correction
                      resFAB(ebvofit(), icomp) = 0.0;
                    }
                  else if (correctionType == 2)
                    {
                      // Kludge valid only for pseudo-1D test case.  May not work for you.
                      Real kappa = ebis.volFrac(ebvofit());
                      kappa = (kappa > 0.5 ? kappa : 0.5);    // Floor on kappa to prevent dividing by a tiny number
                      Real rhoCoeff = (kappa + 0.5)/(2.0*kappa);
                      resFAB(ebvofit(), icomp) *= (1.0 - rhoCoeff);
                    }
                  // else silently do nothing
                }
            }
        }
    }
#endif
}