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