3rd-order WENO-Z reconstruction of a corner quantity onto the face
between q0 and qp1, upwind-biased on the sign of the advecting
velocity adv_vel (MOM6 weno_three_h_weight_reconstruction).
Blends a central candidate c0 (ideal weight 2/3) with an
upwind-side linear extrapolation c1 (1/3); the WENO-Z nonlinear
factor (1+tau/b)^2 collapses the weight of whichever candidate
straddles a PV front. In smooth flow -> the fixed upwind-biased
3rd-order stencil; across a jump -> the ENO (non-oscillatory)
branch. f-baked absolute vorticity is passed in (rdb’s
vector-invariant form multiplies the result by the thickness-
weighted face velocity, so there is no separate h-divide – the
mass-weighting lives in that velocity, not in a PV*vh product).
Branchless apart from the upwind sign pick and MOM6’s exact
divide-guard (|b| <= eps*tau -> degenerate factor), both scalar
per-lane predicates – GPU-safe in do concurrent.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | qm1 | |||
| real(kind=wp), | intent(in) | :: | q0 | |||
| real(kind=wp), | intent(in) | :: | qp1 | |||
| real(kind=wp), | intent(in) | :: | qp2 | |||
| real(kind=wp), | intent(in) | :: | adv_vel |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | private | :: | b0 | ||||
| real(kind=wp), | private | :: | b1 | ||||
| real(kind=wp), | private | :: | c0 | ||||
| real(kind=wp), | private | :: | c1 | ||||
| real(kind=wp), | private | :: | f0 | ||||
| real(kind=wp), | private | :: | f1 | ||||
| real(kind=wp), | private | :: | sinv | ||||
| real(kind=wp), | private | :: | tau | ||||
| real(kind=wp), | private | :: | w0 | ||||
| real(kind=wp), | private | :: | w1 |
pure function weno3_recon(qm1, q0, qp1, qp2, adv_vel) result(qf) !! 3rd-order WENO-Z reconstruction of a corner quantity onto the face !! between `q0` and `qp1`, upwind-biased on the sign of the advecting !! velocity `adv_vel` (MOM6 `weno_three_h_weight_reconstruction`). !! Blends a central candidate `c0` (ideal weight 2/3) with an !! upwind-side linear extrapolation `c1` (1/3); the WENO-Z nonlinear !! factor `(1+tau/b)^2` collapses the weight of whichever candidate !! straddles a PV front. In smooth flow -> the fixed upwind-biased !! 3rd-order stencil; across a jump -> the ENO (non-oscillatory) !! branch. `f`-baked absolute vorticity is passed in (rdb's !! vector-invariant form multiplies the result by the thickness- !! weighted face velocity, so there is no separate `h`-divide -- the !! mass-weighting lives in that velocity, not in a PV*vh product). !! !! Branchless apart from the upwind sign pick and MOM6's exact !! divide-guard (`|b| <= eps*tau` -> degenerate factor), both scalar !! per-lane predicates -- GPU-safe in `do concurrent`. !$acc routine seq real(wp), intent(in) :: qm1, q0, qp1, qp2 real(wp), intent(in) :: adv_vel real(wp) :: qf real(wp) :: c0, c1, b0, b1, tau, w0, w1, f0, f1, sinv if (adv_vel > 0.0_wp) then c0 = 0.5_wp*(q0 + qp1) c1 = 0.5_wp*(-qm1 + 3.0_wp*q0) b0 = (q0 - qp1)**2 b1 = (qm1 - q0)**2 else c0 = 0.5_wp*(qp1 + q0) c1 = 0.5_wp*(-qp2 + 3.0_wp*qp1) b0 = (qp1 - q0)**2 b1 = (qp2 - qp1)**2 end if tau = abs(b0 - b1) f0 = fac_weno(tau, b0) f1 = fac_weno(tau, b1) w0 = (2.0_wp/3.0_wp)*f0 w1 = (1.0_wp/3.0_wp)*f1 sinv = 1.0_wp/(w0 + w1) qf = (w0*c0 + w1*c1)*sinv end function weno3_recon