From 011e98fe623765b0f02fc99dc14d1ae81de845b8 Mon Sep 17 00:00:00 2001 From: David M Fobes Date: Tue, 31 Oct 2023 15:25:36 -0600 Subject: [PATCH] FIX: switch line parameters Native PF assumes no virtual branches in the MATHEMATICAL model, so we removed the line loss parameters after parse in the tests. Also, according to documentation, switch=y has the effect of x1=1, x0=1, r1=1, r0=1, c1=1.1, c0=1, length=0.001, units=none, so the parser was updated to correct this. --- CHANGELOG.md | 5 ++- src/data_model/dss/edge_constructors.jl | 44 +++++++++++----------- src/data_model/transformations/dss2eng.jl | 4 -- src/data_model/transformations/eng2math.jl | 8 ++-- test/en_pf_native_validation.jl | 1 + test/opf_bf.jl | 2 +- 6 files changed, 32 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6221d56c7..3b68f05cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,10 @@ ## staged -- Fixed bug in parsing of dss lines where `switch=y` +- Fixed bug in `DssLine` parser where `c1` was being set to `c0` +- Fixed native pf unit tests, which assume no virtual branches from switches (applied `make_lossless!` before test) +- Added `g_fr`, `g_to`, `b_fr`, `b_to` to switches in `dss2eng` and `eng2math` +- Fixed bug in parsing of dss lines where `switch=y` actually implies `x1=1`, `x0=1`, `r1=1`, `r0=1`, `c1=1.1`, `c0=1`, `length=0.001`, and `units=none` ## v0.15.1 diff --git a/src/data_model/dss/edge_constructors.jl b/src/data_model/dss/edge_constructors.jl index 152885960..71ac693f8 100644 --- a/src/data_model/dss/edge_constructors.jl +++ b/src/data_model/dss/edge_constructors.jl @@ -28,6 +28,14 @@ OpenDSS documentation for valid fields and ways to specify the different properties. """ function create_dss_object(::Type{T}, property_pairs::Vector{Pair{String,String}}, dss::OpenDssDataModel, dss_raw::OpenDssRawDataModel)::T where T <: DssLine + for (i,(field,value)) in enumerate(collect(property_pairs)) + if field == "switch" && parse(Bool, startswith("y", value) ? "true" : "false") + for item in reverse(["r1"=>"1","x1"=>"1","r0"=>"1","x0"=>"1","c1"=>"1.1","c0"=>"1","length"=>"0.001","units"=>"none"]) + insert!(property_pairs, i+1, item) + end + end + end + @warn property_pairs raw_fields = _get_raw_fields(property_pairs) line = _apply_property_pairs(T(), property_pairs, dss, dss_raw) @@ -41,7 +49,7 @@ function create_dss_object(::Type{T}, property_pairs::Vector{Pair{String,String} if line.phases == 1 line.r0 = line.r1 line.x0 = line.x1 - line.c0 = line.c1 + line.c0 = line.c0 line.b0 = line.b1 else if :b0 ∈ raw_fields @@ -90,27 +98,19 @@ function create_dss_object(::Type{T}, property_pairs::Vector{Pair{String,String} line.xmatrix .-= xgmod line.xmatrix .*= lenmult * (line.basefreq / circuit_basefreq) - if !line.switch - line.r1 = line.r1 / _convert_to_meters[line.units] - line.x1 = line.x1 / _convert_to_meters[line.units] - line.r0 = line.r0 / _convert_to_meters[line.units] - line.x0 = line.x0 / _convert_to_meters[line.units] - line.c1 = line.c1 / _convert_to_meters[line.units] - line.c0 = line.c0 / _convert_to_meters[line.units] - line.rmatrix = line.rmatrix / _convert_to_meters[line.units] - line.xmatrix = line.xmatrix / _convert_to_meters[line.units] - line.cmatrix = line.cmatrix / _convert_to_meters[line.units] - line.b1 = line.b1 / _convert_to_meters[line.units] - line.b0 = line.b0 / _convert_to_meters[line.units] - line.length = line.length * _convert_to_meters[line.units] - line.units = "m" - else - # TODO: bug in DSS? - line.b1 = line.b1 / _convert_to_meters[line.units] - line.b0 = line.b0 / _convert_to_meters[line.units] - line.length = 0.001 - line.units = "none" - end + line.r1 = line.r1 / _convert_to_meters[line.units] + line.x1 = line.x1 / _convert_to_meters[line.units] + line.r0 = line.r0 / _convert_to_meters[line.units] + line.x0 = line.x0 / _convert_to_meters[line.units] + line.c1 = line.c1 / _convert_to_meters[line.units] + line.c0 = line.c0 / _convert_to_meters[line.units] + line.rmatrix = line.rmatrix / _convert_to_meters[line.units] + line.xmatrix = line.xmatrix / _convert_to_meters[line.units] + line.cmatrix = line.cmatrix / _convert_to_meters[line.units] + line.b1 = line.b1 / _convert_to_meters[line.units] + line.b0 = line.b0 / _convert_to_meters[line.units] + line.length = line.length * _convert_to_meters[line.units] + line.units = "m" return line end diff --git a/src/data_model/transformations/dss2eng.jl b/src/data_model/transformations/dss2eng.jl index 8c6c40fce..d262c5699 100644 --- a/src/data_model/transformations/dss2eng.jl +++ b/src/data_model/transformations/dss2eng.jl @@ -495,10 +495,6 @@ function _dss2eng_line!(data_eng::Dict{String,<:Any}, data_dss::OpenDssDataModel eng_obj["state"] = CLOSED eng_obj["dispatchable"] = YES - for key in ["g_fr", "b_fr", "g_to", "b_to"] - delete!(eng_obj, key) - end - _add_eng_obj!(data_eng, "switch", id, eng_obj) else _add_eng_obj!(data_eng, "line", id, eng_obj) diff --git a/src/data_model/transformations/eng2math.jl b/src/data_model/transformations/eng2math.jl index 6aadf6817..f82208778 100644 --- a/src/data_model/transformations/eng2math.jl +++ b/src/data_model/transformations/eng2math.jl @@ -613,10 +613,10 @@ function _map_eng2math_switch!(data_math::Dict{String,<:Any}, data_eng::Dict{Str "t_connections" => eng_obj["t_connections"], # should be identical to the switch's to-side connections "br_r" => _impedance_conversion(data_eng, eng_obj, "rs"), "br_x" => _impedance_conversion(data_eng, eng_obj, "xs"), - "g_fr" => zeros(nphases, nphases), - "g_to" => zeros(nphases, nphases), - "b_fr" => zeros(nphases, nphases), - "b_to" => zeros(nphases, nphases), + "g_fr" => _admittance_conversion(data_eng, eng_obj, "g_fr"), + "g_to" => _admittance_conversion(data_eng, eng_obj, "g_to"), + "b_fr" => _admittance_conversion(data_eng, eng_obj, "b_fr"), + "b_to" => _admittance_conversion(data_eng, eng_obj, "b_to"), "angmin" => fill(-10.0, nphases), "angmax" => fill( 10.0, nphases), "c_rating_a" => fill(Inf, nphases), diff --git a/test/en_pf_native_validation.jl b/test/en_pf_native_validation.jl index a37bba140..de9ee08be 100644 --- a/test/en_pf_native_validation.jl +++ b/test/en_pf_native_validation.jl @@ -247,6 +247,7 @@ filter!(e -> e ≠ "case3_balanced_battery_3ph", cases) case_path = "$data_dir/$case.dss" data_eng = parse_file(case_path, transformations=[transform_loops!]) + make_lossless!(data_eng; exclude=collect(filter(x->x!="switch",keys(PowerModelsDistribution._loss_model_objects)))) data_math = transform_data_model(data_eng; kron_reduce=false) diff --git a/test/opf_bf.jl b/test/opf_bf.jl index b28ddbf5a..60ff372d6 100644 --- a/test/opf_bf.jl +++ b/test/opf_bf.jl @@ -62,7 +62,7 @@ vbase = case3_unbalanced_switch["settings"]["vbases_default"]["sourcebus"] @test all(isapprox.(result["solution"]["bus"]["loadbus"]["vm"] ./ vbase, [0.98102, 0.98922, 0.98692]; atol=9e-2)) - @test all(isapprox.(result["solution"]["bus"]["loadbus"]["va"], [-0.2, -120.1, 120.1]; atol=3e-2)) + @test all(isapprox.(result["solution"]["bus"]["loadbus"]["va"], [-0.2312, -120.1135, 120.1174]; atol=3e-2)) end @testset "3-bus unbalanced fbs opf_bf with yy transformer" begin