Пример #1
0
 virtual void linearIn(EBCellFAB& arg,  void* buf, const Box& R,
                       const Interval& comps) const
 {
   EBCellFAB tmp;
   tmp.clone(arg);
   tmp.linearIn(buf, R, comps);
   arg.plus(tmp, R, comps.begin(), comps.begin(), comps.size());
 }
Пример #2
0
void
EBMGAverage::averageFAB(EBCellFAB&       a_coar,
                        const Box&       a_boxCoar,
                        const EBCellFAB& a_refCoar,
                        const DataIndex& a_datInd,
                        const Interval&  a_variables) const
{
  CH_TIMERS("EBMGAverage::average");
  CH_TIMER("regular_average", t1);
  CH_TIMER("irregular_average", t2);
  CH_assert(isDefined());

  const Box& coarBox = a_boxCoar;

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

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

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

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

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

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

}
Пример #3
0
 void op(EBCellFAB& dest,
         const Box& RegionFrom,
         const Interval& Cdest,
         const Box& RegionTo,
         const EBCellFAB& src,
         const Interval& Csrc) const
 {
   dest.plus(src, RegionFrom, Csrc.begin(), Cdest.begin(), Cdest.size());
 }
Пример #4
0
void
EBMGInterp::pwcInterpFAB(EBCellFAB&       a_refCoar,
                         const Box&       a_coarBox,
                         const EBCellFAB& a_coar,
                         const DataIndex& a_datInd,
                         const Interval&  a_variables) const
{
  CH_TIMERS("EBMGInterp::interp");
  CH_TIMER("regular_interp", t1);
  CH_TIMER("irregular_interp", t2);
  CH_assert(isDefined());

  const Box& coarBox = a_coarBox;

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

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

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

      CH_START(t1);

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

      CH_STOP(t1);

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

      CH_START(t2);
      m_interpEBStencil[a_datInd]->apply(a_refCoar, a_coar, true, ivar);
      CH_STOP(t2);
    }
}
Пример #5
0
void
EBStenVarCoef::
cache(const EBCellFAB& a_phi, int a_ivar)
{
  CH_assert(a_phi.getSingleValuedFAB().box()   == m_grownBox);
  const Real* singleValuedPtrPhi =    a_phi.getSingleValuedFAB().dataPtr(a_ivar);
  const Real*  multiValuedPtrPhi =     a_phi.getMultiValuedFAB().dataPtr(a_ivar);

  for (int isrc = 0; isrc < m_sourTerms.size(); isrc++)
    {
      //debugging hook
      //const VolIndex& srcVoF = m_srcVoFs[isrc];
      if (m_sourTerms[isrc].multiValued)
        {
          m_cache[isrc] = *(multiValuedPtrPhi + m_sourTerms[isrc].offset);
        }
      else
        {
          m_cache[isrc] = *(singleValuedPtrPhi + m_sourTerms[isrc].offset);
        }
    }
}
Пример #6
0
void
EBStenVarCoef::
uncache(EBCellFAB& a_phi, int a_ivar) const
{
  CH_assert(a_phi.getSingleValuedFAB().box()    == m_grownBox);

  Real* singleValuedPtrPhi =    a_phi.getSingleValuedFAB().dataPtr(a_ivar);
  Real*  multiValuedPtrPhi =     a_phi.getMultiValuedFAB().dataPtr(a_ivar);
  Real* phiPtr = NULL;

  for (int isrc = 0; isrc < m_sourTerms.size(); isrc++)
    {
      if (m_sourTerms[isrc].multiValued)
        {
          phiPtr  = multiValuedPtrPhi + m_sourTerms[isrc].offset;
        }
      else
        {
          phiPtr  = singleValuedPtrPhi + m_sourTerms[isrc].offset;
        }

      *phiPtr = m_cache[isrc];
    }
}
void
NeumannConductivityDomainBC::
getFaceGradPhi(Real&                 a_faceFlux,
               const FaceIndex&      a_face,
               const int&            a_comp,
               const EBCellFAB&      a_phi,
               const RealVect&       a_probLo,
               const RealVect&       a_dx,
               const int&            a_idir,
               const Side::LoHiSide& a_side,
               const DataIndex&      a_dit,
               const Real&           a_time,
               const bool&           a_useAreaFrac,
               const RealVect&       a_centroid,
               const bool&           a_useHomogeneous)
{
  const int iside = -sign(a_side);

  const EBISBox& ebisBox = a_phi.getEBISBox();

  Real flux = -1.e99;
  if (a_useHomogeneous)
    {
      flux = 0.0;
    }
  else if (m_isFunction)
    {
      const RealVect normal = EBArith::getDomainNormal(a_idir,a_side);
      RealVect point  = a_centroid;
      point *= a_dx;
      point[a_face.direction()] = 0.0;//make this not depend on whatever ebisbox is returning for centroid in the face direction.
      point += EBArith::getFaceLocation(a_face,a_dx,a_probLo);
      flux = m_flux->value(a_face,a_side,a_dit,point,normal,a_time,a_comp);
    }
  else
    {
      if (m_onlyHomogeneous)
        {
          MayDay::Error("NeumannPoissonDomainBC::getFaceFlux called with undefined inhomogeneous BC");
        }
      flux = m_value;
    }
  a_faceFlux = iside*flux;
  if (a_useAreaFrac)
    {
      a_faceFlux *= ebisBox.areaFrac(a_face);
    }
}
void
NeumannConductivityDomainBC::
getFaceFlux(Real&                 a_faceFlux,
            const VolIndex&       a_vof,
            const int&            a_comp,
            const EBCellFAB&      a_phi,
            const RealVect&       a_probLo,
            const RealVect&       a_dx,
            const int&            a_idir,
            const Side::LoHiSide& a_side,
            const DataIndex&      a_dit,
            const Real&           a_time,
            const bool&           a_useHomogeneous)
{
  const EBISBox& ebisBox = a_phi.getEBISBox();

  Real totalMassFlux = 0.0;
  Vector<FaceIndex> faces = ebisBox.getFaces(a_vof,a_idir,a_side);
  for (int i = 0; i < faces.size(); i++)
    {
      const RealVect centroid = ebisBox.centroid(faces[i]);
      Real thisFaceFlux;
      getFaceGradPhi(thisFaceFlux,faces[i],a_comp,a_phi,a_probLo,
                         a_dx,a_idir,a_side,a_dit,a_time,true,centroid,a_useHomogeneous);
      totalMassFlux += thisFaceFlux;
    }

  a_faceFlux = totalMassFlux;

  Real bcoave = 0;
  Real areaTot = 0.0;
  for (int iface = 0; iface < faces.size(); iface++)
    {
      Real areaFrac = ebisBox.areaFrac(faces[iface]);
      areaTot += areaFrac;
      Real bcoFace  = (*m_bcoef)[a_dit][a_idir](faces[iface], 0);
      bcoave += areaFrac*bcoFace;
    }
  if (areaTot > 1.0e-8)
    {
      bcoave /= areaTot;
    }
  a_faceFlux *= bcoave;
}
Пример #9
0
void
setToExactDivF(EBCellFAB&     a_exactDivF,
               const EBISBox& a_ebisBox,
               const Box&     a_region,
               const Real&    a_dx)
{
    a_exactDivF.setVal(0.);
    IntVectSet ivsregion(a_region);
    for (VoFIterator vofit(ivsregion, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit)
    {
        const VolIndex& vof = vofit();
        RealVect xval;
        IntVect iv = vof.gridIndex();
        for (int idir = 0; idir < SpaceDim; idir++)
        {
            xval[idir] = (Real(iv[idir]) + 0.5)*a_dx;
        }
        Real solnrv = exactDivergence(xval);
        Real kappa = a_ebisBox.volFrac(vof);
        a_exactDivF(vof,0) = kappa*solnrv;
    }
}
Пример #10
0
void
EBPlanarShockIBC::
setBndrySlopes(EBCellFAB&       a_deltaPrim,
               const EBCellFAB& a_primState,
               const EBISBox&   a_ebisBox,
               const Box&       a_box,
               const int&       a_dir)
{
  // don't want to deal with the periodic case
 CH_assert(!m_domain.isPeriodic(a_dir));
 CH_assert(m_isDefined);
 CH_assert(m_isFortranCommonSet);

  Box loBox,hiBox,centerBox,domain;
  int hasLo,hasHi;
  Box slopeBox = a_deltaPrim.getRegion()&m_domain;
  int numSlop = a_deltaPrim.nComp();
  // Generate the domain boundary boxes, loBox and hiBox, if there are
  // domain boundarys there
  eblohicenter(loBox,hasLo,hiBox,hasHi,centerBox,domain,
             slopeBox,m_domain,a_dir);

  // Set the boundary slopes if necessary
  if ((hasLo != 0) || (hasHi != 0))
    {
      BaseFab<Real>& regDeltaPrim = a_deltaPrim.getSingleValuedFAB();
      const BaseFab<Real>& regPrimState = a_primState.getSingleValuedFAB();
      /**/
      FORT_SLOPEBCS(CHF_FRA(regDeltaPrim),
                    CHF_CONST_FRA(regPrimState),
                    CHF_CONST_REAL(m_dx),
                    CHF_CONST_INT(a_dir),
                    CHF_BOX(loBox),
                    CHF_CONST_INT(hasLo),
                    CHF_BOX(hiBox),
                    CHF_CONST_INT(hasHi));
      /**/
    }
  for(SideIterator sit; sit.ok(); ++sit)
    {
      bool doThisSide;
      Box thisBox;
      if(sit() == Side::Lo)
        {
          doThisSide = (hasLo != 0);
          thisBox = loBox;
        }
      else
        {
          doThisSide = (hasHi != 0);
          thisBox = hiBox;
        }
      if(doThisSide)
        {

          // the cells for which the regular calculation
          //are incorrect are the grown set of the multivalued
          //cells intersected with the appropriate bndry box
          //and added to the irregular cells on the boundary.
          Box boxGrown = thisBox;
          boxGrown.grow(a_dir, 1);
          boxGrown &= m_domain;
          IntVectSet ivs = a_ebisBox.getMultiCells(boxGrown);
          ivs &= loBox;
          IntVectSet ivsIrreg = a_ebisBox.getIrregIVS(thisBox);
          ivs |= ivsIrreg;
          for(VoFIterator vofit(ivs, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit)
            {
              const VolIndex& vof = vofit();
              //all slopes at boundary get set to zero
              //except normal velocity.  just following the
              //fortran here
              int inormVelVar = a_dir + QVELX;
              for(int ivar = 0; ivar < numSlop; ivar++)
                {
                  if(ivar != inormVelVar)
                    {
                      a_deltaPrim(vof, ivar) = 0.0;
                    }
                }

              //for normal velocity
              //do strangely limited slope
              //just lifted from the fortran.
              Side::LoHiSide otherSide = flip(sit());
              Vector<FaceIndex> faces =
                a_ebisBox.getFaces(vof, a_dir, otherSide);

              Real thisVel = a_primState(vof, inormVelVar);
              Real otherVel = 0.;
              for(int iface = 0; iface < faces.size(); iface++)
                {
                  VolIndex otherVoF = faces[iface].getVoF(otherSide);
                  otherVel += a_primState(otherVoF,inormVelVar);
                }
              if(faces.size() > 0)
                {
                  otherVel /= Real(faces.size());
                  Real slope;
                  if(sit() == Side::Lo)
                    {
                      slope = otherVel - thisVel;
                    }
                  else
                    {
                      slope = thisVel  - otherVel;
                    }
                  //trick to make sure state will not change sign
                  if(slope*thisVel < 0)
                    {
                      a_deltaPrim(vof, inormVelVar) = 0.0;
                    }
                  else
                    { //slope and vel same sign
                      Real rsign = 1.0;
                      if(thisVel < 0.0)
                        rsign = -1.0;
                      //told you this was odd.
                      Real dvmin = Min(Abs(slope), Abs((Real)2.*thisVel));
                      a_deltaPrim(vof, inormVelVar) = rsign*dvmin;
                    }
                }
              else //no faces on high side of low boundary vof
                {
                  a_deltaPrim(vof, inormVelVar) = 0.0;
                }
            } //end loop over irregular vofs at boundary
        }
    } //end loop over boundary sides
}
Пример #11
0
void
EBPlanarShockIBC::
fluxBC(EBFluxFAB&            a_flux,
       const EBCellFAB&      a_primCenter,
       const EBCellFAB&      a_primExtrap,
       const Side::LoHiSide& a_side,
       const Real&           a_time,
       const EBISBox&        a_ebisBox,
       const DataIndex&      a_dit,
       const Box&            a_box,
       const Box&            a_faceBox,
       const int&            a_dir)
{
 CH_assert(m_isDefined);
 CH_assert(m_isFortranCommonSet);
 CH_assert(!m_domain.isPeriodic(a_dir));

  Box FBox = a_flux[a_dir].getSingleValuedFAB().box();
  Box cellBox = FBox;
  int numFlux = a_flux[a_dir].nComp();

  // Determine which side and thus shifting directions
  int isign = sign(a_side);
  cellBox.shiftHalf(a_dir,isign);

  // Is there a domain boundary next to this grid
  if (!m_domain.contains(cellBox))
    {
      cellBox &= m_domain;
      // Find the strip of cells next to the domain boundary
      Box boundaryBox = bdryBox(cellBox, a_dir, a_side, 1);

      // Shift things to all line up correctly
      boundaryBox.shiftHalf(a_dir,-isign);
      BaseFab<Real>& regFlux = a_flux[a_dir].getSingleValuedFAB();
      const BaseFab<Real>& regPrimExtrap = a_primExtrap.getSingleValuedFAB();

      // Set the boundary fluxes
      bool inbackofshock =
        (!m_shockbackward && a_side == Side::Lo) ||
        ( m_shockbackward && a_side == Side::Hi);
      if(a_dir == m_shocknorm && inbackofshock)
        {
          regFlux.shiftHalf(a_dir,-isign);

          // Set the boundary fluxes
          /**/
          FORT_EXTRAPBC(CHF_FRA(regFlux),
                        CHF_CONST_FRA(regPrimExtrap),
                        CHF_CONST_REAL(m_dx),
                        CHF_CONST_INT(a_dir),
                        CHF_BOX(boundaryBox));
          /**/

          // Shift returned fluxes to be face centered
          regFlux.shiftHalf(a_dir,isign);
          //now for the multivalued cells.  Since it is pointwise,
          //the regular calc is correct for all single-valued cells.
          IntVectSet ivs = a_ebisBox.getMultiCells(boundaryBox);
          for(VoFIterator vofit(ivs, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit)
            {
              const VolIndex& vof = vofit();
              Vector<Real> qgdnv(QNUM);
              Vector<Real> fluxv(FNUM);
              for(int ivar = 0; ivar < QNUM; ivar++)
                {
                  qgdnv[ivar] = a_primExtrap(vof, ivar);
                }
              Vector<FaceIndex> bndryFaces =
                a_ebisBox.getFaces(vof, a_dir, a_side);
              for(int iface= 0; iface < bndryFaces.size(); iface++)
                {
                  /**/
                  FORT_POINTGETFLUX(CHF_VR(fluxv),
                                    CHF_VR(qgdnv),
                                    CHF_CONST_INT(a_dir));
                  /**/
                  const FaceIndex& face = bndryFaces[iface];
                  for(int ivar = 0; ivar < FNUM; ivar++)
                    {
                      a_flux[a_dir](face, ivar) = fluxv[ivar];
                    }
                }
            }
        } //end if on the back side of the shock
      else
        {
          regFlux.shiftHalf(a_dir,-isign);
          //solid wall bcs
          FORT_SLIPWALLSOLIDBC(CHF_FRA(regFlux),
                               CHF_CONST_FRA(regPrimExtrap),
                               CHF_CONST_INT(isign),
                               CHF_CONST_REAL(m_dx),
                               CHF_CONST_INT(a_dir),
                               CHF_BOX(boundaryBox));

          // Shift returned fluxes to be face centered
          regFlux.shiftHalf(a_dir,isign);
          int inormMomVar = CMOMX + a_dir;
          int inormVelVar = QVELX + a_dir;
          //now for the multivalued cells.  Since it is pointwise,
          //the regular calc is correct for all single-valued cells.
          IntVectSet ivs = a_ebisBox.getMultiCells(boundaryBox);
          for(VoFIterator vofit(ivs, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit)
            {
              const VolIndex& vof = vofit();
              //set all fluxes except normal momentum  to zero.
              //set normal momemtum flux to sign(normal)*pressure
              Vector<FaceIndex> bndryFaces = a_ebisBox.getFaces(vof, a_dir, a_side);
              for(int iface= 0; iface < bndryFaces.size(); iface++)
                {
                  const FaceIndex& face = bndryFaces[iface];
                  //set all fluxes to zero then fix normal momentum
                  for(int ivar = 0; ivar < numFlux; ivar++)
                    {
                      a_flux[a_dir](face, ivar) = 0;
                    }
                  Real press = a_primExtrap(vof, QPRES);
                  Real dense = a_primExtrap(vof, QRHO);
                  Real unorm = a_primExtrap(vof, inormVelVar);
                  Real speed = sqrt(m_gamma*press/dense);

                  
                  a_flux[a_dir](face, inormMomVar) =
                    press + isign*dense*unorm*speed;

                }
            }
        }
    }
}
Пример #12
0
void
EBCoarsen::coarsenFAB(EBCellFAB&       a_coar,
                      const EBCellFAB& a_fine,
                      const DataIndex& a_datInd,
                      const Interval&  a_variables)
{
  CH_assert(isDefined());
  //do all cells as if they were regular
  BaseFab<Real>& coarRegFAB =  a_coar.getSingleValuedFAB();
  const BaseFab<Real>& fineRegFAB = a_fine.getSingleValuedFAB();

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

  Box coarBox = m_coarsenedFineGrids.get(a_datInd);

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

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

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

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

  //overwrite irregular vofs and coarse vofs next to the cfivs if refRat<4,
  //  for these vofs we coarsen based on
  //  taylor expansions from fine vofs to the coarse cell center
  coarsenIrreg(a_coar,a_fine,a_datInd,a_variables);
}
Пример #13
0
void
kappaDivergence(EBCellFAB&             a_divF,
                const EBFluxFAB&       a_flux,
                const EBISBox&         a_ebisBox,
                const Box&             a_box,
                const Real&            a_dx)
{
    //set the divergence initially to zero
    //then loop through directions and increment the divergence
    //with each directions flux difference.
    a_divF.setVal(0.0);
    BaseFab<Real>&       regDivF = a_divF.getSingleValuedFAB();
    regDivF.setVal(0.);
    for (int idir = 0; idir < SpaceDim; idir++)
    {
        //update for the regular vofs in the nonconservative
        //case  works for all single valued vofs.
        /* do the regular vofs */
        /**/
        const EBFaceFAB& fluxDir = a_flux[idir];
        const BaseFab<Real>& regFluxDir = fluxDir.getSingleValuedFAB();
        int ncons = 1;
        FORT_DIVERGEF( CHF_BOX(a_box),
                       CHF_FRA(regDivF),
                       CHF_CONST_FRA(regFluxDir),
                       CHF_CONST_INT(idir),
                       CHF_CONST_INT(ncons),
                       CHF_CONST_REAL(a_dx));
        /**/
    }
    //update the irregular vofs using conservative diff
    IntVectSet ivsIrreg = a_ebisBox.getIrregIVS(a_box);
    for (VoFIterator vofit(ivsIrreg, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit)
    {
        const VolIndex& vof = vofit();
        //divergence was set in regular update.  we reset it
        // to zero and recalc.
        Real update = 0.;
        for ( int idir = 0; idir < SpaceDim; idir++)
        {
            const EBFaceFAB& fluxDir = a_flux[idir];
            for (SideIterator sit; sit.ok(); ++sit)
            {
                int isign = sign(sit());
                Vector<FaceIndex> faces =
                    a_ebisBox.getFaces(vof, idir, sit());
                for (int iface = 0; iface < faces.size(); iface++)
                {
                    const FaceIndex& face = faces[iface];
                    Real areaFrac = a_ebisBox.areaFrac(face);
                    Real faceFlux =fluxDir(face, 0);
                    update += isign*areaFrac*faceFlux;

                }
            }
        }
        //add EB boundary condtions in divergence
        const IntVect& iv = vof.gridIndex();
        Real bndryArea = a_ebisBox.bndryArea(vof);
        RealVect bndryCent = a_ebisBox.bndryCentroid(vof);
        RealVect normal = a_ebisBox.normal(vof);
        RealVect bndryLoc;
        RealVect exactF;
        for (int idir = 0; idir < SpaceDim; idir++)
        {
            bndryLoc[idir] = a_dx*(iv[idir] + 0.5 + bndryCent[idir]);
        }
        for (int idir = 0; idir < SpaceDim; idir++)
        {
            exactF[idir] = exactFlux(bndryLoc, idir);
        }
        Real bndryFlux = PolyGeom::dot(exactF, normal);

        update -= bndryFlux*bndryArea;
        update /= a_dx; //note NOT divided by volfrac

        a_divF(vof, 0) = update;
    }
}
Пример #14
0
void
EBMGInterp::pwlInterpFAB(EBCellFAB&       a_refCoar,
                         const Box&       a_coarBox,
                         const EBCellFAB& a_coar,
                         const DataIndex& a_datInd,
                         const Interval&  a_variables) const
{
  CH_TIMERS("EBMGInterp::pwlinterpfab");
  CH_TIMER("regular_interp", t1);
  CH_TIMER("irregular_interp", t2);
  CH_assert(isDefined());


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

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

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

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

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

      CH_START(t1);

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

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

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

      CH_START(t2);
      //do what fortran should have done at irregular cells.
      m_linearEBStencil[a_datInd]->apply(a_refCoar, a_coar, true, ivar);
      CH_STOP(t2);
    }
}
Пример #15
0
void
EBGradDivFilter::
gradVel(EBCellFAB&             a_gradVel,
        const  EBCellFAB&      a_vel,
        const Box&             a_grid,
        const EBISBox&         a_ebisBox,
        bool a_lowOrderOneSide)
{
  CH_TIME("EBGradDivFilter::gradVel");
  CH_assert(a_gradVel.nComp() == SpaceDim*SpaceDim);
  CH_assert(a_vel.nComp() == SpaceDim);

  int iLowOrderOneSide = 0;
  if (a_lowOrderOneSide)
    {
      iLowOrderOneSide = 1;
    }

  for (int derivDir = 0; derivDir < SpaceDim; derivDir++)
    {
      Box loBox, hiBox, centerBox;
      int hasLo, hasHi;
      EBArith::loHiCenter(loBox, hasLo, hiBox, hasHi, centerBox, m_domainFine, a_grid, derivDir);
      for (int velDir = 0; velDir < SpaceDim; velDir++)
        {
          BaseFab<Real>&   regGradVel  = a_gradVel.getSingleValuedFAB();
          const BaseFab<Real>& regVel  =     a_vel.getSingleValuedFAB();
          int gradcomp = getGradComp(velDir, derivDir);

          FORT_EBGDFGRADVEL(CHF_FRA1(regGradVel, gradcomp),
                            CHF_CONST_FRA1(regVel, velDir),
                            CHF_BOX(loBox),
                            CHF_INT(hasLo),
                            CHF_BOX(hiBox),
                            CHF_INT(hasHi),
                            CHF_BOX(centerBox),
                            CHF_CONST_REAL(m_dxFine[derivDir]),
                            CHF_CONST_INT(derivDir),
                            CHF_CONST_INT(iLowOrderOneSide));

          IntVectSet ivsIrreg = a_ebisBox.getIrregIVS(a_grid);
          if (!a_lowOrderOneSide)
            {
              ivsIrreg.grow(1);
              ivsIrreg &= a_grid;
            }
          for (VoFIterator vofit(ivsIrreg, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit)
            {
              const VolIndex& vof = vofit();
              bool hasHi, hasLo;
              VolIndex vofHi, vofLo;
              Vector<FaceIndex> facesHi = a_ebisBox.getFaces(vof, derivDir, Side::Hi);
              Vector<FaceIndex> facesLo = a_ebisBox.getFaces(vof, derivDir, Side::Lo);

              hasHi = (facesHi.size() == 1) && (!facesHi[0].isBoundary());
              hasLo = (facesLo.size() == 1) && (!facesLo[0].isBoundary());
              if (hasLo)
                {
                  vofLo = facesLo[0].getVoF(Side::Lo);
                }
              if (hasHi)
                {
                  vofHi = facesHi[0].getVoF(Side::Hi);
                }

              Real gradVal;
              if (hasHi && hasLo)
                {
                  gradVal = (a_vel(vofHi, velDir) - a_vel(vofLo, velDir))/(2.*m_dxFine[derivDir]);
                }
              else if (hasHi || hasLo)
                {
                  //do one-sided diff
                  CH_assert(!(hasHi && hasLo));
                  Side::LoHiSide side;
                  VolIndex vofNear;
                  if (hasLo)
                    {
                      side = Side::Lo;
                      vofNear = vofLo;
                    }
                  else
                    {
                      side = Side::Hi;
                      vofNear = vofHi;
                    }
                  int isign = sign(side);

                  Vector<FaceIndex> facesFar = a_ebisBox.getFaces(vofNear, derivDir, side);
                  bool hasVoFFar = (facesFar.size()==1) && (!facesFar[0].isBoundary());
                  Real valStart = a_vel(vof,     velDir);
                  Real valNear  = a_vel(vofNear, velDir);
                  if (hasVoFFar && !a_lowOrderOneSide)
                    {
                      VolIndex vofFar = facesFar[0].getVoF(side);
                      Real valFar = a_vel(vofFar, velDir);
                      gradVal = (4*(valNear - valStart)- (valFar-valStart))/(2.*isign*m_dxFine[derivDir]);
                    }
                  else
                    {
                      //do not have another point for stencil or specified low order one-sided.
                      //drop order of derivative
                      gradVal = (valNear - valStart)/(isign*m_dxFine[derivDir]);
                    }
                }
              else
                {
                  //only have one point, can only set gradient to zero
                  gradVal = 0.0;
                }

              a_gradVel(vof, gradcomp) = gradVal;
            }
        }
    }
}
Пример #16
0
void
EBGradDivFilter::
cellGradient(EBCellFAB&             a_gradDiv,
             const EBCellFAB&       a_gradVel,
             const  EBCellFAB&      a_vel,
             const EBFluxFAB&       a_fluxVel,
             const EBFluxFAB&       a_div,
             const Box&             a_grid,
             const EBISBox&         a_ebisBox,
             const DataIndex&       a_dataIndex,
             bool a_multiplyByLambda,
             bool a_noExtrapToCovered)
{
  CH_TIME("EBGradDivFilter::cellGradient");
  int icomp = 0;
  EBCellFAB& lambdaFAB = m_lambda[a_dataIndex];
  IntVectSet irregIVS = a_ebisBox.getIrregIVS(a_grid);

  for (int faceDir = 0; faceDir < SpaceDim; faceDir++)
    {
      const EBFaceFAB&  faceDiv       =  a_div[faceDir];
      const BaseFab<Real>& regFaceDiv =   faceDiv.getSingleValuedFAB();
      const BaseFab<Real>& regLambda =   lambdaFAB.getSingleValuedFAB();
      BaseFab<Real>& regGradDiv       = a_gradDiv.getSingleValuedFAB();

      int imultByLambda = 0;
      if (a_multiplyByLambda)
        {
          imultByLambda = 1;
        }
      FORT_EBGDFCELLGRAD(CHF_FRA1(regGradDiv, faceDir),
                         CHF_CONST_FRA1(regFaceDiv, icomp),
                         CHF_CONST_FRA1(regLambda, icomp),
                         CHF_BOX(a_grid),
                         CHF_CONST_REAL(m_dxFine[faceDir]),
                         CHF_CONST_INT(faceDir),
                         CHF_CONST_INT(imultByLambda));

      //nonconservative gradient
      for (VoFIterator vofit(irregIVS, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit)
        {
          const VolIndex& vof = vofit();
          Real gradVal = 0.0;

          Vector<FaceIndex> facesHi = a_ebisBox.getFaces(vof, faceDir, Side::Hi);
          Vector<FaceIndex> facesLo = a_ebisBox.getFaces(vof, faceDir, Side::Lo);

          bool zeroGrad = a_noExtrapToCovered && ((facesHi.size() == 0) || (facesLo.size() == 0));
          if (zeroGrad)
            {
              gradVal = 0;
            }
          else
            {
              Real valHi= 0;
              if (facesHi.size() > 0)
                {
                  for (int iface = 0; iface < facesHi.size(); iface++)
                    {
                      valHi += faceDiv(facesHi[iface], icomp);
                    }
                  valHi /= facesHi.size();
                }
              else
                {
                  valHi = ccpGetCoveredExtrapValue(vof, faceDir, Side::Hi,
                                                   faceDiv, a_ebisBox, a_grid,
                                                   m_domainFine, m_dxFine, icomp);
                }

              Real valLo= 0;
              if (facesLo.size() > 0)
                {
                  for (int iface = 0; iface < facesLo.size(); iface++)
                    {
                      valLo += faceDiv(facesLo[iface], 0);
                    }
                  valLo /= facesLo.size();
                }
              else
                {
                  valLo = ccpGetCoveredExtrapValue(vof, faceDir, Side::Lo ,
                                                   faceDiv, a_ebisBox, a_grid,
                                                   m_domainFine, m_dxFine, icomp);

                }
              gradVal = (valHi-valLo)/(m_dxFine[faceDir]);

              //multiply the lambda in since we have the area fractions lying about
              if (a_multiplyByLambda)
                {
                  Real lambda = lambdaFAB(vof, 0);
                  gradVal *= lambda;
                }
            }

          a_gradDiv(vof, faceDir) = gradVal;
        }
    }
}
Пример #17
0
void
EBCoarseAverage::averageFAB(EBCellFAB&       a_coar,
                            const EBCellFAB& a_fine,
                            const DataIndex& a_datInd,
                            const Interval&  a_variables) const
{
  CH_TIME("EBCoarseAverage::averageFAB(EBCellFAB)");
  CH_assert(isDefined());
  //do all cells as if they were regular
  BaseFab<Real>& coarRegFAB =  a_coar.getSingleValuedFAB();
  const BaseFab<Real>& fineRegFAB = a_fine.getSingleValuedFAB();
  Box refbox(IntVect::Zero, (m_refRat-1)*IntVect::Unit);

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

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

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

  //overwrite irregular cells

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

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

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

      Real volCoar = cellVolCoar*ebisBoxCoar.volFrac(coarVoF);
      for (int ivar = a_variables.begin();
          ivar <= a_variables.end(); ivar++)
        {
          Real dataVal = 0.0;
          if (volCoar > 0.)
            {
              for (int ifine = 0; ifine < fineVoFs.size(); ifine++)
                {
                  const VolIndex& fineVoF = fineVoFs[ifine];
                  //fine cell volume is normalized to one...
                  Real volFine  = ebisBoxFine.volFrac(fineVoF);
                  Real fineVal =  a_fine(fineVoF, ivar);
                  if (volFine > 0.)
                    {
                      dataVal += fineVal*volFine;
                    }
                }
              dataVal /= volCoar;
            }
          else
            {
              //if there is no real volume, just take the ave
              //of fine values
              for (int ifine = 0; ifine < fineVoFs.size(); ifine++)
                {
                  const VolIndex& fineVoF = fineVoFs[ifine];
                  Real fineVal =  a_fine(fineVoF, ivar);
                  dataVal += fineVal;
                }
              if (fineVoFs.size() > 0)
                {
                  dataVal /= Real(fineVoFs.size());
                }
            }
          a_coar(coarVoF, ivar) = dataVal;
        }
    }
}
Пример #18
0
void
EBStenVarCoef::
apply(EBCellFAB&             a_lofphi,
      const EBCellFAB&       a_phi,
      const EBCellFAB&       a_alphaWeight,
      const Real&            a_alpha,
      const EBCellFAB&       a_betaWeight,
      const Real&            a_beta)
{
  CH_TIME("EBStenVarCoef::apply");

  CH_assert(a_lofphi.getSingleValuedFAB().box()      == m_grownBox);
  CH_assert(a_phi.getSingleValuedFAB().box()         == m_grownBox);
  CH_assert(a_alphaWeight.getSingleValuedFAB().box() == m_grownBox);
  CH_assert(a_betaWeight.getSingleValuedFAB().box()  == m_grownBox);

  const Real* singleValuedPtrPhi =    a_phi.getSingleValuedFAB().dataPtr(0);
  const Real*  multiValuedPtrPhi =    a_phi. getMultiValuedFAB().dataPtr(0);

  const Real* singleValuedPtrAlp =    a_alphaWeight.getSingleValuedFAB().dataPtr(0);
  const Real*  multiValuedPtrAlp =    a_alphaWeight. getMultiValuedFAB().dataPtr(0);

  const Real* singleValuedPtrBet =     a_betaWeight.getSingleValuedFAB().dataPtr(0);
  const Real*  multiValuedPtrBet =     a_betaWeight. getMultiValuedFAB().dataPtr(0);

  Real*        multiValuedPtrLph = a_lofphi. getMultiValuedFAB().dataPtr(m_destVar);
  Real*       singleValuedPtrLph = a_lofphi.getSingleValuedFAB().dataPtr(m_destVar);

  //plo is different from phi because of destvar
  //phi is for stencil evaluation.  plo is for the local value at this variable
  const Real*   multiValuedPtrPlo =    a_phi. getMultiValuedFAB().dataPtr(m_destVar);
  const Real*  singleValuedPtrPlo =    a_phi.getSingleValuedFAB().dataPtr(m_destVar);

  for (int isrc = 0; isrc < m_stencil.size(); isrc++)
    {
      //debugging hook
      //const VolIndex& srcVoF = m_srcVoFs[isrc];
      Real*       lphPtr  = NULL;
      const Real* phiPtr  = NULL;
      const Real* alpPtr  = NULL;
      const Real* betPtr  = NULL;
      if (m_sourTerms[isrc].multiValued)
        {
          lphPtr  = multiValuedPtrLph + m_sourTerms[isrc].offset;
          phiPtr  = multiValuedPtrPlo + m_sourTerms[isrc].offset;
          alpPtr  = multiValuedPtrAlp + m_sourTerms[isrc].offset;
          betPtr  = multiValuedPtrBet + m_sourTerms[isrc].offset;
        }
      else
        {
          lphPtr  = singleValuedPtrLph + m_sourTerms[isrc].offset;
          phiPtr  = singleValuedPtrPlo + m_sourTerms[isrc].offset;
          alpPtr  = singleValuedPtrAlp + m_sourTerms[isrc].offset;
          betPtr  = singleValuedPtrBet + m_sourTerms[isrc].offset;
        }

      Real& lph = *lphPtr;
      const Real&         phi = *phiPtr;
      const Real& alphaWeight = *alpPtr;
      const Real&  betaWeight = *betPtr;

      lph =  0.;
      const varcsten_t& stenpt = m_stencil[isrc];
      //single-valued
      for (int isingle = 0; isingle < stenpt.single.size(); isingle++)
        {
          const int & offset = stenpt.single[isingle].offset;
          const Real& phiVal = *(singleValuedPtrPhi + offset);
          const Real& weight = stenpt.single[isingle].weight;
          lph += phiVal*weight;
        }
      //multi-valued
      for (int imulti = 0; imulti < stenpt.multi.size(); imulti++)
        {
          const int & offset = stenpt.multi[imulti].offset;
          const Real& phiVal = *(multiValuedPtrPhi + offset);
          const Real& weight = stenpt.multi[imulti].weight;
          lph += phiVal*weight;
        }
      //at this point lph holds divF.  add in identity terms
      //and multiply by factors
      lph = a_alpha*alphaWeight*phi + a_beta*betaWeight*lph;
    }
}
Пример #19
0
void
EBGradDivFilter::
faceDivergence(EBFaceFAB&             a_divVel,
               const EBCellFAB&       a_gradVel,
               const EBCellFAB&       a_vel,
               const EBFluxFAB&       a_fluxVel,
               const Box&             a_grid,
               const EBISBox&         a_ebisBox,
               const int&             a_faceDir)
{
  CH_TIME("EBGradDivFilter::faceDivergence");
  CH_assert(a_divVel.nComp() == 1);
  CH_assert(a_vel.nComp() == SpaceDim);

  a_divVel.setVal(0.0);
  BaseFab<Real>& regDivVel       =  a_divVel.getSingleValuedFAB();
  const BaseFab<Real>& regVel    =     a_vel.getSingleValuedFAB();
  const BaseFab<Real>& regGradVel= a_gradVel.getSingleValuedFAB();

  Box interiorFaceBox = a_grid;
  interiorFaceBox.grow(a_faceDir, 1);
  interiorFaceBox &= m_domainFine;
  interiorFaceBox.grow(a_faceDir, -1);
  interiorFaceBox.surroundingNodes(a_faceDir);

  for (int divDir = 0; divDir < SpaceDim; divDir++)
    {
      FORT_EBGDFFACEDIVINCR(CHF_FRA1(regDivVel, 0),
                            CHF_FRA(regVel),
                            CHF_FRA(regGradVel),
                            CHF_BOX(interiorFaceBox),
                            CHF_REAL(m_dxFine[divDir]),
                            CHF_INT(a_faceDir),
                            CHF_INT(divDir));
    }

  IntVectSet irregIVS = a_ebisBox.getIrregIVS(a_grid);
  FaceStop::WhichFaces stopCrit;
  if (m_domainFine.isPeriodic(a_faceDir))
    {
      stopCrit = FaceStop::SurroundingWithBoundary;
    }
  else
    {
      stopCrit = FaceStop::SurroundingNoBoundary;
    }
  for (FaceIterator faceit(irregIVS, a_ebisBox.getEBGraph(), a_faceDir,
                          stopCrit);
      faceit.ok(); ++faceit)
    {
      Real divVal = 0.0;
      for (int divDir=0; divDir<SpaceDim; divDir++)
        {
          if (divDir == a_faceDir)
            {
              divVal += (a_vel(faceit().getVoF(Side::Hi), a_faceDir) -
                         a_vel(faceit().getVoF(Side::Lo), a_faceDir))/m_dxFine[divDir];
            }
          else
            {
              // take average of cell-centered tangential derivatives
              // and increment div
              //so this is partial (vel_divdir)/partial (x_divdir)
              int velcomp = divDir;
              int gradcomp = getGradComp(velcomp, divDir);

              divVal += 0.5*(a_gradVel(faceit().getVoF(Side::Hi), gradcomp) +
                             a_gradVel(faceit().getVoF(Side::Lo), gradcomp));
            }
        }

      a_divVel(faceit(), 0) = divVal;
    } // end loop over interior irregular faces

  if (!m_domainFine.isPeriodic(a_faceDir))
    {
      //set the boundary face divergence to an extrapolation of the neighboring face divergences
      for (SideIterator sit; sit.ok(); ++sit)
        {
          Box bndryBox = adjCellBox(a_grid, a_faceDir, sit(), 1);
          int ishift = -sign(sit());
          bndryBox.shift(a_faceDir, ishift);
          IntVectSet bndryIVS(bndryBox);
          for (FaceIterator faceit(bndryIVS, a_ebisBox.getEBGraph(), a_faceDir,
                                  FaceStop::AllBoundaryOnly);
              faceit.ok(); ++faceit)
            {
              Real faceDiv = getDomainDivergence(a_gradVel,
                                                 a_vel,
                                                 a_fluxVel,
                                                 a_grid,
                                                 a_ebisBox,
                                                 a_faceDir,
                                                 faceit(),
                                                 sit());
              a_divVel(faceit(), 0) = faceDiv;
            }
        }
    }
}