Skip to content
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
41 changes: 26 additions & 15 deletions src/core/MOM.F90
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,8 @@ module MOM
real ALLOCABLE_, dimension(NIMEM_,NJMEM_) :: eta_av_bc
!< free surface height or column mass time averaged over the last
!! baroclinic dynamics time step [H ~> m or kg m-2]
real, dimension(:,:), pointer :: &
Hml => NULL() !< active mixed layer depth [Z ~> m]
real, dimension(:,:), pointer :: Hml => NULL()
!< active mixed layer depth, or 0 if there is no boundary layer scheme [Z ~> m]
real :: time_in_cycle !< The running time of the current time-stepping cycle
!! in calls that step the dynamics, and also the length of
!! the time integral of ssh_rint [T ~> s].
Expand Down Expand Up @@ -1327,7 +1327,7 @@ subroutine step_MOM_dynamics(forces, p_surf_begin, p_surf_end, dt, dt_thermo, &
CS%uhtr, CS%vhtr, G%HI, haloshift=0, scale=GV%H_to_MKS*US%L_to_m**2)
endif
call cpu_clock_begin(id_clock_ml_restrat)
call mixedlayer_restrat(h, CS%uhtr, CS%vhtr, CS%tv, forces, dt, CS%visc%MLD, &
call mixedlayer_restrat(h, CS%uhtr, CS%vhtr, CS%tv, forces, dt, CS%visc%MLD, CS%visc%h_ML, &
CS%visc%sfc_buoy_flx, CS%VarMix, G, GV, US, CS%mixedlayer_restrat_CSp)
call cpu_clock_end(id_clock_ml_restrat)
call pass_var(h, G%Domain, clock=id_clock_pass, halo=max(2,CS%cont_stencil))
Expand Down Expand Up @@ -1433,7 +1433,7 @@ subroutine step_MOM_tracer_dyn(CS, G, GV, US, h, Time_local)
call advect_tracer(h, CS%uhtr, CS%vhtr, CS%OBC, CS%t_dyn_rel_adv, G, GV, US, &
CS%tracer_adv_CSp, CS%tracer_Reg, x_first_in=x_first)
if (CS%debug) call MOM_tracer_chksum("Post-advect ", CS%tracer_Reg, G)
call tracer_hordiff(h, CS%t_dyn_rel_adv, CS%MEKE, CS%VarMix, G, GV, US, &
call tracer_hordiff(h, CS%t_dyn_rel_adv, CS%MEKE, CS%VarMix, CS%visc, G, GV, US, &
CS%tracer_diff_CSp, CS%tracer_Reg, CS%tv)
if (CS%debug) call MOM_tracer_chksum("Post-diffuse ", CS%tracer_Reg, G)
if (showCallTree) call callTree_waypoint("finished tracer advection/diffusion (step_MOM)")
Expand Down Expand Up @@ -1882,7 +1882,7 @@ subroutine step_offline(forces, fluxes, sfc_state, Time_start, time_interval, CS
call calc_depth_function(G, CS%VarMix)
call calc_slope_functions(CS%h, CS%tv, dt_offline, G, GV, US, CS%VarMix, OBC=CS%OBC)
endif
call tracer_hordiff(CS%h, dt_offline, CS%MEKE, CS%VarMix, G, GV, US, &
call tracer_hordiff(CS%h, dt_offline, CS%MEKE, CS%VarMix, CS%visc, G, GV, US, &
CS%tracer_diff_CSp, CS%tracer_Reg, CS%tv)
endif
endif
Expand All @@ -1909,7 +1909,7 @@ subroutine step_offline(forces, fluxes, sfc_state, Time_start, time_interval, CS
call calc_depth_function(G, CS%VarMix)
call calc_slope_functions(CS%h, CS%tv, dt_offline, G, GV, US, CS%VarMix, OBC=CS%OBC)
endif
call tracer_hordiff(CS%h, dt_offline, CS%MEKE, CS%VarMix, G, GV, US, &
call tracer_hordiff(CS%h, dt_offline, CS%MEKE, CS%VarMix, CS%visc, G, GV, US, &
CS%tracer_diff_CSp, CS%tracer_Reg, CS%tv)
endif
endif
Expand Down Expand Up @@ -1966,7 +1966,7 @@ subroutine step_offline(forces, fluxes, sfc_state, Time_start, time_interval, CS
CS%h, eatr, ebtr, uhtr, vhtr)
! Perform offline diffusion if requested
if (.not. skip_diffusion) then
call tracer_hordiff(h_end, dt_offline, CS%MEKE, CS%VarMix, G, GV, US, &
call tracer_hordiff(h_end, dt_offline, CS%MEKE, CS%VarMix, CS%visc, G, GV, US, &
CS%tracer_diff_CSp, CS%tracer_Reg, CS%tv)
endif

Expand Down Expand Up @@ -2124,6 +2124,7 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, &
logical :: Boussinesq ! If true, this run is fully Boussinesq
logical :: semi_Boussinesq ! If true, this run is partially non-Boussinesq
logical :: use_KPP ! If true, diabatic is using KPP vertical mixing
logical :: MLE_use_PBL_MLD ! If true, use stored boundary layer depths for submesoscale restratification.
integer :: nkml, nkbl, verbosity, write_geom
integer :: dynamics_stencil ! The computational stencil for the calculations
! in the dynamic core.
Expand Down Expand Up @@ -2728,7 +2729,7 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, &
if (use_frazil) allocate(CS%tv%frazil(isd:ied,jsd:jed), source=0.0)
if (bound_salinity) allocate(CS%tv%salt_deficit(isd:ied,jsd:jed), source=0.0)

if (bulkmixedlayer .or. use_temperature) allocate(CS%Hml(isd:ied,jsd:jed), source=0.0)
allocate(CS%Hml(isd:ied,jsd:jed), source=0.0)

if (bulkmixedlayer) then
GV%nkml = nkml ; GV%nk_rho_varies = nkml + nkbl
Expand Down Expand Up @@ -3270,11 +3271,23 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, &
CS%mixedlayer_restrat = mixedlayer_restrat_init(Time, G, GV, US, param_file, diag, &
CS%mixedlayer_restrat_CSp, restart_CSp)
if (CS%mixedlayer_restrat) then
if (GV%Boussinesq .and. associated(CS%visc%h_ML)) then
! This is here to allow for a transition of restart files between model versions.
call get_param(param_file, "MOM", "MLE_USE_PBL_MLD", MLE_use_PBL_MLD, &
default=.false., do_not_log=.true.)
if (MLE_use_PBL_MLD .and. .not.query_initialized(CS%visc%h_ML, "h_ML", restart_CSp) .and. &
associated(CS%visc%MLD)) then
do j=js,je ; do i=is,ie ; CS%visc%h_ML(i,j) = GV%Z_to_H * CS%visc%MLD(i,j) ; enddo ; enddo
endif
endif

if (.not.(bulkmixedlayer .or. CS%use_ALE_algorithm)) &
call MOM_error(FATAL, "MOM: MIXEDLAYER_RESTRAT true requires a boundary layer scheme.")
! When DIABATIC_FIRST=False and using CS%visc%ML in mixedlayer_restrat we need to update after a restart
if (.not. CS%diabatic_first .and. associated(CS%visc%MLD)) &
call pass_var(CS%visc%MLD, G%domain, halo=1)
if (.not. CS%diabatic_first .and. associated(CS%visc%h_ML)) &
call pass_var(CS%visc%h_ML, G%domain, halo=1)
endif

call MOM_diagnostics_init(MOM_internal_state, CS%ADp, CS%CDp, Time, G, GV, US, &
Expand Down Expand Up @@ -3566,7 +3579,7 @@ subroutine set_restart_fields(GV, US, param_file, CS, restart_CSp)
! hML is needed when using the ice shelf module
call get_param(param_file, '', "ICE_SHELF", use_ice_shelf, default=.false., &
do_not_log=.true.)
if (use_ice_shelf .and. associated(CS%Hml)) then
if (use_ice_shelf) then
call register_restart_field(CS%Hml, "hML", .false., restart_CSp, &
"Mixed layer thickness", "m", conversion=US%Z_to_m)
endif
Expand Down Expand Up @@ -3706,11 +3719,9 @@ subroutine extract_surface_state(CS, sfc_state_in)
enddo ; enddo ; endif

! copy Hml into sfc_state, so that caps can access it
if (associated(CS%Hml)) then
do j=js,je ; do i=is,ie
sfc_state%Hml(i,j) = CS%Hml(i,j)
enddo ; enddo
endif
do j=js,je ; do i=is,ie
sfc_state%Hml(i,j) = CS%Hml(i,j)
enddo ; enddo

if (CS%Hmix < 0.0) then ! A bulk mixed layer is in use, so layer 1 has the properties
if (use_temperature) then ; do j=js,je ; do i=is,ie
Expand Down Expand Up @@ -3875,7 +3886,7 @@ subroutine extract_surface_state(CS, sfc_state_in)
do k=1,nz
call calculate_TFreeze(CS%tv%S(is:ie,j,k), pres(is:ie), T_freeze(is:ie), CS%tv%eqn_of_state)
do i=is,ie
depth_ml = min(CS%HFrz, (US%Z_to_m*GV%m_to_H)*CS%visc%MLD(i,j))
depth_ml = min(CS%HFrz, CS%visc%h_ML(i,j))
if (depth(i) + h(i,j,k) < depth_ml) then
dh = h(i,j,k)
elseif (depth(i) < depth_ml) then
Expand Down
9 changes: 1 addition & 8 deletions src/core/MOM_dynamics_split_RK2.F90
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,6 @@ module MOM_dynamics_split_RK2
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 @@ -139,8 +136,6 @@ 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 @@ -717,9 +712,7 @@ subroutine step_MOM_dyn_split_RK2(u_inst, v_inst, h, tv, visc, Time_local, dt, f

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)
if (associated(visc%h_ML)) hbl(:,:) = visc%h_ML(:,:)
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, &
Expand Down
9 changes: 1 addition & 8 deletions src/core/MOM_dynamics_split_RK2b.F90
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,6 @@ module MOM_dynamics_split_RK2b
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 @@ -147,8 +144,6 @@ module MOM_dynamics_split_RK2b
real ALLOCABLE_, dimension(NIMEM_,NJMEMB_PTR_) :: dv_av_inst !< The barotropic meridional velocity increment
!! between filtered and instantaneous velocities
!! [L T-1 ~> m s-1]
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 @@ -734,9 +729,7 @@ subroutine step_MOM_dyn_split_RK2b(u_av, v_av, h, tv, visc, Time_local, dt, forc

! 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)
! if (associated(visc%h_ML)) hbl(:,:) = visc%h_ML(:,:)
! 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, &
Expand Down
66 changes: 66 additions & 0 deletions src/core/MOM_interface_heights.F90
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module MOM_interface_heights

public find_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

!> Calculates the heights of the free surface or all interfaces from layer thicknesses.
Expand Down Expand Up @@ -824,4 +825,69 @@ subroutine thickness_to_dz_jslice(h, tv, dz, j, G, GV, halo_size)

end subroutine thickness_to_dz_jslice


!> Convert mixed layer depths in height units into the thickness of water in the mixed
!! in thickness units.
subroutine convert_MLD_to_ML_thickness(MLD_in, h, h_MLD, tv, G, GV, halo)
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(SZI_(G),SZJ_(G)), &
intent(in) :: MLD_in !< Input mixed layer depth [Z ~> m].
real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2]
real, dimension(SZI_(G),SZJ_(G)), &
intent(out) :: h_MLD !< Thickness of water in the mixed layer [H ~> m or kg m-2]
type(thermo_var_ptrs), intent(in) :: tv !< Structure containing pointers to any available
!! thermodynamic fields.
integer, optional, intent(in) :: halo !< Halo width over which to calculate frazil

! Local variables
real :: MLD_rem(SZI_(G)) ! The vertical extent of the MLD_in that has not yet been accounted for [Z ~> m]
character(len=128) :: mesg ! A string for error messages
logical :: keep_going
integer :: i, j, k, is, ie, js, je, nz, halos

is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke

halos = 0 ; if (present(halo)) halos = halo
if (present(halo)) then
is = G%isc-halo ; ie = G%iec+halo ; js = G%jsc-halo ; je = G%jec+halo
endif

if (GV%Boussinesq .or. (.not.allocated(tv%SpV_avg))) then
do j=js,je ; do i=is,ie
h_MLD(i,j) = GV%Z_to_H * MLD_in(i,j)
enddo ; enddo
else ! The fully non-Boussinesq conversion between height in MLD_in and thickness.
if ((allocated(tv%SpV_avg)) .and. (tv%valid_SpV_halo < halos)) then
if (tv%valid_SpV_halo < 0) then
mesg = "invalid values of SpV_avg."
else
write(mesg, '("insufficiently large SpV_avg halos of width ", i2, " but ", i2," is needed.")') &
tv%valid_SpV_halo, halos
endif
call MOM_error(FATAL, "convert_MLD_to_ML_thickness called in fully non-Boussinesq mode with "//trim(mesg))
endif

do j=js,je
do i=is,ie ; MLD_rem(i) = MLD_in(i,j) ; h_MLD(i,j) = 0.0 ; enddo
do k=1,nz
keep_going = .false.
do i=is,ie ; if (MLD_rem(i) > 0.0) then
if (MLD_rem(i) > GV%H_to_RZ * h(i,j,k) * tv%SpV_avg(i,j,k)) then
h_MLD(i,j) = h_MLD(i,j) + h(i,j,k)
MLD_rem(i) = MLD_rem(i) - GV%H_to_RZ * h(i,j,k) * tv%SpV_avg(i,j,k)
keep_going = .true.
else
h_MLD(i,j) = h_MLD(i,j) + GV%RZ_to_H * MLD_rem(i) / tv%SpV_avg(i,j,k)
MLD_rem(i) = 0.0
endif
endif ; enddo
if (.not.keep_going) exit
enddo
enddo
endif

end subroutine convert_MLD_to_ML_thickness

end module MOM_interface_heights
3 changes: 2 additions & 1 deletion src/core/MOM_variables.F90
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,8 @@ module MOM_variables
Ray_v !< The Rayleigh drag velocity to be applied to each layer at v-points [H T-1 ~> m s-1 or Pa s m-1].

! The following elements are pointers so they can be used as targets for pointers in the restart registry.
real, pointer, dimension(:,:) :: MLD => NULL() !< Instantaneous active mixing layer depth [Z ~> m].
real, pointer, dimension(:,:) :: MLD => NULL() !< Instantaneous active mixing layer depth [Z ~> m].
real, pointer, dimension(:,:) :: h_ML => NULL() !< Instantaneous active mixing layer thickness [H ~> m or kg m-2].
real, pointer, dimension(:,:) :: sfc_buoy_flx => NULL() !< Surface buoyancy flux (derived) [Z2 T-3 ~> m2 s-3].
real, pointer, dimension(:,:,:) :: Kd_shear => NULL()
!< The shear-driven turbulent diapycnal diffusivity at the interfaces between layers
Expand Down
Loading