Skip to content

Scenario Files

The scenarios/ directory holds the stochastic inputs of a case: the inflow history and the inputs of the PAR(p) inflow model, the external scenario libraries, the load and non-controllable-source statistics and factors, the noise correlation, and the user-supplied noise openings. The Parquet column types, the compression rule and the $schema key are described under Conventions.


Methodology: PAR(p) Inflow Model

Historical inflow observation windows per hydro. Every row is a window, not a point-in-time reading: [start_date, end_date) bounds the period and value_m3s is the mean inflow observed over it.

NameTypeRequiredDefaultUnitsDescription
hydro_idInt32Yes——Hydro plant ID
start_dateDate32Yes——Window start, inclusive
end_dateDate32Yes——Window end, exclusive; after start_date
value_m3sFloat64Yes—m³/sMean inflow over the window (m³/s)

Rows may appear in any order. For a given hydro_id, windows must not overlap; adjacent windows (start_date == previous end_date) are accepted. A hydro_id that names no declared hydro is an InvalidReference error. value_m3s must be finite; a negative value is accepted — the quantity is incremental inflow (a plant’s natural flow minus its upstream plants’), so a negative window is real hydrology, and the LP prices it through the inflow non-negativity slack. Semantic validation reports one warning per file naming the negative count and the most-negative value’s hydro.

The history serves four roles:

  • Estimation. The raw observations from which Novomodelo estimates whichever of inflow_seasonal_stats and inflow_ar_coefficients is absent.
  • Derived inflow-lag seed. The default-seeding record from which Novomodelo derives the PAR lag chain and the mid-period accumulator, layered under the recent_observations conditioning of initial_conditions.json wherever the two cover the same date (see initial_conditions.json).
  • Replay windows. The windows of the historical scheme (see Historical Window Pool).
  • Historical-residual openings. The windows of the historical_residuals method (see Historical-Residual Openings).

Methodology: PAR(p) Inflow Model

PAR(p) model seasonal statistics for each (hydro plant, stage) pair. When the file has any row, it needs a row for every hydro in service at each study stage. Under the external inflow scheme, a hydro of autoregressive order 0 (no annual component) takes the mean and standard deviation of the external scenario file, so its rows here are not used to sample; a hydro of autoregressive order above 0 or with an annual component keeps the statistics this file declares (or the ones estimated from inflow_history.parquet when the file is absent). load_seasonal_stats.parquet and non_controllable_stats.parquet are optional for a class sampled under external; a present load_seasonal_stats.parquet keeps its own rule of a row for every bus at every study stage.

NameTypeRequiredDefaultUnitsDescription
hydro_idInt32Yes——Hydro plant ID
stage_idInt32Yes——Stage ID
mean_m3sFloat64Yes—m³/sSeasonal mean inflow (m³/s); must be finite
std_m3sFloat64Yes—m³/sSeasonal standard deviation (m³/s); must be >= 0 and finite

Methodology: PAR(p) Inflow Model

Autoregressive coefficients for the PAR(p) inflow model. The model’s innovation scale is not an input: Novomodelo derives it at load from the coefficients below via the periodic-ACF closure — see PAR(p) Inflow Model.

NameTypeRequiredDefaultUnitsDescription
hydro_idInt32Yes——Hydro plant ID
stage_idInt32Yes——Stage ID
lagInt32Yes——Lag index (1-based)
coefficientFloat64Yes——AR coefficient for this (hydro, stage, lag)

Columns beyond this schema are ignored — a file carrying an extra column (for example a stored innovation-scale ratio produced by another tool) loads with that column ignored outright; the derived value always wins.


Methodology: PAR(p) Inflow Model

PAR(p)-A annual component of each (hydro, stage) pair: the annual coefficient, and the mean and standard deviation of the rolling 12-month average inflow. PAR(p) Inflow Model — Implementation in Novomodelo states when the file is honoured and when estimation overwrites it.

NameTypeRequiredDefaultUnitsDescription
hydro_idInt32Yes——Hydro plant id; names a declared hydro.
stage_idInt32Yes——Stage id of the matching inflow_seasonal_stats.parquet row.
annual_coefficientFloat64Yes——Annual-component coefficient, dimensionless; finite. Negative, zero and positive values are valid.
annual_mean_m3sFloat64Yes—m³/sMean of the rolling 12-month average inflow at the stage; finite.
annual_std_m3sFloat64Yes—m³/sStandard deviation of the rolling 12-month average inflow at the stage; finite and > 0.

