Skip to content

Block Formulation Variants

This chapter defines the two block formulations supported by Novomodelo — parallel and chronological — which determine how intra-stage time periods (e.g., peak, off-peak, or hourly resolution) are handled in the LP. The choice of block formulation affects water balance constraints, LP size, and the ability to model intra-stage storage dynamics.

For the variable and set definitions used here, see Notation Conventions. For how blocks integrate into the full LP, see LP Formulation. For the system elements that participate in block constraints, see System Element Modeling Overview.

In parallel blocks mode, all blocks within a stage are independent — there is no intra-stage storage dynamics.

A single water balance constraint spans all blocks:

vh=vhin+ζ (ah−eh−rh)+∑k∈Kζk net_flowsh,kv_h = v^{in}_h + \zeta \, (a_h - e_h - r_h) + \sum_{k \in \mathcal{K}} \zeta_k \, \text{net\_flows}_{h,k}

where:

  • vhinv^{in}_h is the incoming storage, pinned at v^h\hat{v}_h
  • ζk=0.0036 τk=wk ζ\zeta_k = 0.0036\,\tau_k = w_k\,\zeta is the flow-to-volume conversion of block kk, with τk\tau_k the duration of block kk in hours and wk=τk/∑k′∈Kτk′w_k = \tau_k / \sum_{k' \in \mathcal{K}} \tau_{k'} the block weight, so the block conversions sum to the stage conversion, ∑k∈Kζk=ζ\sum_{k \in \mathcal{K}} \zeta_k = \zeta
  • aha_h is the stage’s realized incremental inflow
  • ehe_h is the net evaporation: one stage-level value on (vhin+vh)/2(v^{in}_h + v_h)/2, whatever the block count
  • rhr_h is the stage-level withdrawal target
  • net_flowsh,k\text{net\_flows}_{h,k} is the net flow of block kk: the turbined and spilled release credited from upstream and the flows diverted and pumped in, minus the plant’s own turbined, spilled and diverted flow and its pumped-out flow

This formulation assumes the reservoir can freely redistribute water across blocks within the stage. The canonical row with every term — the in-transit arrivals, the travel-time shares and the withdrawal and inflow slacks — is LP Formulation §4.

AspectDescription
LP sizeSmaller: one water-balance row per hydro and one evaporation row per evaporating hydro
Storage dynamicsEnd-of-stage only
Use caseLong-term strategic planning
ConfigurationSelected per stage in the case’s stage definitions (Stage Files)

In chronological blocks mode, blocks are sequential within each stage, enabling modeling of intra-stage storage dynamics (e.g., daily cycling patterns within a monthly stage).

VariableDomainUnitsDescription
vh,kv_{h,k}[V‾h,Vˉh][\underline{V}_h, \bar{V}_h]hm³Storage at end of block kk

The end-of-stage storage (state variable) is: vh=vh,∣K∣v_h = v_{h,|\mathcal{K}|}

For every block k∈Kk \in \mathcal{K}, with vh,0=vhinv_{h,0} = v^{in}_h (the incoming storage, pinned at v^h\hat{v}_h):

vh,k=vh,k−1+ζk (ah−eh,k−rh+net_flowsh,k)v_{h,k} = v_{h,k-1} + \zeta_k \, \big( a_h - e_{h,k} - r_h + \text{net\_flows}_{h,k} \big)

net_flowsh,k\text{net\_flows}_{h,k} credits the upstream release of block kk in full; for an upstream plant on a travel-time arc into hh, the row of block kk instead credits the per-block same-stage shares of that plant’s release in blocks k′≤kk' \le k (LP Formulation — Chronological-Stage Rows).

Block kk receives ζk ah=wk ζ ah\zeta_k\,a_h = w_k\,\zeta\,a_h of the stage’s inflow and the share wkζσm(t)εtw_k \zeta \sigma_{m(t)} \varepsilon_t of its innovation. Each block chains its storage from the previous block’s end storage vh,k−1v_{h,k-1}, so the per-block boundaries vh,0=v^h,vh,1,…,vh,∣K∣v_{h,0} = \hat{v}_h, v_{h,1}, \ldots, v_{h,|\mathcal{K}|} form a within-stage storage trajectory.

Summing the block rows over k∈Kk \in \mathcal{K} gives:

vh=vhin+ζ (ah−rh)−∑k∈Kζk eh,k+∑k∈Kζk net_flowsh,kv_h = v^{in}_h + \zeta \, (a_h - r_h) - \sum_{k \in \mathcal{K}} \zeta_k \, e_{h,k} + \sum_{k \in \mathcal{K}} \zeta_k \, \text{net\_flows}_{h,k}

