Skip to content

Hydro Production Function Models

This spec defines the hydro generation constraint models supported by Cobre, which relate turbined flow and reservoir storage to electrical output. Two models are available during training (policy construction): constant productivity and FPHA. A third model — linearized head — is available only during simulation (policy evaluation) as a higher-fidelity enhancement. The choice among training models trades off accuracy vs. computational cost, and can vary by stage per hydro.

All decision variables use rate units (MW, m³/s) — see the Variable Units Convention in system elements. For variable definitions see notation conventions; for LP integration see LP formulation; for hydro element descriptions see system elements.

The simplest model assumes a linear relationship:

gh,k=ρh,tqh,kg_{h,k} = \rho_{h,t} \cdot q_{h,k}

where ρh,t\rho_{h,t} (MW per m³/s) is the hydro productivity for stage tt:

ρh,t=9.81×ηh×Hh,tref1000\rho_{h,t} = \frac{9.81 \times \eta_h \times H^{ref}_{h,t}}{1000}

with:

  • ηh\eta_h = turbine efficiency (typically 0.85–0.92), from the hydro object’s efficiency field
  • Hh,trefH^{ref}_{h,t} = reference net head (meters), typically at 65% storage, varying by stage

Per-stage productivity: the productivity coefficient is authored per (hydro, stage) rather than per plant. A plant can therefore carry a stage-varying constant productivity — useful when the reference head differs between near-term and far-future stages of the same study, or when the constant model is being used as a coarse approximation that needs different operating points across the horizon. Section 5.1 describes how that per-(hydro, stage) value is resolved at load time.

LP treatment: 1 equality constraint per hydro per block. The generation variable gh,kg_{h,k} is fully determined by qh,kq_{h,k} — no free generation variable is needed. Simple and fast, but ignores head variation with storage within a stage.

Data requirements: a per-stage productivity scalar per hydro plant. No geometry or hyperplane data needed.

2. FPHA (Função de Produção Hidrelétrica Aproximada)

Section titled “2. FPHA (Função de Produção Hidrelétrica Aproximada)”

For accurate modeling of hydroelectric generation, FPHA (Aproximate Hydropower Production Function) captures the nonlinear relationship between storage, flow, spillage, and generation through a piecewise-linear approximation.

This section uses consistent notation with the LP formulation. The following table maps Cobre symbols to equivalent Portuguese terminology for practitioners familiar with DECOMP/DESSEM/NEWAVE:

CobrePortuguese (practitioner reference)DescriptionUnits
ϕ\phiFPHHydro production functionMW
vvVVReservoir storagehm³
qqQQTurbined flowm³/s
ssSS / QverQ_{ver}Spillagem³/s
ghg_hGHHydro generationMW
hforeh_{fore}hmonh_{mon} (montante)Forebay (upstream) levelm
htailh_{tail}hjush_{jus} (jusante)Tailrace (downstream) levelm
hneth_{net}hliqh_{liq} (líquida)Net headm
hlossh_{loss}hPerdHh_{PerdH} (perda hidráulica)Hydraulic lossesm
qoutq_{out}QjusQ_{jus}Total downstream outflowm³/s

The exact hydroelectric production function relates generation to the operating state:

ϕ(v,q,s)=ρespqhnet\phi(v, q, s) = \rho_{esp} \cdot q \cdot h_{net}

where:

  • vv = reservoir storage volume (hm³)
  • qq = turbined flow (m³/s)
  • ss = spillage flow (m³/s)
  • hneth_{net} = net head (m), clamped to 0\ge 0
  • ρesp=9.81ηh/1000\rho_{esp} = 9.81\,\eta_h / 1000 (MW·s/m⁴), with constant efficiency ηh\eta_h per plant (default 1.0)

The net head is computed as:

hnet(v,q,s)=hfore(v)htail(q+s)hlossh_{net}(v, q, s) = h_{fore}(v) - h_{tail}(q + s) - h_{loss}

clamped to max(hnet,0)\max(h_{net}, 0), where:

  • hfore(v)h_{fore}(v) = forebay (upstream reservoir) level as function of storage
  • htail(q+s)h_{tail}(q + s) = tailrace (downstream channel) level as function of total outflow
  • hlossh_{loss} = hydraulic head losses (from the factor or constant model)

Why linearization is needed: ϕ\phi is nonlinear in (v,q)(v, q) due to the bilinear product q×hnetq \times h_{net}, nonlinear topology functions hfore(v)h_{fore}(v) and htail(qout)h_{tail}(q_{out}), and flow-dependent hydraulic losses. For LP formulation, Cobre approximates ϕ\phi with a set of linear hyperplanes.

Cobre uses tabular data with linear interpolation for the forebay curve — more transparent and easier to validate against surveyed data than polynomial fits.

Forebay Level hfore(v)h_{fore}(v)

