Energy System Modeling

Mathematical reference for the energy system model. The model presented here is based on the model in [1]. We express units of parameters and variables using square brackets. In our code, we implement the model as EnergySystemModel(::Params, ::Specs) method, which constructs an EnergySystemModel instance.

The model considers that each time period might encompass varaible number of hours, as a result of using input data that has been clustered. Otherwise, each time period refers to one hour.

Indices and Sets

Indices and sets define the different objects and dimensions in the model.

  • $g∈G$: Generation technologies
  • $G^r⊆G$: Renewable generation technologies
  • $n∈N$: Nodes
  • $l∈L$: Transmission lines, refers to a pair of nodes $(i,j)$ where $i,j∈N$
  • $t∈T$: Time periods
  • $s∈S$: Storage technologies

Parameters

General parameters

  • $κ∈[0,1]$: Fraction of the demand that must be met by renewable generation
  • $μ$: Maximum allowed share of nuclear power
  • $C$: Shedding cost [€/MWh]
  • $\bar{C}$: Shedding capacity [MWh]
  • $C_E$: Minimum percentage of emission reduction needed compared to base year 1990
  • $τ_{t}$: Number of hours clustered in time period $t$ [h]
  • $D_{n,t}$: Demand per node $n$ per time period $t$ [MWh]
  • $r≥0$: Interest rate
  • $R_E$: Carbon emissions in the Reference year 1990

Generation technology parameters

  • $I_g^G$: Annualised investment cost for generation per MW of technology $g$ [€/MW]. Calculated as $I_g^G=EAC(c_g, t_g, r)$ where $c_g$ is the cost and $t_g$ is lifetime of technology $g$.
  • $M_g^G$: Annualised maintenance cost for generation per MW of technology $g$ [€/MW]
  • $C_g^G$: Operational cost per MWh of technology $g$ [€/MWh]. Calculated as $c_g/c'_g/1000$ where $c_g$ is fuel cost 1 and $c'_g$ fuel cost 2 of technology $g.$
  • $e_g$: Technology efficiency
  • $E_g$: Technology emissions
  • $r_g^{-}$: Relative ramp-down limit of technology $g$
  • $r_g^{+}$: Relative ramp-up limit of technology $g$
  • $Q_{g,n}$: Initial capacity [MW]
  • $A_{g,n,t}∈[0,1]$: Availability of technology $g$ per node $n$ at time step $t$

Hydro power parameters

  • $W_{nmax}$: Maximum storage level of hydro reservoir in node $n$ [MWh]
  • $W_{nmin}$: Minimum storage level of hydro reservoir in node $n$ [MWh]
  • $f_{int}$: Hydro inflow to reservoirs in node $n$ during time step $t$ [MWh]
  • $f'_{int}$: Hydro inflow to run-of-river plants in node $n$ during time step $t$ [MWh]
  • $H_n$: Hydro reservoir generation capacity in node $n$ [MW]
  • $H'_n$: Hydro run-of-river generation capacity in node $n$ [MW]
  • $F_{onmin}$: Minimum environmental flow requirement [MWh]

Transmission parameters

  • $I_l^F$: Annualised investment cost for transmission per line $l$ [€/MW]. Calculated as $I_l^F=EAC(c_l⋅d_l + M_l^F, t_l, r)$ where $c_l$ is cost per kilometer and $d_l$ distance in kilometers, $t_l$ the lifetime of transmission line $l.$
  • $M_l^F$: Annualised maintenance cost for transmission per line $l$ [€/MW]
  • $C_l^F$: Transmission cost per line $l$ [€/MWh]
  • $B_l$: Susceptance per line $l$
  • $e_l$: Transmission efficiency per line $l$

Storage parameters

  • $I_s^S$: Annualised investment cost of storage technology $s$ per MW [€/MW]. Calculated as $I_s^S=EAC(c_s, t_s, r)$ where $c_s$ is the (upfront) investment cost and $t_s$ the lifetime of storage $s.$
  • $ξ_s$: Round-trip efficiency of storage technology $s$
  • $C_s^S$: Storage operational cost of storage technology $s$ [€/MWh]
  • $b_{s,n}^0$: Initial capacity of storage $s$ at node $n$ [MWh]

Remarks:

\[EAC(c,r,n) = \frac{c}{a_{n,r}},\quad a_{n,r} = \frac{1-(1+r)^{-n}}{r},\quad a_{n,0}=n,\]

where $c$ is the net present cost of the project, $n$ is the number of periods, and $r$ is the interest rate.

Variables

Generation technology variables

  • $p_{g,n,t}≥0$: Dispatch from technology $g$ at node $n$ in each time step $t$ [MWh]
  • $\bar{p}_{g,n}≥0$: Generation capacity invested in each technology $g$ at node $n$ [MW]

