You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Make in-process SPOTPY the default calibration engine for MNiShed in v4.0, keeping Dakota as a fully-supported alternative for expensive models and MPI/cluster runs (demote, not delete).
Why
The cost of the current Dakota workflow is its fork interface — a fresh Python process per evaluation (~1.5 s startup) — not the optimization algorithm. Running the sampler in-process with the Numba JIT warm is ~100× faster per eval, and SPOTPY provides both an optimizer (SCE-UA) and a Bayesian sampler (DREAM) on the same setup class.
Measured A/B (Cannon, 3-yr, identical model via run_and_score):
Engine
evals
wall
per-eval
best KGE
in-process SCE-UA (SPOTPY)
914
12 s
13 ms
0.806
Dakota EGO + pattern-search
~700
~18 min
~1500 ms (fork)
~0.80
Same optimum, ~90× wall-clock. The in-process framework also yields DREAM posteriors (UQ) that the optimization-only Dakota path never produced.
Scope split (important)
Most of this is additive and non-breaking and should ship in a 3.x minor so the speedup + UQ land without waiting on v4.0:
(3.x) Optional spotpy extra + a reusable in-process runner (ParameterSet + run_and_score + log_flow_residual_terms) supporting SCE-UA (best-fit) and DREAM (UQ).
Reserve for v4.0 only the breaking / positioning changes:
Make params.yml self-describing: a declarative target: field per parameter (e.g. target: recession_coeff[0]; 10** applied for log__ params) so one generic runner serves any basin with no per-basin Python. (Schema change.)
Switch the documented default to in-process SPOTPY; demote the Dakota example to the documented "expensive model / cluster" alternative (keep it).
Docs rewrite (calibration guide, example READMEs).
Retire the per-basin Dakota driver.py hardcoded param→kwarg mapping in favour of the declarative target: mapping (which can also feed a generic Dakota driver).
Notes
Requires numpy < 2.3 for the Numba JIT (the [jit] extra already pins this); spotpy as an optional extra.
Cheap re-runs let the Dakota back-catalog be re-baselined under SPOTPY in minutes — doubles as migration verification (reproduce past optima) and adds posteriors for free.
Goal
Make in-process SPOTPY the default calibration engine for MNiShed in v4.0, keeping Dakota as a fully-supported alternative for expensive models and MPI/cluster runs (demote, not delete).
Why
The cost of the current Dakota workflow is its fork interface — a fresh Python process per evaluation (~1.5 s startup) — not the optimization algorithm. Running the sampler in-process with the Numba JIT warm is ~100× faster per eval, and SPOTPY provides both an optimizer (SCE-UA) and a Bayesian sampler (DREAM) on the same setup class.
Measured A/B (Cannon, 3-yr, identical model via
run_and_score):Same optimum, ~90× wall-clock. The in-process framework also yields DREAM posteriors (UQ) that the optimization-only Dakota path never produced.
Scope split (important)
Most of this is additive and non-breaking and should ship in a 3.x minor so the speedup + UQ land without waiting on v4.0:
spotpyextra + a reusable in-process runner (ParameterSet+run_and_score+log_flow_residual_terms) supporting SCE-UA (best-fit) and DREAM (UQ).Reserve for v4.0 only the breaking / positioning changes:
params.ymlself-describing: a declarativetarget:field per parameter (e.g.target: recession_coeff[0];10**applied forlog__params) so one generic runner serves any basin with no per-basin Python. (Schema change.)driver.pyhardcoded param→kwarg mapping in favour of the declarativetarget:mapping (which can also feed a generic Dakota driver).Notes
numpy < 2.3for the Numba JIT (the[jit]extra already pins this);spotpyas an optional extra.Related: #18 (v4.0 state representation), #19 (basin-element abstraction), and the field-data-priors / identifiability direction.
🤖 Generated with Claude Code