Skip to content

Commit dd1f3f5

Browse files
authored
Add ice shelf pressure initialisation bug fix (#800)
* Add ice shelf pressure initialisation bug fix This commit adds a new parameter FRAC_DP_AT_POS_NEGATIVE_P_BUGFIX and associated bug fix. This bug occurs when TRIM_IC_FOR_P_SURF pressure initialisation is used for ice shelf, whilst in Boussinesq mode and a nonlinear equation of state. The subroutine trim_for_ice calls cut_off_column_top. This routine in Boussinesq mode calls find_depth_of_pressure_in_cell in MOM_density_integrals.F90. This subsequently calls the function frac_dp_at_pos which calls the density equation of state based on given salinity, temperature and depth, which is incorrectly converted into pressure by z position (which is negative) multiplied by g and rho0. The bug results in incorrect densities from the equation of state and therefore an imperfect initialisation of layer thicknesses and sea surface height due to the displacement of water by the ice. The bug is fixed by multiplying the pressure by -1. This commit introduces parameter FRAC_DP_AT_POS_NEGATIVE_P_BUGFIX with default value False to preserve answers. If true, the ice shelf initialisation is accurate to a high degree with a nonlinear equation of state. Answers should not change, except for the added parameter in MOM_parameter_doc. The same functions are called by a unit test in MOM_state_initialization; in this commit I set the MOM_state_initialization unit test to use the existing bug (with a false flag). * Resolve indenting and white space inconsitencies with MOM6 style for ice shelf pressure initialisation bug fix FRAC_DP_AT_POS_NEGATIVE_P_BUGFIX
1 parent 585d24d commit dd1f3f5

File tree

2 files changed

+26
-11
lines changed

2 files changed

+26
-11
lines changed

src/core/MOM_density_integrals.F90

+11-5
Original file line numberDiff line numberDiff line change
@@ -2001,7 +2001,7 @@ end subroutine diagnose_mass_weight_p
20012001

20022002
!> Find the depth at which the reconstructed pressure matches P_tgt
20032003
subroutine find_depth_of_pressure_in_cell(T_t, T_b, S_t, S_b, z_t, z_b, P_t, P_tgt, &
2004-
rho_ref, G_e, EOS, US, P_b, z_out, z_tol)
2004+
rho_ref, G_e, EOS, US, P_b, z_out, z_tol, frac_dp_bugfix)
20052005
real, intent(in) :: T_t !< Potential temperature at the cell top [C ~> degC]
20062006
real, intent(in) :: T_b !< Potential temperature at the cell bottom [C ~> degC]
20072007
real, intent(in) :: S_t !< Salinity at the cell top [S ~> ppt]
@@ -2020,6 +2020,7 @@ subroutine find_depth_of_pressure_in_cell(T_t, T_b, S_t, S_b, z_t, z_b, P_t, P_t
20202020
real, intent(out) :: P_b !< Pressure at the bottom of the cell [R L2 T-2 ~> Pa]
20212021
real, intent(out) :: z_out !< Absolute depth at which anomalous pressure = p_tgt [Z ~> m]
20222022
real, intent(in) :: z_tol !< The tolerance in finding z_out [Z ~> m]
2023+
logical, intent(in) :: frac_dp_bugfix !< If true, use bugfix in frac_dp_at_pos
20232024

20242025
! Local variables
20252026
real :: dp ! Pressure thickness of the layer [R L2 T-2 ~> Pa]
@@ -2032,7 +2033,7 @@ subroutine find_depth_of_pressure_in_cell(T_t, T_b, S_t, S_b, z_t, z_b, P_t, P_t
20322033
GxRho = G_e * rho_ref
20332034

20342035
! Anomalous pressure difference across whole cell
2035-
dp = frac_dp_at_pos(T_t, T_b, S_t, S_b, z_t, z_b, rho_ref, G_e, 1.0, EOS)
2036+
dp = frac_dp_at_pos(T_t, T_b, S_t, S_b, z_t, z_b, rho_ref, G_e, 1.0, EOS, frac_dp_bugfix)
20362037

20372038
P_b = P_t + dp ! Anomalous pressure at bottom of cell
20382039

@@ -2063,7 +2064,7 @@ subroutine find_depth_of_pressure_in_cell(T_t, T_b, S_t, S_b, z_t, z_b, P_t, P_t
20632064
call MOM_error(FATAL, 'find_depth_of_pressure_in_cell completes too many iterations: '//msg)
20642065
endif
20652066
z_out = z_t + ( z_b - z_t ) * F_guess
2066-
Pa = frac_dp_at_pos(T_t, T_b, S_t, S_b, z_t, z_b, rho_ref, G_e, F_guess, EOS) - ( P_tgt - P_t )
2067+
Pa = frac_dp_at_pos(T_t, T_b, S_t, S_b, z_t, z_b, rho_ref, G_e, F_guess, EOS, frac_dp_bugfix) - ( P_tgt - P_t )
20672068

20682069
if (Pa<Pa_left) then
20692070
write(msg,*) Pa_left,Pa,Pa_right,P_t-P_tgt,P_b-P_tgt
@@ -2119,7 +2120,7 @@ end subroutine avg_specific_vol
21192120

21202121
!> Returns change in anomalous pressure change from top to non-dimensional
21212122
!! position pos between z_t and z_b [R L2 T-2 ~> Pa]
2122-
real function frac_dp_at_pos(T_t, T_b, S_t, S_b, z_t, z_b, rho_ref, G_e, pos, EOS)
2123+
real function frac_dp_at_pos(T_t, T_b, S_t, S_b, z_t, z_b, rho_ref, G_e, pos, EOS, frac_dp_bugfix)
21232124
real, intent(in) :: T_t !< Potential temperature at the cell top [C ~> degC]
21242125
real, intent(in) :: T_b !< Potential temperature at the cell bottom [C ~> degC]
21252126
real, intent(in) :: S_t !< Salinity at the cell top [S ~> ppt]
@@ -2131,6 +2132,7 @@ real function frac_dp_at_pos(T_t, T_b, S_t, S_b, z_t, z_b, rho_ref, G_e, pos, EO
21312132
real, intent(in) :: G_e !< The Earth's gravitational acceleration [L2 Z-1 T-2 ~> m s-2]
21322133
real, intent(in) :: pos !< The fractional vertical position, 0 to 1 [nondim]
21332134
type(EOS_type), intent(in) :: EOS !< Equation of state structure
2135+
logical, intent(in) :: frac_dp_bugfix !< If true, use bugfix in frac_dp_at_pos
21342136

21352137
! Local variables
21362138
real, parameter :: C1_90 = 1.0/90.0 ! A rational constant [nondim]
@@ -2150,7 +2152,11 @@ real function frac_dp_at_pos(T_t, T_b, S_t, S_b, z_t, z_b, rho_ref, G_e, pos, EO
21502152
! Salinity and temperature points are linearly interpolated
21512153
S5(n) = top_weight * S_t + bottom_weight * S_b
21522154
T5(n) = top_weight * T_t + bottom_weight * T_b
2153-
p5(n) = ( top_weight * z_t + bottom_weight * z_b ) * ( G_e * rho_ref )
2155+
if (frac_dp_bugfix) then
2156+
p5(n) = (-1) * ( top_weight * z_t + bottom_weight * z_b ) * ( G_e * rho_ref )
2157+
else
2158+
p5(n) = ( top_weight * z_t + bottom_weight * z_b ) * ( G_e * rho_ref )
2159+
endif !bugfix
21542160
enddo
21552161
call calculate_density(T5, S5, p5, rho5, EOS)
21562162
rho5(:) = rho5(:) !- rho_ref ! Work with anomalies relative to rho_ref

src/initialization/MOM_state_initialization.F90

+15-6
Original file line numberDiff line numberDiff line change
@@ -1205,6 +1205,7 @@ subroutine trim_for_ice(PF, G, GV, US, ALE_CSp, tv, h, just_read)
12051205
! answers from 2018, while higher values use more robust
12061206
! forms of the same remapping expressions.
12071207
logical :: use_remapping ! If true, remap the initial conditions.
1208+
logical :: use_frac_dp_bugfix ! If true, use bugfix. Otherwise, pressure input to EOS is negative.
12081209
type(remapping_CS), pointer :: remap_CS => NULL()
12091210

12101211
call get_param(PF, mdl, "SURFACE_PRESSURE_FILE", p_surf_file, &
@@ -1227,7 +1228,10 @@ subroutine trim_for_ice(PF, G, GV, US, ALE_CSp, tv, h, just_read)
12271228
"The tolerance with which to find the depth matching the specified "//&
12281229
"surface pressure with TRIM_IC_FOR_P_SURF.", &
12291230
units="m", default=1.0e-5, scale=US%m_to_Z, do_not_log=just_read)
1230-
1231+
call get_param(PF, mdl, "FRAC_DP_AT_POS_NEGATIVE_P_BUGFIX", use_frac_dp_bugfix, &
1232+
"If true, use bugfix in ice shelf TRIM_IC initialization. "//&
1233+
"Otherwise, pressure input to density EOS is negative.", &
1234+
default=.false., do_not_log=just_read)
12311235
call get_param(PF, mdl, "TRIMMING_USES_REMAPPING", use_remapping, &
12321236
'When trimming the column, also remap T and S.', &
12331237
default=.false., do_not_log=just_read)
@@ -1277,7 +1281,8 @@ subroutine trim_for_ice(PF, G, GV, US, ALE_CSp, tv, h, just_read)
12771281
do j=G%jsc,G%jec ; do i=G%isc,G%iec
12781282
call cut_off_column_top(GV%ke, tv, GV, US, GV%g_Earth, G%bathyT(i,j)+G%Z_ref, min_thickness, &
12791283
tv%T(i,j,:), T_t(i,j,:), T_b(i,j,:), tv%S(i,j,:), S_t(i,j,:), S_b(i,j,:), &
1280-
p_surf(i,j), h(i,j,:), remap_CS, z_tol=z_tolerance)
1284+
p_surf(i,j), h(i,j,:), remap_CS, z_tol=z_tolerance, &
1285+
frac_dp_bugfix=use_frac_dp_bugfix)
12811286
enddo ; enddo
12821287

12831288
end subroutine trim_for_ice
@@ -1368,7 +1373,7 @@ end subroutine calc_sfc_displacement
13681373
!> Adjust the layer thicknesses by removing the top of the water column above the
13691374
!! depth where the hydrostatic pressure matches p_surf
13701375
subroutine cut_off_column_top(nk, tv, GV, US, G_earth, depth, min_thickness, T, T_t, T_b, &
1371-
S, S_t, S_b, p_surf, h, remap_CS, z_tol)
1376+
S, S_t, S_b, p_surf, h, remap_CS, z_tol, frac_dp_bugfix)
13721377
integer, intent(in) :: nk !< Number of layers
13731378
type(thermo_var_ptrs), intent(in) :: tv !< Thermodynamics structure
13741379
type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
@@ -1388,6 +1393,7 @@ subroutine cut_off_column_top(nk, tv, GV, US, G_earth, depth, min_thickness, T,
13881393
!! if associated
13891394
real, intent(in) :: z_tol !< The tolerance with which to find the depth
13901395
!! matching the specified pressure [Z ~> m].
1396+
logical, intent(in) :: frac_dp_bugfix !< If true, use bugfix in frac_dp_at_pos
13911397

13921398
! Local variables
13931399
real, dimension(nk+1) :: e ! Top and bottom edge positions for reconstructions [Z ~> m]
@@ -1416,7 +1422,8 @@ subroutine cut_off_column_top(nk, tv, GV, US, G_earth, depth, min_thickness, T,
14161422
do k=1,nk
14171423
call find_depth_of_pressure_in_cell(T_t(k), T_b(k), S_t(k), S_b(k), e(K), e(K+1), &
14181424
P_t, p_surf, GV%Rho0, G_earth, tv%eqn_of_state, &
1419-
US, P_b, z_out, z_tol=z_tol)
1425+
US, P_b, z_out, z_tol=z_tol, &
1426+
frac_dp_bugfix=frac_dp_bugfix)
14201427
if (z_out>=e(K)) then
14211428
! Imposed pressure was less that pressure at top of cell
14221429
exit
@@ -3139,7 +3146,8 @@ subroutine MOM_state_init_tests(G, GV, US, tv)
31393146
P_t = 0.
31403147
do k = 1, nk
31413148
call find_depth_of_pressure_in_cell(T_t(k), T_b(k), S_t(k), S_b(k), e(K), e(K+1), P_t, 0.5*P_tot, &
3142-
GV%Rho0, GV%g_Earth, tv%eqn_of_state, US, P_b, z_out, z_tol=z_tol)
3149+
GV%Rho0, GV%g_Earth, tv%eqn_of_state, US, P_b, z_out, z_tol=z_tol, &
3150+
frac_dp_bugfix=.false.)
31433151
write(0,*) k, US%RL2_T2_to_Pa*P_t, US%RL2_T2_to_Pa*P_b, 0.5*US%RL2_T2_to_Pa*P_tot, &
31443152
US%Z_to_m*e(K), US%Z_to_m*e(K+1), US%Z_to_m*z_out
31453153
P_t = P_b
@@ -3158,7 +3166,8 @@ subroutine MOM_state_init_tests(G, GV, US, tv)
31583166
! h_neglect=GV%H_subroundoff, h_neglect_edge=GV%H_subroundoff)
31593167
! endif
31603168
call cut_off_column_top(nk, tv, GV, US, GV%g_Earth, -e(nk+1), GV%Angstrom_H, &
3161-
T, T_t, T_b, S, S_t, S_b, 0.5*P_tot, h, remap_CS, z_tol=z_tol)
3169+
T, T_t, T_b, S, S_t, S_b, 0.5*P_tot, h, remap_CS, z_tol=z_tol, &
3170+
frac_dp_bugfix=.false.)
31623171
write(0,*) GV%H_to_m*h(:)
31633172
if (associated(remap_CS)) deallocate(remap_CS)
31643173

0 commit comments

Comments
 (0)