eos_density_specvol_derivs Subroutine

public pure subroutine eos_density_specvol_derivs(eos, T, S, p, rho, dsv_dt, dsv_ds)

eos_density_point AND eos_specvol_derivs at the same point from ONE evaluation of the active EOS. The isopycnal-slope and Redi builders need both (drho/dX = -rho^2 * dSV/dX, locally referenced); calling the two routines separately evaluated the EOS twice – under Roquet, two full roquet_spv_point calls, the first of which threw its derivatives away. Each branch uses the same expressions as the two routines it fuses, so rho, dsv_dt and dsv_ds are the numbers they return.

Arguments

Type IntentOptional Attributes Name
type(eos_t), intent(in) :: eos

Shared EOS handle (variant + scalar coeffs), by value.

real(kind=wp), intent(in) :: T

Potential temperature (degC) and practical salinity (PSU).

real(kind=wp), intent(in) :: S

Potential temperature (degC) and practical salinity (PSU).

real(kind=wp), intent(in) :: p

Pressure (Pa).

real(kind=wp), intent(out) :: rho

In-situ density (kg/m^3), as eos_density_point.

real(kind=wp), intent(out) :: dsv_dt

dSV/dT, dSV/dS, as eos_specvol_derivs.

real(kind=wp), intent(out) :: dsv_ds

dSV/dT, dSV/dS, as eos_specvol_derivs.


Calls

proc~~eos_density_specvol_derivs~~CallsGraph proc~eos_density_specvol_derivs eos_density_specvol_derivs proc~roquet_spv_point roquet_spv_point proc~eos_density_specvol_derivs->proc~roquet_spv_point

Called by

proc~~eos_density_specvol_derivs~~CalledByGraph proc~eos_density_specvol_derivs eos_density_specvol_derivs proc~ocean_slopes_pass_x ocean_slopes_pass_x proc~ocean_slopes_pass_x->proc~eos_density_specvol_derivs proc~ocean_slopes_pass_y ocean_slopes_pass_y proc~ocean_slopes_pass_y->proc~eos_density_specvol_derivs proc~redi_build_column redi_build_column proc~redi_build_column->proc~eos_density_specvol_derivs proc~ocean_slopes_compute_impl ocean_slopes_compute_impl proc~ocean_slopes_compute_impl->proc~ocean_slopes_pass_x proc~ocean_slopes_compute_impl->proc~ocean_slopes_pass_y proc~redi_face_coeffs redi_face_coeffs proc~redi_face_coeffs->proc~redi_build_column proc~ocean_slopes_compute ocean_slopes_compute proc~ocean_slopes_compute->proc~ocean_slopes_compute_impl proc~redi_calc_coeffs_x redi_calc_coeffs_x proc~redi_calc_coeffs_x->proc~redi_face_coeffs proc~redi_calc_coeffs_y redi_calc_coeffs_y proc~redi_calc_coeffs_y->proc~redi_face_coeffs proc~ocean_dyn_step_split ocean_dyn_step_split proc~ocean_dyn_step_split->proc~ocean_slopes_compute proc~redi_calc_coeffs redi_calc_coeffs proc~ocean_dyn_step_split->proc~redi_calc_coeffs proc~redi_calc_coeffs->proc~redi_calc_coeffs_x proc~redi_calc_coeffs->proc~redi_calc_coeffs_y proc~run_stage run_stage proc~run_stage->proc~ocean_slopes_compute proc~engine_step engine_step proc~engine_step->proc~ocean_dyn_step_split proc~ocean_dyn_step ocean_dyn_step proc~ocean_dyn_step->proc~run_stage

Variables

Type Visibility Attributes Name Initial
real(kind=wp), private :: T_sq
real(kind=wp), private :: alpha_0
real(kind=wp), private :: dlam_ds
real(kind=wp), private :: dlam_dt
real(kind=wp), private :: dp0_ds
real(kind=wp), private :: dp0_dt
real(kind=wp), private :: inv_p
real(kind=wp), private :: inv_p2
real(kind=wp), private :: lambda
real(kind=wp), private :: p_0
real(kind=wp), private :: p_plus_p0
real(kind=wp), private :: sv_roq

