Turbulence.f90 Source File


Source Code

#include "Includes.h"
module SpallartAlmarasTurbulence
   use SMConstants
   use VariableConversion_NSSA
   use FluidData_NSSA
   use PhysicsStorage_NSSA
   use FTValueDictionaryClass
   use Utilities
   use mainKeywordsModule
   use Headers
   implicit none
!
!  *****************************
!  Default everything to private
!  *****************************
!
   private
   public SAmodel, InitializeTurbulenceModel, Spalart_Almaras_t, SA_ComputeViscosity

!  ****************
!  Class definition
!  ****************
!
   type Spalart_Almaras_t
      logical                    :: constructed = .false.
      real(kind=RP)              :: cv1 = 7.1_RP
      real(kind=RP)              :: cv2 = 0.7_RP
      real(kind=RP)              :: cv3 = 0.9_RP
      real(kind=RP)              :: cb1 = 0.1355_RP
      real(kind=RP)              :: cb2 = 0.622_RP
      real(kind=RP)              :: cw2 = 0.3_RP
      real(kind=RP)              :: cw3 = 2.0_RP
      real(kind=RP)              :: kappa = 0.41_RP
      real(kind=RP)              :: sigma_sa = 2.0_RP/3.0_RP
      real(kind=RP)              :: rmax  = 2.0_RP
      real(kind=RP)              :: cw1

      contains
!        procedure         :: Destruct          => Class_Destruct
         procedure         :: Initialize        => SAmodel_Initialize
         
         procedure, private ::      Compute_chi
         procedure, private ::      Compute_fv1
         procedure, private ::      Compute_fv2
         procedure, private ::      Compute_sbar
         procedure, private ::      Compute_modifiedvorticity
         procedure, private ::      Compute_gn
         procedure, private ::      Compute_g
         procedure, private ::      Compute_fw
         procedure, private ::      Compute_ProductionTerm
         procedure, private ::      Compute_DestructionTerm
         procedure, private ::      Compute_AdditionalSourceTermKappa

         procedure, public  :: ComputeViscosity    => SA_ComputeViscosity
         procedure          :: ComputeSourceTerms  => SA_Compute_SourceTerms          
   end type Spalart_Almaras_t
!

!
   class(Spalart_Almaras_t), allocatable   :: SAmodel

!  ========
   contains
!  ========
!
!/////////////////////////////////////////////////////////
!
!        Class constructor
!        -----------------
!
!/////////////////////////////////////////////////////////
      subroutine InitializeTurbulenceModel(model, controlVariables)
         implicit none
         class(Spalart_Almaras_t), allocatable        :: model
         class(FTValueDictionary),  intent(in) :: controlVariables
!
!        ---------------
!        Local variables         
!        ---------------

         if (.not. allocated(model)) allocate( Spalart_Almaras_t :: model)

         call model % Initialize(controlVariables)
            
      end subroutine InitializeTurbulenceModel


      subroutine SAmodel_Initialize(self, controlVariables)
         implicit none
         class(Spalart_Almaras_t)              :: self
         class(FTValueDictionary),  intent(in) :: controlVariables

         self % cw1  = self % cb1 / POW2(self % kappa)  + (1.0_RP + self % cb2)/ self % sigma_sa

      end subroutine SAmodel_Initialize
!

!/////////////////////////////////////////////////////////
!  
!        Suitable subroutines for Variable_procedure
!        ---------------------------------------------
!
!/////////////////////////////////////////////////////////
!

      subroutine SA_ComputeViscosity(self, rhotheta, kinematic_viscocity, rho, mu, mu_t, eta, xvec)
         implicit none
         class(Spalart_Almaras_t), intent(inout) :: self
         real(kind=RP), intent(in)            :: rhotheta
         real(kind=RP), intent(in)            :: rho
         real(kind=RP), intent(in)            :: kinematic_viscocity
         real(kind=RP), intent(in)            :: mu
         real(kind=RP), intent(inout)         :: mu_t
         real(kind=RP), intent(inout)         :: eta
         real(kind=RP), intent(in) , optional :: xvec(3)

         real(kind=RP)            :: fv1
         real(kind=RP)            :: chi
         real(kind=RP)            :: theta, etaexact

         theta = rhotheta / rho
         call self % Compute_chi(theta, kinematic_viscocity, chi)
         call self % Compute_fv1(chi, fv1)

         if (theta .GE. 0.0_RP ) then
            mu_t = rho * theta * fv1 
            eta  = dimensionless % mu * mu * (1.0_RP + chi) / self % sigma_sa
        else
             mu_t = 0.0_RP       
             eta  = dimensionless % mu * mu * (1.0_RP + chi + (POW2(chi))/2.0_RP) / self % sigma_sa
        endif 

      end subroutine SA_ComputeViscosity

      !/////////////////////////////////////////////////////////
