Python Input File Support - #1386
Draft
lroberts36 wants to merge 13 commits into
Draft
Conversation
lroberts36
added a commit
that referenced
this pull request
Apr 10, 2026
Collaborator
Author
|
@par-hermes format |
Adds Python bindings and input file support building on core
ParameterInput refactoring.
Features:
- Python bindings for typed parameter input (add_* methods only)
- InputFile class for programmatic input generation
- Command line argument parsing in Python scripts
- MPI rank detection and mpi_print helper
- Example Python input file for fine_advection
Python API:
- add_int/real/bool/string/vectors - Add typed parameters
- does_parameter_exist/does_block_exist - Query structure
- get_parameter_names/get_blocks_with_prefix - Query structure
- Note: Get methods intentionally not exposed to prevent premature finalization
Package organization:
- parthenon_input: New package for input file generation (just API)
- parthenon_tools: Analysis tools (unchanged from develop)
- Real example and testing via example/fine_advection/parthinput.advection.py
Code organization:
- src/parameter_parsers/ - New directory for input parsers
- src/parameter_parsers/python_parser.{hpp,cpp} - Python input loading
- src/pybind/ - Python bindings for ParameterInput C++ class
- Clean separation between parsing logic and bindings
Build system:
- Consolidated PYTHONPATH: export PYTHONPATH=build/lib/python:$PYTHONPATH
- Automatic symlinks to Python packages in build/lib/python/
- Single directory contains compiled module and all packages
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add docs/python_input_summary.md documenting Python input architecture - Fix docstring in input_generator.py to use correct import path (parthenon_input instead of parthenon_tools.input_generator) - Emphasize minimal core philosophy and command line argument parsing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Catch SystemExit in LoadParameterInputFromPython() - Return nullptr for exit code 0 (clean exit like --help) - Fatal error for non-zero exit codes - Check for nullptr in ParthenonInitEnv() and return complete status - Document --help behavior in python_input_summary.md This allows Python input scripts to use argparse --help without triggering a fatal error. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Command line overrides are optional, so 'can apply' is more accurate than 'will apply'.
Replace global variable injection with explicit function call: - Python files must define parthenon_init_parameters(pin) function - Remove get_parameter_input() from Python bindings - Clear error messages guide users to correct pattern - Update fine_advection example to use new pattern Benefits: - No magic global variables - Clear, discoverable entry point - Better error messages - Consistent with modern Python patterns Breaking change: Python input files must wrap code in def parthenon_init_parameters(pin): function Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update python_input_summary.md to reflect new explicit function call pattern: - Architecture diagram shows function call instead of global injection - All usage examples use parthenon_init_parameters(pin) function - Remove references to get_parameter_input() and __parthenon_pi__ - Emphasize explicit parameter passing over magic globals Documentation now matches Phase 1 implementation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update all documentation examples to minimize top-level code: - Move JSON/YAML loading inside function (avoid side effects on file load) - Move InputFile setup inside function - Move application-specific setup inside function Rationale: When files are used for both input parsing and field initialization, they get loaded twice. Top-level code executes both times, causing unwanted side effects. Best practice is to keep only imports at top level. Also change physics-specific example (PhysicsSetup) to generic application example (ProblemSetup) to maintain physics-agnostic nature. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Let SystemExit exceptions propagate from parthenon_init_parameters() to the outer exception handler. Previously, the inner try-catch would catch SystemExit (from argparse --help) and fail immediately, preventing the clean exit handler from working. Now SystemExit is re-thrown to the outer handler which properly returns nullptr for exit code 0 (clean exit like --help). Tested: --help now exits with code 0 and displays help text correctly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Python shared library (.so) gets its own copy of static Globals variables when linking against libparthenon.a, separate from the executable's copy. When MPI_Init sets Globals::my_rank in the executable, the Python module's copy remains at 0, causing mpi_print to output from all ranks. Solution: Change Python bindings to call MPI_Comm_rank/MPI_Comm_size directly instead of reading from Globals. Update mpi_print to call my_rank() as a function. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update pybind11 wrapper to use the renamed API function GetBlockNamesWithPrefix (previously GetBlocksWithPrefix) to match the parameter input refactor. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
lroberts36
force-pushed
the
lroberts36/python-input-support
branch
from
April 13, 2026 22:08
5321c6a to
e879e93
Compare
pgrete
marked this pull request as draft
May 7, 2026 19:34
Collaborator
|
Will remove WIP and review once downstream codes use it. |
13 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR Summary
Summary
This PR adds support for Python scripts as input files (
.pyinstead of.pin), building on the parser separation infrastructure from #1385. Python input files enable programmatic parameter generation with native command-line argument parsing, loops, conditionals, and integration with external data sources. This is obviously inspired by the recent features added to Riot, so we probably want to think about if/how these two things fit together.Primary Use Case: Python's argparse for rich command-line interfaces with type validation, choices, help text, and custom constraints.
Philosophy: Minimal C++ core (~250 lines) that embeds Python and exposes
ParameterInputmethods. Optional Python helper classes (~420 lines) demonstrate usage but can be replaced with user-specific abstractions.Key Features
1. Python Command Line Arguments
Python scripts can use argparse for validation:
--nx=128(enforces int)--helpshows all available options2. Programmatic Configuration
3. Flexible Abstractions
Users can choose their approach:
pi.add_int(),pi.add_real(), etc. directlyInputFile/Blockclasses (optional)Implementation
C++ Core (~250 lines)
New files:
src/parameter_parsers/python_parser.{hpp,cpp}(~120 lines).pyscript to load function definitionsparthenon_init_parameters(pin)function with ParameterInput objectsrc/pybind/parameter_input_bindings.cpp(~135 lines)add_int,add_real,add_bool,add_string,add_*_vectormethodsdoes_parameter_exist,get_parameter_names, etc.Get<T>()methods during parsing (would triggerFinalizeParsing()and break command-line overrides)src/pybind/CMakeLists.txt(~80 lines)parthenon.soPython moduleexport PYTHONPATH=build/lib/python:$PYTHONPATHModified files:
src/parthenon_manager.cpp: Detect.pyextension and callLoadParameterInputFromPython()src/config.hpp.in: AddPARTHENON_ENABLE_PYTHON_BINDINGSdefinesrc/CMakeLists.txt: Addparameter_parsers/*.{cpp,hpp}to libraryPython Tooling (~420 lines, optional)
New package:
scripts/python/packages/parthenon_input/input_generator.py:InputFileandBlockclasses for structured parameter building__init__.py: Exports andmpi_print()helper for rank 0 printingExample:
example/fine_advection/parthinput.advection.py(151 lines)Documentation
New files:
docs/python_input_summary.md(~450 lines)src/pybind/README.md(~100 lines)Integration with Core Refactor (#1385)
Python input integrates seamlessly with parser separation:
parthenon_init_parameters(pin)which populatesParameterInputviaadd_*()methods (usesAddParsedParameter()interface)ParameterInputreturned to C++ModifyFromCmdline()(Parthenon-styleblock/param=value)FinalizeParsing()to mark parsing completeGet<T>()andGetOrAdd<T>()Python scripts run before
FinalizeParsing(), using the same parser interface as text files. The explicit function call pattern (parthenon_init_parameters(pin)) provides a clear entry point with no magic global variables.Build Requirements
Dependencies:
find_package(pybind11))Without Python support:
.pyinput files trigger clear error message: "Python input detected but not enabled at build time"#ifdef PARTHENON_ENABLE_PYTHON_BINDINGSUsage Example
Command Line Argument Flow
parthenon_init_parameters(pin)sys.argv = ["input.py", "--nx=128", "parthenon/mesh/refinement=static"]parse_known_args()to consume--nx=128, ignores restModifyFromCmdline()to overrideparthenon/mesh/refinement=staticBoth Python-style (
--flag=value) and Parthenon-style (block/param=value) arguments work together.Testing
example/fine_advection/parthinput.advection.pydemonstrates full workflowPARTHENON_ENABLE_PYTHON_BINDINGS=ONandOFFtestedLines of Code
Total new code: ~1370 lines (~250 required, ~1120 optional/documentation)
Future Extensions
The minimal core enables diverse use cases:
JSON/YAML input:
Parameter sweeps:
Application-specific abstractions:
Breaking Changes
None. This is a pure addition:
.pinfiles work unchangedDepends On
PR Checklist
// This file was made in part with generative AI.