PhysicsStorage_NS.f90 Source File


Source Code

#include "Includes.h"
      Module Physics_NSKeywordsModule
         IMPLICIT NONE
         INTEGER, PARAMETER :: KEYWORD_LENGTH = 132
         CHARACTER(LEN = KEYWORD_LENGTH), PARAMETER :: REFERENCE_TEMPERATURE_KEY      = "reference temperature (k)"
         CHARACTER(LEN = KEYWORD_LENGTH), PARAMETER :: REFERENCE_PRESSURE_KEY         = "reference pressure (pa)"
         CHARACTER(LEN = KEYWORD_LENGTH), PARAMETER :: MACH_NUMBER_KEY                = "mach number"
         CHARACTER(LEN = KEYWORD_LENGTH), PARAMETER :: REYNOLDS_NUMBER_KEY            = "reynolds number"
         CHARACTER(LEN = KEYWORD_LENGTH), PARAMETER :: PRANDTL_NUMBER_KEY             = "prandtl number"
         CHARACTER(LEN = KEYWORD_LENGTH), PARAMETER :: TURBULENT_PRANDTL_NUMBER_KEY   = "turbulent prandtl number"
         CHARACTER(LEN = KEYWORD_LENGTH), PARAMETER :: FROUDE_NUMBER_KEY              = "froude number"
         CHARACTER(LEN = KEYWORD_LENGTH), PARAMETER :: GRAVITY_DIRECTION_KEY          = "gravity direction"
         CHARACTER(LEN = KEYWORD_LENGTH), PARAMETER :: AOA_THETA_KEY                  = "aoa theta"
         CHARACTER(LEN = KEYWORD_LENGTH), PARAMETER :: AOA_PHI_KEY                    = "aoa phi"
         CHARACTER(LEN = KEYWORD_LENGTH), PARAMETER :: FLOW_EQUATIONS_KEY             = "flow equations"
         CHARACTER(LEN = KEYWORD_LENGTH), PARAMETER :: LESMODEL_KEY                   = "les model"
         CHARACTER(LEN = KEYWORD_LENGTH), PARAMETER :: COMPUTE_GRADIENTS_KEY          = "compute gradients"
         CHARACTER(LEN = KEYWORD_LENGTH), PARAMETER :: SUTHERLAND_TEMPERATURE_KEY     = "sutherland temperature"
         CHARACTER(LEN = KEYWORD_LENGTH), PARAMETER :: SUTHERLAND_REF_TEMPERATURE_KEY = "sutherland reference temperature"

         CHARACTER(LEN=KEYWORD_LENGTH), DIMENSION(2) :: physics_NSKeywords = [MACH_NUMBER_KEY, FLOW_EQUATIONS_KEY]

         !PARTICLES
         CHARACTER(LEN=KEYWORD_LENGTH), PARAMETER :: particlesKey             = "lagrangian particles"
         CHARACTER(LEN=KEYWORD_LENGTH), PARAMETER :: numberOfParticlesKey     = "number of particles"
         CHARACTER(LEN=KEYWORD_LENGTH), PARAMETER :: particlesPerParcelKey    = "particles per parcel"
         CHARACTER(LEN=KEYWORD_LENGTH), PARAMETER :: sourceTermKey            = "high order particles source term"
         CHARACTER(LEN=KEYWORD_LENGTH), PARAMETER :: STOKES_NUMBER_PART_KEY   = "stokes number"
         CHARACTER(LEN=KEYWORD_LENGTH), PARAMETER :: GAMMA_PART_KEY           = "gamma"
         CHARACTER(LEN=KEYWORD_LENGTH), PARAMETER :: PHI_M_PART_KEY           = "phi_m"
         CHARACTER(LEN=KEYWORD_LENGTH), PARAMETER :: I0_PART_KEY              = "radiation source"
         CHARACTER(LEN=KEYWORD_LENGTH), PARAMETER :: MIN_BOX_KEY              = "minimum box"
         CHARACTER(LEN=KEYWORD_LENGTH), PARAMETER :: MAX_BOX_KEY              = "maximum box"
         CHARACTER(LEN=KEYWORD_LENGTH), PARAMETER :: BC_BOX_KEY               = "bc box"
         CHARACTER(LEN=KEYWORD_LENGTH), PARAMETER :: PART_FILE_KEY            = "particles file"
         CHARACTER(LEN=KEYWORD_LENGTH), PARAMETER :: PART_LOG_FILE_KEY        = "vel and temp from file"
         CHARACTER(LEN=KEYWORD_LENGTH), PARAMETER :: PART_LOG_INJ_KEY         = "injection"
         CHARACTER(LEN=KEYWORD_LENGTH), PARAMETER :: PART_INJ_KEY             = "particles injection"
         CHARACTER(LEN=KEYWORD_LENGTH), PARAMETER :: PART_NUMB_PER_STEP_KEY   = "particles per step"
         CHARACTER(LEN=KEYWORD_LENGTH), PARAMETER :: PART_PERIOD_KEY          = "particles iter period"
         CHARACTER(LEN=KEYWORD_LENGTH), PARAMETER :: INJ_VEL_KEY              = "particles injection velocity"
         CHARACTER(LEN=KEYWORD_LENGTH), PARAMETER :: INJ_TEMP_KEY             = "particles injection temperature"

      END MODULE Physics_NSKeywordsModule
