rdb_barotropic_substep Module

Two kernels:

barotropic_substep_linear — linearized shallow-water with closed walls, no Coriolis, no advection. Used by the test_ocean_barotropic_substep analytic checks (rest state, constant forcing, gravity-wave standing mode) and as the unit-test anchor for the dynamics. Not called by the production split driver.

barotropic_substep_nonlinear — production substep with free-surface continuity ((H_ref + η) face thickness), Coriolis ((ζ + f)·v_perp Sadourny enstrophy-conserving), and vector-invariant advection. Called by the split RK2 driver inside each outer baroclinic step.

Both kernels read force_u, force_v as constant slow forcing for the inner substeps and write the time-mean (sum / n_steps) back into bt_eta, bt_work%bt_ubt, bt_work%bt_vbt on exit. Per-substep running sums land in bt_work%eta_sum, bt_work%ubt_sum, bt_work%vbt_sum. The nonlinear path additionally uses bt_work%bt_zeta_corner, bt_work%bt_ke_centre, bt_eta_new as per-substep scratch.

Closed-wall convention on the outer boundary: * u_bt at i=1 and i=nx+1 (array edges) stay at zero * v_bt at j=1 and j=ny+1 (array edges) stay at zero * u_bt at i=nghost+1 and i=nghost+nx_phys+1 (physical walls) stay at zero — slow continuity closes here, so the barotropic substep must too or sum_k(h_layer) drifts from H+bt_eta * v_bt at j=nghost+1 and j=nghost+ny_phys+1 (physical walls) stay at zero — same reason * ζ at the outer corner ring is clamped to zero so (ζ+f)·v reduces to the f-plane Coriolis term there

Stability: Forward-Backward Euler ordering — η update first (consumes u^n, v^n), then u/v updates (consume the just-updated η). Stable on the gravity-wave eigenmode for dt_inner · √(g·H) / dx ≤ 1.

Performance footgun (still relevant): the η-update do-concurrent uses four distinct local() face-thickness variables (h_face_E/W/N/S) rather than reusing a single h_face. gfortran 15.1 + -O3 -funroll-loops was observed to corrupt the flux divergence when h_face was reused across if/else branches. See feedback_gfortran_local_reassign.md in claude memory.


