Meanderpy is a Python library implementing a numerical model of meandering rivers based on the Howard & Knutson (1984) kinematic approach. It simulates channel migration, cutoff formation, and builds 3D stratigraphic models from centerline evolution.
Author: Zoltan Sylvester (zoltan.sylvester@beg.utexas.edu) Version: 0.2.0 License: Apache 2.0
# Install in development mode
pip install -e .
# Run Jupyter notebooks
jupyter lab meanderpy/meanderpy.ipynb
# Create conda environment
conda env create -f environment.ymlmeanderpy/
├── meanderpy/
│ ├── __init__.py # Package init
│ ├── meanderpy.py # Core module (~1750 lines)
│ └── *.ipynb # Example notebooks
├── setup.py # Package configuration
└── environment.yml # Conda environment
Channel- Single channel centerline (x, y, z coords, W width, D depth)Cutoff- Oxbow lake/abandoned loop representationChannelBelt- Collection of channels over time; main simulation containermigrate()- Core simulation methodplot()- Visualization (strat/morph/age views)
ChannelBelt3D- 3D stratigraphic model container
generate_initial_channel()- Create initial sinuous centerlinecompute_curvature(x, y)- Calculate centerline curvaturecompute_migration_rate()- Numba-optimized Howard-Knutson migrationmigrate_one_step()- Single iteration lateral migrationbuild_3d_model()- Create 3D stratigraphic modelsave_3d_chb_to_hdf5()/read_3d_chb_from_hdf5()- HDF5 I/O
numpy, scipy, matplotlib, numba, scikit-image, pillow, tqdm, h5py
| Parameter | Description | Typical Value |
|---|---|---|
W |
Channel width (m) | 50-200 |
D |
Channel depth (m) | W/40 |
deltas |
Point spacing (m) | W/4 to W/2 |
kl |
Migration rate constant | ~1.9e-6 m/s |
kv |
Vertical erosion rate | ~1e-11 m/s |
dt |
Time step | 0.1 years (in seconds) |
crdist |
Cutoff threshold | 2-3 × W |
Cfs |
Chezy friction | ~0.01 |
cfl_factor |
CFL stability factor | 0.5 (default) |
import meanderpy
# 1. Generate initial channel
ch = meanderpy.generate_initial_channel(W, D, Sl, deltas, pad, n_bends)
# 2. Create channel belt
chb = meanderpy.ChannelBelt(channels=[ch], cutoffs=[], cl_times=[0.0], cutoff_times=[])
# 3. Run migration (this is the main simulation)
chb.migrate(nit, saved_ts, deltas, pad, crdist, depths, Cfs, kl, kv, dt, dens,
t1=500, t2=700, t3=1200, aggr_factor=2e-9)
# 4. Visualize
fig = chb.plot('strat', pb_age=20, ob_age=60, end_time=chb.cl_times[-1])
# 5. Build 3D model (optional, computationally expensive)
chb_3d = meanderpy.build_3d_model(chb, model_type='fluvial', h_mud=0.4, ...)- Variable naming:
chb(ChannelBelt),ch(Channel),x,y,z(coordinates) - Time in seconds internally; years via
365*24*60*60.0 - NumPy-style docstrings
- Howard-Knutson constants: omega=-1.0, gamma=2.5
The migration functions implement a CFL-style stability check to prevent numerical instability when time steps or migration rates are too large.
How it works:
- Migration displacement per time step is clamped to
cfl_factor * deltas - Default
cfl_factor = 0.5(displacement limited to half the point spacing) - If violated, a warning is issued and displacement is clamped while preserving direction
Parameters:
cfl_factorinmigrate(): Set toNoneto disable clamping (not recommended)- Stability requires:
|R1| * dt < deltas
If you see CFL warnings:
- Reduce
dt(time step) - Reduce
kl(migration rate constant) - Increase
deltas(point spacing) - but this reduces resolution
compute_migration_rate()is Numba JIT-compiled - this is the computational bottleneck- 3D model building is decoupled from migration for efficiency
- CFL clamping adds minimal overhead but prevents simulation blowup
- HDF5: 3D model storage (
save_3d_chb_to_hdf5) - Eclipse: Reservoir model export (
write_eclipse_grid)
Run tests with the meanderpy conda environment:
source /path/to/conda/etc/profile.d/conda.sh && conda activate meanderpy
python tests/test_meanderpy.py
# Or with pytest if installed:
pytest tests/test_meanderpy.py -vTest coverage includes:
compute_curvature()- straight line, circle, sign changescompute_derivatives()- shapes, arc lengthgenerate_initial_channel()- object creation, attributesresample_centerline()- uniform spacingmigrate_one_step()- coordinate changes, CFL warning, CFL clampingfind_cutoffs()/cut_off_cutoffs()- cutoff detectionget_channel_banks()- bank coordinatesChannel,Cutoff,ChannelBeltclasses
Additional validation via Jupyter notebooks in meanderpy/ directory.
- Main branch:
master - Remote: https://github.com/zsylvester/meanderpy