InflowBC.f90 Source File


Source Code

#include "Includes.h"
module InflowBCClass
   use SMConstants
   use PhysicsStorage
   use VariableConversion, only: GetGradientValues_f
   use FileReaders,            only: controlFileName
   use FileReadingUtilities,   only: GetKeyword, GetValueAsString, PreprocessInputLine
   use FTValueDictionaryClass, only: FTValueDictionary
   use Utilities, only: toLower, almostEqual
   use GenericBoundaryConditionClass
   use FluidData
   implicit none
!
!  *****************************
!  Default everything to private
!  *****************************
!
   private
!
!  ****************
!  Public variables
!  ****************
!
!
!  ******************
!  Public definitions
!  ******************
!
   public InflowBC_t
!
!  ****************************
!  Static variables definitions
!  ****************************
!
!
!  ****************
!  Class definition
!  ****************
!
   type, extends(GenericBC_t) ::  InflowBC_t
#if defined(NAVIERSTOKES)
      real(kind=RP)              :: AoAPhi
      real(kind=RP)              :: AoATheta
      real(kind=RP)              :: v
      real(kind=RP)              :: rho
      real(kind=RP)              :: p
      real(kind=RP)              :: TurbIntensity
      real(kind=RP)              :: eddy_theta
#endif
#if defined(INCNS)
      real(kind=RP)              :: AoAPhi
      real(kind=RP)              :: AoATheta
      real(kind=RP)              :: v
#if defined(CAHNHILLIARD)
      logical                    :: isLayered  = .false.
      logical                    :: isXLimited = .false.
      logical                    :: isYLimited = .false.
      logical                    :: isZLimited = .false.
      real(kind=RP)              :: xLim, yLim, zLim
      real(kind=RP)              :: phase1Vel
      real(kind=RP)              :: phase2Vel
#else
      real(kind=RP)              :: rho
#endif
#endif
      contains
         procedure         :: Destruct          => InflowBC_Destruct
         procedure         :: Describe          => InflowBC_Describe
#if defined(NAVIERSTOKES) || defined(INCNS)
         procedure         :: FlowState         => InflowBC_FlowState
         procedure         :: FlowNeumann       => InflowBC_FlowNeumann
#endif
#if defined(CAHNHILLIARD)
         procedure         :: PhaseFieldState   => InflowBC_PhaseFieldState
         procedure         :: PhaseFieldNeumann => InflowBC_PhaseFieldNeumann
         procedure         :: ChemPotState      => InflowBC_ChemPotState
         procedure         :: ChemPotNeumann    => InflowBC_ChemPotNeumann
#endif
   end type InflowBC_t
!
!  *******************************************************************
!  Traditionally, constructors are exported with the name of the class
!  *******************************************************************
!
   interface InflowBC_t
      module procedure ConstructInflowBC
   end interface InflowBC_t
!
!  *******************
!  Function prototypes
!  *******************
!
   abstract interface
   end interface
!
!  ========
   contains
!  ========
!
!/////////////////////////////////////////////////////////
!
!        Class constructor
!        -----------------
!
!/////////////////////////////////////////////////////////
!
      function ConstructInflowBC(bname)
!
!        ********************************************************************
!        ยท Definition of the inflow boundary condition in the control file:
!              #define boundary bname
!                 type             = inflow
!                 velocity         = #value        (only in incompressible NS)
!                 Mach number      = #value        (only in compressible NS)
!                 AoAPhi           = #value
!                 AoATheta         = #value
!                 density          = #value        (only in monophase)
!                 pressure         = #value        (only in compressible NS)
!                 TurbIntensity    = #value        (only in compressible NS)
!                 multiphase type  = mixed/layered
!                 phase 1 layer x  > #value
!                 phase 1 layer y  > #value
!                 phase 1 layer z  > #value
!                 phase 1 velocity = #value
!                 phase 2 velocity = #value
!              #end
!        ********************************************************************
!
         implicit none
         type(InflowBC_t)             :: ConstructInflowBC
         character(len=*), intent(in) :: bname
!
!        ---------------
!        Local variables
!        ---------------
!
         integer        :: fid, io
         character(len=LINE_LENGTH) :: boundaryHeader
         character(len=LINE_LENGTH) :: currentLine
         character(len=LINE_LENGTH) :: keyword, keyval
         logical                    :: inside
         type(FTValueDIctionary)    :: bcdict

         open(newunit = fid, file = trim(controlFileName), status = "old", action = "read")

         call bcdict % InitWithSize(16)

         ConstructInflowBC % bname  = bname
         ConstructInflowBC % BCType = "inflow"

         call toLower(ConstructInflowBC % bname)