Uses

  • module~~rdb_barotropic_substep~~UsesGraph module~rdb_barotropic_substep rdb_barotropic_substep module~rdb_barotropic_workstate rdb_barotropic_workstate module~rdb_barotropic_substep->module~rdb_barotropic_workstate module~rdb_bt_cont_type rdb_bt_cont_type module~rdb_barotropic_substep->module~rdb_bt_cont_type module~rdb_constants rdb_constants module~rdb_barotropic_substep->module~rdb_constants module~rdb_grid rdb_grid module~rdb_barotropic_substep->module~rdb_grid module~rdb_ocean_boundary_types rdb_ocean_boundary_types module~rdb_barotropic_substep->module~rdb_ocean_boundary_types module~rdb_ocean_fold_exchange rdb_ocean_fold_exchange module~rdb_barotropic_substep->module~rdb_ocean_fold_exchange module~rdb_ocean_halo rdb_ocean_halo module~rdb_barotropic_substep->module~rdb_ocean_halo module~rdb_ocean_halo_counters rdb_ocean_halo_counters module~rdb_barotropic_substep->module~rdb_ocean_halo_counters module~rdb_ocean_metrics rdb_ocean_metrics module~rdb_barotropic_substep->module~rdb_ocean_metrics module~rdb_profiler rdb_profiler module~rdb_barotropic_substep->module~rdb_profiler module~rdb_barotropic_workstate->module~rdb_constants module~rdb_barotropic_workstate->module~rdb_grid iso_fortran_env iso_fortran_env module~rdb_barotropic_workstate->iso_fortran_env module~rdb_mem_report rdb_mem_report module~rdb_barotropic_workstate->module~rdb_mem_report module~rdb_bt_cont_type->module~rdb_barotropic_workstate module~rdb_bt_cont_type->module~rdb_constants pic_types pic_types module~rdb_constants->pic_types module~rdb_grid->module~rdb_constants module~rdb_ocean_boundary_types->module~rdb_constants module~rdb_ocean_boundary_types->module~rdb_grid module~rdb_ocean_boundary_types->iso_fortran_env module~rdb_ocean_boundary_types->module~rdb_mem_report module~rdb_ocean_status rdb_ocean_status module~rdb_ocean_boundary_types->module~rdb_ocean_status module~rdb_ocean_tide_astro rdb_ocean_tide_astro module~rdb_ocean_boundary_types->module~rdb_ocean_tide_astro pic_ascii pic_ascii module~rdb_ocean_boundary_types->pic_ascii pic_logger pic_logger module~rdb_ocean_boundary_types->pic_logger module~rdb_ocean_fold_exchange->module~rdb_constants module~rdb_comm_env rdb_comm_env module~rdb_ocean_fold_exchange->module~rdb_comm_env module~rdb_decomp rdb_decomp module~rdb_ocean_fold_exchange->module~rdb_decomp module~rdb_error_ring rdb_error_ring module~rdb_ocean_fold_exchange->module~rdb_error_ring module~rdb_ocean_fold rdb_ocean_fold module~rdb_ocean_fold_exchange->module~rdb_ocean_fold module~rdb_ocean_fold_plan rdb_ocean_fold_plan module~rdb_ocean_fold_exchange->module~rdb_ocean_fold_plan module~rdb_ocean_fold_exchange->module~rdb_ocean_status module~rdb_ocean_fold_exchange->pic_logger pic_mpi_lib pic_mpi_lib module~rdb_ocean_fold_exchange->pic_mpi_lib pic_strings pic_strings module~rdb_ocean_fold_exchange->pic_strings module~rdb_ocean_halo->module~rdb_constants module~rdb_ocean_halo->module~rdb_ocean_halo_counters module~rdb_ocean_halo->module~rdb_comm_env module~rdb_ocean_halo->module~rdb_decomp module~rdb_ocean_halo->module~rdb_error_ring module~rdb_ocean_periodic rdb_ocean_periodic module~rdb_ocean_halo->module~rdb_ocean_periodic module~rdb_ocean_halo->module~rdb_ocean_status module~rdb_ocean_halo->pic_logger module~rdb_ocean_halo->pic_mpi_lib module~rdb_ocean_halo->pic_strings module~rdb_ocean_halo_counters->iso_fortran_env module~rdb_ocean_halo_counters->pic_strings module~rdb_ocean_metrics->module~rdb_constants module~rdb_ocean_metrics->module~rdb_grid module~rdb_ocean_metrics->iso_fortran_env module~rdb_ocean_metrics->module~rdb_error_ring module~rdb_io_netcdf rdb_io_netcdf module~rdb_ocean_metrics->module~rdb_io_netcdf module~rdb_ocean_metrics->module~rdb_mem_report module~rdb_ocean_bipolar rdb_ocean_bipolar module~rdb_ocean_metrics->module~rdb_ocean_bipolar module~rdb_ocean_metrics->module~rdb_ocean_fold module~rdb_ocean_metrics->module~rdb_ocean_status netcdf netcdf module~rdb_ocean_metrics->netcdf module~rdb_ocean_metrics->pic_logger module~rdb_ocean_metrics->pic_strings module~rdb_profiler->iso_fortran_env module~rdb_profiler->pic_logger module~rdb_comm_env->module~rdb_constants module~rdb_comm_env->iso_fortran_env module~rdb_comm_env->pic_mpi_lib module~rdb_config rdb_config module~rdb_decomp->module~rdb_config module~rdb_error_ring->pic_logger module~rdb_io_netcdf->module~rdb_constants module~rdb_io_netcdf->iso_fortran_env module~rdb_io_netcdf->module~rdb_error_ring module~rdb_io_netcdf->netcdf module~rdb_io_netcdf->pic_logger module~rdb_io_netcdf->pic_strings iso_c_binding iso_c_binding module~rdb_io_netcdf->iso_c_binding module~rdb_mem_report->module~rdb_constants module~rdb_mem_report->iso_fortran_env module~rdb_mem_report->pic_logger module~rdb_mem_report->pic_strings module~rdb_ocean_bipolar->module~rdb_constants module~rdb_ocean_fold->module~rdb_constants module~rdb_ocean_periodic->module~rdb_constants module~rdb_ocean_periodic->module~rdb_grid module~rdb_ocean_periodic->module~rdb_ocean_boundary_types module~rdb_multilayer_state rdb_multilayer_state module~rdb_ocean_periodic->module~rdb_multilayer_state module~rdb_ocean_tide_astro->module~rdb_constants module~rdb_ocean_tide_astro->iso_fortran_env module~rdb_config->module~rdb_constants module~rdb_config->module~rdb_error_ring module~rdb_config->module~rdb_ocean_status module~rdb_config->pic_ascii module~rdb_config->pic_logger module~rdb_config->pic_strings module~rdb_ice_enthalpy rdb_ice_enthalpy module~rdb_config->module~rdb_ice_enthalpy module~rdb_ice_init rdb_ice_init module~rdb_config->module~rdb_ice_init module~rdb_nml_schema rdb_nml_schema module~rdb_config->module~rdb_nml_schema module~rdb_multilayer_state->module~rdb_constants module~rdb_multilayer_state->module~rdb_grid module~rdb_multilayer_state->iso_fortran_env module~rdb_multilayer_state->module~rdb_error_ring module~rdb_multilayer_state->module~rdb_mem_report module~rdb_multilayer_state->pic_logger module~rdb_efp rdb_efp module~rdb_multilayer_state->module~rdb_efp module~rdb_tracer rdb_tracer module~rdb_multilayer_state->module~rdb_tracer module~rdb_efp->iso_fortran_env ieee_arithmetic ieee_arithmetic module~rdb_efp->ieee_arithmetic module~rdb_ice_enthalpy->module~rdb_constants module~rdb_ice_init->module~rdb_constants module~rdb_ice_init->module~rdb_grid module~rdb_ice_init->module~rdb_ocean_metrics module~rdb_ice_init->module~rdb_multilayer_state module~rdb_ice_init->module~rdb_ice_enthalpy module~rdb_ice_column rdb_ice_column module~rdb_ice_init->module~rdb_ice_column module~rdb_ice_state rdb_ice_state module~rdb_ice_init->module~rdb_ice_state module~rdb_nml_schema->module~rdb_constants module~rdb_nml_schema->module~rdb_error_ring module~rdb_nml_schema->pic_logger module~rdb_tracer->module~rdb_constants module~rdb_tracer->module~rdb_grid module~rdb_tracer->iso_fortran_env module~rdb_tracer->module~rdb_mem_report

