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

Data Structures

class  _LazyVersionAction
 --version, resolving the build identity only when the flag is given. More...
 

Functions

 _add_executable_pinning_arguments (parser)
 Attach the executable-selection switches to a staging parser: pinning and index width.
 
 _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_executable_pinning_arguments()

picurv_cli.cli._add_executable_pinning_arguments (   parser)
protected

Attach the executable-selection switches to a staging parser: pinning and index width.

Unset pinning means the workspace's reproducibility.pin_executables decides; without it the run launches the installation's executables. Unset index width means the conductor chooses from the run's particle and grid sizes, or its restart source.

Parameters
[in]parserParser or argument group receiving the switches.
Returns
None.

Definition at line 27 of file cli.py.

27def _add_executable_pinning_arguments(parser):
28 """!
29 @brief Attach the executable-selection switches to a staging parser: pinning and index width.
30 @details Unset pinning means the workspace's `reproducibility.pin_executables` decides; without
31 it the run launches the installation's executables. Unset index width means the
32 conductor chooses from the run's particle and grid sizes, or its restart source.
33 @param[in] parser Parser or argument group receiving the switches.
34 @return None.
35 """
36 pinning = parser.add_mutually_exclusive_group()
37 pinning.add_argument(
38 "--pin-executables", dest="pin_executables", action="store_const", const=True, default=None,
39 help="Copy simulator and postprocessor into the run's config/bin/ at staging, so a later\n"
40 "rebuild of the installation cannot change what the job runs. On a pinned run,\n"
41 "re-pins it to the current build.",
42 )
43 pinning.add_argument(
44 "--no-pin-executables", dest="pin_executables", action="store_const", const=False,
45 help="Launch the installation's executables even when the workspace sets\n"
46 "reproducibility.pin_executables. Slurm jobs still check at start that they\n"
47 "report the build identity read at staging.",
48 )
49 parser.add_argument(
50 "--petsc-index-bits", dest="petsc_index_bits", choices=PETSC_INDEX_BITS_CHOICES, default=None,
51 help="Run on the 32- or 64-bit-index PETSc build (simulator64/postprocessor64, from\n"
52 "`make INDEX_BITS=64`). Default: 64 only when a particle or grid field outgrows\n"
53 "32-bit indices; a restart keeps its source's width. Also PICURV_PETSC_INDEX_BITS.",
54 )
55
56
Here is the caller graph for this function:

◆ _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 57 of file cli.py.