Section titled “Forebay Level hfore(v)h_{fore}(v)hfore​(v)”

The upstream water level is read from the volume-height curve in hydro_geometry.parquet. For storage vv where viv<vi+1v_i \leq v < v_{i+1}:

hfore(v)=hi+hi+1hivi+1vi×(vvi)h_{fore}(v) = h_i + \frac{h_{i+1} - h_i}{v_{i+1} - v_i} \times (v - v_i)

Tailrace Level htail(qout)h_{tail}(q_{out})

Section titled “Tailrace Level htail(qout)h_{tail}(q_{out})htail​(qout​)”

The downstream water level depends on total outflow. Three representations are supported:

Polynomial model (type: "polynomial"):

htail(qout)=c0+c1qout+c2qout2+c3qout3+c4qout4h_{tail}(q_{out}) = c_0 + c_1 q_{out} + c_2 q_{out}^2 + c_3 q_{out}^3 + c_4 q_{out}^4

Piecewise-linear model (type: "piecewise"): tabular breakpoints with linear interpolation between points.

Piecewise-quartic families (exact tailrace): an optional per-plant tailrace table provides piecewise degree-4 polynomial segments (evaluated via Horner’s method), grouped into backwater families keyed by the downstream reservoir’s reference forebay level — see §2.3.1.

Total downstream flow in LP: qout=q+sq_{out} = q + s (turbined flow + spillage). For FPHA fitting, spillage is fixed at s=0s = 0 when building the generation cloud; the lateral-flow secant (§2.7) captures the spillage correction per plane.

2.3.1 Piecewise-Quartic Tailrace Families (Backwater Coupling)

Section titled “2.3.1 Piecewise-Quartic Tailrace Families (Backwater Coupling)”

When plants are hydraulically close, plant ii‘s tailrace level depends on the downstream reservoir’s forebay. An optional per-plant tailrace table provides piecewise-quartic tailrace segments: the flow domain [Qjus,lo,Qjus,hi][Q_{jus,lo}, Q_{jus,hi}] is split into contiguous segments, each a degree-4 polynomial

htail(k)(qjus)=a0(k)+a1(k)qjus+a2(k)qjus2+a3(k)qjus3+a4(k)qjus4h_{tail}^{(k)}(q_{jus}) = a_0^{(k)} + a_1^{(k)} q_{jus} + a_2^{(k)} q_{jus}^2 + a_3^{(k)} q_{jus}^3 + a_4^{(k)} q_{jus}^4

evaluated via Horner’s method for numerical stability. C0 continuity between segments is enforced to ~1 mm. These segments are grouped into backwater families keyed by the downstream reservoir’s reference forebay level (HrefJusHrefJus, in metres). At fitting time, the active family is linearly interpolated by the downstream plant’s resolved stage reference level — clamped to the calibrated level range, never extrapolated. Plants with a single keyless family (no backwater coupling) evaluate that family directly regardless of the downstream level. Plants without a tailrace table use the entity-level polynomial or piecewise-linear tailrace.

Two models are supported:

Factor model — proportional to gross head:

hloss=kloss×(hforehtail)h_{loss} = k_{loss} \times (h_{fore} - h_{tail})

where klossk_{loss} is typically 0.01–0.05 (1–5% losses).

Constant model — fixed head loss:

hloss=Δhconst(metres)h_{loss} = \Delta h_{const} \quad \text{(metres)}

The specific productivity ρesp\rho_{esp} (MW per (m³/s · m)) converts hydraulic power to electrical power:

ρesp,h=9.81×ηh1000\rho_{esp,h} = \frac{9.81 \times \eta_h}{1000}

so the exact production is ϕ=ρespqhnet\phi = \rho_{esp} \cdot q \cdot h_{net} in MW. Cobre uses constant efficiency ηh\eta_h per plant.

FPHA plants author ρesp\rho_{esp} directly — not a single scalar productivity ρ\rho. The equivalent productivity ρeq\rho_{eq} at the reference operating point is derived from ρesp\rho_{esp} and the VHA geometry; the derivation is documented in section 5.1.

The FPHA approximation replaces the nonlinear production function ϕ(v,q,s)\phi(v, q, s) with a set of MM linear hyperplanes that form a concave outer approximation of the exact surface. Each hyperplane mm defines an upper bound on generation:

gh,kγ0m+γvmvhavg+γqmqh,k+γsmsh,kg_{h,k} \leq \gamma_0^m + \gamma_v^m \cdot v_h^{avg} + \gamma_q^m \cdot q_{h,k} + \gamma_s^m \cdot s_{h,k}

Physical interpretation of coefficients:

CoefficientSignMeaning
γ0\gamma_0> 0Intercept (MW at zero storage, flow, spillage)
γv\gamma_v≥ 0Higher storage → higher forebay → more generation
γq\gamma_q≥ 0More turbined flow → more generation
γs\gamma_s≤ 0More spillage → higher tailrace → less net head

