Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(*)Use cuberoot in ePBL_column #541

Merged
merged 3 commits into from
Feb 5, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 77 additions & 28 deletions src/parameterizations/vertical/MOM_energetic_PBL.F90
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use MOM_forcing_type, only : forcing
use MOM_grid, only : ocean_grid_type
use MOM_interface_heights, only : thickness_to_dz
use MOM_intrinsic_functions, only : cuberoot
use MOM_string_functions, only : uppercase
use MOM_unit_scaling, only : unit_scale_type
use MOM_variables, only : thermo_var_ptrs
Expand Down Expand Up @@ -161,7 +162,10 @@
integer :: answer_date !< The vintage of the order of arithmetic and expressions in the ePBL
!! calculations. Values below 20190101 recover the answers from the
!! end of 2018, while higher values use updated and more robust forms
!! of the same expressions.
!! of the same expressions. Values below 20240101 use A**(1./3.) to
!! estimate the cube root of A in several expressions, while higher
!! values use the integer root function cuberoot(A) and therefore
!! can work with scaled variables.
logical :: orig_PE_calc !< If true, the ePBL code uses the original form of the
!! potential energy change code. Otherwise, it uses a newer version
!! that can work with successive increments to the diffusivity in
Expand Down Expand Up @@ -335,8 +339,10 @@
mixvel, & ! A turbulent mixing velocity [Z T-1 ~> m s-1].
mixlen, & ! A turbulent mixing length [Z ~> m].
SpV_dt ! Specific volume interpolated to interfaces divided by dt or 1.0 / (dt * Rho0)
! times conversion factors in [m3 Z-3 R-1 T2 s-3 ~> m3 kg-1 s-1],
! used to convert local TKE into a turbulence velocity cubed.
! times conversion factors for answer dates before 20240101 in
! [m3 Z-3 R-1 T2 s-3 ~> m3 kg-1 s-1] or without the convsersion factors for
! answer dates of 20240101 and later in [R-1 T-1 ~> m3 kg-1 s-1], used to
! convert local TKE into a turbulence velocity cubed.
real :: h_neglect ! A thickness that is so small it is usually lost
! in roundoff and can be neglected [H ~> m or kg m-2].

Expand All @@ -348,6 +354,8 @@
real :: I_rho ! The inverse of the Boussinesq reference density times a ratio of scaling
! factors [Z L-1 R-1 ~> m3 kg-1]
real :: I_dt ! The Adcroft reciprocal of the timestep [T-1 ~> s-1]
real :: I_rho0dt ! The inverse of the Boussinesq reference density times the time
! step [R-1 T-1 ~> m3 kg-1 s-1]
real :: B_Flux ! The surface buoyancy flux [Z2 T-3 ~> m2 s-3]
real :: MLD_io ! The mixed layer depth found by ePBL_column [Z ~> m]

Expand All @@ -374,6 +382,7 @@
h_neglect = GV%H_subroundoff
I_rho = US%L_to_Z * GV%H_to_Z * GV%RZ_to_H ! == US%L_to_Z / GV%Rho0 ! This is not used when fully non-Boussinesq.
I_dt = 0.0 ; if (dt > 0.0) I_dt = 1.0 / dt
I_rho0dt = 1.0 / (GV%Rho0 * dt) ! This is not used when fully non-Boussinesq.

! Zero out diagnostics before accumulation.
if (CS%TKE_diagnostics) then
Expand Down Expand Up @@ -403,9 +412,15 @@
! Set the inverse density used to translating local TKE into a turbulence velocity
SpV_dt(:) = 0.0
if ((dt > 0.0) .and. GV%Boussinesq .or. .not.allocated(tv%SpV_avg)) then
do K=1,nz+1
SpV_dt(K) = (US%Z_to_m**3*US%s_to_T**3) / (dt*GV%Rho0)
enddo
if (CS%answer_date < 20240101) then
do K=1,nz+1
SpV_dt(K) = (US%Z_to_m**3*US%s_to_T**3) / (dt*GV%Rho0)

