// -----------------------------------------------------------------------------
// This does the actual computation to update the state variables.
// I've included this function since the initializeGlobalPressure() and advance()
// functions are, for the most part, the same piece of code.
// -----------------------------------------------------------------------------
void AMRNavierStokes::PPMIGTimeStep (const Real a_oldTime,
                                     const Real a_dt,
                                     const bool a_updatePassiveScalars,
                                     const bool a_doLevelProj)
{
    CH_TIME("AMRNavierStokes::PPMIGTimeStep");
    pout() << setiosflags(ios::scientific) << setprecision(8) << flush;

    // Set up some basic values
    const RealVect& dx = m_levGeoPtr->getDx();
    const DisjointBoxLayout& grids = newVel().getBoxes();
    DataIterator dit = grids.dataIterator();
    const Box domainBox = m_problem_domain.domainBox();
    const bool isViscous = (s_nu > 0.0);

    // Initialize all flux registers
    if (!finestLevel()) {
        m_vel_flux_reg.setToZero();
        for (int comp = 0; comp < s_num_scal_comps; ++comp) {
            m_scal_fluxreg_ptrs[comp]->setToZero();
        }
        m_lambda_flux_reg.setToZero();
    }

    // Sanity checks
    CH_assert(m_levGeoPtr->getBoxes() == grids);
    CH_assert(m_levGeoPtr->getDomain() == m_problem_domain);
    CH_assert(Abs(a_oldTime - (m_time - a_dt)) < TIME_EPS);
    CH_assert(s_num_scal_comps <= 1);
    CH_assert(s_num_scal_comps > 0 || s_gravityMethod == ProblemContext::GravityMethod::NONE);

    // Reference new holders
    LevelData<FArrayBox>& new_vel = newVel();
    LevelData<FArrayBox>& new_lambda = newLambda();
    LevelData<FArrayBox> new_b;
    if (s_num_scal_comps > 0) {
        aliasLevelData(new_b, &(newScal(0)), Interval(0,0));
    }


    // Compute advecting velocities
    LevelData<FArrayBox> old_vel(grids, SpaceDim, m_tracingGhosts);
    fillVelocity(old_vel, a_oldTime);
    old_vel.exchange(m_tracingExCopier);

    LevelData<FluxBox> adv_vel(grids, 1, IntVect::Unit); // Changed from m_tracingGhosts to 1
    computeAdvectingVelocities(adv_vel, old_vel, a_oldTime, a_dt);

    if (a_updatePassiveScalars) {
        // Lambda update
        LevelData<FArrayBox> old_lambda;
        fillLambda(old_lambda, a_oldTime);
        old_lambda.exchange(m_tracingExCopier);

        LevelData<FArrayBox> dLdt(grids, 1);
        getNewLambda(dLdt, new_lambda, old_lambda, old_vel, adv_vel, a_oldTime, a_dt, a_dt);
    }

    LevelData<FArrayBox> old_b;
    if (s_num_scal_comps > 0) {
        // Scalar update
        fillScalars(old_b, a_oldTime, 0);
        old_b.exchange(m_tracingExCopier);

        LevelData<FArrayBox> dSdt(grids, 1);
        getNewScalar(dSdt, new_b, old_b, old_vel, adv_vel, a_oldTime, a_dt, a_dt, 0);
    }

    for (int comp = 1; comp < s_num_scal_comps; ++comp) {
        // Scalar update
        LevelData<FArrayBox> old_scal;
        fillScalars(old_scal, a_oldTime, comp);
        old_scal.exchange(m_tracingExCopier);

        LevelData<FArrayBox> dSdt(grids, 1);
        getNewScalar(dSdt, newScal(comp), old_scal, old_vel, adv_vel, a_oldTime, a_dt, a_dt, comp);
    }

    {   // Update CC velocities
        LevelData<FArrayBox> dUdt(grids, SpaceDim);
        getNewVelocity(dUdt, new_vel, old_vel, adv_vel, a_oldTime, a_dt, a_dt);
    }

    if (s_num_scal_comps > 0) {
        // Do implicit gravity update and CC projection.
        doCCIGProjection(new_vel, new_b, old_vel, old_b, adv_vel, a_oldTime, a_dt, a_doLevelProj);
    } else {
        // Do a standard CC projection.
        doCCProjection(new_vel, a_oldTime + a_dt, a_dt, a_doLevelProj);
    }
}
Esempio n. 2
0
// ---------------------------------------------------------------
// advance solution by one timestep
// return max safe timestep
Real
AMRNavierStokes::advance()
{
  if (s_verbosity >= 2)
  {
    pout () << "AMRNavierStokes::advance " << m_level
            << ", starting time = "
            << setiosflags(ios::fixed) << setprecision(6)
            << setw(12) << m_time
            << ", dt = "
            << setiosflags(ios::fixed) << setprecision(6) << setw(12) << dt()
            << endl;
  }

#ifdef DEBUG
  // if we're at the beginning of a composite timestep,
  // save current multilevel state
  if (m_level == 0)
    {
      AMRNavierStokes* levelPtr = this;
      // figure out finest level
      while (!levelPtr->finestLevel())
        {
          levelPtr = levelPtr->finerNSPtr();
        }
    int finest_level = levelPtr->m_level;

    levelPtr = this;
    for (int lev=0; lev<= finest_level; lev++)
      {
        levelPtr->m_saved_time = m_time;

        levelPtr->newVel().copyTo(levelPtr->newVel().interval(),
                                  *levelPtr->m_vel_save_ptr,
                                  levelPtr->m_vel_save_ptr->interval());

        levelPtr->newLambda().copyTo(levelPtr->newLambda().interval(),
                                     *levelPtr->m_lambda_save_ptr,
                                     levelPtr->m_lambda_save_ptr->interval());

        for (int comp=0; comp<s_num_scal_comps; comp++)
          {
            levelPtr->newScal(comp).copyTo(levelPtr->newScal(comp).interval(),
                                           *levelPtr->m_scal_save[comp],
                                           levelPtr->m_scal_save[comp]->interval());
          }

        levelPtr = levelPtr->finerNSPtr();
      }
    }
#endif

  Real old_time = m_time;
  Real new_time = m_time + m_dt;
  m_dt_save = m_dt;
  swapOldAndNewStates();

  const DisjointBoxLayout levelGrids = newVel().getBoxes();

  // initialize flux registers
  if (!finestLevel())
    {
      m_flux_register.setToZero();
      for (int comp=0; comp<s_num_scal_comps; comp++)
        {
          m_scal_fluxreg_ptrs[comp]->setToZero();
        }
      m_lambda_flux_reg.setToZero();
    }

  // compute advection velocities -- if we're using the
  // patchGodunov approach, these will have ghost cells.
  IntVect advVelGhost(IntVect::Unit);
  LevelData<FluxBox> advectionVel(levelGrids, 1, advVelGhost);

  if (s_set_bogus_values)
    {
      setValLevel(advectionVel, s_bogus_value);
    }

  computeAdvectionVelocities(advectionVel);

  // now that advection velocities have been computed,
  // update advected scalars

  // do scalar boundary conditions on lambda
  // (also grow to appropriate size)

  LevelData<FArrayBox> lambdaTemp;

  fillLambda(lambdaTemp, old_time);

  LevelFluxRegister* crseLambdaFluxRegPtr = NULL;
  if (m_level > 0)
    {
      crseLambdaFluxRegPtr = &(crseNSPtr()->m_lambda_flux_reg);
    }

  advectScalar(newLambda(), lambdaTemp, advectionVel,
               crseLambdaFluxRegPtr, m_lambda_flux_reg,
               m_patchGodLambda,
               m_dt);

  // now do advected-diffused scalars
  if (s_num_scal_comps > 0)
    {
      // loop over scalar components
      for (int comp=0; comp<s_num_scal_comps; comp++)
        {
          BCHolder scalPhysBCs = m_physBCPtr->scalarTraceFuncBC(comp);

          LevelData<FArrayBox> scalarTemp;
          fillScalars(scalarTemp, old_time,comp);

          // now get coarse-level scalars for BC's if necessary
          LevelData<FArrayBox>* newCrseScalPtr = NULL;
          LevelData<FArrayBox>* oldCrseScalPtr = NULL;
          Real oldCrseTime = -s_bogus_value;
          Real newCrseTime = s_bogus_value;
          LevelFluxRegister* crseScalFluxRegPtr = NULL;

          if (m_level > 0)
            {
              newCrseScalPtr = &(crseNSPtr()->newScal(comp));
              oldCrseScalPtr = &(crseNSPtr()->oldScal(comp));
              newCrseTime = crseNSPtr()->time();
              oldCrseTime = newCrseTime - crseNSPtr()->dt();
              crseScalFluxRegPtr = (crseNSPtr()->m_scal_fluxreg_ptrs[comp]);
            }

          advectDiffuseScalar(newScal(comp), scalarTemp,
                              advectionVel,
                              s_scal_coeffs[comp],
                              oldCrseScalPtr, newCrseScalPtr,
                              oldCrseTime, newCrseTime,
                              crseScalFluxRegPtr,
                              *(m_scal_fluxreg_ptrs[comp]),
                              *(m_patchGodScalars[comp]),
                              scalPhysBCs,
                              m_dt, comp);
        } // end loop over components
    } // end advected-diffused scalars

  // now predict velocities -- this returns the advection term
  // put this in "new_vel"
  LevelData<FArrayBox>& uStar = newVel();
  predictVelocities(uStar, advectionVel);

  computeUStar(uStar);

  // if a coarser level exists, will need coarse-level data for proj
  LevelData<FArrayBox>* crseVelPtr = NULL;

  if (m_level > 0)
    {
      const DisjointBoxLayout& crseGrids = crseNSPtr()->newVel().getBoxes();
      crseVelPtr = new LevelData<FArrayBox>(crseGrids, SpaceDim);
      // coarse velocity BC data is interpolated in time
      crseNSPtr()->fillVelocity(*crseVelPtr, new_time);
    }

  // need to do physical boundary conditions and exchanges
  bool isViscous = (s_nu > 0);
  VelBCHolder velBC(m_physBCPtr->uStarFuncBC(isViscous));
  velBC.applyBCs(uStar, levelGrids,
                 m_problem_domain, m_dx,
                 false); // inhomogeneous

  // noel -- all time in level project
  m_projection.LevelProject(uStar, crseVelPtr, new_time, m_dt);

  // as things stand now, physical BC's are re-set in LevelProjection

  // compute maximum safe timestep for next iteration
  Real newDt = computeDt();

  // clean up temp storage
  if (crseVelPtr != NULL)
    {
      delete crseVelPtr;
      crseVelPtr = NULL;
    }

  ++m_level_steps;

  if (s_verbosity >= 2)
    {

      pout () << "AMRNavierStokes::advance " << m_level
              << ",      end time = "
              << setiosflags(ios::fixed) << setprecision(6) << setw(12) << m_time
              << ", dt = "
              << setiosflags(ios::fixed) << setprecision(6)
              << setw(12) << dt()
              << endl;
    }

  return newDt;
}
EBGradDivFilter::
EBGradDivFilter(const DisjointBoxLayout&                  a_gridsFine,
                const DisjointBoxLayout*                  a_gridsCoarPtr,
                const EBISLayout&                         a_ebislFine,
                const EBISLayout*                         a_ebislCoarPtr,
                const ProblemDomain&                      a_domainFine,
                const RealVect&                           a_dxFine,
                const int&                                a_refRat,
                const Real&                               a_lambdaScale,
                const EBIndexSpace* const                 a_ebisPtr)
{
  CH_TIME("EBGradDivFilter::EBGradDivFilter");
  m_gridsFine   =  a_gridsFine    ;
  m_gridsCoarPtr=  a_gridsCoarPtr ;
  m_ebislFine   =  a_ebislFine    ;
  m_eblgFine.define(m_gridsFine, m_ebislFine, m_domainFine);

  m_ebislCoarPtr=  a_ebislCoarPtr ;
  m_domainFine  =  a_domainFine   ;
  m_refRat      =  a_refRat       ;
  m_dxFine      =  a_dxFine;
  m_hasCoarser = (m_gridsCoarPtr != NULL);
  EBCellFactory ebcellfact(m_ebislFine);
  EBFluxFactory ebfluxfact(m_ebislFine);
  m_gradVel.define(m_gridsFine, SpaceDim*SpaceDim, IntVect::Unit, ebcellfact);
  m_lambda.define( m_gridsFine,                 1, IntVect::Zero, ebcellfact);
  m_faceDivCell.define(m_gridsFine,             1,4*IntVect::Unit, ebfluxfact);
  m_dropOrder.define( m_gridsFine);
  m_johanStencil.define(m_gridsFine);
  m_distanceAlongLine.define(m_gridsFine);

  for (DataIterator dit = m_gridsFine.dataIterator(); dit.ok(); ++dit)
    {
      BaseIVFAB<VoFStencil>& curJohanStencil      = m_johanStencil[dit()];
      BaseIVFAB<char>&       curDropOrder         = m_dropOrder[dit()];
      BaseIVFAB<Real>&       curDistanceAlongLine = m_distanceAlongLine[dit()];

      EBGraph ebgraph =  m_ebislFine[dit()].getEBGraph();
      IntVectSet ivsIrreg = m_ebislFine[dit()].getIrregIVS(m_gridsFine.get(dit()));
      curJohanStencil.define(     ivsIrreg,ebgraph, 2);
      curDistanceAlongLine.define(ivsIrreg,ebgraph, 2);
      curDropOrder.define(        ivsIrreg,ebgraph, 1);

      for (VoFIterator vofit(ivsIrreg, ebgraph); vofit.ok(); ++vofit)
        {
          Vector<VoFStencil> pointStencils;
          Vector<Real>       distanceAlongLine;
          bool dropOrder = false;
          EBArith::johanStencil(dropOrder,
                                pointStencils,
                                distanceAlongLine,
                                vofit(), m_ebislFine[dit()], m_dxFine,
                                (*m_eblgFine.getCFIVS())[dit()]);

          curDropOrder(vofit(), 0) = dropOrder;
          if (!dropOrder)
            {
              for (int ipoint = 0; ipoint < 2; ipoint++)
                {
                  curJohanStencil(vofit(), ipoint)      = pointStencils[ipoint];
                  curDistanceAlongLine(vofit(), ipoint) = distanceAlongLine[ipoint];
                }
            }
        }
    }
  m_tensorCFI  = NULL;
  if (m_hasCoarser)
    {
      Real dx = a_dxFine[0];
      m_domainCoar  =  coarsen(m_domainFine, m_refRat);
      m_tensorCFI= new EBTensorCFInterp(m_gridsFine, *m_gridsCoarPtr,
                                        m_ebislFine, *m_ebislCoarPtr,
                                        m_domainCoar, m_refRat, SpaceDim, dx,
                                        *m_eblgFine.getCFIVS(), a_ebisPtr);

    }

  m_lambdaScale = a_lambdaScale;
  fillLambda();
}