!
!////////////////////////////////////////////////////////////////////////
!
!    ******
     MODULE PhysicsStorage_NS
!    ******
!
     USE SMConstants
     use FluidData_NS
     use FileReadingUtilities, only: getRealArrayFromString

     IMPLICIT NONE

     private
     public    flowIsNavierStokes, NCONS, NGRAD
     public    IRHO, IRHOU, IRHOV, IRHOW, IRHOE
     public    NPRIM, IPIRHO, IPU, IPV, IPW, IPP, IPT, IPA2
     public    TemperatureReNormalization_Sutherland, S_div_TRef_Sutherland
     public    computeGradients

     public    ConstructPhysicsStorage_NS, DestructPhysicsStorage_NS, DescribePhysicsStorage_NS
     public    CheckPhysicsNSInputIntegrity
     public    GRADVARS_STATE, GRADVARS_ENTROPY, GRADVARS_ENERGY
     public    grad_vars, SetGradientVariables
!
!    ----------------------------
!    Either NavierStokes or Euler
!    ----------------------------
!
     logical, protected :: flowIsNavierStokes = .true.
     logical, protected :: computeGradients   = .true.
!
!    --------------------------
!!   The sizes of the NS system
!    --------------------------
!
     INTEGER, PARAMETER :: NCONS = 5, NGRAD = 5
!
!    -------------------------------------------
!!   The positions of the conservative variables
!    -------------------------------------------
!
     INTEGER, PARAMETER       :: IRHO = 1 , IRHOU = 2 , IRHOV = 3 , IRHOW = 4 , IRHOE = 5
!
!    ----------------------------------------
!!   The positions of the primitive variables
!    ----------------------------------------
!
     INTEGER, PARAMETER       :: NPRIM = 7
     INTEGER, PARAMETER       :: IPIRHO = 1, IPU = 2, IPV = 3, IPW = 4, IPP = 5, IPT = 6, IPA2 = 7
!
     real(kind=RP), protected :: TRef_Sutherland   ! Sutherland's reference temperature
     real(kind=RP), protected :: S_Sutherland      ! Sutherland's temperature
     real(kind=RP), protected :: TemperatureReNormalization_Sutherland ! TRef/SutherlandsTRef
     real(kind=RP), protected :: S_div_Tref_Sutherland
!
!    --------------------------------
!    Choice of the gradient variables
!    --------------------------------
!
     enum, bind(C)
        enumerator :: GRADVARS_STATE, GRADVARS_ENTROPY, GRADVARS_ENERGY
     end enum
     integer, protected :: grad_vars = GRADVARS_STATE

