PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
 
Loading...
Searching...
No Matches
Functions | Variables
picurv_cli.cli Namespace Reference

Functions

 _add_run_parser (subparsers)
 Attach run parser with staged execution and dry-run support.
 
 _add_sweep_parser (subparsers)
 Perform add sweep parser.
 
 _add_validate_parser (subparsers)
 Perform add validate parser.
 
 _add_precompute_parser (subparsers)
 Attach precompute parser for deterministic artifact generation.
 
 _add_inputs_parser (subparsers)
 Attach explicit workspace input-ingress commands.
 
 _add_version_parsers (subparsers)
 Attach unified source/build/workspace-version commands.
 
 _add_summarize_parser (subparsers)
 Attach summarize parser for read-only run-health views.
 
 _add_cancel_parser (subparsers)
 Perform add cancel parser.
 
 _add_submit_parser (subparsers)
 Perform add submit parser.
 
 _add_init_parser (subparsers)
 Perform add init parser.
 
 _add_build_parser (subparsers)
 Perform add build parser.
 
 _add_sync_config_parser (subparsers)
 Perform add sync config parser.
 
 _add_pull_source_parser (subparsers)
 Perform add pull source parser.
 
 _add_status_source_parser (subparsers)
 Perform add status source parser.
 
 build_main_parser ()
 Build and return the top-level CLI parser.
 
 dispatch_command (args)
 Validate argument combinations and dispatch to command handlers.
 

Variables

tuple CLI_OUTPUT_FORMATS = ("text", "json")
 
tuple RUN_STAGE_CHOICES = ("all", "solve", "post-process")
 
tuple RESTART_STATISTICS_MODES = ("reset", "carry")
 
tuple WORKSPACE_INPUT_KINDS = ("grid", "initial-condition", "inlet-profile", "reference-field")
 
tuple WORKSPACE_INPUT_MODES = ("copy", "reflink", "hardlink", "reference")
 

Detailed Description

Argument parser construction and command dispatch for PICurv.

Function Documentation

◆ _add_run_parser()

picurv_cli.cli._add_run_parser (   subparsers)
protected

Attach run parser with staged execution and dry-run support.

Parameters
[in]subparsersArgument passed to _add_run_parser().
Returns
Value returned by _add_run_parser().

Definition at line 27 of file cli.py.

27def _add_run_parser(subparsers):
28 """!
29 @brief Attach `run` parser with staged execution and dry-run support.
30 @param[in] subparsers Argument passed to `_add_run_parser()`.
31 @return Value returned by `_add_run_parser()`.
32 """
33 p_run = subparsers.add_parser(
34 "run",
35 help="Execute a simulation workflow (solve and/or post-process).",
36 formatter_class=argparse.RawTextHelpFormatter,
37 description=(
38 "Execute solver and/or post-processing stages.\n\n"
39 "Notes:\n"
40 " - --num-procs applies to solver and post-processing stage launches.\n"
41 " - With --solve, --continue resumes the existing run directory in-place.\n"
42 " - With --post-process, --continue resumes the same recipe from the first unfinished step\n"
43 " and caps the launch to the highest fully available contiguous source frontier.\n\n"
44 "Diagnostics:\n"
45 " - PETSc and runtime memory diagnostics live under monitor.yml -> diagnostics.\n"
46 " - Use --dry-run to inspect resolved PETSc flags and expected log destinations.\n\n"
47 "Examples:\n"
48 " picurv run --solve -n 8 --case case.yml --solver solver.yml --monitor monitor.yml\n"
49 " picurv run --solve --restart-from runs/old_run --case case.yml --solver solver.yml --monitor monitor.yml\n"
50 " picurv run --solve --continue --run-dir runs/my_run --case case.yml --solver solver.yml --monitor monitor.yml\n"
51 " picurv run --post-process --run-dir runs/my_run --post post.yml\n"
52 " picurv run --post-process --continue --run-dir runs/my_run --post post.yml\n"
53 " picurv run --solve --case case.yml --solver solver.yml --monitor monitor.yml --dry-run"
54 ),
55 epilog="Next: run `picurv validate ...` first for config-only checks.",
56 )
57 run_group = p_run.add_argument_group("stages")
58 run_group.add_argument("--solve", action="store_true", help="Execute the solver stage (creates a new run directory).")
59 run_group.add_argument("--post-process", action="store_true", help="Execute the post-processing stage on a run directory.")
60
61 solver_group = p_run.add_argument_group("solver inputs (required for --solve)")
62 solver_group.add_argument("--case", help="Path to the case definition file (e.g., case.yml).")
63 solver_group.add_argument("--solver", help="Path to the solver settings profile (e.g., solver.yml).")
64 solver_group.add_argument("--monitor", help="Path to the monitoring, diagnostics, and I/O profile (e.g., monitor.yml).")
65 solver_group.add_argument(
66 "--restart-from", "--from",
67 dest="restart_from",
68 help="Path to an existing run directory to restart from.\n"
69 "Use 'latest' to select the newest compatible local workspace run.",
70 )
71 solver_group.add_argument(
72 "--statistics-state",
73 choices=RESTART_STATISTICS_MODES,
74 default=None,
75 help="For a branched restart with field statistics enabled, this is required:\n"
76 "'reset' discards the parent's accumulated windows, 'carry' resumes compatible\n"
77 "saved window state. Ignored when field statistics are disabled.",
78 )
79 solver_group.add_argument(
80 "--require-precomputed",
81 action="store_true",
82 help="Refuse to build missing or stale deterministic assets while staging the run.",
83 )
84 solver_group.add_argument(
85 "--fetch-missing",
86 action="store_true",
87 help="Try the configured storage profile before rebuilding a missing workspace asset.",
88 )
89 run_group.add_argument(
90 "--continue",
91 action="store_true",
92 dest="continue_run",
93 help="Resume an existing run directory in-place. Requires --run-dir.\n"
94 "With --solve, requires start_step > 0 and appends to existing solver output/logs.\n"
95 "With --post-process, resumes the same recipe from the first unfinished step\n"
96 "and skips already-complete work inside the current live source frontier.",
97 )
98
99 post_group = p_run.add_argument_group("post-processor inputs (required for --post-process)")
100 post_group.add_argument("--run-dir", help="Path to an existing run directory.\n(Used with --post-process or --continue).")
101 post_group.add_argument("--post", help="Path to the post-processing recipe file (e.g., post.yml).")
102 post_group.add_argument(
103 "--only",
104 help="Comma-separated post stages to run: 'fields' (the field post-processor)\n"
105 "and/or 'spectra'. Defaults to every stage.\n"
106 "Use --only spectra to re-measure spectra without rebuilding field output.",
107 )
108
109 p_run.add_argument(
110 "-n",
111 "--num-procs",
112 type=int,
113 default=1,
114 help="Number of MPI processes for solver and post-processing stages.",
115 )
116 p_run.add_argument("--cluster", help="Path to cluster.yml for Slurm execution mode.")
117 p_run.add_argument("--scheduler", help="Explicit scheduler selector (currently 'slurm').")
118 p_run.add_argument("--no-submit", action="store_true", help="Stage run artifacts without starting local execution or Slurm submission.")
119 p_run.add_argument(
120 "--dry-run",
121 action="store_true",
122 help="Resolve and print planned commands/artifacts, including diagnostic flags and log paths, without writing files.",
123 )
124 p_run.add_argument(
125 "--format",
126 dest="output_format",
127 choices=list(CLI_OUTPUT_FORMATS),
128 default="text",
129 help="Output format for --dry-run (default: text).",
130 )
131 return p_run
132
133
Head of a generic C-style linked list.
Definition variables.h:475
Here is the caller graph for this function:

