Skip to content

flixopt.structure

This module contains the core structure of the flixopt framework. These classes are not directly used by the end user, but are used by other modules.

Attributes

EXPAND_INTERPOLATE module-attribute

EXPAND_INTERPOLATE: set[VariableCategory] = {CHARGE_STATE}

State variables that should be interpolated between segment boundaries.

EXPAND_DIVIDE module-attribute

EXPAND_DIVIDE: set[VariableCategory] = {PER_TIMESTEP, SHARE}

Segment totals that should be divided by expansion factor to preserve sums.

EXPAND_FIRST_TIMESTEP module-attribute

EXPAND_FIRST_TIMESTEP: set[VariableCategory] = {STARTUP, SHUTDOWN}

Binary events that should appear only at the first timestep of the segment.

Classes

VariableCategory

Bases: Enum

Fine-grained variable categories - names mirror variable names.

Each variable type has its own category for precise handling during segment expansion and statistics calculation.

SubmodelsMixin

Mixin that provides submodel functionality for both FlowSystemModel and Submodel.

Attributes

all_submodels property
all_submodels: list[Submodel]

Get all submodels including nested ones recursively.

Functions

add_submodels
add_submodels(submodel: Submodel, short_name: str = None) -> Submodel

Register a sub-model with the model

FlowSystemModel

FlowSystemModel(flow_system: FlowSystem)

Bases: Model, SubmodelsMixin

The FlowSystemModel is the linopy Model that is used to create the mathematical model of the flow_system. It is used to create and store the variables and constraints for the flow_system.

Parameters:

Name Type Description Default
flow_system FlowSystem

The flow_system that is used to create the model.

required

Attributes

solution property
solution

Build solution dataset, reindexing to timesteps_extra for consistency.

timestep_duration property
timestep_duration: DataArray

Duration of each timestep in hours.

dims property
dims: list[str]

Active dimension names.

indexes property
indexes: dict[str, Index]

Indexes for active dimensions.

weights property
weights: dict[str, DataArray]

Weights for active dimensions (unit weights if not set).

Scenario weights are always normalized (handled by FlowSystem).

temporal_dims property
temporal_dims: list[str]

Temporal dimensions for summing over time.

Returns ['time', 'cluster'] for clustered systems, ['time'] otherwise.

temporal_weight property
temporal_weight: DataArray

Combined temporal weight (timestep_duration × cluster_weight).

scenario_weights property
scenario_weights: DataArray

Scenario weights of model.

Returns:

Type Description
DataArray
  • Scalar 1 if no scenarios defined
DataArray
  • Unit weights (all 1.0) if scenarios exist but no explicit weights set
DataArray
  • Normalized explicit weights if set via FlowSystem.scenario_weights
objective_weights property
objective_weights: DataArray

Objective weights of model (period_weights × scenario_weights).

all_submodels property
all_submodels: list[Submodel]

Get all submodels including nested ones recursively.

Functions

add_variables
add_variables(lower: DataArray | float = -np.inf, upper: DataArray | float = np.inf, coords: Coordinates | None = None, **kwargs) -> linopy.Variable

Override to ensure bounds are broadcasted to coords shape.

Linopy uses the union of all DataArray dimensions to determine variable shape. This override ensures at least one bound has all target dimensions when coords is provided, allowing internal data to remain compact (scalars, 1D arrays).

sum_temporal
sum_temporal(data: DataArray) -> xr.DataArray

Sum data over temporal dimensions with full temporal weighting.

Example

total_energy = model.sum_temporal(flow_rate)

get_coords
get_coords(dims: Collection[str] | None = None, extra_timestep: bool = False) -> xr.Coordinates | None

Returns the coordinates of the model

Parameters:

Name Type Description Default
dims Collection[str] | None

The dimensions to include in the coordinates. If None, includes all dimensions

None
extra_timestep bool

If True, uses extra timesteps instead of regular timesteps. For clustered FlowSystems, extends time by 1 (for charge_state boundaries).

False

Returns:

Type Description
Coordinates | None

The coordinates of the model, or None if no coordinates are available

Raises:

Type Description
ValueError

If extra_timestep=True but 'time' is not in dims

add_submodels
add_submodels(submodel: Submodel, short_name: str = None) -> Submodel

