Skip to content

Commit

Permalink
introduce new keywords for branch flow constraints
Browse files Browse the repository at this point in the history
  • Loading branch information
mcosovic committed Aug 16, 2024
1 parent 21318de commit 164273d
Show file tree
Hide file tree
Showing 15 changed files with 234 additions and 167 deletions.
22 changes: 10 additions & 12 deletions docs/src/manual/acOptimalPowerFlow.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ addBus!(system; label = "Bus 1", type = 3, active = 0.1, angle = -0.1)
addBus!(system; label = "Bus 2", reactive = 0.01, magnitude = 1.1)
@branch(minDiffAngle = -pi, maxDiffAngle = pi, reactance = 0.5, type = 2)
addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", longTerm = 0.15)
addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", maxFromBus = 0.15)
@generator(maxActive = 0.5, minReactive = -0.1, maxReactive = 0.1, status = 0)
addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 0.4, reactive = 0.2)
Expand Down Expand Up @@ -208,24 +208,19 @@ The `flow` field contains references to the inequality constraints associated wi
* `type = 2` for the active power flow,
* `type = 3` for the current flow magnitude.

These limits are specified using the `longTerm` keyword within the [`addBranch!`](@ref addBranch!) function. By default, the `longTerm` keyword is linked to apparent power (`type = 1`).
These limits are specified using the `minFromBus`, `maxFromBus`, `minToBus` and `maxToBus` keywords within the [`addBranch!`](@ref addBranch!) function. By default, these limit keywords are associated with apparent power (`type = 1`).

However, in the example, we configured it to use active power flow by setting `type = 2`. To access the flow constraints of branches at the from-bus end, we can utilize the following code snippet:
```@repl ACOptimalPowerFlow
print(system.branch.label, analysis.method.constraint.flow.from)
```

Similarly, to access the to-bus end flow constraints of branches we can use the following code snippet:
```@repl ACOptimalPowerFlow
print(system.branch.label, analysis.method.constraint.flow.to)
```

!!! note "Info"
Please note that if the flow constraints are set to `longTerm = 0.0` for the corresponding branch, JuliGrid will omit the corresponding inequality constraint.
Please note that if the flow constraints are set to `minFromBus = 0.0` and `maxFromBus = 0.0` for the corresponding branch, JuliGrid will omit the corresponding inequality constraint at the from-bus end of the branch. The same applies to the to-bus end if `minToBus = 0.0` and `maxToBus = 0.0` are set.

Additionally, by employing the [`updateBranch!`](@ref updateBranch!) function, we have the ability to modify these specific constraints:
```@example ACOptimalPowerFlow
updateBranch!(system, analysis; label = "Branch 1", reactance = 1.0, longTerm = 0.14)
updateBranch!(system, analysis; label = "Branch 1", minFromBus = -0.15, maxToBus = 0.15)
nothing # hide
```

