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). |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | private | :: | i | ||||
| integer, | private | :: | i_src | ||||
| integer, | private | :: | j | ||||
| integer, | private | :: | j_src | ||||
| integer, | private | :: | nx | ||||
| integer, | private | :: | ny | ||||
| integer, | private | :: | off |
subroutine bt_wide_copy_in_impl(this, grid, & bt_eta, bt_H_ref, bt_ubt, bt_vbt, & bt_ubt_prev, bt_vbt_prev, & bt_rem_u, bt_rem_v, & force_u, force_v) !! 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(bt_wide_t), intent(inout) :: this type(hgrid_t), intent(in) :: grid !! Normal-width grid (provides nx_total, ny_total for loop bounds). real(wp), intent(in) :: bt_eta(grid%nx_total, grid%ny_total) !! Barotropic SSH (cell centres, normal-width). real(wp), intent(in) :: bt_H_ref(grid%nx_total, grid%ny_total) !! Reference column depth (cell centres, normal-width). real(wp), intent(in) :: bt_ubt(grid%nx_total + 1, grid%ny_total) !! BT u (east faces, normal-width). real(wp), intent(in) :: bt_vbt(grid%nx_total, grid%ny_total + 1) !! BT v (north faces, normal-width). real(wp), intent(in) :: bt_ubt_prev(grid%nx_total + 1, grid%ny_total) !! BEBT u^{n-1} snapshot (east faces, normal-width). real(wp), intent(in) :: bt_vbt_prev(grid%nx_total, grid%ny_total + 1) !! BEBT v^{n-1} snapshot (north faces, normal-width). real(wp), intent(in) :: bt_rem_u(grid%nx_total + 1, grid%ny_total) !! Multiplicative drag factor for u (east faces, normal-width). real(wp), intent(in) :: bt_rem_v(grid%nx_total, grid%ny_total + 1) !! Multiplicative drag factor for v (north faces, normal-width). real(wp), intent(in) :: force_u(grid%nx_total + 1, grid%ny_total) !! BT slow forcing for u (east faces, normal-width). real(wp), intent(in) :: force_v(grid%nx_total, grid%ny_total + 1) !! BT slow forcing for v (north faces, normal-width). integer :: i, j, nx, ny, off integer :: i_src, j_src off = this%bt_halo nx = grid%nx_total ny = grid%ny_total ! Centre arrays: full wide extent (nx + 2*off, ny + 2*off), clamped ! source indices (constant extrapolation into the outer ring). do concurrent(j=1:ny + 2*off, i=1:nx + 2*off) local(i_src, j_src) i_src = min(max(i - off, 1), nx) j_src = min(max(j - off, 1), ny) this%w_eta(i, j) = bt_eta(i_src, j_src) this%w_H_ref(i, j) = bt_H_ref(i_src, j_src) end do ! East-face arrays: wide extent (nx + 2*off + 1, ny + 2*off). do concurrent(j=1:ny + 2*off, i=1:nx + 2*off + 1) local(i_src, j_src) i_src = min(max(i - off, 1), nx + 1) j_src = min(max(j - off, 1), ny) this%w_ubt(i, j) = bt_ubt(i_src, j_src) this%w_ubt_prev(i, j) = bt_ubt_prev(i_src, j_src) this%w_rem_u(i, j) = bt_rem_u(i_src, j_src) this%w_force_u(i, j) = force_u(i_src, j_src) end do ! North-face arrays: wide extent (nx + 2*off, ny + 2*off + 1). do concurrent(j=1:ny + 2*off + 1, i=1:nx + 2*off) local(i_src, j_src) i_src = min(max(i - off, 1), nx) j_src = min(max(j - off, 1), ny + 1) this%w_vbt(i, j) = bt_vbt(i_src, j_src) this%w_vbt_prev(i, j) = bt_vbt_prev(i_src, j_src) this%w_rem_v(i, j) = bt_rem_v(i_src, j_src) this%w_force_v(i, j) = force_v(i_src, j_src) end do end subroutine bt_wide_copy_in_impl