Register a sub-model with the model

Interface

Base class for all Elements and Models in flixopt that provides serialization capabilities.

This class enables automatic serialization/deserialization of objects containing xarray DataArrays and nested Interface objects to/from xarray Datasets and NetCDF files. It uses introspection of constructor parameters to automatically handle most serialization scenarios.

Key Features
  • Automatic extraction and restoration of xarray DataArrays
  • Support for nested Interface objects
  • NetCDF and JSON export/import
  • Recursive handling of complex nested structures
Subclasses must implement

transform_data(): Transform data to match FlowSystem dimensions

Attributes

prefix property
prefix: str

The prefix used for naming transformed data (e.g., 'Boiler(Q_th)|status_parameters').

flow_system property
flow_system: FlowSystem

Access the FlowSystem this interface is linked to.

Returns:

Type Description
FlowSystem

The FlowSystem instance this interface belongs to.

Raises:

Type Description
RuntimeError

If interface has not been linked to a FlowSystem yet.

Note

For Elements, this is set during add_elements(). For parameter classes, this is set recursively when the parent Element is registered.

Functions

transform_data
transform_data() -> None

Transform the data of the interface to match the FlowSystem's dimensions.

Uses self._prefix (set during link_to_flow_system()) to name transformed data.

Raises:

Type Description
NotImplementedError

Must be implemented by subclasses

Note

The FlowSystem reference is available via self._flow_system (for Interface objects) or self.flow_system property (for Element objects). Elements must be registered to a FlowSystem before calling this method.

link_to_flow_system(flow_system: FlowSystem, prefix: str = '') -> None

Link this interface and all nested interfaces to a FlowSystem.

This method is called automatically during element registration to enable elements to access FlowSystem properties without passing the reference through every method call. It also sets the prefix used for naming transformed data.

Subclasses with nested Interface objects should override this method to propagate the link to their nested interfaces by calling super().link_to_flow_system(flow_system, prefix) first, then linking nested objects with appropriate prefixes.

Parameters:

Name Type Description Default
flow_system FlowSystem

The FlowSystem to link to

required
prefix str

The prefix for naming transformed data (e.g., 'Boiler(Q_th)')

''

Examples:

Override in a subclass with nested interfaces:

def link_to_flow_system(self, flow_system, prefix: str = '') -> None:
    super().link_to_flow_system(flow_system, prefix)
    if self.nested_interface is not None:
        self.nested_interface.link_to_flow_system(flow_system, f'{prefix}|nested' if prefix else 'nested')

Creating an Interface dynamically during modeling:

# In a Model class
if flow.status_parameters is None:
    flow.status_parameters = StatusParameters()
    flow.status_parameters.link_to_flow_system(self._model.flow_system, f'{flow.label_full}')
to_dataset
to_dataset() -> xr.Dataset

Convert the object to an xarray Dataset representation. All DataArrays become dataset variables, everything else goes to attrs.

Its recommended to only call this method on Interfaces with all numeric data stored as xr.DataArrays. Interfaces inside a FlowSystem are automatically converted this form after connecting and transforming the FlowSystem.

Returns:

Type Description
Dataset

xr.Dataset: Dataset containing all DataArrays with basic objects only in attributes

Raises:

Type Description
ValueError

If serialization fails due to naming conflicts or invalid data

to_netcdf
to_netcdf(path: str | Path, compression: int = 5, overwrite: bool = False)

Save the object to a NetCDF file.

Parameters:

Name Type Description Default
path str | Path

Path to save the NetCDF file. Parent directories are created if they don't exist.

required
compression int

Compression level (0-9)

5
overwrite bool

If True, overwrite existing file. If False, raise error if file exists.

False

Raises:

Type Description
FileExistsError

If overwrite=False and file already exists.

ValueError

If serialization fails

IOError

If file cannot be written

from_dataset classmethod
from_dataset(ds: Dataset) -> Interface

Create an instance from an xarray Dataset.

Parameters:

Name Type Description Default
ds Dataset

Dataset containing the object data

required

Returns:

Type Description
Interface

Interface instance

Raises:

Type Description
ValueError

If dataset format is invalid or class mismatch