Source of hyperplanes: planes are either pre-computed (read from fpha_hyperplanes.parquet) or computed from topology data during preprocessing. The computed fit is described in §2.6.

The computed-FPHA path produces hyperplanes from topology data in four stages: convex-hull fit → αFPHA\alpha_{FPHA} correction → lateral-flow secant → optional plane reduction. The fit is resolved per production-model entry (per season or stage range), so planes can differ across the horizon for the same plant. Results are expanded to per-stage hyperplane rows.

The fitter evaluates the exact production function ϕ=ρespqhnet\phi = \rho_{esp} \cdot q \cdot h_{net} on a uniform two-dimensional grid over the fitting window, with spillage s=0s = 0 and lateral flow =0= 0. The grid has:

  • Volume axis: volume_discretization_points uniformly spaced values spanning the fitting window [vmin,vmax][v_{min}, v_{max}] (default 5 points). The window is set by the optional fitting_window block inside fpha_config (absolute volume_min_hm3 / volume_max_hm3 or percentile bounds), defaulting to the plant’s full forebay storage range. It is distinct from reference_volume (§5.1), which fixes an operating point, not this window.
  • Flow axis: turbine_discretization_points uniformly spaced values spanning [0,qmax][0, q_{max}] (default 5 points). The axis starts at q=0q = 0, where generation is zero; this zero-flow column anchors the lower closure of the cloud and eliminates the need for any synthetic closing point.

Each cloud point is capped at the plant’s installed capacity Gˉh\bar{G}_h. Spillage is not a cloud dimension — it is fixed at zero throughout.

Run-of-river plants: when the plant has a single fitting volume (vminvmaxv_{min} \approx v_{max}), two volume samples ~1% of useful storage apart are synthesized to keep the 3-D hull non-degenerate. The resulting γV\gamma_V residual is then snapped to exactly 0, enforcing the correct run-of-river semantics (γV=0\gamma_V = 0).

Determinism: the cloud points and the hull output are canonically sorted, so the fitted hyperplanes are bit-identical regardless of input ordering and MPI rank count.

The 3-D convex hull of the (V,Q,generation)(V, Q, \text{generation}) cloud is computed via the qhull library. The upper-envelope facets — those whose outward normal has a positive generation component — are selected. Each is read as generation=γ0+γVV+γQQ\text{generation} = \gamma_0 + \gamma_V V + \gamma_Q Q. The result is a concave outer approximation (the smallest concave function lying above ϕ\phi); non-concave regions of ϕ\phi fall inside the hull and their facets drop out. Near-parallel coplanar facets arising from hull triangulation are deduplicated by exact coefficient comparison.

2.6.3 Least-Squares αFPHA\alpha_{FPHA} Correction

Section titled “2.6.3 Least-Squares αFPHA\alpha_{FPHA}αFPHA​ Correction”

The raw hull envelope FPHA0FPHA_0 is optimistic where ϕ\phi is non-concave and pessimistic where it is concave. A single scalar αFPHA\alpha_{FPHA} corrects the bias by minimising the mean-squared error between αFPHAFPHA0\alpha_{FPHA} \cdot FPHA_0 and the exact ϕ\phi over the spill=0=0 grid:

αFPHA=i,jFPHA0(Vi,Qj)ϕ(Vi,Qj)i,jFPHA0(Vi,Qj)2,FPHA=αFPHAFPHA0\alpha_{FPHA} = \frac{\sum_{i,j} FPHA_0(V_i,Q_j)\,\phi(V_i,Q_j)}{\sum_{i,j} FPHA_0(V_i,Q_j)^2}, \qquad FPHA = \alpha_{FPHA}\cdot FPHA_0

Key properties:

  • The regression uses the pointwise minimum over the raw hull planes as FPHA0(Vi,Qj)FPHA_0(V_i, Q_j), because the LP applies planes as gγ0m+γVmV+γQmQg \le \gamma_0^m + \gamma_V^m V + \gamma_Q^m Q for every mm, so the binding cap is the minimum, not the maximum.
  • The regression is over the spill=0=0 grid only — adding a spillage axis would pull αFPHA\alpha_{FPHA} toward the larger-deviation spill region and degrade the no-spill operating region.
  • αFPHA\alpha_{FPHA} scales the whole affine function (γ0,γV,γQ\gamma_0, \gamma_V, \gamma_Q alike), not just the intercept. This is why αFPHAκ\alpha_{FPHA} \ne \kappa (the old intercept-only shrink).
  • αFPHA\alpha_{FPHA} may be greater or less than 1 (an MSE balance, not a one-sided shrink). Validation requires αFPHA>0\alpha_{FPHA} > 0. A degenerate denominator (all-zero production) yields the neutral αFPHA=1\alpha_{FPHA} = 1.
  • Validation also requires γV0\gamma_V \ge 0, γQ0\gamma_Q \ge 0, γS0\gamma_S \le 0.

