30def run(implicit, dt, fx, n_steps, to_steady=False):
32 s = sdflow.Solver(N, N, N)
36 s.set_body_force(fx, 0.0, 0.0)
38 s.set_implicit_advection(implicit)
39 s.set_outer_iterations(3)
40 s.set_velocity_solver_params(80)
41 s.set_pressure_pcg(
True, max_iter=120, rtol=1e-9)
42 s.set_solid(sdf, cutcell_pressure=
True, pressure_coarse=
"galerkin")
44 for it
in range(n_steps):
47 if not np.isfinite(u).all():
50 if to_steady
and it > 8
and abs(um - prev) < 1e-6 * (abs(um) + 1e-15):
57 print(
"=== implicit-FOU advection: high-Re stability + moderate-Re correctness ===")
60 print(f
" (1) high Re: dt=5, fx=0.02 (velocity reaches U~2 -> CFL = U*dt/dx >> 1)")
61 ue =
run(implicit=
False, dt=5.0, fx=0.02, n_steps=30)
62 ui =
run(implicit=
True, dt=5.0, fx=0.02, n_steps=30)
63 expl_blew = ue
is None
64 impl_ok = ui
is not None and np.isfinite(ui).all()
and ui.max() < 1e3
65 print(f
" explicit advection : {'BLEW UP (NaN/Inf)' if expl_blew else f'finite, U_max={ue.max():.3f}'}")
66 print(f
" implicit-FOU : {'finite, U_max=%.3f' % ui.max() if impl_ok else 'unstable'}")
69 print(f
" (2) moderate Re: dt=5, fx=2e-4 (steady, both stable)")
70 ue2 =
run(implicit=
False, dt=5.0, fx=2e-4, n_steps=300, to_steady=
True)
71 ui2 =
run(implicit=
True, dt=5.0, fx=2e-4, n_steps=300, to_steady=
True)
72 rel = abs(ui2.max() - ue2.max()) / ue2.max()
73 print(f
" explicit U_max={ue2.max():.5f} implicit-FOU U_max={ui2.max():.5f} diff={rel*100:.2f}%")
75 ok = expl_blew
and impl_ok
and rel < 0.03
76 print(f
" result: {'PASS' if ok else 'FAIL'} (implicit-FOU stable at high Re where explicit fails; "
77 f
"agrees with explicit at moderate Re)")
78 sys.exit(0
if ok
else 1)