57def _add_run_parser(subparsers):
58 """!
59 @brief Attach `run` parser with staged execution and dry-run support.
60 @param[in] subparsers Argument passed to `_add_run_parser()`.
61 @return Value returned by `_add_run_parser()`.
62 """
63 p_run = subparsers.add_parser(
64 "run",
65 help="Execute a simulation workflow (solve and/or post-process).",
66 formatter_class=argparse.RawTextHelpFormatter,
67 description=(
68 "Execute solver and/or post-processing stages.\n\n"
69 "Notes:\n"
70 " - --num-procs applies to solver and post-processing stage launches.\n"
71 " - With --solve, --continue resumes the existing run directory in-place.\n"
72 " - --post-process processes only the steps whose output is missing or stale: no output,\n"
73 " a changed recipe, or a changed checkpoint. Steps without a committed checkpoint\n"
74 " wait for the solver. --recompute regenerates every step.\n\n"
75 "Diagnostics:\n"
76 " - PETSc and runtime memory diagnostics live under monitor.yml -> diagnostics.\n"
77 " - Use --dry-run to inspect resolved PETSc flags and expected log destinations.\n\n"
78 "Examples:\n"
79 " picurv run --solve -n 8 --case case.yml --solver solver.yml --monitor monitor.yml\n"
80 " picurv run --solve --restart-from runs/old_run --case case.yml --solver solver.yml --monitor monitor.yml\n"
81 " picurv run --solve --continue --run-dir runs/my_run --case case.yml --solver solver.yml --monitor monitor.yml\n"
82 " picurv run --post-process --run-dir runs/my_run --post post.yml\n"
83 " picurv run --post-process --recompute --run-dir runs/my_run --post post.yml\n"
84 " picurv run --solve --case case.yml --solver solver.yml --monitor monitor.yml --dry-run"
85 ),
86 epilog="Next: run `picurv validate ...` first for config-only checks.",
87 )
88 run_group = p_run.add_argument_group("stages")
89 run_group.add_argument("--solve", action="store_true", help="Execute the solver stage (creates a new run directory).")
90 run_group.add_argument("--post-process", action="store_true", help="Execute the post-processing stage on a run directory.")
91
92 solver_group = p_run.add_argument_group("solver inputs (required for --solve)")
93 solver_group.add_argument("--case", help="Path to the case definition file (e.g., case.yml).")
94 solver_group.add_argument("--solver", help="Path to the solver settings profile (e.g., solver.yml).")
95 solver_group.add_argument("--monitor", help="Path to the monitoring, diagnostics, and I/O profile (e.g., monitor.yml).")
96 solver_group.add_argument(
97 "--restart-from", "--from",
98 dest="restart_from",
99 help="Path to an existing run directory to restart from.\n"
100 "Use 'latest' to select the newest compatible local workspace run.",
101 )
102 solver_group.add_argument(
103 "--statistics-state",
104 choices=RESTART_STATISTICS_MODES,
105 default=None,
106 help="For a branched restart with field statistics enabled, this is required:\n"
107 "'reset' discards the parent's accumulated windows, 'carry' resumes compatible\n"
108 "saved window state. Ignored when field statistics are disabled.",
109 )
110 solver_group.add_argument(
111 "--require-precomputed",
112 action="store_true",
113 help="Refuse to build missing or stale deterministic assets while staging the run.",
114 )
115 solver_group.add_argument(
116 "--fetch-missing",
117 action="store_true",
118 help="Try the configured storage profile before rebuilding a missing workspace asset.",
119 )
120 run_group.add_argument(
121 "--continue",
122 action="store_true",
123 dest="continue_run",
124 help="Extend an existing run's solve in place. Requires --solve and --run-dir,\n"
125 "and start_step > 0; appends to existing solver output/logs.\n"
126 "Post-processing needs no flag: it always skips up-to-date steps.",
127 )
128
129 post_group = p_run.add_argument_group("post-processor inputs (required for --post-process)")
130 post_group.add_argument("--run-dir", help="Path to an existing run directory.\n(Used with --post-process or --solve --continue).")
131 post_group.add_argument("--post", help="Path to the post-processing recipe file (e.g., post.yml).")
132 post_group.add_argument(
133 "--only",
134 help="Comma-separated post stages to run: 'fields' (the field post-processor),\n"
135 "'spectra', and 'reducers' (the post.yml reducers tasks, on profiles the\n"
136 "field stage wrote). Defaults to every stage.\n"
137 "Use --only spectra to measure spectra without running the field stage.",
138 )
139 post_group.add_argument(
140 "--recompute",
141 action="store_true",
142 dest="recompute_post",
143 help="Regenerate every requested step that has a committed checkpoint, including\n"
144 "steps whose output is up to date (for example, after rebuilding the\n"
145 "postprocessor). Applies to every selected stage.",
146 )
147
148 p_run.add_argument(
149 "-n",
150 "--num-procs",
151 type=int,
152 default=None,
153 help="Number of MPI processes for solver and post-processing stages (default 1, or\n"
154 "the product of --ni --nj --nk). The decomposition is chosen from the grid and\n"
155 "its boundary conditions unless given.",
156 )
157 for axis in ("i", "j", "k"):
158 p_run.add_argument(
159 f"--n{axis}", type=int, default=None,
160 help=f"MPI ranks along the grid's {axis} axis. Give --ni, --nj and --nk together.",
161 )
162 p_run.add_argument("--cluster", help="Path to cluster.yml for Slurm execution mode.")
163 p_run.add_argument("--scheduler", help="Explicit scheduler selector (currently 'slurm').")
164 p_run.add_argument("--no-submit", action="store_true", help="Stage run artifacts without starting local execution or Slurm submission.")
165 _add_executable_pinning_arguments(p_run)
166 p_run.add_argument(
167 "--dry-run",
168 action="store_true",
169 help="Resolve and print planned commands/artifacts, including diagnostic flags and log paths, without writing files.",
170 )
171 p_run.add_argument(
172 "--format",
173 dest="output_format",
174 choices=list(CLI_OUTPUT_FORMATS),
175 default="text",
176 help="Output format for --dry-run (default: text).",
177 )
178 return p_run
179
180
Head of a generic C-style linked list.
Definition variables.h:518
Here is the call graph for this function:
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 181 of file cli.py.

181def _add_sweep_parser(subparsers):
182 """!
183 @brief Perform add sweep parser.
184 @param[in] subparsers Argument passed to `_add_sweep_parser()`.
185 @return Value returned by `_add_sweep_parser()`.
186 """
187 p_sweep = subparsers.add_parser(
188 "sweep",
189 help="Launch or continue a Slurm-based parameter sweep/study.",
190 formatter_class=argparse.RawTextHelpFormatter,
191 description=(
192 "Launch studies from study.yml + cluster.yml, whether the study uses\n"
193 "cross-product parameter combinations or explicit coupled parameter_sets, continue\n"
194 "partially-completed studies, or re-aggregate metrics.\n\n"
195 "Examples:\n"
196 " picurv sweep --study study.yml --cluster cluster.yml\n"
197 " picurv sweep --study study.yml --cluster cluster.yml --no-submit\n"
198 " picurv sweep --continue --study-dir studies/<id>\n"
199 " picurv sweep --continue --study-dir studies/<id> --cluster cluster_more_time.yml\n"
200 " picurv sweep --reaggregate --study-dir studies/<id>"
201 ),
202 epilog=(
203 "Study files support either `parameters` cross-product expansion or explicit `parameter_sets`.\n"
204 "Next: inspect studies/<study_id>/output/analysis/metrics_table.csv for aggregated metrics."
205 ),
206 )
207 p_sweep.add_argument("--study", help="Path to study.yml defining either a `parameters` cross-product expansion or explicit parameter_sets, plus metrics.")
208 p_sweep.add_argument("--cluster", help="Path to cluster.yml defining Slurm resources.")
209 p_sweep.add_argument("--no-submit", action="store_true", help="Generate all study artifacts without submitting jobs.")
210 _add_executable_pinning_arguments(p_sweep)
211 p_sweep.add_argument("--study-dir", help="Path to an existing study directory (for --continue/--reaggregate).")
212 p_sweep.add_argument("--continue", action="store_true", dest="continue_study",
213 help="Continue a partially-completed study. Requires --study-dir.")
214 p_sweep.add_argument("--reaggregate", action="store_true",
215 help="Re-run metrics aggregation on a completed study. Requires --study-dir.")
216 p_sweep.add_argument("--auto-fetch", action="store_true",
217 help="Restore cold-storage study members automatically instead of\n"
218 "refusing. Requires a configured storage profile.")
219 return p_sweep
220
221
Here is the call graph for this function:
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 253 of file cli.py.

