28def run(H=32, L=224, Re=100.0, U=1.0, nz=4, max_steps=8000, dt=0.5):
29 """Run the developing-channel case and return its convergence diagnostics.
31 Uniform inflow at -x, outflow at +x, no-slip walls at +-y, periodic z; marches to steady state and
32 returns a dict with the mass-conservation error, max divergence, outlet u_max/U_mean ratio, the
33 outlet-profile rms against the parabola, and the developed pressure gradient. Returns None off root.
36 s = sdflow.Solver(L, H, nz)
37 s.set_rho(1.0); s.set_mu(nu); s.set_dt(dt); s.set_advection(
True)
38 s.set_domain_bc(0, 2, U, 0.0, 0.0)
40 s.set_domain_bc(2, 1); s.set_domain_bc(3, 1)
41 s.set_velocity_solver_params(60)
42 s.set_pressure_multigrid(
True, levels=8)
43 s.set_pressure_solver_params(80)
44 s.set_pressure_geometry(np.full((L, H, nz), 1e30))
48 for it
in range(max_steps):
52 m = float(u[L - 4, H // 2, nz // 2])
if s.rank() == 0
else 0.0
53 done = it > 1000
and abs(m - prev) < 1e-5 * (abs(m) + 1e-30)
55 if s.bcast_from_root(done):
58 u = s.get_u(); p = s.get_p(); div = s.max_open_divergence()
62 flux_in = float(u[2, :, nz // 2].sum())
63 flux_out = float(u[L - 3, :, nz // 2].sum())
64 mass_err = abs(flux_out - flux_in) / (abs(flux_in) + 1e-30)
66 prof = u[L - 4, :, nz // 2]
67 U_mean = float(prof.mean())
68 eta = (np.arange(H) + 0.5) / H
69 parab = 6.0 * U_mean * eta * (1.0 - eta)
70 prof_rms = float(np.sqrt(np.mean((prof - parab) ** 2)) / (abs(U_mean) + 1e-30))
71 ratio = float(prof.max() / (U_mean + 1e-30))
73 pc = p[:, H // 2, nz // 2]
74 x0, x1 = L // 2, L - 6
75 dpdx = float((pc[x1] - pc[x0]) / (x1 - x0))
76 dpdx_analytic = -12.0 * nu * U_mean / H**2
77 return dict(steps=steps, mass_err=mass_err, div=div, U_mean=U_mean, ratio=ratio,
78 prof_rms=prof_rms, dpdx=dpdx, dpdx_analytic=dpdx_analytic, Re=Re, H=H, L=L)