!
!        Navigate until the "#define boundary bname" sentinel is found
!        -------------------------------------------------------------
         inside = .false.
         do 
            read(fid, '(A)', iostat=io) currentLine

            IF(io .ne. 0 ) EXIT

            call PreprocessInputLine(currentLine)
            call toLower(currentLine)

            if ( index(trim(currentLine),"#define boundary") .ne. 0 ) then
               inside = CheckIfBoundaryNameIsContained(trim(currentLine), trim(ConstructInflowBC % bname)) 
            end if
!
!           Get all keywords inside the zone
!           --------------------------------
            if ( inside ) then
               if ( trim(currentLine) .eq. "#end" ) exit


               keyword  = ADJUSTL(GetKeyword(currentLine))
               keyval   = ADJUSTL(GetValueAsString(currentLine))
               call ToLower(keyword)
      
               call bcdict % AddValueForKey(keyval, trim(keyword))

            end if

         end do
!
!        Analyze the gathered data
!        -------------------------
#if defined(NAVIERSTOKES)
         call GetValueWithDefault(bcdict, "pressure", refValues % p / dimensionless % gammaM2, ConstructInflowBC % p       )
         call GetValueWithDefault(bcdict, "density" , refValues % rho                        , ConstructInflowBC % rho     )
         call GetValueWithDefault(bcdict, "mach"    , dimensionless % Mach                   , ConstructInflowBC % v       )
         call GetValueWithDefault(bcdict, "aoaphi"  , refValues % AoAPhi                     , ConstructInflowBC % AoAPhi  )
         call GetValueWithDefault(bcdict, "aoatheta", refValues % AoATheta                   , ConstructInflowBC % AoATheta)
         call GetValueWithDefault(bcdict, "TurbIntensity", 0.0_RP                            , ConstructInflowBC % TurbIntensity)
#if defined(SPALARTALMARAS)
         call GetValueWithDefault(bcdict, "Turbulence parameter theta", refValues % mu    , ConstructInflowBC % eddy_theta)
#endif
         ConstructInflowBC % p        = ConstructInflowBC % p / refValues % p
         ConstructInflowBC % rho      = ConstructInflowBC % rho / refValues % rho
         ConstructInflowBC % v        = ConstructInflowBC % v * sqrt(thermodynamics % gamma * ConstructInflowBC % p / ConstructInflowBC % rho)
         ConstructInflowBC % AoATheta = ConstructInflowBC % AoATheta * PI / 180.0_RP
         ConstructInflowBC % AoAPhi   = ConstructInflowBC % AoAPhi * PI / 180.0_RP
         ConstructInflowBC % TurbIntensity   = ConstructInflowBC % TurbIntensity / 100.0_RP
#if defined(SPALARTALMARAS)
         ConstructInflowBC % eddy_theta = ConstructInflowBC % eddy_theta / refValues % mu
#endif

#elif defined(INCNS)
         call GetValueWithDefault(bcdict, "velocity", refValues % v, ConstructInflowBC % v)
         call GetValueWithDefault(bcdict, "aoaphi"  , refValues % AoAPhi                     , ConstructInflowBC % AoAPhi  )
         call GetValueWithDefault(bcdict, "aoatheta", refValues % AoATheta                   , ConstructInflowBC % AoATheta)

         ConstructInflowBC % v = ConstructInflowBC % v / refValues % v
         ConstructInflowBC % AoATheta = ConstructInflowBC % AoATheta * PI / 180.0_RP
         ConstructInflowBC % AoAPhi   = ConstructInflowBC % AoAPhi * PI / 180.0_RP

#if (!defined(CAHNHILLIARD))
         call GetValueWithDefault ( bcdict , "density" , refValues % rho , ConstructInflowBC % rho ) 
         ConstructInflowBC % rho = ConstructInflowBC % rho / refValues % rho
#else
!
!        *********************
!        Multiphase input data
!        *********************
!
         if (bcdict % ContainsKey("multiphase type (mixed/layered)") ) then   
            keyval = bcdict % StringValueForKey("multiphase type (mixed/layered)", LINE_LENGTH) 
            call tolower(keyval)
            if ( trim(keyval) .eq. "layered" ) then
               ConstructInflowBC % isLayered = .true.
            else
               ConstructInflowBC % isLayered = .false.
            end if

         else
            ConstructInflowBC % isLayered = .false.

         end if

         if (ConstructInflowBC % isLayered) then
