flow
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
bench_velocity_mg_256.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2"""Velocity-MG benchmark on the DOMAIN-BC paths (lid cavity 256^3, backward-facing step high-res 2D).
3
4Unlike the IBM packed case (which has a dt ceiling from the row-scaled cut/solid coarse-coupling), the
5cavity/BFS have NO immersed solid, so the velocity-MG coarse operator is geometry-exact -> it should be
6both (a) FASTER than RB-GS at high resolution (MG kills the stiff-diffusion error in O(1) V-cycles vs RB-GS
7O(N) sweeps), and (b) free of any dt restriction (a standard Helmholtz MG is unconditionally stable).
8
9Reports, per case:
10 - SPEEDUP: wall-clock + step count to reach steady, RB-GS vs velocity-MG (diffusion-only) at the same dt,
11 and the velocity-MG run with a LARGE dt (pseudo-transient acceleration -> far fewer steps).
12 - NO-DT-RESTRICTION: implicit-FOU + upwind velocity-MG at a sweep of growing dt; must stay finite and keep
13 converging (CFL = U*dt up to O(1000)), where explicit advection and the IBM packed case would diverge.
14"""
15import os
16import sys
17import time
18
19import numpy as np
20
21sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..",
22 os.environ.get("SDFLOW_BUILD", "build_mpi"))))
23from peclet import flow as sdflow # noqa: E402
24
25
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)."""
29 nu = U * N / Re
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)
32 if mode == "vmg_fou":
33 s.set_implicit_advection(True); s.set_outer_iterations(outer)
34 for f in (0, 1, 2):
35 s.set_domain_bc(f, 1)
36 if nz > 1:
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) # +y lid
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))
44 t0 = time.time()
45 for it in range(nsteps):
46 s.step()
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()))
53
54
55def main():
56 N = int(os.environ.get("VMG_N", 256))
57 nz = int(os.environ.get("VMG_NZ", N)) # full 3D by default; set VMG_NZ=4 for quasi-2D
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)) # near the explicit-advection CFL limit -> stiff diffusion
61 print(f"=== lid cavity {N}x{N}x{nz} Re={Re:.0f} ({ns} steps, dt={dts:g}) ===")
62
63 # Reference steady centreline: vel-MG, many V-cycles -> the converged velocity solve each step.
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})")
73
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}")
79
80
81if __name__ == "__main__":
82 main()
cavity(N, nz, Re, dt, mode, U=1.0, nsteps=200, vcyc=4, vel_iter=60, outer=2, pit=40)