!
!    ------------------------------
!    Thermodynamic specs of the Air
!    ------------------------------
!
     type(Thermodynamics_t), target, private :: ThermodynamicsAir = Thermodynamics_t( &
                                                              "Air", & ! Name
                                                      287.15_RP, & ! R  ! J / (kg * °K)
                                                         1.4_RP, & ! gamma
                                                   sqrt(1.4_RP), & ! sqrtGamma
                                                1.4_RP - 1.0_RP, & ! gammaMinus1
                                     (1.4_RP - 1.0_RP) / 2.0_RP, & ! gammaMinus1Div2
                                     (1.4_RP + 1.0_RP) / 2.0_RP, & ! gammaPlus1Div2
                    (1.4_RP - 1.0_RP) / (2.0_RP * sqrt(1.4_RP)), & ! gammaMinus1Div2sg
                          (1.4_RP - 1.0_RP) / (2.0_RP * 1.4_RP), & ! gammaMinus1Div2g
                                     2.0_RP / (1.4_RP + 1.0_RP), & ! InvGammaPlus1Div2
                                     1.0_RP / (1.4_RP - 1.0_RP), & ! InvGammaMinus1
                                                1.0_RP / 1.4_RP, & ! InvGamma
                                   1.4_RP / ( 1.4_RP - 1.0_RP ), & ! gammaDivGammaMinus1
                       287.15_RP * 1.4_RP / ( 1.4_RP - 1.0_RP ), & ! cp
                                287.15_RP / ( 1.4_RP - 1.0_RP ), & ! cv
                                                        0.0_RP  & ! Bulk viscosity ratio
)
!
!    ========
     CONTAINS
!    ========
!
!     ///////////////////////////////////////////////////////
!
!     --------------------------------------------------
!!    Constructor: Define default values for the physics
!!    variables.
!     --------------------------------------------------
!
      SUBROUTINE ConstructPhysicsStorage_NS( controlVariables, Lref, timeref, success )
      USE FTValueDictionaryClass
      USE Physics_NSKeywordsModule
      use Utilities, only: toLower, almostEqual
!
!     ---------
!     Arguments
!     ---------
!
      TYPE(FTValueDictionary)      :: controlVariables
      real(kind=RP), intent(in)    :: Lref
      real(kind=RP), intent(out)   :: timeref
      LOGICAL                      :: success
!
!     ---------------
!     Local variables
!     ---------------
!
      CHARACTER(LEN=KEYWORD_LENGTH) :: keyword
      type(Thermodynamics_t), pointer  :: thermodynamics_
      type(RefValues_t)                :: refValues_
      type(Dimensionless_t)            :: dimensionless_
      real(kind=RP), allocatable       :: array(:)

!
!     --------------------
!     Collect input values
!     --------------------
!
      success = .TRUE.
      CALL CheckPhysicsNSInputIntegrity(controlVariables,success)
      IF(.NOT. success) RETURN
!
!
!     ---------------------
!     Set the gas to be air
!     ---------------------
!
      thermodynamics_ => thermodynamicsAir
!
!     ------------------------
!     Dimensionless quantities
!     ------------------------
!
      dimensionless_ % cp = thermodynamics_ % gamma * thermodynamics_ % InvGammaMinus1
      dimensionless_ % cv = thermodynamics_ % InvGammaMinus1
      dimensionless_ % Mach = controlVariables % doublePrecisionValueForKey(MACH_NUMBER_KEY)

      if ( controlVariables % ContainsKey(PRANDTL_NUMBER_KEY) ) then
         dimensionless_ % Pr   = controlVariables % doublePrecisionValueForKey(PRANDTL_NUMBER_KEY)
      else
         dimensionless_ % Pr = 0.72_RP
      end if
      if ( controlVariables % ContainsKey(TURBULENT_PRANDTL_NUMBER_KEY) ) then
         dimensionless_ % Prt   = controlVariables % doublePrecisionValueForKey(TURBULENT_PRANDTL_NUMBER_KEY)
      else
         dimensionless_ % Prt = dimensionless_ % Pr
      end if
!
!     *********************
!     Select flow equations
!     *********************
!
      keyword = controlVariables % stringValueForKey(FLOW_EQUATIONS_KEY,KEYWORD_LENGTH)
      CALL toLower(keyword)

      IF ( keyword == "euler" )     THEN
         flowIsNavierStokes = .FALSE.
         dimensionless_ % Re = 0.0_RP
         dimensionless_ % mu = 0.0_RP
         dimensionless_ % kappa = 0.0_RP

      ELSE
         flowIsNavierStokes = .TRUE.
!
!        ----------------------------
!        Look for the Reynolds number
!        ----------------------------
!
         IF ( controlVariables % containsKey(REYNOLDS_NUMBER_KEY) )     THEN
            dimensionless_ % Re = controlVariables % doublePrecisionValueForKey(REYNOLDS_NUMBER_KEY)

         ELSE
            PRINT *, "Input file is missing entry for keyword: ", REYNOLDS_NUMBER_KEY
            success = .FALSE.
            RETURN

         END IF
