flow 1.3.0
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
prof.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2"""Profile the bubble-column step from a checkpoint (the VoF step-performance harness, WO-0).
3
4The case is the bubble column of peclet-examples (128 x 96 x 64, 16 VoF block markers, rho/mu
5ratio 0.02, set_superficial_velocity), built by that repo's run_peclet.build() and restarted from
6ckpt_t43.npz. It runs W warm-up steps (not timed), then N timed steps with the driver's per-step
7protocol (dt = 0.25 min(cfl_dt, capillary_dt) from vof_step_limits()). See
8doc/vof_step_performance_design.md (sec. 7 WO-0, sec. 8 G-BIT / G-NUM / G-PERF).
9
10Usage:
11 PYTHONPATH=<flow build> OMP_NUM_THREADS=8 OMP_PROC_BIND=false \\
12 python tests/study/vof_perf/prof.py N [--pcg [--rtol R]] [--timing] [--dump out.npz]
13 [--warm W] [--flux device|python|none] [--levels L] [--bottom MODE] [--fixdt DT]
14 [--ckpt PATH] [--case-dir DIR] [--dummy N]
15
16 --ckpt checkpoint (default ~/Codes/bubble_column_perf/ckpt_t43.npz)
17 --case-dir directory holding run_peclet.py + case.py (default:
18 ~/Codes/peclet-examples/benchmarks/bubble-column/scripts)
19 --pcg MG-PCG pressure with cap 800 and relative tolerance --rtol (default 1e-10)
20 --cheb Chebyshev pressure (cap --cheb-maxit, default 120) at --rtol; prints the
21 solver's num_pressure_chebyshev_restarts when the build has it (D3, §5.13)
22 --dump save u, v, w, p, C, the timed steps' dt and pressure iterations (iters) and every
23 VoF block's colour array (col<id>) -- compare two dumps with cmp.py (G-BIT item 2)
24 --timing per-stage breakdown from diagnostics.vof_timing()
25 --levels L pressure multigrid depth; --bottom MODE = set_pressure_bottom(MODE) (E1)
26 --bottom-solver ENGINE diagnostics.set_pressure_bottom_solver(ENGINE): auto | direct |
27 algebraic (§13: the A/B of the two bottom engines on one build)
28 --div with --dump: also store each timed step's max_open_divergence_projected() (div),
29 read after the step (G-NUM item 3)
30 --stats with --dump: also store every timed step's measured block statistics (st_volume,
31 st_area, st_centroid, st_velocity, st_moments; WO-9's gate, C2 §5.10)
32"""
33import os
34import sys
35import time
36
37import numpy as np
38
39A = list(sys.argv)
40
41
42def arg(name, default, cast=str):
43 return cast(A[A.index(name) + 1]) if name in A else default
44
45
46CASE_DIR = arg("--case-dir", os.path.expanduser(
47 "~/Codes/peclet-examples/benchmarks/bubble-column/scripts"))
48CKPT = arg("--ckpt", os.path.expanduser(
49 "~/Codes/bubble_column_perf/ckpt_t43.npz"))
50sys.path.insert(0, CASE_DIR)
51import run_peclet as rp # noqa: E402
52
53N = int(A[1])
54TIMING = "--timing" in A
55FLUX = arg("--flux", "python")
56DUMP = arg("--dump", None)
57WARM = arg("--warm", 5, int)
58FIXDT = arg("--fixdt", None, float)
59RTOL = arg("--rtol", 1e-10, float)
60
61step, t, blocks, vel, pres, series = rp.load_ckpt(CKPT)
62t_b = time.time()
63if "--dummy" in A:
64 import peclet.flow as _pf
65 _dummy = _pf.Solver(arg("--dummy", 17, int), 13, 11)
66 _dummy.set_pressure_geometry(np.full((arg("--dummy", 17, int), 13, 11), 10.0, order="F"))
67if "--levels" in A:
68 _L = arg("--levels", 4, int)
70
71 class _Shim:
72 def __new__(cls, *a, **k):
73 o = _orig(*a, **k)
75 return o
77if not hasattr(rp.pf.Solver, "set_superficial_velocity") and hasattr(rp.pf.Solver, "set_bulk_velocity"):
79s = rp.build(blocks)
80for c, a in enumerate(vel):
81 s.set_velocity(c, a)
82s.set_field("p", pres)
84# run_peclet.build() now enables the device constraint itself; the other modes switch it off
85for _name in ("set_superficial_velocity", "set_bulk_velocity"):
86 if hasattr(s, _name):
87 getattr(s, _name)(FLUX == "device", "x", 0.0)
88 break
89if "--pcg" in A:
90 s.set_pressure_pcg(True, 800, RTOL)
91if "--cheb" in A: # the variable-density default driver, solver default cap 120, at --rtol
92 s.set_pressure_chebyshev(True, arg("--cheb-maxit", 120, int), RTOL)
93if "--bottom" in A:
94 s.set_pressure_bottom(arg("--bottom", "auto"))
95if "--bottom-solver" in A:
96 s.diagnostics.set_pressure_bottom_solver(arg("--bottom-solver", "auto"))
97DIV = "--div" in A
98divs = []
99STATS = "--stats" in A
100stats = {k: [] for k in ("volume", "area", "centroid", "velocity", "moments")}
101print(f"build {time.time()-t_b:.2f} s", flush=True)
102
104dtsafe = 0.25
105iters = []
106T = {"limits": 0.0, "step": 0.0, "flux": 0.0}
107
108
109def one(timed):
110 global t
111 t0 = time.perf_counter()
112 if FIXDT:
113 dt = FIXDT
114 else:
116 dt = min(dtsafe * L["cfl_dt"], dtsafe * L["capillary_dt"])
117 s.set_dt(dt)
118 t1 = time.perf_counter()
119 s.step()
120 t2 = time.perf_counter()
121 if FLUX == "python":
122 u = s.get_u()
123 s.set_velocity(0, np.asfortranarray(u - float(u.mean())))
124 t3 = time.perf_counter()
125 if timed:
126 T["limits"] += t1 - t0
127 T["step"] += t2 - t1
128 T["flux"] += t3 - t2
130 if DIV:
132 if STATS:
134 for k in stats:
135 stats[k].append([b[k] for b in st])
136 t += dt
137 return dt
138
139
140for _ in range(WARM):
141 one(False)
142if TIMING:
145dts = [one(True) for _ in range(N)]
146wall = time.perf_counter() - w0
147print(f"steps {N} wall {wall:.3f} s {1000*wall/N:.2f} ms/step dt mean {np.mean(dts):.3e}")
148print("per-step ms: " + " ".join(f"{k} {1000*v/N:.2f}" for k, v in T.items()))
149print(f"pressure iters mean {np.mean(iters):.2f} min {min(iters)} max {max(iters)}")
150if "--cheb" in A and hasattr(s.diagnostics, "num_pressure_chebyshev_restarts"):
151 print(f"chebyshev restarts {s.diagnostics.num_pressure_chebyshev_restarts}")
152if TIMING:
154 n = v["steps"]
155 print("vof_timing per step ms (steps=%d):" % n)
156 for k, x in v.items():
157 if k in ("steps", "k_sweeps", "kc_calls"):
158 continue
159 if x:
160 print(f" {k:22s} {1000*x/n:8.3f}")
161if DUMP:
162 cols = {f"col{b['id']}": np.asarray(s.vof_block_color(b["id"]))
164 np.savez(DUMP, u=s.get_u(), v=s.get_v(), w=s.get_w(), p=s.get_field("p"), C=s.get_field("C"),
165 dts=np.array(dts), iters=np.array(iters, dtype=np.int64), **cols,
166 **({"div": np.array(divs)} if DIV else {}),
167 **({f"st_{k}": np.array(v) for k, v in stats.items()} if STATS else {}))
168 print("dumped", DUMP, f"({len(cols)} block colours)")
__new__(cls, *a, **k)
Definition prof.py:72
_orig
Definition prof.py:69
arg(name, default, cast=str)
Definition prof.py:42
one(timed)
Definition prof.py:109
Solver
Definition prof.py:76