Skip to content
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

Stochastic GM+E #280

Merged
merged 4 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions config_src/external/stochastic_physics/stochastic_physics.F90
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module stochastic_physics

!> Initializes the stochastic physics perturbations.
subroutine init_stochastic_physics_ocn(delt, geoLonT, geoLatT, nx, ny, nz, pert_epbl_in, do_sppt_in, &
mpiroot, mpicomm, iret)
do_skeb_in,mpiroot, mpicomm, iret)
real, intent(in) :: delt !< timestep in seconds between calls to run_stochastic_physics_ocn [s]
integer, intent(in) :: nx !< number of gridpoints in the x-direction of the compute grid
integer, intent(in) :: ny !< number of gridpoints in the y-direction of the compute grid
Expand All @@ -25,6 +25,7 @@ subroutine init_stochastic_physics_ocn(delt, geoLonT, geoLatT, nx, ny, nz, pert_
real, intent(in) :: geoLatT(nx,ny) !< Latitude in degrees
logical, intent(in) :: pert_epbl_in !< logical flag, if true generate random pattern for ePBL perturbations
logical, intent(in) :: do_sppt_in !< logical flag, if true generate random pattern for SPPT perturbations
logical, intent(in) :: do_skeb_in !< logical flag, if true generate random pattern for SKEB perturbations
integer, intent(in) :: mpiroot !< root processor
integer, intent(in) :: mpicomm !< mpi communicator
integer, intent(out) :: iret !< return code
Expand All @@ -38,14 +39,20 @@ subroutine init_stochastic_physics_ocn(delt, geoLonT, geoLatT, nx, ny, nz, pert_
call MOM_error(WARNING, 'init_stochastic_physics_ocn: do_sppt needs to be false if using the stub')
iret=-1
endif
if (do_skeb_in) then
call MOM_error(WARNING, 'init_stochastic_physics_ocn: do_skeb needs to be false if using the stub')
iret=-1
endif

! This stub function does not actually do anything.
return
end subroutine init_stochastic_physics_ocn


!> Determines the stochastic physics perturbations.
subroutine run_stochastic_physics_ocn(sppt_wts, t_rp1, t_rp2)
subroutine run_stochastic_physics_ocn(sppt_wts, skeb_wts, t_rp1, t_rp2)
real, intent(inout) :: sppt_wts(:,:) !< array containing random weights for SPPT range [0,2]
real, intent(inout) :: skeb_wts(:,:) !< array containing random weights for SKEB
real, intent(inout) :: t_rp1(:,:) !< array containing random weights for ePBL
!! perturbations (KE generation) range [0,2]
real, intent(inout) :: t_rp2(:,:) !< array containing random weights for ePBL
Expand Down
22 changes: 15 additions & 7 deletions src/core/MOM.F90
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ module MOM
use MOM_diabatic_driver, only : diabatic, diabatic_driver_init, diabatic_CS, extract_diabatic_member
use MOM_diabatic_driver, only : adiabatic, adiabatic_driver_init, diabatic_driver_end
use MOM_diabatic_driver, only : register_diabatic_restarts
use MOM_stochastics, only : stochastics_init, update_stochastics, stochastic_CS
use MOM_stochastics, only : stochastics_init, update_stochastics, stochastic_CS, apply_skeb
use MOM_diagnostics, only : calculate_diagnostic_fields, MOM_diagnostics_init
use MOM_diagnostics, only : register_transport_diags, post_transport_diagnostics
use MOM_diagnostics, only : register_surface_diags, write_static_fields
Expand Down Expand Up @@ -741,7 +741,8 @@ subroutine step_MOM(forces_in, fluxes_in, sfc_state, Time_start, time_int_in, CS
endif
endif
! advance the random pattern if stochastic physics is active
if (CS%stoch_CS%do_sppt .OR. CS%stoch_CS%pert_epbl) call update_stochastics(CS%stoch_CS)
if (CS%stoch_CS%do_sppt .OR. CS%stoch_CS%pert_epbl .OR. CS%stoch_CS%do_skeb) &
call update_stochastics(CS%stoch_CS)

if (do_dyn) then
if (nonblocking_p_surf_update) &
Expand Down Expand Up @@ -1151,7 +1152,8 @@ subroutine step_MOM_dynamics(forces, p_surf_begin, p_surf_end, dt, dt_thermo, &
if (CS%VarMix%use_variable_mixing) &
call calc_slope_functions(h, CS%tv, dt, G, GV, US, CS%VarMix, OBC=CS%OBC)
call thickness_diffuse(h, CS%uhtr, CS%vhtr, CS%tv, dt_thermo, G, GV, US, &
CS%MEKE, CS%VarMix, CS%CDp, CS%thickness_diffuse_CSp)
CS%MEKE, CS%VarMix, CS%CDp, CS%thickness_diffuse_CSp, &
CS%stoch_CS)
call cpu_clock_end(id_clock_thick_diff)
call pass_var(h, G%Domain, clock=id_clock_pass, halo=max(2,CS%cont_stencil))
if (showCallTree) call callTree_waypoint("finished thickness_diffuse_first (step_MOM)")
Expand Down Expand Up @@ -1223,7 +1225,7 @@ subroutine step_MOM_dynamics(forces, p_surf_begin, p_surf_end, dt, dt_thermo, &
call step_MOM_dyn_split_RK2(u, v, h, CS%tv, CS%visc, Time_local, dt, forces, &
p_surf_begin, p_surf_end, CS%uh, CS%vh, CS%uhtr, CS%vhtr, &
CS%eta_av_bc, G, GV, US, CS%dyn_split_RK2_CSp, calc_dtbt, CS%VarMix, &
CS%MEKE, CS%thickness_diffuse_CSp, CS%pbv, waves=waves)
CS%MEKE, CS%thickness_diffuse_CSp, CS%pbv, CS%stoch_CS, waves=waves)
if (showCallTree) call callTree_waypoint("finished step_MOM_dyn_split (step_MOM)")

elseif (CS%do_dynamics) then ! ------------------------------------ not SPLIT
Expand All @@ -1237,11 +1239,13 @@ subroutine step_MOM_dynamics(forces, p_surf_begin, p_surf_end, dt, dt_thermo, &
if (CS%use_RK2) then
call step_MOM_dyn_unsplit_RK2(u, v, h, CS%tv, CS%visc, Time_local, dt, forces, &
p_surf_begin, p_surf_end, CS%uh, CS%vh, CS%uhtr, CS%vhtr, &
CS%eta_av_bc, G, GV, US, CS%dyn_unsplit_RK2_CSp, CS%VarMix, CS%MEKE, CS%pbv)
CS%eta_av_bc, G, GV, US, CS%dyn_unsplit_RK2_CSp, CS%VarMix, CS%MEKE, CS%pbv, &
CS%stoch_CS)
else
call step_MOM_dyn_unsplit(u, v, h, CS%tv, CS%visc, Time_local, dt, forces, &
p_surf_begin, p_surf_end, CS%uh, CS%vh, CS%uhtr, CS%vhtr, &
CS%eta_av_bc, G, GV, US, CS%dyn_unsplit_CSp, CS%VarMix, CS%MEKE, CS%pbv, Waves=Waves)
CS%eta_av_bc, G, GV, US, CS%dyn_unsplit_CSp, CS%VarMix, CS%MEKE, CS%pbv, &
CS%stoch_CS, Waves=Waves)
endif
if (showCallTree) call callTree_waypoint("finished step_MOM_dyn_unsplit (step_MOM)")

Expand Down Expand Up @@ -1282,7 +1286,7 @@ subroutine step_MOM_dynamics(forces, p_surf_begin, p_surf_end, dt, dt_thermo, &
if (CS%VarMix%use_variable_mixing) &
call calc_slope_functions(h, CS%tv, dt, G, GV, US, CS%VarMix, OBC=CS%OBC)
call thickness_diffuse(h, CS%uhtr, CS%vhtr, CS%tv, dt, G, GV, US, &
CS%MEKE, CS%VarMix, CS%CDp, CS%thickness_diffuse_CSp)
CS%MEKE, CS%VarMix, CS%CDp, CS%thickness_diffuse_CSp, CS%stoch_CS)

if (CS%debug) call hchksum(h,"Post-thickness_diffuse h", G%HI, haloshift=1, scale=GV%H_to_MKS)
call cpu_clock_end(id_clock_thick_diff)
Expand Down Expand Up @@ -1584,6 +1588,10 @@ subroutine step_MOM_thermo(CS, G, GV, US, u, v, h, tv, fluxes, dtdia, &
Time_end_thermo, G, GV, US, CS%diabatic_CSp, CS%stoch_CS, CS%OBC, Waves)
fluxes%fluxes_used = .true.

if (CS%stoch_CS%do_skeb) then
call apply_skeb(CS%G,CS%GV,CS%stoch_CS,CS%u,CS%v,CS%h,CS%tv,dtdia,Time_end_thermo)
endif

if (showCallTree) call callTree_waypoint("finished diabatic (step_MOM_thermo)")

! Regridding/remapping is done here, at end of thermodynamics time step
Expand Down
6 changes: 4 additions & 2 deletions src/core/MOM_dynamics_split_RK2.F90
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ module MOM_dynamics_split_RK2
use MOM_PressureForce, only : PressureForce, PressureForce_CS
use MOM_PressureForce, only : PressureForce_init
use MOM_set_visc, only : set_viscous_ML, set_visc_CS
use MOM_stochastics, only : stochastic_CS
use MOM_thickness_diffuse, only : thickness_diffuse_CS
use MOM_self_attr_load, only : SAL_CS
use MOM_self_attr_load, only : SAL_init, SAL_end
Expand Down Expand Up @@ -286,7 +287,7 @@ module MOM_dynamics_split_RK2
!> RK2 splitting for time stepping MOM adiabatic dynamics
subroutine step_MOM_dyn_split_RK2(u, v, h, tv, visc, Time_local, dt, forces, p_surf_begin, p_surf_end, &
uh, vh, uhtr, vhtr, eta_av, G, GV, US, CS, calc_dtbt, VarMix, &
MEKE, thickness_diffuse_CSp, pbv, Waves)
MEKE, thickness_diffuse_CSp, pbv, STOCH, Waves)
type(ocean_grid_type), intent(inout) :: G !< Ocean grid structure
type(verticalGrid_type), intent(in) :: GV !< Ocean vertical grid structure
type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
Expand Down Expand Up @@ -326,6 +327,7 @@ subroutine step_MOM_dyn_split_RK2(u, v, h, tv, visc, Time_local, dt, forces, p_s
type(thickness_diffuse_CS), intent(inout) :: thickness_diffuse_CSp !< Pointer to a structure containing
!! interface height diffusivities
type(porous_barrier_type), intent(in) :: pbv !< porous barrier fractional cell metrics
type(stochastic_CS), intent(inout) :: STOCH !< Stochastic control structure
type(wave_parameters_CS), optional, pointer :: Waves !< A pointer to a structure containing
!! fields related to the surface wave conditions

Expand Down Expand Up @@ -851,7 +853,7 @@ subroutine step_MOM_dyn_split_RK2(u, v, h, tv, visc, Time_local, dt, forces, p_s
call horizontal_viscosity(u_av, v_av, h_av, CS%diffu, CS%diffv, &
MEKE, Varmix, G, GV, US, CS%hor_visc, &
OBC=CS%OBC, BT=CS%barotropic_CSp, TD=thickness_diffuse_CSp, &
ADp=CS%ADp)
ADp=CS%ADp, STOCH=STOCH)
call cpu_clock_end(id_clock_horvisc)
if (showCallTree) call callTree_wayPoint("done with horizontal_viscosity (step_MOM_dyn_split_RK2)")

Expand Down
8 changes: 5 additions & 3 deletions src/core/MOM_dynamics_unsplit.F90
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,9 @@ module MOM_dynamics_unsplit
use MOM_open_boundary, only : open_boundary_zero_normal_flow
use MOM_PressureForce, only : PressureForce, PressureForce_init, PressureForce_CS
use MOM_set_visc, only : set_viscous_ML, set_visc_CS
use MOM_self_attr_load, only : SAL_init, SAL_end, SAL_CS
use MOM_stochastics, only : stochastic_CS
use MOM_tidal_forcing, only : tidal_forcing_init, tidal_forcing_end, tidal_forcing_CS
use MOM_self_attr_load, only : SAL_init, SAL_end, SAL_CS
use MOM_unit_scaling, only : unit_scale_type
use MOM_vert_friction, only : vertvisc, vertvisc_coef, vertvisc_init, vertvisc_CS
use MOM_verticalGrid, only : verticalGrid_type, get_thickness_units
Expand Down Expand Up @@ -189,7 +190,7 @@ module MOM_dynamics_unsplit
!! 3rd order (for the inviscid momentum equations) order scheme
subroutine step_MOM_dyn_unsplit(u, v, h, tv, visc, Time_local, dt, forces, &
p_surf_begin, p_surf_end, uh, vh, uhtr, vhtr, eta_av, G, GV, US, CS, &
VarMix, MEKE, pbv, Waves)
VarMix, MEKE, pbv, STOCH, Waves)
type(ocean_grid_type), intent(inout) :: 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
Expand Down Expand Up @@ -223,6 +224,7 @@ subroutine step_MOM_dyn_unsplit(u, v, h, tv, visc, Time_local, dt, forces, &
type(VarMix_CS), intent(inout) :: VarMix !< Variable mixing control structure
type(MEKE_type), intent(inout) :: MEKE !< MEKE fields
type(porous_barrier_type), intent(in) :: pbv !< porous barrier fractional cell metrics
type(stochastic_CS), intent(inout) :: STOCH !< Stochastic control structure
type(wave_parameters_CS), optional, pointer :: Waves !< A pointer to a structure containing
!! fields related to the surface wave conditions

Expand Down Expand Up @@ -263,7 +265,7 @@ subroutine step_MOM_dyn_unsplit(u, v, h, tv, visc, Time_local, dt, forces, &
! diffu = horizontal viscosity terms (u,h)
call enable_averages(dt, Time_local, CS%diag)
call cpu_clock_begin(id_clock_horvisc)
call horizontal_viscosity(u, v, h, CS%diffu, CS%diffv, MEKE, Varmix, G, GV, US, CS%hor_visc)
call horizontal_viscosity(u, v, h, CS%diffu, CS%diffv, MEKE, Varmix, G, GV, US, CS%hor_visc, STOCH=STOCH)
call cpu_clock_end(id_clock_horvisc)
call disable_averaging(CS%diag)

Expand Down
6 changes: 4 additions & 2 deletions src/core/MOM_dynamics_unsplit_RK2.F90
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ module MOM_dynamics_unsplit_RK2
use MOM_PressureForce, only : PressureForce, PressureForce_init, PressureForce_CS
use MOM_set_visc, only : set_viscous_ML, set_visc_CS
use MOM_self_attr_load, only : SAL_init, SAL_end, SAL_CS
use MOM_stochastics, only : stochastic_CS
use MOM_tidal_forcing, only : tidal_forcing_init, tidal_forcing_end, tidal_forcing_CS
use MOM_unit_scaling, only : unit_scale_type
use MOM_vert_friction, only : vertvisc, vertvisc_coef, vertvisc_init, vertvisc_CS
Expand Down Expand Up @@ -192,7 +193,7 @@ module MOM_dynamics_unsplit_RK2
!> Step the MOM6 dynamics using an unsplit quasi-2nd order Runge-Kutta scheme
subroutine step_MOM_dyn_unsplit_RK2(u_in, v_in, h_in, tv, visc, Time_local, dt, forces, &
p_surf_begin, p_surf_end, uh, vh, uhtr, vhtr, eta_av, G, GV, US, CS, &
VarMix, MEKE, pbv)
VarMix, MEKE, pbv, STOCH)
type(ocean_grid_type), intent(inout) :: 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
Expand Down Expand Up @@ -237,6 +238,7 @@ subroutine step_MOM_dyn_unsplit_RK2(u_in, v_in, h_in, tv, visc, Time_local, dt,
!! fields related to the Mesoscale
!! Eddy Kinetic Energy.
type(porous_barrier_type), intent(in) :: pbv !< porous barrier fractional cell metrics
type(stochastic_CS), intent(inout) :: STOCH !< Stochastic control structure
! Local variables
real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: h_av ! Averaged layer thicknesses [H ~> m or kg m-2]
real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: hp ! Predicted layer thicknesses [H ~> m or kg m-2]
Expand Down Expand Up @@ -276,7 +278,7 @@ subroutine step_MOM_dyn_unsplit_RK2(u_in, v_in, h_in, tv, visc, Time_local, dt,
call enable_averages(dt,Time_local, CS%diag)
call cpu_clock_begin(id_clock_horvisc)
call horizontal_viscosity(u_in, v_in, h_in, CS%diffu, CS%diffv, MEKE, VarMix, &
G, GV, US, CS%hor_visc)
G, GV, US, CS%hor_visc, STOCH=STOCH)
call cpu_clock_end(id_clock_horvisc)
call disable_averaging(CS%diag)
call pass_vector(CS%diffu, CS%diffv, G%Domain, clock=id_clock_pass)
Expand Down
18 changes: 15 additions & 3 deletions src/parameterizations/lateral/MOM_hor_visc.F90
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ module MOM_hor_visc
use MOM_MEKE_types, only : MEKE_type
use MOM_open_boundary, only : ocean_OBC_type, OBC_DIRECTION_E, OBC_DIRECTION_W
use MOM_open_boundary, only : OBC_DIRECTION_N, OBC_DIRECTION_S, OBC_NONE
use MOM_stochastics, only : stochastic_CS
use MOM_unit_scaling, only : unit_scale_type
use MOM_verticalGrid, only : verticalGrid_type
use MOM_variables, only : accel_diag_ptrs
Expand Down Expand Up @@ -241,7 +242,7 @@ module MOM_hor_visc
!! v[is-2:ie+2,js-2:je+2]
!! h[is-1:ie+1,js-1:je+1]
subroutine horizontal_viscosity(u, v, h, diffu, diffv, MEKE, VarMix, G, GV, US, &
CS, OBC, BT, TD, ADp)
CS, OBC, BT, TD, ADp, STOCH)
type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
real, dimension(SZIB_(G),SZJ_(G),SZK_(GV)), &
Expand All @@ -265,6 +266,7 @@ subroutine horizontal_viscosity(u, v, h, diffu, diffv, MEKE, VarMix, G, GV, US,
type(barotropic_CS), intent(in), optional :: BT !< Barotropic control structure
type(thickness_diffuse_CS), intent(in), optional :: TD !< Thickness diffusion control structure
type(accel_diag_ptrs), intent(in), optional :: ADp !< Acceleration diagnostics
type(stochastic_CS), intent(inout), optional :: STOCH !< Stochastic control structure

! Local variables
real, dimension(SZIB_(G),SZJ_(G)) :: &
Expand Down Expand Up @@ -395,6 +397,7 @@ subroutine horizontal_viscosity(u, v, h, diffu, diffv, MEKE, VarMix, G, GV, US,
logical :: apply_OBC = .false.
logical :: use_MEKE_Ku
logical :: use_MEKE_Au
logical :: skeb_use_frict
integer :: is_vort, ie_vort, js_vort, je_vort ! Loop ranges for vorticity terms
integer :: is_Kh, ie_Kh, js_Kh, je_Kh ! Loop ranges for thickness point viscosities
integer :: is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz
Expand Down Expand Up @@ -426,6 +429,9 @@ subroutine horizontal_viscosity(u, v, h, diffu, diffv, MEKE, VarMix, G, GV, US,
inv_PI2 = 1.0/((4.0*atan(1.0))**2)
inv_PI6 = inv_PI3 * inv_PI3

skeb_use_frict = .false.
if (present(STOCH)) skeb_use_frict = STOCH%skeb_use_frict

m_leithy(:,:) = 0.0 ! Initialize

if (present(OBC)) then ; if (associated(OBC)) then ; if (OBC%OBC_pe) then
Expand Down Expand Up @@ -588,12 +594,12 @@ subroutine horizontal_viscosity(u, v, h, diffu, diffv, MEKE, VarMix, G, GV, US,
!$OMP CS, G, GV, US, OBC, VarMix, MEKE, u, v, h, &
!$OMP is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz, is_vort, ie_vort, js_vort, je_vort, &
!$OMP is_Kh, ie_Kh, js_Kh, je_Kh, apply_OBC, rescale_Kh, legacy_bound, find_FrictWork, &
!$OMP use_MEKE_Ku, use_MEKE_Au, u_smooth, v_smooth, &
!$OMP use_MEKE_Ku, use_MEKE_Au, u_smooth, v_smooth, skeb_use_frict, &
!$OMP backscat_subround, GME_effic_h, GME_effic_q, &
!$OMP h_neglect, h_neglect3, inv_PI3, inv_PI6, &
!$OMP diffu, diffv, Kh_h, Kh_q, Ah_h, Ah_q, FrictWork, FrictWork_GME, &
!$OMP div_xx_h, sh_xx_h, vort_xy_q, sh_xy_q, GME_coeff_h, GME_coeff_q, &
!$OMP KH_u_GME, KH_v_GME, grid_Re_Kh, grid_Re_Ah, NoSt, ShSt &
!$OMP KH_u_GME, KH_v_GME, grid_Re_Kh, grid_Re_Ah, NoSt, ShSt, STOCH &
!$OMP ) &
!$OMP private( &
!$OMP i, j, k, n, &
Expand Down Expand Up @@ -1786,6 +1792,12 @@ subroutine horizontal_viscosity(u, v, h, diffu, diffv, MEKE, VarMix, G, GV, US,
+ (v(i+1,J-1,k)-v(i,J-1,k))*G%IdxBu(I,J-1)) ) ) )
enddo ; enddo ; endif

if (skeb_use_frict) then ; do j=js,je ; do i=is,ie
! Note that the sign convention is FrictWork < 0 means energy dissipation.
STOCH%skeb_diss(i,j,k) = STOCH%skeb_diss(i,j,k) - STOCH%skeb_frict_coef * &
FrictWork(i,j,k) / (GV%H_to_RZ * (h(i,j,k) + h_neglect))
enddo ; enddo ; endif

! Make a similar calculation as for FrictWork above but accumulating into
! the vertically integrated MEKE source term, and adjusting for any
! energy loss seen as a reduction in the (biharmonic) frictional source term.
Expand Down
Loading
Loading