253def _add_validate_parser(subparsers):
254 """!
255 @brief Perform add validate parser.
256 @param[in] subparsers Argument passed to `_add_validate_parser()`.
257 @return Value returned by `_add_validate_parser()`.
258 """
259 p_validate = subparsers.add_parser(
260 "validate",
261 help="Validate config files without launching solver/post.",
262 formatter_class=argparse.RawTextHelpFormatter,
263 description=(
264 "Validate one or more config roles. No solver/post execution and no run/study artifact writes.\n\n"
265 "Examples:\n"
266 " picurv validate --case case.yml --solver solver.yml --monitor monitor.yml\n"
267 " picurv validate --post post.yml --cluster cluster.yml\n"
268 " picurv validate --study study.yml --cluster cluster.yml --strict"
269 ),
270 epilog="Next: run `picurv run --dry-run ...` to inspect resolved commands/artifacts.",
271 )
272 p_validate.add_argument("--case", help="Path to case.yml")
273 p_validate.add_argument("--solver", help="Path to solver.yml")
274 p_validate.add_argument("--monitor", help="Path to monitor.yml (logging, diagnostics, profiling, and I/O)")
275 p_validate.add_argument("--restart-from", "--from", dest="restart_from",
276 help="Path to a run directory to validate restart from.")
277 p_validate.add_argument("--continue", action="store_true", dest="continue_run", help="Validate continue-in-place mode. Requires --run-dir.")
278 p_validate.add_argument("--run-dir", help="Path to an existing run directory (for --continue validation).")
279 p_validate.add_argument("--post", help="Path to post.yml")
280 p_validate.add_argument("--cluster", help="Path to cluster.yml")
281 p_validate.add_argument("--study", help="Path to study.yml")
282 p_validate.add_argument("--strict", action="store_true", help="Enable additional strict checks for selected roles.")
283 return p_validate
284
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 285 of file cli.py.

285def _add_precompute_parser(subparsers):
286 """!
287 @brief Attach `precompute` parser for deterministic artifact generation.
288 @param[in] subparsers Argument passed to `_add_precompute_parser()`.
289 @return Configured parser.
290 """
291 p_precompute = subparsers.add_parser(
292 "precompute",
293 help="Generate deterministic case artifacts without launching the solver.",
294 formatter_class=argparse.RawTextHelpFormatter,
295 description=(
296 "Generate configured deterministic artifacts, such as grid_gen grids,\n"
297 "generated prescribed-flow inlet profiles, and ic_gen initial conditions,\n"
298 "as immutable objects in the initialized workspace asset store.\n\n"
299 "Examples:\n"
300 " picurv precompute --case config/case.yml\n"
301 " picurv precompute --case config/case.yml --only grid,initial-condition"
302 ),
303 epilog="Next: inspect the reported asset set, then stage a run that reuses it.",
304 )
305 p_precompute.add_argument("--case", required=True, help="Path to case.yml containing grid/profile/IC generator settings.")
306 p_precompute.add_argument(
307 "--only",
308 default="all",
309 help="Comma-separated asset kinds (grid, initial-condition, inlet-profiles), or all.",
310 )
311 return p_precompute
312
313
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 314 of file cli.py.

314def _add_inputs_parser(subparsers):
315 """!
316 @brief Attach explicit workspace input-ingress commands.
317 @param[in] subparsers Top-level argparse subparser collection.
318 @return Configured inputs command parser.
319 """
320 parser = subparsers.add_parser(
321 "inputs",
322 help="Import or register files used by workspace configurations.",
323 formatter_class=argparse.RawTextHelpFormatter,
324 )
325 actions = parser.add_subparsers(dest="inputs_action", required=True)
326 p_import = actions.add_parser("import", help="Import one external file into its canonical workspace home.")
327 p_import.add_argument(
328 "kind",
329 choices=WORKSPACE_INPUT_KINDS,
330 )
331 p_import.add_argument("source", help="Existing source file.")
332 p_import.add_argument("--name", help="Destination name; defaults to the source basename.")
333 p_import.add_argument(
334 "--mode", choices=WORKSPACE_INPUT_MODES, default="copy",
335 help="How to retain the input. Reference mode records but does not copy an external path.",
336 )
337 p_import.add_argument("--workspace", help="Workspace root; defaults to discovery from the current directory.")
338 return parser
339
340
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 341 of file cli.py.

