-
Notifications
You must be signed in to change notification settings - Fork 4
Generate simulation, model, and package classes #176
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
Only testing sim-nam.dfn for now
Tested with gwf-ic
Remove untag functionality
Subclasses have their own docstrings
Store them directly in the class, not as an inner class
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This pull request introduces a comprehensive code generation framework for creating Python classes from MODFLOW 6 definition files (DFNs). The main purpose is to automatically generate simulation, model, and package classes based on MODFLOW 6 specifications, moving the manually written classes to a new modflow
subdirectory structure.
Key changes include:
- New code generation system with CLI interface and Jinja2 templates for generating Python classes
- Restructured import paths moving existing classes from
flopy4.mf6
toflopy4.mf6.modflow
- Template-based generation system supporting simulation, model, and package class types
Reviewed Changes
Copilot reviewed 23 out of 35 changed files in this pull request and generated 7 comments.
Show a summary per file
File | Description |
---|---|
codegen/generate_classes.py |
Main entry point for code generation with CLI interface |
codegen/make.py |
Core generation logic using Jinja2 templates |
codegen/filters.py |
Utility functions for processing DFNs and type conversions |
codegen/templates/*.jinja |
Jinja2 templates for generating different class types |
test/*.py |
Updated import paths to use new modflow module structure |
docs/examples/*.py |
Updated import paths for documentation examples |
flopy4/mf6/modflow/ |
Restructured module files with updated imports |
Comments suppressed due to low confidence (1)
flopy4/mf6/modflow/gwf/gwf.py:28
- [nitpick] The function name '_convert_grid' uses a leading underscore which typically indicates a private function, but this appears to be a rename from 'convert_grid'. If this function is still used elsewhere, the leading underscore may be inappropriate.
def _convert_grid(value):
nice- just transcribing some things we chatted on yesterday, and responding to a few of your notes
this is related to the parent/child binding problem the writer also needs to solve. detecting when a field is a subcomponent and handling it differently. We should try and unify the detection logic somewhere so codegen and writer can both use it.
we should be able to translate keystring recarray variables into 1d arrays in the generated classes in the same way as we do regular/tabular recarray variables. Keystrings just indicate that you don't know exactly what item type to expect from list-based format: you might get any of these records on each line instead of just one. But ultimately it's still a bunch of arrays. If we can disentangle structural specification from input format, then maybe this translation could become unnecessary, as we said yesterday.. DFNs right now do a little bit (but not all of either) of both: tell you what components connect to what and what fields are in each, and how the input files should look. Meanwhile, both mf6 and flopy need to deal with 1d arrays internally, while the DFN spec we are generating them from encodes them in list-based input structure which is just a convenient way to assign sparse data to large arrays. this feels like unclearly defined scope.
a propos to the above, a nice first step might be doing the list-to-array translation proactively in the TOML DFNs instead of waiting to do it here. such that DFNs define package- or period-data (i.e. space- or time-aligned) arrays with the real shape (aligned to the grid and tdis). maxbound is an artificial dimension, really an mf6 input format detail. a question then is how/where to define this mapping between an input-format-agnostic structural representation and the specific mf6 list-based input format. a new section inside each DFN? "sidecar" file alongside the DFN? entirely separate specification? is it even reasonable to try and separate these concerns, or is the structure of an mf6 simulation inextricable from its input format? the fact that we are considering different input formats (e.g. netcdf) suggests not. |
Simplify some lines remove reader from metadata
# Conflicts: # pixi.lock # uv.lock
and fix word wrapping of inner classes
This pull request introduces a code generation framework for creating Python classes and modules based on MODFLOW 6 definition files (DFNs). The changes include new functionality for generating classes, templates for code generation, and utilities for processing DFNs. Below is a summary of the most important changes, grouped by theme.
IMPORTANT: The moved files you see are not the generated files. I just moved them for easier comparison. They need to go and newly generated files need to be in place.
Core Code Generation Functionality
generate_classes
incodegen/generate_classes.py
, a new entry point for generating Python classes from MODFLOW 6 DFNs. This includes a command-line interface (cli_main
) and options for specifying DFN paths, GitHub repositories, and verbosity.make.py
with functions for generating Python modules (make_all
,make_targets
,make_init
) using Jinja2 templates and filters.Filters and Utilities for DFN Processing
codegen/filters.py
with utility functions for processing DFNs, such as_get_vars
,description
,variables
, andtype_str
. These functions assist in extracting metadata and generating Python-compatible names and types.codegen/__init__.py
to expose thegenerate_classes
function for external use.Jinja2 Templates for Code Generation
codegen/templates/
for generating Python modules:__init__.py.jinja
for module initialization.model.py.jinja
andpackage.py.jinja
for generating model and package classes, respectively. [1] [2]macros.py.jinja
for reusable Jinja2 macros, such asdocstrings
andxattree_field
.recarray.py.jinja
for generating record array classes.TODO
There are still some things to do, because there are quite some special cases that need to be addressed. Especially DIS and TDIS are tricky.