26def cavity(N, nz, Re, dt, mode, U=1.0, nsteps=200, vcyc=4, vel_iter=60, outer=2, pit=40):
27 """Lid-driven cavity (N x N x nz), run a FIXED nsteps; return wall-clock + the converged-so-far centreline
28 umin. mode: 'rbgs' | 'vmg' (diffusion-only) | 'vmg_fou' (implicit-FOU + upwind)."""
30 s = sdflow.Solver(N, N, nz)
31 s.set_rho(1.0); s.set_mu(nu); s.set_dt(dt); s.set_advection(
True)
33 s.set_implicit_advection(
True); s.set_outer_iterations(outer)
37 s.set_domain_bc(4, 1); s.set_domain_bc(5, 1)
38 s.set_domain_bc(3, 2, U, 0.0, 0.0)
39 s.set_velocity_solver_params(vel_iter)
40 if mode
in (
"vmg",
"vmg_fou"):
41 s.set_velocity_multigrid(
True, 8, vcyc)
42 s.set_pressure_multigrid(
True, levels=8); s.set_pressure_solver_params(pit)
43 s.set_pressure_geometry(np.full((N, N, nz), 1e30))
45 for it
in range(nsteps):
47 if not np.isfinite(s.get_u()).all()
or np.abs(s.get_u()).max() > 1e3:
48 return dict(blew=
True, wall=time.time() - t0, sps=(time.time() - t0) / (it + 1), umin=np.nan)
49 wall = time.time() - t0
50 u = np.asarray(s.get_u()).reshape((N, N, nz), order=
"F")
51 uc = 0.5 * (u[N // 2 - 1, :, nz // 2] + u[N // 2, :, nz // 2])
52 return dict(blew=
False, wall=wall, sps=wall / nsteps, umin=float(uc.min()))
56 N = int(os.environ.get(
"VMG_N", 256))
57 nz = int(os.environ.get(
"VMG_NZ", N))
58 Re = float(os.environ.get(
"VMG_RE", 100.0))
59 ns = int(os.environ.get(
"VMG_NSTEPS", 200))
60 dts = float(os.environ.get(
"VMG_DT_SPEEDUP", 2.0))
61 print(f
"=== lid cavity {N}x{N}x{nz} Re={Re:.0f} ({ns} steps, dt={dts:g}) ===")
64 ref =
cavity(N, nz, Re, dt=dts, mode=
"vmg", vcyc=10, nsteps=ns)[
"umin"]
65 print(f
"--- SPEEDUP (cost/step + convergence vs reference umin={ref:.4f}) ---")
66 for label, kw
in [(
"RB-GS 60 sweeps", dict(mode=
"rbgs", vel_iter=60)),
67 (
"RB-GS 200 sweeps", dict(mode=
"rbgs", vel_iter=200)),
68 (
"RB-GS 400 sweeps", dict(mode=
"rbgs", vel_iter=400)),
69 (
"vel-MG 4 vcyc ", dict(mode=
"vmg", vcyc=4))]:
70 r =
cavity(N, nz, Re, dt=dts, nsteps=ns, **kw)
71 print(f
" {label}: {r['sps']*1000:6.0f} ms/step wall={r['wall']:6.1f}s umin={r['umin']:.4f} "
72 f
"(err {abs(r['umin']-ref):.4f})")
74 print(
"--- NO DT RESTRICTION: implicit-FOU + upwind vel-MG, growing dt (CFL=U*dt) ---")
75 for dt
in [30.0, 100.0, 300.0, 1000.0]:
76 r =
cavity(N, nz, Re, dt=dt, mode=
"vmg_fou", vcyc=6, nsteps=120)
77 tag =
"BLEW UP" if r[
"blew"]
else f
"finite, umin={r['umin']:.4f}, {r['sps']*1000:.0f} ms/step"
78 print(f
" dt={dt:7.0f} (CFL~{dt:.0f}): {tag}")
cavity(N, nz, Re, dt, mode, U=1.0, nsteps=200, vcyc=4, vel_iter=60, outer=2, pit=40)