from_netcdf classmethod
from_netcdf(path: str | Path) -> Interface

Load an instance from a NetCDF file.

Parameters:

Name Type Description Default
path str | Path

Path to the NetCDF file

required

Returns:

Type Description
Interface

Interface instance

Raises:

Type Description
IOError

If file cannot be read

ValueError

If file format is invalid

get_structure
get_structure(clean: bool = False, stats: bool = False) -> dict

Get object structure as a dictionary.

Parameters:

Name Type Description Default
clean bool

If True, remove None and empty dicts and lists.

False
stats bool

If True, replace DataArray references with statistics

False

Returns:

Type Description
dict

Dictionary representation of the object structure

to_json
to_json(path: str | Path)

Save the object to a JSON file. This is meant for documentation and comparison, not for reloading.

Parameters:

Name Type Description Default
path str | Path

The path to the JSON file.

required

Raises:

Type Description
IOError

If file cannot be written

copy
copy() -> Interface

Create a copy of the Interface object.

Uses the existing serialization infrastructure to ensure proper copying of all DataArrays and nested objects.

Returns:

Type Description
Interface

A new instance of the same class with copied data.

Element

Element(label: str, meta_data: dict | None = None, color: str | None = None, _variable_names: list[str] | None = None, _constraint_names: list[str] | None = None)

Bases: Interface

This class is the basic Element of flixopt. Every Element has a label

Parameters:

Name Type Description Default
label str

The label of the element

required
meta_data dict | None

used to store more information about the Element. Is not used internally, but saved in the results. Only use python native types.

None
color str | None

Optional color for visualizations (e.g., '#FF6B6B'). If not provided, a color will be automatically assigned during FlowSystem.connect_and_transform().

None
_variable_names list[str] | None

Internal. Variable names for this element (populated after modeling).

None
_constraint_names list[str] | None

Internal. Constraint names for this element (populated after modeling).

None

Attributes

solution property
solution: Dataset

Solution data for this element's variables.

Returns a view into FlowSystem.solution containing only this element's variables.

Raises:

Type Description
ValueError

If no solution is available (optimization not run or not solved).

prefix property
prefix: str

The prefix used for naming transformed data (e.g., 'Boiler(Q_th)|status_parameters').

flow_system property
flow_system: FlowSystem

Access the FlowSystem this interface is linked to.

Returns:

Type Description
FlowSystem

The FlowSystem instance this interface belongs to.

Raises:

Type Description
RuntimeError

If interface has not been linked to a FlowSystem yet.

Note

For Elements, this is set during add_elements(). For parameter classes, this is set recursively when the parent Element is registered.

Functions

transform_data
transform_data() -> None

Transform the data of the interface to match the FlowSystem's dimensions.

Uses self._prefix (set during link_to_flow_system()) to name transformed data.

Raises:

Type Description
NotImplementedError

Must be implemented by subclasses

Note

The FlowSystem reference is available via self._flow_system (for Interface objects) or self.flow_system property (for Element objects). Elements must be registered to a FlowSystem before calling this method.

link_to_flow_system(flow_system: FlowSystem, prefix: str = '') -> None

Link this interface and all nested interfaces to a FlowSystem.

This method is called automatically during element registration to enable elements to access FlowSystem properties without passing the reference through every method call. It also sets the prefix used for naming transformed data.

Subclasses with nested Interface objects should override this method to propagate the link to their nested interfaces by calling super().link_to_flow_system(flow_system, prefix) first, then linking nested objects with appropriate prefixes.

Parameters:

Name Type Description Default
flow_system FlowSystem

The FlowSystem to link to

required
prefix str

The prefix for naming transformed data (e.g., 'Boiler(Q_th)')

''

Examples:

Override in a subclass with nested interfaces:

def link_to_flow_system(self, flow_system, prefix: str = '') -> None:
    super().link_to_flow_system(flow_system, prefix)
    if self.nested_interface is not None:
        self.nested_interface.link_to_flow_system(flow_system, f'{prefix}|nested' if prefix else 'nested')

Creating an Interface dynamically during modeling:

# In a Model class
if flow.status_parameters is None:
    flow.status_parameters = StatusParameters()
    flow.status_parameters.link_to_flow_system(self._model.flow_system, f'{flow.label_full}')