Used by

  • module~~rdb_barotropic_substep~~UsedByGraph module~rdb_barotropic_substep rdb_barotropic_substep module~rdb_ocean_bt_wide rdb_ocean_bt_wide module~rdb_ocean_bt_wide->module~rdb_barotropic_substep module~rdb_ocean_dyn rdb_ocean_dyn module~rdb_ocean_dyn->module~rdb_barotropic_substep module~rdb_ocean_dyn->module~rdb_ocean_bt_wide module~rdb_driver rdb_driver module~rdb_driver->module~rdb_ocean_dyn module~rdb_ocean_engine rdb_ocean_engine module~rdb_driver->module~rdb_ocean_engine module~rdb_ocean_state rdb_ocean_state module~rdb_driver->module~rdb_ocean_state module~rdb_ocean_api rdb_ocean_api module~rdb_ocean_api->module~rdb_ocean_dyn module~rdb_ocean_api->module~rdb_ocean_engine module~rdb_handle rdb_handle module~rdb_ocean_api->module~rdb_handle module~rdb_ocean_diag_derived rdb_ocean_diag_derived module~rdb_ocean_api->module~rdb_ocean_diag_derived module~rdb_ocean_diag_fills rdb_ocean_diag_fills module~rdb_ocean_api->module~rdb_ocean_diag_fills module~rdb_ocean_engine->module~rdb_ocean_dyn module~rdb_ocean_setup rdb_ocean_setup module~rdb_ocean_engine->module~rdb_ocean_setup module~rdb_ocean_engine->module~rdb_ocean_state module~rdb_ocean_engine->module~rdb_ocean_diag_derived module~rdb_ocean_engine->module~rdb_ocean_diag_fills module~rdb_ocean_setup->module~rdb_ocean_dyn module~rdb_ocean_setup->module~rdb_ocean_state module~rdb_ocean_state->module~rdb_ocean_dyn module~rdb_handle->module~rdb_ocean_engine module~rdb_handle->module~rdb_ocean_state module~rdb_ocean_diag_derived->module~rdb_ocean_state module~rdb_ocean_diag_derived->module~rdb_ocean_diag_fills module~rdb_ocean_diag_fills->module~rdb_ocean_state

