Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

afc/ward decomposition for embedded HVDC #64

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/PowerNetworkMatrices.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export to_hdf5
export validate_connectivity
export VirtualLODF
export VirtualPTDF
export Ward_data
export Ybus

using DocStringExtensions
Expand Down Expand Up @@ -58,5 +59,6 @@ include("lodf_calculations.jl")
include("virtual_lodf_calculations.jl")
include("system_utils.jl")
include("serialization.jl")
include("ward_calculations.jl")

end
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
end
end

49 changes: 49 additions & 0 deletions src/ward_calculations.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"""
structure and functions for power systems analysis based on Ward's decomposition
"""

"""
Data related to the considered Ward decomposition is here stored.
Given the set of buses under study, the original Ybus can be divided into
sub matrices belongin to study (S) and external (E) buses.
|Y_ss Y_se|
Ybus = | |
|Y_es Y_ee|

# Arguments
- `A::Matrix{ComplexF64}`:
the product of Y_se * inv(Y_ee) * Y_es
- `B::Matrix{ComplexF64}`:
the transposed product of Y_se * inv(Y_ee)
- `study_buses::Vector{Int64}`:
vector of the study buses (all other buses will be aggregated according
to the Ward's decomposition)
"""
struct Ward_data
A::Matrix{ComplexF64}
B::Matrix{ComplexF64}
study_buses::Vector{Int64}
end

function Ward_data(
ybus::Ybus{Tuple{Vector{Int64}, Vector{Int64}}, Tuple{Dict{Int64, Int64}, Dict{Int64, Int64}}},
study_buses::Vector{Int64}
Comment on lines +29 to +30
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
ybus::Ybus{Tuple{Vector{Int64}, Vector{Int64}}, Tuple{Dict{Int64, Int64}, Dict{Int64, Int64}}},
study_buses::Vector{Int64}
ybus::Ybus{
Tuple{Vector{Int64}, Vector{Int64}},
Tuple{Dict{Int64, Int64}, Dict{Int64, Int64}},
},
study_buses::Vector{Int64},

)
# get the indeces of the study and external buses
select_x = [ybus.lookup[1][i] for i in study_buses];
select_y = [ybus.lookup[2][i] for i in study_buses];
unselect_x = [ybus.lookup[1][i] for i in keys(ybus.lookup[1]) if i ∉ study_buses];
unselect_y = [ybus.lookup[2][i] for i in keys(ybus.lookup[1]) if i ∉ study_buses];
Comment on lines +33 to +36
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
select_x = [ybus.lookup[1][i] for i in study_buses];
select_y = [ybus.lookup[2][i] for i in study_buses];
unselect_x = [ybus.lookup[1][i] for i in keys(ybus.lookup[1]) if i study_buses];
unselect_y = [ybus.lookup[2][i] for i in keys(ybus.lookup[1]) if i study_buses];
select_x = [ybus.lookup[1][i] for i in study_buses]
select_y = [ybus.lookup[2][i] for i in study_buses]
unselect_x = [ybus.lookup[1][i] for i in keys(ybus.lookup[1]) if i study_buses]
unselect_y = [ybus.lookup[2][i] for i in keys(ybus.lookup[1]) if i study_buses]

# first reorder the Ybus to get the intermediate sub matrices
Y_se = ybus.data[select_x, unselect_y];
Y_es = ybus.data[unselect_x, select_y];
Y_ee = ybus.data[unselect_x, unselect_y];
Comment on lines +38 to +40
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
Y_se = ybus.data[select_x, unselect_y];
Y_es = ybus.data[unselect_x, select_y];
Y_ee = ybus.data[unselect_x, unselect_y];
Y_se = ybus.data[select_x, unselect_y]
Y_es = ybus.data[unselect_x, select_y]
Y_ee = ybus.data[unselect_x, unselect_y]

# get the matrices
A = -Y_se*KLU.solve!(KLU.klu(Y_ee), Matrix(Y_es));
B = KLU.solve!(KLU.klu(Y_ee), Matrix(transpose(Y_se)));
Comment on lines +42 to +43
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
A = -Y_se*KLU.solve!(KLU.klu(Y_ee), Matrix(Y_es));
B = KLU.solve!(KLU.klu(Y_ee), Matrix(transpose(Y_se)));
A = -Y_se * KLU.solve!(KLU.klu(Y_ee), Matrix(Y_es))
B = KLU.solve!(KLU.klu(Y_ee), Matrix(transpose(Y_se)))

return Ward_data(
A,
B,
study_buses
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
study_buses
study_buses,

)
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
end
end

66 changes: 66 additions & 0 deletions test/try_YBus_inversion.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using Revise
using Test
import Logging
import LinearAlgebra: I
using PowerNetworkMatrices
using PowerSystems
using InfrastructureSystems
using PowerSystemCaseBuilder
using TimeSeries
using KLU
using SparseArrays
using PowerFlows

const IS = InfrastructureSystems
const PSY = PowerSystems
const PSB = PowerSystemCaseBuilder
const PNM = PowerNetworkMatrices

# ============================================================================
# ============================================================================

# try the code with a RTS system
sys = PSB.build_system(PSB.PSISystems, "RTS_GMLC_DA_sys");

# get network matrices
a_mat = PNM.IncidenceMatrix(sys)
ba_mat = PNM.BA_Matrix(sys)
ptdf_mat = PNM.PTDF(sys)

# get the 2T HVDC data, then the buses connecting
hvdc_line = PSY.get_component(PSY.TwoTerminalHVDCLine, sys, "DC1");
study_buses = [
PSY.get_from(PSY.get_arc(hvdc_line)),
PSY.get_to(PSY.get_arc(hvdc_line))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change
PSY.get_to(PSY.get_arc(hvdc_line))
PSY.get_to(PSY.get_arc(hvdc_line)),

]

# get all other buses
other_buses = PSY.get_components(x -> !(x in study_buses), PSY.ACBus, sys)

# get flows and angles
data = PowerFlowData(DCPowerFlow(), sys)
power_injection =
deepcopy(data.bus_activepower_injection - data.bus_activepower_withdrawals)
matrix_data = deepcopy(data.power_network_matrix.K) # LU factorization of ABA
aux_network_matrix = deepcopy(data.aux_network_matrix) # BA matrix

valid_ix = setdiff(1:length(power_injection), data.aux_network_matrix.ref_bus_positions)
ref_bus_angles = deepcopy(data.bus_angles)
ref_flow_values = deepcopy(data.branch_flow_values)

ref_bus_angles[valid_ix] = matrix_data \ power_injection[valid_ix]
ref_flow_values = transpose(aux_network_matrix.data) * ref_bus_angles

# get the angles from the PSY data
thetas = zeros((length(ba_mat.axes[1]),))
for b in PSY.get_components(PSY.ACBus, sys)
idx = ba_mat.lookup[1][PSY.get_number(b)]
thetas[idx] = PSY.get_angle(b)
end

# ! angles are different after computation


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[JuliaFormatter] reported by reviewdog 🐶

Suggested change

# now evaluate the Ward decomposition
ybus = PNM.Ybus(sys)
ward_data = Ward_data(ybus, PSY.get_number.(study_buses))
Loading