38def bfs(S, Re, dt, mode, Lr=12, U_in=1.0, nz=4, max_steps=6000, tol=2e-5, vcyc=4, vel_iter=60, outer=2):
39 H, L, nu = 2 * S, Lr * S, U_in * S / Re
40 s = sdflow.Solver(L, H, nz)
41 s.set_rho(1.0); s.set_mu(nu); s.set_dt(dt); s.set_advection(
True)
43 s.set_implicit_advection(
True); s.set_outer_iterations(outer)
45 s.set_domain_bc(1, 3); s.set_domain_bc(2, 1); s.set_domain_bc(3, 1)
46 s.set_velocity_solver_params(vel_iter)
47 if mode
in (
"vmg",
"vmg_fou"):
48 s.set_velocity_multigrid(
True, 8, vcyc)
49 s.set_pressure_multigrid(
True, levels=8); s.set_pressure_solver_params(80)
50 prev =
None; steps = max_steps; t0 = time.time()
51 for it
in range(max_steps):
54 if not np.isfinite(u).all()
or np.abs(u).max() > 1e3:
55 return dict(blew=
True, steps=it, wall=time.time() - t0, xr=np.nan)
57 uu = np.asarray(u).reshape((L, H, nz), order=
"F")
58 cur = uu[:, :, nz // 2].copy()
59 if prev
is not None and np.max(np.abs(cur - prev)) / (np.max(np.abs(cur)) + 1e-30) < tol:
62 uu = np.asarray(s.get_u()).reshape((L, H, nz), order=
"F")
64 return dict(blew=
False, steps=steps, wall=time.time() - t0, xr=xr)
68 S = int(os.environ.get(
"VMG_S", 128))
69 Re = float(os.environ.get(
"VMG_RE", 200.0))
70 ms = int(os.environ.get(
"VMG_MAXSTEPS", 6000))
71 print(f
"=== backward-facing step {12*S}x{2*S}x4 Re_S={Re:.0f} ===")
72 dts = float(os.environ.get(
"VMG_DT_SPEEDUP", 0.4))
73 print(f
"--- SPEEDUP: time to steady (explicit-advection dt={dts:g}) ---")
74 rb =
bfs(S, Re, dt=dts, mode=
"rbgs", vel_iter=60, max_steps=ms)
75 print(f
" RB-GS 60 sweeps : steps={rb['steps']:5d} wall={rb['wall']:7.1f}s x_r/S={rb['xr']:.2f}")
76 rb2 =
bfs(S, Re, dt=dts, mode=
"rbgs", vel_iter=200, max_steps=ms)
77 print(f
" RB-GS 200 sweeps : steps={rb2['steps']:5d} wall={rb2['wall']:7.1f}s x_r/S={rb2['xr']:.2f}")
78 vg =
bfs(S, Re, dt=dts, mode=
"vmg", vcyc=4, max_steps=ms)
79 print(f
" vel-MG 4 vcyc : steps={vg['steps']:5d} wall={vg['wall']:7.1f}s x_r/S={vg['xr']:.2f}"
80 f
" speedup x{rb2['wall'] / max(vg['wall'], 1e-9):.2f} (vs RB-GS 200)")
81 print(
"--- NO DT RESTRICTION: implicit-FOU + upwind vel-MG, growing dt (CFL=U*dt) ---")
82 for dt
in [2.0, 8.0, 32.0, 128.0]:
83 r =
bfs(S, Re, dt=dt, mode=
"vmg_fou", vcyc=6, max_steps=600)
84 tag =
"BLEW UP" if r[
"blew"]
else f
"finite, x_r/S={r['xr']:.2f} (steps {r['steps']})"
85 print(f
" dt={dt:7.1f} (CFL~{dt:.0f}): {tag}")
bfs(S, Re, dt, mode, Lr=12, U_in=1.0, nz=4, max_steps=6000, tol=2e-5, vcyc=4, vel_iter=60, outer=2)