3D y-face (Cv) fold: north-halo fill + on-line antisymmetric
projection at the fold row. See the 2D twin for the negate
(vector vs. scalar) contract.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(inout) | :: | v(nx_total,ny_face,nz) |
y-face 3D field, shape (nx_total, ny_total+1, nz). |
||
| integer, | intent(in) | :: | nx_total | |||
| integer, | intent(in) | :: | ny_face | |||
| integer, | intent(in) | :: | nz | |||
| integer, | intent(in) | :: | nx_phys | |||
| integer, | intent(in) | :: | ny_phys | |||
| integer, | intent(in) | :: | nghost | |||
| logical, | intent(in), | optional | :: | negate |
|
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | private | :: | i | ||||
| integer, | private | :: | i_lo | ||||
| integer, | private | :: | isum | ||||
| integer, | private | :: | j | ||||
| integer, | private | :: | j_fold | ||||
| integer, | private | :: | jsum | ||||
| integer, | private | :: | k | ||||
| logical, | private | :: | negate_l | ||||
| integer, | private | :: | p | ||||
| integer, | private | :: | pm | ||||
| real(kind=wp), | private | :: | sgn |
pure subroutine fold_north_v_face_3d(v, nx_total, ny_face, nz, & nx_phys, ny_phys, nghost, negate) !! 3D y-face (Cv) fold: north-halo fill + on-line antisymmetric !! projection at the fold row. See the 2D twin for the `negate` !! (vector vs. scalar) contract. integer, intent(in) :: nx_total, ny_face, nz, nx_phys, ny_phys, nghost real(wp), intent(inout) :: v(nx_total, ny_face, nz) !! y-face 3D field, shape (nx_total, ny_total+1, nz). logical, intent(in), optional :: negate !! `.true.` (default) = true-vector component; `.false.` = scalar. integer :: i, j, k, isum, jsum, j_fold, i_lo, p, pm real(wp) :: sgn logical :: negate_l negate_l = .true. if (present(negate)) negate_l = negate sgn = merge(-1.0_wp, 1.0_wp, negate_l) isum = 2*nghost + nx_phys + 1 jsum = 2*nghost + 2*ny_phys + 2 ! v is SOUTH-face: y = j-1 j_fold = nghost + ny_phys + 1 ! the self-conjugate fold row i_lo = nghost + 1 ! first physical column ! (1) Halo rows strictly beyond the fold row. do concurrent(k=1:nz, j=j_fold + 1:ny_face, i=1:nx_total) v(i, j, k) = sgn*v(isum - i, jsum - j, k) end do ! (2) On-line projection at j = j_fold (see the 2D twin): every ! storage column whose physical index p is in the west half ! takes sgn*(its east mirror p' = ni+1-p); the self-conjugate ! column (odd ni only) is zeroed for a vector, left as is for a ! scalar; the east half is the read-only source, so the kernel ! is race-free. do concurrent(k=1:nz, i=1:nx_total) local(p, pm) p = modulo(i - i_lo, nx_phys) + 1 pm = nx_phys + 1 - p if (p < pm) then v(i, j_fold, k) = sgn*v(nghost + pm, j_fold, k) else if (p == pm .and. negate_l) then v(i, j_fold, k) = 0.0_wp end if end do end subroutine fold_north_v_face_3d