341def _add_version_parsers(subparsers):
342 """!
343 @brief Attach unified source/build/workspace-version commands.
344 @param[in] subparsers Top-level argparse subparser collection.
345 @return Version, versions, and source command parsers.
346 """
347 p_version = subparsers.add_parser(
348 "version",
349 help="Report the build identity of the conductor and every native executable.",
350 formatter_class=argparse.RawTextHelpFormatter,
351 description=(
352 "Report the build identity shared by the Python conductor and the native\n"
353 "executables, plus any workspace version requirement.\n\n"
354 "With the 'status' action this also validates that they agree, and exits 1\n"
355 "when they do not, so a job script can refuse an incoherent build.\n\n"
356 "Examples:\n"
357 " picurv version\n"
358 " picurv version status\n"
359 " picurv version status --format json"
360 ),
361 )
362 p_version.add_argument(
363 "version_action", nargs="?", choices=["status"], default=None,
364 help="'status' validates conductor/executable/workspace coherence and exits 1 on disagreement.",
365 )
366 p_version.add_argument("--format", dest="output_format", choices=list(CLI_OUTPUT_FORMATS), default="text",
367 help="Output format (default: text).")
368
369 p_versions = subparsers.add_parser("versions", help="List, install, or activate PICurv source versions.")
370 actions = p_versions.add_subparsers(dest="versions_action", required=True)
371 actions.add_parser("list", help="List local Git tags and the active build.")
372 p_install = actions.add_parser("install", help="Fetch a named version and build it in the source checkout.")
373 p_install.add_argument("version", help="Tag, bare release (resolved to v<release>), or commit.")
374 p_activate = actions.add_parser("activate", help="Checkout and build the version required by this workspace.")
375 p_activate.add_argument("version", nargs="?", help="Version/tag; defaults to the workspace requirement.")
376 p_activate.add_argument("--workspace", help="Workspace root; defaults to discovery from the current directory.")
377 for parser in (p_install, p_activate):
378 parser.add_argument(
379 "make_args", nargs=argparse.REMAINDER,
380 help="Make variables passed to the build, as with 'picurv build' (for example "
381 "SYSTEM=cluster); make options go after '--'. Place them after every picurv option.",
382 )
383
384 p_source = subparsers.add_parser("source", help="Manage the source checkout used by PICurv.")
385 source_actions = p_source.add_subparsers(dest="source_action", required=True)
386 p_update = source_actions.add_parser("update", help="Fetch source updates without changing the active version.")
387 p_update.add_argument("--remote", default="origin", help="Git remote to fetch from (default: origin).")
388 return p_version, p_versions, p_source
389
390
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 391 of file cli.py.

391def _add_summarize_parser(subparsers):
392 """!
393 @brief Attach `summarize` parser for read-only run-health views.
394 @param[in] subparsers Argument passed to `_add_summarize_parser()`.
395 @return Value returned by `_add_summarize_parser()`.
396 """
397 p_summarize = subparsers.add_parser(
398 "summarize",
399 help="Summarize run configs/health and plot scalar log histories.",
400 formatter_class=argparse.RawTextHelpFormatter,
401 description=(
402 "Build read-only configuration overviews, run-health summaries, and scalar time-history plots.\n"
403 "It does not modify solver output and works for active or completed runs.\n\n"
404 "Examples:\n"
405 " picurv summarize --run-dir runs/my_run --overview\n"
406 " picurv summarize --run-dir runs/my_run --case --solver\n"
407 " picurv summarize --run-dir runs/my_run --latest\n"
408 " picurv summarize --run-dir runs/my_run --monitor --step 500\n"
409 " picurv summarize --run-dir runs/my_run --list-plot-series\n"
410 " picurv summarize --run-dir runs/my_run --plot momentum.residual_norm --last 100\n"
411 " picurv summarize --run-dir runs/my_run --table poisson --last 10\n"
412 " picurv summarize --run-dir runs/my_run --latest --format json"
413 ),
414 epilog="Next: use `picurv run ...` to create runs or `picurv sweep ...` for multi-case studies.",
415 )
416 p_summarize.add_argument("--run-dir", required=True, help="Path to the run directory to inspect.")
417 p_summarize.add_argument(
418 "--overview",
419 action="store_true",
420 help="Summarize run metadata plus copied case, solver, and monitor configs without implicitly requesting health.",
421 )
422 p_summarize.add_argument("--case", action="store_true", help="Summarize the copied run-local case.yml.")
423 p_summarize.add_argument("--solver", action="store_true", help="Summarize the copied run-local solver.yml.")
424 p_summarize.add_argument("--monitor", action="store_true", help="Summarize the copied run-local monitor.yml.")
425 plot_group = p_summarize.add_mutually_exclusive_group()
426 plot_group.add_argument(
427 "--list-plot-series",
428 dest="list_plot_series",
429 action="store_true",
430 help="List scalar histories available to --plot.",
431 )
432 plot_group.add_argument(
433 "--list-series",
434 dest="list_plot_series",
435 action="store_true",
436 help=argparse.SUPPRESS,
437 )
438 plot_group.add_argument(
439 "--plot",
440 dest="plot_series",
441 help="Plot one qualified scalar history, such as momentum.residual_norm (requires matplotlib).",
442 )
443 plot_group.add_argument(
444 "--plot-spectrum",
445 dest="plot_spectrum",
446 nargs="?",
447 const="",
448 help="Plot up to six representative measured energy spectra, including the first\n"
449 "and last states, overlaid on the initial-condition spectrum. Takes an optional\n"
450 "task-name substring when the recipe measured more than one spectrum\n"
451 "(requires matplotlib).",
452 )
453 plot_group.add_argument(
454 "--table",
455 dest="table",
456 help="Print the last rows of one of the run's CSV records as aligned columns, such as\n"
457 "continuity, poisson, search or memory; a per-block record takes ':<block>'.",
458 )
459 plot_group.add_argument(
460 "--list-tables",
461 dest="list_tables",
462 action="store_true",
463 help="List the CSV records this run has, for --table.",
464 )
465 p_summarize.add_argument("--columns", dest="table_columns",
466 help="With --table: comma-separated columns to show (the first column is always kept).")
467 p_summarize.add_argument("--last", dest="last_n", type=int,
468 help="With --plot: only the last N chronological records per line.\n"
469 "With --table: the last N rows (default 20).")
470 p_summarize.add_argument("--plot-output", help="Save the plot to this path instead of opening an interactive window.")
471 p_summarize.add_argument("--linear-y", action="store_true", help="Force linear y-axis scaling instead of automatic residual/norm log scaling.")
472 step_group = p_summarize.add_mutually_exclusive_group()
473 step_group.add_argument("--step", type=int, help="Specific completed timestep to summarize.")
474 step_group.add_argument(
475 "--latest",
476 action="store_true",
477 help="Summarize the most recently appended completed step found in available artifacts (default behavior).",
478 )
479 step_group.add_argument(
480 "--max-step",
481 action="store_true",
482 help="Summarize the numerically largest timestep found in available artifacts.",
483 )
484 p_summarize.add_argument(
485 "--snapshot-rows",
486 type=int,
487 default=5,
488 help="Number of sampled particle snapshot rows to preview when solver stream output contains them.",
489 )
490 p_summarize.add_argument(
491 "--format",
492 dest="output_format",
493 choices=list(CLI_OUTPUT_FORMATS),
494 default="text",
495 help="Output format (default: text).",
496 )
497 return p_summarize
498
499
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 500 of file cli.py.

