2D y-face (Cv) fold: north-halo fill + on-line antisymmetric
projection at the fold row. Used for the barotropic bt_vbt
field in the BT fast loop. negate (default .true., see the
u-face twin) selects true-vector (sign flip + self-conjugate
zero) vs. scalar (copy + self-conjugate left unchanged, matching
fold_north_corner_2d’s scalar contract) — a scalar on a v-face
(e.g. visc_rem_v) is the SAME physical attribute of the SAME
face seen from both sides of the seam, so the duplicated DOF at
the fold line must agree, not cancel.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(inout) | :: | v(nx_total,ny_face) |
y-face 2D field, shape (nx_total, ny_total+1). |
||
| integer, | intent(in) | :: | nx_total | |||
| integer, | intent(in) | :: | ny_face | |||
| 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 | ||||
| logical, | private | :: | negate_l | ||||
| integer, | private | :: | p | ||||
| integer, | private | :: | pm | ||||
| real(kind=wp), | private | :: | sgn |
pure subroutine fold_north_v_face_2d(v, nx_total, ny_face, & nx_phys, ny_phys, nghost, negate) !! 2D y-face (Cv) fold: north-halo fill + on-line antisymmetric !! projection at the fold row. Used for the barotropic `bt_vbt` !! field in the BT fast loop. `negate` (default `.true.`, see the !! u-face twin) selects true-vector (sign flip + self-conjugate !! zero) vs. scalar (copy + self-conjugate left unchanged, matching !! `fold_north_corner_2d`'s scalar contract) — a scalar on a v-face !! (e.g. `visc_rem_v`) is the SAME physical attribute of the SAME !! face seen from both sides of the seam, so the duplicated DOF at !! the fold line must agree, not cancel. integer, intent(in) :: nx_total, ny_face, nx_phys, ny_phys, nghost real(wp), intent(inout) :: v(nx_total, ny_face) !! y-face 2D field, shape (nx_total, ny_total+1). logical, intent(in), optional :: negate !! `.true.` (default) = true-vector component; `.false.` = scalar. integer :: i, j, 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 ! north face of the last T-row i_lo = nghost + 1 ! (1) Halo rows strictly beyond the fold row. do concurrent(j=j_fold + 1:ny_face, i=1:nx_total) v(i, j) = sgn*v(isum - i, jsum - j) end do ! (2) On-line projection at j = j_fold, over EVERY storage column ! (periodic ghosts included, so the row stays periodic-consistent ! without a second wrap): a column whose physical index p lies in ! the west half takes sgn*(the east mirror p' = ni+1-p); the east ! half is the (read-only) source. Self-conjugate column: zeroed ! for a vector (v = -v ⇒ 0), left as is for a scalar. do concurrent(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) = sgn*v(nghost + pm, j_fold) else if (p == pm .and. negate_l) then v(i, j_fold) = 0.0_wp end if end do end subroutine fold_north_v_face_2d