//called by projection solve for irreg x domain
void InflowOutflowPoissonDomainBC::getInhomFaceFlux(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)
{
  bool isOutflow= (a_side==Side::Hi) && (a_idir==m_flowDir);
  if (!isOutflow)
    {
      NeumannPoissonDomainBC neumannBC;
      neumannBC.setValue(0.0);
      neumannBC.getInhomFaceFlux(a_faceFlux, a_vof, a_comp, a_phi, a_probLo,
                                 a_dx, a_idir, a_side, a_dit, a_time);
    }
  else
    {
      DirichletPoissonDomainBC diriBC;
      diriBC.setValue(0.0);
      diriBC.getInhomFaceFlux(a_faceFlux, a_vof, a_comp, a_phi, a_probLo,
                              a_dx, a_idir, a_side, a_dit, a_time);
      // diriBC.getHigherOrderFaceFlux(a_faceFlux, a_vof, a_comp, a_phi, a_probLo,
      //                               a_dx, a_idir, a_side, a_dit, a_time);
    }
}
//called by macEnforceGradientBC, useAreaFrac = false
void InflowOutflowPoissonDomainBC::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)
{
  bool isOutflow= (a_side==Side::Hi) && (a_idir==m_flowDir);

  if (!isOutflow)
    {
      NeumannPoissonDomainBC neumannBC;
      neumannBC.setValue(0.0);
      neumannBC.getFaceGradPhi(a_faceFlux, a_face, a_comp,a_phi, a_probLo,
                               a_dx, a_idir, a_side, a_dit,a_time,a_useAreaFrac,a_centroid,a_useHomogeneous);
    }
  else
    {
      DirichletPoissonDomainBC diriBC;
      diriBC.setValue(0.0);
      diriBC.getFaceGradPhi(a_faceFlux, a_face, a_comp, a_phi, a_probLo,
                            a_dx, a_idir, a_side, a_dit,a_time,a_useAreaFrac,a_centroid,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
    {
      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);
    }
}
//called by macEnforceGradientBC, useAreaFrac = false
void InflowOutflowPoissonDomainBC::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)
{
  bool isInsideTube = false;
  if ((m_doJet2) && (a_side==Side::Hi) && (a_idir == m_flowDir))
    {
      RealVect probLo = RealVect::Zero;
      RealVect loc = EBArith::getFaceLocation(a_face,a_dx,probLo);
      const RealVect tubeCenter = m_jet2PoiseInflowFunc->getTubeCenter();
      Real tubeRadius = m_jet2PoiseInflowFunc->getTubeRadius();
      Real radius = m_jet2PoiseInflowFunc->getRadius(loc);
      CH_assert(loc[m_flowDir] == tubeCenter[m_flowDir]);

// 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

      if (radius <= tubeRadius)
        {
          isInsideTube = true;
        }
    }
  bool isOutflow = (a_side==Side::Hi) && (a_idir==m_flowDir) && (!(isInsideTube));
 
//  bool isOutflow= (a_side==Side::Hi) && (a_idir==m_flowDir);

  if (!isOutflow)
    {
      NeumannPoissonDomainBC neumannBC;
      neumannBC.setValue(0.0);
      neumannBC.getFaceGradPhi(a_faceFlux, a_face, a_comp,a_phi, a_probLo,
                               a_dx, a_idir, a_side, a_dit,a_time,a_useAreaFrac,a_centroid,a_useHomogeneous);
    }
  else
    {
      DirichletPoissonDomainBC diriBC;
      diriBC.setValue(0.0);
      diriBC.getFaceGradPhi(a_faceFlux, a_face, a_comp, a_phi, a_probLo,
                            a_dx, a_idir, a_side, a_dit,a_time,a_useAreaFrac,a_centroid,a_useHomogeneous);
    }
}
//velocity stencil
void InflowOutflowHelmholtzDomainBC::getFluxStencil(      VoFStencil&      a_stencil,
                                                    const VolIndex&        a_vof,
                                                    const int&             a_comp,
                                                    const RealVect&        a_dx,
                                                    const int&             a_idir,
                                                    const Side::LoHiSide&  a_side,
                                                    const EBISBox&         a_ebisBox)
{
  bool isInsideTube = false;
  if ((m_doJet2) && (a_side==Side::Hi) && (a_idir == m_flowDir))
    {
      RealVect probLo = RealVect::Zero;
      RealVect loc = EBArith::getVofLocation(a_vof,a_dx,probLo);
      loc[a_idir] += 0.5*a_dx[a_idir]; // loc at face center
      const RealVect tubeCenter = m_jet2PoiseInflowFunc->getTubeCenter();
      Real tubeRadius = m_jet2PoiseInflowFunc->getTubeRadius();
      Real radius = m_jet2PoiseInflowFunc->getRadius(loc);
      CH_assert(loc[m_flowDir] == tubeCenter[m_flowDir]);

// 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

      if (radius <= tubeRadius)
        {
          isInsideTube = true;
        }
    }
  bool isOutflow = (a_side==Side::Hi) && (a_idir==m_flowDir) && (!(isInsideTube)); 

//  bool isOutflow = (a_side==Side::Hi) && (a_idir==m_flowDir);
  bool isSlipWall= ((a_idir!=m_flowDir) && (a_idir != a_comp) && ((m_doSlipWallsHi[a_idir]==1 && a_side == Side::Hi)||(m_doSlipWallsLo[a_idir]==1 && a_side == Side::Lo)));
  if (isOutflow || isSlipWall)
    {
      NeumannPoissonDomainBC neumannBC;
      neumannBC.getFluxStencil(a_stencil, a_vof, a_comp, a_dx, a_idir, a_side, a_ebisBox);
    }
  else
    {
      DirichletPoissonDomainBC diriBC;
      diriBC.setEBOrder(2);
      diriBC.getFluxStencil(a_stencil, a_vof, a_comp, a_dx, a_idir, a_side, a_ebisBox);
    }
}
//pressure stencil
void InflowOutflowPoissonDomainBC::getFluxStencil(      VoFStencil&      a_stencil,
                                                  const VolIndex&        a_vof,
                                                  const int&             a_comp,
                                                  const RealVect&        a_dx,
                                                  const int&             a_idir,
                                                  const Side::LoHiSide&  a_side,
                                                  const EBISBox&         a_ebisBox)
{
  bool isOutflow= (a_side==Side::Hi) && (a_idir==m_flowDir);
  if (!isOutflow)
    {
      NeumannPoissonDomainBC neumannBC;
      neumannBC.setValue(0.0);
      neumannBC.getFluxStencil(a_stencil, a_vof, a_comp, a_dx, a_idir, a_side, a_ebisBox);
    }
  else
    {
      DirichletPoissonDomainBC diriBC;
      diriBC.setValue(0.0);
      diriBC.setEBOrder(1);
      diriBC.getFluxStencil(a_stencil, a_vof, a_comp, a_dx, a_idir, a_side, a_ebisBox);
    }
}
//velocity stencil
void InflowOutflowHelmholtzDomainBC::getFluxStencil(      VoFStencil&      a_stencil,
                                                    const VolIndex&        a_vof,
                                                    const int&             a_comp,
                                                    const RealVect&        a_dx,
                                                    const int&             a_idir,
                                                    const Side::LoHiSide&  a_side,
                                                    const EBISBox&         a_ebisBox)
{
  bool isOutflow = (a_side==Side::Hi) && (a_idir==m_flowDir);
  bool isSlipWall= ((a_idir!=m_flowDir) && (a_idir != a_comp) && ((m_doSlipWallsHi[a_idir]==1 && a_side == Side::Hi)||(m_doSlipWallsLo[a_idir]==1 && a_side == Side::Lo)));
  if (isOutflow || isSlipWall)
    {
      NeumannPoissonDomainBC neumannBC;
      neumannBC.setValue(0.0);
      neumannBC.getFluxStencil(a_stencil, a_vof, a_comp, a_dx, a_idir, a_side, a_ebisBox);
    }
  else
    {
      DirichletPoissonDomainBC diriBC;
      diriBC.setValue(0.0);
      diriBC.setEBOrder(2);
      diriBC.getFluxStencil(a_stencil, a_vof, a_comp, a_dx, a_idir, a_side, a_ebisBox);
    }
}
//called by EBAMRPoissonOp::applyOp for viscous Helmholtz EB x domain
void InflowOutflowHelmholtzDomainBC::getInhomFaceFlux(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)
{
  //vel: outflow is Neumann. all others Dirichlet
  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 (isVelNeum)
    {
      NeumannPoissonDomainBC neumannBC;
      neumannBC.setValue(0.);
      neumannBC.getInhomFaceFlux(a_faceFlux, a_vof, a_comp, a_phi, a_probLo,
                                 a_dx, a_idir, a_side, a_dit,a_time);
    }
  else if (isInflow)
    {
      DirichletPoissonDomainBC diriBC;
      if (velcomp==m_flowDir)
        {
          if (!m_doPoiseInflow && !m_doWomersleyInflow)
          {
            diriBC.setValue(m_inflowVel);
          }
          else if (m_doPoiseInflow)
            {
              diriBC.setFunction(m_poiseInflowFunc);
            }
          else if (m_doWomersleyInflow)
            {
              double PI = 3.1416;
              int freq[10] =
              {
                1,2,3,4,5,6,7,8
              };
              double Vp[10] =
              {
                0.33,0.24,0.24,0.12,0.11,0.13,0.06,0.04
              };
              double Theta[10] =
              {
                74,79,121,146,147,179,233,218
              };
              double AmpXsi[10] =
              {
                1.7639,1.4363,1.2517,1.1856,1.1603,1.1484,1.1417,1.1214
              };
              double AngXsi[10] =
              {
                -0.2602,-0.3271,-0.2799,-0.2244,-0.1843,-0.1576,-0.1439,-0.1195
              };

              Real VelMult = 2;

              int Maxp = 8;

              for (int p=0;p<Maxp;p++)
                VelMult += Vp[p] * AmpXsi[p] * cos (2 * PI * freq[p] * g_simulationTime - Theta[p]*PI/180 + AngXsi[p]);

              diriBC.setValue(m_inflowVel*VelMult/2);
            }
        }
      else
        {
          diriBC.setValue(0.0);
        }
      //called by EBAMRPoissonOp::applyOp for viscous Helmholtz EB x domain
      if (s_higherOrderHelmBC)
        {
          diriBC.getHigherOrderInhomFaceFlux(a_faceFlux, a_vof, a_comp, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit, a_time);
        }
      else
        {
          diriBC.getInhomFaceFlux(a_faceFlux, a_vof, a_comp, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit,a_time);
        }
    }
  else
    {
      //wall bc no slip
      DirichletPoissonDomainBC diriBC;
      diriBC.setValue(0.0);
      if (s_higherOrderHelmBC)
        {
          diriBC.getHigherOrderInhomFaceFlux(a_faceFlux, a_vof, a_comp, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit, a_time);
        }
      else
        {
          diriBC.getInhomFaceFlux(a_faceFlux, a_vof, a_comp, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit,a_time);
        }
    }
}
//called by EBAMRPoissonOp::applyOp for viscous Helmholtz EB x domain
void InflowOutflowHelmholtzDomainBC::getInhomFaceFlux(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)
{
  //vel: outflow is Neumann. all others Dirichlet
  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.getInhomFaceFlux(a_faceFlux, a_vof, a_comp, a_phi, a_probLo,
                                 a_dx, a_idir, a_side, a_dit,a_time);
    }
  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);
        }
      //called by EBAMRPoissonOp::applyOp for viscous Helmholtz EB x domain
      if (s_higherOrderHelmBC)
        {
          diriBC.getHigherOrderInhomFaceFlux(a_faceFlux, a_vof, a_comp, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit, a_time);
        }
      else
        {
          diriBC.getInhomFaceFlux(a_faceFlux, a_vof, a_comp, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit,a_time);
        }
    }
  else if (isOutflow)
    {
      if (!m_doJet2)
        {
          NeumannPoissonDomainBC neumannBC;
          neumannBC.setValue(0.);
          neumannBC.getInhomFaceFlux(a_faceFlux, a_vof, a_comp, a_phi, a_probLo,
                                     a_dx, a_idir, a_side, a_dit,a_time);
        }
      else if (m_doJet2)
        {
          const IntVect& iv = a_vof.gridIndex();
          RealVect loc = EBArith::getIVLocation(iv,a_dx,a_probLo);
          loc[a_idir] += 0.5*a_dx[a_idir]; // loc is face centered
          const RealVect tubeCenter = m_jet2PoiseInflowFunc->getTubeCenter();
          Real tubeRadius = m_jet2PoiseInflowFunc->getTubeRadius();
          CH_assert(loc[m_flowDir] == tubeCenter[m_flowDir]);
          bool isInsideTube = false;
          Real radius = m_jet2PoiseInflowFunc->getRadius(loc);

// 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

          if (radius <= tubeRadius)
            {
              isInsideTube = true;
            }

          if (!(isInsideTube))
            {
              NeumannPoissonDomainBC neumannBC;
              neumannBC.setValue(0.);
              neumannBC.getInhomFaceFlux(a_faceFlux, a_vof, a_comp, a_phi, a_probLo,
                                         a_dx, a_idir, a_side, a_dit,a_time);
            }
          else if (isInsideTube)
            {
              DirichletPoissonDomainBC diriBC;
              if (velcomp==m_flowDir)
                {
                  if (!m_doJet2PoiseInflow)
                    {
                      diriBC.setValue(m_jet2inflowVel);
                    }
                  else if (m_doJet2PoiseInflow)
                    {
                      diriBC.setFunction(m_jet2PoiseInflowFunc);
                    }
                }
              else
                {
                  diriBC.setValue(0.0);
                }
              //called by EBAMRPoissonOp::applyOp for viscous Helmholtz EB x domain
              if (s_higherOrderHelmBC)
                {
                  diriBC.getHigherOrderInhomFaceFlux(a_faceFlux, a_vof, a_comp, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit, a_time);
                }
              else
                {
                  diriBC.getInhomFaceFlux(a_faceFlux, a_vof, a_comp, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit,a_time);
                }
            } 
        }
    }
  else
    {
      //wall bc no slip
      DirichletPoissonDomainBC diriBC;
      diriBC.setValue(0.0);
      if (s_higherOrderHelmBC)
        {
          diriBC.getHigherOrderInhomFaceFlux(a_faceFlux, a_vof, a_comp, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit, a_time);
        }
      else
        {
          diriBC.getInhomFaceFlux(a_faceFlux, a_vof, a_comp, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit,a_time);
        }
    }
}
/**
   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
                    }
                }
            }
        }
    }
}
示例#12
0
int
main(int argc,char **argv)
{
#ifdef CH_MPI
    MPI_Init(&argc, &argv);
#endif

    // registerDebugger();

    // begin forever present scoping trick
    {
        pout()<<std::endl;

        Vector<std::string> names0(1, "phi");
        Vector<int> refRatio(3,2);
        Vector<Real> coveredVal(1,3.0);

        const char* in_file = "sphere.inputs";
        // read in an input file or use default file
        // if (argc > 1)
        // {
        //   in_file = argv[1];
        // }

        //parse input file
        ParmParse pp(0,NULL,NULL,in_file);
        RealVect center;
        Real radius;
        RealVect origin;
        RealVect dx;
        Box domain;
        ProblemDomain pDomain(domain);

        int eekflag = 0;



        LevelData<EBCellFAB> fine, med, coarse;

        LevelData<EBCellFAB> fineRHS, medRHS, coarseRHS;
        LevelData<EBCellFAB> fineResidual, mediumResidual, coarseResidual;


        Vector<LevelData<EBCellFAB>* > ebvector(3,NULL);
        Vector<LevelData<EBCellFAB>* > vresidual(3,NULL);
        Vector<LevelData<EBCellFAB>* > rhsvector(3,NULL);
        ebvector[0]=&coarse;
        ebvector[1]=&med;
        ebvector[2]=&fine;
        vresidual[0]=&coarseResidual;
        vresidual[1]=&mediumResidual;
        vresidual[2]=&fineResidual;
        rhsvector[0] = &coarseRHS;
        rhsvector[1] = &medRHS;
        rhsvector[2] = &fineRHS;




        readGeometryInfo(domain,
                         dx,
                         origin,
                         center,
                         radius);

        Box domainFine(domain), domainMedi, domainCoar;
        ProblemDomain pFine(domain);
        RealVect dxFine(dx), dxMedi, dxCoar;

        CH_assert(eekflag == 0);

        domainMedi = coarsen(domainFine, 2);
        domainCoar = coarsen(domainMedi, 2);
        dxMedi = 2.0*dxFine;
        dxCoar = 2.0*dxMedi;
        Vector<RealVect> xVec(3, IntVect::Unit);
        xVec[0]*= dxCoar;
        xVec[1]*= dxMedi;
        xVec[2]*= dxFine;

        Vector<DisjointBoxLayout> grids(3);
        ProblemDomain baseDomain(domainCoar);
        ProblemDomain pMed(domainMedi);
        Vector<ProblemDomain> pd(3);
        pd[0] = baseDomain;
        pd[1] = pMed;
        pd[2] = ProblemDomain(domainFine);


        RefCountedPtr<BaseBCValue>value(new DirichletBC());
        DirichletPoissonDomainBC*  domainBC = new DirichletPoissonDomainBC();
        domainBC->setFunction(value);
        RefCountedPtr<BaseDomainBC> bc(domainBC);



        //make data holders
        Vector<int> comps(2,1);

        int steps= 5;
        int step = 0;


        while (step < steps)
        {


            eekflag = makeGeometry(
                          domain,
                          dx,
                          origin,
                          center,
                          radius);


            //make grids
            //IntVectSet tags = mfIndexSpace->interfaceRegion(2);
            IntVectSet   tags(domainCoar);
            tags.grow(1);
            makeHierarchy(grids, baseDomain, tags);


            const CH_XD::EBIndexSpace* ebisPtr = Chombo_EBIS::instance();

            Vector<EBISLayout> layouts(3);
            EBISLayout& fineLayout = layouts[2];
            ebisPtr->fillEBISLayout(fineLayout, grids[2], domainFine, 2);
            EBCellFactory fineFactory(fineLayout);
            ebvector[2]->define(grids[2], 1, IntVect::Unit, fineFactory);
            rhsvector[2]->define(grids[2], 1, IntVect::Zero, fineFactory);

            EBISLayout& medLayout = layouts[1];
            ebisPtr->fillEBISLayout(medLayout, grids[1], domainMedi, 2);
            EBCellFactory medFactory(medLayout);
            ebvector[1]->define(grids[1], 1, IntVect::Unit, medFactory);
            rhsvector[1]->define(grids[1], 1, IntVect::Zero, medFactory);

            EBISLayout& coarseLayout = layouts[0];
            ebisPtr->fillEBISLayout(coarseLayout, grids[0], domainCoar, 2);
            EBCellFactory coarseFactory(coarseLayout);
            ebvector[0]->define(grids[0], 1, IntVect::Unit, coarseFactory);
            rhsvector[0]->define(grids[0], 1, IntVect::Zero, coarseFactory);



            for (int lev=0; lev<3; lev++)
            {
                setValue(*rhsvector[lev], RHS(), pd[lev].domainBox(), xVec[lev], origin, true);
            }



            Vector<int> refRatio(3,2);

            int max_iter = 40;
            pp.get("max_iter", max_iter);
            Real eps = 1.e-6;
            pp.get("eps", eps);
            int relaxType;
            pp.get("relaxType",relaxType);

            DirichletPoissonDomainBCFactory* domDirBC = new DirichletPoissonDomainBCFactory();
            domDirBC->setFunction(value);
            RefCountedPtr<BaseDomainBCFactory> domBC( domDirBC );
            DirichletPoissonEBBCFactory* ebDirBC = new DirichletPoissonEBBCFactory();
            ebDirBC->setFunction(value);
            RefCountedPtr<BaseEBBCFactory> ebBC( ebDirBC );

            Vector<EBLevelGrid> eblgs(3);
            Vector<RefCountedPtr<EBQuadCFInterp> > quadCFI(3, RefCountedPtr<EBQuadCFInterp>());
            for (int i=0; i<3; i++)
            {
                eblgs[i] = EBLevelGrid(grids[i], layouts[i], pd[i]);
                if (i > 0)
                {
                    quadCFI[i] = RefCountedPtr<EBQuadCFInterp>(
                                     new EBQuadCFInterp(grids[i],
                                                        grids[i-1],
                                                        layouts[i],
                                                        layouts[i-1],
                                                        pd[i-1],
                                                        refRatio[i-1],
                                                        1, *eblgs[i].getCFIVS()));
                }
            }

            EBAMRPoissonOpFactory opFact(eblgs, refRatio, quadCFI, xVec[0], RealVect::Zero,
                                         4, relaxType, domBC, ebBC, 0.0, 1.0, 0.0,
                                         IntVect::Unit, IntVect::Zero);
            for (int i=0; i<3; i++)
            {

                LevelData<EBCellFAB> &phi=*ebvector[i], &rhs=*rhsvector[i], &residual=*vresidual[i];
                LevelData<EBCellFAB> correction;

                DisjointBoxLayout dblMGCoar;
                EBISLayout ebislMGCoar;

                EBAMRPoissonOp* opPtr = opFact.AMRnewOp(pd[i]);
                EBAMRPoissonOp& op = *opPtr;


                RelaxSolver<LevelData<EBCellFAB> > solver;
                solver.define(&op, false);
                solver.m_imax = max_iter;
                solver.m_eps  = eps;

                op.create(residual, rhs);
                op.create(correction, phi);
                op.setToZero(residual);
                op.setToZero(phi);

                op.residual(residual, phi, rhs);
                Real r2norm = op.norm(residual, 2);
                Real r0norm = op.norm(residual, 0);


                pout()<<indent<<"Residual L2 norm "<<r2norm<<"Residual max norm = "
                      <<r0norm<<std::endl;

                solver.solve(phi, rhs);

                op.residual(residual, phi, rhs);
                r2norm = op.norm(residual, 2);
                r0norm = op.norm(residual, 0);


                pout()<<indent2<<"Residual L2 norm "<<r2norm<<" Residual max norm = "
                      <<r0norm<<std::endl;

                delete opPtr;
            }


#ifdef CH_USE_HDF5
            sprintf(iter_str, "residual.%03d.%dd.hdf5",step, SpaceDim);
            Vector<std::string> names(1);
            names[0]="residual";

            writeEBHDF5(iter_str, grids, vresidual, names, domainCoar,
                        dxCoar[0], 1, step, refRatio, 3, true, coveredVal);

            sprintf(iter_str, "phi.%03d.%dd.hdf5",step, SpaceDim);
            names[0]="phi";
            writeEBHDF5(iter_str, grids, ebvector ,names, domainCoar,
                        dxCoar[0], 1, step, refRatio, 3, true, coveredVal);
#endif
            step++;

            center[0]-= dx[0]/3.0;
            center[1]-= dx[1]/2.0;
            radius += dx[0]/6.0;

            Chombo_EBIS::instance()->clear();
            pout()<<step<<std::endl;
        }

        pout() <<"\n "<<indent2<<pgmname<<" test passed " << endl;



    } // end scoping trick





#ifdef CH_MPI
    MPI_Finalize();
#endif

    return 0;
}