diff --git a/src/core/MOM_PressureForce.F90 b/src/core/MOM_PressureForce.F90 index ad76a9a9f5..191ee439c9 100644 --- a/src/core/MOM_PressureForce.F90 +++ b/src/core/MOM_PressureForce.F90 @@ -16,7 +16,7 @@ module MOM_PressureForce use MOM_self_attr_load, only : SAL_CS use MOM_tidal_forcing, only : tidal_forcing_CS use MOM_unit_scaling, only : unit_scale_type -use MOM_variables, only : thermo_var_ptrs +use MOM_variables, only : thermo_var_ptrs, accel_diag_ptrs use MOM_verticalGrid, only : verticalGrid_type use MOM_ALE, only: ALE_CS implicit none ; private @@ -38,7 +38,7 @@ module MOM_PressureForce contains !> A thin layer between the model and the Boussinesq and non-Boussinesq pressure force routines. -subroutine PressureForce(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm, pbce, eta) +subroutine PressureForce(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, ADp, p_atm, pbce, eta) 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 @@ -51,6 +51,7 @@ subroutine PressureForce(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm, pbce, e intent(out) :: PFv !< Meridional pressure force acceleration [L T-2 ~> m s-2] type(PressureForce_CS), intent(inout) :: CS !< Pressure force control structure type(ALE_CS), pointer :: ALE_CSp !< ALE control structure + type(accel_diag_ptrs), pointer :: ADp !< Acceleration diagnostic pointers real, dimension(:,:), pointer :: p_atm !< The pressure at the ice-ocean or !! atmosphere-ocean interface [R L2 T-2 ~> Pa]. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & @@ -63,10 +64,10 @@ subroutine PressureForce(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm, pbce, e if (CS%Analytic_FV_PGF) then if (GV%Boussinesq) then call PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS%PressureForce_FV, & - ALE_CSp, p_atm, pbce, eta) + ALE_CSp, ADp, p_atm, pbce, eta) else call PressureForce_FV_nonBouss(h, tv, PFu, PFv, G, GV, US, CS%PressureForce_FV, & - ALE_CSp, p_atm, pbce, eta) + ALE_CSp, ADp, p_atm, pbce, eta) endif else if (GV%Boussinesq) then @@ -81,7 +82,7 @@ subroutine PressureForce(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm, pbce, e end subroutine Pressureforce !> Initialize the pressure force control structure -subroutine PressureForce_init(Time, G, GV, US, param_file, diag, CS, SAL_CSp, tides_CSp) +subroutine PressureForce_init(Time, G, GV, US, param_file, diag, CS, ADp, SAL_CSp, tides_CSp) type(time_type), target, intent(in) :: Time !< Current model time type(ocean_grid_type), intent(in) :: G !< Ocean grid structure type(verticalGrid_type), intent(in) :: GV !< Vertical grid structure @@ -89,6 +90,7 @@ subroutine PressureForce_init(Time, G, GV, US, param_file, diag, CS, SAL_CSp, ti type(param_file_type), intent(in) :: param_file !< Parameter file handles type(diag_ctrl), target, intent(inout) :: diag !< Diagnostics control structure type(PressureForce_CS), intent(inout) :: CS !< Pressure force control structure + type(accel_diag_ptrs), pointer :: ADp !< Acceleration diagnostic pointers type(SAL_CS), intent(in), optional :: SAL_CSp !< SAL control structure type(tidal_forcing_CS), intent(in), optional :: tides_CSp !< Tide control structure #include "version_variable.h" @@ -105,7 +107,7 @@ subroutine PressureForce_init(Time, G, GV, US, param_file, diag, CS, SAL_CSp, ti if (CS%Analytic_FV_PGF) then call PressureForce_FV_init(Time, G, GV, US, param_file, diag, & - CS%PressureForce_FV, SAL_CSp, tides_CSp) + CS%PressureForce_FV, ADp, SAL_CSp, tides_CSp) else call PressureForce_Mont_init(Time, G, GV, US, param_file, diag, & CS%PressureForce_Mont, SAL_CSp, tides_CSp) diff --git a/src/core/MOM_PressureForce_FV.F90 b/src/core/MOM_PressureForce_FV.F90 index c160d7c7c9..aaabab3500 100644 --- a/src/core/MOM_PressureForce_FV.F90 +++ b/src/core/MOM_PressureForce_FV.F90 @@ -14,7 +14,7 @@ module MOM_PressureForce_FV use MOM_tidal_forcing, only : calc_tidal_forcing, tidal_forcing_CS use MOM_tidal_forcing, only : calc_tidal_forcing_legacy use MOM_unit_scaling, only : unit_scale_type -use MOM_variables, only : thermo_var_ptrs +use MOM_variables, only : thermo_var_ptrs, accel_diag_ptrs use MOM_verticalGrid, only : verticalGrid_type use MOM_EOS, only : calculate_density, calculate_spec_vol, EOS_domain use MOM_density_integrals, only : int_density_dz, int_specific_vol_dp @@ -98,6 +98,10 @@ module MOM_PressureForce_FV integer :: id_p_stanley = -1 !< Diagnostic identifier integer :: id_MassWt_u = -1 !< Diagnostic identifier integer :: id_MassWt_v = -1 !< Diagnostic identifier + integer :: id_sal_u = -1 !< Diagnostic identifier + integer :: id_sal_v = -1 !< Diagnostic identifier + integer :: id_tides_u = -1 !< Diagnostic identifier + integer :: id_tides_v = -1 !< Diagnostic identifier type(SAL_CS), pointer :: SAL_CSp => NULL() !< SAL control structure type(tidal_forcing_CS), pointer :: tides_CSp => NULL() !< Tides control structure end type PressureForce_FV_CS @@ -113,7 +117,7 @@ module MOM_PressureForce_FV !! To work, the following fields must be set outside of the usual (is:ie,js:je) !! range before this subroutine is called: !! h(isB:ie+1,jsB:je+1), T(isB:ie+1,jsB:je+1), and S(isB:ie+1,jsB:je+1). -subroutine PressureForce_FV_nonBouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm, pbce, eta) +subroutine PressureForce_FV_nonBouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, ADp, p_atm, pbce, eta) type(ocean_grid_type), intent(in) :: G !< Ocean grid structure type(verticalGrid_type), intent(in) :: GV !< Vertical grid structure type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type @@ -123,6 +127,7 @@ subroutine PressureForce_FV_nonBouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_ real, dimension(SZI_(G),SZJB_(G),SZK_(GV)), intent(out) :: PFv !< Meridional acceleration [L T-2 ~> m s-2] type(PressureForce_FV_CS), intent(in) :: CS !< Finite volume PGF control structure type(ALE_CS), pointer :: ALE_CSp !< ALE control structure + type(accel_diag_ptrs), pointer :: ADp !< Acceleration diagnostic pointers real, dimension(:,:), pointer :: p_atm !< The pressure at the ice-ocean !! or atmosphere-ocean interface [R L2 T-2 ~> Pa]. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), optional, intent(out) :: pbce !< The baroclinic pressure @@ -255,7 +260,7 @@ subroutine PressureForce_FV_nonBouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_ real :: SpV5(5) ! Specific volume anomalies at five quadrature points [R-1 ~> m3 kg-1] real :: wt_R ! A weighting factor [nondim] -! real :: oneatm ! 1 standard atmosphere of pressure in [R L2 T-2 ~> Pa] + ! real :: oneatm ! 1 standard atmosphere of pressure in [R L2 T-2 ~> Pa] real, parameter :: C1_6 = 1.0/6.0 ! [nondim] real, parameter :: C1_90 = 1.0/90.0 ! A rational constant [nondim] integer :: is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz, nkmb @@ -888,9 +893,13 @@ subroutine PressureForce_FV_nonBouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_ endif endif - ! To be consistent with old runs, tidal forcing diagnostic also includes total SAL. - ! New diagnostics are given for each individual field. + if (CS%id_MassWt_u>0) call post_data(CS%id_MassWt_u, MassWt_u, CS%diag) + if (CS%id_MassWt_v>0) call post_data(CS%id_MassWt_v, MassWt_v, CS%diag) + + ! Diagnostics for tidal forcing and SAL height anomaly if (CS%id_e_tide>0) then + ! To be consistent with old runs, tidal forcing diagnostic also includes total SAL. + ! New diagnostics are given for each individual field. if (CS%tides_answer_date>20230630) then ; do j=Jsq,Jeq+1 ; do i=Isq,Ieq+1 e_sal_and_tide(i,j) = e_sal(i,j) + e_tidal_eq(i,j) + e_tidal_sal(i,j) enddo ; enddo ; endif @@ -899,9 +908,32 @@ subroutine PressureForce_FV_nonBouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_ if (CS%id_e_sal>0) call post_data(CS%id_e_sal, e_sal, CS%diag) if (CS%id_e_tidal_eq>0) call post_data(CS%id_e_tidal_eq, e_tidal_eq, CS%diag) if (CS%id_e_tidal_sal>0) call post_data(CS%id_e_tidal_sal, e_tidal_sal, CS%diag) - if (CS%id_MassWt_u>0) call post_data(CS%id_MassWt_u, MassWt_u, CS%diag) - if (CS%id_MassWt_v>0) call post_data(CS%id_MassWt_v, MassWt_v, CS%diag) + ! Diagnostics for tidal forcing and SAL horizontal gradients + if (CS%calculate_SAL .and. (associated(ADp%sal_u) .or. associated(ADp%sal_v))) then + if (CS%tides) then ; do j=Jsq,Jeq+1 ; do i=Isq,Ieq+1 + e_sal(i,j) = e_sal(i,j) + e_tidal_sal(i,j) + enddo ; enddo ; endif + if (associated(ADp%sal_u)) then ; do k=1,nz ; do j=js,je ; do I=Isq,Ieq + ADp%sal_u(I,j,k) = (e_sal(i+1,j) - e_sal(i,j)) * GV%g_Earth * G%IdxCu(I,j) + enddo ; enddo ; enddo ; endif + if (associated(ADp%sal_v)) then ; do k=1,nz ; do J=Jsq,Jeq ; do i=is,ie + ADp%sal_v(i,J,k) = (e_sal(i,j+1) - e_sal(i,j)) * GV%g_Earth * G%IdyCv(i,J) + enddo ; enddo ; enddo ; endif + if (CS%id_sal_u>0) call post_data(CS%id_sal_u, ADp%sal_u, CS%diag) + if (CS%id_sal_v>0) call post_data(CS%id_sal_v, ADp%sal_v, CS%diag) + endif + + if (CS%tides .and. (associated(ADp%tides_u) .or. associated(ADp%tides_v))) then + if (associated(ADp%tides_u)) then ; do k=1,nz ; do j=js,je ; do I=Isq,Ieq + ADp%tides_u(I,j,k) = (e_tidal_eq(i+1,j) - e_tidal_eq(i,j)) * GV%g_Earth * G%IdxCu(I,j) + enddo ; enddo ; enddo ; endif + if (associated(ADp%tides_v)) then ; do k=1,nz ; do J=Jsq,Jeq ; do i=is,ie + ADp%tides_v(i,J,k) = (e_tidal_eq(i,j+1) - e_tidal_eq(i,j)) * GV%g_Earth * G%IdyCv(i,J) + enddo ; enddo ; enddo ; endif + if (CS%id_tides_u>0) call post_data(CS%id_tides_u, ADp%tides_u, CS%diag) + if (CS%id_tides_v>0) call post_data(CS%id_tides_v, ADp%tides_v, CS%diag) + endif end subroutine PressureForce_FV_nonBouss !> \brief Boussinesq analytically-integrated finite volume form of pressure gradient @@ -912,7 +944,7 @@ end subroutine PressureForce_FV_nonBouss !! To work, the following fields must be set outside of the usual (is:ie,js:je) !! range before this subroutine is called: !! h(isB:ie+1,jsB:je+1), T(isB:ie+1,jsB:je+1), and S(isB:ie+1,jsB:je+1). -subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm, pbce, eta) +subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, ADp, p_atm, pbce, eta) type(ocean_grid_type), intent(in) :: G !< Ocean grid structure type(verticalGrid_type), intent(in) :: GV !< Vertical grid structure type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type @@ -922,6 +954,7 @@ subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm real, dimension(SZI_(G),SZJB_(G),SZK_(GV)), intent(out) :: PFv !< Meridional acceleration [L T-2 ~> m s-2] type(PressureForce_FV_CS), intent(in) :: CS !< Finite volume PGF control structure type(ALE_CS), pointer :: ALE_CSp !< ALE control structure + type(accel_diag_ptrs), pointer :: ADp !< Acceleration diagnostic pointers real, dimension(:,:), pointer :: p_atm !< The pressure at the ice-ocean !! or atmosphere-ocean interface [R L2 T-2 ~> Pa]. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), optional, intent(out) :: pbce !< The baroclinic pressure @@ -1910,9 +1943,17 @@ subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm endif endif - ! To be consistent with old runs, tidal forcing diagnostic also includes total SAL. - ! New diagnostics are given for each individual field. + if (CS%id_MassWt_u>0) call post_data(CS%id_MassWt_u, MassWt_u, CS%diag) + if (CS%id_MassWt_v>0) call post_data(CS%id_MassWt_v, MassWt_v, CS%diag) + + if (CS%id_rho_pgf>0) call post_data(CS%id_rho_pgf, rho_pgf, CS%diag) + if (CS%id_rho_stanley_pgf>0) call post_data(CS%id_rho_stanley_pgf, rho_stanley_pgf, CS%diag) + if (CS%id_p_stanley>0) call post_data(CS%id_p_stanley, p_stanley, CS%diag) + + ! Diagnostics for tidal forcing and SAL height anomaly if (CS%id_e_tide>0) then + ! To be consistent with old runs, tidal forcing diagnostic also includes total SAL. + ! New diagnostics are given for each individual field. if (CS%tides_answer_date>20230630) then ; do j=Jsq,Jeq+1 ; do i=Isq,Ieq+1 e_sal_and_tide(i,j) = e_sal(i,j) + e_tidal_eq(i,j) + e_tidal_sal(i,j) enddo ; enddo ; endif @@ -1921,17 +1962,62 @@ subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm if (CS%id_e_sal>0) call post_data(CS%id_e_sal, e_sal, CS%diag) if (CS%id_e_tidal_eq>0) call post_data(CS%id_e_tidal_eq, e_tidal_eq, CS%diag) if (CS%id_e_tidal_sal>0) call post_data(CS%id_e_tidal_sal, e_tidal_sal, CS%diag) - if (CS%id_MassWt_u>0) call post_data(CS%id_MassWt_u, MassWt_u, CS%diag) - if (CS%id_MassWt_v>0) call post_data(CS%id_MassWt_v, MassWt_v, CS%diag) - if (CS%id_rho_pgf>0) call post_data(CS%id_rho_pgf, rho_pgf, CS%diag) - if (CS%id_rho_stanley_pgf>0) call post_data(CS%id_rho_stanley_pgf, rho_stanley_pgf, CS%diag) - if (CS%id_p_stanley>0) call post_data(CS%id_p_stanley, p_stanley, CS%diag) + ! Diagnostics for tidal forcing and SAL horizontal gradients + if (CS%calculate_SAL .and. ((associated(ADp%sal_u) .or. associated(ADp%sal_v)))) then + if (CS%tides) then ; do j=Jsq,Jeq+1 ; do i=Isq,Ieq+1 + e_sal(i,j) = e_sal(i,j) + e_tidal_sal(i,j) + enddo ; enddo ; endif + if (CS%bq_sal_tides) then + ! sal_u = ( e(i+1) - e(i) ) * g / dx + if (associated(ADp%sal_u)) then ; do k=1,nz ; do j=js,je ; do I=Isq,Ieq + ADp%sal_u(I,j,k) = (e_sal(i+1,j) - e_sal(i,j)) * GV%g_Earth * G%IdxCu(I,j) + enddo ; enddo ; enddo ; endif + if (associated(ADp%sal_v)) then ; do k=1,nz ; do J=Jsq,Jeq ; do i=is,ie + ADp%sal_v(i,J,k) = (e_sal(i,j+1) - e_sal(i,j)) * GV%g_Earth * G%IdyCv(i,J) + enddo ; enddo ; enddo ; endif + else + ! sal_u = ( e(i+1) - e(i) ) * g / dx * (rho(k) / rho0) + if (associated(ADp%sal_u)) then ; do k=1,nz ; do j=js,je ; do I=Isq,Ieq + ADp%sal_u(I,j,k) = (e_sal(i+1,j) - e_sal(i,j)) * G%IdxCu(I,j) * I_Rho0 * & + (2.0 * intx_dpa(I,j,k) * GV%Z_to_H / ((h(i,j,k) + h(i+1,j,k)) + h_neglect) + GxRho_ref) + enddo ; enddo ; enddo ; endif + if (associated(ADp%sal_v)) then ; do k=1,nz ; do J=Jsq,Jeq ; do i=is,ie + ADp%sal_v(i,J,k) = (e_sal(i,j+1) - e_sal(i,j)) * G%IdyCv(i,J) * I_Rho0 * & + (2.0 * inty_dpa(i,J,k) * GV%Z_to_H / ((h(i,j,k) + h(i,j+1,k)) + h_neglect) + GxRho_ref) + enddo ; enddo ; enddo ; endif + endif + if (CS%id_sal_u>0) call post_data(CS%id_sal_u, ADp%sal_u, CS%diag) + if (CS%id_sal_v>0) call post_data(CS%id_sal_v, ADp%sal_v, CS%diag) + endif + if (CS%tides .and. ((associated(ADp%tides_u) .or. associated(ADp%tides_v)))) then + if (CS%bq_sal_tides) then + ! tides_u = ( e(i+1) - e(i) ) * g / dx + if (associated(ADp%tides_u)) then ; do k=1,nz ; do j=js,je ; do I=Isq,Ieq + ADp%tides_u(I,j,k) = (e_tidal_eq(i+1,j) - e_tidal_eq(i,j)) * GV%g_Earth * G%IdxCu(I,j) + enddo ; enddo ; enddo ; endif + if (associated(ADp%tides_v)) then ; do k=1,nz ; do J=Jsq,Jeq ; do i=is,ie + ADp%tides_v(i,J,k) = (e_tidal_eq(i,j+1) - e_tidal_eq(i,j)) * GV%g_Earth * G%IdyCv(i,J) + enddo ; enddo ; enddo ; endif + else + ! tides_u = ( e(i+1) - e(i) ) * g / dx * (rho(k) / rho0) + if (associated(ADp%tides_u)) then ; do k=1,nz ; do j=js,je ; do I=Isq,Ieq + ADp%tides_u(I,j,k) = (e_tidal_eq(i+1,j) - e_tidal_eq(i,j)) * G%IdxCu(I,j) * I_Rho0 * & + (2.0 * intx_dpa(I,j,k) * GV%Z_to_H / ((h(i,j,k) + h(i+1,j,k)) + h_neglect) + GxRho_ref) + enddo ; enddo ; enddo ; endif + if (associated(ADp%tides_v)) then ; do k=1,nz ; do J=Jsq,Jeq ; do i=is,ie + ADp%tides_v(i,J,k) = (e_tidal_eq(i,j+1) - e_tidal_eq(i,j)) * G%IdyCv(i,J) * I_Rho0 * & + (2.0 * inty_dpa(i,J,k) * GV%Z_to_H / ((h(i,j,k) + h(i,j+1,k)) + h_neglect) + GxRho_ref) + enddo ; enddo ; enddo ; endif + endif + if (CS%id_tides_u>0) call post_data(CS%id_tides_u, ADp%tides_u, CS%diag) + if (CS%id_tides_v>0) call post_data(CS%id_tides_v, ADp%tides_v, CS%diag) + endif end subroutine PressureForce_FV_Bouss !> Initializes the finite volume pressure gradient control structure -subroutine PressureForce_FV_init(Time, G, GV, US, param_file, diag, CS, SAL_CSp, tides_CSp) +subroutine PressureForce_FV_init(Time, G, GV, US, param_file, diag, CS, ADp, SAL_CSp, tides_CSp) type(time_type), target, intent(in) :: Time !< Current model time type(ocean_grid_type), intent(in) :: G !< Ocean grid structure type(verticalGrid_type), intent(in) :: GV !< Vertical grid structure @@ -1939,6 +2025,7 @@ subroutine PressureForce_FV_init(Time, G, GV, US, param_file, diag, CS, SAL_CSp, type(param_file_type), intent(in) :: param_file !< Parameter file handles type(diag_ctrl), target, intent(inout) :: diag !< Diagnostics control structure type(PressureForce_FV_CS), intent(inout) :: CS !< Finite volume PGF control structure + type(accel_diag_ptrs), pointer :: ADp !< Acceleration diagnostic pointers type(SAL_CS), intent(in), target, optional :: SAL_CSp !< SAL control structure type(tidal_forcing_CS), intent(in), target, optional :: tides_CSp !< Tides control structure @@ -1956,6 +2043,10 @@ subroutine PressureForce_FV_init(Time, G, GV, US, param_file, diag, CS, SAL_CSp, # include "version_variable.h" character(len=40) :: mdl ! This module's name. logical :: use_ALE ! If true, use the Vertical Lagrangian Remap algorithm + integer :: isd, ied, jsd, jed, IsdB, IedB, JsdB, JedB, nz + + isd = G%isd ; ied = G%ied ; jsd = G%jsd ; jed = G%jed ; nz = GV%ke + IsdB = G%IsdB ; IedB = G%IedB ; JsdB = G%JsdB ; JedB = G%JedB CS%initialized = .true. CS%diag => diag ; CS%Time => Time @@ -2109,8 +2200,16 @@ subroutine PressureForce_FV_init(Time, G, GV, US, param_file, diag, CS, SAL_CSp, Time, 'p in PGF with Stanley correction', 'Pa', conversion=US%RL2_T2_to_Pa) endif if (CS%calculate_SAL) then - CS%id_e_sal = register_diag_field('ocean_model', 'e_sal', diag%axesT1, & - Time, 'Self-attraction and loading height anomaly', 'meter', conversion=US%Z_to_m) + CS%id_e_sal = register_diag_field('ocean_model', 'e_sal', diag%axesT1, Time, & + 'Self-attraction and loading height anomaly', 'meter', conversion=US%Z_to_m) + CS%id_sal_u = register_diag_field('ocean_model', 'SAL_u', diag%axesCuL, Time, & + 'Zonal Acceleration due to self-attraction and loading', 'm s-2', conversion=US%L_T2_to_m_s2) + CS%id_sal_v = register_diag_field('ocean_model', 'SAL_v', diag%axesCvL, Time, & + 'Meridional Acceleration due to self-attraction and loading', 'm s-2', conversion=US%L_T2_to_m_s2) + if (CS%id_sal_u > 0) & + call safe_alloc_ptr(ADp%sal_u, IsdB, IedB, jsd, jed, nz) + if (CS%id_sal_v > 0) & + call safe_alloc_ptr(ADp%sal_v, isd, ied, JsdB, JedB, nz) endif if (CS%tides) then CS%id_e_tide = register_diag_field('ocean_model', 'e_tidal', diag%axesT1, Time, & @@ -2119,6 +2218,14 @@ subroutine PressureForce_FV_init(Time, G, GV, US, param_file, diag, CS, SAL_CSp, 'Equilibrium tides height anomaly', 'meter', conversion=US%Z_to_m) CS%id_e_tidal_sal = register_diag_field('ocean_model', 'e_tide_sal', diag%axesT1, Time, & 'Read-in tidal self-attraction and loading height anomaly', 'meter', conversion=US%Z_to_m) + CS%id_tides_u = register_diag_field('ocean_model', 'tides_u', diag%axesCuL, Time, & + 'Zonal Acceleration due to tidal forcing', 'm s-2', conversion=US%L_T2_to_m_s2) + CS%id_tides_v = register_diag_field('ocean_model', 'tides_v', diag%axesCvL, Time, & + 'Meridional Acceleration due to tidal forcing', 'm s-2', conversion=US%L_T2_to_m_s2) + if (CS%id_tides_u > 0) & + call safe_alloc_ptr(ADp%tides_u, IsdB, IedB, jsd, jed, nz) + if (CS%id_tides_v > 0) & + call safe_alloc_ptr(ADp%tides_v, isd, ied, JsdB, JedB, nz) endif CS%id_MassWt_u = register_diag_field('ocean_model', 'MassWt_u', diag%axesCuL, Time, & diff --git a/src/core/MOM_barotropic.F90 b/src/core/MOM_barotropic.F90 index dcd5b4afb0..15861316d0 100644 --- a/src/core/MOM_barotropic.F90 +++ b/src/core/MOM_barotropic.F90 @@ -325,6 +325,7 @@ module MOM_barotropic !>@{ Diagnostic IDs integer :: id_PFu_bt = -1, id_PFv_bt = -1, id_Coru_bt = -1, id_Corv_bt = -1 + integer :: id_LDu_bt = -1, id_LDv_bt = -1 integer :: id_ubtforce = -1, id_vbtforce = -1, id_uaccel = -1, id_vaccel = -1 integer :: id_visc_rem_u = -1, id_visc_rem_v = -1, id_eta_cor = -1 integer :: id_ubt = -1, id_vbt = -1, id_eta_bt = -1, id_ubtav = -1, id_vbtav = -1 @@ -531,16 +532,16 @@ subroutine btstep(U_in, V_in, eta_in, dt, bc_accel_u, bc_accel_v, forces, pbce, ubt_wtd, & ! A weighted sum used to find the filtered final ubt [L T-1 ~> m s-1]. PFu_avg, & ! The average zonal barotropic pressure gradient force [L T-2 ~> m s-2]. Coru_avg, & ! The average zonal barotropic Coriolis acceleration [L T-2 ~> m s-2]. + LDu_avg, & ! The average zonal barotropic linear wave drag acceleration [L T-2 ~> m s-2]. ubt_dt ! The zonal barotropic velocity tendency [L T-2 ~> m s-2]. real, dimension(SZI_(G),SZJB_(G)) :: & av_rem_v, & ! The weighted average of visc_rem_v [nondim] tmp_v, & ! A temporary array at v points [L T-2 ~> m s-2] or [nondim] vbt_st, & ! The meridional barotropic velocity at the start of timestep [L T-1 ~> m s-1]. vbt_wtd, & ! A weighted sum used to find the filtered final vbt [L T-1 ~> m s-1]. - PFv_avg, & ! The average meridional barotropic pressure gradient force, - ! [L T-2 ~> m s-2]. - Corv_avg, & ! The summed meridional barotropic Coriolis acceleration, - ! [L T-2 ~> m s-2]. + PFv_avg, & ! The average meridional barotropic pressure gradient force [L T-2 ~> m s-2]. + Corv_avg, & ! The average meridional barotropic Coriolis acceleration [L T-2 ~> m s-2]. + LDv_avg, & ! The average meridional barotropic linear wave drag acceleration [L T-2 ~> m s-2]. vbt_dt ! The meridional barotropic velocity tendency [L T-2 ~> m s-2]. real, dimension(SZI_(G),SZJ_(G)) :: & tmp_h, & ! A temporary array at h points [nondim] @@ -1763,9 +1764,9 @@ subroutine btstep(U_in, V_in, eta_in, dt, bc_accel_u, bc_accel_v, forces, pbce, f_4_u, f_4_v, bt_rem_u, bt_rem_v, & BT_force_u, BT_force_v, Cor_ref_u, Cor_ref_v, Rayleigh_u, Rayleigh_v, & eta_PF, gtot_E, gtot_W, gtot_N, gtot_S, SpV_col_avg, dgeo_de, & - eta_sum, eta_wtd, ubt_wtd, vbt_wtd, Coru_avg, PFu_avg, Corv_avg, PFv_avg, & - use_BT_cont, interp_eta_PF, find_etaav, dt, dtbt, nstep, nfilter, & - wt_vel, wt_eta, wt_accel, wt_trans, wt_accel2, OBC, CS%BT_OBC, CS, G, MS, GV, US) + eta_sum, eta_wtd, ubt_wtd, vbt_wtd, Coru_avg, PFu_avg, LDu_avg, Corv_avg, PFv_avg, & + LDv_avg, use_BT_cont, interp_eta_PF, find_etaav, dt, dtbt, nstep, nfilter, & + wt_vel, wt_eta, wt_accel, wt_trans, wt_accel2, ADp, OBC, CS%BT_OBC, CS, G, MS, GV, US) if (id_clock_calc > 0) call cpu_clock_end(id_clock_calc) @@ -1863,8 +1864,14 @@ subroutine btstep(U_in, V_in, eta_in, dt, bc_accel_u, bc_accel_v, forces, pbce, do J=js-1,je ; do i=is,ie v_accel_bt(i,J) = v_accel_bt(i,J) - Drag_v(i,J) enddo ; enddo - endif + if ((CS%id_LDu_bt > 0) .or. (associated(ADp%bt_lwd_u))) then ; do j=js,je ; do I=is-1,ie + LDu_avg(I,j) = LDu_avg(I,j) - Drag_u(I,j) + enddo ; enddo ; endif + if ((CS%id_LDv_bt > 0) .or. (associated(ADp%bt_lwd_v))) then ; do J=js-1,je ; do i=is,ie + LDv_avg(i,J) = LDv_avg(i,J) - Drag_v(i,J) + enddo ; enddo ; endif + endif if (id_clock_calc_post > 0) call cpu_clock_end(id_clock_calc_post) if (id_clock_pass_post > 0) call cpu_clock_begin(id_clock_pass_post) @@ -1915,6 +1922,8 @@ subroutine btstep(U_in, V_in, eta_in, dt, bc_accel_u, bc_accel_v, forces, pbce, if (CS%id_PFv_bt > 0) call post_data(CS%id_PFv_bt, PFv_avg, CS%diag) if (CS%id_Coru_bt > 0) call post_data(CS%id_Coru_bt, Coru_avg, CS%diag) if (CS%id_Corv_bt > 0) call post_data(CS%id_Corv_bt, Corv_avg, CS%diag) + if (CS%id_LDu_bt > 0) call post_data(CS%id_LDu_bt, LDu_avg, CS%diag) + if (CS%id_LDv_bt > 0) call post_data(CS%id_LDv_bt, LDv_avg, CS%diag) else ! if (CS%answer_date < 20190101) then if (CS%id_PFu_bt > 0) then do j=js,je ; do I=is-1,ie @@ -1941,6 +1950,8 @@ subroutine btstep(U_in, V_in, eta_in, dt, bc_accel_u, bc_accel_v, forces, pbce, call post_data(CS%id_Corv_bt, Corv_avg, CS%diag) endif endif + + ! Diagnostics for time tendency if (CS%id_ubtdt > 0) then do j=js,je ; do I=is-1,ie ubt_dt(I,j) = (ubt_wtd(I,j) - ubt_st(I,j))*Idt @@ -1954,6 +1965,32 @@ subroutine btstep(U_in, V_in, eta_in, dt, bc_accel_u, bc_accel_v, forces, pbce, call post_data(CS%id_vbtdt, vbt_dt(isd:ied,JsdB:JedB), CS%diag) endif + ! Copy decomposed barotropic accelerations to ADp + if (associated(ADp%bt_pgf_u)) then ; do k=1,nz ; do j=js,je ; do I=is-1,ie + ADp%bt_pgf_u(I,j,k) = PFu_avg(I,j) - & + (((pbce(i+1,j,k) - gtot_W(i+1,j)) * e_anom(i+1,j)) - & + ((pbce(i,j,k) - gtot_E(i,j)) * e_anom(i,j))) * CS%IdxCu(I,j) + enddo ; enddo ; enddo ; endif + if (associated(ADp%bt_pgf_v)) then ; do k=1,nz ; do J=js-1,je ; do i=is,ie + ADp%bt_pgf_v(i,J,k) = PFv_avg(i,J) - & + (((pbce(i,j+1,k) - gtot_S(i,j+1)) * e_anom(i,j+1)) - & + ((pbce(i,j,k) - gtot_N(i,j)) * e_anom(i,j))) * CS%IdyCv(i,J) + enddo ; enddo ; enddo ; endif + + if (associated(ADp%bt_cor_u)) then ; do j=js,je ; do I=is-1,ie + ADp%bt_cor_u(I,j) = Coru_avg(I,j) + enddo ; enddo ; endif + if (associated(ADp%bt_cor_v)) then ; do J=js-1,je ; do i=is,ie + ADp%bt_cor_v(i,J) = Corv_avg(i,J) + enddo ; enddo ; endif + + if (associated(ADp%bt_lwd_u)) then ; do j=js,je ; do I=is-1,ie + ADp%bt_lwd_u(I,j) = LDu_avg(I,j) + enddo ; enddo ; endif + if (associated(ADp%bt_lwd_v)) then ; do J=js-1,je ; do i=is,ie + ADp%bt_lwd_v(i,J) = LDv_avg(i,J) + enddo ; enddo ; endif + if (CS%id_ubtforce > 0) call post_data(CS%id_ubtforce, BT_force_u(IsdB:IedB,jsd:jed), CS%diag) if (CS%id_vbtforce > 0) call post_data(CS%id_vbtforce, BT_force_v(isd:ied,JsdB:JedB), CS%diag) if (CS%id_uaccel > 0) call post_data(CS%id_uaccel, u_accel_bt(IsdB:IedB,jsd:jed), CS%diag) @@ -2103,9 +2140,9 @@ subroutine btstep_timeloop(eta, ubt, vbt, uhbt0, Datu, BTCL_u, vhbt0, Datv, BTCL f_4_u, f_4_v, bt_rem_u, bt_rem_v, & BT_force_u, BT_force_v, Cor_ref_u, Cor_ref_v, Rayleigh_u, Rayleigh_v, & eta_PF, gtot_E, gtot_W, gtot_N, gtot_S, SpV_col_avg, dgeo_de, & - eta_sum, eta_wtd, ubt_wtd, vbt_wtd, Coru_avg, PFu_avg, Corv_avg, PFv_avg, & - use_BT_cont, interp_eta_PF, find_etaav, dt, dtbt, nstep, nfilter, & - wt_vel, wt_eta, wt_accel, wt_trans, wt_accel2, OBC, BT_OBC, CS, G, MS, GV, US) + eta_sum, eta_wtd, ubt_wtd, vbt_wtd, Coru_avg, PFu_avg, LDu_avg, Corv_avg, PFv_avg, & + LDv_avg, use_BT_cont, interp_eta_PF, find_etaav, dt, dtbt, nstep, nfilter, & + wt_vel, wt_eta, wt_accel, wt_trans, wt_accel2, ADp, OBC, BT_OBC, CS, G, MS, GV, US) type(barotropic_CS), intent(inout) :: CS !< Barotropic control structure type(ocean_grid_type), intent(inout) :: G !< The ocean's grid structure (inout to allow for halo updates) @@ -2232,11 +2269,15 @@ subroutine btstep_timeloop(eta, ubt, vbt, uhbt0, Datu, BTCL_u, vhbt0, Datv, BTCL real, dimension(SZIB_(G),SZJ_(G)), intent(out) :: & Coru_avg !< The average zonal barotropic Coriolis acceleration [L T-2 ~> m s-2] real, dimension(SZIB_(G),SZJ_(G)), intent(out) :: & - PFu_avg !< The summed zonal barotropic pressure gradient force [L T-2 ~> m s-2] + PFu_avg !< The average zonal barotropic pressure gradient force [L T-2 ~> m s-2] + real, dimension(SZIB_(G),SZJ_(G)), intent(out) :: & + LDu_avg !< The average zonal barotropic linear wave drag acceleration [L T-2 ~> m s-2] real, dimension(SZI_(G),SZJB_(G)), intent(out) :: & Corv_avg !< The average meridional barotropic Coriolis acceleration [L T-2 ~> m s-2] real, dimension(SZI_(G),SZJB_(G)), intent(out) :: & PFv_avg !< The average meridional barotropic pressure gradient force [L T-2 ~> m s-2] + real, dimension(SZI_(G),SZJB_(G)), intent(out) :: & + LDv_avg !< The average meridional barotropic linear wave drag acceleration [L T-2 ~> m s-2] logical, intent(in) :: use_BT_cont !< If true, use the information in the bt_cont_types to !! calculate the mass transports logical, intent(in) :: interp_eta_PF !< If true, interpolate the reference value of eta used @@ -2261,6 +2302,7 @@ subroutine btstep_timeloop(eta, ubt, vbt, uhbt0, Datu, BTCL_u, vhbt0, Datv, BTCL real, dimension(nstep+nfilter+1), intent(in) :: & wt_accel2 !< Potentially un-normalized relative weights of each of the !! barotropic timesteps in determining the average accelerations [nondim] + type(accel_diag_ptrs), pointer :: ADp !< Acceleration diagnostic pointers type(ocean_OBC_type), pointer :: OBC !< An associated pointer to an OBC type type(BT_OBC_type), intent(in) :: BT_OBC !< A structure with the private barotropic arrays !! related to the open boundary conditions, @@ -2351,7 +2393,10 @@ subroutine btstep_timeloop(eta, ubt, vbt, uhbt0, Datu, BTCL_u, vhbt0, Datv, BTCL ! Manage diagnostics do_ave = query_averaging_enabled(CS%diag) .and. & - ((CS%id_PFu_bt > 0) .or. (CS%id_PFv_bt > 0) .or. (CS%id_Coru_bt > 0) .or. (CS%id_Corv_bt > 0)) + ((CS%id_PFu_bt > 0) .or. (CS%id_Coru_bt > 0) .or. (CS%id_LDu_bt > 0) .or. & + (CS%id_PFv_bt > 0) .or. (CS%id_Corv_bt > 0) .or. (CS%id_LDv_bt > 0) .or. & + associated(ADp%bt_pgf_u) .or. associated(ADp%bt_cor_u) .or. associated(ADp%bt_lwd_u) .or. & + associated(ADp%bt_pgf_v) .or. associated(ADp%bt_cor_v) .or. associated(ADp%bt_lwd_v)) do_hifreq_output = .false. if ((CS%id_ubt_hifreq > 0) .or. (CS%id_vbt_hifreq > 0) .or. & @@ -2379,7 +2424,7 @@ subroutine btstep_timeloop(eta, ubt, vbt, uhbt0, Datu, BTCL_u, vhbt0, Datv, BTCL do j=js,je ; do I=is-1,ie CS%ubtav(I,j) = 0.0 ; uhbtav(I,j) = 0.0 PFu_avg(I,j) = 0.0 ; Coru_avg(I,j) = 0.0 - ubt_wtd(I,j) = 0.0 + LDu_avg(I,j) = 0.0 ; ubt_wtd(I,j) = 0.0 enddo ; enddo !$OMP do do j=jsvf-1,jevf+1 ; do I=isvf-1,ievf @@ -2389,7 +2434,7 @@ subroutine btstep_timeloop(eta, ubt, vbt, uhbt0, Datu, BTCL_u, vhbt0, Datv, BTCL do J=js-1,je ; do i=is,ie CS%vbtav(i,J) = 0.0 ; vhbtav(i,J) = 0.0 PFv_avg(i,J) = 0.0 ; Corv_avg(i,J) = 0.0 - vbt_wtd(i,J) = 0.0 + LDv_avg(i,J) = 0.0 ; vbt_wtd(i,J) = 0.0 enddo ; enddo !$OMP do do J=jsvf-1,jevf ; do i=isvf-1,ievf+1 @@ -2644,34 +2689,51 @@ subroutine btstep_timeloop(eta, ubt, vbt, uhbt0, Datu, BTCL_u, vhbt0, Datv, BTCL ! Accumulate some diagnostics of time-averaged barotropic accelerations. if (do_ave) then - if (CS%id_PFu_bt > 0) then + if ((CS%id_PFu_bt > 0) .or. associated(ADp%bt_pgf_u)) then !$OMP do do j=js,je ; do I=is-1,ie PFu_avg(I,j) = PFu_avg(I,j) + wt_accel2(n) * PFu(I,j) enddo ; enddo !$OMP end do nowait endif - if (CS%id_PFv_bt > 0) then + if ((CS%id_PFv_bt > 0) .or. associated(ADp%bt_pgf_v)) then !$OMP do do J=js-1,je ; do i=is,ie PFv_avg(i,J) = PFv_avg(i,J) + wt_accel2(n) * PFv(i,J) enddo ; enddo !$OMP end do nowait endif - if (CS%id_Coru_bt > 0) then + if ((CS%id_Coru_bt > 0) .or. associated(ADp%bt_cor_u)) then !$OMP do do j=js,je ; do I=is-1,ie Coru_avg(I,j) = Coru_avg(I,j) + wt_accel2(n) * Cor_u(I,j) enddo ; enddo !$OMP end do nowait endif - if (CS%id_Corv_bt > 0) then + if ((CS%id_Corv_bt > 0) .or. associated(ADp%bt_cor_v)) then !$OMP do do J=js-1,je ; do i=is,ie Corv_avg(i,J) = Corv_avg(i,J) + wt_accel2(n) * Cor_v(i,J) enddo ; enddo !$OMP end do nowait endif + + if (CS%linear_wave_drag) then + if ((CS%id_LDu_bt > 0) .or. (associated(ADp%bt_lwd_u))) then + !$OMP do + do j=js,je ; do I=is-1,ie + LDu_avg(I,j) = LDu_avg(I,j) - wt_accel2(n) * (ubt(I,j) * Rayleigh_u(I,j)) + enddo ; enddo + !$OMP end do nowait + endif + if ((CS%id_LDv_bt > 0) .or. (associated(ADp%bt_lwd_v))) then + !$OMP do + do J=js-1,je ; do i=is,ie + LDv_avg(i,J) = LDv_avg(i,J) - wt_accel2(n) * (vbt(i,J) * Rayleigh_v(i,J)) + enddo ; enddo + !$OMP end do nowait + endif + endif endif if (do_hifreq_output) then @@ -5304,7 +5366,7 @@ subroutine barotropic_init(u, v, h, Time, G, GV, US, param_file, diag, CS, & call get_param(param_file, mdl, "BT_WAVE_DRAG_FILE", wave_drag_file, & "The name of the file with the barotropic linear wave drag "//& "piston velocities.", default="", & - do_not_log=.not.CS%linear_wave_drag.and..not.CS%linear_freq_drag) + do_not_log=(.not.CS%linear_wave_drag) .and. (.not.CS%linear_freq_drag)) call get_param(param_file, mdl, "BT_WAVE_DRAG_VAR", wave_drag_var, & "The name of the variable in BT_WAVE_DRAG_FILE with the "//& "barotropic linear wave drag piston velocities at h points. "//& @@ -5656,6 +5718,12 @@ subroutine barotropic_init(u, v, h, Time, G, GV, US, param_file, diag, CS, & 'Zonal Anomalous Barotropic Pressure Force Acceleration', 'm s-2', conversion=US%L_T2_to_m_s2) CS%id_PFv_bt = register_diag_field('ocean_model', 'PFvBT', diag%axesCv1, Time, & 'Meridional Anomalous Barotropic Pressure Force Acceleration', 'm s-2', conversion=US%L_T2_to_m_s2) + if (CS%linear_wave_drag .or. (CS%use_filter .and. CS%linear_freq_drag)) then + CS%id_LDu_bt = register_diag_field('ocean_model', 'WaveDraguBT', diag%axesCu1, Time, & + 'Zonal Barotropic Linear Wave Drag Acceleration', 'm s-2', conversion=US%L_T2_to_m_s2) + CS%id_LDv_bt = register_diag_field('ocean_model', 'WaveDragvBT', diag%axesCv1, Time, & + 'Meridional Barotropic Linear Wave Drag Acceleration', 'm s-2', conversion=US%L_T2_to_m_s2) + endif CS%id_Coru_bt = register_diag_field('ocean_model', 'CoruBT', diag%axesCu1, Time, & 'Zonal Barotropic Coriolis Acceleration', 'm s-2', conversion=US%L_T2_to_m_s2) CS%id_Corv_bt = register_diag_field('ocean_model', 'CorvBT', diag%axesCv1, Time, & @@ -5793,7 +5861,7 @@ subroutine barotropic_init(u, v, h, Time, G, GV, US, param_file, diag, CS, & do J=js-1,je ; do i=is,ie ; CS%vbt_IC(i,J) = CS%vbtav(i,J) ; enddo ; enddo endif endif -! Calculate other constants which are used for btstep. + ! Calculate other constants which are used for btstep. if (.not.CS%nonlin_stress) then Mean_SL = G%Z_ref @@ -5829,7 +5897,7 @@ subroutine barotropic_init(u, v, h, Time, G, GV, US, param_file, diag, CS, & call create_group_pass(pass_bt_hbt_btav, CS%ubtav, CS%vbtav, G%Domain) call do_group_pass(pass_bt_hbt_btav, G%Domain) -! id_clock_pass = cpu_clock_id('(Ocean BT halo updates)', grain=CLOCK_ROUTINE) + ! id_clock_pass = cpu_clock_id('(Ocean BT halo updates)', grain=CLOCK_ROUTINE) id_clock_calc_pre = cpu_clock_id('(Ocean BT pre-calcs only)', grain=CLOCK_ROUTINE) id_clock_pass_pre = cpu_clock_id('(Ocean BT pre-step halo updates)', grain=CLOCK_ROUTINE) id_clock_calc = cpu_clock_id('(Ocean BT stepping calcs only)', grain=CLOCK_ROUTINE) diff --git a/src/core/MOM_dynamics_split_RK2.F90 b/src/core/MOM_dynamics_split_RK2.F90 index 5ab26f1097..db0d7458ba 100644 --- a/src/core/MOM_dynamics_split_RK2.F90 +++ b/src/core/MOM_dynamics_split_RK2.F90 @@ -490,7 +490,7 @@ subroutine step_MOM_dyn_split_RK2(u_inst, v_inst, h, tv, visc, Time_local, dt, f if (CS%begw == 0.0) call enable_averages(dt, Time_local, CS%diag) call cpu_clock_begin(id_clock_pres) call PressureForce(h, tv, CS%PFu, CS%PFv, G, GV, US, CS%PressureForce_CSp, & - CS%ALE_CSp, p_surf, CS%pbce, CS%eta_PF) + CS%ALE_CSp, CS%ADp, p_surf, CS%pbce, CS%eta_PF) if (dyn_p_surf) then pres_to_eta = 1.0 / (GV%g_Earth * GV%H_to_RZ) !$OMP parallel do default(shared) @@ -817,7 +817,7 @@ subroutine step_MOM_dyn_split_RK2(u_inst, v_inst, h, tv, visc, Time_local, dt, f ! pbce = dM/deta call cpu_clock_begin(id_clock_pres) call PressureForce(hp, tv, CS%PFu, CS%PFv, G, GV, US, CS%PressureForce_CSp, & - CS%ALE_CSp, p_surf, CS%pbce, CS%eta_PF) + CS%ALE_CSp, CS%ADp, p_surf, CS%pbce, CS%eta_PF) ! Stokes shear force contribution to pressure gradient Use_Stokes_PGF = present(Waves) if (Use_Stokes_PGF) then @@ -1521,7 +1521,7 @@ subroutine initialize_dyn_split_RK2(u, v, h, tv, uh, vh, eta, Time, G, GV, US, p else HA_CSp => NULL() endif - call PressureForce_init(Time, G, GV, US, param_file, diag, CS%PressureForce_CSp, & + call PressureForce_init(Time, G, GV, US, param_file, diag, CS%PressureForce_CSp, CS%ADp, & CS%SAL_CSp, CS%tides_CSp) call hor_visc_init(Time, G, GV, US, param_file, diag, CS%hor_visc, ADp=CS%ADp) call vertvisc_init(MIS, Time, G, GV, US, param_file, diag, CS%ADp, dirs, ntrunc, CS%vertvisc_CSp) diff --git a/src/core/MOM_dynamics_split_RK2b.F90 b/src/core/MOM_dynamics_split_RK2b.F90 index 28c8b6b35f..7896000a28 100644 --- a/src/core/MOM_dynamics_split_RK2b.F90 +++ b/src/core/MOM_dynamics_split_RK2b.F90 @@ -504,7 +504,7 @@ subroutine step_MOM_dyn_split_RK2b(u_av, v_av, h, tv, visc, Time_local, dt, forc if (CS%begw == 0.0) call enable_averages(dt, Time_local, CS%diag) call cpu_clock_begin(id_clock_pres) call PressureForce(h, tv, CS%PFu, CS%PFv, G, GV, US, CS%PressureForce_CSp, & - CS%ALE_CSp, p_surf, CS%pbce, CS%eta_PF) + CS%ALE_CSp, CS%ADp, p_surf, CS%pbce, CS%eta_PF) if (dyn_p_surf) then pres_to_eta = 1.0 / (GV%g_Earth * GV%H_to_RZ) !$OMP parallel do default(shared) @@ -827,7 +827,7 @@ subroutine step_MOM_dyn_split_RK2b(u_av, v_av, h, tv, visc, Time_local, dt, forc ! pbce = dM/deta call cpu_clock_begin(id_clock_pres) call PressureForce(hp, tv, CS%PFu, CS%PFv, G, GV, US, CS%PressureForce_CSp, & - CS%ALE_CSp, p_surf, CS%pbce, CS%eta_PF) + CS%ALE_CSp, CS%ADp, p_surf, CS%pbce, CS%eta_PF) ! Stokes shear force contribution to pressure gradient if (present(Waves)) then ; if (associated(Waves)) then ; if (Waves%Stokes_PGF) then call thickness_to_dz(h, tv, dz, G, GV, US, halo_size=1) @@ -1434,7 +1434,7 @@ subroutine initialize_dyn_split_RK2b(u, v, h, tv, uh, vh, eta, Time, G, GV, US, else HA_CSp => NULL() endif - call PressureForce_init(Time, G, GV, US, param_file, diag, CS%PressureForce_CSp, & + call PressureForce_init(Time, G, GV, US, param_file, diag, CS%PressureForce_CSp, CS%ADp, & CS%SAL_CSp, CS%tides_CSp) call hor_visc_init(Time, G, GV, US, param_file, diag, CS%hor_visc, ADp=CS%ADp) call vertvisc_init(MIS, Time, G, GV, US, param_file, diag, CS%ADp, dirs, & diff --git a/src/core/MOM_dynamics_unsplit.F90 b/src/core/MOM_dynamics_unsplit.F90 index c4b7c89edc..e35fe104f1 100644 --- a/src/core/MOM_dynamics_unsplit.F90 +++ b/src/core/MOM_dynamics_unsplit.F90 @@ -316,7 +316,7 @@ subroutine step_MOM_dyn_unsplit(u, v, h, tv, visc, Time_local, dt, forces, & p_surf(i,j) = 0.75*p_surf_begin(i,j) + 0.25*p_surf_end(i,j) enddo ; enddo ; endif call PressureForce(h_av, tv, CS%PFu, CS%PFv, G, GV, US, & - CS%PressureForce_CSp, CS%ALE_CSp, p_surf) + CS%PressureForce_CSp, CS%ALE_CSp, CS%ADp, p_surf) call cpu_clock_end(id_clock_pres) if (associated(CS%OBC)) then ; if (CS%OBC%update_OBC) then @@ -383,7 +383,7 @@ subroutine step_MOM_dyn_unsplit(u, v, h, tv, visc, Time_local, dt, forces, & p_surf(i,j) = 0.25*p_surf_begin(i,j) + 0.75*p_surf_end(i,j) enddo ; enddo ; endif call PressureForce(h_av, tv, CS%PFu, CS%PFv, G, GV, US, & - CS%PressureForce_CSp, CS%ALE_CSp, p_surf) + CS%PressureForce_CSp, CS%ALE_CSp, CS%ADp, p_surf) call cpu_clock_end(id_clock_pres) if (associated(CS%OBC)) then ; if (CS%OBC%update_OBC) then @@ -476,7 +476,7 @@ subroutine step_MOM_dyn_unsplit(u, v, h, tv, visc, Time_local, dt, forces, & ! PFu = d/dx M(h_av,T,S) call cpu_clock_begin(id_clock_pres) call PressureForce(h_av, tv, CS%PFu, CS%PFv, G, GV, US, & - CS%PressureForce_CSp, CS%ALE_CSp, p_surf) + CS%PressureForce_CSp, CS%ALE_CSp, CS%ADp, p_surf) call cpu_clock_end(id_clock_pres) if (associated(CS%OBC)) then ; if (CS%OBC%update_OBC) then @@ -709,7 +709,7 @@ subroutine initialize_dyn_unsplit(u, v, h, Time, G, GV, US, param_file, diag, CS call CoriolisAdv_init(Time, G, GV, US, param_file, diag, CS%ADp, CS%CoriolisAdv) if (CS%calculate_SAL) call SAL_init(G, GV, US, param_file, CS%SAL_CSp) if (CS%use_tides) call tidal_forcing_init(Time, G, US, param_file, CS%tides_CSp) - call PressureForce_init(Time, G, GV, US, param_file, diag, CS%PressureForce_CSp, & + call PressureForce_init(Time, G, GV, US, param_file, diag, CS%PressureForce_CSp, CS%ADp, & CS%SAL_CSp, CS%tides_CSp) call hor_visc_init(Time, G, GV, US, param_file, diag, CS%hor_visc) call vertvisc_init(MIS, Time, G, GV, US, param_file, diag, CS%ADp, dirs, & diff --git a/src/core/MOM_dynamics_unsplit_RK2.F90 b/src/core/MOM_dynamics_unsplit_RK2.F90 index 7ca2c700f7..547add6327 100644 --- a/src/core/MOM_dynamics_unsplit_RK2.F90 +++ b/src/core/MOM_dynamics_unsplit_RK2.F90 @@ -311,7 +311,7 @@ subroutine step_MOM_dyn_unsplit_RK2(u_in, v_in, h_in, tv, visc, Time_local, dt, if (dyn_p_surf) then ; do j=js-2,je+2 ; do i=is-2,ie+2 p_surf(i,j) = 0.5*p_surf_begin(i,j) + 0.5*p_surf_end(i,j) enddo ; enddo ; endif - call PressureForce(h_in, tv, CS%PFu, CS%PFv, G, GV, US, CS%PressureForce_CSp, CS%ALE_CSp, p_surf) + call PressureForce(h_in, tv, CS%PFu, CS%PFv, G, GV, US, CS%PressureForce_CSp, CS%ALE_CSp, CS%ADp, p_surf) call cpu_clock_end(id_clock_pres) call pass_vector(CS%PFu, CS%PFv, G%Domain, clock=id_clock_pass) call pass_vector(CS%CAu, CS%CAv, G%Domain, clock=id_clock_pass) @@ -673,7 +673,7 @@ subroutine initialize_dyn_unsplit_RK2(u, v, h, Time, G, GV, US, param_file, diag call CoriolisAdv_init(Time, G, GV, US, param_file, diag, CS%ADp, CS%CoriolisAdv) if (CS%calculate_SAL) call SAL_init(G, GV, US, param_file, CS%SAL_CSp) if (CS%use_tides) call tidal_forcing_init(Time, G, US, param_file, CS%tides_CSp) - call PressureForce_init(Time, G, GV, US, param_file, diag, CS%PressureForce_CSp, & + call PressureForce_init(Time, G, GV, US, param_file, diag, CS%PressureForce_CSp, CS%ADp, & CS%SAL_CSp, CS%tides_CSp) call hor_visc_init(Time, G, GV, US, param_file, diag, CS%hor_visc) call vertvisc_init(MIS, Time, G, GV, US, param_file, diag, CS%ADp, dirs, & diff --git a/src/core/MOM_variables.F90 b/src/core/MOM_variables.F90 index 30e40313bb..e849ffa018 100644 --- a/src/core/MOM_variables.F90 +++ b/src/core/MOM_variables.F90 @@ -180,10 +180,16 @@ module MOM_variables !! in du_dt_visc) [L T-2 ~> m s-2] dv_dt_str => NULL(), & !< Meridional acceleration due to the surface stress (included !! in dv_dt_visc) [L T-2 ~> m s-2] - du_dt_dia => NULL(), & !< Zonal acceleration due to diapycnal mixing [L T-2 ~> m s-2] - dv_dt_dia => NULL(), & !< Meridional acceleration due to diapycnal mixing [L T-2 ~> m s-2] + du_dt_dia => NULL(), & !< Zonal acceleration due to diapycnal mixing [L T-2 ~> m s-2] + dv_dt_dia => NULL(), & !< Meridional acceleration due to diapycnal mixing [L T-2 ~> m s-2] u_accel_bt => NULL(), &!< Pointer to the zonal barotropic-solver acceleration [L T-2 ~> m s-2] - v_accel_bt => NULL() !< Pointer to the meridional barotropic-solver acceleration [L T-2 ~> m s-2] + v_accel_bt => NULL(), &!< Pointer to the meridional barotropic-solver acceleration [L T-2 ~> m s-2] + + ! sal_[uv] and tide_[uv] are 3D fields because of their baroclinic component in Boussinesq mode. + sal_u => NULL(), & !< Zonal acceleration due to self-attraction and loading [L T-2 ~> m s-2] + sal_v => NULL(), & !< Meridional acceleration due to self-attraction and loading [L T-2 ~> m s-2] + tides_u => NULL(), & !< Zonal acceleration due to astronomical tidal forcing [L T-2 ~> m s-2] + tides_v => NULL() !< Meridional acceleration due to astronomical tidal forcing [L T-2 ~> m s-2] real, pointer, dimension(:,:,:) :: du_other => NULL() !< Zonal velocity changes due to any other processes that are !! not due to any explicit accelerations [L T-1 ~> m s-1]. @@ -191,6 +197,24 @@ module MOM_variables !< Meridional velocity changes due to any other processes that are !! not due to any explicit accelerations [L T-1 ~> m s-1]. + ! Sub-terms of [uv]_accel_bt + real, pointer :: bt_pgf_u(:,:,:) => NULL() !< Zonal acceleration due to anomalous pressure gradient from + !! barotropic solver, a 3D component of u_accel_bt that includes both + !! PFuBT and the offset term for central differencing timestepping + !! [L T-2 ~> m s-2] + real, pointer :: bt_pgf_v(:,:,:) => NULL() !< Meridional acceleration due to anomalous pressure gradient from + !! barotropic solver, a 3D component of v_accel_bt that includes both + !! PFvBT and the offset term for central differencing timestepping + !! [L T-2 ~> m s-2] + real, pointer :: bt_cor_u(:,:) => NULL() !< Zonal acceleration due to anomalous Coriolis force from barotropic + !! solver, a 2D component of u_accel_bt [L T-2 ~> m s-2] + real, pointer :: bt_cor_v(:,:) => NULL() !< Meridional acceleration due to anomalous Coriolis force from barotropic + !! solver, a 2D component of v_accel_bt [L T-2 ~> m s-2] + real, pointer :: bt_lwd_u(:,:) => NULL() !< Zonal acceleration due to linear wave drag from barotropic solver, + !! a 2D component of u_accel_bt [L T-2 ~> m s-2] + real, pointer :: bt_lwd_v(:,:) => NULL() !< Meridional acceleration due to linear wave drag from barotropic solver, + !! a 2D component of v_accel_bt [L T-2 ~> m s-2] + ! These accelerations are sub-terms included in the accelerations above. real, pointer :: gradKEu(:,:,:) => NULL() !< gradKEu = - d/dx(u2) [L T-2 ~> m s-2] real, pointer :: gradKEv(:,:,:) => NULL() !< gradKEv = - d/dy(u2) [L T-2 ~> m s-2] diff --git a/src/diagnostics/MOM_diagnostics.F90 b/src/diagnostics/MOM_diagnostics.F90 index 4d7d9f79e9..d164363ec4 100644 --- a/src/diagnostics/MOM_diagnostics.F90 +++ b/src/diagnostics/MOM_diagnostics.F90 @@ -81,6 +81,10 @@ module MOM_diagnostics integer :: id_col_ht = -1, id_dh_dt = -1 integer :: id_KE = -1, id_dKEdt = -1 integer :: id_PE_to_KE = -1, id_KE_BT = -1 + integer :: id_KE_SAL = -1, id_KE_TIDES = -1 + integer :: id_KE_BT_PF = -1, id_KE_BT_CF = -1 + integer :: id_KE_BT_WD = -1 + integer :: id_PE_to_KE_btbc = -1, id_KE_Coradv_btbc = -1 integer :: id_KE_Coradv = -1, id_KE_adv = -1 integer :: id_KE_visc = -1, id_KE_stress = -1 integer :: id_KE_visc_gl90 = -1 @@ -1078,7 +1082,45 @@ subroutine calculate_energy_diagnostics(u, v, h, uh, vh, ADp, CDp, G, GV, US, CS * ((KE_u(I,j) + KE_u(I-1,j)) + (KE_v(i,J) + KE_v(i,J-1))) enddo ; enddo enddo - if (CS%id_PE_to_KE > 0) call post_data(CS%id_PE_to_KE, KE_term, CS%diag) + call post_data(CS%id_PE_to_KE, KE_term, CS%diag) + endif + + if (CS%id_KE_SAL > 0) then + ! Calculate the KE source from self-attraction and loading [H L2 T-3 ~> m3 s-3 or W m-2]. + do k=1,nz + do j=js,je ; do I=Isq,Ieq + KE_u(I,j) = uh(I,j,k) * G%dxCu(I,j) * ADp%sal_u(I,j,k) + enddo ; enddo + do J=Jsq,Jeq ; do i=is,ie + KE_v(i,J) = vh(i,J,k) * G%dyCv(i,J) * ADp%sal_v(i,J,k) + enddo ; enddo + if (.not.G%symmetric) & + call do_group_pass(CS%pass_KE_uv, G%domain) + do j=js,je ; do i=is,ie + KE_term(i,j,k) = 0.5 * G%IareaT(i,j) & + * ((KE_u(I,j) + KE_u(I-1,j)) + (KE_v(i,J) + KE_v(i,J-1))) + enddo ; enddo + enddo + call post_data(CS%id_KE_SAL, KE_term, CS%diag) + endif + + if (CS%id_KE_TIDES > 0) then + ! Calculate the KE source from astronomical tidal forcing [H L2 T-3 ~> m3 s-3 or W m-2]. + do k=1,nz + do j=js,je ; do I=Isq,Ieq + KE_u(I,j) = uh(I,j,k) * G%dxCu(I,j) * ADp%tides_u(I,j,k) + enddo ; enddo + do J=Jsq,Jeq ; do i=is,ie + KE_v(i,J) = vh(i,J,k) * G%dyCv(i,J) * ADp%tides_v(i,J,k) + enddo ; enddo + if (.not.G%symmetric) & + call do_group_pass(CS%pass_KE_uv, G%domain) + do j=js,je ; do i=is,ie + KE_term(i,j,k) = 0.5 * G%IareaT(i,j) & + * ((KE_u(I,j) + KE_u(I-1,j)) + (KE_v(i,J) + KE_v(i,J-1))) + enddo ; enddo + enddo + call post_data(CS%id_KE_TIDES, KE_term, CS%diag) endif if (CS%id_KE_BT > 0) then @@ -1100,6 +1142,107 @@ subroutine calculate_energy_diagnostics(u, v, h, uh, vh, ADp, CDp, G, GV, US, CS call post_data(CS%id_KE_BT, KE_term, CS%diag) endif + if (CS%id_PE_to_KE_btbc > 0) then + ! Calculate the potential energy to KE term including barotropic solver contribution + ! [H L2 T-3 ~> m3 s-3 or W m-2]. + do k=1,nz + do j=js,je ; do I=Isq,Ieq + KE_u(I,j) = uh(I,j,k) * G%dxCu(I,j) * (ADp%PFu(I,j,k) + ADp%bt_pgf_u(I,j,k)) + enddo ; enddo + do J=Jsq,Jeq ; do i=is,ie + KE_v(i,J) = vh(i,J,k) * G%dyCv(i,J) * (ADp%PFv(i,J,k) + ADp%bt_pgf_v(i,J,k)) + enddo ; enddo + if (.not.G%symmetric) & + call do_group_pass(CS%pass_KE_uv, G%domain) + do j=js,je ; do i=is,ie + KE_term(i,j,k) = 0.5 * G%IareaT(i,j) & + * ((KE_u(I,j) + KE_u(I-1,j)) + (KE_v(i,J) + KE_v(i,J-1))) + enddo ; enddo + enddo + call post_data(CS%id_PE_to_KE_btbc, KE_term, CS%diag) + endif + + if (CS%id_KE_Coradv_btbc > 0) then + ! Calculate the KE source from Coriolis and advection terms including barotropic solver contribution + ! [H L2 T-3 ~> m3 s-3 or W m-2]. + do k=1,nz + do j=js,je ; do I=Isq,Ieq + KE_u(I,j) = uh(I,j,k) * G%dxCu(I,j) * (ADp%CAu(I,j,k) + ADp%bt_cor_u(I,j)) + enddo ; enddo + do J=Jsq,Jeq ; do i=is,ie + KE_v(i,J) = vh(i,J,k) * G%dyCv(i,J) * (ADp%CAv(i,J,k) + ADp%bt_cor_v(i,J)) + enddo ; enddo + do j=js,je ; do i=is,ie + KE_h(i,j) = -KE(i,j,k) * G%IareaT(i,j) & + * ((uh(I,j,k) - uh(I-1,j,k)) + (vh(i,J,k) - vh(i,J-1,k))) + enddo ; enddo + if (.not.G%symmetric) & + call do_group_pass(CS%pass_KE_uv, G%domain) + do j=js,je ; do i=is,ie + KE_term(i,j,k) = KE_h(i,j) + 0.5 * G%IareaT(i,j) & + * ((KE_u(I,j) + KE_u(I-1,j)) + (KE_v(i,J) + KE_v(i,J-1))) + enddo ; enddo + enddo + call post_data(CS%id_KE_Coradv_btbc, KE_term, CS%diag) + endif + + if (CS%id_KE_BT_PF > 0) then + ! Calculate the anomalous pressure gradient force contribution to KE term [H L2 T-3 ~> m3 s-3 or W m-2]. + do k=1,nz + do j=js,je ; do I=Isq,Ieq + KE_u(I,j) = uh(I,j,k) * G%dxCu(I,j) * ADp%bt_pgf_u(I,j,k) + enddo ; enddo + do J=Jsq,Jeq ; do i=is,ie + KE_v(i,J) = vh(i,J,k) * G%dyCv(i,J) * ADp%bt_pgf_v(i,J,k) + enddo ; enddo + if (.not.G%symmetric) & + call do_group_pass(CS%pass_KE_uv, G%domain) + do j=js,je ; do i=is,ie + KE_term(i,j,k) = 0.5 * G%IareaT(i,j) & + * ((KE_u(I,j) + KE_u(I-1,j)) + (KE_v(i,J) + KE_v(i,J-1))) + enddo ; enddo + enddo + call post_data(CS%id_KE_BT_PF, KE_term, CS%diag) + endif + + if (CS%id_KE_BT_CF > 0) then + ! Calculate the anomalous Coriolis force contribution to KE term [H L2 T-3 ~> m3 s-3 or W m-2]. + do k=1,nz + do j=js,je ; do I=Isq,Ieq + KE_u(I,j) = uh(I,j,k) * G%dxCu(I,j) * ADp%bt_cor_u(I,j) + enddo ; enddo + do J=Jsq,Jeq ; do i=is,ie + KE_v(i,J) = vh(i,J,k) * G%dyCv(i,J) * ADp%bt_cor_v(i,J) + enddo ; enddo + if (.not.G%symmetric) & + call do_group_pass(CS%pass_KE_uv, G%domain) + do j=js,je ; do i=is,ie + KE_term(i,j,k) = 0.5 * G%IareaT(i,j) & + * ((KE_u(I,j) + KE_u(I-1,j)) + (KE_v(i,J) + KE_v(i,J-1))) + enddo ; enddo + enddo + call post_data(CS%id_KE_BT_CF, KE_term, CS%diag) + endif + + if (CS%id_KE_BT_WD > 0) then + ! Calculate the barotropic linear wave drag contribution to KE term [H L2 T-3 ~> m3 s-3 or W m-2]. + do k=1,nz + do j=js,je ; do I=Isq,Ieq + KE_u(I,j) = uh(I,j,k) * G%dxCu(I,j) * ADp%bt_lwd_u(I,j) + enddo ; enddo + do J=Jsq,Jeq ; do i=is,ie + KE_v(i,J) = vh(i,J,k) * G%dyCv(i,J) * ADp%bt_lwd_v(i,J) + enddo ; enddo + if (.not.G%symmetric) & + call do_group_pass(CS%pass_KE_uv, G%domain) + do j=js,je ; do i=is,ie + KE_term(i,j,k) = 0.5 * G%IareaT(i,j) & + * ((KE_u(I,j) + KE_u(I-1,j)) + (KE_v(i,J) + KE_v(i,J-1))) + enddo ; enddo + enddo + call post_data(CS%id_KE_BT_WD, KE_term, CS%diag) + endif + if (CS%id_KE_Coradv > 0) then ! Calculate the KE source from the combined Coriolis and advection terms [H L2 T-3 ~> m3 s-3 or W m-2]. ! The Coriolis source should be zero, but is not due to truncation errors. There should be @@ -1636,6 +1779,8 @@ subroutine MOM_diagnostics_init(MIS, ADp, CDp, Time, G, GV, US, param_file, diag logical :: better_speed_est ! If true, use a more robust estimate of the first ! mode wave speed as the starting point for iterations. logical :: split ! True if using the barotropic-baroclinic split algorithm + logical :: calc_tides ! True if using tidal forcing + logical :: calc_sal ! True if using self-attraction and loading logical :: om4_remap_via_sub_cells ! Use the OM4-era ramap_via_sub_cells for calculating the EBT structure ! This include declares and sets the variable "version". # include "version_variable.h" @@ -1693,6 +1838,8 @@ subroutine MOM_diagnostics_init(MIS, ADp, CDp, Time, G, GV, US, param_file, diag if (.not.GV%Boussinesq) remap_answer_date = max(remap_answer_date, 20230701) call get_param(param_file, mdl, "SPLIT", split, default=.true., do_not_log=.true.) + call get_param(param_file, mdl, "TIDES", calc_tides, default=.false., do_not_log=.true.) + call get_param(param_file, mdl, "CALCULATE_SAL", calc_sal, default=calc_tides, do_not_log=.true.) thickness_units = get_thickness_units(GV) flux_units = get_flux_units(GV) @@ -1889,10 +2036,33 @@ subroutine MOM_diagnostics_init(MIS, ADp, CDp, Time, G, GV, US, param_file, diag CS%id_PE_to_KE = register_diag_field('ocean_model', 'PE_to_KE', diag%axesTL, Time, & 'Potential to Kinetic Energy Conversion of Layer', & 'm3 s-3', conversion=GV%H_to_m*(US%L_T_to_m_s**2)*US%s_to_T) + if (calc_sal) & + CS%id_KE_SAL = register_diag_field('ocean_model', 'KE_SAL', diag%axesTL, Time, & + 'Kinetic Energy Source from Self-Attraction and Loading', & + 'm3 s-3', conversion=GV%H_to_m*(US%L_T_to_m_s**2)*US%s_to_T) + if (calc_tides) & + CS%id_KE_TIDES = register_diag_field('ocean_model', 'KE_tides', diag%axesTL, Time, & + 'Kinetic Energy Source from Astronomical Tidal Forcing', & + 'm3 s-3', conversion=GV%H_to_m*(US%L_T_to_m_s**2)*US%s_to_T) if (split) then CS%id_KE_BT = register_diag_field('ocean_model', 'KE_BT', diag%axesTL, Time, & 'Barotropic contribution to Kinetic Energy', & 'm3 s-3', conversion=GV%H_to_m*(US%L_T_to_m_s**2)*US%s_to_T) + CS%id_PE_to_KE_btbc = register_diag_field('ocean_model', 'PE_to_KE_btbc', diag%axesTL, Time, & + 'Potential to Kinetic Energy Conversion of Layer (including barotropic solver contribution)', & + 'm3 s-3', conversion=GV%H_to_m*(US%L_T_to_m_s**2)*US%s_to_T) + CS%id_KE_Coradv_btbc = register_diag_field('ocean_model', 'KE_Coradv_btbc', diag%axesTL, Time, & + 'Kinetic Energy Source from Coriolis and Advection (including barotropic solver contribution)', & + 'm3 s-3', conversion=GV%H_to_m*(US%L_T_to_m_s**2)*US%s_to_T) + CS%id_KE_BT_PF = register_diag_field('ocean_model', 'KE_BTPF', diag%axesTL, Time, & + 'Kinetic Energy Source from Barotropic Pressure Gradient Force.', & + 'm3 s-3', conversion=GV%H_to_m*(US%L_T_to_m_s**2)*US%s_to_T) + CS%id_KE_BT_CF = register_diag_field('ocean_model', 'KE_BTCF', diag%axesTL, Time, & + 'Kinetic Energy Source from Barotropic Coriolis Force.', & + 'm3 s-3', conversion=GV%H_to_m*(US%L_T_to_m_s**2)*US%s_to_T) + CS%id_KE_BT_WD = register_diag_field('ocean_model', 'KE_BTWD', diag%axesTL, Time, & + 'Kinetic Energy Source from Barotropic Linear Wave Drag.', & + 'm3 s-3', conversion=GV%H_to_m*(US%L_T_to_m_s**2)*US%s_to_T) endif CS%id_KE_Coradv = register_diag_field('ocean_model', 'KE_Coradv', diag%axesTL, Time, & 'Kinetic Energy Source from Coriolis and Advection', & @@ -2351,10 +2521,37 @@ subroutine set_dependent_diagnostics(MIS, ADp, CDp, G, GV, CS) call safe_alloc_ptr(CDp%diapyc_vel,isd,ied,jsd,jed,nz+1) endif + if ((CS%id_PE_to_KE_btbc > 0) .or. (CS%id_KE_BT_PF > 0)) then + call safe_alloc_ptr(ADp%bt_pgf_u, IsdB, IedB, jsd, jed, nz) + call safe_alloc_ptr(ADp%bt_pgf_v, isd, ied, JsdB, JedB, nz) + endif + + if ((CS%id_KE_Coradv_btbc > 0) .or. (CS%id_KE_BT_CF > 0)) then + call safe_alloc_ptr(ADp%bt_cor_u, IsdB, IedB, jsd, jed) + call safe_alloc_ptr(ADp%bt_cor_v, isd, ied, JsdB, JedB) + endif + + if (CS%id_KE_BT_WD > 0) then + call safe_alloc_ptr(ADp%bt_lwd_u, IsdB, IedB, jsd, jed) + call safe_alloc_ptr(ADp%bt_lwd_v, isd, ied, JsdB, JedB) + endif + + if (CS%id_KE_SAL > 0) then + call safe_alloc_ptr(ADp%sal_u, IsdB, IedB, jsd, jed, nz) + call safe_alloc_ptr(ADp%sal_v, isd, ied, JsdB, JedB, nz) + endif + + if (CS%id_KE_TIDES > 0) then + call safe_alloc_ptr(ADp%tides_u, IsdB, IedB, jsd, jed, nz) + call safe_alloc_ptr(ADp%tides_v, isd, ied, JsdB, JedB, nz) + endif + CS%KE_term_on = ((CS%id_dKEdt > 0) .or. (CS%id_PE_to_KE > 0) .or. (CS%id_KE_BT > 0) .or. & (CS%id_KE_Coradv > 0) .or. (CS%id_KE_adv > 0) .or. (CS%id_KE_visc > 0) .or. & (CS%id_KE_visc_gl90 > 0) .or. (CS%id_KE_stress > 0) .or. (CS%id_KE_horvisc > 0) .or. & - (CS%id_KE_dia > 0)) + (CS%id_KE_dia > 0) .or. (CS%id_PE_to_KE_btbc > 0) .or. (CS%id_KE_BT_PF > 0) .or. & + (CS%id_KE_Coradv_btbc > 0) .or. (CS%id_KE_BT_CF > 0) .or. (CS%id_KE_BT_WD > 0) .or. & + (CS%id_KE_SAL > 0) .or. (CS%id_KE_TIDES > 0)) if (CS%id_h_du_dt > 0) call safe_alloc_ptr(ADp%diag_hu,IsdB,IedB,jsd,jed,nz) if (CS%id_h_dv_dt > 0) call safe_alloc_ptr(ADp%diag_hv,isd,ied,JsdB,JedB,nz) @@ -2394,6 +2591,20 @@ subroutine MOM_diagnostics_end(CS, ADp, CDp) if (associated(ADp%du_other)) deallocate(ADp%du_other) if (associated(ADp%dv_other)) deallocate(ADp%dv_other) + if (associated(ADp%bt_pgf_u)) deallocate(ADp%bt_pgf_u) + if (associated(ADp%bt_pgf_v)) deallocate(ADp%bt_pgf_v) + if (associated(ADp%bt_cor_u)) deallocate(ADp%bt_cor_u) + if (associated(ADp%bt_cor_v)) deallocate(ADp%bt_cor_v) + if (associated(ADp%bt_lwd_u)) deallocate(ADp%bt_lwd_u) + if (associated(ADp%bt_lwd_v)) deallocate(ADp%bt_lwd_v) + + ! NOTE: sal_[uv] and tide_[uv] may be allocated either here (KE budget diagnostics) or + ! PressureForce module (momentum acceleration diagnostics) + if (associated(ADp%sal_u)) deallocate(ADp%sal_u) + if (associated(ADp%sal_v)) deallocate(ADp%sal_v) + if (associated(ADp%tides_u)) deallocate(ADp%tides_u) + if (associated(ADp%tides_v)) deallocate(ADp%tides_v) + if (associated(ADp%diag_hfrac_u)) deallocate(ADp%diag_hfrac_u) if (associated(ADp%diag_hfrac_v)) deallocate(ADp%diag_hfrac_v)