22 """2x2x2 sphere packing as a 3-D array sdf[x,y,z]; negative inside the spheres (min-image)."""
25 cs = [(cx + 0.5) * N / 2.0
for cx
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)
38def run(N, rho=1.0, mu=0.1, dt=60.0, F=1e-3, max_steps=200):
40 porosity = 1.0 - 8.0 * (4.0 / 3.0 * np.pi * R**3) / N**3
42 s = sdflow.Solver(N, N, N)
46 s.set_body_force((F, 0.0, 0.0))
47 s.set_advection(
False)
50 s.diagnostics.set_velocity_solver_params(80)
51 s.set_pressure_solver_params(20)
52 s.set_pressure_multigrid(
True, levels=1)
53 s.set_solid(sdf, cutcell_pressure=
True)
55 deep_solid = sdf < -2.0
57 for it
in range(max_steps):
62 umean = float(u.mean())
63 converged = it > 8
and abs(umean - prev) < 3e-4 * (abs(umean) + 1e-15)
65 if s.diagnostics.bcast_from_root(converged):
69 div = s.max_open_divergence()
72 k = mu * float(u.mean()) / F
73 u_solid = float(np.abs(u[deep_solid]).max())
74 return N, porosity, k, u_solid, float(u.max()), div
79 results = [
run(N)
for N
in (32, 64)]
80 if results[0]
is None:
82 print(
"=== sdflow: Stokes flow through a periodic sphere packing (rho/mu units) ===")
83 print(f
"{'N':>4} {'porosity':>9} {'permeability k':>15} {'max|u|solid':>12} {'max fluxdiv':>12}")
85 for N_, phi, k, us, umax, div
in results:
86 print(f
"{N_:4d} {phi:9.3f} {k:15.6e} {us:12.3e} {div:12.3e}")
87 ks.append((k, us, umax, div))
88 k32, k64 = ks[0][0], ks[1][0]
89 incompressible = all(d < 1e-6 * umax
for (_, _, umax, d)
in ks)
90 no_slip = all(us == 0.0
for (_, us, _, _)
in ks)
91 sensible = 0.0 < k32 < k64
and np.isfinite(k64)
92 ok = incompressible
and no_slip
and sensible
93 print(f
" permeability k(N=32)={k32:.3e} k(N=64)={k64:.3e} (rises as the spheres resolve)")
94 print(f
" incompressible={incompressible} no-slip(exact in solid)={no_slip} sensible-k={sensible}")
95 print(f
" result: {'PASS' if ok else 'FAIL'} (incompressible Stokes flow, exact no-slip on SDF spheres)")
96 sys.exit(0
if ok
else 1)