Skip to content

Commit 0b836b4

Browse files
Release v0.2.0
- Bump version to 0.2.0 - Add __version__ to package __init__.py for programmatic access - Fix download_url typo in setup.py (missing dot before tar.gz) - Add CLAUDE.md project guide Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 85502ef commit 0b836b4

File tree

4 files changed

+162
-4
lines changed

4 files changed

+162
-4
lines changed

CLAUDE.md

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# CLAUDE.md - Meanderpy Project Guide
2+
3+
## Project Overview
4+
5+
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.
6+
7+
**Author**: Zoltan Sylvester (zoltan.sylvester@beg.utexas.edu)
8+
**Version**: 0.2.0
9+
**License**: Apache 2.0
10+
11+
## Quick Commands
12+
13+
```bash
14+
# Install in development mode
15+
pip install -e .
16+
17+
# Run Jupyter notebooks
18+
jupyter lab meanderpy/meanderpy.ipynb
19+
20+
# Create conda environment
21+
conda env create -f environment.yml
22+
```
23+
24+
## Project Structure
25+
26+
```
27+
meanderpy/
28+
├── meanderpy/
29+
│ ├── __init__.py # Package init
30+
│ ├── meanderpy.py # Core module (~1750 lines)
31+
│ └── *.ipynb # Example notebooks
32+
├── setup.py # Package configuration
33+
└── environment.yml # Conda environment
34+
```
35+
36+
## Core Architecture
37+
38+
### Main Classes (meanderpy.py)
39+
40+
- **`Channel`** - Single channel centerline (x, y, z coords, W width, D depth)
41+
- **`Cutoff`** - Oxbow lake/abandoned loop representation
42+
- **`ChannelBelt`** - Collection of channels over time; main simulation container
43+
- `migrate()` - Core simulation method
44+
- `plot()` - Visualization (strat/morph/age views)
45+
- **`ChannelBelt3D`** - 3D stratigraphic model container
46+
47+
### Key Functions
48+
49+
- `generate_initial_channel()` - Create initial sinuous centerline
50+
- `compute_curvature(x, y)` - Calculate centerline curvature
51+
- `compute_migration_rate()` - **Numba-optimized** Howard-Knutson migration
52+
- `migrate_one_step()` - Single iteration lateral migration
53+
- `build_3d_model()` - Create 3D stratigraphic model
54+
- `save_3d_chb_to_hdf5()` / `read_3d_chb_from_hdf5()` - HDF5 I/O
55+
56+
## Dependencies
57+
58+
numpy, scipy, matplotlib, numba, scikit-image, pillow, tqdm, h5py
59+
60+
## Key Parameters
61+
62+
| Parameter | Description | Typical Value |
63+
|-----------|-------------|---------------|
64+
| `W` | Channel width (m) | 50-200 |
65+
| `D` | Channel depth (m) | W/40 |
66+
| `deltas` | Point spacing (m) | W/4 to W/2 |
67+
| `kl` | Migration rate constant | ~1.9e-6 m/s |
68+
| `kv` | Vertical erosion rate | ~1e-11 m/s |
69+
| `dt` | Time step | 0.1 years (in seconds) |
70+
| `crdist` | Cutoff threshold | 2-3 × W |
71+
| `Cfs` | Chezy friction | ~0.01 |
72+
| `cfl_factor` | CFL stability factor | 0.5 (default) |
73+
74+
## Typical Usage Pattern
75+
76+
```python
77+
import meanderpy
78+
79+
# 1. Generate initial channel
80+
ch = meanderpy.generate_initial_channel(W, D, Sl, deltas, pad, n_bends)
81+
82+
# 2. Create channel belt
83+
chb = meanderpy.ChannelBelt(channels=[ch], cutoffs=[], cl_times=[0.0], cutoff_times=[])
84+
85+
# 3. Run migration (this is the main simulation)
86+
chb.migrate(nit, saved_ts, deltas, pad, crdist, depths, Cfs, kl, kv, dt, dens,
87+
t1=500, t2=700, t3=1200, aggr_factor=2e-9)
88+
89+
# 4. Visualize
90+
fig = chb.plot('strat', pb_age=20, ob_age=60, end_time=chb.cl_times[-1])
91+
92+
# 5. Build 3D model (optional, computationally expensive)
93+
chb_3d = meanderpy.build_3d_model(chb, model_type='fluvial', h_mud=0.4, ...)
94+
```
95+
96+
## Code Conventions
97+
98+
- Variable naming: `chb` (ChannelBelt), `ch` (Channel), `x,y,z` (coordinates)
99+
- Time in seconds internally; years via `365*24*60*60.0`
100+
- NumPy-style docstrings
101+
- Howard-Knutson constants: omega=-1.0, gamma=2.5
102+
103+
## Numerical Stability (CFL Condition)
104+
105+
The migration functions implement a CFL-style stability check to prevent numerical instability when time steps or migration rates are too large.
106+
107+
**How it works:**
108+
- Migration displacement per time step is clamped to `cfl_factor * deltas`
109+
- Default `cfl_factor = 0.5` (displacement limited to half the point spacing)
110+
- If violated, a warning is issued and displacement is clamped while preserving direction
111+
112+
**Parameters:**
113+
- `cfl_factor` in `migrate()`: Set to `None` to disable clamping (not recommended)
114+
- Stability requires: `|R1| * dt < deltas`
115+
116+
**If you see CFL warnings:**
117+
1. Reduce `dt` (time step)
118+
2. Reduce `kl` (migration rate constant)
119+
3. Increase `deltas` (point spacing) - but this reduces resolution
120+
121+
## Performance Notes
122+
123+
- `compute_migration_rate()` is Numba JIT-compiled - this is the computational bottleneck
124+
- 3D model building is decoupled from migration for efficiency
125+
- CFL clamping adds minimal overhead but prevents simulation blowup
126+
127+
## File Formats
128+
129+
- **HDF5**: 3D model storage (`save_3d_chb_to_hdf5`)
130+
- **Eclipse**: Reservoir model export (`write_eclipse_grid`)
131+
132+
## Testing
133+
134+
Run tests with the meanderpy conda environment:
135+
136+
```bash
137+
source /path/to/conda/etc/profile.d/conda.sh && conda activate meanderpy
138+
python tests/test_meanderpy.py
139+
# Or with pytest if installed:
140+
pytest tests/test_meanderpy.py -v
141+
```
142+
143+
Test coverage includes:
144+
- `compute_curvature()` - straight line, circle, sign changes
145+
- `compute_derivatives()` - shapes, arc length
146+
- `generate_initial_channel()` - object creation, attributes
147+
- `resample_centerline()` - uniform spacing
148+
- `migrate_one_step()` - coordinate changes, CFL warning, CFL clamping
149+
- `find_cutoffs()` / `cut_off_cutoffs()` - cutoff detection
150+
- `get_channel_banks()` - bank coordinates
151+
- `Channel`, `Cutoff`, `ChannelBelt` classes
152+
153+
Additional validation via Jupyter notebooks in `meanderpy/` directory.
154+
155+
## Git Workflow
156+
157+
- Main branch: `master`
158+
- Remote: https://github.com/zsylvester/meanderpy

