Skip to content

What Novomodelo Solves

This chapter answers the foundational question: what problem does Novomodelo compute, and what does a user get when a run completes? It frames the scope for the chapters that follow and threads the capability statements that appear throughout this site.

Power systems that rely heavily on hydroelectric generation face a planning problem that is both large-scale and deeply uncertain. Water stored in reservoirs today is water available for generation in future months; the right dispatch policy depends on how much rain is likely to fall across a multi-year horizon, the cost of thermal alternatives, and the risk appetite of the system operator.

Novomodelo solves the multi-stage stochastic hydrothermal dispatch problem: given a power system with hydro reservoirs, thermal plants, and a stochastic inflow process, find the operating policy that minimises expected generation cost over a planning horizon while meeting load at every stage under every scenario. The state space is continuous (reservoir levels, autoregressive inflow lags), the uncertainty is structured by a periodic autoregressive model, and the horizon spans many stages.

It is a planning problem of hydro-dominated power systems, and the one the Novomodelo SDDP solver is built for.

Novomodelo implements Stochastic Dual Dynamic Programming (SDDP). SDDP solves the multi-stage problem by decomposing it into per-stage linear programmes that are linked through state variables (reservoir levels and inflow lags). Iterating forward and backward through the stage tree, the algorithm builds piecewise-linear approximations of the cost-to-go function at each stage. These approximations, called Benders cuts, carry future cost information from the last stage back to the first.

Each iteration updates a lower bound and an upper-bound evaluation of the policy’s cost (Methodology Guarantees); training stops when its stopping rules are met (Stopping Rules). See The SDDP Framework in One Page for the one-page framing, and SDDP Algorithm for the full algorithmic treatment.

At convergence, Novomodelo provides a lower bound on the optimal policy cost and one of two upper-bound evaluations of the policy’s cost, selected by the forward pass:

  1. Lower bound — the first stage’s risk-adjusted value over its openings with the current cuts (definition). It does not decrease across iterations. Under the hypotheses in Cut Management — when bounds and certificates hold, it is a valid lower bound (Tier 1), and under an expectation measure at every stage it converges to the optimal value of the model as trained with probability 1 (Tier 2).
  2. Statistical upper bound — the sample-average cost of forward simulations under the current policy, with a confidence interval. This estimate carries genuine sampling error that narrows only as more scenarios are drawn; it can fall below the lower bound and is not a certificate.
  3. Exact (deterministic) upper bound — the policy’s cost evaluated over an enumerated scenario tree, visiting every leaf path exactly once. It carries no sampling error. With the lower bound, it limits from above how far the policy’s cost lies above the optimal value when the risk measure is uniform across stages (Tier 3).

Novomodelo’s determinism guarantee is stated per binary under Methodology Principles.

Novomodelo is operated through two equivalent interfaces:

CLI: Novomodelo is driven via the novomodelo CLI; the same case directories and configuration files used from Python are used from the CLI.

Python: Novomodelo is callable from Python via PyO3 bindings; cases can be configured, runs launched, and results loaded from Python without leaving the methodology layer.

A run writes machine-parseable output (JSON and Parquet files, and the binary policy checkpoint) alongside its human-readable progress output. Results are structured and self-describing: a completed training run writes the policy, the convergence record, and the output statistics to known paths in its output directory (output/ inside the case directory unless another is given).

A training run writes its policy as a checkpoint at the end of training. A later run of the same novomodelo version on the same study (the same state dimension, the same entity behind each state variable, the same stages and the same study graph) can resume training from it instead of starting over.

A study runs as a single process or, with the MPI build, across many MPI ranks (HPC & Cluster Deployment). One binary on one platform image gives bit-identical results at any rank count and thread count; the single-process and MPI builds are different binaries, whose results are not promised equal (Determinism & Provenance).

Novomodelo is designed for production-scale studies: a long planning horizon of many stages, with large fleets of hydro plants and thermal units, many inflow scenarios per stage, and multiple load blocks within each stage.

The following principles govern how Novomodelo is built.

  • Reproducibility — Every Novomodelo run can be re-derived by anyone holding its inputs and the metadata it records: the same inputs and seed, run by the same binary on the same platform image, give the same policy, the same bounds at every iteration and the same simulation costs, up to the stopping iteration under a wall-clock stopping criterion. See Determinism & Provenance §5 for what each run records.

  • Determinism — Novomodelo produces bit-identical results at any MPI rank count and thread count of one binary on one platform image, and on every re-run with the same inputs and seed. This is an explicit methodology commitment, achieved through coordinated mechanisms in the algorithm design. See Determinism & Provenance for the scope, the mechanisms and what is out of scope.

  • Declaration order invariance — Optimisation results are bit-for-bit identical regardless of the order in which entities are declared in input files; Novomodelo orders the entities of each kind by operational start date, then by ID, before it builds any stage problem. Reordering hydro plants, thermal units, or transmission lines in the case configuration produces no change in the computed policy or bounds. This property is critical for programmatic workflows where input files are assembled by tools rather than edited by hand.

  • Agent-readability — A run writes its results as JSON and Parquet files whose layouts the Reference pages document, alongside human-readable progress output, so programmatic tools can compose, monitor and verify Novomodelo workflows.

Novomodelo reads its own case format: a case directory of JSON and Parquet input files. A case prepared for a supported hydrothermal planning tool is converted into a Novomodelo case by novomodelo-bridge, a separate Python package; Converting an existing case covers what it converts and how to compare the source tool’s results with Novomodelo’s.

Scope and limitations. Every stage problem is a linear programme, so Novomodelo has no integer unit-commitment decisions. The transmission network is a transport model: each line carries flow between two buses, up to a capacity in each direction, and no power-flow equations apply. The stage problems are lossless: transmission losses do not enter them, and Novomodelo computes them from the solved flows and reports them in the simulation results.

What differs. Novomodelo represents every hydro plant individually, with its own storage, generation model and, where it has one, downstream plant. A converted case solved by Novomodelo is not expected to reproduce another tool’s results exactly, because the two models can differ in formulation, inflow model and stopping rule. For equivalent terms in other planning tools, see the Glossary.

  • The SDDP Framework in One Page — one-page algorithmic framing: forward simulation, backward cut generation, and convergence bounds
  • How to Read This Site — navigation guide for the site’s sidebar groups and reading paths for different readers
  • SDDP Algorithm — full algorithmic treatment: stage LPs, cut generation, convergence theory
  • Determinism & Provenance — per-binary bit-identical scope, coordinating mechanisms, and what each run records