to_dataset
to_dataset() -> xr.Dataset

Convert the object to an xarray Dataset representation. All DataArrays become dataset variables, everything else goes to attrs.

Its recommended to only call this method on Interfaces with all numeric data stored as xr.DataArrays. Interfaces inside a FlowSystem are automatically converted this form after connecting and transforming the FlowSystem.

Returns:

Type Description
Dataset

xr.Dataset: Dataset containing all DataArrays with basic objects only in attributes

Raises:

Type Description
ValueError

If serialization fails due to naming conflicts or invalid data

to_netcdf
to_netcdf(path: str | Path, compression: int = 5, overwrite: bool = False)

Save the object to a NetCDF file.

Parameters:

Name Type Description Default
path str | Path

Path to save the NetCDF file. Parent directories are created if they don't exist.

required
compression int

Compression level (0-9)

5
overwrite bool

If True, overwrite existing file. If False, raise error if file exists.

False

Raises:

Type Description
FileExistsError

If overwrite=False and file already exists.

ValueError

If serialization fails

IOError

If file cannot be written

from_dataset classmethod
from_dataset(ds: Dataset) -> Interface

Create an instance from an xarray Dataset.

Parameters:

Name Type Description Default
ds Dataset

Dataset containing the object data

required

Returns:

Type Description
Interface

Interface instance

Raises:

Type Description
ValueError

If dataset format is invalid or class mismatch

from_netcdf classmethod
from_netcdf(path: str | Path) -> Interface

Load an instance from a NetCDF file.

Parameters:

Name Type Description Default
path str | Path

Path to the NetCDF file

required

Returns:

Type Description
Interface

Interface instance

Raises:

Type Description
IOError

If file cannot be read

ValueError

If file format is invalid

get_structure
get_structure(clean: bool = False, stats: bool = False) -> dict

Get object structure as a dictionary.

Parameters:

Name Type Description Default
clean bool

If True, remove None and empty dicts and lists.

False
stats bool

If True, replace DataArray references with statistics

False

Returns:

Type Description
dict

Dictionary representation of the object structure

to_json
to_json(path: str | Path)

Save the object to a JSON file. This is meant for documentation and comparison, not for reloading.

Parameters:

Name Type Description Default
path str | Path

The path to the JSON file.

required

Raises:

Type Description
IOError

If file cannot be written

copy
copy() -> Interface

Create a copy of the Interface object.

Uses the existing serialization infrastructure to ensure proper copying of all DataArrays and nested objects.

Returns:

Type Description
Interface

A new instance of the same class with copied data.

ContainerMixin

ContainerMixin(elements: list[T] | dict[str, T] | None = None, element_type_name: str = 'elements', truncate_repr: int | None = None, item_name: str | None = None)

Bases: dict[str, T]

Mixin providing shared container functionality with nice repr and error messages.

Subclasses must implement _get_label() to extract the label from elements.

Parameters:

Name Type Description Default
elements list[T] | dict[str, T] | None

Initial elements to add (list or dict)

None
element_type_name str

Name for display (e.g., 'components', 'buses')

'elements'
truncate_repr int | None

Maximum number of items to show in repr. If None, show all items. Default: None

None
item_name str | None

Singular name for error messages (e.g., 'Component', 'Carrier'). If None, inferred from first added item's class name.

None

Functions

add
add(element: T) -> None

Add an element to the container.

ElementContainer

ElementContainer(elements: list[T] | dict[str, T] | None = None, element_type_name: str = 'elements', truncate_repr: int | None = None, item_name: str | None = None)

Bases: ContainerMixin[T]

Container for Element objects (Component, Bus, Flow, Effect).

Uses element.label_full for keying.

Parameters:

Name Type Description Default
elements list[T] | dict[str, T] | None

Initial elements to add (list or dict)

None
element_type_name str

Name for display (e.g., 'components', 'buses')

'elements'
truncate_repr int | None

Maximum number of items to show in repr. If None, show all items. Default: None

None
item_name str | None

Singular name for error messages (e.g., 'Component', 'Carrier'). If None, inferred from first added item's class name.

None

Functions

add
add(element: T) -> None

Add an element to the container.

ResultsContainer