meanderpy/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
name = "meanderpy"
2+
__version__ = "0.2.0"
23
from .meanderpy import *

meanderpy/meanderpy.ipynb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,11 +323,10 @@
323323
},
324324
{
325325
"cell_type": "code",
326-
"execution_count": 21,
326+
"execution_count": null,
327327
"metadata": {},
328328
"outputs": [],
329329
"source": [
330-
"reload(mp)\n",
331330
"nit = 2000 # number of iterations\n",
332331
"W = 200.0 # channel width (m)\n",
333332
"D = 6.0 # channel depth (m)\n",

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from setuptools import setup, find_namespace_packages
22

3-
VERSION="0.1.9"
3+
VERSION="0.2.0"
44
DESCRIPTION = "meanderpy: a simple model of meandering"
55
with open("README.md", "r") as f:
66
long_description_readme = f.read()
@@ -15,7 +15,7 @@
1515
long_description=long_description_readme,
1616
long_description_content_type="text/markdown",
1717
url="https://github.com/zsylvester/meanderpy",
18-
download_url="https://github.com/zsylvester/meanderpy/archive/refs/tags/v{0}tar.gz".format(VERSION),
18+
download_url="https://github.com/zsylvester/meanderpy/archive/refs/tags/v{0}.tar.gz".format(VERSION),
1919
packages=find_namespace_packages(include=['meanderpy', 'meanderpy.*']),
2020
install_requires=['numpy','matplotlib', 'scipy','numba','pillow','scikit-image','tqdm'],
2121
classifiers=[

0 commit comments

Comments
 (0)