◆ _add_sweep_parser()

picurv_cli.cli._add_sweep_parser (   subparsers)
protected

Perform add sweep parser.

Parameters
[in]subparsersArgument passed to _add_sweep_parser().
Returns
Value returned by _add_sweep_parser().

Definition at line 134 of file cli.py.

134def _add_sweep_parser(subparsers):
135 """!
136 @brief Perform add sweep parser.
137 @param[in] subparsers Argument passed to `_add_sweep_parser()`.
138 @return Value returned by `_add_sweep_parser()`.
139 """
140 p_sweep = subparsers.add_parser(
141 "sweep",
142 help="Launch or continue a Slurm-based parameter sweep/study.",
143 formatter_class=argparse.RawTextHelpFormatter,
144 description=(
145 "Launch studies from study.yml + cluster.yml, whether the study uses\n"
146 "cross-product parameter combinations or explicit coupled parameter_sets, continue\n"
147 "partially-completed studies, or re-aggregate metrics.\n\n"
148 "Examples:\n"
149 " picurv sweep --study study.yml --cluster cluster.yml\n"
150 " picurv sweep --study study.yml --cluster cluster.yml --no-submit\n"
151 " picurv sweep --continue --study-dir studies/<id>\n"
152 " picurv sweep --continue --study-dir studies/<id> --cluster cluster_more_time.yml\n"
153 " picurv sweep --reaggregate --study-dir studies/<id>"
154 ),
155 epilog=(
156 "Study files support either `parameters` cross-product expansion or explicit `parameter_sets`.\n"
157 "Next: inspect studies/<study_id>/results/metrics_table.csv for aggregated metrics."
158 ),
159 )
160 p_sweep.add_argument("--study", help="Path to study.yml defining either a `parameters` cross-product expansion or explicit parameter_sets, plus metrics.")
161 p_sweep.add_argument("--cluster", help="Path to cluster.yml defining Slurm resources.")
162 p_sweep.add_argument("--no-submit", action="store_true", help="Generate all study artifacts without submitting jobs.")
163 p_sweep.add_argument("--study-dir", help="Path to an existing study directory (for --continue/--reaggregate).")
164 p_sweep.add_argument("--continue", action="store_true", dest="continue_study",
165 help="Continue a partially-completed study. Requires --study-dir.")
166 p_sweep.add_argument("--reaggregate", action="store_true",
167 help="Re-run metrics aggregation on a completed study. Requires --study-dir.")
168 p_sweep.add_argument("--auto-fetch", action="store_true",
169 help="Restore cold-storage study members automatically instead of\n"
170 "refusing. Requires a configured storage profile.")
171 return p_sweep
172
173
Here is the caller graph for this function:

◆ _add_validate_parser()

picurv_cli.cli._add_validate_parser (   subparsers)
protected

Perform add validate parser.

Parameters
[in]subparsersArgument passed to _add_validate_parser().
Returns
Value returned by _add_validate_parser().

Definition at line 174 of file cli.py.