500def _add_cancel_parser(subparsers):
501 """!
502 @brief Perform add cancel parser.
503 @param[in] subparsers Argument passed to `_add_cancel_parser()`.
504 @return Value returned by `_add_cancel_parser()`.
505 """
506 p_cancel = subparsers.add_parser(
507 "cancel",
508 help="Cancel Slurm-submitted jobs for an existing run directory.",
509 formatter_class=argparse.RawTextHelpFormatter,
510 description=(
511 "Look up scheduler/submission.json inside an existing run directory and cancel\n"
512 "the recorded Slurm job(s) without requiring manual job-id lookup.\n\n"
513 "Examples:\n"
514 " picurv cancel --run-dir runs/my_run\n"
515 " picurv cancel --run-dir runs/my_run --stage solve\n"
516 " picurv cancel --run-dir runs/my_run --stage solve --graceful\n"
517 " picurv cancel --run-dir runs/my_run --dry-run\n\n"
518 "Default cancellation is a hard Slurm cancel (`scancel <job_id>`). With\n"
519 "`--graceful`, Slurm sends SIGUSR1 to the solver process tree so PICurv can write the latest\n"
520 "safe off-cadence step at the next runtime checkpoint before exiting.\n"
521 "Post-process jobs still use ordinary hard cancellation."
522 ),
523 epilog="Next: use `picurv summarize --run-dir ...` to inspect whatever output the run already produced.",
524 )
525 p_cancel.add_argument("--run-dir", required=True, help="Path to the run directory whose Slurm job(s) should be canceled.")
526 p_cancel.add_argument(
527 "--stage",
528 choices=list(RUN_STAGE_CHOICES),
529 default="all",
530 help="Which recorded stage job(s) to cancel (default: all).",
531 )
532 p_cancel.add_argument(
533 "--dry-run",
534 action="store_true",
535 help="Show which `scancel` command(s) would run without actually canceling anything.",
536 )
537 p_cancel.add_argument(
538 "--graceful",
539 action="store_true",
540 help=(
541 "For solver jobs, request a clean runtime shutdown by sending SIGUSR1 to the process tree instead of "
542 "hard-canceling immediately. The solver writes the latest safe off-cadence step at "
543 "the next checkpoint. Non-solver stages still use ordinary scancel."
544 ),
545 )
546 return p_cancel
547
548
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 549 of file cli.py.

549def _add_submit_parser(subparsers):
550 """!
551 @brief Perform add submit parser.
552 @param[in] subparsers Argument passed to `_add_submit_parser()`.
553 @return Value returned by `_add_submit_parser()`.
554 """
555 p_submit = subparsers.add_parser(
556 "submit",
557 help="Execute or submit previously staged artifacts from an existing run or study directory.",
558 formatter_class=argparse.RawTextHelpFormatter,
559 description=(
560 "Consume an existing artifact set created by 'picurv run ... --no-submit' or\n"
561 "'picurv sweep ... --no-submit' and execute/submit it later without\n"
562 "regenerating configs or scripts.\n"
563 "A post-process job decides when it starts which steps need work, so\n"
564 "submitting it again skips output that is already up to date.\n\n"
565 "Examples:\n"
566 " picurv submit --run-dir runs/my_run\n"
567 " picurv submit --run-dir runs/my_run --stage solve\n"
568 " picurv submit --study-dir studies/my_study --dry-run"
569 ),
570 epilog="Next: use `picurv summarize --run-dir ...` or `picurv cancel --run-dir ...` after submission as needed.",
571 )
572 target_group = p_submit.add_mutually_exclusive_group(required=True)
573 target_group.add_argument("--run-dir", help="Path to a staged run directory created by `picurv run ... --no-submit`.")
574 target_group.add_argument("--study-dir", help="Path to a staged study directory created by `picurv sweep --cluster ... --no-submit`.")
575 p_submit.add_argument(
576 "--stage",
577 choices=list(RUN_STAGE_CHOICES),
578 default="all",
579 help="Which staged job(s) to submit (default: all, every stage the target staged).",
580 )
581 p_submit.add_argument(
582 "--force",
583 action="store_true",
584 help="Allow re-submitting a stage already marked as submitted in scheduler/submission.json.",
585 )
586 p_submit.add_argument(
587 "--dry-run",
588 action="store_true",
589 help="Show which local command(s) or `sbatch` command(s) would run without starting anything.",
590 )
591 return p_submit
592
593
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 594 of file cli.py.