!
!        ------------------------------------------------
!        Set molecular viscosity and thermal conductivity
!        ------------------------------------------------
!
         if ( .not. almostEqual(dimensionless_ % Re, 0.0_RP) ) then
            dimensionless_ % mu   = 1.0_RP / dimensionless_ % Re
            dimensionless_ % kappa = 1.0_RP / ( thermodynamics_ % gammaMinus1 * &
                                                 POW2( dimensionless_ % Mach) * &
                                         dimensionless_ % Re * dimensionless_ % Pr )
         else
            dimensionless_ % mu = 0.0_RP
            dimensionless_ % kappa = 0.0_RP

         end if

         dimensionless_ % mu_to_kappa = 1.0_RP / (thermodynamics_ % gammaMinus1*POW2(dimensionless_ % Mach)* dimensionless_ % Pr)
      END IF
!
!     **************************************
!     Check if state gradients are requested
!     **************************************
!
      if ( controlVariables % containsKey(COMPUTE_GRADIENTS_KEY) ) then
!
!        Do not compute gradients if Euler equations are used and it is specified in the control file
!        --------------------------------------------------------------------------------------------
         if ( .not. flowIsNavierStokes ) then
            if ( .not. controlVariables % logicalValueForKey(COMPUTE_GRADIENTS_KEY) ) then
               computeGradients = .false.

            end if
         end if
      else
!
!        Do not compute gradients if Euler equations and the default option is selected
!        ------------------------------------------------------------------------------
         if ( .not. flowIsNavierStokes ) then
            computeGradients = .false.

         end if
      end if

      dimensionless_ % gammaM2 = thermodynamics_ % gamma * POW2( dimensionless_ % Mach )
!
!     ********************
!     Set reference values
!     ********************
!
      if ( controlVariables % ContainsKey(REFERENCE_TEMPERATURE_KEY) ) then
         refValues_ % T = controlVariables % DoublePrecisionValueForKey(REFERENCE_TEMPERATURE_KEY)
      else
         refValues_ % T = 520.0_RP*5.0_RP/9.0_RP     ! ≃ 288.88 K
      end if

      if ( controlVariables % ContainsKey(REFERENCE_PRESSURE_KEY) ) then
         refValues_ % rho = controlVariables % DoublePrecisionValueForKey(REFERENCE_PRESSURE_KEY) / (thermodynamics_ % R * refValues_ % T)
      else
         refValues_ % rho = 101325.0_RP / (thermodynamics_ % R * refValues_ % T)
      end if

      refValues_ % V =   dimensionless_ % Mach &
                       * sqrt( thermodynamics_ % gamma * thermodynamics_ % R * refValues_ % T )

      refValues_ % p = refValues_ % rho * POW2( refValues_ % V )

      if ( flowIsNavierStokes ) then
         refValues_ % mu = refValues_ % rho * refValues_ % V * Lref * dimensionless_ % mu
         refValues_ % kappa = refValues_ % mu * thermodynamics_ % cp / dimensionless_ % Pr

      else
         refValues_ % mu = 0.0_RP
         refValues_ % kappa = 0.0_RP

      end if

      timeref = Lref / refValues_ % V
!
!     *******************************************
!     Set the Froude number and gravity direction
!     *******************************************
!
      if ( controlVariables % ContainsKey(FROUDE_NUMBER_KEY) ) then
         dimensionless_ % Fr = controlVariables % DoublePrecisionValueForKey(FROUDE_NUMBER_KEY)

      else
!
!        Default Froude number: earth's gravity
!        --------------------------------------
         dimensionless_ % Fr = refValues_ % V / sqrt(9.81_RP * Lref)

      end if

      if ( controlVariables % ContainsKey(GRAVITY_DIRECTION_KEY) ) then
         allocate(array(1:3))
         array = getRealArrayFromString( controlVariables % StringValueForKey(GRAVITY_DIRECTION_KEY,&
                                                                             KEYWORD_LENGTH))
         dimensionless_ % gravity_dir = array(1:3)

         if ( norm2(dimensionless_ % gravity_dir) < epsilon(1.0_RP)*10.0_RP ) then
