Skip to content

Make in-process SPOTPY the default calibration engine (Dakota → expensive/cluster alternative) #20

Description

@awickert

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):

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.
  • Does not gate or delay Drop K=1 special-casing — uniform per-sub-catchment state representation #18 (the headline v4.0 state-representation change).

Related: #18 (v4.0 state representation), #19 (basin-element abstraction), and the field-data-priors / identifiability direction.

🤖 Generated with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions