compute_partition_functions Subroutine

private pure subroutine compute_partition_functions(total_mass, moments, frequencies, n_freqs, temperature, pressure, sigma, is_linear, q_trans, q_rot, q_vib)

Compute partition functions for translation, rotation, and vibration.

Arguments

Type IntentOptional Attributes Name
real(kind=dp), intent(in) :: total_mass

Total mass in amu

real(kind=dp), intent(in) :: moments(3)

Principal moments in amu*Angstrom^2

real(kind=dp), intent(in) :: frequencies(:)

Frequencies in cm^-1

integer, intent(in) :: n_freqs

Number of frequencies

real(kind=dp), intent(in) :: temperature

Temperature in K

real(kind=dp), intent(in) :: pressure

Pressure in atm

integer, intent(in) :: sigma

Symmetry number

logical, intent(in) :: is_linear

True if linear molecule

real(kind=dp), intent(out) :: q_trans

Translational partition function

real(kind=dp), intent(out) :: q_rot

Rotational partition function

real(kind=dp), intent(out) :: q_vib

Vibrational partition function


Called by

proc~~compute_partition_functions~~CalledByGraph proc~compute_partition_functions compute_partition_functions proc~compute_thermochemistry compute_thermochemistry proc~compute_thermochemistry->proc~compute_partition_functions proc~compute_mbe compute_mbe proc~compute_mbe->proc~compute_thermochemistry proc~print_vibrational_analysis print_vibrational_analysis proc~compute_mbe->proc~print_vibrational_analysis proc~gmbe_pie_coordinator gmbe_pie_coordinator proc~gmbe_pie_coordinator->proc~compute_thermochemistry proc~gmbe_pie_coordinator->proc~print_vibrational_analysis proc~hessian_coordinator hessian_coordinator proc~hessian_coordinator->proc~compute_thermochemistry proc~hessian_coordinator->proc~print_vibrational_analysis proc~print_vibrational_analysis->proc~compute_thermochemistry proc~serial_gmbe_pie_processor serial_gmbe_pie_processor proc~serial_gmbe_pie_processor->proc~compute_thermochemistry proc~serial_gmbe_pie_processor->proc~print_vibrational_analysis proc~unfragmented_calculation unfragmented_calculation proc~unfragmented_calculation->proc~compute_thermochemistry proc~unfragmented_calculation->proc~print_vibrational_analysis interface~hessian_coordinator hessian_coordinator interface~hessian_coordinator->proc~hessian_coordinator interface~unfragmented_calculation unfragmented_calculation interface~unfragmented_calculation->proc~unfragmented_calculation proc~compute_gmbe compute_gmbe proc~compute_gmbe->proc~print_vibrational_analysis proc~global_coordinator global_coordinator proc~global_coordinator->proc~compute_mbe proc~gmbe_run_distributed gmbe_context_t%gmbe_run_distributed proc~gmbe_run_distributed->proc~gmbe_pie_coordinator proc~gmbe_run_serial gmbe_context_t%gmbe_run_serial proc~gmbe_run_serial->proc~serial_gmbe_pie_processor proc~serial_fragment_processor serial_fragment_processor proc~serial_fragment_processor->proc~compute_mbe interface~global_coordinator global_coordinator interface~global_coordinator->proc~global_coordinator interface~serial_fragment_processor serial_fragment_processor interface~serial_fragment_processor->proc~serial_fragment_processor proc~distributed_unfragmented_hessian distributed_unfragmented_hessian proc~distributed_unfragmented_hessian->interface~hessian_coordinator proc~run_unfragmented_calculation run_unfragmented_calculation proc~run_unfragmented_calculation->interface~unfragmented_calculation interface~distributed_unfragmented_hessian distributed_unfragmented_hessian interface~distributed_unfragmented_hessian->proc~distributed_unfragmented_hessian proc~mbe_run_distributed mbe_context_t%mbe_run_distributed proc~mbe_run_distributed->interface~global_coordinator proc~mbe_run_serial mbe_context_t%mbe_run_serial proc~mbe_run_serial->interface~serial_fragment_processor proc~run_calculation run_calculation proc~run_calculation->proc~run_unfragmented_calculation

Variables

Type Visibility Attributes Name Initial
real(kind=dp), private :: P_pa
real(kind=dp), private :: T
real(kind=dp), private :: V_molar
integer, private :: i
real(kind=dp), private :: lambda
real(kind=dp), private :: mass_kg
real(kind=dp), private :: theta_rot(3)
real(kind=dp), private :: u

Source Code

   pure subroutine compute_partition_functions(total_mass, moments, frequencies, n_freqs, &
                                               temperature, pressure, sigma, is_linear, &
                                               q_trans, q_rot, q_vib)
      !! Compute partition functions for translation, rotation, and vibration.
      real(dp), intent(in) :: total_mass        !! Total mass in amu
      real(dp), intent(in) :: moments(3)        !! Principal moments in amu*Angstrom^2
      real(dp), intent(in) :: frequencies(:)    !! Frequencies in cm^-1
      integer, intent(in) :: n_freqs            !! Number of frequencies
      real(dp), intent(in) :: temperature       !! Temperature in K
      real(dp), intent(in) :: pressure          !! Pressure in atm
      integer, intent(in) :: sigma              !! Symmetry number
      logical, intent(in) :: is_linear          !! True if linear molecule
      real(dp), intent(out) :: q_trans          !! Translational partition function
      real(dp), intent(out) :: q_rot            !! Rotational partition function
      real(dp), intent(out) :: q_vib            !! Vibrational partition function

      real(dp) :: mass_kg, T, P_pa
      real(dp) :: lambda, V_molar
      real(dp) :: theta_rot(3), u
      integer :: i

      T = temperature
      mass_kg = total_mass*AMU_TO_KG
      P_pa = pressure*ATM_TO_PA

      ! Translational partition function: q_trans = (2*pi*m*k*T/h^2)^(3/2) * V
      ! where V = kT/P for ideal gas (per molecule)
      lambda = H_SI/sqrt(2.0_dp*PI*mass_kg*KB_SI*T)  ! thermal de Broglie wavelength
      V_molar = KB_SI*T/P_pa  ! volume per molecule
      q_trans = V_molar/(lambda**3)

      ! Rotational partition function
      ! theta_rot = h^2 / (8*pi^2*I*k_B) = ROTTEMP_AMUA2_TO_K / I (for I in amu*Angstrom^2)
      do i = 1, 3
         if (moments(i) > 1.0e-6_dp) then
            theta_rot(i) = ROTTEMP_AMUA2_TO_K/moments(i)
         else
            theta_rot(i) = 0.0_dp
         end if
      end do

      if (is_linear) then
         ! Linear: q_rot = T / (sigma * theta_rot)
         if (theta_rot(3) > 0.0_dp) then
            q_rot = T/(real(sigma, dp)*theta_rot(3))
         else
            q_rot = 1.0_dp
         end if
      else
         ! Nonlinear: q_rot = sqrt(pi) * T^(3/2) / (sigma * sqrt(theta_A * theta_B * theta_C))
         if (theta_rot(1) > 0.0_dp .and. theta_rot(2) > 0.0_dp .and. theta_rot(3) > 0.0_dp) then
            q_rot = sqrt(PI)*(T**1.5_dp)/ &
                    (real(sigma, dp)*sqrt(theta_rot(1)*theta_rot(2)*theta_rot(3)))
         else
            q_rot = 1.0_dp
         end if
      end if

      ! Vibrational partition function: q_vib = Product_i [1 / (1 - exp(-u_i))]
      ! where u_i = h*nu/(k*T) = theta_vib/T = 1.4388 * nu(cm^-1) / T
      q_vib = 1.0_dp
      do i = 1, n_freqs
         if (frequencies(i) > 10.0_dp) then  ! Skip near-zero frequencies
            u = CM1_TO_KELVIN*frequencies(i)/T
            if (u < 100.0_dp) then  ! Avoid overflow
               q_vib = q_vib/(1.0_dp - exp(-u))
            end if
         end if
      end do

   end subroutine compute_partition_functions