Shadow state for the wide-halo barotropic march-in.
When bt_halo > 0, the BT fast loop runs on WIDE arrays with ghost
width ng_wide = nghost + bt_halo. Ghost cells outside the valid
band evolve stale data that creeps INWARD at 2 cells/substep; one
grouped exchange every bt_halo/2 substeps keeps the physical interior
clean. The mid-substep u exchange is absorbed (within the 2-cell/substep
stencil budget).
Lifecycle:
1. init — allocate wide arrays + wide grid/metrics/f_corner.
2. enter_data — attach all wide arrays to the GPU present table.
3. Per outer step: copy_in -> (entry_exchange + substep) -> copy_out
-> normal-width exit exchange (in the caller).
4. exit_data — release GPU present table entries.
5. destroy — free host memory.
Wide-halo shadow state for the barotropic fast loop.
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | public | :: | bt_halo | = | 0 |
Requested wide-halo width (cells; even, > 0). |
|
| real(kind=wp), | public, | allocatable | :: | f_corner_w(:,:) |
Coriolis at wide-grid C-grid corners (nx_w+1, ny_w+1). |
||
| type(hgrid_t), | public | :: | grid_w |
Wide hgrid_t: nghost = ng_wide. |
|||
| logical, | public | :: | is_init | = | .false. |
True after |
|
| type(ocean_metrics_t), | public | :: | metrics_w |
Metrics built on |
|||
| integer, | public | :: | ng_wide | = | 0 |
Effective ghost width: |
|
| integer, | public | :: | num_cycles | = | 0 |
Substeps between grouped wide exchanges: |
|
| real(kind=wp), | public, | allocatable | :: | w_H_ref(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | w_eta(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | w_eta_end(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | w_eta_new(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | w_eta_sum(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | w_force_u(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | w_force_v(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | w_ke(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | w_rem_u(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | w_rem_v(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | w_ubt(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | w_ubt_end(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | w_ubt_prev(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | w_ubt_sum(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | w_uhbt(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | w_uhbt_sum(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | w_vbt(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | w_vbt_end(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | w_vbt_prev(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | w_vbt_sum(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | w_vhbt(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | w_vhbt_sum(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | w_zeta(:,:) |
| procedure, public, non_overridable :: bytes => bt_wide_bytes | |
| procedure, public, non_overridable :: copy_in => bt_wide_copy_in | |
| procedure, public, non_overridable :: copy_out => bt_wide_copy_out | |
| procedure, public, non_overridable :: destroy => bt_wide_destroy | |
| procedure, public, non_overridable :: enter_data => bt_wide_enter_data | |
| procedure, public, non_overridable :: entry_exchange => bt_wide_entry_exchange | |
| procedure, public, non_overridable :: exit_data => bt_wide_exit_data | |
| procedure, public, non_overridable :: init => bt_wide_init |
Counted allocatable footprint of the wide-halo BT shadow state
(0 when unallocated, i.e. whenever &ocean_bt_nml bt_halo = 0).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(bt_wide_t), | intent(in) | :: | this |
Wide-halo (march-in) entry point for the nonlinear barotropic fast
loop. Unpacks the wide shadow arrays (w_*, wide grid/metrics, wide
f_corner) and forwards them to barotropic_substep_nonlinear with
bt_halo = bt_wide%bt_halo, so the ~20-array plumbing lives here once
rather than at the call site. bc propagates by absence. Tides
(eta_forcing) are a configure-time exclusion on the wide path, so
none is forwarded. Interior twin: barotropic_substep_nonlinear_interior.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(bt_wide_t), | intent(inout) | :: | bt_wide | |||
| type(barotropic_workstate_t), | intent(inout) | :: | bt_work | |||
| integer, | intent(in) | :: | n_steps | |||
| real(kind=wp), | intent(in) | :: | dt_inner | |||
| type(ocean_bc_state_t), | intent(inout), | optional | :: | bc |
Offset-copy normal-width input arrays into the wide shadow arrays.
Dispatches to the non-polymorphic _impl body to avoid the
class-box GPU descriptor issue (same pattern as enter/exit_data).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(bt_wide_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| real(kind=wp), | intent(in) | :: | bt_eta(grid%nx_total,grid%ny_total) | |||
| real(kind=wp), | intent(in) | :: | bt_H_ref(grid%nx_total,grid%ny_total) | |||
| real(kind=wp), | intent(in) | :: | bt_ubt(grid%nx_total+1,grid%ny_total) | |||
| real(kind=wp), | intent(in) | :: | bt_vbt(grid%nx_total,grid%ny_total+1) | |||
| real(kind=wp), | intent(in) | :: | bt_ubt_prev(grid%nx_total+1,grid%ny_total) | |||
| real(kind=wp), | intent(in) | :: | bt_vbt_prev(grid%nx_total,grid%ny_total+1) | |||
| real(kind=wp), | intent(in) | :: | bt_rem_u(grid%nx_total+1,grid%ny_total) | |||
| real(kind=wp), | intent(in) | :: | bt_rem_v(grid%nx_total,grid%ny_total+1) | |||
| 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) |
Non-polymorphic copy_in body. Offset = bt_halo:
w_X(iw, jw) = X(clamp(iw-off), clamp(jw-off)) over the FULL wide
extent — the inner band is a direct offset copy; the outer bt_halo
ring is a clamped-index (constant-extrapolation) fill. The ring
fill matters: without it the ring carries stale end-of-fast-loop
values from the previous stage (H_ref = 0, eta from t-1), which at
a PHYSICAL (non-seam) edge is never refreshed by any exchange and
free-runs an inconsistent zero-depth integration that blows up in
O(25) outer steps. At an MPI seam the ring is immediately
overwritten with true neighbour data by entry_exchange, so the
clamped fill only governs physical edges — the same sane ghost-band
construction the v1 normal-width path gets from its own ghosts.
Scratch / accumulator arrays (w_eta_new, w_ke, w_eta_sum, …) do not
need copy-in — the substep initialises them.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(bt_wide_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid |
Normal-width grid (provides nx_total, ny_total for loop bounds). |
||
| real(kind=wp), | intent(in) | :: | bt_eta(grid%nx_total,grid%ny_total) |
Barotropic SSH (cell centres, normal-width). |
||
| real(kind=wp), | intent(in) | :: | bt_H_ref(grid%nx_total,grid%ny_total) |
Reference column depth (cell centres, normal-width). |
||
| real(kind=wp), | intent(in) | :: | bt_ubt(grid%nx_total+1,grid%ny_total) |
BT u (east faces, normal-width). |
||
| real(kind=wp), | intent(in) | :: | bt_vbt(grid%nx_total,grid%ny_total+1) |
BT v (north faces, normal-width). |
||
| real(kind=wp), | intent(in) | :: | bt_ubt_prev(grid%nx_total+1,grid%ny_total) |
BEBT u^{n-1} snapshot (east faces, normal-width). |
||
| real(kind=wp), | intent(in) | :: | bt_vbt_prev(grid%nx_total,grid%ny_total+1) |
BEBT v^{n-1} snapshot (north faces, normal-width). |
||
| real(kind=wp), | intent(in) | :: | bt_rem_u(grid%nx_total+1,grid%ny_total) |
Multiplicative drag factor for u (east faces, normal-width). |
||
| real(kind=wp), | intent(in) | :: | bt_rem_v(grid%nx_total,grid%ny_total+1) |
Multiplicative drag factor for v (north faces, normal-width). |
||
| real(kind=wp), | intent(in) | :: | force_u(grid%nx_total+1,grid%ny_total) |
BT slow forcing for u (east faces, normal-width). |
||
| real(kind=wp), | intent(in) | :: | force_v(grid%nx_total,grid%ny_total+1) |
BT slow forcing for v (north faces, normal-width). |
Offset-copy wide output arrays back to the normal-width arrays.
Dispatches to the non-polymorphic _impl body.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(bt_wide_t), | intent(in) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| real(kind=wp), | intent(out) | :: | bt_eta(grid%nx_total,grid%ny_total) | |||
| real(kind=wp), | intent(out) | :: | bt_ubt(grid%nx_total+1,grid%ny_total) | |||
| real(kind=wp), | intent(out) | :: | bt_vbt(grid%nx_total,grid%ny_total+1) | |||
| real(kind=wp), | intent(out) | :: | bt_uhbt(grid%nx_total+1,grid%ny_total) | |||
| real(kind=wp), | intent(out) | :: | bt_vhbt(grid%nx_total,grid%ny_total+1) | |||
| real(kind=wp), | intent(out) | :: | bt_eta_end(grid%nx_total,grid%ny_total) | |||
| real(kind=wp), | intent(out) | :: | bt_ubt_end(grid%nx_total+1,grid%ny_total) | |||
| real(kind=wp), | intent(out) | :: | bt_vbt_end(grid%nx_total,grid%ny_total+1) |
Non-polymorphic copy_out body. X(i,j) = w_X(i+off, j+off) over the full normal index range. Outputs: time-mean eta/ubt/vbt, uhbt/vhbt, *_end snapshots.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(bt_wide_t), | intent(in) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid |
Normal-width grid. |
||
| real(kind=wp), | intent(out) | :: | bt_eta(grid%nx_total,grid%ny_total) |
Time-mean barotropic SSH (output). |
||
| real(kind=wp), | intent(out) | :: | bt_ubt(grid%nx_total+1,grid%ny_total) |
Time-mean BT u (output). |
||
| real(kind=wp), | intent(out) | :: | bt_vbt(grid%nx_total,grid%ny_total+1) |
Time-mean BT v (output). |
||
| real(kind=wp), | intent(out) | :: | bt_uhbt(grid%nx_total+1,grid%ny_total) |
Time-mean depth-integrated u transport (output). |
||
| real(kind=wp), | intent(out) | :: | bt_vhbt(grid%nx_total,grid%ny_total+1) |
Time-mean depth-integrated v transport (output). |
||
| real(kind=wp), | intent(out) | :: | bt_eta_end(grid%nx_total,grid%ny_total) |
End-of-loop eta snapshot (output). |
||
| real(kind=wp), | intent(out) | :: | bt_ubt_end(grid%nx_total+1,grid%ny_total) |
End-of-loop u snapshot (output). |
||
| real(kind=wp), | intent(out) | :: | bt_vbt_end(grid%nx_total,grid%ny_total+1) |
End-of-loop v snapshot (output). |
Deallocate all wide state.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(bt_wide_t), | intent(inout) | :: | this |
Attach all wide arrays (and wide metrics leaf arrays) to the GPU
present table. The containing ocean_dyn_t is already mapped by
the caller; this routine attaches the components.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(bt_wide_t), | intent(inout) | :: | this |
Non-polymorphic enter_data body (avoids class-box GPU descriptor issue).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(bt_wide_t), | intent(inout) | :: | this |
One wide grouped exchange (eta+ubt+vbt) + wide singles for the other
7 input arrays (H_ref, ubt_prev, rem_u, force_u, vbt_prev, rem_v,
force_v). Fills the entire wide ghost band before the fast loop.
Counter effect: +1 bt_group, +1 centre_2d, +3 face_x_2d, +3 face_y_2d.
Dispatches to the non-polymorphic _impl body.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(bt_wide_t), | intent(inout) | :: | this |
Non-polymorphic entry_exchange body.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(bt_wide_t), | intent(inout) | :: | this |
Detach all wide arrays from the GPU present table.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(bt_wide_t), | intent(inout) | :: | this |
Non-polymorphic exit_data body.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(bt_wide_t), | intent(inout) | :: | this |
Allocate the wide shadow state. Builds grid_w (same nx_phys/ny_phys
as grid, nghost = grid%nghost + bt_halo), fills wide metrics via the
same formula generator, fills wide f_corner.
grid_config must be GRID_CONFIG_CARTESIAN or GRID_CONFIG_SPHERICAL;
supergrid/tripolar are excluded at configure time.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(bt_wide_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid |
Normal-width grid descriptor for this subdomain. |
||
| real(kind=wp), | intent(in) | :: | dx |
Cell spacing (m for Cartesian; deg for spherical). |
||
| real(kind=wp), | intent(in) | :: | dy |
Cell spacing (m for Cartesian; deg for spherical). |
||
| real(kind=wp), | intent(in) | :: | lon_west |
South-west corner (used only for spherical; ignored for Cartesian). |
||
| real(kind=wp), | intent(in) | :: | lat_south |
South-west corner (used only for spherical; ignored for Cartesian). |
||
| real(kind=wp), | intent(in) | :: | rad_earth |
Earth radius (m; used only for spherical; ignored for Cartesian). |
||
| integer, | intent(in) | :: | grid_config |
GRID_CONFIG_CARTESIAN or GRID_CONFIG_SPHERICAL. |
||
| real(kind=wp), | intent(in) | :: | f_0 |
Beta-plane Coriolis parameters. |
||
| real(kind=wp), | intent(in) | :: | beta |
Beta-plane Coriolis parameters. |
||
| real(kind=wp), | intent(in) | :: | y_ref |
Beta-plane Coriolis parameters. |
||
| integer, | intent(in) | :: | coriolis_scheme |
CORIOLIS_SCHEME_BETA_PLANE or CORIOLIS_SCHEME_PLANETARY. |
||
| real(kind=wp), | intent(in), | optional | :: | omega |
Planetary rotation rate for the planetary scheme. Absent => 0. |