174def _add_validate_parser(subparsers):
175 """!
176 @brief Perform add validate parser.
177 @param[in] subparsers Argument passed to `_add_validate_parser()`.
178 @return Value returned by `_add_validate_parser()`.
179 """
180 p_validate = subparsers.add_parser(
181 "validate",
182 help="Validate config files without launching solver/post.",
183 formatter_class=argparse.RawTextHelpFormatter,
184 description=(
185 "Validate one or more config roles. No solver/post execution and no run/study artifact writes.\n\n"
186 "Examples:\n"
187 " picurv validate --case case.yml --solver solver.yml --monitor monitor.yml\n"
188 " picurv validate --post post.yml --cluster cluster.yml\n"
189 " picurv validate --study study.yml --cluster cluster.yml --strict"
190 ),
191 epilog="Next: run `picurv run --dry-run ...` to inspect resolved commands/artifacts.",
192 )
193 p_validate.add_argument("--case", help="Path to case.yml")
194 p_validate.add_argument("--solver", help="Path to solver.yml")
195 p_validate.add_argument("--monitor", help="Path to monitor.yml (logging, diagnostics, profiling, and I/O)")
196 p_validate.add_argument("--restart-from", help="Path to a run directory to validate restart from.")
197 p_validate.add_argument("--continue", action="store_true", dest="continue_run", help="Validate continue-in-place mode. Requires --run-dir.")
198 p_validate.add_argument("--run-dir", help="Path to an existing run directory (for --continue validation).")
199 p_validate.add_argument("--post", help="Path to post.yml")
200 p_validate.add_argument("--cluster", help="Path to cluster.yml")
201 p_validate.add_argument("--study", help="Path to study.yml")
202 p_validate.add_argument("--strict", action="store_true", help="Enable additional strict checks for selected roles.")
203 return p_validate
204
Here is the caller graph for this function:

◆ _add_precompute_parser()

picurv_cli.cli._add_precompute_parser (   subparsers)
protected

Attach precompute parser for deterministic artifact generation.

Parameters
[in]subparsersArgument passed to _add_precompute_parser().
Returns
Configured parser.

Definition at line 205 of file cli.py.

205def _add_precompute_parser(subparsers):
206 """!
207 @brief Attach `precompute` parser for deterministic artifact generation.
208 @param[in] subparsers Argument passed to `_add_precompute_parser()`.
209 @return Configured parser.
210 """
211 p_precompute = subparsers.add_parser(
212 "precompute",
213 help="Generate deterministic case artifacts without launching the solver.",
214 formatter_class=argparse.RawTextHelpFormatter,
215 description=(
216 "Generate configured deterministic artifacts, such as grid_gen grids,\n"
217 "generated prescribed-flow inlet profiles, and ic_gen initial conditions,\n"
218 "as immutable objects in the initialized workspace asset store.\n\n"
219 "Examples:\n"
220 " picurv precompute --case config/case.yml\n"
221 " picurv precompute --case config/case.yml --only grid,initial-condition"
222 ),
223 epilog="Next: inspect the reported asset set, then stage a run that reuses it.",
224 )
225 p_precompute.add_argument("--case", required=True, help="Path to case.yml containing grid/profile/IC generator settings.")
226 p_precompute.add_argument(
227 "--only",
228 default="all",
229 help="Comma-separated asset kinds (grid, initial-condition, inlet-profiles), or all.",
230 )
231 return p_precompute
232
233
Here is the caller graph for this function:

◆ _add_inputs_parser()

picurv_cli.cli._add_inputs_parser (   subparsers)
protected

Attach explicit workspace input-ingress commands.

Parameters
[in]subparsersTop-level argparse subparser collection.
Returns
Configured inputs command parser.

Definition at line 234 of file cli.py.

234def _add_inputs_parser(subparsers):
235 """!
236 @brief Attach explicit workspace input-ingress commands.
237 @param[in] subparsers Top-level argparse subparser collection.
238 @return Configured inputs command parser.
239 """
240 parser = subparsers.add_parser(
241 "inputs",
242 help="Import or register files used by workspace configurations.",
243 formatter_class=argparse.RawTextHelpFormatter,
244 )
245 actions = parser.add_subparsers(dest="inputs_action", required=True)
246 p_import = actions.add_parser("import", help="Import one external file into its canonical workspace home.")
247 p_import.add_argument(
248 "kind",
249 choices=WORKSPACE_INPUT_KINDS,
250 )
251 p_import.add_argument("source", help="Existing source file.")
252 p_import.add_argument("--name", help="Destination name; defaults to the source basename.")
253 p_import.add_argument(
254 "--mode", choices=WORKSPACE_INPUT_MODES, default="copy",
255 help="How to retain the input. Reference mode records but does not copy an external path.",
256 )
257 p_import.add_argument("--workspace", help="Workspace root; defaults to discovery from the current directory.")
258 return parser
259
260
Here is the caller graph for this function:

◆ _add_version_parsers()

picurv_cli.cli._add_version_parsers (   subparsers)
protected

Attach unified source/build/workspace-version commands.

Parameters
[in]subparsersTop-level argparse subparser collection.
Returns
Version, versions, and source command parsers.

Definition at line 261 of file cli.py.

