Skip to content

Commit 72d1a77

Browse files
committed
New OGF: Proxy for minimizing compressor power
Replacing the nonlinear compressor power objective with a linear proxy, which is the absolute value of the pressure difference at the compressors endpoints
1 parent 837d7fe commit 72d1a77

File tree

8 files changed

+87
-4
lines changed

8 files changed

+87
-4
lines changed

src/GasModels.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ module GasModels
8383
include("prob/ls.jl")
8484
include("prob/nels.jl")
8585
include("prob/ogf.jl")
86+
include("prob/new_ogf.jl")
8687
include("prob/transient_ogf.jl")
8788
include("prob/transient_ogf_archived_storage.jl")
8889

src/core/constraint.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,15 @@ end
211211
function constraint_compressor_mass_flow_ne(gm::AbstractGasModel, n::Int, k, f_min, f_max)
212212
end
213213

214+
"Constraint: constraints to serve as a proxy for minimizing the compressor power"
215+
function constraint_compressor_minpower_proxy(gm::AbstractGasModel, n::Int, k, i, j)
216+
pi = var(gm, n, :psqr, i)
217+
pj = var(gm, n, :psqr, j)
218+
mpp = var(gm, n, :min_power_proxy, k)
219+
220+
_add_constraint!(gm, n, :compressor_minpower_proxy1, k, JuMP.@constraint(gm.model, mpp >= pi - pj ))
221+
_add_constraint!(gm, n, :compressor_minpower_proxy2, k, JuMP.@constraint(gm.model, mpp >= pj - pi ))
222+
end
214223

215224
#################################################################################################
216225
# Constraints associated with control valves

