Pack every layer of a 3D field into the open group: the sender’s owned mirror-source points, rows below (and, for v / corner, on) the fold line.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | fld(nxa,nya,nz) |
Field; see |
||
| integer, | intent(in) | :: | nxa |
Storage extents of |
||
| integer, | intent(in) | :: | nya |
Storage extents of |
||
| integer, | intent(in) | :: | nz |
Storage extents of |
||
| integer, | intent(in) | :: | stagger |
|
||
| logical, | intent(in), | optional | :: | device_resident |
|
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | private | :: | L | ||||
| integer, | private | :: | cap | ||||
| integer, | private | :: | fam | ||||
| integer, | private | :: | g | ||||
| integer, | private | :: | g0 | ||||
| integer, | private | :: | ng_e | ||||
| integer, | private | :: | nrow | ||||
| integer, | private | :: | oT | ||||
| integer, | private | :: | oU | ||||
| logical, | private | :: | on_device | ||||
| integer, | private | :: | p | ||||
| integer, | private | :: | r | ||||
| integer, | private | :: | sbase |
subroutine ocean_fold_pack_3d(fld, nxa, nya, nz, stagger, device_resident) !! Pack every layer of a 3D field into the open group: the sender's !! owned mirror-source points, rows below (and, for v / corner, on) !! the fold line. integer, intent(in) :: nxa, nya, nz !! Storage extents of `fld`. real(wp), intent(in) :: fld(nxa, nya, nz) !! Field; see `ocean_fold_pack_2d` for the per-stagger shape. integer, intent(in) :: stagger !! `FOLD_STAG_*`. logical, intent(in), optional :: device_resident !! `.false.` ⇒ host arrays; default device-resident. integer :: fam, nrow, sbase, g, g0, ng_e, L, r, p, cap, oT, oU logical :: on_device if (.not. fx_active) return if (.not. fx_open .or. fx_sent) then error stop "rdb_ocean_fold_exchange: ocean_fold_pack outside an open, unsent group" end if on_device = .true. if (present(device_resident)) on_device = device_resident fam = fold_stagger_family(stagger) nrow = fold_stagger_nrows(stagger, fx_ng) if (sum(fx_poff) + nrow*nz > fx_slab_cap) then error stop "rdb_ocean_fold_exchange: group larger than its ocean_fold_begin size" end if ! Source row of message row r: ng+nyl+1-r (T, u) / ng+nyl+2-r (v, ! corner; r = 1 is the fold-line row) — `fold_row_map`. sbase = fx_ng + fx_nyl + 1 if (nrow == fx_ng + 1) sbase = sbase + 1 g0 = fx_s0(fam) ng_e = fx_ns(fam) cap = fx_cap oT = fx_poff(FOLD_FAM_T) oU = fx_poff(FOLD_FAM_U) if (ng_e > 0) then if (on_device) then !$acc parallel loop collapse(3) private(p) & !$acc& present(fx_sbuf, fx_scol, fx_speer, fx_se, fx_sn, fld) do L = 1, nz do r = 1, nrow do g = g0 + 1, g0 + ng_e p = fx_speer(g) fx_sbuf((p - 1)*cap + oT*fx_sn(p, FOLD_FAM_T) + oU*fx_sn(p, FOLD_FAM_U) & + ((L - 1)*nrow + (r - 1))*fx_sn(p, fam) + fx_se(g)) = & fld(fx_scol(g), sbase - r, L) end do end do end do else do L = 1, nz do r = 1, nrow do g = g0 + 1, g0 + ng_e p = fx_speer(g) fx_sbuf((p - 1)*cap + oT*fx_sn(p, FOLD_FAM_T) + oU*fx_sn(p, FOLD_FAM_U) & + ((L - 1)*nrow + (r - 1))*fx_sn(p, fam) + fx_se(g)) = & fld(fx_scol(g), sbase - r, L) end do end do end do end if end if fx_poff(fam) = fx_poff(fam) + nrow*nz end subroutine ocean_fold_pack_3d