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