Validation rules. Each rule names the error kind that novomodelo validate reports.

  • Row checks. Every column is present with its type, no value is null, annual_coefficient and annual_mean_m3s are finite, and annual_std_m3s is finite and > 0. Kind: SchemaViolation.
  • Declared hydro. A hydro_id that names no declared hydro is an InvalidReference error.
  • Pairing with the statistics. When the case supplies scenarios/inflow_seasonal_stats.parquet, each (hydro_id, stage_id) pair appears once here and has a row there; a repeated pair, or a pair with no statistics row, is a SchemaError. Without a statistics file neither check runs.
  • Season. With a statistics file supplied, every stage that has a row in this file needs a season, from a season_id on the stage or from season_definitions in stages.json; otherwise the case is refused with a ConstraintError.
  • Monthly cycle. PAR(p)-A is monthly-only: when stages.json declares season_definitions, a cycle_type of weekly or custom together with any row here is a BusinessRuleViolation.

scenarios/external_inflow_scenarios.parquet

Section titled “scenarios/external_inflow_scenarios.parquet”

Methodology: Scenario Generation

Pre-computed inflow realizations, read when the inflow scheme is "external" in training.scenario_source or simulation.scenario_source. Realizations are numbered per stage by scenario_id; how the passes draw from them is described in Scenario Generation §4, and which classes take their mean and standard deviation from the file is stated under scenarios/inflow_seasonal_stats.parquet.

NameTypeRequiredDefaultUnitsDescription
stage_idInt32Yes——Declared study-stage id from stages.json (not a 0-based position); >= 0.
scenario_idInt32Yes——0-based realization index at that stage; >= 0.
hydro_idInt32Yes——Hydro plant id; names a declared hydro.
value_m3sFloat64Yes—m³/sInflow value of the realization at the stage; finite.

Validation rules. Each rule names the error kind that novomodelo validate and novomodelo run print.

  • Row checks. Each file is read whenever it is present, whatever the class’s scheme. stage_id >= 0, scenario_id >= 0, a finite value, and no repeated (stage_id, scenario_id, entity) row; a missing column or a column of the wrong type fails the same way. Kind: SchemaViolation.
  • Entity references. An entity id that names no declared hydro, bus or NCS (the entity column of each of the three files) is an InvalidReference error.
  • Scheme with no data. A class whose scheme resolves to external (in training, or in simulation when simulation.scenario_source is declared) while its file is absent or holds no rows is a BusinessRuleViolation on config.json.
  • Library coherence. The following rules read the classes that training.scenario_source samples under external; a class that is external only in simulation.scenario_source is not checked by them.
    • Unresolved stage. Every stage_id must be a declared study-stage id; otherwise InvalidValue.
    • Scenario ids. At each stage every entity that has rows carries exactly the ids 0 to n − 1, once each, where n is the number of distinct scenario_id values at that stage; a 1-based numbering or a gap is a BusinessRuleViolation.
    • One realization axis. Every such class declares the same n at each stage; otherwise BusinessRuleViolation.
    • Constant inflow column (inflow only). A hydro whose values at a stage are all equal (σ = 0) is a BusinessRuleViolation when the hydro has a row in scenarios/inflow_ar_coefficients.parquet or scenarios/inflow_annual_component.parquet; see Deterministic external inflow column under an autoregressive model.
    • Prefix coherence. Under a declared policy_graph.nodes[] graph (see stages.json), the two columns that a transition’s nodes point to must agree at every stage up to the source node’s stage; otherwise a ModelQuality warning.
  • Entity coverage. A class whose scheme resolves to external (in training, or in simulation when simulation.scenario_source is declared) needs at least one row for every entity its noise vector places (see the entity ordering under scenarios/noise_openings.parquet): every declared hydro, every bus with a row in scenarios/load_seasonal_stats.parquet, and every NCS with a row in scenarios/non_controllable_stats.parquet. novomodelo run refuses a class with a missing entity when it sets the study up, with an insufficient data error that names the class and the entity, and exits 1. A class that is external only in simulation.scenario_source is refused with a library width mismatch error (exit 1) when its file adds an entity that the training noise vector does not place: a bus whose std_mw is 0, or an NCS without a non_controllable_stats.parquet row. novomodelo validate reports either refusal on every case: as phase StudySetupError, labelled scenarios/ for insufficient data and config.json for the width mismatch, or as BoundaryReconciliationError with the message prefixed policy.boundary: when policy.boundary is configured.