!
!           Disable gravity
!           ---------------
            dimensionless_ % gravity_dir = 0.0_RP
            dimensionless_ % invFr2 = 0.0_RP
            dimensionless_ % Fr = huge(1.0_RP)
         else
            dimensionless_ % gravity_dir = dimensionless_ % gravity_dir / norm2(dimensionless_ % gravity_dir)
            dimensionless_ % invFr2 = 1.0_RP / POW2(dimensionless_ % Fr)

         end if
      else
         if ( controlVariables % ContainsKey(FROUDE_NUMBER_KEY) ) then
            print*, "When specifying a Froude number, the gravity direction must be specified"
            print*, "Gravity direction = [x,y,z]"
            errorMessage(STD_OUT)
            error stop

         else
!
!           Gravity is disabled
!           -------------------
            dimensionless_ % gravity_dir = 0.0_RP
            dimensionless_ % Fr = huge(1.0_RP)
            dimensionless_ % invFr2 = 0.0_RP

         end if
      end if
!
!     **********
!     LES Models
!     **********
!
      if ( controlVariables % containsKey(LESMODEL_KEY)) then
         if ( controlVariables % stringValueForKey(LESMODEL_KEY,4) .ne. "none") then
!
!           Enable NS fluxes
!           ----------------
            flowIsNavierStokes = .true.
            computeGradients = .true.

         end if
      end if
!
!     ***************
!     Angle of attack
!     ***************
!
      IF ( controlVariables % containsKey(AOA_PHI_KEY) )     THEN
         refValues_ % AOAPhi = controlVariables % doublePrecisionValueForKey(AOA_PHI_KEY)

      ELSE
!
!        Phi angle of attack is zero by default
!        --------------------------------------
         refValues_ % AOAPhi = 0.0_RP

      END IF

      IF ( controlVariables % containsKey(AOA_THETA_KEY) )     THEN
         refValues_ % AOATheta = controlVariables % doublePrecisionValueForKey(AOA_THETA_KEY)

      ELSE
!
!        Theta angle of attack is zero by default
!        ----------------------------------------
         refValues_ % AOATheta = 0.0_RP

      END IF
!
!     **************************
!     Sutherland's law constants
!     **************************
!
      if ( controlVariables % ContainsKey(SUTHERLAND_TEMPERATURE_KEY) ) then
         S_Sutherland = controlVariables % DoublePrecisionValueForKey(SUTHERLAND_TEMPERATURE_KEY)
      else
         S_Sutherland = 198.6_RP*5.0_RP/9.0_RP ! ≃ 110.4
      end if

      if ( controlVariables % ContainsKey(SUTHERLAND_REF_TEMPERATURE_KEY) ) then
         TRef_Sutherland = controlVariables % DoublePrecisionValueForKey(SUTHERLAND_REF_TEMPERATURE_KEY)
      else
         TRef_Sutherland = refValues_ % T
      end if

      S_div_TRef_Sutherland = S_Sutherland / TRef_Sutherland
      TemperatureReNormalization_Sutherland = refValues_ % T / TRef_Sutherland
!
!     **********************************************************************
!     Set the global (proteted) thermodynamics, dimensionless, and refValues
!     **********************************************************************
!
      call setThermodynamics( thermodynamics_ )
      call setDimensionless( dimensionless_ )
      call setRefValues( refValues_ )

      END SUBROUTINE ConstructPhysicsStorage_NS
!
!     ///////////////////////////////////////////////////////
!
!     -------------------------------------------------
!!    Destructor: Does nothing for this storage
!     -------------------------------------------------
!
      SUBROUTINE DestructPhysicsStorage_NS

      END SUBROUTINE DestructPhysicsStorage_NS
