@@ -43,8 +43,9 @@ module MOM_PressureForce_FV
43
43
logical :: sal_use_bpa = .false. ! < If true, use bottom pressure anomaly instead of SSH
44
44
! ! to calculate SAL.
45
45
logical :: tides = .false. ! < If true, apply tidal momentum forcing.
46
- real :: Rho0 ! < The density used in the Boussinesq
47
- ! ! approximation [R ~> kg m-3].
46
+ real :: rho_ref ! < The reference density that is subtracted off when calculating pressure
47
+ ! ! gradient forces [R ~> kg m-3].
48
+ logical :: rho_ref_bug ! < If true, recover a bug that mixes GV%Rho0 and CS%rho_ref in Boussinesq mode.
48
49
real :: GFS_scale ! < A scaling of the surface pressure gradients to
49
50
! ! allow the use of a reduced gravity model [nondim].
50
51
type (time_type), pointer :: Time ! < A pointer to the ocean model's clock.
@@ -278,7 +279,7 @@ subroutine PressureForce_FV_nonBouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_
278
279
279
280
H_to_RL2_T2 = GV% g_Earth* GV% H_to_RZ
280
281
dp_neglect = GV% g_Earth* GV% H_to_RZ * GV% H_subroundoff
281
- alpha_ref = 1.0 / CS% Rho0
282
+ alpha_ref = 1.0 / CS% rho_ref
282
283
I_gEarth = 1.0 / GV% g_Earth
283
284
p_nonvanished = GV% g_Earth* GV% H_to_RZ* CS% h_nonvanished
284
285
@@ -977,7 +978,10 @@ subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm
977
978
! consistent with what is used in the density integral routines [R L2 T-2 ~> Pa]
978
979
real :: p0(SZI_(G)) ! An array of zeros to use for pressure [R L2 T-2 ~> Pa].
979
980
real :: dz_geo_sfc ! The change in surface geopotential height between adjacent cells [L2 T-2 ~> m2 s-2]
980
- real :: GxRho ! The gravitational acceleration times density [R L2 Z-1 T-2 ~> Pa m-1]
981
+ real :: GxRho0 ! The gravitational acceleration times mean ocean density [R L2 Z-1 T-2 ~> Pa m-1]
982
+ real :: GxRho_ref ! The gravitational acceleration times reference density [R L2 Z-1 T-2 ~> Pa m-1]
983
+ real :: rho0_int_density ! Rho0 used in int_density_dz_* subroutines [R ~> kg m-3]
984
+ real :: rho0_set_pbce ! Rho0 used in set_pbce_Bouss subroutine [R ~> kg m-3]
981
985
real :: h_neglect ! A thickness that is so small it is usually lost
982
986
! in roundoff and can be neglected [H ~> m].
983
987
real :: I_Rho0 ! The inverse of the Boussinesq reference density [R-1 ~> m3 kg-1].
@@ -1029,8 +1033,20 @@ subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm
1029
1033
dz_nonvanished = GV% H_to_Z* CS% h_nonvanished
1030
1034
I_Rho0 = 1.0 / GV% Rho0
1031
1035
G_Rho0 = GV% g_Earth / GV% Rho0
1032
- GxRho = GV% g_Earth * GV% Rho0
1033
- rho_ref = CS% Rho0
1036
+ GxRho0 = GV% g_Earth * GV% Rho0
1037
+ rho_ref = CS% rho_ref
1038
+
1039
+ if (CS% rho_ref_bug) then
1040
+ rho0_int_density = rho_ref
1041
+ rho0_set_pbce = rho_ref
1042
+ GxRho_ref = GxRho0
1043
+ I_g_rho = 1.0 / (rho_ref * GV% g_Earth)
1044
+ else
1045
+ rho0_int_density = GV% Rho0
1046
+ rho0_set_pbce = GV% Rho0
1047
+ GxRho_ref = GV% g_Earth * rho_ref
1048
+ I_g_rho = 1.0 / (GV% rho0 * GV% g_Earth)
1049
+ endif
1034
1050
1035
1051
if ((CS% id_MassWt_u > 0 ) .or. (CS% id_MassWt_v > 0 )) then
1036
1052
MassWt_u(:,:,:) = 0.0 ; MassWt_v(:,:,:) = 0.0
@@ -1141,17 +1157,16 @@ subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm
1141
1157
if (use_p_atm) then
1142
1158
! $OMP parallel do default(shared)
1143
1159
do j= Jsq,Jeq+1 ; do i= Isq,Ieq+1
1144
- pa(i,j,1 ) = GxRho * (e(i,j,1 ) - G% Z_ref) + p_atm(i,j)
1160
+ pa(i,j,1 ) = GxRho_ref * (e(i,j,1 ) - G% Z_ref) + p_atm(i,j)
1145
1161
enddo ; enddo
1146
1162
else
1147
1163
! $OMP parallel do default(shared)
1148
1164
do j= Jsq,Jeq+1 ; do i= Isq,Ieq+1
1149
- pa(i,j,1 ) = GxRho * (e(i,j,1 ) - G% Z_ref)
1165
+ pa(i,j,1 ) = GxRho_ref * (e(i,j,1 ) - G% Z_ref)
1150
1166
enddo ; enddo
1151
1167
endif
1152
1168
1153
1169
if (CS% use_SSH_in_Z0p .and. use_p_atm) then
1154
- I_g_rho = 1.0 / (CS% rho0* GV% g_Earth)
1155
1170
do j= Jsq,Jeq+1 ; do i= Isq,Ieq+1
1156
1171
Z_0p(i,j) = e(i,j,1 ) + p_atm(i,j) * I_g_rho
1157
1172
enddo ; enddo
@@ -1177,23 +1192,23 @@ subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm
1177
1192
if ( use_ALE .and. CS% Recon_Scheme > 0 ) then
1178
1193
if ( CS% Recon_Scheme == 1 ) then
1179
1194
call int_density_dz_generic_plm(k, tv, T_t, T_b, S_t, S_b, e, &
1180
- rho_ref, CS % Rho0 , GV% g_Earth, dz_neglect, G% bathyT, &
1195
+ rho_ref, rho0_int_density , GV% g_Earth, dz_neglect, G% bathyT, &
1181
1196
G% HI, GV, tv% eqn_of_state, US, CS% use_stanley_pgf, dpa(:,:,k), intz_dpa(:,:,k), &
1182
1197
intx_dpa(:,:,k), inty_dpa(:,:,k), &
1183
1198
MassWghtInterp= CS% MassWghtInterp, &
1184
1199
use_inaccurate_form= CS% use_inaccurate_pgf_rho_anom, Z_0p= Z_0p, &
1185
1200
MassWghtInterpVanOnly= CS% MassWghtInterpVanOnly, h_nv= dz_nonvanished)
1186
1201
elseif ( CS% Recon_Scheme == 2 ) then
1187
1202
call int_density_dz_generic_ppm(k, tv, T_t, T_b, S_t, S_b, e, &
1188
- rho_ref, CS % Rho0 , GV% g_Earth, dz_neglect, G% bathyT, &
1203
+ rho_ref, rho0_int_density , GV% g_Earth, dz_neglect, G% bathyT, &
1189
1204
G% HI, GV, tv% eqn_of_state, US, CS% use_stanley_pgf, dpa(:,:,k), intz_dpa(:,:,k), &
1190
1205
intx_dpa(:,:,k), inty_dpa(:,:,k), &
1191
1206
MassWghtInterp= CS% MassWghtInterp, Z_0p= Z_0p, &
1192
1207
MassWghtInterpVanOnly= CS% MassWghtInterpVanOnly, h_nv= dz_nonvanished)
1193
1208
endif
1194
1209
else
1195
1210
call int_density_dz(tv_tmp% T(:,:,k), tv_tmp% S(:,:,k), e(:,:,K), e(:,:,K+1 ), &
1196
- rho_ref, CS % Rho0 , GV% g_Earth, G% HI, tv% eqn_of_state, US, dpa(:,:,k), &
1211
+ rho_ref, rho0_int_density , GV% g_Earth, G% HI, tv% eqn_of_state, US, dpa(:,:,k), &
1197
1212
intz_dpa(:,:,k), intx_dpa(:,:,k), inty_dpa(:,:,k), G% bathyT, e(:,:,1 ), dz_neglect, &
1198
1213
CS% MassWghtInterp, Z_0p= Z_0p, &
1199
1214
MassWghtInterpVanOnly= CS% MassWghtInterpVanOnly, h_nv= dz_nonvanished)
@@ -1239,7 +1254,7 @@ subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm
1239
1254
if (CS% sal_use_bpa) then
1240
1255
! $OMP parallel do default(shared)
1241
1256
do j= Jsq,Jeq+1 ; do i= Isq,Ieq+1
1242
- pbot(i,j) = pa(i,j,nz+1 ) - GxRho * e(i,j,nz+1 )
1257
+ pbot(i,j) = pa(i,j,nz+1 ) - GxRho_ref * ( e(i,j,nz+1 ) - G % Z_ref )
1243
1258
enddo ; enddo
1244
1259
call calc_SAL(pbot, e_sal, G, CS% SAL_CSp, tmp_scale= US% Z_to_m)
1245
1260
else
@@ -1253,7 +1268,7 @@ subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm
1253
1268
! $OMP parallel do default(shared)
1254
1269
do j= Jsq,Jeq+1 ; do i= Isq,Ieq+1
1255
1270
e(i,j,K) = e(i,j,K) - e_sal(i,j)
1256
- pa(i,j,K) = pa(i,j,K) - GxRho * e_sal(i,j)
1271
+ pa(i,j,K) = pa(i,j,K) - GxRho_ref * e_sal(i,j)
1257
1272
enddo ; enddo
1258
1273
enddo ; endif
1259
1274
endif
@@ -1265,7 +1280,7 @@ subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm
1265
1280
! $OMP parallel do default(shared)
1266
1281
do j= Jsq,Jeq+1 ; do i= Isq,Ieq+1
1267
1282
e(i,j,K) = e(i,j,K) - (e_tidal_eq(i,j) + e_tidal_sal(i,j))
1268
- pa(i,j,K) = pa(i,j,K) - GxRho * (e_tidal_eq(i,j) + e_tidal_sal(i,j))
1283
+ pa(i,j,K) = pa(i,j,K) - GxRho_ref * (e_tidal_eq(i,j) + e_tidal_sal(i,j))
1269
1284
enddo ; enddo
1270
1285
enddo ; endif
1271
1286
endif
@@ -1288,7 +1303,7 @@ subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm
1288
1303
! $OMP parallel do default(shared) private(p_surf_EOS)
1289
1304
do j= Jsq,Jeq+1
1290
1305
! P_surf_EOS here is consistent with the pressure that is used in the int_density_dz routines.
1291
- do i= Isq,Ieq+1 ; p_surf_EOS(i) = - GxRho * (e(i,j,1 ) - Z_0p(i,j)) ; enddo
1306
+ do i= Isq,Ieq+1 ; p_surf_EOS(i) = - GxRho0 * (e(i,j,1 ) - Z_0p(i,j)) ; enddo
1292
1307
call calculate_density(T_top(:,j), S_top(:,j), p_surf_EOS, rho_top(:,j), &
1293
1308
tv% eqn_of_state, EOSdom, rho_ref= rho_ref)
1294
1309
enddo
@@ -1316,8 +1331,8 @@ subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm
1316
1331
S5(1 ) = S_top(i,j) ; S5(5 ) = S_top(i+1 ,j)
1317
1332
pa5(1 ) = pa(i,j,1 ) ; pa5(5 ) = pa(i+1 ,j,1 )
1318
1333
! Pressure input to density EOS is consistent with the pressure used in the int_density_dz routines.
1319
- p5(1 ) = - GxRho * (e(i,j,1 ) - Z_0p(i,j))
1320
- p5(5 ) = - GxRho * (e(i+1 ,j,1 ) - Z_0p(i,j))
1334
+ p5(1 ) = - GxRho0 * (e(i,j,1 ) - Z_0p(i,j))
1335
+ p5(5 ) = - GxRho0 * (e(i+1 ,j,1 ) - Z_0p(i,j))
1321
1336
do m= 2 ,4
1322
1337
wt_R = 0.25 * real (m-1 )
1323
1338
T5(m) = T5(1 ) + (T5(5 )- T5(1 ))* wt_R
@@ -1351,8 +1366,8 @@ subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm
1351
1366
S5(1 ) = S_top(i,j) ; S5(5 ) = S_top(i,j+1 )
1352
1367
pa5(1 ) = pa(i,j,1 ) ; pa5(5 ) = pa(i,j+1 ,1 )
1353
1368
! Pressure input to density EOS is consistent with the pressure used in the int_density_dz routines.
1354
- p5(1 ) = - GxRho * (e(i,j,1 ) - Z_0p(i,j))
1355
- p5(5 ) = - GxRho * (e(i,j+1 ,1 ) - Z_0p(i,j))
1369
+ p5(1 ) = - GxRho0 * (e(i,j,1 ) - Z_0p(i,j))
1370
+ p5(5 ) = - GxRho0 * (e(i,j+1 ,1 ) - Z_0p(i,j))
1356
1371
1357
1372
do m= 2 ,4
1358
1373
wt_R = 0.25 * real (m-1 )
@@ -1464,8 +1479,8 @@ subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm
1464
1479
! This is a typical case in the open ocean, so use the topmost interface.
1465
1480
T_int_W(I,j) = T_top(i,j) ; T_int_E(I,j) = T_top(i+1 ,j)
1466
1481
S_int_W(I,j) = S_top(i,j) ; S_int_E(I,j) = S_top(i+1 ,j)
1467
- p_int_W(I,j) = - GxRho * (e(i,j,1 ) - Z_0p(i,j))
1468
- p_int_E(I,j) = - GxRho * (e(i+1 ,j,1 ) - Z_0p(i,j))
1482
+ p_int_W(I,j) = - GxRho0 * (e(i,j,1 ) - Z_0p(i,j))
1483
+ p_int_E(I,j) = - GxRho0 * (e(i+1 ,j,1 ) - Z_0p(i,j))
1469
1484
intx_pa_nonlin(I,j) = intx_pa(I,j,1 ) - 0.5 * (pa(i,j,1 ) + pa(i+1 ,j,1 ))
1470
1485
dgeo_x(I,j) = GV% g_Earth * (e(i+1 ,j,1 )- e(i,j,1 ))
1471
1486
seek_x_cor(I,j) = .false.
@@ -1485,8 +1500,8 @@ subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm
1485
1500
S_int_W(I,j) = S_b(i,j,k) ; S_int_E(I,j) = S_b(i+1 ,j,k)
1486
1501
! These pressures are only used for the equation of state, and are only a function of
1487
1502
! height, consistent with the expressions in the int_density_dz routines.
1488
- p_int_W(I,j) = - GxRho * (e(i,j,K+1 ) - Z_0p(i,j))
1489
- p_int_E(I,j) = - GxRho * (e(i+1 ,j,K+1 ) - Z_0p(i,j))
1503
+ p_int_W(I,j) = - GxRho0 * (e(i,j,K+1 ) - Z_0p(i,j))
1504
+ p_int_E(I,j) = - GxRho0 * (e(i+1 ,j,K+1 ) - Z_0p(i,j))
1490
1505
1491
1506
intx_pa_nonlin(I,j) = intx_pa(I,j,K+1 ) - 0.5 * (pa(i,j,K+1 ) + pa(i+1 ,j,K+1 ))
1492
1507
dgeo_x(I,j) = GV% g_Earth * (e(i+1 ,j,K+1 )- e(i,j,K+1 ))
@@ -1503,8 +1518,8 @@ subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm
1503
1518
do j= js,je ; do I= Isq,Ieq ; if (seek_x_cor(I,j)) then
1504
1519
T_int_W(I,j) = T_top(i,j) ; T_int_E(I,j) = T_top(i+1 ,j)
1505
1520
S_int_W(I,j) = S_top(i,j) ; S_int_E(I,j) = S_top(i+1 ,j)
1506
- p_int_W(I,j) = - GxRho * (e(i,j,1 ) - Z_0p(i,j))
1507
- p_int_E(I,j) = - GxRho * (e(i+1 ,j,1 ) - Z_0p(i,j))
1521
+ p_int_W(I,j) = - GxRho0 * (e(i,j,1 ) - Z_0p(i,j))
1522
+ p_int_E(I,j) = - GxRho0 * (e(i+1 ,j,1 ) - Z_0p(i,j))
1508
1523
intx_pa_nonlin(I,j) = intx_pa(I,j,1 ) - 0.5 * (pa(i,j,1 ) + pa(i+1 ,j,1 ))
1509
1524
dgeo_x(I,j) = GV% g_Earth * (e(i+1 ,j,1 )- e(i,j,1 ))
1510
1525
seek_x_cor(I,j) = .false.
@@ -1546,8 +1561,8 @@ subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm
1546
1561
! This is a typical case in the open ocean, so use the topmost interface.
1547
1562
T_int_S(i,J) = T_top(i,j) ; T_int_N(i,J) = T_top(i,j+1 )
1548
1563
S_int_S(i,J) = S_top(i,j) ; S_int_N(i,J) = S_top(i,j+1 )
1549
- p_int_S(i,J) = - GxRho * (e(i,j,1 ) - Z_0p(i,j))
1550
- p_int_N(i,J) = - GxRho * (e(i,j+1 ,1 ) - Z_0p(i,j))
1564
+ p_int_S(i,J) = - GxRho0 * (e(i,j,1 ) - Z_0p(i,j))
1565
+ p_int_N(i,J) = - GxRho0 * (e(i,j+1 ,1 ) - Z_0p(i,j))
1551
1566
inty_pa_nonlin(i,J) = inty_pa(i,J,1 ) - 0.5 * (pa(i,j,1 ) + pa(i,j+1 ,1 ))
1552
1567
dgeo_y(i,J) = GV% g_Earth * (e(i,j+1 ,1 )- e(i,j,1 ))
1553
1568
seek_y_cor(i,J) = .false.
@@ -1567,8 +1582,8 @@ subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm
1567
1582
S_int_S(i,J) = S_b(i,j,k) ; S_int_N(i,J) = S_b(i,j+1 ,k)
1568
1583
! These pressures are only used for the equation of state, and are only a function of
1569
1584
! height, consistent with the expressions in the int_density_dz routines.
1570
- p_int_S(i,J) = - GxRho * (e(i,j,K+1 ) - Z_0p(i,j))
1571
- p_int_N(i,J) = - GxRho * (e(i,j+1 ,K+1 ) - Z_0p(i,j))
1585
+ p_int_S(i,J) = - GxRho0 * (e(i,j,K+1 ) - Z_0p(i,j))
1586
+ p_int_N(i,J) = - GxRho0 * (e(i,j+1 ,K+1 ) - Z_0p(i,j))
1572
1587
inty_pa_nonlin(i,J) = inty_pa(i,J,K+1 ) - 0.5 * (pa(i,j,K+1 ) + pa(i,j+1 ,K+1 ))
1573
1588
dgeo_y(i,J) = GV% g_Earth * (e(i,j+1 ,K+1 )- e(i,j,K+1 ))
1574
1589
seek_y_cor(i,J) = .false.
@@ -1584,8 +1599,8 @@ subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm
1584
1599
do J= Jsq,Jeq ; do i= is,ie ; if (seek_y_cor(i,J)) then
1585
1600
T_int_S(i,J) = T_top(i,j) ; T_int_N(i,J) = T_top(i,j+1 )
1586
1601
S_int_S(i,J) = S_top(i,j) ; S_int_N(i,J) = S_top(i,j+1 )
1587
- p_int_S(i,J) = - GxRho * (e(i,j,1 ) - Z_0p(i,j))
1588
- p_int_N(i,J) = - GxRho * (e(i,j+1 ,1 ) - Z_0p(i,j))
1602
+ p_int_S(i,J) = - GxRho0 * (e(i,j,1 ) - Z_0p(i,j))
1603
+ p_int_N(i,J) = - GxRho0 * (e(i,j+1 ,1 ) - Z_0p(i,j))
1589
1604
inty_pa_nonlin(i,J) = inty_pa(i,J,1 ) - 0.5 * (pa(i,j,1 ) + pa(i,j+1 ,1 ))
1590
1605
dgeo_y(i,J) = GV% g_Earth * (e(i,j+1 ,1 )- e(i,j,1 ))
1591
1606
seek_y_cor(i,J) = .false.
@@ -1709,7 +1724,7 @@ subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm
1709
1724
endif
1710
1725
1711
1726
if (present (pbce)) then
1712
- call set_pbce_Bouss(e, tv_tmp, G, GV, US, CS % Rho0 , CS% GFS_scale, pbce)
1727
+ call set_pbce_Bouss(e, tv_tmp, G, GV, US, rho0_set_pbce , CS% GFS_scale, pbce)
1713
1728
endif
1714
1729
1715
1730
if (present (eta)) then
@@ -1836,11 +1851,16 @@ subroutine PressureForce_FV_init(Time, G, GV, US, param_file, diag, CS, SAL_CSp,
1836
1851
call get_param(param_file, mdl, " DEBUG" , CS% debug, &
1837
1852
" If true, write out verbose debugging data." , &
1838
1853
default= .false. , debuggingParam= .true. , do_not_log= .true. )
1839
- call get_param(param_file, mdl, " RHO_PGF_REF" , CS% Rho0 , &
1854
+ call get_param(param_file, mdl, " RHO_PGF_REF" , CS% rho_ref , &
1840
1855
" The reference density that is subtracted off when calculating pressure " // &
1841
1856
" gradient forces. Its inverse is subtracted off of specific volumes when " // &
1842
1857
" in non-Boussinesq mode. The default is RHO_0." , &
1843
1858
units= " kg m-3" , default= GV% Rho0* US% R_to_kg_m3, scale= US% kg_m3_to_R)
1859
+ call get_param(param_file, mdl, " RHO_PGF_REF_BUG" , CS% rho_ref_bug, &
1860
+ " If true, recover a bug that RHO_0 (the mean seawater density in Boussinesq mode) " // &
1861
+ " and RHO_PGF_REF (the subtracted reference density in finite volume pressure " // &
1862
+ " gradient forces) are incorrectly interchanged in several instances in Boussinesq mode." , &
1863
+ default= .true. )
1844
1864
call get_param(param_file, mdl, " TIDES" , CS% tides, &
1845
1865
" If true, apply tidal momentum forcing." , default= .false. )
1846
1866
call get_param(param_file, ' ' , " DEFAULT_ANSWER_DATE" , default_answer_date, default= 99991231 )
0 commit comments