Expand All @@ -235,6 +230,9 @@ print(system.branch.label, analysis.method.constraint.flow.from)
print(system.branch.label, analysis.method.constraint.flow.to)
```

!!! tip "Tip"
In typical scenarios, `minFromBus` is equal to `minToBus`, and `maxFromBus` is equal to `maxToBus`. However, we allow these values to be defined separately for greater flexibility, enabling, among other things, the option to apply constraints on only one side of the branch.

---

##### Power Capability Constraints
Expand Down Expand Up @@ -529,9 +527,9 @@ addBus!(system; label = "Bus 2", active = 0.1, reactive = 0.01, conductance = 0.
addBus!(system; label = "Bus 3", active = 0.05, reactive = 0.02)
@branch(resistance = 0.5, reactance = 1.0, conductance = 1e-4, susceptance = 0.01)
addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", longTerm = 0.15)
addBranch!(system; label = "Branch 2", from = "Bus 1", to = "Bus 3", longTerm = 0.10)
addBranch!(system; label = "Branch 3", from = "Bus 2", to = "Bus 3", longTerm = 0.25)
addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", maxFromBus = 0.15)
addBranch!(system; label = "Branch 2", from = "Bus 1", to = "Bus 3", maxFromBus = 0.10)
addBranch!(system; label = "Branch 3", from = "Bus 2", to = "Bus 3", maxFromBus = 0.25)
@generator(maxActive = 0.5, minReactive = -0.1, maxReactive = 0.1)
addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 3.2, reactive = 0.5)
Expand Down
6 changes: 3 additions & 3 deletions docs/src/manual/dcOptimalPowerFlow.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ addBus!(system; label = "Bus 1", type = 3, angle = 0.17)
addBus!(system; label = "Bus 2", active = 0.1, conductance = 0.04)
addBus!(system; label = "Bus 3", active = 0.05)
@branch(minDiffAngle = -3.1, maxDiffAngle = 3.1, longTerm = 0.12)
@branch(minDiffAngle = -3.1, maxDiffAngle = 3.1, maxFromBus = 0.12)
addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.05)
addBranch!(system; label = "Branch 2", from = "Bus 1", to = "Bus 3", reactance = 0.01)
addBranch!(system; label = "Branch 3", from = "Bus 2", to = "Bus 3", reactance = 0.01)
Expand Down Expand Up @@ -184,7 +184,7 @@ print(system.branch.label, analysis.method.constraint.flow.active)
By employing the [`updateBranch!`](@ref updateBranch!) function, we have the ability to modify these specific constraints, for example:
```@example DCOptimalPowerFlow
updateBranch!(system, analysis; label = "Branch 1", status = 0)
updateBranch!(system, analysis; label = "Branch 2", reactance = 0.03, longTerm = 0.14)
updateBranch!(system, analysis; label = "Branch 2", reactance = 0.03, maxFromBus = 0.14)
nothing # hide
```

Expand Down Expand Up @@ -450,7 +450,7 @@ addBus!(system; label = "Bus 1", type = 3, angle = 0.17)
addBus!(system; label = "Bus 2", active = 0.1, conductance = 0.04)
addBus!(system; label = "Bus 3", active = 0.05)
@branch(minDiffAngle = -pi, maxDiffAngle = pi, longTerm = 0.12)
@branch(minDiffAngle = -pi, maxDiffAngle = pi, maxFromBus = 0.12)
addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.05)
addBranch!(system; label = "Branch 2", from = "Bus 1", to = "Bus 3", reactance = 0.01)
addBranch!(system; label = "Branch 3", from = "Bus 2", to = "Bus 3", reactance = 0.01)
Expand Down
4 changes: 2 additions & 2 deletions docs/src/tutorials/acOptimalPowerFlow.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ addBus!(system; label = 1, type = 3, active = 0.1, angle = -0.1)
addBus!(system; label = 2, reactive = 0.01, magnitude = 1.1)
@branch(minDiffAngle = -pi, maxDiffAngle = pi, reactance = 0.5, type = 2)
addBranch!(system; label = 1, from = 1, to = 2, longTerm = 0.15)
addBranch!(system; label = 1, from = 1, to = 2, maxFromBus = 0.15, maxToBus = 0.15)
@generator(maxActive = 0.5, minReactive = -0.1, maxReactive = 0.1)
addGenerator!(system; label = 1, bus = 1, active = 0.4, reactive = 0.2)
Expand Down Expand Up @@ -291,7 +291,7 @@ Specifically, `type = 1` is used for apparent power flow, `type = 2` for active
```
These rating constraints ensure that the power flow or current in each branch does not exceed the specified limits, helping to maintain the security and reliability of the power system. The upper bounds are determined based on the vector ``\mathbf{F}_{\text{max}} = [F_{ij}^\text{max}]``, ``(i,j) \in \mathcal{E}``. These bounds can be accessed using the following variable:
```@repl ACOptimalPowerFlow
𝐅ₘₐₓ = system.branch.flow.longTerm
𝐅ₘₐₓ = system.branch.flow.maxFromBus
```

