Ejemplo n.º 1
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
}
Ejemplo n.º 2
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;

                }
            }
        }
    }
}