! Compute Spallart Almaras Source  terms

       subroutine SA_Compute_SourceTerms(self, rhotheta, kinematic_viscocity, rho, dwall,&
                                         Q, Q_x, Q_y, Q_z, S_SA, xvec)
         implicit none
         !-----------------------------------------------------------
         class(Spalart_Almaras_t), intent(inout) :: self
         real(kind=RP), intent(in)            :: rhotheta
         real(kind=RP), intent(in)            :: kinematic_viscocity
         real(kind=RP), intent(in)            :: rho
         real(kind=RP), intent(in)            :: dwall
         real(kind=RP), intent(in)            :: Q(NCONS)
         real(kind=RP), intent(in)            :: Q_x(NCONS)
         real(kind=RP), intent(in)            :: Q_y(NCONS)
         real(kind=RP), intent(in)            :: Q_z(NCONS)
         real(kind=RP), intent(out)           :: S_SA(NCONS)
         real(kind=RP), intent(in) , optional :: xvec(NDIM)

         !-----------------------------------------------------------
         real(kind=RP)           :: chi , sbar, Production, thetaexact, rhoexact, DESTRUCTION2, DESTRUCTION1, DESTRUCTION3
         real(kind=RP)           :: theta
         real(kind=RP)           :: vort, somega
         real(kind=RP)           :: fv1
         real(kind=RP)           :: production_G
         real(kind=RP)           :: destruction_Y
         real(kind=RP)           :: source_Kappa
         real(kind=RP)           :: U_x(NDIM)
         real(kind=RP)           :: U_y(NDIM)
         real(kind=RP)           :: U_z(NDIM)         
         real(kind=RP)           :: Theta_x, Theta_y, Theta_z
         theta = rhotheta / rho
         call getVelocityGradients(Q,Q_x,Q_y,Q_z,U_x,U_y,U_z)
         call ComputeVorticity(U_x, U_y, U_z, vort)
         call geteddyviscositygradients(Q, Q_x, Q_y, Q_z, Theta_x, Theta_y, Theta_z)

         call self % Compute_chi(theta, kinematic_viscocity, chi)
         call self % Compute_fv1(chi, fv1)

         if (dwall .GT. 0.0_RP) then 
            call self % Compute_ProductionTerm(chi, fv1, vort, rho, theta, dwall,  production_G)
            call self % Compute_DestructionTerm(chi, fv1, vort, rho, theta, dwall,  destruction_Y)       
         else
            production_G = 0.0_RP
            destruction_Y = 0.0_RP
         endif

         call self % Compute_AdditionalSourceTermKappa(rho, Theta_x, Theta_y, Theta_z, source_Kappa)   

         S_SA(1:5) = 0.0_RP
         S_SA(6)   = production_G - destruction_Y + source_Kappa 
            
     end subroutine SA_Compute_SourceTerms



!/////////////////////////////////////////////////////////
      subroutine Compute_chi(self, theta, kinematic_viscocity, chi)
         implicit none
         class(Spalart_Almaras_t), intent(inout) :: self
         real(kind=RP), intent(in)            :: theta
         real(kind=RP), intent(in)            :: kinematic_viscocity
         real(kind=RP), intent(out)           :: chi

         chi = theta / kinematic_viscocity

      end subroutine Compute_chi

      subroutine Compute_fv1(self, chi, fv1)
         implicit none
         class(Spalart_Almaras_t), intent(inout) :: self
         real(kind=RP), intent(in)            :: chi
         real(kind=RP), intent(out)            :: fv1

         fv1 = (chi**3.0_RP)/((chi**3.0_RP) + (self % cv1)**3.0_RP)

      end subroutine Compute_fv1

!/////////////////////////////////////////////////////////
! compute production terms 

      subroutine Compute_ProductionTerm(self, chi, fv1, vort, rho, theta, dwall, production_G)
         implicit none
         !-----------------------------------------------------------
         class(Spalart_Almaras_t), intent(inout) :: self
         real(kind=RP), intent(in)            :: chi
         real(kind=RP), intent(in)            :: fv1
         real(kind=RP), intent(in)            :: vort
         real(kind=RP), intent(in)            :: rho
         real(kind=RP), intent(in)            :: theta
         real(kind=RP), intent(in)            :: dwall
         real(kind=RP), intent(inout)         :: production_G
         !-----------------------------------------------------------
         real(kind=RP)                        :: fv2
         real(kind=RP)                        :: sbar, stilda 
         real(kind=RP)                        :: gn, PRODUCTION1, PRODUCTION2, PRODUCTION3

      if (theta .GE. 0.0_RP ) then

            fv2    =  Compute_fv2(self, chi, fv1)
            sbar   =  Compute_sbar(self, theta, dwall, fv2)
            stilda =  Compute_modifiedvorticity(self, vort, sbar)
            production_G = self % cb1 * stilda * rho * theta
            
         else
            gn = Compute_gn(self, chi)
            production_G = self % cb1 * vort * rho * theta * gn 
            
         end if 

      end subroutine Compute_ProductionTerm

      function Compute_fv2(self, chi, fv1) result(fv2)
         implicit none
         class(Spalart_Almaras_t), intent(inout) :: self
         real(kind=RP), intent(in)            :: chi
         real(kind=RP), intent(in)            :: fv1
         real(kind=RP)                        :: fv2

         fv2 = 1.0_RP - chi / (1.0_RP + chi * fv1) 
     
      end function Compute_fv2

      function Compute_sbar(self, theta, dwall, fv2) result(sbar)
         implicit none
         class(Spalart_Almaras_t), intent(inout) :: self
         real(kind=RP), intent(in)            :: theta
         real(kind=RP), intent(in)            :: fv2
         real(kind=RP), intent(in)            :: dwall
         real(kind=RP)                        :: sbar

         sbar =  dimensionless % mu * theta * fv2/ (POW2(self % kappa) * POW2(dwall) ) 
     
      end function Compute_sbar

      function Compute_modifiedvorticity(self, vort, sbar) result(stilda)
         implicit none
         class(Spalart_Almaras_t), intent(inout) :: self
         real(kind=RP), intent(in)            :: vort
         real(kind=RP), intent(in)            :: sbar
         real(kind=RP)                        :: stilda

         IF (sbar .GE. - self % cv2 * vort) then
            stilda = vort + sbar 
         ELSE
            stilda =  vort +  (vort*(POW2(self % cv2)*vort + self % cv3 * sbar))/((self % cv3 - 2.0_RP* self % cv2)*vort - sbar)
         END IF     
      end function Compute_modifiedvorticity

      function Compute_gn(self, chi) result (gn)
         implicit none
         class(Spalart_Almaras_t), intent(inout) :: self
         real(kind=RP), intent(in)            :: chi
         real(kind=RP)                        :: gn

         gn = 1.0_RP - (1000.0_RP*POW2(chi))/(1.0_RP + POW2(chi) )

     end function Compute_gn

