fluxopt
¶
Modules:
| Name | Description |
|---|---|
benchmark |
User-runnable benchmark: build a few realistic energy systems, report speed and memory. |
components |
|
contract |
The cross-layer data contract. |
contributions |
Per-contributor effect breakdown, read off the program. |
elements |
|
flow_system |
|
leontief |
Cross-effect propagation: the Leontief inverse of |
math |
fluxopt's math, and the engine that builds it. |
model_data |
|
results |
|
schema |
JSON Schema and dict/JSON round-trip for the element layer. |
stats |
Derived statistics from optimization results. |
types |
|
validation |
System-level structural validation, shared by every entry path. |
Type Aliases:
| Name | Description |
|---|---|
Variate |
Any input that varies over a subset of the model's variate dims ( |
Classes:
| Name | Description |
|---|---|
Converter |
Conversion between input and output flows. |
Port |
System boundary importing and exporting carriers. |
Carrier |
Physical energy medium (electricity, heat, gas, …). |
Effect |
A tracked quantity across the optimization horizon (cost, CO₂, …). |
Flow |
A single energy flow on a carrier. |
Investment |
Singular discrete build-timing optimization. |
PiecewiseConversion |
Piecewise-linear conversion linking N flows. |
Sizing |
Capacity optimization parameters. |
Status |
Binary on/off behavior parameters. |
Storage |
Energy storage with level dynamics. |
FlowSystem |
A declarative flow-system description (see module docstring). |
Dims |
The model's temporal axes: what a timestep is, and what a period is. |
ModelData |
|
Result |
Optimization result with solution variables and model data. |
ProfileRef |
Reference to a time-series stored outside the model definition. |
Functions:
| Name | Description |
|---|---|
all_element_schemas |
Return JSON Schemas for every element type, keyed by class name. |
element_schema |
Return the JSON Schema for one element type. |
from_dict |
Reconstruct an element from a dict produced by :func: |
to_dict |
Serialize an element to a JSON-safe dict. |
as_dataarray |
Convert a Variate to a DataArray aligned to given coordinates. |
optimize |
Build data, build model, optimize, return results. |
Variate
¶
Any input that varies over a subset of the model's variate dims (time,
optionally period, eventually scenario).
- Scalar: broadcast to all variate dims.
- 1-D (
list/ndarray): matched to a coord by length (must be unambiguous). - 1-D (
pd.Series): index name selects the dim if set; else matched by length. - 2-D (
pd.DataFrame):index.nameandcolumns.namemust match target dims. - n-D (
xr.DataArray): dims must be a subset of the target; coords must match exactly.
Per-field reach (which dims a particular field can vary over) is documented on
the field itself; as_dataarray enforces that user input only uses dims the
caller declared in coords.
Converter
pydantic-model
¶
Bases: Element
Conversion between input and output flows.
Two mutually exclusive modes:
- Linear —
conversion_factors=[{flow_short_id: a_f}, ...], one dict per equation; constraintsum_f(a_f * P_{f,t}) = 0. - Piecewise —
conversion=PiecewiseConversion(...); the solver interpolates between breakpoints, optionally with on/off viaPiecewiseConversion.status.
Show JSON schema:
{
"$defs": {
"Flow": {
"description": "A single energy flow on a carrier.\n\n``short_id`` defaults to ``carrier`` (or ``carrier:node`` when ``node``\nis set). Set explicitly to disambiguate multiple flows on the same\ncarrier::\n\n Flow(carrier='elec') # short_id='elec'\n Flow(carrier='heat', node='A') # short_id='heat:A'\n Flow(carrier='elec', short_id='base') # short_id='base'\n\n``short_id`` must be unique within a component. The system-global\nqualified id ``component(short_id)`` is derived at build time and\nappears as the ``flow`` coordinate in ``ModelData`` and results; the\nflow itself is never modified. Storage resolves colliding short_ids\nto ``charge`` / ``discharge`` at that point.\n\nSee: docs/math/flows.md",
"properties": {
"carrier": {
"title": "Carrier",
"type": "string"
},
"short_id": {
"default": "",
"title": "Short Id",
"type": "string"
},
"node": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Node"
},
"size": {
"anyOf": [
{
"type": "number"
},
{
"$ref": "#/$defs/Sizing"
},
{
"$ref": "#/$defs/Investment"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"relative_rate_min": {
"$ref": "#/$defs/Variate",
"default": 0.0
},
"relative_rate_max": {
"$ref": "#/$defs/Variate",
"default": 1.0
},
"fixed_relative_profile": {
"anyOf": [
{
"$ref": "#/$defs/Variate"
},
{
"type": "null"
}
],
"default": null
},
"effects_per_flow_hour": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Flow Hour",
"type": "object"
},
"flow_hours_min": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Flow Hours Min"
},
"flow_hours_max": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Flow Hours Max"
},
"load_factor_min": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Load Factor Min"
},
"load_factor_max": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Load Factor Max"
},
"ramp_up_per_hour": {
"anyOf": [
{
"$ref": "#/$defs/Variate"
},
{
"type": "null"
}
],
"default": null
},
"ramp_down_per_hour": {
"anyOf": [
{
"$ref": "#/$defs/Variate"
},
{
"type": "null"
}
],
"default": null
},
"status": {
"anyOf": [
{
"$ref": "#/$defs/Status"
},
{
"type": "null"
}
],
"default": null
},
"prior_rates": {
"anyOf": [
{
"items": {
"type": "number"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Prior Rates"
}
},
"required": [
"carrier"
],
"title": "Flow",
"type": "object"
},
"Investment": {
"description": "Singular discrete build-timing optimization.\n\nThe solver decides WHEN to build (which period) and at what size.\nOnce built, capacity is available for ``lifetime`` periods.\nSize is decided once \u2014 no growth or partial retirement.",
"properties": {
"size_min": {
"minimum": 0,
"title": "Size Min",
"type": "number"
},
"size_max": {
"minimum": 0,
"title": "Size Max",
"type": "number"
},
"mandatory": {
"default": true,
"title": "Mandatory",
"type": "boolean"
},
"lifetime": {
"anyOf": [
{
"exclusiveMinimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Lifetime"
},
"prior_size": {
"default": 0.0,
"minimum": 0,
"title": "Prior Size",
"type": "number"
},
"effects_per_size_at_build": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Size At Build",
"type": "object"
},
"effects_fixed_at_build": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Fixed At Build",
"type": "object"
},
"effects_per_size_recurring": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Size Recurring",
"type": "object"
},
"effects_fixed_recurring": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Fixed Recurring",
"type": "object"
}
},
"required": [
"size_min",
"size_max"
],
"title": "Investment",
"type": "object"
},
"PiecewiseConversion": {
"description": "Piecewise-linear conversion linking N flows.\n\nWraps :func:`linopy.piecewise.add_piecewise_formulation`. All flows\nshare interpolation weights \u2014 every operating point lies on the same\npiece of the curve.\n\nTwo input forms:\n\n- **Dict** \u2014 equality-only, terse for the common case::\n\n PiecewiseConversion(points={'fuel': [0, 50, 100], 'Heat': [0, 45, 70]})\n\n- **List of tuples** \u2014 supports per-flow inequality bounds::\n\n PiecewiseConversion(\n points=[\n ('fuel', [0, 50, 100]),\n ('Heat', [0, 45, 70], '>='),\n ]\n )\n\nSee: docs/math/converters.md",
"properties": {
"points": {
"anyOf": [
{
"additionalProperties": {
"items": {
"$ref": "#/$defs/Variate"
},
"type": "array"
},
"type": "object"
},
{
"items": {
"anyOf": [
{
"maxItems": 2,
"minItems": 2,
"prefixItems": [
{
"type": "string"
},
{
"items": {
"$ref": "#/$defs/Variate"
},
"type": "array"
}
],
"type": "array"
},
{
"maxItems": 3,
"minItems": 3,
"prefixItems": [
{
"type": "string"
},
{
"items": {
"$ref": "#/$defs/Variate"
},
"type": "array"
},
{
"enum": [
"==",
"<=",
">="
],
"type": "string"
}
],
"type": "array"
}
]
},
"type": "array"
}
],
"title": "Points"
},
"method": {
"$ref": "#/$defs/PiecewiseMethod",
"default": "auto"
},
"status": {
"anyOf": [
{
"$ref": "#/$defs/Status"
},
{
"type": "null"
}
],
"default": null
},
"availability": {
"$ref": "#/$defs/Variate",
"default": 1.0
}
},
"required": [
"points"
],
"title": "PiecewiseConversion",
"type": "object"
},
"PiecewiseMethod": {
"enum": [
"auto",
"sos2",
"incremental",
"lp"
],
"type": "string"
},
"ProfileRef": {
"description": "Reference to a time-series stored outside the model definition.\n\nA serializable stand-in for an inline ``Variate`` array: the profile lives\nin a data file / dataset and is named here, so structural definitions\nround-trip to YAML/JSON without inlining 8760-point series. Resolve it to a\n:class:`xr.DataArray` with :meth:`resolve` before building the model.",
"properties": {
"dataset": {
"title": "Dataset",
"type": "string"
},
"variable": {
"title": "Variable",
"type": "string"
}
},
"required": [
"dataset",
"variable"
],
"title": "ProfileRef",
"type": "object"
},
"Sizing": {
"description": "Capacity optimization parameters.\n\nThe solver decides the optimal size within [size_min, size_max].\n\n- ``mandatory=True``: continuous, size in [min, max], no binary.\n- ``mandatory=False``: binary indicator gates size: 0 or [min, max].\n- ``size_min == size_max`` with ``mandatory=False``: binary invest\n at exact size (yes/no).\n\nSee: docs/math/sizing.md",
"properties": {
"size_min": {
"minimum": 0,
"title": "Size Min",
"type": "number"
},
"size_max": {
"minimum": 0,
"title": "Size Max",
"type": "number"
},
"mandatory": {
"default": true,
"title": "Mandatory",
"type": "boolean"
},
"effects_per_size": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Size",
"type": "object"
},
"effects_fixed": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Fixed",
"type": "object"
}
},
"required": [
"size_min",
"size_max"
],
"title": "Sizing",
"type": "object"
},
"Status": {
"description": "Binary on/off behavior parameters.\n\nTogether with relative bounds, gives semi-continuous behavior:\n``{0} U [min, max] * size``.\n\nSee: docs/math/status.md",
"properties": {
"uptime_min": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Uptime Min"
},
"uptime_max": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Uptime Max"
},
"downtime_min": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Downtime Min"
},
"downtime_max": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Downtime Max"
},
"effects_per_running_hour": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Running Hour",
"type": "object"
},
"effects_per_startup": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Startup",
"type": "object"
}
},
"title": "Status",
"type": "object"
},
"Variate": {
"anyOf": [
{
"type": "number"
},
{
"type": "integer"
},
{
"items": {
"type": "number"
},
"type": "array"
},
{
"$ref": "#/$defs/ProfileRef"
}
]
}
},
"description": "Conversion between input and output flows.\n\nTwo mutually exclusive modes:\n\n- **Linear** \u2014 ``conversion_factors=[{flow_short_id: a_f}, ...]``,\n one dict per equation; constraint ``sum_f(a_f * P_{f,t}) = 0``.\n- **Piecewise** \u2014 ``conversion=PiecewiseConversion(...)``; the solver\n interpolates between breakpoints, optionally with on/off via\n ``PiecewiseConversion.status``.",
"properties": {
"id": {
"title": "Id",
"type": "string"
},
"inputs": {
"items": {
"$ref": "#/$defs/Flow"
},
"title": "Inputs",
"type": "array"
},
"outputs": {
"items": {
"$ref": "#/$defs/Flow"
},
"title": "Outputs",
"type": "array"
},
"conversion_factors": {
"items": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"type": "object"
},
"title": "Conversion Factors",
"type": "array"
},
"conversion": {
"anyOf": [
{
"$ref": "#/$defs/PiecewiseConversion"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"id",
"inputs",
"outputs"
],
"title": "Converter",
"type": "object"
}
Fields:
-
id(str) -
inputs(list[Flow]) -
outputs(list[Flow]) -
conversion_factors(list[dict[str, Variate]]) -
conversion(PiecewiseConversion | None)
conversion_factors
pydantic-field
¶
Linear-mode equations. Empty when
conversion is set.
conversion
pydantic-field
¶
conversion: PiecewiseConversion | None = None
Piecewise-mode curve. None for linear mode.
model_post_init
¶
model_post_init(__context: Any) -> None
Validate short_id uniqueness, mode exclusivity, and factor references.
Source code in src/fluxopt/components.py
boiler
classmethod
¶
boiler(
id: str, thermal_efficiency: Variate, fuel_flow: Flow, thermal_flow: Flow
) -> Converter
Create a boiler converter: fuel * eta = thermal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
str
|
Converter id. |
required |
|
Variate
|
Thermal efficiency eta. |
required |
|
Flow
|
Input fuel flow. |
required |
|
Flow
|
Output thermal flow. |
required |
Source code in src/fluxopt/components.py
heat_pump
classmethod
¶
heat_pump(
id: str,
cop: Variate,
electrical_flow: Flow,
source_flow: Flow,
thermal_flow: Flow,
) -> Converter
Create a heat pump converter with source heat.
Two conversion equations
electrical * COP = thermal electrical + source = thermal
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
str
|
Converter id. |
required |
|
Variate
|
Coefficient of performance. |
required |
|
Flow
|
Input electrical flow. |
required |
|
Flow
|
Input environmental heat flow (air, ground, water). |
required |
|
Flow
|
Output thermal flow. |
required |
Source code in src/fluxopt/components.py
power2heat
classmethod
¶
power2heat(
id: str, efficiency: Variate, electrical_flow: Flow, thermal_flow: Flow
) -> Converter
Create an electric resistance heater: electrical * eta = thermal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
str
|
Converter id. |
required |
|
Variate
|
Electrical-to-thermal efficiency. |
required |
|
Flow
|
Input electrical flow. |
required |
|
Flow
|
Output thermal flow. |
required |
Source code in src/fluxopt/components.py
chp
classmethod
¶
chp(
id: str,
eta_el: Variate,
eta_th: Variate,
fuel_flow: Flow,
electrical_flow: Flow,
thermal_flow: Flow,
) -> Converter
Create a CHP converter with separate electrical and thermal outputs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
str
|
Converter id. |
required |
|
Variate
|
Electrical efficiency. |
required |
|
Variate
|
Thermal efficiency. |
required |
|
Flow
|
Input fuel flow. |
required |
|
Flow
|
Output electrical flow. |
required |
|
Flow
|
Output thermal flow. |
required |
Source code in src/fluxopt/components.py
Port
pydantic-model
¶
Bases: Element
System boundary importing and exporting carriers.
imports bring flow into the system (sources); exports send it out
of the system (sinks).
Show JSON schema:
{
"$defs": {
"Flow": {
"description": "A single energy flow on a carrier.\n\n``short_id`` defaults to ``carrier`` (or ``carrier:node`` when ``node``\nis set). Set explicitly to disambiguate multiple flows on the same\ncarrier::\n\n Flow(carrier='elec') # short_id='elec'\n Flow(carrier='heat', node='A') # short_id='heat:A'\n Flow(carrier='elec', short_id='base') # short_id='base'\n\n``short_id`` must be unique within a component. The system-global\nqualified id ``component(short_id)`` is derived at build time and\nappears as the ``flow`` coordinate in ``ModelData`` and results; the\nflow itself is never modified. Storage resolves colliding short_ids\nto ``charge`` / ``discharge`` at that point.\n\nSee: docs/math/flows.md",
"properties": {
"carrier": {
"title": "Carrier",
"type": "string"
},
"short_id": {
"default": "",
"title": "Short Id",
"type": "string"
},
"node": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Node"
},
"size": {
"anyOf": [
{
"type": "number"
},
{
"$ref": "#/$defs/Sizing"
},
{
"$ref": "#/$defs/Investment"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"relative_rate_min": {
"$ref": "#/$defs/Variate",
"default": 0.0
},
"relative_rate_max": {
"$ref": "#/$defs/Variate",
"default": 1.0
},
"fixed_relative_profile": {
"anyOf": [
{
"$ref": "#/$defs/Variate"
},
{
"type": "null"
}
],
"default": null
},
"effects_per_flow_hour": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Flow Hour",
"type": "object"
},
"flow_hours_min": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Flow Hours Min"
},
"flow_hours_max": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Flow Hours Max"
},
"load_factor_min": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Load Factor Min"
},
"load_factor_max": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Load Factor Max"
},
"ramp_up_per_hour": {
"anyOf": [
{
"$ref": "#/$defs/Variate"
},
{
"type": "null"
}
],
"default": null
},
"ramp_down_per_hour": {
"anyOf": [
{
"$ref": "#/$defs/Variate"
},
{
"type": "null"
}
],
"default": null
},
"status": {
"anyOf": [
{
"$ref": "#/$defs/Status"
},
{
"type": "null"
}
],
"default": null
},
"prior_rates": {
"anyOf": [
{
"items": {
"type": "number"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Prior Rates"
}
},
"required": [
"carrier"
],
"title": "Flow",
"type": "object"
},
"Investment": {
"description": "Singular discrete build-timing optimization.\n\nThe solver decides WHEN to build (which period) and at what size.\nOnce built, capacity is available for ``lifetime`` periods.\nSize is decided once \u2014 no growth or partial retirement.",
"properties": {
"size_min": {
"minimum": 0,
"title": "Size Min",
"type": "number"
},
"size_max": {
"minimum": 0,
"title": "Size Max",
"type": "number"
},
"mandatory": {
"default": true,
"title": "Mandatory",
"type": "boolean"
},
"lifetime": {
"anyOf": [
{
"exclusiveMinimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Lifetime"
},
"prior_size": {
"default": 0.0,
"minimum": 0,
"title": "Prior Size",
"type": "number"
},
"effects_per_size_at_build": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Size At Build",
"type": "object"
},
"effects_fixed_at_build": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Fixed At Build",
"type": "object"
},
"effects_per_size_recurring": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Size Recurring",
"type": "object"
},
"effects_fixed_recurring": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Fixed Recurring",
"type": "object"
}
},
"required": [
"size_min",
"size_max"
],
"title": "Investment",
"type": "object"
},
"ProfileRef": {
"description": "Reference to a time-series stored outside the model definition.\n\nA serializable stand-in for an inline ``Variate`` array: the profile lives\nin a data file / dataset and is named here, so structural definitions\nround-trip to YAML/JSON without inlining 8760-point series. Resolve it to a\n:class:`xr.DataArray` with :meth:`resolve` before building the model.",
"properties": {
"dataset": {
"title": "Dataset",
"type": "string"
},
"variable": {
"title": "Variable",
"type": "string"
}
},
"required": [
"dataset",
"variable"
],
"title": "ProfileRef",
"type": "object"
},
"Sizing": {
"description": "Capacity optimization parameters.\n\nThe solver decides the optimal size within [size_min, size_max].\n\n- ``mandatory=True``: continuous, size in [min, max], no binary.\n- ``mandatory=False``: binary indicator gates size: 0 or [min, max].\n- ``size_min == size_max`` with ``mandatory=False``: binary invest\n at exact size (yes/no).\n\nSee: docs/math/sizing.md",
"properties": {
"size_min": {
"minimum": 0,
"title": "Size Min",
"type": "number"
},
"size_max": {
"minimum": 0,
"title": "Size Max",
"type": "number"
},
"mandatory": {
"default": true,
"title": "Mandatory",
"type": "boolean"
},
"effects_per_size": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Size",
"type": "object"
},
"effects_fixed": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Fixed",
"type": "object"
}
},
"required": [
"size_min",
"size_max"
],
"title": "Sizing",
"type": "object"
},
"Status": {
"description": "Binary on/off behavior parameters.\n\nTogether with relative bounds, gives semi-continuous behavior:\n``{0} U [min, max] * size``.\n\nSee: docs/math/status.md",
"properties": {
"uptime_min": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Uptime Min"
},
"uptime_max": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Uptime Max"
},
"downtime_min": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Downtime Min"
},
"downtime_max": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Downtime Max"
},
"effects_per_running_hour": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Running Hour",
"type": "object"
},
"effects_per_startup": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Startup",
"type": "object"
}
},
"title": "Status",
"type": "object"
},
"Variate": {
"anyOf": [
{
"type": "number"
},
{
"type": "integer"
},
{
"items": {
"type": "number"
},
"type": "array"
},
{
"$ref": "#/$defs/ProfileRef"
}
]
}
},
"description": "System boundary importing and exporting carriers.\n\n``imports`` bring flow into the system (sources); ``exports`` send it out\nof the system (sinks).",
"properties": {
"id": {
"title": "Id",
"type": "string"
},
"imports": {
"items": {
"$ref": "#/$defs/Flow"
},
"title": "Imports",
"type": "array"
},
"exports": {
"items": {
"$ref": "#/$defs/Flow"
},
"title": "Exports",
"type": "array"
}
},
"required": [
"id"
],
"title": "Port",
"type": "object"
}
Config:
default:_PYDANTIC_CFG
Fields:
imports
pydantic-field
¶
Flows bringing the carrier into the system (sources, e.g. grid supply).
exports
pydantic-field
¶
Flows sending the carrier out of the system (sinks, e.g. demand).
Carrier
pydantic-model
¶
Bases: Element
Physical energy medium (electricity, heat, gas, …).
Show JSON schema:
{
"description": "Physical energy medium (electricity, heat, gas, \u2026).",
"properties": {
"id": {
"title": "Id",
"type": "string"
},
"nodes": {
"items": {
"type": "string"
},
"title": "Nodes",
"type": "array"
},
"unit": {
"default": "MWh",
"title": "Unit",
"type": "string"
},
"color": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Color"
},
"description": {
"default": "",
"title": "Description",
"type": "string"
}
},
"required": [
"id"
],
"title": "Carrier",
"type": "object"
}
Fields:
nodes
pydantic-field
¶
Sub-nodes for multi-node balancing. Empty means single-node.
Effect
pydantic-model
¶
Bases: Element
A tracked quantity across the optimization horizon (cost, CO₂, …).
One effect is designated as the objective to minimize via the
objective argument of optimize(). Others can be bounded
to enforce budgets (e.g. emission caps).
Effects accumulate contributions from two domains:
- Temporal — per-timestep flow costs, running costs, startup costs.
- Lump — one-time sizing costs and fixed costs.
Cross-effect chains (e.g. CO₂ → cost) are supported via
contribution_from.
See: docs/math/effects.md
Show JSON schema:
{
"$defs": {
"ProfileRef": {
"description": "Reference to a time-series stored outside the model definition.\n\nA serializable stand-in for an inline ``Variate`` array: the profile lives\nin a data file / dataset and is named here, so structural definitions\nround-trip to YAML/JSON without inlining 8760-point series. Resolve it to a\n:class:`xr.DataArray` with :meth:`resolve` before building the model.",
"properties": {
"dataset": {
"title": "Dataset",
"type": "string"
},
"variable": {
"title": "Variable",
"type": "string"
}
},
"required": [
"dataset",
"variable"
],
"title": "ProfileRef",
"type": "object"
},
"Variate": {
"anyOf": [
{
"type": "number"
},
{
"type": "integer"
},
{
"items": {
"type": "number"
},
"type": "array"
},
{
"$ref": "#/$defs/ProfileRef"
}
]
}
},
"description": "A tracked quantity across the optimization horizon (cost, CO\u2082, \u2026).\n\nOne effect is designated as the objective to minimize via the\n``objective`` argument of ``optimize()``. Others can be bounded\nto enforce budgets (e.g. emission caps).\n\nEffects accumulate contributions from two domains:\n\n- **Temporal** \u2014 per-timestep flow costs, running costs, startup costs.\n- **Lump** \u2014 one-time sizing costs and fixed costs.\n\nCross-effect chains (e.g. CO\u2082 \u2192 cost) are supported via\n``contribution_from``.\n\nSee: docs/math/effects.md",
"properties": {
"id": {
"title": "Id",
"type": "string"
},
"unit": {
"default": "",
"title": "Unit",
"type": "string"
},
"total_max": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Max"
},
"total_min": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Min"
},
"periodic_max": {
"anyOf": [
{
"$ref": "#/$defs/Variate"
},
{
"type": "null"
}
],
"default": null
},
"periodic_min": {
"anyOf": [
{
"$ref": "#/$defs/Variate"
},
{
"type": "null"
}
],
"default": null
},
"contribution_from": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Contribution From",
"type": "object"
},
"period_weights": {
"anyOf": [
{
"items": {
"type": "number"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Period Weights"
}
},
"required": [
"id"
],
"title": "Effect",
"type": "object"
}
Fields:
-
id(str) -
unit(str) -
total_max(float | None) -
total_min(float | None) -
periodic_max(Variate | None) -
periodic_min(Variate | None) -
contribution_from(dict[str, Variate]) -
period_weights(list[float] | None)
total_max
pydantic-field
¶
total_max: float | None = None
Upper bound on weighted total across all periods.
total_min
pydantic-field
¶
total_min: float | None = None
Lower bound on weighted total across all periods.
periodic_max
pydantic-field
¶
periodic_max: Variate | None = None
Upper bound applied to each period independently. Scalar or per-period values (multi-period only).
periodic_min
pydantic-field
¶
periodic_min: Variate | None = None
Lower bound applied to each period independently. Scalar or per-period values (multi-period only).
contribution_from
pydantic-field
¶
Cross-effect factors {source_effect: factor}.
Scalar factors apply identically to both domains. Time-varying factors
apply per-timestep in the temporal domain and are rejected at build time
when the source effect carries lump (sizing/fixed) contributions.
Flow
pydantic-model
¶
Bases: Element
A single energy flow on a carrier.
short_id defaults to carrier (or carrier:node when node
is set). Set explicitly to disambiguate multiple flows on the same
carrier::
Flow(carrier='elec') # short_id='elec'
Flow(carrier='heat', node='A') # short_id='heat:A'
Flow(carrier='elec', short_id='base') # short_id='base'
short_id must be unique within a component. The system-global
qualified id component(short_id) is derived at build time and
appears as the flow coordinate in ModelData and results; the
flow itself is never modified. Storage resolves colliding short_ids
to charge / discharge at that point.
See: docs/math/flows.md
Show JSON schema:
{
"$defs": {
"Investment": {
"description": "Singular discrete build-timing optimization.\n\nThe solver decides WHEN to build (which period) and at what size.\nOnce built, capacity is available for ``lifetime`` periods.\nSize is decided once \u2014 no growth or partial retirement.",
"properties": {
"size_min": {
"minimum": 0,
"title": "Size Min",
"type": "number"
},
"size_max": {
"minimum": 0,
"title": "Size Max",
"type": "number"
},
"mandatory": {
"default": true,
"title": "Mandatory",
"type": "boolean"
},
"lifetime": {
"anyOf": [
{
"exclusiveMinimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Lifetime"
},
"prior_size": {
"default": 0.0,
"minimum": 0,
"title": "Prior Size",
"type": "number"
},
"effects_per_size_at_build": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Size At Build",
"type": "object"
},
"effects_fixed_at_build": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Fixed At Build",
"type": "object"
},
"effects_per_size_recurring": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Size Recurring",
"type": "object"
},
"effects_fixed_recurring": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Fixed Recurring",
"type": "object"
}
},
"required": [
"size_min",
"size_max"
],
"title": "Investment",
"type": "object"
},
"ProfileRef": {
"description": "Reference to a time-series stored outside the model definition.\n\nA serializable stand-in for an inline ``Variate`` array: the profile lives\nin a data file / dataset and is named here, so structural definitions\nround-trip to YAML/JSON without inlining 8760-point series. Resolve it to a\n:class:`xr.DataArray` with :meth:`resolve` before building the model.",
"properties": {
"dataset": {
"title": "Dataset",
"type": "string"
},
"variable": {
"title": "Variable",
"type": "string"
}
},
"required": [
"dataset",
"variable"
],
"title": "ProfileRef",
"type": "object"
},
"Sizing": {
"description": "Capacity optimization parameters.\n\nThe solver decides the optimal size within [size_min, size_max].\n\n- ``mandatory=True``: continuous, size in [min, max], no binary.\n- ``mandatory=False``: binary indicator gates size: 0 or [min, max].\n- ``size_min == size_max`` with ``mandatory=False``: binary invest\n at exact size (yes/no).\n\nSee: docs/math/sizing.md",
"properties": {
"size_min": {
"minimum": 0,
"title": "Size Min",
"type": "number"
},
"size_max": {
"minimum": 0,
"title": "Size Max",
"type": "number"
},
"mandatory": {
"default": true,
"title": "Mandatory",
"type": "boolean"
},
"effects_per_size": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Size",
"type": "object"
},
"effects_fixed": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Fixed",
"type": "object"
}
},
"required": [
"size_min",
"size_max"
],
"title": "Sizing",
"type": "object"
},
"Status": {
"description": "Binary on/off behavior parameters.\n\nTogether with relative bounds, gives semi-continuous behavior:\n``{0} U [min, max] * size``.\n\nSee: docs/math/status.md",
"properties": {
"uptime_min": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Uptime Min"
},
"uptime_max": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Uptime Max"
},
"downtime_min": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Downtime Min"
},
"downtime_max": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Downtime Max"
},
"effects_per_running_hour": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Running Hour",
"type": "object"
},
"effects_per_startup": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Startup",
"type": "object"
}
},
"title": "Status",
"type": "object"
},
"Variate": {
"anyOf": [
{
"type": "number"
},
{
"type": "integer"
},
{
"items": {
"type": "number"
},
"type": "array"
},
{
"$ref": "#/$defs/ProfileRef"
}
]
}
},
"description": "A single energy flow on a carrier.\n\n``short_id`` defaults to ``carrier`` (or ``carrier:node`` when ``node``\nis set). Set explicitly to disambiguate multiple flows on the same\ncarrier::\n\n Flow(carrier='elec') # short_id='elec'\n Flow(carrier='heat', node='A') # short_id='heat:A'\n Flow(carrier='elec', short_id='base') # short_id='base'\n\n``short_id`` must be unique within a component. The system-global\nqualified id ``component(short_id)`` is derived at build time and\nappears as the ``flow`` coordinate in ``ModelData`` and results; the\nflow itself is never modified. Storage resolves colliding short_ids\nto ``charge`` / ``discharge`` at that point.\n\nSee: docs/math/flows.md",
"properties": {
"carrier": {
"title": "Carrier",
"type": "string"
},
"short_id": {
"default": "",
"title": "Short Id",
"type": "string"
},
"node": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Node"
},
"size": {
"anyOf": [
{
"type": "number"
},
{
"$ref": "#/$defs/Sizing"
},
{
"$ref": "#/$defs/Investment"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"relative_rate_min": {
"$ref": "#/$defs/Variate",
"default": 0.0
},
"relative_rate_max": {
"$ref": "#/$defs/Variate",
"default": 1.0
},
"fixed_relative_profile": {
"anyOf": [
{
"$ref": "#/$defs/Variate"
},
{
"type": "null"
}
],
"default": null
},
"effects_per_flow_hour": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Flow Hour",
"type": "object"
},
"flow_hours_min": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Flow Hours Min"
},
"flow_hours_max": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Flow Hours Max"
},
"load_factor_min": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Load Factor Min"
},
"load_factor_max": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Load Factor Max"
},
"ramp_up_per_hour": {
"anyOf": [
{
"$ref": "#/$defs/Variate"
},
{
"type": "null"
}
],
"default": null
},
"ramp_down_per_hour": {
"anyOf": [
{
"$ref": "#/$defs/Variate"
},
{
"type": "null"
}
],
"default": null
},
"status": {
"anyOf": [
{
"$ref": "#/$defs/Status"
},
{
"type": "null"
}
],
"default": null
},
"prior_rates": {
"anyOf": [
{
"items": {
"type": "number"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Prior Rates"
}
},
"required": [
"carrier"
],
"title": "Flow",
"type": "object"
}
Fields:
-
carrier(str) -
short_id(str) -
node(str | None) -
size(float | Sizing | Investment | None) -
relative_rate_min(Variate) -
relative_rate_max(Variate) -
fixed_relative_profile(Variate | None) -
effects_per_flow_hour(dict[str, Variate]) -
flow_hours_min(float | None) -
flow_hours_max(float | None) -
load_factor_min(float | None) -
load_factor_max(float | None) -
ramp_up_per_hour(Variate | None) -
ramp_down_per_hour(Variate | None) -
status(Status | None) -
prior_rates(list[float] | None)
short_id
pydantic-field
¶
short_id: str = ''
Component-local identifier; defaults to carrier
(or carrier:node). The qualified form component(short_id)
is derived at build time.
size
pydantic-field
¶
size: float | Sizing | Investment | None = None
Nominal capacity [MW], Sizing for investment optimization,
or None (unsized / unbounded).
relative_rate_min
pydantic-field
¶
relative_rate_min: Variate = 0.0
Lower bound as fraction of size.
relative_rate_max
pydantic-field
¶
relative_rate_max: Variate = 1.0
Upper bound as fraction of size.
fixed_relative_profile
pydantic-field
¶
fixed_relative_profile: Variate | None = None
Fixed profile as fraction of size; sets both lower and upper bounds equal to the profile value.
effects_per_flow_hour
pydantic-field
¶
Effect coefficients per flow-hour (e.g. €/MWh).
flow_hours_min
pydantic-field
¶
flow_hours_min: float | None = None
Lower bound on total flow-hours Σ P·Δt [MWh],
applied to each period independently.
flow_hours_max
pydantic-field
¶
flow_hours_max: float | None = None
Upper bound on total flow-hours Σ P·Δt [MWh],
applied to each period independently.
load_factor_min
pydantic-field
¶
load_factor_min: float | None = None
Lower bound on utilization Σ P·Δt / (size·T),
applied to each period independently. Requires size.
load_factor_max
pydantic-field
¶
load_factor_max: float | None = None
Upper bound on utilization Σ P·Δt / (size·T),
applied to each period independently. Requires size.
ramp_up_per_hour
pydantic-field
¶
ramp_up_per_hour: Variate | None = None
Maximum rate increase between consecutive
timesteps, as fraction of size per hour. Requires size.
ramp_down_per_hour
pydantic-field
¶
ramp_down_per_hour: Variate | None = None
Maximum rate decrease between consecutive
timesteps, as fraction of size per hour. Requires size.
status
pydantic-field
¶
status: Status | None = None
On/off behavior (semi-continuous, startup costs, durations).
prior_rates
pydantic-field
¶
Flow rates [MW] before the horizon, used for status initial conditions.
model_post_init
¶
model_post_init(__context: Any) -> None
Default short_id from carrier/node and validate field combinations.
Source code in src/fluxopt/elements.py
Investment
pydantic-model
¶
Bases: Element
Singular discrete build-timing optimization.
The solver decides WHEN to build (which period) and at what size.
Once built, capacity is available for lifetime periods.
Size is decided once — no growth or partial retirement.
Show JSON schema:
{
"$defs": {
"ProfileRef": {
"description": "Reference to a time-series stored outside the model definition.\n\nA serializable stand-in for an inline ``Variate`` array: the profile lives\nin a data file / dataset and is named here, so structural definitions\nround-trip to YAML/JSON without inlining 8760-point series. Resolve it to a\n:class:`xr.DataArray` with :meth:`resolve` before building the model.",
"properties": {
"dataset": {
"title": "Dataset",
"type": "string"
},
"variable": {
"title": "Variable",
"type": "string"
}
},
"required": [
"dataset",
"variable"
],
"title": "ProfileRef",
"type": "object"
},
"Variate": {
"anyOf": [
{
"type": "number"
},
{
"type": "integer"
},
{
"items": {
"type": "number"
},
"type": "array"
},
{
"$ref": "#/$defs/ProfileRef"
}
]
}
},
"description": "Singular discrete build-timing optimization.\n\nThe solver decides WHEN to build (which period) and at what size.\nOnce built, capacity is available for ``lifetime`` periods.\nSize is decided once \u2014 no growth or partial retirement.",
"properties": {
"size_min": {
"minimum": 0,
"title": "Size Min",
"type": "number"
},
"size_max": {
"minimum": 0,
"title": "Size Max",
"type": "number"
},
"mandatory": {
"default": true,
"title": "Mandatory",
"type": "boolean"
},
"lifetime": {
"anyOf": [
{
"exclusiveMinimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Lifetime"
},
"prior_size": {
"default": 0.0,
"minimum": 0,
"title": "Prior Size",
"type": "number"
},
"effects_per_size_at_build": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Size At Build",
"type": "object"
},
"effects_fixed_at_build": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Fixed At Build",
"type": "object"
},
"effects_per_size_recurring": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Size Recurring",
"type": "object"
},
"effects_fixed_recurring": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Fixed Recurring",
"type": "object"
}
},
"required": [
"size_min",
"size_max"
],
"title": "Investment",
"type": "object"
}
Fields:
-
size_min(float) -
size_max(float) -
mandatory(bool) -
lifetime(int | None) -
prior_size(float) -
effects_per_size_at_build(dict[str, Variate]) -
effects_fixed_at_build(dict[str, Variate]) -
effects_per_size_recurring(dict[str, Variate]) -
effects_fixed_recurring(dict[str, Variate])
Validators:
-
_bounds_are_ordered
mandatory
pydantic-field
¶
mandatory: bool = True
If True, must build exactly once; if False, may build at most once.
effects_per_size_at_build
pydantic-field
¶
One-time per-MW costs charged in the build period.
effects_fixed_at_build
pydantic-field
¶
One-time fixed costs charged in the build period.
effects_per_size_recurring
pydantic-field
¶
Recurring per-MW costs charged every active period.
PiecewiseConversion
pydantic-model
¶
Bases: Element
Piecewise-linear conversion linking N flows.
Wraps :func:linopy.piecewise.add_piecewise_formulation. All flows
share interpolation weights — every operating point lies on the same
piece of the curve.
Two input forms:
-
Dict — equality-only, terse for the common case::
PiecewiseConversion(points={'fuel': [0, 50, 100], 'Heat': [0, 45, 70]})
-
List of tuples — supports per-flow inequality bounds::
PiecewiseConversion( points=[ ('fuel', [0, 50, 100]), ('Heat', [0, 45, 70], '>='), ] )
See: docs/math/converters.md
Show JSON schema:
{
"$defs": {
"PiecewiseMethod": {
"enum": [
"auto",
"sos2",
"incremental",
"lp"
],
"type": "string"
},
"ProfileRef": {
"description": "Reference to a time-series stored outside the model definition.\n\nA serializable stand-in for an inline ``Variate`` array: the profile lives\nin a data file / dataset and is named here, so structural definitions\nround-trip to YAML/JSON without inlining 8760-point series. Resolve it to a\n:class:`xr.DataArray` with :meth:`resolve` before building the model.",
"properties": {
"dataset": {
"title": "Dataset",
"type": "string"
},
"variable": {
"title": "Variable",
"type": "string"
}
},
"required": [
"dataset",
"variable"
],
"title": "ProfileRef",
"type": "object"
},
"Status": {
"description": "Binary on/off behavior parameters.\n\nTogether with relative bounds, gives semi-continuous behavior:\n``{0} U [min, max] * size``.\n\nSee: docs/math/status.md",
"properties": {
"uptime_min": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Uptime Min"
},
"uptime_max": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Uptime Max"
},
"downtime_min": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Downtime Min"
},
"downtime_max": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Downtime Max"
},
"effects_per_running_hour": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Running Hour",
"type": "object"
},
"effects_per_startup": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Startup",
"type": "object"
}
},
"title": "Status",
"type": "object"
},
"Variate": {
"anyOf": [
{
"type": "number"
},
{
"type": "integer"
},
{
"items": {
"type": "number"
},
"type": "array"
},
{
"$ref": "#/$defs/ProfileRef"
}
]
}
},
"description": "Piecewise-linear conversion linking N flows.\n\nWraps :func:`linopy.piecewise.add_piecewise_formulation`. All flows\nshare interpolation weights \u2014 every operating point lies on the same\npiece of the curve.\n\nTwo input forms:\n\n- **Dict** \u2014 equality-only, terse for the common case::\n\n PiecewiseConversion(points={'fuel': [0, 50, 100], 'Heat': [0, 45, 70]})\n\n- **List of tuples** \u2014 supports per-flow inequality bounds::\n\n PiecewiseConversion(\n points=[\n ('fuel', [0, 50, 100]),\n ('Heat', [0, 45, 70], '>='),\n ]\n )\n\nSee: docs/math/converters.md",
"properties": {
"points": {
"anyOf": [
{
"additionalProperties": {
"items": {
"$ref": "#/$defs/Variate"
},
"type": "array"
},
"type": "object"
},
{
"items": {
"anyOf": [
{
"maxItems": 2,
"minItems": 2,
"prefixItems": [
{
"type": "string"
},
{
"items": {
"$ref": "#/$defs/Variate"
},
"type": "array"
}
],
"type": "array"
},
{
"maxItems": 3,
"minItems": 3,
"prefixItems": [
{
"type": "string"
},
{
"items": {
"$ref": "#/$defs/Variate"
},
"type": "array"
},
{
"enum": [
"==",
"<=",
">="
],
"type": "string"
}
],
"type": "array"
}
]
},
"type": "array"
}
],
"title": "Points"
},
"method": {
"$ref": "#/$defs/PiecewiseMethod",
"default": "auto"
},
"status": {
"anyOf": [
{
"$ref": "#/$defs/Status"
},
{
"type": "null"
}
],
"default": null
},
"availability": {
"$ref": "#/$defs/Variate",
"default": 1.0
}
},
"required": [
"points"
],
"title": "PiecewiseConversion",
"type": "object"
}
Fields:
-
points(dict[str, list[Variate]] | list[_CurveTuple]) -
method(PiecewiseMethod) -
status(Status | None) -
availability(Variate)
points
pydantic-field
¶
Per-flow breakpoints. Either {flow: [bp...]} (equality
only) or a list of (flow, [bp...]) / (flow, [bp...], '<='|'>=')
tuples. Need >=2 flows; all breakpoint lists must share the same
length (>=2). At most one tuple may carry a non-equality bound,
and only when exactly two flows are present.
method
pydantic-field
¶
Formulation. "auto" picks LP (2 flows + bounded +
matching convexity), else incremental (monotonic) or sos2.
Override with "sos2" / "incremental" / "lp".
status
pydantic-field
¶
status: Status | None = None
Component-level on/off behavior gating the curve.
availability
pydantic-field
¶
availability: Variate = 1.0
Time-varying scaling of the upper breakpoint.
model_post_init
¶
model_post_init(__context: Any) -> None
Validate normalized breakpoints and bound combinations.
Source code in src/fluxopt/elements.py
Sizing
pydantic-model
¶
Bases: Element
Capacity optimization parameters.
The solver decides the optimal size within [size_min, size_max].
mandatory=True: continuous, size in [min, max], no binary.mandatory=False: binary indicator gates size: 0 or [min, max].size_min == size_maxwithmandatory=False: binary invest at exact size (yes/no).
See: docs/math/sizing.md
Show JSON schema:
{
"$defs": {
"ProfileRef": {
"description": "Reference to a time-series stored outside the model definition.\n\nA serializable stand-in for an inline ``Variate`` array: the profile lives\nin a data file / dataset and is named here, so structural definitions\nround-trip to YAML/JSON without inlining 8760-point series. Resolve it to a\n:class:`xr.DataArray` with :meth:`resolve` before building the model.",
"properties": {
"dataset": {
"title": "Dataset",
"type": "string"
},
"variable": {
"title": "Variable",
"type": "string"
}
},
"required": [
"dataset",
"variable"
],
"title": "ProfileRef",
"type": "object"
},
"Variate": {
"anyOf": [
{
"type": "number"
},
{
"type": "integer"
},
{
"items": {
"type": "number"
},
"type": "array"
},
{
"$ref": "#/$defs/ProfileRef"
}
]
}
},
"description": "Capacity optimization parameters.\n\nThe solver decides the optimal size within [size_min, size_max].\n\n- ``mandatory=True``: continuous, size in [min, max], no binary.\n- ``mandatory=False``: binary indicator gates size: 0 or [min, max].\n- ``size_min == size_max`` with ``mandatory=False``: binary invest\n at exact size (yes/no).\n\nSee: docs/math/sizing.md",
"properties": {
"size_min": {
"minimum": 0,
"title": "Size Min",
"type": "number"
},
"size_max": {
"minimum": 0,
"title": "Size Max",
"type": "number"
},
"mandatory": {
"default": true,
"title": "Mandatory",
"type": "boolean"
},
"effects_per_size": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Size",
"type": "object"
},
"effects_fixed": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Fixed",
"type": "object"
}
},
"required": [
"size_min",
"size_max"
],
"title": "Sizing",
"type": "object"
}
Fields:
-
size_min(float) -
size_max(float) -
mandatory(bool) -
effects_per_size(dict[str, Variate]) -
effects_fixed(dict[str, Variate])
Validators:
-
_bounds_are_ordered
effects_per_size
pydantic-field
¶
Effect cost per unit size (e.g. €/MW).
Status
pydantic-model
¶
Bases: Element
Binary on/off behavior parameters.
Together with relative bounds, gives semi-continuous behavior:
{0} U [min, max] * size.
See: docs/math/status.md
Show JSON schema:
{
"$defs": {
"ProfileRef": {
"description": "Reference to a time-series stored outside the model definition.\n\nA serializable stand-in for an inline ``Variate`` array: the profile lives\nin a data file / dataset and is named here, so structural definitions\nround-trip to YAML/JSON without inlining 8760-point series. Resolve it to a\n:class:`xr.DataArray` with :meth:`resolve` before building the model.",
"properties": {
"dataset": {
"title": "Dataset",
"type": "string"
},
"variable": {
"title": "Variable",
"type": "string"
}
},
"required": [
"dataset",
"variable"
],
"title": "ProfileRef",
"type": "object"
},
"Variate": {
"anyOf": [
{
"type": "number"
},
{
"type": "integer"
},
{
"items": {
"type": "number"
},
"type": "array"
},
{
"$ref": "#/$defs/ProfileRef"
}
]
}
},
"description": "Binary on/off behavior parameters.\n\nTogether with relative bounds, gives semi-continuous behavior:\n``{0} U [min, max] * size``.\n\nSee: docs/math/status.md",
"properties": {
"uptime_min": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Uptime Min"
},
"uptime_max": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Uptime Max"
},
"downtime_min": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Downtime Min"
},
"downtime_max": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Downtime Max"
},
"effects_per_running_hour": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Running Hour",
"type": "object"
},
"effects_per_startup": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Startup",
"type": "object"
}
},
"title": "Status",
"type": "object"
}
Fields:
-
uptime_min(float | None) -
uptime_max(float | None) -
downtime_min(float | None) -
downtime_max(float | None) -
effects_per_running_hour(dict[str, Variate]) -
effects_per_startup(dict[str, Variate])
Validators:
-
_durations_are_ordered
effects_per_running_hour
pydantic-field
¶
Effect cost per running hour.
Storage
pydantic-model
¶
Bases: Element
Energy storage with level dynamics.
Flow ids are qualified as storage(flow) at build time. When both
flows share a short_id, the qualified ids use charge /
discharge instead (the flows themselves are never modified)::
Storage(
id='bat', charging=Flow(carrier='elec'), discharging=Flow(carrier='elec')
) # bat(charge), bat(discharge)
Storage(
id='bat',
charging=Flow(carrier='elec', short_id='in'),
discharging=Flow(carrier='elec', short_id='out'),
) # bat(in), bat(out)
Level balance::
E_{s,t+1} = E_{s,t} (1 - δ)^Δt + P^c η^c Δt - P^d / η^d Δt
See: docs/math/storage.md
Show JSON schema:
{
"$defs": {
"Flow": {
"description": "A single energy flow on a carrier.\n\n``short_id`` defaults to ``carrier`` (or ``carrier:node`` when ``node``\nis set). Set explicitly to disambiguate multiple flows on the same\ncarrier::\n\n Flow(carrier='elec') # short_id='elec'\n Flow(carrier='heat', node='A') # short_id='heat:A'\n Flow(carrier='elec', short_id='base') # short_id='base'\n\n``short_id`` must be unique within a component. The system-global\nqualified id ``component(short_id)`` is derived at build time and\nappears as the ``flow`` coordinate in ``ModelData`` and results; the\nflow itself is never modified. Storage resolves colliding short_ids\nto ``charge`` / ``discharge`` at that point.\n\nSee: docs/math/flows.md",
"properties": {
"carrier": {
"title": "Carrier",
"type": "string"
},
"short_id": {
"default": "",
"title": "Short Id",
"type": "string"
},
"node": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Node"
},
"size": {
"anyOf": [
{
"type": "number"
},
{
"$ref": "#/$defs/Sizing"
},
{
"$ref": "#/$defs/Investment"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"relative_rate_min": {
"$ref": "#/$defs/Variate",
"default": 0.0
},
"relative_rate_max": {
"$ref": "#/$defs/Variate",
"default": 1.0
},
"fixed_relative_profile": {
"anyOf": [
{
"$ref": "#/$defs/Variate"
},
{
"type": "null"
}
],
"default": null
},
"effects_per_flow_hour": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Flow Hour",
"type": "object"
},
"flow_hours_min": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Flow Hours Min"
},
"flow_hours_max": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Flow Hours Max"
},
"load_factor_min": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Load Factor Min"
},
"load_factor_max": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Load Factor Max"
},
"ramp_up_per_hour": {
"anyOf": [
{
"$ref": "#/$defs/Variate"
},
{
"type": "null"
}
],
"default": null
},
"ramp_down_per_hour": {
"anyOf": [
{
"$ref": "#/$defs/Variate"
},
{
"type": "null"
}
],
"default": null
},
"status": {
"anyOf": [
{
"$ref": "#/$defs/Status"
},
{
"type": "null"
}
],
"default": null
},
"prior_rates": {
"anyOf": [
{
"items": {
"type": "number"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Prior Rates"
}
},
"required": [
"carrier"
],
"title": "Flow",
"type": "object"
},
"Investment": {
"description": "Singular discrete build-timing optimization.\n\nThe solver decides WHEN to build (which period) and at what size.\nOnce built, capacity is available for ``lifetime`` periods.\nSize is decided once \u2014 no growth or partial retirement.",
"properties": {
"size_min": {
"minimum": 0,
"title": "Size Min",
"type": "number"
},
"size_max": {
"minimum": 0,
"title": "Size Max",
"type": "number"
},
"mandatory": {
"default": true,
"title": "Mandatory",
"type": "boolean"
},
"lifetime": {
"anyOf": [
{
"exclusiveMinimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Lifetime"
},
"prior_size": {
"default": 0.0,
"minimum": 0,
"title": "Prior Size",
"type": "number"
},
"effects_per_size_at_build": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Size At Build",
"type": "object"
},
"effects_fixed_at_build": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Fixed At Build",
"type": "object"
},
"effects_per_size_recurring": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Size Recurring",
"type": "object"
},
"effects_fixed_recurring": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Fixed Recurring",
"type": "object"
}
},
"required": [
"size_min",
"size_max"
],
"title": "Investment",
"type": "object"
},
"ProfileRef": {
"description": "Reference to a time-series stored outside the model definition.\n\nA serializable stand-in for an inline ``Variate`` array: the profile lives\nin a data file / dataset and is named here, so structural definitions\nround-trip to YAML/JSON without inlining 8760-point series. Resolve it to a\n:class:`xr.DataArray` with :meth:`resolve` before building the model.",
"properties": {
"dataset": {
"title": "Dataset",
"type": "string"
},
"variable": {
"title": "Variable",
"type": "string"
}
},
"required": [
"dataset",
"variable"
],
"title": "ProfileRef",
"type": "object"
},
"Sizing": {
"description": "Capacity optimization parameters.\n\nThe solver decides the optimal size within [size_min, size_max].\n\n- ``mandatory=True``: continuous, size in [min, max], no binary.\n- ``mandatory=False``: binary indicator gates size: 0 or [min, max].\n- ``size_min == size_max`` with ``mandatory=False``: binary invest\n at exact size (yes/no).\n\nSee: docs/math/sizing.md",
"properties": {
"size_min": {
"minimum": 0,
"title": "Size Min",
"type": "number"
},
"size_max": {
"minimum": 0,
"title": "Size Max",
"type": "number"
},
"mandatory": {
"default": true,
"title": "Mandatory",
"type": "boolean"
},
"effects_per_size": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Size",
"type": "object"
},
"effects_fixed": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Fixed",
"type": "object"
}
},
"required": [
"size_min",
"size_max"
],
"title": "Sizing",
"type": "object"
},
"Status": {
"description": "Binary on/off behavior parameters.\n\nTogether with relative bounds, gives semi-continuous behavior:\n``{0} U [min, max] * size``.\n\nSee: docs/math/status.md",
"properties": {
"uptime_min": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Uptime Min"
},
"uptime_max": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Uptime Max"
},
"downtime_min": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Downtime Min"
},
"downtime_max": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Downtime Max"
},
"effects_per_running_hour": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Running Hour",
"type": "object"
},
"effects_per_startup": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Startup",
"type": "object"
}
},
"title": "Status",
"type": "object"
},
"Variate": {
"anyOf": [
{
"type": "number"
},
{
"type": "integer"
},
{
"items": {
"type": "number"
},
"type": "array"
},
{
"$ref": "#/$defs/ProfileRef"
}
]
}
},
"description": "Energy storage with level dynamics.\n\nFlow ids are qualified as ``storage(flow)`` at build time. When both\nflows share a short_id, the qualified ids use ``charge`` /\n``discharge`` instead (the flows themselves are never modified)::\n\n Storage(\n id='bat', charging=Flow(carrier='elec'), discharging=Flow(carrier='elec')\n ) # bat(charge), bat(discharge)\n Storage(\n id='bat',\n charging=Flow(carrier='elec', short_id='in'),\n discharging=Flow(carrier='elec', short_id='out'),\n ) # bat(in), bat(out)\n\nLevel balance::\n\n E_{s,t+1} = E_{s,t} (1 - \u03b4)^\u0394t + P^c \u03b7^c \u0394t - P^d / \u03b7^d \u0394t\n\nSee: docs/math/storage.md",
"properties": {
"id": {
"title": "Id",
"type": "string"
},
"charging": {
"$ref": "#/$defs/Flow"
},
"discharging": {
"$ref": "#/$defs/Flow"
},
"capacity": {
"anyOf": [
{
"type": "number"
},
{
"$ref": "#/$defs/Sizing"
},
{
"$ref": "#/$defs/Investment"
},
{
"type": "null"
}
],
"default": null,
"title": "Capacity"
},
"eta_charge": {
"$ref": "#/$defs/Variate",
"default": 1.0
},
"eta_discharge": {
"$ref": "#/$defs/Variate",
"default": 1.0
},
"relative_loss_per_hour": {
"$ref": "#/$defs/Variate",
"default": 0.0
},
"prior_level": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Prior Level"
},
"cyclic": {
"default": true,
"title": "Cyclic",
"type": "boolean"
},
"relative_level_min": {
"$ref": "#/$defs/Variate",
"default": 0.0
},
"relative_level_max": {
"$ref": "#/$defs/Variate",
"default": 1.0
},
"final_level_min": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Final Level Min"
},
"final_level_max": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Final Level Max"
},
"prevent_simultaneous": {
"default": false,
"title": "Prevent Simultaneous",
"type": "boolean"
},
"status": {
"anyOf": [
{
"$ref": "#/$defs/Status"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"id",
"charging",
"discharging"
],
"title": "Storage",
"type": "object"
}
Fields:
-
id(str) -
charging(Flow) -
discharging(Flow) -
capacity(float | Sizing | Investment | None) -
eta_charge(Variate) -
eta_discharge(Variate) -
relative_loss_per_hour(Variate) -
prior_level(float | None) -
cyclic(bool) -
relative_level_min(Variate) -
relative_level_max(Variate) -
final_level_min(float | None) -
final_level_max(float | None) -
prevent_simultaneous(bool) -
status(Status | None)
capacity
pydantic-field
¶
capacity: float | Sizing | Investment | None = None
Maximum stored energy [MWh], Sizing for investment
optimization, or None.
relative_loss_per_hour
pydantic-field
¶
relative_loss_per_hour: Variate = 0.0
Self-discharge rate [1/h].
prior_level
pydantic-field
¶
prior_level: float | None = None
Initial energy level [MWh]; None = unconstrained.
relative_level_min
pydantic-field
¶
relative_level_min: Variate = 0.0
Min SOC as fraction of capacity.
relative_level_max
pydantic-field
¶
relative_level_max: Variate = 1.0
Max SOC as fraction of capacity.
final_level_min
pydantic-field
¶
final_level_min: float | None = None
Lower bound on the level at the last timestep [MWh], per period; None = unconstrained.
final_level_max
pydantic-field
¶
final_level_max: float | None = None
Upper bound on the level at the last timestep [MWh], per period; None = unconstrained.
prevent_simultaneous
pydantic-field
¶
prevent_simultaneous: bool = False
If True, a binary per timestep excludes charging and discharging at once. Requires sized flows (fixed or Sizing/Investment) for the big-M bound.
status
pydantic-field
¶
status: Status | None = None
Component-level on/off behavior gating both charging and
discharging. Forbids flow-level status on the child flows
(the two switches would have no defined precedence).
model_post_init
¶
model_post_init(__context: Any) -> None
Validate physical ranges, carrier match, and status/size requirements.
Source code in src/fluxopt/elements.py
FlowSystem
pydantic-model
¶
Bases: BaseModel
A declarative flow-system description (see module docstring).
Show JSON schema:
{
"$defs": {
"Carrier": {
"description": "Physical energy medium (electricity, heat, gas, \u2026).",
"properties": {
"id": {
"title": "Id",
"type": "string"
},
"nodes": {
"items": {
"type": "string"
},
"title": "Nodes",
"type": "array"
},
"unit": {
"default": "MWh",
"title": "Unit",
"type": "string"
},
"color": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Color"
},
"description": {
"default": "",
"title": "Description",
"type": "string"
}
},
"required": [
"id"
],
"title": "Carrier",
"type": "object"
},
"Converter": {
"description": "Conversion between input and output flows.\n\nTwo mutually exclusive modes:\n\n- **Linear** \u2014 ``conversion_factors=[{flow_short_id: a_f}, ...]``,\n one dict per equation; constraint ``sum_f(a_f * P_{f,t}) = 0``.\n- **Piecewise** \u2014 ``conversion=PiecewiseConversion(...)``; the solver\n interpolates between breakpoints, optionally with on/off via\n ``PiecewiseConversion.status``.",
"properties": {
"id": {
"title": "Id",
"type": "string"
},
"inputs": {
"items": {
"$ref": "#/$defs/Flow"
},
"title": "Inputs",
"type": "array"
},
"outputs": {
"items": {
"$ref": "#/$defs/Flow"
},
"title": "Outputs",
"type": "array"
},
"conversion_factors": {
"items": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"type": "object"
},
"title": "Conversion Factors",
"type": "array"
},
"conversion": {
"anyOf": [
{
"$ref": "#/$defs/PiecewiseConversion"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"id",
"inputs",
"outputs"
],
"title": "Converter",
"type": "object"
},
"Effect": {
"description": "A tracked quantity across the optimization horizon (cost, CO\u2082, \u2026).\n\nOne effect is designated as the objective to minimize via the\n``objective`` argument of ``optimize()``. Others can be bounded\nto enforce budgets (e.g. emission caps).\n\nEffects accumulate contributions from two domains:\n\n- **Temporal** \u2014 per-timestep flow costs, running costs, startup costs.\n- **Lump** \u2014 one-time sizing costs and fixed costs.\n\nCross-effect chains (e.g. CO\u2082 \u2192 cost) are supported via\n``contribution_from``.\n\nSee: docs/math/effects.md",
"properties": {
"id": {
"title": "Id",
"type": "string"
},
"unit": {
"default": "",
"title": "Unit",
"type": "string"
},
"total_max": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Max"
},
"total_min": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Total Min"
},
"periodic_max": {
"anyOf": [
{
"$ref": "#/$defs/Variate"
},
{
"type": "null"
}
],
"default": null
},
"periodic_min": {
"anyOf": [
{
"$ref": "#/$defs/Variate"
},
{
"type": "null"
}
],
"default": null
},
"contribution_from": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Contribution From",
"type": "object"
},
"period_weights": {
"anyOf": [
{
"items": {
"type": "number"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Period Weights"
}
},
"required": [
"id"
],
"title": "Effect",
"type": "object"
},
"Flow": {
"description": "A single energy flow on a carrier.\n\n``short_id`` defaults to ``carrier`` (or ``carrier:node`` when ``node``\nis set). Set explicitly to disambiguate multiple flows on the same\ncarrier::\n\n Flow(carrier='elec') # short_id='elec'\n Flow(carrier='heat', node='A') # short_id='heat:A'\n Flow(carrier='elec', short_id='base') # short_id='base'\n\n``short_id`` must be unique within a component. The system-global\nqualified id ``component(short_id)`` is derived at build time and\nappears as the ``flow`` coordinate in ``ModelData`` and results; the\nflow itself is never modified. Storage resolves colliding short_ids\nto ``charge`` / ``discharge`` at that point.\n\nSee: docs/math/flows.md",
"properties": {
"carrier": {
"title": "Carrier",
"type": "string"
},
"short_id": {
"default": "",
"title": "Short Id",
"type": "string"
},
"node": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Node"
},
"size": {
"anyOf": [
{
"type": "number"
},
{
"$ref": "#/$defs/Sizing"
},
{
"$ref": "#/$defs/Investment"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
},
"relative_rate_min": {
"$ref": "#/$defs/Variate",
"default": 0.0
},
"relative_rate_max": {
"$ref": "#/$defs/Variate",
"default": 1.0
},
"fixed_relative_profile": {
"anyOf": [
{
"$ref": "#/$defs/Variate"
},
{
"type": "null"
}
],
"default": null
},
"effects_per_flow_hour": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Flow Hour",
"type": "object"
},
"flow_hours_min": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Flow Hours Min"
},
"flow_hours_max": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Flow Hours Max"
},
"load_factor_min": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Load Factor Min"
},
"load_factor_max": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Load Factor Max"
},
"ramp_up_per_hour": {
"anyOf": [
{
"$ref": "#/$defs/Variate"
},
{
"type": "null"
}
],
"default": null
},
"ramp_down_per_hour": {
"anyOf": [
{
"$ref": "#/$defs/Variate"
},
{
"type": "null"
}
],
"default": null
},
"status": {
"anyOf": [
{
"$ref": "#/$defs/Status"
},
{
"type": "null"
}
],
"default": null
},
"prior_rates": {
"anyOf": [
{
"items": {
"type": "number"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Prior Rates"
}
},
"required": [
"carrier"
],
"title": "Flow",
"type": "object"
},
"Investment": {
"description": "Singular discrete build-timing optimization.\n\nThe solver decides WHEN to build (which period) and at what size.\nOnce built, capacity is available for ``lifetime`` periods.\nSize is decided once \u2014 no growth or partial retirement.",
"properties": {
"size_min": {
"minimum": 0,
"title": "Size Min",
"type": "number"
},
"size_max": {
"minimum": 0,
"title": "Size Max",
"type": "number"
},
"mandatory": {
"default": true,
"title": "Mandatory",
"type": "boolean"
},
"lifetime": {
"anyOf": [
{
"exclusiveMinimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Lifetime"
},
"prior_size": {
"default": 0.0,
"minimum": 0,
"title": "Prior Size",
"type": "number"
},
"effects_per_size_at_build": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Size At Build",
"type": "object"
},
"effects_fixed_at_build": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Fixed At Build",
"type": "object"
},
"effects_per_size_recurring": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Size Recurring",
"type": "object"
},
"effects_fixed_recurring": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Fixed Recurring",
"type": "object"
}
},
"required": [
"size_min",
"size_max"
],
"title": "Investment",
"type": "object"
},
"PiecewiseConversion": {
"description": "Piecewise-linear conversion linking N flows.\n\nWraps :func:`linopy.piecewise.add_piecewise_formulation`. All flows\nshare interpolation weights \u2014 every operating point lies on the same\npiece of the curve.\n\nTwo input forms:\n\n- **Dict** \u2014 equality-only, terse for the common case::\n\n PiecewiseConversion(points={'fuel': [0, 50, 100], 'Heat': [0, 45, 70]})\n\n- **List of tuples** \u2014 supports per-flow inequality bounds::\n\n PiecewiseConversion(\n points=[\n ('fuel', [0, 50, 100]),\n ('Heat', [0, 45, 70], '>='),\n ]\n )\n\nSee: docs/math/converters.md",
"properties": {
"points": {
"anyOf": [
{
"additionalProperties": {
"items": {
"$ref": "#/$defs/Variate"
},
"type": "array"
},
"type": "object"
},
{
"items": {
"anyOf": [
{
"maxItems": 2,
"minItems": 2,
"prefixItems": [
{
"type": "string"
},
{
"items": {
"$ref": "#/$defs/Variate"
},
"type": "array"
}
],
"type": "array"
},
{
"maxItems": 3,
"minItems": 3,
"prefixItems": [
{
"type": "string"
},
{
"items": {
"$ref": "#/$defs/Variate"
},
"type": "array"
},
{
"enum": [
"==",
"<=",
">="
],
"type": "string"
}
],
"type": "array"
}
]
},
"type": "array"
}
],
"title": "Points"
},
"method": {
"$ref": "#/$defs/PiecewiseMethod",
"default": "auto"
},
"status": {
"anyOf": [
{
"$ref": "#/$defs/Status"
},
{
"type": "null"
}
],
"default": null
},
"availability": {
"$ref": "#/$defs/Variate",
"default": 1.0
}
},
"required": [
"points"
],
"title": "PiecewiseConversion",
"type": "object"
},
"PiecewiseMethod": {
"enum": [
"auto",
"sos2",
"incremental",
"lp"
],
"type": "string"
},
"Port": {
"description": "System boundary importing and exporting carriers.\n\n``imports`` bring flow into the system (sources); ``exports`` send it out\nof the system (sinks).",
"properties": {
"id": {
"title": "Id",
"type": "string"
},
"imports": {
"items": {
"$ref": "#/$defs/Flow"
},
"title": "Imports",
"type": "array"
},
"exports": {
"items": {
"$ref": "#/$defs/Flow"
},
"title": "Exports",
"type": "array"
}
},
"required": [
"id"
],
"title": "Port",
"type": "object"
},
"ProfileRef": {
"description": "Reference to a time-series stored outside the model definition.\n\nA serializable stand-in for an inline ``Variate`` array: the profile lives\nin a data file / dataset and is named here, so structural definitions\nround-trip to YAML/JSON without inlining 8760-point series. Resolve it to a\n:class:`xr.DataArray` with :meth:`resolve` before building the model.",
"properties": {
"dataset": {
"title": "Dataset",
"type": "string"
},
"variable": {
"title": "Variable",
"type": "string"
}
},
"required": [
"dataset",
"variable"
],
"title": "ProfileRef",
"type": "object"
},
"Sizing": {
"description": "Capacity optimization parameters.\n\nThe solver decides the optimal size within [size_min, size_max].\n\n- ``mandatory=True``: continuous, size in [min, max], no binary.\n- ``mandatory=False``: binary indicator gates size: 0 or [min, max].\n- ``size_min == size_max`` with ``mandatory=False``: binary invest\n at exact size (yes/no).\n\nSee: docs/math/sizing.md",
"properties": {
"size_min": {
"minimum": 0,
"title": "Size Min",
"type": "number"
},
"size_max": {
"minimum": 0,
"title": "Size Max",
"type": "number"
},
"mandatory": {
"default": true,
"title": "Mandatory",
"type": "boolean"
},
"effects_per_size": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Size",
"type": "object"
},
"effects_fixed": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Fixed",
"type": "object"
}
},
"required": [
"size_min",
"size_max"
],
"title": "Sizing",
"type": "object"
},
"Status": {
"description": "Binary on/off behavior parameters.\n\nTogether with relative bounds, gives semi-continuous behavior:\n``{0} U [min, max] * size``.\n\nSee: docs/math/status.md",
"properties": {
"uptime_min": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Uptime Min"
},
"uptime_max": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Uptime Max"
},
"downtime_min": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Downtime Min"
},
"downtime_max": {
"anyOf": [
{
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Downtime Max"
},
"effects_per_running_hour": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Running Hour",
"type": "object"
},
"effects_per_startup": {
"additionalProperties": {
"$ref": "#/$defs/Variate"
},
"title": "Effects Per Startup",
"type": "object"
}
},
"title": "Status",
"type": "object"
},
"Storage": {
"description": "Energy storage with level dynamics.\n\nFlow ids are qualified as ``storage(flow)`` at build time. When both\nflows share a short_id, the qualified ids use ``charge`` /\n``discharge`` instead (the flows themselves are never modified)::\n\n Storage(\n id='bat', charging=Flow(carrier='elec'), discharging=Flow(carrier='elec')\n ) # bat(charge), bat(discharge)\n Storage(\n id='bat',\n charging=Flow(carrier='elec', short_id='in'),\n discharging=Flow(carrier='elec', short_id='out'),\n ) # bat(in), bat(out)\n\nLevel balance::\n\n E_{s,t+1} = E_{s,t} (1 - \u03b4)^\u0394t + P^c \u03b7^c \u0394t - P^d / \u03b7^d \u0394t\n\nSee: docs/math/storage.md",
"properties": {
"id": {
"title": "Id",
"type": "string"
},
"charging": {
"$ref": "#/$defs/Flow"
},
"discharging": {
"$ref": "#/$defs/Flow"
},
"capacity": {
"anyOf": [
{
"type": "number"
},
{
"$ref": "#/$defs/Sizing"
},
{
"$ref": "#/$defs/Investment"
},
{
"type": "null"
}
],
"default": null,
"title": "Capacity"
},
"eta_charge": {
"$ref": "#/$defs/Variate",
"default": 1.0
},
"eta_discharge": {
"$ref": "#/$defs/Variate",
"default": 1.0
},
"relative_loss_per_hour": {
"$ref": "#/$defs/Variate",
"default": 0.0
},
"prior_level": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Prior Level"
},
"cyclic": {
"default": true,
"title": "Cyclic",
"type": "boolean"
},
"relative_level_min": {
"$ref": "#/$defs/Variate",
"default": 0.0
},
"relative_level_max": {
"$ref": "#/$defs/Variate",
"default": 1.0
},
"final_level_min": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Final Level Min"
},
"final_level_max": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Final Level Max"
},
"prevent_simultaneous": {
"default": false,
"title": "Prevent Simultaneous",
"type": "boolean"
},
"status": {
"anyOf": [
{
"$ref": "#/$defs/Status"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"id",
"charging",
"discharging"
],
"title": "Storage",
"type": "object"
},
"Timesteps": {
"anyOf": [
{
"items": {
"format": "date-time",
"type": "string"
},
"type": "array"
},
{
"items": {
"type": "integer"
},
"type": "array"
}
]
},
"Variate": {
"anyOf": [
{
"type": "number"
},
{
"type": "integer"
},
{
"items": {
"type": "number"
},
"type": "array"
},
{
"$ref": "#/$defs/ProfileRef"
}
]
}
},
"description": "A declarative flow-system description (see module docstring).",
"properties": {
"timesteps": {
"$ref": "#/$defs/Timesteps"
},
"carriers": {
"items": {
"$ref": "#/$defs/Carrier"
},
"title": "Carriers",
"type": "array"
},
"effects": {
"items": {
"$ref": "#/$defs/Effect"
},
"title": "Effects",
"type": "array"
},
"ports": {
"items": {
"$ref": "#/$defs/Port"
},
"title": "Ports",
"type": "array"
},
"objective": {
"anyOf": [
{
"type": "string"
},
{
"additionalProperties": {
"type": "number"
},
"type": "object"
}
],
"title": "Objective"
},
"converters": {
"items": {
"$ref": "#/$defs/Converter"
},
"title": "Converters",
"type": "array"
},
"storages": {
"items": {
"$ref": "#/$defs/Storage"
},
"title": "Storages",
"type": "array"
},
"dt": {
"anyOf": [
{
"type": "number"
},
{
"items": {
"type": "number"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Dt"
},
"periods": {
"anyOf": [
{
"items": {
"type": "integer"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Periods"
},
"period_weights": {
"anyOf": [
{
"items": {
"type": "number"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"title": "Period Weights"
}
},
"required": [
"timesteps",
"carriers",
"effects",
"ports",
"objective"
],
"title": "FlowSystem",
"type": "object"
}
Config:
default:_PYDANTIC_CFG
Fields:
-
timesteps(Timesteps) -
carriers(list[Carrier]) -
effects(list[Effect]) -
ports(list[Port]) -
objective(str | dict[str, float]) -
converters(list[Converter]) -
storages(list[Storage]) -
dt(float | list[float] | None) -
periods(list[int] | None) -
period_weights(list[float] | None)
Validators:
-
_validate_references
objective
pydantic-field
¶
Effect(s) to minimize — a name or {effect: weight}. Must name at
least one non-penalty effect.
converters
pydantic-field
¶
Linear/piecewise converters between carriers.
dt
pydantic-field
¶
Timestep duration in hours. Auto-derived if None.
periods
pydantic-field
¶
Integer period labels for multi-period optimization.
period_weights
pydantic-field
¶
Explicit weights per period. Inferred from gaps if None.
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> FlowSystem
from_yaml
classmethod
¶
from_yaml(path: str | Path) -> FlowSystem
to_dict
¶
to_yaml
¶
required_profiles
¶
Enumerate the external data this system needs, as {dataset: variables}.
The contract a profiles supply must cover before
:meth:build_model / :meth:optimize can run. Empty when every value
is inline.
Source code in src/fluxopt/flow_system.py
math
¶
math() -> Any
The equations this system will be solved as, as data.
An :class:lpspec.Model — the whole program, before any of this
system's numbers are bound to it. Read it (to_yaml()), typeset it
(mathspec.to_latex(...)), or edit it and hand it back to
:meth:optimize as math=: adding a named quantity to
expressions: or a row to constraints: is how a caller extends
the math now, in the same language and with the same load-time checks
the shipped program gets.
Source code in src/fluxopt/flow_system.py
parameters
¶
parameters(profiles: Mapping[str, Any] | None = None) -> Parameters
The numbers this system binds to its math, as data.
The other half of :meth:math. That returns the equations before any
of this system's numbers reach them; this returns the numbers, keyed
as the program declares them — so (math, parameters/) is the
whole problem, hashable and diffable, and a caller adding a constraint
through math= can see what they are adding to.
Derived, never authored: the fold and the pre-scaling have already turned what the user declared into what the solver adds up, so the set is worth keeping and not worth editing. Change the elements or change the program.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
Mapping[str, Any] | None
|
Mapping from |
None
|
Source code in src/fluxopt/flow_system.py
build_data
¶
Materialize this declaration's data, resolving profile references.
Resolves ProfileRef references (on a copy — the system stays
reusable across different profiles) and builds the ModelData
both lanes read.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
Mapping[str, Any] | None
|
Mapping from |
None
|
Raises:
| Type | Description |
|---|---|
KeyError
|
If any |
Source code in src/fluxopt/flow_system.py
optimize
¶
optimize(
profiles: Mapping[str, Any] | None = None,
*,
solver: str = 'highs',
math: Any = None,
dimensions: Mapping[str, Any] | None = None,
lookups: Mapping[str, Any] | None = None,
parameters: Mapping[str, Any] | None = None,
**kwargs: Any,
) -> Result
Resolve profile references, build the data, and solve.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
Mapping[str, Any] | None
|
Mapping from |
None
|
|
str
|
Solver name — |
'highs'
|
|
Any
|
An edited :meth: |
None
|
|
Mapping[str, Any] | None
|
Labels for dimensions math adds. |
None
|
|
Mapping[str, Any] | None
|
Data for lookups math adds, as |
None
|
|
Mapping[str, Any] | None
|
Data for parameters math adds. The three are the language's own declaration blocks, and
:meth: |
None
|
|
Any
|
Passed to the solver verbatim, in its own vocabulary. |
{}
|
Source code in src/fluxopt/flow_system.py
Dims
dataclass
¶
The model's temporal axes: what a timestep is, and what a period is.
Two tables, indexed by position like every other container. The labels the user gave ride along as a column, because they are what a result is reported against and nothing else keys on them.
Absence is a missing table: a system with no investment periods has an
empty periods, which is what has_periods reads.
Methods:
| Name | Description |
|---|---|
coords |
Return shared coordinates for variable/DataArray creation. |
build |
Build Dims from a time index and optional periods. |
Attributes:
| Name | Type | Description |
|---|---|---|
has_periods |
bool
|
Whether the system declares an investment period axis. |
n_time |
int
|
How many timesteps the horizon has. |
n_periods |
int
|
How many periods the program indexes — one, when none are declared. |
period_labels |
list[Any]
|
The period labels, or |
time |
DataArray
|
Timestep labels as a coordinate. |
dt |
DataArray
|
Timestep durations [h] as a time-indexed array. |
weights |
DataArray
|
Timestep weights as a time-indexed array. |
period |
DataArray | None
|
Period labels as a coordinate, or None when there is no period axis. |
period_weights |
DataArray | None
|
Period duration weights, or None when there is no period axis. |
n_periods
property
¶
n_periods: int
How many periods the program indexes — one, when none are declared.
period_labels
property
¶
The period labels, or [0] when the system declares no periods.
period
property
¶
period: DataArray | None
Period labels as a coordinate, or None when there is no period axis.
period_weights
property
¶
period_weights: DataArray | None
Period duration weights, or None when there is no period axis.
coords
¶
Return shared coordinates for variable/DataArray creation.
Also the single point of truth for the model's variate dims used by
:func:fluxopt.types.as_dataarray: pick the reach a field supports
(e.g. coords(time=True, period=True) for operational profiles,
coords(period=True) for investment-time fields). When a new
variate dim (e.g. scenario) is added, extend this method once
and every call site picks it up.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
bool
|
Include the time coordinate. |
False
|
|
bool
|
Include the period coordinate (no-op in single-period mode). |
False
|
Source code in src/fluxopt/model_data.py
build
classmethod
¶
build(
time: TimeIndex,
dt: DataArray,
periods: list[int] | Index | None = None,
period_weights: list[float] | None = None,
) -> Self
Build Dims from a time index and optional periods.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
TimeIndex
|
Normalized time index. |
required |
|
DataArray
|
Timestep durations. |
required |
|
list[int] | Index | None
|
Integer period labels for multi-period optimization. |
None
|
|
list[float] | None
|
Explicit weights per period. Inferred from gaps if None. |
None
|
Source code in src/fluxopt/model_data.py
ModelData
dataclass
¶
ModelData(
flows: FlowsData,
carriers: CarriersData,
converters: ConvertersData | None,
effects: EffectsData,
storages: StoragesData | None,
dims: Dims,
piecewise: PiecewiseData | None = None,
status: StatusData | None = None,
)
Methods:
| Name | Description |
|---|---|
__post_init__ |
Check ids referenced between tables resolve. |
save |
Write the model data as a directory of tables. |
load |
Read model data written by :meth: |
build |
Build ModelData from element objects. |
__post_init__
¶
Check ids referenced between tables resolve.
Layer 3, and the clearest case for it: no single table can answer this, and a reloaded file never passed the system layer. See docs/design/validation-layers.md.
Each table validates itself in its own __post_init__; this checks
that ids referenced between tables resolve, so a tampered or
hand-edited file fails here instead of as a KeyError deep in
model building.
Source code in src/fluxopt/model_data.py
save
¶
Write the model data as a directory of tables.
One parquet file per frame, in a directory per container. Parquet because these are tables: it carries the schema, so a column with no rows still knows it holds strings, and an empty frame reloads as the same empty frame rather than as something that lost its dtypes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
str | Path
|
Directory to write into. Created if absent. |
required |
Source code in src/fluxopt/model_data.py
load
classmethod
¶
Read model data written by :meth:save.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
str | Path
|
The directory :meth: |
required |
Raises:
| Type | Description |
|---|---|
OSError
|
If the directory holds no fluxopt model data. |
Source code in src/fluxopt/model_data.py
build
classmethod
¶
build(
timesteps: Timesteps,
carriers: list[Carrier],
effects: list[Effect],
ports: list[Port],
converters: list[Converter] | None = None,
storages: list[Storage] | None = None,
dt: float | list[float] | None = None,
periods: list[int] | Index | None = None,
period_weights: list[float] | None = None,
) -> Self
Build ModelData from element objects.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
Timesteps
|
Time index for the optimization horizon. |
required |
|
list[Carrier]
|
Carrier declarations. |
required |
|
list[Effect]
|
Effects to track. |
required |
|
list[Port]
|
System boundary ports. |
required |
|
list[Converter] | None
|
Linear converters. |
None
|
|
list[Storage] | None
|
Energy storages. |
None
|
|
float | list[float] | None
|
Timestep duration in hours. Auto-derived if None. |
None
|
|
list[int] | Index | None
|
Integer period labels for multi-period optimization. |
None
|
|
list[float] | None
|
Explicit weights per period. Inferred from gaps if None. |
None
|
Source code in src/fluxopt/model_data.py
1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 | |
Result
dataclass
¶
Result(
solution: Dataset,
data: ModelData,
duals: Dataset = Dataset(),
expressions: Dataset = Dataset(),
)
Optimization result with solution variables and model data.
Provides access to flow rates, storage levels, effect totals, and investment decisions. Key properties::
result.objective # scalar objective value
result.flow_rates # (flow, time) DataArray
result.flow_rate('id') # single flow time series
result.storage_levels # (storage, time) DataArray
result.effect_totals # (effect,) DataArray
result.effects_temporal # (effect, time) DataArray
result.effects_lump # (effect,) DataArray
result.sizes # (flow,) DataArray — invested sizes
result.storage_capacities # (storage,) DataArray
Per-contributor effect breakdown is available via result.stats.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
Dataset
|
Solved variable values as xr.Dataset. |
required |
|
ModelData
|
ModelData used to build the optimization. |
required |
|
Dataset
|
Dual values (shadow prices) from the solver. |
Dataset()
|
|
Dataset
|
Every quantity the model names, evaluated at this
solution. A named expression is evaluated against a solve, so it
can only be had here — carrying them is what makes a |
Dataset()
|
Methods:
| Name | Description |
|---|---|
flow_rate |
Get flow rate time series for a single flow. |
storage_level |
Get charge state time series for a single storage. |
expression |
One quantity the model names, at this solution. |
save |
Write the result as a directory. |
load |
Read a result written by :meth: |
Attributes:
| Name | Type | Description |
|---|---|---|
objective |
float
|
Objective function value. |
objective_weights |
dict[str, float]
|
Effect weights the objective was minimized with (provenance). |
flow_rates |
DataArray
|
All flow rates as (flow, time) DataArray. |
storage_levels |
DataArray
|
All storage levels as (storage, time) DataArray. |
sizes |
DataArray
|
Optimized flow sizes as (flow,) DataArray. |
storage_capacities |
DataArray
|
Optimized storage capacities as (storage,) DataArray. |
effect_totals |
DataArray
|
Total effect values as (effect,) DataArray. |
effects_temporal |
DataArray
|
Per-timestep effect values as (effect, time) DataArray. |
effects_lump |
DataArray
|
Non-temporal effect values as (effect,) DataArray. |
topology |
dict[Literal['carriers', 'converters'], dict[str, dict[str, list[str]]]]
|
Carrier and converter connectivity derived from model data. |
stats |
StatsAccessor
|
Post-processing statistics accessor. |
plot |
PlotAccessor
|
Plotting accessor (requires |
objective_weights
property
¶
Effect weights the objective was minimized with (provenance).
Includes the built-in penalty effect (auto-added at 1.0 unless
named in objective). Empty for results saved before
this field existed.
storage_levels
property
¶
storage_levels: DataArray
All storage levels as (storage, time) DataArray.
storage_capacities
property
¶
storage_capacities: DataArray
Optimized storage capacities as (storage,) DataArray.
effects_temporal
property
¶
effects_temporal: DataArray
Per-timestep effect values as (effect, time) DataArray.
Reconstructed from flow rates and coefficients — the model carries no per-timestep effect variables (temporal closure).
topology
cached
property
¶
Carrier and converter connectivity derived from model data.
Returns a dict with carriers and converters keys, each mapping
element ids to their inputs (flows that produce into the element)
and outputs (flows that consume from it).
flow_rate
¶
storage_level
¶
storage_level(storage_id: str) -> DataArray
expression
¶
One quantity the model names, at this solution.
Whatever the program declares under expressions: — including
anything a caller added through optimize(math=...).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
str
|
The expression's name in the program. |
required |
Raises:
| Type | Description |
|---|---|
KeyError
|
Naming what this Result does carry, since a model that declared it and a Result that kept it are different things. |
Source code in src/fluxopt/results.py
save
¶
Write the result as a directory.
The solution and the named quantities are labelled N-dimensional
arrays, so they stay netCDF; the model data is tables and goes to
parquet under model/.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
str | Path
|
Directory to write into. Created if absent. |
required |
Source code in src/fluxopt/results.py
load
classmethod
¶
Read a result written by :meth:save.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
str | Path
|
The directory :meth: |
required |
Raises:
| Type | Description |
|---|---|
OSError
|
If the directory holds no solution. |
Source code in src/fluxopt/results.py
ProfileRef
pydantic-model
¶
Bases: BaseModel
Reference to a time-series stored outside the model definition.
A serializable stand-in for an inline Variate array: the profile lives
in a data file / dataset and is named here, so structural definitions
round-trip to YAML/JSON without inlining 8760-point series. Resolve it to a
:class:xr.DataArray with :meth:resolve before building the model.
Show JSON schema:
{
"description": "Reference to a time-series stored outside the model definition.\n\nA serializable stand-in for an inline ``Variate`` array: the profile lives\nin a data file / dataset and is named here, so structural definitions\nround-trip to YAML/JSON without inlining 8760-point series. Resolve it to a\n:class:`xr.DataArray` with :meth:`resolve` before building the model.",
"properties": {
"dataset": {
"title": "Dataset",
"type": "string"
},
"variable": {
"title": "Variable",
"type": "string"
}
},
"required": [
"dataset",
"variable"
],
"title": "ProfileRef",
"type": "object"
}
Config:
frozen:True
Fields:
resolve
¶
Look up the referenced series in profiles.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
Mapping[str, Dataset | Mapping[str, DataArray]]
|
Mapping from dataset id to a dataset (or mapping) that
contains |
required |
Raises:
| Type | Description |
|---|---|
KeyError
|
If dataset or variable is absent from profiles. |
Source code in src/fluxopt/types.py
all_element_schemas
¶
Return JSON Schemas for every element type, keyed by class name.
element_schema
¶
element_schema(element_type: type) -> dict[str, Any]
from_dict
¶
to_dict
¶
Serialize an element to a JSON-safe dict.
Nested elements and ProfileRef references are
included; inline array-valued Variate fields are not serializable —
reference them with a ProfileRef instead.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
object
|
Any element instance (e.g. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the element holds inline array values, listing each offending field. |
Source code in src/fluxopt/schema.py
as_dataarray
¶
as_dataarray(
value: Variate,
coords: Mapping[str, Any],
*,
name: str = 'value',
broadcast: bool = True,
) -> DataArray
Convert a Variate to a DataArray aligned to given coordinates.
Pipeline: convert → validate dims → validate coord values → broadcast.
See :data:Variate for accepted inputs. Pandas inputs (Series,
DataFrame) follow the same convention as linopy.as_dataarray: the
axis name attribute selects the corresponding target dim. For
ndarray/list, the dim is selected by length (must be unambiguous).
For DataArray, dims must be a subset of coords and coord values must
match exactly — alignment errors are surfaced loudly, not silently masked.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
Variate
|
Scalar, list, ndarray, Series, DataFrame, or DataArray. |
required |
|
Mapping[str, Any]
|
Target coordinates, e.g. |
required |
|
str
|
Name for the resulting DataArray. |
'value'
|
|
bool
|
Expand result to span all dimensions in coords. |
True
|
Source code in src/fluxopt/types.py
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | |
optimize
¶
optimize(
timesteps: Timesteps,
carriers: list[Carrier],
effects: list[Effect],
ports: list[Port],
objective: str | dict[str, float],
converters: list[Converter] | None = None,
storages: list[Storage] | None = None,
dt: float | list[float] | None = None,
periods: list[int] | None = None,
period_weights: list[float] | None = None,
profiles: Mapping[str, Any] | None = None,
solver: str = 'highs',
math: Any = None,
parameters: Mapping[str, Any] | None = None,
**kwargs: Any,
) -> Result
Build data, build model, optimize, return results.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
Timesteps
|
Time index for the optimization horizon. |
required |
|
list[Carrier]
|
Carrier declarations. |
required |
|
list[Effect]
|
Effects to track (costs, emissions, etc.). |
required |
|
list[Port]
|
System boundary ports with imports/exports. |
required |
|
str | dict[str, float]
|
Effect(s) to minimize. A single name, or a dict
mapping effect names to objective weights
( |
required |
|
list[Converter] | None
|
Linear converters between carriers. |
None
|
|
list[Storage] | None
|
Energy storages. |
None
|
|
float | list[float] | None
|
Timestep duration in hours. Auto-derived if None. |
None
|
|
list[int] | None
|
Integer period labels for multi-period optimization. |
None
|
|
list[float] | None
|
Explicit weights per period. Inferred from gaps if None. |
None
|
|
Mapping[str, Any] | None
|
Mapping from |
None
|
|
str
|
Solver name — |
'highs'
|
|
Any
|
An edited program to solve instead of the shipped one; see
:meth: |
None
|
|
Mapping[str, Any] | None
|
Data for the parameters math adds. |
None
|
|
Any
|
Passed to the solver verbatim, in its own vocabulary. |
{}
|