Skip to content

Commit

Permalink
inverter test models added and phases added to components
Browse files Browse the repository at this point in the history
  • Loading branch information
jtabarez committed Jun 13, 2024
1 parent da27eff commit 4e3f030
Show file tree
Hide file tree
Showing 11 changed files with 288 additions and 125 deletions.
2 changes: 1 addition & 1 deletion src/PowerModelsProtection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ module PowerModelsProtection
const _SP = SparseArrays
import JSON

include("core/types.jl")
include("core/admittance_matrix.jl")
include("core/variable.jl")
include("core/constraint_template.jl")
Expand All @@ -26,7 +27,6 @@ module PowerModelsProtection
include("core/expression.jl")
include("core/ref.jl")
include("core/objective.jl")
include("core/types.jl")
include("core/solution.jl")

include("data_model/units.jl")
Expand Down
225 changes: 154 additions & 71 deletions src/core/admittance_matrix.jl

Large diffs are not rendered by default.

50 changes: 50 additions & 0 deletions src/core/data.jl
Original file line number Diff line number Diff line change
Expand Up @@ -473,3 +473,53 @@ function calc_line_paramters!(line::Dict{String,<:Any}, data_dss::Dict{String,<:
nothing
end
end


function add_pre_fault!(pre_v, model::AdmittanceModel)
add_pre_fault_bus_voltage!(pre_v, model)
add_pre_fault_gfli_current!(pre_v, model)
end


function add_pre_fault_bus_voltage!(pre_v, model::AdmittanceModel)
for (_, bus) in model.data["bus"]
_v = zeros(Complex{Float64}, 1, length(bus["terminals"]))
for (i, j) in enumerate(bus["terminals"])
if haskey(model.data["admittance_map"], (bus["bus_i"], j))
_v[1, i] = pre_v[model.data["admittance_map"][(bus["bus_i"], j)], 1]
end
end
bus["pre_fault"] = _v
end
end

function add_pre_fault_gfli_current!(pre_v, model::AdmittanceModel)
for (_, gen) in model.data["gen"]
if gen["element"] == SolarElement
transformer = model.data["transformer"][gen["transformer_id"]]
if gen["phases"] == 3
f_bus = transformer["f_bus"]
t_bus = transformer["t_bus"]
y = transformer["p_matrix"]
n = size(y)[1]
_v = zeros(Complex{Float64}, n, 1)
for (i, j) in enumerate(transformer["f_connections"])
if haskey(model.data["admittance_map"], (f_bus, j))
_v[i, 1] = pre_v[model.data["admittance_map"][(f_bus, j)], 1]
else
_v[i, 1] = 0.0 + 0.0im
end
end
for (i, j) in enumerate(transformer["t_connections"])
if haskey(model.data["admittance_map"], (t_bus, j))
_v[i+length(transformer["t_connections"]), 1] = pre_v[model.data["admittance_map"][(t_bus, j)], 1]
else
_v[i+length(transformer["t_connections"]), 1] = 0.0 + 0.0im
end
end
_i = y * _v
gen["pre_fault"] = _i
end
end
end
end
6 changes: 5 additions & 1 deletion src/core/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ struct AdmittanceModel
delta_i::Matrix{Complex{Float64}}
end

@enum ResponseCharateristic ConstantPQ ConstantZ ConstantI ConstantZIP ConstantPAtPF ConstantPV ConstantPFixedQ ConstantPXFixedQ ConstantPQCurrentLimited
@enum ResponseCharateristic ConstantPQ ConstantZ ConstantI ConstantZIP ConstantPAtPF ConstantPV ConstantPFixedQ ConstantPXFixedQ ConstantPQCurrentLimited ConstantV ConstantVCurrentLimited

@enum Element VoltageSourceElement CurrentSourceElement LoadElement Transformer2WElement Transformer3WElement TransformerCenterTapElement SolarElement GeneratorElement

@enum Standard IEEE2800



Expand Down
21 changes: 15 additions & 6 deletions src/data_model/components.jl
Original file line number Diff line number Diff line change
Expand Up @@ -382,15 +382,21 @@ end
function _map_eng2math_mc_admittance_solar!(data_math::Dict{String,<:Any}, data_eng::Dict{String,<:Any}; pass_props::Vector{String}=String[])
if haskey(data_math, "gen")
for (name, gen) in data_math["gen"]
if occursin("solar", gen["source_id"])
if gen["element"] == SolarElement
n = length(gen["connections"])
y = zeros(n, n)
y = zeros(Complex{Float64}, n, n)
if gen["configuration"] == _PMD.WYE
for (i, connection) in enumerate(gen["connections"])
j = findall(x->x==4, gen["connections"])[1]
if connection != 4
y[i,i] = 1/1e6
y[j,j] = y[i,i]
if gen["grid_forming"]
zs = .0001 + .0005im
y[i,i] = 1/zs
y[j,j] = y[i,i]
else
y[i,i] = 1/1e6im
y[j,j] = y[i,i]
end
end
end
end
Expand Down Expand Up @@ -464,7 +470,7 @@ function _map_eng2math_mc_admittance_2w_transformer!(transformer::Dict{String,<:
(2,2) => [7,4],
(2,3) => [11,6]
)
if transformer["dss"]["phases"] == 3
if transformer["phases"] == 3
z = sum(transformer["rw"]) + 1im .* transformer["xsc"][1]
z_1volt= z * 3/transformer["sm_nom"][1]/1000
z_b = [z_1volt 0 0;0 z_1volt 0;0 0 z_1volt]
Expand Down Expand Up @@ -519,6 +525,9 @@ function _map_eng2math_mc_admittance_2w_transformer!(transformer::Dict{String,<:
end
y_w = n*y1*transpose(n)
p_matrix = a*y_w*transpose(a)
if transformer["dss"]["name"] == "xfm1"
Nothing
end

ybase = (transformer["sm_nom"][1]/3) / (transformer["tm_nom"][2]*transformer["tm_set"][2][1]/sqrt(3))^2 /1000
if haskey(transformer["dss"], "%noloadloss")
Expand All @@ -535,7 +544,7 @@ function _map_eng2math_mc_admittance_2w_transformer!(transformer::Dict{String,<:
p_matrix[8,8] += 3*shunt
end
transformer["p_matrix"] = p_matrix
elseif transformer["dss"]["phases"] == 1
elseif transformer["phases"] == 1
z = sum(transformer["rw"]) + 1im .* transformer["xsc"][1]
z_1volt= z * 1/transformer["sm_nom"][1]/1000
b = [1 ;-1]
Expand Down
17 changes: 9 additions & 8 deletions src/data_model/eng2math.jl
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,11 @@ end

"field/values to passthrough from the ENGINEERING to MATHEMATICAL data models"
const _pmp_eng2math_passthrough = Dict{String,Vector{String}}(
"generator" => String["zr", "zx", "gen_model", "xdp", "rp", "xdpp", "vnom_kv"],
"solar" => String["i_max", "solar_max", "kva", "pf", "grid_forming", "balanced", "vminpu", "transformer", "type", "pv_model", "transformer_id"],
"voltage_source" => String["zr", "zx"],
"load" => String["vminpu", "vmaxpu", "response"],
"transformer" => String["leadlag"]
"generator" => String["zr", "zx", "gen_model", "xdp", "rp", "xdpp", "vnom_kv", "phases", "response", "element"],
"solar" => String["i_max", "solar_max", "kva", "pf", "grid_forming", "balanced", "vminpu", "transformer", "type", "pv_model", "phases", "response", "element"],
"voltage_source" => String["zr", "zx", "phases", "response", "element"],
"load" => String["vminpu", "vmaxpu", "response", "phases", "element"],
"transformer" => String["leadlag", "phases", "element"]
)


Expand Down Expand Up @@ -309,7 +309,7 @@ function populate_bus_voltages!(data::Dict{String,Any})
f_bus = transformer["f_bus"]
t_bus = transformer["t_bus"]
if haskey(transformer, "tm_nom")
transformer["dss"]["phases"] == 3 ? multi = 1/sqrt(3) : multi = 1
transformer["phases"] == 3 ? multi = 1/sqrt(3) : multi = 1
if !haskey(data["bus"][string(f_bus)], "vbase")
data["bus"][string(f_bus)]["vbase"] = transformer["tm_nom"][1]*multi
end
Expand All @@ -332,7 +332,7 @@ function populate_bus_voltages!(data::Dict{String,Any})

for (i, gen) in data["gen"]
if !haskey(data["bus"][string(gen["gen_bus"])], "vbase")
if occursin("voltage_source", gen["source_id"])
if gen["element"] == VoltageSourceElement
data["bus"][string(gen["gen_bus"])]["vbase"] = gen["vg"][1]
end
end
Expand Down Expand Up @@ -390,4 +390,5 @@ function correct_grounds!(data::Dict{String,Any})
end
end
end
end
end

2 changes: 1 addition & 1 deletion src/data_model/eng2math_pmd.jl
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ end
function _eng2math_link_transformer(data_math::Dict{String,<:Any}, data_eng::Dict{String,<:Any})
for (_, gen) in data_math["gen"]
if haskey(gen, "type")
if gen["type"] == "solar"
if gen["element"] == SolarElement
# TODO adds transformer need to add for when transformer key set to false
for (id, transformer) in data_math["transformer"]
if transformer["f_bus"] == gen["gen_bus"] || transformer["t_bus"] == gen["gen_bus"]
Expand Down
60 changes: 52 additions & 8 deletions src/io/dss/dss2eng.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ function _dss2eng_solar_dynamics!(data_eng::Dict{String,<:Any}, data_dss::Dict{S
else
model = 1
end
if haskey(dss_obj, "phases")
phases = dss_obj["phases"]
else
phases = 3
end
ncnd = length(solar["connections"]) >= 3 ? 3 : 1
solar["i_max"] = fill(1/vminpu * kva / (ncnd/sqrt(3)*dss_obj["kv"]), ncnd)
solar["solar_max"] = irradiance*pmpp
Expand All @@ -57,8 +62,16 @@ function _dss2eng_solar_dynamics!(data_eng::Dict{String,<:Any}, data_dss::Dict{S
solar["vminpu"] = vminpu
solar["type"] = "solar"
solar["pv_model"] = model
solar["transformer"] = false
solar["grid_forming"] = false
if model == 1
solar["response"] = ConstantPAtPF
elseif model == 2
solar["response"] = ConstantI
elseif model == 3
solar["response"] = ConstantPQ
end
solar["phases"] = phases
solar["element"] = SolarElement
end
end
end
Expand All @@ -69,18 +82,25 @@ function _dss2eng_load_dynamics!(data_eng::Dict{String,<:Any}, data_dss::Dict{St
if haskey(data_eng, "load")
for (id, load) in data_eng["load"]
dss_obj = data_dss["load"][id]
defaults = _PMD._apply_ordered_properties(_PMD._create_pvsystem(id; _PMD._to_kwargs(dss_obj)...), dss_obj)
if haskey(dss_obj, "vminpu")
vminpu = dss_obj["vminpu"]
else
vminpu = .95
vminpu = defaults["vminpu"]
end
if haskey(dss_obj, "vmaxpu")
vmaxpu = dss_obj["vmaxpu"]
else
vmaxpu = 1.05
vmaxpu = defaults["vmaxpu"]
end
if haskey(dss_obj, "phases")
phases = dss_obj["phases"]
else
phases = defaults["phases"]
end
load["vminpu"] = vminpu
load["vmaxpu"] = vmaxpu
load["phases"] = phases
if load["model"] == _PMD.IMPEDANCE
load["response"] = ConstantZ
elseif load["model"] == _PMD.POWER
Expand All @@ -90,6 +110,7 @@ function _dss2eng_load_dynamics!(data_eng::Dict{String,<:Any}, data_dss::Dict{St
elseif load["model"] == _PMD.ZIP
load["response"] = ConstantZIP
end
load["element"] = LoadElement
end
end
end
Expand All @@ -99,14 +120,29 @@ end
function _dss2eng_transformer_dynamics!(data_eng::Dict{String,<:Any}, data_dss::Dict{String,<:Any})
if haskey(data_eng, "transformer")
for (id, transformer) in data_eng["transformer"]
if transformer["configuration"] != _PMD.ConnConfig[_PMD.WYE, _PMD.WYE] # need to fix combining single phase into 3 phase
dss_obj = data_dss["transformer"][id]
if haskey(dss_obj, "leadlag")
transformer["leadlag"] = dss_obj["leadlag"]
dss_obj = data_dss["transformer"][id]
defaults = _PMD._apply_ordered_properties(_PMD._create_pvsystem(id; _PMD._to_kwargs(dss_obj)...), dss_obj)
if haskey(dss_obj, "leadlag")
leadlag = dss_obj["leadlag"]
else
if haskey(defaults, "leadlag")
leadlag = defaults["leadlag"]
else
transformer["leadlag"] = "lag"
leadlag = "lag"
end
end
if haskey(dss_obj, "phases")
phases = dss_obj["phases"]
else
phases = defaults["phases"]
end
transformer["leadlag"] = leadlag
transformer["phases"] = phases
if length(transformer["connections"]) == 2
transformer["element"] = Transformer2WElement
else
Nothing
end
end
end
end
Expand All @@ -118,6 +154,13 @@ function _dss2eng_voltage_source_dynamics!(data_eng::Dict{String,<:Any}, data_ds
for (id, voltage_source) in data_eng["voltage_source"]
dss_obj = data_dss["vsource"][id]
defaults = _PMD._apply_ordered_properties(_PMD._create_vsource(id; _PMD._to_kwargs(dss_obj)...), dss_obj)
if haskey(dss_obj, "phases")
phases = dss_obj["phases"]
else
phases = defaults["phases"]
end
voltage_source["phases"] = phases
voltage_source["element"] = VoltageSourceElement
if haskey(dss_obj, "r1") && haskey(dss_obj, "x1")
r1 = dss_obj["r1"]
x1 = dss_obj["x1"]
Expand Down Expand Up @@ -167,6 +210,7 @@ function _dss2eng_gen_dynamics!(data_eng::Dict{String,<:Any}, data_dss::Dict{Str
if haskey(generator["dss"], "kv")
generator["vnom_kv"] = generator["dss"]["kv"] / sqrt(3)
end
generator["element"] = GeneratorElement
# if generator["dss"]["model"] == 3
# dss_obj = data_dss["generator"][id]
# _PMD._apply_like!(dss_obj, data_dss, "generator")
Expand Down
2 changes: 1 addition & 1 deletion src/io/opendss.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ data model adding some extra data transformations specific to fault studies.
`kwargs` can be any valid keyword arguments from PowerModelsDistribution's `parse_file` function.
"""
function parse_opendss(file::String; method::Union{String,Missing}=missing, kwargs...)
pm_data = _PMD.parse_file(file; bank_transformers=false, dss2eng_extensions=[_dss2eng_solar_dynamics!, _dss2eng_load_dynamics!, _dss2eng_gen_dynamics!, _dss2eng_transformer_dynamics!, _dss2eng_phases!, _dss2eng_issues!], kwargs...)
pm_data = _PMD.parse_file(file; bank_transformers=false, dss2eng_extensions=[_dss2eng_solar_dynamics!, _dss2eng_load_dynamics!, _dss2eng_voltage_source_dynamics!, _dss2eng_gen_dynamics!, _dss2eng_transformer_dynamics!, _dss2eng_issues!], kwargs...)
if ismissing(method)
pm_data["method"] = "PMD"
else
Expand Down
13 changes: 0 additions & 13 deletions test/fs_mc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -119,17 +119,4 @@
@test calculate_error_percentage(sol["loadbus"]["3pg"][2], 1531.0) < .02
@test calculate_error_percentage(sol["loadbus"]["3pg"][3], 1532.0) < .02
end
@testset "check 3 phase gfli defined pq" begin
model = PowerModelsProtection.instantiate_mc_admittance_model(gfli_case;loading=false)
sol = PowerModelsProtection.solve_mc_fault_study(model)
@test calculate_error_percentage(sol["loadbus"]["ll"][(1,2)][1], 13799.0) < .001
@test calculate_error_percentage(sol["loadbus"]["ll"][(2,3)][1], 13799.0) < .001
@test calculate_error_percentage(sol["loadbus"]["ll"][(1,3)][1], 13799.0) < .001
@test calculate_error_percentage(sol["loadbus"]["lg"][1][1], 9570.5) < .001
@test calculate_error_percentage(sol["loadbus"]["lg"][2][1], 9570.5) < .001
@test calculate_error_percentage(sol["loadbus"]["lg"][3][1], 9570.5) < .001
@test calculate_error_percentage(sol["loadbus"]["3pg"][1], 15929.0) < .001
@test calculate_error_percentage(sol["loadbus"]["3pg"][2], 15929.0) < .001
@test calculate_error_percentage(sol["loadbus"]["3pg"][3], 15929.0) < .001
end
end
15 changes: 0 additions & 15 deletions test/pf_mc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -68,21 +68,6 @@
@test calculate_error_percentage(sol["bus"]["3"]["vm"][3], 230.59) < .001
@test calculate_error_percentage(sol["bus"]["3"]["va"][3], 121.4) < .001
end
@testset "check 3 phase gfli defined pq" begin
model = PowerModelsProtection.instantiate_mc_admittance_model(gfli_case)
sol = PowerModelsProtection.compute_mc_pf(model)
@test sol["solver"]["it"] < 10
@test calculate_error_percentage(sol["bus"]["3"]["vm"][1], 2299.3) < .001
@test calculate_error_percentage(sol["bus"]["3"]["vm"][2], 2299.3) < .001
@test calculate_error_percentage(sol["bus"]["3"]["va"][2], -119.9) < .001
@test calculate_error_percentage(sol["bus"]["3"]["vm"][3], 2299.3) < .001
@test calculate_error_percentage(sol["bus"]["3"]["va"][3], 120.1) < .001
@test calculate_error_percentage(sol["bus"]["5"]["vm"][1], 235.87) < .001
@test calculate_error_percentage(sol["bus"]["5"]["vm"][2], 235.87) < .001
@test calculate_error_percentage(sol["bus"]["5"]["va"][2], -147.8) < .001
@test calculate_error_percentage(sol["bus"]["5"]["vm"][3], 235.87) < .001
@test calculate_error_percentage(sol["bus"]["5"]["va"][3], 92.2) < .001
end
end


Expand Down

0 comments on commit 4e3f030

Please sign in to comment.