Subroutines

public pure subroutine barotropic_substep_linear(grid, metrics, bt_work, force_u, force_v, n_steps, dt_inner, eta_forcing)

Public only for the unit-test suite (no production module imports it); ignore when developing production code in other modules. Linearized barotropic-substep kernel. Forward-Euler steps the barotropic state (eta, ubt, vbt) at dt_inner for n_steps against the constant slow forcing force_u, force_v (each at the same C-grid location as ubt, vbt). Accumulates the per-step running sums into ubt_sum, vbt_sum, eta_sum; at the end divides by n_steps and stores the time-mean back into bt_eta, bt_ubt, bt_vbt for the caller.

Read more…

Arguments

Type IntentOptional Attributes Name
type(hgrid_t), intent(in) :: grid
type(ocean_metrics_t), intent(in) :: metrics
type(barotropic_workstate_t), intent(inout) :: bt_work
real(kind=wp), intent(in) :: force_u(grid%nx_total+1,grid%ny_total)
real(kind=wp), intent(in) :: force_v(grid%nx_total,grid%ny_total+1)
integer, intent(in) :: n_steps
real(kind=wp), intent(in) :: dt_inner
real(kind=wp), intent(in), optional :: eta_forcing(grid%nx_total,grid%ny_total)

Optional equilibrium-tide elevation (m); when present the PGF drives grad(eta - eta_forcing). Absent => bit-identical.

public subroutine barotropic_substep_nonlinear(grid, bt_work, force_u, force_v, n_steps, dt_inner, bt_eta, bt_H_ref, bt_eta_new, bt_ke_centre, eta_sum, bt_eta_end, bt_ubt, bt_ubt_prev, bt_rem_u, ubt_sum, uhbt_sum, bt_uhbt, bt_ubt_end, bt_vbt, bt_vbt_prev, bt_rem_v, vbt_sum, vhbt_sum, bt_vhbt, bt_vbt_end, bt_zeta_corner, f_corner, area_cu, area_cv, dx_cu, dx_cv, dy_cu, dy_cv, iarea_bu, iarea_t, idx_cu, idy_cv, bc, t, eta_forcing, bt_halo)

Nonlinear barotropic substep. Same time-mean accumulator pattern as barotropic_substep_linear but the per-substep dynamics include the three barotropic nonlinearities that matter for MOM6-grade physics:

Read more…

Arguments

Type IntentOptional Attributes Name
type(hgrid_t), intent(in) :: grid
type(barotropic_workstate_t), intent(inout) :: bt_work

Carries scalars (g_bt, bebt, wetdry_enable, use_bt_cont_type, use_upstream_h_face, bt_substep_drag, wd_) and the BTCL_u/v, h_face_up_x/y, wd_ arrays that are NOT promoted. The 22 fast-loop 2D arrays below replace the bt_work% and cor% derefs; bt_work itself is still needed here.

