26 cs = [(c + 0.5) * N / 2.0
for c
in (0, 1)]
27 X, Y, Z = np.meshgrid(gx, gx, gx, indexing=
"ij")
28 best = np.full((N, N, N), 1e30)
32 dx = X - sx; dx -= N * np.round(dx / N)
33 dy = Y - sy; dy -= N * np.round(dy / N)
34 dz = Z - sz; dz -= N * np.round(dz / N)
35 best = np.minimum(best, np.sqrt(dx * dx + dy * dy + dz * dz) - R)
36 return np.asfortranarray(best), R
39def run(SolverCls, N, mu=0.1, dt=60.0, F=1e-3, steps=400):
41 s = SolverCls(N, N, N)
45 s.set_body_force(F, 0.0, 0.0)
46 s.set_advection(
False)
47 s.set_velocity_solver_params(80)
48 s.set_pressure_pcg(
True, 500, 1e-10)
49 s.set_solid(sdf, cutcell_pressure=
True)
52 for it
in range(steps):
54 um = float(s.get_u().mean())
55 if it > 8
and abs(um - prev) < 3e-4 * (abs(um) + 1e-15):
60 k = mu * float(u.mean()) / F
61 u_solid = float(np.abs(u[sdf < -2.0]).max())
62 return k, u_solid, float(s.max_open_divergence()), float(u.max())
67 print(
"=== sdflow phase-4: collocated cut-cell IBM โ Stokes permeability through a sphere packing ===")
68 print(f
"{'N':>4} {'k_stag':>12} {'k_coloc':>12} {'rel.diff':>9} {'maxdiv_co':>11} {'u_solid_co':>11}")
71 ks, _, _, _ =
run(sdflow.Solver, N)
72 kc, usc, dc, umc =
run(sdflow.SolverColocated, N)
73 rel = 100.0 * abs(kc - ks) / ks
74 print(f
"{N:4d} {ks:12.5e} {kc:12.5e} {rel:8.2f}% {dc:11.2e} {usc:11.2e}")
75 rows.append((ks, kc, rel, dc, usc))
77 incompressible = all(r[3] < 1e-7
for r
in rows)
78 no_slip = all(r[4] == 0.0
for r
in rows)
79 k_converges = rows[0][1] < rows[1][1] < rows[2][1]
80 rel_shrinks = rows[2][2] < rows[0][2]
81 ok = incompressible
and no_slip
and k_converges
and rel_shrinks
82 print(f
" incompressible (face div <1e-7): {incompressible}")
83 print(f
" exact no-slip in deep solid: {no_slip}")
84 print(f
" collocated k grid-converges: {k_converges} ({rows[0][1]:.4e} -> {rows[2][1]:.4e})")
85 print(f
" collocated -> staggered with N: {rel_shrinks} ({rows[0][2]:.2f}% -> {rows[2][2]:.2f}%)")
86 print(f
" result: {'PASS' if ok else 'FAIL'} (Option A area-weighting + central-diff cell correction)")
87 sys.exit(0
if ok
else 1)