Fit-quality diagnostic: after the full pipeline, the relative mean-absolute-deviation of the emitted min-envelope vs the exact ϕ\phi over the spill=0=0 grid is computed. A warning is emitted (in canonical plant/stage order) when it exceeds 5% — typically indicating a strongly non-concave surface that no single αFPHA\alpha_{FPHA} can track well.

Precomputed input: when using source: "precomputed", hyperplanes are read directly from fpha_hyperplanes.parquet. That file retains a kappa column (defaulting to 1.0); for precomputed planes it is still applied as an intercept-only scale (γ0γ0κ\gamma_0 \leftarrow \gamma_0 \cdot \kappa) and is validated to lie in (0,1](0, 1]. Only the computed path retired κ\kappa — there the whole-affine αFPHA\alpha_{FPHA} correction above replaces it.

Spillage raises the tailrace level, lowering net head and generation. The γS\gamma_S coefficient for each plane is fit by a per-plane 1-D ordinary-least-squares secant of generation vs lateral flow (in the current default: own spillage ss) over 9 evenly-spaced samples of qlat[0,Smax]q_{lat} \in [0, S_{max}], evaluated at the plane’s representative (active-maximum) operating point:

Smax={2MLTif MLT>02qmaxif MLT=0S_{max} = \begin{cases}2 \cdot \text{MLT} & \text{if MLT} > 0 \\ 2 \cdot q_{max} & \text{if MLT} = 0\end{cases}

where MLT is the long-term mean inflow (m³/s). The representative operating point for each plane is the spill=0=0 grid point where that plane is the active (tightest) upper bound and attains the largest generation — the operating region the plane actually governs. The secant samples the uncapped production function ϕ\phi (not clipped at installed capacity Gˉh\bar{G}_h), so the spillage sensitivity is read from the raw head curve and is not flattened wherever the capacity ceiling binds — unlike the cloud and the αFPHA\alpha_{FPHA} regression (§2.6), which both use the capacity-capped output.

Sign: γS0\gamma_S \le 0 (more lateral flow raises the tailrace, reduces generation). Near-zero slopes γS<1010|\gamma_S| < 10^{-10} of either sign are snapped to exactly 0 to protect LP column scaling from near-zero structural coefficients.

Default lateral axis: own spillage (qlat=sq_{lat} = s). The more general QjusQ_{jus} composition (upstream defluences, post-incremental inflows with participation factors) is a deferred future extension.

An optional post-fit step merges consecutive near-parallel or near-coincident planes into their mean hyperplane to shrink the LP. Two mutually-exclusive methods are supported, configured via an fpha_plane_reduction block:

  • Angle (method: angle, tolerance in degrees): merge consecutive pairs whose normal-vector angle θ=arccos(n1n2/n1n2)\theta = \arccos(\mathbf{n}_1 \cdot \mathbf{n}_2 / \|\mathbf{n}_1\|\|\mathbf{n}_2\|) satisfies θ<ε\theta < \varepsilon (strict). Fully deterministic from coefficients.
  • Distance (method: distance, tolerance in percent + sample count): merge consecutive pairs whose normalised mean-squared generation difference δ=EQM/Gˉh2<ε/100\delta = \text{EQM}/\bar{G}_h^2 < \varepsilon/100. Uses a deterministically-seeded PRNG (seeded from stable plant/stage/plane-pair identity, never from wall clock or MPI rank), so results are bit-identical across input ordering and rank count.

Origin-plane invariant: the plane through the origin (γ00γV0\gamma_0 \approx 0 \wedge \gamma_V \approx 0, generating zero power at zero turbining) is never merged. This guarantees the zero-generation floor.

Off by default: no reduction is applied unless an fpha_plane_reduction block is present in the production-models config.

For each hydro hh using FPHA, block kk, and plane mMhm \in \mathcal{M}_h:

gh,kγ0m+γvmvhavg+γqmqh,k+γsmsh,kg_{h,k} \leq \gamma_0^m + \gamma_v^m \cdot v_h^{avg} + \gamma_q^m \cdot q_{h,k} + \gamma_s^m \cdot s_{h,k}

The coefficients are already αFPHA\alpha_{FPHA}-scaled — there is no separate pre-scaling step. These are hard constraints — no slack variables. Feasibility is ensured through the turbined_cost regularization mechanism (see section 2.10).

The average storage vhavgv^{avg}_h over the stage:

vhavg=vhin+vh2v^{avg}_h = \frac{v^{in}_h + v_h}{2}

where vhinv^{in}_h is the incoming storage LP variable (pinned to v^h\hat{v}_h via column bounds — see LP Formulation §4a) and vhv_h is end-of-stage storage. Both are LP variables, so vhinv^{in}_h appears in the FPHA constraint with coefficient γvm/2\gamma_v^m / 2. The LP solver automatically accounts for this in the reduced cost of the pinned vhinv^{in}_h column.

When using FPHA, the generation variable gh,kg_{h,k} is not directly computed from turbined flow. Instead:

  1. Generation is a free LP variable bounded by [0,Gˉh][0, \bar{G}_h] (user-defined bounds from hydros.json)
  2. FPHA constraints (one per plane mm) provide upper bounds relating generation to storage, flow, and spillage
  3. The optimizer maximizes generation subject to FPHA constraints
  4. At optimum, generation lies on one of the FPHA hyperplane facets

Key insight: Because minimizing cost includes maximizing hydro generation (which has zero fuel cost), the optimizer naturally pushes generation to the FPHA surface boundary. The turbined_cost regularization (section 2.10) ensures the solution lies on the boundary rather than at an interior point.

A small regularization cost chtc^{t}_h is applied to the turbined flow variable of every hydro in the objective:

kτkchtqh,k\sum_{k} \tau_k \cdot c^{t}_h \cdot q_{h,k}

This cost must satisfy cht>chspillc^{t}_h > c^{spill}_h for each plant. The rule serves two purposes.

For hydros using the FPHA production model, the regularization keeps the solver on the FPHA surface boundary rather than at an interior point: without it, the optimizer could find degenerate solutions where turbined flow and spillage are both artificially high (with net generation unchanged), because the FPHA surface has a flat region where increasing qq and ss simultaneously can maintain the same gg. The penalty making every unit of turbined flow carry a small additional cost collapses the degenerate interior region.

For hydros using constant productivity, the same regularization is applied uniformly so that the LP tie-breaks (turbined, spillage) decompositions consistently with NEWAVE. Applying it uniformly rather than only under FPHA matters on cases that mix the two production models: a constant-productivity plant that paid nothing on the turbine column would diverge from the reference model. Plants using linearized_head (simulation-only, see section 3) are not subject to this regularization during training because training uses only constant_productivity and fpha; during simulation, the cost is irrelevant because no policy is being constructed.

For the full penalty taxonomy and priority ordering, see Penalty System.

The FPHA formulation affects water value computation. Because the incoming storage variable vhinv^{in}_h appears in the FPHA constraint (via vhavg=(vhin+vh)/2v^{avg}_h = (v^{in}_h + v_h)/2, section 2.9), the FPHA hyperplane duals contribute to the marginal value of incoming storage. However, the implementation does not require manually combining duals from the water balance and FPHA constraints. Instead, pinning vhinv^{in}_h to v^h\hat{v}_h by column bounds (see LP Formulation §4a) makes its reduced cost capture the total sensitivity Qt/v^h\partial Q_t / \partial \hat{v}_h automatically — the LP solver propagates the FPHA contribution through vhinv^{in}_h.

The cut coefficient for storage is simply the reduced cost of the pinned vhinv^{in}_h column:

πhv=cˉhin/dhcol\pi^v_h = \bar{c}^{in}_h / d^{col}_h

This dual implicitly includes the water balance contribution (πhwb\pi^{wb}_h), the FPHA contribution (12mπmfphaγvm\frac{1}{2} \sum_m \pi_m^{fpha} \cdot \gamma_v^m), and any generic constraint contributions — all resolved by the LP solver without explicit dual combination.

For the complete cut coefficient computation, see cut management.

When a hydro transitions between production models across stages:

TransitionCut InterpretationAction
Constant → FPHACuts at stage tt use constant modelCut valid but conservative
FPHA → ConstantStage t+1t+1 backward pass uses constantMay overestimate value
FPHA → FPHA (different params)Parameters changeCuts remain valid if conservative

Recommendation: When using stage-dependent FPHA configuration, ensure the FPHA at stage tt is at least as conservative as stage t+1t+1 for cut validity.

3. Linearized Head Model (Simulation-Only Enhancement)

Section titled “3. Linearized Head Model (Simulation-Only Enhancement)”

An intermediate model between constant productivity and full FPHA that captures first-order head variation with storage:

gh,k=ρrefqh,k(k0+kVvhavg)g_{h,k} = \rho_{ref} \cdot q_{h,k} \cdot \left( k_0 + k_V \cdot v_h^{avg} \right)

where:

  • k0,kVk_0, k_V are linearization coefficients derived from hfore(v)h_{fore}(v)
  • k0=1kVVrefk_0 = 1 - k_V \cdot V_{ref} (normalization at reference volume)
  • kV=1HrefdhforedVVrefk_V = \frac{1}{H_{ref}} \cdot \frac{dh_{fore}}{dV}\bigg|_{V_{ref}}

The product qh,kvhavgq_{h,k} \cdot v_h^{avg} is a bilinear term — both qq and vavgv^{avg} are LP variables. To maintain LP linearity, the standard approach fixes vavgv^{avg} from the previous SDDP iteration (or from a reference volume on the first iteration), converting the constraint to a linear equality. However, this means the LP constraint coefficients change between iterations: the effective productivity ρref(k0+kVvfixedavg)\rho_{ref} \cdot (k_0 + k_V \cdot v^{avg}_{fixed}) is different after each forward pass updates the storage trajectory.

This violates a foundational assumption of SDDP: each stage must have a fixed LP structure across all iterations. Benders cuts generated under one linearization point encode dual information about a specific LP. When the LP changes (because vfixedavgv^{avg}_{fixed} changed), previously generated cuts are not guaranteed to be valid — they may cut off the true optimal solution or produce inconsistent value function approximations. This breaks the convergence guarantees of the algorithm.

During simulation, linearized head is safe because simulation executes a single forward pass through the policy — there are no cuts being accumulated, no convergence to verify. The model provides a higher-fidelity generation estimate than constant productivity without the preprocessing cost of fitting FPHA hyperplanes.

The linearized head model fills a practical gap in the simulation step:

  • More accurate than constant productivity: Captures how reservoir level affects generation — important for plants with significant head variation that are modeled with constant_productivity during training for computational reasons
  • Cheaper than FPHA: Requires only the Volume-Height-Area curve (hydro_geometry.parquet), no hyperplane fitting
  • Single constraint: One equality constraint per hydro per block, compared to MM inequality constraints for FPHA

Typical use: plants where full FPHA accuracy is justified for near-term training stages but far-future stages use constant_productivity during training, then linearized_head during simulation for improved analytics.

productivity_mw_per_m3s from hydros.json plus hydro_geometry.parquet for the Volume-Height-Area curve.

Only constant_productivity and fpha are valid during training. The linearized head model is excluded because it changes the LP between iterations (see section 3.1).

ScenarioRecommended ModelRationale
High-head storage reservoirsFPHASignificant head variation (>20%)
Large storage variation plantsFPHAOperating across wide volume range
Run-of-river plantsFPHA or ConstantHull now supports run-of-river
Initial algorithm testingConstant productivityFast iteration, debug focus
Near-term stagesFPHAAccuracy for operational decisions
Far-future stagesConstant productivityComputational efficiency

All three models are available during simulation. The linearized head model is particularly useful as a simulation-only upgrade for plants that used constant_productivity during training:

ScenarioRecommended ModelRationale
Plants trained with FPHAFPHAConsistency with training model
Plants trained with constant, low head variationConstant productivityNo benefit from head correction
Plants trained with constant, significant head variationLinearized headBetter analytics without FPHA fitting cost
Post-optimization validationCompare all modelsVerify approximation quality

The production model may vary by stage or by season per hydro, configured via the stage_ranges and seasonal selection modes in hydro_production_models.json.

The three production models of sections 1–3 describe how generation depends on the operating state. For accounting purposes — natural-inflow energy (ENA), stored reservoir energy (EARM), and per-stage MW/MWh reporting — Cobre reduces each plant’s production model to a small set of per-(hydro, stage) scalars at a representative operating point. These scalars are computed once at study setup and reused on every stage of every scenario.

5.1 Equivalent Productivity ρeq\rho_{eq}

Section titled “5.1 Equivalent Productivity ρeq\rho_{eq}ρeq​”

The equivalent productivity ρeq,h,t\rho_{eq,h,t} (MW per m³/s) is the single-scalar productivity that the plant would carry at the reference operating point (Vh,tref,Qh,tref)(V^{ref}_{h,t},\, Q^{ref}_{h,t}). The derivation depends on the active generation model at stage tt:

Generation modelρeq,h,t\rho_{eq,h,t} derivation
constant_productivityA per-(hydro, stage) numeric value authored by the case — see “Authoring sources” below.
linearized_headA per-(hydro, stage) numeric value authored by the case — same resolution as constant_productivity.
fphaρeq,h,t=ρesp,hheq(Vh,tref,Qh,tref)\rho_{eq,h,t} = \rho_{esp,h} \cdot h_{eq}(V^{ref}_{h,t},\, Q^{ref}_{h,t}), where heqh_{eq} is the net head computed from the VHA geometry (section 2.3) at the reference point. FPHA hydros do not author a separate ρeq\rho_{eq} scalar in the production-models input — it is derived. A parquet-level override is still accepted (see “FPHA override path”).

Reference volume: the reference operating volume Vh,trefV^{ref}_{h,t} is declared by a single reference_volume field in the production-model config entry (stage_range or seasonal). The field takes exactly one of two forms: an absolute volume_hm3 value, or a percentile (fraction of useful volume between VminV_{min} and VmaxV_{max}); when absent it defaults to 65% of useful volume. This single field is the source of truth for the ρeq\rho_{eq} derivation above and for the reservoir reference level at which the computed-FPHA piecewise-quartic tailrace families are interpolated (§2.3.1 — a plant’s reference volume sets the downstream forebay level seen by the plant immediately upstream). It does not set the computed-FPHA volume fitting window [Vmin,Vmax][V_{min}, V_{max}]: that window is configured separately by the optional fitting_window block inside fpha_config (§2.6.1), defaulting to the plant’s full forebay storage range.

The reference flow QrefQ^{ref} is typically set at installed turbine capacity.

Two complementary inputs supply ρeq,h,t\rho_{eq,h,t} for constant_productivity and linearized_head plants:

  1. Range-level productivity in the hydro production models input. Each stage_range or seasonal entry may carry a single productivity_mw_per_m3s value that applies to every stage the entry covers. This is the natural authoring shape for “this productivity is the same for the next five stages” — declarative, low-volume.
  2. Per-stage productivity in the hydro energy productivity input (a per-row table indexed by (hydro_id, stage_id)). Each row may name a specific stage or carry a per-hydro default (no stage_id set). This is the natural authoring shape for “this productivity changes every stage” — tabular, high-volume.

Either source — but not both for the same (hydro, stage) — may supply the value. The contract is symmetric with the generic-constraint authoring contract: a declarative JSON file owns model selection plus range-level values, and a tabular parquet file owns per-stage numerical refinement.

For a non-FPHA hydro hh at study stage tt, the value of ρeq,h,t\rho_{eq,h,t} is resolved in this order:

  1. A per-stage row in the energy-productivity input whose stage_id matches tt exactly.
  2. A per-hydro default row in the energy-productivity input (no stage_id set) for hydro hh.
  3. The productivity_mw_per_m3s value from the matching stage_range or seasonal entry in the production-models input.

The first three options are mutually exclusive at load time (see “Conflict and coverage” below), so this ordering is descriptive rather than a precedence in the sense of “earlier source overrides later”; it is the order in which the resolver consults sources, stopping at the first hit.

Two load-time invariants are enforced:

  • Conflict: when the per-stage parquet row (or the per-hydro default) and the production-models JSON entry both supply a value for the same (h,t)(h, t), the case is rejected at load time. The error names both files and the offending (h,t)(h, t).
  • Coverage: when neither source supplies a value for some study stage tt of a non-FPHA hydro hh, the case is rejected at load time. The error names the offending (h,t)(h, t) pair.

A coverage failure never reaches the dispatch pipeline — it is caught alongside the other case-validation rules. This is the same boundary discipline used elsewhere in the load pipeline: structural problems surface as load-time errors, never as deeper dispatch-time panics.

For FPHA hydros, ρeq\rho_{eq} is derived from VHA geometry and ρesp\rho_{esp} at the reference operating point. The per-stage energy-productivity input remains available as an override: if a row supplies a value for an FPHA (h,t)(h, t), it replaces the derived value. The production-models JSON file does not accept productivity_mw_per_m3s for FPHA — that field is rejected at parse time. FPHA hydros are therefore exempt from the non-FPHA conflict and coverage rules.

A resolved ρeq,h,t=0\rho_{eq,h,t} = 0 is accepted for non-FPHA hydros and a resolved ρesp,h=0\rho_{esp,h} = 0 is accepted for FPHA hydros. Both are interpreted as a planned outage for the affected stage: the LP uses these scalars as multipliers (never divisors), so zero productivity produces zero generation cleanly without any divide-by-zero or feasibility hazard. The same relaxation applies to the parquet ρeq\rho_{eq} override, the parquet ρesp\rho_{esp} column, and the JSON range-level productivity. Negative values are still rejected at load time as nonsensical.

This relaxation lets real-world cases mark a plant as out-of-service for specific stages without the case author needing to remove it from the system definition, restructure the cascade, or work around a strict-positivity check.

5.2 Accumulated Cascade Productivity ρacum\rho_{acum}

Section titled “5.2 Accumulated Cascade Productivity ρacum\rho_{acum}ρacum​”

The accumulated productivity ρacum,h,t\rho_{acum,h,t} (MW per m³/s) is the energy that one m³/s of incremental inflow into plant hh contributes once it is routed through plant hh and every plant downstream of hh along the cascade:

ρacum,h,t  =  ρeq,h,t  +  hdownstream(h)ρeq,h,t\rho_{acum,h,t} \;=\; \rho_{eq,h,t} \;+\; \sum_{h' \,\in\, \text{downstream}(h)} \rho_{eq,h',t}

The sum is taken in topological order over the cascade (see system elements for the cascade topology). Plants with no downstream successors have ρacum=ρeq\rho_{acum} = \rho_{eq}. The accumulation is per-stage because each summand can vary by stage.

ρacum\rho_{acum} converts hydraulic quantities to energy units that downstream reporting expects:

Incremental inflow energy (MW):

ENAh,k  =  ρacum,h,tah,k\text{ENA}_{h,k} \;=\; \rho_{acum,h,t} \cdot a_{h,k}

This is the rate-form natural energy inflow in MW. Stagewise energy (MWh) is recovered by multiplying by block duration τk\tau_k in hours.

Stored reservoir energy (MWh):

EARMhinit  =  (VhinitVhmin)ρacum,h,t1063600EARMhfinal  =  (VhfinalVhmin)ρacum,h,t1063600\text{EARM}^{\,\text{init}}_h \;=\; (V^{init}_h - V^{min}_h) \cdot \rho_{acum,h,t} \cdot \frac{10^6}{3600} \qquad \text{EARM}^{\,\text{final}}_h \;=\; (V^{final}_h - V^{min}_h) \cdot \rho_{acum,h,t} \cdot \frac{10^6}{3600}

The conversion factor 106/360010^6 / 3600 converts hm³ to m³ and seconds to hours so that storage in hm³ multiplied by productivity in MW/(m³/s) yields MWh.

These quantities do not enter the LP — they are accounting outputs derived from the LP solution. Their methodology relevance is that they make the production model auditable in the same energy units used by the load forecast and the cost objective.

The full FPHA production function (section 2) is multi-dimensional and concave; constant productivity is a scalar but per-plant; linearized head is bilinear in (q,vavg)(q, v^{avg}). None of these can be summed across a cascade or scaled by inflow without a reference operating point. The energy-conversion scalars resolve this: each model is reduced to one number per (hydro, stage), at one operating point, and that number is what the cascade-summation, ENA, and EARM formulas above can consume uniformly. The LP continues to enforce the full production model — the scalar reduction is for accounting, not for dispatch.

Data SourceRequired FieldsUsed For
Hydro plant entitytailrace (polynomial, piecewise, or piecewise-quartic families)htail(qout)h_{tail}(q_{out}) computation
Hydro plant entityhydraulic_losses (factor or constant)hlossh_{loss} computation
Hydro plant entityefficiency (constant)Turbine efficiency η\eta
Hydro plant entityspecific_productivity_mw_per_m3s_per_m (FPHA)ρesp\rho_{esp} for ρeq\rho_{eq} derivation (§5.1)
Hydro plant entityCascade topology (downstream pointer)ρacum\rho_{acum} topological sum (§5.2)
Hydro production models inputRange-level productivity per stage_range / seasonal entry (non-FPHA, optional)ρh,t\rho_{h,t} for sections 1 and 3 (§5.1 authoring source 1)
Hydro production models inputreference_volume per stage_range / seasonal entry (absolute or percentile)VrefV^{ref} for the energy-conversion reduction (§5.1) and the tailrace backwater reference level (§2.3.1)
Hydro production models inputFPHA fitting_window per stage_range / seasonal entry (absolute or percentile bounds, optional)Computed-FPHA volume grid [vmin,vmax][v_{min}, v_{max}] (§2.6.1)
Hydro production models inputFPHA fitting configuration and optional fpha_plane_reduction blockGrid sizes, plane reduction method (§2.6–§2.8)
Hydro energy productivity inputPer-(hydro, stage) equivalent_productivity_mw_per_m3sρeq,h,t\rho_{eq,h,t} override (§5.1 authoring source 2 + FPHA override path)
Hydro geometryvolume_hm3, height_mhfore(v)h_{fore}(v) interpolation (§2.3)
Pre-fitted FPHA planesγ0,γv,γq,γs\gamma_0, \gamma_v, \gamma_q, \gamma_s (plus kappa column retained for back-compat, defaults to 1.0)Optional alternative to in-process fitting

For non-FPHA hydros, the per-(hydro, stage) productivity coefficient is resolved from exactly one of the two authoring sources listed in §5.1: range-level productivity in the production-models input, or per-stage productivity in the energy-productivity input. Supplying a value from both for the same (h,t)(h, t) is rejected at load time; supplying neither for any study stage of a non-FPHA hydro is also rejected at load time.

For FPHA hydros, the production-models input does not accept a productivity scalar — ρeq\rho_{eq} is derived from VHA geometry and ρesp\rho_{esp} unless the energy-productivity input supplies an override.

  • Notation conventions — variable and set definitions (ghg_h, qhq_h, vhv_h, shs_h, ρh\rho_h)
  • System elements — hydro plant element description, decision variables, Variable Units Convention
  • LP formulation — how production constraints integrate into the assembled LP
  • Penalty systemturbined_cost regularization, penalty priority ordering
  • Cut management — Benders cut generation affected by FPHA dual variables
  • Equipment formulations — thermal and hydro equipment constraint patterns