Check warning on line 417 in src/parameterizations/vertical/MOM_energetic_PBL.F90

View check run for this annotation

Codecov / codecov/patch

src/parameterizations/vertical/MOM_energetic_PBL.F90#L416-L417

Added lines #L416 - L417 were not covered by tests
enddo
else
do K=1,nz+1
SpV_dt(K) = I_rho0dt
enddo
endif
endif

! Determine the initial mech_TKE and conv_PErel, including the energy required
Expand Down Expand Up @@ -442,11 +457,19 @@
endif

if (allocated(tv%SpV_avg) .and. .not.GV%Boussinesq) then
SpV_dt(1) = (US%Z_to_m**3*US%s_to_T**3) * tv%SpV_avg(i,j,1) * I_dt
do K=2,nz
SpV_dt(K) = (US%Z_to_m**3*US%s_to_T**3) * 0.5*(tv%SpV_avg(i,j,k-1) + tv%SpV_avg(i,j,k)) * I_dt
enddo
SpV_dt(nz+1) = (US%Z_to_m**3*US%s_to_T**3) * tv%SpV_avg(i,j,nz) * I_dt
if (CS%answer_date < 20240101) then
SpV_dt(1) = (US%Z_to_m**3*US%s_to_T**3) * tv%SpV_avg(i,j,1) * I_dt
do K=2,nz
SpV_dt(K) = (US%Z_to_m**3*US%s_to_T**3) * 0.5*(tv%SpV_avg(i,j,k-1) + tv%SpV_avg(i,j,k)) * I_dt

Check warning on line 463 in src/parameterizations/vertical/MOM_energetic_PBL.F90

View check run for this annotation

Codecov / codecov/patch

src/parameterizations/vertical/MOM_energetic_PBL.F90#L461-L463

Added lines #L461 - L463 were not covered by tests
enddo
SpV_dt(nz+1) = (US%Z_to_m**3*US%s_to_T**3) * tv%SpV_avg(i,j,nz) * I_dt

Check warning on line 465 in src/parameterizations/vertical/MOM_energetic_PBL.F90

View check run for this annotation

Codecov / codecov/patch

src/parameterizations/vertical/MOM_energetic_PBL.F90#L465

Added line #L465 was not covered by tests
else
SpV_dt(1) = tv%SpV_avg(i,j,1) * I_dt
do K=2,nz
SpV_dt(K) = 0.5*(tv%SpV_avg(i,j,k-1) + tv%SpV_avg(i,j,k)) * I_dt

Check warning on line 469 in src/parameterizations/vertical/MOM_energetic_PBL.F90

View check run for this annotation

Codecov / codecov/patch

src/parameterizations/vertical/MOM_energetic_PBL.F90#L467-L469

Added lines #L467 - L469 were not covered by tests
enddo
SpV_dt(nz+1) = tv%SpV_avg(i,j,nz) * I_dt

Check warning on line 471 in src/parameterizations/vertical/MOM_energetic_PBL.F90

View check run for this annotation

Codecov / codecov/patch

src/parameterizations/vertical/MOM_energetic_PBL.F90#L471

Added line #L471 was not covered by tests
endif
endif

B_flux = buoy_flux(i,j)
Expand Down Expand Up @@ -565,9 +588,13 @@
real, dimension(SZK_(GV)), intent(in) :: dSV_dS !< The partial derivative of in-situ specific
!! volume with salinity [R-1 S-1 ~> m3 kg-1 ppt-1].
real, dimension(SZK_(GV)+1), intent(in) :: SpV_dt !< Specific volume interpolated to interfaces
!! divided by dt or 1.0 / (dt * Rho0) times conversion
!! factors in [m3 Z-3 R-1 T2 s-3 ~> m3 kg-1 s-1],
!! used to convert local TKE into a turbulence velocity.
!! divided by dt or 1.0 / (dt * Rho0), times conversion
!! factors for answer dates before 20240101 in
!! [m3 Z-3 R-1 T2 s-3 ~> m3 kg-1 s-1] or without
!! the convsersion factors for answer dates of
!! 20240101 and later in [R-1 T-1 ~> m3 kg-1 s-1],
!! used to convert local TKE into a turbulence
!! velocity cubed.
real, dimension(SZK_(GV)), intent(in) :: TKE_forcing !< The forcing requirements to homogenize the
!! forcing that has been applied to each layer
!! [R Z3 T-2 ~> J m-2].
Expand Down Expand Up @@ -819,7 +846,7 @@
max_itt = 20

