69 "odd": (7.3, 850.0, 0.037, 2.5),
83def build(name, spin, n=N, phi=PHI, beta=BETA, shift=(0.0, 0.0, 0.0)):
84 L, rho, mu, f = SYSTEMS[name]
87 s = pf.Solver((n, n, n))
89 s = pf.Solver((n, n, n), extent=(L, L, L))
91 dt = beta * h * h * rho / mu
95 s.set_body_force((0.0
if spin
else f, 0.0, 0.0))
96 s.set_advection(
False)
97 s.set_pressure_multigrid(
True, levels=3)
98 s.set_pressure_pcg(
True, 200, 1e-12)
99 s.diagnostics.set_velocity_solver_params(400, 1e-13)
100 R = (3.0 * phi / (4.0 * math.pi)) ** (1.0 / 3.0) * L
104 c0 = 0.5 * L - (0.5
if s.unit_scales[
"identity"]
else 0.0)
105 c = [c0 + shift[k] * h
for k
in range(3)]
106 ni = np.array([1, -1, -1], dtype=np.int32)
111 ii = np.array([0, -1], dtype=np.int32)
116 s.set_scene(ni, nr, ii, ir, periodic=
True)
117 omega = OMEGA_DT / dt
119 s.set_instance_motion(0, ang_vel=[0.0, 0.0, omega], center=c)
120 s.set_solid_from_scene(cutcell_pressure=
True)
121 return s, dict(L=L, rho=rho, mu=mu, f=f, R=R, h=h, dt=dt, omega=omega)
125 s, p = build(name, spin=
False)
127 for it
in range(600):
129 um = float(np.mean(s.get_u()))
130 if it > 10
and abs(um - prev) < 1e-9 * abs(um):
133 U = float(np.mean(s.get_u()))
134 rea = np.asarray(s.hydro_force_torque_reaction())
135 tra = np.asarray(s.diagnostics.hydro_force_torque_traction())
136 with warnings.catch_warnings(record=
True)
as caught:
137 warnings.simplefilter(
"always")
138 old = np.asarray(s.hydro_force_torque())
139 warned = [w
for w
in caught
if issubclass(w.category, DeprecationWarning)
140 and "hydro_force_torque_reaction()" in str(w.message)]
142 fV = p[
"f"] * (p[
"L"] ** 3 - math.pi / 6.0 * D ** 3)
143 r = dict(steps=it + 1,
144 K=p[
"f"] * p[
"L"] ** 3 / (3.0 * math.pi * p[
"mu"] * D * U),
145 rea_over_fV=rea[0, 0, 0] / fV,
146 tra_over_rea=tra[0, 0, 0] / rea[0, 0, 0],
147 tra_p_over_rea=tra[2, 0, 0] / rea[0, 0, 0],
148 tra_v_over_rea=tra[3, 0, 0] / rea[0, 0, 0],
149 old_vs_tra=float(np.max(np.abs(old - tra)) / np.max(np.abs(tra))),
150 old_shape=old.shape == tra.shape == (4, 1, 3),
151 old_warned=len(warned) == 1,
152 T_rea_rel=float(np.linalg.norm(rea[1, 0]) / (np.linalg.norm(rea[0, 0]) * p[
"R"])))
153 print(
" %-4s steps %3d K %.9f F_rea/(f V_fl) %.9f traction/reaction %.9f "
154 "(pressure %.6f + viscous %.6f)" % (name, r[
"steps"], r[
"K"], r[
"rea_over_fV"],
155 r[
"tra_over_rea"], r[
"tra_p_over_rea"],
156 r[
"tra_v_over_rea"]))
186 """Steady spinning sphere: T_z against the periodic-array value 8 pi mu a^3 Omega / (1 - phi)
187 (a rigid rotation sets the cell's mean vorticity, so the fluid counter-rotates at -phi Omega
188 to leading order; phi 0.008 and 0.027 at equal R/h agree to 3e-4 under this reference)."""
189 s, p = build(
"unit",
True, n=n, phi=phi, beta=BETA * (n / N) ** 2)
190 steps = steady(s,
lambda: float(np.asarray(s.hydro_force_torque_reaction())[1, 0, 2]))
191 T0 = 8.0 * math.pi * p[
"mu"] * p[
"R"] ** 3 * p[
"omega"] / (1.0 - phi)
192 rea = np.asarray(s.hydro_force_torque_reaction())
193 tra = np.asarray(s.diagnostics.hydro_force_torque_traction())
194 r = dict(T_rea=-rea[1, 0, 2] / T0, T_tra=-tra[1, 0, 2] / T0,
195 off_axis=float(np.linalg.norm(rea[1, 0, :2]) / abs(rea[1, 0, 2])))
196 print(
" unit N %d phi %.3f R/h %.2f steps %d: -T_z (1 - phi) / (8 pi mu a^3 Omega) reaction "
197 "%.6f traction %.6f" % (n, phi, p[
"R"] / p[
"h"], steps, r[
"T_rea"], r[
"T_tra"]))
202 """Steady translating sphere OFF the cell vertex: the true torque is zero, and no discrete
203 symmetry makes it so -- what is left is each getter's own torque error."""
204 s, p = build(
"unit",
False, n=n, phi=phi, shift=shift)
205 steps = steady(s,
lambda: float(np.mean(s.get_u())))
206 rea = np.asarray(s.hydro_force_torque_reaction())
207 tra = np.asarray(s.diagnostics.hydro_force_torque_traction())
208 r = dict(rea=float(np.linalg.norm(rea[1, 0]) / (np.linalg.norm(rea[0, 0]) * p[
"R"])),
209 tra=float(np.linalg.norm(tra[1, 0]) / (np.linalg.norm(tra[0, 0]) * p[
"R"])))
210 print(
" unit N %d phi %.3f R/h %.2f centre + %s h, steps %d: |T| / (|F| R) reaction %.2e "
211 "traction %.2e" % (n, phi, p[
"R"] / p[
"h"], shift, steps, r[
"rea"], r[
"tra"]))