diff --git a/docs/format.md b/docs/format.md index 0733fb5..114d40a 100644 --- a/docs/format.md +++ b/docs/format.md @@ -28,13 +28,14 @@ Each section is described in detail below. For a complete example, see [case14]( ### Parameters -This section describes system-wide parameters, such as power balance penalties, optimization parameters, such as the length of the planning horizon and the time. +This section describes system-wide parameters, such as power balance and reserve shortfall penalties, and optimization parameters, such as the length of the planning horizon and the time. | Key | Description | Default | Time series? | :----------------------------- | :------------------------------------------------ | :------: | :------------: -| `Time horizon (h)` | Length of the planning horizon (in hours). | Required | N +| `Time horizon (h)` | Length of the planning horizon (in hours). | Required | N | `Time step (min)` | Length of each time step (in minutes). Must be a divisor of 60 (e.g. 60, 30, 20, 15, etc). | `60` | N | `Power balance penalty ($/MW)` | Penalty for system-wide shortage or surplus in production (in $/MW). This is charged per time step. For example, if there is a shortage of 1 MW for three time steps, three times this amount will be charged. | `1000.0` | Y +| `Reserve shortfall penalty (\$/MW)` | Penalty for system-wide shortage in meeting reserve requirements (in $/MW). This is charged per time step. Negative value implies no penalty. | `-1` | Y #### Example @@ -43,6 +44,7 @@ This section describes system-wide parameters, such as power balance penalties, "Parameters": { "Time horizon (h)": 4, "Power balance penalty ($/MW)": 1000.0 + "Reserve shortfall penalty ($/MW)": -1.0 } } ``` diff --git a/src/instance/read.jl b/src/instance/read.jl index 84e76c2..01573f7 100644 --- a/src/instance/read.jl +++ b/src/instance/read.jl @@ -100,7 +100,7 @@ function _from_json(json; repair = true) ) shortfall_penalty = timeseries( json["Parameters"]["Reserve shortfall penalty (\$/MW)"], - default = [0.0 for t in 1:T], + default = [-1.0 for t in 1:T], ) # Read buses diff --git a/src/model/formulations/base/system.jl b/src/model/formulations/base/system.jl index 88bc78a..f88c15e 100644 --- a/src/model/formulations/base/system.jl +++ b/src/model/formulations/base/system.jl @@ -39,12 +39,12 @@ function _add_reserve_eqs!(model::JuMP.Model)::Nothing eq_min_reserve[t] = @constraint( model, sum(model[:reserve][g.name, t] for g in instance.units) + ( - shortfall_penalty > 1e-7 ? model[:reserve_shortfall][t] : 0.0 + shortfall_penalty > -1e-7 ? model[:reserve_shortfall][t] : 0.0 ) >= instance.reserves.spinning[t] ) # Account for shortfall contribution to objective - if shortfall_penalty > 1e-7 + if shortfall_penalty > -1e-7 add_to_expression!( model.obj, shortfall_penalty,