MOM6 set_viscous_BBL (the
BOTTOMDRAGLAW branch): the per-face bottom-boundary-layer
viscosity kv_bbl_u/v and thickness bbl_thick_u/v that the
vertical-friction glue reads. Called ONCE per outer step, before
the stage loop, from the state at the start of the step — MOM6
calls it once per step, from step_MOM_dynamics, before the
predictor. No-op unless bbl_glue .and. bbl_per_face.
Per face (bed up; MOM6 counts from the surface, so its k = nz
is our k = 1):
h_at_vel: harmonic mean of the two cells when the flow runs
thin -> thick (u·Δh >= 0), else arithmetic;
T and S at the face are plain averages of the two cells’
CONCENTRATIONS (I1′ column rule).u_bbl: the h_at_vel-weighted mean, over the bottom HBBL,
of sqrt(u² + v_at_u² + DRAG_BG_VEL²) (v_at_u the masked
thickness-weighted average of the four transverse faces,
set_v_at_u); u* = sqrt(CDRAG)·u_bbl, or
sqrt(CDRAG)·DRAG_BG_VEL for the linear law or an empty
average.h_N: the stratification-limited thickness, integrating the
density jump up from the bed until h·Δρ reaches
400·ρ₀·u*²/g (Killworth & Edwards 1999 eq. 2.22), with
∂ρ/∂T, ∂ρ/∂S at the BBL-mean T/S and the
bottom pressure ρ₀·g·Σh (no surface-pressure term).bbl_thick = h_N/(1/2 + sqrt(1/4 + (2f·h_N/u*)²)) (rotation,
Killworth & Edwards 1999 eq. 2.20), floored at BBL_THICK_MIN,
capped at HBBL/2 under kappa-shear.kv_bbl = sqrt(CDRAG)·u*·bbl_thick — the viscosity whose
stress over bbl_thick is CDRAG·u_bbl².A dry face gets kv_bbl = 0, bbl_thick = HBBL. Open-boundary
faces are NOT given MOM6’s zero-gradient projection: they read
their two cells like any interior face.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_vdiff_t), | intent(inout) | :: | this | |||
| type(multilayer_state_t), | intent(in) | :: | ms | |||
| type(eos_t), | intent(in) | :: | eos |
The run’s equation of state, for |
||
| real(kind=wp), | intent(in) | :: | f_corner(grid%nx_total+1,grid%ny_total+1) |
Coriolis parameter at cell SW corners (1/s), |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | private | :: | nx | ||||
| integer, | private | :: | ny | ||||
| integer, | private | :: | nz | ||||
| logical, | private | :: | use_eos |
subroutine vdiff_set_viscous_bbl(grid, this, ms, eos, f_corner) !! MOM6 `set_viscous_BBL` (the !! `BOTTOMDRAGLAW` branch): the per-face bottom-boundary-layer !! viscosity `kv_bbl_u/v` and thickness `bbl_thick_u/v` that the !! vertical-friction glue reads. Called ONCE per outer step, before !! the stage loop, from the state at the start of the step — MOM6 !! calls it once per step, from `step_MOM_dynamics`, before the !! predictor. No-op unless `bbl_glue .and. bbl_per_face`. !! !! Per face (bed up; MOM6 counts from the surface, so its `k = nz` !! is our `k = 1`): !! !! 1. `h_at_vel`: harmonic mean of the two cells when the flow runs !! thin -> thick (`u·Δh >= 0`), else arithmetic; !! T and S at the face are plain averages of the two cells' !! CONCENTRATIONS (I1′ column rule). !! 2. `u_bbl`: the `h_at_vel`-weighted mean, over the bottom `HBBL`, !! of `sqrt(u² + v_at_u² + DRAG_BG_VEL²)` (`v_at_u` the masked !! thickness-weighted average of the four transverse faces, !! `set_v_at_u`); `u* = sqrt(CDRAG)·u_bbl`, or !! `sqrt(CDRAG)·DRAG_BG_VEL` for the linear law or an empty !! average. !! 3. `h_N`: the stratification-limited thickness, integrating the !! density jump up from the bed until `h·Δρ` reaches !! `400·ρ₀·u*²/g` (Killworth & Edwards 1999 eq. 2.22), with !! `∂ρ/∂T`, `∂ρ/∂S` at the BBL-mean T/S and the !! bottom pressure `ρ₀·g·Σh` (no surface-pressure term). !! 4. `bbl_thick = h_N/(1/2 + sqrt(1/4 + (2f·h_N/u*)²))` (rotation, !! Killworth & Edwards 1999 eq. 2.20), floored at `BBL_THICK_MIN`, !! capped at `HBBL/2` under kappa-shear. !! 5. `kv_bbl = sqrt(CDRAG)·u*·bbl_thick` — the viscosity whose !! stress over `bbl_thick` is `CDRAG·u_bbl²`. !! !! A dry face gets `kv_bbl = 0`, `bbl_thick = HBBL`. Open-boundary !! faces are NOT given MOM6's zero-gradient projection: they read !! their two cells like any interior face. type(hgrid_t), intent(in) :: grid type(ocean_vdiff_t), intent(inout) :: this type(multilayer_state_t), intent(in) :: ms type(eos_t), intent(in) :: eos !! The run's equation of state, for `∂ρ/∂T` and `∂ρ/∂S`. real(wp), intent(in) :: f_corner(grid%nx_total + 1, grid%ny_total + 1) !! Coriolis parameter at cell SW corners (1/s), `cor%f_corner`. integer :: nx, ny, nz logical :: use_eos if (.not. (this%bbl_glue .and. this%bbl_per_face)) return nx = grid%nx_total ny = grid%ny_total nz = ms%nz_ml use_eos = ms%idx_temperature > 0 .and. ms%idx_salinity > 0 if (use_eos) then call bbl_column_conc_impl(nx, ny, nz, ms%h_layer, & ms%tracers(ms%idx_temperature)%hTr, this%bbl_conc_t) call bbl_column_conc_impl(nx, ny, nz, ms%h_layer, & ms%tracers(ms%idx_salinity)%hTr, this%bbl_conc_s) end if call bbl_faces_impl(nx + 1, ny, nx, ny, nz, .true., & ms%u_face_x_layer, ms%v_face_y_layer, ms%h_layer, ms%wet_mask, & this%bbl_conc_t, this%bbl_conc_s, size(this%bbl_conc_t, 1), & size(this%bbl_conc_t, 2), size(this%bbl_conc_t, 3), & f_corner, use_eos, eos, this%bbl_form, this%bbl_cd, this%bbl_hbbl, & this%bbl_bg_vel, this%bbl_thick_min, this%bbl_rino_cap, & this%bbl_rho0, this%kv_bbl_u, this%bbl_thick_u) call bbl_faces_impl(nx, ny + 1, nx, ny, nz, .false., & ms%u_face_x_layer, ms%v_face_y_layer, ms%h_layer, ms%wet_mask, & this%bbl_conc_t, this%bbl_conc_s, size(this%bbl_conc_t, 1), & size(this%bbl_conc_t, 2), size(this%bbl_conc_t, 3), & f_corner, use_eos, eos, this%bbl_form, this%bbl_cd, this%bbl_hbbl, & this%bbl_bg_vel, this%bbl_thick_min, this%bbl_rino_cap, & this%bbl_rho0, this%kv_bbl_v, this%bbl_thick_v) end subroutine vdiff_set_viscous_bbl