Source Code

   pure subroutine eos_density_specvol_derivs(eos, T, S, p, rho, dsv_dt, dsv_ds)
      !! `eos_density_point` AND `eos_specvol_derivs` at the same point from
      !! ONE evaluation of the active EOS.  The isopycnal-slope and Redi
      !! builders need both (`drho/dX = -rho^2 * dSV/dX`, locally
      !! referenced); calling the two routines separately evaluated the EOS
      !! twice -- under Roquet, two full `roquet_spv_point` calls, the first
      !! of which threw its derivatives away.  Each branch uses the same
      !! expressions as the two routines it fuses, so `rho`, `dsv_dt` and
      !! `dsv_ds` are the numbers they return.
      !$acc routine seq
      type(eos_t), intent(in) :: eos
         !! Shared EOS handle (variant + scalar coeffs), by value.
      real(wp), intent(in) :: T, S
         !! Potential temperature (degC) and practical salinity (PSU).
      real(wp), intent(in) :: p
         !! Pressure (Pa).
      real(wp), intent(out) :: rho
         !! In-situ density (kg/m^3), as `eos_density_point`.
      real(wp), intent(out) :: dsv_dt, dsv_ds
         !! dSV/dT, dSV/dS, as `eos_specvol_derivs`.

      real(wp) :: T_sq, alpha_0, p_0, lambda, p_plus_p0, inv_p, inv_p2
      real(wp) :: dp0_dt, dlam_dt, dp0_ds, dlam_ds
      real(wp) :: sv_roq

      if (eos%variant == EOS_VARIANT_ROQUET_SPV) then
         call roquet_spv_point(T, S, p, sv_roq, dsv_dt, dsv_ds)
         rho = 1.0_wp/sv_roq
      else if (eos%variant == EOS_VARIANT_WRIGHT_97) then
         T_sq = T*T
         alpha_0 = WRIGHT_A0 + WRIGHT_A1*T + WRIGHT_A2*S
         p_0 = WRIGHT_B0 + WRIGHT_B1*T + WRIGHT_B2*T_sq + WRIGHT_B3*T_sq*T + &
               WRIGHT_B4*S + WRIGHT_B5*S*T
         lambda = WRIGHT_C0 + WRIGHT_C1*T + WRIGHT_C2*T_sq + WRIGHT_C3*T_sq*T + &
                  WRIGHT_C4*S + WRIGHT_C5*S*T
         p_plus_p0 = p + p_0
         rho = p_plus_p0/(lambda + alpha_0*p_plus_p0)
         dp0_dt = WRIGHT_B1 + 2.0_wp*WRIGHT_B2*T + 3.0_wp*WRIGHT_B3*T_sq + &
                  WRIGHT_B5*S
         dlam_dt = WRIGHT_C1 + 2.0_wp*WRIGHT_C2*T + 3.0_wp*WRIGHT_C3*T_sq + &
                   WRIGHT_C5*S
         dp0_ds = WRIGHT_B4 + WRIGHT_B5*T
         dlam_ds = WRIGHT_C4 + WRIGHT_C5*T
         inv_p = 1.0_wp/p_plus_p0
         inv_p2 = inv_p*inv_p
         dsv_dt = WRIGHT_A1 + dlam_dt*inv_p - lambda*dp0_dt*inv_p2
         dsv_ds = WRIGHT_A2 + dlam_ds*inv_p - lambda*dp0_ds*inv_p2
      else
         rho = eos%rho0 + eos%beta_S*(S - eos%S_ref) - eos%alpha_T*(T - eos%T_ref)
         dsv_dt = eos%alpha_T/(eos%rho0*eos%rho0)
         dsv_ds = -eos%beta_S/(eos%rho0*eos%rho0)
      end if
   end subroutine eos_density_specvol_derivs