Fill ghost cells of a cell-centred 3D field (e.g. h_layer, hTr, T, S).
no_wait (optional, default .false.): when .true., loops issue on
OpenACC queue 1 and the routine returns WITHOUT syncing, so a batched
caller can pipeline many tiny ghost-slab wraps and !$acc wait(1)
once. Default ⇒ self-contained blocking wrap. Not pure (directives).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(inout) | :: | fld(nx_total,ny_total,nz) |
Cell-centred field, shape (nx_total, ny_total, nz). |
||
| integer, | intent(in) | :: | nx_total | |||
| integer, | intent(in) | :: | ny_total | |||
| integer, | intent(in) | :: | nz | |||
| integer, | intent(in) | :: | nx_phys | |||
| integer, | intent(in) | :: | ny_phys | |||
| integer, | intent(in) | :: | nghost | |||
| logical, | intent(in) | :: | wrap_x | |||
| logical, | intent(in) | :: | wrap_y | |||
| logical, | intent(in), | optional | :: | no_wait |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | private | :: | i | ||||
| integer, | private | :: | j | ||||
| integer, | private | :: | k | ||||
| logical, | private | :: | lwait |
subroutine ocean_periodic_wrap_centre_3d(fld, nx_total, ny_total, nz, & nx_phys, ny_phys, nghost, & wrap_x, wrap_y, no_wait) !! Fill ghost cells of a cell-centred 3D field (e.g. h_layer, hTr, T, S). !! `no_wait` (optional, default .false.): when .true., loops issue on !! OpenACC queue 1 and the routine returns WITHOUT syncing, so a batched !! caller can pipeline many tiny ghost-slab wraps and `!$acc wait(1)` !! once. Default ⇒ self-contained blocking wrap. Not `pure` (directives). integer, intent(in) :: nx_total, ny_total, nz, nx_phys, ny_phys, nghost real(wp), intent(inout) :: fld(nx_total, ny_total, nz) !! Cell-centred field, shape (nx_total, ny_total, nz). logical, intent(in) :: wrap_x logical, intent(in) :: wrap_y logical, intent(in), optional :: no_wait integer :: i, j, k logical :: lwait lwait = .true. ! default: blocking (wait) — safe for non-batched callers if (present(no_wait)) lwait = .not. no_wait ! X-wrap first, then Y-wrap in a separate loop. Two passes needed ! because the Y-wrap reads the x-ghost columns the X-pass just wrote. ! Same queue ⇒ ordered ⇒ the X→Y dependency holds. !$acc kernels async(1) if (wrap_x) then do concurrent(k=1:nz, j=1:ny_total, i=1:nx_total) if (i <= nghost) then fld(i, j, k) = fld(i + nx_phys, j, k) end if if (i > nx_phys + nghost) then fld(i, j, k) = fld(i - nx_phys, j, k) end if end do end if if (wrap_y) then do concurrent(k=1:nz, j=1:ny_total, i=1:nx_total) if (j <= nghost) then fld(i, j, k) = fld(i, j + ny_phys, k) end if if (j > ny_phys + nghost) then fld(i, j, k) = fld(i, j - ny_phys, k) end if end do end if !$acc end kernels if (lwait) then !$acc wait(1) end if end subroutine ocean_periodic_wrap_centre_3d