FreeSlipWallBC.f90 Source File


Source Code

#include "Includes.h"
module FreeSlipWallBCClass
   use SMConstants
   use PhysicsStorage
   use VariableConversion, only: GetGradientValues_f
   use FileReaders,            only: controlFileName
   use FileReadingUtilities,   only: GetKeyword, GetValueAsString, PreprocessInputLine
   use FTValueDictionaryClass, only: FTValueDictionary
   use GenericBoundaryConditionClass
   use FluidData
   use FileReadingUtilities, only: getRealArrayFromString
   use Utilities, only: toLower, almostEqual
   implicit none
!
!  *****************************
!  Default everything to private
!  *****************************
!
   private
!
!  ****************
!  Public variables
!  ****************
!
!
!  ******************
!  Public definitions
!  ******************
!
   public FreeSlipWallBC_t
!
!  ****************************
!  Static variables definitions
!  ****************************
!
!
!  ****************
!  Class definition
!  ****************
!
   type, extends(GenericBC_t) ::  FreeSlipWallBC_t
#ifdef NAVIERSTOKES
      logical           :: isAdiabatic
      real(kind=RP)     :: Twall
      real(kind=RP)     :: ewall       ! Wall internal energy
      real(kind=RP)     :: invTwall
      real(kind=RP)     :: wallType    ! 0/Adia 1/Isothermal
#endif
#ifdef CAHNHILLIARD
      real(kind=RP)     :: thetaw
#endif
      contains
         procedure         :: Destruct          => FreeSlipWallBC_Destruct
         procedure         :: Describe          => FreeSlipWallBC_Describe
#ifdef FLOW
         procedure         :: FlowState         => FreeSlipWallBC_FlowState
         procedure         :: FlowGradVars      => FreeSlipWallBC_FlowGradVars
         procedure         :: FlowNeumann       => FreeSlipWallBC_FlowNeumann
#endif
#ifdef CAHNHILLIARD
         procedure         :: PhaseFieldState   => FreeSlipWallBC_PhaseFieldState
         procedure         :: PhaseFieldNeumann => FreeSlipWallBC_PhaseFieldNeumann
         procedure         :: ChemPotState      => FreeSlipWallBC_ChemPotState
         procedure         :: ChemPotNeumann    => FreeSlipWallBC_ChemPotNeumann
#endif
   end type FreeSlipWallBC_t
!
!  *******************************************************************
!  Traditionally, constructors are exported with the name of the class
!  *******************************************************************
!
   interface FreeSlipWallBC_t
      module procedure ConstructFreeSlipWallBC
   end interface FreeSlipWallBC_t
!
!  *******************
!  Function prototypes
!  *******************
!
   abstract interface
   end interface
!
!  ========
   contains
!  ========
!
!/////////////////////////////////////////////////////////
!
!        Class constructor
!        -----------------
!
!/////////////////////////////////////////////////////////
!
      function ConstructFreeSlipWallBC(bname)
!
!        ********************************************************************
!        · Definition of the noSlipWall boundary condition in the control file:
!              #define boundary bname
!                 type             = noSlipWall
!                 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)
!                 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(FreeSlipWallBC_t)             :: ConstructFreeSlipWallBC
         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)

         ConstructFreeSlipWallBC % BCType = "freeslipwall"
         ConstructFreeSlipWallBC % bname  = bname
         call toLower(ConstructFreeSlipWallBC % bname)

         write(boundaryHeader,'(A,A)') "#define boundary ",trim(bname)
         call toLower(boundaryHeader)
