Skip to content

Storage Unit

Use the StorageUnit class to represent a storage unit with a given active power capacity (p_nom), in order to optimize its active power over time (StorageUnitOptimizationDynamicResults.p). The storage unit's energy capacity is determined by its max_hours in conjunction with p_nom.

Use the ExtendableStorageUnit class to represent a hypothetical storage unit with an active power capacity that is flexible, in order to also optimize the active power capacity (ExtendableStorageUnitOptimizationStaticResults.p_nom_opt).

API Reference

StorageUnit and ExtendableStorageUnit both inherit from the BaseStorageUnit parent class.

BaseStorageUnit

Bases: PNomExtendableComponent[T]

Storage units enable inter-temporal energy shifting with fixed nominal-energy-to-nominal-power ratio.

PyPSA user guide for this component.

bus: str = Field(min_length=1)

Name of bus to which storage unit is attached.

control: ControlType = 'PQ'

P,Q,V control strategy for PF, must be "PQ", "PV" or "Slack".

p_nom_extendable: bool

Switch to allow capacity p_nom to be extended in optimisation.

p_min_pu: float | Series[T] = Field(default=(-1.0), ge=(-1.0), le=1.0)

The minimum output for each snapshot per unit of p_nom for the optimisation. Negative sign implies storing mode withdrawing power from bus.

p_max_pu: float | Series[T] = Field(default=1.0, ge=(-1.0), le=1.0)

The maximum output for each snapshot per unit of p_nom for the optimisation. Positive sign implies discharging mode injecting power into bus.

p_set: float | Series[T] | None = None

Active power set point (for power flow only)

q_set: float | Series[T] = 0.0

Reactive power set point (for power flow only)

p_dispatch_set: float | Series[T] | None = None

Active power dispatch set point (for optimisation only)

p_store_set: float | Series[T] | None = None

Active power charging set point (for optimisation only)

sign: SignType = +1

Sign denoting the orientation of the dispatch variable.

carrier: str | None = Field(default=None, min_length=1)

Prime mover energy carrier (e.g. coal, gas, wind, solar); required for global constraints on primary energy in optimisation

spill_cost: float | Series[T] = 0.0

Cost of spilling 1 MWh

marginal_cost: float | Series[T] = Field(default=0.0, ge=0.0)

Marginal cost of production (discharge) of 1 MWh.

marginal_cost_quadratic: float | Series[T] = Field(default=0.0, ge=0.0)

Quadratic marginal cost of production (discharge) of 1 MWh.

marginal_cost_storage: float | Series[T] = Field(default=0.0, ge=0.0)

Marginal cost of energy storage of 1 MWh for one hour.

active: bool = True

Whether to consider the component in optimisation or not.

build_year: int | None = None

Build year.

lifetime: float | None = Field(default=None, gt=0.0)

Lifetime.

state_of_charge_initial: float = Field(default=0.0, ge=0.0, le=1.0)

State of charge before the snapshots in the optimisation.

state_of_charge_initial_per_period: bool = False

Switch: if True, the state of charge at the beginning of an investment period is set to state_of_charge_initial.

state_of_charge_set: float | Series[T] | None = Field(default=None, ge=0.0, le=1.0)

State of charge set points for snapshots in the optimisation.

cyclic_state_of_charge: bool = False

Switch: if True, then state_of_charge_initial is ignored and the initial state of charge is set to the final state of charge for the group of snapshots in the optimisation (soc[-1] = soc[len(snapshots)-1]).

cyclic_state_of_charge_per_period: bool = False

Switch: if True, the cyclic constraints are applied to each investment period separately.

max_hours: float = Field(gt=0.0)

Maximum state of charge capacity in terms of hours at full output power capacity p_nom.

efficiency_store: float | Series[T] = Field(default=1.0, gt=0.0, le=1.0)

Efficiency of storage on the way into the storage.

efficiency_dispatch: float | Series[T] = Field(default=1.0, gt=0.0, le=1.0)

Efficiency of storage on the way out of the storage.

standing_loss: float | Series[T] = Field(default=0.0, ge=0.0)

Losses per hour to state of charge.

inflow: float | Series[T] = Field(default=0.0, ge=0.0)

Inflow to the state of charge (e.g. due to river inflow in hydro reservoir).

StorageUnit

Bases: BaseStorageUnit[T]

p_nom: float | None = Field(default=None, gt=0.0)

Nominal power for limits on p in optimisation.

ExtendableStorageUnit

Bases: BaseStorageUnit[T]

p_nom_mod: float = Field(default=0.0, ge=0.0)

Nominal power of the storage unit module. Introduces integer variables if set.

p_nom_min: float = Field(default=0.0, ge=0.0)

Minimum value of p_nom_opt.

p_nom_max: float | None = Field(default=None, gt=0.0)

Maximum value of p_nom_opt.

p_nom_set: float | None = Field(default=None, ge=0.0)

Set value of p_nom_opt.

capital_cost: float = Field(default=0.0, ge=0.0)

Fixed period costs of extending p_nom by 1 MW, including periodized investment costs and periodic fixed O&M costs (e.g. annuitized investment costs).

StorageUnitBaseDynamicResults

Bases: BaseDynamicResults

p: pandas.DataFrame

Active power at bus (positive if net generation).

StorageUnitOptimizationDynamicResults

Bases: StorageUnitBaseDynamicResults

p_dispatch: pandas.DataFrame

Active power dispatch at bus.

p_store: pandas.DataFrame

Active power charging at bus.

state_of_charge: pandas.DataFrame

State of charge as calculated by the optimisation.

spill: pandas.DataFrame

Spillage for each snapshot (e.g. hydro-dam letting water flow over the spillway without generating electricity).

mu_upper: pandas.DataFrame

Shadow price of upper p_nom limit.

mu_lower: pandas.DataFrame

Shadow price of lower p_nom limit.

mu_state_of_charge_set: pandas.DataFrame

Shadow price of fixed state of charge state_of_charge_set.

mu_energy_balance: pandas.DataFrame

Shadow price of storage consistency equations.

StorageUnitPfDynamicResults

StorageUnitNonlinearPfDynamicResults

Bases: StorageUnitPfDynamicResults

q: pandas.DataFrame

Reactive power (positive if net generation).