Sure! Here’s an adapted version of my code for the PTDF calculation:
using PowerModels
using AxisArrays
networkData = PowerModels.parse_file("/home/u0128861/.julia/packages/PowerModels/fEPoB/test/data/matpower/case30.m")
# Create vector of bus and branch names
# If no name / string given, use the index instead
BusNames = sort(
[get(v, "string", v["index"]) for (k,v) in networkData["bus"]]
)
BranchNames = sort(
[get(v, "name", v["index"]) for (k,v) in networkData["branch"]]
)
B_inv = PowerModels.calc_susceptance_matrix_inv(networkData)
PTDF = AxisArray(
zeros(
length(networkData["bus"]), length(networkData["branch"])
),
Axis{:Bus}(BusNames),
Axis{:Branch}(BranchNames),
)
# Dictionaries mapping bus / branch indices to their names
busIndices2Names = Dict(
v["index"] => get(v, "name", v["index"]) for (k,v) in networkData["bus"]
)
branchIndices2Names = Dict(
v["index"] => get(v, "name", v["index"]) for (k,v) in networkData["branch"]
)
# Compute PTDF matrix
for (b, branch) in networkData["branch"]
bus_fr = B_inv.bus_to_idx[branch["f_bus"]]
bus_to = B_inv.bus_to_idx[branch["t_bus"]]
b_val = imag(inv(branch["br_r"] + branch["br_x"]im))
branch_name = branchIndices2Names[branch["index"]]
for (k, bus) in networkData["bus"]
n = B_inv_bus_to_idx[bus["index"]]
bus_name = busIndices2Names[bus["index"]]
PTDF[bus_name, branch_name] = B_inv.matrix[bus_fr, n] - B_inv.matrix[bus_to, n]
end
end
I noticed you had defined a variable b_val
, but this is not used in the PTDF calculation you wrote - where does it go? (As you may have noticed by now, I am not an electrical engineer and I’m quite clueless about power flow…)
For that particular test case, the buses / branches didn’t have names, hence the get(v, "name", v["index"])
calls. I should probably also include checks that a) all buses / branches have names and if not b) that their indices go from 1:n.
Regarding point b), that because if you construct an AxisArray with an axis of integers, it will behave like a normal Array unless you pass the commant atvalue
when getting the index:
julia> A = AxisArray([1,2,3], Axis{:String}(["1","2","4"]))
1-dimensional AxisArray{Int64,1,...} with axes:
:String, ["1", "2", "4"]
And data, a 3-element Array{Int64,1}:
1
2
3
julia> A["4"]
3
julia> A = AxisArray([1,2,3], Axis{:Int}([1,2,4]))
1-dimensional AxisArray{Int64,1,...} with axes:
:Int, [1, 2, 4]
And data, a 3-element Array{Int64,1}:
1
2
3
julia> A[4]
ERROR: BoundsError: attempt to access 3-element Array{Int64,1} at index [4]
Stacktrace:
[1] getindex at ./array.jl:744 [inlined]
[2] getindex(::AxisArray{Int64,1,Array{Int64,1},Tuple{Axis{:Int,Array{Int64,1}}}}, ::Int64) at /home/u0128861/.julia/packages/AxisArrays/IFpjG/src/indexing.jl:39
[3] top-level scope at none:0
julia> A[atvalue(4)]
3