Пример #1
0
void
BaseFab<Real>::performCopy (const BaseFab<Real>& src,
                            const Box&           srcbox,
                            int                  srccomp,
                            const Box&           destbox,
                            int                  destcomp,
                            int                  numcomp)
{
    BL_ASSERT(destbox.ok());
    BL_ASSERT(src.box().contains(srcbox));
    BL_ASSERT(box().contains(destbox));
    BL_ASSERT(destbox.sameSize(srcbox));
    BL_ASSERT(srccomp >= 0 && srccomp+numcomp <= src.nComp());
    BL_ASSERT(destcomp >= 0 && destcomp+numcomp <= nComp());

    if (destbox == domain && srcbox == src.box())
    {
        Real*       data_dst = dataPtr(destcomp);
        const Real* data_src = src.dataPtr(srccomp);

        for (long i = 0, N = numcomp*numpts; i < N; i++)
        {
            *data_dst++ = *data_src++;
        }
    }
    else
    {
        const int* destboxlo  = destbox.loVect();
        const int* destboxhi  = destbox.hiVect();
        const int* _th_plo    = loVect();
        const int* _th_phi    = hiVect();
        const int* _x_lo      = srcbox.loVect();
        const int* _x_plo     = src.loVect();
        const int* _x_phi     = src.hiVect();
        Real*       _th_p     = dataPtr(destcomp);
        const Real* _x_p      = src.dataPtr(srccomp);

        FORT_FASTCOPY(_th_p,
                      ARLIM(_th_plo),
                      ARLIM(_th_phi),
                      D_DECL(destboxlo[0],destboxlo[1],destboxlo[2]),
                      D_DECL(destboxhi[0],destboxhi[1],destboxhi[2]),
                      _x_p,
                      ARLIM(_x_plo),
                      ARLIM(_x_phi),
                      D_DECL(_x_lo[0],_x_lo[1],_x_lo[2]),
                      &numcomp);
    }
}
/**
   This is called by EBAMRPoissonOp::applyDomainFlux in EBAMRPoissonOp::applyOp
   for reg cells.
   For boundary conditions on velocity in viscous operator.
*/
void InflowOutflowHelmholtzDomainBC::getFaceFlux(BaseFab<Real>&        a_faceFlux,
                                                 const BaseFab<Real>&  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)
{
  //vel: outflow is neumann. all others dirichlet.  inflow uses inflow vel as the value
  int velcomp =  DirichletPoissonEBBC::s_velComp;
  bool isOutflow =  ((a_side==Side::Hi) && (a_idir==m_flowDir));
  bool isInflow =  ((a_side==Side::Lo) && (a_idir==m_flowDir));
  bool isSlipWall = ((a_idir!=m_flowDir) && (a_idir != velcomp) && ((m_doSlipWallsHi[a_idir]==1 && a_side == Side::Hi)||(m_doSlipWallsLo[a_idir]==1 && a_side == Side::Lo)));
//  bool isVelNeum =  (isOutflow || isSlipWall);

  if (isSlipWall)
    {
      NeumannPoissonDomainBC neumannBC;
      neumannBC.setValue(0.);
      neumannBC.getFaceFlux(a_faceFlux, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit, a_time, a_useHomogeneous);
    }
  else if (isInflow)
    {
      DirichletPoissonDomainBC diriBC;
      if (velcomp==m_flowDir)
        {
          if (!m_doJet1PoiseInflow)
            {
              diriBC.setValue(m_jet1inflowVel);
            }
          else if (m_doJet1PoiseInflow)
            {
              diriBC.setFunction(m_jet1PoiseInflowFunc);
            }
        }
      else
        {
          diriBC.setValue(0.0);
        }

      //basefab flux--EBAMRPoissonOp::applyDomainFlux calls this directly for viscous operator
      if (s_higherOrderHelmBC)
        {
          diriBC.getHigherOrderFaceFlux(a_faceFlux, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit, a_time, a_useHomogeneous);
        }
      else
        {
          diriBC.getFaceFlux(a_faceFlux, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit, a_time, a_useHomogeneous);
        }
    }
  else if (isOutflow)
    {
      if (!m_doJet2)
        {
          NeumannPoissonDomainBC neumannBC;
          neumannBC.setValue(0.);
          neumannBC.getFaceFlux(a_faceFlux, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit, a_time, a_useHomogeneous);
        }
      else if (m_doJet2)
        {
          const RealVect tubeCenter = m_jet2PoiseInflowFunc->getTubeCenter();
          Real tubeRadius = m_jet2PoiseInflowFunc->getTubeRadius();
          CH_assert(a_phi.nComp() == 1);

// start hardwire
          Real wallThickness = 0.075;
          Real bcFactor = 0.5; // % of outflow face to be set to inflow condition
          ParmParse pp;
          pp.get("wall_thickness",wallThickness);
          tubeRadius += wallThickness * bcFactor /2.0;
// end hardwire

          for (int comp=0; comp<a_phi.nComp(); comp++)
            {
              const Box& box = a_faceFlux.box();
              int iside = -1; //a_side == Side::Hi
              BoxIterator bit(box);
              for (bit.begin(); bit.ok(); ++bit)
                {
                  const IntVect& iv = bit();
                  RealVect loc = EBArith::getIVLocation(iv,a_dx,a_probLo);
                  loc[a_idir] -= iside * 0.5 * a_dx[a_idir];//point is now at the face center     
                  CH_assert(loc[m_flowDir] == tubeCenter[m_flowDir]);
                  bool isInsideTube = false;
                  Real radius = m_jet2PoiseInflowFunc->getRadius(loc);
                  if (radius <= tubeRadius)
                    {
                      isInsideTube = true;
                    }
                  if (isInsideTube) // Dirichlet
                    {
                      Real value = 0.0; // takes care of tangential comps
                      if (velcomp == m_flowDir)
                        {
                          if (m_doJet2PoiseInflow)
                            {
                              value = m_jet2PoiseInflowFunc->getVel(radius)[m_flowDir];
                            }
                          else if (!(m_doJet2PoiseInflow))
                            {
                              value = m_jet2inflowVel;
                            }
                        }
                      if (s_higherOrderHelmBC)
                        {
                          IntVect iv1 = bit();
                          Real phi0 = a_phi(iv1,comp);
                          iv1[a_idir] += iside;
                          Real phi1 = a_phi(iv1,comp);
                          iv1[a_idir] -= iside;
                          a_faceFlux(iv,comp) = -iside*(8.0*value + phi1 - 9.0*phi0)/(3.0*a_dx[a_idir]);
                        }
                      else if (!s_higherOrderHelmBC)
                        {
                          Real ihdx = 2.0 / a_dx[a_idir];
                          Real phiVal = a_phi(iv,comp);
                          a_faceFlux(iv,comp) = iside * ihdx * (phiVal - value);
                        }
                    }
                  else if (!isInsideTube) // Neumann
                    {
                      Real value = 0.0;
                      a_faceFlux(iv,comp) = iside * value;
                    }
                }
            } 
        }
    }
  else
    {
      //wall bc no slip
      DirichletPoissonDomainBC diriBC;
      diriBC.setValue(0.0);
      if (s_higherOrderHelmBC)
        {
          diriBC.getHigherOrderFaceFlux(a_faceFlux, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit, a_time, a_useHomogeneous);
        }
      else
        {
          diriBC.getFaceFlux(a_faceFlux, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit, a_time, a_useHomogeneous);
        }
    }
}
//////called by MAC projection solver for domain bc on phi
void InflowOutflowPoissonDomainBC::getFaceFlux(BaseFab<Real>&        a_faceFlux,
                                               const BaseFab<Real>&  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)
{

  //for phi: outflow  dirichlet. inflow neumann
  bool isOutflow= (a_side==Side::Hi) && (a_idir==m_flowDir);
  if (!isOutflow)
    {
      NeumannPoissonDomainBC neumannBC;
      neumannBC.setValue(0.0);
      neumannBC.getFaceFlux(a_faceFlux, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit, a_time, a_useHomogeneous);
    }
  else
    {
      if (!(m_doJet2))
        {
          DirichletPoissonDomainBC diriBC;
          diriBC.setValue(0.0);
          diriBC.getFaceFlux(a_faceFlux, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit, a_time, a_useHomogeneous);
          // diriBC.getHigherOrderFaceFlux(a_faceFlux, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit, a_time, a_useHomogeneous);
        }
      else if (m_doJet2)
        {
          const RealVect tubeCenter = m_jet2PoiseInflowFunc->getTubeCenter();
          Real tubeRadius = m_jet2PoiseInflowFunc->getTubeRadius();

// start hardwire
          Real wallThickness = 0.075;
          Real bcFactor = 0.5; // % of outflow face to be set to inflow condition
          ParmParse pp;
          pp.get("wall_thickness",wallThickness);
          tubeRadius += wallThickness * bcFactor /2.0;
// end hardwire

          CH_assert(a_phi.nComp() == 1);
          for (int comp=0; comp<a_phi.nComp(); comp++)
            {
              const Box& box = a_faceFlux.box();

              int iside = -1; // a_side == Side::Hi in this loop
              Real value = 0.0;
              BoxIterator bit(box);
              for (bit.begin(); bit.ok(); ++bit)
                {
                  const IntVect& iv = bit();
                  RealVect loc = EBArith::getIVLocation(iv,a_dx,a_probLo);
                  loc[a_idir] -= iside * 0.5 * a_dx[a_idir]; //loc is now at the face center
                  CH_assert(loc[m_flowDir] == tubeCenter[m_flowDir]);
                  bool isInsideTube = false;
                  Real radius = m_jet2PoiseInflowFunc->getRadius(loc);
                  if (radius <= tubeRadius)
                    {
                      isInsideTube = true;
                    }
                   if (isInsideTube)
                    {
                      a_faceFlux(iv,comp) = iside * value; //Neumann
                    }
                  else if (!(isInsideTube))
                    {
                      Real ihdx = 2.0 / a_dx[a_idir];
                      Real phiVal = a_phi(iv,comp);
                      a_faceFlux(iv,comp) = iside * ihdx * (phiVal - value); //Dirichlet
                    }
                }
            }
        }
    }
}
void
NeumannConductivityDomainBC::
getFaceFlux(BaseFab<Real>&        a_faceFlux,
            const BaseFab<Real>&  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)
{
  CH_TIME("NeumannPoissonDomainBC::getFaceFlux");
  CH_assert(a_phi.nComp() == 1);
  for (int comp=0; comp<a_phi.nComp(); comp++)
    {

      const Box& box = a_faceFlux.box();

      int iside;

      if (a_side == Side::Lo)
        {
          iside = 1;
        }
      else
        {
          iside = -1;
        }

      if (a_useHomogeneous)
        {
          Real value = 0.0;

          a_faceFlux.setVal(iside * value);
        }
      else
        {
          if (m_isFunction)
            {
              BoxIterator bit(box);

              for (bit.begin(); bit.ok(); ++bit)
                {
                  const IntVect& iv = bit();

                  RealVect point = EBArith::getIVLocation(iv,a_dx,a_probLo);
                  point[a_idir] -= iside * 0.5 * a_dx[a_idir];//point is now at the face center

                  RealVect normal = RealVect::Zero;
                  normal[a_idir] = iside;

                  a_faceFlux(iv,comp) = iside * m_flux->value(iv,a_dit,point,normal,a_time,comp);
                }
            }
          else
            {
              if (m_onlyHomogeneous)
                {
                  MayDay::Error("NeumannPoissonDomainBC::getFaceFlux called with undefined inhomogeneous BC");
                }

              Real value = m_value;

              a_faceFlux.setVal(iside * value);
            }
        }
    }

  //again, following the odd convention of EBAMRPoissonOp
  //(because I am reusing its BC classes),
  //the input flux here is CELL centered and the input box
  //is the box adjacent to the domain boundary on the valid side.
  //because I am not insane (yet) I will just shift the flux's box
  //over and multiply by the appropriate coefficient
  a_faceFlux.shiftHalf(a_idir, -sign(a_side));
  const Box& faceBox = a_faceFlux.box();
  const BaseFab<Real>&   regCoef = (*m_bcoef)[a_dit][a_idir].getSingleValuedFAB();
  int  isrc = 0;
  int  idst = 0;
  int  inum = 1;
  FORT_MULTIPLYTWOFAB(CHF_FRA(a_faceFlux),
                      CHF_CONST_FRA(regCoef),
                      CHF_BOX(faceBox),
                      CHF_INT(isrc),CHF_INT(idst),CHF_INT(inum));

  //shift flux back to cell centered land
  a_faceFlux.shiftHalf(a_idir,  sign(a_side));
}