!
!        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(ConstructFreeSlipWallBC % 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
!        -------------------------
#ifdef NAVIERSTOKES
         if ( bcdict % ContainsKey("wall type (adiabatic/isothermal)") ) then
            keyval = bcdict % StringValueForKey("wall type (adiabatic/isothermal)", LINE_LENGTH)
            call tolower(keyval)
         else
            keyval = "adiabatic"
         end if

         if ( trim(keyval) .eq. "adiabatic" ) then
            ConstructFreeSlipWallBC % isAdiabatic = .true.
            ConstructFreeSlipWallBC % ewall = 0.0_RP
            ConstructFreeSlipWallBC % Twall = 0.0_RP
            ConstructFreeSlipWallBC % invTwall = 0.0_RP
            ConstructFreeSlipWallBC % wallType = 0.0_RP
         else
            ConstructFreeSlipWallBC % isAdiabatic = .false.
            call GetValueWithDefault(bcdict, "wall temperature" , refValues % T, ConstructFreeSlipWallBC % Twall     )
            ConstructFreeSlipWallBC % ewall = ConstructFreeSlipWallBC % Twall / (refValues % T*thermodynamics % gammaMinus1*dimensionless % gammaM2)
            ConstructFreeSlipWallBC % invTwall = dimensionless % gammaM2*refValues % T / ConstructFreeSlipWallBC % Twall
            ConstructFreeSlipWallBC % wallType = 1.0_RP
         end if
#endif
#ifdef CAHNHILLIARD
         call GetValueWithDefault(bcdict, "contact angle", 90.0_RP, ConstructFreeSlipWallBC % thetaw)
#endif

         close(fid)
         call bcdict % Destruct
   
      end function ConstructFreeSlipWallBC

      subroutine FreeSlipWallBC_Describe(self)
!
!        ***************************************************
!              Describe the inflow boundary condition
         implicit none
         class(FreeSlipWallBC_t),  intent(in)  :: self
         write(STD_OUT,'(30X,A,A28,A)') "->", " Boundary condition type: ", "FreeSlipWall"
#ifdef NAVIERSTOKES
         if ( self % isAdiabatic ) then
            write(STD_OUT,'(30X,A,A28,A)') "->", ' Thermal type: ', "Adiabatic"


         else
            write(STD_OUT,'(30X,A,A28,A)') "->", ' Thermal type: ', "Isothermal"
            write(STD_OUT,'(30X,A,A28,F10.2)') "->", ' Wall temperature: ', self % Twall * refValues % T
         end if
#endif
#ifdef CAHNHILLIARD
         write(STD_OUT,'(30X,A,A28,F10.2)') "->", ' Wall contact angle: ', self % thetaw
#endif
         
      end subroutine FreeSlipWallBC_Describe

!
!/////////////////////////////////////////////////////////
!
!        Class destructors
!        -----------------
!
!/////////////////////////////////////////////////////////
!
      subroutine FreeSlipWallBC_Destruct(self)
         implicit none
         class(FreeSlipWallBC_t)    :: self

      end subroutine FreeSlipWallBC_Destruct
!
!////////////////////////////////////////////////////////////////////////////
!
!        Subroutines for compressible Navier--Stokes equations
!        -----------------------------------------------------
!
!////////////////////////////////////////////////////////////////////////////
!
#ifdef NAVIERSTOKES
      subroutine FreeSlipWallBC_FlowState(self, x, t, nHat, Q)
!
!        *************************************************************
!           Compute the state variables for a general wall
!
!           · Density is computed from the interior state
!           · Wall velocity is set to v_interior - 2v_normal:
!                 -> Maintains tangential speed.
!                 -> Removes normal speed (weakly).
!           · Internal energy is either the interior state for 
!              adiabatic walls, or the imposed for isothermal.
!              eBC = eInt + kWallType (eIso - eInt)
!              where kWallType = 0 for adiabatic and 1 for isothermal.        
!        *************************************************************
!
         implicit none
         class(FreeSlipWallBC_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) :: qNorm, pressure_aux

         qNorm = nHat(IX) * Q(IRHOU) + nHat(IY) * Q(IRHOV) + nHat(IZ) * Q(IRHOW)

         Q(IRHOU:IRHOW) = Q(IRHOU:IRHOW) - 2.0_RP * qNorm * nHat

         !Isothermal BC
         pressure_aux = Q(IRHO) * self % Twall / (refValues % T * dimensionless % gammaM2)
         Q(IRHOE) = Q(IRHOE) + self % wallType*(pressure_aux/thermodynamics % gammaMinus1 + 0.5_RP*(POW2(Q(IRHOU))+POW2(Q(IRHOV))+POW2(Q(IRHOW)))/Q(IRHO) - Q(IRHOE))


      end subroutine FreeSlipWallBC_FlowState

      subroutine FreeSlipWallBC_FlowGradVars(self, x, t, nHat, Q, U, GetGradients)
!
!        *****************************************************************
!           Only set the temperature, velocity is Neumann, use interior!
!        *****************************************************************
!
         implicit none
         class(FreeSlipWallBC_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(inout) :: U(NGRAD)
         procedure(GetGradientValues_f)        :: GetGradients
!
!        ---------------
!        Local variables
!        ---------------
!
         real(kind=RP)  :: rhou_n
         real(kind=RP)  :: Q_aux(NCONS)

         Q_aux(IRHO) = Q(IRHO)
         Q_aux(IRHOU:IRHOW) = Q(IRHOU:IRHOW)
         Q_aux(IRHOE) = Q(IRHOE) + self % wallType*(Q(IRHO)*self % eWall+0.5_RP*(POW2(Q(IRHOU))+POW2(Q(IRHOV))+POW2(Q(IRHOW)))/Q(IRHO)-Q(IRHOE))
#if defined(SPALARTALMARAS)
         Q_aux(IRHOTHETA)= Q(IRHOTHETA)
#endif
         call GetGradients(NCONS, NGRAD, Q_aux, U)

      end subroutine FreeSlipWallBC_FlowGradVars

      subroutine FreeSlipWallBC_FlowNeumann(self, x, t, nHat, Q, U_x, U_y, U_z, flux)
!
!        ***********************************************************
!           In momentum, free slip is Neumann. In temperature, 
!           depends on the adiabatic/isothermal choice
!        ***********************************************************
!
         implicit none
         class(FreeSlipWallBC_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)
!
!        ---------------
!        Local Variables
!        ---------------
!   
         real(kind=RP)  :: viscWork, heatFlux

         viscWork = (flux(IRHOU)*Q(IRHOU)+flux(IRHOV)*Q(IRHOV)+flux(IRHOW)*Q(IRHOW))/Q(IRHO)
         heatFlux = flux(IRHOE) - viscWork
         flux(IRHO:IRHOW) = 0.0_RP
         flux(IRHOE) = self % wallType * heatFlux  ! 0 (Adiabatic)/ heatFlux (Isothermal)
#if defined(SPALARTALMARAS)
         flux(IRHOTHETA) = 0.0_RP
#endif
      end subroutine FreeSlipWallBC_FlowNeumann
#endif
!
!////////////////////////////////////////////////////////////////////////////
!
!        Subroutines for incompressible Navier--Stokes equations
!        -------------------------------------------------------
!
!////////////////////////////////////////////////////////////////////////////
!
#ifdef INCNS
      subroutine FreeSlipWallBC_FlowState(self, x, t, nHat, Q)
!
!        *************************************************************
!           Compute the state variables for a general wall
!
!           · Density is computed from the interior state
!           · Wall velocity is set to 2v_wall - v_interior
!           · Pressure is computed from the interior state
!        *************************************************************
!

         implicit none
         class(FreeSlipWallBC_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)  :: vn
!
!        -----------------------------------------------
!        Generate the external flow along the face, that
!        represents a solid wall.
!        -----------------------------------------------
!
         vn = sum(Q(INSRHOU:INSRHOW)*nHat)

         Q(INSRHO)          = Q(INSRHO)
         Q(INSRHOU:INSRHOW) = Q(INSRHOU:INSRHOW) - 2.0_RP * vn * nHat
         Q(INSP)            = Q(INSP)

      end subroutine FreeSlipWallBC_FlowState

      subroutine FreeSlipWallBC_FlowGradVars(self, x, t, nHat, Q, U, GetGradients)
!
!        **************************************************************
!           Use the interior velocity: Neumann BC!
!        **************************************************************
!
         implicit none
         class(FreeSlipWallBC_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(inout) :: U(NGRAD)
         procedure(GetGradientValues_f)        :: GetGradients

      end subroutine FreeSlipWallBC_FlowGradVars

      subroutine FreeSlipWallBC_FlowNeumann(self, x, t, nHat, Q, U_x, U_y, U_z, flux)
!
!        ***************************************************************
!           Set homogeneous Neumann BCs everywhere
!        ***************************************************************
!        
         implicit none
         class(FreeSlipWallBC_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 FreeSlipWallBC_FlowNeumann
#endif
!
!////////////////////////////////////////////////////////////////////////////
!
!        Subroutines for multiphase solver
!        ---------------------------------
!
!////////////////////////////////////////////////////////////////////////////
!
#ifdef MULTIPHASE
      subroutine FreeSlipWallBC_FlowState(self, x, t, nHat, Q)
!
!        *************************************************************
!           Compute the state variables for a general wall
!
!           · Density is computed from the interior state
!           · Wall velocity is set to 2v_wall - v_interior
!           · Pressure is computed from the interior state
!        *************************************************************
!

         implicit none
         class(FreeSlipWallBC_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)  :: vn
!
!        -----------------------------------------------
!        Generate the external flow along the face, that
!        represents a solid wall.
!        -----------------------------------------------
!
         vn = sum(Q(IMSQRHOU:IMSQRHOW)*nHat)

         Q(IMC)      = Q(IMC)
         Q(IMSQRHOU) = Q(IMSQRHOU) - 2.0_RP * vn * nHat(IX)
         Q(IMSQRHOV) = Q(IMSQRHOV) - 2.0_RP * vn * nHat(IY)
         Q(IMSQRHOW) = Q(IMSQRHOW) - 2.0_RP * vn * nHat(IZ)
         Q(IMP)      = Q(IMP)

      end subroutine FreeSlipWallBC_FlowState

      subroutine FreeSlipWallBC_FlowGradVars(self, x, t, nHat, Q, U, GetGradients)
!
!        **************************************************************
!           Use the interior velocity: Neumann BC!
!        **************************************************************
!
         implicit none
         class(FreeSlipWallBC_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(inout) :: U(NGRAD)
         procedure(GetGradientValues_f)        :: GetGradients
      end subroutine FreeSlipWallBC_FlowGradVars

      subroutine FreeSlipWallBC_FlowNeumann(self, x, t, nHat, Q, U_x, U_y, U_z, flux)
         implicit none
         class(FreeSlipWallBC_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 FreeSlipWallBC_FlowNeumann
#endif
!
!////////////////////////////////////////////////////////////////////////////
!
!        Subroutines for Cahn--Hilliard
!        ------------------------------
!
!////////////////////////////////////////////////////////////////////////////
!
#if defined(CAHNHILLIARD)
      subroutine FreeSlipWallBC_PhaseFieldState(self, x, t, nHat, Q)
         implicit none
         class(FreeSlipWallBC_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 FreeSlipWallBC_PhaseFieldState

      subroutine FreeSlipWallBC_PhaseFieldNeumann(self, x, t, nHat, Q, U_x, U_y, U_z, flux)
         implicit none
         class(FreeSlipWallBC_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)
!
!        ---------------
!        Local variables
!        ---------------
!  
         real(kind=RP), parameter   :: MIN_ = 1.0e-1_RP
         real(kind=RP)              :: prod
         real(kind=RP)              :: prod12, prod13, prod23, c3

         prod = Q(1) * (1.0_RP - Q(1))

         if ( prod .le. MIN_ ) then
            prod = 0.0_RP
         end if

         flux = -4.0_RP * multiphase % invEps * cos(DEG2RAD*self % thetaw) * prod 

      end subroutine FreeSlipWallBC_PhaseFieldNeumann

      subroutine FreeSlipWallBC_ChemPotState(self, x, t, nHat, Q)
         implicit none
         class(FreeSlipWallBC_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 FreeSlipWallBC_ChemPotState

      subroutine FreeSlipWallBC_ChemPotNeumann(self, x, t, nHat, Q, U_x, U_y, U_z, flux)
         implicit none
         class(FreeSlipWallBC_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 FreeSlipWallBC_ChemPotNeumann

#endif
end module FreeSlipWallBCClass