-
Notifications
You must be signed in to change notification settings - Fork 81
Baroclinic sea level calculation #1104
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
base: dev/gfdl
Are you sure you want to change the base?
Changes from 5 commits
41f2e9f
cd016b8
8ef7786
650e20b
cec2d80
b31b374
1390983
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,7 +19,7 @@ module MOM_interface_heights | |
|
|
||
| #include <MOM_memory.h> | ||
|
|
||
| public find_eta, find_dz_for_eta, dz_to_thickness, thickness_to_dz, dz_to_thickness_simple | ||
| public find_eta, find_bsl, find_dz_for_eta, dz_to_thickness, thickness_to_dz, dz_to_thickness_simple | ||
| public calc_derived_thermo | ||
| public convert_MLD_to_ML_thickness | ||
| public find_rho_bottom, find_col_avg_SpV, find_col_mass | ||
|
|
@@ -290,6 +290,105 @@ subroutine find_eta_2d(h, tv, G, GV, US, eta, eta_bt, halo_size, dZref) | |
|
|
||
| end subroutine find_eta_2d | ||
|
|
||
| !> Calculates the baroclinic sea level, following Xu et al., to be submitted to JPO | ||
| subroutine find_bsl(h, tv, G, GV, US, rho_s, bsl, dZref) | ||
| type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure | ||
| type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure | ||
| type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type | ||
| real, intent(in) :: rho_s !< Surface density [R ~> kg m-3] | ||
| real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2] | ||
| type(thermo_var_ptrs), intent(in) :: tv !< A structure pointing to various | ||
| !! thermodynamic variables | ||
| real, dimension(SZI_(G),SZJ_(G)), intent(out) :: bsl !< Baroclinic sea level [Z ~> m] | ||
| real, optional, intent(in) :: dZref !< The difference in the | ||
| !! reference height between G%bathyT and eta [Z ~> m]. The default is 0 | ||
|
|
||
| ! Local variables | ||
| real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1) :: eta ! layer interface heights [Z ~> m] | ||
| real, dimension(SZI_(G),SZJ_(G)) :: & | ||
| bathyT, & ! Bathymetry at T points plus dZ_ref [Z ~> m] | ||
| pt, & ! Pressure at the top of a layer [R L2 T-2 ~> Pa] | ||
| pb, & ! Pressure at the bottom of a layer [R L2 T-2 ~> Pa] | ||
| gz, & ! Geopotential at the bottom of a layer [L2 T-2 ~> m2 s-2] | ||
| dp, & ! Pressure change across a layer in Boussinesq mode [R L2 T-2 ~> Pa] | ||
| dg, & ! Geopotential change across a layer in non-Boussinesq mode [L2 T-2 ~> m2 s-2] | ||
| dp_int, & ! Layer-integrated pressure change in Boussinesq mode [R L2 Z T-2 ~> Pa m] | ||
| dg_int, & ! Layer-integrated geopotential change in non-Boussinesq mode [R L4 T-4 ~> Pa m2 s-2] | ||
| p_int ! Vertical integral of pressure at the bottom of a layer [R L2 Z T-2 ~> Pa m] | ||
| ! or that scaled by GV%g_Earth in non-Boussinesq and EOS mode [R L4 T-4 ~> Pa m2 s-2] | ||
| ! or that normalized by GV%g_Earth in non-EOS mode [R Z2 ~> Pa s2] | ||
| real :: dZ_ref ! The difference in the reference height between G%bathyT and eta [Z ~> m] | ||
| ! dZ_ref is 0 unless the optional argument dZref is present | ||
| real :: I_gEarth ! The inverse of the gravitational acceleration [T2 Z L-2 ~> s2 m-1] | ||
| real :: SpV_s ! Specific volume of the surface layer [R-1 ~> m3 kg-1] | ||
| logical, dimension(SZI_(G),SZJ_(G)) :: maskT ! Mask at T points for skipping land points in calculations | ||
| integer :: i, j, k, is, ie, js, je, nz | ||
|
|
||
| is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke | ||
|
|
||
| dZ_ref = 0.0 ; if (present(dZref)) dZ_ref = dZref | ||
|
|
||
| I_gEarth = 1.0 / GV%g_Earth; SpV_s = 1.0 / rho_s | ||
|
|
||
| call find_eta(h, tv, G, GV, US, eta, halo_size=1, dZref=dZ_ref) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This call to |
||
|
|
||
| !$OMP parallel default(shared) | ||
| !$OMP do | ||
| do j=js,je ; do i=is,ie | ||
| pt(i,j) = 0.0 ; pb(i,j) = 0.0 ; gz(i,j) = 0.0 ; p_int(i,j) = 0.0 ; bsl(i,j) = 0.0 | ||
| bathyT(i,j) = G%bathyT(i,j) + dZ_ref | ||
| maskT(i,j) = G%mask2dT(i,j) > 0.0 .and. bathyT(i,j) > 0.0 | ||
| enddo ; enddo | ||
|
|
||
| if (associated(tv%eqn_of_state)) then | ||
| if (GV%Boussinesq) then | ||
| do k=1,nz | ||
| call int_density_dz(tv%T(:,:,k), tv%S(:,:,k), eta(:,:,k), eta(:,:,k+1), rho_s, & | ||
| GV%Rho0, GV%g_Earth, G%HI, tv%eqn_of_state, US, dp, dp_int) | ||
| !$OMP do | ||
| do j=js,je ; do i=is,ie ; if (maskT(i,j)) then | ||
| p_int(i,j) = p_int(i,j) + (pt(i,j) * (GV%H_to_Z * h(i,j,k)) + dp_int(i,j)) | ||
| pt(i,j) = pt(i,j) + dp(i,j) | ||
| endif ; enddo ; enddo | ||
| enddo | ||
| !$OMP do | ||
| do j=js,je ; do i=is,ie ; if (maskT(i,j)) then | ||
| bsl(i,j) = - (p_int(i,j) * I_gEarth) / (rho_s * bathyT(i,j)) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suspect that there are cases where dividing by |
||
| endif ; enddo ; enddo | ||
| else ! (.not. GV%Boussinesq) | ||
| do k=1,nz | ||
| !$OMP do | ||
| do j=js,je ; do i=is,ie ; if (maskT(i,j)) then | ||
| dp(i,j) = GV%g_Earth * (GV%H_to_RZ * h(i,j,k)) | ||
| pb(i,j) = pt(i,j) + dp(i,j) | ||
| endif ; enddo ; enddo | ||
| call int_specific_vol_dp(tv%T(:,:,k), tv%S(:,:,k), pt, pb, SpV_s, G%HI, & | ||
| tv%eqn_of_state, US, dg, dg_int) | ||
| !$OMP do | ||
| do j=js,je ; do i=is,ie ; if (maskT(i,j)) then | ||
| gz(i,j) = gz(i,j) + dg(i,j) | ||
| p_int(i,j) = p_int(i,j) + (gz(i,j) * dp(i,j) + dg_int(i,j)) | ||
| pt(i,j) = pb(i,j) | ||
| endif ; enddo ; enddo | ||
| enddo | ||
| !$OMP do | ||
| do j=js,je ; do i=is,ie ; if (maskT(i,j)) then | ||
| bsl(i,j) = (p_int(i,j) * (I_gEarth * I_gEarth)) / (rho_s * bathyT(i,j)) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that the denominator here should be the sum of the layer thicknesses. Also, there should be spaces around the semicolon on the next line to follow the pattern used elsewhere. |
||
| endif ;enddo ; enddo | ||
| endif ! (GV%Boussinesq) | ||
| else ! (.not. associated(tv%eqn_of_state)) | ||
| !$OMP do | ||
| do j=js,je ; do i=is,ie ; if (maskT(i,j)) then | ||
| do k=2,nz | ||
| p_int(i,j) = p_int(i,j) + (GV%Rlay(k) - GV%Rlay(k-1)) * & | ||
| ((eta(i,j,k) + bathyT(i,j)) * (eta(i,j,k) + bathyT(i,j))) | ||
| enddo | ||
| bsl(i,j) = - 0.5 * (p_int(i,j) / (rho_s * bathyT(i,j))) | ||
| endif ; enddo ; enddo | ||
| endif ! (associated(tv%eqn_of_state)) | ||
| !$OMP end parallel | ||
|
|
||
| end subroutine find_bsl | ||
|
|
||
| !> Calculate derived thermodynamic quantities for re-use later. | ||
| subroutine calc_derived_thermo(tv, h, G, GV, US, halo, debug) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment here should make it clear that this is the anomaly in the pressure change across a layer relative to what would be found if the density of the layer were
rho_s. Without this clarification, it is very hard to see how the code in this routine would generate the baroclinic sea level anomaly. This comment also pertains to the descriptions ofdg,dp_int,dg_intandp_intin the next few lines, all of which are also anomalies relative to the reference state.