flow 1.3.0
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
plot_channel_18.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2"""Plot the WO-W3 `channel_18` profiles, and overlay TBFsolver's when a run of it exists.
3
4 python plot_channel_18.py runs/prod/stats.npz [--tbf tbf_profiles.npz] [--out channel_18.png]
5
6`stats.npz` is what `run_channel_18.py` writes; a `--tbf` file is what `tbf_profiles.py` writes
7from a TBFsolver output folder — the same key names, so the two overlay directly. The two codes
8have DIFFERENT wall-normal resolutions (80 vs 160 rows across the channel), so each set is folded
9about the centreline with its own row count, never with the other's.
10"""
11import sys
12
13import numpy as np
14import matplotlib
15matplotlib.use("Agg")
16import matplotlib.pyplot as plt
17
18
19def arg(name, default):
20 return sys.argv[sys.argv.index(name) + 1] if name in sys.argv else default
21
22
23def fold(z, key, even=True):
24 """Average the two channel halves of one profile onto y/h in [0, 1], with z's own ny."""
25 a = np.asarray(z[key])
26 n = len(a) // 2
27 b, c = a[:n], a[::-1][:n]
28 return (0.5 * (b + c)) if even else (0.5 * (b - c)), np.asarray(z["y"])[:n]
29
30
31def main():
32 src = sys.argv[1] if len(sys.argv) > 1 else "runs/prod/stats.npz"
33 ref = arg("--tbf", None)
34 out = arg("--out", "channel_18.png")
35 z = np.load(src)
36 ut = float(z["utau"])
37 r = np.load(ref) if ref else None
38 rut = float(r["utau"]) if r is not None else 1.0
39
40 fig, ax = plt.subplots(1, 3, figsize=(15, 4.6))
41
42 v, y = fold(z, "u_liq")
43 ax[0].plot(v / ut, y, "-o", ms=3, label="peclet (liquid)")
44 v, y = fold(z, "u")
45 ax[0].plot(v / ut, y, "--", lw=1, label="peclet (all)")
46 if r is not None:
47 v, y2 = fold(r, "u_liq")
48 ax[0].plot(v / rut, y2, "k-", label="TBFsolver (liquid)")
49 ax[0].set_xlabel(r"$\langle u\rangle/u_\tau$")
50 ax[0].set_ylabel("$y/h$")
51 ax[0].legend(fontsize=8)
52 ax[0].grid(alpha=0.3)
53
54 v, y = fold(z, "alpha")
55 ax[1].plot(v, y, "-o", ms=3, label="peclet")
56 if r is not None:
57 v, y2 = fold(r, "alpha")
58 ax[1].plot(v, y2, "k-", label="TBFsolver")
59 ax[1].set_xlabel(r"void fraction $\langle\alpha\rangle$")
60 ax[1].legend(fontsize=8)
61 ax[1].grid(alpha=0.3)
62
63 for k, lab, col in (("urms_liq", "$u'$", "C0"), ("vrms_liq", "$v'$", "C1"),
64 ("wrms_liq", "$w'$", "C2")):
65 v, y = fold(z, k)
66 ax[2].plot(v / ut, y, "-", color=col, label=lab + " peclet")
67 if r is not None:
68 v, y2 = fold(r, k)
69 ax[2].plot(v / rut, y2, "--", color=col, label=lab + " TBF")
70 ax[2].set_xlabel(r"rms$/u_\tau$ (liquid)")
71 ax[2].legend(fontsize=7, ncol=2)
72 ax[2].grid(alpha=0.3)
73
74 g = tuple(int(q) for q in np.asarray(z["grid"]))
75 w = np.asarray(z["window_turnovers"]) if "window_turnovers" in z.files else None
76 win = f"window $t u_\\tau/h$ {w[0]:.2f}–{w[1]:.2f}, " if w is not None else ""
77 fig.suptitle(f"channel_18 — peclet block VoF {g[0]}x{g[1]}x{g[2]}"
78 + (" vs TBFsolver 192x160x96" if r is not None else "")
79 + f" — {win}{int(z['samples'])} samples")
80 fig.tight_layout()
81 fig.savefig(out, dpi=140)
82 print("wrote", out)
83
84
85if __name__ == "__main__":
86 main()
arg(name, default)
fold(z, key, even=True)