real(kind=wp), intent(in) :: force_u(grid%nx_total+1,grid%ny_total)
real(kind=wp), intent(in) :: force_v(grid%nx_total,grid%ny_total+1)
integer, intent(in) :: n_steps
real(kind=wp), intent(in) :: dt_inner
real(kind=wp), intent(inout) :: bt_eta(grid%nx_total,grid%ny_total)

Barotropic SSH at cell centres; read+written every substep.

real(kind=wp), intent(in) :: bt_H_ref(grid%nx_total,grid%ny_total)

Reference column thickness (m); read-only inside the fast loop.

real(kind=wp), intent(inout) :: bt_eta_new(grid%nx_total,grid%ny_total)

Per-substep η^{n+1} Jacobi scratch; written in Pass 1, read in η-swap.

real(kind=wp), intent(inout) :: bt_ke_centre(grid%nx_total,grid%ny_total)

Barotropic KE at cell centres; written in Pass 1, read in Pass 2b/2c.

real(kind=wp), intent(inout) :: eta_sum(grid%nx_total,grid%ny_total)

η time-mean accumulator; zeroed at entry, accumulated each substep.

real(kind=wp), intent(inout) :: bt_eta_end(grid%nx_total,grid%ny_total)

End-of-loop η snapshot (before time-mean overwrite).

real(kind=wp), intent(inout) :: bt_ubt(grid%nx_total+1,grid%ny_total)

Depth-mean u at east faces; read+written every substep.

real(kind=wp), intent(inout) :: bt_ubt_prev(grid%nx_total+1,grid%ny_total)

u^{n-1} BEBT projection snapshot; read+written when bebt > 0.

real(kind=wp), intent(in) :: bt_rem_u(grid%nx_total+1,grid%ny_total)

BT-substep multiplicative drag factor at u-faces; read-only.

real(kind=wp), intent(inout) :: ubt_sum(grid%nx_total+1,grid%ny_total)

u time-mean accumulator; zeroed at entry, accumulated each substep.

real(kind=wp), intent(inout) :: uhbt_sum(grid%nx_total+1,grid%ny_total)

Depth-integrated u transport accumulator; zeroed and accumulated.

real(kind=wp), intent(inout) :: bt_uhbt(grid%nx_total+1,grid%ny_total)

Time-mean east-face transport (m²/s); written at loop end.

real(kind=wp), intent(inout) :: bt_ubt_end(grid%nx_total+1,grid%ny_total)

End-of-loop u snapshot (before time-mean overwrite).

real(kind=wp), intent(inout) :: bt_vbt(grid%nx_total,grid%ny_total+1)

Depth-mean v at north faces; read+written every substep.

real(kind=wp), intent(inout) :: bt_vbt_prev(grid%nx_total,grid%ny_total+1)

v^{n-1} BEBT projection snapshot; read+written when bebt > 0.

real(kind=wp), intent(in) :: bt_rem_v(grid%nx_total,grid%ny_total+1)

BT-substep multiplicative drag factor at v-faces; read-only.

real(kind=wp), intent(inout) :: vbt_sum(grid%nx_total,grid%ny_total+1)

v time-mean accumulator; zeroed at entry, accumulated each substep.

real(kind=wp), intent(inout) :: vhbt_sum(grid%nx_total,grid%ny_total+1)

Depth-integrated v transport accumulator; zeroed and accumulated.

real(kind=wp), intent(inout) :: bt_vhbt(grid%nx_total,grid%ny_total+1)

Time-mean north-face transport (m²/s); written at loop end.

real(kind=wp), intent(inout) :: bt_vbt_end(grid%nx_total,grid%ny_total+1)

End-of-loop v snapshot (before time-mean overwrite).

real(kind=wp), intent(inout) :: bt_zeta_corner(grid%nx_total+1,grid%ny_total+1)

