|
7 | 7 | L2(rho(T) - rho(0)) measures the accumulated scheme spatial truncation error. |
8 | 8 | No non-conservative alpha equation — clean benchmark for all schemes. |
9 | 9 |
|
10 | | -CFL=0.02 by default so that RK3 temporal error O(dt^3) is negligible relative |
11 | | -to the spatial error at all tested resolutions, allowing WENO5/7 to show their |
12 | | -true spatial rates. |
| 10 | +WENO5/TENO5 use CFL=0.02: RK3 temporal error O(dt^3) is then negligible |
| 11 | +relative to the O(h^5) spatial error at N=128-512. |
| 12 | +
|
| 13 | +WENO7/TENO7 use CFL=0.005: at CFL=0.02 the RK3 temporal error (~3.4e-12 at |
| 14 | +N=128) is comparable to the spatial error (~4.4e-12), giving a spurious rate |
| 15 | +of ~3.7. With CFL=0.005 the temporal error drops by (0.005/0.02)^3 = 1/64 |
| 16 | +to ~5.3e-14, well below spatial, and the measured rate approaches 7. |
| 17 | +N is capped at 256 — the machine-precision floor is reached near N=512. |
13 | 18 |
|
14 | 19 | WENO3-JS degrades to 2nd order at smooth extrema (Henrick et al. 2005). |
15 | 20 | The expected rate for WENO3 here is therefore 2, not 3; the 2D isentropic |
|
19 | 24 | limiters clip slopes to zero at smooth extrema and stall at 1st order on the |
20 | 25 | sine wave; the unlimited limiter preserves 2nd-order convergence everywhere. |
21 | 26 |
|
22 | | -TENO5 uses the same 5th-order stencil as WENO5 with threshold-based stencil |
23 | | -selection (CT=1e-6). On smooth problems all stencils are selected and the |
24 | | -rate equals WENO5; TENO's advantage is sharper shock capturing. |
25 | | -
|
26 | | -WENO7/TENO7: capped at N=256 — the machine-precision floor (~2e-15) is |
27 | | -reached near N=512 for 7th-order schemes on this smooth problem. |
28 | | -
|
29 | 27 | Usage: |
30 | | - python toolchain/mfc/test/run_convergence_1d.py [--no-build] [--resolutions 32 64 128] |
| 28 | + python toolchain/mfc/test/run_convergence_1d.py [--resolutions 128 256 512 1024] |
31 | 29 | """ |
32 | 30 |
|
33 | 31 | import argparse |
|
46 | 44 | MFC = "./mfc.sh" |
47 | 45 |
|
48 | 46 | # (label, extra_args, expected_order, tolerance, min_N, max_N) |
| 47 | +# CFL is baked into each scheme's extra_args so that WENO7/TENO7 can use a |
| 48 | +# smaller CFL independently of all other schemes. |
| 49 | +# |
49 | 50 | # Per-scheme resolution bounds let each scheme run over the range where its |
50 | 51 | # asymptotic order is cleanly visible: |
51 | 52 | # WENO5 : cap at N=512 — double-precision floor kills the rate at N=1024 |
|
56 | 57 | # WENO1 : full range [128,1024]; rate 0.97. |
57 | 58 | # MUSCL2 : full range [128,1024]; unlimited slope, rate exactly 2.00. |
58 | 59 | # TENO5 : same range as WENO5; CT=1e-6; rate matches WENO5 on smooth problems. |
59 | | -# WENO7 : cap at N=256; measured rate ~3.7 — spatial h^7 and RK3 temporal |
60 | | -# h^3 errors are comparable at these N; threshold set >=3.0 to |
61 | | -# confirm convergence without requiring a higher-order time integrator. |
62 | | -# TENO7 : same range and reasoning as WENO7; CT=1e-9. |
| 60 | +# WENO7 : CFL=0.005, cap at N=256 — machine-precision floor near N=512; |
| 61 | +# rate ≥6.5 (fits ≥6.0 threshold with tolerance 0.5 after temporal fix). |
| 62 | +# TENO7 : same range and CFL as WENO7; CT=1e-9. |
63 | 63 | SCHEMES = [ |
64 | | - ("WENO5", ["--order", "5"], 5, 0.2, 128, 512), |
65 | | - ("WENO3", ["--order", "3"], 2, 0.2, 256, None), |
66 | | - ("WENO1", ["--order", "1"], 1, 0.05, 128, None), |
67 | | - ("MUSCL2", ["--muscl"], 2, 0.1, 128, None), |
68 | | - ("TENO5", ["--order", "5", "--teno", "--teno-ct", "1e-6"], 5, 0.2, 128, 512), |
69 | | - ("WENO7", ["--order", "7"], 7, 4.0, 128, 256), |
70 | | - ("TENO7", ["--order", "7", "--teno", "--teno-ct", "1e-9"], 7, 4.0, 128, 256), |
| 64 | + ("WENO5", ["--order", "5", "--cfl", "0.02"], 5, 0.2, 128, 512), |
| 65 | + ("WENO3", ["--order", "3", "--cfl", "0.02"], 2, 0.2, 256, None), |
| 66 | + ("WENO1", ["--order", "1", "--cfl", "0.02"], 1, 0.05, 128, None), |
| 67 | + ("MUSCL2", ["--muscl", "--cfl", "0.02"], 2, 0.1, 128, None), |
| 68 | + ("TENO5", ["--order", "5", "--teno", "--teno-ct", "1e-6", "--cfl", "0.02"], 5, 0.2, 128, 512), |
| 69 | + ("WENO7", ["--order", "7", "--cfl", "0.005"], 7, 0.5, 128, 256), |
| 70 | + ("TENO7", ["--order", "7", "--teno", "--teno-ct", "1e-9", "--cfl", "0.005"], 7, 0.5, 128, 256), |
71 | 71 | ] |
72 | 72 |
|
73 | 73 |
|
@@ -196,18 +196,17 @@ def main(): |
196 | 196 | default=["WENO5", "WENO3", "WENO1", "MUSCL2", "TENO5", "WENO7", "TENO7"], |
197 | 197 | help="Schemes to test", |
198 | 198 | ) |
199 | | - parser.add_argument("--cfl", type=float, default=0.02, help="CFL number (default: 0.02; small so RK3 temporal error is negligible)") |
200 | 199 | parser.add_argument("--muscl-lim", type=int, default=0, help="MUSCL limiter (0=unlimited 1=minmod ...; default: 0)") |
201 | 200 | args = parser.parse_args() |
202 | 201 |
|
203 | | - cfl_extra = ["--cfl", str(args.cfl), "--muscl-lim", str(args.muscl_lim)] |
| 202 | + muscl_extra = ["--muscl-lim", str(args.muscl_lim)] |
204 | 203 |
|
205 | 204 | results = {} |
206 | 205 | for label, extra_args, expected_order, tol, min_N, max_N in SCHEMES: |
207 | 206 | if label not in args.schemes: |
208 | 207 | continue |
209 | 208 | try: |
210 | | - passed = test_scheme(label, extra_args + cfl_extra, expected_order, tol, args.resolutions, min_N, max_N) |
| 209 | + passed = test_scheme(label, extra_args + muscl_extra, expected_order, tol, args.resolutions, min_N, max_N) |
211 | 210 | except Exception as e: |
212 | 211 | print(f" ERROR: {e}") |
213 | 212 | passed = False |
|
0 commit comments