261def _add_version_parsers(subparsers):
262 """!
263 @brief Attach unified source/build/workspace-version commands.
264 @param[in] subparsers Top-level argparse subparser collection.
265 @return Version, versions, and source command parsers.
266 """
267 p_version = subparsers.add_parser(
268 "version",
269 help="Report the active PICurv release and build identity.",
270 formatter_class=argparse.RawTextHelpFormatter,
271 description=(
272 "Report the build identity shared by the Python conductor and the native\n"
273 "executables, plus any workspace version requirement.\n\n"
274 "With the 'status' action this also validates that they agree, and exits 1\n"
275 "when they do not, so a job script can refuse an incoherent build.\n\n"
276 "Examples:\n"
277 " picurv version\n"
278 " picurv version status\n"
279 " picurv version status --format json"
280 ),
281 )
282 p_version.add_argument(
283 "version_action", nargs="?", choices=["status"], default=None,
284 help="'status' validates conductor/executable/workspace coherence and exits 1 on disagreement.",
285 )
286 p_version.add_argument("--format", dest="output_format", choices=list(CLI_OUTPUT_FORMATS), default="text")
287
288 p_versions = subparsers.add_parser("versions", help="List, install, or activate PICurv source versions.")
289 actions = p_versions.add_subparsers(dest="versions_action", required=True)
290 actions.add_parser("list", help="List local Git tags and the active build.")
291 p_install = actions.add_parser("install", help="Fetch a named version and build it in the source checkout.")
292 p_install.add_argument("version")
293 p_activate = actions.add_parser("activate", help="Checkout and build the version required by this workspace.")
294 p_activate.add_argument("version", nargs="?", help="Version/tag; defaults to the workspace requirement.")
295 p_activate.add_argument("--workspace", help="Workspace root; defaults to discovery from the current directory.")
296
297 p_source = subparsers.add_parser("source", help="Manage the source checkout used by PICurv.")
298 source_actions = p_source.add_subparsers(dest="source_action", required=True)
299 p_update = source_actions.add_parser("update", help="Fetch source updates without changing the active version.")
300 p_update.add_argument("--remote", default="origin")
301 return p_version, p_versions, p_source
302
303
Here is the caller graph for this function:

◆ _add_summarize_parser()

picurv_cli.cli._add_summarize_parser (   subparsers)
protected

Attach summarize parser for read-only run-health views.

Parameters
[in]subparsersArgument passed to _add_summarize_parser().
Returns
Value returned by _add_summarize_parser().

Definition at line 304 of file cli.py.

304def _add_summarize_parser(subparsers):
305 """!
306 @brief Attach `summarize` parser for read-only run-health views.
307 @param[in] subparsers Argument passed to `_add_summarize_parser()`.
308 @return Value returned by `_add_summarize_parser()`.
309 """
310 p_summarize = subparsers.add_parser(
311 "summarize",
312 help="Summarize run configs/health and plot scalar log histories.",
313 formatter_class=argparse.RawTextHelpFormatter,
314 description=(
315 "Build read-only configuration overviews, run-health summaries, and scalar time-history plots.\n"
316 "It does not modify solver output and works for active or completed runs.\n\n"
317 "Examples:\n"
318 " picurv summarize --run-dir runs/my_run --overview\n"
319 " picurv summarize --run-dir runs/my_run --case --solver\n"
320 " picurv summarize --run-dir runs/my_run --latest\n"
321 " picurv summarize --run-dir runs/my_run --monitor --step 500\n"
322 " picurv summarize --run-dir runs/my_run --list-plot-series\n"
323 " picurv summarize --run-dir runs/my_run --plot momentum.residual_norm --last 100\n"
324 " picurv summarize --run-dir runs/my_run --latest --format json"
325 ),
326 epilog="Next: use `picurv run ...` to create runs or `picurv sweep ...` for multi-case studies.",
327 )
328 p_summarize.add_argument("--run-dir", required=True, help="Path to the run directory to inspect.")
329 p_summarize.add_argument(
330 "--overview",
331 action="store_true",
332 help="Summarize run metadata plus copied case, solver, and monitor configs without implicitly requesting health.",
333 )
334 p_summarize.add_argument("--case", action="store_true", help="Summarize the copied run-local case.yml.")
335 p_summarize.add_argument("--solver", action="store_true", help="Summarize the copied run-local solver.yml.")
336 p_summarize.add_argument("--monitor", action="store_true", help="Summarize the copied run-local monitor.yml.")
337 plot_group = p_summarize.add_mutually_exclusive_group()
338 plot_group.add_argument(
339 "--list-plot-series",
340 dest="list_plot_series",
341 action="store_true",
342 help="List scalar histories available to --plot.",
343 )
344 plot_group.add_argument(
345 "--list-series",
346 dest="list_plot_series",
347 action="store_true",
348 help=argparse.SUPPRESS,
349 )
350 plot_group.add_argument(
351 "--plot",
352 dest="plot_series",
353 help="Plot one qualified scalar history, such as momentum.residual_norm (requires matplotlib).",
354 )
355 plot_group.add_argument(
356 "--plot-spectrum",
357 dest="plot_spectrum",
358 nargs="?",
359 const="",
360 help="Plot up to six representative measured energy spectra, including the first\n"
361 "and last states, overlaid on the initial-condition spectrum. Takes an optional\n"
362 "task-name substring when the recipe measured more than one spectrum\n"
363 "(requires matplotlib).",
364 )
365 p_summarize.add_argument("--last", dest="last_n", type=int, help="Plot only the last N chronological records per line.")
366 p_summarize.add_argument("--plot-output", help="Save the plot to this path instead of opening an interactive window.")
367 p_summarize.add_argument("--linear-y", action="store_true", help="Force linear y-axis scaling instead of automatic residual/norm log scaling.")
368 step_group = p_summarize.add_mutually_exclusive_group()
369 step_group.add_argument("--step", type=int, help="Specific completed timestep to summarize.")
370 step_group.add_argument(
371 "--latest",
372 action="store_true",
373 help="Summarize the most recently appended completed step found in available artifacts (default behavior).",
374 )
375 step_group.add_argument(
376 "--max-step",
377 action="store_true",
378 help="Summarize the numerically largest timestep found in available artifacts.",
379 )
380 p_summarize.add_argument(
381 "--snapshot-rows",
382 type=int,
383 default=5,
384 help="Number of sampled particle snapshot rows to preview when solver stream output contains them.",
385 )
386 p_summarize.add_argument(
387 "--format",
388 dest="output_format",
389 choices=list(CLI_OUTPUT_FORMATS),
390 default="text",
391 help="Output format (default: text).",
392 )
393 return p_summarize
394
395
Here is the caller graph for this function:

