ge_models.f90 Source File


Source Code

module yaeos__models_ge
   !! Excess Gibbs Models.
   use yaeos__constants, only: pr, R
   use yaeos__models_base, only: BaseModel
   implicit none

   type, extends(BaseModel), abstract :: GeModel
      !! Excess Gibbs energy model.
   contains
      procedure(excess_gibbs), deferred :: excess_gibbs
      procedure :: ln_activity_coefficient => ln_activity_coefficient
      procedure :: excess_enthalpy => excess_enthalpy
      procedure :: excess_entropy => excess_entropy
   end type

   abstract interface
      subroutine excess_gibbs(self, n, T, Ge, GeT, GeT2, Gen, GeTn, Gen2)
         !! Calculate Excess Gibbs and its derivatives.
         !!
         import pr, GeModel
         class(GeModel), intent(in) :: self !! Model
         real(pr), intent(in) ::n(:) !! Moles vector
         real(pr), intent(in) :: T !! Temperature [K]
         real(pr), optional, intent(out) :: Ge !! Excess Gibbs free energy
         real(pr), optional, intent(out) :: GeT !! \(\frac{dG^E}{dT}\)
         real(pr), optional, intent(out) :: GeT2 !! \(\frac{d^2G^E}{dT^2}\)
         real(pr), optional, intent(out) :: Gen(size(n)) !! \(\frac{dG^E}{dn}\)
         real(pr), optional, intent(out) :: GeTn(size(n))
         !! \(\frac{d^2G^E}{dTdn}\)
         real(pr), optional, intent(out) :: Gen2(size(n), size(n))
         !! \(\frac{d^2G^E}{dn^2}\)
      end subroutine
   end interface

contains

   subroutine ln_activity_coefficient(self, n, T, lngamma, dlngammadT, dlngammadn)
      !! Calculate natural logarithm of activity coefficients.
      !!
      !! \[
      !!  \ln \gamma_i = \frac{1}{RT} \frac{\partial G^E}{\partial n_i}
      !! \]
      !!
      class(GeModel), intent(in) :: self !! Model
      real(pr), intent(in) :: n(:) !! Moles vector
      real(pr), intent(in) :: T !! Temperature [K]
      real(pr), optional, intent(out) :: lngamma(:)
      !! Natural logarithm of activity coefficients
      real(pr), optional, intent(out) :: dlngammadT(size(n))
      !! \(\frac{d\ln \gamma_i}{dT}\)
      real(pr), optional, intent(out) :: dlngammadn(size(n),size(n))
      !! \(\frac{d\ln \gamma_i}{dn_j}\)

      real(pr) :: Ge, Gen(size(n)), GeTn(size(n)), Gen2(size(n), size(n))

      logical :: tt, dt, dn

      tt = present(lngamma)
      dt = present(dlngammadT)
      dn = present(dlngammadn)

      if (tt .and. .not. dt .and. .not. dn) then
         call self%excess_gibbs(n, T, Ge=Ge, Gen=Gen)
      else if (.not. dn) then
         call self%excess_gibbs(n, T, Ge=Ge, Gen=Gen, GeTn=GeTn)
      else
         call self%excess_gibbs(n, T, Ge=Ge, Gen=Gen, GeTn=GeTn, Gen2=Gen2)
      end if

      if (tt) lngamma = Gen / (R * T)
      if (dt) dlngammadT = (GeTn - Gen / T) / (R * T)
      if (dn) dlngammadn = Gen2 / (R * T)
   end subroutine

   subroutine excess_enthalpy(self, n, T, He, HeT, Hen)
      !! Calculate Excess enthalpy and its derivatives.
      !!
      !! \[
      !! H^E = G^E - T \frac{\partial G^E}{\partial T}
      !! \]
      !!
      !! ## References
      !! [1] https://en.wikipedia.org/wiki/Gibbs%E2%80%93Helmholtz_equation
      !!
      class(GeModel), intent(in) :: self !! Model
      real(pr), intent(in) :: n(:) !! Moles vector
      real(pr), intent(in) :: T !! Temperature [K]
      real(pr), optional, intent(out) :: He !! Excess enthalpy
      real(pr), optional, intent(out) :: HeT !! \(\frac{dH^E}{dT}\)
      real(pr), optional, intent(out) :: Hen(:) !! \(\frac{dH^E}{dn}\)

      real(pr) :: Ge, GeT, GeT2, Gen(size(n)), GeTn(size(n))

      call self%excess_gibbs(&
         n, T, Ge=Ge, GeT=GeT, GeT2=GeT2, Gen=Gen, GeTn=GeTn &
         )

      if (present(He)) He = Ge - T*GeT
      if (present(HeT)) HeT = -T * GeT2
      if (present(Hen)) Hen = Gen - T*GeTn
   end subroutine excess_enthalpy

   subroutine excess_entropy(self, n, T, Se, SeT, Sen)
      !! Calculate Excess entropy and its derivatives.
      !!
      !! \[
      !! S^E = \frac{H^E - G^E}{T}
      !! \]
      !!
      class(GeModel), intent(in) :: self !! Model
      real(pr), intent(in) :: n(:) !! Moles vector
      real(pr), intent(in) :: T !! Temperature [K]
      real(pr), optional, intent(out) :: Se !! Excess entropy
      real(pr), optional, intent(out) :: SeT !! \(\frac{dS^E}{dT}\)
      real(pr), optional, intent(out) :: Sen(:) !! \(\frac{dS^E}{dn}\)

      real(pr) :: Ge, GeT, GeT2, GeTn(size(n))

      call self%excess_gibbs(n, T, Ge=Ge, GeT=GeT, GeT2=GeT2, GeTn=GeTn)

      if (present(Se)) Se = -GeT
      if (present(SeT)) SeT = -GeT2
      if (present(Sen)) Sen = -GeTn
   end subroutine excess_entropy
end module