Tutorial: Packaging and Running IWFM Models#
This tutorial demonstrates how to package an IWFM model directory into a distributable ZIP archive and generate platform-appropriate run scripts using pyiwfm.
Learning Objectives#
By the end of this tutorial, you will be able to:
Collect model files from an IWFM model directory
Package a complete model into a ZIP archive with a manifest
Generate run scripts for Windows (
.bat/.ps1) and Linux (.sh)Use the
pyiwfm packageandpyiwfm runCLI commands
Prerequisites#
Install pyiwfm with basic dependencies:
pip install pyiwfm
No additional extras are required for packaging and script generation.
Collecting Model Files#
The collect_model_files() function walks an
IWFM model directory and returns all files relevant to the model, filtering
out output files, caches, and version-control directories:
from pathlib import Path
from pyiwfm.io import collect_model_files
model_dir = Path("C2VSimCG")
files = collect_model_files(model_dir)
print(f"Found {len(files)} model files")
for f in files[:10]:
print(f" {f.relative_to(model_dir)}")
Default exclusions:
Results/,__pycache__/,.git/,.svn/directories.hdf/.h5output files.exe/.dll/.soexecutables
Including executables or results:
# Include executables for a self-contained package
files_with_exes = collect_model_files(model_dir, include_executables=True)
# Include results directory and HDF5 output files
files_with_results = collect_model_files(model_dir, include_results=True)
# Include everything
all_files = collect_model_files(
model_dir,
include_executables=True,
include_results=True,
)
Creating a ZIP Archive#
Use package_model() to create a ZIP archive
that preserves the directory structure and includes a manifest.json:
from pyiwfm.io import package_model
result = package_model(
model_dir,
output_path=Path("C2VSimCG_v1.0.zip"),
)
print(f"Archive: {result.archive_path}")
print(f"Files: {len(result.files_included)}")
print(f"Size: {result.total_size_bytes / 1024 / 1024:.1f} MB")
The archive preserves the standard IWFM directory layout:
C2VSimCG_v1.0.zip
├── manifest.json
├── Preprocessor/
│ ├── Preprocessor.in
│ ├── Nodal.dat
│ ├── Element.dat
│ ├── Stratigraphy.dat
│ └── ...
├── Simulation/
│ ├── Simulation.in
│ ├── Groundwater/
│ ├── Streams/
│ └── ...
└── ...
Packaging with executables (self-contained):
result = package_model(
model_dir,
output_path=Path("C2VSimCG_standalone.zip"),
include_executables=True,
)
Inspecting the manifest:
The manifest maps each file in the archive to a category (input,
binary, script, gis, executable, data):
import json
for rel_path, category in sorted(result.manifest.items()):
print(f" [{category:10s}] {rel_path}")
Generating Run Scripts#
pyiwfm generates platform-appropriate run scripts for executing the IWFM preprocessor, simulation, and optional post-processors (Budget, ZBudget).
Basic Script Generation#
from pyiwfm.roundtrip.script_generator import generate_run_scripts
scripts = generate_run_scripts(
model_dir=Path("C2VSimCG"),
preprocessor_main="Preprocessor/Preprocessor.in",
simulation_main="Simulation/Simulation.in",
)
for s in scripts:
print(f"Generated: {s.name}")
On Windows this creates .bat and .ps1 scripts by default; on
Linux/macOS it creates .sh scripts.
Generated scripts:
run_preprocessor– runs the IWFM PreProcessorrun_simulation– runs the IWFM Simulationrun_all– runs preprocessor then simulation in sequence
Choosing Script Formats#
Use the formats parameter to control which script types are generated:
# Generate all three formats
scripts = generate_run_scripts(
model_dir=Path("C2VSimCG"),
preprocessor_main="Preprocessor/Preprocessor.in",
simulation_main="Simulation/Simulation.in",
formats=["bat", "ps1", "sh"],
)
# -> 9 scripts (3 per format)
Adding Budget and ZBudget Scripts#
Pass budget_exe and/or zbudget_exe to also generate post-processor
run scripts:
scripts = generate_run_scripts(
model_dir=Path("C2VSimCG"),
preprocessor_main="Preprocessor/Preprocessor.in",
simulation_main="Simulation/Simulation.in",
budget_exe="Budget_x64.exe",
zbudget_exe="ZBudget_x64.exe",
)
for s in scripts:
print(f"Generated: {s.name}")
This adds run_budget and run_zbudget scripts, and the run_all
script is updated to include them after the simulation step.
CLI Commands#
Both packaging and script generation are available from the command line.
pyiwfm package#
Package a model directory into a ZIP archive:
# Basic packaging (inputs only)
pyiwfm package --model-dir ./C2VSimCG
# Custom output path
pyiwfm package --model-dir ./C2VSimCG --output C2VSimCG_v1.0.zip
# Include executables for a self-contained archive
pyiwfm package --model-dir ./C2VSimCG --include-executables
# Include results/output files
pyiwfm package --model-dir ./C2VSimCG --include-results
Example output:
Packaged 147 files (23.4 MB) -> C:\models\C2VSimCG.zip
pyiwfm run#
Generate run scripts and optionally download executables:
# Generate run scripts only (auto-detects platform)
pyiwfm run --model-dir ./C2VSimCG --scripts-only
# Generate specific format(s)
pyiwfm run --model-dir ./C2VSimCG --scripts-only --format bat --format ps1
# Download executables from GitHub and generate scripts
pyiwfm run --model-dir ./C2VSimCG --download-executables --scripts-only
Example output:
Generated: C:\models\C2VSimCG\run_preprocessor.bat
Generated: C:\models\C2VSimCG\run_simulation.bat
Generated: C:\models\C2VSimCG\run_all.bat
Generated: C:\models\C2VSimCG\run_preprocessor.ps1
Generated: C:\models\C2VSimCG\run_simulation.ps1
Generated: C:\models\C2VSimCG\run_all.ps1
Complete Workflow#
Here is a complete example that packages a model, downloads executables, and generates run scripts:
"""Package an IWFM model for distribution."""
from pathlib import Path
from pyiwfm.io import package_model
from pyiwfm.roundtrip.script_generator import generate_run_scripts
model_dir = Path("C2VSimCG")
# 1. Generate run scripts
scripts = generate_run_scripts(
model_dir=model_dir,
preprocessor_main="Preprocessor/Preprocessor.in",
simulation_main="Simulation/Simulation.in",
budget_exe="Budget_x64.exe",
formats=["bat", "ps1", "sh"],
)
print(f"Generated {len(scripts)} run scripts")
# 2. Package the model (scripts are now included in the ZIP)
result = package_model(
model_dir,
output_path=Path("C2VSimCG_distribution.zip"),
include_executables=True,
)
print(f"Archive: {result.archive_path}")
print(f"Files: {len(result.files_included)}")
print(f"Size: {result.total_size_bytes / 1024 / 1024:.1f} MB")
# 3. Print manifest summary
categories = {}
for category in result.manifest.values():
categories[category] = categories.get(category, 0) + 1
for cat, count in sorted(categories.items()):
print(f" {cat}: {count} files")
Next Steps#
See Tutorial: Reading an Existing IWFM Model for loading and inspecting IWFM models
See Tutorial: Building the IWFM Sample Model from Scratch for constructing a model from scratch
See Reading and Writing Files for all supported file formats
See Roundtrip and CLI Modules for the full API reference