!
!     //////////////////////////////////////////////////////
!
!     -----------------------------------------
!!    Descriptor: Shows the gathered data
!     -----------------------------------------
!
      SUBROUTINE DescribePhysicsStorage_NS()
         USE Headers
         use MPI_Process_Info
         IMPLICIT NONE
         real(kind=RP)  :: pRef

         if ( .not. MPI_Process % isRoot ) return

         pRef = thermodynamics % R * refValues % rho * refValues % T

         write(STD_OUT,'(/,/)')
         if (flowIsNavierStokes) then
            call Section_Header("Loading Navier-Stokes physics")
         else
            call Section_Header("Loading Euler physics")
         end if

         write(STD_OUT,'(/)')
         call SubSection_Header("Fluid data")
         write(STD_OUT,'(30X,A,A22,A10)') "->" , "Gas: " , "Air"
         write(STD_OUT,'(30X,A,A22,F10.3,A)') "->" , "State constant: " , thermodynamics % R, " I.S."
         write(STD_OUT,'(30X,A,A22,F10.3)') "->" , "Specific heat ratio: " , thermodynamics % gamma

         write(STD_OUT,'(/)')
         call SubSection_Header("Reference quantities")
         write(STD_OUT,'(30X,A,A30,F10.3,A)') "->" , "Reference Temperature: " , refValues % T, " K."
         write(STD_OUT,'(30X,A,A30,F10.3,A)') "->" , "Reference pressure: " , pRef, " Pa."
         write(STD_OUT,'(30X,A,A30,F10.3,A)') "->" , "Reference density: " , refValues % rho , " kg/m^3."
         write(STD_OUT,'(30X,A,A30,F10.3,A)') "->" , "Reference velocity: " , refValues % V , " m/s."

         if ( flowIsNavierStokes ) then
            write(STD_OUT,'(30X,A,A30,1pG10.3,A)') "->" , "Reference viscosity: ",refValues % mu , " Pa·s."
            write(STD_OUT,'(30X,A,A30,1pG10.3,A)') "->" , "Reference conductivity: ", refValues % kappa, " W/(m·K)."
         end if

         write(STD_OUT,'(/)')
         call SubSection_Header("Dimensionless quantities")
         write(STD_OUT,'(30X,A,A27,F10.3)') "->" , "Mach number: " , dimensionless % Mach
         if ( flowIsNavierStokes ) then
            write(STD_OUT,'(30X,A,A27,ES10.3)') "->" , "Reynolds number: " , dimensionless % Re
            write(STD_OUT,'(30X,A,A27,F10.3)') "->" , "Prandtl number: " , dimensionless % Pr
            write(STD_OUT,'(30X,A,A27,F10.3)') "->" , "Turbulent Prandtl number: " , dimensionless % Prt
         end if

         write(STD_OUT,'(30X,A,A27,F10.3)') "->" , "Froude number: " , dimensionless % Fr
         write(STD_OUT,'(30X,A,A27,A,F4.1,A,F4.1,A,F4.1,A)') "->" , "Gravity direction: ","[", &
                                                   dimensionless % gravity_dir(1), ", ", &
                                                   dimensionless % gravity_dir(2), ", ", &
                                                   dimensionless % gravity_dir(3), "]"

      END SUBROUTINE DescribePhysicsStorage_NS
!
!////////////////////////////////////////////////////////////////////////
!
      SUBROUTINE CheckPhysicsNSInputIntegrity( controlVariables, success )
         USE FTValueDictionaryClass
         USE Physics_NSKeywordsModule
         IMPLICIT NONE
!
!        ---------
!        Arguments
!        ---------
!
         TYPE(FTValueDictionary) :: controlVariables
         LOGICAL                 :: success
!
!        ---------------
!        Local variables
!        ---------------
!
         CLASS(FTObject), POINTER :: obj
         INTEGER                  :: i
         success = .TRUE.

         DO i = 1, SIZE(physics_NSKeywords)
            obj => controlVariables % objectForKey(physics_NSKeywords(i))
            IF ( .NOT. ASSOCIATED(obj) )     THEN
               PRINT *, "Input file is missing entry for keyword: ",physics_NSKeywords(i)
               success = .FALSE.
            END IF
         END DO

      END SUBROUTINE CheckPhysicsNSInputIntegrity

      subroutine SetGradientVariables(grad_vars_)
         implicit none
         integer, intent(in)  :: grad_vars_

         select case(grad_vars_)
         case(GRADVARS_STATE, GRADVARS_ENTROPY, GRADVARS_ENERGY)
            grad_vars = grad_vars_
         case default
            print*, "Unrecognized option"
            errorMessage(STD_OUT)
            error stop
         end select

      end subroutine SetGradientVariables

!
!    **********
     END MODULE PhysicsStorage_NS
!    **********