◆ _add_cancel_parser()

picurv_cli.cli._add_cancel_parser (   subparsers)
protected

Perform add cancel parser.

Parameters
[in]subparsersArgument passed to _add_cancel_parser().
Returns
Value returned by _add_cancel_parser().

Definition at line 396 of file cli.py.

396def _add_cancel_parser(subparsers):
397 """!
398 @brief Perform add cancel parser.
399 @param[in] subparsers Argument passed to `_add_cancel_parser()`.
400 @return Value returned by `_add_cancel_parser()`.
401 """
402 p_cancel = subparsers.add_parser(
403 "cancel",
404 help="Cancel Slurm-submitted jobs for an existing run directory.",
405 formatter_class=argparse.RawTextHelpFormatter,
406 description=(
407 "Look up scheduler/submission.json inside an existing run directory and cancel\n"
408 "the recorded Slurm job(s) without requiring manual job-id lookup.\n\n"
409 "Examples:\n"
410 " picurv cancel --run-dir runs/my_run\n"
411 " picurv cancel --run-dir runs/my_run --stage solve\n"
412 " picurv cancel --run-dir runs/my_run --stage solve --graceful\n"
413 " picurv cancel --run-dir runs/my_run --dry-run\n\n"
414 "Default cancellation is a hard Slurm cancel (`scancel <job_id>`). With\n"
415 "`--graceful`, Slurm sends SIGUSR1 to the solver process tree so PICurv can write the latest\n"
416 "safe off-cadence step at the next runtime checkpoint before exiting.\n"
417 "Post-process jobs still use ordinary hard cancellation."
418 ),
419 epilog="Next: use `picurv summarize --run-dir ...` to inspect whatever output the run already produced.",
420 )
421 p_cancel.add_argument("--run-dir", required=True, help="Path to the run directory whose Slurm job(s) should be canceled.")
422 p_cancel.add_argument(
423 "--stage",
424 choices=list(RUN_STAGE_CHOICES),
425 default="all",
426 help="Which recorded stage job(s) to cancel (default: all).",
427 )
428 p_cancel.add_argument(
429 "--dry-run",
430 action="store_true",
431 help="Show which `scancel` command(s) would run without actually canceling anything.",
432 )
433 p_cancel.add_argument(
434 "--graceful",
435 action="store_true",
436 help=(
437 "For solver jobs, request a clean runtime shutdown by sending SIGUSR1 to the process tree instead of "
438 "hard-canceling immediately. The solver writes the latest safe off-cadence step at "
439 "the next checkpoint. Non-solver stages still use ordinary scancel."
440 ),
441 )
442 return p_cancel
443
444
Here is the caller graph for this function:

◆ _add_submit_parser()

picurv_cli.cli._add_submit_parser (   subparsers)
protected

Perform add submit parser.

Parameters
[in]subparsersArgument passed to _add_submit_parser().
Returns
Value returned by _add_submit_parser().

Definition at line 445 of file cli.py.

445def _add_submit_parser(subparsers):
446 """!
447 @brief Perform add submit parser.
448 @param[in] subparsers Argument passed to `_add_submit_parser()`.
449 @return Value returned by `_add_submit_parser()`.
450 """
451 p_submit = subparsers.add_parser(
452 "submit",
453 help="Execute or submit previously staged artifacts from an existing run or study directory.",
454 formatter_class=argparse.RawTextHelpFormatter,
455 description=(
456 "Consume an existing artifact set created by picurv --no-submit and\n"
457 "execute/submit it later without regenerating configs or scripts.\n\n"
458 "Examples:\n"
459 " picurv submit --run-dir runs/my_run\n"
460 " picurv submit --run-dir runs/my_run --stage solve\n"
461 " picurv submit --study-dir studies/my_study --dry-run"
462 ),
463 epilog="Next: use `picurv summarize --run-dir ...` or `picurv cancel --run-dir ...` after submission as needed.",
464 )
465 target_group = p_submit.add_mutually_exclusive_group(required=True)
466 target_group.add_argument("--run-dir", help="Path to a staged run directory created by `picurv run ... --no-submit`.")
467 target_group.add_argument("--study-dir", help="Path to a staged study directory created by `picurv sweep --cluster ... --no-submit`.")
468 p_submit.add_argument(
469 "--stage",
470 choices=list(RUN_STAGE_CHOICES),
471 default="all",
472 help="Which staged job(s) to submit (default: all).",
473 )
474 p_submit.add_argument(
475 "--force",
476 action="store_true",
477 help="Allow re-submitting a stage already marked as submitted in scheduler/submission.json.",
478 )
479 p_submit.add_argument(
480 "--dry-run",
481 action="store_true",
482 help="Show which local command(s) or `sbatch` command(s) would run without starting anything.",
483 )
484 return p_submit
485
486
Here is the caller graph for this function:

◆ _add_init_parser()

picurv_cli.cli._add_init_parser (   subparsers)
protected

Perform add init parser.

Parameters
[in]subparsersArgument passed to _add_init_parser().
Returns
Value returned by _add_init_parser().

Definition at line 487 of file cli.py.

