Skip to content

Commit 9737d2c

Browse files
Theresa MorrisonTheresa Morrison
Theresa Morrison
authored and
Theresa Morrison
committed
Add option for MLD density difference
Add the option to set a reference pressure (and depth) to use when calculating the MLD based on a densiy difference. The reference pressure is used to calculate the potential density and the density at that pressure (depth) is used as the "surface" density when calculaing the density difference.
1 parent 0f41403 commit 9737d2c

File tree

2 files changed

+119
-17
lines changed

2 files changed

+119
-17
lines changed

src/parameterizations/vertical/MOM_diabatic_aux.F90

+101-14
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,7 @@ end subroutine set_pen_shortwave
679679
!> Diagnose a mixed layer depth (MLD) determined by a given density difference with the surface.
680680
!> This routine is appropriate in MOM_diabatic_aux due to its position within the time stepping.
681681
subroutine diagnoseMLDbyDensityDifference(id_MLD, h, tv, densityDiff, G, GV, US, diagPtr, &
682-
id_N2subML, id_MLDsq, dz_subML)
682+
id_N2subML, id_MLDsq, dz_subML, ref_p_mld, id_ref_z)
683683
type(ocean_grid_type), intent(in) :: G !< Grid type
684684
type(verticalGrid_type), intent(in) :: GV !< ocean vertical grid structure
685685
type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
@@ -694,10 +694,14 @@ subroutine diagnoseMLDbyDensityDifference(id_MLD, h, tv, densityDiff, G, GV, US,
694694
integer, optional, intent(in) :: id_MLDsq !< Optional handle (ID) of squared MLD
695695
real, optional, intent(in) :: dz_subML !< The distance over which to calculate N2subML
696696
!! or 50 m if missing [Z ~> m]
697+
real, optional, intent(in) :: ref_p_mld !< Optional reference pressure used to calculate the
698+
!! densisty, defults to 0.0 is not present [R L2 T-2 ~> Pa].
699+
integer, optional, intent(in) :: id_ref_z !< Handle (ID) of reference depth diagnostic
697700

698701
! Local variables
699702
real, dimension(SZI_(G)) :: deltaRhoAtKm1, deltaRhoAtK ! Density differences [R ~> kg m-3].
700703
real, dimension(SZI_(G)) :: pRef_MLD, pRef_N2 ! Reference pressures [R L2 T-2 ~> Pa].
704+
real, dimension(SZI_(G)) :: hRef_MLD ! Depth of reference pressures [ ~> ].
701705
real, dimension(SZI_(G)) :: H_subML, dH_N2 ! Summed thicknesses used in N2 calculation [H ~> m or kg m-2]
702706
real, dimension(SZI_(G)) :: dZ_N2 ! Summed vertical distance used in N2 calculation [Z ~> m]
703707
real, dimension(SZI_(G)) :: T_subML, T_deeper ! Temperatures used in the N2 calculation [C ~> degC].
@@ -706,6 +710,8 @@ subroutine diagnoseMLDbyDensityDifference(id_MLD, h, tv, densityDiff, G, GV, US,
706710
real, dimension(SZI_(G),SZK_(GV)) :: dZ_2d ! Layer thicknesses in depth units [Z ~> m]
707711
real, dimension(SZI_(G)) :: dZ, dZm1 ! Layer thicknesses associated with interfaces [Z ~> m]
708712
real, dimension(SZI_(G)) :: rhoSurf ! Density used in finding the mixed layer depth [R ~> kg m-3].
713+
real :: rhoSurf_ref ! Density used in finding the mixed layer depth [R ~> kg m-3].
714+
real, dimension(SZI_(G), SZJ_(G)) :: z_ref_diag ! the actual depth of the k interface [Z ~> m].
709715
real, dimension(SZI_(G), SZJ_(G)) :: MLD ! Diagnosed mixed layer depth [Z ~> m].
710716
real, dimension(SZI_(G), SZJ_(G)) :: subMLN2 ! Diagnosed stratification below ML [T-2 ~> s-2].
711717
real, dimension(SZI_(G), SZJ_(G)) :: MLD2 ! Diagnosed MLD^2 [Z2 ~> m2].
@@ -716,6 +722,8 @@ subroutine diagnoseMLDbyDensityDifference(id_MLD, h, tv, densityDiff, G, GV, US,
716722
real :: dZ_sub_ML ! Depth below ML over which to diagnose stratification [Z ~> m]
717723
real :: aFac ! A nondimensional factor [nondim]
718724
real :: ddRho ! A density difference [R ~> kg m-3]
725+
real, dimension(SZI_(G)) :: ks
726+
real :: errZ, errZm1
719727
integer, dimension(2) :: EOSdom ! The i-computational domain for the equation of state
720728
integer :: i, j, is, ie, js, je, k, nz, id_N2, id_SQ
721729

@@ -737,24 +745,100 @@ subroutine diagnoseMLDbyDensityDifference(id_MLD, h, tv, densityDiff, G, GV, US,
737745

738746
is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke
739747

740-
pRef_MLD(:) = 0.0
748+
pRef_MLD(:) = 0.0; hRef_MLD(:) = 0.0
749+
if (present(ref_p_mld)) pRef_MLD(is:ie) = ref_p_mld
750+
if (present(ref_p_mld)) hRef_MLD(is:ie) = ref_p_mld ! horrible pressure to depth calc
751+
z_ref_diag(:,:) = 0.
752+
741753
EOSdom(:) = EOS_domain(G%HI)
742754
do j=js,je
743755
! Find the vertical distances across layers.
744756
call thickness_to_dz(h, tv, dZ_2d, j, G, GV)
745757

746-
do i=is,ie ; dZ(i) = 0.5 * dZ_2d(i,1) ; enddo ! Depth of center of surface layer
747-
call calculate_density(tv%T(:,j,1), tv%S(:,j,1), pRef_MLD, rhoSurf, tv%eqn_of_state, EOSdom)
748-
do i=is,ie
749-
deltaRhoAtK(i) = 0.
750-
MLD(i,j) = 0.
751-
if (id_N2>0) then
752-
subMLN2(i,j) = 0.0
753-
H_subML(i) = h(i,j,1) ; dH_N2(i) = 0.0 ; dZ_N2(i) = 0.0
754-
T_subML(i) = 0.0 ; S_subML(i) = 0.0 ; T_deeper(i) = 0.0 ; S_deeper(i) = 0.0
755-
N2_region_set(i) = (G%mask2dT(i,j)<0.5) ! Only need to work on ocean points.
756-
endif
757-
enddo
758+
if (pRef_MLD(is) .ne. 0.0) then
759+
ks(is:ie) = 0
760+
do i=is,ie
761+
dZ(i) = 0.5 * dZ_2d(i,1) ! Depth of center of surface layer
762+
if (dZ(i) >= hRef_MLD(i)) ks(i) = k
763+
enddo
764+
do k=2,nz
765+
do i=is,ie
766+
if (ks(i)==0 .and. k<nz) then ! still havent found 10 m depth
767+
if (dZ(i) >= hRef_MLD(i)) then ! check whether the previous layer was closer
768+
errZ = dZ(i) - hRef_MLD(i)
769+
errZm1 = hRef_MLD(i) - dZm1(i)
770+
if (errZ <= errZm1) then; ks(i) = k; z_ref_diag(i,j)=dZ(i); ! set the k reference
771+
elseif (errZm1 < errZ) then; ks(i) = k-1; z_ref_diag(i,j)=dZm1(i); endif
772+
elseif (dZ(i) < hRef_MLD(i)) then ! go to the next layer
773+
dZm1(i) = dZ(i) ! Depth of center of layer K-1
774+
dZ(i) = dZ(i) + 0.5 * ( dZ_2d(i,k) + dZ_2d(i,k-1) ) ! Depth of center of layer K
775+
endif
776+
elseif (ks(i)==0 .and. k==nz) then
777+
ks(i)=1
778+
endif
779+
enddo
780+
enddo
781+
do i=is,ie
782+
call calculate_density(tv%T(i,j,ks(i)), tv%S(i,j,ks(i)), pRef_MLD(i), rhoSurf_ref, tv%eqn_of_state)
783+
rhoSurf(i) = rhoSurf_ref
784+
deltaRhoAtK(i) = 0.
785+
MLD(i,j) = 0.
786+
if (id_N2>0) then
787+
subMLN2(i,j) = 0.0
788+
H_subML(i) = h(i,j,1) ; dH_N2(i) = 0.0 ; dZ_N2(i) = 0.0 ! may need to cahnge the 1 on this line?
789+
T_subML(i) = 0.0 ; S_subML(i) = 0.0 ; T_deeper(i) = 0.0 ; S_deeper(i) = 0.0
790+
N2_region_set(i) = (G%mask2dT(i,j)<0.5) ! Only need to work on ocean points.
791+
endif
792+
enddo
793+
!!!!!!!!!!!!
794+
!do i=is,ie
795+
! ks(i) = 0
796+
! dZm1(i) = 0.0
797+
! dZ(i) = 0.5 * dZ_2d(i,1) ! Depth of center of surface layer
798+
! if (dZ(i) >= hRef_MLD(i)) then; ks(i) = k;
799+
! else
800+
! do k=2,nz
801+
! if (ks(i)==0) then ! still havent found 10 m depth
802+
! if (dZ(i) >= hRef_MLD(i)) then ! find the
803+
! errZ = dZ(i) - hRef_MLD(i)
804+
! errZm1 = hRef_MLD(i) - dZm1(i)
805+
! if (errZ <= errZm1) then; ks(i) = k;
806+
! elseif (errZm1 < errZ) then; ks(i) = k-1; endif
807+
! elseif (dZ(i) < hRef_MLD(i)) then ! go to the next layer
808+
! dZm1(i) = dZ(i) ! Depth of center of layer K-1
809+
! dZ(i) = dZ(i) + 0.5 * ( dZ_2d(i,k) + dZ_2d(i,k-1) ) ! Depth of center of layer K
810+
! endif
811+
! endif
812+
! enddo
813+
! if (k>=nz .and. ks(i)==0.0) ks(i)=1
814+
! endif
815+
! !rhoSurf(i,j) = call calculate density
816+
! call calculate_density(tv%T(i,j,ks(i)), tv%S(i,j,ks(i)), pRef_MLD(i), rhoSurf_ref, tv%eqn_of_state)
817+
! rhoSurf(i) = rhoSurf_ref
818+
! deltaRhoAtK(i) = 0.
819+
! MLD(i,j) = 0.
820+
! if (id_N2>0) then
821+
! subMLN2(i,j) = 0.0
822+
! H_subML(i) = h(i,j,1) ; dH_N2(i) = 0.0 ; dZ_N2(i) = 0.0 ! may need to cahnge the 1 on this line?
823+
! T_subML(i) = 0.0 ; S_subML(i) = 0.0 ; T_deeper(i) = 0.0 ; S_deeper(i) = 0.0
824+
! N2_region_set(i) = (G%mask2dT(i,j)<0.5) ! Only need to work on ocean points.
825+
! endif
826+
!enddo
827+
elseif (pRef_MLD(is) == 0.0) then
828+
do i=is,ie ; dZ(i) = 0.5 * dZ_2d(i,1) ; enddo ! Depth of center of surface layer
829+
call calculate_density(tv%T(:,j,1), tv%S(:,j,1), pRef_MLD, rhoSurf, tv%eqn_of_state, EOSdom)
830+
do i=is,ie
831+
deltaRhoAtK(i) = 0.
832+
MLD(i,j) = 0.
833+
if (id_N2>0) then
834+
subMLN2(i,j) = 0.0
835+
H_subML(i) = h(i,j,1) ; dH_N2(i) = 0.0 ; dZ_N2(i) = 0.0
836+
T_subML(i) = 0.0 ; S_subML(i) = 0.0 ; T_deeper(i) = 0.0 ; S_deeper(i) = 0.0
837+
N2_region_set(i) = (G%mask2dT(i,j)<0.5) ! Only need to work on ocean points.
838+
endif
839+
enddo
840+
endif
841+
758842
do k=2,nz
759843
do i=is,ie
760844
dZm1(i) = dZ(i) ! Depth of center of layer K-1
@@ -800,6 +884,7 @@ subroutine diagnoseMLDbyDensityDifference(id_MLD, h, tv, densityDiff, G, GV, US,
800884
if (id_SQ > 0) MLD2(i,j) = MLD(i,j)**2
801885
enddo ! i-loop
802886
enddo ! k-loop
887+
! if reference layer is the surface
803888
do i=is,ie
804889
if ((MLD(i,j) == 0.) .and. (deltaRhoAtK(i) < densityDiff)) MLD(i,j) = dZ(i) ! Mixing goes to the bottom
805890
enddo
@@ -823,6 +908,8 @@ subroutine diagnoseMLDbyDensityDifference(id_MLD, h, tv, densityDiff, G, GV, US,
823908
if (id_N2 > 0) call post_data(id_N2, subMLN2, diagPtr)
824909
if (id_SQ > 0) call post_data(id_SQ, MLD2, diagPtr)
825910

911+
if ((id_ref_z > 0) .and. (pRef_MLD(is).ne.0.)) call post_data(id_ref_z, z_ref_diag , diagPtr)
912+
826913
end subroutine diagnoseMLDbyDensityDifference
827914

828915
!> Diagnose a mixed layer depth (MLD) determined by the depth a given energy value would mix.

src/parameterizations/vertical/MOM_diabatic_driver.F90

+18-3
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ module MOM_diabatic_driver
175175
real :: dz_subML_N2 !< The distance over which to calculate a diagnostic of the
176176
!! average stratification at the base of the mixed layer [Z ~> m].
177177
real :: MLD_En_vals(3) !< Energy values for energy mixed layer diagnostics [R Z3 T-2 ~> J m-2]
178+
real :: ref_p_mld = 0.0 !< A referece pressure for density used in a difference mixed based
179+
!! MLD calculation [R L2 T-2 ~> Pa].
178180

179181
!>@{ Diagnostic IDs
180182
integer :: id_ea = -1, id_eb = -1 ! used by layer diabatic
@@ -183,6 +185,7 @@ module MOM_diabatic_driver
183185
integer :: id_Tdif = -1, id_Sdif = -1, id_Tadv = -1, id_Sadv = -1
184186
! These are handles to diagnostics related to the mixed layer properties.
185187
integer :: id_MLD_003 = -1, id_MLD_0125 = -1, id_MLD_user = -1, id_mlotstsq = -1
188+
integer :: id_MLD_003_zr = -1
186189
integer :: id_MLD_EN1 = -1, id_MLD_EN2 = -1, id_MLD_EN3 = -1, id_subMLN2 = -1
187190

188191
! These are handles to diagnostics that are only available in non-ALE layered mode.
@@ -479,13 +482,16 @@ subroutine diabatic(u, v, h, tv, BLD, fluxes, visc, ADp, CDp, dt, Time_end, &
479482
call enable_averages(dt, Time_end, CS%diag)
480483
if (CS%id_MLD_003 > 0 .or. CS%id_subMLN2 > 0 .or. CS%id_mlotstsq > 0) then
481484
call diagnoseMLDbyDensityDifference(CS%id_MLD_003, h, tv, 0.03*US%kg_m3_to_R, G, GV, US, CS%diag, &
482-
id_N2subML=CS%id_subMLN2, id_MLDsq=CS%id_mlotstsq, dz_subML=CS%dz_subML_N2)
485+
id_N2subML=CS%id_subMLN2, id_MLDsq=CS%id_mlotstsq, dz_subML=CS%dz_subML_N2, &
486+
ref_P_MLD=CS%ref_p_mld, id_ref_z=CS%id_MLD_003_zr)
483487
endif
484488
if (CS%id_MLD_0125 > 0) then
485-
call diagnoseMLDbyDensityDifference(CS%id_MLD_0125, h, tv, 0.125*US%kg_m3_to_R, G, GV, US, CS%diag)
489+
call diagnoseMLDbyDensityDifference(CS%id_MLD_0125, h, tv, 0.125*US%kg_m3_to_R, G, GV, US, CS%diag, &
490+
ref_P_MLD=CS%ref_p_mld)
486491
endif
487492
if (CS%id_MLD_user > 0) then
488-
call diagnoseMLDbyDensityDifference(CS%id_MLD_user, h, tv, CS%MLDdensityDifference, G, GV, US, CS%diag)
493+
call diagnoseMLDbyDensityDifference(CS%id_MLD_user, h, tv, CS%MLDdensityDifference, G, GV, US, CS%diag, &
494+
ref_P_MLD=CS%ref_p_mld)
489495
endif
490496
if ((CS%id_MLD_EN1 > 0) .or. (CS%id_MLD_EN2 > 0) .or. (CS%id_MLD_EN3 > 0)) then
491497
call diagnoseMLDbyEnergy((/CS%id_MLD_EN1, CS%id_MLD_EN2, CS%id_MLD_EN3/),&
@@ -3217,6 +3223,8 @@ subroutine diabatic_driver_init(Time, G, GV, US, param_file, useALEalgorithm, di
32173223
'Mixed layer depth (delta rho = 0.03)', units='m', conversion=US%Z_to_m, &
32183224
cmor_field_name='mlotst', cmor_long_name='Ocean Mixed Layer Thickness Defined by Sigma T', &
32193225
cmor_standard_name='ocean_mixed_layer_thickness_defined_by_sigma_t')
3226+
CS%id_MLD_003_zr = register_diag_field('ocean_model', 'MLD_003_refZ', diag%axesT1, Time, &
3227+
'Depth of reference density for MLD (delta rho = 0.03)', units='m', conversion=US%Z_to_m)
32203228
CS%id_mlotstsq = register_diag_field('ocean_model', 'mlotstsq', diag%axesT1, Time, &
32213229
long_name='Square of Ocean Mixed Layer Thickness Defined by Sigma T', &
32223230
standard_name='square_of_ocean_mixed_layer_thickness_defined_by_sigma_t', &
@@ -3248,6 +3256,13 @@ subroutine diabatic_driver_init(Time, G, GV, US, param_file, useALEalgorithm, di
32483256
'Squared buoyancy frequency below mixed layer', units='s-2', conversion=US%s_to_T**2)
32493257
CS%id_MLD_user = register_diag_field('ocean_model', 'MLD_user', diag%axesT1, Time, &
32503258
'Mixed layer depth (used defined)', units='m', conversion=US%Z_to_m)
3259+
if (CS%id_MLD_003 > 0 .or. CS%id_MLD_0125 > 0 .or. CS%id_MLD_0125 > 0) then
3260+
call get_param(param_file, mdl, "PREF_FOR_MLD", CS%ref_p_mld, &
3261+
"Refernced pressure used to calculate the potential density used to find the mixed layer depth "//&
3262+
"based on a density difference.", &
3263+
units='Pa', default=0.0, scale=US%Pa_to_RL2_T2)
3264+
!! MLD calculation [R L2 T-2 ~> Pa].
3265+
endif
32513266
endif
32523267
call get_param(param_file, mdl, "DIAG_MLD_DENSITY_DIFF", CS%MLDdensityDifference, &
32533268
"The density difference used to determine a diagnostic mixed "//&

0 commit comments

Comments
 (0)