Skip to content

Commit

Permalink
improve support for pwl uc functions and add test (#795)
Browse files Browse the repository at this point in the history
  • Loading branch information
ccoffrin authored Oct 27, 2021
1 parent 84252ad commit 686c010
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ PowerModels.jl Change Log
=========================

### Staged
- Improved support for PWL costs with on/off generators
- Added support for two-terminal HVDC lines to PSSE export (#754)
- Improved formulation of `relaxation_sin_on_off` constraint (#786)

Expand Down
20 changes: 15 additions & 5 deletions src/core/objective.jl
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,12 @@ function objective_variable_pg_cost(pm::AbstractPowerModel, report::Bool=true)
pg_cost = var(pm, n)[:pg_cost] = Dict{Int,Any}()

for (i,gen) in ref(pm, n, :gen)
points = calc_pwl_points(gen["ncost"], gen["cost"], gen["pmin"], gen["pmax"])
pg_vars = [var(pm, n, :pg, i)[c] for c in conductor_ids(pm, n)]
pmin = sum(JuMP.lower_bound.(pg_vars))
pmax = sum(JuMP.upper_bound.(pg_vars))

# note pmin/pmax may be different from gen["pmin"]/gen["pmax"] in the on/off case
points = calc_pwl_points(gen["ncost"], gen["cost"], pmin, pmax)

pg_cost_lambda = JuMP.@variable(pm.model,
[i in 1:length(points)], base_name="$(n)_pg_cost_lambda",
Expand All @@ -497,7 +502,7 @@ function objective_variable_pg_cost(pm::AbstractPowerModel, report::Bool=true)
pg_expr += point.mw*pg_cost_lambda[i]
pg_cost_expr += point.cost*pg_cost_lambda[i]
end
JuMP.@constraint(pm.model, pg_expr == sum(var(pm, n, :pg, i)[c] for c in conductor_ids(pm, n)))
JuMP.@constraint(pm.model, pg_expr == sum(pg_vars))
pg_cost[i] = pg_cost_expr
end

Expand All @@ -512,7 +517,13 @@ function objective_variable_dc_cost(pm::AbstractPowerModel, report::Bool=true)
p_dc_cost = var(pm, n)[:p_dc_cost] = Dict{Int,Any}()

for (i,dcline) in ref(pm, n, :dcline)
points = calc_pwl_points(dcline["ncost"], dcline["cost"], dcline["pminf"], dcline["pmaxf"])
arc = (i, dcline["f_bus"], dcline["t_bus"])
p_dc_vars = [var(pm, n, :p_dc)[arc][c] for c in conductor_ids(pm, n)]
pmin = sum(JuMP.lower_bound.(p_dc_vars))
pmax = sum(JuMP.upper_bound.(p_dc_vars))

# note pmin/pmax may be different from dcline["pminf"]/dcline["pmaxf"] in the on/off case
points = calc_pwl_points(dcline["ncost"], dcline["cost"], pmin, pmax)

dc_p_cost_lambda = JuMP.@variable(pm.model,
[i in 1:length(points)], base_name="$(n)_dc_p_cost_lambda",
Expand All @@ -528,8 +539,7 @@ function objective_variable_dc_cost(pm::AbstractPowerModel, report::Bool=true)
dc_p_cost_expr += point.cost*dc_p_cost_lambda[i]
end

arc = (i, dcline["f_bus"], dcline["t_bus"])
JuMP.@constraint(pm.model, dc_p_expr == sum(var(pm, n, :p_dc)[arc][c] for c in conductor_ids(pm, n)))
JuMP.@constraint(pm.model, dc_p_expr == sum(p_dc_vars))
p_dc_cost[i] = dc_p_cost_expr
end

Expand Down
10 changes: 5 additions & 5 deletions test/data/matpower/case5_pwlc.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
%% generator data
% bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin
mpc.gen = [
1 40.0 30.0 30.0 -30.0 1.07762 100.0 1 40.0 0.0;
1 170.0 127.5 127.5 -127.5 1.07762 100.0 1 170.0 0.0;
3 324.498 390.0 390.0 -390.0 1.1 100.0 1 520.0 0.0;
4 0.0 -10.802 150.0 -150.0 1.06414 100.0 1 200.0 0.0;
10 470.694 -165.039 450.0 -450.0 1.06907 100.0 1 600.0 0.0;
1 40.0 30.0 30.0 -30.0 1.07762 100.0 1 40.0 0.0;
1 170.0 127.5 127.5 -127.5 1.07762 100.0 1 170.0 50.0;
3 324.498 390.0 390.0 -390.0 1.1 100.0 1 520.0 100.0;
4 0.0 -10.802 150.0 -150.0 1.06414 100.0 1 200.0 50.0;
10 470.694 -165.039 450.0 -450.0 1.06907 100.0 1 600.0 60.0;
];

%% generator cost data
Expand Down
13 changes: 13 additions & 0 deletions test/opf-var.jl
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,19 @@ end
@test isapprox(result["objective"], 17613.2; atol = 1e0)
@test isapprox(result["solution"]["gen"]["4"]["gen_status"], 0.0)
end

@testset "5-bus uc pwl case" begin
data = parse_file("../test/data/matpower/case5_pwlc.m")
for (i,load) in data["load"]
load["pd"] = 0.5*load["pd"]
end
result = PowerModels._run_ucopf(data, DCPPowerModel, cbc_solver)

@test result["termination_status"] == OPTIMAL
@test isapprox(result["objective"], 8008.0; atol = 1e0)
@test isapprox(result["solution"]["gen"]["4"]["gen_status"], 0.0)
@test isapprox(result["solution"]["gen"]["5"]["gen_status"], 0.0)
end
end


Expand Down

0 comments on commit 686c010

Please sign in to comment.