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
2 changes: 1 addition & 1 deletion src/core/MOM.F90
Original file line number Diff line number Diff line change
Expand Up @@ -1388,9 +1388,9 @@ subroutine step_MOM_dynamics(forces, p_surf_begin, p_surf_end, dt, dt_tr_adv, &
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%stoch_CS)

if (CS%debug) call hchksum(h,"Post-thickness_diffuse h", G%HI, haloshift=1, unscale=GV%H_to_MKS)
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 (CS%debug) call hchksum(h,"Post-thickness_diffuse h", G%HI, haloshift=1, unscale=GV%H_to_MKS)
if (showCallTree) call callTree_waypoint("finished thickness_diffuse (step_MOM)")
endif

Expand Down
81 changes: 77 additions & 4 deletions src/core/MOM_barotropic.F90
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,12 @@ module MOM_barotropic
!! equation. Otherwise the transports are the sum of the transports
!! based on a series of instantaneous velocities and the BT_CONT_TYPE
!! for transports. This is only valid if a BT_CONT_TYPE is used.
logical :: bt_adjust_src_for_filter !< If true, increases the rate at which BT mass sources are
!! applied so that they are all used up before the steps within the
!! filtering period start. This avoids the mass sink driving the SSH
!! below the bottom during the period of filtering.
logical :: bt_limit_integral_transport !< If true, limit the time-integrated transports by the
!! initial volume accounting for sinks of mass.
logical :: integral_OBCs !< This is true if integral_bt_cont is true and there are open boundary
!! conditions being applied somewhere in the global domain.
logical :: Nonlinear_continuity !< If true, the barotropic continuity equation
Expand Down Expand Up @@ -1731,9 +1737,10 @@ subroutine btstep(U_in, V_in, eta_in, dt, bc_accel_u, bc_accel_v, forces, pbce,
endif
nfilter = ceiling(dt_filt / dtbt)

if (nstep+nfilter==0 ) call MOM_error(FATAL, &
if ( nstep+nfilter<=0 ) call MOM_error(FATAL, &
"btstep: number of barotropic step (nstep+nfilter) is 0")

if ( CS%bt_limit_integral_transport .and. nstep-nfilter<=0 ) call MOM_error(FATAL, &
"btstep: barotropic filter steps too large (nstep-nfilter) is 0")

! Set up the normalized weights for the filtered velocity.
sum_wt_vel = 0.0 ; sum_wt_eta = 0.0 ; sum_wt_accel = 0.0 ; sum_wt_trans = 0.0
Expand Down Expand Up @@ -2374,7 +2381,8 @@ subroutine btstep_timeloop(eta, ubt, vbt, uhbt0, Datu, BTCL_u, vhbt0, Datv, BTCL
real, target, dimension(SZIW_(CS),SZJW_(CS)) :: &
eta_pred ! A predictor value of eta [H ~> m or kg m-2] like eta
real, dimension(SZIW_(CS),SZJW_(CS)) :: &
p_surf_dyn !< A dynamic surface pressure under rigid ice [L2 T-2 ~> m2 s-2]
p_surf_dyn, & !< A dynamic surface pressure under rigid ice [L2 T-2 ~> m2 s-2]
cfl_ltd_vol !< The volume available after removing sinks used to limit uhbt_int and vhbt_int [H L2 ~> m3]
real :: wt_end ! The weighting of the final value of eta_PF [nondim]
real :: Instep ! The inverse of the number of barotropic time steps to take [nondim]
real :: trans_wt1, trans_wt2 ! The weights used to compute ubt_trans and vbt_trans [nondim]
Expand All @@ -2389,6 +2397,8 @@ subroutine btstep_timeloop(eta, ubt, vbt, uhbt0, Datu, BTCL_u, vhbt0, Datv, BTCL
real :: be_proj ! The fractional amount by which velocities are projected
! when project_velocity is true [nondim]. For now be_proj is set
! to equal bebt, as they have similar roles and meanings.
real :: eta_cor_multiplier ! Increases the rate of applying CS%eta_cor so that the mass
! source is all used up by the beginning of the filtering [nondim]
logical :: do_hifreq_output ! If true, output occurs every barotropic step.
logical :: do_ave ! If true, diagnostics are enabled on this step.
logical :: evolving_face_areas
Expand Down Expand Up @@ -2490,6 +2500,28 @@ subroutine btstep_timeloop(eta, ubt, vbt, uhbt0, Datu, BTCL_u, vhbt0, Datv, BTCL
endif

p_surf_dyn(:,:) = 0.0
cfl_ltd_vol(:,:) = huge( GV%Z_to_H )
if (CS%bt_limit_integral_transport) then
! Issue warnings if there are unphysical values of the initial sea surface height or total water column mass.
if (GV%Boussinesq) then
do j=js,je ; do i=is,ie
if ((eta_IC(i,j) < -GV%Z_to_H*G%bathyT(i,j)) .and. (G%mask2dT(i,j) > 0.0)) then
write(mesg,'(ES24.16," vs. ",ES24.16, " at ", ES12.4, ES12.4, i7, i7)') GV%H_to_m*eta(i,j), &
-US%Z_to_m*G%bathyT(i,j), G%geoLonT(i,j), G%geoLatT(i,j), i + G%HI%idg_offset, j + G%HI%jdg_offset
call MOM_error(FATAL, "btstep: eta_IC starts below bathyT: "//trim(mesg), all_print=.true.)
endif
enddo ; enddo
else
do j=js,je ; do i=is,ie
if (eta_IC(i,j) < 0.0) then
write(mesg,'(" at ", ES12.4, ES12.4, i7, i7)') &
G%geoLonT(i,j), G%geoLatT(i,j), i + G%HI%idg_offset, j + G%HI%jdg_offset
call MOM_error(FATAL, "btstep: negative eta_IC at start of a non-Boussinesq barotropic solver "//&
trim(mesg), all_print=.true.)
endif
enddo ; enddo
endif
endif

! Set up the group pass used for halo updates within the barotropic time stepping loops.
call create_group_pass(CS%pass_eta_ubt, eta, CS%BT_Domain)
Expand Down Expand Up @@ -2601,12 +2633,30 @@ subroutine btstep_timeloop(eta, ubt, vbt, uhbt0, Datu, BTCL_u, vhbt0, Datv, BTCL

! Determine the transports based on the updated velocities when no OBCs are applied
if (integral_BT_cont) then
if (CS%bt_limit_integral_transport) then
! Calculate the volume that could be used for divergent transport to use for a limter. This applies to
! uhbt_int and vhbt_int at each BT step. It does not allow for temporary flooding during the BT cycling.
! Only the sink is accounted for: if diverent motion occurs at the beginning of the BT cycling but the volume
! was due only to a +ve source being applied gradually, then the instantaneous eta could drop below the bottom.
if (GV%Boussinesq) then
do j=jsv,jev ; do i=isv,iev
cfl_ltd_vol(i,j) = ( CS%maxCFL_BT_cont * G%areaT(i,j) ) * &
max( 0., ( GV%Z_to_H*G%bathyT(i,j) + eta_IC(i,j) ) + nstep * min( 0., eta_src(i,j) ) )
enddo ; enddo
else
do j=jsv,jev ; do i=isv,iev
cfl_ltd_vol(i,j) = ( CS%maxCFL_BT_cont * G%areaT(i,j) ) * &
max( 0., eta_IC(i,j) + nstep * min( 0., eta_src(i,j) ) )
enddo ; enddo
endif
endif
!$OMP do schedule(static)
do j=jsv,jev ; do I=isv-1,iev
ubt_trans(I,j) = trans_wt1*ubt(I,j) + trans_wt2*ubt_prev(I,j)
ubt_int_prev(I,j) = ubt_int(I,j) ! Store the previous integrated velocity so it can be reset by at OBC points
ubt_int(I,j) = ubt_int(I,j) + dtbt * ubt_trans(I,j)
uhbt_int(I,j) = find_uhbt(ubt_int(I,j), BTCL_u(I,j)) + n*dtbt*uhbt0(I,j)
uhbt_int(I,j) = max( -cfl_ltd_vol(i+1,j), min( uhbt_int(I,j), cfl_ltd_vol(i,j) ) )
! Estimate the mass flux within a single timestep to take the filtered average.
uhbt(I,j) = (uhbt_int(I,j) - uhbt_int_prev(I,j)) * Idtbt
enddo ; enddo
Expand All @@ -2617,6 +2667,7 @@ subroutine btstep_timeloop(eta, ubt, vbt, uhbt0, Datu, BTCL_u, vhbt0, Datv, BTCL
vbt_int_prev(i,J) = vbt_int(i,J) ! Store the previous integrated velocity so it can be reset by at OBC points
vbt_int(i,J) = vbt_int(i,J) + dtbt * vbt_trans(i,J)
vhbt_int(i,J) = find_vhbt(vbt_int(i,J), BTCL_v(i,J)) + n*dtbt*vhbt0(i,J)
vhbt_int(i,J) = max( -cfl_ltd_vol(i,j+1), min( vhbt_int(i,J), cfl_ltd_vol(i,j) ) )
! Estimate the mass flux within a single timestep to take the filtered average.
vhbt(i,J) = (vhbt_int(i,J) - vhbt_int_prev(i,J)) * Idtbt
enddo ; enddo
Expand Down Expand Up @@ -2712,9 +2763,17 @@ subroutine btstep_timeloop(eta, ubt, vbt, uhbt0, Datu, BTCL_u, vhbt0, Datv, BTCL

! Update eta in a corrector step using the barotropic continuity equation.
if (integral_BT_cont) then
eta_cor_multiplier = n
if ( CS%bt_adjust_src_for_filter ) then
if ( nstep > nfilter ) then
eta_cor_multiplier = min(nstep - nfilter, n) * nstep / real(nstep - nfilter)
else
eta_cor_multiplier = nstep
endif
endif
!$OMP do
do j=jsv,jev ; do i=isv,iev
eta(i,j) = (eta_IC(i,j) + n*eta_src(i,j)) + CS%IareaT_OBCmask(i,j) * &
eta(i,j) = (eta_IC(i,j) + eta_cor_multiplier*eta_src(i,j)) + CS%IareaT_OBCmask(i,j) * &
((uhbt_int(I-1,j) - uhbt_int(I,j)) + (vhbt_int(i,J-1) - vhbt_int(i,J)))
eta_wtd(i,j) = eta_wtd(i,j) + eta(i,j) * wt_eta(n)
enddo ; enddo
Expand All @@ -2740,6 +2799,8 @@ subroutine btstep_timeloop(eta, ubt, vbt, uhbt0, Datu, BTCL_u, vhbt0, Datv, BTCL
if ((eta(i,j) < -GV%Z_to_H*G%bathyT(i,j)) .and. (G%mask2dT(i,j) > 0.0)) then
write(mesg,'(ES24.16," vs. ",ES24.16, " at ", ES12.4, ES12.4, i7, i7)') GV%H_to_m*eta(i,j), &
-US%Z_to_m*G%bathyT(i,j), G%geoLonT(i,j), G%geoLatT(i,j), i + G%HI%idg_offset, j + G%HI%jdg_offset
if (CS%bt_limit_integral_transport) &
call MOM_error(FATAL, "btstep: eta has dropped below bathyT: "//trim(mesg))
if (err_count < 2) &
call MOM_error(WARNING, "btstep: eta has dropped below bathyT: "//trim(mesg), all_print=.true.)
err_count = err_count + 1
Expand All @@ -2750,6 +2811,8 @@ subroutine btstep_timeloop(eta, ubt, vbt, uhbt0, Datu, BTCL_u, vhbt0, Datv, BTCL
if (eta(i,j) < 0.0) then
write(mesg,'(" at ", ES12.4, ES12.4, i7, i7)') &
G%geoLonT(i,j), G%geoLatT(i,j), i + G%HI%idg_offset, j + G%HI%jdg_offset
if (CS%bt_limit_integral_transport) &
call MOM_error(FATAL, "btstep: negative eta in a non-Boussinesq barotropic solver "//trim(mesg))
if (err_count < 2) &
call MOM_error(WARNING, "btstep: negative eta in a non-Boussinesq barotropic solver "//&
trim(mesg), all_print=.true.)
Expand Down Expand Up @@ -5439,6 +5502,16 @@ subroutine barotropic_init(u, v, h, Time, G, GV, US, param_file, diag, CS, &
"This is a decent approximation to the inclusion of "//&
"sum(u dh_dt) while also correcting for truncation errors.", &
default=.false.)
call get_param(param_file, mdl, "BT_ADJUST_SRC_FOR_FILTER", CS%bt_adjust_src_for_filter, &
"If true, increases the rate at which BT mass sources are applied so "//&
"that they are all used up before the filtering period starts. "//&
"This option is only valid if INTEGRAL_BT_CONTINUITY = True.", &
default=.false., do_not_log=.not.CS%integral_bt_cont)
call get_param(param_file, mdl, "BT_LIMIT_INTEGRAL_TRANSPORT", CS%bt_limit_integral_transport, &
"If true, limit the time-integrated transports by the initial volume "//&
"accounting for sinks of mass. The limiter uses MAXCFL_BT_CONT. "//&
"This option is only valid if INTEGRAL_BT_CONTINUITY = True.", &
default=.false., do_not_log=.not.CS%integral_bt_cont)
call get_param(param_file, mdl, "BT_USE_VISC_REM_U_UH0", CS%visc_rem_u_uh0, &
"If true, use the viscous remnants when estimating the "//&
"barotropic velocities that were used to calculate uh0 "//&
Expand Down
16 changes: 13 additions & 3 deletions src/core/MOM_dynamics_split_RK2.F90
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,9 @@ module MOM_dynamics_split_RK2
logical :: BT_use_layer_fluxes !< If true, use the summed layered fluxes plus
!! an adjustment due to a changed barotropic
!! velocity in the barotropic continuity equation.
logical :: BT_adj_corr_mass_src !< If true, recalculates the barotropic mass source after
Comment thread
Hallberg-NOAA marked this conversation as resolved.
!! predictor step. This should make little difference in the
!! deep ocean but appears to help for vanished layers.
logical :: split_bottom_stress !< If true, provide the bottom stress
!! calculated by the vertical viscosity to the
!! barotropic solver.
Expand Down Expand Up @@ -817,9 +820,11 @@ subroutine step_MOM_dyn_split_RK2(u_inst, v_inst, h, tv, visc, Time_local, dt, f
! used in the next call to btstep. This call is at this point so that
! hp can be changed if CS%begw /= 0.
! eta_cor = ... (hidden inside CS%barotropic_CSp)
call cpu_clock_begin(id_clock_btcalc)
call bt_mass_source(hp, eta_pred, .false., G, GV, CS%barotropic_CSp)
call cpu_clock_end(id_clock_btcalc)
if (CS%BT_adj_corr_mass_src) then
call cpu_clock_begin(id_clock_btcalc)
call bt_mass_source(hp, eta_pred, .false., G, GV, CS%barotropic_CSp)
call cpu_clock_end(id_clock_btcalc)
endif

if (CS%begw /= 0.0) then
! hp <- (1-begw)*h_in + begw*hp
Expand Down Expand Up @@ -1454,6 +1459,11 @@ subroutine initialize_dyn_split_RK2(u, v, h, tv, uh, vh, eta, Time, G, GV, US, p
"If true, use the summed layered fluxes plus an "//&
"adjustment due to the change in the barotropic velocity "//&
"in the barotropic continuity equation.", default=.true.)
call get_param(param_file, mdl, "BT_ADJ_CORR_MASS_SRC", CS%BT_adj_corr_mass_src, &
"If true, recalculates the barotropic mass source after "//&
"predictor step. This should make little difference in the "//&
"deep ocean but appears to help for vanished layers. If false, "//&
"uses the same mass source as from the predictor step.", default=.true.)
call get_param(param_file, mdl, "STORE_CORIOLIS_ACCEL", CS%store_CAu, &
"If true, calculate the Coriolis accelerations at the end of each "//&
"timestep for use in the predictor step of the next split RK2 timestep.", &
Expand Down
16 changes: 13 additions & 3 deletions src/core/MOM_dynamics_split_RK2b.F90
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ module MOM_dynamics_split_RK2b
!! effective summed open face areas as a function
!! of barotropic flow.

logical :: BT_adj_corr_mass_src !< If true, recalculates the barotropic mass source after
!! predictor step. This should make little difference in the
!! deep ocean but appears to help for vanished layers.
logical :: split_bottom_stress !< If true, provide the bottom stress
!! calculated by the vertical viscosity to the
!! barotropic solver.
Expand Down Expand Up @@ -811,9 +814,11 @@ subroutine step_MOM_dyn_split_RK2b(u_av, v_av, h, tv, visc, Time_local, dt, forc
! used in the next call to btstep. This call is at this point so that
! hp can be changed if CS%begw /= 0.
! eta_cor = ... (hidden inside CS%barotropic_CSp)
call cpu_clock_begin(id_clock_btcalc)
call bt_mass_source(hp, eta_pred, .false., G, GV, CS%barotropic_CSp)
call cpu_clock_end(id_clock_btcalc)
if (CS%BT_adj_corr_mass_src) then
call cpu_clock_begin(id_clock_btcalc)
call bt_mass_source(hp, eta_pred, .false., G, GV, CS%barotropic_CSp)
call cpu_clock_end(id_clock_btcalc)
endif

if (CS%begw /= 0.0) then
! hp <- (1-begw)*h_in + begw*hp
Expand Down Expand Up @@ -1350,6 +1355,11 @@ subroutine initialize_dyn_split_RK2b(u, v, h, tv, uh, vh, eta, Time, G, GV, US,
call get_param(param_file, mdl, "SPLIT_BOTTOM_STRESS", CS%split_bottom_stress, &
"If true, provide the bottom stress calculated by the "//&
"vertical viscosity to the barotropic solver.", default=.false.)
call get_param(param_file, mdl, "BT_ADJ_CORR_MASS_SRC", CS%BT_adj_corr_mass_src, &
"If true, recalculates the barotropic mass source after "//&
"predictor step. This should make little difference in the "//&
"deep ocean but appears to help for vanished layers. If false, "//&
"uses the same mass source as from the predictor step.", default=.true.)
! call get_param(param_file, mdl, "FPMIX", CS%fpmix, &
! "If true, apply profiles of momentum flux magnitude and direction.", &
! default=.false.)
Expand Down
Loading