@@ -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
0 commit comments