487def _add_init_parser(subparsers):
488 """!
489 @brief Perform add init parser.
490 @param[in] subparsers Argument passed to `_add_init_parser()`.
491 @return Value returned by `_add_init_parser()`.
492 """
493 p_init = subparsers.add_parser(
494 "init",
495 help="Initialize a new case study directory from a template.",
496 formatter_class=argparse.RawTextHelpFormatter,
497 description=(
498 "Create a study directory from examples/<template_name>.\n\n"
499 "Examples:\n"
500 " picurv init flat_channel --dest my_case\n"
501 " picurv init bent_channel --dest my_bent_case\n"
502 " picurv init decaying_isotropic_turbulence --dest dit_case"
503 ),
504 epilog="Next: run `picurv validate --case ... --solver ... --monitor ...` before execution.",
505 )
506 p_init.add_argument("template_name", help="Name of the case template directory to copy (e.g., 'flat_channel').")
507 p_init.add_argument(
508 "--dest",
509 dest="dest_name",
510 help="Optional name for the new directory. Defaults to the template name.\nPath is relative to your current working directory.",
511 )
512 p_init.add_argument(
513 "--source-root",
514 help="Optional override for the PICurv source repository root.\nUseful when running from a copied case without metadata.",
515 )
516 p_init.add_argument(
517 "--pin-binaries",
518 action="store_true",
519 default=False,
520 help="Copy simulator and postprocessor into the case directory.\nUse this to freeze specific binary versions for reproducibility\nor to protect running jobs from concurrent rebuilds.",
521 )
522 return p_init
523
524
Here is the caller graph for this function:

◆ _add_build_parser()

picurv_cli.cli._add_build_parser (   subparsers)
protected

Perform add build parser.

Parameters
[in]subparsersArgument passed to _add_build_parser().
Returns
Value returned by _add_build_parser().

Definition at line 525 of file cli.py.

525def _add_build_parser(subparsers):
526 """!
527 @brief Perform add build parser.
528 @param[in] subparsers Argument passed to `_add_build_parser()`.
529 @return Value returned by `_add_build_parser()`.
530 """
531 p_build = subparsers.add_parser(
532 "build",
533 help="Build project executables using the Makefile.",
534 formatter_class=argparse.RawTextHelpFormatter,
535 description=(
536 "Calls the project's Makefile directly through `make`.\n"
537 "If you do not pass an explicit make target, `picurv build` runs `make all`.\n"
538 "Any arguments provided after 'build' are passed directly to make.\n\n"
539 "Examples:\n"
540 " picurv build\n"
541 " picurv build clean-project\n"
542 " picurv build SYSTEM=cluster\n"
543 " picurv build all SYSTEM=cluster\n"
544 " picurv build postprocessor\n"
545 " ./picurv build clean-project # from an initialized case directory"
546 ),
547 epilog="Next: run `picurv --help` or `picurv run --help` for execution commands.",
548 )
549 p_build.add_argument(
550 "--source-root",
551 help="Optional override for the PICurv source repository root.",
552 )
553 p_build.add_argument(
554 "--case-dir",
555 help="Optional case directory used to resolve .picurv-origin.json when not running from that case.",
556 )
557 p_build.add_argument(
558 "make_args",
559 nargs=argparse.REMAINDER,
560 help="Arguments to pass directly to the make command (e.g., 'clean-project').",
561 )
562 return p_build
563
564
Here is the caller graph for this function:

◆ _add_sync_config_parser()

picurv_cli.cli._add_sync_config_parser (   subparsers)
protected

Perform add sync config parser.

Parameters
[in]subparsersArgument passed to _add_sync_config_parser().
Returns
Value returned by _add_sync_config_parser().

Definition at line 565 of file cli.py.

565def _add_sync_config_parser(subparsers):
566 """!
567 @brief Perform add sync config parser.
568 @param[in] subparsers Argument passed to `_add_sync_config_parser()`.
569 @return Value returned by `_add_sync_config_parser()`.
570 """
571 p_sync_config = subparsers.add_parser(
572 "sync-config",
573 help="Refresh template-managed files in a case directory from examples/<template>.",
574 formatter_class=argparse.RawTextHelpFormatter,
575 description=(
576 "Copy updated example template files into an existing case directory.\n"
577 "Modified files are preserved unless --overwrite is used.\n"
578 "--prune removes only files that were previously tracked as template-managed and\n"
579 "have since been removed from the source template.\n\n"
580 "Examples:\n"
581 " ./picurv sync-config\n"
582 " ./picurv sync-config --overwrite\n"
583 " ./picurv sync-config --prune\n"
584 " ./bin/picurv sync-config --case-dir my_case --template-name flat_channel"
585 ),
586 epilog="Next: run `picurv validate ...` after syncing configs.",
587 )
588 p_sync_config.add_argument("--case-dir", help="Optional case directory to refresh. Defaults to the current case.")
589 p_sync_config.add_argument("--source-root", help="Optional override for the PICurv source repository root.")
590 p_sync_config.add_argument(
591 "--template-name",
592 help="Optional template name override (e.g., flat_channel). Required when metadata is absent.",
593 )
594 p_sync_config.add_argument("--overwrite", action="store_true", help="Overwrite case files even when they differ from the template.")
595 p_sync_config.add_argument(
596 "--prune",
597 action="store_true",
598 help="Remove stale files that were previously tracked as template-managed but no longer exist in the source template.",
599 )
600 return p_sync_config
601
602
Here is the caller graph for this function:

◆ _add_pull_source_parser()

picurv_cli.cli._add_pull_source_parser (   subparsers)
protected

Perform add pull source parser.

Parameters
[in]subparsersArgument passed to _add_pull_source_parser().
Returns
Value returned by _add_pull_source_parser().

Definition at line 603 of file cli.py.

