Skip to content

Commit

Permalink
Merge pull request #256 from gustavo-marques/fpmix_draft_15August2023
Browse files Browse the repository at this point in the history
Add option to apply non-local momentum flux
  • Loading branch information
alperaltuntas authored Sep 8, 2023
2 parents d4aa108 + d9aa751 commit 8fd5104
Show file tree
Hide file tree
Showing 5 changed files with 501 additions and 5 deletions.
3 changes: 3 additions & 0 deletions config_src/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ subroutine convert_IOB_to_fluxes(IOB, fluxes, index_bounds, Time, valid_time, G,
call allocate_forcing_type(G, fluxes, water=.true., heat=.true., ustar=.true., &
press=.true., fix_accum_bug=CS%fix_ustar_gustless_bug, &
cfc=CS%use_CFC, hevap=CS%enthalpy_cpl)
call safe_alloc_ptr(fluxes%omega_w2x,isd,ied,jsd,jed)

call safe_alloc_ptr(fluxes%sw_vis_dir,isd,ied,jsd,jed)
call safe_alloc_ptr(fluxes%sw_vis_dif,isd,ied,jsd,jed)
Expand Down Expand Up @@ -704,6 +705,7 @@ subroutine convert_IOB_to_forces(IOB, forces, index_bounds, Time, G, US, CS)

call safe_alloc_ptr(forces%p_surf,isd,ied,jsd,jed)
call safe_alloc_ptr(forces%p_surf_full,isd,ied,jsd,jed)
call safe_alloc_ptr(forces%omega_w2x,isd,ied,jsd,jed)

if (CS%rigid_sea_ice) then
call safe_alloc_ptr(forces%rigidity_ice_u,IsdB,IedB,jsd,jed)
Expand Down Expand Up @@ -864,6 +866,7 @@ subroutine convert_IOB_to_forces(IOB, forces, index_bounds, Time, G, US, CS)
forces%tau_mag(i,j) = gustiness + G%mask2dT(i,j) * sqrt(taux_at_h(i,j)**2 + tauy_at_h(i,j)**2)
forces%ustar(i,j) = sqrt(gustiness*Irho0 + Irho0 * G%mask2dT(i,j) * &
sqrt(taux_at_h(i,j)**2 + tauy_at_h(i,j)**2))
forces%omega_w2x(i,j) = atan(tauy_at_h(i,j), taux_at_h(i,j))
enddo ; enddo
call pass_vector(forces%taux, forces%tauy, G%Domain, halo=1)
else ! C-grid wind stresses.
Expand Down
79 changes: 77 additions & 2 deletions src/core/MOM_dynamics_split_RK2.F90
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,13 @@ module MOM_dynamics_split_RK2
use MOM_unit_scaling, only : unit_scale_type
use MOM_vert_friction, only : vertvisc, vertvisc_coef, vertvisc_remnant
use MOM_vert_friction, only : vertvisc_init, vertvisc_end, vertvisc_CS
use MOM_vert_friction, only : updateCFLtruncationValue
use MOM_vert_friction, only : updateCFLtruncationValue, vertFPmix
use MOM_verticalGrid, only : verticalGrid_type, get_thickness_units
use MOM_verticalGrid, only : get_flux_units, get_tr_flux_units
use MOM_wave_interface, only: wave_parameters_CS, Stokes_PGF
use MOM_CVMix_KPP, only : KPP_get_BLD, KPP_CS
use MOM_energetic_PBL, only : energetic_PBL_get_MLD, energetic_PBL_CS
use MOM_diabatic_driver, only : diabatic_CS, extract_diabatic_member

implicit none ; private

Expand Down Expand Up @@ -134,6 +137,8 @@ module MOM_dynamics_split_RK2
real ALLOCABLE_, dimension(NIMEM_,NJMEM_,NKMEM_) :: pbce !< pbce times eta gives the baroclinic pressure
!! anomaly in each layer due to free surface height
!! anomalies [L2 H-1 T-2 ~> m s-2 or m4 kg-1 s-2].
type(KPP_CS), pointer :: KPP_CSp => NULL() !< KPP control structure needed to ge
type(energetic_PBL_CS), pointer :: energetic_PBL_CSp => NULL() !< ePBL control structure

real, pointer, dimension(:,:) :: taux_bot => NULL() !< frictional x-bottom stress from the ocean
!! to the seafloor [R L Z T-2 ~> Pa]
Expand Down Expand Up @@ -172,10 +177,12 @@ module MOM_dynamics_split_RK2
!! Euler (1) [nondim]. 0 is often used.
logical :: debug !< If true, write verbose checksums for debugging purposes.
logical :: debug_OBC !< If true, do debugging calls for open boundary conditions.
logical :: fpmix !< If true, applies profiles of momentum flux magnitude and direction.

logical :: module_is_initialized = .false. !< Record whether this module has been initialized.

!>@{ Diagnostic IDs
integer :: id_uold = -1, id_vold = -1
integer :: id_uh = -1, id_vh = -1
integer :: id_umo = -1, id_vmo = -1
integer :: id_umo_2d = -1, id_vmo_2d = -1
Expand Down Expand Up @@ -346,6 +353,11 @@ subroutine step_MOM_dyn_split_RK2(u, v, h, tv, visc, Time_local, dt, forces, p_s
real, dimension(SZI_(G),SZJB_(G),SZK_(GV)) :: v_old_rad_OBC ! The starting meridional velocities, which are
! saved for use in the Flather open boundary condition code [L T-1 ~> m s-1]

! GMM, TODO: make these allocatable?
real, dimension(SZIB_(G),SZJ_(G),SZK_(GV)) :: uold ! u-velocity before vert_visc is applied, for fpmix
! [L T-1 ~> m s-1]
real, dimension(SZI_(G),SZJB_(G),SZK_(GV)) :: vold ! v-velocity before vert_visc is applied, for fpmix
! [L T-1 ~> m s-1]
real :: pres_to_eta ! A factor that converts pressures to the units of eta
! [H T2 R-1 L-2 ~> m Pa-1 or kg m-2 Pa-1]
real, pointer, dimension(:,:) :: &
Expand All @@ -369,9 +381,9 @@ subroutine step_MOM_dyn_split_RK2(u, v, h, tv, visc, Time_local, dt, forces, p_s
v_av, & ! The meridional velocity time-averaged over a time step [L T-1 ~> m s-1].
h_av ! The layer thickness time-averaged over a time step [H ~> m or kg m-2].

real, dimension(SZI_(G),SZJ_(G)) :: hbl ! Boundary layer depth from Cvmix
real :: dt_pred ! The time step for the predictor part of the baroclinic time stepping [T ~> s].
real :: Idt_bc ! Inverse of the baroclinic timestep [T-1 ~> s-1]

logical :: dyn_p_surf
logical :: BT_cont_BT_thick ! If true, use the BT_cont_type to estimate the
! relative weightings of the layers in calculating
Expand Down Expand Up @@ -659,10 +671,40 @@ subroutine step_MOM_dyn_split_RK2(u, v, h, tv, visc, Time_local, dt, forces, p_s
if (CS%debug) then
call uvchksum("0 before vertvisc: [uv]p", up, vp, G%HI,haloshift=0, symmetric=sym, scale=US%L_T_to_m_s)
endif

if (CS%fpmix) then
uold(:,:,:) = 0.0
vold(:,:,:) = 0.0
do k = 1, nz
do j = js , je
do I = Isq, Ieq
uold(I,j,k) = up(I,j,k)
enddo
enddo
do J = Jsq, Jeq
do i = is, ie
vold(i,J,k) = vp(i,J,k)
enddo
enddo
enddo
endif

call vertvisc_coef(up, vp, h, forces, visc, dt_pred, G, GV, US, CS%vertvisc_CSp, &
CS%OBC, VarMix)
call vertvisc(up, vp, h, forces, visc, dt_pred, CS%OBC, CS%AD_pred, CS%CDp, G, &
GV, US, CS%vertvisc_CSp, CS%taux_bot, CS%tauy_bot, waves=waves)

if (CS%fpmix) then
hbl(:,:) = 0.0
if (ASSOCIATED(CS%KPP_CSp)) call KPP_get_BLD(CS%KPP_CSp, hbl, G, US, m_to_BLD_units=GV%m_to_H)
if (ASSOCIATED(CS%energetic_PBL_CSp)) &
call energetic_PBL_get_MLD(CS%energetic_PBL_CSp, hbl, G, US, m_to_MLD_units=GV%m_to_H)
call vertFPmix(up, vp, uold, vold, hbl, h, forces, &
dt_pred, G, GV, US, CS%vertvisc_CSp, CS%OBC)
call vertvisc(up, vp, h, forces, visc, dt_pred, CS%OBC, CS%ADp, CS%CDp, G, &
GV, US, CS%vertvisc_CSp, CS%taux_bot, CS%tauy_bot, waves=waves)
endif

if (showCallTree) call callTree_wayPoint("done with vertvisc (step_MOM_dyn_split_RK2)")
if (G%nonblocking_updates) then
call cpu_clock_end(id_clock_vertvisc)
Expand Down Expand Up @@ -880,9 +922,35 @@ subroutine step_MOM_dyn_split_RK2(u, v, h, tv, visc, Time_local, dt, forces, p_s
! u <- u + dt d/dz visc d/dz u
! u_av <- u_av + dt d/dz visc d/dz u_av
call cpu_clock_begin(id_clock_vertvisc)

if (CS%fpmix) then
uold(:,:,:) = 0.0
vold(:,:,:) = 0.0
do k = 1, nz
do j = js , je
do I = Isq, Ieq
uold(I,j,k) = u(I,j,k)
enddo
enddo
do J = Jsq, Jeq
do i = is, ie
vold(i,J,k) = v(i,J,k)
enddo
enddo
enddo
endif

call vertvisc_coef(u, v, h, forces, visc, dt, G, GV, US, CS%vertvisc_CSp, CS%OBC, VarMix)
call vertvisc(u, v, h, forces, visc, dt, CS%OBC, CS%ADp, CS%CDp, G, GV, US, &
CS%vertvisc_CSp, CS%taux_bot, CS%tauy_bot,waves=waves)

if (CS%fpmix) then
call vertFPmix(u, v, uold, vold, hbl, h, forces, dt, &
G, GV, US, CS%vertvisc_CSp, CS%OBC)
call vertvisc(u, v, h, forces, visc, dt, CS%OBC, CS%ADp, CS%CDp, G, GV, US, &
CS%vertvisc_CSp, CS%taux_bot, CS%tauy_bot, waves=waves)
endif

if (G%nonblocking_updates) then
call cpu_clock_end(id_clock_vertvisc)
call start_group_pass(CS%pass_uv, G%Domain, clock=id_clock_pass)
Expand Down Expand Up @@ -963,6 +1031,10 @@ subroutine step_MOM_dyn_split_RK2(u, v, h, tv, visc, Time_local, dt, forces, p_s
CS%CAu_pred_stored = .false.
endif

if (CS%fpmix) then
if (CS%id_uold > 0) call post_data(CS%id_uold , uold, CS%diag)
if (CS%id_vold > 0) call post_data(CS%id_vold , vold, CS%diag)
endif

! The time-averaged free surface height has already been set by the last call to btstep.

Expand Down Expand Up @@ -1298,6 +1370,9 @@ subroutine initialize_dyn_split_RK2(u, v, h, uh, vh, eta, Time, G, GV, US, param
"If true, calculate the Coriolis accelerations at the end of each "//&
"timestep for use in the predictor step of the next split RK2 timestep.", &
default=.true.)
call get_param(param_file, mdl, "FPMIX", CS%fpmix, &
"If true, apply profiles of momentum flux magnitude and "//&
" direction", default=.false.)
call get_param(param_file, mdl, "REMAP_AUXILIARY_VARS", CS%remap_aux, &
"If true, apply ALE remapping to all of the auxiliary 3-dimensional "//&
"variables that are needed to reproduce across restarts, similarly to "//&
Expand Down
25 changes: 23 additions & 2 deletions src/core/MOM_forcing_type.F90
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ module MOM_forcing_type

! surface stress components and turbulent velocity scale
real, pointer, dimension(:,:) :: &
omega_w2x => NULL(), & !< the counter-clockwise angle of the wind stress with respect
ustar => NULL(), & !< surface friction velocity scale [Z T-1 ~> m s-1].
tau_mag => NULL(), & !< Magnitude of the wind stress averaged over tracer cells,
!! including any contributions from sub-gridscale variability
Expand Down Expand Up @@ -226,7 +227,9 @@ module MOM_forcing_type
tau_mag => NULL(), & !< Magnitude of the wind stress averaged over tracer cells, including any
!! contributions from sub-gridscale variability or gustiness [R L Z T-2 ~> Pa]
ustar => NULL(), & !< surface friction velocity scale [Z T-1 ~> m s-1].
net_mass_src => NULL() !< The net mass source to the ocean [R Z T-1 ~> kg m-2 s-1]
net_mass_src => NULL(), & !< The net mass source to the ocean [R Z T-1 ~> kg m-2 s-1]
omega_w2x => NULL() !< the counter-clockwise angle of the wind stress with respect
!! to the horizontal abscissa (x-coordinate) at tracer points [rad].

! applied surface pressure from other component models (e.g., atmos, sea ice, land ice)
real, pointer, dimension(:,:) :: p_surf_full => NULL()
Expand Down Expand Up @@ -362,8 +365,8 @@ module MOM_forcing_type
integer :: id_taux = -1
integer :: id_tauy = -1
integer :: id_ustar = -1
integer :: id_omega_w2x = -1
integer :: id_tau_mag = -1

integer :: id_psurf = -1
integer :: id_TKE_tidal = -1
integer :: id_buoy = -1
Expand Down Expand Up @@ -1328,6 +1331,9 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles,
'Surface friction velocity = [(gustiness + tau_magnitude)/rho0]^(1/2)', &
'm s-1', conversion=US%Z_to_m*US%s_to_T)

handles%id_omega_w2x = register_diag_field('ocean_model', 'omega_w2x', diag%axesT1, Time, &
'Counter-clockwise angle of the wind stress from the horizontal axis.', 'rad')

if (present(use_berg_fluxes)) then
if (use_berg_fluxes) then
handles%id_ustar_berg = register_diag_field('ocean_model', 'ustar_berg', diag%axesT1, Time, &
Expand Down Expand Up @@ -2165,6 +2171,11 @@ subroutine copy_common_forcing_fields(forces, fluxes, G, skip_pres)
enddo ; enddo
endif

if (associated(forces%omega_w2x) .and. associated(fluxes%omega_w2x)) then
do j=js,je ; do i=is,ie
fluxes%omega_w2x(i,j) = forces%omega_w2x(i,j)
enddo ; enddo
endif
if (associated(forces%tau_mag) .and. associated(fluxes%tau_mag)) then
do j=js,je ; do i=is,ie
fluxes%tau_mag(i,j) = forces%tau_mag(i,j)
Expand Down Expand Up @@ -2302,6 +2313,11 @@ subroutine copy_back_forcing_fields(fluxes, forces, G)
enddo ; enddo
endif

if (associated(forces%omega_w2x) .and. associated(fluxes%omega_w2x)) then
do j=js,je ; do i=is,ie
forces%omega_w2x(i,j) = fluxes%omega_w2x(i,j)
enddo ; enddo
endif
if (associated(forces%tau_mag) .and. associated(fluxes%tau_mag)) then
do j=js,je ; do i=is,ie
forces%tau_mag(i,j) = fluxes%tau_mag(i,j)
Expand Down Expand Up @@ -2950,6 +2966,9 @@ subroutine forcing_diagnostics(fluxes_in, sfc_state, G_in, US, time_end, diag, h
if ((handles%id_ustar > 0) .and. associated(fluxes%ustar)) &
call post_data(handles%id_ustar, fluxes%ustar, diag)

if ((handles%id_omega_w2x > 0) .and. associated(fluxes%omega_w2x)) &
call post_data(handles%id_omega_w2x, fluxes%omega_w2x, diag)

if ((handles%id_ustar_berg > 0) .and. associated(fluxes%ustar_berg)) &
call post_data(handles%id_ustar_berg, fluxes%ustar_berg, diag)

Expand Down Expand Up @@ -3275,6 +3294,7 @@ end subroutine myAlloc
subroutine deallocate_forcing_type(fluxes)
type(forcing), intent(inout) :: fluxes !< Forcing fields structure

if (associated(fluxes%omega_w2x)) deallocate(fluxes%omega_w2x)
if (associated(fluxes%ustar)) deallocate(fluxes%ustar)
if (associated(fluxes%ustar_gustless)) deallocate(fluxes%ustar_gustless)
if (associated(fluxes%tau_mag)) deallocate(fluxes%tau_mag)
Expand Down Expand Up @@ -3334,6 +3354,7 @@ end subroutine deallocate_forcing_type
subroutine deallocate_mech_forcing(forces)
type(mech_forcing), intent(inout) :: forces !< Forcing fields structure

if (associated(forces%omega_w2x)) deallocate(forces%omega_w2x)
if (associated(forces%taux)) deallocate(forces%taux)
if (associated(forces%tauy)) deallocate(forces%tauy)
if (associated(forces%ustar)) deallocate(forces%ustar)
Expand Down
3 changes: 2 additions & 1 deletion src/parameterizations/vertical/MOM_set_viscosity.F90
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ module MOM_set_visc
#include <MOM_memory.h>

public set_viscous_BBL, set_viscous_ML, set_visc_init, set_visc_end
public set_visc_register_restarts, remap_vertvisc_aux_vars
public set_visc_register_restarts, set_u_at_v, set_v_at_u
public remap_vertvisc_aux_vars

! A note on unit descriptions in comments: MOM6 uses units that can be rescaled for dimensional
! consistency testing. These are noted in comments with units like Z, H, L, and T, along with
Expand Down
Loading

0 comments on commit 8fd5104

Please sign in to comment.