!
!           Require for x, y, and/or z limits
!           ---------------------------------
            if ( bcdict % ContainsKey("interface x > x0") ) then
               ConstructInflowBC % isXLimited = .true.
               ConstructInflowBC % xLim = bcdict % DoublePrecisionValueForKey("interface x > x0")
            else
               ConstructInflowBC % isXLimited = .false.
            end if

            if ( bcdict % ContainsKey("interface y > y0") ) then
               ConstructInflowBC % isYLimited = .true.
               ConstructInflowBC % yLim = bcdict % DoublePrecisionValueForKey("interface y > y0")
            else
               ConstructInflowBC % isYLimited = .false.
            end if

            if ( bcdict % ContainsKey("interface z > z0") ) then
               ConstructInflowBC % isZLimited = .true.
               ConstructInflowBC % zLim = bcdict % DoublePrecisionValueForKey("interface z > z0")
            else
               ConstructInflowBC % isZLimited = .false.
            end if

            call GetValueWithDefault(bcdict, "phase 1 velocity", refValues % v, ConstructInflowBC % phase1Vel) 
            call GetValueWithDefault(bcdict, "phase 2 velocity", refValues % v, ConstructInflowBC % phase2Vel) 
   
            ConstructInflowBC % phase1Vel = ConstructInflowBC % phase1Vel / refValues % v
            ConstructInflowBC % phase2Vel = ConstructInflowBC % phase2Vel / refValues % v

         end if
#endif
#endif
         call bcdict % Destruct
         close(fid)
   
      end function ConstructInflowBC

      subroutine InflowBC_Describe(self)
!
!        ***************************************************
!              Describe the inflow boundary condition
         implicit none
         class(InflowBC_t),  intent(in)  :: self
         write(STD_OUT,'(30X,A,A28,A)') "->", " Boundary condition type: ", "Inflow"
#if defined(NAVIERSTOKES)
         write(STD_OUT,'(30X,A,A28,F10.2)') "->", ' Velocity: ', self % v * refValues % v
         write(STD_OUT,'(30X,A,A28,F10.2)') "->", ' Mach number: ', self % v / sqrt(thermodynamics % gamma * self % p / self % rho)
         write(STD_OUT,'(30X,A,A28,F10.2)') "->", ' Pressure: ', self % p * refValues % p
         write(STD_OUT,'(30X,A,A28,F10.2)') "->", ' Density: ', self % rho * refValues % rho
         write(STD_OUT,'(30X,A,A28,F10.2)') "->", ' AoaPhi: ', self % AoAPhi * 180.0_RP / PI
         write(STD_OUT,'(30X,A,A28,F10.2)') "->", ' AoaTheta: ', self % AoATheta * 180.0_RP / PI

         write(STD_OUT,'(30X,A,A28,F10.2)') "->", ' Max. Vel. Fluct. in % (from TurbIntensity): ', (self % TurbIntensity)
#if defined(SPALARTALMARAS)
         write(STD_OUT,'(30X,A,A28,F10.2)') "->", ' Initial Value of Turbulence variable: ', (3.0_RP * self % eddy_theta)
#endif
#elif defined(INCNS)
         write(STD_OUT,'(30X,A,A28,F10.2)') "->", ' Velocity: ', self % v * refValues % v
#if (!defined(CAHNHILLIARD))
         write(STD_OUT,'(30X,A,A28,F10.2)') "->", ' Density: ', self % rho * refValues % rho
#endif
         write(STD_OUT,'(30X,A,A28,F10.2)') "->", ' AoaPhi: ', self % AoAPhi * 180.0_RP / PI
         write(STD_OUT,'(30X,A,A28,F10.2)') "->", ' AoaTheta: ', self % AoATheta * 180.0_RP / PI
#if defined(CAHNHILLIARD)
         if ( self % isLayered ) then
            write(STD_OUT,'(30X,A,A28,A)') "->", ' Multiphase type: '," Layered"
         else
            write(STD_OUT,'(30X,A,A28,A)') "->", ' Multiphase type: '," Mixed"
         end if
         
         if ( self % isLayered ) then
            if ( self % isXLimited ) write(STD_OUT,'(30X,A,A28,F10.2)') "->", " Interface limits x>x0: ", self % xLim
            if ( self % isYLimited ) write(STD_OUT,'(30X,A,A28,F10.2)') "->", " Interface limits y>y0: ", self % yLim
            if ( self % isZLimited ) write(STD_OUT,'(30X,A,A28,F10.2)') "->", " Interface limits z>z0: ", self % zLim
            
            write(STD_OUT,'(30X,A,A28,F10.2)') "->", " Phase 1 velocity: ", self % phase1Vel * refValues % v
            write(STD_OUT,'(30X,A,A28,F10.2)') "->", " Phase 2 velocity: ", self % phase2Vel * refValues % v
         end if