ResultsContainer(elements: list[T] | dict[str, T] | None = None, element_type_name: str = 'elements', truncate_repr: int | None = None, item_name: str | None = None)

Bases: ContainerMixin[T]

Container for Results objects (ComponentResults, BusResults, etc).

Uses element.label for keying.

Parameters:

Name Type Description Default
elements list[T] | dict[str, T] | None

Initial elements to add (list or dict)

None
element_type_name str

Name for display (e.g., 'components', 'buses')

'elements'
truncate_repr int | None

Maximum number of items to show in repr. If None, show all items. Default: None

None
item_name str | None

Singular name for error messages (e.g., 'Component', 'Carrier'). If None, inferred from first added item's class name.

None

Functions

add
add(element: T) -> None

Add an element to the container.

FlowContainer

FlowContainer(elements: list[T] | dict[str, T] | None = None, element_type_name: str = 'elements', truncate_repr: int | None = None, item_name: str | None = None)

Bases: ContainerMixin[T]

Container for Flow objects with dual access: by index or by label_full.

Supports
  • container['Boiler(Q_th)'] # label_full-based access
  • container['Q_th'] # short-label access (when all flows share same component)
  • container[0] # index-based access
  • container.add(flow)
  • for flow in container.values()
  • container1 + container2 # concatenation

Examples:

>>> boiler = Boiler(label='Boiler', inputs=[Flow('Q_th', bus=heat_bus)])
>>> boiler.inputs[0]  # Index access
>>> boiler.inputs['Boiler(Q_th)']  # Full label access
>>> boiler.inputs['Q_th']  # Short label access (same component)
>>> for flow in boiler.inputs.values():
...     print(flow.label_full)

Parameters:

Name Type Description Default
elements list[T] | dict[str, T] | None

Initial elements to add (list or dict)

None
element_type_name str

Name for display (e.g., 'components', 'buses')

'elements'
truncate_repr int | None

Maximum number of items to show in repr. If None, show all items. Default: None

None
item_name str | None

Singular name for error messages (e.g., 'Component', 'Carrier'). If None, inferred from first added item's class name.

None

Functions

add
add(element: T) -> None

Add an element to the container.

CompositeContainerMixin

Bases: Generic[T_element]

Mixin providing unified dict-like access across multiple typed containers.

This mixin enables classes that manage multiple containers (e.g., components, buses, effects, flows) to provide a unified interface for accessing elements across all containers, as if they were a single collection.

Type Parameter

T_element: The type of elements stored in the containers. Can be a union type for containers holding multiple types (e.g., 'ComponentResults | BusResults').

Key Features
  • Dict-like access: obj['element_name'] searches all containers
  • Iteration: for label in obj: iterates over all elements
  • Membership: 'element' in obj checks across all containers
  • Standard dict methods: keys(), values(), items()
  • Grouped display: Formatted repr showing elements by type
  • Type hints: Full IDE and type checker support
Subclasses must implement

_get_container_groups() -> dict[str, dict]: Returns a dictionary mapping group names (e.g., 'Components', 'Buses') to container dictionaries. Containers are displayed in the order returned.

Example
class MySystem(CompositeContainerMixin[Component | Bus]):
    def __init__(self):
        self.components = {'Boiler': Component(...), 'CHP': Component(...)}
        self.buses = {'Heat': Bus(...), 'Power': Bus(...)}

    def _get_container_groups(self):
        return {
            'Components': self.components,
            'Buses': self.buses,
        }


system = MySystem()
comp = system['Boiler']  # Type: Component | Bus (with proper IDE support)
'Heat' in system  # True
labels = system.keys()  # Type: list[str]
elements = system.values()  # Type: list[Component | Bus]
Integration with ContainerMixin

This mixin is designed to work alongside ContainerMixin-based containers (ElementContainer, ResultsContainer) by aggregating them into a unified interface while preserving their individual functionality.

Functions

keys
keys() -> list[str]

Return all element labels across all containers.

values
values() -> list[T_element]

Return all element objects across all containers.

items
items() -> list[tuple[str, T_element]]

Return (label, element) pairs for all elements.

Submodel

Submodel(model: FlowSystemModel, label_of_element: str, label_of_model: str | None = None)