By default, JuliaGrid employs the rating constraints linked with the apparent power flow (`type = 1`). This constraint at the from-bus is specified as:
Expand Down
8 changes: 4 additions & 4 deletions docs/src/tutorials/dcOptimalPowerFlow.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ addBus!(system; label = 2, type = 2, active = 0.1, conductance = 0.04)
addBus!(system; label = 3, type = 1, active = 0.05)
@branch(minDiffAngle = -pi, maxDiffAngle = pi)
addBranch!(system; label = 1, from = 1, to = 2, reactance = 0.05, longTerm = 0.15)
addBranch!(system; label = 2, from = 1, to = 3, reactance = 0.01, longTerm = 0.10)
addBranch!(system; label = 3, from = 2, to = 3, reactance = 0.01, longTerm = 0.25)
addBranch!(system; label = 1, from = 1, to = 2, reactance = 0.05, maxFromBus = 0.15)
addBranch!(system; label = 2, from = 1, to = 3, reactance = 0.01, maxFromBus = 0.10)
addBranch!(system; label = 3, from = 2, to = 3, reactance = 0.01, maxFromBus = 0.25)
@generator(minActive = 0.0)
addGenerator!(system; label = 1, bus = 1, active = 3.2, maxActive = 0.5)
Expand Down Expand Up @@ -229,7 +229,7 @@ The inequality constraint related to active power flow is used to represent ther
```
Here, the lower and upper bounds are determined based on the vector ``\mathbf{P}_{\text{max}} = [P_{ij}^\text{max}]``, ``(i,j) \in \mathcal{E}``. These bounds can be accessed using the following variable:
```@repl DCOptimalPowerFlow
𝐏ₘₐₓ = system.branch.flow.longTerm
𝐏ₘₐₓ = system.branch.flow.maxFromBus
```

The active power flow at branch ``(i,j) \in \mathcal{E}`` can be derived using the [Branch Network Equations](@ref DCBranchNetworkEquationsTutorials) and is given by:
Expand Down
Binary file modified src/data/case14.h5
Binary file not shown.
7 changes: 4 additions & 3 deletions src/definition/internal.jl
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,10 @@ Base.@kwdef mutable struct BranchTemplate
shiftAngle::ContainerTemplate = ContainerTemplate()
minDiffAngle::ContainerTemplate = ContainerTemplate(-2*pi, true)
maxDiffAngle::ContainerTemplate = ContainerTemplate(2*pi, true)
longTerm::ContainerTemplate = ContainerTemplate()
shortTerm::ContainerTemplate = ContainerTemplate()
emergency::ContainerTemplate = ContainerTemplate()
minFromBus::ContainerTemplate = ContainerTemplate()
maxFromBus::ContainerTemplate = ContainerTemplate()
minToBus::ContainerTemplate = ContainerTemplate()
maxToBus::ContainerTemplate = ContainerTemplate()
label::String = "?"
turnsRatio::Float64 = 1.0
status::Int8 = Int8(1)
Expand Down
7 changes: 4 additions & 3 deletions src/definition/system.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ mutable struct BranchParameter
end

mutable struct BranchFlow
longTerm::Array{Float64,1}
shortTerm::Array{Float64,1}
emergency::Array{Float64,1}
minFromBus::Array{Float64,1}
maxFromBus::Array{Float64,1}
minToBus::Array{Float64,1}
maxToBus::Array{Float64,1}
type::Array{Int8,1}
end

Expand Down
45 changes: 34 additions & 11 deletions src/optimalPowerFlow/acOptimalPowerFlow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,10 @@ function addFlow(system::PowerSystem, jump::JuMP.Model, magnitude::Vector{Variab
branch = system.branch
ac = system.model.ac

if branch.flow.longTerm[i] 0 && branch.flow.longTerm[i] < 10^16
fromBus = branch.flow.minFromBus[i] != 0.0 || branch.flow.maxFromBus[i] != 0.0
toBus = branch.flow.minToBus[i] != 0.0 || branch.flow.maxToBus[i] != 0.0

if fromBus || toBus
from = branch.layout.from[i]
to = branch.layout.to[i]

Expand All @@ -523,22 +526,42 @@ function addFlow(system::PowerSystem, jump::JuMP.Model, magnitude::Vector{Variab
Dji = βij * (gij * bsi - bij * gsi)

if branch.flow.type[i] == 1
refFrom[i] = @constraint(jump, 0 <= sqrt(Aij * Vi^4 + Bij * Vi^2 * Vj^2 - 2 * Vi^3 * Vj * (Cij * cosθ - Dij * sinθ)) <= branch.flow.longTerm[i])
refTo[i] = @constraint(jump, 0 <= sqrt(Aji * Vj^4 + Bij * Vi^2 * Vj^2 - 2 * Vi * Vj^3 * (Cji * cosθ + Dji * sinθ)) <= branch.flow.longTerm[i])
if fromBus
refFrom[i] = @constraint(jump, branch.flow.minFromBus[i] <= sqrt(Aij * Vi^4 + Bij * Vi^2 * Vj^2 - 2 * Vi^3 * Vj * (Cij * cosθ - Dij * sinθ)) <= branch.flow.maxFromBus[i])
end
if toBus
refTo[i] = @constraint(jump, branch.flow.minToBus[i] <= sqrt(Aji * Vj^4 + Bij * Vi^2 * Vj^2 - 2 * Vi * Vj^3 * (Cji * cosθ + Dji * sinθ)) <= branch.flow.maxToBus[i])
end
elseif branch.flow.type[i] == 3
refFrom[i] = @constraint(jump, 0 <= sqrt(Aij * Vi^2 + Bij * Vj^2 - 2 * Vi * Vj * (Cij * cosθ - Dij * sinθ)) <= branch.flow.longTerm[i])
refTo[i] = @constraint(jump, 0 <= sqrt(Aji * Vj^2 + Bij * Vi^2 - 2 * Vi * Vj * (Cji * cosθ + Dji * sinθ)) <= branch.flow.longTerm[i])
if fromBus
refFrom[i] = @constraint(jump, branch.flow.minFromBus[i] <= sqrt(Aij * Vi^2 + Bij * Vj^2 - 2 * Vi * Vj * (Cij * cosθ - Dij * sinθ)) <= branch.flow.maxFromBus[i])
end
if toBus
refTo[i] = @constraint(jump, branch.flow.minToBus[i] <= sqrt(Aji * Vj^2 + Bij * Vi^2 - 2 * Vi * Vj * (Cji * cosθ + Dji * sinθ)) <= branch.flow.maxToBus[i])
end
end
elseif branch.flow.type[i] == 2
if gij != 0 && bij != 0
refFrom[i] = @constraint(jump, -branch.flow.longTerm[i] <= βij^2 * (gij + gsi) * Vi^2 - βij * Vi * Vj * (gij * cosθ + bij * sinθ) <= branch.flow.longTerm[i])
refTo[i] = @constraint(jump, -branch.flow.longTerm[i] <= (gij + gsi) * Vj^2 - βij * Vi * Vj * (gij * cosθ - bij * sinθ) <= branch.flow.longTerm[i])
if fromBus
refFrom[i] = @constraint(jump, branch.flow.minFromBus[i] <= βij^2 * (gij + gsi) * Vi^2 - βij * Vi * Vj * (gij * cosθ + bij * sinθ) <= branch.flow.maxFromBus[i])
end
if toBus
refTo[i] = @constraint(jump, branch.flow.minToBus[i] <= (gij + gsi) * Vj^2 - βij * Vi * Vj * (gij * cosθ - bij * sinθ) <= branch.flow.maxToBus[i])
end
elseif gij != 0
refFrom[i] = @constraint(jump, -branch.flow.longTerm[i] <= βij^2 * (gij + gsi) * Vi^2 - βij * Vi * Vj * gij * cosθ <= branch.flow.longTerm[i])
refTo[i] = @constraint(jump, -branch.flow.longTerm[i] <= (gij + gsi) * Vj^2 - βij * Vi * Vj * gij * cosθ <= branch.flow.longTerm[i])
if fromBus
refFrom[i] = @constraint(jump, branch.flow.minFromBus[i] <= βij^2 * (gij + gsi) * Vi^2 - βij * Vi * Vj * gij * cosθ <= branch.flow.maxFromBus[i])
end
if toBus
refTo[i] = @constraint(jump, branch.flow.minToBus[i] <= (gij + gsi) * Vj^2 - βij * Vi * Vj * gij * cosθ <= branch.flow.maxToBus[i])
end
elseif bij != 0
refFrom[i] = @constraint(jump, -branch.flow.longTerm[i] <= βij^2 * (gij + gsi) * Vi^2 - βij * Vi * Vj * bij * sinθ <= branch.flow.longTerm[i])
refTo[i] = @constraint(jump, -branch.flow.longTerm[i] <= (gij + gsi) * Vj^2 + βij * Vi * Vj * bij * sinθ <= branch.flow.longTerm[i])
if fromBus
refFrom[i] = @constraint(jump, branch.flow.minFromBus[i] <= βij^2 * (gij + gsi) * Vi^2 - βij * Vi * Vj * bij * sinθ <= branch.flow.maxFromBus[i])
end
if toBus
refTo[i] = @constraint(jump, branch.flow.minToBus[i] <= (gij + gsi) * Vj^2 + βij * Vi * Vj * bij * sinθ <= branch.flow.maxToBus[i])
end
end
end
end
Expand Down
8 changes: 4 additions & 4 deletions src/optimalPowerFlow/dcOptimalPowerFlow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -223,11 +223,11 @@ function addBalance(system::PowerSystem, jump::JuMP.Model, active::Vector{Variab
end

######### Flow Constraints ##########
function addFlow(system::PowerSystem, jump::JuMP.Model, angle::Vector{VariableRef}, ref::Dict{Int64, ConstraintRef}, index::Int64)
function addFlow(system::PowerSystem, jump::JuMP.Model, angle::Vector{VariableRef}, ref::Dict{Int64, ConstraintRef}, i::Int64)
branch = system.branch
if branch.flow.longTerm[index] 0 && branch.flow.longTerm[index] < 10^16
restriction = branch.flow.longTerm[index] / system.model.dc.admittance[index]
ref[index] = @constraint(jump, - restriction + branch.parameter.shiftAngle[index] <= angle[branch.layout.from[index]] - angle[branch.layout.to[index]] <= restriction + branch.parameter.shiftAngle[index])

if branch.flow.minFromBus[i] != 0.0 || branch.flow.maxFromBus[i] != 0.0
ref[i] = @constraint(jump, branch.flow.minFromBus[i] <= system.model.dc.admittance[i] * (angle[branch.layout.from[i]] - angle[branch.layout.to[i]] - branch.parameter.shiftAngle[i]) <= branch.flow.maxFromBus[i])
end

return jump, ref
Expand Down
Loading

0 comments on commit 164273d

Please sign in to comment.