#endif
#endif
         
      end subroutine InflowBC_Describe
!
!/////////////////////////////////////////////////////////
!
!        Class destructors
!        -----------------
!
!/////////////////////////////////////////////////////////
!
      subroutine InflowBC_Destruct(self)
         implicit none
         class(InflowBC_t)    :: self

      end subroutine InflowBC_Destruct
!
!////////////////////////////////////////////////////////////////////////////
!
!        Subroutines for compressible Navier--Stokes equations
!        -----------------------------------------------------
!
!////////////////////////////////////////////////////////////////////////////
!
#if defined(NAVIERSTOKES)
      subroutine InflowBC_FlowState(self, x, t, nHat, Q)
         implicit none
         class(InflowBC_t),   intent(in)    :: self
         real(kind=RP),       intent(in)    :: x(NDIM)
         real(kind=RP),       intent(in)    :: t
         real(kind=RP),       intent(in)    :: nHat(NDIM)
         real(kind=RP),       intent(inout) :: Q(NCONS)
!
!        ---------------
!        Local variables
!        ---------------
!
         real(kind=RP) :: qq, u, v, w
         real(kind=RP) :: u_prime, v_prime, w_prime

         associate ( gammaM2 => dimensionless % gammaM2, &
                     gamma => thermodynamics % gamma )
!        MAX Turb intensity = u_prime/u, isotropic turb. at inlet & random fluctuations with max turb
                     !call random_seed (Gonzalo: this was giving problems for a particular problem)
                     call random_number(u_prime)
                     call random_number(v_prime)
                     call random_number(w_prime)
         qq = self % v
         u  = qq*cos(self % AoAtheta)*COS(self % AoAphi)
         v  = qq*sin(self % AoAtheta)*COS(self % AoAphi)
         w  = qq*SIN(self % AoAphi)
         u_prime = (2.0_RP*u_prime - 1.0_RP)*self % TurbIntensity * u
         v_prime = (2.0_RP*v_prime - 1.0_RP)*self % TurbIntensity * v
         w_prime = (2.0_RP*w_prime - 1.0_RP)*self % TurbIntensity * w
         u  = u+u_prime
         v  = v+v_prime
         w  = w+w_prime

         Q(1) = self % rho
         Q(2) = Q(1)*u
         Q(3) = Q(1)*v
         Q(4) = Q(1)*w
         Q(5) = self % p/(gamma - 1._RP) + 0.5_RP*Q(1)*(u**2 + v**2 + w**2)
#if defined(SPALARTALMARAS)
         Q(6) = Q(1) * 3.0_RP*self % eddy_theta
#endif
         end associate

      end subroutine InflowBC_FlowState

      subroutine InflowBC_FlowNeumann(self, x, t, nHat, Q, U_x, U_y, U_z, flux)
!
!        *******************************************
!        Cancel out the viscous flux at the inlet
!        *******************************************
!
         implicit none
         class(InflowBC_t),   intent(in)    :: self
         real(kind=RP),       intent(in)    :: x(NDIM)
         real(kind=RP),       intent(in)    :: t
         real(kind=RP),       intent(in)    :: nHat(NDIM)
         real(kind=RP),       intent(in)    :: Q(NCONS)
         real(kind=RP),       intent(in)    :: U_x(NGRAD)
         real(kind=RP),       intent(in)    :: U_y(NGRAD)
         real(kind=RP),       intent(in)    :: U_z(NGRAD)
         real(kind=RP),       intent(inout) :: flux(NCONS)

         flux = 0.0_RP

      end subroutine InflowBC_FlowNeumann
#endif
!
!////////////////////////////////////////////////////////////////////////////
!
!        Subroutines for incompressible Navier--Stokes equations
!        -------------------------------------------------------
!
!////////////////////////////////////////////////////////////////////////////
!
#if defined(INCNS)
      subroutine InflowBC_FlowState(self, x, t, nHat, Q)
         implicit none
         class(InflowBC_t),  intent(in)    :: self
         real(kind=RP),       intent(in)    :: x(NDIM)
         real(kind=RP),       intent(in)    :: t
         real(kind=RP),       intent(in)    :: nHat(NDIM)
         real(kind=RP),       intent(inout) :: Q(NCONS)