Methodology: Scenario Generation

Pre-computed load realizations, read when the load scheme is "external" in training.scenario_source or simulation.scenario_source. Realizations are numbered per stage by scenario_id; how the passes draw from them is described in Scenario Generation §4, and which classes take their mean and standard deviation from the file is stated under scenarios/inflow_seasonal_stats.parquet.

NameTypeRequiredDefaultUnitsDescription
stage_idInt32Yes——Declared study-stage id from stages.json (not a 0-based position); >= 0.
scenario_idInt32Yes——0-based realization index at that stage; >= 0.
bus_idInt32Yes——Bus id; names a declared bus.
value_mwFloat64Yes—MWLoad value of the realization at the stage; finite.

These rules apply as listed under scenarios/external_inflow_scenarios.parquet; the constant-column rule is inflow-only.


Methodology: Scenario Generation

Pre-computed non-controllable-source availability realizations, read when the NCS scheme is "external" in training.scenario_source or simulation.scenario_source. Realizations are numbered per stage by scenario_id; how the passes draw from them is described in Scenario Generation §4, and which classes take their mean and standard deviation from the file is stated under scenarios/inflow_seasonal_stats.parquet.

NameTypeRequiredDefaultUnitsDescription
stage_idInt32Yes——Declared study-stage id from stages.json (not a 0-based position); >= 0.
scenario_idInt32Yes——0-based realization index at that stage; >= 0.
ncs_idInt32Yes——Non-controllable source id; names a declared NCS.
availability_factorFloat64Yes——Availability factor of the realization at the stage, dimensionless; finite.

These rules apply as listed under scenarios/external_inflow_scenarios.parquet; the constant-column rule is inflow-only.


Methodology: Scenario Generation

Seasonal load statistics of each (bus, stage) pair. mean_mw is the bus’s mean load at the stage; the load of each block is the stage value times the block factor of scenarios/load_factors.json. When the file has any row, it needs a row for every bus at every study stage. Without the file every bus carries zero load, unless the load scheme is external in training. A bus whose std_mw is above 0 carries load noise (Scenario Generation §5.1). Under the external load scheme the file is optional and the mean and standard deviation come from the external file (see scenarios/inflow_seasonal_stats.parquet).

NameTypeRequiredDefaultUnitsDescription
bus_idInt32Yes——Bus id; names a declared bus.
stage_idInt32Yes——Declared study-stage id from stages.json (not a 0-based position).
mean_mwFloat64Yes—MWMean load of the bus at the stage; finite.
std_mwFloat64Yes—MWStandard deviation of the load at the stage; finite and >= 0. 0 is a deterministic load.

Validation rules. Each rule names the error kind that novomodelo validate reports.

  • Row checks. Every column is present with its type, mean_mw is finite, and std_mw is finite and >= 0. Kind: SchemaViolation.
  • Coverage. When the file has any row, every bus has a row at every study stage; each missing pair is a DimensionMismatch error, Bus <id> missing load seasonal stats for stage <id>.
  • Declared bus. A bus_id that names no declared bus is an InvalidReference error.

Methodology: Scenario Generation

Per-bus, per-stage, per-block load scaling factors. When present, each factor multiplies the stochastic load demand realization at the specified bus for the specified block. This allows you to model time-of-day or seasonal patterns in load shape without changing the underlying statistical model.

When this file is absent, all load factors default to 1.0. When a (bus_id, stage_id) pair is absent from the file, its factors also default to 1.0 for every block.

JSON structure:

{
"load_factors": [
{
"bus_id": 0,
"stage_id": 0,
"block_factors": [
{ "block_id": 0, "factor": 0.8 },
{ "block_id": 1, "factor": 1.2 }
]
}
]
}

Fields per entry:

NameTypeRequiredDefaultUnitsDescription
load_factors[].bus_idintegerYes——Bus entity ID. Must refer to a bus defined in system/buses.json.
load_factors[].stage_idintegerYes——Declared study-stage id from stages.json.
load_factors[].block_factorsarrayYes——Array of { block_id, factor } pairs for each load block.

block_factors entry fields:

NameTypeRequiredDefaultUnitsDescription
load_factors[].block_factors[].block_idintegerYes——Must be a valid block for stage. Zero-based block index within the stage.
load_factors[].block_factors[].factornumberYes——Must be > 0, finite. Multiplier applied to the stochastic load realization (MW) at this bus and block.

Effect: load_rhs = mean_mw * stochastic_noise_factor * block_factor. A factor of 1.0 leaves the load unchanged. Values less than 1.0 reduce load; values greater than 1.0 increase it.


Methodology: Scenario Generation · Equipment-Specific Formulations

Per-NCS, per-stage, per-block scaling factors for non-controllable source (NCS) available generation. When present, each factor multiplies the source’s available generation for the specified block: the bound from constraints/ncs_bounds.parquet (max_generation_mw where no row applies) for a source with no stochastic availability model, and max_generation_mw times the availability ratio for a source with rows in scenarios/non_controllable_stats.parquet. This allows modeling of intra-stage availability patterns such as diurnal solar irradiance profiles or wind speed variations across load blocks.

When this file is absent, all NCS block factors default to 1.0. When a (ncs_id, stage_id) pair is absent from the file, its factors default to 1.0 for every block.

JSON structure:

{
"non_controllable_factors": [
{
"ncs_id": 0,
"stage_id": 0,
"block_factors": [
{ "block_id": 0, "factor": 0.3 },
{ "block_id": 1, "factor": 0.8 }
]
}
]
}

Fields per entry:

NameTypeRequiredDefaultUnitsDescription
non_controllable_factors[].ncs_idintegerYes——NCS entity ID. Must refer to a source in system/non_controllable_sources.json.
non_controllable_factors[].stage_idintegerYes——Declared study-stage id from stages.json.
non_controllable_factors[].block_factorsarrayYes——Array of { block_id, factor } pairs for each load block.

block_factors entry fields:

NameTypeRequiredDefaultUnitsDescription
non_controllable_factors[].block_factors[].block_idintegerYes——Must be a valid block for stage. Zero-based block index within the stage.
non_controllable_factors[].block_factors[].factornumberYes——Must be > 0, finite. Multiplier applied to the stage available generation bound for this block.

Effect: for a source with no stochastic availability model, available_mw_block = available_generation_mw * block_factor; for a source with rows in non_controllable_stats.parquet, available_mw_block = max_generation_mw * ratio * block_factor, where ratio is the realized availability ratio of the scenario, drawn from that file’s model or, under the external scheme, from external_ncs_scenarios.parquet. A source with no row in that file that draws its availability from external_ncs_scenarios.parquet under the external scheme is not scaled by the factors. A factor of 1.0 leaves the bound unchanged; factors below 1.0 reduce available generation and factors above 1.0 raise it. The factor must be strictly positive — 0.0 is rejected at load.


Methodology: Scenario Generation · Equipment-Specific Formulations

Per-NCS, per-stage stochastic availability model. Each row provides the mean and standard deviation of the availability factor for one NCS entity at one stage. The availability ratio of a stage and scenario is clamp(mean + std × η, 0, 1); each block’s available generation is the source’s max_generation_mw × that ratio × the block factor from scenarios/non_controllable_factors.json (the factor is 1 when none is given); a constraints/ncs_bounds.parquet row does not change this available generation (see Equipment-Specific Formulations §6).

NameTypeRequiredDefaultUnitsDescription
ncs_idInt32Yes——Non-controllable source ID
stage_idInt32Yes——Stage ID
meanFloat64Yes——Mean availability factor in [0, 1]
stdFloat64Yes——Standard deviation of availability factor (>= 0)

When absent, NCS availability is deterministic from constraints/ncs_bounds.parquet or the entity’s max_generation_mw.


Methodology: Scenario Generation

Spatial correlation of the noise: named profiles of correlation groups and an optional stage-to-profile schedule. A group holds entities of one class (inflow, load or ncs), and each class is correlated separately. The decomposition of the matrices and the treatment of negative eigenvalues are in Scenario Generation §2.1; the PAR(p) Inflow Model Configure tab gives a worked example and the per-path use of the file.

