Skip to content

Commit 42f003e

Browse files
authored
feat: WENO5 sum-of-squares beta on uniform grids (cancellation-free smoothness indicators) (#1408)
1 parent 13a0dec commit 42f003e

19 files changed

Lines changed: 883 additions & 1011 deletions

src/simulation/m_weno.fpp

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ module m_weno
7373
integer :: v_size !< Number of WENO-reconstructed cell-average variables
7474
$:GPU_DECLARE(create='[v_size]')
7575

76+
logical :: uniform_grid(3) !< True if grid spacing is uniform in each direction
77+
$:GPU_DECLARE(create='[uniform_grid]')
78+
7679
!> @name Indical bounds in the s1-, s2- and s3-directions
7780
!> @{
7881
type(int_bounds_info) :: is1_weno, is2_weno, is3_weno
@@ -183,6 +186,7 @@ contains
183186
integer :: i !< Generic loop iterator
184187
real(wp) :: w(1:8) !< Intermediate var for ideal weights: s_cb across overall stencil
185188
real(wp) :: y(1:4) !< Intermediate var for poly & beta: diff(s_cb) across sub-stencil
189+
real(wp) :: h0 !< Reference spacing for uniform-grid detection
186190

187191
! Determine cell count, boundary locations, and BCs for selected WENO direction
188192

@@ -843,12 +847,24 @@ contains
843847
end if
844848
#:endfor
845849

850+
! Detect whether grid spacing is uniform (enables cancellation-free sum-of-squares beta). Tolerance uses sqrt(epsilon) so it
851+
! works in both double and single precision: ~1.5e-8 relative in double, ~3.5e-4 in single - above FP noise, below real
852+
! stretching.
853+
uniform_grid(weno_dir) = .true.
854+
h0 = (s_cb(s) - s_cb(0))/real(s, wp)
855+
do i = 0, s - 1
856+
if (abs((s_cb(i + 1) - s_cb(i)) - h0) > sqrt(epsilon(h0))*abs(h0)) then
857+
uniform_grid(weno_dir) = .false.
858+
exit
859+
end if
860+
end do
861+
846862
if (weno_dir == 1) then
847-
$:GPU_UPDATE(device='[poly_coef_cbL_x, poly_coef_cbR_x, d_cbL_x, d_cbR_x, beta_coef_x]')
863+
$:GPU_UPDATE(device='[poly_coef_cbL_x, poly_coef_cbR_x, d_cbL_x, d_cbR_x, beta_coef_x, uniform_grid]')
848864
else if (weno_dir == 2) then
849-
$:GPU_UPDATE(device='[poly_coef_cbL_y, poly_coef_cbR_y, d_cbL_y, d_cbR_y, beta_coef_y]')
865+
$:GPU_UPDATE(device='[poly_coef_cbL_y, poly_coef_cbR_y, d_cbL_y, d_cbR_y, beta_coef_y, uniform_grid]')
850866
else
851-
$:GPU_UPDATE(device='[poly_coef_cbL_z, poly_coef_cbR_z, d_cbL_z, d_cbR_z, beta_coef_z]')
867+
$:GPU_UPDATE(device='[poly_coef_cbL_z, poly_coef_cbR_z, d_cbL_z, d_cbR_z, beta_coef_z, uniform_grid]')
852868
end if
853869

854870
! Nullifying WENO coefficients and cell-boundary locations pointers
@@ -1053,12 +1069,22 @@ contains
10531069
poly(2) = v_rs_ws_${XYZ}$ (j, k, l, i) + poly_coef_cbL_${XYZ}$ (j, 2, &
10541070
& 0)*dvd(-1) + poly_coef_cbL_${XYZ}$ (j, 2, 1)*dvd(-2)
10551071

1056-
beta(0) = beta_coef_${XYZ}$ (j, 0, 0)*dvd(1)*dvd(1) + beta_coef_${XYZ}$ (j, 0, &
1057-
& 1)*dvd(1)*dvd(0) + beta_coef_${XYZ}$ (j, 0, 2)*dvd(0)*dvd(0) + weno_eps
1058-
beta(1) = beta_coef_${XYZ}$ (j, 1, 0)*dvd(0)*dvd(0) + beta_coef_${XYZ}$ (j, 1, &
1059-
& 1)*dvd(0)*dvd(-1) + beta_coef_${XYZ}$ (j, 1, 2)*dvd(-1)*dvd(-1) + weno_eps
1060-
beta(2) = beta_coef_${XYZ}$ (j, 2, 0)*dvd(-1)*dvd(-1) + beta_coef_${XYZ}$ (j, 2, &
1061-
& 1)*dvd(-1)*dvd(-2) + beta_coef_${XYZ}$ (j, 2, 2)*dvd(-2)*dvd(-2) + weno_eps
1072+
! Jiang & Shu (1996) sum-of-squares form on uniform grids: all terms non-negative, no
1073+
! cancellation. On non-uniform grids, fall back to precomputed coefficients.
1074+
if (uniform_grid(${WENO_DIR}$)) then
1075+
beta(0) = 13._wp/12._wp*(dvd(1) - dvd(0))**2 + 0.25_wp*(dvd(1) - 3._wp*dvd(0))**2 &
1076+
& + weno_eps
1077+
beta(1) = 13._wp/12._wp*(dvd(0) - dvd(-1))**2 + 0.25_wp*(dvd(0) + dvd(-1))**2 + weno_eps
1078+
beta(2) = 13._wp/12._wp*(dvd(-1) - dvd(-2))**2 + 0.25_wp*(3._wp*dvd(-1) - dvd(-2))**2 &
1079+
& + weno_eps
1080+
else
1081+
beta(0) = beta_coef_${XYZ}$ (j, 0, 0)*dvd(1)*dvd(1) + beta_coef_${XYZ}$ (j, 0, &
1082+
& 1)*dvd(1)*dvd(0) + beta_coef_${XYZ}$ (j, 0, 2)*dvd(0)*dvd(0) + weno_eps
1083+
beta(1) = beta_coef_${XYZ}$ (j, 1, 0)*dvd(0)*dvd(0) + beta_coef_${XYZ}$ (j, 1, &
1084+
& 1)*dvd(0)*dvd(-1) + beta_coef_${XYZ}$ (j, 1, 2)*dvd(-1)*dvd(-1) + weno_eps
1085+
beta(2) = beta_coef_${XYZ}$ (j, 2, 0)*dvd(-1)*dvd(-1) + beta_coef_${XYZ}$ (j, 2, &
1086+
& 1)*dvd(-1)*dvd(-2) + beta_coef_${XYZ}$ (j, 2, 2)*dvd(-2)*dvd(-2) + weno_eps
1087+
end if
10621088

10631089
if (wenojs) then
10641090
do q = 0, weno_num_stencils

tests/059D137F/golden-metadata.txt

Lines changed: 85 additions & 98 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)