Skip to content

Commit

Permalink
Write out DC line data to dict (#111)
Browse files Browse the repository at this point in the history
* Add Matpower compatible DC line extension
* Adding file for AC-DC Power flow model
* Add DC arcs and buspairs to base.jl
* Consistent pmin, pmax formulation, form the to and from side of the lines
* Further improve support for DC lines
* Bugfix/rewrite for negative PMIN values in a Matpower case
* Finalized testing of DC Line implementation
* Updated opf and pf tests and validated active DC lines cases against Matpower
* Warning that DC line costs are not supported
* add case3_dc.m, case5_dc.m
* Avoiding infinite bounds on pmin and pmax for DC lines
* Avoiding negative losses, by checking input data, overwriting bad values and throwing warnings
* Update of documentation
* Updated description of keys in pm.ref
  • Loading branch information
hakanergun authored and ccoffrin committed Jul 29, 2017
1 parent 9250fe3 commit 7843133
Show file tree
Hide file tree
Showing 31 changed files with 773 additions and 136 deletions.
9 changes: 5 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
PowerModels.jl Change Log
PowerModels.jl Change Log
=================

### Staged
Expand All @@ -7,16 +7,17 @@ PowerModels.jl Change Log
- Fixed bug in constants for w-space phase angle difference constraints
- Fixed bug when no refrence bus was specified
- Fixed dcline parsing bug
- Support for DC Line formulation compatible with matpower

### v0.3.3
- Added JuMP v0.17 compatibility
- Reorganized documentation into Manual, Library, Developer, and Experimental Results
- Reorganized documentation into Manual, Library, Developer, and Experimental Results

### v0.3.2
- Updated type declarations to Julia v0.6 syntax
- Moved documentation to Documenter.jl (thanks to @yeesian)
- Added basic OPF results to Documentation
- Extended pm.ref include all fields from pm.data
- Extended pm.ref include all fields from pm.data

### v0.3.1
- Added JuMP v0.16 and Julia v0.6 compatibility
Expand Down Expand Up @@ -46,7 +47,7 @@ PowerModels.jl Change Log
- Added support Matlab cell arrays
- Added support for Matpower bus_names
- Added ability for reading non-standard Matpower data elements
- Added JuMP version v0.14 upper bound
- Added JuMP version v0.14 upper bound

### v0.2.2
- Added Transmission Network Expansion Planning (tnep) problem.
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# PowerModels.jl
# PowerModels.jl

Release: [![PowerModels](http://pkg.julialang.org/badges/PowerModels_0.4.svg)](http://pkg.julialang.org/?pkg=PowerModels), [![PowerModels](http://pkg.julialang.org/badges/PowerModels_0.5.svg)](http://pkg.julialang.org/?pkg=PowerModels), [![PowerModels](http://pkg.julialang.org/badges/PowerModels_0.6.svg)](http://pkg.julialang.org/?pkg=PowerModels),
Release: [![PowerModels](http://pkg.julialang.org/badges/PowerModels_0.4.svg)](http://pkg.julialang.org/?pkg=PowerModels), [![PowerModels](http://pkg.julialang.org/badges/PowerModels_0.5.svg)](http://pkg.julialang.org/?pkg=PowerModels), [![PowerModels](http://pkg.julialang.org/badges/PowerModels_0.6.svg)](http://pkg.julialang.org/?pkg=PowerModels),
[![](https://img.shields.io/badge/docs-stable-blue.svg)](https://lanl-ansi.github.io/PowerModels.jl/stable)

Dev:
Expand Down Expand Up @@ -42,6 +42,7 @@ The primary developer is Carleton Coffrin, with significant contributions from R

Special thanks to Miles Lubin for his assistance in integrating with Julia/JuMP.

Frederik Geth and Hakan Ergun (both KU Leuven) contributed to the Matpower-compatible DC Line formulation.

## License

Expand Down
7 changes: 7 additions & 0 deletions docs/src/constraints.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,13 @@ constraint_phase_angle_difference_ne
constraint_loss_lb
```

## DC Line Constraints
### Network Flow Constraints

```@docs
constraint_dcline
```

## Commonly Used Constraints
The following methods generally assume that the model contains `p` and `q` values for branches line flows and bus flow conservation.

Expand Down
2 changes: 2 additions & 0 deletions docs/src/network-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ The data exchange via JSON files is ideal for building algorithms, however it is

In addition to parsing the standard Matpower parameters, PowerModels also supports extending the standard Matpower format in a number of ways as illustrated by the following examples. In these examples JSON document fragments are used to indicate the structure of the PowerModel dictionary.

Note that for DC lines, the flow results are returned using the same convention as for the AC lines, i.e. positive values for `p_from`/`q_from `and `p_to`/`q_to` indicating power flow from the 'to' node or 'from' node into the line. This means that w.r.t matpower the sign is identical for `p_from`, but opposite for `q_from`/`p_to`/`q_to`.

### Single Values
Single values are added to the root of the dictionary as follows,

Expand Down
15 changes: 15 additions & 0 deletions docs/src/quickguide.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,21 @@ run_opf(network_data, ACPPowerModel, IpoptSolver())

For additional details about the network data, see the [PowerModels Network Data Format](@ref) section.

## Inspecting AC and DC branch flow results
The flow AC and DC branch results are not written to the result by default. To inspect the flow results, pass a settings Dict
```julia
result = run_opf("nesta_case3_dc.m", ACPPowerModel, IpoptSolver(), setting = Dict("output" => Dict("line_flows" => true)))
result["solution"]["dcline"]["1"]
result["solution"]["branch"]["2"]
```

The losses of a AC or DC branch can be derived:
```julia
loss_ac = Dict(name => data["p_to"]+data["p_from"] for (name, data) in result["solution"]["branch"])
loss_dc = Dict(name => data["p_to"]+data["p_from"] for (name, data) in result["solution"]["dcline"])
```


## Inspecting the Formulation
The following example demonstrates how to break a `run_opf` call into seperate model building and solving steps. This allows inspection of the JuMP model created by PowerModels for the AC-OPF problem,

Expand Down
24 changes: 21 additions & 3 deletions docs/src/specifications.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ variable_voltage(pm)
variable_active_generation(pm)
variable_reactive_generation(pm)
variable_line_flow(pm)
variable_dcline_flow(pm)
```

### Constraints
Expand All @@ -31,6 +32,9 @@ for (i,branch) in pm.ref[:branch]
constraint_thermal_limit_from(pm, branch)
constraint_thermal_limit_to(pm, branch)
end
for (i,dcline) in pm.ref[:dcline]
constraint_dcline(pm, dcline)
end
```

## Optimal Transmission Switching (OTS)
Expand All @@ -48,6 +52,7 @@ variable_voltage_on_off(pm)
variable_active_generation(pm)
variable_reactive_generation(pm)
variable_line_flow(pm)
variable_dcline_flow(pm)
```

### Objective
Expand All @@ -73,6 +78,9 @@ for (i,branch) in pm.ref[:branch]
constraint_thermal_limit_from_on_off(pm, branch)
constraint_thermal_limit_to_on_off(pm, branch)
end
for (i,dcline) in pm.ref[:dcline]
constraint_dcline(pm, dcline)
end
```

## Power Flow (PF)
Expand All @@ -85,6 +93,7 @@ variable_voltage(pm, bounded = false)
variable_active_generation(pm, bounded = false)
variable_reactive_generation(pm, bounded = false)
variable_line_flow(pm, bounded = false)
variable_dcline_flow(pm, bounded = false)
```

### Constraints
Expand All @@ -93,6 +102,7 @@ constraint_theta_ref(pm)
constraint_voltage_magnitude_setpoint(pm, pm.ref[:bus][pm.ref[:ref_bus]])
constraint_voltage(pm)


for (i,bus) in pm.ref[:bus]
constraint_kcl_shunt(pm, bus)

Expand All @@ -113,6 +123,10 @@ for (i,branch) in pm.ref[:branch]
constraint_ohms_yt_from(pm, branch)
constraint_ohms_yt_to(pm, branch)
end
for (i,dcline) in pm.ref[:dcline]
constraint_active_dc_line_setpoint(pm, dcline)
constraint_dcline_voltage(pm, dcline; epsilon = 0.00001)
end
```

## Transmission Network Expansion Planning (TNEP)
Expand All @@ -124,12 +138,13 @@ objective_tnep_cost(pm)

### Variables
```julia
variable_line_ne(pm)
variable_line_ne(pm)
variable_voltage(pm)
variable_voltage_ne(pm)
variable_active_generation(pm)
variable_reactive_generation(pm)
variable_line_flow(pm)
variable_dcline_flow(pm)
variable_line_flow_ne(pm)
```

Expand All @@ -151,15 +166,18 @@ for (i,branch) in pm.ref[:branch]

constraint_thermal_limit_from(pm, branch)
constraint_thermal_limit_to(pm, branch)
end
end

for (i,branch) in pm.ref[:ne_branch]
constraint_ohms_yt_from_ne(pm, branch)
constraint_ohms_yt_to_ne(pm, branch)
constraint_ohms_yt_to_ne(pm, branch)

constraint_phase_angle_difference_ne(pm, branch)

constraint_thermal_limit_from_ne(pm, branch)
constraint_thermal_limit_to_ne(pm, branch)
end
for (i,dcline) in pm.ref[:dcline]
constraint_dcline(pm, dcline)
end
```
64 changes: 62 additions & 2 deletions src/core/base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export
```
type GenericPowerModel{T<:AbstractPowerFormulation}
model::JuMP.Model
data::Dict{String,Any}
data::Dict{String,Any}
setting::Dict{String,Any}
solution::Dict{String,Any}
ref::Dict{Symbol,Any} # reference data
Expand Down Expand Up @@ -150,8 +150,13 @@ Some of the common keys include:
* `:arcs_to` -- the set `[(i,b["t_bus"],b["f_bus"]) for (i,b) in ref[:branch]]`,
* `:arcs` -- the set of arcs from both `arcs_from` and `arcs_to`,
* `:bus_arcs` -- the mapping `Dict(i => [(l,i,j) for (l,i,j) in ref[:arcs]])`,
* `:buspairs` -- (see `buspair_parameters(ref[:arcs_from], ref[:branch], ref[:bus])`), and
* `:buspairs` -- (see `buspair_parameters(ref[:arcs_from], ref[:branch], ref[:bus])`),
* `:bus_gens` -- the mapping `Dict(i => [gen["gen_bus"] for (i,gen) in ref[:gen]])`.
* `:arcs_from_dc` -- the set `[(i,b["f_bus"],b["t_bus"]) for (i,b) in ref[:dcline]]`,
* `:arcs_to_dc` -- the set `[(i,b["t_bus"],b["f_bus"]) for (i,b) in ref[:dcline]]`,
* `:arcs_dc` -- the set of arcs from both `arcs_from_dc` and `arcs_to_dc`,
* `:bus_arcs_dc` -- the mapping `Dict(i => [(l,i,j) for (l,i,j) in ref[:arcs_dc]])`, and
* `:buspairs_dc` -- (see `buspair_parameters(ref[:arcs_from_dc], ref[:dcline], ref[:bus])`),
If `:ne_branch` exists, then the following keys are also available with similar semantics:
Expand All @@ -176,11 +181,16 @@ function build_ref(data::Dict{String,Any})
ref[:bus] = filter((i, bus) -> bus["bus_type"] != 4, ref[:bus])
ref[:gen] = filter((i, gen) -> gen["gen_status"] == 1 && gen["gen_bus"] in keys(ref[:bus]), ref[:gen])
ref[:branch] = filter((i, branch) -> branch["br_status"] == 1 && branch["f_bus"] in keys(ref[:bus]) && branch["t_bus"] in keys(ref[:bus]), ref[:branch])
ref[:dcline] = filter((i, dcline) -> dcline["br_status"] == 1 && dcline["f_bus"] in keys(ref[:bus]) && dcline["t_bus"] in keys(ref[:bus]), ref[:dcline])

ref[:arcs_from] = [(i,branch["f_bus"],branch["t_bus"]) for (i,branch) in ref[:branch]]
ref[:arcs_to] = [(i,branch["t_bus"],branch["f_bus"]) for (i,branch) in ref[:branch]]
ref[:arcs] = [ref[:arcs_from]; ref[:arcs_to]]

ref[:arcs_from_dc] = [(i,dcline["f_bus"],dcline["t_bus"]) for (i,dcline) in ref[:dcline]]
ref[:arcs_to_dc] = [(i,dcline["t_bus"],dcline["f_bus"]) for (i,dcline) in ref[:dcline]]
ref[:arcs_dc] = [ref[:arcs_from_dc]; ref[:arcs_to_dc]]

bus_gens = Dict([(i, []) for (i,bus) in ref[:bus]])
for (i,gen) in ref[:gen]
push!(bus_gens[gen["gen_bus"]], i)
Expand All @@ -193,6 +203,11 @@ function build_ref(data::Dict{String,Any})
end
ref[:bus_arcs] = bus_arcs

bus_arcs_dc = Dict([(i, []) for (i,bus) in ref[:bus]])
for (l,i,j) in ref[:arcs_dc]
push!(bus_arcs_dc[i], (l,i,j))
end
ref[:bus_arcs_dc] = bus_arcs_dc

# a set of buses to support multiple connected components
ref_buses = Dict()
Expand All @@ -217,6 +232,11 @@ function build_ref(data::Dict{String,Any})


ref[:buspairs] = buspair_parameters(ref[:arcs_from], ref[:branch], ref[:bus])
############################ DC LINES##########################################
if haskey(ref, :dcline)
ref[:buspairs_dc] = buspair_parameters_dc(ref[:arcs_from_dc], ref[:dcline], ref[:bus])
end
###############################################################################

if haskey(ref, :ne_branch)
ref[:ne_branch] = filter((i, branch) -> branch["br_status"] == 1 && branch["f_bus"] in keys(ref[:bus]) && branch["t_bus"] in keys(ref[:bus]), ref[:ne_branch])
Expand Down Expand Up @@ -284,3 +304,43 @@ function buspair_parameters(arcs_from, branches, buses)

return buspairs
end

"compute bus pair level structures for DC"
function buspair_parameters_dc(arcs_from_dc, dclines, buses)
buspair_indexes = collect(Set([(i,j) for (l,i,j) in arcs_from_dc]))

bp_angmin = Dict([(bp, -Inf) for bp in buspair_indexes])
bp_angmax = Dict([(bp, Inf) for bp in buspair_indexes])
bp_line = Dict([(bp, Inf) for bp in buspair_indexes])
pmint = Dict([(bp, Inf) for bp in buspair_indexes])
pminf = Dict([(bp, Inf) for bp in buspair_indexes])
pmaxt = Dict([(bp, Inf) for bp in buspair_indexes])
pmaxf = Dict([(bp, Inf) for bp in buspair_indexes])

for (l,dcline) in dclines
i = dcline["f_bus"]
j = dcline["t_bus"]

bp_line[(i,j)] = min(bp_line[(i,j)], l)
end

buspairs_dc = Dict([((i,j), Dict(
"line"=>bp_line[(i,j)],
"pminf"=>dclines[bp_line[(i,j)]]["pminf"],
"pmaxf"=>dclines[bp_line[(i,j)]]["pmaxf"],
"pmint"=>dclines[bp_line[(i,j)]]["pmint"],
"pmaxt"=>dclines[bp_line[(i,j)]]["pmaxt"],
"qminf"=>dclines[bp_line[(i,j)]]["qminf"],
"qmaxf"=>dclines[bp_line[(i,j)]]["qmaxf"],
"qmint"=>dclines[bp_line[(i,j)]]["qmint"],
"qmaxt"=>dclines[bp_line[(i,j)]]["qmaxt"],
"pf"=>dclines[bp_line[(i,j)]]["pf"],
"pt"=>dclines[bp_line[(i,j)]]["pt"],
"qf"=>dclines[bp_line[(i,j)]]["qf"],
"qt"=>dclines[bp_line[(i,j)]]["qt"],
"vf"=>dclines[bp_line[(i,j)]]["vf"],
"vt"=>dclines[bp_line[(i,j)]]["vt"]
)) for (i,j) in buspair_indexes])

return buspairs_dc
end
21 changes: 20 additions & 1 deletion src/core/constraint.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
###############################################################################
# This file defines commonly used constraints for power flow models
# These constraints generally assume that the model contains p and q values
# These constraints generally assume that the model contains p and q values
# for branches line flows and bus flow conservation
###############################################################################

Expand Down Expand Up @@ -88,3 +88,22 @@ function constraint_reactive_gen_setpoint(pm::GenericPowerModel, i, qg)
c = @constraint(pm.model, qg_var == qg)
return Set([c])
end

"`pf[i] == pf, pt[i] == pt`"
function constraint_active_dcline_setpoint(pm::GenericPowerModel, i, f_idx, t_idx, pf, pt, epsilon)
p_fr = getindex(pm.model, :p_dc)[f_idx]
p_to = getindex(pm.model, :p_dc)[t_idx]

if epsilon == 0.0
c1 = @constraint(pm.model, p_fr == pf)
c2 = @constraint(pm.model, p_to == pt)
return Set([c1,c2])
else
c1 = @constraint(pm.model, p_fr >= pf - epsilon)
c2 = @constraint(pm.model, p_to >= pt - epsilon)
c3 = @constraint(pm.model, p_fr <= pf + epsilon)
c4 = @constraint(pm.model, p_to <= pt + epsilon)
return Set([c1,c2,c3,c4])
end

end
Loading

0 comments on commit 7843133

Please sign in to comment.