Bases: SubmodelsMixin

Stores Variables and Constraints. Its a subset of a FlowSystemModel. Variables and constraints are stored in the main FlowSystemModel, and are referenced here. Can have other Submodels assigned, and can be a Submodel of another Submodel.

Parameters:

Name Type Description Default
model FlowSystemModel

The FlowSystemModel that is used to create the model.

required
label_of_element str

The label of the parent (Element). Used to construct the full label of the model.

required
label_of_model str | None

The label of the model. Used as a prefix in all variables and constraints.

None

Attributes

variables_direct property
variables_direct: Variables

Variables of the model, excluding those of sub-models

constraints_direct property
constraints_direct: Constraints

Constraints of the model, excluding those of sub-models

constraints property
constraints: Constraints

All constraints of the model, including those of all sub-models

variables property
variables: Variables

All variables of the model, including those of all sub-models

all_submodels property
all_submodels: list[Submodel]

Get all submodels including nested ones recursively.

Functions

add_variables
add_variables(short_name: str = None, category: VariableCategory = None, **kwargs: Any) -> linopy.Variable

Create and register a variable in one step.

Parameters:

Name Type Description Default
short_name str

Short name for the variable (used as suffix in full name).

None
category VariableCategory

Category for segment expansion handling. See VariableCategory.

None
**kwargs Any

Additional arguments passed to linopy.Model.add_variables().

{}

Returns:

Type Description
Variable

The created linopy Variable.

add_constraints
add_constraints(expression, short_name: str = None, **kwargs) -> linopy.Constraint

Create and register a constraint in one step

register_variable
register_variable(variable: Variable, short_name: str = None) -> linopy.Variable

Register a variable with the model

register_constraint
register_constraint(constraint: Constraint, short_name: str = None) -> linopy.Constraint

Register a constraint with the model

get
get(name: str, default=None)

Get variable by short name, returning default if not found

add_submodels
add_submodels(submodel: Submodel, short_name: str = None) -> Submodel

Register a sub-model with the model

Submodels dataclass

Submodels(data: dict[str, Submodel])

A simple collection for storing submodels with easy access and representation.

Functions

add
add(submodel: Submodel, name: str) -> None

Add a submodel to the collection.

get
get(name: str, default=None)

Get submodel by name, returning default if not found.

ElementModel

ElementModel(model: FlowSystemModel, element: Element)

Bases: Submodel

Stores the mathematical Variables and Constraints for Elements. ElementModels are directly registered in the main FlowSystemModel

Parameters:

Name Type Description Default
model FlowSystemModel

The FlowSystemModel that is used to create the model.

required
element Element

The element this model is created for.

required

Attributes

all_submodels property
all_submodels: list[Submodel]

Get all submodels including nested ones recursively.

variables_direct property
variables_direct: Variables

Variables of the model, excluding those of sub-models

constraints_direct property
constraints_direct: Constraints

Constraints of the model, excluding those of sub-models

constraints property
constraints: Constraints

All constraints of the model, including those of all sub-models

variables property
variables: Variables

All variables of the model, including those of all sub-models

Functions

add_submodels
add_submodels(submodel: Submodel, short_name: str = None) -> Submodel

Register a sub-model with the model

add_variables
add_variables(short_name: str = None, category: VariableCategory = None, **kwargs: Any) -> linopy.Variable

Create and register a variable in one step.

Parameters:

Name Type Description Default
short_name str

Short name for the variable (used as suffix in full name).

None
category VariableCategory

Category for segment expansion handling. See VariableCategory.

None
**kwargs Any

Additional arguments passed to linopy.Model.add_variables().

{}

Returns:

Type Description
Variable

The created linopy Variable.

add_constraints
add_constraints(expression, short_name: str = None, **kwargs) -> linopy.Constraint

Create and register a constraint in one step

register_variable
register_variable(variable: Variable, short_name: str = None) -> linopy.Variable

Register a variable with the model

register_constraint
register_constraint(constraint: Constraint, short_name: str = None) -> linopy.Constraint

Register a constraint with the model

get
get(name: str, default=None)

Get variable by short name, returning default if not found

Functions

register_class_for_io

register_class_for_io(cls)

Register a class for serialization/deserialization.