dz_tt_min = 0.0
vstar_unit_scale = US%m_to_Z * US%T_to_s
if (CS%answer_date < 20240101) vstar_unit_scale = US%m_to_Z * US%T_to_s

MLD_guess = MLD_io

Expand Down Expand Up @@ -1160,12 +1187,22 @@
dz_tt = dztot + dz_tt_min
TKE_here = mech_TKE + CS%wstar_ustar_coef*conv_PErel
if (TKE_here > 0.0) then
if (CS%wT_scheme==wT_from_cRoot_TKE) then
vstar = CS%vstar_scale_fac * vstar_unit_scale * (SpV_dt(K)*TKE_here)**C1_3
elseif (CS%wT_scheme==wT_from_RH18) then
Surface_Scale = max(0.05, 1.0 - dztot / MLD_guess)
vstar = CS%vstar_scale_fac * Surface_Scale * (CS%vstar_surf_fac*u_star + &
vstar_unit_scale * (CS%wstar_ustar_coef*conv_PErel*SpV_dt(K))**C1_3)
if (CS%answer_date < 20240101) then
if (CS%wT_scheme==wT_from_cRoot_TKE) then
vstar = CS%vstar_scale_fac * vstar_unit_scale * (SpV_dt(K)*TKE_here)**C1_3
elseif (CS%wT_scheme==wT_from_RH18) then
Surface_Scale = max(0.05, 1.0 - dztot / MLD_guess)

Check warning on line 1194 in src/parameterizations/vertical/MOM_energetic_PBL.F90

View check run for this annotation

Codecov / codecov/patch

src/parameterizations/vertical/MOM_energetic_PBL.F90#L1192-L1194

Added lines #L1192 - L1194 were not covered by tests
vstar = CS%vstar_scale_fac * Surface_Scale * (CS%vstar_surf_fac*u_star + &
vstar_unit_scale * (CS%wstar_ustar_coef*conv_PErel*SpV_dt(K))**C1_3)

Check warning on line 1196 in src/parameterizations/vertical/MOM_energetic_PBL.F90

View check run for this annotation

Codecov / codecov/patch

src/parameterizations/vertical/MOM_energetic_PBL.F90#L1196

Added line #L1196 was not covered by tests
endif
else
if (CS%wT_scheme==wT_from_cRoot_TKE) then
vstar = CS%vstar_scale_fac * cuberoot(SpV_dt(K)*TKE_here)
elseif (CS%wT_scheme==wT_from_RH18) then
Surface_Scale = max(0.05, 1.0 - dztot / MLD_guess)

Check warning on line 1202 in src/parameterizations/vertical/MOM_energetic_PBL.F90

View check run for this annotation

Codecov / codecov/patch

src/parameterizations/vertical/MOM_energetic_PBL.F90#L1201-L1202

Added lines #L1201 - L1202 were not covered by tests
vstar = (CS%vstar_scale_fac * Surface_Scale) * ( CS%vstar_surf_fac*u_star + &
cuberoot((CS%wstar_ustar_coef*conv_PErel) * SpV_dt(K)) )

Check warning on line 1204 in src/parameterizations/vertical/MOM_energetic_PBL.F90

View check run for this annotation

Codecov / codecov/patch

src/parameterizations/vertical/MOM_energetic_PBL.F90#L1204

