Skip to content

Commit

Permalink
fixes Add solve_powerflow! for AC power flow #49
Browse files Browse the repository at this point in the history
  • Loading branch information
Roman Bolgaryn committed Jan 9, 2025
1 parent d688b58 commit 11d86a1
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 51 deletions.
2 changes: 1 addition & 1 deletion src/PowerFlows.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module PowerFlows

export solve_powerflow
export solve_ac_powerflow!
export solve_powerflow!
export PowerFlowData
export DCPowerFlow
export NLSolveACPowerFlow
Expand Down
96 changes: 59 additions & 37 deletions src/newton_ac_powerflow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,32 +30,34 @@ solve_ac_powerflow!(sys)
solve_ac_powerflow!(sys, method=:newton)
```
"""
function solve_ac_powerflow!(
function solve_powerflow!(
pf::ACPowerFlow{<:ACPowerFlowSolverType},
system::PSY.System;
kwargs...,
kwargs...
)
#Save per-unit flag
settings_unit_cache = deepcopy(system.units_settings.unit_system)
#Work in System per unit
PSY.set_units_base_system!(system, "SYSTEM_BASE")
check_reactive_power_limits = get(kwargs, :check_reactive_power_limits, false)

data = PowerFlowData(
pf,
system;
check_connectivity = get(kwargs, :check_connectivity, true),
)
max_iterations = DEFAULT_MAX_REDISTRIBUTION_ITERATIONS
converged, x = _solve_powerflow!(pf, data, check_reactive_power_limits; kwargs...)

converged, x = _ac_powereflow(data, pf, system; kwargs...)

if converged
write_powerflow_solution!(system, x, max_iterations)
write_powerflow_solution!(system, x, get(kwargs, :maxIter, DEFAULT_NR_MAX_ITER))
@info("PowerFlow solve converged, the results have been stored in the system")
#Restore original per unit base
PSY.set_units_base_system!(system, settings_unit_cache)
return converged
else
@error("The powerflow solver returned convergence = $(converged)")
end
@error("The powerflow solver returned convergence = $(converged)")

#Restore original per unit base
PSY.set_units_base_system!(system, settings_unit_cache)

return converged
end

Expand All @@ -74,33 +76,57 @@ res = solve_powerflow(sys, method=:newton)
function solve_powerflow(
pf::ACPowerFlow{<:ACPowerFlowSolverType},
system::PSY.System;
kwargs...,
kwargs...
)
#Save per-unit flag
settings_unit_cache = deepcopy(system.units_settings.unit_system)
#Work in System per unit
PSY.set_units_base_system!(system, "SYSTEM_BASE")

data = PowerFlowData(
pf,
system;
check_connectivity = get(kwargs, :check_connectivity, true),
)
# @error(typeof(data))

converged, x = _solve_powerflow!(pf, data, pf.check_reactive_power_limits; kwargs...)

converged, x = _ac_powereflow(data, pf, system; kwargs...)
if converged
@info("PowerFlow solve converged, the results are exported in DataFrames")
df_results = write_results(pf, system, data, x)
#Restore original per unit base
PSY.set_units_base_system!(system, settings_unit_cache)
return df_results
else
df_results = missing
@error("The powerflow solver returned convergence = $(converged)")
end
@error("The powerflow solver returned convergence = $(converged)")

#Restore original per unit base
PSY.set_units_base_system!(system, settings_unit_cache)
return converged

return df_results
end

function _check_q_limit_bounds!(data::ACPowerFlowData, zero::Vector{Float64})

function _ac_powereflow(
data::PowerFlowData,
pf::ACPowerFlow{<:ACPowerFlowSolverType},
system::PSY.System;
kwargs...
)
check_reactive_power_limits = get(kwargs, :check_reactive_power_limits, false)

for _ in 1:MAX_REACTIVE_POWER_ITERATIONS
converged, x = _newton_powerflow(pf, data; kwargs...)
if !converged || !check_reactive_power_limits || _check_q_limit_bounds!(data, x)
return converged, x
end
end

@error("could not enforce reactive power limits after $MAX_REACTIVE_POWER_ITERATIONS")
return converged, x
end

function _check_q_limit_bounds!(data::PowerFlowData, zero::Vector{Float64})
bus_names = data.power_network_matrix.axes[1]
within_limits = true
for (ix, b) in enumerate(data.bus_type)
Expand Down Expand Up @@ -133,20 +159,16 @@ function _solve_powerflow!(
check_reactive_power_limits;
nlsolve_kwargs...,
)
if check_reactive_power_limits
for _ in 1:MAX_REACTIVE_POWER_ITERATIONS
converged, x = _newton_powerflow(pf, data; nlsolve_kwargs...)
if converged
if _check_q_limit_bounds!(data, x)
return converged, x
end
else
return converged, x
end

for _ in 1:MAX_REACTIVE_POWER_ITERATIONS
converged, x = _newton_powerflow(pf, data; nlsolve_kwargs...)
if !converged || !check_reactive_power_limits || _check_q_limit_bounds!(data, x)
return converged, x
end
else
return _newton_powerflow(pf, data; nlsolve_kwargs...)
end
# todo: throw error? set converged to false?
@error("could not enforce reactive power limits after $MAX_REACTIVE_POWER_ITERATIONS")
return converged, x
end

function _newton_powerflow(
Expand Down Expand Up @@ -389,11 +411,11 @@ end
function _newton_powerflow(
pf::ACPowerFlow{KLUACPowerFlow},
data::ACPowerFlowData;
nlsolve_kwargs...,
kwargs...,
)
# Fetch maxIter and tol from kwargs, or use defaults if not provided
maxIter = get(nlsolve_kwargs, :maxIter, DEFAULT_NR_MAX_ITER)
tol = get(nlsolve_kwargs, :tol, DEFAULT_NR_TOL)
maxIter = get(kwargs, :maxIter, DEFAULT_NR_MAX_ITER)
tol = get(kwargs, :tol, DEFAULT_NR_TOL)
i = 0

Ybus = data.power_network_matrix.data
Expand Down Expand Up @@ -568,11 +590,11 @@ end
function _newton_powerflow(
pf::ACPowerFlow{LUACPowerFlow},
data::ACPowerFlowData;
nlsolve_kwargs...,
kwargs...,
)
# Fetch maxIter and tol from kwargs, or use defaults if not provided
maxIter = get(nlsolve_kwargs, :maxIter, DEFAULT_NR_MAX_ITER)
tol = get(nlsolve_kwargs, :tol, DEFAULT_NR_TOL)
maxIter = get(kwargs, :maxIter, DEFAULT_NR_MAX_ITER)
tol = get(kwargs, :tol, DEFAULT_NR_TOL)
i = 0

Ybus = data.power_network_matrix.data
Expand Down
22 changes: 11 additions & 11 deletions test/test_newton_ac_powerflow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
#Compare results between finite diff methods and Jacobian method
converged1, x1 = PowerFlows._solve_powerflow!(pf, data, false)
@test LinearAlgebra.norm(result_14 - x1, Inf) <= 1e-6
@test solve_ac_powerflow!(pf, sys; method = :newton)
@test solve_powerflow!(pf, sys; method = :newton)

# Test enforcing the reactive power Limits
set_reactive_power!(get_component(PowerLoad, sys, "Bus4"), 0.0)
Expand All @@ -63,15 +63,15 @@ end
branch = first(PSY.get_components(Line, sys))
dyn_branch = DynamicBranch(branch)
add_component!(sys, dyn_branch)
@test dyn_pf = solve_ac_powerflow!(pf, sys)
@test dyn_pf = solve_powerflow!(pf, sys)
dyn_pf = solve_powerflow(pf, sys)
@test LinearAlgebra.norm(dyn_pf["bus_results"].Vm - base_res["bus_results"].Vm, Inf) <=
1e-6

sys = PSB.build_system(PSB.PSITestSystems, "c_sys14"; add_forecasts = false)
line = get_component(Line, sys, "Line4")
PSY.set_available!(line, false)
solve_ac_powerflow!(pf, sys)
solve_powerflow!(pf, sys)
@test PSY.get_active_power_flow(line) == 0.0
test_bus = get_component(PSY.Bus, sys, "Bus 4")
@test isapprox(PSY.get_magnitude(test_bus), 1.002; atol = 1e-3, rtol = 0)
Expand Down Expand Up @@ -119,7 +119,7 @@ end
@test_logs(
(:error, "The powerflow solver returned convergence = false"),
match_mode = :any,
@test !solve_ac_powerflow!(pf, pf_sys5_re)
@test !solve_powerflow!(pf, pf_sys5_re)
)
end

Expand All @@ -145,7 +145,7 @@ end

pf = ACPowerFlow{ACSolver}()

pf1 = solve_ac_powerflow!(pf, system)
pf1 = solve_powerflow!(pf, system)
@test pf1
pf_result_df = solve_powerflow(pf, system)

Expand Down Expand Up @@ -203,13 +203,13 @@ end
)
add_component!(sys, s2)
pf = ACPowerFlow{ACSolver}()
@test solve_ac_powerflow!(pf, sys)
@test solve_powerflow!(pf, sys)

#Create power mismatch, test for error
set_active_power!(get_component(Source, sys, "source_1"), -0.4)
@test_throws ErrorException(
"Sources do not match P and/or Q requirements for reference bus.",
) solve_ac_powerflow!(pf, sys)
) solve_powerflow!(pf, sys)
end

@testset "AC PowerFlow with Multiple sources at PV" for ACSolver in
Expand Down Expand Up @@ -289,11 +289,11 @@ end

pf = ACPowerFlow{ACSolver}()

@test solve_ac_powerflow!(pf, sys)
@test solve_powerflow!(pf, sys)

#Create power mismatch, test for error
set_reactive_power!(get_component(Source, sys, "source_3"), -0.5)
@test_throws ErrorException("Sources do not match Q requirements for PV bus.") solve_ac_powerflow!(
@test_throws ErrorException("Sources do not match Q requirements for PV bus.") solve_powerflow!(
pf,
sys,
)
Expand Down Expand Up @@ -352,7 +352,7 @@ end

pf = ACPowerFlow{ACSolver}()

@test solve_ac_powerflow!(pf, sys)
@test solve_powerflow!(pf, sys)
@test isapprox(
get_active_power(get_component(Source, sys, "source_1")),
0.5;
Expand Down Expand Up @@ -453,7 +453,7 @@ end

pf = ACPowerFlow{ACSolver}()

@test solve_ac_powerflow!(pf, sys)
@test solve_powerflow!(pf, sys)
@test isapprox(
get_active_power(get_component(Source, sys, "source_2")),
0.5;
Expand Down
4 changes: 2 additions & 2 deletions test/test_utils/psse_results_compare.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ function psse_bus_results_compare(file_name::String, pf_results::Dict)
return v_diff, angle_diff, number
end

function psse_bus_results_compare(file_name::String, pf_results::Bool)
throw(ArgumentError("pf_results not available - calculation failed"))
function psse_bus_results_compare(file_name::String, pf_results::Missing)
throw(ArgumentError("pf_results are missing - calculation failed"))
end

function psse_gen_results_compare(file_name, system::PSY.System)
Expand Down

0 comments on commit 11d86a1

Please sign in to comment.