src/core/constraint_template.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,14 @@ function constraint_compressor_energy(gm::AbstractGasModel, k; n::Int = nw_id_de
444444
constraint_compressor_energy(gm, n, k, power_max, m, work, flow_max, ratio_max)
445445
end
446446

447+
"Template: Constraints to support the proxy for minimizing the compressor power"
448+
function constraint_compressor_minpower_proxy(gm::AbstractGasModel, k; n::Int = nw_id_default)
449+
compressor = ref(gm, n, :compressor, k)
450+
i = compressor["fr_junction"]
451+
j = compressor["to_junction"]
447452

453+
constraint_compressor_minpower_proxy(gm, n, k, i, j)
454+
end
448455
#################################################################################################
449456
# Templates for control valves
450457
#################################################################################################

src/core/objective.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ end
206206
"function for minimizing new economic costs: ``\\min \\sum_{j \\in {\\cal D}} \\kappa_j \\boldsymbol{d}_j - \\sum_{j \\in {\\cal T}} \\kappa_j \\boldsymbol{\\tau}_j - \\sum_{j \\in {\\cal R}} \\kappa_j \\boldsymbol{r}_j -
207207
\\sum_{k \\in {\\cal C}} \\boldsymbol{p^2}_{jk} - \\boldsymbol{p^2}_{ik} ``"
208208
function objective_min_new_economic_costs(gm::AbstractGasModel, nws = [nw_id_default])
209-
r = Dict(n => var(gm, n, :rsqr) for n in nws)
209+
mpp = Dict(n => var(gm, n, :min_power_proxy) for n in nws)
210210
f = Dict(n => var(gm, n, :f_compressor) for n in nws)
211211
p2 = Dict(n => var(gm, n, :psqr) for n in nws)
212212
fl = Dict(n => var(gm, n, :fl) for n in nws)
@@ -260,7 +260,7 @@ function objective_min_new_economic_costs(gm::AbstractGasModel, nws = [nw_id_def
260260
sum(-transfer_prices[n][i] * ft[n][i] for i in transfer_set[n]) +
261261
economic_weighting * sum(prod_prices[n][i] * fg[n][i] for i in prod_set[n]) +
262262
(1.0 - economic_weighting) *
263-
sum( (p2[n][compressor["to_junction"]] - p2[n][compressor["fr_junction"]]) for (i, compressor) in ref(gm, n, :compressor))
263+
sum(mpp[n][i] for (i, compressor) in ref(gm, n, :compressor))
264264
for n in nws
265265
))
266266
return JuMP.@objective(gm.model, Min, z)

src/core/variable.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,24 @@ function variable_compressor_ratio_sqr_ne(gm::AbstractGasModel, nw::Int=nw_id_de
685685
report && sol_component_value(gm, nw, :ne_compressor, :rsqr_ne, keys(compressors), rsqr)
686686
end
687687

688+
"Variable Set: variables associated with proxy for minimizing compression power"
689+
function variable_compressor_minpower_proxy(gm::AbstractGasModel, nw::Int=nw_id_default; bounded::Bool=true, report::Bool=true, compressors = ref(gm, nw, :compressor))
690+
mpp = var(gm, nw)[:min_power_proxy] = JuMP.@variable(gm.model,
691+
[i in keys(compressors)],
692+
base_name="$(nw)_mpp",
693+
start=comp_start_value(ref(gm, nw, :compressor), i, "min_power_proxy_start", 0.0)
694+
)
695+
696+
if bounded
697+
for (i, compressor) in compressors
698+
JuMP.set_lower_bound(mpp[i], 0)
699+
end
700+
end
701+
702+
report && sol_component_value(gm, nw, :compressor, :min_power_proxy, keys(compressors), mpp)
703+
end
704+
705+
688706
"Support function for getting a one off y direction variable"
689707
function get_compressor_y(gm::AbstractGasModel, n::Int, k)
690708
if !haskey(var(gm, n),:y_compressor)

src/prob/ogf_new.jl renamed to src/prob/new_ogf.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Definitions for running the new optimal gas flow (ogf) (with a proxy compressor power term in the objective)
22

33
"entry point into running the new ogf problem"
4-
function run_nw_ogf(file, model_type, optimizer; kwargs...)
4+
function run_new_ogf(file, model_type, optimizer; kwargs...)
55
return run_model(
66
file,
77
model_type,
@@ -49,6 +49,7 @@ function build_new_ogf(gm::AbstractGasModel)
4949
variable_production_mass_flow(gm)
5050
variable_transfer_mass_flow(gm)
5151
variable_compressor_ratio_sqr(gm)
52+
variable_compressor_minpower_proxy(gm)
5253
variable_storage(gm)
5354
variable_form_specific(gm)
5455

@@ -88,6 +89,7 @@ function build_new_ogf(gm::AbstractGasModel)
8889
constraint_compressor_ratios(gm, i)
8990
constraint_compressor_mass_flow(gm, i)
9091
constraint_compressor_ratio_value(gm, i)
92+
constraint_compressor_minpower_proxy(gm, i)
9193
end
9294

9395
for i in keys(bounded_compressors)

test/new_ogf.jl

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
@testset "test new ogf" begin
2+
@testset "test wp new ogf" begin
3+
@testset "case 6 new ogf" begin
4+
@info "Testing NEW OGF"
5+
data = GasModels.parse_file("../test/data/matgas/case-6-no-power-limits.m")
6+
result = run_new_ogf(data, WPGasModel, nlp_solver)
7+
@test result["termination_status"] in [LOCALLY_SOLVED, ALMOST_LOCALLY_SOLVED, OPTIMAL, :Suboptimal]
8+
@test isapprox(result["objective"], -253.683; atol = 1e-2)
9+
GasModels.make_si_units!(result["solution"])
10+
@test isapprox(result["solution"]["receipt"]["1"]["fg"], 123.6822; atol = 1e-2)
11+
end
12+
13+
@testset "case 6 new ogf weymouth lin rel" begin
14+
@info "Testing NEW OGF Linear Relaxation of Pipe Weymouth Physics"
15+
data = GasModels.parse_file("../test/data/matgas/case-6-no-power-limits.m")
16+
result = run_new_ogf(data, LRWPGasModel, lp_solver)
17+
@test result["termination_status"] in [LOCALLY_SOLVED, ALMOST_LOCALLY_SOLVED, OPTIMAL, :Suboptimal]
18+
@test isapprox(result["objective"], -260.00; atol = 1e-2)
19+
GasModels.make_si_units!(result["solution"])
20+
@test isapprox(result["solution"]["receipt"]["1"]["fg"], 130.00; atol = 1e-2)
21+
end
22+
23+
24+
@testset "case 6 wp new ogf binding energy constraint" begin
25+
@info "Testing NEW OGF Binding Energy Cosntraint"
26+
data = GasModels.parse_file("../test/data/matgas/case-6.m")
27+
result = run_new_ogf(data, WPGasModel, nlp_solver)
28+
@test result["termination_status"] in [LOCALLY_SOLVED, ALMOST_LOCALLY_SOLVED, OPTIMAL, :Suboptimal]
29+
@test isapprox(result["objective"], -237.718; atol = 1e-2)
30+
GasModels.make_si_units!(result["solution"])
31+
@test isapprox(result["solution"]["receipt"]["1"]["fg"], 97.33; atol = 1e-2)
32+
end
33+
34+
@testset "case 6 wp new ogf elevation constraint" begin
35+
@info "Testing NEW OGF Elevation Cosntraint"
36+
data = GasModels.parse_file("../test/data/matgas/case-6-elevation.m")
37+
result = run_new_ogf(data, WPGasModel, nlp_solver)
38+
@test result["termination_status"] in [LOCALLY_SOLVED, ALMOST_LOCALLY_SOLVED, OPTIMAL, :Suboptimal]
39+
@test isapprox(result["objective"], -245.251; atol = 1e-2)
40+
GasModels.make_si_units!(result["solution"])
41+
@test isapprox(result["solution"]["receipt"]["1"]["fg"], 102.5677; atol = 1e-2)
42+
end
43+
end
44+
end

test/runtests.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import Ipopt
1717
import HiGHS
1818
import Juniper
1919

20-
using MathOptInterface
20+
using MathOptInterface
2121

2222
const MOI = MathOptInterface
2323

@@ -52,6 +52,8 @@ include("common.jl")
5252

5353
include("ogf.jl")
5454

55+
include("new_ogf.jl")
56+
5557
include("ls.jl")
5658

5759
include("nels.jl")

0 commit comments

Comments
 (0)