flow 1.3.0
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
colocated_varrho_motion.py
Go to the documentation of this file.
1#!/usr/bin/env python
2"""WO-V3 (doc/collocated_varrho_forces.md ยง8, Q4/Q5) -- an INSTRUMENT that decides the motion
3rating of the collocated variable-density path; report only, not a gate.
4
51. Translating drop, ratio 1000: a heavy drop (R = 6) in a periodic 32^3 box, seeded with the
6 uniform velocity U = 0.05 along x, no gravity, sigma = 0.01, mu = 0.01. The exact solution
7 translates rigidly with U forever. After the drop has crossed one box length: max|u - U|
8 (spurious currents), the colour volume drift, and the L1 shape error against the initial colour
9 (the box is periodic, so after one length the exact colour IS the initial one). Staggered
10 (enable_vof_momentum, the ratio-1000 reference), collocated V8 with the balanced-force
11 projection ON (the default) and OFF.
122. Rayleigh-Taylor, ratio 3 (Atwood 0.5): tests/study/rayleigh_taylor.py's sharp-VoF case on both
13 grids, the interface amplitude at t = 40, 80, ..., 240.
14
15Run: OMP_NUM_THREADS=8 OMP_PROC_BIND=false PYTHONPATH=<build> python tests/study/colocated_varrho_motion.py
16"""
17import numpy as np
18
19import peclet.flow as F
20
21N, R, RATIO, SIGMA, MU, U0 = 32, 6.0, 1000.0, 0.01, 0.01, 0.05
22
23
24def sphere_c(sub=4):
25 off = (np.arange(sub) + 0.5) / sub
26 c = np.array([N / 2 + 0.13, N / 2 + 0.27, N / 2 + 0.11])
27 out = np.zeros((N, N, N))
28 for a in off:
29 for b in off:
30 for d in off:
31 X, Y, Z = np.meshgrid(np.arange(N) + a, np.arange(N) + b, np.arange(N) + d,
32 indexing="ij")
33 out += ((X - c[0]) ** 2 + (Y - c[1]) ** 2 + (Z - c[2]) ** 2 < R * R)
34 return np.asfortranarray(out / sub ** 3)
35
36
37def translating(cls, bfp=None):
38 s = cls(N, N, N)
39 s.set_rho(RATIO)
40 s.set_mu(MU)
41 s.set_dt(1.0)
42 s.set_advection(True)
43 s.set_pressure_geometry(np.asfortranarray(np.full((N, N, N), 10.0)))
44 s.enable_vof()
45 c0 = sphere_c()
46 s.set_vof(c0)
47 s.set_property_model("rho", "linear", "C", [1.0, RATIO - 1.0])
48 s.set_surface_tension(SIGMA)
49 if cls is F.Solver:
50 s.enable_vof_momentum(1.0, RATIO)
51 if bfp is not None:
52 s.set_balanced_force_projection(bfp)
53 dt = min(0.5 * s.capillary_dt(), 0.2 / U0)
54 s.set_dt(dt)
55 s.set_field("u", np.asfortranarray(np.full((N, N, N), U0)))
56 steps = int(round(N / (U0 * dt)))
57 v0 = float(np.sum(c0))
58 worst = 0.0
59 for _ in range(steps):
60 s.step()
61 du = max(np.max(np.abs(np.asarray(s.get_u()) - U0)), np.max(np.abs(s.get_v())),
62 np.max(np.abs(s.get_w())))
63 if not np.isfinite(du):
64 return steps, np.inf, np.inf, np.inf, np.inf
65 worst = max(worst, du)
66 c = np.asarray(s.get_vof())
67 return (steps, du / U0, worst / U0, (np.sum(c) - v0) / v0, np.sum(np.abs(c - c0)) / v0)
68
69
70def rayleigh_taylor_vof(cls, N=48, NZ=96, g=0.005, mu=0.002, steps=240, cfl=0.2, dt0=1.0):
71 s = cls(N, 4, NZ)
72 s.set_rho(1.0)
73 s.set_mu(mu)
74 s.set_dt(dt0)
75 s.set_advection(True)
76 s.set_domain_bc("-z", "wall", (0, 0, 0))
77 s.set_domain_bc("+z", "wall", (0, 0, 0))
78 s.set_pressure_geometry(np.asfortranarray(np.full((N, 4, NZ), 10.0)))
79 s.enable_vof()
80 x, z = np.arange(N), np.arange(NZ)
81 zi = NZ / 2 + 1.5 * np.cos(2 * np.pi * x / N)
82 c0 = np.clip((z[None, :] + 1.0) - zi[:, None], 0.0, 1.0)
83 s.set_vof(np.asfortranarray(np.repeat(c0[:, None, :], 4, axis=1)))
84 s.set_property_model("rho", "linear", "C", [1.0, 2.0])
85 s.set_property_model("force_z", "linear", "rho", [0.0, -g])
86
87 def amp():
88 h = np.asarray(s.get_vof())[:, 1, :].sum(axis=1)
89 zc = NZ - h
90 return 0.5 * (zc.max() - zc.min())
91
92 t, dt, sample, hist = 0.0, dt0, 40.0, [amp()]
93 while t < steps - 1e-9:
94 c = s.vof_max_courant()
95 if c > 0:
96 dt = min(2.0 * dt, dt * cfl / c, dt0)
97 dt = min(dt, sample - t)
98 s.set_dt(dt)
99 s.step()
100 t += dt
101 if t >= sample - 1e-9:
102 hist.append(amp())
103 sample += 40.0
104 return hist
105
106
107def main():
108 print(f"1. translating drop, ratio {RATIO:g}, R {R:g}, U {U0:g}, one box length")
109 for name, cls, bfp in (("staggered (vof momentum)", F.Solver, None),
110 ("collocated V8, BFP ON", F.SolverColocated, None),
111 ("collocated V8, BFP OFF", F.SolverColocated, False)):
112 try:
113 st, fin, worst, dv, shape = translating(cls, bfp)
114 print(f" {name:26s} {st} steps max|u-U|/U final {fin:.3e} worst {worst:.3e} "
115 f"volume drift {dv:.2e} L1 shape err {shape:.3e}")
116 except RuntimeError as exc:
117 print(f" {name:26s} THREW: {exc}")
118 print("2. Rayleigh-Taylor ratio 3 (sharp VoF), amplitude at t = 0, 40, ..., 240")
119 for name, cls in (("staggered", F.Solver), ("collocated V8 (BFP ON)", F.SolverColocated)):
120 try:
121 h = rayleigh_taylor_vof(cls)
122 print(f" {name:24s} " + " -> ".join(f"{a:.2f}" for a in h))
123 except RuntimeError as exc:
124 print(f" {name:24s} THREW: {exc}")
125
126
127if __name__ == "__main__":
128 main()
rayleigh_taylor_vof(cls, N=48, NZ=96, g=0.005, mu=0.002, steps=240, cfl=0.2, dt0=1.0)