Skip to content

Commit

Permalink
add Switch Shunt struct & psse.jl updates on 3WT
Browse files Browse the repository at this point in the history
  • Loading branch information
mcllerena committed Jan 14, 2025
1 parent ba3eef7 commit 4ffdf64
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 68 deletions.
10 changes: 8 additions & 2 deletions src/descriptors/power_system_structs.json
Original file line number Diff line number Diff line change
Expand Up @@ -1469,16 +1469,22 @@
"name": "number_of_steps",
"comment": "Number of steps for adjustable shunt",
"null_value": "0",
"data_type": "Int",
"data_type": "Union{Int, Vector{Int}}",
"default": "0"
},
{
"name": "Y_increase",
"comment": "Admittance increment for each of step increase",
"null_value": "0",
"data_type": "Complex{Float64}",
"data_type": "Union{Complex{Float64}, Vector{Complex{Float64}}}",
"default": "0"
},
{ "name": "admittance_limits",
"comment": "Shunt admittance limits for switched shunt model",
"null_value": "(min=0.0, max=0.0)",
"data_type": "MinMax",
"default": "(min=1.0, max=1.0)"
},
{
"name": "dynamic_injector",
"data_type": "Union{Nothing, DynamicInjection}",
Expand Down
29 changes: 19 additions & 10 deletions src/models/generated/SwitchedAdmittance.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ This file is auto-generated. Do not edit.
available::Bool
bus::ACBus
Y::Complex{Float64}
number_of_steps::Int
Y_increase::Complex{Float64}
number_of_steps::Union{Int, Vector{Int}}
Y_increase::Union{Complex{Float64}, Vector{Complex{Float64}}}
admittance_limits::MinMax
dynamic_injector::Union{Nothing, DynamicInjection}
services::Vector{Service}
ext::Dict{String, Any}
Expand All @@ -27,8 +28,9 @@ Most often used in power flow studies, iterating over the steps to see impacts o
- `available::Bool`: Indicator of whether the component is connected and online (`true`) or disconnected, offline, or down (`false`). Unavailable components are excluded during simulations
- `bus::ACBus`: Bus that this component is connected to
- `Y::Complex{Float64}`: Initial admittance at N = 0
- `number_of_steps::Int`: (default: `0`) Number of steps for adjustable shunt
- `Y_increase::Complex{Float64}`: (default: `0`) Admittance increment for each of step increase
- `number_of_steps::Union{Int, Vector{Int}}`: (default: `0`) Number of steps for adjustable shunt
- `Y_increase::Union{Complex{Float64}, Vector{Complex{Float64}}}`: (default: `0`) Admittance increment for each of step increase
- `admittance_limits::MinMax`: (default: `(min=1.0, max=1.0)`) Shunt admittance limits for switched shunt model
- `dynamic_injector::Union{Nothing, DynamicInjection}`: (default: `nothing`) corresponding dynamic injection model for admittance
- `services::Vector{Service}`: (default: `Device[]`) Services that this device contributes to
- `ext::Dict{String, Any}`: (default: `Dict{String, Any}()`) An [*ext*ra dictionary](@ref additional_fields) for users to add metadata that are not used in simulation, such as latitude and longitude.
Expand All @@ -44,9 +46,11 @@ mutable struct SwitchedAdmittance <: ElectricLoad
"Initial admittance at N = 0"
Y::Complex{Float64}
"Number of steps for adjustable shunt"
number_of_steps::Int
number_of_steps::Union{Int, Vector{Int}}
"Admittance increment for each of step increase"
Y_increase::Complex{Float64}
Y_increase::Union{Complex{Float64}, Vector{Complex{Float64}}}
"Shunt admittance limits for switched shunt model"
admittance_limits::MinMax
"corresponding dynamic injection model for admittance"
dynamic_injector::Union{Nothing, DynamicInjection}
"Services that this device contributes to"
Expand All @@ -57,12 +61,12 @@ mutable struct SwitchedAdmittance <: ElectricLoad
internal::InfrastructureSystemsInternal
end

function SwitchedAdmittance(name, available, bus, Y, number_of_steps=0, Y_increase=0, dynamic_injector=nothing, services=Device[], ext=Dict{String, Any}(), )
SwitchedAdmittance(name, available, bus, Y, number_of_steps, Y_increase, dynamic_injector, services, ext, InfrastructureSystemsInternal(), )
function SwitchedAdmittance(name, available, bus, Y, number_of_steps=0, Y_increase=0, admittance_limits=(min=1.0, max=1.0), dynamic_injector=nothing, services=Device[], ext=Dict{String, Any}(), )
SwitchedAdmittance(name, available, bus, Y, number_of_steps, Y_increase, admittance_limits, dynamic_injector, services, ext, InfrastructureSystemsInternal(), )
end

function SwitchedAdmittance(; name, available, bus, Y, number_of_steps=0, Y_increase=0, dynamic_injector=nothing, services=Device[], ext=Dict{String, Any}(), internal=InfrastructureSystemsInternal(), )
SwitchedAdmittance(name, available, bus, Y, number_of_steps, Y_increase, dynamic_injector, services, ext, internal, )
function SwitchedAdmittance(; name, available, bus, Y, number_of_steps=0, Y_increase=0, admittance_limits=(min=1.0, max=1.0), dynamic_injector=nothing, services=Device[], ext=Dict{String, Any}(), internal=InfrastructureSystemsInternal(), )
SwitchedAdmittance(name, available, bus, Y, number_of_steps, Y_increase, admittance_limits, dynamic_injector, services, ext, internal, )
end

# Constructor for demo purposes; non-functional.
Expand All @@ -74,6 +78,7 @@ function SwitchedAdmittance(::Nothing)
Y=0.0,
number_of_steps=0,
Y_increase=0,
admittance_limits=(min=0.0, max=0.0),
dynamic_injector=nothing,
services=Device[],
ext=Dict{String, Any}(),
Expand All @@ -92,6 +97,8 @@ get_Y(value::SwitchedAdmittance) = value.Y
get_number_of_steps(value::SwitchedAdmittance) = value.number_of_steps
"""Get [`SwitchedAdmittance`](@ref) `Y_increase`."""
get_Y_increase(value::SwitchedAdmittance) = value.Y_increase
"""Get [`SwitchedAdmittance`](@ref) `admittance_limits`."""
get_admittance_limits(value::SwitchedAdmittance) = value.admittance_limits
"""Get [`SwitchedAdmittance`](@ref) `dynamic_injector`."""
get_dynamic_injector(value::SwitchedAdmittance) = value.dynamic_injector
"""Get [`SwitchedAdmittance`](@ref) `services`."""
Expand All @@ -111,6 +118,8 @@ set_Y!(value::SwitchedAdmittance, val) = value.Y = val
set_number_of_steps!(value::SwitchedAdmittance, val) = value.number_of_steps = val
"""Set [`SwitchedAdmittance`](@ref) `Y_increase`."""
set_Y_increase!(value::SwitchedAdmittance, val) = value.Y_increase = val
"""Set [`SwitchedAdmittance`](@ref) `admittance_limits`."""
set_admittance_limits!(value::SwitchedAdmittance, val) = value.admittance_limits = val
"""Set [`SwitchedAdmittance`](@ref) `services`."""
set_services!(value::SwitchedAdmittance, val) = value.services = val
"""Set [`SwitchedAdmittance`](@ref) `ext`."""
Expand Down
2 changes: 2 additions & 0 deletions src/models/generated/includes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ export get_active_power_limits
export get_active_power_limits_from
export get_active_power_limits_pump
export get_active_power_limits_to
export get_admittance_limits
export get_angle
export get_angle_limits
export get_arc
Expand Down Expand Up @@ -1045,6 +1046,7 @@ export set_active_power_limits!
export set_active_power_limits_from!
export set_active_power_limits_pump!
export set_active_power_limits_to!
export set_admittance_limits!
export set_angle!
export set_angle_limits!
export set_arc!
Expand Down
162 changes: 107 additions & 55 deletions src/parsers/pm_io/psse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ function _create_starbus_from_transformer(
starbus["bus_type"] = bus_type
starbus["area"] = _get_bus_value(transformer["I"], "area", pm_data)
starbus["zone"] = _get_bus_value(transformer["I"], "zone", pm_data)
starbus["hidden"] = true
starbus["source_id"] = push!(
["transformer", starbus["bus_i"], starbus["name"]],
transformer["I"],
Expand Down Expand Up @@ -288,6 +289,7 @@ function _psse2pm_bus!(pm_data::Dict, pti_data::Dict, import_all::Bool)
sub_data["name"] = pop!(bus, "NAME")
sub_data["vmax"] = pop!(bus, "NVHI")
sub_data["vmin"] = pop!(bus, "NVLO")
sub_data["hidden"] = false

sub_data["source_id"] = ["bus", "$(bus["I"])"]
sub_data["index"] = pop!(bus, "I")
Expand Down Expand Up @@ -347,26 +349,24 @@ function _psse2pm_shunt!(pm_data::Dict, pti_data::Dict, import_all::Bool)
@info "Parsing PSS(R)E Shunt data into a PowerModels Dict..."

pm_data["shunt"] = []

pm_data["fixed_shunt"] = []
if haskey(pti_data, "FIXED SHUNT")
for fixed_shunt in pti_data["FIXED SHUNT"]
for shunt in pti_data["FIXED SHUNT"]
sub_data = Dict{String, Any}()

sub_data["shunt_bus"] = pop!(fixed_shunt, "I")
sub_data["gs"] = pop!(fixed_shunt, "GL")
sub_data["bs"] = pop!(fixed_shunt, "BL")
sub_data["status"] = pop!(fixed_shunt, "STATUS")
sub_data["shunt_bus"] = pop!(shunt, "I")
sub_data["gs"] = pop!(shunt, "GL")
sub_data["bs"] = pop!(shunt, "BL")
sub_data["status"] = pop!(shunt, "STATUS")

sub_data["source_id"] =
["fixed shunt", sub_data["shunt_bus"], pop!(fixed_shunt, "ID")]
sub_data["index"] = length(pm_data["fixed_shunt"]) + 1
["fixed shunt", sub_data["shunt_bus"], pop!(shunt, "ID")]
sub_data["index"] = length(pm_data["shunt"]) + 1

if import_all
_import_remaining_keys!(sub_data, fixed_shunt)
_import_remaining_keys!(sub_data, shunt)
end

push!(pm_data["fixed_shunt"], sub_data)
push!(pm_data["shunt"], sub_data)
end
end

Expand All @@ -381,13 +381,15 @@ function _psse2pm_shunt!(pm_data::Dict, pti_data::Dict, import_all::Bool)
sub_data["gs"] = 0.0
sub_data["bs"] = pop!(switched_shunt, "BINIT")
sub_data["status"] = pop!(switched_shunt, "STAT")
sub_data["admittance_limits"] = (pop!(switched_shunt, "VSWLO"), pop!(switched_shunt, "VSWHI"))

step_numbers = Dict(k => v for (k, v) in switched_shunt if startswith(k, "N") && isdigit(last(k)))
step_numbers_sorted = sort(collect(keys(step_numbers)), by = x -> parse(Int, x[2:end]))
sub_data["step_number"] = [step_numbers[k] for k in step_numbers_sorted]

# Add remaining data
sub_data["upper_limit"] = pop!(switched_shunt, "VSWHI")
sub_data["lower_limit"] = pop!(switched_shunt, "VSWLO")
sub_data["step_number"] = Dict(k => v for (k, v) in switched_shunt if startswith(k, "N") && isdigit(last(k)))
sub_data["b_increment"] = Dict(k => v for (k, v) in switched_shunt if startswith(k, "B") && isdigit(last(k)))
# ==================
y_increment = Dict(k => v for (k, v) in switched_shunt if startswith(k, "B") && isdigit(last(k)))
y_increment_sorted = sort(collect(keys(y_increment)), by = x -> parse(Int, x[2:end]))
sub_data["y_increment"] = [y_increment[k] for k in y_increment_sorted]

sub_data["source_id"] =
["switched shunt", sub_data["shunt_bus"], pop!(switched_shunt, "SWREM")]
Expand Down Expand Up @@ -622,21 +624,21 @@ function _psse2pm_transformer!(pm_data::Dict, pti_data::Dict, import_all::Bool)

push!(pm_data["branch"], sub_data)
else # Three-winding Transformers
# Create 3w-transformer key
if !haskey(pm_data, "3w_transformer")
pm_data["3w_transformer"] = []
end

bus_id1, bus_id2, bus_id3 =
transformer["I"], transformer["J"], transformer["K"]

# Creates a starbus (or "dummy" bus) to which each winding of the transformer will connect
starbus = _create_starbus_from_transformer(pm_data, transformer, starbus_id)
pm_data["bus"][starbus_id] = starbus
starbus_id += 1

## Warn on adding the dummy bus when exporting to a PSSE file / test it on the function /

# Create 3 branches from a three winding transformer (one for each winding, which will each connect to the starbus)
br_r12, br_r23, br_r31 =
transformer["R1-2"], transformer["R2-3"], transformer["R3-1"]
br_x12, br_x23, br_x31 =
transformer["X1-2"], transformer["X2-3"], transformer["X3-1"]
br_r12, br_r23, br_r31 = transformer["R1-2"], transformer["R2-3"], transformer["R3-1"]
br_x12, br_x23, br_x31 = transformer["X1-2"], transformer["X2-3"], transformer["X3-1"]

# Unit Transformations
if transformer["CZ"] == 3 # "for transformer load loss in watts and impedance magnitude in pu on a specified MVA base and winding voltage base."
Expand All @@ -651,37 +653,13 @@ function _psse2pm_transformer!(pm_data::Dict, pti_data::Dict, import_all::Bool)

# Unit Transformations
if transformer["CZ"] != 1 # NOT "for resistance and reactance in pu on system MVA base and winding voltage base"
br_r12 *=
(
transformer["NOMV1"] /
_get_bus_value(bus_id1, "base_kv", pm_data)
)^2 * (pm_data["baseMVA"] / transformer["SBASE1-2"])
br_r23 *=
(
transformer["NOMV2"] /
_get_bus_value(bus_id2, "base_kv", pm_data)
)^2 * (pm_data["baseMVA"] / transformer["SBASE2-3"])
br_r31 *=
(
transformer["NOMV3"] /
_get_bus_value(bus_id3, "base_kv", pm_data)
)^2 * (pm_data["baseMVA"] / transformer["SBASE3-1"])
br_r12 *= (transformer["NOMV1"]/_get_bus_value(bus_id1, "base_kv", pm_data))^2 * (pm_data["baseMVA"] / transformer["SBASE1-2"])
br_r23 *= (transformer["NOMV2"]/_get_bus_value(bus_id2, "base_kv", pm_data))^2 * (pm_data["baseMVA"] / transformer["SBASE2-3"])
br_r31 *= (transformer["NOMV3"]/_get_bus_value(bus_id3, "base_kv", pm_data))^2 * (pm_data["baseMVA"] / transformer["SBASE3-1"])

br_x12 *=
(
transformer["NOMV1"] /
_get_bus_value(bus_id1, "base_kv", pm_data)
)^2 * (pm_data["baseMVA"] / transformer["SBASE1-2"])
br_x23 *=
(
transformer["NOMV2"] /
_get_bus_value(bus_id2, "base_kv", pm_data)
)^2 * (pm_data["baseMVA"] / transformer["SBASE2-3"])
br_x31 *=
(
transformer["NOMV3"] /
_get_bus_value(bus_id3, "base_kv", pm_data)
)^2 * (pm_data["baseMVA"] / transformer["SBASE3-1"])
br_x12 *= (transformer["NOMV1"]/_get_bus_value(bus_id1, "base_kv", pm_data))^2 * (pm_data["baseMVA"] / transformer["SBASE1-2"])
br_x23 *= (transformer["NOMV2"]/_get_bus_value(bus_id2, "base_kv", pm_data))^2 * (pm_data["baseMVA"] / transformer["SBASE2-3"])
br_x31 *= (transformer["NOMV3"]/_get_bus_value(bus_id3, "base_kv", pm_data))^2 * (pm_data["baseMVA"] / transformer["SBASE3-1"])
end

# See "Power System Stability and Control", ISBN: 0-07-035958-X, Eq. 6.72
Expand All @@ -692,6 +670,79 @@ function _psse2pm_transformer!(pm_data::Dict, pti_data::Dict, import_all::Bool)
Zx_s = 1 / 2 * (br_x23 - br_x31 + br_x12)
Zx_t = 1 / 2 * (br_x31 - br_x12 + br_x23)

# Add parameters to the 3w-transformer key
sub_data = Dict{String, Any}()
sub_data["name"] = transformer["NAME"]
if transformer["STAT"] != 0
sub_data["available"] = true
end
# sub_data["primary_secondary_arc"] = 0.0
# sub_data["secondary_tertiary_arc"] = 0.0
# sub_data["primary_tertiary_arc"] = 0.0
sub_data["star_bus"] = starbus_id

# sub_data["active_power_flow_primary"] = 0.0
# sub_data["reactive_power_flow_primary"] = 0.0
# sub_data["active_power_flow_secondary"] = 0.0
# sub_data["reactive_power_flow_secondary"] = 0.0
# sub_data["active_power_flow_tertiary"] = 0.0
# sub_data["reactive_power_flow_tertiary"] = 0.0

sub_data["r_primary"] = Zr_p
sub_data["x_primary"] = Zx_p
sub_data["r_secondary"] = Zr_s
sub_data["x_secondary"] = Zx_s
sub_data["r_tertiary"] = Zr_t
sub_data["x_tertiary"] = Zx_t

sub_data["rating_primary"] = min(transformer["RATA1"], transformer["RATB1"], transformer["RATC1"])
sub_data["rating_secondary"] = min(transformer["RATA2"], transformer["RATB2"], transformer["RATC2"])
sub_data["rating_tertiary"] = min(transformer["RATA3"], transformer["RATB3"], transformer["RATC3"])
sub_data["rating"] = min(sub_data["rating_primary"], sub_data["rating_secondary"], sub_data["rating_tertiary"])

sub_data["r_12"] = br_r12
sub_data["x_12"] = br_x12
sub_data["r_23"] = br_r23
sub_data["x_23"] = br_x23
sub_data["r_13"] = br_r31
sub_data["x_13"] = br_x31
sub_data["g"] = transformer["MAG1"]
sub_data["b"] = transformer["MAG2"]

if transformer["CW"] == 1
sub_data["primary_turns_ratio"] = transformer["WINDV1"]
sub_data["secondary_turns_ratio"] = transformer["WINDV2"]
sub_data["tertiary_turns_ratio"] = transformer["WINDV3"]
else
sub_data["primary_turns_ratio"] = 1.0
sub_data["secondary_turns_ratio"] = 1.0
sub_data["tertiary_turns_ratio"] = 1.0
end

sub_data["circuit"] = transformer["CKT"]

sub_data["index"] = length(pm_data["3w_transformer"]) + 1

if import_all
_import_remaining_keys!(
sub_data,
transformer;
exclude = [
"NAME",
"STAT",
"MAG1",
"MAG2",
"WINDV1",
"WINDV2",
"WINDV3"
],
)
end

push!(pm_data["3w_transformer"], sub_data)

starbus_id += 1 # after adding the 1st 3WT, increase the counter

# Build each of the three transformer branches
for (m, (bus_id, br_r, br_x)) in enumerate(
zip(
Expand Down Expand Up @@ -818,6 +869,7 @@ function _psse2pm_transformer!(pm_data::Dict, pti_data::Dict, import_all::Bool)
)
end

# TODO: Delete this line (changes to 3W Transformer)
push!(pm_data["branch"], sub_data)
end
end
Expand Down Expand Up @@ -1054,7 +1106,7 @@ function _pti_to_powermodels!(
_psse2pm_dcline!(pm_data, pti_data, import_all)
_psse2pm_storage!(pm_data, pti_data, import_all)
_psse2pm_switch!(pm_data, pti_data, import_all)

if import_all
_import_remaining_comps!(
pm_data,
Expand Down
2 changes: 1 addition & 1 deletion src/parsers/power_models_data.jl
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,7 @@ function read_dcline!(
end

function make_shunt(name::String, d::Dict, bus::ACBus)
return FixedAdmittance(;
return (;
name = name,
available = Bool(d["status"]),
bus = bus,
Expand Down

0 comments on commit 4ffdf64

Please sign in to comment.