1"""Tune multigrid parameters for the SDF sphere-packing pressure solve."""
6from copy
import deepcopy
8THIS_DIR = os.path.dirname(__file__)
9sys.path.append(THIS_DIR)
11from benchmark_sdf_packing_multigrid
import load_sdf, run_case, warm_up_cuda
19 pressure_mg=(4, 1, 1, 16, 1),
20 velocity_mg=(4, 2, 2, 32, 1),
25 "pressure_iter": pressure_iter,
26 "velocity_iter": velocity_iter,
27 "pressure_mg": pressure_mg,
28 "velocity_mg": velocity_mg,
33 make_config(
"rbgs_p50_v2",
"rbgs", pressure_iter=50, velocity_iter=2),
34 make_config(
"rbgs_p20_v2",
"rbgs", pressure_iter=20, velocity_iter=2),
35 make_config(
"rbgs_p10_v2",
"rbgs", pressure_iter=10, velocity_iter=2),
36 make_config(
"rbgs_p20_v4",
"rbgs", pressure_iter=20, velocity_iter=4),
37 make_config(
"pmg_l2_light",
"pmg", pressure_mg=(2, 1, 1, 16, 1)),
38 make_config(
"pmg_l3_light",
"pmg", pressure_mg=(3, 1, 1, 16, 1)),
39 make_config(
"pmg_l3_light_v1",
"pmg", velocity_iter=1, pressure_mg=(3, 1, 1, 16, 1)),
40 make_config(
"pmg_l3_light_v4",
"pmg", velocity_iter=4, pressure_mg=(3, 1, 1, 16, 1)),
41 make_config(
"pmg_l3_light_b8",
"pmg", pressure_mg=(3, 1, 1, 8, 1)),
42 make_config(
"pmg_l3_light_b32",
"pmg", pressure_mg=(3, 1, 1, 32, 1)),
43 make_config(
"pmg_l3_mid",
"pmg", pressure_mg=(3, 1, 1, 16, 2)),
44 make_config(
"pmg_l3_default",
"pmg", pressure_mg=(3, 2, 2, 32, 2)),
45 make_config(
"pmg_l4_light",
"pmg", pressure_mg=(4, 1, 1, 16, 1)),
46 make_config(
"fullmg_l2_balanced",
"fullmg", pressure_mg=(2, 1, 1, 16, 1), velocity_mg=(2, 2, 2, 32, 1)),
47 make_config(
"fullmg_l3_balanced",
"fullmg", pressure_mg=(3, 1, 1, 16, 1), velocity_mg=(3, 2, 2, 32, 1)),
48 make_config(
"fullmg_l3_inner4",
"fullmg", pressure_mg=(3, 1, 1, 16, 1), velocity_mg=(3, 4, 4, 32, 1)),
49 make_config(
"fullmg_l3_robust",
"fullmg", pressure_mg=(3, 2, 2, 32, 1), velocity_mg=(3, 4, 4, 64, 1)),
55 cfg.pressure_iter = config[
"pressure_iter"]
56 cfg.velocity_iter = config[
"velocity_iter"]
58 cfg.pressure_mg_levels,
61 cfg.pressure_mg_bottom,
62 cfg.pressure_mg_cycles,
63 ) = config[
"pressure_mg"]
65 cfg.velocity_mg_levels,
68 cfg.velocity_mg_bottom,
69 cfg.velocity_mg_cycles,
70 ) = config[
"velocity_mg"]
74def run_config(base_args, sdf_zyx, origin, spacing, config):
77 "name": config[
"name"],
78 "method": config[
"method"],
79 "pressure_iter": config[
"pressure_iter"],
80 "velocity_iter": config[
"velocity_iter"],
81 "pressure_mg": config[
"pressure_mg"],
82 "velocity_mg": config[
"velocity_mg"],
86 result = run_case(args, sdf_zyx, origin, spacing, config[
"method"])
88 except Exception
as exc:
91 "status": f
"failed: {exc}",
92 "elapsed_s": float(
"nan"),
93 "per_step_s": float(
"nan"),
95 "outer_iterations_mean": float(
"nan"),
96 "outer_iterations_max": 0,
97 "u_mean": float(
"nan"),
98 "v_mean": float(
"nan"),
99 "w_mean": float(
"nan"),
100 "p_mean": float(
"nan"),
101 "u_abs_max": float(
"nan"),
102 "p_abs_max": float(
"nan"),
109 os.makedirs(os.path.dirname(output_csv), exist_ok=
True)
120 "outer_iterations_mean",
121 "outer_iterations_max",
127 with open(output_csv,
"w", newline=
"", encoding=
"utf-8")
as handle:
128 writer = csv.DictWriter(handle, fieldnames=fieldnames)
131 writer.writerow({name: row.get(name)
for name
in fieldnames})
135 print(f
"Packing SDF: {args.sdf}")
137 f
"dt={args.dt}, max_steps={args.max_steps}, convergence_stride={args.convergence_stride}, "
138 f
"convergence_rel_tol={args.convergence_rel_tol}, outer_tol={args.outer_tol}, outer_mode={args.outer_mode}"
142 f
"{'config':<20} {'method':<8} {'time(s)':>10} {'steps':>8} {'outer_mean':>12} "
143 f
"{'outer_max':>10} {'u_mean':>12} {'status':<24}"
149 row[
"status"] !=
"ok",
150 row[
"elapsed_s"]
if row[
"elapsed_s"] == row[
"elapsed_s"]
else float(
"inf"),
155 f
"{row['name']:<20} {row['method']:<8} {row['elapsed_s']:10.3f} "
156 f
"{row['steps_taken']:8d} {row['outer_iterations_mean']:12.2f} "
157 f
"{row['outer_iterations_max']:10d} {row['u_mean']:12.4e} {row['status']:<24}"
162 parser = argparse.ArgumentParser(
163 description=
"Tune RBGS and multigrid settings on a real SDF packing geometry."
167 default=os.path.abspath(os.path.join(THIS_DIR,
"../ring_packing_sdf.vti")),
169 parser.add_argument(
"--configs", nargs=
"+", default=
None)
170 parser.add_argument(
"--dt", type=float, default=1.0)
171 parser.add_argument(
"--max-steps", type=int, default=100)
172 parser.add_argument(
"--convergence-stride", type=int, default=10)
173 parser.add_argument(
"--convergence-rel-tol", type=float, default=1e-8)
174 parser.add_argument(
"--force-x", type=float, default=1.0)
175 parser.add_argument(
"--force-y", type=float, default=0.0)
176 parser.add_argument(
"--force-z", type=float, default=0.0)
177 parser.add_argument(
"--rho", type=float, default=0.0)
178 parser.add_argument(
"--mu", type=float, default=1.0)
179 parser.add_argument(
"--ibm-scheme", type=int, default=0)
180 parser.add_argument(
"--outer-iterations", type=int, default=800)
181 parser.add_argument(
"--outer-tol", type=float, default=1e-6)
182 parser.add_argument(
"--outer-mode", type=int, default=1)
185 default=
"output/packing_multigrid_tuning.csv",
187 return parser.parse_args()
192 if args.configs
is None:
195 wanted = set(args.configs)
196 configs = [config
for config
in CONFIGS
if config[
"name"]
in wanted]
197 missing = sorted(wanted - {config[
"name"]
for config
in configs})
199 raise ValueError(f
"unknown configs requested: {missing}")
201 sdf_zyx, origin, spacing = load_sdf(args.sdf)
205 for config
in configs:
206 print(f
"Running config={config['name']}")
207 rows.append(
run_config(args, sdf_zyx, origin, spacing, config))
211 print(f
"Wrote tuning CSV to {args.output_csv}")
214if __name__ ==
"__main__":
print_summary(rows, args)
run_config(base_args, sdf_zyx, origin, spacing, config)
make_config(name, method, pressure_iter=50, velocity_iter=2, pressure_mg=(4, 1, 1, 16, 1), velocity_mg=(4, 2, 2, 32, 1))
write_csv(rows, output_csv)
apply_config(args, config)