!/////////////////////////////////////////////////////////
! compute destruction terms 
      
      subroutine Compute_DestructionTerm(self, chi, fv1, vort, rho, theta, dwall, destruction_Y)
         implicit none
         class(Spalart_Almaras_t), intent(inout) :: self
         real(kind=RP), intent(in)            :: chi
         real(kind=RP), intent(in)            :: fv1
         real(kind=RP), intent(in)            :: vort
         real(kind=RP), intent(in)            :: rho
         real(kind=RP), intent(in)            :: theta
         real(kind=RP), intent(in)            :: dwall
         real(kind=RP), intent(inout)         :: destruction_Y
         
         real(kind=RP)            :: g
         real(kind=RP)            :: fw
         real(kind=RP)            :: fv2
         real(kind=RP)            :: sbar, stilda 

         if (theta .GE. 0.0_RP ) then
            fv2    =  Compute_fv2(self, chi, fv1)
            sbar   =  Compute_sbar(self, theta, dwall, fv2)
            stilda =  Compute_modifiedvorticity(self, vort, sbar)
            g  = Compute_g(self, theta, dwall, stilda)
            fw = Compute_fw(self, g)
            destruction_Y =    dimensionless % mu * self % cw1 * fw * (rho*POW2(theta))/(POW2(dwall))          
         else
            destruction_Y =  - dimensionless % mu * self % cw1 * (rho*POW2(theta))/(POW2(dwall)) 
         end if 

      end subroutine Compute_DestructionTerm

      function Compute_g(self, theta, dwall, stilda) result(g)
         implicit none
         class(Spalart_Almaras_t), intent(inout) :: self
         real(kind=RP), intent(in)            :: theta
         real(kind=RP), intent(in)            :: dwall
         real(kind=RP), intent(in)            :: stilda
         real(kind=RP)                        :: g
         real(kind=RP)                        :: r
         
         if (stilda .EQ. 0.0_RP) then
            r = self % rmax
         else 
            r = min(dimensionless % mu * theta/(stilda * POW2(self % kappa) * POW2(dwall)), self % rmax )
         endif

         g = r + self % cw2 * ( (r**6.0_RP) - r)

      end function Compute_g

      function Compute_fw(self, g) result(fw)
         implicit none
         class(Spalart_Almaras_t), intent(inout) :: self
         real(kind=RP), intent(in)            :: g
         real(kind=RP)            :: fw

         fw = g * ((1.0_RP + self % cw3**6.0_RP) / (g**6.0_RP + self % cw3**6.0_RP))**(1.0_RP/6.0_RP)

      end function Compute_fw

!/////////////////////////////////////////////////////////
! compute additional source  terms

       subroutine Compute_AdditionalSourceTermKappa(self, rho, Theta_x, Theta_y, Theta_z, source_Kappa)
         implicit none
         class(Spalart_Almaras_t), intent(inout) :: self
         real(kind=RP), intent(in)            :: rho
         real(kind=RP), intent(in)            :: Theta_x
         real(kind=RP), intent(in)            :: Theta_y
         real(kind=RP), intent(in)            :: Theta_z
         real(kind=RP), intent(inout)           :: source_Kappa

         source_Kappa  = dimensionless % mu * self % cb2 * rho * (POW2(Theta_x) + POW2(Theta_y) + POW2(Theta_z)) / self % sigma_sa
               
      end subroutine Compute_AdditionalSourceTermKappa

   
end module SpallartAlmarasTurbulence