594def _add_init_parser(subparsers):
595 """!
596 @brief Perform add init parser.
597 @param[in] subparsers Argument passed to `_add_init_parser()`.
598 @return Value returned by `_add_init_parser()`.
599 """
600 p_init = subparsers.add_parser(
601 "init",
602 help="Initialize a new case workspace from a template.",
603 formatter_class=argparse.RawTextHelpFormatter,
604 description=(
605 "Create a case workspace from examples/<template_name>.\n\n"
606 "Examples:\n"
607 " picurv init flat_channel --dest my_case\n"
608 " picurv init bent_channel --dest my_bent_case\n"
609 " picurv init decaying_isotropic_turbulence --dest dit_case"
610 ),
611 epilog="Next: run `picurv validate --case ... --solver ... --monitor ...` before execution.",
612 )
613 p_init.add_argument("template_name", help="Name of the case template directory to copy (e.g., 'flat_channel').")
614 p_init.add_argument(
615 "--dest",
616 dest="dest_name",
617 help="Optional name for the new directory. Defaults to the template name.\nPath is relative to your current working directory.",
618 )
619 p_init.add_argument(
620 "--source-root",
621 help="Optional override for the PICurv source repository root.\nUseful when running from a copied case without metadata.",
622 )
623 p_init.add_argument(
624 "--pin-binaries",
625 action="store_true",
626 default=False,
627 help="(Legacy) Copy simulator and postprocessor into the case directory, used only when\n"
628 "that directory's own picurv is invoked. To freeze the executables a run uses,\n"
629 "use 'picurv run --pin-executables'.",
630 )
631 return p_init
632
633
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 634 of file cli.py.

634def _add_build_parser(subparsers):
635 """!
636 @brief Perform add build parser.
637 @param[in] subparsers Argument passed to `_add_build_parser()`.
638 @return Value returned by `_add_build_parser()`.
639 """
640 p_build = subparsers.add_parser(
641 "build",
642 help="Build project executables using the Makefile.",
643 formatter_class=argparse.RawTextHelpFormatter,
644 description=(
645 "Calls the project's Makefile directly through `make`.\n"
646 "If you do not pass an explicit make target, `picurv build` runs `make all`.\n"
647 "Targets and variables after 'build' are passed directly to make; make options\n"
648 "such as -j8 go after '--'.\n\n"
649 "Examples:\n"
650 " picurv build\n"
651 " picurv build clean-project\n"
652 " picurv build SYSTEM=cluster\n"
653 " picurv build all SYSTEM=cluster\n"
654 " picurv build postprocessor\n"
655 " picurv build -- -j8 all\n"
656 " picurv build INDEX_BITS=64 PETSC_DIR=$HOME/sw/petsc-int64 # simulator64/postprocessor64\n"
657 " ./picurv build clean-project # from an initialized case directory"
658 ),
659 epilog="Next: run `picurv --help` or `picurv run --help` for execution commands.",
660 )
661 p_build.add_argument(
662 "--source-root",
663 help="Optional override for the PICurv source repository root.",
664 )
665 p_build.add_argument(
666 "--case-dir",
667 help="Optional case directory used to resolve .picurv-origin.json when not running from that case.",
668 )
669 p_build.add_argument(
670 "make_args",
671 nargs=argparse.REMAINDER,
672 help="Targets and variables passed to make (e.g., 'clean-project'); make options go after '--'.",
673 )
674 return p_build
675
676
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 677 of file cli.py.

677def _add_sync_config_parser(subparsers):
678 """!
679 @brief Perform add sync config parser.
680 @param[in] subparsers Argument passed to `_add_sync_config_parser()`.
681 @return Value returned by `_add_sync_config_parser()`.
682 """
683 p_sync_config = subparsers.add_parser(
684 "sync-config",
685 help="Refresh template-managed files in a case directory from examples/<template>.",
686 formatter_class=argparse.RawTextHelpFormatter,
687 description=(
688 "Copy updated example template files into an existing case directory.\n"
689 "Modified files are preserved unless --overwrite is used.\n"
690 "--prune removes only files that were previously tracked as template-managed and\n"
691 "have since been removed from the source template.\n\n"
692 "Examples:\n"
693 " ./picurv sync-config\n"
694 " ./picurv sync-config --overwrite\n"
695 " ./picurv sync-config --prune\n"
696 " ./bin/picurv sync-config --case-dir my_case --template-name flat_channel"
697 ),
698 epilog="Next: run `picurv validate ...` after syncing configs.",
699 )
700 p_sync_config.add_argument("--case-dir", help="Optional case directory to refresh. Defaults to the current case.")
701 p_sync_config.add_argument("--source-root", help="Optional override for the PICurv source repository root.")
702 p_sync_config.add_argument(
703 "--template-name",
704 help="Optional template name override (e.g., flat_channel). Required when metadata is absent.",
705 )
706 p_sync_config.add_argument("--overwrite", action="store_true", help="Overwrite case files even when they differ from the template.")
707 p_sync_config.add_argument(
708 "--prune",
709 action="store_true",
710 help="Remove stale files that were previously tracked as template-managed but no longer exist in the source template.",
711 )
712 return p_sync_config
713
714
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 715 of file cli.py.

