flow 1.3.0
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
verify_colocated_poiseuille.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2"""Phase-2 verification (collocated grid): plane Poiseuille flow through an SDF channel, driven by a body
3force, with Robust-Scaled cut-cell IBM no-slip walls and NO pressure projection (cutcell_pressure=False).
4
5Runs the SAME setup on both grids: sdflow.Solver (staggered) and sdflow.SolverColocated (cell-centered).
6The steady centreline velocity must match the analytic parabola U_max = F*H^2/(8*mu) and the error must
7shrink with resolution on the collocated grid too. The u-component's wall-normal (y) location is the cell
8centre on BOTH grids, so the two solvers should agree closely. This exercises the collocated {0,0,0} IBM
9offset + implicit diffusion path (advection is ~0 for unidirectional flow; it is stressed in phase 3).
10"""
11import sys
12
13import numpy as np
14
15from _bootstrap import ensure_flow # noqa: E402
16sdflow = ensure_flow()
17
18
19def channel_sdf(nx, ny, nz, ylo, yhi):
20 gy = np.arange(ny, dtype=np.float64)
21 sdf = np.empty((nx, ny, nz))
22 sdf[:, :, :] = np.minimum(gy - ylo, yhi - gy)[None, :, None]
23 return sdf
24
25
26def run(SolverCls, N, rho=1.0, mu=0.1, dt=50.0, F=0.01, max_steps=400):
27 nx, nz = 8, 8
28 ny = N
29 ylo = round(0.30 * ny) + 0.5
30 yhi = round(0.70 * ny) + 0.5
31 H = yhi - ylo
32
33 s = SolverCls(nx, ny, nz)
34 s.set_rho(rho)
35 s.set_mu(mu)
36 s.set_dt(dt)
37 s.set_body_force((F, 0.0, 0.0))
38 s.diagnostics.set_velocity_solver_params(200)
39 s.set_solid(channel_sdf(nx, ny, nz, ylo, yhi), cutcell_pressure=False)
40
41 prev = 0.0
42 for it in range(max_steps):
43 s.step()
44 u_now = float(s.get_u().max())
45 if it > 5 and abs(u_now - prev) < 1e-7 * (abs(u_now) + 1e-12):
46 break
47 prev = u_now
48
49 U_sim = float(s.get_u().max())
50 U_ana = F * H * H / (8.0 * mu)
51 err = 100.0 * abs(U_sim - U_ana) / U_ana
52 return ny, H, U_sim, U_ana, err
53
54
55def main():
56 print("=== sdflow phase-2: collocated vs staggered Poiseuille (cut-cell IBM, no pressure) ===")
57 print(f"{'Ny':>5} {'H':>6} {'U_stag':>11} {'U_coloc':>11} {'U_ana':>11} {'err_st%':>8} {'err_co%':>8} {'|st-co|':>9}")
58 errs_co = []
59 ok_all = True
60 for N in (16, 32, 64):
61 _, H, U_st, U_an, e_st = run(sdflow.Solver, N)
62 _, _, U_co, _, e_co = run(sdflow.SolverColocated, N)
63 d = abs(U_st - U_co)
64 print(f"{N:5d} {H:6.1f} {U_st:11.5f} {U_co:11.5f} {U_an:11.5f} {e_st:8.3f} {e_co:8.3f} {d:9.2e}")
65 errs_co.append(e_co)
66 ok_all = errs_co[-1] < 2.0 and errs_co[-1] <= errs_co[0] + 1e-9
67 print(f" result: {'PASS' if ok_all else 'FAIL'} (collocated error shrinks with resolution, <2% at N=64)")
68 sys.exit(0 if ok_all else 1)
69
70
71if __name__ == "__main__":
72 main()
run(SolverCls, N, rho=1.0, mu=0.1, dt=50.0, F=0.01, max_steps=400)