603def _add_pull_source_parser(subparsers):
604 """!
605 @brief Perform add pull source parser.
606 @param[in] subparsers Argument passed to `_add_pull_source_parser()`.
607 @return Value returned by `_add_pull_source_parser()`.
608 """
609 p_pull = subparsers.add_parser(
610 "pull-source",
611 help="Refresh source branches from an initialized case directory.",
612 formatter_class=argparse.RawTextHelpFormatter,
613 description=(
614 "Update the source repository without leaving an initialized case directory.\n\n"
615 "By default this refreshes every local branch that tracks an upstream,\n"
616 "then restores the branch you started on.\n\n"
617 "Examples:\n"
618 " ./picurv pull-source\n"
619 " ./picurv pull-source --current-branch-only\n"
620 " ./picurv pull-source --no-rebase\n"
621 " ./picurv pull-source --remote origin --branch main"
622 ),
623 epilog="Next: run `./picurv build` if source changes require rebuilt executables.",
624 )
625 p_pull.add_argument("--case-dir", help="Optional case directory used to resolve .picurv-origin.json.")
626 p_pull.add_argument("--source-root", help="Optional override for the PICurv source repository root.")
627 p_pull.add_argument("--remote", help="Optional git remote name (e.g., origin).")
628 p_pull.add_argument("--branch", help="Optional branch name. If provided without --remote, origin is assumed.")
629 p_pull.add_argument(
630 "--current-branch-only",
631 action="store_true",
632 help="Only pull the currently checked out branch instead of iterating across all local tracking branches.",
633 )
634 p_pull.add_argument("--no-rebase", action="store_true", help="Use plain git pull instead of git pull --rebase.")
635 return p_pull
636
637
Here is the caller graph for this function:

◆ _add_status_source_parser()

picurv_cli.cli._add_status_source_parser (   subparsers)
protected

Perform add status source parser.

Parameters
[in]subparsersArgument passed to _add_status_source_parser().
Returns
Value returned by _add_status_source_parser().

Definition at line 638 of file cli.py.

638def _add_status_source_parser(subparsers):
639 """!
640 @brief Perform add status source parser.
641 @param[in] subparsers Argument passed to `_add_status_source_parser()`.
642 @return Value returned by `_add_status_source_parser()`.
643 """
644 p_status = subparsers.add_parser(
645 "status-source",
646 help="Report source/case drift for an initialized case directory.",
647 formatter_class=argparse.RawTextHelpFormatter,
648 description=(
649 "Inspect whether the source repo, copied binaries, and template-managed files have drifted\n"
650 "from the current case directory.\n\n"
651 "Examples:\n"
652 " ./picurv status-source\n"
653 " ./picurv status-source --format json\n"
654 " ./bin/picurv status-source --case-dir my_case"
655 ),
656 epilog="Next: use `pull-source`, `build`, or `sync-config` based on the reported drift.",
657 )
658 p_status.add_argument("--case-dir", help="Optional case directory used to resolve .picurv-origin.json.")
659 p_status.add_argument("--source-root", help="Optional override for the PICurv source repository root.")
660 p_status.add_argument("--template-name", help="Optional template name override when metadata is absent.")
661 p_status.add_argument(
662 "--format",
663 dest="output_format",
664 choices=list(CLI_OUTPUT_FORMATS),
665 default="text",
666 help="Output format (default: text).",
667 )
668 return p_status
669
670
Here is the caller graph for this function:

◆ build_main_parser()

picurv_cli.cli.build_main_parser ( )

Build and return the top-level CLI parser.

Returns
Value returned by build_main_parser().

Definition at line 671 of file cli.py.

671def build_main_parser():
672 """!
673 @brief Build and return the top-level CLI parser.
674 @return Value returned by `build_main_parser()`.
675 """
676 parser = argparse.ArgumentParser(
677 description="picurv: A comprehensive conductor for the PICurv simulation platform.",
678 formatter_class=argparse.RawTextHelpFormatter,
679 epilog=(
680 "Examples:\n"
681 " picurv validate --case case.yml --solver solver.yml --monitor monitor.yml --post post.yml\n"
682 " picurv run --solve --post-process --case case.yml --solver solver.yml --monitor monitor.yml --post post.yml --dry-run\n"
683 " picurv run --solve --post-process --case case.yml --solver solver.yml --monitor monitor.yml --post post.yml --no-submit\n"
684 " picurv precompute --case config/case.yml --only grid,initial-condition\n"
685 " picurv run --post-process --continue --run-dir runs/my_run --post post.yml\n"
686 " picurv summarize --run-dir runs/my_run --latest\n"
687 " picurv summarize --run-dir runs/my_run --list-plot-series\n"
688 " picurv summarize --run-dir runs/my_run --plot momentum.residual_norm --last 100\n"
689 " picurv submit --run-dir runs/my_run\n"
690 " picurv cancel --run-dir runs/my_run\n"
691 " picurv cancel --run-dir runs/my_run --stage solve --graceful\n"
692 " picurv sweep --study study.yml --cluster cluster.yml\n\n"
693 "Next commands:\n"
694 " - First run: picurv init ... -> picurv validate ... -> picurv run ...\n"
695 " - Config debugging: picurv validate ...\n"
696 " - Artifact generation: picurv precompute ...\n"
697 " - Launch planning: picurv run ... --dry-run\n"
698 " - Post-only catch-up: picurv run --post-process --continue --run-dir ... --post ...\n"
699 " - Deferred submission: picurv submit --run-dir ...\n"
700 " - Run inspection/plots: picurv summarize ...\n"
701 " - Run cancellation: picurv cancel --run-dir ...; use --graceful for solver final-output shutdown"
702 ),
703 )
704 parser.add_argument("-v", "--version", action="version", version=f"picurv {PICURV_VERSION}")
705 subparsers = parser.add_subparsers(dest="command", required=True, help="Available commands")
706 _add_run_parser(subparsers)
707 _add_sweep_parser(subparsers)
708 _add_validate_parser(subparsers)
709 _add_precompute_parser(subparsers)
710 _add_inputs_parser(subparsers)
711 _add_summarize_parser(subparsers)
712 _add_submit_parser(subparsers)
713 _add_cancel_parser(subparsers)
714 _add_init_parser(subparsers)
715 _add_build_parser(subparsers)
716 _add_sync_config_parser(subparsers)
717 _add_pull_source_parser(subparsers)
718 _add_status_source_parser(subparsers)
719 _add_version_parsers(subparsers)
720 add_storage_parser(subparsers)
721 return parser
722
723
Here is the call graph for this function:

