47KN_R, KI_I, KI_R = 16, 2, 17
54 node_ints = np.array([1, -1, -1], dtype=np.int32)
55 node_reals = np.zeros(KN_R); node_reals[0] = R
56 node_reals[14] = 1.0; node_reals[15] = 1.0
57 ii = np.zeros((1, KI_I), dtype=np.int32); ii[0] = (0, -1)
58 ir = np.zeros((1, KI_R)); ir[0, 0:3] = CEN; ir[0, 6] = 1.0; ir[0, 7] = 1.0
59 s = sdflow.Solver(N, N, N)
60 s.set_rho(RHO_F); s.set_mu(MU); s.set_dt(DT
if dt
is None else dt)
61 s.set_advection(
False)
62 s.set_velocity_solver_params(80)
63 s.set_pressure_solver_params(20)
67 s.set_pressure_multigrid(
True, levels=4)
68 s.set_body_force(body_force, 0.0, 0.0)
69 s.set_scene(node_ints, node_reals, ii.ravel(), ir.ravel(), periodic=
True)
75 s.set_solid_from_scene(
True)
76 for _
in range(steps
or NCAL):
78 u = np.asarray(s.get_u())
83 Fd = np.asarray(s.hydro_force_torque_reaction())[0][0]
84 Ftr = np.asarray(s.diagnostics.hydro_force_torque_traction())[0][0]
85 Nc = s.fluid_momentum_cells()
86 umean = float(u.mean())
87 lam = Fd[0] / (6.0 * np.pi * MU * R * umean)
88 print(
"(a) calibration: %d steps at dt=%.1f f=%.1e <u>=%.6e F_drag=(%+.4e,%+.1e,%+.1e)"
89 % (steps
or NCAL, DT_CAL, f, umean, *Fd))
90 print(
" REACTION identity F / (f*N_fluid) - 1 = %+.3e (must be ~unsteady tail + solver "
91 "residual; percent-level means a budget term is missing)" % (Fd[0] / (f * Nc[0]) - 1))
92 print(
" [traction diagnostic on the same run: F / (f*V_fluid) = %.5f -- the ~29%% under-read "
93 "kept visible]" % (Ftr[0] / (f * V_FLUID)))
94 print(
" lambda = F_drag / (6 pi mu R <u>) = %.4f (1 would be an isolated sphere)" % lam)
101 Fg = 6.0 * np.pi * MU * R * lam * 0.02
102 fcomp = -Fg / V_FLUID
105 d = pdem.Simulation(1)
106 d.initialize(shape_type=1, radius=R)
107 d.set_domain((0.0, 0.0, 0.0), (float(N), float(N), float(N)))
108 d.enable_periodicity(
True,
True,
True)
109 d.set_gravity(0.0, 0.0, 0.0)
110 pos = np.zeros((1, 4), dtype=np.float32)
114 d.set_velocities(np.zeros((1, 4), dtype=np.float32))
122 d.set_inv_mass(np.array([1.0 / m], dtype=np.float32))
123 if os.environ.get(
"SEED_FRESH",
"0") ==
"1":
124 s.set_fresh_cell_seed(
True)
125 drv = ResolvedCfdDem(s, d, radius=R, mu=MU, rho_f=RHO_F, fluid_dt=DT, dem_substeps=10,
126 periodic=
True, gravity=(Fg / m, 0.0, 0.0), rho_p=rho_p, buoyancy=
False,
128 pred = Fg / (6.0 * np.pi * MU * R * lam)
131 for k
in range(NSTEP):
133 up = float(np.asarray(d.get_velocities())[0, 0])
134 uf = float(np.asarray(s.get_u()).
mean())
135 hist.append(abs(uf - up))
141 mom.append(m * up + RHO_F * uf * N**3)
142 if k % max(1, NSTEP // 10) == max(1, NSTEP // 10) - 1:
143 print(
" step %3d |U_slip|=%.6e (pred %.6e, ratio %.4f) U_p=%+.4e <u>=%+.4e "
144 "p_tot=%+.4e" % (k + 1, hist[-1], pred, hist[-1] / pred, up, uf, mom[-1]))
146 tail = max(1, NSTEP // 20)
147 drift = abs(hist[-1] - hist[-1 - tail]) / abs(pred)
148 print(
"(b) settling: F_g=%.4e m=%.4e (rho_p=%.3f)" % (Fg, m, rho_p))
149 print(
" terminal |<u> - U_p| = %.6e" % slip)
150 print(
" predicted from the MEASURED lambda = %.6e" % pred)
151 print(
" ratio %.4f (slip drift over the last %d steps: %.2e of the prediction)"
152 % (slip / pred, tail, drift))
157 print(
" momentum: p_tot %+.4e -> %+.4e over %d steps (%.2e F_g per unit time; the "
158 "traction-force version leaked 0.58 F_g per unit time)"
159 % (mom[0], mom[-1], NSTEP,
160 abs(mom[-1] - mom[0]) / (NSTEP * DT * max(abs(Fg), 1e-300))))
161 ok = abs(slip / pred - 1.0) < 0.05
162 print(
"GATE %s [claim: terminal velocity matches the same box's measured drag within 5%%]"
163 % (
"PASS" if ok
else "FAIL"))