715def _add_pull_source_parser(subparsers):
716 """!
717 @brief Perform add pull source parser.
718 @param[in] subparsers Argument passed to `_add_pull_source_parser()`.
719 @return Value returned by `_add_pull_source_parser()`.
720 """
721 p_pull = subparsers.add_parser(
722 "pull-source",
723 help="(Legacy; use 'source update') Refresh source branches from a case directory.",
724 formatter_class=argparse.RawTextHelpFormatter,
725 description=(
726 "Legacy maintenance command; new workspaces use `picurv source update` and\n"
727 "`picurv versions`. Updates the source repository without leaving an\n"
728 "initialized case directory.\n\n"
729 "By default this refreshes every local branch that tracks an upstream,\n"
730 "then restores the branch you started on.\n\n"
731 "Examples:\n"
732 " ./picurv pull-source\n"
733 " ./picurv pull-source --current-branch-only\n"
734 " ./picurv pull-source --no-rebase\n"
735 " ./picurv pull-source --remote origin --branch main"
736 ),
737 epilog="Next: run `./picurv build` if source changes require rebuilt executables.",
738 )
739 p_pull.add_argument("--case-dir", help="Optional case directory used to resolve .picurv-origin.json.")
740 p_pull.add_argument("--source-root", help="Optional override for the PICurv source repository root.")
741 p_pull.add_argument("--remote", help="Optional git remote name (e.g., origin).")
742 p_pull.add_argument("--branch", help="Optional branch name. If provided without --remote, origin is assumed.")
743 p_pull.add_argument(
744 "--current-branch-only",
745 action="store_true",
746 help="Only pull the currently checked out branch instead of iterating across all local tracking branches.",
747 )
748 p_pull.add_argument("--no-rebase", action="store_true", help="Use plain git pull instead of git pull --rebase.")
749 return p_pull
750
751
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 752 of file cli.py.

752def _add_status_source_parser(subparsers):
753 """!
754 @brief Perform add status source parser.
755 @param[in] subparsers Argument passed to `_add_status_source_parser()`.
756 @return Value returned by `_add_status_source_parser()`.
757 """
758 p_status = subparsers.add_parser(
759 "status-source",
760 help="(Legacy; use 'version status') Report source/case drift for a case directory.",
761 formatter_class=argparse.RawTextHelpFormatter,
762 description=(
763 "Legacy maintenance command; `picurv version status` reports build coherence for\n"
764 "new workspaces. Inspects whether the source repo, copied binaries, and template-managed files have drifted\n"
765 "from the current case directory.\n\n"
766 "Examples:\n"
767 " ./picurv status-source\n"
768 " ./picurv status-source --format json\n"
769 " ./bin/picurv status-source --case-dir my_case"
770 ),
771 epilog="Next: use `source update`, `build`, or `sync-config` based on the reported drift.",
772 )
773 p_status.add_argument("--case-dir", help="Optional case directory used to resolve .picurv-origin.json.")
774 p_status.add_argument("--source-root", help="Optional override for the PICurv source repository root.")
775 p_status.add_argument("--template-name", help="Optional template name override when metadata is absent.")
776 p_status.add_argument(
777 "--format",
778 dest="output_format",
779 choices=list(CLI_OUTPUT_FORMATS),
780 default="text",
781 help="Output format (default: text).",
782 )
783 return p_status
784
785
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 786 of file cli.py.

786def build_main_parser():
787 """!
788 @brief Build and return the top-level CLI parser.
789 @return Value returned by `build_main_parser()`.
790 """
791 parser = argparse.ArgumentParser(
792 description="picurv: A comprehensive conductor for the PICurv simulation platform.",
793 formatter_class=argparse.RawTextHelpFormatter,
794 epilog=(
795 "Examples:\n"
796 " picurv validate --case case.yml --solver solver.yml --monitor monitor.yml --post post.yml\n"
797 " picurv run --solve --post-process --case case.yml --solver solver.yml --monitor monitor.yml --post post.yml --dry-run\n"
798 " picurv run --solve --post-process --case case.yml --solver solver.yml --monitor monitor.yml --post post.yml --no-submit\n"
799 " picurv precompute --case config/case.yml --only grid,initial-condition\n"
800 " picurv run --post-process --run-dir runs/my_run --post post.yml\n"
801 " picurv summarize --run-dir runs/my_run --latest\n"
802 " picurv summarize --run-dir runs/my_run --list-plot-series\n"
803 " picurv summarize --run-dir runs/my_run --plot momentum.residual_norm --last 100\n"
804 " picurv submit --run-dir runs/my_run\n"
805 " picurv cancel --run-dir runs/my_run\n"
806 " picurv cancel --run-dir runs/my_run --stage solve --graceful\n"
807 " picurv sweep --study study.yml --cluster cluster.yml\n\n"
808 "Next commands:\n"
809 " - First run: picurv init ... -> picurv validate ... -> picurv run ...\n"
810 " - Config debugging: picurv validate ...\n"
811 " - Artifact generation: picurv precompute ...\n"
812 " - Launch planning: picurv run ... --dry-run\n"
813 " - Post-only catch-up: picurv run --post-process --run-dir ... --post ...\n"
814 " - Deferred submission: picurv submit --run-dir ...\n"
815 " - Run inspection/plots: picurv summarize ...\n"
816 " - Run cancellation: picurv cancel --run-dir ...; use --graceful for solver final-output shutdown"
817 ),
818 )
819 parser.add_argument(
820 "-v", "--version", action=_LazyVersionAction,
821 help="Print the conductor's build identity and exit. 'picurv version' also reports\n"
822 "each native executable and the PETSc it uses.",
823 )
824 subparsers = parser.add_subparsers(dest="command", required=True, help="Available commands")
825 _add_run_parser(subparsers)
826 _add_sweep_parser(subparsers)
827 _add_validate_parser(subparsers)
828 _add_precompute_parser(subparsers)
829 _add_inputs_parser(subparsers)
830 _add_summarize_parser(subparsers)
831 _add_submit_parser(subparsers)
832 _add_cancel_parser(subparsers)
833 _add_init_parser(subparsers)
834 _add_build_parser(subparsers)
835 _add_sync_config_parser(subparsers)
836 _add_pull_source_parser(subparsers)
837 _add_status_source_parser(subparsers)
838 _add_version_parsers(subparsers)
839 add_storage_parser(subparsers)
840 return parser
841
842
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 843 of file cli.py.