Added line #L1204 was not covered by tests
endif
endif
hbs_here = min(hb_hs(K), MixLen_shape(K))
mixlen(K) = MAX(CS%min_mix_len, ((dz_tt*hbs_here)*vstar) / &
Expand Down Expand Up @@ -1209,12 +1246,22 @@
! Does MKE_src need to be included in the calculation of vstar here?
TKE_here = mech_TKE + CS%wstar_ustar_coef*(conv_PErel-PE_chg_max)
if (TKE_here > 0.0) then
if (CS%wT_scheme==wT_from_cRoot_TKE) then
vstar = CS%vstar_scale_fac * vstar_unit_scale * (SpV_dt(K)*TKE_here)**C1_3
elseif (CS%wT_scheme==wT_from_RH18) then
Surface_Scale = max(0.05, 1. - dztot / MLD_guess)
vstar = CS%vstar_scale_fac * Surface_Scale * (CS%vstar_surf_fac*u_star + &
vstar_unit_scale * (CS%wstar_ustar_coef*conv_PErel*SpV_dt(K))**C1_3)
if (CS%answer_date < 20240101) then
if (CS%wT_scheme==wT_from_cRoot_TKE) then
vstar = CS%vstar_scale_fac * vstar_unit_scale * (SpV_dt(K)*TKE_here)**C1_3
elseif (CS%wT_scheme==wT_from_RH18) then
Surface_Scale = max(0.05, 1. - dztot / MLD_guess)

Check warning on line 1253 in src/parameterizations/vertical/MOM_energetic_PBL.F90

View check run for this annotation

Codecov / codecov/patch

src/parameterizations/vertical/MOM_energetic_PBL.F90#L1251-L1253

Added lines #L1251 - L1253 were not covered by tests
vstar = CS%vstar_scale_fac * Surface_Scale * (CS%vstar_surf_fac*u_star + &
vstar_unit_scale * (CS%wstar_ustar_coef*conv_PErel*SpV_dt(K))**C1_3)

Check warning on line 1255 in src/parameterizations/vertical/MOM_energetic_PBL.F90

View check run for this annotation

Codecov / codecov/patch

src/parameterizations/vertical/MOM_energetic_PBL.F90#L1255

Added line #L1255 was not covered by tests
endif
else
if (CS%wT_scheme==wT_from_cRoot_TKE) then
vstar = CS%vstar_scale_fac * cuberoot(SpV_dt(K)*TKE_here)
elseif (CS%wT_scheme==wT_from_RH18) then
Surface_Scale = max(0.05, 1. - dztot / MLD_guess)

Check warning on line 1261 in src/parameterizations/vertical/MOM_energetic_PBL.F90

View check run for this annotation

Codecov / codecov/patch

src/parameterizations/vertical/MOM_energetic_PBL.F90#L1260-L1261

Added lines #L1260 - L1261 were not covered by tests
vstar = (CS%vstar_scale_fac * Surface_Scale) * ( CS%vstar_surf_fac*u_star + &
cuberoot((CS%wstar_ustar_coef*conv_PErel) * SpV_dt(K)) )

Check warning on line 1263 in src/parameterizations/vertical/MOM_energetic_PBL.F90

View check run for this annotation

Codecov / codecov/patch

src/parameterizations/vertical/MOM_energetic_PBL.F90#L1263

Added line #L1263 was not covered by tests
endif
endif
hbs_here = min(hb_hs(K), MixLen_shape(K))
mixlen(K) = max(CS%min_mix_len, ((dz_tt*hbs_here)*vstar) / &
Expand Down Expand Up @@ -2076,7 +2123,9 @@
"The vintage of the order of arithmetic and expressions in the energetic "//&
"PBL calculations. Values below 20190101 recover the answers from the "//&
"end of 2018, while higher values use updated and more robust forms of the "//&
"same expressions.", &
"same expressions. Values below 20240101 use A**(1./3.) to estimate the cube "//&
"root of A in several expressions, while higher values use the integer root "//&
"function cuberoot(A) and therefore can work with scaled variables.", &
default=default_answer_date, do_not_log=.not.GV%Boussinesq)
if (.not.GV%Boussinesq) CS%answer_date = max(CS%answer_date, 20230701)

Expand Down
Loading