Skip to content

Commit

Permalink
Merge pull request #88 from ozgurcansakinci/master
Browse files Browse the repository at this point in the history
AC voltage droop implementation and testing for ACDC power flow
  • Loading branch information
hakanergun authored Apr 4, 2024
2 parents a0bef78 + c3e669b commit 877a90f
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 11 deletions.
7 changes: 7 additions & 0 deletions src/core/constraint_template.jl
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,13 @@ function constraint_dc_droop_control(pm::_PM.AbstractPowerModel, i::Int; nw::Int
constraint_dc_droop_control(pm, nw, i, conv["busdc_i"], conv["Vdcset"], conv["Pdcset"], conv["droop"])
end

function constraint_ac_voltage_droop_control(pm::_PM.AbstractPowerModel, i::Int; nw::Int=_PM.nw_id_default)
conv = _PM.ref(pm, nw, :convdc, i)
bus = _PM.ref(pm, nw, :bus, conv["busac_i"])
v_ref = conv["Vtar"]
constraint_ac_voltage_droop_control(pm, nw, i, bus["index"], v_ref, conv["Q_g"], conv["kq_droop"])
end

############## TNEP Constraints #####################
function constraint_voltage_dc_ne(pm::_PM.AbstractPowerModel; nw::Int=_PM.nw_id_default)
constraint_voltage_dc_ne(pm, nw)
Expand Down
6 changes: 6 additions & 0 deletions src/formconv/acp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,12 @@ function constraint_dc_droop_control(pm::_PM.AbstractACPModel, n::Int, i::Int, b
JuMP.@constraint(pm.model, pconv_dc == pref_dc - sign(pref_dc) * 1 / k_droop * (vdc - vref_dc))
end

function constraint_ac_voltage_droop_control(pm::_PM.AbstractACPModel, n::Int, i::Int, busac_i, v_ref, qref, kq_droop)
q_inj = _PM.var(pm, n, :qconv_tf_fr, i)
vac = _PM.var(pm, n, :vm, busac_i)
# Arranging the signs of reactive powers below
JuMP.@constraint(pm.model, q_inj == -qref - kq_droop * (v_ref - vac))
end

#################### TNEP Constraints #########################
"""
Expand Down
17 changes: 9 additions & 8 deletions src/prob/acdcpf.jl
Original file line number Diff line number Diff line change
Expand Up @@ -74,23 +74,24 @@ function build_acdcpf(pm::_PM.AbstractPowerModel)
constraint_conv_filter(pm, c)
if conv["type_dc"] == 2
constraint_dc_voltage_magnitude_setpoint(pm, c)
constraint_reactive_conv_setpoint(pm, c)
elseif conv["type_dc"] == 3
if typeof(pm) <: _PM.AbstractACPModel || typeof(pm) <: _PM.AbstractACRModel
constraint_dc_droop_control(pm, c)
constraint_reactive_conv_setpoint(pm, c)
else
Memento.warn(_PM._LOGGER, join(["Droop only defined for ACP and ACR formulations, converter ", c, " will be treated as type 2"]))
constraint_dc_voltage_magnitude_setpoint(pm, c)
constraint_reactive_conv_setpoint(pm, c)
end
else
if conv["type_ac"] == 2
constraint_active_conv_setpoint(pm, c)
else
constraint_active_conv_setpoint(pm, c)
constraint_reactive_conv_setpoint(pm, c)
constraint_active_conv_setpoint(pm, c)
end
if conv["type_ac"] == 2
if haskey(conv, "acq_droop") && conv["acq_droop"] == 1 # AC voltage droop control
constraint_ac_voltage_droop_control(pm, c)
else # Constant AC voltage control
_PM.constraint_voltage_magnitude_setpoint(pm, conv["busac_i"])
end
else
constraint_reactive_conv_setpoint(pm, c)
end
constraint_converter_losses(pm, c)
constraint_converter_current(pm, c)
Expand Down
60 changes: 60 additions & 0 deletions test/data/case4_acdroop.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
function mpc = case4acdroop()
% 4bus case to test the AC voltage control functionalities of HVDC converters

%% MATPOWER Case Format : Version 1
%%----- Power Flow Data -----%%
%% system MVA base
mpc.baseMVA = 1000;

%% bus data
% bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin
mpc.bus = [
1 3 0 0 0 0 1 1 0 380 1 1.1 0.9;
2 3 0 0 0 0 1 1 0 380 1 1.1 0.9;
3 2 0 0 0 0 1 1 0 380 1 1.1 0.9;
4 2 0 0 0 0 1 1 0 380 1 1.1 0.9;
];

%% generator data
% bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin pc1 pc2 qlcmin qlcmax qc2min qc2max ramp_agc ramp_10 ramp_30 ramp_q apf
mpc.gen = [
1 -600 0 400 -400 1 100 1 1000 -1000 0 0 0 0 0 0 0 0 0 0 0;
2 600 0 400 -400 1 100 1 1000 -1000 0 0 0 0 0 0 0 0 0 0 0;
];

%% branch data
% fbus tbus r x b rateA rateB rateC ratio angle status angmin angmax
mpc.branch = [
1 3 0.111803414E-01 0.758119137E-01 0.945984133E-02 250 250 250 0 0 1 -90 90;
2 4 0.401327479E-01 0.272541773 0.340797668E-01 250 250 250 0 0 1 -90 90;
];


%% dc grid topology
%colunm_names% dcpoles
mpc.dcpol=1;
% numbers of poles (1=monopolar grid, 2=bipolar grid)
%% bus data
%column_names% busdc_i grid Pdc Vdc basekVdc Vdcmax Vdcmin Cdc
mpc.busdc = [
1 1 -600 1 380 1.1 0.9 0;
2 1 600 1 380 1.1 0.9 0;
3 1 -600 1 380 1.1 0.9 0;
4 1 600 1 380 1.1 0.9 0;
];

%% converters
%column_names% busdc_i busac_i type_dc type_ac P_g Q_g islcc Vtar rtf xtf transformer tm bf filter rc xc reactor basekVac Vmmax Vmmin Imax status LossA LossB LossCrec LossCinv droop Pdcset Vdcset dVdcset Pacmax Pacmin Qacmax Qacmin acq_droop kq_droop Vtar
mpc.convdc = [
1 3 2 2 -600 100 0 1 0 0 0 1 0 0 0.0074 0.1849 1 380 1.1 0.9 11 1 0 0 0 0 0.0050 -58.6274 1.0079 0 250 -250 100 -100 1 20 1;
2 4 1 2 600 100 0 1 0 0 0 1 0 0 0.0074 0.1849 1 380 1.1 0.9 11 1 0 0 0 0 0.0070 21.9013 1.0000 0 250 -250 100 -100 0 0 1;
3 3 2 2 -600 -100 0 1 0 0 0 1 0 0 0.0074 0.1849 1 380 1.1 0.9 11 1 0 0 0 0 0.0050 -58.6274 1.0079 0 250 -250 100 -100 1 10 1;
4 4 1 1 600 100 0 1 0 0 0 1 0 0 0.0074 0.1849 1 380 1.1 0.9 11 1 0 0 0 0 0.0070 21.9013 1.0000 0 250 -250 100 -100 0 0 1;
];

%% branches
%column_names% fbusdc tbusdc r l c rateA rateB rateC status
mpc.branchdc = [
1 2 0.644767896E-02 0 0 250 250 250 1;
3 4 0.644767896E-02 0 0 250 250 250 1;
];
37 changes: 34 additions & 3 deletions test/pf.jl
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ s = Dict("output" => Dict("branch_flows" => true), "conv_losses_mp" => true)
@test isapprox(result["solution"]["bus"]["1"]["vm"], 1.06; atol = 2e-3)
@test isapprox(result["solution"]["bus"]["1"]["va"], 0.00000; atol = 2e-3)
@test isapprox(result["solution"]["bus"]["2"]["vm"], 1.00; atol = 2e-3)
@test isapprox(result["solution"]["bus"]["3"]["vm"], 0.995; atol = 2e-3)
@test isapprox(result["solution"]["bus"]["3"]["vm"], 1.00; atol = 2e-3)

@test isapprox(result["solution"]["busdc"]["1"]["vm"], 1.0079; atol = 1e-4)
@test isapprox(result["solution"]["busdc"]["2"]["vm"], 0.999987; atol = 1e-4)
Expand Down Expand Up @@ -110,8 +110,8 @@ end

@test isapprox(result["solution"]["bus"]["1"]["vr"], 1.06; atol = 2e-3)
@test isapprox(result["solution"]["bus"]["1"]["vi"], 0.00000; atol = 2e-3)
@test isapprox(result["solution"]["bus"]["2"]["vr"], 0.999108; atol = 2e-3)
@test isapprox(result["solution"]["bus"]["3"]["vr"], 0.993324; atol = 2e-3)
@test isapprox(result["solution"]["bus"]["2"]["vr"], 0.999108; atol = 1e-2)
@test isapprox(result["solution"]["bus"]["3"]["vr"], 0.993324; atol = 1e-2)

@test isapprox(result["solution"]["busdc"]["1"]["vm"], 1.0079; atol = 1e-4)
@test isapprox(result["solution"]["busdc"]["2"]["vm"], 0.999987; atol = 1e-4)
Expand Down Expand Up @@ -146,4 +146,35 @@ end
@test isapprox(result["solution"]["convdc"]["2"]["pgrid"], -0.753; atol = 2e-3)
@test isapprox(result["solution"]["convdc"]["3"]["pdc"], -1.39167; atol = 2e-3)
end
end

@testset "4-bus ac voltage droop case" begin
result = run_acdcpf("../test/data/case4_acdroop.m", ACPPowerModel, ipopt_solver; setting = s)

@test result["termination_status"] == LOCALLY_SOLVED
@test isapprox(result["objective"], 0; atol = 1e-2)

@test isapprox(result["solution"]["gen"]["1"]["pg"], 1.24; atol = 1e-2)
@test isapprox(result["solution"]["gen"]["2"]["pg"], -1.142; atol = 1e-2)
@test isapprox(result["solution"]["gen"]["1"]["qg"], -0.057; atol = 1e-2)
@test isapprox(result["solution"]["gen"]["2"]["qg"], 0.352; atol = 1e-2)

@test isapprox(result["solution"]["bus"]["1"]["vm"], 1.0; atol = 1e-2)
@test isapprox(result["solution"]["bus"]["1"]["va"], 0.00000; atol = 1e-2)
@test isapprox(result["solution"]["bus"]["2"]["vm"], 1.0; atol = 1e-2)
@test isapprox(result["solution"]["bus"]["2"]["va"], 0.00000; atol = 1e-2)
@test isapprox(result["solution"]["bus"]["3"]["vm"], 0.995; atol = 1e-2)
@test isapprox(result["solution"]["bus"]["3"]["va"], -0.095; atol = 1e-2)
@test isapprox(result["solution"]["bus"]["4"]["vm"], 1.0; atol = 1e-2)
@test isapprox(result["solution"]["bus"]["4"]["va"], 0.332; atol = 1e-2)

@test isapprox(result["solution"]["convdc"]["1"]["pgrid"], 0.6067; atol = 1e-2)
@test isapprox(result["solution"]["convdc"]["1"]["qgrid"], -0.2081; atol = 1e-2)
@test isapprox(result["solution"]["convdc"]["3"]["pgrid"], 0.6067; atol = 1e-2)
@test isapprox(result["solution"]["convdc"]["3"]["qgrid"], 0.0459; atol = 1e-2)
@test isapprox(result["solution"]["convdc"]["2"]["pgrid"], -0.6; atol = 1e-2)
@test isapprox(result["solution"]["convdc"]["2"]["qgrid"], 0.0932; atol = 1e-2)
@test isapprox(result["solution"]["convdc"]["4"]["pgrid"], -0.6; atol = 1e-2)
@test isapprox(result["solution"]["convdc"]["4"]["qgrid"], -0.1; atol = 1e-2)

end
12 changes: 12 additions & 0 deletions test/scripts/ACdrooptest.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using PowerModels, JuMP, Ipopt

casename = "case4_acdroop"

file = "./test/data/$casename.m"
data = PowerModels.parse_file(file)
PowerModelsACDC.process_additional_data!(data)

ipopt = JuMP.optimizer_with_attributes(Ipopt.Optimizer, "tol" => 1e-6, "print_level" => 0)
s = Dict("output" => Dict("branch_flows" => true), "conv_losses_mp" => false)
result = run_acdcpf(data, ACPPowerModel, ipopt; setting = s)
println(result["termination_status"])

3 comments on commit 877a90f

@hakanergun
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@hakanergun
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

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

Registration pull request created: JuliaRegistries/General/104290

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.7.1 -m "<description of version>" 877a90f1d64eead52d9d75fecc6363e9ea1602f3
git push origin v0.7.1

Please sign in to comment.