Barotropic relative vorticity at corners; written in Pass 1, read in Pass 2b/2c.

real(kind=wp), intent(in) :: f_corner(grid%nx_total+1,grid%ny_total+1)

Coriolis parameter at corners (from coriolis_adv_t%f_corner); read-only. Passed explicitly so a wide-halo caller (Phase 3c) can supply a wide f_corner without touching the arithmetic body.

real(kind=wp), intent(in) :: area_cu(grid%nx_total+1,grid%ny_total)
real(kind=wp), intent(in) :: area_cv(grid%nx_total,grid%ny_total+1)
real(kind=wp), intent(in) :: dx_cu(grid%nx_total+1,grid%ny_total)
real(kind=wp), intent(in) :: dx_cv(grid%nx_total,grid%ny_total+1)
real(kind=wp), intent(in) :: dy_cu(grid%nx_total+1,grid%ny_total)
real(kind=wp), intent(in) :: dy_cv(grid%nx_total,grid%ny_total+1)
real(kind=wp), intent(in) :: iarea_bu(grid%nx_total+1,grid%ny_total+1)
real(kind=wp), intent(in) :: iarea_t(grid%nx_total,grid%ny_total)
real(kind=wp), intent(in) :: idx_cu(grid%nx_total+1,grid%ny_total)
real(kind=wp), intent(in) :: idy_cv(grid%nx_total,grid%ny_total+1)
type(ocean_bc_state_t), intent(inout), optional :: bc

intent(inout) so the routine can update the persistent eta_old_chapman_* scalars used by the OBC_CHAPMAN radiation BC. Other BC types (WALL/OPEN/CLAMPED/TIDAL) treat bc as read-only — the inout intent is for the Chapman state lifecycle.

real(kind=wp), intent(in), optional :: t

Outer-step wall time (s) used to evaluate the per-edge tidal constituent table for OBC_TIDAL. Treated as a constant across the barotropic substeps (tidal periods are orders of magnitude longer than the inner dt). Absent ⇒ t = 0; the OBC_TIDAL formula degenerates to OBC_OPEN.

real(kind=wp), intent(in), optional :: eta_forcing(grid%nx_total,grid%ny_total)

Optional equilibrium-tide elevation (m); when present the PGF drives grad(eta - eta_forcing). Absent => bit-identical.

integer, intent(in), optional :: bt_halo

Wide-halo march-in width (Phase 3c). When > 0 the caller has supplied wide shadow arrays and grid has nghost = nghost + bt_halo. The mid-substep u exchange is absorbed and the per-substep group exchange is replaced by one wide exchange every bt_halo/2 substeps. Absent or 0 => v1 per-substep exchange path (bit-identical).

public subroutine barotropic_substep_nonlinear_interior(grid, metrics, bt_work, f_corner, n_steps, dt_inner, bc, t, eta_forcing)

Interior (normal-width) entry point for the nonlinear barotropic fast loop. Unpacks the bt_work fast-loop arrays and forwards them to barotropic_substep_nonlinear (bt_halo=0), so the ~20-array plumbing lives here once instead of at every call site. The optional bc/t/eta_forcing propagate by absence (F2018 15.5.2.13), so this single entry reproduces the former present()-branch call variants bit-for-bit. See bt_wide_substep for the wide-halo march-in twin.

Arguments

Type IntentOptional Attributes Name
type(hgrid_t), intent(in) :: grid
type(ocean_metrics_t), intent(in) :: metrics
type(barotropic_workstate_t), intent(inout) :: bt_work
real(kind=wp), intent(in) :: f_corner(grid%nx_total+1,grid%ny_total+1)

Coriolis at corners (coriolis_adv_t%f_corner); forwarded read-only.

integer, intent(in) :: n_steps
real(kind=wp), intent(in) :: dt_inner
type(ocean_bc_state_t), intent(inout), optional :: bc
real(kind=wp), intent(in), optional :: t
real(kind=wp), intent(in), optional :: eta_forcing(grid%nx_total,grid%ny_total)