843def dispatch_command(args):
844 """!
845 @brief Validate argument combinations and dispatch to command handlers.
846 @param[in] args Command-line style argument list supplied to the function.
847 """
848 if args.command == "run":
849 if not args.solve and not args.post_process:
850 fail_cli_usage("At least one stage (--solve or --post-process) must be selected.")
851 if args.solve and (not args.case or not args.solver or not args.monitor):
852 fail_cli_usage("--solve requires --case, --solver, and --monitor.")
853 if args.post_process and not args.post:
854 fail_cli_usage("--post-process requires --post.")
855 if args.post_process and not args.solve and not args.run_dir:
856 fail_cli_usage("--post-process requires --run-dir when not used with --solve.")
857 if args.continue_run and not args.run_dir:
858 fail_cli_usage(RESTART_RUN_DIR_REQUIRED_MESSAGE)
859 if getattr(args, "only", None) and not args.post_process:
860 fail_cli_usage("--only selects post-processing stages and requires --post-process.")
861 try:
862 resolve_post_stage_selection(getattr(args, "only", None))
863 except ValueError as exc:
864 fail_cli_usage(str(exc))
865 if getattr(args, "recompute_post", False) and not args.post_process:
866 fail_cli_usage("--recompute regenerates post-processing output and requires --post-process.")
867 if args.scheduler and not args.cluster:
868 fail_cli_usage("--scheduler requires --cluster in this version.")
869 normalize_decomposition_args(args)
870 run_workflow(args)
871 return
872 if args.command == "sweep":
873 if args.continue_study:
874 if not args.study_dir:
875 fail_cli_usage("--continue requires --study-dir.")
876 sweep_continue_workflow(args)
877 return
878 if args.reaggregate:
879 if not args.study_dir:
880 fail_cli_usage("--reaggregate requires --study-dir.")
881 sweep_reaggregate_workflow(args)
882 return
883 # Default: launch new study
884 if not args.study:
885 fail_cli_usage("--study is required when launching a new sweep.")
886 if not args.cluster:
887 fail_cli_usage("--cluster is required when launching a new sweep.")
888 sweep_workflow(args)
889 return
890 if args.command == "validate":
891 validate_workflow(args)
892 return
893 if args.command == "precompute":
894 try:
895 precompute_workflow(args)
896 except ValueError as e:
897 emit_structured_error(
898 ERROR_CODE_CFG_INVALID_VALUE,
899 key="precompute",
900 file_path=getattr(args, "case", "-"),
901 message=str(e),
902 hint="'picurv precompute --help' lists the asset kinds --only accepts.",
903 )
904 sys.exit(1)
905 return
906 if args.command == "inputs":
907 try:
908 inputs_workflow(args)
909 except ValueError as exc:
910 print(f"[FATAL] {exc}", file=sys.stderr)
911 sys.exit(1)
912 return
913 if args.command == "version":
914 version_workflow(args)
915 return
916 if args.command == "versions":
917 try:
918 versions_workflow(args)
919 except ValueError as exc:
920 print(f"[FATAL] {exc}", file=sys.stderr)
921 sys.exit(1)
922 return
923 if args.command == "source":
924 try:
925 source_workflow(args)
926 except ValueError as exc:
927 print(f"[FATAL] {exc}", file=sys.stderr)
928 sys.exit(1)
929 return
930 if args.command == "summarize":
931 summarize_workflow(args)
932 return
933 if args.command == "submit":
934 submit_staged_jobs(args)
935 return
936 if args.command == "cancel":
937 cancel_run_jobs(args)
938 return
939 if args.command == "init":
940 init_case(args)
941 return
942 if args.command == "build":
943 build_project(args)
944 return
945 if args.command == "sync-config":
946 sync_case_config_command(args)
947 return
948 if args.command == "pull-source":
949 pull_source_repo(args)
950 return
951 if args.command == "status-source":
952 status_source_command(args)
953 return
954 if args.command == "storage":
955 storage_workflow(args)
956 return
957 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.