!
!        ---------------
!        Local variables
!        ---------------
!
         real(kind=RP)  :: rho, u, v, w, vel

         u = self % v * cos(self % AoAtheta) * cos(self % AoAphi)
         v = self % v * sin(self % AoAtheta) * cos(self % AoAphi)
         w = self % v * sin(self % AoAphi)

         Q(INSRHO)  = self % rho
         Q(INSRHOU) = Q(INSRHO)*u
         Q(INSRHOV) = Q(INSRHO)*v
         Q(INSRHOW) = Q(INSRHO)*w

      end subroutine InflowBC_FlowState

      subroutine InflowBC_FlowNeumann(self, x, t, nHat, Q, U_x, U_y, U_z, flux)
         implicit none
         class(InflowBC_t),  intent(in)     :: self
         real(kind=RP),       intent(in)    :: x(NDIM)
         real(kind=RP),       intent(in)    :: t
         real(kind=RP),       intent(in)    :: nHat(NDIM)
         real(kind=RP),       intent(in)    :: Q(NCONS)
         real(kind=RP),       intent(in)    :: U_x(NCONS)
         real(kind=RP),       intent(in)    :: U_y(NCONS)
         real(kind=RP),       intent(in)    :: U_z(NCONS)
         real(kind=RP),       intent(inout) :: flux(NCONS)

         flux = 0.0_RP

      end subroutine InflowBC_FlowNeumann
#endif
!
!////////////////////////////////////////////////////////////////////////////
!
!        Subroutines for Cahn--Hilliard: all do--nothing in Inflows
!        ----------------------------------------------------------
!
!////////////////////////////////////////////////////////////////////////////
!
#if defined(CAHNHILLIARD)
      subroutine InflowBC_PhaseFieldState(self, x, t, nHat, Q)
         implicit none
         class(InflowBC_t),  intent(in)    :: self
         real(kind=RP),       intent(in)    :: x(NDIM)
         real(kind=RP),       intent(in)    :: t
         real(kind=RP),       intent(in)    :: nHat(NDIM)
         real(kind=RP),       intent(inout) :: Q(NCOMP)
      end subroutine InflowBC_PhaseFieldState

      subroutine InflowBC_PhaseFieldNeumann(self, x, t, nHat, Q, U_x, U_y, U_z, flux)
         implicit none
         class(InflowBC_t),  intent(in)    :: self
         real(kind=RP),       intent(in)    :: x(NDIM)
         real(kind=RP),       intent(in)    :: t
         real(kind=RP),       intent(in)    :: nHat(NDIM)
         real(kind=RP),       intent(in)    :: Q(NCOMP)
         real(kind=RP),       intent(in)    :: U_x(NCOMP)
         real(kind=RP),       intent(in)    :: U_y(NCOMP)
         real(kind=RP),       intent(in)    :: U_z(NCOMP)
         real(kind=RP),       intent(inout) :: flux(NCOMP)

         flux = 0.0_RP

      end subroutine InflowBC_PhaseFieldNeumann

      subroutine InflowBC_ChemPotState(self, x, t, nHat, Q)
         implicit none
         class(InflowBC_t),  intent(in)    :: self
         real(kind=RP),       intent(in)    :: x(NDIM)
         real(kind=RP),       intent(in)    :: t
         real(kind=RP),       intent(in)    :: nHat(NDIM)
         real(kind=RP),       intent(inout) :: Q(NCOMP)
      end subroutine InflowBC_ChemPotState

      subroutine InflowBC_ChemPotNeumann(self, x, t, nHat, Q, U_x, U_y, U_z, flux)
         implicit none
         class(InflowBC_t),  intent(in)    :: self
         real(kind=RP),       intent(in)    :: x(NDIM)
         real(kind=RP),       intent(in)    :: t
         real(kind=RP),       intent(in)    :: nHat(NDIM)
         real(kind=RP),       intent(in)    :: Q(NCOMP)
         real(kind=RP),       intent(in)    :: U_x(NCOMP)
         real(kind=RP),       intent(in)    :: U_y(NCOMP)
         real(kind=RP),       intent(in)    :: U_z(NCOMP)
         real(kind=RP),       intent(inout) :: flux(NCOMP)

         flux = 0.0_RP

      end subroutine InflowBC_ChemPotNeumann
#endif
end module InflowBCClass