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