◆ dispatch_command()

picurv_cli.cli.dispatch_command (   args)

Validate argument combinations and dispatch to command handlers.

Parameters
[in]argsCommand-line style argument list supplied to the function.

Definition at line 724 of file cli.py.

724def dispatch_command(args):
725 """!
726 @brief Validate argument combinations and dispatch to command handlers.
727 @param[in] args Command-line style argument list supplied to the function.
728 """
729 if args.command == "run":
730 if not args.solve and not args.post_process:
731 fail_cli_usage("At least one stage (--solve or --post-process) must be selected.")
732 if args.solve and (not args.case or not args.solver or not args.monitor):
733 fail_cli_usage("--solve requires --case, --solver, and --monitor.")
734 if args.post_process and not args.post:
735 fail_cli_usage("--post-process requires --post.")
736 if getattr(args, "only", None) and not args.post_process:
737 fail_cli_usage("--only selects post-processing stages and requires --post-process.")
738 if args.scheduler and not args.cluster:
739 fail_cli_usage("--scheduler requires --cluster in this version.")
740 run_workflow(args)
741 return
742 if args.command == "sweep":
743 if args.continue_study:
744 if not args.study_dir:
745 fail_cli_usage("--continue requires --study-dir.")
746 sweep_continue_workflow(args)
747 return
748 if args.reaggregate:
749 if not args.study_dir:
750 fail_cli_usage("--reaggregate requires --study-dir.")
751 sweep_reaggregate_workflow(args)
752 return
753 # Default: launch new study
754 if not args.study:
755 fail_cli_usage("--study is required when launching a new sweep.")
756 if not args.cluster:
757 fail_cli_usage("--cluster is required when launching a new sweep.")
758 sweep_workflow(args)
759 return
760 if args.command == "validate":
761 validate_workflow(args)
762 return
763 if args.command == "precompute":
764 try:
765 precompute_workflow(args)
766 except ValueError as e:
767 emit_structured_error(
768 ERROR_CODE_CFG_INVALID_VALUE,
769 key="precompute",
770 file_path=getattr(args, "case", "-"),
771 message=str(e),
772 )
773 sys.exit(1)
774 return
775 if args.command == "inputs":
776 try:
777 inputs_workflow(args)
778 except ValueError as exc:
779 print(f"[FATAL] {exc}", file=sys.stderr)
780 sys.exit(1)
781 return
782 if args.command == "version":
783 version_workflow(args)
784 return
785 if args.command == "versions":
786 try:
787 versions_workflow(args)
788 except ValueError as exc:
789 print(f"[FATAL] {exc}", file=sys.stderr)
790 sys.exit(1)
791 return
792 if args.command == "source":
793 try:
794 source_workflow(args)
795 except ValueError as exc:
796 print(f"[FATAL] {exc}", file=sys.stderr)
797 sys.exit(1)
798 return
799 if args.command == "summarize":
800 summarize_workflow(args)
801 return
802 if args.command == "submit":
803 submit_staged_jobs(args)
804 return
805 if args.command == "cancel":
806 cancel_run_jobs(args)
807 return
808 if args.command == "init":
809 init_case(args)
810 return
811 if args.command == "build":
812 build_project(args)
813 return
814 if args.command == "sync-config":
815 sync_case_config_command(args)
816 return
817 if args.command == "pull-source":
818 pull_source_repo(args)
819 return
820 if args.command == "status-source":
821 status_source_command(args)
822 return
823 if args.command == "storage":
824 storage_workflow(args)
825 return
826 fail_cli_usage(f"Unsupported command '{args.command}'.")
Here is the call graph for this function:

Variable Documentation

◆ CLI_OUTPUT_FORMATS

tuple picurv_cli.cli.CLI_OUTPUT_FORMATS = ("text", "json")

Definition at line 12 of file cli.py.

◆ RUN_STAGE_CHOICES

tuple picurv_cli.cli.RUN_STAGE_CHOICES = ("all", "solve", "post-process")

Definition at line 15 of file cli.py.

◆ RESTART_STATISTICS_MODES

tuple picurv_cli.cli.RESTART_STATISTICS_MODES = ("reset", "carry")

Definition at line 18 of file cli.py.

◆ WORKSPACE_INPUT_KINDS

tuple picurv_cli.cli.WORKSPACE_INPUT_KINDS = ("grid", "initial-condition", "inlet-profile", "reference-field")

Definition at line 21 of file cli.py.

◆ WORKSPACE_INPUT_MODES

tuple picurv_cli.cli.WORKSPACE_INPUT_MODES = ("copy", "reflink", "hardlink", "reference")

Definition at line 24 of file cli.py.