System Entity Files
The system/ directory holds one registry file for each entity type. This page documents the six registries other than the hydro plants: buses, lines, thermal plants, non-controllable sources, pumping stations and energy contracts. system/buses.json, system/lines.json and system/thermals.json are required; the other three files are optional. The hydro plant registry is on Hydro Plant Files. Every entity carries a required operational_start_date, described once under Shared entity fields.
system/buses.json
Section titled “system/buses.json”Methodology: System Element Modeling Overview
Electrical bus registry. Buses are the nodes of the transmission network.
| Name | Type | Required | Default | Units | Description |
|---|---|---|---|---|---|
buses[].id | integer | Yes | — | — | Bus identifier (integer, unique) |
buses[].name | string | Yes | — | — | Human-readable bus name (string) |
buses[].operational_start_date | string | Yes | — | — | Required on every entity; see Shared entity fields. |
buses[].deficit_segments | array | null | No | — | — | Entity-level deficit cost tiers; when present they replace bus.deficit_segments in penalties.json for this bus and follow the same rules (non-empty, costs strictly increasing, last depth_mw null) |
buses[].deficit_segments[].depth_mw | number | null | No | — | MW | Segment depth (MW); the last segment’s depth_mw must be null (unbounded) |
buses[].deficit_segments[].cost | number | Yes | — | USD/MWh | Cost per MWh of deficit in this tier (USD/MWh); > 0 |
system/lines.json
Section titled “system/lines.json”Methodology: System Element Modeling Overview · Equipment-Specific Formulations
Transmission line registry. Lines connect buses and carry power flows.
| Name | Type | Required | Default | Units | Description |
|---|---|---|---|---|---|
lines[].id | integer | Yes | — | — | Line identifier (integer, unique) |
lines[].name | string | Yes | — | — | Human-readable line name (string) |
lines[].source_bus_id | integer | Yes | — | — | Sending-end bus ID |
lines[].target_bus_id | integer | Yes | — | — | Receiving-end bus ID |
lines[].operational_start_date | string | Yes | — | — | Required on every entity; see Shared entity fields. |
lines[].entry_stage_id | integer | null | No | null | — | Stage when line enters service; null = always exists |
lines[].exit_stage_id | integer | null | No | null | — | Stage when line is decommissioned; null = never |
lines[].capacity.direct_mw | number | Yes | — | MW | Maximum power flow in the direct direction (MW) |
lines[].capacity.reverse_mw | number | Yes | — | MW | Maximum power flow in the reverse direction (MW) |
lines[].exchange_cost | number | null | No | null | USD/MWh | Entity-level exchange cost override (USD/MWh); absent = line.exchange_cost in penalties.json |
lines[].losses_percent | number | No | 0.0 | % | Transmission losses as percentage (default: 0.0) |
Validation:
entry_stage_idmust be less thanexit_stage_idwhen both are set.capacity.direct_mw,capacity.reverse_mwandlosses_percentmust be>= 0.
system/thermals.json
Section titled “system/thermals.json”Methodology: Equipment-Specific Formulations · State Augmentation
Thermal plant registry. Each entry defines a dispatchable generation unit.
| Name | Type | Required | Default | Units | Description |
|---|---|---|---|---|---|
thermals[].id | integer | Yes | — | — | Plant identifier (integer, unique) |
thermals[].name | string | Yes | — | — | Human-readable plant name |
thermals[].bus_id | integer | Yes | — | — | Bus where generation is injected |
thermals[].generation | object | Yes | — | — | Dispatch-bounds object with min_mw and max_mw |
thermals[].generation.min_mw | number | Yes | — | MW | Minimum dispatch level (MW) |
thermals[].generation.max_mw | number | Yes | — | MW | Maximum dispatch level (MW) |
thermals[].cost_per_mwh | number | Yes | — | USD/MWh | Linear generation cost (USD/MWh) |
thermals[].operational_start_date | string | Yes | — | — | Required on every entity; see Shared entity fields. |
thermals[].entry_stage_id | integer | null | No | null | — | Stage when the unit enters service (null = present from stage 0) |
thermals[].exit_stage_id | integer | null | No | null | — | Stage when the unit is decommissioned (null = never) |
thermals[].anticipated_config | object | null | No | — | — | Anticipated-dispatch lead: an object with exactly one of lead_stages (integer >= 1) or lead_time_hours (finite and > 0); both or neither is rejected at load. See the Equipment-Specific Formulations Configure tab |
thermals[].anticipated_config.lead_stages | integer | Conditional | — | — | Anticipated-dispatch lead in stages (integer >= 1). Exactly one of lead_stages or lead_time_hours is set; both or neither is rejected at load. |
thermals[].anticipated_config.lead_time_hours | number | Conditional | — | h | Anticipated-dispatch lead in hours (finite and > 0). Exactly one of lead_stages or lead_time_hours is set; both or neither is rejected at load. |
Validation:
entry_stage_idmust be less thanexit_stage_idwhen both are set.generation.min_mwandgeneration.max_mwmust be>= 0, withmax_mw >= min_mw;cost_per_mwhmust be>= 0.
system/non_controllable_sources.json
Section titled “system/non_controllable_sources.json”Methodology: Equipment-Specific Formulations
Non-controllable source (NCS) registry. Each entry defines an intermittent or
aggregate generator — wind, solar, small hydro, biomass, distributed generation —
whose available output is a scenario input rather than a free LP decision. The
file is optional; when absent, no non-controllable sources are modeled.
Per-scenario availability is supplied by the
scenarios/non_controllable_factors.json and
scenarios/non_controllable_stats.parquet inputs.
| Name | Type | Required | Default | Units | Description |
|---|---|---|---|---|---|
non_controllable_sources[].id | integer | Yes | — | — | Source identifier (integer, unique within the file) |
non_controllable_sources[].name | string | Yes | — | — | Human-readable source name (string) |
non_controllable_sources[].bus_id | integer | Yes | — | — | Bus into which the source’s generation is injected |
non_controllable_sources[].operational_start_date | string | Yes | — | — | Required on every entity; see Shared entity fields. |
non_controllable_sources[].max_generation_mw | number | Yes | — | MW | Installed capacity [MW]; it scales the stochastic availability and does not cap the available generation |
non_controllable_sources[].allow_curtailment | boolean | No | true | — | Whether the LP may curtail this source. true (default) — dispatch within [0, max_generation_mw × availability] at the curtailment cost; false — must-run, dispatch pinned to the realized availability every scenario |
non_controllable_sources[].curtailment_cost | number | null | No | null | USD/MWh | Entity-level curtailment cost override [USD/MWh]; falls back to non_controllable_source.curtailment_cost in penalties.json when absent |
non_controllable_sources[].entry_stage_id | integer | null | No | null | — | Stage when the source enters service; null or absent = present from stage 0 |
non_controllable_sources[].exit_stage_id | integer | null | No | null | — | Stage when the source is decommissioned; null or absent = never |
Minimal valid example:
{ "$schema": "https://docs.novomodelo.invalid/schemas/non_controllable_sources.schema.json", "non_controllable_sources": [ { "id": 0, "name": "Complexo Eólico Nordeste", "bus_id": 4, "operational_start_date": "2015-06-01", "max_generation_mw": 1200.0 } ]}Validation:
entry_stage_idmust be less thanexit_stage_idwhen both are set.max_generation_mwmust be>= 0.
system/pumping_stations.json
Section titled “system/pumping_stations.json”Methodology: Equipment-Specific Formulations
Pumping station registry. Each entry defines a pumped-storage or water-transfer installation that withdraws water from a source hydro reservoir, injects it into a destination hydro reservoir, and consumes electrical power from a bus. The file is optional; when absent, no pumping stations are modeled.
| Name | Type | Required | Default | Units | Description |
|---|---|---|---|---|---|
pumping_stations[].id | integer | Yes | — | — | Station identifier (integer, unique) |
pumping_stations[].name | string | Yes | — | — | Human-readable station name (string) |
pumping_stations[].bus_id | integer | Yes | — | — | Bus from which electrical power is consumed |
pumping_stations[].source_hydro_id | integer | Yes | — | — | Hydro plant from whose reservoir water is extracted |
pumping_stations[].destination_hydro_id | integer | Yes | — | — | Hydro plant into whose reservoir water is injected |
pumping_stations[].consumption_mw_per_m3s | number | Yes | — | MW/(m³/s) | Power drawn per unit of pumped flow [MW/(m³/s)]; must be >= 0 |
pumping_stations[].operational_start_date | string | Yes | — | — | Required on every entity; see Shared entity fields. |
pumping_stations[].entry_stage_id | integer | null | No | null | — | Stage when the station enters service; null or absent = present from stage 0 |
pumping_stations[].exit_stage_id | integer | null | No | null | — | Stage when the station is decommissioned; null or absent = never |
pumping_stations[].flow | object | Yes | — | — | Nested object with min_m3s and max_m3s (see below) |
pumping_stations[].flow.min_m3s | number | Yes | — | m³/s | Minimum pumped flow [m³/s]; must be >= 0 |
pumping_stations[].flow.max_m3s | number | Yes | — | m³/s | Maximum pumped flow (installed pump capacity) [m³/s]; must be >= flow.min_m3s |
The pumped flow variable is bounded by [flow.min_m3s, flow.max_m3s] in the LP.
At each stage within [entry_stage_id, exit_stage_id), the flow appears with
a negative sign in the source reservoir water-balance row and a positive sign in
the destination reservoir water-balance row. Power consumed equals
consumption_mw_per_m3s × flow_m3s and is charged as load on the station’s bus.
Stage-varying flow bounds can be overridden via constraints/pumping_bounds.parquet.
Minimal valid example:
{ "$schema": "https://docs.novomodelo.invalid/schemas/pumping_stations.schema.json", "pumping_stations": [ { "id": 0, "name": "Bombeamento Serra da Mesa", "bus_id": 10, "operational_start_date": "2010-09-15", "source_hydro_id": 3, "destination_hydro_id": 5, "consumption_mw_per_m3s": 0.5, "flow": { "min_m3s": 0.0, "max_m3s": 150.0 } } ]}Validation:
entry_stage_idmust be less thanexit_stage_idwhen both are set.source_hydro_idmust differ fromdestination_hydro_id.- The station is in service only at stages where both its source and its destination hydro are Operating (neither PreFilling nor Filling); see Equipment-Specific Formulations for the rule.
system/energy_contracts.json
Section titled “system/energy_contracts.json”Methodology: Equipment-Specific Formulations
Energy contract registry. Each entry defines a bilateral energy purchase or sale obligation with a counterparty outside the modeled system. The file is optional; when absent, no contracts are modeled.
| Name | Type | Required | Default | Units | Description |
|---|---|---|---|---|---|
contracts[].id | integer | Yes | — | — | Contract identifier (integer, unique) |
contracts[].name | string | Yes | — | — | Human-readable contract name (string) |
contracts[].bus_id | integer | Yes | — | — | Bus where power is injected (import) or withdrawn (export) |
contracts[].type | string | Yes | — | — | One of "import", "export". Energy flow direction. |
contracts[].price_per_mwh | number | Yes | — | USD/MWh | Contract price [USD/MWh]. Positive = cost (import); negative = revenue (export) |
contracts[].limits.min_mw | number | Yes | — | MW | Minimum dispatch level [MW]; use 0.0 unless a take-or-pay floor applies |
contracts[].limits.max_mw | number | Yes | — | MW | Maximum dispatch level [MW]; must be >= limits.min_mw |
contracts[].operational_start_date | string | Yes | — | — | Required on every entity; see Shared entity fields. |
contracts[].entry_stage_id | integer | null | No | null | — | Stage when the contract enters service; null or absent = present from stage 0 |
contracts[].exit_stage_id | integer | null | No | null | — | Stage when the contract is decommissioned; null or absent = never |
At each active stage within [entry_stage_id, exit_stage_id), the LP adds one
column per block per direction bounded by [limits.min_mw, limits.max_mw]. An
import column injects +1.0 MW into the bus power-balance row; an export column
withdraws −1.0 MW. At dormant stages the column bounds are pinned to [0, 0]
and the output row is emitted with power_mw = 0. Stage-varying bounds and prices
can be overridden via constraints/contract_bounds.parquet.
Minimal valid example:
{ "$schema": "https://docs.novomodelo.invalid/schemas/energy_contracts.schema.json", "contracts": [ { "id": 0, "name": "Import base load", "bus_id": 0, "operational_start_date": "2018-01-01", "type": "import", "price_per_mwh": 200.0, "limits": { "min_mw": 0.0, "max_mw": 50.0 } }, { "id": 1, "name": "Export revenue (stage 1 only)", "bus_id": 0, "operational_start_date": "2019-06-01", "type": "export", "entry_stage_id": 1, "exit_stage_id": 2, "price_per_mwh": -150.0, "limits": { "min_mw": 0.0, "max_mw": 30.0 } } ]}Validation:
entry_stage_idmust be less thanexit_stage_idwhen both are set.limits.min_mwandlimits.max_mwmust be>= 0.