This is the §1.1 row with the per-block evaporation ∑k∈Kζk eh,k\sum_{k \in \mathcal{K}} \zeta_k\,e_{h,k} in place of ζ eh\zeta\,e_h and, on a travel-time arc, per-block same-stage shares of the upstream release (see LP Formulation — Summing the Block Rows).

Each block’s hydro production (FPHA) and evaporation are evaluated on that block’s own average storage (vh,k−1+vh,k)/2(v_{h,k-1} + v_{h,k})/2, rather than the single stage-average storage that parallel mode shares across all blocks. Each storage coefficient therefore enters the block-kk row as minus half its value on both bounding storage columns vh,k−1v_{h,k-1} and vh,kv_{h,k}, so the block sees the mean of its entry and exit storage: the FPHA plane storage coefficient γvm\gamma_v^m, apportioned to cell (h,b)(h,b) by λh,b\lambda_{h,b}, as −λh,b γvm/2-\lambda_{h,b}\,\gamma_v^m/2 in that cell’s row for the plane, and the evaporation storage slope γv,hev\gamma^{ev}_{v,h} as −γv,hev/2-\gamma^{ev}_{v,h}/2 in the evaporation row. This lets a chronological stage capture the head and evaporative-area variation that tracks the within-stage storage trajectory.

On a parallel stage the plant keeps one stage-level evaporation on (vhin+vh)/2(v^{in}_h + v_h)/2 whatever its block count; per-block evaporation exists only on a chronological stage.

Only end-of-stage storage is a state variable:

vh=vh,∣K∣v_h = v_{h,|\mathcal{K}|}

Inter-block storages vh,kv_{h,k} for k<∣K∣k < |\mathcal{K}| are internal LP variables — not state variables. This ensures:

  1. Cuts are computed with respect to end-of-stage storage only
  2. State dimension does not increase with number of blocks

In chronological mode, the incoming storage LP variable vhinv^{in}_h is pinned to its trial value v^h\hat{v}_h by equal column bounds (see State Augmentation §2). The reduced cost of that pinned column gives the storage cut coefficient directly:

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

By the LP envelope theorem, this reduced cost automatically captures all downstream effects through the chain of inter-block water balances (vhin→vh,1→…→vh,∣K∣v^{in}_h \to v_{h,1} \to \ldots \to v_{h,|\mathcal{K}|}), FPHA constraints, and generic constraints. No special handling or dual combination is required. See Cut Management.

AspectDescription
LP sizeLarger: Nhydro×(∣K∣−1)N_{hydro} \times (\lvert\mathcal{K}\rvert - 1) more storage columns and water-balance rows, and ∣K∣\lvert\mathcal{K}\rvert evaporation rows (each with its evaporation column and two slack columns) per evaporating hydro instead of one
Storage dynamicsIntra-stage cycling modeled
Use caseShort-term planning with storage cycling
ConfigurationSelected per stage in the case’s stage definitions (Stage Files)

The figure contrasts the two modes for one hydro hh. In the parallel panel one water balance takes the incoming storage vhinv^{in}_h to the end-of-stage storage vhv_h, and FPHA and evaporation are evaluated on (vhin+vh)/2(v^{in}_h + v_h)/2 (§1.1, §2.4). In the chronological panel the block rows chain vhin=vh,0→vh,1→⋯→vh,∣K∣=vhv^{in}_h = v_{h,0} \to v_{h,1} \to \cdots \to v_{h,|\mathcal{K}|} = v_h, and block kk evaluates FPHA and evaporation on its own average (vh,k−1+vh,k)/2(v_{h,k-1} + v_{h,k})/2 (§2.2, §2.4). Of the storages in either panel, the cut built at the stage reads only the incoming storage vhinv^{in}_h under both modes: its storage coefficient is the reduced cost of the pinned vhinv^{in}_h column (§2.6), and the interior storages vh,kv_{h,k}, k<∣K∣k < |\mathcal{K}|, enter no cut (§4).

ParallelChronologicalincoming storage vⁱⁿone balance over all blocksend-of-stage storage vvⁱⁿ = v₀block 1 → v₁…block |K| → v FPHA, evaporation on (vⁱⁿ + v)/2on (vₖ₋₁ + vₖ)/2on (vₖ₋₁ + vₖ)/2on (vₖ₋₁ + vₖ)/2
AspectParallel BlocksChronological Blocks
Water balance1 per hydro per stage∣K∣\lvert\mathcal{K}\rvert per hydro per stage
Inter-block storageNot modeledExplicit continuity
State variablesEnd-of-stage onlyEnd-of-stage only
LP variablesFewerMore
LP constraintsFewerMore
Intra-stage dynamicsNoneFull

