Hydrological model extension package extracted from dmg
Project description
dmot
Hydrological model extension package extracted from dmg, now extended with a
modular reservoir dispatch scheduling kernel.
Package Structure
dmotpy/
├── models/ # Hydrological rainfall-runoff models (HBV, GR4J, …)
│ ├── core/ # 38+ step-function model implementations
│ ├── flux/ # Flux calculation components
│ ├── unithydro/ # Unit hydrograph routing
│ └── special/ # Full class-based model wrappers
├── neural_networks/ # Calibration & parameterization networks
├── trainers/ # Training loops (CalTrainer, FasterTrainer)
└── dispatch/ # *** NEW: Reservoir dispatch scheduling kernel ***
├── domain/ # Layer 3: Domain objects
├── kernel/ # Layer 5: Physics kernel & simulator
├── plugins/ # Layer 4 & 6: Operation modules & plugin registry
├── services/ # Layer 2: Service orchestration
├── evaluator.py # Evaluation engine
└── mcp/ # Layer 1: FastMCP tool interface
Dispatch Kernel — 6-Layer Architecture
The dispatch module implements a single-reservoir, modular, service-oriented scheduling kernel designed for:
- Rule-based dispatch with structured operation modules
- Unified simulation with un-bypassable physics core
- Plugin-based objectives, constraints, and strategies
- FastMCP tool exposure for agent integration
- Future extension to CBR, multi-objective optimization, and game-theoretic planning
Layer 1: Interface (FastMCP)
Exposes high-level capabilities as MCP tools:
| Tool | Description |
|---|---|
get_snapshot |
Current state, spec, available modules |
list_operation_modules |
Available module types with descriptions |
create_program |
Create a dispatch program |
simulate_program |
Run a simulation against a forecast |
evaluate_program |
Simulate and evaluate against objectives |
compare_programs |
Compare multiple programs side-by-side |
explain_program |
Human-readable program explanation |
Does not expose: direct state mutation, kernel bypass, constraint override.
Layer 2: Services
| Service | Responsibility |
|---|---|
SnapshotService |
State and spec queries |
ProgramService |
Dispatch program CRUD |
SimulationService |
Run simulations, simulate-and-evaluate |
EvaluationService |
Evaluate results, compare programs |
ExplanationService |
Generate human-readable explanations |
Layer 3: Domain Objects
| Object | Purpose |
|---|---|
ReservoirSpec |
Static reservoir geometry, curves, gates, limits |
ReservoirState |
Dynamic state: level, storage, inflow, outflow |
ForecastBundle |
Single-value or ensemble forecast scenarios |
DispatchProgram |
Structured scheduling via operation modules |
ModuleInstance |
A concrete module with params & switch conditions |
ConstraintSet |
Collection of hard/soft constraint rules |
ObjectiveSet |
Weighted multi-criteria evaluation objectives |
SimulationResult |
Full trajectory with water balance diagnostics |
EvaluationResult |
Multi-level scoring output |
Layer 4: Operation Modules
6 built-in module types:
| Module Type | Description |
|---|---|
constant_release |
Fixed flow release regardless of state |
inflow_driven |
Release = f(inflow) with ratio + offset |
storage_driven |
Release based on level deviation from target |
combined_driven |
Multi-factor conditional logic (flood/drought/normal) |
level_tracking |
PID-like target water level tracking |
external_constraint |
Follow a pre-computed release schedule |
New module types can be added by implementing ModuleHandler and registering
with ModuleRegistry.
Layer 5: Physics Kernel
The un-bypassable core:
- Water balance:
S(t+1) = S(t) + (I - O) × Δt - Level-capacity interpolation (forward & inverse)
- Release clamping to physical limits (min/max/outlet capacity)
- Level change rate limiting
- Constraint checking (level max/min, release max/min, change rate)
No strategy, agent, or optimizer can directly mutate state — all transitions must go through the physics kernel.
Layer 6: Plugins
Pre-registered plugin slots for future extension:
| Slot | Status | Future Use |
|---|---|---|
ModuleHandler |
✅ Built-in | Custom operation modules |
ConstraintPlugin |
✅ Built-in | Custom constraint types |
ObjectivePlugin |
✅ Built-in | Custom evaluation criteria |
SolverPlugin |
🔲 Reserved | Multi-objective optimization |
CaseRetrievalPlugin |
🔲 Reserved | CBR knowledge reuse |
PlannerPlugin |
🔲 Reserved | Game-theoretic / LLM planning |
Quick Start
Define a reservoir
from dmotpy.dispatch.domain.reservoir_spec import ReservoirSpec
spec = ReservoirSpec(
name="MyReservoir",
dead_level=100.0, normal_level=120.0,
flood_limit_level=130.0, check_flood_level=135.0, crest_level=140.0,
total_capacity=3500.0, flood_control_capacity=1300.0, dead_capacity=100.0,
level_capacity={100.0: 100, 120.0: 1200, 130.0: 2200, 140.0: 3500},
max_release=3000.0, min_release=10.0,
)
Create a dispatch program
from dmotpy.dispatch.domain.dispatch_program import DispatchProgram, ModuleInstance
program = DispatchProgram(
name="flood_response",
modules=[
ModuleInstance(
module_type="constant_release", name="normal",
params={"release": 50.0},
switch_in_conditions={"level_below": 128.0},
),
ModuleInstance(
module_type="inflow_driven", name="flood",
params={"ratio": 1.2, "min_release": 100.0},
switch_in_conditions={"level_above": 128.0},
),
],
)
Run simulation
from datetime import datetime
from dmotpy.dispatch.domain.reservoir_state import ReservoirState
from dmotpy.dispatch.domain.forecast import ForecastBundle
from dmotpy.dispatch.kernel.simulator import DispatchSimulator
state = ReservoirState(
timestamp=datetime(2024, 7, 1),
level=118.0, storage=900.0, inflow=100.0, outflow=50.0,
)
forecast = ForecastBundle.from_deterministic([50]*6 + [800, 1200, 1000, 700, 400, 200] + [50]*12)
sim = DispatchSimulator(spec)
result = sim.simulate(state, forecast, program)
print(result.summary())
Evaluate
from dmotpy.dispatch.domain.objectives import ObjectiveSet, ObjectiveWeight, ObjectiveType, ObjectiveDirection
from dmotpy.dispatch.evaluator import Evaluator
obj = ObjectiveSet()
obj.add(ObjectiveWeight(name="flood", objective_type=ObjectiveType.FLOOD_CONTROL,
direction=ObjectiveDirection.MAXIMIZE, weight=0.7))
obj.add(ObjectiveWeight(name="eco", objective_type=ObjectiveType.ECOLOGY,
direction=ObjectiveDirection.MAXIMIZE, weight=0.3))
evaluator = Evaluator(spec, obj)
eval_result = evaluator.evaluate(result, program)
print(eval_result.summary())
Use via MCP (for agents)
from dmotpy.dispatch.mcp import DispatchMCPServer
server = DispatchMCPServer(spec, initial_state)
server.get_snapshot() # Get state + spec
server.create_program("p1", "constant_release", {"release": 80.0})
server.simulate_program("p1", [60.0]*24) # Simulate 24 steps
server.compare_programs(["p1", "p2"], [60.0]*24) # Compare
server.explain_program("p1") # Explain
Running Tests
pip install pytest
pytest tests/dispatch/ -v
Dependencies
| Package | Purpose |
|---|---|
| numpy | Numerical computation |
| scipy | Scientific computing |
| torch | Differentiable models |
| pydantic | Domain object validation (v2) |
| fastmcp | MCP tool interface (optional) |
| pytest | Testing |
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dmotpy-0.1.0.tar.gz.
File metadata
- Download URL: dmotpy-0.1.0.tar.gz
- Upload date:
- Size: 129.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.11 {"installer":{"name":"uv","version":"0.9.11"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
03989c81b5034ab458a1b6f32dc6c9f80915a34a909415fc719ee155c8b1ab82
|
|
| MD5 |
ca8f6d5436fc29e21dffb7fe8486eda3
|
|
| BLAKE2b-256 |
80279869dc8d5185b3339cfa3dd6e5e0c013f62b05d77b3f4038b38fbf37e442
|
File details
Details for the file dmotpy-0.1.0-py3-none-any.whl.
File metadata
- Download URL: dmotpy-0.1.0-py3-none-any.whl
- Upload date:
- Size: 193.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.11 {"installer":{"name":"uv","version":"0.9.11"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d49a337abc2da32e7e0ffc7015a8debee57bc4e2fce95ad3ede2d4a85f200522
|
|
| MD5 |
637376b81418a622415e9c86c071d349
|
|
| BLAKE2b-256 |
46a11a36bf28f7ba1d5e33b4fb571529acab7be3e6f09ac4e2e61210c7cba5d9
|