Hydro power variables

  • $w_{nt}≥0$: Hydro reservoir storage level in node $n$ during time step $t$ [MWh]
  • $f_{ont}≥0$: Hydro outflow from reservoirs in node $n$ during time step $t$ [MWh]
  • $f'_{ont}≥0$: Hydro outflow trough the turbine in node $n$ during time step $t$ [MWh]
  • $f''_{ont}≥0$: Hydro outflow bypassing the turbine in node $n$ during time step $t$ [MWh]
  • $h_{nt}≥0$: Hydro generation in node $n$ during time step $t$ [MWh]
  • $h'_{nt}≥0$: Hydro run-of-river generation in node $n$ during time step $t$ [MWh]

Shedding variables

  • $σ_{n,t}≥0$: Loss of load at node $n$ in each time step $t$ [MWh]

Transmission variables

  • $f_{l,t}$: Transmission flow per line $l$ in each time step $t$ [MWh]
  • $f^{abs}_{l,t}$: Absolute value of transmission flow per line $l$ in each time step $t$ [MWh]
  • $\bar{f}_l$: Transmission capacity per line $l$ [MW]

Storage variables

  • $b_{s,n,t}≥0$: Storage level of storage $s$ at node $n$ in each time step $t$ [MWh]
  • $\bar{b}_{s,n}≥0$: Storage capacity of storage $s$ at node $n$ [MWh]
  • $b_{s,n,t}^{+}≥0$: Charging of storage $s$ at node $n$ in each time step $t$ [MWh]
  • $b_{s,n,t}^{-}≥0$: Discharging of storage $s$ at node $n$ in each time step $t$ [MWh]

Voltage angle variables

  • $θ_{n,t}≥0$: Voltage angle at node $n$ in each time step $t$
  • $θ'_{n,t}≥0$: Voltage angle at node $n$ in each time step $t$

We use Variables struct to store the variable values after optimization. We can query the values from the model using Variables(::EnergySystemModel) method.

Objective

We define the objective as cost minimization

\[\mathrm{minimize}_{p_{g,t}, \bar{p}_g, σ_{t}, f_{l,t}, \bar{f}_l, b_{s,n,t}^{+}, b_{s,n,t}^{-}} (f_1 + ... + f_7).\]

The individual objectives are defined as follows.

Investment and maintenance cost of generation capacity

\[f_1=\sum_{g,n} (I_g^G+M_g^G)\bar{p}_{g,n} \tag{f1}\]

The operational cost of generation dispatch

\[f_2=\sum_{g,n,t} C_g^G p_{g,t,n} τ_{t} \tag{f2}\]

Shedding cost

\[f_3=\sum_{n,t} C σ_{n,t} τ_{t} \tag{f3}\]

Investment and maintenance cost of transmission capacity

\[f_4=\sum_{l} (I_l^F+M_l^F) \bar{f}_l \tag{f4}\]

The operational cost of transmission flow

\[f_5=\sum_{l,t} C_l^F f^{abs}_{l,t} τ_{t} \tag{f5}\]

Investment cost of storage capacity

\[f_6=\sum_{s,n} I_s^S \bar{b}_{s,n} \tag{f6}\]

The operational cost of storage

\[f_7=\sum_{s,n,t} C_s^S (b_{s,n,t}^{+}+b_{s,n,t}^{-}) τ_{t} \tag{f7}\]

We use Objectives struct to store the objetive values after optimization. We can query the values from the model using Objectives(::EnergySystemModel) method.

Constraints

In this section, we list all the constraints in the energy system model and explain their function. Each constraint is named in the code using the equation labels. We can then access the individual constraints using the standard JuMP syntax, for example, model[:b1].

We use the Specs struct to control whether we include certain constraints in the model.

Balance

Transmission lines to node $n$

\[L_n^-=\{l∈L∣i∈N,(i,n)=l\}\]

Transmission lines from node $n$

\[L_n^+=\{l∈L∣j∈N,(n,j)=l\}\]

Energy balance

\[\sum_{g} p_{g,n,t} + σ_{n,t} + \sum_{l∈L_n^-} e_l f_{l^-,t} - \sum_{l∈L_n^+} e_l f_{l^+,t} + \sum_{l∈L_n^-}(ξ_s b^-_{s,n,t} - b^+_{s,n,t} )+ h_{n,t} = \\ D_{n,t},\quad ∀s,n,t \tag{b1}\]

Generation

Generation capacity

\[p_{g,n,t} ≤ A_{g,n,t} (Q_{g,n} + \bar{p}_{g,n}) , \quad ∀g,n,t \tag{g1}\]

\[Q_{g,n} + \bar{p}_{g,n} ≤ \bar{Q}_{g,n} , \quad ∀g,n \tag{g2}\]

Minimum renewables share

\[\sum_{g∈G^r,n,t} p_{g,n,t} + \sum_{n,t} h_{n,t} ≥ κ \sum_{g∈G^r,n,t} p_{g,n,t} + \sum_{n,t} h_{n,t} \tag{g3}\]