4. Cut Portability Across Block Structures

Section titled “4. Cut Portability Across Block Structures”

The block structure of a stage (its block set K\mathcal{K}, the durations τk\tau_k, and the parallel or chronological formulation) shapes the stage LP but not the state that links consecutive stages. A cut trained under one block structure is therefore written in coordinates that every other block structure shares (§4.1), but it keeps its meaning only for the model it was trained on (§4.2).

4.1 Why cuts are block-structure-independent coordinates

Section titled “4.1 Why cuts are block-structure-independent coordinates”

Only end-of-stage storage vhv_h is carried as storage state (§2.5); the interior block storages vh,kv_{h,k} for k<∣K∣k < |\mathcal{K}| are internal LP variables. A cut is an affine function of the incoming state vector, whose coordinates (end-of-stage storage plus any inflow lags and augmented state slots) do not depend on how many blocks a stage carries or on whether they are parallel or chronological. The storage cut coefficient βhv\beta^v_h is the reduced cost of the pinned incoming-storage column vhinv^{in}_h (§2.6), and that column pins the same coordinate, the incoming storage v^h\hat{v}_h, under every block structure. A cut trained under one partition is therefore an affine function of the same state vector under another, and it loads into the other partition’s stage LP without transformation: each coefficient multiplies the coordinate it was computed for.

4.2 What a cut means under another partition

Section titled “4.2 What a cut means under another partition”

A cut is a valid lower approximation of the cost-to-go of the model it was trained on (Cut Management — when bounds and certificates hold). A different block partition, different block durations, or the other formulation defines a different stage model, with its own stage costs and feasible sets and therefore its own cost-to-go. The trained cuts need not lie below that cost-to-go; depending on how the two models differ, they can underestimate or overestimate it.

A policy evaluated under another partition is therefore a heuristic with no bound guarantee. The lower bound reached in training bounds the optimal value of the trained model; it need not bound the other model’s optimal value from below, and the optimality gap between it and a cost simulated under the other partition certifies nothing. The simulated cost estimates what the policy costs in the other model, and nothing bounds how far that lies from the other model’s optimum. Training under a coarse partition and simulating under a finer one is a use of this kind.

Cuts injected as a terminal boundary (Post-Study Boundary & Chained Studies) from a study trained under another partition have the same status: they lower-approximate the source model’s cost-to-go and carry no bound guarantee for a continuation modeled under the current partition.

5. Note on Fine-Grained Temporal Resolution

Section titled “5. Note on Fine-Grained Temporal Resolution”

Novomodelo models one level of temporal decomposition within a stage: the blocks of §1 and §2, each of duration τk\tau_k. A study’s training and simulation solve the same blocks; a policy evaluated under another block partition is the case §4 covers. Novomodelo has no representative-day decomposition, in which a stage is split into weighted day types that each hold chronological sub-daily blocks.

The methodology above defines the two block formulations and what a cut means across them; the tab below covers how Novomodelo’s policy loads treat a change of block structure.

Non-normative software behavior for block formulations — what Novomodelo does at runtime, beyond the equations above. This tab references the methodology body (§4) for cut portability rather than restating it.

What a policy load checks across block structures

Section titled “What a policy load checks across block structures”

A policy load matches a checkpoint to the study on state identity. A full-FCF load (warm-start, resume, simulation-only) compares the state-vector dimension and the per-slot entity manifest, which binds each state coordinate to the entity it was trained on, with the study’s; a boundary load reconciles the source’s slots to the study’s by entity identity. Neither check reads the block mode, the block count, or the block durations. The full sequence is in Policy Management — Check order.

A full-FCF load uses a stored LP basis only when it fits its stage LP (stored-basis gate). A change of block mode or block count that changes the column count of a stage LP therefore leaves that stage’s stored basis out, with one warning, and the load proceeds. On a stage with hydro plants both changes do: the turbine, spillage, and diversion columns are allocated per block, and a chronological stage with more than one block also carries an interior storage column per hydro and interior block boundary that a parallel stage does not.

A boundary load reads no basis, so the same cuts still load through policy.boundary across block modes and block counts.

The checkpoint manifest records the block mode a policy was trained under in its producer block (policy/manifest.bin): training_block_mode holds "parallel" or "chronological" when every stage agrees and "mixed" otherwise, and training_block_mode_per_stage lists each stage’s mode, in study-stage order, for a mixed study only. Both fields are descriptive: no policy load checks them.