From 719143ea40447bf129e39de209f1e701f4d27e32 Mon Sep 17 00:00:00 2001 From: Alinson S Xavier Date: Wed, 21 Jul 2021 10:54:40 -0500 Subject: [PATCH] Flip coefficients in eq_net_injection; add example to the docs --- docs/model.md | 50 ++++++++++++++++++++++++++- src/model/formulations/base/system.jl | 6 ++-- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/docs/model.md b/docs/model.md index 1b6a6eb..218dcd5 100644 --- a/docs/model.md +++ b/docs/model.md @@ -148,7 +148,7 @@ for g in instance.units end ``` -### Modifying the model +### Fixing variables, modifying objective function and adding constraints Since we now have a direct reference to the JuMP decision variables, it is possible to fix variables, change the coefficients in the objective function, or even add new constraints to the model before solving it. The script below shows how can this be accomplished. For more information on modifying an existing model, [see the JuMP documentation](https://jump.dev/JuMP.jl/stable/manual/variables/). @@ -190,6 +190,54 @@ JuMP.set_objective_coefficient( UnitCommitment.optimize!(model) ``` +### Adding new component to a bus + +The following snippet shows how to add a new grid component to a particular bus. For each time step, we create decision variables for the new grid component, add these variables to the objective function, then attach the component to a particular bus by modifying some existing model constraints. + +```julia +using Cbc +using JuMP +using UnitCommitment + +# Load instance and build base model +instance = UnitCommitment.read_benchmark("matpower/case118/2017-02-01") +model = UnitCommitment.build_model( + instance=instance, + optimizer=Cbc.Optimizer, +) + +# Get the number of time steps in the original instance +T = instance.time + +# Create decision variables for the new grid component. +# In this example, we assume that the new component can +# inject up to 10 MW of power at each time step, so we +# create new continuous variables 0 ≤ x[t] ≤ 10. +@variable(model, x[1:T], lower_bound=0.0, upper_bound=10.0) + +# For each time step +for t in 1:T + + # Add production costs to the objective function. + # In this example, we assume a cost of $5/MW. + set_objective_coefficient(model, x[t], 5.0) + + # Attach the new component to bus b1, by modifying the + # constraint `eq_net_injection`. + set_normalized_coefficient( + model[:eq_net_injection]["b1", t], + x[t], + 1.0, + ) +end + +# Solve the model +UnitCommitment.optimize!(model) + +# Show optimal values for the x variables +@show value.(x) +``` + References ---------- * [KnOsWa20] **Bernard Knueven, James Ostrowski and Jean-Paul Watson.** "On Mixed-Integer Programming Formulations for the Unit Commitment Problem". INFORMS Journal on Computing (2020). [DOI: 10.1287/ijoc.2019.0944](https://doi.org/10.1287/ijoc.2019.0944) diff --git a/src/model/formulations/base/system.jl b/src/model/formulations/base/system.jl index bdec641..496ea2b 100644 --- a/src/model/formulations/base/system.jl +++ b/src/model/formulations/base/system.jl @@ -11,12 +11,12 @@ end function _add_net_injection_eqs!(model::JuMP.Model)::Nothing T = model[:instance].time net_injection = _init(model, :net_injection) - eq_net_injection_def = _init(model, :eq_net_injection_def) + eq_net_injection = _init(model, :eq_net_injection) eq_power_balance = _init(model, :eq_power_balance) for t in 1:T, b in model[:instance].buses n = net_injection[b.name, t] = @variable(model) - eq_net_injection_def[t, b.name] = - @constraint(model, n == model[:expr_net_injection][b.name, t]) + eq_net_injection[b.name, t] = + @constraint(model, -n + model[:expr_net_injection][b.name, t] == 0) end for t in 1:T eq_power_balance[t] = @constraint(