Skip to content

Commit

Permalink
Merge pull request #47 from NREL-Sienna/fixing_distributed_slack
Browse files Browse the repository at this point in the history
Fixing bug on PTDF calculation with distributed slack
  • Loading branch information
jd-lara authored Aug 2, 2023
2 parents 82c5591 + 4841224 commit 79a1694
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 24 deletions.
2 changes: 1 addition & 1 deletion src/common.jl
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ function make_entries_zero!(vector::Vector{Float64}, tol::Float64)
vector[i] = 0.0
end
end
return vector
return
end

"""
Expand Down
36 changes: 23 additions & 13 deletions src/ptdf_calculations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ function _calculate_PTDF_matrix_KLU(
# inizialize matrices for evaluation
valid_ix = setdiff(1:buscount, ref_bus_positions)
PTDFm_t = zeros(buscount, linecount)

if !isempty(dist_slack) && length(ref_bus_positions) != 1
error(
"Distibuted slack is not supported for systems with multiple reference buses.",
Expand All @@ -153,13 +154,15 @@ function _calculate_PTDF_matrix_KLU(
@info "Distributed bus"
copyto!(PTDFm_t, BA)
PTDFm_t[valid_ix, :] = KLU.solve!(K, PTDFm_t[valid_ix, :])
PTDFm_t[ref_bus_positions, :] .= 0.0
PTDFm_t[collect(ref_bus_positions), :] .= 0.0
slack_array = dist_slack / sum(dist_slack)
slack_array = reshape(slack_array, 1, buscount)
return PTDFm_t - (PTDFm_t * slack_array) * ones(1, buscount)
return PTDFm_t - ones(buscount, 1) * (slack_array * PTDFm_t)
else
error("Distributed bus specification doesn't match the number of buses.")
end

return
end

"""
Expand Down Expand Up @@ -246,15 +249,21 @@ function _calculate_PTDF_matrix_DENSE(
return PTDFm_t
elseif length(dist_slack) == buscount
@info "Distributed bus"
PTDFm_t[valid_ixs, :] = gemm(
'N',
'N',
getri!(ABA, bipiv),
BA[valid_ixs, :],
)
slack_array = dist_slack / sum(dist_slack)
slack_array = reshape(slack_array, buscount, 1)
slack_array = reshape(slack_array, 1, buscount)
return PTDFm_t -
gemm('N', 'N', gemm('N', 'N', PTDFm, slack_array), ones(1, buscount))
gemm('N', 'N', ones(buscount, 1), gemm('N', 'N', slack_array, PTDFm_t))
else
error("Distributed bus specification doesn't match the number of buses.")
end

return PTDFm_t
return
end

"""
Expand Down Expand Up @@ -316,28 +325,29 @@ function _calculate_PTDF_matrix_MKLPardiso(
ps = Pardiso.MKLPardisoSolver()
Pardiso.set_iparm!(ps, 59, 2)
Pardiso.set_msglvl!(ps, Pardiso.MESSAGE_LEVEL_ON)

Pardiso.solve!(ps, ABA_inv, ABA, Ix)
# inizialize matrices for evaluation
valid_ix = setdiff(1:buscount, ref_bus_positions)
PTDFm_t = zeros(buscount, linecount)
row_idx = setdiff(1:size(PTDFm_t, 1), ref_bus_positions)

if !isempty(dist_slack) && length(ref_bus_positions) != 1
error(
"Distibuted slack is not supported for systems with multiple reference buses.",
)
elseif isempty(dist_slack) && length(ref_bus_positions) < buscount
PTDFm_t[row_idx, :] = ABA_inv * @view BA[row_idx, :]
elseif isempty(dist_slack) && length(ref_bus_positions) != buscount
PTDFm_t[valid_ix, :] = ABA_inv * @view BA[valid_ix, :]
return PTDFm_t
elseif length(dist_slack) == buscount
@info "Distributed bus"
PTDFm_t[row_idx, :] = ABA_inv * @view BA[row_idx, :]
PTDFm_t[valid_ix, :] = ABA_inv * @view BA[valid_ix, :]
slack_array = dist_slack / sum(dist_slack)
slack_array = reshape(slack_array, buscount, 1)
PTDFm_t = PTDFm_t - (PTDFm_t * slack_array) * ones(1, buscount)
slack_array = reshape(slack_array, 1, buscount)
return PTDFm_t - ones(buscount, 1) * (slack_array * PTDFm_t)
else
error("Distributed bus specification doesn't match the number of buses.")
end

return PTDFm_t
return
end

"""
Expand Down
5 changes: 2 additions & 3 deletions src/virtual_lodf_calculations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -242,10 +242,9 @@ function _getindex(
lodf_row[row] = -1.0
# add slack bus value (zero) and make copy of temp into the cache
if get_tol(vlodf) > eps()
vlodf.cache[row] = make_entries_zero!(deepcopy(lodf_row), get_tol(vlodf))
else
vlodf.cache[row] = deepcopy(lodf_row)
make_entries_zero!(lodf_row, get_tol(vlodf))
end
vlodf.cache[row] = deepcopy(lodf_row)
return vlodf.cache[row][column]
end
end
Expand Down
33 changes: 26 additions & 7 deletions src/virtual_ptdf_calculations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ function VirtualPTDF(
tol::Float64 = eps(),
max_cache_size::Int = MAX_CACHE_SIZE_MiB,
persistent_lines::Vector{String} = String[])
if length(dist_slack) != 0
@info "Distributed bus"
end

#Get axis names
line_ax = [PSY.get_name(branch) for branch in branches]
Expand Down Expand Up @@ -171,19 +174,35 @@ function _getindex(
# Needs improvement
valid_ix = vptdf.valid_ix
lin_solve = KLU.solve!(vptdf.K, Vector(vptdf.BA[valid_ix, row]))
buscount = size(vptdf, 1)

# ! missing dist_slack case

for i in eachindex(valid_ix)
vptdf.temp_data[valid_ix[i]] = lin_solve[i]
if !isempty(vptdf.dist_slack) && length(vptdf.ref_bus_positions) != 1
error(
"Distibuted slack is not supported for systems with multiple reference buses.",
)
elseif isempty(vptdf.dist_slack) && length(vptdf.ref_bus_positions) < buscount
for i in eachindex(valid_ix)
vptdf.temp_data[valid_ix[i]] = lin_solve[i]
end
vptdf.cache[row] = deepcopy(vptdf.temp_data)
elseif length(vptdf.dist_slack) == buscount
for i in eachindex(valid_ix)
vptdf.temp_data[valid_ix[i]] = lin_solve[i]
end
slack_array = vptdf.dist_slack / sum(vptdf.dist_slack)
slack_array = reshape(slack_array, buscount)
vptdf.cache[row] =
deepcopy(vptdf.temp_data .- dot(vptdf.temp_data, slack_array))
else
error("Distributed bus specification doesn't match the number of buses.")
end

# add slack bus value (zero) and make copy of temp into the cache
if get_tol(vptdf) > eps()
vptdf.cache[row] = make_entries_zero!(deepcopy(vptdf.temp_data), get_tol(vptdf))
else
vptdf.cache[row] = deepcopy(vptdf.temp_data)
# vptdf.cache[row] = make_entries_zero!(deepcopy(vptdf.temp_data), get_tol(vptdf))
make_entries_zero!(vptdf.cache[row], get_tol(vptdf))
end

return vptdf.cache[row][column]
end
end
Expand Down
17 changes: 17 additions & 0 deletions test/test_ptdf.jl
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,20 @@ end
# Test Throw error when isolated buses are connected to an available branch
@test_throws IS.ConflictingInputsError ptdf_2 = PTDF(sys_2)
end

@testset "PTDF matrices with distributed slack" begin
sys5 = PSB.build_system(PSB.PSITestSystems, "c_sys5")

buscount = length(PNM.get_buses(sys5))

dist_slack = 1 / buscount * ones(buscount)
slack_array = dist_slack / sum(dist_slack)

P5_1 = PTDF(sys5; dist_slack = slack_array, linear_solver = "KLU")
P5_2 = PTDF(sys5; dist_slack = slack_array, linear_solver = "Dense")
P5_3 = PTDF(sys5; dist_slack = slack_array, linear_solver = "MKLPardiso")

@assert isapprox(P5_1.data, P5_2.data, atol = 1e-5)
@assert isapprox(P5_1.data, P5_3.data, atol = 1e-5)
@assert isapprox(P5_2.data, P5_3.data, atol = 1e-5)
end
16 changes: 16 additions & 0 deletions test/test_virtual_ptdf.jl
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,19 @@ end
@test vptdf.lookup[1][l] keys(vptdf.cache.temp_cache)
end
end

@testset "Test virtual PTDF with distributed slack" begin
# get 5 bus system
sys = PSB.build_system(PSB.PSITestSystems, "c_sys5")
bus_number = length(PNM.get_buses(sys))
dist_slack = 1 / bus_number * ones(bus_number)
# compute full PTDF
ptdf = PTDF(sys; dist_slack = dist_slack)
# compute each row of the virtual PTDF and compare values
vptdf = VirtualPTDF(sys; dist_slack = dist_slack)
for row in 1:size(ptdf.data, 2)
# evaluate the column (just needs one element)
vptdf[row, 1]
@assert isapprox(vptdf.cache[row], ptdf[row, :], atol = 1e-5)
end
end

0 comments on commit 79a1694

Please sign in to comment.