Maximum nuclear share

\[\sum_{n∈N,t} p_{g,n,t} ≤ μ\sum_{g∈G^r,n,t} p_{g,n,t} + \sum_{n∈N,t} h_{n,t} \tag{g4}\]

Carbon cap

\[\sum_{g} E_g \sum_{n∈N,t} \frac{p_{g,n,t}}{e_g} ≤ R_E (1 - C_E) \tag{g5}\]

Shedding

Shedding upper bound

\[σ_{n,t} ≤ \bar{C} D_{n,t} ,\quad ∀n,t \tag{g6}\]

Transmission

Transmission capacity

\[f_{l,t} ≤ \bar{f}_l,\quad ∀l,t \tag{t1}\]

\[f_{l,t} ≥ -\bar{f}_l,\quad ∀l,t \tag{t2}\]

These auxiliary constraints are used to capture the absolute value of the transmission for the objective function.

\[f^{abs}_{l,t} ≥ f_{l,t},\quad ∀l,t \tag{t3}\]

\[f^{abs}_{l,t} ≥ -f_{l,t},\quad ∀l,t \tag{t4}\]

Storage

Storage capacity

\[b_{s,n,t}≤\bar{b}_{s,n},\quad ∀s,n,t \tag{s1}\]

Discharge at $t=1$

\[b_{s,n,t}^{-}≤b_{s,n}^0,\quad ∀s,n,t=1 \tag{s2}\]

Discharge at $t>1$

\[b_{s,n,t}^{-}≤b_{s,n,t-1},\quad ∀s,n,t>1 \tag{s3}\]

Charge

\[ξ_sb_{s,n,t}^{+}≤\bar{b}_{s,n} - b_{s,n,t},\quad ∀s,n,t \tag{s4}\]

Storage levels

\[b_{s,n,t}=b_{s,n,t-1} + ξ_s b_{s,n,t}^{+} - b_{s,n,t}^{-},\quad ∀s,n,t>1 \tag{s5}\]

Storage continuity

\[b_{s,n,t=1} = b_{s,n,t=t_{end}},\quad ∀s,n \tag{s6}\]

Ramping Limits

Ramping limit up and down

\[p_{g,n,t} - p_{g,n,t-1} ≤ r_g^{+}(Q_{g,n} + \bar{p}_{g,n}), \quad ∀g,n,t>1 \tag{r1}\]

\[p_{g,n,t} - p_{g,n,t-1} ≥ -r_g^{-}(Q_{g,n} + \bar{p}_{g,n}), \quad ∀g,n,t>1 \tag{r2}\]

Voltage Angles

Faraday law for accounting voltage angles

\[(θ_{n,t} - θ_{n',t}') B_l = p_{g,n,t} - p_{g,n',t}, \quad ∀g,l,n,n',t>1 \tag{v1}\]

Hydro energy

Reservoir level bounds

\[W_{nmin} ≤ w_{n,t} ≤ W_{nmax},\quad ∀n,t \tag{h1}\]

Reservoir levels

\[w_{n,t} = w_{n,t-1} + f_{i,n,t-1} - f_{o,n,t-1},\quad ∀n,t>1 \tag{h2}\]

Reservoir level continuity

\[w_{n,t=1} = w_{n,t=t_{end}},\quad ∀n \tag{h3}\]

Outflow balance

\[f_{o,n,t} = f'_{o,n,t} + f''_{o,n,t},\quad ∀n,t \tag{h4}\]

Environmental flow requirement

\[f_{o,n,t} ≥ F_{omin},\quad ∀n,t \tag{h5}\]

Reservoir generation (turbine capacity for outflow)

\[0 ≤ f'_{o,n,t} ≤ H_n,\quad ∀n,t \tag{h6}\]

Run-of-river generation (available inflow and capacity)

\[0 ≤ h'_{n,t} ≤ f'_{i,n,t},\quad ∀n,t \tag{h7}\]

\[0 ≤ h'_{n,t} ≤ H'_n,\quad ∀n,t \tag{h8}\]

Hydro generation balance

\[h_{n,t} = h'_{n,t} + f'_{o,n,t},\quad ∀n,t \tag{h9}\]

Instances

Users can provide input parameters for different instances as a directory containing CSV and JSON files, and also include a README file, which describes the instance. Users can distribute instances as .zip archives. We provide an example instance in examples/instance as a reference. We describe the input format in Params(::AbstractString).

We can write Specs, Params, Variables, and Objectives structs into JSON files using save_json and read them from JSON files using load_json.

References

  • 1Pineda, S., & Morales, J. M. (2018). Chronological time-period clustering for optimal capacity expansion planning with storage. IEEE Transactions on Power Systems, 33(6), 7162–7170. https://doi.org/10.1109/TPWRS.2018.2842093