NameTypeRequiredDefaultUnitsDescription
methodstringYes——One of "spectral". Decomposition method of the correlation matrices.
profilesobjectYes——Named correlation profiles, keyed by profile name; holds at least one.
profiles.<name>.correlation_groupsarrayYes——Groups of correlated entities of the profile <name>; may be empty.
profiles.<name>.correlation_groups[].namestringYes——Group label.
profiles.<name>.correlation_groups[].entitiesarrayYes——Entity references of the group, in matrix order; at least one, all of one type.
profiles.<name>.correlation_groups[].entities[].typestringYes——Entity class: "inflow" (a hydro’s inflow), "load" (a bus’s load) or "ncs" (a non-controllable source’s availability).
profiles.<name>.correlation_groups[].entities[].idintegerYes——Id of the hydro (inflow), bus (load) or NCS (ncs); names a declared entity.
profiles.<name>.correlation_groups[].matrixarrayYes——Correlation matrix in row-major order, one row and one column per entity; symmetric, diagonal 1.0, entries in [-1.0, 1.0].
schedulearray | nullNo——Stage-to-profile entries. Absent or null is the empty schedule.
schedule[].stage_idintegerYes——Stage the entry’s profile applies to. The opening tree matches a declared study-stage id from stages.json; out-of-sample forward and simulation sampling matches the stage’s 0-based position among the study stages. The two coincide when the ids are 0, 1, 2, ….
schedule[].profile_namestringYes——Name of a profile in profiles.

Validation rules. Each rule names the error kind that novomodelo validate reports.

  • Structure. A missing required key, a value of the wrong type, a method other than "spectral", or an unknown key in any object is a ParseError.
  • Profiles. profiles holds at least one profile. Kind: SchemaViolation.
  • Matrix. Each group’s matrix has one row per entity and is square; its entries lie in [-1.0, 1.0]; its diagonal is 1.0; and it is symmetric, each pair of mirrored entries differing by at most 1e-10. Kind: SchemaViolation.
  • Schedule. Every schedule[].profile_name names a profile of profiles. Kind: SchemaViolation. A stage_id is not checked against stages.json.
  • Entity references. An entities[].id that names no declared hydro (inflow), bus (load) or NCS (ncs), and a type other than these three, are each an InvalidReference error.
  • One class per group. The entities of a group share one type; a mixed group is a BusinessRuleViolation.
  • Default profile. The "default" profile, or the only profile, applies at every stage that schedule does not name. With more than one profile and none named "default", the case is refused with a StochasticPreparationError.
  • Groups. A group lists at least one entity. Within a profile an id value appears in at most one group, and once in it, whatever its type: an inflow group and a load group that both list id 0 are rejected (the message ends groups must be disjoint). Kind: StochasticPreparationError.

Methodology: Scenario Generation

User-supplied backward-pass opening tree, read only when config.json declares training.scenario_source.openings = {"source": "file"} (an undeclared file is ignored; a declared but absent file is an error). Not admitted with a nodes[] policy graph or under enumerated forward selection (see training.scenario_source). This enables cross-tool comparison, sensitivity analysis, and round-trip replay of a previously exported opening tree.

NameTypeRequiredDefaultUnitsDescription
stage_idInt32Yes——Declared study-stage id from stages.json (not a 0-based position)
opening_indexUInt32Yes——0-based opening index within the stage (0 to that stage’s num_openings − 1)
entity_indexUInt32Yes——0-based position in the noise vector (see entity ordering below)
valueFloat64Yes——Noise realization for this (stage, opening, entity) triple

Entity ordering. The noise vector is hydros in canonical order (operational_start_date, then id), then the load buses that carry load noise (std_mw > 0, or every load bus under the external load scheme), then every NCS with availability statistics (including std = 0, plus external-scenario NCS under external); the load-bus and NCS blocks are each sorted by id. A zero-std NCS still occupies a slot. Violating this order causes silent value misassignment because the file stores indices only, not entity identifiers.

Validation rules. The loader raises a hard error on failure:

  • Unresolved stage — every stage_id must be a declared study-stage id.
  • Dimension mismatch — the number of distinct entity_index values must equal the noise-vector length defined above.
  • Stage count mismatch — the distinct stage_id values must be the declared study stages.
  • Missing opening indices — for each stage, every opening index from 0 to that stage’s num_openings − 1 must be present for every entity. Gaps are not permitted; partial-stage override is not supported.

The total row count must equal the sum over study stages of num_openings × dimension.

See Scenario Generation for the opening tree and Configuration for the openings field.