From dadefbe7e89c59e57edeb4d0af1b23038956aec9 Mon Sep 17 00:00:00 2001 From: jjospina Date: Mon, 5 Aug 2024 09:36:42 -0600 Subject: [PATCH 01/27] WIP: ravens to math converter for PMD. --- src/PowerModelsDistribution.jl | 2 + src/data_model/transformations/ravens2math.jl | 814 ++++++++++++++++++ src/data_model/utils_ravens.jl | 52 ++ src/prob/common.jl | 43 + 4 files changed, 911 insertions(+) create mode 100644 src/data_model/transformations/ravens2math.jl create mode 100644 src/data_model/utils_ravens.jl diff --git a/src/PowerModelsDistribution.jl b/src/PowerModelsDistribution.jl index 0a8443a3a..77669ba5f 100644 --- a/src/PowerModelsDistribution.jl +++ b/src/PowerModelsDistribution.jl @@ -71,6 +71,7 @@ module PowerModelsDistribution include("data_model/transformations/math2eng.jl") include("data_model/transformations/utils.jl") include("data_model/transformations/reduce.jl") + include("data_model/transformations/ravens2math.jl") include("core/data.jl") include("core/ref.jl") @@ -113,6 +114,7 @@ module PowerModelsDistribution include("io/common.jl") include("data_model/utils.jl") + include("data_model/utils_ravens.jl") include("data_model/checks.jl") include("data_model/components.jl") include("data_model/multinetwork.jl") diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl new file mode 100644 index 000000000..b098de30f --- /dev/null +++ b/src/data_model/transformations/ravens2math.jl @@ -0,0 +1,814 @@ +"cim-ravens to math object mapping" +const _math_to_ravens = Dict{String,String}( + "bus" => "connectivity_node", + "transformer" => "power_transformer", + "switch" => "switch", + # "shunt" => "shunt_compensator", + "load" => "energy_consumer", + # "generator" => "rotating_machine", + # "solar" => "photovoltaic_unit", + # "storage" => "battery_unit", + "voltage_source" => "energy_source", +) + + +"list of nodal type elements in the ravens model" +const _ravens_node_elements = String[ + "energy_consumer", "energy_source" +] + +"list of edge type elements in the ravens model" +const _ravens_edge_elements = String[ + "conductor" +] + +"list of all ravens asset types" +const pmd_ravens_asset_types = String[ + "connectivity_node", _ravens_edge_elements..., _ravens_node_elements... +] + + +function transform_data_model_ravens( + data::Dict{String,<:Any}; + kron_reduce::Bool=true, + phase_project::Bool=false, + multinetwork::Bool=false, + global_keys::Set{String}=Set{String}(), + ravens2math_passthrough::Dict{String,<:Vector{<:String}}=Dict{String,Vector{String}}(), + ravens2math_extensions::Vector{<:Function}=Function[], + make_pu::Bool=true, + make_pu_extensions::Vector{<:Function}=Function[], + correct_network_data::Bool=true, + )::Dict{String,Any} + + current_data_model = get(data, "data_model", MATHEMATICAL) + + ## TODO + # if multinetwork && !ismultinetwork(data) + # data = make_multinetwork(data; global_keys=global_keys) + # end + + data_math = _map_ravens2math( + data; + kron_reduce=kron_reduce, + phase_project=phase_project, + ravens2math_extensions=ravens2math_extensions, + ravens2math_passthrough=ravens2math_passthrough, + global_keys=global_keys, + ) + + # TODO: Correct network data transforms a lot of the values of lines/branches (other values maybe too) + correct_network_data && correct_network_data!(data_math; make_pu=make_pu, make_pu_extensions=make_pu_extensions) + + return data_math + +end + + +"base function for converting ravens model to mathematical model" +function _map_ravens2math( + data_ravens::Dict{String,<:Any}; + kron_reduce::Bool=true, + phase_project::Bool=false, + ravens2math_extensions::Vector{<:Function}=Function[], + ravens2math_passthrough::Dict{String,Vector{String}}=Dict{String,Vector{String}}(), + global_keys::Set{String}=Set{String}(), + )::Dict{String,Any} + + _data_ravens = deepcopy(data_ravens) + + ## TODO + # if kron_reduce + # apply_kron_reduction!(_data_ravens) + # apply_phase_projection_delta!(_data_ravens) + # end + + # if phase_project + # apply_phase_projection!(_data_ravens) + # end + + + # # TODO: Add vbases to settings + # _vbases_default = Dict("vbases_default" => Dict{String, Real}()) + # for (name, ravens_obj) in get(data_ravens, "BaseVoltage", Dict{String,Any}()) + # _vbases_default = Dict(name => ravens_obj["BaseVoltage.nominalVoltage"]) + # end + + # TODO: Add settings (defaults) + basemva = 100 + _settings = Dict("sbase_default" => basemva * 1e3, + "voltage_scale_factor" => 1e3, + "power_scale_factor" => 1e3, + "base_frequency" => 60.0, + "vbases_default" => Dict{String,Real}() + ) + + ## TODO: Multinetwork + if ismultinetwork(data_ravens) + data_math = Dict{String,Any}( + "name" => get(_data_ravens, "name", ""), + "data_model" => MATHEMATICAL, + "nw" => Dict{String,Any}( + n => Dict{String,Any}( + "per_unit" => get(_data_ravens, "per_unit", false), + "is_projected" => get(nw, "is_projected", false), + "is_kron_reduced" => get(nw, "is_kron_reduced", false), + "settings" => deepcopy(_settings), + "time_elapsed" => get(nw, "time_elapsed", 1.0), + ) for (n,nw) in _data_ravens["nw"] + ), + "multinetwork" => ismultinetwork(data_ravens), + [k => data_ravens[k] for k in global_keys if haskey(data_ravens, k)]... + ) + else + data_math = Dict{String,Any}( + "name" => get(_data_ravens, "name", ""), + "per_unit" => get(_data_ravens, "per_unit", false), + "data_model" => MATHEMATICAL, + "is_projected" => get(_data_ravens, "is_projected", false), + "is_kron_reduced" => get(_data_ravens, "is_kron_reduced", false), + "settings" => deepcopy(_settings), + "time_elapsed" => get(_data_ravens, "time_elapsed", 1.0), + ) + end + + + @info "$(data_math)" + gfdgfdgf + + apply_pmd!(_map_ravens2math_nw!, data_math, _data_ravens; ravens2math_passthrough=ravens2math_passthrough, ravens2math_extensions=ravens2math_extensions) + + if ismultinetwork(data_ravens) + _collect_nw_maps!(data_math) + _collect_nw_bus_lookups!(data_math) + end + + return data_math +end + + +""" +""" +function _map_ravens2math_nw!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; ravens2math_passthrough::Dict{String,Vector{String}}=Dict{String,Vector{String}}(), ravens2math_extensions::Vector{<:Function}=Function[]) + data_math["map"] = Vector{Dict{String,Any}}([ + Dict{String,Any}("unmap_function" => "_map_math2ravens_root!") + ]) + + _init_base_components!(data_math) + + ## TODO + # for property in get(ravens2math_passthrough, "root", String[]) + # if haskey(data_ravens, property) + # data_math[property] = deepcopy(data_ravens[property]) + # end + # end + + for type in pmd_ravens_asset_types + getfield(PowerModelsDistribution, Symbol("_map_ravens2math_$(type)!"))(data_math, data_ravens; pass_props=get(ravens2math_passthrough, type, String[])) + end + + # Custom ravens2math transformation functions + for ravens2math_func! in ravens2math_extensions + ravens2math_func!(data_math, data_ravens) + end + + ## TODO: See if this is still neccesary for RAVENS + # # post fix + # if !get(data_math, "is_kron_reduced", false) + # #TODO fix this in place / throw error instead? IEEE8500 leads to switches + # # with 3x3 R matrices but only 1 phase + # #NOTE: Don't do this when kron-reducing, it will undo the padding + # _slice_branches!(data_math) + # end + + find_conductor_ids!(data_math) + _map_conductor_ids!(data_math) + + # TODO: See if this is still neccesary for RAVENS + _map_settings_vbases_default!(data_math) + +end + + +"converts ravens connectivity_node components into mathematical bus components" +function _map_ravens2math_connectivity_node!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) + + for (name, ravens_obj) in get(data_ravens, "ConnectivityNode", Dict{String,Any}()) + + math_obj = _init_math_obj_ravens("bus", name, ravens_obj, length(data_math["bus"])+1; pass_props=pass_props) + math_obj["bus_i"] = math_obj["index"] + math_obj["source_id"] = "bus.$name" + + # default bus_type, change as elements are added (e.g., load, generator, source). + math_obj["bus_type"] = 1 + + # TODO: needed? - default grounded + math_obj["grounded"] = Bool[0, 0, 0] + + ## TODO + # # take care of grounding; convert to shunt if lossy + # grounded_perfect, shunts = _convert_grounding(ravens_obj["terminals"], ravens_obj["grounded"], ravens_obj["rg"], ravens_obj["xg"]) + + # math_obj["grounded"] = grounded_perfect + # to_sh = [] + # for (sh_connections, sh_y) in shunts + # sh_index = length(data_math["shunt"]) + 1 + # data_math["shunt"]["$sh_index"] = Dict( + # "index" => sh_index, + # "shunt_bus" => math_obj["bus_i"], + # "connections" => sh_connections, + # "gs" => real.(sh_y), + # "bs" => imag.(sh_y), + # ) + # push!(to_sh, "shunt.$sh_index") + # end + + if haskey(ravens_obj, "SvVoltage.v") + math_obj["vm"] = ravens_obj["SvVoltage.v"] + end + + if haskey(ravens_obj, "SvVoltage.angle") + math_obj["va"] = ravens_obj["SvVoltage.angle"] + end + + # TODO: add vm_pair_lb/ub (may not be needed!) + math_obj["vm_pair_lb"] = Tuple{Any, Any, Real}[] + math_obj["vm_pair_ub"] = Tuple{Any, Any, Real}[] + + data_math["bus"]["$(math_obj["index"])"] = math_obj + + if !haskey(data_math, "bus_lookup") + data_math["bus_lookup"] = Dict{Any,Int}() + end + + data_math["bus_lookup"][name] = math_obj["index"] + + push!(data_math["map"], Dict{String,Any}( + "from" => name, + "to" => "bus.$(math_obj["index"])", + "unmap_function" => "_map_math2ravens_bus!", + )) + end +end + + +"converts ravensineering conductors (e.g., ACLineSegments) into mathematical branches" +function _map_ravens2math_conductor!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) + + _data_ravens_conductor = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["Conductor"] + + for (name, ravens_obj) in get(_data_ravens_conductor, "ACLineSegment", Dict{Any,Dict{String,Any}}()) + + math_obj = _init_math_obj_ravens("ac_line_segment", name, ravens_obj, length(data_math["branch"])+1; pass_props=pass_props) + + nphases = length(ravens_obj["ACLineSegment.ACLineSegmentPhase"]) + + f_connectivity_node = replace(split(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"], "::")[2], "'" => "") + t_connectivity_node = replace(split(ravens_obj["ConductingEquipment.Terminals"][2]["Terminal.ConnectivityNode"], "::")[2], "'" => "") + math_obj["f_bus"] = data_math["bus_lookup"][f_connectivity_node] + math_obj["t_bus"] = data_math["bus_lookup"][t_connectivity_node] + + # define the number of terminals (i.e., phases) that the bus/es have, based on the lines + if nphases >= 3 + data_math["bus"][string(math_obj["f_bus"])]["terminals"]= [i for i = 1:nphases] + data_math["bus"][string(math_obj["t_bus"])]["terminals"]= [i for i = 1:nphases] + else + _terminals = Vector{Int64}() + for phase_info in ravens_obj["ACLineSegment.ACLineSegmentPhase"] + phase = phase_info["ACLineSegmentPhase.phase"] + if phase == "SinglePhaseKind.A" + push!(_terminals, 1) + elseif phase == "SinglePhaseKind.B" + push!(_terminals, 2) + elseif phase == "SinglePhaseKind.C" + push!(_terminals, 3) + else + @error("Terminals/Phases for buses '$(f_connectivity_node)' and '$(t_connectivity_node)' not recognized. Check your model!") + end + end + data_math["bus"][string(math_obj["f_bus"])]["terminals"]= _terminals + data_math["bus"][string(math_obj["t_bus"])]["terminals"]= _terminals + end + + # Initilize vmin and vmax in buses + data_math["bus"][string(math_obj["f_bus"])]["vmin"] = fill(0.0, nphases) + data_math["bus"][string(math_obj["f_bus"])]["vmax"] = fill(Inf, nphases) + + data_math["bus"][string(math_obj["t_bus"])]["vmin"] = fill(0.0, nphases) + data_math["bus"][string(math_obj["t_bus"])]["vmax"] = fill(Inf, nphases) + + #------------------------------------------------------------------------------- + + # f_ and t_connections for the lines/branches + math_obj["f_connections"] = data_math["bus"][string(math_obj["f_bus"])]["terminals"] + math_obj["t_connections"] = data_math["bus"][string(math_obj["t_bus"])]["terminals"] + + + _perlengthimpedance_name = replace(split(ravens_obj["ACLineSegment.PerLengthImpedance"], "::")[2], "'" => "") + _perlengthimpedance_data = data_ravens["PerLengthLineParameter"]["PerLengthImpedance"]["PerLengthPhaseImpedance"][_perlengthimpedance_name] + + math_obj["br_r"] = _impedance_conversion_ravens(_perlengthimpedance_data, ravens_obj, "PhaseImpedanceData.r") + math_obj["br_x"] = _impedance_conversion_ravens(_perlengthimpedance_data, ravens_obj, "PhaseImpedanceData.x") + + # b is given in mhos in CIM-RAVENS schema + math_obj["b_fr"] = _admittance_conversion_ravens(_perlengthimpedance_data, ravens_obj, "PhaseImpedanceData.b") + math_obj["b_to"] = _admittance_conversion_ravens(_perlengthimpedance_data, ravens_obj, "PhaseImpedanceData.b") + + # g is given in mhos in CIM-RAVENS schema + math_obj["g_fr"] = _admittance_conversion_ravens(_perlengthimpedance_data, ravens_obj, "PhaseImpedanceData.g") + math_obj["g_to"] = _admittance_conversion_ravens(_perlengthimpedance_data, ravens_obj, "PhaseImpedanceData.g") + + ## TODO:: these do not appear in JSON schema, are they needed? if yes, we need to represent them on CIM-RAVENS schema + math_obj["angmin"] = get(ravens_obj, "vad_lb", fill(-60.0, nphases)) + math_obj["angmax"] = get(ravens_obj, "vad_ub", fill( 60.0, nphases)) + + # Operational Limits + _oplimitset_id = replace(split(ravens_obj["ConductingEquipment.Terminals"][1]["ACDCTerminal.OperationalLimitSet"], "::")[2], "'" => "") + _oplimitset = data_ravens["OperationalLimitSet"][_oplimitset_id]["OperationalLimitSet.OperationalLimitValue"][2] # [1] is Normal amps, [2] is Emergency amps - by default use emerg amps + + for (f_key, t_key) in [("CurrentLimit.value", "c_rating_a"), ("CurrentLimit.value", "c_rating_b"), ("CurrentLimit.value", "c_rating_c"), + ("ApparentPowerLimit.value", "rate_a"), ("ApparentPowerLimit.value", "rate_b"), ("ApparentPowerLimit.value", "rate_c")] + math_obj[t_key] = haskey(_oplimitset, f_key) ? fill(_oplimitset[f_key], nphases) : fill(Inf, nphases) + end + + math_obj["br_status"] = get(ravens_obj, "ConductingEquipment.SvStatus", 1) + + data_math["branch"]["$(math_obj["index"])"] = math_obj + + push!(data_math["map"], Dict{String,Any}( + "from" => name, + "to" => "branch.$(math_obj["index"])", + "unmap_function" => "_map_math2ravens_line!", + )) + end + +end + +# TODO: Transformers need a lot of changes/refactors!!! +"converts ravensineering n-winding transformers into mathematical ideal 2-winding lossless transformer branches and impedance branches to represent the loss model" +function _map_ravens2math_power_transformer!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) + + _data_ravens_transformer = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"] + + for (name, ravens_obj) in get(_data_ravens_transformer, "PowerTransformer", Dict{Any,Dict{String,Any}}()) + + # Build map first, so we can update it as we decompose the transformer + push!(data_math["map"], Dict{String,Any}( + "from" => name, + "to" => String[], + "unmap_function" => "_map_math2ravens_transformer!", + )) + + to_map = data_math["map"][end]["to"] + + # _apply_xfmrcode!(ravens_obj, data_ravens) + + # PowerTransformerTank + if haskey(ravens_obj, "PowerTransformer.TransformerTank") + + @info "PowerTransformerTank ENTER" + @assert all(haskey(ravens_obj, k) for k in ["f_bus", "t_bus", "f_connections", "t_connections"]) "Incomplete definition of AL2W tranformer $name, aborting ravens2math conversion" + + nphases = length(ravens_obj["f_connections"]) + + math_obj = Dict{String,Any}( + "name" => name, + "source_id" => ravens_obj["source_id"], + "f_bus" => data_math["bus_lookup"][ravens_obj["f_bus"]], + "t_bus" => data_math["bus_lookup"][ravens_obj["t_bus"]], + "f_connections" => ravens_obj["f_connections"], + "t_connections" => ravens_obj["t_connections"], + "configuration" => get(ravens_obj, "configuration", WYE), + "tm_nom" => get(ravens_obj, "tm_nom", 1.0), + "tm_set" => get(ravens_obj, "tm_set", fill(1.0, nphases)), + "tm_fix" => get(ravens_obj, "tm_fix", fill(true, nphases)), + "polarity" => get(ravens_obj, "polarity", -1), + "sm_ub" => get(ravens_obj, "sm_ub", Inf), + "cm_ub" => get(ravens_obj, "cm_ub", Inf), + "status" => Int(get(ravens_obj, "status", ENABLED)), + "index" => length(data_math["transformer"])+1 + ) + + for k in [["tm_lb", "tm_ub"]; pass_props] + if haskey(ravens_obj, k) + math_obj[k] = ravens_obj[k] + end + end + + data_math["transformer"]["$(math_obj["index"])"] = math_obj + + push!(to_map, "transformer.$(math_obj["index"])") + + + # PowerTransformerEnd + else + + nrw = length(ravens_obj["bus"]) + + for w in 1:length(ravens_obj["PowerTransformer.PowerTransformerEnd"]) + + vnom = ravens_obj["PowerTransformer.PowerTransformerEnd"][w]["PowerTransformerEnd.ratedU"] + snom = ravens_obj["PowerTransformer.PowerTransformerEnd"][w]["PowerTransformerEnd.ratedS"] + + # calculate zbase in which the data is specified, and convert to SI + zbase = (vnom.^2) ./ snom + + # x_sc is specified with respect to first winding + x_sc = ravens_obj["xsc"] .* zbase[1] + + # rs is specified with respect to each winding + r_s = ravens_obj["rw"] .* zbase + + g_sh = (ravens_obj["noloadloss"]*snom[1])/vnom[1]^2 + b_sh = -(ravens_obj["cmag"]*snom[1])/vnom[1]^2 + + # data is measured externally, but we now refer it to the internal side + ratios = vnom/data_ravens["settings"]["voltage_scale_factor"] + x_sc = x_sc./ratios[1]^2 + r_s = r_s./ratios.^2 + g_sh = g_sh*ratios[1]^2 + b_sh = b_sh*ratios[1]^2 + + # convert x_sc from list of upper triangle elements to an explicit dict + y_sh = g_sh + im*b_sh + z_sc = Dict([(key, im*x_sc[i]) for (i,key) in enumerate([(i,j) for i in 1:nrw for j in i+1:nrw])]) + + dims = length(ravens_obj["tm_set"][1]) + transformer_t_bus_w = _build_loss_model!(data_math, name, to_map, r_s, z_sc, y_sh,ravens_obj["connections"][1]; nphases=dims, status=Int(ravens_obj["status"] == ENABLED)) + + # 2-WINDING TRANSFORMER + # make virtual bus and mark it for reduction + tm_nom = ravens_obj["configuration"][w]==DELTA ? ravens_obj["vm_nom"][w]*sqrt(3) : ravens_obj["vm_nom"][w] + transformer_2wa_obj = Dict{String,Any}( + "name" => "_virtual_transformer.$name.$w", + "source_id" => "_virtual_transformer.$(ravens_obj["source_id"]).$w", + "f_bus" => data_math["bus_lookup"][ravens_obj["bus"][w]], + "t_bus" => transformer_t_bus_w[w], + "tm_nom" => tm_nom, + "f_connections" => ravens_obj["connections"][w], + "t_connections" => get(data_math, "is_kron_reduced", false) ? ravens_obj["connections"][1] : collect(1:dims+1), + "configuration" => ravens_obj["configuration"][w], + "polarity" => ravens_obj["polarity"][w], + "tm_set" => ravens_obj["tm_set"][w], + "tm_fix" => ravens_obj["tm_fix"][w], + "sm_ub" => get(ravens_obj, "sm_ub", Inf), + "cm_ub" => get(ravens_obj, "cm_ub", Inf), + "status" => ravens_obj["status"] == DISABLED ? 0 : 1, + "index" => length(data_math["transformer"])+1 + ) + + for prop in [["tm_lb", "tm_ub", "tm_step"]; pass_props] + if haskey(ravens_obj, prop) + transformer_2wa_obj[prop] = ravens_obj[prop][w] + end + end + + data_math["transformer"]["$(transformer_2wa_obj["index"])"] = transformer_2wa_obj + + # add regcontrol items to math model + if haskey(ravens_obj,"controls") && !all(data_math["transformer"]["$(transformer_2wa_obj["index"])"]["tm_fix"]) + reg_obj = Dict{String,Any}( + "vreg" => ravens_obj["controls"]["vreg"][w], + "band" => ravens_obj["controls"]["band"][w], + "ptratio" => ravens_obj["controls"]["ptratio"][w], + "ctprim" => ravens_obj["controls"]["ctprim"][w], + "r" => ravens_obj["controls"]["r"][w], + "x" => ravens_obj["controls"]["x"][w], + ) + data_math["transformer"]["$(transformer_2wa_obj["index"])"]["controls"] = reg_obj + end + + if w==3 && ravens_obj["polarity"][w]==-1 # identify center-tapped transformer and mark all secondary-side nodes as triplex by adding va_start + default_va = [0, -120, 120][ravens_obj["connections"][1][1]] + data_math["bus"]["$(transformer_2wa_obj["f_bus"])"]["va_start"] = haskey(data_ravens["bus"][ravens_obj["bus"][w]],"va_start") ? data_ravens["bus"][ravens_obj["bus"][w]]["va_start"] : [default_va, (default_va+180)] + idx = 0 + bus_ids = [] + t_bus = haskey(data_ravens, "line") ? [data["t_bus"] for (_,data) in data_ravens["line"] if data["f_bus"] == ravens_obj["bus"][w]] : [] + while length(t_bus)>0 || idx "") + + # Initialize energy consumer object + math_obj = _init_math_obj_ravens("energy_consumer", name, ravens_obj, length(data_math["load"])+1; pass_props=pass_props) + + # Get Bus/ConnectivityNode + connectivity_node = replace(split(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"], "::")[2], "'" => "") + math_obj["load_bus"] = data_math["bus_lookup"][connectivity_node] + + # Model of the Load/EnergyConsumer + if load_response_characts == "Constant Z" + + elseif load_response_characts == "Motor" + + elseif load_response_characts == "Mix Motor/Res" + + elseif load_response_characts == "Constant I" + + elseif load_response_characts == "Variable P, Fixed Q" + + elseif load_response_characts == "Variable P, Fixed X" + + # "Constant kVA" : default + else + + if load_response_characts != "Constant kVA" + @warn("Load model (response characteristic) for $(name) not supported! Defaulting to 'Constant kVA'") + end + + # Add the model of the load based on loadresponsecharacteristic + math_obj["model"] = POWER + + # P and Q consumption + math_obj["pd"] = [ravens_obj["EnergyConsumer.p"]] + math_obj["qd"] = [ravens_obj["EnergyConsumer.q"]] + + end + + # Vnom + base_voltage_ref = replace(split(ravens_obj["ConductingEquipment.BaseVoltage"], "::")[2], "'" => "") + math_obj["vnom_kv"] = data_ravens["BaseVoltage"][base_voltage_ref]["BaseVoltage.nominalVoltage"] + + # Get voltage bounds for specific bus connected (TODO: see if it can be coverted to standalone function to avoid repetition) + bus_info = string(math_obj["load_bus"]) + bus_conn = data_math["bus"][bus_info] + + base_voltage_id = replace(split(ravens_obj["ConductingEquipment.BaseVoltage"], "::")[2], "'" => "") + base_voltage = data_ravens["BaseVoltage"][base_voltage_id]["BaseVoltage.nominalVoltage"] + op_limit_id = replace(split(data_ravens["ConnectivityNode"][connectivity_node]["ConnectivityNode.OperationalLimitSet"], "::")[2], "'" => "") + # op_limit_max = data_ravens["OperationalLimitSet"][op_limit_id]["OperationalLimitSet.OperationalLimitValue"][1]["VoltageLimit.value"]./base_voltage + # op_limit_min = data_ravens["OperationalLimitSet"][op_limit_id]["OperationalLimitSet.OperationalLimitValue"][2]["VoltageLimit.value"]./base_voltage + op_limit_max = data_ravens["OperationalLimitSet"][op_limit_id]["OperationalLimitSet.OperationalLimitValue"][1]["VoltageLimit.value"] + op_limit_min = data_ravens["OperationalLimitSet"][op_limit_id]["OperationalLimitSet.OperationalLimitValue"][2]["VoltageLimit.value"] + + _connections = Vector{Int64}() + if haskey(ravens_obj, "EnergyConsumer.EnergyConsumerPhase") + for phase_info in ravens_obj["EnergyConsumer.EnergyConsumerPhase"] + phase = phase_info["EnergyConsumerPhase.phase"] + if phase == "SinglePhaseKind.A" + phase_index = findfirst(==(1), bus_conn["terminals"]) + bus_conn["vmax"][phase_index] = op_limit_max + bus_conn["vmin"][phase_index] = op_limit_min + push!(_connections, 1) + elseif phase == "SinglePhaseKind.B" + phase_index = findfirst(==(2), bus_conn["terminals"]) + bus_conn["vmax"][phase_index] = op_limit_max + bus_conn["vmin"][phase_index] = op_limit_min + push!(_connections, 2) + elseif phase == "SinglePhaseKind.C" + phase_index = findfirst(==(3), bus_conn["terminals"]) + bus_conn["vmax"][phase_index] = op_limit_max + bus_conn["vmin"][phase_index] = op_limit_min + push!(_connections, 3) + else + @error("Terminals/Phases for buses '$(f_connectivity_node)' and '$(t_connectivity_node)' not recognized. Check your model!") + end + end + math_obj["connections"] = _connections + else + # assumes it is a three-phase connection + N = length(bus_conn["terminals"]) + bus_conn["vmax"] = fill(op_limit_max, N) + bus_conn["vmin"] = fill(op_limit_min, N) + math_obj["connections"] = bus_conn["terminals"] + end + + # TODO: Configuration + _config = ravens_obj["EnergyConsumer.phaseConnection"] + if _config == "PhaseShuntConnectionKind.Y" + math_obj["configuration"] = WYE + elseif _config == "PhaseShuntConnectionKind.D" + math_obj["configuration"] = DELTA + elseif _config == "PhaseShuntConnectionKind.Yn" + elseif _config == "PhaseShuntConnectionKind.I" + elseif _config == "PhaseShuntConnectionKind.G" + else + @error("Configuration of load $(name) is not supported.") + end + + # Status + math_obj["status"] = ravens_obj["ConductingEquipment.SvStatus"] + + # TODO: Dispatchable? default=0 + math_obj["dispatchable"] = 0 + + # Index + data_math["load"]["$(math_obj["index"])"] = math_obj + + # TODO: Assign 'grounding' to corresponding connectivity node + if ravens_obj["EnergyConsumer.grounded"] == "true" + bus_conn["grounded"] = Bool[0, 0, 0] + end + + # Revise bus_type of connectivity node to PQ bus + bus_conn["bus_type"] = 1 + + push!(data_math["map"], Dict{String,Any}( + "from" => name, + "to" => "load.$(math_obj["index"])", + "unmap_function" => "_map_math2ravens_load!", + )) + + end +end + + +#TODO: +"converts ravensineering voltage sources into mathematical generators and (if needed) impedance branches to represent the loss model" +function _map_ravens2math_energy_source!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) + + _data_ravens_energyconnection = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"] + + for (name, ravens_obj) in get(_data_ravens_energyconnection, "EnergySource", Dict{String,Any}()) + + math_obj = _init_math_obj_ravens("energy_source", name, ravens_obj, length(data_math["gen"])+1; pass_props=pass_props) + math_obj["name"] = "_virtual_gen.energy_source.$name" + + # get connectivity node info. (bus info) + connectivity_node = replace(split(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"], "::")[2], "'" => "") + math_obj["gen_bus"] = gen_bus = data_math["bus_lookup"][connectivity_node] + bus_conn = data_math["bus"][string(gen_bus)] + + # Revise bus_type of connectivity node to PV bus + bus_conn["bus_type"] = 3 + + nconductors = 0 + _connections = Vector{Int64}() + if haskey(ravens_obj, "EnergySource.EnergySourcePhase") + + nconductors = length(ravens_obj["EnergySource.EnergySourcePhase"]) + # TODO: how to redefine the kron reduction? + # nphases = get(ravens_obj, "configuration", WYE) == WYE && !get(data_ravens, "is_kron_reduced", false) ? nconductors - 1 : nconductors + nphases = nconductors + + for phase_info in ravens_obj["EnergySource.EnergySourcePhase"] + phase = phase_info["EnergySourcePhase.phase"] + if phase == "SinglePhaseKind.A" + push!(_connections, 1) + elseif phase == "SinglePhaseKind.B" + push!(_connections, 2) + elseif phase == "SinglePhaseKind.C" + push!(_connections, 3) + else + @error("Connections for energy source '$(name)' not recognized. Check your model!") + end + end + + math_obj["connections"] = _connections + else + # assumes it is a three-phase connection + nconductors = length(bus_conn["terminals"]) + # TODO: how to redefine the kron reduction? we need + # nphases = get(ravens_obj, "configuration", WYE) == WYE && !get(data_ravens, "is_kron_reduced", false) ? nconductors - 1 : nconductors + nphases = nconductors + math_obj["connections"] = bus_conn["terminals"] + end + + math_obj["gen_status"] = status = Int(ravens_obj["ConductingEquipment.SvStatus"]) + + # Vnom and add vbases_default from energy source + base_voltage_ref = replace(split(ravens_obj["ConductingEquipment.BaseVoltage"], "::")[2], "'" => "") + vnom = data_ravens["BaseVoltage"][base_voltage_ref]["BaseVoltage.nominalVoltage"] / sqrt(nphases) + data_math["settings"]["vbases_default"][connectivity_node] = vnom + + # P, Q, Vg, etc. + math_obj["pg"] = get(ravens_obj, "EnergySource.activePower", fill(0.0, nphases)).*fill(1.0, nphases) + math_obj["qg"] = get(ravens_obj, "EnergySource.reactivePower", fill(0.0, nphases)).*fill(1.0, nphases) + math_obj["vg"] = get(ravens_obj, "EnergySource.voltageMagnitude", fill(1.0, nphases)).*fill(1.0, nphases) + math_obj["pmin"] = get(ravens_obj, "EnergySource.pMin", fill(-Inf, nphases)).*fill(1.0, nphases) + math_obj["pmax"] = get(ravens_obj, "EnergySource.pMax", fill( Inf, nphases)).*fill(1.0, nphases) + math_obj["qmin"] = get(ravens_obj, "EnergySource.qMin", fill(-Inf, nphases)).*fill(1.0, nphases) + math_obj["qmax"] = get(ravens_obj, "EnergySource.qMax", fill( Inf, nphases)).*fill(1.0, nphases) + + #TODO: how to define configuration from terminals or add a connectionKind parameter? add to RAVENS schema? + math_obj["configuration"] = get(ravens_obj, "EnergySource.connectionKind", WYE) + + # TODO: Do we need a control_mode parameter for this? add to RAVENS schema + math_obj["control_mode"] = control_mode = Int(get(ravens_obj, "EnergySource.connectionKind", ISOCHRONOUS)) + math_obj["source_id"] = "energy_source.$name" + + # TODO: inside this function, there are elements that do not exist in the RAVENS schema, so the default is used. + _add_gen_cost_model!(math_obj, ravens_obj) + + map_to = "gen.$(math_obj["index"])" + + if !all(isapprox.(get(ravens_obj, "EnergySource.r", zeros(1, 1)), 0)) && !all(isapprox.(get(ravens_obj, "EnergySource.x", zeros(1, 1)), 0)) + + # Revise bus_type of connectivity node to PV bus (virtual bus becomes the new slack bus) + bus_conn["bus_type"] = 1 + + f_bus = deepcopy(data_math["bus"]["$(math_obj["gen_bus"])"]) + + bus_obj = Dict{String,Any}( + "bus_i" => length(data_math["bus"])+1, + "index" => length(data_math["bus"])+1, + "terminals" => math_obj["connections"], + # TODO: grounded energyosurce default? + "grounded" => Bool[0, 0, 0], + "name" => "_virtual_bus.energy_source.$name", + "bus_type" => status == 0 ? 4 : control_mode == Int(ISOCHRONOUS) ? 3 : 2, + "vm" => fill(ravens_obj["EnergySource.voltageMagnitude"], nphases), + "va" => rad2deg.(_wrap_to_pi.([-2*pi/nphases*(i-1)+deg2rad(ravens_obj["EnergySource.voltageAngle"]) for i in 1:nphases])), + "vmin" => fill(ravens_obj["EnergySource.voltageMagnitude"], nphases), + "vmax" => fill(ravens_obj["EnergySource.voltageMagnitude"], nphases), + "vm_pair_lb" => deepcopy(get(ravens_obj, "EnergySource.vpairMin", Tuple{Any,Any,Real}[])), + "vm_pair_ub" => deepcopy(get(ravens_obj, "EnergySource.vpairMax", Tuple{Any,Any,Real}[])), + "source_id" => "energy_source.$name", + ) + + # TODO: + # for (i,t) in enumerate(math_obj["connections"]) + # if data_math["bus"]["$(data_math["bus_lookup"][ravens_obj["bus"]])"]["grounded"][i] + # bus_obj["vm"][i] = 0 + # bus_obj["vmin"][i] = 0 + # bus_obj["vmax"][i] = Inf + # end + # end + + math_obj["gen_bus"] = gen_bus = bus_obj["bus_i"] + + data_math["bus"]["$(bus_obj["index"])"] = bus_obj + + branch_obj = Dict{String,Any}( + "name" => "_virtual_branch.energy_source.$name", + "source_id" => "energy_source.$name", + "f_bus" => bus_obj["bus_i"], + "t_bus" => data_math["bus_lookup"][connectivity_node], + # TODO: + "f_connections" => math_obj["connections"], + "t_connections" => math_obj["connections"], + "angmin" => fill(-10.0, nconductors), + "angmax" => fill( 10.0, nconductors), + "c_rating_a" => fill(Inf, nconductors), + "br_status" => status, + # "br_r" => _impedance_conversion_ravens(data_ravens, ravens_obj, "rs"), + # "br_x" => _impedance_conversion_ravens(data_ravens, ravens_obj, "xs"), + "br_r" => ravens_obj["EnergySource.r"], + "br_x" => ravens_obj["EnergySource.x"], + "g_fr" => zeros(nconductors, nconductors), + "g_to" => zeros(nconductors, nconductors), + "b_fr" => zeros(nconductors, nconductors), + "b_to" => zeros(nconductors, nconductors), + "index" => length(data_math["branch"])+1 + ) + + data_math["branch"]["$(branch_obj["index"])"] = branch_obj + + map_to = [map_to, "bus.$(bus_obj["index"])", "branch.$(branch_obj["index"])"] + else + vm_lb = control_mode == Int(ISOCHRONOUS) ? ravens_obj["EnergySource.voltageMagnitude"] : get(ravens_obj, "EnergySource.vMin", fill(0.0, nphases)) + vm_ub = control_mode == Int(ISOCHRONOUS) ? ravens_obj["EnergySource.voltageMagnitude"] : get(ravens_obj, "EnergySource.vMax", fill(Inf, nphases)) + + data_math["bus"]["$gen_bus"]["vmin"] = [vm_lb..., [0.0 for n in 1:(nconductors-nphases)]...] + data_math["bus"]["$gen_bus"]["vmax"] = [vm_ub..., [Inf for n in 1:(nconductors-nphases)]...] + data_math["bus"]["$gen_bus"]["vm"] = [ravens_obj["EnergySource.voltageMagnitude"]..., [0.0 for n in 1:(nconductors-nphases)]...] + data_math["bus"]["$gen_bus"]["va"] = [ravens_obj["EnergySource.voltageAngle"]..., [0.0 for n in 1:(nconductors-nphases)]...] + + bus_type = data_math["bus"]["$gen_bus"]["bus_type"] + data_math["bus"]["$gen_bus"]["bus_type"] = _compute_bus_type(bus_type, status, control_mode) + end + + data_math["gen"]["$(math_obj["index"])"] = math_obj + + push!(data_math["map"], Dict{String,Any}( + "from" => name, + "to" => map_to, + "unmap_function" => "_map_math2ravens_energy_source!", + )) + end +end + + +"converts ravensineering switches into mathematical switches and (if neeed) impedance branches to represent loss model" +function _map_ravens2math_switch!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) + # TODO enable real switches (right now only using vitual lines) + for (name, ravens_obj) in get(data_ravens, "switch", Dict{Any,Dict{String,Any}}()) + # TODO + end +end diff --git a/src/data_model/utils_ravens.jl b/src/data_model/utils_ravens.jl new file mode 100644 index 000000000..cfa7a5821 --- /dev/null +++ b/src/data_model/utils_ravens.jl @@ -0,0 +1,52 @@ + +"initializes the base math object of any type" +function _init_math_obj_ravens(obj_type::String, eng_id::Any, eng_obj::Dict{String,<:Any}, index::Int; pass_props::Vector{String}=String[])::Dict{String,Any} + math_obj = Dict{String,Any}( + "name" => "$eng_id", + "source_id" => "$obj_type.$eng_id" + ) + + math_obj["index"] = index + + return math_obj +end + + +"converts impendance in Ohm/m by multiplying by length" +function _impedance_conversion_ravens(data_eng::Dict{String,Any}, eng_obj::Dict{String,Any}, key::String) + + _conductor_count = data_eng["PerLengthPhaseImpedance.conductorCount"] + _impedance_matrix = zeros(Float64, _conductor_count, _conductor_count) + + _index = 1 + for i in 1:_conductor_count + for j in 1:i + _impedance_matrix[i, j] = get(data_eng["PerLengthPhaseImpedance.PhaseImpedanceData"][_index], key, 0.0) + _impedance_matrix[j, i] = get(data_eng["PerLengthPhaseImpedance.PhaseImpedanceData"][_index], key, 0.0) + _index += 1 + end + end + + return _impedance_matrix .* get(eng_obj, "Conductor.length", 1.0) +end + + +"converts admittance by multiplying by 2πωl" +function _admittance_conversion_ravens(data_eng::Dict{String,<:Any}, eng_obj::Dict{String,<:Any}, key::String) + + _conductor_count = data_eng["PerLengthPhaseImpedance.conductorCount"] + _admittance_matrix = zeros(Float64, _conductor_count, _conductor_count) + + _index = 1 + for i in 1:_conductor_count + for j in 1:i + _admittance_matrix[i, j] = get(data_eng["PerLengthPhaseImpedance.PhaseImpedanceData"][_index], key, 0.0) + _admittance_matrix[j, i] = get(data_eng["PerLengthPhaseImpedance.PhaseImpedanceData"][_index], key, 0.0) + _index += 1 + end + end + + # TODO: Default frequency - get actual frequency from ravens data + freq = 60.0 + return _admittance_matrix .* get(eng_obj, "Conductor.length", 1.0) .* freq ./ 1e2 # divide by 2 to get both sides _to and _fr +end diff --git a/src/prob/common.jl b/src/prob/common.jl index d0f9ea408..7f86adf3d 100644 --- a/src/prob/common.jl +++ b/src/prob/common.jl @@ -129,6 +129,49 @@ function instantiate_mc_model( end + +function instantiate_mc_model_ravens( + data::Dict{String,<:Any}, + model_type::Type, + build_method::Function; + ref_extensions::Vector{<:Function}=Function[], + multinetwork::Bool=ismultinetwork(data), + global_keys::Set{String}=Set{String}(), + ravens2math_extensions::Vector{<:Function}=Function[], + ravens2math_passthrough::Dict{String,<:Vector{<:String}}=Dict{String,Vector{String}}(), + make_pu_extensions::Vector{<:Function}=Function[], + kwargs... + ) + + # @info "$(data)" + + @info "Converting CIM-RAVENS data model to MATHEMATICAL first to build JuMP model" + + data = transform_data_model_ravens( + data; + multinetwork=multinetwork, + global_keys=global_keys, + ravens2math_extensions=ravens2math_extensions, + ravens2math_passthrough=ravens2math_passthrough, + make_pu_extensions=make_pu_extensions, + ) + + @info "$(data["load"])" + + DEFINIDOEN_instantiate_mc_model + + return _IM.instantiate_model( + data, + model_type, + build_method, + ref_add_core!, + union(_pmd_math_global_keys, global_keys), + pmd_it_sym; + ref_extensions=ref_extensions, + kwargs... + ) +end + """ solve_mc_model( data::Dict{String,<:Any}, From 542f3dd20d8412848af228bf1a48902eb2e0a8b4 Mon Sep 17 00:00:00 2001 From: jjospina Date: Mon, 5 Aug 2024 13:16:38 -0600 Subject: [PATCH 02/27] WIP: add bases to certain elements - debugging changes --- src/data_model/transformations/eng2math.jl | 3 ++ src/data_model/transformations/ravens2math.jl | 31 ++++++++++--------- src/data_model/utils_ravens.jl | 4 +-- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/data_model/transformations/eng2math.jl b/src/data_model/transformations/eng2math.jl index f82208778..00bafc858 100644 --- a/src/data_model/transformations/eng2math.jl +++ b/src/data_model/transformations/eng2math.jl @@ -223,6 +223,9 @@ function _map_eng2math( apply_pmd!(_map_eng2math_nw!, data_math, _data_eng; eng2math_passthrough=eng2math_passthrough, eng2math_extensions=eng2math_extensions) + @info "$(data_math)" + gfdgfdgf + if ismultinetwork(data_eng) _collect_nw_maps!(data_math) _collect_nw_bus_lookups!(data_math) diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index b098de30f..cdb8cdfee 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -99,7 +99,7 @@ function _map_ravens2math( _settings = Dict("sbase_default" => basemva * 1e3, "voltage_scale_factor" => 1e3, "power_scale_factor" => 1e3, - "base_frequency" => 60.0, + "base_frequency" => get(_data_ravens, "BaseFrequency", 60.0), "vbases_default" => Dict{String,Real}() ) @@ -132,11 +132,11 @@ function _map_ravens2math( ) end + apply_pmd!(_map_ravens2math_nw!, data_math, _data_ravens; ravens2math_passthrough=ravens2math_passthrough, ravens2math_extensions=ravens2math_extensions) - @info "$(data_math)" - gfdgfdgf - apply_pmd!(_map_ravens2math_nw!, data_math, _data_ravens; ravens2math_passthrough=ravens2math_passthrough, ravens2math_extensions=ravens2math_extensions) + @info "$(data_math["branch"])" + gfdgfdgf if ismultinetwork(data_ravens) _collect_nw_maps!(data_math) @@ -193,6 +193,8 @@ end "converts ravens connectivity_node components into mathematical bus components" function _map_ravens2math_connectivity_node!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) + _voltage_scale_factor = data_math["settings"]["voltage_scale_factor"]*sqrt(3) + for (name, ravens_obj) in get(data_ravens, "ConnectivityNode", Dict{String,Any}()) math_obj = _init_math_obj_ravens("bus", name, ravens_obj, length(data_math["bus"])+1; pass_props=pass_props) @@ -224,7 +226,7 @@ function _map_ravens2math_connectivity_node!(data_math::Dict{String,<:Any}, data # end if haskey(ravens_obj, "SvVoltage.v") - math_obj["vm"] = ravens_obj["SvVoltage.v"] + math_obj["vm"] = (ravens_obj["SvVoltage.v"]/_voltage_scale_factor) end if haskey(ravens_obj, "SvVoltage.angle") @@ -311,12 +313,12 @@ function _map_ravens2math_conductor!(data_math::Dict{String,<:Any}, data_ravens: math_obj["br_x"] = _impedance_conversion_ravens(_perlengthimpedance_data, ravens_obj, "PhaseImpedanceData.x") # b is given in mhos in CIM-RAVENS schema - math_obj["b_fr"] = _admittance_conversion_ravens(_perlengthimpedance_data, ravens_obj, "PhaseImpedanceData.b") - math_obj["b_to"] = _admittance_conversion_ravens(_perlengthimpedance_data, ravens_obj, "PhaseImpedanceData.b") + math_obj["b_fr"] = _admittance_conversion_ravens(_perlengthimpedance_data, ravens_obj, "PhaseImpedanceData.b"; freq=data_math["settings"]["base_frequency"]) + math_obj["b_to"] = _admittance_conversion_ravens(_perlengthimpedance_data, ravens_obj, "PhaseImpedanceData.b"; freq=data_math["settings"]["base_frequency"]) # g is given in mhos in CIM-RAVENS schema - math_obj["g_fr"] = _admittance_conversion_ravens(_perlengthimpedance_data, ravens_obj, "PhaseImpedanceData.g") - math_obj["g_to"] = _admittance_conversion_ravens(_perlengthimpedance_data, ravens_obj, "PhaseImpedanceData.g") + math_obj["g_fr"] = _admittance_conversion_ravens(_perlengthimpedance_data, ravens_obj, "PhaseImpedanceData.g"; freq=data_math["settings"]["base_frequency"]) + math_obj["g_to"] = _admittance_conversion_ravens(_perlengthimpedance_data, ravens_obj, "PhaseImpedanceData.g"; freq=data_math["settings"]["base_frequency"]) ## TODO:: these do not appear in JSON schema, are they needed? if yes, we need to represent them on CIM-RAVENS schema math_obj["angmin"] = get(ravens_obj, "vad_lb", fill(-60.0, nphases)) @@ -644,6 +646,7 @@ end function _map_ravens2math_energy_source!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) _data_ravens_energyconnection = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"] + _voltage_scale_factor = data_math["settings"]["voltage_scale_factor"]*sqrt(3) for (name, ravens_obj) in get(_data_ravens_energyconnection, "EnergySource", Dict{String,Any}()) @@ -700,7 +703,7 @@ function _map_ravens2math_energy_source!(data_math::Dict{String,<:Any}, data_rav # P, Q, Vg, etc. math_obj["pg"] = get(ravens_obj, "EnergySource.activePower", fill(0.0, nphases)).*fill(1.0, nphases) math_obj["qg"] = get(ravens_obj, "EnergySource.reactivePower", fill(0.0, nphases)).*fill(1.0, nphases) - math_obj["vg"] = get(ravens_obj, "EnergySource.voltageMagnitude", fill(1.0, nphases)).*fill(1.0, nphases) + math_obj["vg"] = fill(get(ravens_obj, "EnergySource.voltageMagnitude", _voltage_scale_factor)/_voltage_scale_factor, nphases) math_obj["pmin"] = get(ravens_obj, "EnergySource.pMin", fill(-Inf, nphases)).*fill(1.0, nphases) math_obj["pmax"] = get(ravens_obj, "EnergySource.pMax", fill( Inf, nphases)).*fill(1.0, nphases) math_obj["qmin"] = get(ravens_obj, "EnergySource.qMin", fill(-Inf, nphases)).*fill(1.0, nphases) @@ -733,10 +736,10 @@ function _map_ravens2math_energy_source!(data_math::Dict{String,<:Any}, data_rav "grounded" => Bool[0, 0, 0], "name" => "_virtual_bus.energy_source.$name", "bus_type" => status == 0 ? 4 : control_mode == Int(ISOCHRONOUS) ? 3 : 2, - "vm" => fill(ravens_obj["EnergySource.voltageMagnitude"], nphases), + "vm" => fill(ravens_obj["EnergySource.voltageMagnitude"]/_voltage_scale_factor, nphases), "va" => rad2deg.(_wrap_to_pi.([-2*pi/nphases*(i-1)+deg2rad(ravens_obj["EnergySource.voltageAngle"]) for i in 1:nphases])), - "vmin" => fill(ravens_obj["EnergySource.voltageMagnitude"], nphases), - "vmax" => fill(ravens_obj["EnergySource.voltageMagnitude"], nphases), + "vmin" => fill(ravens_obj["EnergySource.voltageMagnitude"]/_voltage_scale_factor, nphases), + "vmax" => fill(ravens_obj["EnergySource.voltageMagnitude"]/_voltage_scale_factor, nphases), "vm_pair_lb" => deepcopy(get(ravens_obj, "EnergySource.vpairMin", Tuple{Any,Any,Real}[])), "vm_pair_ub" => deepcopy(get(ravens_obj, "EnergySource.vpairMax", Tuple{Any,Any,Real}[])), "source_id" => "energy_source.$name", @@ -787,7 +790,7 @@ function _map_ravens2math_energy_source!(data_math::Dict{String,<:Any}, data_rav data_math["bus"]["$gen_bus"]["vmin"] = [vm_lb..., [0.0 for n in 1:(nconductors-nphases)]...] data_math["bus"]["$gen_bus"]["vmax"] = [vm_ub..., [Inf for n in 1:(nconductors-nphases)]...] - data_math["bus"]["$gen_bus"]["vm"] = [ravens_obj["EnergySource.voltageMagnitude"]..., [0.0 for n in 1:(nconductors-nphases)]...] + data_math["bus"]["$gen_bus"]["vm"] = [ravens_obj["EnergySource.voltageMagnitude"]/_voltage_scale_factor..., [0.0 for n in 1:(nconductors-nphases)]...] data_math["bus"]["$gen_bus"]["va"] = [ravens_obj["EnergySource.voltageAngle"]..., [0.0 for n in 1:(nconductors-nphases)]...] bus_type = data_math["bus"]["$gen_bus"]["bus_type"] diff --git a/src/data_model/utils_ravens.jl b/src/data_model/utils_ravens.jl index cfa7a5821..55a63e7ee 100644 --- a/src/data_model/utils_ravens.jl +++ b/src/data_model/utils_ravens.jl @@ -32,7 +32,7 @@ end "converts admittance by multiplying by 2πωl" -function _admittance_conversion_ravens(data_eng::Dict{String,<:Any}, eng_obj::Dict{String,<:Any}, key::String) +function _admittance_conversion_ravens(data_eng::Dict{String,<:Any}, eng_obj::Dict{String,<:Any}, key::String; freq::Float64=60.0) _conductor_count = data_eng["PerLengthPhaseImpedance.conductorCount"] _admittance_matrix = zeros(Float64, _conductor_count, _conductor_count) @@ -46,7 +46,5 @@ function _admittance_conversion_ravens(data_eng::Dict{String,<:Any}, eng_obj::Di end end - # TODO: Default frequency - get actual frequency from ravens data - freq = 60.0 return _admittance_matrix .* get(eng_obj, "Conductor.length", 1.0) .* freq ./ 1e2 # divide by 2 to get both sides _to and _fr end From b5dea9733a3f29a8135c45baae7ebc007d2faf87 Mon Sep 17 00:00:00 2001 From: jjospina Date: Wed, 7 Aug 2024 11:03:44 -0600 Subject: [PATCH 03/27] WIP: revise case3 ravens to math model code. --- src/data_model/transformations/eng2math.jl | 3 -- src/data_model/transformations/ravens2math.jl | 40 +++++++++---------- src/data_model/utils_ravens.jl | 24 +++++++++++ src/prob/common.jl | 6 ++- 4 files changed, 47 insertions(+), 26 deletions(-) diff --git a/src/data_model/transformations/eng2math.jl b/src/data_model/transformations/eng2math.jl index 00bafc858..f82208778 100644 --- a/src/data_model/transformations/eng2math.jl +++ b/src/data_model/transformations/eng2math.jl @@ -223,9 +223,6 @@ function _map_eng2math( apply_pmd!(_map_eng2math_nw!, data_math, _data_eng; eng2math_passthrough=eng2math_passthrough, eng2math_extensions=eng2math_extensions) - @info "$(data_math)" - gfdgfdgf - if ismultinetwork(data_eng) _collect_nw_maps!(data_math) _collect_nw_bus_lookups!(data_math) diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index cdb8cdfee..8771d6196 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -134,10 +134,6 @@ function _map_ravens2math( apply_pmd!(_map_ravens2math_nw!, data_math, _data_ravens; ravens2math_passthrough=ravens2math_passthrough, ravens2math_extensions=ravens2math_extensions) - - @info "$(data_math["branch"])" - gfdgfdgf - if ismultinetwork(data_ravens) _collect_nw_maps!(data_math) _collect_nw_bus_lookups!(data_math) @@ -193,7 +189,7 @@ end "converts ravens connectivity_node components into mathematical bus components" function _map_ravens2math_connectivity_node!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) - _voltage_scale_factor = data_math["settings"]["voltage_scale_factor"]*sqrt(3) + _voltage_scale_factor_sqrt3 = data_math["settings"]["voltage_scale_factor"]*sqrt(3) for (name, ravens_obj) in get(data_ravens, "ConnectivityNode", Dict{String,Any}()) @@ -226,7 +222,7 @@ function _map_ravens2math_connectivity_node!(data_math::Dict{String,<:Any}, data # end if haskey(ravens_obj, "SvVoltage.v") - math_obj["vm"] = (ravens_obj["SvVoltage.v"]/_voltage_scale_factor) + math_obj["vm"] = (ravens_obj["SvVoltage.v"]/_voltage_scale_factor_sqrt3) end if haskey(ravens_obj, "SvVoltage.angle") @@ -511,6 +507,8 @@ end function _map_ravens2math_energy_consumer!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) _data_ravens_energyconnection = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"] + _power_scale_factor = data_math["settings"]["power_scale_factor"] + _voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] for (name, ravens_obj) in get(_data_ravens_energyconnection, "EnergyConsumer", Dict{Any,Dict{String,Any}}()) @@ -548,14 +546,14 @@ function _map_ravens2math_energy_consumer!(data_math::Dict{String,<:Any}, data_r math_obj["model"] = POWER # P and Q consumption - math_obj["pd"] = [ravens_obj["EnergyConsumer.p"]] - math_obj["qd"] = [ravens_obj["EnergyConsumer.q"]] + math_obj["pd"] = [ravens_obj["EnergyConsumer.p"]/_power_scale_factor] + math_obj["qd"] = [ravens_obj["EnergyConsumer.q"]/_power_scale_factor] end # Vnom base_voltage_ref = replace(split(ravens_obj["ConductingEquipment.BaseVoltage"], "::")[2], "'" => "") - math_obj["vnom_kv"] = data_ravens["BaseVoltage"][base_voltage_ref]["BaseVoltage.nominalVoltage"] + math_obj["vnom_kv"] = (data_ravens["BaseVoltage"][base_voltage_ref]["BaseVoltage.nominalVoltage"]/_voltage_scale_factor)/(sqrt(3)/2) # Get voltage bounds for specific bus connected (TODO: see if it can be coverted to standalone function to avoid repetition) bus_info = string(math_obj["load_bus"]) @@ -646,7 +644,8 @@ end function _map_ravens2math_energy_source!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) _data_ravens_energyconnection = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"] - _voltage_scale_factor = data_math["settings"]["voltage_scale_factor"]*sqrt(3) + _voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] + _voltage_scale_factor_sqrt3 = data_math["settings"]["voltage_scale_factor"]*sqrt(3) for (name, ravens_obj) in get(_data_ravens_energyconnection, "EnergySource", Dict{String,Any}()) @@ -698,18 +697,18 @@ function _map_ravens2math_energy_source!(data_math::Dict{String,<:Any}, data_rav # Vnom and add vbases_default from energy source base_voltage_ref = replace(split(ravens_obj["ConductingEquipment.BaseVoltage"], "::")[2], "'" => "") vnom = data_ravens["BaseVoltage"][base_voltage_ref]["BaseVoltage.nominalVoltage"] / sqrt(nphases) - data_math["settings"]["vbases_default"][connectivity_node] = vnom + data_math["settings"]["vbases_default"][connectivity_node] = vnom/_voltage_scale_factor # P, Q, Vg, etc. math_obj["pg"] = get(ravens_obj, "EnergySource.activePower", fill(0.0, nphases)).*fill(1.0, nphases) math_obj["qg"] = get(ravens_obj, "EnergySource.reactivePower", fill(0.0, nphases)).*fill(1.0, nphases) - math_obj["vg"] = fill(get(ravens_obj, "EnergySource.voltageMagnitude", _voltage_scale_factor)/_voltage_scale_factor, nphases) + math_obj["vg"] = fill(get(ravens_obj, "EnergySource.voltageMagnitude", _voltage_scale_factor_sqrt3)/_voltage_scale_factor_sqrt3, nphases) math_obj["pmin"] = get(ravens_obj, "EnergySource.pMin", fill(-Inf, nphases)).*fill(1.0, nphases) math_obj["pmax"] = get(ravens_obj, "EnergySource.pMax", fill( Inf, nphases)).*fill(1.0, nphases) math_obj["qmin"] = get(ravens_obj, "EnergySource.qMin", fill(-Inf, nphases)).*fill(1.0, nphases) math_obj["qmax"] = get(ravens_obj, "EnergySource.qMax", fill( Inf, nphases)).*fill(1.0, nphases) - #TODO: how to define configuration from terminals or add a connectionKind parameter? add to RAVENS schema? + # configuration math_obj["configuration"] = get(ravens_obj, "EnergySource.connectionKind", WYE) # TODO: Do we need a control_mode parameter for this? add to RAVENS schema @@ -736,10 +735,10 @@ function _map_ravens2math_energy_source!(data_math::Dict{String,<:Any}, data_rav "grounded" => Bool[0, 0, 0], "name" => "_virtual_bus.energy_source.$name", "bus_type" => status == 0 ? 4 : control_mode == Int(ISOCHRONOUS) ? 3 : 2, - "vm" => fill(ravens_obj["EnergySource.voltageMagnitude"]/_voltage_scale_factor, nphases), + "vm" => fill(ravens_obj["EnergySource.voltageMagnitude"]/_voltage_scale_factor_sqrt3, nphases), "va" => rad2deg.(_wrap_to_pi.([-2*pi/nphases*(i-1)+deg2rad(ravens_obj["EnergySource.voltageAngle"]) for i in 1:nphases])), - "vmin" => fill(ravens_obj["EnergySource.voltageMagnitude"]/_voltage_scale_factor, nphases), - "vmax" => fill(ravens_obj["EnergySource.voltageMagnitude"]/_voltage_scale_factor, nphases), + "vmin" => fill(ravens_obj["EnergySource.voltageMagnitude"]/_voltage_scale_factor_sqrt3, nphases), + "vmax" => fill(ravens_obj["EnergySource.voltageMagnitude"]/_voltage_scale_factor_sqrt3, nphases), "vm_pair_lb" => deepcopy(get(ravens_obj, "EnergySource.vpairMin", Tuple{Any,Any,Real}[])), "vm_pair_ub" => deepcopy(get(ravens_obj, "EnergySource.vpairMax", Tuple{Any,Any,Real}[])), "source_id" => "energy_source.$name", @@ -763,17 +762,14 @@ function _map_ravens2math_energy_source!(data_math::Dict{String,<:Any}, data_rav "source_id" => "energy_source.$name", "f_bus" => bus_obj["bus_i"], "t_bus" => data_math["bus_lookup"][connectivity_node], - # TODO: "f_connections" => math_obj["connections"], "t_connections" => math_obj["connections"], "angmin" => fill(-10.0, nconductors), "angmax" => fill( 10.0, nconductors), "c_rating_a" => fill(Inf, nconductors), "br_status" => status, - # "br_r" => _impedance_conversion_ravens(data_ravens, ravens_obj, "rs"), - # "br_x" => _impedance_conversion_ravens(data_ravens, ravens_obj, "xs"), - "br_r" => ravens_obj["EnergySource.r"], - "br_x" => ravens_obj["EnergySource.x"], + "br_r" => _impedance_conversion_ravens_energy_source(data_ravens, ravens_obj, "EnergySource.r", "EnergySource.r0"), + "br_x" => _impedance_conversion_ravens_energy_source(data_ravens, ravens_obj, "EnergySource.x", "EnergySource.x0"), "g_fr" => zeros(nconductors, nconductors), "g_to" => zeros(nconductors, nconductors), "b_fr" => zeros(nconductors, nconductors), @@ -790,7 +786,7 @@ function _map_ravens2math_energy_source!(data_math::Dict{String,<:Any}, data_rav data_math["bus"]["$gen_bus"]["vmin"] = [vm_lb..., [0.0 for n in 1:(nconductors-nphases)]...] data_math["bus"]["$gen_bus"]["vmax"] = [vm_ub..., [Inf for n in 1:(nconductors-nphases)]...] - data_math["bus"]["$gen_bus"]["vm"] = [ravens_obj["EnergySource.voltageMagnitude"]/_voltage_scale_factor..., [0.0 for n in 1:(nconductors-nphases)]...] + data_math["bus"]["$gen_bus"]["vm"] = [ravens_obj["EnergySource.voltageMagnitude"]/_voltage_scale_factor_sqrt3..., [0.0 for n in 1:(nconductors-nphases)]...] data_math["bus"]["$gen_bus"]["va"] = [ravens_obj["EnergySource.voltageAngle"]..., [0.0 for n in 1:(nconductors-nphases)]...] bus_type = data_math["bus"]["$gen_bus"]["bus_type"] diff --git a/src/data_model/utils_ravens.jl b/src/data_model/utils_ravens.jl index 55a63e7ee..27ca59a61 100644 --- a/src/data_model/utils_ravens.jl +++ b/src/data_model/utils_ravens.jl @@ -31,6 +31,30 @@ function _impedance_conversion_ravens(data_eng::Dict{String,Any}, eng_obj::Dict{ end +"converts impendance in Ohm/m by multiplying by length" +function _impedance_conversion_ravens_energy_source(data_eng::Dict{String,Any}, eng_obj::Dict{String,Any}, key1::String, key2::String) + # Default energy sources considered 3 phases + nphases = 3 + _impedance_matrix = zeros(Float64, nphases, nphases) + + z = get(eng_obj, key1, 0.0) + z0 = get(eng_obj, key2, 0.0) + + for i in 1:nphases + for j in 1:i + if(i==j) + _impedance_matrix[i, j] = z + ((z0 - z)/3) + else + _impedance_matrix[i, j] = (z0 - z)/3 + _impedance_matrix[j, i] = (z0 - z)/3 + end + end + end + + return _impedance_matrix .* get(eng_obj, "Conductor.length", 1.0) +end + + "converts admittance by multiplying by 2πωl" function _admittance_conversion_ravens(data_eng::Dict{String,<:Any}, eng_obj::Dict{String,<:Any}, key::String; freq::Float64=60.0) diff --git a/src/prob/common.jl b/src/prob/common.jl index 7f86adf3d..3508d93cb 100644 --- a/src/prob/common.jl +++ b/src/prob/common.jl @@ -116,6 +116,10 @@ function instantiate_mc_model( ) end + @info "$(data["load"])" + + DEFINIDOEN_instantiate_mc_model + return _IM.instantiate_model( data, model_type, @@ -158,7 +162,7 @@ function instantiate_mc_model_ravens( @info "$(data["load"])" - DEFINIDOEN_instantiate_mc_model + DEFINIDOEN_instantiate_mc_model_ravens return _IM.instantiate_model( data, From d616a1e0c7aef56c2d26b3e021a35f5c64e8119e Mon Sep 17 00:00:00 2001 From: jjospina Date: Wed, 7 Aug 2024 15:33:19 -0600 Subject: [PATCH 04/27] WIP: case3 balanced working. Still missing transformers, shunts, generators, solar, and storage. --- src/data_model/transformations/ravens2math.jl | 163 +----------------- src/prob/common.jl | 12 +- 2 files changed, 10 insertions(+), 165 deletions(-) diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index 8771d6196..b7268016b 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -349,155 +349,6 @@ function _map_ravens2math_power_transformer!(data_math::Dict{String,<:Any}, data _data_ravens_transformer = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"] for (name, ravens_obj) in get(_data_ravens_transformer, "PowerTransformer", Dict{Any,Dict{String,Any}}()) - - # Build map first, so we can update it as we decompose the transformer - push!(data_math["map"], Dict{String,Any}( - "from" => name, - "to" => String[], - "unmap_function" => "_map_math2ravens_transformer!", - )) - - to_map = data_math["map"][end]["to"] - - # _apply_xfmrcode!(ravens_obj, data_ravens) - - # PowerTransformerTank - if haskey(ravens_obj, "PowerTransformer.TransformerTank") - - @info "PowerTransformerTank ENTER" - @assert all(haskey(ravens_obj, k) for k in ["f_bus", "t_bus", "f_connections", "t_connections"]) "Incomplete definition of AL2W tranformer $name, aborting ravens2math conversion" - - nphases = length(ravens_obj["f_connections"]) - - math_obj = Dict{String,Any}( - "name" => name, - "source_id" => ravens_obj["source_id"], - "f_bus" => data_math["bus_lookup"][ravens_obj["f_bus"]], - "t_bus" => data_math["bus_lookup"][ravens_obj["t_bus"]], - "f_connections" => ravens_obj["f_connections"], - "t_connections" => ravens_obj["t_connections"], - "configuration" => get(ravens_obj, "configuration", WYE), - "tm_nom" => get(ravens_obj, "tm_nom", 1.0), - "tm_set" => get(ravens_obj, "tm_set", fill(1.0, nphases)), - "tm_fix" => get(ravens_obj, "tm_fix", fill(true, nphases)), - "polarity" => get(ravens_obj, "polarity", -1), - "sm_ub" => get(ravens_obj, "sm_ub", Inf), - "cm_ub" => get(ravens_obj, "cm_ub", Inf), - "status" => Int(get(ravens_obj, "status", ENABLED)), - "index" => length(data_math["transformer"])+1 - ) - - for k in [["tm_lb", "tm_ub"]; pass_props] - if haskey(ravens_obj, k) - math_obj[k] = ravens_obj[k] - end - end - - data_math["transformer"]["$(math_obj["index"])"] = math_obj - - push!(to_map, "transformer.$(math_obj["index"])") - - - # PowerTransformerEnd - else - - nrw = length(ravens_obj["bus"]) - - for w in 1:length(ravens_obj["PowerTransformer.PowerTransformerEnd"]) - - vnom = ravens_obj["PowerTransformer.PowerTransformerEnd"][w]["PowerTransformerEnd.ratedU"] - snom = ravens_obj["PowerTransformer.PowerTransformerEnd"][w]["PowerTransformerEnd.ratedS"] - - # calculate zbase in which the data is specified, and convert to SI - zbase = (vnom.^2) ./ snom - - # x_sc is specified with respect to first winding - x_sc = ravens_obj["xsc"] .* zbase[1] - - # rs is specified with respect to each winding - r_s = ravens_obj["rw"] .* zbase - - g_sh = (ravens_obj["noloadloss"]*snom[1])/vnom[1]^2 - b_sh = -(ravens_obj["cmag"]*snom[1])/vnom[1]^2 - - # data is measured externally, but we now refer it to the internal side - ratios = vnom/data_ravens["settings"]["voltage_scale_factor"] - x_sc = x_sc./ratios[1]^2 - r_s = r_s./ratios.^2 - g_sh = g_sh*ratios[1]^2 - b_sh = b_sh*ratios[1]^2 - - # convert x_sc from list of upper triangle elements to an explicit dict - y_sh = g_sh + im*b_sh - z_sc = Dict([(key, im*x_sc[i]) for (i,key) in enumerate([(i,j) for i in 1:nrw for j in i+1:nrw])]) - - dims = length(ravens_obj["tm_set"][1]) - transformer_t_bus_w = _build_loss_model!(data_math, name, to_map, r_s, z_sc, y_sh,ravens_obj["connections"][1]; nphases=dims, status=Int(ravens_obj["status"] == ENABLED)) - - # 2-WINDING TRANSFORMER - # make virtual bus and mark it for reduction - tm_nom = ravens_obj["configuration"][w]==DELTA ? ravens_obj["vm_nom"][w]*sqrt(3) : ravens_obj["vm_nom"][w] - transformer_2wa_obj = Dict{String,Any}( - "name" => "_virtual_transformer.$name.$w", - "source_id" => "_virtual_transformer.$(ravens_obj["source_id"]).$w", - "f_bus" => data_math["bus_lookup"][ravens_obj["bus"][w]], - "t_bus" => transformer_t_bus_w[w], - "tm_nom" => tm_nom, - "f_connections" => ravens_obj["connections"][w], - "t_connections" => get(data_math, "is_kron_reduced", false) ? ravens_obj["connections"][1] : collect(1:dims+1), - "configuration" => ravens_obj["configuration"][w], - "polarity" => ravens_obj["polarity"][w], - "tm_set" => ravens_obj["tm_set"][w], - "tm_fix" => ravens_obj["tm_fix"][w], - "sm_ub" => get(ravens_obj, "sm_ub", Inf), - "cm_ub" => get(ravens_obj, "cm_ub", Inf), - "status" => ravens_obj["status"] == DISABLED ? 0 : 1, - "index" => length(data_math["transformer"])+1 - ) - - for prop in [["tm_lb", "tm_ub", "tm_step"]; pass_props] - if haskey(ravens_obj, prop) - transformer_2wa_obj[prop] = ravens_obj[prop][w] - end - end - - data_math["transformer"]["$(transformer_2wa_obj["index"])"] = transformer_2wa_obj - - # add regcontrol items to math model - if haskey(ravens_obj,"controls") && !all(data_math["transformer"]["$(transformer_2wa_obj["index"])"]["tm_fix"]) - reg_obj = Dict{String,Any}( - "vreg" => ravens_obj["controls"]["vreg"][w], - "band" => ravens_obj["controls"]["band"][w], - "ptratio" => ravens_obj["controls"]["ptratio"][w], - "ctprim" => ravens_obj["controls"]["ctprim"][w], - "r" => ravens_obj["controls"]["r"][w], - "x" => ravens_obj["controls"]["x"][w], - ) - data_math["transformer"]["$(transformer_2wa_obj["index"])"]["controls"] = reg_obj - end - - if w==3 && ravens_obj["polarity"][w]==-1 # identify center-tapped transformer and mark all secondary-side nodes as triplex by adding va_start - default_va = [0, -120, 120][ravens_obj["connections"][1][1]] - data_math["bus"]["$(transformer_2wa_obj["f_bus"])"]["va_start"] = haskey(data_ravens["bus"][ravens_obj["bus"][w]],"va_start") ? data_ravens["bus"][ravens_obj["bus"][w]]["va_start"] : [default_va, (default_va+180)] - idx = 0 - bus_ids = [] - t_bus = haskey(data_ravens, "line") ? [data["t_bus"] for (_,data) in data_ravens["line"] if data["f_bus"] == ravens_obj["bus"][w]] : [] - while length(t_bus)>0 || idx "") - math_obj["vnom_kv"] = (data_ravens["BaseVoltage"][base_voltage_ref]["BaseVoltage.nominalVoltage"]/_voltage_scale_factor)/(sqrt(3)/2) + base_voltage = data_ravens["BaseVoltage"][base_voltage_ref]["BaseVoltage.nominalVoltage"] + math_obj["vnom_kv"] = (base_voltage/_voltage_scale_factor)/(sqrt(3)/2) # Get voltage bounds for specific bus connected (TODO: see if it can be coverted to standalone function to avoid repetition) bus_info = string(math_obj["load_bus"]) bus_conn = data_math["bus"][bus_info] - base_voltage_id = replace(split(ravens_obj["ConductingEquipment.BaseVoltage"], "::")[2], "'" => "") - base_voltage = data_ravens["BaseVoltage"][base_voltage_id]["BaseVoltage.nominalVoltage"] op_limit_id = replace(split(data_ravens["ConnectivityNode"][connectivity_node]["ConnectivityNode.OperationalLimitSet"], "::")[2], "'" => "") - # op_limit_max = data_ravens["OperationalLimitSet"][op_limit_id]["OperationalLimitSet.OperationalLimitValue"][1]["VoltageLimit.value"]./base_voltage - # op_limit_min = data_ravens["OperationalLimitSet"][op_limit_id]["OperationalLimitSet.OperationalLimitValue"][2]["VoltageLimit.value"]./base_voltage - op_limit_max = data_ravens["OperationalLimitSet"][op_limit_id]["OperationalLimitSet.OperationalLimitValue"][1]["VoltageLimit.value"] - op_limit_min = data_ravens["OperationalLimitSet"][op_limit_id]["OperationalLimitSet.OperationalLimitValue"][2]["VoltageLimit.value"] + op_limit_max = data_ravens["OperationalLimitSet"][op_limit_id]["OperationalLimitSet.OperationalLimitValue"][1]["VoltageLimit.value"]./_voltage_scale_factor_sqrt3 + op_limit_min = data_ravens["OperationalLimitSet"][op_limit_id]["OperationalLimitSet.OperationalLimitValue"][2]["VoltageLimit.value"]./_voltage_scale_factor_sqrt3 _connections = Vector{Int64}() if haskey(ravens_obj, "EnergyConsumer.EnergyConsumerPhase") @@ -645,7 +494,7 @@ function _map_ravens2math_energy_source!(data_math::Dict{String,<:Any}, data_rav _data_ravens_energyconnection = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"] _voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] - _voltage_scale_factor_sqrt3 = data_math["settings"]["voltage_scale_factor"]*sqrt(3) + _voltage_scale_factor_sqrt3 = _voltage_scale_factor*sqrt(3) for (name, ravens_obj) in get(_data_ravens_energyconnection, "EnergySource", Dict{String,Any}()) diff --git a/src/prob/common.jl b/src/prob/common.jl index 3508d93cb..45c2bdfbf 100644 --- a/src/prob/common.jl +++ b/src/prob/common.jl @@ -116,9 +116,8 @@ function instantiate_mc_model( ) end - @info "$(data["load"])" - - DEFINIDOEN_instantiate_mc_model + # @info "$(data)" + # DEFINIDOEN_instantiate_mc_model return _IM.instantiate_model( data, @@ -147,8 +146,6 @@ function instantiate_mc_model_ravens( kwargs... ) - # @info "$(data)" - @info "Converting CIM-RAVENS data model to MATHEMATICAL first to build JuMP model" data = transform_data_model_ravens( @@ -160,9 +157,8 @@ function instantiate_mc_model_ravens( make_pu_extensions=make_pu_extensions, ) - @info "$(data["load"])" - - DEFINIDOEN_instantiate_mc_model_ravens + # @info "$(data["bus"])" + # DEFINIDOEN_instantiate_mc_model_ravens return _IM.instantiate_model( data, From 15d72f8da128da49b6bb4ae9e15ed446fad67e3b Mon Sep 17 00:00:00 2001 From: Juan Ospina Date: Thu, 8 Aug 2024 09:41:08 -0600 Subject: [PATCH 05/27] Revise ravens schema (#2) * REF: revise and refactor ravens2math functions to simplify them. * FIX: issues with dictionary access in ravens funcs. --- src/data_model/transformations/ravens2math.jl | 485 +++++++----------- 1 file changed, 175 insertions(+), 310 deletions(-) diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index b7268016b..5baf17208 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -77,23 +77,6 @@ function _map_ravens2math( _data_ravens = deepcopy(data_ravens) - ## TODO - # if kron_reduce - # apply_kron_reduction!(_data_ravens) - # apply_phase_projection_delta!(_data_ravens) - # end - - # if phase_project - # apply_phase_projection!(_data_ravens) - # end - - - # # TODO: Add vbases to settings - # _vbases_default = Dict("vbases_default" => Dict{String, Real}()) - # for (name, ravens_obj) in get(data_ravens, "BaseVoltage", Dict{String,Any}()) - # _vbases_default = Dict(name => ravens_obj["BaseVoltage.nominalVoltage"]) - # end - # TODO: Add settings (defaults) basemva = 100 _settings = Dict("sbase_default" => basemva * 1e3, @@ -168,169 +151,113 @@ function _map_ravens2math_nw!(data_math::Dict{String,<:Any}, data_ravens::Dict{S ravens2math_func!(data_math, data_ravens) end - ## TODO: See if this is still neccesary for RAVENS - # # post fix - # if !get(data_math, "is_kron_reduced", false) - # #TODO fix this in place / throw error instead? IEEE8500 leads to switches - # # with 3x3 R matrices but only 1 phase - # #NOTE: Don't do this when kron-reducing, it will undo the padding - # _slice_branches!(data_math) - # end - find_conductor_ids!(data_math) _map_conductor_ids!(data_math) - - # TODO: See if this is still neccesary for RAVENS _map_settings_vbases_default!(data_math) end -"converts ravens connectivity_node components into mathematical bus components" +""" +Converts ravens connectivity_node components into mathematical bus components. +""" function _map_ravens2math_connectivity_node!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) + voltage_scale_factor_sqrt3 = data_math["settings"]["voltage_scale_factor"] * sqrt(3) + connectivity_nodes = get(data_ravens, "ConnectivityNode", Dict{String,Any}()) - _voltage_scale_factor_sqrt3 = data_math["settings"]["voltage_scale_factor"]*sqrt(3) - - for (name, ravens_obj) in get(data_ravens, "ConnectivityNode", Dict{String,Any}()) + for (name, ravens_obj) in connectivity_nodes + index = length(data_math["bus"]) + 1 + math_obj = _init_math_obj_ravens("bus", name, ravens_obj, index; pass_props=pass_props) - math_obj = _init_math_obj_ravens("bus", name, ravens_obj, length(data_math["bus"])+1; pass_props=pass_props) - math_obj["bus_i"] = math_obj["index"] + # Set basic bus properties + math_obj["bus_i"] = index math_obj["source_id"] = "bus.$name" - - # default bus_type, change as elements are added (e.g., load, generator, source). - math_obj["bus_type"] = 1 - - # TODO: needed? - default grounded + math_obj["bus_type"] = 1 # Default bus_type, will be modified as needed math_obj["grounded"] = Bool[0, 0, 0] + math_obj["vm_pair_lb"] = Tuple{Any, Any, Real}[] + math_obj["vm_pair_ub"] = Tuple{Any, Any, Real}[] - ## TODO - # # take care of grounding; convert to shunt if lossy - # grounded_perfect, shunts = _convert_grounding(ravens_obj["terminals"], ravens_obj["grounded"], ravens_obj["rg"], ravens_obj["xg"]) - - # math_obj["grounded"] = grounded_perfect - # to_sh = [] - # for (sh_connections, sh_y) in shunts - # sh_index = length(data_math["shunt"]) + 1 - # data_math["shunt"]["$sh_index"] = Dict( - # "index" => sh_index, - # "shunt_bus" => math_obj["bus_i"], - # "connections" => sh_connections, - # "gs" => real.(sh_y), - # "bs" => imag.(sh_y), - # ) - # push!(to_sh, "shunt.$sh_index") - # end - + # Set voltage magnitude and angle if haskey(ravens_obj, "SvVoltage.v") - math_obj["vm"] = (ravens_obj["SvVoltage.v"]/_voltage_scale_factor_sqrt3) + math_obj["vm"] = (ravens_obj["SvVoltage.v"] / voltage_scale_factor_sqrt3) end if haskey(ravens_obj, "SvVoltage.angle") math_obj["va"] = ravens_obj["SvVoltage.angle"] end - # TODO: add vm_pair_lb/ub (may not be needed!) - math_obj["vm_pair_lb"] = Tuple{Any, Any, Real}[] - math_obj["vm_pair_ub"] = Tuple{Any, Any, Real}[] - - data_math["bus"]["$(math_obj["index"])"] = math_obj - - if !haskey(data_math, "bus_lookup") - data_math["bus_lookup"] = Dict{Any,Int}() - end + # Store the mathematical bus object + data_math["bus"]["$(index)"] = math_obj - data_math["bus_lookup"][name] = math_obj["index"] + # Update bus lookup if necessary + data_math["bus_lookup"] = get(data_math, "bus_lookup", Dict{Any,Int}()) + data_math["bus_lookup"][name] = index - push!(data_math["map"], Dict{String,Any}( + # Map the ravens object to the math object + push!(data_math["map"], Dict( "from" => name, - "to" => "bus.$(math_obj["index"])", - "unmap_function" => "_map_math2ravens_bus!", + "to" => "bus.$index", + "unmap_function" => "_map_math2ravens_bus!" )) end end -"converts ravensineering conductors (e.g., ACLineSegments) into mathematical branches" +""" +Converts ravens conductors (e.g., ACLineSegments) into mathematical branches. +""" function _map_ravens2math_conductor!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) + conductors = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["Conductor"] - _data_ravens_conductor = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["Conductor"] - - for (name, ravens_obj) in get(_data_ravens_conductor, "ACLineSegment", Dict{Any,Dict{String,Any}}()) - - math_obj = _init_math_obj_ravens("ac_line_segment", name, ravens_obj, length(data_math["branch"])+1; pass_props=pass_props) + for (name, ravens_obj) in get(conductors, "ACLineSegment", Dict{Any,Dict{String,Any}}()) + math_obj = _init_math_obj_ravens("ac_line_segment", name, ravens_obj, length(data_math["branch"]) + 1; pass_props=pass_props) nphases = length(ravens_obj["ACLineSegment.ACLineSegmentPhase"]) + terminals = ravens_obj["ConductingEquipment.Terminals"] - f_connectivity_node = replace(split(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"], "::")[2], "'" => "") - t_connectivity_node = replace(split(ravens_obj["ConductingEquipment.Terminals"][2]["Terminal.ConnectivityNode"], "::")[2], "'" => "") - math_obj["f_bus"] = data_math["bus_lookup"][f_connectivity_node] - math_obj["t_bus"] = data_math["bus_lookup"][t_connectivity_node] + f_node = replace(split(terminals[1]["Terminal.ConnectivityNode"], "::")[2], "'" => "") + t_node = replace(split(terminals[2]["Terminal.ConnectivityNode"], "::")[2], "'" => "") - # define the number of terminals (i.e., phases) that the bus/es have, based on the lines - if nphases >= 3 - data_math["bus"][string(math_obj["f_bus"])]["terminals"]= [i for i = 1:nphases] - data_math["bus"][string(math_obj["t_bus"])]["terminals"]= [i for i = 1:nphases] - else - _terminals = Vector{Int64}() - for phase_info in ravens_obj["ACLineSegment.ACLineSegmentPhase"] - phase = phase_info["ACLineSegmentPhase.phase"] - if phase == "SinglePhaseKind.A" - push!(_terminals, 1) - elseif phase == "SinglePhaseKind.B" - push!(_terminals, 2) - elseif phase == "SinglePhaseKind.C" - push!(_terminals, 3) - else - @error("Terminals/Phases for buses '$(f_connectivity_node)' and '$(t_connectivity_node)' not recognized. Check your model!") - end - end - data_math["bus"][string(math_obj["f_bus"])]["terminals"]= _terminals - data_math["bus"][string(math_obj["t_bus"])]["terminals"]= _terminals - end + math_obj["f_bus"] = data_math["bus_lookup"][f_node] + math_obj["t_bus"] = data_math["bus_lookup"][t_node] - # Initilize vmin and vmax in buses - data_math["bus"][string(math_obj["f_bus"])]["vmin"] = fill(0.0, nphases) - data_math["bus"][string(math_obj["f_bus"])]["vmax"] = fill(Inf, nphases) - - data_math["bus"][string(math_obj["t_bus"])]["vmin"] = fill(0.0, nphases) - data_math["bus"][string(math_obj["t_bus"])]["vmax"] = fill(Inf, nphases) - - #------------------------------------------------------------------------------- - - # f_ and t_connections for the lines/branches - math_obj["f_connections"] = data_math["bus"][string(math_obj["f_bus"])]["terminals"] - math_obj["t_connections"] = data_math["bus"][string(math_obj["t_bus"])]["terminals"] + phase_map = Dict("SinglePhaseKind.A" => 1, "SinglePhaseKind.B" => 2, "SinglePhaseKind.C" => 3) + bus_terminals = nphases >= 3 ? collect(1:nphases) : [phase_map[phase["ACLineSegmentPhase.phase"]] for phase in ravens_obj["ACLineSegment.ACLineSegmentPhase"]] + for bus in [math_obj["f_bus"], math_obj["t_bus"]] + data_math["bus"][string(bus)]["terminals"] = bus_terminals + data_math["bus"][string(bus)]["vmin"] = fill(0.0, nphases) + data_math["bus"][string(bus)]["vmax"] = fill(Inf, nphases) + end - _perlengthimpedance_name = replace(split(ravens_obj["ACLineSegment.PerLengthImpedance"], "::")[2], "'" => "") - _perlengthimpedance_data = data_ravens["PerLengthLineParameter"]["PerLengthImpedance"]["PerLengthPhaseImpedance"][_perlengthimpedance_name] + math_obj["f_connections"] = bus_terminals + math_obj["t_connections"] = bus_terminals - math_obj["br_r"] = _impedance_conversion_ravens(_perlengthimpedance_data, ravens_obj, "PhaseImpedanceData.r") - math_obj["br_x"] = _impedance_conversion_ravens(_perlengthimpedance_data, ravens_obj, "PhaseImpedanceData.x") + impedance_name = replace(split(ravens_obj["ACLineSegment.PerLengthImpedance"], "::")[2], "'" => "") + impedance_data = data_ravens["PerLengthLineParameter"]["PerLengthImpedance"]["PerLengthPhaseImpedance"][impedance_name] - # b is given in mhos in CIM-RAVENS schema - math_obj["b_fr"] = _admittance_conversion_ravens(_perlengthimpedance_data, ravens_obj, "PhaseImpedanceData.b"; freq=data_math["settings"]["base_frequency"]) - math_obj["b_to"] = _admittance_conversion_ravens(_perlengthimpedance_data, ravens_obj, "PhaseImpedanceData.b"; freq=data_math["settings"]["base_frequency"]) + math_obj["br_r"] = _impedance_conversion_ravens(impedance_data, ravens_obj, "PhaseImpedanceData.r") + math_obj["br_x"] = _impedance_conversion_ravens(impedance_data, ravens_obj, "PhaseImpedanceData.x") - # g is given in mhos in CIM-RAVENS schema - math_obj["g_fr"] = _admittance_conversion_ravens(_perlengthimpedance_data, ravens_obj, "PhaseImpedanceData.g"; freq=data_math["settings"]["base_frequency"]) - math_obj["g_to"] = _admittance_conversion_ravens(_perlengthimpedance_data, ravens_obj, "PhaseImpedanceData.g"; freq=data_math["settings"]["base_frequency"]) + base_freq = data_math["settings"]["base_frequency"] + for (key, param) in [("b_fr", "PhaseImpedanceData.b"), ("b_to", "PhaseImpedanceData.b"), ("g_fr", "PhaseImpedanceData.g"), ("g_to", "PhaseImpedanceData.g")] + math_obj[key] = _admittance_conversion_ravens(impedance_data, ravens_obj, param; freq=base_freq) + end - ## TODO:: these do not appear in JSON schema, are they needed? if yes, we need to represent them on CIM-RAVENS schema math_obj["angmin"] = get(ravens_obj, "vad_lb", fill(-60.0, nphases)) - math_obj["angmax"] = get(ravens_obj, "vad_ub", fill( 60.0, nphases)) + math_obj["angmax"] = get(ravens_obj, "vad_ub", fill(60.0, nphases)) - # Operational Limits - _oplimitset_id = replace(split(ravens_obj["ConductingEquipment.Terminals"][1]["ACDCTerminal.OperationalLimitSet"], "::")[2], "'" => "") - _oplimitset = data_ravens["OperationalLimitSet"][_oplimitset_id]["OperationalLimitSet.OperationalLimitValue"][2] # [1] is Normal amps, [2] is Emergency amps - by default use emerg amps + oplimitset_id = replace(split(terminals[1]["ACDCTerminal.OperationalLimitSet"], "::")[2], "'" => "") + oplimitset = data_ravens["OperationalLimitSet"][oplimitset_id]["OperationalLimitSet.OperationalLimitValue"][2] - for (f_key, t_key) in [("CurrentLimit.value", "c_rating_a"), ("CurrentLimit.value", "c_rating_b"), ("CurrentLimit.value", "c_rating_c"), - ("ApparentPowerLimit.value", "rate_a"), ("ApparentPowerLimit.value", "rate_b"), ("ApparentPowerLimit.value", "rate_c")] - math_obj[t_key] = haskey(_oplimitset, f_key) ? fill(_oplimitset[f_key], nphases) : fill(Inf, nphases) + limit_keys = [("CurrentLimit.value", "c_rating_a"), ("CurrentLimit.value", "c_rating_b"), ("CurrentLimit.value", "c_rating_c"), + ("ApparentPowerLimit.value", "rate_a"), ("ApparentPowerLimit.value", "rate_b"), ("ApparentPowerLimit.value", "rate_c")] + + for (f_key, t_key) in limit_keys + math_obj[t_key] = haskey(oplimitset, f_key) ? fill(oplimitset[f_key], nphases) : fill(Inf, nphases) end math_obj["br_status"] = get(ravens_obj, "ConductingEquipment.SvStatus", 1) - data_math["branch"]["$(math_obj["index"])"] = math_obj push!(data_math["map"], Dict{String,Any}( @@ -338,10 +265,11 @@ function _map_ravens2math_conductor!(data_math::Dict{String,<:Any}, data_ravens: "to" => "branch.$(math_obj["index"])", "unmap_function" => "_map_math2ravens_line!", )) - end + end end + # TODO: Transformers need a lot of changes/refactors!!! "converts ravensineering n-winding transformers into mathematical ideal 2-winding lossless transformer branches and impedance branches to represent the loss model" function _map_ravens2math_power_transformer!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) @@ -353,297 +281,234 @@ function _map_ravens2math_power_transformer!(data_math::Dict{String,<:Any}, data end - -"converts ravensineering load components into mathematical load components" +""" +Converts ravens load components into mathematical load components. +""" function _map_ravens2math_energy_consumer!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) + conducting_equipment = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"] + power_scale_factor = data_math["settings"]["power_scale_factor"] + voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] + voltage_scale_factor_sqrt3 = voltage_scale_factor * sqrt(3) - _data_ravens_energyconnection = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"] - _power_scale_factor = data_math["settings"]["power_scale_factor"] - _voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] - _voltage_scale_factor_sqrt3 = _voltage_scale_factor*sqrt(3) - - for (name, ravens_obj) in get(_data_ravens_energyconnection, "EnergyConsumer", Dict{Any,Dict{String,Any}}()) - - # Get load response characteristic - load_response_characts = replace(split(ravens_obj["EnergyConsumer.LoadResponseCharacteristic"], "::")[2], "'" => "") + for (name, ravens_obj) in get(conducting_equipment, "EnergyConsumer", Dict{Any,Dict{String,Any}}()) + math_obj = _init_math_obj_ravens("energy_consumer", name, ravens_obj, length(data_math["load"]) + 1; pass_props=pass_props) - # Initialize energy consumer object - math_obj = _init_math_obj_ravens("energy_consumer", name, ravens_obj, length(data_math["load"])+1; pass_props=pass_props) - - # Get Bus/ConnectivityNode + # Set the load bus based on connectivity node connectivity_node = replace(split(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"], "::")[2], "'" => "") math_obj["load_bus"] = data_math["bus_lookup"][connectivity_node] - # Model of the Load/EnergyConsumer + # Handle Load Response Characteristics + load_response_characts = replace(split(ravens_obj["EnergyConsumer.LoadResponseCharacteristic"], "::")[2], "'" => "") if load_response_characts == "Constant Z" - + math_obj["model"] = IMPEDANCE elseif load_response_characts == "Motor" - + @error("Load model not supported yet!") elseif load_response_characts == "Mix Motor/Res" - + @error("Load model not supported yet!") elseif load_response_characts == "Constant I" - + math_obj["model"] = CURRENT elseif load_response_characts == "Variable P, Fixed Q" - + @error("Load model not supported yet!") elseif load_response_characts == "Variable P, Fixed X" - - # "Constant kVA" : default + @error("Load model not supported yet!") else - if load_response_characts != "Constant kVA" @warn("Load model (response characteristic) for $(name) not supported! Defaulting to 'Constant kVA'") end - - # Add the model of the load based on loadresponsecharacteristic + # Set default model and consumption values math_obj["model"] = POWER - - # P and Q consumption - math_obj["pd"] = [ravens_obj["EnergyConsumer.p"]/_power_scale_factor] - math_obj["qd"] = [ravens_obj["EnergyConsumer.q"]/_power_scale_factor] - end - # Vnom + # Set p and q + math_obj["pd"] = [ravens_obj["EnergyConsumer.p"] / power_scale_factor] + math_obj["qd"] = [ravens_obj["EnergyConsumer.q"] / power_scale_factor] + + # Set the nominal voltage base_voltage_ref = replace(split(ravens_obj["ConductingEquipment.BaseVoltage"], "::")[2], "'" => "") base_voltage = data_ravens["BaseVoltage"][base_voltage_ref]["BaseVoltage.nominalVoltage"] - math_obj["vnom_kv"] = (base_voltage/_voltage_scale_factor)/(sqrt(3)/2) + math_obj["vnom_kv"] = (base_voltage / voltage_scale_factor) / (sqrt(3) / 2) - # Get voltage bounds for specific bus connected (TODO: see if it can be coverted to standalone function to avoid repetition) + # Set voltage bounds for the bus connected bus_info = string(math_obj["load_bus"]) bus_conn = data_math["bus"][bus_info] - op_limit_id = replace(split(data_ravens["ConnectivityNode"][connectivity_node]["ConnectivityNode.OperationalLimitSet"], "::")[2], "'" => "") - op_limit_max = data_ravens["OperationalLimitSet"][op_limit_id]["OperationalLimitSet.OperationalLimitValue"][1]["VoltageLimit.value"]./_voltage_scale_factor_sqrt3 - op_limit_min = data_ravens["OperationalLimitSet"][op_limit_id]["OperationalLimitSet.OperationalLimitValue"][2]["VoltageLimit.value"]./_voltage_scale_factor_sqrt3 + op_limits = data_ravens["OperationalLimitSet"][op_limit_id]["OperationalLimitSet.OperationalLimitValue"] + op_limit_max = op_limits[1]["VoltageLimit.value"] / voltage_scale_factor_sqrt3 + op_limit_min = op_limits[2]["VoltageLimit.value"] / voltage_scale_factor_sqrt3 - _connections = Vector{Int64}() + # Handle phase-specific or three-phase connection + phase_map = Dict("SinglePhaseKind.A" => 1, "SinglePhaseKind.B" => 2, "SinglePhaseKind.C" => 3) if haskey(ravens_obj, "EnergyConsumer.EnergyConsumerPhase") + connections = Vector{Int64}() for phase_info in ravens_obj["EnergyConsumer.EnergyConsumerPhase"] - phase = phase_info["EnergyConsumerPhase.phase"] - if phase == "SinglePhaseKind.A" - phase_index = findfirst(==(1), bus_conn["terminals"]) - bus_conn["vmax"][phase_index] = op_limit_max - bus_conn["vmin"][phase_index] = op_limit_min - push!(_connections, 1) - elseif phase == "SinglePhaseKind.B" - phase_index = findfirst(==(2), bus_conn["terminals"]) - bus_conn["vmax"][phase_index] = op_limit_max - bus_conn["vmin"][phase_index] = op_limit_min - push!(_connections, 2) - elseif phase == "SinglePhaseKind.C" - phase_index = findfirst(==(3), bus_conn["terminals"]) - bus_conn["vmax"][phase_index] = op_limit_max - bus_conn["vmin"][phase_index] = op_limit_min - push!(_connections, 3) - else - @error("Terminals/Phases for buses '$(f_connectivity_node)' and '$(t_connectivity_node)' not recognized. Check your model!") - end + phase = phase_map[phase_info["EnergyConsumerPhase.phase"]] + phase_index = findfirst(==(phase), bus_conn["terminals"]) + bus_conn["vmax"][phase_index] = op_limit_max + bus_conn["vmin"][phase_index] = op_limit_min + push!(connections, phase) end - math_obj["connections"] = _connections + math_obj["connections"] = connections else - # assumes it is a three-phase connection N = length(bus_conn["terminals"]) bus_conn["vmax"] = fill(op_limit_max, N) bus_conn["vmin"] = fill(op_limit_min, N) math_obj["connections"] = bus_conn["terminals"] end - # TODO: Configuration - _config = ravens_obj["EnergyConsumer.phaseConnection"] - if _config == "PhaseShuntConnectionKind.Y" - math_obj["configuration"] = WYE - elseif _config == "PhaseShuntConnectionKind.D" - math_obj["configuration"] = DELTA - elseif _config == "PhaseShuntConnectionKind.Yn" - elseif _config == "PhaseShuntConnectionKind.I" - elseif _config == "PhaseShuntConnectionKind.G" + # Set the configuration + # TODO: ADD: "PhaseShuntConnectionKind.Yn", "PhaseShuntConnectionKind.I", "PhaseShuntConnectionKind.G" + config_map = Dict("PhaseShuntConnectionKind.Y" => WYE, "PhaseShuntConnectionKind.D" => DELTA) + config = get(config_map, ravens_obj["EnergyConsumer.phaseConnection"], nothing) + if config !== nothing + math_obj["configuration"] = config else @error("Configuration of load $(name) is not supported.") end - # Status + # Set status, dispatchable flag, and index math_obj["status"] = ravens_obj["ConductingEquipment.SvStatus"] - - # TODO: Dispatchable? default=0 math_obj["dispatchable"] = 0 - - # Index data_math["load"]["$(math_obj["index"])"] = math_obj - # TODO: Assign 'grounding' to corresponding connectivity node + # Handle grounding if ravens_obj["EnergyConsumer.grounded"] == "true" bus_conn["grounded"] = Bool[0, 0, 0] end - # Revise bus_type of connectivity node to PQ bus + # Set bus type to PQ bus bus_conn["bus_type"] = 1 + # Map the object push!(data_math["map"], Dict{String,Any}( "from" => name, "to" => "load.$(math_obj["index"])", "unmap_function" => "_map_math2ravens_load!", )) - - end + end end -#TODO: -"converts ravensineering voltage sources into mathematical generators and (if needed) impedance branches to represent the loss model" +""" +Converts ravens voltage sources into mathematical generators and (if needed) impedance branches to represent the loss model. +""" function _map_ravens2math_energy_source!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) + conducting_equipment = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"] + voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] + voltage_scale_factor_sqrt3 = voltage_scale_factor * sqrt(3) - _data_ravens_energyconnection = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"] - _voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] - _voltage_scale_factor_sqrt3 = _voltage_scale_factor*sqrt(3) - - for (name, ravens_obj) in get(_data_ravens_energyconnection, "EnergySource", Dict{String,Any}()) - - math_obj = _init_math_obj_ravens("energy_source", name, ravens_obj, length(data_math["gen"])+1; pass_props=pass_props) + for (name, ravens_obj) in get(conducting_equipment, "EnergySource", Dict{Any,Dict{String,Any}}()) + math_obj = _init_math_obj_ravens("energy_source", name, ravens_obj, length(data_math["gen"]) + 1; pass_props=pass_props) math_obj["name"] = "_virtual_gen.energy_source.$name" - # get connectivity node info. (bus info) + # Get connectivity node info (bus info) connectivity_node = replace(split(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"], "::")[2], "'" => "") - math_obj["gen_bus"] = gen_bus = data_math["bus_lookup"][connectivity_node] + gen_bus = data_math["bus_lookup"][connectivity_node] + math_obj["gen_bus"] = gen_bus bus_conn = data_math["bus"][string(gen_bus)] + bus_conn["bus_type"] = 3 # Set bus type to PV bus - # Revise bus_type of connectivity node to PV bus - bus_conn["bus_type"] = 3 + # Handle phase-specific or three-phase connection + connections = Vector{Int64}() + nconductors = length(get(ravens_obj, "EnergySource.EnergySourcePhase", bus_conn["terminals"])) - nconductors = 0 - _connections = Vector{Int64}() if haskey(ravens_obj, "EnergySource.EnergySourcePhase") - - nconductors = length(ravens_obj["EnergySource.EnergySourcePhase"]) - # TODO: how to redefine the kron reduction? - # nphases = get(ravens_obj, "configuration", WYE) == WYE && !get(data_ravens, "is_kron_reduced", false) ? nconductors - 1 : nconductors - nphases = nconductors - + phase_map = Dict("SinglePhaseKind.A" => 1, "SinglePhaseKind.B" => 2, "SinglePhaseKind.C" => 3) for phase_info in ravens_obj["EnergySource.EnergySourcePhase"] - phase = phase_info["EnergySourcePhase.phase"] - if phase == "SinglePhaseKind.A" - push!(_connections, 1) - elseif phase == "SinglePhaseKind.B" - push!(_connections, 2) - elseif phase == "SinglePhaseKind.C" - push!(_connections, 3) - else - @error("Connections for energy source '$(name)' not recognized. Check your model!") - end + phase = phase_map[phase_info["EnergySourcePhase.phase"]] + push!(connections, phase) end - - math_obj["connections"] = _connections + math_obj["connections"] = connections else - # assumes it is a three-phase connection - nconductors = length(bus_conn["terminals"]) - # TODO: how to redefine the kron reduction? we need - # nphases = get(ravens_obj, "configuration", WYE) == WYE && !get(data_ravens, "is_kron_reduced", false) ? nconductors - 1 : nconductors - nphases = nconductors math_obj["connections"] = bus_conn["terminals"] end - math_obj["gen_status"] = status = Int(ravens_obj["ConductingEquipment.SvStatus"]) - - # Vnom and add vbases_default from energy source - base_voltage_ref = replace(split(ravens_obj["ConductingEquipment.BaseVoltage"], "::")[2], "'" => "") - vnom = data_ravens["BaseVoltage"][base_voltage_ref]["BaseVoltage.nominalVoltage"] / sqrt(nphases) - data_math["settings"]["vbases_default"][connectivity_node] = vnom/_voltage_scale_factor - - # P, Q, Vg, etc. - math_obj["pg"] = get(ravens_obj, "EnergySource.activePower", fill(0.0, nphases)).*fill(1.0, nphases) - math_obj["qg"] = get(ravens_obj, "EnergySource.reactivePower", fill(0.0, nphases)).*fill(1.0, nphases) - math_obj["vg"] = fill(get(ravens_obj, "EnergySource.voltageMagnitude", _voltage_scale_factor_sqrt3)/_voltage_scale_factor_sqrt3, nphases) - math_obj["pmin"] = get(ravens_obj, "EnergySource.pMin", fill(-Inf, nphases)).*fill(1.0, nphases) - math_obj["pmax"] = get(ravens_obj, "EnergySource.pMax", fill( Inf, nphases)).*fill(1.0, nphases) - math_obj["qmin"] = get(ravens_obj, "EnergySource.qMin", fill(-Inf, nphases)).*fill(1.0, nphases) - math_obj["qmax"] = get(ravens_obj, "EnergySource.qMax", fill( Inf, nphases)).*fill(1.0, nphases) - - # configuration + # Generator status and configuration + math_obj["gen_status"] = Int(ravens_obj["ConductingEquipment.SvStatus"]) math_obj["configuration"] = get(ravens_obj, "EnergySource.connectionKind", WYE) - # TODO: Do we need a control_mode parameter for this? add to RAVENS schema - math_obj["control_mode"] = control_mode = Int(get(ravens_obj, "EnergySource.connectionKind", ISOCHRONOUS)) + # Vnom and vbases_default + base_voltage_ref = replace(split(ravens_obj["ConductingEquipment.BaseVoltage"], "::")[2], "'" => "") + vnom = data_ravens["BaseVoltage"][base_voltage_ref]["BaseVoltage.nominalVoltage"] / sqrt(nconductors) + data_math["settings"]["vbases_default"][connectivity_node] = vnom / voltage_scale_factor + + # Power, voltage, and limits + nphases = nconductors # You can adjust nphases based on your specific kron reduction logic if needed + fill_values = (v) -> fill(v, nphases) + math_obj["pg"] = get(ravens_obj, "EnergySource.activePower", fill_values(0.0)) + math_obj["qg"] = get(ravens_obj, "EnergySource.reactivePower", fill_values(0.0)) + math_obj["vg"] = fill(get(ravens_obj, "EnergySource.voltageMagnitude", voltage_scale_factor_sqrt3) / voltage_scale_factor_sqrt3, nphases) + math_obj["pmin"] = get(ravens_obj, "EnergySource.pMin", fill_values(-Inf)) + math_obj["pmax"] = get(ravens_obj, "EnergySource.pMax", fill_values(Inf)) + math_obj["qmin"] = get(ravens_obj, "EnergySource.qMin", fill_values(-Inf)) + math_obj["qmax"] = get(ravens_obj, "EnergySource.qMax", fill_values(Inf)) + + # Control mode and source ID + math_obj["control_mode"] = Int(get(ravens_obj, "EnergySource.connectionKind", ISOCHRONOUS)) math_obj["source_id"] = "energy_source.$name" - # TODO: inside this function, there are elements that do not exist in the RAVENS schema, so the default is used. + # Add generator cost model _add_gen_cost_model!(math_obj, ravens_obj) + # Check for impedance and adjust bus type if necessary map_to = "gen.$(math_obj["index"])" - if !all(isapprox.(get(ravens_obj, "EnergySource.r", zeros(1, 1)), 0)) && !all(isapprox.(get(ravens_obj, "EnergySource.x", zeros(1, 1)), 0)) + bus_conn["bus_type"] = 1 # Virtual bus becomes the new slack bus - # Revise bus_type of connectivity node to PV bus (virtual bus becomes the new slack bus) - bus_conn["bus_type"] = 1 - - f_bus = deepcopy(data_math["bus"]["$(math_obj["gen_bus"])"]) - - bus_obj = Dict{String,Any}( - "bus_i" => length(data_math["bus"])+1, - "index" => length(data_math["bus"])+1, + bus_obj = Dict( + "bus_i" => length(data_math["bus"]) + 1, + "index" => length(data_math["bus"]) + 1, "terminals" => math_obj["connections"], - # TODO: grounded energyosurce default? "grounded" => Bool[0, 0, 0], "name" => "_virtual_bus.energy_source.$name", - "bus_type" => status == 0 ? 4 : control_mode == Int(ISOCHRONOUS) ? 3 : 2, - "vm" => fill(ravens_obj["EnergySource.voltageMagnitude"]/_voltage_scale_factor_sqrt3, nphases), - "va" => rad2deg.(_wrap_to_pi.([-2*pi/nphases*(i-1)+deg2rad(ravens_obj["EnergySource.voltageAngle"]) for i in 1:nphases])), - "vmin" => fill(ravens_obj["EnergySource.voltageMagnitude"]/_voltage_scale_factor_sqrt3, nphases), - "vmax" => fill(ravens_obj["EnergySource.voltageMagnitude"]/_voltage_scale_factor_sqrt3, nphases), + "bus_type" => math_obj["gen_status"] == 0 ? 4 : math_obj["control_mode"] == Int(ISOCHRONOUS) ? 3 : 2, + "vm" => fill(ravens_obj["EnergySource.voltageMagnitude"] / voltage_scale_factor_sqrt3, nphases), + "va" => rad2deg.(_wrap_to_pi.([-2 * π / nphases * (i - 1) + deg2rad(ravens_obj["EnergySource.voltageAngle"]) for i in 1:nphases])), + "vmin" => fill(ravens_obj["EnergySource.voltageMagnitude"] / voltage_scale_factor_sqrt3, nphases), + "vmax" => fill(ravens_obj["EnergySource.voltageMagnitude"] / voltage_scale_factor_sqrt3, nphases), "vm_pair_lb" => deepcopy(get(ravens_obj, "EnergySource.vpairMin", Tuple{Any,Any,Real}[])), "vm_pair_ub" => deepcopy(get(ravens_obj, "EnergySource.vpairMax", Tuple{Any,Any,Real}[])), "source_id" => "energy_source.$name", ) - # TODO: - # for (i,t) in enumerate(math_obj["connections"]) - # if data_math["bus"]["$(data_math["bus_lookup"][ravens_obj["bus"]])"]["grounded"][i] - # bus_obj["vm"][i] = 0 - # bus_obj["vmin"][i] = 0 - # bus_obj["vmax"][i] = Inf - # end - # end - - math_obj["gen_bus"] = gen_bus = bus_obj["bus_i"] - + math_obj["gen_bus"] = bus_obj["bus_i"] data_math["bus"]["$(bus_obj["index"])"] = bus_obj - branch_obj = Dict{String,Any}( + branch_obj = Dict( "name" => "_virtual_branch.energy_source.$name", "source_id" => "energy_source.$name", "f_bus" => bus_obj["bus_i"], - "t_bus" => data_math["bus_lookup"][connectivity_node], + "t_bus" => gen_bus, "f_connections" => math_obj["connections"], "t_connections" => math_obj["connections"], "angmin" => fill(-10.0, nconductors), - "angmax" => fill( 10.0, nconductors), + "angmax" => fill(10.0, nconductors), "c_rating_a" => fill(Inf, nconductors), - "br_status" => status, + "br_status" => math_obj["gen_status"], "br_r" => _impedance_conversion_ravens_energy_source(data_ravens, ravens_obj, "EnergySource.r", "EnergySource.r0"), "br_x" => _impedance_conversion_ravens_energy_source(data_ravens, ravens_obj, "EnergySource.x", "EnergySource.x0"), "g_fr" => zeros(nconductors, nconductors), "g_to" => zeros(nconductors, nconductors), "b_fr" => zeros(nconductors, nconductors), "b_to" => zeros(nconductors, nconductors), - "index" => length(data_math["branch"])+1 + "index" => length(data_math["branch"]) + 1 ) data_math["branch"]["$(branch_obj["index"])"] = branch_obj - map_to = [map_to, "bus.$(bus_obj["index"])", "branch.$(branch_obj["index"])"] else - vm_lb = control_mode == Int(ISOCHRONOUS) ? ravens_obj["EnergySource.voltageMagnitude"] : get(ravens_obj, "EnergySource.vMin", fill(0.0, nphases)) - vm_ub = control_mode == Int(ISOCHRONOUS) ? ravens_obj["EnergySource.voltageMagnitude"] : get(ravens_obj, "EnergySource.vMax", fill(Inf, nphases)) + # Handle bus voltage limits if no impedance is present + vm_lb = math_obj["control_mode"] == Int(ISOCHRONOUS) ? ravens_obj["EnergySource.voltageMagnitude"] : get(ravens_obj, "EnergySource.vMin", fill(0.0, nphases)) + vm_ub = math_obj["control_mode"] == Int(ISOCHRONOUS) ? ravens_obj["EnergySource.voltageMagnitude"] : get(ravens_obj, "EnergySource.vMax", fill(Inf, nphases)) - data_math["bus"]["$gen_bus"]["vmin"] = [vm_lb..., [0.0 for n in 1:(nconductors-nphases)]...] - data_math["bus"]["$gen_bus"]["vmax"] = [vm_ub..., [Inf for n in 1:(nconductors-nphases)]...] - data_math["bus"]["$gen_bus"]["vm"] = [ravens_obj["EnergySource.voltageMagnitude"]/_voltage_scale_factor_sqrt3..., [0.0 for n in 1:(nconductors-nphases)]...] - data_math["bus"]["$gen_bus"]["va"] = [ravens_obj["EnergySource.voltageAngle"]..., [0.0 for n in 1:(nconductors-nphases)]...] + data_math["bus"]["$gen_bus"]["vmin"] = [vm_lb..., fill(0.0, nconductors - nphases)...] + data_math["bus"]["$gen_bus"]["vmax"] = [vm_ub..., fill(Inf, nconductors - nphases)...] + data_math["bus"]["$gen_bus"]["vm"] = fill(ravens_obj["EnergySource.voltageMagnitude"] / voltage_scale_factor_sqrt3, nphases) + data_math["bus"]["$gen_bus"]["va"] = fill(ravens_obj["EnergySource.voltageAngle"], nphases) - bus_type = data_math["bus"]["$gen_bus"]["bus_type"] - data_math["bus"]["$gen_bus"]["bus_type"] = _compute_bus_type(bus_type, status, control_mode) + data_math["bus"]["$gen_bus"]["bus_type"] = _compute_bus_type(bus_conn["bus_type"], math_obj["gen_status"], math_obj["control_mode"]) end data_math["gen"]["$(math_obj["index"])"] = math_obj - push!(data_math["map"], Dict{String,Any}( "from" => name, "to" => map_to, From bbfa2d7c19a8cd3f0e8013196a80cba9c1a8e8e6 Mon Sep 17 00:00:00 2001 From: jjospina Date: Thu, 5 Sep 2024 11:02:33 -0600 Subject: [PATCH 06/27] ADD: generator or rotating machine parser for ravens2math --- src/data_model/transformations/ravens2math.jl | 97 +++++++++++++++++-- src/prob/common.jl | 8 +- 2 files changed, 95 insertions(+), 10 deletions(-) diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index 5baf17208..9d079f8df 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -5,7 +5,7 @@ const _math_to_ravens = Dict{String,String}( "switch" => "switch", # "shunt" => "shunt_compensator", "load" => "energy_consumer", - # "generator" => "rotating_machine", + "generator" => "rotating_machine", # "solar" => "photovoltaic_unit", # "storage" => "battery_unit", "voltage_source" => "energy_source", @@ -14,7 +14,7 @@ const _math_to_ravens = Dict{String,String}( "list of nodal type elements in the ravens model" const _ravens_node_elements = String[ - "energy_consumer", "energy_source" + "energy_consumer", "rotating_machine", "energy_source" ] "list of edge type elements in the ravens model" @@ -247,8 +247,12 @@ function _map_ravens2math_conductor!(data_math::Dict{String,<:Any}, data_ravens: math_obj["angmin"] = get(ravens_obj, "vad_lb", fill(-60.0, nphases)) math_obj["angmax"] = get(ravens_obj, "vad_ub", fill(60.0, nphases)) - oplimitset_id = replace(split(terminals[1]["ACDCTerminal.OperationalLimitSet"], "::")[2], "'" => "") - oplimitset = data_ravens["OperationalLimitSet"][oplimitset_id]["OperationalLimitSet.OperationalLimitValue"][2] + if (haskey(terminals[1], "ACDCTerminal.OperationalLimitSet")) + oplimitset_id = replace(split(terminals[1]["ACDCTerminal.OperationalLimitSet"], "::")[2], "'" => "") + oplimitset = data_ravens["OperationalLimitSet"][oplimitset_id]["OperationalLimitSet.OperationalLimitValue"][2] + else + oplimitset = Dict() + end limit_keys = [("CurrentLimit.value", "c_rating_a"), ("CurrentLimit.value", "c_rating_b"), ("CurrentLimit.value", "c_rating_c"), ("ApparentPowerLimit.value", "rate_a"), ("ApparentPowerLimit.value", "rate_b"), ("ApparentPowerLimit.value", "rate_c")] @@ -366,7 +370,7 @@ function _map_ravens2math_energy_consumer!(data_math::Dict{String,<:Any}, data_r end # Set status, dispatchable flag, and index - math_obj["status"] = ravens_obj["ConductingEquipment.SvStatus"] + math_obj["status"] = haskey(ravens_obj, "ConductingEquipment.SvStatus") ? ravens_obj["ConductingEquipment.SvStatus"] : 1 math_obj["dispatchable"] = 0 data_math["load"]["$(math_obj["index"])"] = math_obj @@ -423,7 +427,7 @@ function _map_ravens2math_energy_source!(data_math::Dict{String,<:Any}, data_rav end # Generator status and configuration - math_obj["gen_status"] = Int(ravens_obj["ConductingEquipment.SvStatus"]) + math_obj["gen_status"] = haskey(ravens_obj, "ConductingEquipment.SvStatus") ? Int(ravens_obj["ConductingEquipment.SvStatus"]) : 1 math_obj["configuration"] = get(ravens_obj, "EnergySource.connectionKind", WYE) # Vnom and vbases_default @@ -518,6 +522,87 @@ function _map_ravens2math_energy_source!(data_math::Dict{String,<:Any}, data_rav end + +"converts engineering generators into mathematical generators" +function _map_ravens2math_rotating_machine!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) + + regulating_cond_eq = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"]["RegulatingCondEq"] + power_scale_factor = data_math["settings"]["power_scale_factor"] + voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] + voltage_scale_factor_sqrt3 = voltage_scale_factor * sqrt(3) + + for (name, ravens_obj) in get(regulating_cond_eq, "RotatingMachine", Dict{Any,Dict{String,Any}}()) + + math_obj = _init_math_obj_ravens("rotating_machine", name, ravens_obj, length(data_math["gen"])+1; pass_props=pass_props) + + # TODO: connections/phases do not exist in the RAVENS-CIM (Need to be added) - should come from terminals + connections = [1, 2, 3] # TODO + nconductors = length(connections) + math_obj["connections"] = connections + + connectivity_node = replace(split(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"], "::")[2], "'" => "") + math_obj["gen_bus"] = data_math["bus_lookup"][connectivity_node] + math_obj["gen_status"] = status = Int(get(ravens_obj, "ConductingEquipment.SvStatus", 1)) + + # TODO: control mode do not exist in the RAVENS-CIM (Need to be added) + math_obj["control_mode"] = control_mode = Int(get(ravens_obj, "control_mode", FREQUENCYDROOP)) + + # Set Pmax for generator + if !haskey(ravens_obj, "GeneratingUnit.maxOperatingP") + math_obj["pmax"] = ((get(ravens_obj, "SynchronousMachine.ratedS", Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) + else + math_obj["pmax"] = ((get(ravens_obj, "GeneratingUnit.maxOperatingP", Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) + end + + # Set bus type + bus_type = data_math["bus"]["$(math_obj["gen_bus"])"]["bus_type"] + data_math["bus"]["$(math_obj["gen_bus"])"]["bus_type"] = _compute_bus_type(bus_type, status, control_mode) + + # Set the nominal voltage + base_voltage_ref = replace(split(ravens_obj["ConductingEquipment.BaseVoltage"], "::")[2], "'" => "") + nominal_voltage = data_ravens["BaseVoltage"][base_voltage_ref]["BaseVoltage.nominalVoltage"] + base_voltage = nominal_voltage / sqrt(nconductors) + math_obj["vbase"] = base_voltage / voltage_scale_factor + + if control_mode == Int(ISOCHRONOUS) && status == 1 + data_math["bus"]["$(math_obj["gen_bus"])"]["vm"] = ((get(ravens_obj, "SynchronousMachine.ratedU", nominal_voltage))/nominal_voltage)* ones(nconductors) + data_math["bus"]["$(math_obj["gen_bus"])"]["vmax"] = ((get(ravens_obj, "SynchronousMachine.ratedU", nominal_voltage))/nominal_voltage)* ones(nconductors) + data_math["bus"]["$(math_obj["gen_bus"])"]["vmin"] = ((get(ravens_obj, "SynchronousMachine.ratedU", nominal_voltage))/nominal_voltage)* ones(nconductors) + data_math["bus"]["$(math_obj["gen_bus"])"]["va"] = [0.0, -120, 120, zeros(length(data_math["bus"]["$(math_obj["gen_bus"])"]) - 3)...][data_math["bus"]["$(math_obj["gen_bus"])"]["terminals"]] + end + + # Set pmin + math_obj["pmin"] = ((get(ravens_obj, "GeneratingUnit.minOperatingP", 0) * ones(nconductors)) ./ nconductors)./(power_scale_factor) + # Set qmin + math_obj["qmin"] = ((get(ravens_obj, "SynchronousMachine.minQ", -Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) + # Set qmax + math_obj["qmax"] = ((get(ravens_obj, "SynchronousMachine.maxQ", Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) + + # Set pg and qg + math_obj["pg"] = (get(ravens_obj, "SynchronousMachine.p", 0.0) * ones(nconductors) ./ nconductors)./(power_scale_factor) + math_obj["qg"] = (get(ravens_obj, "SynchronousMachine.q", 0.0) * ones(nconductors) ./ nconductors)./(power_scale_factor) + + # TODO: add a polynomial parameters to be added to gen cost + _add_gen_cost_model!(math_obj, ravens_obj) + + # TODO: configuration for generators is not available on CIM (yet) + math_obj["configuration"] = get(ravens_obj, "configuration", WYE) + + # Set index + data_math["gen"]["$(math_obj["index"])"] = math_obj + + push!(data_math["map"], Dict{String,Any}( + "from" => name, + "to" => "gen.$(math_obj["index"])", + "unmap_function" => "_map_math2ravens_rotating_machine!", + )) + end + + +end + + + "converts ravensineering switches into mathematical switches and (if neeed) impedance branches to represent loss model" function _map_ravens2math_switch!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) # TODO enable real switches (right now only using vitual lines) diff --git a/src/prob/common.jl b/src/prob/common.jl index 45c2bdfbf..6eb79c6d4 100644 --- a/src/prob/common.jl +++ b/src/prob/common.jl @@ -116,8 +116,8 @@ function instantiate_mc_model( ) end - # @info "$(data)" - # DEFINIDOEN_instantiate_mc_model + @info "$(data["gen"])" + DEFINIDOEN_instantiate_mc_model return _IM.instantiate_model( data, @@ -157,8 +157,8 @@ function instantiate_mc_model_ravens( make_pu_extensions=make_pu_extensions, ) - # @info "$(data["bus"])" - # DEFINIDOEN_instantiate_mc_model_ravens + @info "$(data["gen"])" + DEFINIDOEN_instantiate_mc_model_ravens return _IM.instantiate_model( data, From 03a55d4f18a3ee352618a29a88ca2c3f56feff78 Mon Sep 17 00:00:00 2001 From: jjospina Date: Thu, 5 Sep 2024 12:54:56 -0600 Subject: [PATCH 07/27] ADD: pv or photovoltaic unit parser for ravens2math. --- src/data_model/transformations/ravens2math.jl | 99 ++++++++++++++++++- 1 file changed, 96 insertions(+), 3 deletions(-) diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index 9d079f8df..8b01347ab 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -6,7 +6,7 @@ const _math_to_ravens = Dict{String,String}( # "shunt" => "shunt_compensator", "load" => "energy_consumer", "generator" => "rotating_machine", - # "solar" => "photovoltaic_unit", + "solar" => "photovoltaic_unit", # "storage" => "battery_unit", "voltage_source" => "energy_source", ) @@ -14,7 +14,7 @@ const _math_to_ravens = Dict{String,String}( "list of nodal type elements in the ravens model" const _ravens_node_elements = String[ - "energy_consumer", "rotating_machine", "energy_source" + "energy_consumer", "rotating_machine", "photovoltaic_unit", "energy_source" ] "list of edge type elements in the ravens model" @@ -529,7 +529,6 @@ function _map_ravens2math_rotating_machine!(data_math::Dict{String,<:Any}, data_ regulating_cond_eq = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"]["RegulatingCondEq"] power_scale_factor = data_math["settings"]["power_scale_factor"] voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] - voltage_scale_factor_sqrt3 = voltage_scale_factor * sqrt(3) for (name, ravens_obj) in get(regulating_cond_eq, "RotatingMachine", Dict{Any,Dict{String,Any}}()) @@ -602,6 +601,100 @@ function _map_ravens2math_rotating_machine!(data_math::Dict{String,<:Any}, data_ end +"converts ravens photovoltaic_unit components into mathematical generators" +function _map_ravens2math_photovoltaic_unit!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) + + regulating_cond_eq = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"]["RegulatingCondEq"] + power_scale_factor = data_math["settings"]["power_scale_factor"] + voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] + + for (name, ravens_obj) in get(regulating_cond_eq, "PowerElectronicsConnection", Dict{Any,Dict{String,Any}}()) + + # Get type of PowerElectronicsUnit + pec_type = get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "Ravens.CimObjectType", "") + + if pec_type == "PhotoVoltaicUnit" + + math_obj = _init_math_obj_ravens("photovoltaic_unit", name, ravens_obj, length(data_math["gen"])+1; pass_props=pass_props) + + # TODO: connections/phases do not exist in the RAVENS-CIM (Need to be added) - should come from terminals + connections = [1, 2, 3] # TODO + nconductors = length(connections) + math_obj["connections"] = connections + + connectivity_node = replace(split(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"], "::")[2], "'" => "") + math_obj["gen_bus"] = data_math["bus_lookup"][connectivity_node] + math_obj["gen_status"] = status = Int(get(ravens_obj, "ConductingEquipment.SvStatus", 1)) + + # TODO: control mode do not exist in the RAVENS-CIM (Need to be added) + math_obj["control_mode"] = control_mode = Int(get(ravens_obj, "control_mode", FREQUENCYDROOP)) + + # Set bus type + bus_type = data_math["bus"]["$(math_obj["gen_bus"])"]["bus_type"] + data_math["bus"]["$(math_obj["gen_bus"])"]["bus_type"] = _compute_bus_type(bus_type, status, control_mode) + + # Set the nominal voltage + base_voltage_ref = replace(split(ravens_obj["ConductingEquipment.BaseVoltage"], "::")[2], "'" => "") + nominal_voltage = data_ravens["BaseVoltage"][base_voltage_ref]["BaseVoltage.nominalVoltage"] + base_voltage = nominal_voltage / sqrt(nconductors) + math_obj["vbase"] = base_voltage / voltage_scale_factor + + if control_mode == Int(ISOCHRONOUS) && status == 1 + data_math["bus"]["$(math_obj["gen_bus"])"]["vm"] = ((get(ravens_obj, "PowerElectronicsConnection.ratedU", nominal_voltage))/nominal_voltage)* ones(nconductors) + data_math["bus"]["$(math_obj["gen_bus"])"]["vmax"] = ((get(ravens_obj, "PowerElectronicsConnection.ratedU", nominal_voltage))/nominal_voltage)* ones(nconductors) + data_math["bus"]["$(math_obj["gen_bus"])"]["vmin"] = ((get(ravens_obj, "PowerElectronicsConnection.ratedU", nominal_voltage))/nominal_voltage)* ones(nconductors) + data_math["bus"]["$(math_obj["gen_bus"])"]["va"] = [0.0, -120, 120, zeros(length(data_math["bus"]["$(math_obj["gen_bus"])"]) - 3)...][data_math["bus"]["$(math_obj["gen_bus"])"]["terminals"]] + data_math["bus"]["$(math_obj["gen_bus"])"]["bus_type"] = 3 + end + + # Set vg + for (fr_k, to_k) in [("PowerElectronicsConnection.ratedU", "vg")] + if haskey(ravens_obj, fr_k) + math_obj[to_k] = (ravens_obj[fr_k]/nominal_voltage)*ones(nconductors)/voltage_scale_factor + end + end + + # TODO: configuration for generators is not available on CIM (yet) + math_obj["configuration"] = get(ravens_obj, "configuration", WYE) + + + # TODO: refactor the calculation of N when connections and configuration issues are solved. + N = math_obj["configuration"]==DELTA && length(connections)==1 ? 1 : _infer_int_dim(connections, math_obj["configuration"], false) # if solar is delta-connected to triplex node, N can be equal to 1 + + # Set pmax + if !haskey(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "PowerElectronicsUnit.maxP") + math_obj["pmax"] = ((get(ravens_obj, "PowerElectronicsConnection.ratedS", Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) + else + math_obj["pmax"] = ((get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "PowerElectronicsUnit.maxP", Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) + end + # Set pmin + math_obj["pmin"] = ((get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "PowerElectronicsUnit.minP", 0) * ones(nconductors)) ./ nconductors)./(power_scale_factor) + # Set qmin + math_obj["qmin"] = ((get(ravens_obj, "PowerElectronicsConnection.minQ", -0) * ones(nconductors)) ./ nconductors)./(power_scale_factor) + # Set qmax + math_obj["qmax"] = ((get(ravens_obj, "PowerElectronicsConnection.maxQ", 0) * ones(nconductors)) ./ nconductors)./(power_scale_factor) + + + # Set pg and qg + math_obj["pg"] = (get(ravens_obj, "PowerElectronicsConnection.p", 0.0) * ones(nconductors) ./ nconductors)./(power_scale_factor) + math_obj["qg"] = (get(ravens_obj, "PowerElectronicsConnection.q", 0.0) * ones(nconductors) ./ nconductors)./(power_scale_factor) + + # TODO: add a polynomial parameters to be added to gen cost + _add_gen_cost_model!(math_obj, ravens_obj) + + # Set index + data_math["gen"]["$(math_obj["index"])"] = math_obj + + push!(data_math["map"], Dict{String,Any}( + "from" => name, + "to" => "gen.$(math_obj["index"])", + "unmap_function" => "_map_math2ravens_photovoltaic_unit!", + )) + + end + end +end + "converts ravensineering switches into mathematical switches and (if neeed) impedance branches to represent loss model" function _map_ravens2math_switch!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) From 05f483e43316bfde9962a53d5fe6f42de361d858 Mon Sep 17 00:00:00 2001 From: jjospina Date: Thu, 5 Sep 2024 15:24:22 -0600 Subject: [PATCH 08/27] ADD: storage or battery unit parser for ravens2math --- src/data_model/transformations/ravens2math.jl | 97 ++++++++++++++++++- src/prob/common.jl | 8 +- 2 files changed, 97 insertions(+), 8 deletions(-) diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index 8b01347ab..3f2e5d41d 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -1,20 +1,20 @@ "cim-ravens to math object mapping" const _math_to_ravens = Dict{String,String}( "bus" => "connectivity_node", - "transformer" => "power_transformer", - "switch" => "switch", + "transformer" => "power_transformer", # TODO + "switch" => "switch", # TODO # "shunt" => "shunt_compensator", "load" => "energy_consumer", "generator" => "rotating_machine", "solar" => "photovoltaic_unit", - # "storage" => "battery_unit", + "storage" => "battery_unit", "voltage_source" => "energy_source", ) "list of nodal type elements in the ravens model" const _ravens_node_elements = String[ - "energy_consumer", "rotating_machine", "photovoltaic_unit", "energy_source" + "energy_consumer", "rotating_machine", "photovoltaic_unit", "battery_unit", "energy_source" ] "list of edge type elements in the ravens model" @@ -696,6 +696,95 @@ function _map_ravens2math_photovoltaic_unit!(data_math::Dict{String,<:Any}, data end + +"converts engineering storage into mathematical storage" +function _map_ravens2math_battery_unit!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) + + regulating_cond_eq = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"]["RegulatingCondEq"] + power_scale_factor = data_math["settings"]["power_scale_factor"] + voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] + + for (name, ravens_obj) in get(regulating_cond_eq, "PowerElectronicsConnection", Dict{Any,Dict{String,Any}}()) + + # Get type of PowerElectronicsUnit + pec_type = get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "Ravens.CimObjectType", "") + + if pec_type == "BatteryUnit" + + math_obj = _init_math_obj_ravens("storage", name, ravens_obj, length(data_math["storage"])+1; pass_props=pass_props) + + # TODO: connections/phases do not exist in the RAVENS-CIM (Need to be added) - should come from terminals + connections = [1, 2, 3] # TODO + nconductors = length(connections) + math_obj["connections"] = connections + + # Set the bus + connectivity_node = replace(split(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"], "::")[2], "'" => "") + math_obj["storage_bus"] = data_math["bus_lookup"][connectivity_node] + math_obj["status"] = status = Int(get(ravens_obj, "ConductingEquipment.SvStatus", 1)) + + # TODO: configuration for generators is not available on CIM (yet) + math_obj["configuration"] = get(ravens_obj, "configuration", WYE) + + # Set battery parameters + math_obj["energy"] = ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"]["BatteryUnit.storedE"]/power_scale_factor + + if !haskey(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "InefficientBatteryUnit.limitEnergy") + math_obj["energy_rating"] = ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"]["BatteryUnit.ratedE"]/power_scale_factor + else + math_obj["energy_rating"] = ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"]["InefficientBatteryUnit.limitEnergy"]/power_scale_factor + end + + if !haskey(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "PowerElectronicsUnit.maxP") + math_obj["charge_rating"] = (get(ravens_obj, "PowerElectronicsConnection.ratedS", Inf))./(power_scale_factor) + math_obj["discharge_rating"] = math_obj["charge_rating"] + else + math_obj["charge_rating"] = (get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "PowerElectronicsUnit.maxP", Inf))./(power_scale_factor) + math_obj["discharge_rating"] = math_obj["charge_rating"] + end + + math_obj["charge_efficiency"] = get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "InefficientBatteryUnit.efficiencyCharge", 100.0) / 100.0 + math_obj["discharge_efficiency"] = get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "InefficientBatteryUnit.efficiencyDischarge", 100.0) / 100.0 + math_obj["thermal_rating"] = get(ravens_obj, "PowerElectronicsConnection.ratedS", Inf)/power_scale_factor + + math_obj["qmin"] = (get(ravens_obj, "PowerElectronicsConnection.minQ", -math_obj["discharge_rating"]*power_scale_factor))./(power_scale_factor) + math_obj["qmax"] = (get(ravens_obj, "PowerElectronicsConnection.maxQ", math_obj["charge_rating"]*power_scale_factor))./(power_scale_factor) + + # TODO: verify that these CIM terms are equivalent to the needed values. + math_obj["r"] = get(ravens_obj, "PowerElectronicsConnection.r", 0) + math_obj["x"] = get(ravens_obj, "PowerElectronicsConnection.x", 0) + + # TODO: These are still missing from the RAVENS Schema + math_obj["p_loss"] = get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "InefficientBatteryUnit.idlingActivePower", 0)./(power_scale_factor) + math_obj["q_loss"] = get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "InefficientBatteryUnit.idlingReactivePower", 0)./(power_scale_factor) + + # TODO: control mode do not exist in the RAVENS-CIM (Need to be added) + math_obj["control_mode"] = control_mode = Int(get(ravens_obj, "control_mode", FREQUENCYDROOP)) + + # Set the ps and qs + math_obj["ps"] = (get(ravens_obj, "PowerElectronicsConnection.p", 0.0))./(power_scale_factor) + math_obj["qs"] = (get(ravens_obj, "PowerElectronicsConnection.q", 0.0))./(power_scale_factor) + + # Set bus type + bus_type = data_math["bus"]["$(math_obj["storage_bus"])"]["bus_type"] + data_math["bus"]["$(math_obj["storage_bus"])"]["bus_type"] = _compute_bus_type(bus_type, status, control_mode) + + if control_mode == Int(ISOCHRONOUS) && math_obj["status"] == 1 + data_math["bus"]["$(math_obj["storage_bus"])"]["va"] = [0.0, -120, 120, zeros(length(data_math["bus"]["$(math_obj["storage_bus"])"]) - 3)...][data_math["bus"]["$(math_obj["storage_bus"])"]["terminals"]] + end + + data_math["storage"]["$(math_obj["index"])"] = math_obj + + push!(data_math["map"], Dict{String,Any}( + "from" => name, + "to" => "storage.$(math_obj["index"])", + "unmap_function" => "_map_math2ravens_battery_unit!", + )) + end + end +end + + "converts ravensineering switches into mathematical switches and (if neeed) impedance branches to represent loss model" function _map_ravens2math_switch!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) # TODO enable real switches (right now only using vitual lines) diff --git a/src/prob/common.jl b/src/prob/common.jl index 6eb79c6d4..2a255bf27 100644 --- a/src/prob/common.jl +++ b/src/prob/common.jl @@ -116,8 +116,8 @@ function instantiate_mc_model( ) end - @info "$(data["gen"])" - DEFINIDOEN_instantiate_mc_model + # @info "$(data["storage"])" + # DEFINIDOEN_instantiate_mc_model return _IM.instantiate_model( data, @@ -157,8 +157,8 @@ function instantiate_mc_model_ravens( make_pu_extensions=make_pu_extensions, ) - @info "$(data["gen"])" - DEFINIDOEN_instantiate_mc_model_ravens + # @info "$(data["storage"])" + # DEFINIDOEN_instantiate_mc_model_ravens return _IM.instantiate_model( data, From 1021d87cd0f85ed7ff6c9c60e529a9a3055b4076 Mon Sep 17 00:00:00 2001 From: jjospina Date: Thu, 5 Sep 2024 16:07:42 -0600 Subject: [PATCH 09/27] REF: combined PVs and Battery Units in Ravens parser to avoid multiple loops through PowerElectronicsConnection. --- src/data_model/transformations/ravens2math.jl | 28 ++++--------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index 3f2e5d41d..4cd0d3437 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -14,7 +14,7 @@ const _math_to_ravens = Dict{String,String}( "list of nodal type elements in the ravens model" const _ravens_node_elements = String[ - "energy_consumer", "rotating_machine", "photovoltaic_unit", "battery_unit", "energy_source" + "energy_consumer", "rotating_machine", "power_electronics", "energy_source" ] "list of edge type elements in the ravens model" @@ -601,8 +601,8 @@ function _map_ravens2math_rotating_machine!(data_math::Dict{String,<:Any}, data_ end -"converts ravens photovoltaic_unit components into mathematical generators" -function _map_ravens2math_photovoltaic_unit!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) +"converts ravens power_electronics units such as PVs and Batteries into mathematical components" +function _map_ravens2math_power_electronics!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) regulating_cond_eq = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"]["RegulatingCondEq"] power_scale_factor = data_math["settings"]["power_scale_factor"] @@ -613,7 +613,7 @@ function _map_ravens2math_photovoltaic_unit!(data_math::Dict{String,<:Any}, data # Get type of PowerElectronicsUnit pec_type = get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "Ravens.CimObjectType", "") - if pec_type == "PhotoVoltaicUnit" + if (pec_type == "PhotoVoltaicUnit") math_obj = _init_math_obj_ravens("photovoltaic_unit", name, ravens_obj, length(data_math["gen"])+1; pass_props=pass_props) @@ -691,25 +691,7 @@ function _map_ravens2math_photovoltaic_unit!(data_math::Dict{String,<:Any}, data "unmap_function" => "_map_math2ravens_photovoltaic_unit!", )) - end - end -end - - - -"converts engineering storage into mathematical storage" -function _map_ravens2math_battery_unit!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) - - regulating_cond_eq = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"]["RegulatingCondEq"] - power_scale_factor = data_math["settings"]["power_scale_factor"] - voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] - - for (name, ravens_obj) in get(regulating_cond_eq, "PowerElectronicsConnection", Dict{Any,Dict{String,Any}}()) - - # Get type of PowerElectronicsUnit - pec_type = get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "Ravens.CimObjectType", "") - - if pec_type == "BatteryUnit" + elseif (pec_type == "BatteryUnit") math_obj = _init_math_obj_ravens("storage", name, ravens_obj, length(data_math["storage"])+1; pass_props=pass_props) From d7559d7aed829cccdfb55cc4e031e3622e3e1fac Mon Sep 17 00:00:00 2001 From: jjospina Date: Thu, 26 Sep 2024 12:45:21 -0600 Subject: [PATCH 10/27] REF: ravens2math parser to fix impedance calculations and support files coming from dss-xml-json ravens exporters. --- src/data_model/transformations/ravens2math.jl | 89 +++++++++++++++---- src/data_model/utils_ravens.jl | 26 +++--- src/prob/common.jl | 4 +- 3 files changed, 88 insertions(+), 31 deletions(-) diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index 4cd0d3437..2deb9e187 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -335,10 +335,25 @@ function _map_ravens2math_energy_consumer!(data_math::Dict{String,<:Any}, data_r # Set voltage bounds for the bus connected bus_info = string(math_obj["load_bus"]) bus_conn = data_math["bus"][bus_info] - op_limit_id = replace(split(data_ravens["ConnectivityNode"][connectivity_node]["ConnectivityNode.OperationalLimitSet"], "::")[2], "'" => "") - op_limits = data_ravens["OperationalLimitSet"][op_limit_id]["OperationalLimitSet.OperationalLimitValue"] - op_limit_max = op_limits[1]["VoltageLimit.value"] / voltage_scale_factor_sqrt3 - op_limit_min = op_limits[2]["VoltageLimit.value"] / voltage_scale_factor_sqrt3 + + if haskey(data_ravens["ConnectivityNode"][connectivity_node], "ConnectivityNode.OperationalLimitSet") + op_limit_id = replace(split(data_ravens["ConnectivityNode"][connectivity_node]["ConnectivityNode.OperationalLimitSet"], "::")[2], "'" => "") + op_limits = data_ravens["OperationalLimitSet"][op_limit_id]["OperationalLimitSet.OperationalLimitValue"] + + # Loop through op. limits + for lim in op_limits + lim_type = lim["OperationalLimit.OperationalLimitType"]["OperationalLimitType.direction"] + if lim_type == "OperationalLimitDirectionKind.high" + op_limit_max = lim["VoltageLimit.value"] / voltage_scale_factor_sqrt3 + elseif lim_type == "OperationalLimitDirectionKind.low" + op_limit_min = lim["VoltageLimit.value"] / voltage_scale_factor_sqrt3 + end + end + + else + op_limit_max = Inf + op_limit_min = 0.0 + end # Handle phase-specific or three-phase connection phase_map = Dict("SinglePhaseKind.A" => 1, "SinglePhaseKind.B" => 2, "SinglePhaseKind.C" => 3) @@ -423,7 +438,29 @@ function _map_ravens2math_energy_source!(data_math::Dict{String,<:Any}, data_rav end math_obj["connections"] = connections else - math_obj["connections"] = bus_conn["terminals"] + # Terminal Phases + if haskey(ravens_obj["ConductingEquipment.Terminals"][1], "Terminal.phases") + phasecode = ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.phases"] + if (phasecode == "PhaseCode.ABC") + math_obj["connections"] = [1, 2, 3] + elseif (phasecode == "PhaseCode.AB") + math_obj["connections"] = [1, 2] + elseif (phasecode == "PhaseCode.AC") + math_obj["connections"] = [1, 3] + elseif (phasecode == "PhaseCode.BC") + math_obj["connections"] = [2, 3] + elseif (phasecode == "PhaseCode.A") + math_obj["connections"] = [1] + elseif (phasecode == "PhaseCode.B") + math_obj["connections"] = [2] + elseif (phasecode == "PhaseCode.C") + math_obj["connections"] = [3] + else + @error("PhaseCode not supported yet!") + end + else + math_obj["connections"] = bus_conn["terminals"] + end end # Generator status and configuration @@ -534,8 +571,30 @@ function _map_ravens2math_rotating_machine!(data_math::Dict{String,<:Any}, data_ math_obj = _init_math_obj_ravens("rotating_machine", name, ravens_obj, length(data_math["gen"])+1; pass_props=pass_props) - # TODO: connections/phases do not exist in the RAVENS-CIM (Need to be added) - should come from terminals - connections = [1, 2, 3] # TODO + # Connections/phases obtained from Terminals + if haskey(ravens_obj["ConductingEquipment.Terminals"][1], "Terminal.phases") + phasecode = ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.phases"] + if (phasecode == "PhaseCode.ABC") + connections = [1, 2, 3] + elseif (phasecode == "PhaseCode.AB") + connections = [1, 2] + elseif (phasecode == "PhaseCode.AC") + connections = [1, 3] + elseif (phasecode == "PhaseCode.BC") + connections = [2, 3] + elseif (phasecode == "PhaseCode.A") + connections = [1] + elseif (phasecode == "PhaseCode.B") + connections = [2] + elseif (phasecode == "PhaseCode.C") + connections = [3] + else + @error("PhaseCode not supported yet!") + end + else + connections = [1, 2, 3] # default + end + nconductors = length(connections) math_obj["connections"] = connections @@ -548,7 +607,7 @@ function _map_ravens2math_rotating_machine!(data_math::Dict{String,<:Any}, data_ # Set Pmax for generator if !haskey(ravens_obj, "GeneratingUnit.maxOperatingP") - math_obj["pmax"] = ((get(ravens_obj, "SynchronousMachine.ratedS", Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) + math_obj["pmax"] = ((get(ravens_obj, "RotatingMachine.ratedS", Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) else math_obj["pmax"] = ((get(ravens_obj, "GeneratingUnit.maxOperatingP", Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) end @@ -564,22 +623,22 @@ function _map_ravens2math_rotating_machine!(data_math::Dict{String,<:Any}, data_ math_obj["vbase"] = base_voltage / voltage_scale_factor if control_mode == Int(ISOCHRONOUS) && status == 1 - data_math["bus"]["$(math_obj["gen_bus"])"]["vm"] = ((get(ravens_obj, "SynchronousMachine.ratedU", nominal_voltage))/nominal_voltage)* ones(nconductors) - data_math["bus"]["$(math_obj["gen_bus"])"]["vmax"] = ((get(ravens_obj, "SynchronousMachine.ratedU", nominal_voltage))/nominal_voltage)* ones(nconductors) - data_math["bus"]["$(math_obj["gen_bus"])"]["vmin"] = ((get(ravens_obj, "SynchronousMachine.ratedU", nominal_voltage))/nominal_voltage)* ones(nconductors) + data_math["bus"]["$(math_obj["gen_bus"])"]["vm"] = ((get(ravens_obj, "RotatingMachine.ratedU", nominal_voltage))/nominal_voltage)* ones(nconductors) + data_math["bus"]["$(math_obj["gen_bus"])"]["vmax"] = ((get(ravens_obj, "RotatingMachine.ratedU", nominal_voltage))/nominal_voltage)* ones(nconductors) + data_math["bus"]["$(math_obj["gen_bus"])"]["vmin"] = ((get(ravens_obj, "RotatingMachine.ratedU", nominal_voltage))/nominal_voltage)* ones(nconductors) data_math["bus"]["$(math_obj["gen_bus"])"]["va"] = [0.0, -120, 120, zeros(length(data_math["bus"]["$(math_obj["gen_bus"])"]) - 3)...][data_math["bus"]["$(math_obj["gen_bus"])"]["terminals"]] end # Set pmin math_obj["pmin"] = ((get(ravens_obj, "GeneratingUnit.minOperatingP", 0) * ones(nconductors)) ./ nconductors)./(power_scale_factor) # Set qmin - math_obj["qmin"] = ((get(ravens_obj, "SynchronousMachine.minQ", -Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) + math_obj["qmin"] = ((get(ravens_obj, "RotatingMachine.minQ", -Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) # Set qmax - math_obj["qmax"] = ((get(ravens_obj, "SynchronousMachine.maxQ", Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) + math_obj["qmax"] = ((get(ravens_obj, "RotatingMachine.maxQ", Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) # Set pg and qg - math_obj["pg"] = (get(ravens_obj, "SynchronousMachine.p", 0.0) * ones(nconductors) ./ nconductors)./(power_scale_factor) - math_obj["qg"] = (get(ravens_obj, "SynchronousMachine.q", 0.0) * ones(nconductors) ./ nconductors)./(power_scale_factor) + math_obj["pg"] = (get(ravens_obj, "RotatingMachine.p", 0.0) * ones(nconductors) ./ nconductors)./(power_scale_factor) + math_obj["qg"] = (get(ravens_obj, "RotatingMachine.q", 0.0) * ones(nconductors) ./ nconductors)./(power_scale_factor) # TODO: add a polynomial parameters to be added to gen cost _add_gen_cost_model!(math_obj, ravens_obj) diff --git a/src/data_model/utils_ravens.jl b/src/data_model/utils_ravens.jl index 27ca59a61..adf2ec79a 100644 --- a/src/data_model/utils_ravens.jl +++ b/src/data_model/utils_ravens.jl @@ -18,13 +18,12 @@ function _impedance_conversion_ravens(data_eng::Dict{String,Any}, eng_obj::Dict{ _conductor_count = data_eng["PerLengthPhaseImpedance.conductorCount"] _impedance_matrix = zeros(Float64, _conductor_count, _conductor_count) - _index = 1 - for i in 1:_conductor_count - for j in 1:i - _impedance_matrix[i, j] = get(data_eng["PerLengthPhaseImpedance.PhaseImpedanceData"][_index], key, 0.0) - _impedance_matrix[j, i] = get(data_eng["PerLengthPhaseImpedance.PhaseImpedanceData"][_index], key, 0.0) - _index += 1 - end + for obj in data_eng["PerLengthPhaseImpedance.PhaseImpedanceData"] + row = obj["PhaseImpedanceData.row"] + col = obj["PhaseImpedanceData.column"] + value = get(obj, key, 0.0) + _impedance_matrix[row, col] = value + _impedance_matrix[col, row] = value end return _impedance_matrix .* get(eng_obj, "Conductor.length", 1.0) @@ -61,13 +60,12 @@ function _admittance_conversion_ravens(data_eng::Dict{String,<:Any}, eng_obj::Di _conductor_count = data_eng["PerLengthPhaseImpedance.conductorCount"] _admittance_matrix = zeros(Float64, _conductor_count, _conductor_count) - _index = 1 - for i in 1:_conductor_count - for j in 1:i - _admittance_matrix[i, j] = get(data_eng["PerLengthPhaseImpedance.PhaseImpedanceData"][_index], key, 0.0) - _admittance_matrix[j, i] = get(data_eng["PerLengthPhaseImpedance.PhaseImpedanceData"][_index], key, 0.0) - _index += 1 - end + for obj in data_eng["PerLengthPhaseImpedance.PhaseImpedanceData"] + row = obj["PhaseImpedanceData.row"] + col = obj["PhaseImpedanceData.column"] + value = get(obj, key, 0.0) + _admittance_matrix[row, col] = value + _admittance_matrix[col, row] = value end return _admittance_matrix .* get(eng_obj, "Conductor.length", 1.0) .* freq ./ 1e2 # divide by 2 to get both sides _to and _fr diff --git a/src/prob/common.jl b/src/prob/common.jl index 2a255bf27..90ce1673b 100644 --- a/src/prob/common.jl +++ b/src/prob/common.jl @@ -116,7 +116,7 @@ function instantiate_mc_model( ) end - # @info "$(data["storage"])" + # @info "$(data["branch"])" # DEFINIDOEN_instantiate_mc_model return _IM.instantiate_model( @@ -157,7 +157,7 @@ function instantiate_mc_model_ravens( make_pu_extensions=make_pu_extensions, ) - # @info "$(data["storage"])" + # @info "$(data["branch"])" # DEFINIDOEN_instantiate_mc_model_ravens return _IM.instantiate_model( From e7b082ccdb827d6ab047ed513a8820720e2e2a9c Mon Sep 17 00:00:00 2001 From: jjospina Date: Thu, 26 Sep 2024 13:53:09 -0600 Subject: [PATCH 11/27] REF: add haskey check when looking for gens and power electronics --- src/data_model/transformations/ravens2math.jl | 264 +++++++++--------- src/prob/common.jl | 8 +- 2 files changed, 140 insertions(+), 132 deletions(-) diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index 2deb9e187..fbf86e3f2 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -563,11 +563,13 @@ end "converts engineering generators into mathematical generators" function _map_ravens2math_rotating_machine!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) - regulating_cond_eq = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"]["RegulatingCondEq"] - power_scale_factor = data_math["settings"]["power_scale_factor"] - voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] + if haskey(data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"], "RegulatingCondEq") + + regulating_cond_eq = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"]["RegulatingCondEq"] + power_scale_factor = data_math["settings"]["power_scale_factor"] + voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] - for (name, ravens_obj) in get(regulating_cond_eq, "RotatingMachine", Dict{Any,Dict{String,Any}}()) + for (name, ravens_obj) in get(regulating_cond_eq, "RotatingMachine", Dict{Any,Dict{String,Any}}()) math_obj = _init_math_obj_ravens("rotating_machine", name, ravens_obj, length(data_math["gen"])+1; pass_props=pass_props) @@ -654,8 +656,9 @@ function _map_ravens2math_rotating_machine!(data_math::Dict{String,<:Any}, data_ "to" => "gen.$(math_obj["index"])", "unmap_function" => "_map_math2ravens_rotating_machine!", )) - end + end + end end @@ -663,166 +666,171 @@ end "converts ravens power_electronics units such as PVs and Batteries into mathematical components" function _map_ravens2math_power_electronics!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) - regulating_cond_eq = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"]["RegulatingCondEq"] - power_scale_factor = data_math["settings"]["power_scale_factor"] - voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] + if haskey(data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"], "RegulatingCondEq") - for (name, ravens_obj) in get(regulating_cond_eq, "PowerElectronicsConnection", Dict{Any,Dict{String,Any}}()) + regulating_cond_eq = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"]["RegulatingCondEq"] + power_scale_factor = data_math["settings"]["power_scale_factor"] + voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] - # Get type of PowerElectronicsUnit - pec_type = get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "Ravens.CimObjectType", "") + for (name, ravens_obj) in get(regulating_cond_eq, "PowerElectronicsConnection", Dict{Any,Dict{String,Any}}()) - if (pec_type == "PhotoVoltaicUnit") + # Get type of PowerElectronicsUnit + pec_type = get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "Ravens.CimObjectType", "") - math_obj = _init_math_obj_ravens("photovoltaic_unit", name, ravens_obj, length(data_math["gen"])+1; pass_props=pass_props) + if (pec_type == "PhotoVoltaicUnit") - # TODO: connections/phases do not exist in the RAVENS-CIM (Need to be added) - should come from terminals - connections = [1, 2, 3] # TODO - nconductors = length(connections) - math_obj["connections"] = connections + math_obj = _init_math_obj_ravens("photovoltaic_unit", name, ravens_obj, length(data_math["gen"])+1; pass_props=pass_props) - connectivity_node = replace(split(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"], "::")[2], "'" => "") - math_obj["gen_bus"] = data_math["bus_lookup"][connectivity_node] - math_obj["gen_status"] = status = Int(get(ravens_obj, "ConductingEquipment.SvStatus", 1)) - - # TODO: control mode do not exist in the RAVENS-CIM (Need to be added) - math_obj["control_mode"] = control_mode = Int(get(ravens_obj, "control_mode", FREQUENCYDROOP)) - - # Set bus type - bus_type = data_math["bus"]["$(math_obj["gen_bus"])"]["bus_type"] - data_math["bus"]["$(math_obj["gen_bus"])"]["bus_type"] = _compute_bus_type(bus_type, status, control_mode) - - # Set the nominal voltage - base_voltage_ref = replace(split(ravens_obj["ConductingEquipment.BaseVoltage"], "::")[2], "'" => "") - nominal_voltage = data_ravens["BaseVoltage"][base_voltage_ref]["BaseVoltage.nominalVoltage"] - base_voltage = nominal_voltage / sqrt(nconductors) - math_obj["vbase"] = base_voltage / voltage_scale_factor - - if control_mode == Int(ISOCHRONOUS) && status == 1 - data_math["bus"]["$(math_obj["gen_bus"])"]["vm"] = ((get(ravens_obj, "PowerElectronicsConnection.ratedU", nominal_voltage))/nominal_voltage)* ones(nconductors) - data_math["bus"]["$(math_obj["gen_bus"])"]["vmax"] = ((get(ravens_obj, "PowerElectronicsConnection.ratedU", nominal_voltage))/nominal_voltage)* ones(nconductors) - data_math["bus"]["$(math_obj["gen_bus"])"]["vmin"] = ((get(ravens_obj, "PowerElectronicsConnection.ratedU", nominal_voltage))/nominal_voltage)* ones(nconductors) - data_math["bus"]["$(math_obj["gen_bus"])"]["va"] = [0.0, -120, 120, zeros(length(data_math["bus"]["$(math_obj["gen_bus"])"]) - 3)...][data_math["bus"]["$(math_obj["gen_bus"])"]["terminals"]] - data_math["bus"]["$(math_obj["gen_bus"])"]["bus_type"] = 3 - end + # TODO: connections/phases do not exist in the RAVENS-CIM (Need to be added) - should come from terminals + connections = [1, 2, 3] # TODO + nconductors = length(connections) + math_obj["connections"] = connections + + connectivity_node = replace(split(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"], "::")[2], "'" => "") + math_obj["gen_bus"] = data_math["bus_lookup"][connectivity_node] + math_obj["gen_status"] = status = Int(get(ravens_obj, "ConductingEquipment.SvStatus", 1)) + + # TODO: control mode do not exist in the RAVENS-CIM (Need to be added) + math_obj["control_mode"] = control_mode = Int(get(ravens_obj, "control_mode", FREQUENCYDROOP)) + + # Set bus type + bus_type = data_math["bus"]["$(math_obj["gen_bus"])"]["bus_type"] + data_math["bus"]["$(math_obj["gen_bus"])"]["bus_type"] = _compute_bus_type(bus_type, status, control_mode) + + # Set the nominal voltage + base_voltage_ref = replace(split(ravens_obj["ConductingEquipment.BaseVoltage"], "::")[2], "'" => "") + nominal_voltage = data_ravens["BaseVoltage"][base_voltage_ref]["BaseVoltage.nominalVoltage"] + base_voltage = nominal_voltage / sqrt(nconductors) + math_obj["vbase"] = base_voltage / voltage_scale_factor - # Set vg - for (fr_k, to_k) in [("PowerElectronicsConnection.ratedU", "vg")] - if haskey(ravens_obj, fr_k) - math_obj[to_k] = (ravens_obj[fr_k]/nominal_voltage)*ones(nconductors)/voltage_scale_factor + if control_mode == Int(ISOCHRONOUS) && status == 1 + data_math["bus"]["$(math_obj["gen_bus"])"]["vm"] = ((get(ravens_obj, "PowerElectronicsConnection.ratedU", nominal_voltage))/nominal_voltage)* ones(nconductors) + data_math["bus"]["$(math_obj["gen_bus"])"]["vmax"] = ((get(ravens_obj, "PowerElectronicsConnection.ratedU", nominal_voltage))/nominal_voltage)* ones(nconductors) + data_math["bus"]["$(math_obj["gen_bus"])"]["vmin"] = ((get(ravens_obj, "PowerElectronicsConnection.ratedU", nominal_voltage))/nominal_voltage)* ones(nconductors) + data_math["bus"]["$(math_obj["gen_bus"])"]["va"] = [0.0, -120, 120, zeros(length(data_math["bus"]["$(math_obj["gen_bus"])"]) - 3)...][data_math["bus"]["$(math_obj["gen_bus"])"]["terminals"]] + data_math["bus"]["$(math_obj["gen_bus"])"]["bus_type"] = 3 end - end - # TODO: configuration for generators is not available on CIM (yet) - math_obj["configuration"] = get(ravens_obj, "configuration", WYE) + # Set vg + for (fr_k, to_k) in [("PowerElectronicsConnection.ratedU", "vg")] + if haskey(ravens_obj, fr_k) + math_obj[to_k] = (ravens_obj[fr_k]/nominal_voltage)*ones(nconductors)/voltage_scale_factor + end + end + # TODO: configuration for generators is not available on CIM (yet) + math_obj["configuration"] = get(ravens_obj, "configuration", WYE) - # TODO: refactor the calculation of N when connections and configuration issues are solved. - N = math_obj["configuration"]==DELTA && length(connections)==1 ? 1 : _infer_int_dim(connections, math_obj["configuration"], false) # if solar is delta-connected to triplex node, N can be equal to 1 - # Set pmax - if !haskey(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "PowerElectronicsUnit.maxP") - math_obj["pmax"] = ((get(ravens_obj, "PowerElectronicsConnection.ratedS", Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) - else - math_obj["pmax"] = ((get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "PowerElectronicsUnit.maxP", Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) - end - # Set pmin - math_obj["pmin"] = ((get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "PowerElectronicsUnit.minP", 0) * ones(nconductors)) ./ nconductors)./(power_scale_factor) - # Set qmin - math_obj["qmin"] = ((get(ravens_obj, "PowerElectronicsConnection.minQ", -0) * ones(nconductors)) ./ nconductors)./(power_scale_factor) - # Set qmax - math_obj["qmax"] = ((get(ravens_obj, "PowerElectronicsConnection.maxQ", 0) * ones(nconductors)) ./ nconductors)./(power_scale_factor) + # TODO: refactor the calculation of N when connections and configuration issues are solved. + N = math_obj["configuration"]==DELTA && length(connections)==1 ? 1 : _infer_int_dim(connections, math_obj["configuration"], false) # if solar is delta-connected to triplex node, N can be equal to 1 + # Set pmax + if !haskey(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "PowerElectronicsUnit.maxP") + math_obj["pmax"] = ((get(ravens_obj, "PowerElectronicsConnection.ratedS", Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) + else + math_obj["pmax"] = ((get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "PowerElectronicsUnit.maxP", Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) + end + # Set pmin + math_obj["pmin"] = ((get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "PowerElectronicsUnit.minP", 0) * ones(nconductors)) ./ nconductors)./(power_scale_factor) + # Set qmin + math_obj["qmin"] = ((get(ravens_obj, "PowerElectronicsConnection.minQ", -0) * ones(nconductors)) ./ nconductors)./(power_scale_factor) + # Set qmax + math_obj["qmax"] = ((get(ravens_obj, "PowerElectronicsConnection.maxQ", 0) * ones(nconductors)) ./ nconductors)./(power_scale_factor) - # Set pg and qg - math_obj["pg"] = (get(ravens_obj, "PowerElectronicsConnection.p", 0.0) * ones(nconductors) ./ nconductors)./(power_scale_factor) - math_obj["qg"] = (get(ravens_obj, "PowerElectronicsConnection.q", 0.0) * ones(nconductors) ./ nconductors)./(power_scale_factor) - # TODO: add a polynomial parameters to be added to gen cost - _add_gen_cost_model!(math_obj, ravens_obj) + # Set pg and qg + math_obj["pg"] = (get(ravens_obj, "PowerElectronicsConnection.p", 0.0) * ones(nconductors) ./ nconductors)./(power_scale_factor) + math_obj["qg"] = (get(ravens_obj, "PowerElectronicsConnection.q", 0.0) * ones(nconductors) ./ nconductors)./(power_scale_factor) - # Set index - data_math["gen"]["$(math_obj["index"])"] = math_obj + # TODO: add a polynomial parameters to be added to gen cost + _add_gen_cost_model!(math_obj, ravens_obj) - push!(data_math["map"], Dict{String,Any}( - "from" => name, - "to" => "gen.$(math_obj["index"])", - "unmap_function" => "_map_math2ravens_photovoltaic_unit!", - )) + # Set index + data_math["gen"]["$(math_obj["index"])"] = math_obj - elseif (pec_type == "BatteryUnit") + push!(data_math["map"], Dict{String,Any}( + "from" => name, + "to" => "gen.$(math_obj["index"])", + "unmap_function" => "_map_math2ravens_photovoltaic_unit!", + )) - math_obj = _init_math_obj_ravens("storage", name, ravens_obj, length(data_math["storage"])+1; pass_props=pass_props) + elseif (pec_type == "BatteryUnit") - # TODO: connections/phases do not exist in the RAVENS-CIM (Need to be added) - should come from terminals - connections = [1, 2, 3] # TODO - nconductors = length(connections) - math_obj["connections"] = connections + math_obj = _init_math_obj_ravens("storage", name, ravens_obj, length(data_math["storage"])+1; pass_props=pass_props) - # Set the bus - connectivity_node = replace(split(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"], "::")[2], "'" => "") - math_obj["storage_bus"] = data_math["bus_lookup"][connectivity_node] - math_obj["status"] = status = Int(get(ravens_obj, "ConductingEquipment.SvStatus", 1)) + # TODO: connections/phases do not exist in the RAVENS-CIM (Need to be added) - should come from terminals + connections = [1, 2, 3] # TODO + nconductors = length(connections) + math_obj["connections"] = connections - # TODO: configuration for generators is not available on CIM (yet) - math_obj["configuration"] = get(ravens_obj, "configuration", WYE) + # Set the bus + connectivity_node = replace(split(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"], "::")[2], "'" => "") + math_obj["storage_bus"] = data_math["bus_lookup"][connectivity_node] + math_obj["status"] = status = Int(get(ravens_obj, "ConductingEquipment.SvStatus", 1)) - # Set battery parameters - math_obj["energy"] = ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"]["BatteryUnit.storedE"]/power_scale_factor + # TODO: configuration for generators is not available on CIM (yet) + math_obj["configuration"] = get(ravens_obj, "configuration", WYE) - if !haskey(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "InefficientBatteryUnit.limitEnergy") - math_obj["energy_rating"] = ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"]["BatteryUnit.ratedE"]/power_scale_factor - else - math_obj["energy_rating"] = ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"]["InefficientBatteryUnit.limitEnergy"]/power_scale_factor - end + # Set battery parameters + math_obj["energy"] = ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"]["BatteryUnit.storedE"]/power_scale_factor - if !haskey(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "PowerElectronicsUnit.maxP") - math_obj["charge_rating"] = (get(ravens_obj, "PowerElectronicsConnection.ratedS", Inf))./(power_scale_factor) - math_obj["discharge_rating"] = math_obj["charge_rating"] - else - math_obj["charge_rating"] = (get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "PowerElectronicsUnit.maxP", Inf))./(power_scale_factor) - math_obj["discharge_rating"] = math_obj["charge_rating"] - end + if !haskey(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "InefficientBatteryUnit.limitEnergy") + math_obj["energy_rating"] = ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"]["BatteryUnit.ratedE"]/power_scale_factor + else + math_obj["energy_rating"] = ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"]["InefficientBatteryUnit.limitEnergy"]/power_scale_factor + end - math_obj["charge_efficiency"] = get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "InefficientBatteryUnit.efficiencyCharge", 100.0) / 100.0 - math_obj["discharge_efficiency"] = get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "InefficientBatteryUnit.efficiencyDischarge", 100.0) / 100.0 - math_obj["thermal_rating"] = get(ravens_obj, "PowerElectronicsConnection.ratedS", Inf)/power_scale_factor + if !haskey(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "PowerElectronicsUnit.maxP") + math_obj["charge_rating"] = (get(ravens_obj, "PowerElectronicsConnection.ratedS", Inf))./(power_scale_factor) + math_obj["discharge_rating"] = math_obj["charge_rating"] + else + math_obj["charge_rating"] = (get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "PowerElectronicsUnit.maxP", Inf))./(power_scale_factor) + math_obj["discharge_rating"] = math_obj["charge_rating"] + end - math_obj["qmin"] = (get(ravens_obj, "PowerElectronicsConnection.minQ", -math_obj["discharge_rating"]*power_scale_factor))./(power_scale_factor) - math_obj["qmax"] = (get(ravens_obj, "PowerElectronicsConnection.maxQ", math_obj["charge_rating"]*power_scale_factor))./(power_scale_factor) + math_obj["charge_efficiency"] = get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "InefficientBatteryUnit.efficiencyCharge", 100.0) / 100.0 + math_obj["discharge_efficiency"] = get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "InefficientBatteryUnit.efficiencyDischarge", 100.0) / 100.0 + math_obj["thermal_rating"] = get(ravens_obj, "PowerElectronicsConnection.ratedS", Inf)/power_scale_factor - # TODO: verify that these CIM terms are equivalent to the needed values. - math_obj["r"] = get(ravens_obj, "PowerElectronicsConnection.r", 0) - math_obj["x"] = get(ravens_obj, "PowerElectronicsConnection.x", 0) + math_obj["qmin"] = (get(ravens_obj, "PowerElectronicsConnection.minQ", -math_obj["discharge_rating"]*power_scale_factor))./(power_scale_factor) + math_obj["qmax"] = (get(ravens_obj, "PowerElectronicsConnection.maxQ", math_obj["charge_rating"]*power_scale_factor))./(power_scale_factor) - # TODO: These are still missing from the RAVENS Schema - math_obj["p_loss"] = get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "InefficientBatteryUnit.idlingActivePower", 0)./(power_scale_factor) - math_obj["q_loss"] = get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "InefficientBatteryUnit.idlingReactivePower", 0)./(power_scale_factor) + # TODO: verify that these CIM terms are equivalent to the needed values. + math_obj["r"] = get(ravens_obj, "PowerElectronicsConnection.r", 0) + math_obj["x"] = get(ravens_obj, "PowerElectronicsConnection.x", 0) - # TODO: control mode do not exist in the RAVENS-CIM (Need to be added) - math_obj["control_mode"] = control_mode = Int(get(ravens_obj, "control_mode", FREQUENCYDROOP)) + # TODO: These are still missing from the RAVENS Schema + math_obj["p_loss"] = get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "InefficientBatteryUnit.idlingActivePower", 0)./(power_scale_factor) + math_obj["q_loss"] = get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "InefficientBatteryUnit.idlingReactivePower", 0)./(power_scale_factor) - # Set the ps and qs - math_obj["ps"] = (get(ravens_obj, "PowerElectronicsConnection.p", 0.0))./(power_scale_factor) - math_obj["qs"] = (get(ravens_obj, "PowerElectronicsConnection.q", 0.0))./(power_scale_factor) + # TODO: control mode do not exist in the RAVENS-CIM (Need to be added) + math_obj["control_mode"] = control_mode = Int(get(ravens_obj, "control_mode", FREQUENCYDROOP)) - # Set bus type - bus_type = data_math["bus"]["$(math_obj["storage_bus"])"]["bus_type"] - data_math["bus"]["$(math_obj["storage_bus"])"]["bus_type"] = _compute_bus_type(bus_type, status, control_mode) + # Set the ps and qs + math_obj["ps"] = (get(ravens_obj, "PowerElectronicsConnection.p", 0.0))./(power_scale_factor) + math_obj["qs"] = (get(ravens_obj, "PowerElectronicsConnection.q", 0.0))./(power_scale_factor) - if control_mode == Int(ISOCHRONOUS) && math_obj["status"] == 1 - data_math["bus"]["$(math_obj["storage_bus"])"]["va"] = [0.0, -120, 120, zeros(length(data_math["bus"]["$(math_obj["storage_bus"])"]) - 3)...][data_math["bus"]["$(math_obj["storage_bus"])"]["terminals"]] - end + # Set bus type + bus_type = data_math["bus"]["$(math_obj["storage_bus"])"]["bus_type"] + data_math["bus"]["$(math_obj["storage_bus"])"]["bus_type"] = _compute_bus_type(bus_type, status, control_mode) + + if control_mode == Int(ISOCHRONOUS) && math_obj["status"] == 1 + data_math["bus"]["$(math_obj["storage_bus"])"]["va"] = [0.0, -120, 120, zeros(length(data_math["bus"]["$(math_obj["storage_bus"])"]) - 3)...][data_math["bus"]["$(math_obj["storage_bus"])"]["terminals"]] + end - data_math["storage"]["$(math_obj["index"])"] = math_obj + data_math["storage"]["$(math_obj["index"])"] = math_obj - push!(data_math["map"], Dict{String,Any}( - "from" => name, - "to" => "storage.$(math_obj["index"])", - "unmap_function" => "_map_math2ravens_battery_unit!", - )) + push!(data_math["map"], Dict{String,Any}( + "from" => name, + "to" => "storage.$(math_obj["index"])", + "unmap_function" => "_map_math2ravens_battery_unit!", + )) + end end + end + end diff --git a/src/prob/common.jl b/src/prob/common.jl index 90ce1673b..c96407c27 100644 --- a/src/prob/common.jl +++ b/src/prob/common.jl @@ -116,8 +116,8 @@ function instantiate_mc_model( ) end - # @info "$(data["branch"])" - # DEFINIDOEN_instantiate_mc_model + @info "$(data["switch"])" + DEFINIDOEN_instantiate_mc_model return _IM.instantiate_model( data, @@ -157,8 +157,8 @@ function instantiate_mc_model_ravens( make_pu_extensions=make_pu_extensions, ) - # @info "$(data["branch"])" - # DEFINIDOEN_instantiate_mc_model_ravens + @info "$(data["switch"])" + DEFINIDOEN_instantiate_mc_model_ravens return _IM.instantiate_model( data, From 8bb608de7b2dab5a118b3426448f00f16aa26248 Mon Sep 17 00:00:00 2001 From: jjospina Date: Thu, 26 Sep 2024 15:32:21 -0600 Subject: [PATCH 12/27] WIP: Switches - still missing connection to virtual bus and branches. --- src/data_model/transformations/ravens2math.jl | 130 +++++++++++++++++- src/prob/common.jl | 8 +- 2 files changed, 130 insertions(+), 8 deletions(-) diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index fbf86e3f2..3406fe19a 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -19,7 +19,7 @@ const _ravens_node_elements = String[ "list of edge type elements in the ravens model" const _ravens_edge_elements = String[ - "conductor" + "conductor", "switch" ] "list of all ravens asset types" @@ -834,10 +834,132 @@ function _map_ravens2math_power_electronics!(data_math::Dict{String,<:Any}, data end -"converts ravensineering switches into mathematical switches and (if neeed) impedance branches to represent loss model" +"converts ravens switches into mathematical switches and (if neeed) impedance branches to represent loss model" function _map_ravens2math_switch!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) + # TODO enable real switches (right now only using vitual lines) - for (name, ravens_obj) in get(data_ravens, "switch", Dict{Any,Dict{String,Any}}()) - # TODO + if haskey(data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"], "Switch") + + conducting_equipment = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"] + + for (name, ravens_obj) in get(conducting_equipment, "Switch", Dict{Any,Dict{String,Any}}()) + + math_obj = _init_math_obj_ravens("switch", name, ravens_obj, length(data_math["switch"])+1; pass_props=pass_props) + + # Terminals and phases + terminals = ravens_obj["ConductingEquipment.Terminals"] + + # TODO: refactor - Loop through terminals and verify connections + f_conns = [0,0,0] + t_conns = [0,0,0] + for term in terminals + if haskey(term, "Terminal.phases") + phasecode = term["Terminal.phases"] + if (phasecode == "PhaseCode.ABC") + if term["ACDCTerminal.sequenceNumber"] == 1 + f_conns = [1, 2, 3] + else + t_conns = [1, 2, 3] + end + elseif (phasecode == "PhaseCode.AB") + if term["ACDCTerminal.sequenceNumber"] == 1 + f_conns = [1, 2] + else + t_conns = [1, 2] + end + elseif (phasecode == "PhaseCode.AC") + if term["ACDCTerminal.sequenceNumber"] == 1 + f_conns = [1, 3] + else + t_conns = [1, 3] + end + elseif (phasecode == "PhaseCode.BC") + if term["ACDCTerminal.sequenceNumber"] == 1 + f_conns = [2, 3] + else + t_conns = [2, 3] + end + elseif (phasecode == "PhaseCode.A") + if term["ACDCTerminal.sequenceNumber"] == 1 + f_conns = [1] + else + t_conns = [1] + end + elseif (phasecode == "PhaseCode.B") + if term["ACDCTerminal.sequenceNumber"] == 1 + f_conns = [2] + else + t_conns = [2] + end + elseif (phasecode == "PhaseCode.C") + if term["ACDCTerminal.sequenceNumber"] == 1 + f_conns = [3] + else + t_conns = [3] + end + else + @error("PhaseCode not supported yet!") + end + else + f_conns = [1, 2, 3] + t_conns = [1, 2, 3] + end + end + + # Verify connections are correct. + if (f_conns != t_conns ) + @error("f_conns are not equal to t_conns!. Revise connections/phases in Switch terminals") + end + + # Phases + nphases = length(f_conns) + + # Connectivity Nodes + f_node = replace(split(terminals[1]["Terminal.ConnectivityNode"], "::")[2], "'" => "") + t_node = replace(split(terminals[2]["Terminal.ConnectivityNode"], "::")[2], "'" => "") + math_obj["f_bus"] = data_math["bus_lookup"][f_node] + math_obj["t_bus"] = data_math["bus_lookup"][t_node] + + # TODO: Status + math_obj["status"] = get(ravens_obj, "ConductingEquipment.SvStatus", 1) + + # State + sw_state = get(ravens_obj, "Switch.open", "false") + sw_state = sw_state == "false" ? CLOSED : OPEN + math_obj["state"] = Int(sw_state) + + # TODO: Dispatchable + math_obj["dispatchable"] = Int(get(ravens_obj, "dispatchable", YES)) + + # TODO: OPF bounds - Do we really need all of these values? + for (f_key, t_key) in [("Switch.ratedCurrent", "current_rating"), ("cm_ub_b", "c_rating_b"), ("cm_ub_c", "c_rating_c"), + ("sm_ub", "thermal_rating"), ("sm_ub_b", "rate_b"), ("sm_ub_c", "rate_c")] + math_obj[t_key] = haskey(ravens_obj, f_key) ? fill(ravens_obj[f_key], nphases) : fill(Inf, nphases) + + @info "$(math_obj[t_key])" + + end + + # Map index + map_to = "switch.$(math_obj["index"])" + + # TODO: Apply linecode? No information is given in CIM related to linecodes + + + # TODO: Create virtual bus + + + # Push Mapping + data_math["switch"]["$(math_obj["index"])"] = math_obj + + push!(data_math["map"], Dict{String,Any}( + "from" => name, + "to" => map_to, + "unmap_function" => "_map_math2ravens_switch!", + )) + + end + end + end diff --git a/src/prob/common.jl b/src/prob/common.jl index c96407c27..6f00dc75c 100644 --- a/src/prob/common.jl +++ b/src/prob/common.jl @@ -116,8 +116,8 @@ function instantiate_mc_model( ) end - @info "$(data["switch"])" - DEFINIDOEN_instantiate_mc_model + # @info "$(data["switch"])" + # DEFINIDOEN_instantiate_mc_model return _IM.instantiate_model( data, @@ -157,8 +157,8 @@ function instantiate_mc_model_ravens( make_pu_extensions=make_pu_extensions, ) - @info "$(data["switch"])" - DEFINIDOEN_instantiate_mc_model_ravens + # @info "$(data["switch"])" + # DEFINIDOEN_instantiate_mc_model_ravens return _IM.instantiate_model( data, From 248210b69512e4d77b82526434b9914586b24ca3 Mon Sep 17 00:00:00 2001 From: jjospina Date: Thu, 3 Oct 2024 12:41:44 -0600 Subject: [PATCH 13/27] REF: OperationalLimitType parsing with new style. --- src/data_model/transformations/ravens2math.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index 3406fe19a..af07737e2 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -342,7 +342,9 @@ function _map_ravens2math_energy_consumer!(data_math::Dict{String,<:Any}, data_r # Loop through op. limits for lim in op_limits - lim_type = lim["OperationalLimit.OperationalLimitType"]["OperationalLimitType.direction"] + lim_type_name = replace(split(lim["OperationalLimit.OperationalLimitType"], "::")[2], "'" => "") + lim_type = data_ravens["OperationalLimitType"][lim_type_name]["OperationalLimitType.direction"] + if lim_type == "OperationalLimitDirectionKind.high" op_limit_max = lim["VoltageLimit.value"] / voltage_scale_factor_sqrt3 elseif lim_type == "OperationalLimitDirectionKind.low" From dda9e4a3fca3962e1407fa8ec6a0c4cd3ee9080b Mon Sep 17 00:00:00 2001 From: jjospina Date: Mon, 7 Oct 2024 13:20:32 -0600 Subject: [PATCH 14/27] FIX: storage ravens2math parser. --- src/data_model/transformations/ravens2math.jl | 6 +++--- src/prob/common.jl | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index af07737e2..6caa078c7 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -780,14 +780,14 @@ function _map_ravens2math_power_electronics!(data_math::Dict{String,<:Any}, data if !haskey(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "InefficientBatteryUnit.limitEnergy") math_obj["energy_rating"] = ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"]["BatteryUnit.ratedE"]/power_scale_factor else - math_obj["energy_rating"] = ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"]["InefficientBatteryUnit.limitEnergy"]/power_scale_factor + math_obj["energy_rating"] = ((ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"]["InefficientBatteryUnit.limitEnergy"]/100)*ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"]["BatteryUnit.ratedE"])/power_scale_factor end if !haskey(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "PowerElectronicsUnit.maxP") - math_obj["charge_rating"] = (get(ravens_obj, "PowerElectronicsConnection.ratedS", Inf))./(power_scale_factor) + math_obj["charge_rating"] = -(get(ravens_obj, "PowerElectronicsConnection.ratedS", Inf))./(power_scale_factor) math_obj["discharge_rating"] = math_obj["charge_rating"] else - math_obj["charge_rating"] = (get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "PowerElectronicsUnit.maxP", Inf))./(power_scale_factor) + math_obj["charge_rating"] = -(get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "PowerElectronicsUnit.maxP", Inf))./(power_scale_factor) math_obj["discharge_rating"] = math_obj["charge_rating"] end diff --git a/src/prob/common.jl b/src/prob/common.jl index 6f00dc75c..2a255bf27 100644 --- a/src/prob/common.jl +++ b/src/prob/common.jl @@ -116,7 +116,7 @@ function instantiate_mc_model( ) end - # @info "$(data["switch"])" + # @info "$(data["storage"])" # DEFINIDOEN_instantiate_mc_model return _IM.instantiate_model( @@ -157,7 +157,7 @@ function instantiate_mc_model_ravens( make_pu_extensions=make_pu_extensions, ) - # @info "$(data["switch"])" + # @info "$(data["storage"])" # DEFINIDOEN_instantiate_mc_model_ravens return _IM.instantiate_model( From a5d54a469b0a64d8a16f7ab1f053714b415e4ed3 Mon Sep 17 00:00:00 2001 From: jjospina Date: Mon, 7 Oct 2024 13:43:27 -0600 Subject: [PATCH 15/27] REF: a function that extracts the name of a ravens string. --- src/data_model/transformations/ravens2math.jl | 36 +++++++++---------- src/data_model/utils_ravens.jl | 7 ++++ 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index 6caa078c7..5ca5bbfea 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -215,8 +215,8 @@ function _map_ravens2math_conductor!(data_math::Dict{String,<:Any}, data_ravens: nphases = length(ravens_obj["ACLineSegment.ACLineSegmentPhase"]) terminals = ravens_obj["ConductingEquipment.Terminals"] - f_node = replace(split(terminals[1]["Terminal.ConnectivityNode"], "::")[2], "'" => "") - t_node = replace(split(terminals[2]["Terminal.ConnectivityNode"], "::")[2], "'" => "") + f_node = _extract_name(terminals[1]["Terminal.ConnectivityNode"]) + t_node = _extract_name(terminals[2]["Terminal.ConnectivityNode"]) math_obj["f_bus"] = data_math["bus_lookup"][f_node] math_obj["t_bus"] = data_math["bus_lookup"][t_node] @@ -233,7 +233,7 @@ function _map_ravens2math_conductor!(data_math::Dict{String,<:Any}, data_ravens: math_obj["f_connections"] = bus_terminals math_obj["t_connections"] = bus_terminals - impedance_name = replace(split(ravens_obj["ACLineSegment.PerLengthImpedance"], "::")[2], "'" => "") + impedance_name = _extract_name(ravens_obj["ACLineSegment.PerLengthImpedance"]) impedance_data = data_ravens["PerLengthLineParameter"]["PerLengthImpedance"]["PerLengthPhaseImpedance"][impedance_name] math_obj["br_r"] = _impedance_conversion_ravens(impedance_data, ravens_obj, "PhaseImpedanceData.r") @@ -248,7 +248,7 @@ function _map_ravens2math_conductor!(data_math::Dict{String,<:Any}, data_ravens: math_obj["angmax"] = get(ravens_obj, "vad_ub", fill(60.0, nphases)) if (haskey(terminals[1], "ACDCTerminal.OperationalLimitSet")) - oplimitset_id = replace(split(terminals[1]["ACDCTerminal.OperationalLimitSet"], "::")[2], "'" => "") + oplimitset_id = _extract_name(terminals[1]["ACDCTerminal.OperationalLimitSet"]) oplimitset = data_ravens["OperationalLimitSet"][oplimitset_id]["OperationalLimitSet.OperationalLimitValue"][2] else oplimitset = Dict() @@ -298,11 +298,11 @@ function _map_ravens2math_energy_consumer!(data_math::Dict{String,<:Any}, data_r math_obj = _init_math_obj_ravens("energy_consumer", name, ravens_obj, length(data_math["load"]) + 1; pass_props=pass_props) # Set the load bus based on connectivity node - connectivity_node = replace(split(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"], "::")[2], "'" => "") + connectivity_node = _extract_name(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"]) math_obj["load_bus"] = data_math["bus_lookup"][connectivity_node] # Handle Load Response Characteristics - load_response_characts = replace(split(ravens_obj["EnergyConsumer.LoadResponseCharacteristic"], "::")[2], "'" => "") + load_response_characts = _extract_name(ravens_obj["EnergyConsumer.LoadResponseCharacteristic"]) if load_response_characts == "Constant Z" math_obj["model"] = IMPEDANCE elseif load_response_characts == "Motor" @@ -328,7 +328,7 @@ function _map_ravens2math_energy_consumer!(data_math::Dict{String,<:Any}, data_r math_obj["qd"] = [ravens_obj["EnergyConsumer.q"] / power_scale_factor] # Set the nominal voltage - base_voltage_ref = replace(split(ravens_obj["ConductingEquipment.BaseVoltage"], "::")[2], "'" => "") + base_voltage_ref = _extract_name(ravens_obj["ConductingEquipment.BaseVoltage"]) base_voltage = data_ravens["BaseVoltage"][base_voltage_ref]["BaseVoltage.nominalVoltage"] math_obj["vnom_kv"] = (base_voltage / voltage_scale_factor) / (sqrt(3) / 2) @@ -337,12 +337,12 @@ function _map_ravens2math_energy_consumer!(data_math::Dict{String,<:Any}, data_r bus_conn = data_math["bus"][bus_info] if haskey(data_ravens["ConnectivityNode"][connectivity_node], "ConnectivityNode.OperationalLimitSet") - op_limit_id = replace(split(data_ravens["ConnectivityNode"][connectivity_node]["ConnectivityNode.OperationalLimitSet"], "::")[2], "'" => "") + op_limit_id = _extract_name(data_ravens["ConnectivityNode"][connectivity_node]["ConnectivityNode.OperationalLimitSet"]) op_limits = data_ravens["OperationalLimitSet"][op_limit_id]["OperationalLimitSet.OperationalLimitValue"] # Loop through op. limits for lim in op_limits - lim_type_name = replace(split(lim["OperationalLimit.OperationalLimitType"], "::")[2], "'" => "") + lim_type_name = _extract_name(lim["OperationalLimit.OperationalLimitType"]) lim_type = data_ravens["OperationalLimitType"][lim_type_name]["OperationalLimitType.direction"] if lim_type == "OperationalLimitDirectionKind.high" @@ -422,7 +422,7 @@ function _map_ravens2math_energy_source!(data_math::Dict{String,<:Any}, data_rav math_obj["name"] = "_virtual_gen.energy_source.$name" # Get connectivity node info (bus info) - connectivity_node = replace(split(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"], "::")[2], "'" => "") + connectivity_node = _extract_name(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"]) gen_bus = data_math["bus_lookup"][connectivity_node] math_obj["gen_bus"] = gen_bus bus_conn = data_math["bus"][string(gen_bus)] @@ -470,7 +470,7 @@ function _map_ravens2math_energy_source!(data_math::Dict{String,<:Any}, data_rav math_obj["configuration"] = get(ravens_obj, "EnergySource.connectionKind", WYE) # Vnom and vbases_default - base_voltage_ref = replace(split(ravens_obj["ConductingEquipment.BaseVoltage"], "::")[2], "'" => "") + base_voltage_ref = _extract_name(ravens_obj["ConductingEquipment.BaseVoltage"]) vnom = data_ravens["BaseVoltage"][base_voltage_ref]["BaseVoltage.nominalVoltage"] / sqrt(nconductors) data_math["settings"]["vbases_default"][connectivity_node] = vnom / voltage_scale_factor @@ -602,7 +602,7 @@ function _map_ravens2math_rotating_machine!(data_math::Dict{String,<:Any}, data_ nconductors = length(connections) math_obj["connections"] = connections - connectivity_node = replace(split(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"], "::")[2], "'" => "") + connectivity_node = _extract_name(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"]) math_obj["gen_bus"] = data_math["bus_lookup"][connectivity_node] math_obj["gen_status"] = status = Int(get(ravens_obj, "ConductingEquipment.SvStatus", 1)) @@ -621,7 +621,7 @@ function _map_ravens2math_rotating_machine!(data_math::Dict{String,<:Any}, data_ data_math["bus"]["$(math_obj["gen_bus"])"]["bus_type"] = _compute_bus_type(bus_type, status, control_mode) # Set the nominal voltage - base_voltage_ref = replace(split(ravens_obj["ConductingEquipment.BaseVoltage"], "::")[2], "'" => "") + base_voltage_ref = _extract_name(ravens_obj["ConductingEquipment.BaseVoltage"]) nominal_voltage = data_ravens["BaseVoltage"][base_voltage_ref]["BaseVoltage.nominalVoltage"] base_voltage = nominal_voltage / sqrt(nconductors) math_obj["vbase"] = base_voltage / voltage_scale_factor @@ -688,7 +688,7 @@ function _map_ravens2math_power_electronics!(data_math::Dict{String,<:Any}, data nconductors = length(connections) math_obj["connections"] = connections - connectivity_node = replace(split(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"], "::")[2], "'" => "") + connectivity_node = _extract_name(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"]) math_obj["gen_bus"] = data_math["bus_lookup"][connectivity_node] math_obj["gen_status"] = status = Int(get(ravens_obj, "ConductingEquipment.SvStatus", 1)) @@ -700,7 +700,7 @@ function _map_ravens2math_power_electronics!(data_math::Dict{String,<:Any}, data data_math["bus"]["$(math_obj["gen_bus"])"]["bus_type"] = _compute_bus_type(bus_type, status, control_mode) # Set the nominal voltage - base_voltage_ref = replace(split(ravens_obj["ConductingEquipment.BaseVoltage"], "::")[2], "'" => "") + base_voltage_ref = _extract_name(ravens_obj["ConductingEquipment.BaseVoltage"]) nominal_voltage = data_ravens["BaseVoltage"][base_voltage_ref]["BaseVoltage.nominalVoltage"] base_voltage = nominal_voltage / sqrt(nconductors) math_obj["vbase"] = base_voltage / voltage_scale_factor @@ -767,7 +767,7 @@ function _map_ravens2math_power_electronics!(data_math::Dict{String,<:Any}, data math_obj["connections"] = connections # Set the bus - connectivity_node = replace(split(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"], "::")[2], "'" => "") + connectivity_node = _extract_name(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"]) math_obj["storage_bus"] = data_math["bus_lookup"][connectivity_node] math_obj["status"] = status = Int(get(ravens_obj, "ConductingEquipment.SvStatus", 1)) @@ -917,8 +917,8 @@ function _map_ravens2math_switch!(data_math::Dict{String,<:Any}, data_ravens::Di nphases = length(f_conns) # Connectivity Nodes - f_node = replace(split(terminals[1]["Terminal.ConnectivityNode"], "::")[2], "'" => "") - t_node = replace(split(terminals[2]["Terminal.ConnectivityNode"], "::")[2], "'" => "") + f_node = _extract_name(terminals[1]["Terminal.ConnectivityNode"]) + t_node = _extract_name(terminals[2]["Terminal.ConnectivityNode"]) math_obj["f_bus"] = data_math["bus_lookup"][f_node] math_obj["t_bus"] = data_math["bus_lookup"][t_node] diff --git a/src/data_model/utils_ravens.jl b/src/data_model/utils_ravens.jl index adf2ec79a..188a1ccad 100644 --- a/src/data_model/utils_ravens.jl +++ b/src/data_model/utils_ravens.jl @@ -70,3 +70,10 @@ function _admittance_conversion_ravens(data_eng::Dict{String,<:Any}, eng_obj::Di return _admittance_matrix .* get(eng_obj, "Conductor.length", 1.0) .* freq ./ 1e2 # divide by 2 to get both sides _to and _fr end + +"extracts the name from a ravens reference string" +function _extract_name(element) + + name = replace(split(element, "::")[2], "'" => "") + return name +end From 2fb384d68d1cc856d1e86c0f5cd929e79a9fdfcf Mon Sep 17 00:00:00 2001 From: jjospina Date: Mon, 7 Oct 2024 15:45:47 -0600 Subject: [PATCH 16/27] REF: replace SvStatus with Equipment.inService --- src/data_model/transformations/ravens2math.jl | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index 5ca5bbfea..5dd35d107 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -261,7 +261,7 @@ function _map_ravens2math_conductor!(data_math::Dict{String,<:Any}, data_ravens: math_obj[t_key] = haskey(oplimitset, f_key) ? fill(oplimitset[f_key], nphases) : fill(Inf, nphases) end - math_obj["br_status"] = get(ravens_obj, "ConductingEquipment.SvStatus", 1) + math_obj["br_status"] = get(ravens_obj, "Equipment.inService", "true") == "true" ? 1 : 0 data_math["branch"]["$(math_obj["index"])"] = math_obj push!(data_math["map"], Dict{String,Any}( @@ -387,7 +387,8 @@ function _map_ravens2math_energy_consumer!(data_math::Dict{String,<:Any}, data_r end # Set status, dispatchable flag, and index - math_obj["status"] = haskey(ravens_obj, "ConductingEquipment.SvStatus") ? ravens_obj["ConductingEquipment.SvStatus"] : 1 + math_obj["status"] = haskey(ravens_obj, "Equipment.inService") ? ravens_obj["Equipment.inService"] : "true" + math_obj["status"] = math_obj["status"] == "true" ? 1 : 0 math_obj["dispatchable"] = 0 data_math["load"]["$(math_obj["index"])"] = math_obj @@ -466,7 +467,9 @@ function _map_ravens2math_energy_source!(data_math::Dict{String,<:Any}, data_rav end # Generator status and configuration - math_obj["gen_status"] = haskey(ravens_obj, "ConductingEquipment.SvStatus") ? Int(ravens_obj["ConductingEquipment.SvStatus"]) : 1 + math_obj["gen_status"] = haskey(ravens_obj, "Equipment.inService") ? ravens_obj["Equipment.inService"] : "true" + math_obj["gen_status"] = math_obj["gen_status"] == "true" ? 1 : 0 + math_obj["configuration"] = get(ravens_obj, "EnergySource.connectionKind", WYE) # Vnom and vbases_default @@ -604,7 +607,8 @@ function _map_ravens2math_rotating_machine!(data_math::Dict{String,<:Any}, data_ connectivity_node = _extract_name(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"]) math_obj["gen_bus"] = data_math["bus_lookup"][connectivity_node] - math_obj["gen_status"] = status = Int(get(ravens_obj, "ConductingEquipment.SvStatus", 1)) + math_obj["gen_status"] = get(ravens_obj, "Equipment.inService", "true") + math_obj["gen_status"] = status = math_obj["gen_status"] == "true" ? 1 : 0 # TODO: control mode do not exist in the RAVENS-CIM (Need to be added) math_obj["control_mode"] = control_mode = Int(get(ravens_obj, "control_mode", FREQUENCYDROOP)) @@ -690,7 +694,8 @@ function _map_ravens2math_power_electronics!(data_math::Dict{String,<:Any}, data connectivity_node = _extract_name(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"]) math_obj["gen_bus"] = data_math["bus_lookup"][connectivity_node] - math_obj["gen_status"] = status = Int(get(ravens_obj, "ConductingEquipment.SvStatus", 1)) + math_obj["gen_status"] = get(ravens_obj, "Equipment.inService", "true") + math_obj["gen_status"] = status = math_obj["gen_status"] == "true" ? 1 : 0 # TODO: control mode do not exist in the RAVENS-CIM (Need to be added) math_obj["control_mode"] = control_mode = Int(get(ravens_obj, "control_mode", FREQUENCYDROOP)) @@ -769,7 +774,8 @@ function _map_ravens2math_power_electronics!(data_math::Dict{String,<:Any}, data # Set the bus connectivity_node = _extract_name(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"]) math_obj["storage_bus"] = data_math["bus_lookup"][connectivity_node] - math_obj["status"] = status = Int(get(ravens_obj, "ConductingEquipment.SvStatus", 1)) + math_obj["status"] = get(ravens_obj, "Equipment.inService", "true") + math_obj["status"] = status = math_obj["status"] == "true" ? 1 : 0 # TODO: configuration for generators is not available on CIM (yet) math_obj["configuration"] = get(ravens_obj, "configuration", WYE) @@ -923,7 +929,8 @@ function _map_ravens2math_switch!(data_math::Dict{String,<:Any}, data_ravens::Di math_obj["t_bus"] = data_math["bus_lookup"][t_node] # TODO: Status - math_obj["status"] = get(ravens_obj, "ConductingEquipment.SvStatus", 1) + math_obj["status"] = get(ravens_obj, "Equipment.inService", "true") + math_obj["status"] = status = math_obj["status"] == "true" ? 1 : 0 # State sw_state = get(ravens_obj, "Switch.open", "false") From b54fbc5dbc743879905af8501971a6baa22e0f6b Mon Sep 17 00:00:00 2001 From: jjospina Date: Thu, 10 Oct 2024 10:39:23 -0600 Subject: [PATCH 17/27] FIX: charge and discharge on BatteryUnit. --- src/data_model/transformations/ravens2math.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index 5dd35d107..10594f421 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -790,11 +790,11 @@ function _map_ravens2math_power_electronics!(data_math::Dict{String,<:Any}, data end if !haskey(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "PowerElectronicsUnit.maxP") - math_obj["charge_rating"] = -(get(ravens_obj, "PowerElectronicsConnection.ratedS", Inf))./(power_scale_factor) + math_obj["charge_rating"] = (get(ravens_obj, "PowerElectronicsConnection.ratedS", Inf))./(power_scale_factor) math_obj["discharge_rating"] = math_obj["charge_rating"] else - math_obj["charge_rating"] = -(get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "PowerElectronicsUnit.maxP", Inf))./(power_scale_factor) - math_obj["discharge_rating"] = math_obj["charge_rating"] + math_obj["charge_rating"] = -(get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "PowerElectronicsUnit.minP", Inf))./(power_scale_factor) + math_obj["discharge_rating"] = (get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "PowerElectronicsUnit.maxP", Inf))./(power_scale_factor) end math_obj["charge_efficiency"] = get(ravens_obj["PowerElectronicsConnection.PowerElectronicsUnit"], "InefficientBatteryUnit.efficiencyCharge", 100.0) / 100.0 From 8ee4faa51cdaf370c4f4fa3ad5c975f857f55899 Mon Sep 17 00:00:00 2001 From: jjospina Date: Thu, 10 Oct 2024 15:39:33 -0600 Subject: [PATCH 18/27] WIP: Add Parser for PowerTransformer based on PowerTransformerEnd. Errors still exist. --- src/data_model/transformations/eng2math.jl | 5 + src/data_model/transformations/ravens2math.jl | 203 +++++++++++++++++- src/prob/common.jl | 8 +- 3 files changed, 207 insertions(+), 9 deletions(-) diff --git a/src/data_model/transformations/eng2math.jl b/src/data_model/transformations/eng2math.jl index f82208778..61f57e097 100644 --- a/src/data_model/transformations/eng2math.jl +++ b/src/data_model/transformations/eng2math.jl @@ -157,6 +157,11 @@ function transform_data_model( eng2math_passthrough=eng2math_passthrough, global_keys=global_keys, ) + + @info "$(data_math)" + + dadadsa + correct_network_data && correct_network_data!(data_math; make_pu=make_pu, make_pu_extensions=make_pu_extensions) return data_math diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index 10594f421..2736ce074 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -1,7 +1,7 @@ "cim-ravens to math object mapping" const _math_to_ravens = Dict{String,String}( "bus" => "connectivity_node", - "transformer" => "power_transformer", # TODO + "transformer" => "power_transformer", "switch" => "switch", # TODO # "shunt" => "shunt_compensator", "load" => "energy_consumer", @@ -19,7 +19,7 @@ const _ravens_node_elements = String[ "list of edge type elements in the ravens model" const _ravens_edge_elements = String[ - "conductor", "switch" + "conductor", "switch", "power_transformer" ] "list of all ravens asset types" @@ -57,6 +57,8 @@ function transform_data_model_ravens( global_keys=global_keys, ) + @info "$(data_math)" + # TODO: Correct network data transforms a lot of the values of lines/branches (other values maybe too) correct_network_data && correct_network_data!(data_math; make_pu=make_pu, make_pu_extensions=make_pu_extensions) @@ -275,12 +277,203 @@ end # TODO: Transformers need a lot of changes/refactors!!! -"converts ravensineering n-winding transformers into mathematical ideal 2-winding lossless transformer branches and impedance branches to represent the loss model" +"converts ravens n-winding transformers into mathematical ideal 2-winding lossless transformer branches and impedance branches to represent the loss model" function _map_ravens2math_power_transformer!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) - _data_ravens_transformer = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"] + conducting_equipment = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"] + power_scale_factor = data_math["settings"]["power_scale_factor"] + voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] + voltage_scale_factor_sqrt3 = voltage_scale_factor * sqrt(3) + + for (name, ravens_obj) in get(conducting_equipment, "PowerTransformer", Dict{Any,Dict{String,Any}}()) + + # Build map first, so we can update it as we decompose the transformer + push!(data_math["map"], Dict{String,Any}( + "from" => name, + "to" => String[], + "unmap_function" => "_map_math2ravens_transformer!", + )) + + to_map = data_math["map"][end]["to"] + + # TODO: Check if we still need this function (or a similar function) + # _apply_xfmrcode!(ravens_obj, data_ravens) + + # Get nrw: number of windings + wdgs = ravens_obj["PowerTransformer.PowerTransformerEnd"] + nrw = length(wdgs) + + # Loop through Windings + wdg1_data = 0 + wdg2_data = 0 + wdgN_data = 0 + # connections + connections = Vector{Int64}[] + # Nodes + f_node = "" + t_node = "" + for wdg in wdgs + + # wdg phasecode + wdg_terminals = wdg["ConductingEquipment.Terminals"][1] + wdg_phasecode = wdg_terminals["Terminal.phases"] + + if (wdg_phasecode == "PhaseCode.ABC") + push!(connections, [1, 2, 3]) + elseif (wdg_phasecode == "PhaseCode.AB") + push!(connections, [1, 2]) + elseif (wdg_phasecode == "PhaseCode.AC") + push!(connections, [1, 3]) + elseif (wdg_phasecode == "PhaseCode.BC") + push!(connections, [2, 3]) + elseif (wdg_phasecode == "PhaseCode.A") + push!(connections, [1]) + elseif (wdg_phasecode == "PhaseCode.B") + push!(connections, [2]) + elseif (wdg_phasecode == "PhaseCode.C") + push!(connections, [3]) + else + @error("PhaseCode not supported yet!") + end + + # wdg endNumber + wdg_endNumber = wdg["TransformerEnd.endNumber"] + + # nphases + nphases = length(connections[1]) + + # Get Winding 1 information & create bus + if wdg_endNumber == 1 + wdg1_data = wdg + f_node = _extract_name(wdg_terminals["Terminal.ConnectivityNode"]) + f_bus = data_math["bus_lookup"][f_node] + data_math["bus"][string(f_bus)]["terminals"] = connections[wdg_endNumber] + data_math["bus"][string(f_bus)]["vmin"] = fill(0.0, nphases) + data_math["bus"][string(f_bus)]["vmax"] = fill(Inf, nphases) + # Get Winding 2 information & create bus + elseif wdg_endNumber == 2 + wdg2_data = wdg + t_node = _extract_name(wdg_terminals["Terminal.ConnectivityNode"]) + t_bus= data_math["bus_lookup"][t_node] + data_math["bus"][string(t_bus)]["terminals"] = connections[wdg_endNumber] + data_math["bus"][string(t_bus)]["vmin"] = fill(0.0, nphases) + data_math["bus"][string(t_bus)]["vmax"] = fill(Inf, nphases) + else + wdgN_data = wdg + end + end + + # nphases + nphases = length(connections[1]) + + # vnom and snom + vnom = [wdg1_data["PowerTransformerEnd.ratedU"], wdg2_data["PowerTransformerEnd.ratedU"]] + snom = [wdg1_data["PowerTransformerEnd.ratedS"], wdg2_data["PowerTransformerEnd.ratedS"]] + + # calculate zbase in which the data is specified, and convert to SI + zbase = (vnom.^2) ./ snom + + # x_sc is specified with respect to first winding + x_sc = [wdg1_data["TransformerEnd.MeshImpedance"]["TransformerMeshImpedance.x"]] + + # rs is specified with respect to each winding + r_s = [wdg1_data["PowerTransformerEnd.r"], wdg2_data["PowerTransformerEnd.r"]] + + g_sh = (wdg1_data["TransformerEnd.CoreAdmittance"]["TransformerCoreAdmittance.g"]) + b_sh = -(wdg1_data["TransformerEnd.CoreAdmittance"]["TransformerCoreAdmittance.b"]) - for (name, ravens_obj) in get(_data_ravens_transformer, "PowerTransformer", Dict{Any,Dict{String,Any}}()) + # data is measured externally, but we now refer it to the internal side + ratios = vnom/voltage_scale_factor + x_sc = x_sc./ratios[1]^2 + r_s = r_s./ratios.^2 + g_sh = g_sh*ratios[1]^2 + b_sh = b_sh*ratios[1]^2 + + # convert x_sc from list of upper triangle elements to an explicit dict + y_sh = g_sh + im*b_sh + z_sc = Dict([(key, im*x_sc[i]) for (i,key) in enumerate([(i,j) for i in 1:nrw for j in i+1:nrw])]) + + # TODO: RatioTapChanger + if haskey(wdg1_data, "TransformerEnd.RatioTapChanger") || haskey(wdg2_data, "TransformerEnd.RatioTapChanger") + else # default + tm_set = Vector{Vector{Float64}}(fill(fill(1.0, nphases), nrw)) + tm_lb = Vector{Vector{Float64}}(fill(fill(0.9, nphases), nrw)) + tm_ub = Vector{Vector{Float64}}(fill(fill(1.1, nphases), nrw)) + tm_fix = Vector{Vector{Bool}}(fill(ones(Bool, nphases), nrw)) + tm_step = Vector{Vector{Float64}}(fill(fill(1/32, nphases), nrw)) + end + + dims = length(tm_set[1]) + + + # TODO: Polarity + polarity = fill(1, nrw) + + # Status + status = haskey(ravens_obj, "Equipment.inService") ? ravens_obj["Equipment.inService"] : "true" + status = status == "true" ? 1 : 0 + + # Build loss model + transformer_t_bus_w = _build_loss_model!(data_math, name, to_map, r_s, z_sc, y_sh, connections[1]; nphases=dims, status=Int(status == ENABLED)) + + # Mathematical model for transformer + for w in 1:nrw + # 2-WINDING TRANSFORMER + + # Configuration + if wdgs[w]["PowerTransformerEnd.connectionKind"] == "WindingConnection.Y" + configuration = WYE + elseif wdgs[w]["PowerTransformerEnd.connectionKind"] == "WindingConnection.D" + configuration = DELTA + else + @error("PowerTransformer ConnectionKind not supported yet!") + end + + # make virtual bus and mark it for reduction + tm_nom = configuration==DELTA ? wdgs[w]["PowerTransformerEnd.ratedU"]*sqrt(3)/voltage_scale_factor : wdgs[w]["PowerTransformerEnd.ratedU"]/voltage_scale_factor + + # Transformer Object + transformer_2wa_obj = Dict{String,Any}( + "name" => "_virtual_transformer.$name.$w", + "source_id" => "_virtual_transformer.powertransformer.$name.$w", + "f_bus" => data_math["bus_lookup"][f_node], + "t_bus" => transformer_t_bus_w[w], + "tm_nom" => tm_nom, + "f_connections" => connections[w], + "t_connections" => connections[w], + "configuration" => configuration, + "polarity" => polarity[w], + "tm_set" => tm_set[w], + "tm_fix" => tm_fix[w], + "sm_ub" => get(wdgs[w], "PowerTransformerEnd.ratedS", Inf)/power_scale_factor, + "cm_ub" => get(wdgs[w], "PowerTransformerEnd.ratedI", Inf), + "status" => status, + "index" => length(data_math["transformer"])+1 + ) + + # TODO: RatioTapChanger + for prop in [pass_props] + if haskey(wdgs[w], prop) + transformer_2wa_obj[prop] = wdgs[w][prop] + end + end + transformer_2wa_obj["tm_lb"] = tm_lb[w] + transformer_2wa_obj["tm_ub"] = tm_ub[w] + transformer_2wa_obj["tm_step"] = tm_step[w] + + data_math["transformer"]["$(transformer_2wa_obj["index"])"] = transformer_2wa_obj + + ## TODO: Regulator Control + # if haskey(eng_obj,"controls") && !all(data_math["transformer"]["$(transformer_2wa_obj["index"])"]["tm_fix"]) + # end + + # TODO: Center-Tapped Transformers (3 Windings) + # if w==3 && eng_obj["polarity"][w]==-1 # identify center-tapped transformer and mark all secondary-side nodes as triplex by adding va_start + # end + + push!(to_map, "transformer.$(transformer_2wa_obj["index"])") + + end end end diff --git a/src/prob/common.jl b/src/prob/common.jl index 2a255bf27..f0edc9445 100644 --- a/src/prob/common.jl +++ b/src/prob/common.jl @@ -116,8 +116,8 @@ function instantiate_mc_model( ) end - # @info "$(data["storage"])" - # DEFINIDOEN_instantiate_mc_model + @info "$(data["transformer"])" + DEFINIDOEN_instantiate_mc_model return _IM.instantiate_model( data, @@ -157,8 +157,8 @@ function instantiate_mc_model_ravens( make_pu_extensions=make_pu_extensions, ) - # @info "$(data["storage"])" - # DEFINIDOEN_instantiate_mc_model_ravens + @info "$(data["transformer"])" + DEFINIDOEN_instantiate_mc_model_ravens return _IM.instantiate_model( data, From f6698b930c37a5b798d86a70eadb653410fe0ff1 Mon Sep 17 00:00:00 2001 From: jjospina Date: Thu, 10 Oct 2024 16:36:55 -0600 Subject: [PATCH 19/27] WIP: debig powertransformer issues related to terminals and bus_type coming from build_loss --- src/data_model/transformations/eng2math.jl | 5 ----- src/data_model/transformations/ravens2math.jl | 10 ++++------ 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/data_model/transformations/eng2math.jl b/src/data_model/transformations/eng2math.jl index 61f57e097..f82208778 100644 --- a/src/data_model/transformations/eng2math.jl +++ b/src/data_model/transformations/eng2math.jl @@ -157,11 +157,6 @@ function transform_data_model( eng2math_passthrough=eng2math_passthrough, global_keys=global_keys, ) - - @info "$(data_math)" - - dadadsa - correct_network_data && correct_network_data!(data_math; make_pu=make_pu, make_pu_extensions=make_pu_extensions) return data_math diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index 2736ce074..0ab60d81b 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -57,8 +57,6 @@ function transform_data_model_ravens( global_keys=global_keys, ) - @info "$(data_math)" - # TODO: Correct network data transforms a lot of the values of lines/branches (other values maybe too) correct_network_data && correct_network_data!(data_math; make_pu=make_pu, make_pu_extensions=make_pu_extensions) @@ -97,7 +95,7 @@ function _map_ravens2math( n => Dict{String,Any}( "per_unit" => get(_data_ravens, "per_unit", false), "is_projected" => get(nw, "is_projected", false), - "is_kron_reduced" => get(nw, "is_kron_reduced", false), + "is_kron_reduced" => get(nw, "is_kron_reduced", true), # TODO: Kron reduction? "settings" => deepcopy(_settings), "time_elapsed" => get(nw, "time_elapsed", 1.0), ) for (n,nw) in _data_ravens["nw"] @@ -111,7 +109,7 @@ function _map_ravens2math( "per_unit" => get(_data_ravens, "per_unit", false), "data_model" => MATHEMATICAL, "is_projected" => get(_data_ravens, "is_projected", false), - "is_kron_reduced" => get(_data_ravens, "is_kron_reduced", false), + "is_kron_reduced" => get(_data_ravens, "is_kron_reduced", true), # TODO: Kron reduction? "settings" => deepcopy(_settings), "time_elapsed" => get(_data_ravens, "time_elapsed", 1.0), ) @@ -414,7 +412,7 @@ function _map_ravens2math_power_transformer!(data_math::Dict{String,<:Any}, data status = status == "true" ? 1 : 0 # Build loss model - transformer_t_bus_w = _build_loss_model!(data_math, name, to_map, r_s, z_sc, y_sh, connections[1]; nphases=dims, status=Int(status == ENABLED)) + transformer_t_bus_w = _build_loss_model!(data_math, name, to_map, r_s, z_sc, y_sh, connections[1]; nphases=dims, status=status) # Mathematical model for transformer for w in 1:nrw @@ -435,7 +433,7 @@ function _map_ravens2math_power_transformer!(data_math::Dict{String,<:Any}, data # Transformer Object transformer_2wa_obj = Dict{String,Any}( "name" => "_virtual_transformer.$name.$w", - "source_id" => "_virtual_transformer.powertransformer.$name.$w", + "source_id" => "_virtual_transformer.transformer.$name.$w", "f_bus" => data_math["bus_lookup"][f_node], "t_bus" => transformer_t_bus_w[w], "tm_nom" => tm_nom, From 86f3f47eb96977c8eb8186ef756ce4e8e4d8b2dd Mon Sep 17 00:00:00 2001 From: jjospina Date: Fri, 11 Oct 2024 10:22:16 -0600 Subject: [PATCH 20/27] FIX: powertransformer issue related to fnode when creating virtual branches. --- src/data_model/transformations/ravens2math.jl | 6 +++++- src/prob/common.jl | 8 ++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index 0ab60d81b..28841a6c6 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -430,11 +430,15 @@ function _map_ravens2math_power_transformer!(data_math::Dict{String,<:Any}, data # make virtual bus and mark it for reduction tm_nom = configuration==DELTA ? wdgs[w]["PowerTransformerEnd.ratedU"]*sqrt(3)/voltage_scale_factor : wdgs[w]["PowerTransformerEnd.ratedU"]/voltage_scale_factor + # Get correct f_node for winding + wdg_term = wdgs[w]["ConductingEquipment.Terminals"][1] + f_node_wdgterm = _extract_name(wdg_term["Terminal.ConnectivityNode"]) + # Transformer Object transformer_2wa_obj = Dict{String,Any}( "name" => "_virtual_transformer.$name.$w", "source_id" => "_virtual_transformer.transformer.$name.$w", - "f_bus" => data_math["bus_lookup"][f_node], + "f_bus" => data_math["bus_lookup"][f_node_wdgterm], "t_bus" => transformer_t_bus_w[w], "tm_nom" => tm_nom, "f_connections" => connections[w], diff --git a/src/prob/common.jl b/src/prob/common.jl index f0edc9445..3ab55c1f6 100644 --- a/src/prob/common.jl +++ b/src/prob/common.jl @@ -116,8 +116,8 @@ function instantiate_mc_model( ) end - @info "$(data["transformer"])" - DEFINIDOEN_instantiate_mc_model + # @info "$(data["transformer"])" + # DEFINIDOEN_instantiate_mc_model return _IM.instantiate_model( data, @@ -157,8 +157,8 @@ function instantiate_mc_model_ravens( make_pu_extensions=make_pu_extensions, ) - @info "$(data["transformer"])" - DEFINIDOEN_instantiate_mc_model_ravens + # @info "$(data["transformer"])" + # DEFINIDOEN_instantiate_mc_model_ravens return _IM.instantiate_model( data, From 87269410692fa9a57b5b481991df35783968f893 Mon Sep 17 00:00:00 2001 From: Juan Ospina Date: Fri, 11 Oct 2024 14:07:55 -0600 Subject: [PATCH 21/27] REF: phasecode in transformers. --- src/data_model/transformations/ravens2math.jl | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index 28841a6c6..40bd45465 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -310,26 +310,26 @@ function _map_ravens2math_power_transformer!(data_math::Dict{String,<:Any}, data # Nodes f_node = "" t_node = "" + + phasecode_map = Dict( + "PhaseCode.ABC" => [1, 2, 3], + "PhaseCode.AB" => [1, 2], + "PhaseCode.AC" => [1, 3], + "PhaseCode.BC" => [2, 3], + "PhaseCode.A" => [1], + "PhaseCode.B" => [2], + "PhaseCode.C" => [3] + ) + for wdg in wdgs # wdg phasecode wdg_terminals = wdg["ConductingEquipment.Terminals"][1] wdg_phasecode = wdg_terminals["Terminal.phases"] - if (wdg_phasecode == "PhaseCode.ABC") - push!(connections, [1, 2, 3]) - elseif (wdg_phasecode == "PhaseCode.AB") - push!(connections, [1, 2]) - elseif (wdg_phasecode == "PhaseCode.AC") - push!(connections, [1, 3]) - elseif (wdg_phasecode == "PhaseCode.BC") - push!(connections, [2, 3]) - elseif (wdg_phasecode == "PhaseCode.A") - push!(connections, [1]) - elseif (wdg_phasecode == "PhaseCode.B") - push!(connections, [2]) - elseif (wdg_phasecode == "PhaseCode.C") - push!(connections, [3]) + # Connections (based on phasecode_map) + if haskey(phasecode_map, wdg_phasecode) + push!(connections, phasecode_map[wdg_phasecode]) else @error("PhaseCode not supported yet!") end @@ -356,8 +356,6 @@ function _map_ravens2math_power_transformer!(data_math::Dict{String,<:Any}, data data_math["bus"][string(t_bus)]["terminals"] = connections[wdg_endNumber] data_math["bus"][string(t_bus)]["vmin"] = fill(0.0, nphases) data_math["bus"][string(t_bus)]["vmax"] = fill(Inf, nphases) - else - wdgN_data = wdg end end From 4688964c85a80ec5c52dee25494eccb66d433e5a Mon Sep 17 00:00:00 2001 From: jjospina Date: Mon, 14 Oct 2024 12:39:52 -0600 Subject: [PATCH 22/27] ADD: ShuntCompensator ravens parser. --- src/data_model/transformations/ravens2math.jl | 84 ++++++++++++++++++- src/data_model/utils_ravens.jl | 10 +++ 2 files changed, 91 insertions(+), 3 deletions(-) diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index 40bd45465..59a9538d3 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -2,8 +2,8 @@ const _math_to_ravens = Dict{String,String}( "bus" => "connectivity_node", "transformer" => "power_transformer", - "switch" => "switch", # TODO - # "shunt" => "shunt_compensator", + "switch" => "switch", + "shunt" => "shunt_compensator", "load" => "energy_consumer", "generator" => "rotating_machine", "solar" => "photovoltaic_unit", @@ -14,7 +14,7 @@ const _math_to_ravens = Dict{String,String}( "list of nodal type elements in the ravens model" const _ravens_node_elements = String[ - "energy_consumer", "rotating_machine", "power_electronics", "energy_source" + "energy_consumer", "shunt_compensator", "rotating_machine", "power_electronics", "energy_source" ] "list of edge type elements in the ravens model" @@ -1165,3 +1165,81 @@ function _map_ravens2math_switch!(data_math::Dict{String,<:Any}, data_ravens::Di end end + + +"converts ravens generic shunt components into mathematical shunt components" +function _map_ravens2math_shunt_compensator!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) + + regulating_cond_eq = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"]["RegulatingCondEq"] + power_scale_factor = data_math["settings"]["power_scale_factor"] + voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] + + for (name, ravens_obj) in get(regulating_cond_eq, "ShuntCompensator", Dict{Any,Dict{String,Any}}()) + + math_obj = _init_math_obj("shunt", name, ravens_obj, length(data_math["shunt"])+1; pass_props=pass_props) + + # Get connectivity node info (bus info) + connectivity_node = _extract_name(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"]) + math_obj["shunt_bus"] = data_math["bus_lookup"][connectivity_node] + + # Status + status = haskey(ravens_obj, "Equipment.inService") ? ravens_obj["Equipment.inService"] : "true" + math_obj["status"] = status == "true" ? 1 : 0 + + # Connections/phases obtained from Terminals + if haskey(ravens_obj["ConductingEquipment.Terminals"][1], "Terminal.phases") + phasecode = ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.phases"] + if (phasecode == "PhaseCode.ABC") + connections = [1, 2, 3] + elseif (phasecode == "PhaseCode.AB") + connections = [1, 2] + elseif (phasecode == "PhaseCode.AC") + connections = [1, 3] + elseif (phasecode == "PhaseCode.BC") + connections = [2, 3] + elseif (phasecode == "PhaseCode.A") + connections = [1] + elseif (phasecode == "PhaseCode.B") + connections = [2] + elseif (phasecode == "PhaseCode.C") + connections = [3] + else + @error("PhaseCode not supported yet!") + end + else + connections = [1, 2, 3] # default + end + math_obj["connections"] = connections + terminals = connections + + # TODO: dispatchable + math_obj["dispatchable"] = 0 + + # bs - TODO: make sure b matrix is being calculated correctly + b = ravens_obj["LinearShuntCompensator.bPerSection"] + B = _calc_shunt_admittance_matrix(terminals, b) + math_obj["bs"] = B + + # gs + if haskey(ravens_obj, "LinearShuntCompensator.gPerSection") + g = ravens_obj["LinearShuntCompensator.gPerSection"] + G = _calc_shunt_admittance_matrix(terminals, g) + math_obj["gs"] = G + else + math_obj["gs"] = zeros(size(math_obj["bs"])) + end + + # Index + data_math["shunt"]["$(math_obj["index"])"] = math_obj + + # TODO: Add CapControl + # ..... + + push!(data_math["map"], Dict{String,Any}( + "from" => name, + "to" => "shunt.$(math_obj["index"])", + "unmap_function" => "_map_math2ravens_shunt!", + )) + + end +end diff --git a/src/data_model/utils_ravens.jl b/src/data_model/utils_ravens.jl index 188a1ccad..8376b31c7 100644 --- a/src/data_model/utils_ravens.jl +++ b/src/data_model/utils_ravens.jl @@ -77,3 +77,13 @@ function _extract_name(element) name = replace(split(element, "::")[2], "'" => "") return name end + + +"calculates the shunt admittance matrix based on terminals and b or g" +function _calc_shunt_admittance_matrix(terminals, b) + + N = length(terminals) + _shunt_matrix = b* Matrix(LinearAlgebra.I, N, N) + return _shunt_matrix + +end From 5f89b05f4dabfe5987040020ee6fbc835d531e71 Mon Sep 17 00:00:00 2001 From: jjospina Date: Thu, 7 Nov 2024 14:03:20 -0700 Subject: [PATCH 23/27] FIX: issues to be able to run test case with switches. --- src/data_model/transformations/ravens2math.jl | 136 +++++++++--------- 1 file changed, 67 insertions(+), 69 deletions(-) diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index 59a9538d3..5ba8c91e9 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -535,8 +535,9 @@ function _map_ravens2math_energy_consumer!(data_math::Dict{String,<:Any}, data_r # Loop through op. limits for lim in op_limits - lim_type_name = _extract_name(lim["OperationalLimit.OperationalLimitType"]) - lim_type = data_ravens["OperationalLimitType"][lim_type_name]["OperationalLimitType.direction"] + # lim_type_name = _extract_name(lim["OperationalLimit.OperationalLimitType"]) # TODO: separate way of doing where OperationalLimitType is separated + # lim_type = data_ravens["OperationalLimitType"][lim_type_name]["OperationalLimitType.direction"] + lim_type = lim["OperationalLimit.OperationalLimitType"]["OperationalLimitType.direction"] if lim_type == "OperationalLimitDirectionKind.high" op_limit_max = lim["VoltageLimit.value"] / voltage_scale_factor_sqrt3 @@ -1038,7 +1039,7 @@ end "converts ravens switches into mathematical switches and (if neeed) impedance branches to represent loss model" function _map_ravens2math_switch!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) - # TODO enable real switches (right now only using vitual lines) + # TODO enable real switches (right now only using virtual lines) if haskey(data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"], "Switch") conducting_equipment = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"] @@ -1112,6 +1113,9 @@ function _map_ravens2math_switch!(data_math::Dict{String,<:Any}, data_ravens::Di @error("f_conns are not equal to t_conns!. Revise connections/phases in Switch terminals") end + math_obj["f_connections"] = f_conns + math_obj["t_connections"] = t_conns + # Phases nphases = length(f_conns) @@ -1137,20 +1141,11 @@ function _map_ravens2math_switch!(data_math::Dict{String,<:Any}, data_ravens::Di for (f_key, t_key) in [("Switch.ratedCurrent", "current_rating"), ("cm_ub_b", "c_rating_b"), ("cm_ub_c", "c_rating_c"), ("sm_ub", "thermal_rating"), ("sm_ub_b", "rate_b"), ("sm_ub_c", "rate_c")] math_obj[t_key] = haskey(ravens_obj, f_key) ? fill(ravens_obj[f_key], nphases) : fill(Inf, nphases) - - @info "$(math_obj[t_key])" - end # Map index map_to = "switch.$(math_obj["index"])" - # TODO: Apply linecode? No information is given in CIM related to linecodes - - - # TODO: Create virtual bus - - # Push Mapping data_math["switch"]["$(math_obj["index"])"] = math_obj @@ -1170,76 +1165,79 @@ end "converts ravens generic shunt components into mathematical shunt components" function _map_ravens2math_shunt_compensator!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) - regulating_cond_eq = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"]["RegulatingCondEq"] - power_scale_factor = data_math["settings"]["power_scale_factor"] - voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] + if haskey(data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"], "RegulatingCondEq") + regulating_cond_eq = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"]["RegulatingCondEq"] + power_scale_factor = data_math["settings"]["power_scale_factor"] + voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] - for (name, ravens_obj) in get(regulating_cond_eq, "ShuntCompensator", Dict{Any,Dict{String,Any}}()) + for (name, ravens_obj) in get(regulating_cond_eq, "ShuntCompensator", Dict{Any,Dict{String,Any}}()) - math_obj = _init_math_obj("shunt", name, ravens_obj, length(data_math["shunt"])+1; pass_props=pass_props) + math_obj = _init_math_obj("shunt", name, ravens_obj, length(data_math["shunt"])+1; pass_props=pass_props) - # Get connectivity node info (bus info) - connectivity_node = _extract_name(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"]) - math_obj["shunt_bus"] = data_math["bus_lookup"][connectivity_node] + # Get connectivity node info (bus info) + connectivity_node = _extract_name(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"]) + math_obj["shunt_bus"] = data_math["bus_lookup"][connectivity_node] - # Status - status = haskey(ravens_obj, "Equipment.inService") ? ravens_obj["Equipment.inService"] : "true" - math_obj["status"] = status == "true" ? 1 : 0 + # Status + status = haskey(ravens_obj, "Equipment.inService") ? ravens_obj["Equipment.inService"] : "true" + math_obj["status"] = status == "true" ? 1 : 0 - # Connections/phases obtained from Terminals - if haskey(ravens_obj["ConductingEquipment.Terminals"][1], "Terminal.phases") - phasecode = ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.phases"] - if (phasecode == "PhaseCode.ABC") - connections = [1, 2, 3] - elseif (phasecode == "PhaseCode.AB") - connections = [1, 2] - elseif (phasecode == "PhaseCode.AC") - connections = [1, 3] - elseif (phasecode == "PhaseCode.BC") - connections = [2, 3] - elseif (phasecode == "PhaseCode.A") - connections = [1] - elseif (phasecode == "PhaseCode.B") - connections = [2] - elseif (phasecode == "PhaseCode.C") - connections = [3] + # Connections/phases obtained from Terminals + if haskey(ravens_obj["ConductingEquipment.Terminals"][1], "Terminal.phases") + phasecode = ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.phases"] + if (phasecode == "PhaseCode.ABC") + connections = [1, 2, 3] + elseif (phasecode == "PhaseCode.AB") + connections = [1, 2] + elseif (phasecode == "PhaseCode.AC") + connections = [1, 3] + elseif (phasecode == "PhaseCode.BC") + connections = [2, 3] + elseif (phasecode == "PhaseCode.A") + connections = [1] + elseif (phasecode == "PhaseCode.B") + connections = [2] + elseif (phasecode == "PhaseCode.C") + connections = [3] + else + @error("PhaseCode not supported yet!") + end else - @error("PhaseCode not supported yet!") + connections = [1, 2, 3] # default end - else - connections = [1, 2, 3] # default - end - math_obj["connections"] = connections - terminals = connections + math_obj["connections"] = connections + terminals = connections - # TODO: dispatchable - math_obj["dispatchable"] = 0 + # TODO: dispatchable + math_obj["dispatchable"] = 0 - # bs - TODO: make sure b matrix is being calculated correctly - b = ravens_obj["LinearShuntCompensator.bPerSection"] - B = _calc_shunt_admittance_matrix(terminals, b) - math_obj["bs"] = B + # bs - TODO: make sure b matrix is being calculated correctly + b = ravens_obj["LinearShuntCompensator.bPerSection"] + B = _calc_shunt_admittance_matrix(terminals, b) + math_obj["bs"] = B - # gs - if haskey(ravens_obj, "LinearShuntCompensator.gPerSection") - g = ravens_obj["LinearShuntCompensator.gPerSection"] - G = _calc_shunt_admittance_matrix(terminals, g) - math_obj["gs"] = G - else - math_obj["gs"] = zeros(size(math_obj["bs"])) - end + # gs + if haskey(ravens_obj, "LinearShuntCompensator.gPerSection") + g = ravens_obj["LinearShuntCompensator.gPerSection"] + G = _calc_shunt_admittance_matrix(terminals, g) + math_obj["gs"] = G + else + math_obj["gs"] = zeros(size(math_obj["bs"])) + end - # Index - data_math["shunt"]["$(math_obj["index"])"] = math_obj + # Index + data_math["shunt"]["$(math_obj["index"])"] = math_obj - # TODO: Add CapControl - # ..... + # TODO: Add CapControl + # ..... - push!(data_math["map"], Dict{String,Any}( - "from" => name, - "to" => "shunt.$(math_obj["index"])", - "unmap_function" => "_map_math2ravens_shunt!", - )) + push!(data_math["map"], Dict{String,Any}( + "from" => name, + "to" => "shunt.$(math_obj["index"])", + "unmap_function" => "_map_math2ravens_shunt!", + )) + + end end end From 6aa181df4ca6eaec625a48d08a3f155d294b2421 Mon Sep 17 00:00:00 2001 From: jjospina Date: Fri, 8 Nov 2024 11:54:43 -0700 Subject: [PATCH 24/27] REF: ravens2math by removing if statements and using phasecode map in utils ravens. --- src/data_model/transformations/ravens2math.jl | 132 +++--------------- src/data_model/utils_ravens.jl | 10 ++ 2 files changed, 27 insertions(+), 115 deletions(-) diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index 5ba8c91e9..c3807b39c 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -294,9 +294,6 @@ function _map_ravens2math_power_transformer!(data_math::Dict{String,<:Any}, data to_map = data_math["map"][end]["to"] - # TODO: Check if we still need this function (or a similar function) - # _apply_xfmrcode!(ravens_obj, data_ravens) - # Get nrw: number of windings wdgs = ravens_obj["PowerTransformer.PowerTransformerEnd"] nrw = length(wdgs) @@ -311,25 +308,15 @@ function _map_ravens2math_power_transformer!(data_math::Dict{String,<:Any}, data f_node = "" t_node = "" - phasecode_map = Dict( - "PhaseCode.ABC" => [1, 2, 3], - "PhaseCode.AB" => [1, 2], - "PhaseCode.AC" => [1, 3], - "PhaseCode.BC" => [2, 3], - "PhaseCode.A" => [1], - "PhaseCode.B" => [2], - "PhaseCode.C" => [3] - ) - for wdg in wdgs # wdg phasecode wdg_terminals = wdg["ConductingEquipment.Terminals"][1] wdg_phasecode = wdg_terminals["Terminal.phases"] - # Connections (based on phasecode_map) - if haskey(phasecode_map, wdg_phasecode) - push!(connections, phasecode_map[wdg_phasecode]) + # Connections (based on _phasecode_map) + if haskey(_phasecode_map, wdg_phasecode) + push!(connections, _phasecode_map[wdg_phasecode]) else @error("PhaseCode not supported yet!") end @@ -401,7 +388,6 @@ function _map_ravens2math_power_transformer!(data_math::Dict{String,<:Any}, data dims = length(tm_set[1]) - # TODO: Polarity polarity = fill(1, nrw) @@ -535,9 +521,13 @@ function _map_ravens2math_energy_consumer!(data_math::Dict{String,<:Any}, data_r # Loop through op. limits for lim in op_limits - # lim_type_name = _extract_name(lim["OperationalLimit.OperationalLimitType"]) # TODO: separate way of doing where OperationalLimitType is separated - # lim_type = data_ravens["OperationalLimitType"][lim_type_name]["OperationalLimitType.direction"] - lim_type = lim["OperationalLimit.OperationalLimitType"]["OperationalLimitType.direction"] + + if haskey(data_ravens, "OperationalLimitType") + lim_type_name = _extract_name(lim["OperationalLimit.OperationalLimitType"]) + lim_type = data_ravens["OperationalLimitType"][lim_type_name]["OperationalLimitType.direction"] + else + lim_type = lim["OperationalLimit.OperationalLimitType"]["OperationalLimitType.direction"] + end if lim_type == "OperationalLimitDirectionKind.high" op_limit_max = lim["VoltageLimit.value"] / voltage_scale_factor_sqrt3 @@ -638,23 +628,7 @@ function _map_ravens2math_energy_source!(data_math::Dict{String,<:Any}, data_rav # Terminal Phases if haskey(ravens_obj["ConductingEquipment.Terminals"][1], "Terminal.phases") phasecode = ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.phases"] - if (phasecode == "PhaseCode.ABC") - math_obj["connections"] = [1, 2, 3] - elseif (phasecode == "PhaseCode.AB") - math_obj["connections"] = [1, 2] - elseif (phasecode == "PhaseCode.AC") - math_obj["connections"] = [1, 3] - elseif (phasecode == "PhaseCode.BC") - math_obj["connections"] = [2, 3] - elseif (phasecode == "PhaseCode.A") - math_obj["connections"] = [1] - elseif (phasecode == "PhaseCode.B") - math_obj["connections"] = [2] - elseif (phasecode == "PhaseCode.C") - math_obj["connections"] = [3] - else - @error("PhaseCode not supported yet!") - end + math_obj["connections"] = _phasecode_map[phasecode] else math_obj["connections"] = bus_conn["terminals"] end @@ -775,23 +749,7 @@ function _map_ravens2math_rotating_machine!(data_math::Dict{String,<:Any}, data_ # Connections/phases obtained from Terminals if haskey(ravens_obj["ConductingEquipment.Terminals"][1], "Terminal.phases") phasecode = ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.phases"] - if (phasecode == "PhaseCode.ABC") - connections = [1, 2, 3] - elseif (phasecode == "PhaseCode.AB") - connections = [1, 2] - elseif (phasecode == "PhaseCode.AC") - connections = [1, 3] - elseif (phasecode == "PhaseCode.BC") - connections = [2, 3] - elseif (phasecode == "PhaseCode.A") - connections = [1] - elseif (phasecode == "PhaseCode.B") - connections = [2] - elseif (phasecode == "PhaseCode.C") - connections = [3] - else - @error("PhaseCode not supported yet!") - end + connections = _phasecode_map[phasecode] else connections = [1, 2, 3] # default end @@ -1051,56 +1009,16 @@ function _map_ravens2math_switch!(data_math::Dict{String,<:Any}, data_ravens::Di # Terminals and phases terminals = ravens_obj["ConductingEquipment.Terminals"] - # TODO: refactor - Loop through terminals and verify connections + # Loop through terminals f_conns = [0,0,0] t_conns = [0,0,0] for term in terminals if haskey(term, "Terminal.phases") phasecode = term["Terminal.phases"] - if (phasecode == "PhaseCode.ABC") - if term["ACDCTerminal.sequenceNumber"] == 1 - f_conns = [1, 2, 3] - else - t_conns = [1, 2, 3] - end - elseif (phasecode == "PhaseCode.AB") - if term["ACDCTerminal.sequenceNumber"] == 1 - f_conns = [1, 2] - else - t_conns = [1, 2] - end - elseif (phasecode == "PhaseCode.AC") - if term["ACDCTerminal.sequenceNumber"] == 1 - f_conns = [1, 3] - else - t_conns = [1, 3] - end - elseif (phasecode == "PhaseCode.BC") - if term["ACDCTerminal.sequenceNumber"] == 1 - f_conns = [2, 3] - else - t_conns = [2, 3] - end - elseif (phasecode == "PhaseCode.A") - if term["ACDCTerminal.sequenceNumber"] == 1 - f_conns = [1] - else - t_conns = [1] - end - elseif (phasecode == "PhaseCode.B") - if term["ACDCTerminal.sequenceNumber"] == 1 - f_conns = [2] - else - t_conns = [2] - end - elseif (phasecode == "PhaseCode.C") - if term["ACDCTerminal.sequenceNumber"] == 1 - f_conns = [3] - else - t_conns = [3] - end + if term["ACDCTerminal.sequenceNumber"] == 1 + f_conns = _phasecode_map[phasecode] else - @error("PhaseCode not supported yet!") + t_conns = _phasecode_map[phasecode] end else f_conns = [1, 2, 3] @@ -1185,23 +1103,7 @@ function _map_ravens2math_shunt_compensator!(data_math::Dict{String,<:Any}, data # Connections/phases obtained from Terminals if haskey(ravens_obj["ConductingEquipment.Terminals"][1], "Terminal.phases") phasecode = ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.phases"] - if (phasecode == "PhaseCode.ABC") - connections = [1, 2, 3] - elseif (phasecode == "PhaseCode.AB") - connections = [1, 2] - elseif (phasecode == "PhaseCode.AC") - connections = [1, 3] - elseif (phasecode == "PhaseCode.BC") - connections = [2, 3] - elseif (phasecode == "PhaseCode.A") - connections = [1] - elseif (phasecode == "PhaseCode.B") - connections = [2] - elseif (phasecode == "PhaseCode.C") - connections = [3] - else - @error("PhaseCode not supported yet!") - end + connections = _phasecode_map[phasecode] else connections = [1, 2, 3] # default end diff --git a/src/data_model/utils_ravens.jl b/src/data_model/utils_ravens.jl index 8376b31c7..7091e60ae 100644 --- a/src/data_model/utils_ravens.jl +++ b/src/data_model/utils_ravens.jl @@ -1,3 +1,13 @@ +const _phasecode_map = Dict( + "PhaseCode.ABC" => [1, 2, 3], + "PhaseCode.AB" => [1, 2], + "PhaseCode.AC" => [1, 3], + "PhaseCode.BC" => [2, 3], + "PhaseCode.A" => [1], + "PhaseCode.B" => [2], + "PhaseCode.C" => [3] +) + "initializes the base math object of any type" function _init_math_obj_ravens(obj_type::String, eng_id::Any, eng_obj::Dict{String,<:Any}, index::Int; pass_props::Vector{String}=String[])::Dict{String,Any} From e04a1f00863bf93ea7d68bed997055c7dc4e4bb9 Mon Sep 17 00:00:00 2001 From: jjospina Date: Fri, 8 Nov 2024 13:13:17 -0700 Subject: [PATCH 25/27] REF: ravens2math to reduce if levels. --- src/data_model/transformations/ravens2math.jl | 258 +++++++++--------- 1 file changed, 125 insertions(+), 133 deletions(-) diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index c3807b39c..fb56328fb 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -468,12 +468,12 @@ end Converts ravens load components into mathematical load components. """ function _map_ravens2math_energy_consumer!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) - conducting_equipment = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"] + energy_connections = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"] power_scale_factor = data_math["settings"]["power_scale_factor"] voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] voltage_scale_factor_sqrt3 = voltage_scale_factor * sqrt(3) - for (name, ravens_obj) in get(conducting_equipment, "EnergyConsumer", Dict{Any,Dict{String,Any}}()) + for (name, ravens_obj) in get(energy_connections, "EnergyConsumer", Dict{Any,Dict{String,Any}}()) math_obj = _init_math_obj_ravens("energy_consumer", name, ravens_obj, length(data_math["load"]) + 1; pass_props=pass_props) # Set the load bus based on connectivity node @@ -598,11 +598,11 @@ end Converts ravens voltage sources into mathematical generators and (if needed) impedance branches to represent the loss model. """ function _map_ravens2math_energy_source!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) - conducting_equipment = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"] + energy_connections = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"] voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] voltage_scale_factor_sqrt3 = voltage_scale_factor * sqrt(3) - for (name, ravens_obj) in get(conducting_equipment, "EnergySource", Dict{Any,Dict{String,Any}}()) + for (name, ravens_obj) in get(energy_connections, "EnergySource", Dict{Any,Dict{String,Any}}()) math_obj = _init_math_obj_ravens("energy_source", name, ravens_obj, length(data_math["gen"]) + 1; pass_props=pass_props) math_obj["name"] = "_virtual_gen.energy_source.$name" @@ -735,85 +735,86 @@ end "converts engineering generators into mathematical generators" function _map_ravens2math_rotating_machine!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) + energy_connections = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"] - if haskey(data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"], "RegulatingCondEq") + if haskey(energy_connections, "RegulatingCondEq") - regulating_cond_eq = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"]["RegulatingCondEq"] + regulating_cond_eq = energy_connections["RegulatingCondEq"] power_scale_factor = data_math["settings"]["power_scale_factor"] voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] for (name, ravens_obj) in get(regulating_cond_eq, "RotatingMachine", Dict{Any,Dict{String,Any}}()) - math_obj = _init_math_obj_ravens("rotating_machine", name, ravens_obj, length(data_math["gen"])+1; pass_props=pass_props) + math_obj = _init_math_obj_ravens("rotating_machine", name, ravens_obj, length(data_math["gen"])+1; pass_props=pass_props) - # Connections/phases obtained from Terminals - if haskey(ravens_obj["ConductingEquipment.Terminals"][1], "Terminal.phases") - phasecode = ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.phases"] - connections = _phasecode_map[phasecode] - else - connections = [1, 2, 3] # default - end - - nconductors = length(connections) - math_obj["connections"] = connections + # Connections/phases obtained from Terminals + if haskey(ravens_obj["ConductingEquipment.Terminals"][1], "Terminal.phases") + phasecode = ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.phases"] + connections = _phasecode_map[phasecode] + else + connections = [1, 2, 3] # default + end - connectivity_node = _extract_name(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"]) - math_obj["gen_bus"] = data_math["bus_lookup"][connectivity_node] - math_obj["gen_status"] = get(ravens_obj, "Equipment.inService", "true") - math_obj["gen_status"] = status = math_obj["gen_status"] == "true" ? 1 : 0 + nconductors = length(connections) + math_obj["connections"] = connections - # TODO: control mode do not exist in the RAVENS-CIM (Need to be added) - math_obj["control_mode"] = control_mode = Int(get(ravens_obj, "control_mode", FREQUENCYDROOP)) + connectivity_node = _extract_name(ravens_obj["ConductingEquipment.Terminals"][1]["Terminal.ConnectivityNode"]) + math_obj["gen_bus"] = data_math["bus_lookup"][connectivity_node] + math_obj["gen_status"] = get(ravens_obj, "Equipment.inService", "true") + math_obj["gen_status"] = status = math_obj["gen_status"] == "true" ? 1 : 0 - # Set Pmax for generator - if !haskey(ravens_obj, "GeneratingUnit.maxOperatingP") - math_obj["pmax"] = ((get(ravens_obj, "RotatingMachine.ratedS", Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) - else - math_obj["pmax"] = ((get(ravens_obj, "GeneratingUnit.maxOperatingP", Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) - end + # TODO: control mode do not exist in the RAVENS-CIM (Need to be added) + math_obj["control_mode"] = control_mode = Int(get(ravens_obj, "control_mode", FREQUENCYDROOP)) - # Set bus type - bus_type = data_math["bus"]["$(math_obj["gen_bus"])"]["bus_type"] - data_math["bus"]["$(math_obj["gen_bus"])"]["bus_type"] = _compute_bus_type(bus_type, status, control_mode) + # Set Pmax for generator + if !haskey(ravens_obj, "GeneratingUnit.maxOperatingP") + math_obj["pmax"] = ((get(ravens_obj, "RotatingMachine.ratedS", Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) + else + math_obj["pmax"] = ((get(ravens_obj, "GeneratingUnit.maxOperatingP", Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) + end - # Set the nominal voltage - base_voltage_ref = _extract_name(ravens_obj["ConductingEquipment.BaseVoltage"]) - nominal_voltage = data_ravens["BaseVoltage"][base_voltage_ref]["BaseVoltage.nominalVoltage"] - base_voltage = nominal_voltage / sqrt(nconductors) - math_obj["vbase"] = base_voltage / voltage_scale_factor - - if control_mode == Int(ISOCHRONOUS) && status == 1 - data_math["bus"]["$(math_obj["gen_bus"])"]["vm"] = ((get(ravens_obj, "RotatingMachine.ratedU", nominal_voltage))/nominal_voltage)* ones(nconductors) - data_math["bus"]["$(math_obj["gen_bus"])"]["vmax"] = ((get(ravens_obj, "RotatingMachine.ratedU", nominal_voltage))/nominal_voltage)* ones(nconductors) - data_math["bus"]["$(math_obj["gen_bus"])"]["vmin"] = ((get(ravens_obj, "RotatingMachine.ratedU", nominal_voltage))/nominal_voltage)* ones(nconductors) - data_math["bus"]["$(math_obj["gen_bus"])"]["va"] = [0.0, -120, 120, zeros(length(data_math["bus"]["$(math_obj["gen_bus"])"]) - 3)...][data_math["bus"]["$(math_obj["gen_bus"])"]["terminals"]] - end + # Set bus type + bus_type = data_math["bus"]["$(math_obj["gen_bus"])"]["bus_type"] + data_math["bus"]["$(math_obj["gen_bus"])"]["bus_type"] = _compute_bus_type(bus_type, status, control_mode) + + # Set the nominal voltage + base_voltage_ref = _extract_name(ravens_obj["ConductingEquipment.BaseVoltage"]) + nominal_voltage = data_ravens["BaseVoltage"][base_voltage_ref]["BaseVoltage.nominalVoltage"] + base_voltage = nominal_voltage / sqrt(nconductors) + math_obj["vbase"] = base_voltage / voltage_scale_factor + + if control_mode == Int(ISOCHRONOUS) && status == 1 + data_math["bus"]["$(math_obj["gen_bus"])"]["vm"] = ((get(ravens_obj, "RotatingMachine.ratedU", nominal_voltage))/nominal_voltage)* ones(nconductors) + data_math["bus"]["$(math_obj["gen_bus"])"]["vmax"] = ((get(ravens_obj, "RotatingMachine.ratedU", nominal_voltage))/nominal_voltage)* ones(nconductors) + data_math["bus"]["$(math_obj["gen_bus"])"]["vmin"] = ((get(ravens_obj, "RotatingMachine.ratedU", nominal_voltage))/nominal_voltage)* ones(nconductors) + data_math["bus"]["$(math_obj["gen_bus"])"]["va"] = [0.0, -120, 120, zeros(length(data_math["bus"]["$(math_obj["gen_bus"])"]) - 3)...][data_math["bus"]["$(math_obj["gen_bus"])"]["terminals"]] + end - # Set pmin - math_obj["pmin"] = ((get(ravens_obj, "GeneratingUnit.minOperatingP", 0) * ones(nconductors)) ./ nconductors)./(power_scale_factor) - # Set qmin - math_obj["qmin"] = ((get(ravens_obj, "RotatingMachine.minQ", -Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) - # Set qmax - math_obj["qmax"] = ((get(ravens_obj, "RotatingMachine.maxQ", Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) + # Set pmin + math_obj["pmin"] = ((get(ravens_obj, "GeneratingUnit.minOperatingP", 0) * ones(nconductors)) ./ nconductors)./(power_scale_factor) + # Set qmin + math_obj["qmin"] = ((get(ravens_obj, "RotatingMachine.minQ", -Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) + # Set qmax + math_obj["qmax"] = ((get(ravens_obj, "RotatingMachine.maxQ", Inf) * ones(nconductors)) ./ nconductors)./(power_scale_factor) - # Set pg and qg - math_obj["pg"] = (get(ravens_obj, "RotatingMachine.p", 0.0) * ones(nconductors) ./ nconductors)./(power_scale_factor) - math_obj["qg"] = (get(ravens_obj, "RotatingMachine.q", 0.0) * ones(nconductors) ./ nconductors)./(power_scale_factor) + # Set pg and qg + math_obj["pg"] = (get(ravens_obj, "RotatingMachine.p", 0.0) * ones(nconductors) ./ nconductors)./(power_scale_factor) + math_obj["qg"] = (get(ravens_obj, "RotatingMachine.q", 0.0) * ones(nconductors) ./ nconductors)./(power_scale_factor) - # TODO: add a polynomial parameters to be added to gen cost - _add_gen_cost_model!(math_obj, ravens_obj) + # TODO: add a polynomial parameters to be added to gen cost + _add_gen_cost_model!(math_obj, ravens_obj) - # TODO: configuration for generators is not available on CIM (yet) - math_obj["configuration"] = get(ravens_obj, "configuration", WYE) + # TODO: configuration for generators is not available on CIM (yet) + math_obj["configuration"] = get(ravens_obj, "configuration", WYE) - # Set index - data_math["gen"]["$(math_obj["index"])"] = math_obj + # Set index + data_math["gen"]["$(math_obj["index"])"] = math_obj - push!(data_math["map"], Dict{String,Any}( - "from" => name, - "to" => "gen.$(math_obj["index"])", - "unmap_function" => "_map_math2ravens_rotating_machine!", - )) + push!(data_math["map"], Dict{String,Any}( + "from" => name, + "to" => "gen.$(math_obj["index"])", + "unmap_function" => "_map_math2ravens_rotating_machine!", + )) end end @@ -823,10 +824,11 @@ end "converts ravens power_electronics units such as PVs and Batteries into mathematical components" function _map_ravens2math_power_electronics!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) + energy_connections = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"] - if haskey(data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"], "RegulatingCondEq") + if haskey(energy_connections, "RegulatingCondEq") - regulating_cond_eq = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"]["RegulatingCondEq"] + regulating_cond_eq = energy_connections["RegulatingCondEq"] power_scale_factor = data_math["settings"]["power_scale_factor"] voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] @@ -988,103 +990,95 @@ function _map_ravens2math_power_electronics!(data_math::Dict{String,<:Any}, data )) end end - end - end "converts ravens switches into mathematical switches and (if neeed) impedance branches to represent loss model" function _map_ravens2math_switch!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) + conducting_equipment = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"] - # TODO enable real switches (right now only using virtual lines) - if haskey(data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"], "Switch") - - conducting_equipment = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"] - - for (name, ravens_obj) in get(conducting_equipment, "Switch", Dict{Any,Dict{String,Any}}()) + for (name, ravens_obj) in get(conducting_equipment, "Switch", Dict{Any,Dict{String,Any}}()) - math_obj = _init_math_obj_ravens("switch", name, ravens_obj, length(data_math["switch"])+1; pass_props=pass_props) + math_obj = _init_math_obj_ravens("switch", name, ravens_obj, length(data_math["switch"])+1; pass_props=pass_props) - # Terminals and phases - terminals = ravens_obj["ConductingEquipment.Terminals"] + # Terminals and phases + terminals = ravens_obj["ConductingEquipment.Terminals"] - # Loop through terminals - f_conns = [0,0,0] - t_conns = [0,0,0] - for term in terminals - if haskey(term, "Terminal.phases") - phasecode = term["Terminal.phases"] - if term["ACDCTerminal.sequenceNumber"] == 1 - f_conns = _phasecode_map[phasecode] - else - t_conns = _phasecode_map[phasecode] - end + # Loop through terminals + f_conns = [0,0,0] + t_conns = [0,0,0] + for term in terminals + if haskey(term, "Terminal.phases") + phasecode = term["Terminal.phases"] + if term["ACDCTerminal.sequenceNumber"] == 1 + f_conns = _phasecode_map[phasecode] else - f_conns = [1, 2, 3] - t_conns = [1, 2, 3] + t_conns = _phasecode_map[phasecode] end + else + f_conns = [1, 2, 3] + t_conns = [1, 2, 3] end + end - # Verify connections are correct. - if (f_conns != t_conns ) - @error("f_conns are not equal to t_conns!. Revise connections/phases in Switch terminals") - end - - math_obj["f_connections"] = f_conns - math_obj["t_connections"] = t_conns + # Verify connections are correct. + if (f_conns != t_conns ) + @error("f_conns are not equal to t_conns!. Revise connections/phases in Switch terminals") + end - # Phases - nphases = length(f_conns) + math_obj["f_connections"] = f_conns + math_obj["t_connections"] = t_conns - # Connectivity Nodes - f_node = _extract_name(terminals[1]["Terminal.ConnectivityNode"]) - t_node = _extract_name(terminals[2]["Terminal.ConnectivityNode"]) - math_obj["f_bus"] = data_math["bus_lookup"][f_node] - math_obj["t_bus"] = data_math["bus_lookup"][t_node] + # Phases + nphases = length(f_conns) - # TODO: Status - math_obj["status"] = get(ravens_obj, "Equipment.inService", "true") - math_obj["status"] = status = math_obj["status"] == "true" ? 1 : 0 + # Connectivity Nodes + f_node = _extract_name(terminals[1]["Terminal.ConnectivityNode"]) + t_node = _extract_name(terminals[2]["Terminal.ConnectivityNode"]) + math_obj["f_bus"] = data_math["bus_lookup"][f_node] + math_obj["t_bus"] = data_math["bus_lookup"][t_node] - # State - sw_state = get(ravens_obj, "Switch.open", "false") - sw_state = sw_state == "false" ? CLOSED : OPEN - math_obj["state"] = Int(sw_state) + # TODO: Status + math_obj["status"] = get(ravens_obj, "Equipment.inService", "true") + math_obj["status"] = status = math_obj["status"] == "true" ? 1 : 0 - # TODO: Dispatchable - math_obj["dispatchable"] = Int(get(ravens_obj, "dispatchable", YES)) + # State + sw_state = get(ravens_obj, "Switch.open", "false") + sw_state = sw_state == "false" ? CLOSED : OPEN + math_obj["state"] = Int(sw_state) - # TODO: OPF bounds - Do we really need all of these values? - for (f_key, t_key) in [("Switch.ratedCurrent", "current_rating"), ("cm_ub_b", "c_rating_b"), ("cm_ub_c", "c_rating_c"), - ("sm_ub", "thermal_rating"), ("sm_ub_b", "rate_b"), ("sm_ub_c", "rate_c")] - math_obj[t_key] = haskey(ravens_obj, f_key) ? fill(ravens_obj[f_key], nphases) : fill(Inf, nphases) - end + # TODO: Dispatchable + math_obj["dispatchable"] = Int(get(ravens_obj, "dispatchable", YES)) - # Map index - map_to = "switch.$(math_obj["index"])" + # TODO: OPF bounds - Do we really need all of these values? + for (f_key, t_key) in [("Switch.ratedCurrent", "current_rating"), ("cm_ub_b", "c_rating_b"), ("cm_ub_c", "c_rating_c"), + ("sm_ub", "thermal_rating"), ("sm_ub_b", "rate_b"), ("sm_ub_c", "rate_c")] + math_obj[t_key] = haskey(ravens_obj, f_key) ? fill(ravens_obj[f_key], nphases) : fill(Inf, nphases) + end - # Push Mapping - data_math["switch"]["$(math_obj["index"])"] = math_obj + # Map index + map_to = "switch.$(math_obj["index"])" - push!(data_math["map"], Dict{String,Any}( - "from" => name, - "to" => map_to, - "unmap_function" => "_map_math2ravens_switch!", - )) + # Push Mapping + data_math["switch"]["$(math_obj["index"])"] = math_obj - end + push!(data_math["map"], Dict{String,Any}( + "from" => name, + "to" => map_to, + "unmap_function" => "_map_math2ravens_switch!", + )) end - end "converts ravens generic shunt components into mathematical shunt components" function _map_ravens2math_shunt_compensator!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) + energy_connections = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"] - if haskey(data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"], "RegulatingCondEq") - regulating_cond_eq = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"]["RegulatingCondEq"] + if haskey(energy_connections, "RegulatingCondEq") + regulating_cond_eq = energy_connections["RegulatingCondEq"] power_scale_factor = data_math["settings"]["power_scale_factor"] voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] @@ -1138,8 +1132,6 @@ function _map_ravens2math_shunt_compensator!(data_math::Dict{String,<:Any}, data "to" => "shunt.$(math_obj["index"])", "unmap_function" => "_map_math2ravens_shunt!", )) - end - end end From 86fa5be51407b76b950c543c9a9ed6ddf4a0d973 Mon Sep 17 00:00:00 2001 From: jjospina Date: Fri, 8 Nov 2024 14:37:56 -0700 Subject: [PATCH 26/27] ADD: unit tests for ravens parser. --- test/data/ravens/ravens_case3_withcap.json | 580 ++++++++++++ test/data/ravens/ravens_case3_withgens.json | 606 +++++++++++++ .../ravens/ravens_case3_withpvandstorage.json | 621 +++++++++++++ test/data/ravens/ravens_case3_withsubxf.json | 836 ++++++++++++++++++ test/data/ravens/ravens_test_switch_1w.json | 554 ++++++++++++ test/data/ravens/ravens_test_switch_3w.json | 785 ++++++++++++++++ test/opf_ravens.jl | 70 ++ test/runtests.jl | 2 + test/test_cases.jl | 8 + 9 files changed, 4062 insertions(+) create mode 100644 test/data/ravens/ravens_case3_withcap.json create mode 100644 test/data/ravens/ravens_case3_withgens.json create mode 100644 test/data/ravens/ravens_case3_withpvandstorage.json create mode 100644 test/data/ravens/ravens_case3_withsubxf.json create mode 100644 test/data/ravens/ravens_test_switch_1w.json create mode 100644 test/data/ravens/ravens_test_switch_3w.json create mode 100644 test/opf_ravens.jl diff --git a/test/data/ravens/ravens_case3_withcap.json b/test/data/ravens/ravens_case3_withcap.json new file mode 100644 index 000000000..a5afd36fc --- /dev/null +++ b/test/data/ravens/ravens_case3_withcap.json @@ -0,0 +1,580 @@ +{ + "PerLengthLineParameter": { + "PerLengthImpedance": { + "PerLengthPhaseImpedance": { + "4/0quad": { + "Ravens.CimObjectType": "PerLengthPhaseImpedance", + "IdentifiedObject.mRID": "b9ede34e-a50f-4afc-b83e-f3cd0578a600", + "IdentifiedObject.name": "4/0quad", + "PerLengthPhaseImpedance.conductorCount": 3, + "PerLengthPhaseImpedance.PhaseImpedanceData": [ + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 2, + "PhaseImpedanceData.r": 0.0467, + "PhaseImpedanceData.x": 0.0267, + "PhaseImpedanceData.b": -0.0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 2, + "PhaseImpedanceData.column": 2, + "PhaseImpedanceData.r": 0.1167, + "PhaseImpedanceData.x": 0.0667, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 2, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.0467, + "PhaseImpedanceData.x": 0.0267, + "PhaseImpedanceData.b": -0.0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 1, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.1167, + "PhaseImpedanceData.x": 0.0667, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 3, + "PhaseImpedanceData.r": 0.1167, + "PhaseImpedanceData.x": 0.0667, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.0467, + "PhaseImpedanceData.x": 0.0267, + "PhaseImpedanceData.b": -0.0 + } + ] + }, + "556mcm": { + "Ravens.CimObjectType": "PerLengthPhaseImpedance", + "IdentifiedObject.mRID": "c71a840c-a77b-4be6-b20e-8a372d0af874", + "IdentifiedObject.name": "556mcm", + "PerLengthPhaseImpedance.conductorCount": 3, + "PerLengthPhaseImpedance.PhaseImpedanceData": [ + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 3, + "PhaseImpedanceData.r": 0.1, + "PhaseImpedanceData.x": 0.0583, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 2, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.04, + "PhaseImpedanceData.x": 0.0233, + "PhaseImpedanceData.b": -0.0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 2, + "PhaseImpedanceData.r": 0.04, + "PhaseImpedanceData.x": 0.0233, + "PhaseImpedanceData.b": -0.0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.04, + "PhaseImpedanceData.x": 0.0233, + "PhaseImpedanceData.b": -0.0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 1, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.1, + "PhaseImpedanceData.x": 0.0583, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 2, + "PhaseImpedanceData.column": 2, + "PhaseImpedanceData.r": 0.1, + "PhaseImpedanceData.x": 0.0583, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + } + ] + } + } + } + }, + "PowerSystemResource": { + "Equipment": { + "ConductingEquipment": { + "Conductor": { + "ACLineSegment": { + "quad": { + "Ravens.CimObjectType": "ACLineSegment", + "IdentifiedObject.mRID": "f501b03c-aee6-4524-a253-3adc0a016c92", + "IdentifiedObject.name": "quad", + "Conductor.length": 1.0, + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "ACLineSegment.PerLengthImpedance": "PerLengthPhaseImpedance::'4/0quad'", + "ACLineSegment.ACLineSegmentPhase": [ + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "9cce4dc1-447a-435f-ae0f-8b31058209b7", + "IdentifiedObject.name": "quad_A", + "ACLineSegmentPhase.phase": "SinglePhaseKind.A", + "ACLineSegmentPhase.sequenceNumber": 1 + }, + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "349837bd-1743-4fdd-9305-129146cf7048", + "IdentifiedObject.name": "quad_B", + "ACLineSegmentPhase.phase": "SinglePhaseKind.B", + "ACLineSegmentPhase.sequenceNumber": 2 + }, + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "31349b5e-6351-4ccb-8462-1f2717f03565", + "IdentifiedObject.name": "quad_C", + "ACLineSegmentPhase.phase": "SinglePhaseKind.C", + "ACLineSegmentPhase.sequenceNumber": 3 + } + ], + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "645b55d4-e061-4163-b1ba-d0d74395a42c", + "IdentifiedObject.name": "quad_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'primary'" + }, + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "208c5aea-a854-4124-b365-c69677b1a5b2", + "IdentifiedObject.name": "quad_T2", + "ACDCTerminal.sequenceNumber": 2, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ] + }, + "ohline": { + "Ravens.CimObjectType": "ACLineSegment", + "IdentifiedObject.mRID": "ea549d70-b21a-4132-a5d2-ef9996f6c0ea", + "IdentifiedObject.name": "ohline", + "Conductor.length": 1.0, + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "ACLineSegment.PerLengthImpedance": "PerLengthPhaseImpedance::'556mcm'", + "ACLineSegment.ACLineSegmentPhase": [ + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "b3094d11-632b-489b-a645-fa006dde1367", + "IdentifiedObject.name": "ohline_A", + "ACLineSegmentPhase.phase": "SinglePhaseKind.A", + "ACLineSegmentPhase.sequenceNumber": 1 + }, + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "5191b2b6-09ee-44d5-b3a8-17de5b345216", + "IdentifiedObject.name": "ohline_B", + "ACLineSegmentPhase.phase": "SinglePhaseKind.B", + "ACLineSegmentPhase.sequenceNumber": 2 + }, + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "d8523544-a3e0-466a-94ab-b68dbdf4f36a", + "IdentifiedObject.name": "ohline_C", + "ACLineSegmentPhase.phase": "SinglePhaseKind.C", + "ACLineSegmentPhase.sequenceNumber": 3 + } + ], + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "d15f3652-af59-4f84-a4d4-b218c4ad6b2a", + "IdentifiedObject.name": "ohline_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'sourcebus'" + }, + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "c72fbd81-3362-436d-be2b-ebff11174263", + "IdentifiedObject.name": "ohline_T2", + "ACDCTerminal.sequenceNumber": 2, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'primary'" + } + ] + } + } + }, + "EnergyConnection": { + "EnergyConsumer": { + "l1": { + "Ravens.CimObjectType": "EnergyConsumer", + "IdentifiedObject.mRID": "8bef6e0f-813f-4cd5-9613-4fe60e159e7b", + "IdentifiedObject.name": "l1", + "EnergyConsumer.p": 6000.0, + "EnergyConsumer.q": 3000.0, + "EnergyConsumer.customerCount": 1, + "EnergyConsumer.grounded": "true", + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "EnergyConsumer.phaseConnection": "PhaseShuntConnectionKind.Y", + "EnergyConsumer.LoadResponseCharacteristic": "LoadResponseCharacteristic::'Constant kVA'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "09eb27e3-654c-4823-bdce-51fc6b3dbffe", + "IdentifiedObject.name": "l1_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.A", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ], + "EnergyConsumer.EnergyConsumerPhase": [ + { + "Ravens.CimObjectType": "EnergyConsumerPhase", + "IdentifiedObject.mRID": "317c70ec-5985-482f-b515-bf94de7eef00", + "IdentifiedObject.name": "l1_A", + "EnergyConsumerPhase.p": 6000.0, + "EnergyConsumerPhase.q": 3000.0, + "EnergyConsumerPhase.phase": "SinglePhaseKind.A" + } + ] + }, + "l2": { + "Ravens.CimObjectType": "EnergyConsumer", + "IdentifiedObject.mRID": "92d0f990-dc53-4496-86a7-25244905f08e", + "IdentifiedObject.name": "l2", + "EnergyConsumer.p": 6000.0, + "EnergyConsumer.q": 3000.0, + "EnergyConsumer.customerCount": 1, + "EnergyConsumer.grounded": "true", + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "EnergyConsumer.phaseConnection": "PhaseShuntConnectionKind.Y", + "EnergyConsumer.LoadResponseCharacteristic": "LoadResponseCharacteristic::'Constant kVA'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "d4cb98f1-86d4-4860-aafd-563dd86e7a52", + "IdentifiedObject.name": "l2_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.B", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ], + "EnergyConsumer.EnergyConsumerPhase": [ + { + "Ravens.CimObjectType": "EnergyConsumerPhase", + "IdentifiedObject.mRID": "d20c16f2-db2b-459a-81f1-535a1559c762", + "IdentifiedObject.name": "l2_B", + "EnergyConsumerPhase.p": 6000.0, + "EnergyConsumerPhase.q": 3000.0, + "EnergyConsumerPhase.phase": "SinglePhaseKind.B" + } + ] + }, + "l3": { + "Ravens.CimObjectType": "EnergyConsumer", + "IdentifiedObject.mRID": "6bc98558-9400-4d89-a6fe-54ccaee27b38", + "IdentifiedObject.name": "l3", + "EnergyConsumer.p": 6000.0, + "EnergyConsumer.q": 3000.0, + "EnergyConsumer.customerCount": 1, + "EnergyConsumer.grounded": "true", + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "EnergyConsumer.phaseConnection": "PhaseShuntConnectionKind.Y", + "EnergyConsumer.LoadResponseCharacteristic": "LoadResponseCharacteristic::'Constant kVA'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "701902a4-7dab-40eb-b1f6-f5008e5fcb9c", + "IdentifiedObject.name": "l3_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.C", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ], + "EnergyConsumer.EnergyConsumerPhase": [ + { + "Ravens.CimObjectType": "EnergyConsumerPhase", + "IdentifiedObject.mRID": "cdacb568-8574-4002-9635-64a893e4a2b0", + "IdentifiedObject.name": "l3_C", + "EnergyConsumerPhase.p": 6000.0, + "EnergyConsumerPhase.q": 3000.0, + "EnergyConsumerPhase.phase": "SinglePhaseKind.C" + } + ] + } + }, + "EnergySource": { + "source": { + "Ravens.CimObjectType": "EnergySource", + "IdentifiedObject.mRID": "c0d17284-08ca-46f4-899a-5a87055acd9a", + "IdentifiedObject.name": "source", + "EnergySource.nominalVoltage": 400.0, + "EnergySource.voltageMagnitude": 398.36, + "EnergySource.voltageAngle": 0.0, + "EnergySource.r": 3.880570000581328e-08, + "EnergySource.x": 1.5522280002325312e-07, + "EnergySource.r0": 5.069596039676399e-08, + "EnergySource.x0": 1.5208788119029196e-07, + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "2709c1dc-e81b-41c1-9cdb-262c3df42a9e", + "IdentifiedObject.name": "source_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'sourcebus'" + } + ] + } + }, + "RegulatingCondEq": { + "ShuntCompensator": { + "c1": { + "Ravens.CimObjectType": "LinearShuntCompensator", + "IdentifiedObject.mRID": "41f54a4b-8980-4117-9aaf-985c316768ea", + "IdentifiedObject.name": "c1", + "ShuntCompensator.nomU": 400.0, + "LinearShuntCompensator.bPerSection": 0.12499999999999997, + "LinearShuntCompensator.gPerSection": 0.0, + "ShuntCompensator.phaseConnection": "ShuntConnectionKind.Y", + "LinearShuntCompensator.b0PerSection": 0.12499999999999997, + "LinearShuntCompensator.g0PerSection": 0.0, + "LinearShuntCompensator.normalSections": 1, + "LinearShuntCompensator.maximumSections": 1, + "Equipment.inService": "true", + "LinearShuntCompensator.aVRDelay": 0.0, + "ShuntCompensator.sections": 1, + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "6095aca4-7c9c-4d4e-801c-469a47c6b595", + "IdentifiedObject.name": "c1_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ] + } + } + } + } + } + } + }, + "OperationalLimitSet": { + "OpLimI_38.97114317029974_51.96152422706632": { + "Ravens.CimObjectType": "OperationalLimitSet", + "IdentifiedObject.mRID": "44764d73-372f-4d55-8e84-5ab8ffc703da", + "IdentifiedObject.name": "OpLimI_38.97114317029974_51.96152422706632", + "OperationalLimitSet.OperationalLimitValue": [ + { + "Ravens.CimObjectType": "CurrentLimit", + "IdentifiedObject.mRID": "7f1251a9-83e6-42e1-9447-7af24510b432", + "IdentifiedObject.name": "OpLimI_38.97114317029974_51.96152422706632_Norm", + "CurrentLimit.value": 38.97114317029974, + "CurrentLimit.normalValue": 38.97114317029974, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'absoluteValueType_5000000000.0s'" + }, + { + "Ravens.CimObjectType": "CurrentLimit", + "IdentifiedObject.mRID": "26784e14-226e-4420-84c3-e11c926df475", + "IdentifiedObject.name": "OpLimI_38.97114317029974_51.96152422706632_Emerg", + "CurrentLimit.value": 51.96152422706632, + "CurrentLimit.normalValue": 38.97114317029974, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'absoluteValueType_86400.0s'" + } + ] + }, + "OpLimI_400.0_600.0": { + "Ravens.CimObjectType": "OperationalLimitSet", + "IdentifiedObject.mRID": "f59e344b-c2c5-4465-8584-11feeefaec83", + "IdentifiedObject.name": "OpLimI_400.0_600.0", + "OperationalLimitSet.OperationalLimitValue": [ + { + "Ravens.CimObjectType": "CurrentLimit", + "IdentifiedObject.mRID": "e2876119-1166-41b7-82b2-55c3af3724ff", + "IdentifiedObject.name": "OpLimI_400.0_600.0_Emerg", + "CurrentLimit.value": 600.0, + "CurrentLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'absoluteValueType_86400.0s'" + }, + { + "Ravens.CimObjectType": "CurrentLimit", + "IdentifiedObject.mRID": "318af2aa-38b8-4073-915d-cba9e3c02b3c", + "IdentifiedObject.name": "OpLimI_400.0_600.0_Norm", + "CurrentLimit.value": 400.0, + "CurrentLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'absoluteValueType_5000000000.0s'" + } + ] + }, + "OpLimV_380.0-420.00000000000006": { + "Ravens.CimObjectType": "OperationalLimitSet", + "IdentifiedObject.mRID": "ebe9634e-a35b-4086-be5a-3784f598c20a", + "IdentifiedObject.name": "OpLimV_380.0-420.00000000000006", + "OperationalLimitSet.OperationalLimitValue": [ + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "d0fb9602-f090-467f-bdcc-594f7ea61c64", + "IdentifiedObject.name": "OpLimV_380.0-420.00000000000006_RangeAhigh", + "VoltageLimit.value": 420.00000000000006, + "VoltageLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'highType_5000000000.0s'" + }, + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "6f5f1408-a98b-47cc-afa7-117e80e51771", + "IdentifiedObject.name": "OpLimV_380.0-420.00000000000006_RangeAlow", + "VoltageLimit.value": 380.0, + "VoltageLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'lowType_5000000000.0s'" + } + ] + } + }, + "Location": { + "primary_Location": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "37309db4-0940-411e-857a-93153c0359a2", + "IdentifiedObject.name": "primary_Location", + "Location.PositionPoints": [ + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 1, + "PositionPoint.xPosition": 0.0, + "PositionPoint.yPosition": 0.0 + } + ] + }, + "loadbus_Location": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "f570a5d2-6a61-4776-959e-f4a8f19b1706", + "IdentifiedObject.name": "loadbus_Location", + "Location.PositionPoints": [ + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 1, + "PositionPoint.xPosition": 0.0, + "PositionPoint.yPosition": 0.0 + } + ] + }, + "sourcebus_Location": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "758373e1-f065-4503-af46-6f89b548922c", + "IdentifiedObject.name": "sourcebus_Location", + "Location.PositionPoints": [ + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 1, + "PositionPoint.xPosition": 0.0, + "PositionPoint.yPosition": 0.0 + } + ] + } + }, + "EnergyConnectionProfile": { + "Ravens.CimObjectType": "EnergyConnectionProfile", + "IdentifiedObject.mRID": "d4723d5b-add9-49b0-88a1-d8e47ebbde66", + "IdentifiedObject.name": "Load::::::defaultload", + "EnergyConnectionProfile.dssSpectrum": "defaultload" + }, + "Versions": { + "IEC61970CIMVersion": { + "Ravens.CimObjectType": "IEC61970CIMVersion", + "IEC61970CIMVersion.version": "IEC61970CIM100", + "IEC61970CIMVersion.date": "2019-04-01" + } + }, + "OperationalLimitType": { + "absoluteValueType_5000000000.0s": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "9c0ee368-c6f1-4ace-afeb-4e760aecba46", + "IdentifiedObject.name": "absoluteValueType_5000000000.0s", + "OperationalLimitType.direction": "OperationalLimitDirectionKind.absoluteValue", + "OperationalLimitType.acceptableDuration": 5000000000.0 + }, + "highType_5000000000.0s": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "05706366-f802-478e-91d6-f5aafaa14e04", + "IdentifiedObject.name": "highType_5000000000.0s", + "OperationalLimitType.direction": "OperationalLimitDirectionKind.high", + "OperationalLimitType.acceptableDuration": 5000000000.0 + }, + "absoluteValueType_86400.0s": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "34e53b7e-0543-4ac6-8d1d-fa971d98b53f", + "IdentifiedObject.name": "absoluteValueType_86400.0s", + "OperationalLimitType.direction": "OperationalLimitDirectionKind.absoluteValue", + "OperationalLimitType.acceptableDuration": 86400.0 + }, + "lowType_5000000000.0s": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "473b0218-b900-4e00-9e93-8e8adc1767d2", + "IdentifiedObject.name": "lowType_5000000000.0s", + "OperationalLimitType.direction": "OperationalLimitDirectionKind.low", + "OperationalLimitType.acceptableDuration": 5000000000.0 + } + }, + "ConnectivityNode": { + "primary": { + "Ravens.CimObjectType": "ConnectivityNode", + "IdentifiedObject.mRID": "88e0ace1-46b4-491a-a521-bac23f64b8c0", + "IdentifiedObject.name": "primary" + }, + "sourcebus": { + "Ravens.CimObjectType": "ConnectivityNode", + "IdentifiedObject.mRID": "b4d268bc-7862-4be1-a540-71dcf3feeb4e", + "IdentifiedObject.name": "sourcebus" + }, + "loadbus": { + "Ravens.CimObjectType": "ConnectivityNode", + "IdentifiedObject.mRID": "a8274412-8b0f-4bb3-a8d8-1db65e3a3685", + "IdentifiedObject.name": "loadbus", + "ConnectivityNode.OperationalLimitSet": "OperationalLimitSet::'OpLimV_380.0-420.00000000000006'" + } + }, + "BaseVoltage": { + "BaseV_0.4": { + "Ravens.CimObjectType": "BaseVoltage", + "IdentifiedObject.mRID": "5c7d64a6-5188-43a6-bf1a-1740452091ef", + "IdentifiedObject.name": "BaseV_0.4", + "BaseVoltage.nominalVoltage": 400.0 + } + }, + "LoadResponseCharacteristic": { + "Constant kVA": { + "Ravens.CimObjectType": "LoadResponseCharacteristic", + "IdentifiedObject.mRID": "0d3ba428-f9a0-40ad-953a-52a09911bc60", + "IdentifiedObject.name": "Constant kVA", + "LoadResponseCharacteristic.pConstantPower": 100, + "LoadResponseCharacteristic.qConstantPower": 100 + } + } +} diff --git a/test/data/ravens/ravens_case3_withgens.json b/test/data/ravens/ravens_case3_withgens.json new file mode 100644 index 000000000..ecc5fac68 --- /dev/null +++ b/test/data/ravens/ravens_case3_withgens.json @@ -0,0 +1,606 @@ +{ + "PerLengthLineParameter": { + "PerLengthImpedance": { + "PerLengthPhaseImpedance": { + "4/0quad": { + "Ravens.CimObjectType": "PerLengthPhaseImpedance", + "IdentifiedObject.mRID": "88bc7e59-e9ce-4600-a949-3e2cecbc2fda", + "IdentifiedObject.name": "4/0quad", + "PerLengthPhaseImpedance.conductorCount": 3, + "PerLengthPhaseImpedance.PhaseImpedanceData": [ + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 2, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.0467, + "PhaseImpedanceData.x": 0.0267, + "PhaseImpedanceData.b": -0.0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 1, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.1167, + "PhaseImpedanceData.x": 0.0667, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 2, + "PhaseImpedanceData.r": 0.0467, + "PhaseImpedanceData.x": 0.0267, + "PhaseImpedanceData.b": -0.0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 3, + "PhaseImpedanceData.r": 0.1167, + "PhaseImpedanceData.x": 0.0667, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 2, + "PhaseImpedanceData.column": 2, + "PhaseImpedanceData.r": 0.1167, + "PhaseImpedanceData.x": 0.0667, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.0467, + "PhaseImpedanceData.x": 0.0267, + "PhaseImpedanceData.b": -0.0 + } + ] + }, + "556mcm": { + "Ravens.CimObjectType": "PerLengthPhaseImpedance", + "IdentifiedObject.mRID": "d6879f7a-124f-4e82-987a-46f5ba3e2f9d", + "IdentifiedObject.name": "556mcm", + "PerLengthPhaseImpedance.conductorCount": 3, + "PerLengthPhaseImpedance.PhaseImpedanceData": [ + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 3, + "PhaseImpedanceData.r": 0.1, + "PhaseImpedanceData.x": 0.0583, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.04, + "PhaseImpedanceData.x": 0.0233, + "PhaseImpedanceData.b": -0.0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 2, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.04, + "PhaseImpedanceData.x": 0.0233, + "PhaseImpedanceData.b": -0.0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 2, + "PhaseImpedanceData.column": 2, + "PhaseImpedanceData.r": 0.1, + "PhaseImpedanceData.x": 0.0583, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 1, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.1, + "PhaseImpedanceData.x": 0.0583, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 2, + "PhaseImpedanceData.r": 0.04, + "PhaseImpedanceData.x": 0.0233, + "PhaseImpedanceData.b": -0.0 + } + ] + } + } + } + }, + "PowerSystemResource": { + "Equipment": { + "ConductingEquipment": { + "EnergyConnection": { + "RegulatingCondEq": { + "RotatingMachine": { + "gen2": { + "Ravens.CimObjectType": "SynchronousMachine", + "IdentifiedObject.mRID": "c657d8a1-32c2-402f-8403-9b06c112318a", + "IdentifiedObject.name": "gen2", + "RotatingMachine.p": 1000.0, + "RotatingMachine.q": 484.3221048378525, + "RotatingMachine.ratedS": 1200.0, + "RotatingMachine.ratedU": 461.88021535170066, + "Equipment.inService": "true", + "RotatingMachine.ratedPowerFactor": 0.9, + "GeneratingUnit.minOperatingP": 0.0, + "GeneratingUnit.maxOperatingP": 1080.0, + "SynchronousMachine.maxQ": 523.0678732248807, + "SynchronousMachine.minQ": -523.0678732248807, + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "012eb2d2-f4d8-4cc9-825f-b634c66e5d84", + "IdentifiedObject.name": "gen2_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'primary'" + } + ] + }, + "gen1": { + "Ravens.CimObjectType": "SynchronousMachine", + "IdentifiedObject.mRID": "3f2267a8-4f0c-4ac5-9415-8568d7d414b2", + "IdentifiedObject.name": "gen1", + "RotatingMachine.p": 2000.0, + "RotatingMachine.q": 968.644209675705, + "RotatingMachine.ratedS": 2400.0, + "RotatingMachine.ratedU": 461.88021535170066, + "Equipment.inService": "true", + "RotatingMachine.ratedPowerFactor": 0.9, + "GeneratingUnit.minOperatingP": 0.0, + "GeneratingUnit.maxOperatingP": 2160.0, + "SynchronousMachine.maxQ": 1046.1357464497614, + "SynchronousMachine.minQ": -1046.1357464497614, + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "20cd756e-faae-47d9-a177-b605e6ae55fb", + "IdentifiedObject.name": "gen1_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ] + } + } + }, + "EnergySource": { + "source": { + "Ravens.CimObjectType": "EnergySource", + "IdentifiedObject.mRID": "494c011a-7640-4ed7-a3d5-2cd1a55413c0", + "IdentifiedObject.name": "source", + "EnergySource.nominalVoltage": 400.0, + "EnergySource.voltageMagnitude": 398.36, + "EnergySource.voltageAngle": 0.0, + "EnergySource.r": 3.880570000581328e-08, + "EnergySource.x": 1.5522280002325312e-07, + "EnergySource.r0": 5.069596039676399e-08, + "EnergySource.x0": 1.5208788119029196e-07, + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "327a6ba6-06c2-40ff-a0cc-550dd50d824d", + "IdentifiedObject.name": "source_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'sourcebus'" + } + ] + } + }, + "EnergyConsumer": { + "l2": { + "Ravens.CimObjectType": "EnergyConsumer", + "IdentifiedObject.mRID": "f227af26-b8ae-47b3-97cc-4d1e5d6bbfd3", + "IdentifiedObject.name": "l2", + "EnergyConsumer.p": 6000.0, + "EnergyConsumer.q": 3000.0, + "EnergyConsumer.customerCount": 1, + "EnergyConsumer.grounded": "true", + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "EnergyConsumer.phaseConnection": "PhaseShuntConnectionKind.Y", + "EnergyConsumer.LoadResponseCharacteristic": "LoadResponseCharacteristic::'Constant kVA'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "9f8d612e-85f8-4757-9ff8-f9ae5947ddd8", + "IdentifiedObject.name": "l2_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.B", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ], + "EnergyConsumer.EnergyConsumerPhase": [ + { + "Ravens.CimObjectType": "EnergyConsumerPhase", + "IdentifiedObject.mRID": "f3cd189c-bd31-4fd4-beed-8967142aa0ea", + "IdentifiedObject.name": "l2_B", + "EnergyConsumerPhase.p": 6000.0, + "EnergyConsumerPhase.q": 3000.0, + "EnergyConsumerPhase.phase": "SinglePhaseKind.B" + } + ] + }, + "l1": { + "Ravens.CimObjectType": "EnergyConsumer", + "IdentifiedObject.mRID": "8bff0407-deee-4f99-92fa-1dee4047621e", + "IdentifiedObject.name": "l1", + "EnergyConsumer.p": 6000.0, + "EnergyConsumer.q": 3000.0, + "EnergyConsumer.customerCount": 1, + "EnergyConsumer.grounded": "true", + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "EnergyConsumer.phaseConnection": "PhaseShuntConnectionKind.Y", + "EnergyConsumer.LoadResponseCharacteristic": "LoadResponseCharacteristic::'Constant kVA'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "4c93404d-1381-4fb2-b2db-36da5d6a0583", + "IdentifiedObject.name": "l1_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.A", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ], + "EnergyConsumer.EnergyConsumerPhase": [ + { + "Ravens.CimObjectType": "EnergyConsumerPhase", + "IdentifiedObject.mRID": "d4f8dc3a-8a95-4361-968a-1d841de4d7d1", + "IdentifiedObject.name": "l1_A", + "EnergyConsumerPhase.p": 6000.0, + "EnergyConsumerPhase.q": 3000.0, + "EnergyConsumerPhase.phase": "SinglePhaseKind.A" + } + ] + }, + "l3": { + "Ravens.CimObjectType": "EnergyConsumer", + "IdentifiedObject.mRID": "f8e9430c-56a5-44c3-8b53-98464182dec3", + "IdentifiedObject.name": "l3", + "EnergyConsumer.p": 6000.0, + "EnergyConsumer.q": 3000.0, + "EnergyConsumer.customerCount": 1, + "EnergyConsumer.grounded": "true", + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "EnergyConsumer.phaseConnection": "PhaseShuntConnectionKind.Y", + "EnergyConsumer.LoadResponseCharacteristic": "LoadResponseCharacteristic::'Constant kVA'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "ec5de9d0-8f3a-409c-afaa-5dd15969842f", + "IdentifiedObject.name": "l3_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.C", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ], + "EnergyConsumer.EnergyConsumerPhase": [ + { + "Ravens.CimObjectType": "EnergyConsumerPhase", + "IdentifiedObject.mRID": "cdb85d03-72cd-4c1a-aa27-ee985895d65c", + "IdentifiedObject.name": "l3_C", + "EnergyConsumerPhase.p": 6000.0, + "EnergyConsumerPhase.q": 3000.0, + "EnergyConsumerPhase.phase": "SinglePhaseKind.C" + } + ] + } + } + }, + "Conductor": { + "ACLineSegment": { + "ohline": { + "Ravens.CimObjectType": "ACLineSegment", + "IdentifiedObject.mRID": "357e3f68-a996-4ef9-8e29-5a9701da50f5", + "IdentifiedObject.name": "ohline", + "Conductor.length": 1.0, + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "ACLineSegment.PerLengthImpedance": "PerLengthPhaseImpedance::'556mcm'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "262a28c0-79c8-46f8-be2f-48baba94b09b", + "IdentifiedObject.name": "ohline_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'sourcebus'" + }, + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "20c1e2b3-faab-4f16-9d28-1438cf5adc31", + "IdentifiedObject.name": "ohline_T2", + "ACDCTerminal.sequenceNumber": 2, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'primary'" + } + ], + "ACLineSegment.ACLineSegmentPhase": [ + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "43a9f788-638f-48c5-9211-437795fad9da", + "IdentifiedObject.name": "ohline_A", + "ACLineSegmentPhase.phase": "SinglePhaseKind.A", + "ACLineSegmentPhase.sequenceNumber": 1 + }, + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "939db8dd-1631-44e8-aa9d-cb391f06136d", + "IdentifiedObject.name": "ohline_B", + "ACLineSegmentPhase.phase": "SinglePhaseKind.B", + "ACLineSegmentPhase.sequenceNumber": 2 + }, + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "8a764636-52d0-470f-abcd-9cee75f114de", + "IdentifiedObject.name": "ohline_C", + "ACLineSegmentPhase.phase": "SinglePhaseKind.C", + "ACLineSegmentPhase.sequenceNumber": 3 + } + ] + }, + "quad": { + "Ravens.CimObjectType": "ACLineSegment", + "IdentifiedObject.mRID": "b0c876f2-8724-4b1d-9bb8-16ad6dc08866", + "IdentifiedObject.name": "quad", + "Conductor.length": 1.0, + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "ACLineSegment.PerLengthImpedance": "PerLengthPhaseImpedance::'4/0quad'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "fba92277-7b25-42e3-8782-10e01ebf3ccf", + "IdentifiedObject.name": "quad_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'primary'" + }, + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "7a7bd627-5599-4139-bd71-a659a313fafc", + "IdentifiedObject.name": "quad_T2", + "ACDCTerminal.sequenceNumber": 2, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ], + "ACLineSegment.ACLineSegmentPhase": [ + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "06ccbe19-290d-4808-8edb-40afc7e7c41e", + "IdentifiedObject.name": "quad_A", + "ACLineSegmentPhase.phase": "SinglePhaseKind.A", + "ACLineSegmentPhase.sequenceNumber": 1 + }, + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "79df9209-3379-4ce7-bd5b-2f927daccd8a", + "IdentifiedObject.name": "quad_B", + "ACLineSegmentPhase.phase": "SinglePhaseKind.B", + "ACLineSegmentPhase.sequenceNumber": 2 + }, + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "27dfc4e3-829a-4c4a-abb2-dab081e599c7", + "IdentifiedObject.name": "quad_C", + "ACLineSegmentPhase.phase": "SinglePhaseKind.C", + "ACLineSegmentPhase.sequenceNumber": 3 + } + ] + } + } + } + } + } + }, + "EnergyConnectionProfile": { + "Ravens.CimObjectType": "EnergyConnectionProfile", + "IdentifiedObject.mRID": "b1c858fa-9961-4915-ac2b-6c40546f4e55", + "IdentifiedObject.name": "Load::::::defaultload", + "EnergyConnectionProfile.dssSpectrum": "defaultload" + }, + "OperationalLimitSet": { + "OpLimV_360.00000000000006-440.00000000000006": { + "Ravens.CimObjectType": "OperationalLimitSet", + "IdentifiedObject.mRID": "1fd3801e-4bc9-4995-a833-b8a934a51856", + "IdentifiedObject.name": "OpLimV_360.00000000000006-440.00000000000006", + "OperationalLimitSet.OperationalLimitValue": [ + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "e2cbc64e-5a29-4df5-b214-f9ed9aa5cb5d", + "IdentifiedObject.name": "OpLimV_360.00000000000006-440.00000000000006_RangeAlow", + "VoltageLimit.value": 360.00000000000006, + "VoltageLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'lowType_5000000000.0s'" + }, + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "27d3baf8-3d5e-4465-9e84-3e52708211f1", + "IdentifiedObject.name": "OpLimV_360.00000000000006-440.00000000000006_RangeAhigh", + "VoltageLimit.value": 440.00000000000006, + "VoltageLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'highType_5000000000.0s'" + } + ] + }, + "OpLimV_380.0-420.00000000000006": { + "Ravens.CimObjectType": "OperationalLimitSet", + "IdentifiedObject.mRID": "35e30ea0-641e-43b7-a1e4-0e15e42334e1", + "IdentifiedObject.name": "OpLimV_380.0-420.00000000000006", + "OperationalLimitSet.OperationalLimitValue": [ + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "cce047bb-3dc5-4f08-85ae-401c93562f34", + "IdentifiedObject.name": "OpLimV_380.0-420.00000000000006_RangeAhigh", + "VoltageLimit.value": 420.00000000000006, + "VoltageLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'highType_5000000000.0s'" + }, + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "88c7ce0d-859b-4dda-bb25-64d33ba36831", + "IdentifiedObject.name": "OpLimV_380.0-420.00000000000006_RangeAlow", + "VoltageLimit.value": 380.0, + "VoltageLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'lowType_5000000000.0s'" + } + ] + }, + "OpLimI_400.0_600.0": { + "Ravens.CimObjectType": "OperationalLimitSet", + "IdentifiedObject.mRID": "47ba5a2e-b0e0-469d-b456-b74d90a89598", + "IdentifiedObject.name": "OpLimI_400.0_600.0", + "OperationalLimitSet.OperationalLimitValue": [ + { + "Ravens.CimObjectType": "CurrentLimit", + "IdentifiedObject.mRID": "ce6d7dcd-e426-44cb-ab33-9e8a6de1b60f", + "IdentifiedObject.name": "OpLimI_400.0_600.0_Emerg", + "CurrentLimit.value": 600.0, + "CurrentLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'absoluteValueType_86400.0s'" + }, + { + "Ravens.CimObjectType": "CurrentLimit", + "IdentifiedObject.mRID": "a301065e-a50e-4dd7-856b-c7035e9ea52f", + "IdentifiedObject.name": "OpLimI_400.0_600.0_Norm", + "CurrentLimit.value": 400.0, + "CurrentLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'absoluteValueType_5000000000.0s'" + } + ] + } + }, + "Location": { + "primary_Location": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "db2f0d86-da66-46ac-adc1-6eec717cf555", + "IdentifiedObject.name": "primary_Location", + "Location.PositionPoints": [ + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 1, + "PositionPoint.xPosition": 0.0, + "PositionPoint.yPosition": 0.0 + } + ] + }, + "loadbus_Location": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "76056310-0c84-49e6-9d92-c0a3cce574e4", + "IdentifiedObject.name": "loadbus_Location", + "Location.PositionPoints": [ + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 1, + "PositionPoint.xPosition": 0.0, + "PositionPoint.yPosition": 0.0 + } + ] + }, + "sourcebus_Location": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "4c73c3dd-7250-4f6a-af69-d203960b0a34", + "IdentifiedObject.name": "sourcebus_Location", + "Location.PositionPoints": [ + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 1, + "PositionPoint.xPosition": 0.0, + "PositionPoint.yPosition": 0.0 + } + ] + } + }, + "Versions": { + "IEC61970CIMVersion": { + "Ravens.CimObjectType": "IEC61970CIMVersion", + "IEC61970CIMVersion.version": "IEC61970CIM100", + "IEC61970CIMVersion.date": "2019-04-01" + } + }, + "ConnectivityNode": { + "loadbus": { + "Ravens.CimObjectType": "ConnectivityNode", + "IdentifiedObject.mRID": "4ac8da05-a223-4bf6-b372-12c9479c495a", + "IdentifiedObject.name": "loadbus", + "ConnectivityNode.OperationalLimitSet": "OperationalLimitSet::'OpLimV_360.00000000000006-440.00000000000006'" + }, + "primary": { + "Ravens.CimObjectType": "ConnectivityNode", + "IdentifiedObject.mRID": "3e877b8a-ef33-4e18-8c80-1b05050bfc40", + "IdentifiedObject.name": "primary", + "ConnectivityNode.OperationalLimitSet": "OperationalLimitSet::'OpLimV_360.00000000000006-440.00000000000006'" + }, + "sourcebus": { + "Ravens.CimObjectType": "ConnectivityNode", + "IdentifiedObject.mRID": "d192d550-1fc0-489f-8e47-72209fa989e7", + "IdentifiedObject.name": "sourcebus" + } + }, + "OperationalLimitType": { + "absoluteValueType_86400.0s": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "d60da1eb-6a60-41ba-99df-7313cad312fa", + "IdentifiedObject.name": "absoluteValueType_86400.0s", + "OperationalLimitType.direction": "OperationalLimitDirectionKind.absoluteValue", + "OperationalLimitType.acceptableDuration": 86400.0 + }, + "highType_5000000000.0s": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "a1a82ad0-e426-4ecb-816a-5a58f034756b", + "IdentifiedObject.name": "highType_5000000000.0s", + "OperationalLimitType.direction": "OperationalLimitDirectionKind.high", + "OperationalLimitType.acceptableDuration": 5000000000.0 + }, + "lowType_5000000000.0s": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "1eaf0044-6272-4146-bf43-5c5310023469", + "IdentifiedObject.name": "lowType_5000000000.0s", + "OperationalLimitType.direction": "OperationalLimitDirectionKind.low", + "OperationalLimitType.acceptableDuration": 5000000000.0 + }, + "absoluteValueType_5000000000.0s": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "1a39544c-2df7-46a9-a6c0-cfb28ab6eaab", + "IdentifiedObject.name": "absoluteValueType_5000000000.0s", + "OperationalLimitType.direction": "OperationalLimitDirectionKind.absoluteValue", + "OperationalLimitType.acceptableDuration": 5000000000.0 + } + }, + "LoadResponseCharacteristic": { + "Constant kVA": { + "Ravens.CimObjectType": "LoadResponseCharacteristic", + "IdentifiedObject.mRID": "777f5c7c-dea1-4a88-8db0-e5bd71a2fd4b", + "IdentifiedObject.name": "Constant kVA", + "LoadResponseCharacteristic.pConstantPower": 100, + "LoadResponseCharacteristic.qConstantPower": 100 + } + }, + "BaseVoltage": { + "BaseV_0.4": { + "Ravens.CimObjectType": "BaseVoltage", + "IdentifiedObject.mRID": "93c27318-44cd-41b7-a873-f9001d1b831f", + "IdentifiedObject.name": "BaseV_0.4", + "BaseVoltage.nominalVoltage": 400.0 + } + } +} \ No newline at end of file diff --git a/test/data/ravens/ravens_case3_withpvandstorage.json b/test/data/ravens/ravens_case3_withpvandstorage.json new file mode 100644 index 000000000..73b959d88 --- /dev/null +++ b/test/data/ravens/ravens_case3_withpvandstorage.json @@ -0,0 +1,621 @@ +{ + "OperationalLimitSet": { + "OpLimI_400.0_600.0": { + "Ravens.CimObjectType": "OperationalLimitSet", + "IdentifiedObject.mRID": "1e3d77af-8a23-466a-bdd9-39cee9f9fe92", + "IdentifiedObject.name": "OpLimI_400.0_600.0", + "OperationalLimitSet.OperationalLimitValue": [ + { + "Ravens.CimObjectType": "CurrentLimit", + "IdentifiedObject.mRID": "fc496404-0ea3-49ad-a418-fb8b10aa2724", + "IdentifiedObject.name": "OpLimI_400.0_600.0_Emerg", + "CurrentLimit.value": 600.0, + "CurrentLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'absoluteValueType_86400.0s'" + }, + { + "Ravens.CimObjectType": "CurrentLimit", + "IdentifiedObject.mRID": "33f3b868-cb9b-4223-b83c-e050cd47a7d0", + "IdentifiedObject.name": "OpLimI_400.0_600.0_Norm", + "CurrentLimit.value": 400.0, + "CurrentLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'absoluteValueType_5000000000.0s'" + } + ] + }, + "OpLimV_360.00000000000006-440.00000000000006": { + "Ravens.CimObjectType": "OperationalLimitSet", + "IdentifiedObject.mRID": "514c489d-6957-4739-bb9d-ff5da50e8f4e", + "IdentifiedObject.name": "OpLimV_360.00000000000006-440.00000000000006", + "OperationalLimitSet.OperationalLimitValue": [ + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "513ecee1-8a86-4ced-b436-e4def25953cc", + "IdentifiedObject.name": "OpLimV_360.00000000000006-440.00000000000006_RangeAhigh", + "VoltageLimit.value": 440.00000000000006, + "VoltageLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'highType_5000000000.0s'" + }, + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "e22b44ed-3b12-4bf9-8be3-a591a3cf732b", + "IdentifiedObject.name": "OpLimV_360.00000000000006-440.00000000000006_RangeAlow", + "VoltageLimit.value": 360.00000000000006, + "VoltageLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'lowType_5000000000.0s'" + } + ] + }, + "OpLimV_380.0-420.00000000000006": { + "Ravens.CimObjectType": "OperationalLimitSet", + "IdentifiedObject.mRID": "5c5e7910-bdea-408b-9cba-c96967e39939", + "IdentifiedObject.name": "OpLimV_380.0-420.00000000000006", + "OperationalLimitSet.OperationalLimitValue": [ + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "5f98e299-22cb-48a5-acd0-ba5404111eed", + "IdentifiedObject.name": "OpLimV_380.0-420.00000000000006_RangeAlow", + "VoltageLimit.value": 380.0, + "VoltageLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'lowType_5000000000.0s'" + }, + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "43fb3ee9-3b9a-4a7b-ace5-5ddcac6d59d5", + "IdentifiedObject.name": "OpLimV_380.0-420.00000000000006_RangeAhigh", + "VoltageLimit.value": 420.00000000000006, + "VoltageLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'highType_5000000000.0s'" + } + ] + } + }, + "PowerSystemResource": { + "Equipment": { + "ConductingEquipment": { + "Conductor": { + "ACLineSegment": { + "ohline": { + "Ravens.CimObjectType": "ACLineSegment", + "IdentifiedObject.mRID": "e9c718d0-d75c-41cf-b31e-5d1467780362", + "IdentifiedObject.name": "ohline", + "Conductor.length": 1.0, + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "ACLineSegment.PerLengthImpedance": "PerLengthPhaseImpedance::'556mcm'", + "ACLineSegment.ACLineSegmentPhase": [ + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "350fed0a-7395-4736-aa12-ac2d7e87ac92", + "IdentifiedObject.name": "ohline_A", + "ACLineSegmentPhase.phase": "SinglePhaseKind.A", + "ACLineSegmentPhase.sequenceNumber": 1 + }, + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "3b5406ff-4fb5-4a30-8e2c-4f09db60a544", + "IdentifiedObject.name": "ohline_B", + "ACLineSegmentPhase.phase": "SinglePhaseKind.B", + "ACLineSegmentPhase.sequenceNumber": 2 + }, + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "8d10892c-1893-4a48-8f5b-615fcb4c0d55", + "IdentifiedObject.name": "ohline_C", + "ACLineSegmentPhase.phase": "SinglePhaseKind.C", + "ACLineSegmentPhase.sequenceNumber": 3 + } + ], + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "37415ad4-1071-481c-b741-06e6b8ca05d4", + "IdentifiedObject.name": "ohline_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'sourcebus'" + }, + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "3bd4d2fc-d02b-4238-9630-83fe0b294662", + "IdentifiedObject.name": "ohline_T2", + "ACDCTerminal.sequenceNumber": 2, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'primary'" + } + ] + }, + "quad": { + "Ravens.CimObjectType": "ACLineSegment", + "IdentifiedObject.mRID": "edba552d-daee-40f3-9488-336f9c9231dc", + "IdentifiedObject.name": "quad", + "Conductor.length": 1.0, + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "ACLineSegment.PerLengthImpedance": "PerLengthPhaseImpedance::'4/0quad'", + "ACLineSegment.ACLineSegmentPhase": [ + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "c087897c-8221-477a-b33b-59ed2ff423c7", + "IdentifiedObject.name": "quad_A", + "ACLineSegmentPhase.phase": "SinglePhaseKind.A", + "ACLineSegmentPhase.sequenceNumber": 1 + }, + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "57c71971-b70b-49a2-868b-a64aceb3b031", + "IdentifiedObject.name": "quad_B", + "ACLineSegmentPhase.phase": "SinglePhaseKind.B", + "ACLineSegmentPhase.sequenceNumber": 2 + }, + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "732aea91-11c1-4dcb-a9ed-45de010dde2f", + "IdentifiedObject.name": "quad_C", + "ACLineSegmentPhase.phase": "SinglePhaseKind.C", + "ACLineSegmentPhase.sequenceNumber": 3 + } + ], + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "82cce1dc-5fc1-4a98-9f53-2b347ed1d3b5", + "IdentifiedObject.name": "quad_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'primary'" + }, + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "f0e02033-fa13-4ac4-b6cf-0e0444d72d18", + "IdentifiedObject.name": "quad_T2", + "ACDCTerminal.sequenceNumber": 2, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ] + } + } + }, + "EnergyConnection": { + "EnergyConsumer": { + "l2": { + "Ravens.CimObjectType": "EnergyConsumer", + "IdentifiedObject.mRID": "09b604b2-00d7-4a4e-994d-2f189ee9642b", + "IdentifiedObject.name": "l2", + "EnergyConsumer.p": 6000.0, + "EnergyConsumer.q": 3000.0, + "EnergyConsumer.customerCount": 1, + "EnergyConsumer.grounded": "true", + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "EnergyConsumer.phaseConnection": "PhaseShuntConnectionKind.Y", + "EnergyConsumer.LoadResponseCharacteristic": "LoadResponseCharacteristic::'Constant kVA'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "9b397420-cdcf-4127-85ae-73559a000953", + "IdentifiedObject.name": "l2_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.B", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ], + "EnergyConsumer.EnergyConsumerPhase": [ + { + "Ravens.CimObjectType": "EnergyConsumerPhase", + "IdentifiedObject.mRID": "03858c77-6453-407c-8119-da6a76508b59", + "IdentifiedObject.name": "l2_B", + "EnergyConsumerPhase.p": 6000.0, + "EnergyConsumerPhase.q": 3000.0, + "EnergyConsumerPhase.phase": "SinglePhaseKind.B" + } + ] + }, + "l3": { + "Ravens.CimObjectType": "EnergyConsumer", + "IdentifiedObject.mRID": "f9667c10-e77a-4409-8099-072bfdce24e0", + "IdentifiedObject.name": "l3", + "EnergyConsumer.p": 6000.0, + "EnergyConsumer.q": 3000.0, + "EnergyConsumer.customerCount": 1, + "EnergyConsumer.grounded": "true", + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "EnergyConsumer.phaseConnection": "PhaseShuntConnectionKind.Y", + "EnergyConsumer.LoadResponseCharacteristic": "LoadResponseCharacteristic::'Constant kVA'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "18771bf2-42eb-4758-a101-0a92cb9508e5", + "IdentifiedObject.name": "l3_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.C", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ], + "EnergyConsumer.EnergyConsumerPhase": [ + { + "Ravens.CimObjectType": "EnergyConsumerPhase", + "IdentifiedObject.mRID": "dbfde1f4-2422-4e65-933b-7b9d43a22cc7", + "IdentifiedObject.name": "l3_C", + "EnergyConsumerPhase.p": 6000.0, + "EnergyConsumerPhase.q": 3000.0, + "EnergyConsumerPhase.phase": "SinglePhaseKind.C" + } + ] + }, + "l1": { + "Ravens.CimObjectType": "EnergyConsumer", + "IdentifiedObject.mRID": "089386b2-ecab-4d6f-ab32-12c2c5527ee5", + "IdentifiedObject.name": "l1", + "EnergyConsumer.p": 6000.0, + "EnergyConsumer.q": 3000.0, + "EnergyConsumer.customerCount": 1, + "EnergyConsumer.grounded": "true", + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "EnergyConsumer.phaseConnection": "PhaseShuntConnectionKind.Y", + "EnergyConsumer.LoadResponseCharacteristic": "LoadResponseCharacteristic::'Constant kVA'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "8db69196-5be7-4038-a656-c345313d6dcc", + "IdentifiedObject.name": "l1_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.A", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ], + "EnergyConsumer.EnergyConsumerPhase": [ + { + "Ravens.CimObjectType": "EnergyConsumerPhase", + "IdentifiedObject.mRID": "445afb26-9fca-40ff-9161-1fae6c0c1619", + "IdentifiedObject.name": "l1_A", + "EnergyConsumerPhase.p": 6000.0, + "EnergyConsumerPhase.q": 3000.0, + "EnergyConsumerPhase.phase": "SinglePhaseKind.A" + } + ] + } + }, + "EnergySource": { + "source": { + "Ravens.CimObjectType": "EnergySource", + "IdentifiedObject.mRID": "5181f211-4f84-4220-905d-ce5a2136c86b", + "IdentifiedObject.name": "source", + "EnergySource.nominalVoltage": 400.0, + "EnergySource.voltageMagnitude": 398.36, + "EnergySource.voltageAngle": 0.0, + "EnergySource.r": 3.880570000581328e-08, + "EnergySource.x": 1.5522280002325312e-07, + "EnergySource.r0": 5.069596039676399e-08, + "EnergySource.x0": 1.5208788119029196e-07, + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "f67ae006-bbc4-408b-90bc-ac62d33ce9d5", + "IdentifiedObject.name": "source_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'sourcebus'" + } + ] + } + }, + "RegulatingCondEq": { + "PowerElectronicsConnection": { + "pv1": { + "Ravens.CimObjectType": "PowerElectronicsConnection", + "IdentifiedObject.mRID": "997cec18-9472-4c89-8fb7-6e7d8ca4d377", + "IdentifiedObject.name": "pv1", + "PowerElectronicsConnection.maxIFault": 1.1111111111111112, + "PowerElectronicsConnection.p": 9999.997590992734, + "PowerElectronicsConnection.q": -0.0016831415801767946, + "PowerElectronicsConnection.ratedS": 10000.0, + "PowerElectronicsConnection.ratedU": 400.0, + "PowerElectronicsConnection.maxQ": 10000.0, + "PowerElectronicsConnection.minQ": -10000.0, + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "a1d1a18a-5c36-4804-8fc0-13f756823d19", + "IdentifiedObject.name": "pv1_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ], + "PowerElectronicsConnection.PowerElectronicsUnit": { + "Ravens.CimObjectType": "PhotoVoltaicUnit", + "IdentifiedObject.mRID": "24872726-129e-491f-83cc-74135a8432b4", + "IdentifiedObject.name": "pv1_PVPanels", + "PowerElectronicsUnit.minP": 2000.0, + "PowerElectronicsUnit.maxP": 500000.0 + } + }, + "s1": { + "Ravens.CimObjectType": "PowerElectronicsConnection", + "IdentifiedObject.mRID": "cb0d7d2e-e799-4aaf-bb04-5daf2bfb9a00", + "IdentifiedObject.name": "s1", + "PowerElectronicsConnection.maxIFault": 1.1111111111111112, + "PowerElectronicsConnection.p": -0.0, + "PowerElectronicsConnection.q": -0.0, + "PowerElectronicsConnection.ratedS": 60000.0, + "PowerElectronicsConnection.ratedU": 400.0, + "PowerElectronicsConnection.maxQ": 25000.0, + "PowerElectronicsConnection.minQ": -25000.0, + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "6f75e791-02dc-496f-8117-106bef0e0700", + "IdentifiedObject.name": "s1_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ], + "PowerElectronicsConnection.PowerElectronicsUnit": { + "Ravens.CimObjectType": "BatteryUnit", + "IdentifiedObject.mRID": "09908453-5eb9-4927-817a-0dd0a84e0f95", + "IdentifiedObject.name": "s1_Cells", + "PowerElectronicsUnit.minP": -60000.0, + "PowerElectronicsUnit.maxP": 60000.0, + "BatteryUnit.storedE": 6000.0, + "BatteryUnit.ratedE": 60000.0, + "InefficientBatteryUnit.reserveEnery": 20.0, + "InefficientBatteryUnit.limitEnergy": 100.0, + "InefficientBatteryUnit.efficiencyDischarge": 98.0, + "InefficientBatteryUnit.efficiencyCharge": 95.0 + } + } + } + } + } + } + } + }, + "Versions": { + "IEC61970CIMVersion": { + "Ravens.CimObjectType": "IEC61970CIMVersion", + "IEC61970CIMVersion.version": "IEC61970CIM100", + "IEC61970CIMVersion.date": "2019-04-01" + } + }, + "PerLengthLineParameter": { + "PerLengthImpedance": { + "PerLengthPhaseImpedance": { + "4/0quad": { + "Ravens.CimObjectType": "PerLengthPhaseImpedance", + "IdentifiedObject.mRID": "a2ccef36-6f66-45e7-8db4-fdd9766d8c8d", + "IdentifiedObject.name": "4/0quad", + "PerLengthPhaseImpedance.conductorCount": 3, + "PerLengthPhaseImpedance.PhaseImpedanceData": [ + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 2, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.0467, + "PhaseImpedanceData.x": 0.0267, + "PhaseImpedanceData.b": -0.0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.0467, + "PhaseImpedanceData.x": 0.0267, + "PhaseImpedanceData.b": -0.0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 2, + "PhaseImpedanceData.column": 2, + "PhaseImpedanceData.r": 0.1167, + "PhaseImpedanceData.x": 0.0667, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 2, + "PhaseImpedanceData.r": 0.0467, + "PhaseImpedanceData.x": 0.0267, + "PhaseImpedanceData.b": -0.0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 3, + "PhaseImpedanceData.r": 0.1167, + "PhaseImpedanceData.x": 0.0667, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 1, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.1167, + "PhaseImpedanceData.x": 0.0667, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + } + ] + }, + "556mcm": { + "Ravens.CimObjectType": "PerLengthPhaseImpedance", + "IdentifiedObject.mRID": "8a93bb2a-3217-48d0-b19b-ae8354399310", + "IdentifiedObject.name": "556mcm", + "PerLengthPhaseImpedance.conductorCount": 3, + "PerLengthPhaseImpedance.PhaseImpedanceData": [ + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 3, + "PhaseImpedanceData.r": 0.1, + "PhaseImpedanceData.x": 0.0583, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 2, + "PhaseImpedanceData.r": 0.04, + "PhaseImpedanceData.x": 0.0233, + "PhaseImpedanceData.b": -0.0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 1, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.1, + "PhaseImpedanceData.x": 0.0583, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 2, + "PhaseImpedanceData.column": 2, + "PhaseImpedanceData.r": 0.1, + "PhaseImpedanceData.x": 0.0583, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 2, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.04, + "PhaseImpedanceData.x": 0.0233, + "PhaseImpedanceData.b": -0.0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.04, + "PhaseImpedanceData.x": 0.0233, + "PhaseImpedanceData.b": -0.0 + } + ] + } + } + } + }, + "Location": { + "primary_Location": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "cd4c22b1-390a-48b4-ba9b-c5b0a6a13e79", + "IdentifiedObject.name": "primary_Location", + "Location.PositionPoints": [ + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 1, + "PositionPoint.xPosition": 0.0, + "PositionPoint.yPosition": 0.0 + } + ] + }, + "loadbus_Location": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "1f628e25-f631-49b3-b43c-b8618559661c", + "IdentifiedObject.name": "loadbus_Location", + "Location.PositionPoints": [ + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 1, + "PositionPoint.xPosition": 0.0, + "PositionPoint.yPosition": 0.0 + } + ] + }, + "sourcebus_Location": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "17d93d69-c091-40d2-8292-e9800154e3f9", + "IdentifiedObject.name": "sourcebus_Location", + "Location.PositionPoints": [ + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 1, + "PositionPoint.xPosition": 0.0, + "PositionPoint.yPosition": 0.0 + } + ] + } + }, + "EnergyConnectionProfile": { + "Ravens.CimObjectType": "EnergyConnectionProfile", + "IdentifiedObject.mRID": "a7098736-cc57-4a69-b250-3101ae6dd9f5", + "IdentifiedObject.name": "Load::::::defaultload", + "EnergyConnectionProfile.dssSpectrum": "defaultload" + }, + "BaseVoltage": { + "BaseV_0.4": { + "Ravens.CimObjectType": "BaseVoltage", + "IdentifiedObject.mRID": "270f81bf-ab58-46e9-863a-08744d924604", + "IdentifiedObject.name": "BaseV_0.4", + "BaseVoltage.nominalVoltage": 400.0 + } + }, + "OperationalLimitType": { + "highType_5000000000.0s": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "48f1510a-52d8-4c04-a0e7-59a8876eafa2", + "IdentifiedObject.name": "highType_5000000000.0s", + "OperationalLimitType.direction": "OperationalLimitDirectionKind.high", + "OperationalLimitType.acceptableDuration": 5000000000.0 + }, + "absoluteValueType_5000000000.0s": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "faf34841-2190-4133-bf8d-cf31f35a80a0", + "IdentifiedObject.name": "absoluteValueType_5000000000.0s", + "OperationalLimitType.direction": "OperationalLimitDirectionKind.absoluteValue", + "OperationalLimitType.acceptableDuration": 5000000000.0 + }, + "absoluteValueType_86400.0s": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "14a68643-2417-4e41-b809-940b9b1856d1", + "IdentifiedObject.name": "absoluteValueType_86400.0s", + "OperationalLimitType.direction": "OperationalLimitDirectionKind.absoluteValue", + "OperationalLimitType.acceptableDuration": 86400.0 + }, + "lowType_5000000000.0s": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "33ce2fce-d1cb-4df3-924f-0399aa127edd", + "IdentifiedObject.name": "lowType_5000000000.0s", + "OperationalLimitType.direction": "OperationalLimitDirectionKind.low", + "OperationalLimitType.acceptableDuration": 5000000000.0 + } + }, + "ConnectivityNode": { + "loadbus": { + "Ravens.CimObjectType": "ConnectivityNode", + "IdentifiedObject.mRID": "0f25fa64-77ce-4721-ad73-ecad9127fa2e", + "IdentifiedObject.name": "loadbus", + "ConnectivityNode.OperationalLimitSet": "OperationalLimitSet::'OpLimV_380.0-420.00000000000006'" + }, + "sourcebus": { + "Ravens.CimObjectType": "ConnectivityNode", + "IdentifiedObject.mRID": "e4ff4b6e-79fe-40b2-af40-e0226cf5f4a4", + "IdentifiedObject.name": "sourcebus" + }, + "primary": { + "Ravens.CimObjectType": "ConnectivityNode", + "IdentifiedObject.mRID": "cc97ba78-4f37-4d8f-8044-55f023a74a28", + "IdentifiedObject.name": "primary" + } + }, + "LoadResponseCharacteristic": { + "Constant kVA": { + "Ravens.CimObjectType": "LoadResponseCharacteristic", + "IdentifiedObject.mRID": "141f856d-53fd-4d9b-b71b-464b1db94318", + "IdentifiedObject.name": "Constant kVA", + "LoadResponseCharacteristic.pConstantPower": 100, + "LoadResponseCharacteristic.qConstantPower": 100 + } + } +} diff --git a/test/data/ravens/ravens_case3_withsubxf.json b/test/data/ravens/ravens_case3_withsubxf.json new file mode 100644 index 000000000..7f2ec6db4 --- /dev/null +++ b/test/data/ravens/ravens_case3_withsubxf.json @@ -0,0 +1,836 @@ +{ + "OperationalLimitSet": { + "OpLimI_400.0_600.0": { + "Ravens.CimObjectType": "OperationalLimitSet", + "IdentifiedObject.mRID": "1e3d77af-8a23-466a-bdd9-39cee9f9fe92", + "IdentifiedObject.name": "OpLimI_400.0_600.0", + "OperationalLimitSet.OperationalLimitValue": [ + { + "Ravens.CimObjectType": "CurrentLimit", + "IdentifiedObject.mRID": "fc496404-0ea3-49ad-a418-fb8b10aa2724", + "IdentifiedObject.name": "OpLimI_400.0_600.0_Emerg", + "CurrentLimit.value": 600.0, + "CurrentLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'absoluteValueType_86400.0s'" + }, + { + "Ravens.CimObjectType": "CurrentLimit", + "IdentifiedObject.mRID": "33f3b868-cb9b-4223-b83c-e050cd47a7d0", + "IdentifiedObject.name": "OpLimI_400.0_600.0_Norm", + "CurrentLimit.value": 400.0, + "CurrentLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'absoluteValueType_5000000000.0s'" + } + ] + }, + "OpLimV_360.00000000000006-440.00000000000006": { + "Ravens.CimObjectType": "OperationalLimitSet", + "IdentifiedObject.mRID": "514c489d-6957-4739-bb9d-ff5da50e8f4e", + "IdentifiedObject.name": "OpLimV_360.00000000000006-440.00000000000006", + "OperationalLimitSet.OperationalLimitValue": [ + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "513ecee1-8a86-4ced-b436-e4def25953cc", + "IdentifiedObject.name": "OpLimV_360.00000000000006-440.00000000000006_RangeAhigh", + "VoltageLimit.value": 440.00000000000006, + "VoltageLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'highType_5000000000.0s'" + }, + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "e22b44ed-3b12-4bf9-8be3-a591a3cf732b", + "IdentifiedObject.name": "OpLimV_360.00000000000006-440.00000000000006_RangeAlow", + "VoltageLimit.value": 360.00000000000006, + "VoltageLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'lowType_5000000000.0s'" + } + ] + }, + "OpLimV_380.0-420.00000000000006": { + "Ravens.CimObjectType": "OperationalLimitSet", + "IdentifiedObject.mRID": "5c5e7910-bdea-408b-9cba-c96967e39939", + "IdentifiedObject.name": "OpLimV_380.0-420.00000000000006", + "OperationalLimitSet.OperationalLimitValue": [ + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "5f98e299-22cb-48a5-acd0-ba5404111eed", + "IdentifiedObject.name": "OpLimV_380.0-420.00000000000006_RangeAlow", + "VoltageLimit.value": 380.0, + "VoltageLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'lowType_5000000000.0s'" + }, + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "43fb3ee9-3b9a-4a7b-ace5-5ddcac6d59d5", + "IdentifiedObject.name": "OpLimV_380.0-420.00000000000006_RangeAhigh", + "VoltageLimit.value": 420.00000000000006, + "VoltageLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'highType_5000000000.0s'" + } + ] + }, + "OpLimV_7.2000": { + "Ravens.CimObjectType": "OperationalLimitSet", + "IdentifiedObject.mRID": "_665DF148-4555-4F76-BFD4-71BA3D55F876", + "IdentifiedObject.name": "OpLimV_7.2000", + "OperationalLimitSet.OperationalLimitValue": [ + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "_69C733F4-2D96-47C2-B6AE-D7593EDAD548", + "IdentifiedObject.name": "OpLimV_7.2000_RangeAHi", + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'case3_balanced_RangeAHiType'", + "VoltageLimit.value": 7560, + "VoltageLimit.normalValue": 7200.0 + }, + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "_8133C550-DC0B-482E-ABCA-DA0038702079", + "IdentifiedObject.name": "OpLimV_7.2000_RangeALo", + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'case3_balanced_RangeALoType'", + "VoltageLimit.value": 6840, + "VoltageLimit.normalValue": 7200.0 + } + ] + }, + "OpLimI_1323.1_1804.2": { + "Ravens.CimObjectType": "OperationalLimitSet", + "IdentifiedObject.mRID": "_433D75D6-4693-4413-9564-12E93A04ECC3", + "IdentifiedObject.name": "OpLimI_1323.1_1804.2", + "OperationalLimitSet.OperationalLimitValue": [ + { + "Ravens.CimObjectType": "CurrentLimit", + "IdentifiedObject.mRID": "_4180E9E9-AB79-4F18-8076-16E6FA4BB993", + "IdentifiedObject.name": "OpLimI_1323.1_1804.2_Norm", + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'case3_balanced_NormAmpsType'", + "CurrentLimit.value": 1323.0944, + "CurrentLimit.normalValue": 1323.0944 + }, + { + "Ravens.CimObjectType": "CurrentLimit", + "IdentifiedObject.mRID": "_9102C72B-FAE2-4BB2-925E-36A755252B0A", + "IdentifiedObject.name": "OpLimI_1323.1_1804.2_Emerg", + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'case3_balanced_EmergencyAmpsType'", + "CurrentLimit.value": 1804.2196, + "CurrentLimit.normalValue": 1323.0944 + } + ] + } + }, + "PowerSystemResource": { + "Equipment": { + "ConductingEquipment": { + "Conductor": { + "ACLineSegment": { + "ohline": { + "Ravens.CimObjectType": "ACLineSegment", + "IdentifiedObject.mRID": "e9c718d0-d75c-41cf-b31e-5d1467780362", + "IdentifiedObject.name": "ohline", + "Conductor.length": 1.0, + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "ACLineSegment.PerLengthImpedance": "PerLengthPhaseImpedance::'556mcm'", + "ACLineSegment.ACLineSegmentPhase": [ + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "350fed0a-7395-4736-aa12-ac2d7e87ac92", + "IdentifiedObject.name": "ohline_A", + "ACLineSegmentPhase.phase": "SinglePhaseKind.A", + "ACLineSegmentPhase.sequenceNumber": 1 + }, + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "3b5406ff-4fb5-4a30-8e2c-4f09db60a544", + "IdentifiedObject.name": "ohline_B", + "ACLineSegmentPhase.phase": "SinglePhaseKind.B", + "ACLineSegmentPhase.sequenceNumber": 2 + }, + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "8d10892c-1893-4a48-8f5b-615fcb4c0d55", + "IdentifiedObject.name": "ohline_C", + "ACLineSegmentPhase.phase": "SinglePhaseKind.C", + "ACLineSegmentPhase.sequenceNumber": 3 + } + ], + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "37415ad4-1071-481c-b741-06e6b8ca05d4", + "IdentifiedObject.name": "ohline_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'subxfbus'" + }, + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "3bd4d2fc-d02b-4238-9630-83fe0b294662", + "IdentifiedObject.name": "ohline_T2", + "ACDCTerminal.sequenceNumber": 2, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'primary'" + } + ] + }, + "quad": { + "Ravens.CimObjectType": "ACLineSegment", + "IdentifiedObject.mRID": "edba552d-daee-40f3-9488-336f9c9231dc", + "IdentifiedObject.name": "quad", + "Conductor.length": 1.0, + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "ACLineSegment.PerLengthImpedance": "PerLengthPhaseImpedance::'4/0quad'", + "ACLineSegment.ACLineSegmentPhase": [ + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "c087897c-8221-477a-b33b-59ed2ff423c7", + "IdentifiedObject.name": "quad_A", + "ACLineSegmentPhase.phase": "SinglePhaseKind.A", + "ACLineSegmentPhase.sequenceNumber": 1 + }, + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "57c71971-b70b-49a2-868b-a64aceb3b031", + "IdentifiedObject.name": "quad_B", + "ACLineSegmentPhase.phase": "SinglePhaseKind.B", + "ACLineSegmentPhase.sequenceNumber": 2 + }, + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "732aea91-11c1-4dcb-a9ed-45de010dde2f", + "IdentifiedObject.name": "quad_C", + "ACLineSegmentPhase.phase": "SinglePhaseKind.C", + "ACLineSegmentPhase.sequenceNumber": 3 + } + ], + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "82cce1dc-5fc1-4a98-9f53-2b347ed1d3b5", + "IdentifiedObject.name": "quad_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'primary'" + }, + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "f0e02033-fa13-4ac4-b6cf-0e0444d72d18", + "IdentifiedObject.name": "quad_T2", + "ACDCTerminal.sequenceNumber": 2, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ] + } + } + }, + "EnergyConnection": { + "EnergyConsumer": { + "l2": { + "Ravens.CimObjectType": "EnergyConsumer", + "IdentifiedObject.mRID": "09b604b2-00d7-4a4e-994d-2f189ee9642b", + "IdentifiedObject.name": "l2", + "EnergyConsumer.p": 6000.0, + "EnergyConsumer.q": 3000.0, + "EnergyConsumer.customerCount": 1, + "EnergyConsumer.grounded": "true", + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "EnergyConsumer.phaseConnection": "PhaseShuntConnectionKind.Y", + "EnergyConsumer.LoadResponseCharacteristic": "LoadResponseCharacteristic::'Constant kVA'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "9b397420-cdcf-4127-85ae-73559a000953", + "IdentifiedObject.name": "l2_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.B", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ], + "EnergyConsumer.EnergyConsumerPhase": [ + { + "Ravens.CimObjectType": "EnergyConsumerPhase", + "IdentifiedObject.mRID": "03858c77-6453-407c-8119-da6a76508b59", + "IdentifiedObject.name": "l2_B", + "EnergyConsumerPhase.p": 6000.0, + "EnergyConsumerPhase.q": 3000.0, + "EnergyConsumerPhase.phase": "SinglePhaseKind.B" + } + ] + }, + "l3": { + "Ravens.CimObjectType": "EnergyConsumer", + "IdentifiedObject.mRID": "f9667c10-e77a-4409-8099-072bfdce24e0", + "IdentifiedObject.name": "l3", + "EnergyConsumer.p": 6000.0, + "EnergyConsumer.q": 3000.0, + "EnergyConsumer.customerCount": 1, + "EnergyConsumer.grounded": "true", + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "EnergyConsumer.phaseConnection": "PhaseShuntConnectionKind.Y", + "EnergyConsumer.LoadResponseCharacteristic": "LoadResponseCharacteristic::'Constant kVA'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "18771bf2-42eb-4758-a101-0a92cb9508e5", + "IdentifiedObject.name": "l3_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.C", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ], + "EnergyConsumer.EnergyConsumerPhase": [ + { + "Ravens.CimObjectType": "EnergyConsumerPhase", + "IdentifiedObject.mRID": "dbfde1f4-2422-4e65-933b-7b9d43a22cc7", + "IdentifiedObject.name": "l3_C", + "EnergyConsumerPhase.p": 6000.0, + "EnergyConsumerPhase.q": 3000.0, + "EnergyConsumerPhase.phase": "SinglePhaseKind.C" + } + ] + }, + "l1": { + "Ravens.CimObjectType": "EnergyConsumer", + "IdentifiedObject.mRID": "089386b2-ecab-4d6f-ab32-12c2c5527ee5", + "IdentifiedObject.name": "l1", + "EnergyConsumer.p": 6000.0, + "EnergyConsumer.q": 3000.0, + "EnergyConsumer.customerCount": 1, + "EnergyConsumer.grounded": "true", + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "EnergyConsumer.phaseConnection": "PhaseShuntConnectionKind.Y", + "EnergyConsumer.LoadResponseCharacteristic": "LoadResponseCharacteristic::'Constant kVA'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "8db69196-5be7-4038-a656-c345313d6dcc", + "IdentifiedObject.name": "l1_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.A", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ], + "EnergyConsumer.EnergyConsumerPhase": [ + { + "Ravens.CimObjectType": "EnergyConsumerPhase", + "IdentifiedObject.mRID": "445afb26-9fca-40ff-9161-1fae6c0c1619", + "IdentifiedObject.name": "l1_A", + "EnergyConsumerPhase.p": 6000.0, + "EnergyConsumerPhase.q": 3000.0, + "EnergyConsumerPhase.phase": "SinglePhaseKind.A" + } + ] + } + }, + "EnergySource": { + "source": { + "Ravens.CimObjectType": "EnergySource", + "IdentifiedObject.mRID": "5181f211-4f84-4220-905d-ce5a2136c86b", + "IdentifiedObject.name": "source", + "EnergySource.nominalVoltage": 7200, + "EnergySource.voltageMagnitude": 7170.48, + "EnergySource.voltageAngle": 0.0, + "EnergySource.r": 1.2573047e-05, + "EnergySource.x": 5.0292187e-05, + "EnergySource.r0": 1.6425491e-05, + "EnergySource.x0": 4.9276474e-05, + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_7.2000'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "f67ae006-bbc4-408b-90bc-ac62d33ce9d5", + "IdentifiedObject.name": "source_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'sourcebus'" + } + ] + } + }, + "RegulatingCondEq": { + "PowerElectronicsConnection": { + "pv1": { + "Ravens.CimObjectType": "PowerElectronicsConnection", + "IdentifiedObject.mRID": "997cec18-9472-4c89-8fb7-6e7d8ca4d377", + "IdentifiedObject.name": "pv1", + "PowerElectronicsConnection.maxIFault": 1.1111111111111112, + "PowerElectronicsConnection.p": 9999.997590992734, + "PowerElectronicsConnection.q": -0.0016831415801767946, + "PowerElectronicsConnection.ratedS": 10000.0, + "PowerElectronicsConnection.ratedU": 400.0, + "PowerElectronicsConnection.maxQ": 10000.0, + "PowerElectronicsConnection.minQ": -10000.0, + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "a1d1a18a-5c36-4804-8fc0-13f756823d19", + "IdentifiedObject.name": "pv1_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ], + "PowerElectronicsConnection.PowerElectronicsUnit": { + "Ravens.CimObjectType": "PhotoVoltaicUnit", + "IdentifiedObject.mRID": "24872726-129e-491f-83cc-74135a8432b4", + "IdentifiedObject.name": "pv1_PVPanels", + "PowerElectronicsUnit.minP": 2000.0, + "PowerElectronicsUnit.maxP": 500000.0 + } + }, + "s1": { + "Ravens.CimObjectType": "PowerElectronicsConnection", + "IdentifiedObject.mRID": "cb0d7d2e-e799-4aaf-bb04-5daf2bfb9a00", + "IdentifiedObject.name": "s1", + "PowerElectronicsConnection.maxIFault": 1.1111111111111112, + "PowerElectronicsConnection.p": -0.0, + "PowerElectronicsConnection.q": -0.0, + "PowerElectronicsConnection.ratedS": 60000.0, + "PowerElectronicsConnection.ratedU": 400.0, + "PowerElectronicsConnection.maxQ": 25000.0, + "PowerElectronicsConnection.minQ": -25000.0, + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "6f75e791-02dc-496f-8117-106bef0e0700", + "IdentifiedObject.name": "s1_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ], + "PowerElectronicsConnection.PowerElectronicsUnit": { + "Ravens.CimObjectType": "BatteryUnit", + "IdentifiedObject.mRID": "09908453-5eb9-4927-817a-0dd0a84e0f95", + "IdentifiedObject.name": "s1_Cells", + "PowerElectronicsUnit.minP": -60000.0, + "PowerElectronicsUnit.maxP": 60000.0, + "BatteryUnit.storedE": 6000.0, + "BatteryUnit.ratedE": 60000.0, + "InefficientBatteryUnit.reserveEnery": 20.0, + "InefficientBatteryUnit.limitEnergy": 100.0, + "InefficientBatteryUnit.efficiencyDischarge": 98.0, + "InefficientBatteryUnit.efficiencyCharge": 95.0 + } + } + } + } + }, + "PowerTransformer": { + "subxf": { + "Ravens.CimObjectType": "PowerTransformer", + "IdentifiedObject.mRID": "_B626B2F6-EC37-4A57-AF79-1DFC2973CC62", + "IdentifiedObject.name": "subxf", + "PowerTransformer.vectorGroup": "Yy", + "PowerSystemResource.Location": "Location::'subxf_Loc'", + "PowerTransformer.PowerTransformerEnd": [ + { + "Ravens.CimObjectType": "PowerTransformerEnd", + "IdentifiedObject.mRID": "_11C98A2D-4F3B-499F-9C93-997F5E6B6050", + "IdentifiedObject.name": "subxf_End_1", + "PowerTransformerEnd.ratedS": 15000000, + "PowerTransformerEnd.ratedU": 7200, + "PowerTransformerEnd.r": 1.728e-05, + "PowerTransformerEnd.connectionKind": "WindingConnection.Y", + "PowerTransformerEnd.phaseAngleClock": 0, + "TransformerEnd.endNumber": 1, + "TransformerEnd.grounded": "true", + "TransformerEnd.rground": 0, + "TransformerEnd.xground": 0, + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_7.2000'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "_16ECD631-0E7C-4CF8-BFBE-47B70741FBB5", + "IdentifiedObject.name": "subxf_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'sourcebus'" + } + ], + "TransformerEnd.CoreAdmittance": { + "Ravens.CimObjectType": "TransformerCoreAdmittance", + "IdentifiedObject.mRID": "_82EF01DC-693A-456D-80B7-88480B854940", + "IdentifiedObject.name": "subxf_Yc", + "TransformerCoreAdmittance.g": 0, + "TransformerCoreAdmittance.g0": 0, + "TransformerCoreAdmittance.b": 0, + "TransformerCoreAdmittance.b0": 0 + }, + "TransformerEnd.MeshImpedance": { + "Ravens.CimObjectType": "TransformerMeshImpedance", + "IdentifiedObject.mRID": "_C7842810-3C4F-495F-AD46-C3B29FF7727F", + "IdentifiedObject.name": "subxf_Zsc_1", + "TransformerMeshImpedance.r": 3.456e-05, + "TransformerMeshImpedance.r0": 3.456e-05, + "TransformerMeshImpedance.x": 0.0003456, + "TransformerMeshImpedance.x0": 0.0003456 + } + }, + { + "Ravens.CimObjectType": "PowerTransformerEnd", + "IdentifiedObject.mRID": "_A96426D2-9C2C-43D9-964F-A2F37B45368C", + "IdentifiedObject.name": "subxf_End_2", + "PowerTransformerEnd.ratedS": 15000000, + "PowerTransformerEnd.ratedU": 400, + "PowerTransformerEnd.r": 5.3333333e-08, + "PowerTransformerEnd.connectionKind": "WindingConnection.Y", + "PowerTransformerEnd.phaseAngleClock": 0, + "TransformerEnd.endNumber": 2, + "TransformerEnd.grounded": "true", + "TransformerEnd.rground": 0, + "TransformerEnd.xground": 0, + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4000'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "_7D0ABC1E-3EA3-4532-8122-DA10A6B933FB", + "IdentifiedObject.name": "subxf_T2", + "ACDCTerminal.sequenceNumber": 2, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'subxfbus'" + } + ], + "TransformerEnd.MeshImpedance": { + "Ravens.CimObjectType": "TransformerMeshImpedance", + "IdentifiedObject.mRID": "_C7842810-3C4F-495F-AD46-C3B29FF7727F", + "IdentifiedObject.name": "subxf_Zsc_1", + "TransformerMeshImpedance.r": 3.456e-05, + "TransformerMeshImpedance.r0": 3.456e-05, + "TransformerMeshImpedance.x": 0.0003456, + "TransformerMeshImpedance.x0": 0.0003456 + } + } + ] + } + } + } + } + }, + "Versions": { + "IEC61970CIMVersion": { + "Ravens.CimObjectType": "IEC61970CIMVersion", + "IEC61970CIMVersion.version": "IEC61970CIM100", + "IEC61970CIMVersion.date": "2019-04-01" + } + }, + "PerLengthLineParameter": { + "PerLengthImpedance": { + "PerLengthPhaseImpedance": { + "4/0quad": { + "Ravens.CimObjectType": "PerLengthPhaseImpedance", + "IdentifiedObject.mRID": "a2ccef36-6f66-45e7-8db4-fdd9766d8c8d", + "IdentifiedObject.name": "4/0quad", + "PerLengthPhaseImpedance.conductorCount": 3, + "PerLengthPhaseImpedance.PhaseImpedanceData": [ + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 2, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.0467, + "PhaseImpedanceData.x": 0.0267, + "PhaseImpedanceData.b": -0.0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.0467, + "PhaseImpedanceData.x": 0.0267, + "PhaseImpedanceData.b": -0.0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 2, + "PhaseImpedanceData.column": 2, + "PhaseImpedanceData.r": 0.1167, + "PhaseImpedanceData.x": 0.0667, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 2, + "PhaseImpedanceData.r": 0.0467, + "PhaseImpedanceData.x": 0.0267, + "PhaseImpedanceData.b": -0.0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 3, + "PhaseImpedanceData.r": 0.1167, + "PhaseImpedanceData.x": 0.0667, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 1, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.1167, + "PhaseImpedanceData.x": 0.0667, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + } + ] + }, + "556mcm": { + "Ravens.CimObjectType": "PerLengthPhaseImpedance", + "IdentifiedObject.mRID": "8a93bb2a-3217-48d0-b19b-ae8354399310", + "IdentifiedObject.name": "556mcm", + "PerLengthPhaseImpedance.conductorCount": 3, + "PerLengthPhaseImpedance.PhaseImpedanceData": [ + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 3, + "PhaseImpedanceData.r": 0.1, + "PhaseImpedanceData.x": 0.0583, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 2, + "PhaseImpedanceData.r": 0.04, + "PhaseImpedanceData.x": 0.0233, + "PhaseImpedanceData.b": -0.0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 1, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.1, + "PhaseImpedanceData.x": 0.0583, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 2, + "PhaseImpedanceData.column": 2, + "PhaseImpedanceData.r": 0.1, + "PhaseImpedanceData.x": 0.0583, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 2, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.04, + "PhaseImpedanceData.x": 0.0233, + "PhaseImpedanceData.b": -0.0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.04, + "PhaseImpedanceData.x": 0.0233, + "PhaseImpedanceData.b": -0.0 + } + ] + } + } + } + }, + "Location": { + "primary_Location": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "cd4c22b1-390a-48b4-ba9b-c5b0a6a13e79", + "IdentifiedObject.name": "primary_Location", + "Location.PositionPoints": [ + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 1, + "PositionPoint.xPosition": 0.0, + "PositionPoint.yPosition": 0.0 + } + ] + }, + "loadbus_Location": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "1f628e25-f631-49b3-b43c-b8618559661c", + "IdentifiedObject.name": "loadbus_Location", + "Location.PositionPoints": [ + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 1, + "PositionPoint.xPosition": 0.0, + "PositionPoint.yPosition": 0.0 + } + ] + }, + "sourcebus_Location": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "17d93d69-c091-40d2-8292-e9800154e3f9", + "IdentifiedObject.name": "sourcebus_Location", + "Location.PositionPoints": [ + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 1, + "PositionPoint.xPosition": 0.0, + "PositionPoint.yPosition": 0.0 + } + ] + } + }, + "EnergyConnectionProfile": { + "Ravens.CimObjectType": "EnergyConnectionProfile", + "IdentifiedObject.mRID": "a7098736-cc57-4a69-b250-3101ae6dd9f5", + "IdentifiedObject.name": "Load::::::defaultload", + "EnergyConnectionProfile.dssSpectrum": "defaultload" + }, + "BaseVoltage": { + "BaseV_0.4": { + "Ravens.CimObjectType": "BaseVoltage", + "IdentifiedObject.mRID": "270f81bf-ab58-46e9-863a-08744d924604", + "IdentifiedObject.name": "BaseV_0.4", + "BaseVoltage.nominalVoltage": 400.0 + }, + "BaseV_7.2000": { + "Ravens.CimObjectType": "BaseVoltage", + "IdentifiedObject.mRID": "_200EDAAE-4DBD-4A69-9033-B4032B2270FE", + "IdentifiedObject.name": "BaseV_7.2000", + "BaseVoltage.nominalVoltage": 7200 + } + }, + "OperationalLimitType": { + "highType_5000000000.0s": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "48f1510a-52d8-4c04-a0e7-59a8876eafa2", + "IdentifiedObject.name": "highType_5000000000.0s", + "OperationalLimitType.direction": "OperationalLimitDirectionKind.high", + "OperationalLimitType.acceptableDuration": 5000000000.0 + }, + "absoluteValueType_5000000000.0s": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "faf34841-2190-4133-bf8d-cf31f35a80a0", + "IdentifiedObject.name": "absoluteValueType_5000000000.0s", + "OperationalLimitType.direction": "OperationalLimitDirectionKind.absoluteValue", + "OperationalLimitType.acceptableDuration": 5000000000.0 + }, + "absoluteValueType_86400.0s": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "14a68643-2417-4e41-b809-940b9b1856d1", + "IdentifiedObject.name": "absoluteValueType_86400.0s", + "OperationalLimitType.direction": "OperationalLimitDirectionKind.absoluteValue", + "OperationalLimitType.acceptableDuration": 86400.0 + }, + "lowType_5000000000.0s": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "33ce2fce-d1cb-4df3-924f-0399aa127edd", + "IdentifiedObject.name": "lowType_5000000000.0s", + "OperationalLimitType.direction": "OperationalLimitDirectionKind.low", + "OperationalLimitType.acceptableDuration": 5000000000.0 + }, + "case3_balanced_NormAmpsType": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "_F8347896-5AFD-4AD3-BDFB-C2B164917AB7", + "IdentifiedObject.name": "case3_balanced_NormAmpsType", + "OperationalLimitType.acceptableDuration": 5000000000.0, + "OperationalLimitType.direction": "OperationalLimitDirectionKind.absoluteValue" + }, + "case3_balanced_EmergencyAmpsType": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "_65F6EC19-7482-49EA-8064-6F2E06BF9E28", + "IdentifiedObject.name": "case3_balanced_EmergencyAmpsType", + "OperationalLimitType.acceptableDuration": 7200, + "OperationalLimitType.direction": "OperationalLimitDirectionKind.absoluteValue" + }, + "case3_balanced_RangeAHiType": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "_5B420D61-5A29-40E4-BFB8-7E4B7E0B4215", + "IdentifiedObject.name": "case3_balanced_RangeAHiType", + "OperationalLimitType.acceptableDuration": 5000000000.0, + "OperationalLimitType.direction": "OperationalLimitDirectionKind.high" + }, + "case3_balanced_RangeALoType": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "_C8B99699-7B9D-40AF-AEFB-E862D9A0109B", + "IdentifiedObject.name": "case3_balanced_RangeALoType", + "OperationalLimitType.acceptableDuration": 5000000000.0, + "OperationalLimitType.direction": "OperationalLimitDirectionKind.low" + } + }, + "ConnectivityNode": { + "loadbus": { + "Ravens.CimObjectType": "ConnectivityNode", + "IdentifiedObject.mRID": "0f25fa64-77ce-4721-ad73-ecad9127fa2e", + "IdentifiedObject.name": "loadbus", + "ConnectivityNode.OperationalLimitSet": "OperationalLimitSet::'OpLimV_380.0-420.00000000000006'" + }, + "sourcebus": { + "Ravens.CimObjectType": "ConnectivityNode", + "IdentifiedObject.mRID": "e4ff4b6e-79fe-40b2-af40-e0226cf5f4a4", + "IdentifiedObject.name": "sourcebus", + "ConnectivityNode.OperationalLimitSet": "OperationalLimitSet::'OpLimV_7.2000'" + }, + "primary": { + "Ravens.CimObjectType": "ConnectivityNode", + "IdentifiedObject.mRID": "cc97ba78-4f37-4d8f-8044-55f023a74a28", + "IdentifiedObject.name": "primary", + "ConnectivityNode.OperationalLimitSet": "OperationalLimitSet::'OpLimV_380.0-420.00000000000006'" + }, + "subxfbus": { + "Ravens.CimObjectType": "ConnectivityNode", + "IdentifiedObject.mRID": "_FE727D13-2277-4F78-A5F2-FF1DF2FB8883", + "IdentifiedObject.name": "subxfbus", + "ConnectivityNode.OperationalLimitSet": "OperationalLimitSet::'OpLimV_380.0-420.00000000000006'" + } + }, + "LoadResponseCharacteristic": { + "Constant kVA": { + "Ravens.CimObjectType": "LoadResponseCharacteristic", + "IdentifiedObject.mRID": "141f856d-53fd-4d9b-b71b-464b1db94318", + "IdentifiedObject.name": "Constant kVA", + "LoadResponseCharacteristic.pConstantPower": 100, + "LoadResponseCharacteristic.qConstantPower": 100 + } + }, + "CoordinateSystem": { + "case3_balanced_CrsUrn": { + "Ravens.CimObjectType": "CoordinateSystem", + "IdentifiedObject.mRID": "_6FD1030A-4977-4961-A980-0E5A7F46D48A", + "IdentifiedObject.name": "case3_balanced_CrsUrn", + "CoordinateSystem.crsUrn": "OpenDSSLocalBusCoordinates" + } + }, + "Group": { + "GeographicalRegion": { + "case3_balanced_Region": { + "Ravens.CimObjectType": "GeographicalRegion", + "IdentifiedObject.mRID": "_2A0B22A1-CCB4-46F8-8F42-9090CA3B29AC", + "IdentifiedObject.name": "case3_balanced_Region" + } + }, + "SubGeographicalRegion": { + "case3_balanced_SubRegion": { + "Ravens.CimObjectType": "SubGeographicalRegion", + "IdentifiedObject.mRID": "_62CD9221-3F2B-4741-AF1B-16DED6354EEA", + "IdentifiedObject.name": "case3_balanced_SubRegion", + "SubGeographicalRegion.Region": "GeographicalRegion::'case3_balanced_Region'" + } + }, + "EquipmentContainer": { + "Ravens.CimObjectType": "Substation", + "IdentifiedObject.mRID": "_745276ED-1EDC-499C-9E0D-C9C138A9C49E", + "IdentifiedObject.name": "case3_balanced_Substation", + "PowerSystemResource.Location": "Location::'case3_balanced_Location'", + "Substation.Region": "SubGeographicalRegion::'case3_balanced_SubRegion'" + }, + "TopologicalIsland": { + "case3_balanced_Island": { + "Ravens.CimObjectType": "TopologicalIsland", + "IdentifiedObject.mRID": "_6A44C429-666A-4200-B3AE-10FCFDF8A04A", + "IdentifiedObject.name": "case3_balanced_Island" + } + } + } +} diff --git a/test/data/ravens/ravens_test_switch_1w.json b/test/data/ravens/ravens_test_switch_1w.json new file mode 100644 index 000000000..0c177322a --- /dev/null +++ b/test/data/ravens/ravens_test_switch_1w.json @@ -0,0 +1,554 @@ +{ + "Versions": { + "IEC61970CIMVersion": { + "Ravens.CimObjectType": "IEC61970CIMVersion", + "IEC61970CIMVersion.version": "IEC61970CIM100", + "IEC61970CIMVersion.date": "2019-04-01" + } + }, + "CoordinateSystem": { + "test_CrsUrn": { + "Ravens.CimObjectType": "CoordinateSystem", + "IdentifiedObject.mRID": "_9EF37BD9-0C2D-4AE1-AE0F-B7B851E66544", + "IdentifiedObject.name": "test_CrsUrn", + "CoordinateSystem.crsUrn": "OpenDSSLocalBusCoordinates" + } + }, + "Group": { + "GeographicalRegion": { + "test_Region": { + "Ravens.CimObjectType": "GeographicalRegion", + "IdentifiedObject.mRID": "_90228F7F-5927-47CB-8796-8489A7068FC1", + "IdentifiedObject.name": "test_Region" + } + }, + "SubGeographicalRegion": { + "test_SubRegion": { + "Ravens.CimObjectType": "SubGeographicalRegion", + "IdentifiedObject.mRID": "_424DAD1E-F5F9-4573-B62A-6FDE7CD692C9", + "IdentifiedObject.name": "test_SubRegion", + "SubGeographicalRegion.Region": "GeographicalRegion::'test_Region'" + } + }, + "EquipmentContainer": { + "Ravens.CimObjectType": "Substation", + "IdentifiedObject.mRID": "_AD96408A-13FD-44CD-8441-D474E3744E1F", + "IdentifiedObject.name": "test_Substation", + "PowerSystemResource.Location": "Location::'test_Location'", + "Substation.Region": "SubGeographicalRegion::'test_SubRegion'" + }, + "TopologicalIsland": { + "test_Island": { + "Ravens.CimObjectType": "TopologicalIsland", + "IdentifiedObject.mRID": "_62B53E99-C000-4FEE-80CE-6F29110E1873", + "IdentifiedObject.name": "test_Island" + } + } + }, + "Location": { + "test_Location": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "_2B41D90F-6E55-496B-8BEA-23C7CD041DBF", + "IdentifiedObject.name": "test_Location", + "Location.CoordinateSystem": "CoordinateSystem::'test_CrsUrn'" + }, + "source_Loc": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "_44C707B5-0B86-4815-9F65-A2D2F7BB0243", + "IdentifiedObject.name": "source_Loc", + "Location.CoordinateSystem": "CoordinateSystem::'test_CrsUrn'", + "Location.PositionPoints": [ + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 1, + "PositionPoint.xPosition": 0, + "PositionPoint.yPosition": 0 + } + ] + }, + "line1_Loc": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "_52FB75B7-56B0-4F20-B2E2-6BF70AFB5E41", + "IdentifiedObject.name": "line1_Loc", + "Location.CoordinateSystem": "CoordinateSystem::'test_CrsUrn'", + "Location.PositionPoints": [ + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 1, + "PositionPoint.xPosition": 0, + "PositionPoint.yPosition": 0 + }, + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 2, + "PositionPoint.xPosition": 0, + "PositionPoint.yPosition": 0 + } + ] + }, + "switch_Loc": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "_1E0CF052-B39C-424B-B945-BF89267A5411", + "IdentifiedObject.name": "switch_Loc", + "Location.CoordinateSystem": "CoordinateSystem::'test_CrsUrn'", + "Location.PositionPoints": [ + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 1, + "PositionPoint.xPosition": 0, + "PositionPoint.yPosition": 0 + }, + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 2, + "PositionPoint.xPosition": 0, + "PositionPoint.yPosition": 0 + } + ] + }, + "load1_Loc": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "_2B553B02-E33C-4527-9A2C-FAF6741A8C90", + "IdentifiedObject.name": "load1_Loc", + "Location.CoordinateSystem": "CoordinateSystem::'test_CrsUrn'", + "Location.PositionPoints": [ + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 1, + "PositionPoint.xPosition": 0, + "PositionPoint.yPosition": 0 + } + ] + } + }, + "OperationalLimitSet": { + "OpLimI_400.0_600.0": { + "Ravens.CimObjectType": "OperationalLimitSet", + "IdentifiedObject.mRID": "_89FAB3C8-F3EA-42D6-9FFB-C7218A5B700C", + "IdentifiedObject.name": "OpLimI_400.0_600.0", + "OperationalLimitSet.OperationalLimitValue": [ + { + "Ravens.CimObjectType": "CurrentLimit", + "IdentifiedObject.mRID": "_CCAE60BA-5D56-4F8F-8400-9A21902C2A9D", + "IdentifiedObject.name": "OpLimI_400.0_600.0_Norm", + "CurrentLimit.value": 400, + "OperationalLimit.OperationalLimitType": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "_3F1940AC-91FD-4679-B727-9275063CCC2E", + "IdentifiedObject.name": "test_NormAmpsType", + "OperationalLimitType.acceptableDuration": 5000000000.0, + "OperationalLimitType.direction": "OperationalLimitDirectionKind.absoluteValue" + } + }, + { + "Ravens.CimObjectType": "CurrentLimit", + "IdentifiedObject.mRID": "_1AB18FDA-00CF-4A84-AB9E-D3EFF39464A5", + "IdentifiedObject.name": "OpLimI_400.0_600.0_Emerg", + "CurrentLimit.value": 600, + "OperationalLimit.OperationalLimitType": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "_51A01C28-E11F-4684-8137-15D0140100D1", + "IdentifiedObject.name": "test_EmergencyAmpsType", + "OperationalLimitType.acceptableDuration": 7200, + "OperationalLimitType.direction": "OperationalLimitDirectionKind.absoluteValue" + } + } + ] + }, + "OpLimV_0.4000": { + "Ravens.CimObjectType": "OperationalLimitSet", + "IdentifiedObject.mRID": "_DC0A7C69-F8A9-4A07-B4B6-AA56A138CFED", + "IdentifiedObject.name": "OpLimV_0.4000", + "OperationalLimitSet.OperationalLimitValue": [ + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "_860EBBB7-81B5-45D5-9D15-EBDADB0903F9", + "IdentifiedObject.name": "OpLimV_0.4000_RangeAHi", + "VoltageLimit.value": 420, + "OperationalLimit.OperationalLimitType": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "_1CBA95F9-4F8F-4930-8376-94867399492F", + "IdentifiedObject.name": "test_RangeAHiType", + "OperationalLimitType.acceptableDuration": 5000000000.0, + "OperationalLimitType.direction": "OperationalLimitDirectionKind.high" + } + }, + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "_36431E54-2475-4280-8443-827DFD546DEC", + "IdentifiedObject.name": "OpLimV_0.4000_RangeALo", + "VoltageLimit.value": 380, + "OperationalLimit.OperationalLimitType": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "_EEBC518E-8B78-4C6B-8F85-2DF8C9C53C71", + "IdentifiedObject.name": "test_RangeALoType", + "OperationalLimitType.acceptableDuration": 5000000000.0, + "OperationalLimitType.direction": "OperationalLimitDirectionKind.low" + } + }, + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "_97FB217B-7289-4DCF-B690-67F2451EF298", + "IdentifiedObject.name": "OpLimV_0.4000_RangeBHi", + "VoltageLimit.value": 423.33332, + "OperationalLimit.OperationalLimitType": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "_FDABBB3E-12E8-4AD3-B1C9-43B35C5C57B3", + "IdentifiedObject.name": "test_RangeBHiType", + "OperationalLimitType.acceptableDuration": 86400, + "OperationalLimitType.direction": "OperationalLimitDirectionKind.high" + } + }, + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "_8106713D-D130-4A5D-80C2-42A8374B5BC3", + "IdentifiedObject.name": "OpLimV_0.4000_RangeBLo", + "VoltageLimit.value": 366.66668, + "OperationalLimit.OperationalLimitType": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "_BCFA3B34-0937-4455-B154-7233DAEE4310", + "IdentifiedObject.name": "test_RangeBLoType", + "OperationalLimitType.acceptableDuration": 86400, + "OperationalLimitType.direction": "OperationalLimitDirectionKind.low" + } + } + ] + } + }, + "BaseVoltage": { + "BaseV_0.4000": { + "Ravens.CimObjectType": "BaseVoltage", + "IdentifiedObject.mRID": "_46C78529-FF4F-40A8-841D-418D7D52BEFD", + "IdentifiedObject.name": "BaseV_0.4000", + "BaseVoltage.nominalVoltage": 400 + } + }, + "TopologicalNode": { + "b1": { + "Ravens.CimObjectType": "TopologicalNode", + "IdentifiedObject.mRID": "_1D7153A2-9354-4542-8A08-F6FCF43002D1", + "IdentifiedObject.name": "b1", + "TopologicalNode.TopologicalIsland": "TopologicalIsland::'test_Island'" + }, + "x1": { + "Ravens.CimObjectType": "TopologicalNode", + "IdentifiedObject.mRID": "_B764BFB0-EEB1-4CFF-9BA5-894D76A00B8E", + "IdentifiedObject.name": "x1", + "TopologicalNode.TopologicalIsland": "TopologicalIsland::'test_Island'" + }, + "x2": { + "Ravens.CimObjectType": "TopologicalNode", + "IdentifiedObject.mRID": "_DE499DAA-E9D0-4EEC-8BAE-FB7E9A439230", + "IdentifiedObject.name": "x2", + "TopologicalNode.TopologicalIsland": "TopologicalIsland::'test_Island'" + } + }, + "ConnectivityNode": { + "b1": { + "Ravens.CimObjectType": "ConnectivityNode", + "IdentifiedObject.mRID": "_DB090751-3E13-456A-A662-CF7D7C528C94", + "IdentifiedObject.name": "b1", + "ConnectivityNode.TopologicalNode": "TopologicalNode::'b1'", + "ConnectivityNode.OperationalLimitSet": "OperationalLimitSet::'OpLimV_0.4000'" + }, + "x1": { + "Ravens.CimObjectType": "ConnectivityNode", + "IdentifiedObject.mRID": "_6E6F3550-3BFB-4009-B76F-6693D5604960", + "IdentifiedObject.name": "x1", + "ConnectivityNode.TopologicalNode": "TopologicalNode::'x1'", + "ConnectivityNode.OperationalLimitSet": "OperationalLimitSet::'OpLimV_0.4000'" + }, + "x2": { + "Ravens.CimObjectType": "ConnectivityNode", + "IdentifiedObject.mRID": "_B1CC7BCB-0E9C-4246-8AC9-4BB6B0453256", + "IdentifiedObject.name": "x2", + "ConnectivityNode.TopologicalNode": "TopologicalNode::'x2'", + "ConnectivityNode.OperationalLimitSet": "OperationalLimitSet::'OpLimV_0.4000'" + } + }, + "PowerSystemResource": { + "Equipment": { + "ConductingEquipment": { + "EnergyConnection": { + "EnergySource": { + "source": { + "Ravens.CimObjectType": "EnergySource", + "IdentifiedObject.mRID": "_5CF553FD-BC94-4E9D-8B6D-D928BCF554A3", + "IdentifiedObject.name": "source", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4000'", + "EnergySource.nominalVoltage": 400, + "EnergySource.voltageMagnitude": 400, + "EnergySource.voltageAngle": 0, + "EnergySource.r": 3.88057e-10, + "EnergySource.x": 1.552228e-09, + "EnergySource.r0": 5.069596e-10, + "EnergySource.x0": 1.5208788e-09, + "PowerSystemResource.Location": "Location::'source_Loc'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "_BB8461F8-A1E9-4D73-94E2-EB857395A8DF", + "IdentifiedObject.name": "source_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.ConnectivityNode": "ConnectivityNode::'b1'" + } + ] + } + }, + "EnergyConsumer": { + "load1": { + "Ravens.CimObjectType": "EnergyConsumer", + "IdentifiedObject.mRID": "_D322D86C-C523-48E9-B2AE-A5F57975536B", + "IdentifiedObject.name": "load1", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4000'", + "EnergyConsumer.p": 4500, + "EnergyConsumer.q": 2179.4495, + "EnergyConsumer.customerCount": 1, + "EnergyConsumer.phaseConnection": "PhaseShuntConnectionKind.Y", + "EnergyConsumer.grounded": "true", + "PowerSystemResource.Location": "Location::'load1_Loc'", + "EnergyConsumer.LoadResponseCharacteristic": "LoadResponseCharacteristic::'Constant kVA'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "_37E125ED-75BE-4C31-8CFE-AC4A3C9E19D7", + "IdentifiedObject.name": "load1_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.ConnectivityNode": "ConnectivityNode::'x2'" + } + ], + "EnergyConsumer.EnergyConsumerPhase": [ + { + "Ravens.CimObjectType": "EnergyConsumerPhase", + "IdentifiedObject.mRID": "_C8574EA9-6EB0-40F9-B051-3807FB0196FD", + "IdentifiedObject.name": "load1_B", + "EnergyConsumerPhase.phase": "SinglePhaseKind.B", + "EnergyConsumerPhase.p": 4500, + "EnergyConsumerPhase.q": 2179.4495, + "PowerSystemResource.Location": "Location::'load1_Loc'" + } + ] + } + } + }, + "Conductor": { + "ACLineSegment": { + "line1": { + "Ravens.CimObjectType": "ACLineSegment", + "IdentifiedObject.mRID": "_6B5FF69A-404A-4389-9FA1-F43943464A66", + "IdentifiedObject.name": "line1", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4000'", + "Conductor.length": 500, + "PowerSystemResource.Location": "Location::'line1_Loc'", + "ACLineSegment.PerLengthImpedance": "PerLengthPhaseImpedance::'z'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "_B2950608-195A-4420-97AE-425C0B09A2C1", + "IdentifiedObject.name": "line1_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.ConnectivityNode": "ConnectivityNode::'b1'" + }, + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "_F1E9D575-D53F-4386-A904-929F0D7A44CE", + "IdentifiedObject.name": "line1_T2", + "ACDCTerminal.sequenceNumber": 2, + "Terminal.ConnectivityNode": "ConnectivityNode::'x1'" + } + ], + "ACLineSegment.ACLineSegmentPhase": [ + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "_B59AC09D-9E51-4585-B330-3A24C685CB8A", + "IdentifiedObject.name": "line1_A", + "ACLineSegmentPhase.phase": "SinglePhaseKind.A", + "ACLineSegmentPhase.sequenceNumber": 1, + "PowerSystemResource.Location": "Location::'line1_Loc'" + } + ] + } + } + }, + "Switch": { + "switch": { + "Ravens.CimObjectType": "LoadBreakSwitch", + "IdentifiedObject.mRID": "_25E1438A-99DB-46BB-B727-26C74AE79D60", + "IdentifiedObject.name": "switch", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4000'", + "ProtectedSwitch.breakingCapacity": 400, + "Switch.ratedCurrent": 400, + "Switch.normalOpen": "false", + "Switch.open": "false", + "Switch.retained": "true", + "PowerSystemResource.Location": "Location::'switch_Loc'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "_9294CBC6-783E-4840-8196-357BFF6BA45A", + "IdentifiedObject.name": "switch_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.ConnectivityNode": "ConnectivityNode::'x1'" + }, + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "_E1443DD5-526D-47E3-A87A-0C1F0A9B2DDC", + "IdentifiedObject.name": "switch_T2", + "ACDCTerminal.sequenceNumber": 2, + "Terminal.ConnectivityNode": "ConnectivityNode::'x2'" + } + ], + "Switch.SwitchPhase": [ + { + "Ravens.CimObjectType": "SwitchPhase", + "IdentifiedObject.mRID": "_B7162222-1F35-4713-9A3A-8360A2205C64", + "IdentifiedObject.name": "switch_A", + "SwitchPhase.closed": "true", + "SwitchPhase.normalOpen": "false", + "SwitchPhase.phaseSide1": "SinglePhaseKind.A", + "SwitchPhase.phaseSide2": "SinglePhaseKind.B", + "PowerSystemResource.Location": "Location::'switch_Loc'" + } + ] + } + } + } + } + }, + "LoadResponseCharacteristic": { + "Constant kVA": { + "Ravens.CimObjectType": "LoadResponseCharacteristic", + "IdentifiedObject.mRID": "_289E6326-E370-4C24-A190-53BFCC2C8848", + "IdentifiedObject.name": "Constant kVA", + "LoadResponseCharacteristic.exponentModel": "false", + "LoadResponseCharacteristic.pConstantImpedance": 0, + "LoadResponseCharacteristic.pConstantCurrent": 0, + "LoadResponseCharacteristic.pConstantPower": 100, + "LoadResponseCharacteristic.qConstantImpedance": 0, + "LoadResponseCharacteristic.qConstantCurrent": 0, + "LoadResponseCharacteristic.qConstantPower": 100, + "LoadResponseCharacteristic.pVoltageExponent": 0, + "LoadResponseCharacteristic.qVoltageExponent": 0, + "LoadResponseCharacteristic.pFrequencyExponent": 0, + "LoadResponseCharacteristic.qFrequencyExponent": 0 + }, + "Constant Z": { + "Ravens.CimObjectType": "LoadResponseCharacteristic", + "IdentifiedObject.mRID": "_A48E7B14-EF00-4F4D-A66E-0A92D0D5FD79", + "IdentifiedObject.name": "Constant Z", + "LoadResponseCharacteristic.exponentModel": "false", + "LoadResponseCharacteristic.pConstantImpedance": 100, + "LoadResponseCharacteristic.pConstantCurrent": 0, + "LoadResponseCharacteristic.pConstantPower": 0, + "LoadResponseCharacteristic.qConstantImpedance": 100, + "LoadResponseCharacteristic.qConstantCurrent": 0, + "LoadResponseCharacteristic.qConstantPower": 0, + "LoadResponseCharacteristic.pVoltageExponent": 0, + "LoadResponseCharacteristic.qVoltageExponent": 0, + "LoadResponseCharacteristic.pFrequencyExponent": 0, + "LoadResponseCharacteristic.qFrequencyExponent": 0 + }, + "Motor": { + "Ravens.CimObjectType": "LoadResponseCharacteristic", + "IdentifiedObject.mRID": "_F9289DA6-1EE6-4075-A5BE-BA990ABA3B40", + "IdentifiedObject.name": "Motor", + "LoadResponseCharacteristic.exponentModel": "false", + "LoadResponseCharacteristic.pConstantImpedance": 0, + "LoadResponseCharacteristic.pConstantCurrent": 0, + "LoadResponseCharacteristic.pConstantPower": 100, + "LoadResponseCharacteristic.qConstantImpedance": 100, + "LoadResponseCharacteristic.qConstantCurrent": 0, + "LoadResponseCharacteristic.qConstantPower": 0, + "LoadResponseCharacteristic.pVoltageExponent": 0, + "LoadResponseCharacteristic.qVoltageExponent": 0, + "LoadResponseCharacteristic.pFrequencyExponent": 0, + "LoadResponseCharacteristic.qFrequencyExponent": 0 + }, + "Mix Motor/Res": { + "Ravens.CimObjectType": "LoadResponseCharacteristic", + "IdentifiedObject.mRID": "_EDC6EAFB-A22C-45F1-AF5C-9DE0CCAA51EC", + "IdentifiedObject.name": "Mix Motor/Res", + "LoadResponseCharacteristic.exponentModel": "true", + "LoadResponseCharacteristic.pConstantImpedance": 0, + "LoadResponseCharacteristic.pConstantCurrent": 0, + "LoadResponseCharacteristic.pConstantPower": 0, + "LoadResponseCharacteristic.qConstantImpedance": 0, + "LoadResponseCharacteristic.qConstantCurrent": 0, + "LoadResponseCharacteristic.qConstantPower": 0, + "LoadResponseCharacteristic.pVoltageExponent": 1, + "LoadResponseCharacteristic.qVoltageExponent": 2, + "LoadResponseCharacteristic.pFrequencyExponent": 0, + "LoadResponseCharacteristic.qFrequencyExponent": 0 + }, + "Constant I": { + "Ravens.CimObjectType": "LoadResponseCharacteristic", + "IdentifiedObject.mRID": "_585ED09B-E47D-4EB9-9DB5-FD74719C3125", + "IdentifiedObject.name": "Constant I", + "LoadResponseCharacteristic.exponentModel": "false", + "LoadResponseCharacteristic.pConstantImpedance": 0, + "LoadResponseCharacteristic.pConstantCurrent": 100, + "LoadResponseCharacteristic.pConstantPower": 0, + "LoadResponseCharacteristic.qConstantImpedance": 0, + "LoadResponseCharacteristic.qConstantCurrent": 100, + "LoadResponseCharacteristic.qConstantPower": 0, + "LoadResponseCharacteristic.pVoltageExponent": 0, + "LoadResponseCharacteristic.qVoltageExponent": 0, + "LoadResponseCharacteristic.pFrequencyExponent": 0, + "LoadResponseCharacteristic.qFrequencyExponent": 0 + }, + "Variable P, Fixed Q": { + "Ravens.CimObjectType": "LoadResponseCharacteristic", + "IdentifiedObject.mRID": "_72B0F5AF-3B37-4467-82B5-C425210463B1", + "IdentifiedObject.name": "Variable P, Fixed Q", + "LoadResponseCharacteristic.exponentModel": "false", + "LoadResponseCharacteristic.pConstantImpedance": 0, + "LoadResponseCharacteristic.pConstantCurrent": 0, + "LoadResponseCharacteristic.pConstantPower": 100, + "LoadResponseCharacteristic.qConstantImpedance": 0, + "LoadResponseCharacteristic.qConstantCurrent": 0, + "LoadResponseCharacteristic.qConstantPower": 100, + "LoadResponseCharacteristic.pVoltageExponent": 0, + "LoadResponseCharacteristic.qVoltageExponent": 0, + "LoadResponseCharacteristic.pFrequencyExponent": 0, + "LoadResponseCharacteristic.qFrequencyExponent": 0 + }, + "Variable P, Fixed X": { + "Ravens.CimObjectType": "LoadResponseCharacteristic", + "IdentifiedObject.mRID": "_A5CAED93-49D2-4F4F-AD82-524C76A76AC5", + "IdentifiedObject.name": "Variable P, Fixed X", + "LoadResponseCharacteristic.exponentModel": "false", + "LoadResponseCharacteristic.pConstantImpedance": 0, + "LoadResponseCharacteristic.pConstantCurrent": 0, + "LoadResponseCharacteristic.pConstantPower": 100, + "LoadResponseCharacteristic.qConstantImpedance": 100, + "LoadResponseCharacteristic.qConstantCurrent": 0, + "LoadResponseCharacteristic.qConstantPower": 0, + "LoadResponseCharacteristic.pVoltageExponent": 0, + "LoadResponseCharacteristic.qVoltageExponent": 0, + "LoadResponseCharacteristic.pFrequencyExponent": 0, + "LoadResponseCharacteristic.qFrequencyExponent": 0 + } + }, + "PerLengthLineParameter": { + "PerLengthImpedance": { + "PerLengthPhaseImpedance": { + "z": { + "Ravens.CimObjectType": "PerLengthPhaseImpedance", + "IdentifiedObject.mRID": "_BF7B98AF-6218-4723-B7CA-A9F210A42553", + "IdentifiedObject.name": "z", + "PerLengthPhaseImpedance.conductorCount": 1, + "PerLengthPhaseImpedance.PhaseImpedanceData": [ + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 1, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.00022721762, + "PhaseImpedanceData.x": 0.00087932601, + "PhaseImpedanceData.b": 0 + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/test/data/ravens/ravens_test_switch_3w.json b/test/data/ravens/ravens_test_switch_3w.json new file mode 100644 index 000000000..ae7c35260 --- /dev/null +++ b/test/data/ravens/ravens_test_switch_3w.json @@ -0,0 +1,785 @@ +{ + "Versions": { + "IEC61970CIMVersion": { + "Ravens.CimObjectType": "IEC61970CIMVersion", + "IEC61970CIMVersion.version": "IEC61970CIM100", + "IEC61970CIMVersion.date": "2019-04-01" + } + }, + "CoordinateSystem": { + "test_CrsUrn": { + "Ravens.CimObjectType": "CoordinateSystem", + "IdentifiedObject.mRID": "_9EF37BD9-0C2D-4AE1-AE0F-B7B851E66544", + "IdentifiedObject.name": "test_CrsUrn", + "CoordinateSystem.crsUrn": "OpenDSSLocalBusCoordinates" + } + }, + "Group": { + "GeographicalRegion": { + "test_Region": { + "Ravens.CimObjectType": "GeographicalRegion", + "IdentifiedObject.mRID": "_90228F7F-5927-47CB-8796-8489A7068FC1", + "IdentifiedObject.name": "test_Region" + } + }, + "SubGeographicalRegion": { + "test_SubRegion": { + "Ravens.CimObjectType": "SubGeographicalRegion", + "IdentifiedObject.mRID": "_424DAD1E-F5F9-4573-B62A-6FDE7CD692C9", + "IdentifiedObject.name": "test_SubRegion", + "SubGeographicalRegion.Region": "GeographicalRegion::'test_Region'" + } + }, + "EquipmentContainer": { + "Ravens.CimObjectType": "Substation", + "IdentifiedObject.mRID": "_AD96408A-13FD-44CD-8441-D474E3744E1F", + "IdentifiedObject.name": "test_Substation", + "PowerSystemResource.Location": "Location::'test_Location'", + "Substation.Region": "SubGeographicalRegion::'test_SubRegion'" + }, + "TopologicalIsland": { + "test_Island": { + "Ravens.CimObjectType": "TopologicalIsland", + "IdentifiedObject.mRID": "_62B53E99-C000-4FEE-80CE-6F29110E1873", + "IdentifiedObject.name": "test_Island" + } + } + }, + "Location": { + "test_Location": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "_2B41D90F-6E55-496B-8BEA-23C7CD041DBF", + "IdentifiedObject.name": "test_Location", + "Location.CoordinateSystem": "CoordinateSystem::'test_CrsUrn'" + }, + "source_Loc": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "_44C707B5-0B86-4815-9F65-A2D2F7BB0243", + "IdentifiedObject.name": "source_Loc", + "Location.CoordinateSystem": "CoordinateSystem::'test_CrsUrn'", + "Location.PositionPoints": [ + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 1, + "PositionPoint.xPosition": 0, + "PositionPoint.yPosition": 0 + } + ] + }, + "line1_Loc": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "_52FB75B7-56B0-4F20-B2E2-6BF70AFB5E41", + "IdentifiedObject.name": "line1_Loc", + "Location.CoordinateSystem": "CoordinateSystem::'test_CrsUrn'", + "Location.PositionPoints": [ + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 1, + "PositionPoint.xPosition": 0, + "PositionPoint.yPosition": 0 + }, + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 2, + "PositionPoint.xPosition": 0, + "PositionPoint.yPosition": 0 + } + ] + }, + "line2_Loc": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "_BAD30397-D375-41B3-9540-9EEE6348178B", + "IdentifiedObject.name": "line2_Loc", + "Location.CoordinateSystem": "CoordinateSystem::'test_CrsUrn'", + "Location.PositionPoints": [ + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 1, + "PositionPoint.xPosition": 0, + "PositionPoint.yPosition": 0 + }, + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 2, + "PositionPoint.xPosition": 0, + "PositionPoint.yPosition": 0 + } + ] + }, + "switch_Loc": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "_1E0CF052-B39C-424B-B945-BF89267A5411", + "IdentifiedObject.name": "switch_Loc", + "Location.CoordinateSystem": "CoordinateSystem::'test_CrsUrn'", + "Location.PositionPoints": [ + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 1, + "PositionPoint.xPosition": 0, + "PositionPoint.yPosition": 0 + }, + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 2, + "PositionPoint.xPosition": 0, + "PositionPoint.yPosition": 0 + } + ] + }, + "load1_Loc": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "_2B553B02-E33C-4527-9A2C-FAF6741A8C90", + "IdentifiedObject.name": "load1_Loc", + "Location.CoordinateSystem": "CoordinateSystem::'test_CrsUrn'", + "Location.PositionPoints": [ + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 1, + "PositionPoint.xPosition": 0, + "PositionPoint.yPosition": 0 + } + ] + } + }, + "OperationalLimitSet": { + "OpLimI_400.0_600.0": { + "Ravens.CimObjectType": "OperationalLimitSet", + "IdentifiedObject.mRID": "_89FAB3C8-F3EA-42D6-9FFB-C7218A5B700C", + "IdentifiedObject.name": "OpLimI_400.0_600.0", + "OperationalLimitSet.OperationalLimitValue": [ + { + "Ravens.CimObjectType": "CurrentLimit", + "IdentifiedObject.mRID": "_CCAE60BA-5D56-4F8F-8400-9A21902C2A9D", + "IdentifiedObject.name": "OpLimI_400.0_600.0_Norm", + "CurrentLimit.value": 400, + "OperationalLimit.OperationalLimitType": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "_3F1940AC-91FD-4679-B727-9275063CCC2E", + "IdentifiedObject.name": "test_NormAmpsType", + "OperationalLimitType.acceptableDuration": 5000000000.0, + "OperationalLimitType.direction": "OperationalLimitDirectionKind.absoluteValue" + } + }, + { + "OperationalLimit.OperationalLimitType": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "_51A01C28-E11F-4684-8137-15D0140100D1", + "IdentifiedObject.name": "test_EmergencyAmpsType", + "OperationalLimitType.acceptableDuration": 7200, + "OperationalLimitType.direction": "OperationalLimitDirectionKind.absoluteValue" + } + } + ] + }, + "OpLimI_325.0_600.0": { + "Ravens.CimObjectType": "OperationalLimitSet", + "IdentifiedObject.mRID": "_16C3AE1B-6C4F-4EFF-82F5-320881E41F05", + "IdentifiedObject.name": "OpLimI_325.0_600.0", + "OperationalLimitSet.OperationalLimitValue": [ + { + "Ravens.CimObjectType": "CurrentLimit", + "IdentifiedObject.mRID": "_E570FFBB-3E31-4A1A-B409-276C80B48F06", + "IdentifiedObject.name": "OpLimI_325.0_600.0_Norm", + "CurrentLimit.value": 325, + "OperationalLimitSet": { + "OpLimI_400.0_600.0": { + "OperationalLimitSet.OperationalLimitValue": [ + { + "OperationalLimit.OperationalLimitType": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "_3F1940AC-91FD-4679-B727-9275063CCC2E", + "IdentifiedObject.name": "test_NormAmpsType", + "OperationalLimitType.acceptableDuration": 5000000000.0, + "OperationalLimitType.direction": "OperationalLimitDirectionKind.absoluteValue" + } + } + ] + } + } + }, + { + "Ravens.CimObjectType": "CurrentLimit", + "IdentifiedObject.mRID": "_D1958AB8-9E7F-49E2-B1C9-891DC6F438C4", + "IdentifiedObject.name": "OpLimI_325.0_600.0_Emerg", + "CurrentLimit.value": 600, + "OperationalLimitSet": { + "OpLimI_400.0_600.0": { + "OperationalLimitSet.OperationalLimitValue": [ + { + "OperationalLimit.OperationalLimitType": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "_51A01C28-E11F-4684-8137-15D0140100D1", + "IdentifiedObject.name": "test_EmergencyAmpsType", + "OperationalLimitType.acceptableDuration": 7200, + "OperationalLimitType.direction": "OperationalLimitDirectionKind.absoluteValue" + } + } + ] + } + } + } + ] + }, + "OpLimV_0.4000": { + "Ravens.CimObjectType": "OperationalLimitSet", + "IdentifiedObject.mRID": "_DC0A7C69-F8A9-4A07-B4B6-AA56A138CFED", + "IdentifiedObject.name": "OpLimV_0.4000", + "OperationalLimitSet.OperationalLimitValue": [ + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "_860EBBB7-81B5-45D5-9D15-EBDADB0903F9", + "IdentifiedObject.name": "OpLimV_0.4000_RangeAHi", + "VoltageLimit.value": 420, + "OperationalLimit.OperationalLimitType": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "_1CBA95F9-4F8F-4930-8376-94867399492F", + "IdentifiedObject.name": "test_RangeAHiType", + "OperationalLimitType.acceptableDuration": 5000000000.0, + "OperationalLimitType.direction": "OperationalLimitDirectionKind.high" + } + }, + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "_36431E54-2475-4280-8443-827DFD546DEC", + "IdentifiedObject.name": "OpLimV_0.4000_RangeALo", + "VoltageLimit.value": 380, + "OperationalLimit.OperationalLimitType": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "_EEBC518E-8B78-4C6B-8F85-2DF8C9C53C71", + "IdentifiedObject.name": "test_RangeALoType", + "OperationalLimitType.acceptableDuration": 5000000000.0, + "OperationalLimitType.direction": "OperationalLimitDirectionKind.low" + } + }, + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "_97FB217B-7289-4DCF-B690-67F2451EF298", + "IdentifiedObject.name": "OpLimV_0.4000_RangeBHi", + "VoltageLimit.value": 423.33332, + "OperationalLimit.OperationalLimitType": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "_FDABBB3E-12E8-4AD3-B1C9-43B35C5C57B3", + "IdentifiedObject.name": "test_RangeBHiType", + "OperationalLimitType.acceptableDuration": 86400, + "OperationalLimitType.direction": "OperationalLimitDirectionKind.high" + } + }, + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "_8106713D-D130-4A5D-80C2-42A8374B5BC3", + "IdentifiedObject.name": "OpLimV_0.4000_RangeBLo", + "VoltageLimit.value": 366.66668, + "OperationalLimit.OperationalLimitType": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "_BCFA3B34-0937-4455-B154-7233DAEE4310", + "IdentifiedObject.name": "test_RangeBLoType", + "OperationalLimitType.acceptableDuration": 86400, + "OperationalLimitType.direction": "OperationalLimitDirectionKind.low" + } + } + ] + } + }, + "BaseVoltage": { + "BaseV_0.4000": { + "Ravens.CimObjectType": "BaseVoltage", + "IdentifiedObject.mRID": "_46C78529-FF4F-40A8-841D-418D7D52BEFD", + "IdentifiedObject.name": "BaseV_0.4000", + "BaseVoltage.nominalVoltage": 400 + } + }, + "TopologicalNode": { + "b1": { + "Ravens.CimObjectType": "TopologicalNode", + "IdentifiedObject.mRID": "_1D7153A2-9354-4542-8A08-F6FCF43002D1", + "IdentifiedObject.name": "b1", + "TopologicalNode.TopologicalIsland": "TopologicalIsland::'test_Island'" + }, + "x1": { + "Ravens.CimObjectType": "TopologicalNode", + "IdentifiedObject.mRID": "_B764BFB0-EEB1-4CFF-9BA5-894D76A00B8E", + "IdentifiedObject.name": "x1", + "TopologicalNode.TopologicalIsland": "TopologicalIsland::'test_Island'" + }, + "x2": { + "Ravens.CimObjectType": "TopologicalNode", + "IdentifiedObject.mRID": "_DE499DAA-E9D0-4EEC-8BAE-FB7E9A439230", + "IdentifiedObject.name": "x2", + "TopologicalNode.TopologicalIsland": "TopologicalIsland::'test_Island'" + }, + "b2": { + "Ravens.CimObjectType": "TopologicalNode", + "IdentifiedObject.mRID": "_6D31F0A7-328F-482B-B800-E86BFE69E9F1", + "IdentifiedObject.name": "b2", + "TopologicalNode.TopologicalIsland": "TopologicalIsland::'test_Island'" + } + }, + "ConnectivityNode": { + "b1": { + "Ravens.CimObjectType": "ConnectivityNode", + "IdentifiedObject.mRID": "_3C23D8DF-C749-40CE-AB59-E9BCB6A51F6B", + "IdentifiedObject.name": "b1", + "ConnectivityNode.TopologicalNode": "TopologicalNode::'b1'", + "ConnectivityNode.OperationalLimitSet": "OperationalLimitSet::'OpLimV_0.4000'" + }, + "x1": { + "Ravens.CimObjectType": "ConnectivityNode", + "IdentifiedObject.mRID": "_3626FADA-426C-484F-8B69-5371B1EFF327", + "IdentifiedObject.name": "x1", + "ConnectivityNode.TopologicalNode": "TopologicalNode::'x1'", + "ConnectivityNode.OperationalLimitSet": "OperationalLimitSet::'OpLimV_0.4000'" + }, + "x2": { + "Ravens.CimObjectType": "ConnectivityNode", + "IdentifiedObject.mRID": "_59C1D3CF-5E4E-49CD-AEB3-4799F2383036", + "IdentifiedObject.name": "x2", + "ConnectivityNode.TopologicalNode": "TopologicalNode::'x2'", + "ConnectivityNode.OperationalLimitSet": "OperationalLimitSet::'OpLimV_0.4000'" + }, + "b2": { + "Ravens.CimObjectType": "ConnectivityNode", + "IdentifiedObject.mRID": "_58F5C3B9-8A22-4B99-BF8A-CF781597CAD5", + "IdentifiedObject.name": "b2", + "ConnectivityNode.TopologicalNode": "TopologicalNode::'b2'", + "ConnectivityNode.OperationalLimitSet": "OperationalLimitSet::'OpLimV_0.4000'" + } + }, + "PowerSystemResource": { + "Equipment": { + "ConductingEquipment": { + "EnergyConnection": { + "EnergySource": { + "source": { + "Ravens.CimObjectType": "EnergySource", + "IdentifiedObject.mRID": "_358FCE15-BEE2-42A8-A2EA-AD2BE89D86E5", + "IdentifiedObject.name": "source", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4000'", + "EnergySource.nominalVoltage": 400, + "EnergySource.voltageMagnitude": 400, + "EnergySource.voltageAngle": 0, + "EnergySource.r": 3.88057e-10, + "EnergySource.x": 1.552228e-09, + "EnergySource.r0": 5.069596e-10, + "EnergySource.x0": 1.5208788e-09, + "PowerSystemResource.Location": "Location::'source_Loc'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "_BB8461F8-A1E9-4D73-94E2-EB857395A8DF", + "IdentifiedObject.name": "source_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.ConnectivityNode": "ConnectivityNode::'b1'" + } + ] + } + }, + "EnergyConsumer": { + "load1": { + "Ravens.CimObjectType": "EnergyConsumer", + "IdentifiedObject.mRID": "_E8F49CFB-ECE7-4059-A6EE-4825FE7FFEFD", + "IdentifiedObject.name": "load1", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4000'", + "EnergyConsumer.p": 4500, + "EnergyConsumer.q": 2179.4495, + "EnergyConsumer.customerCount": 1, + "EnergyConsumer.phaseConnection": "PhaseShuntConnectionKind.Y", + "EnergyConsumer.grounded": "true", + "PowerSystemResource.Location": "Location::'load1_Loc'", + "EnergyConsumer.LoadResponseCharacteristic": "LoadResponseCharacteristic::'Constant kVA'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "_37E125ED-75BE-4C31-8CFE-AC4A3C9E19D7", + "IdentifiedObject.name": "load1_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.ConnectivityNode": "ConnectivityNode::'b2'" + } + ], + "EnergyConsumer.EnergyConsumerPhase": [ + { + "Ravens.CimObjectType": "EnergyConsumerPhase", + "IdentifiedObject.mRID": "_D358F738-0512-45C7-BFAC-10639DD0CE55", + "IdentifiedObject.name": "load1_A", + "EnergyConsumerPhase.phase": "SinglePhaseKind.A", + "EnergyConsumerPhase.p": 4500, + "EnergyConsumerPhase.q": 2179.4495, + "PowerSystemResource.Location": "Location::'load1_Loc'" + } + ] + } + } + }, + "Conductor": { + "ACLineSegment": { + "line1": { + "Ravens.CimObjectType": "ACLineSegment", + "IdentifiedObject.mRID": "_7172CC52-4D06-433D-A057-3CD4899F1162", + "IdentifiedObject.name": "line1", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4000'", + "Conductor.length": 500, + "PowerSystemResource.Location": "Location::'line1_Loc'", + "ACLineSegment.PerLengthImpedance": "PerLengthPhaseImpedance::'zabc'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "_B2950608-195A-4420-97AE-425C0B09A2C1", + "IdentifiedObject.name": "line1_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.ConnectivityNode": "ConnectivityNode::'b1'" + }, + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "_F1E9D575-D53F-4386-A904-929F0D7A44CE", + "IdentifiedObject.name": "line1_T2", + "ACDCTerminal.sequenceNumber": 2, + "Terminal.ConnectivityNode": "ConnectivityNode::'x1'" + } + ], + "ACLineSegment.ACLineSegmentPhase": [ + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "_B59AC09D-9E51-4585-B330-3A24C685CB8A", + "IdentifiedObject.name": "line1_A", + "ACLineSegmentPhase.phase": "SinglePhaseKind.A", + "ACLineSegmentPhase.sequenceNumber": 1, + "PowerSystemResource.Location": "Location::'line1_Loc'" + }, + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "_E93F91B2-E00F-417A-855A-B203615EF628", + "IdentifiedObject.name": "line1_B", + "ACLineSegmentPhase.phase": "SinglePhaseKind.B", + "ACLineSegmentPhase.sequenceNumber": 2, + "PowerSystemResource.Location": "Location::'line1_Loc'" + }, + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "_29601914-BE61-417C-A333-0AD243A0A9C2", + "IdentifiedObject.name": "line1_C", + "ACLineSegmentPhase.phase": "SinglePhaseKind.C", + "ACLineSegmentPhase.sequenceNumber": 3, + "PowerSystemResource.Location": "Location::'line1_Loc'" + } + ] + }, + "line2": { + "Ravens.CimObjectType": "ACLineSegment", + "IdentifiedObject.mRID": "_4BFECD8D-AB5A-4D82-BB7D-6AEAE0378878", + "IdentifiedObject.name": "line2", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4000'", + "Conductor.length": 500, + "PowerSystemResource.Location": "Location::'line2_Loc'", + "ACLineSegment.PerLengthImpedance": "PerLengthPhaseImpedance::'zabc'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "_4308397E-D8AA-4109-9F42-AFB3095DEF49", + "IdentifiedObject.name": "line2_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.ConnectivityNode": "ConnectivityNode::'x2'" + }, + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "_1FE3FC50-F1F6-4359-A291-27F931567289", + "IdentifiedObject.name": "line2_T2", + "ACDCTerminal.sequenceNumber": 2, + "Terminal.ConnectivityNode": "ConnectivityNode::'b2'" + } + ], + "ACLineSegment.ACLineSegmentPhase": [ + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "_E7299BD3-2968-4C64-B698-F3E551AA8DC5", + "IdentifiedObject.name": "line2_A", + "ACLineSegmentPhase.phase": "SinglePhaseKind.A", + "ACLineSegmentPhase.sequenceNumber": 1, + "PowerSystemResource.Location": "Location::'line2_Loc'" + }, + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "_9156496B-AEBC-4632-81FB-D604FE43C564", + "IdentifiedObject.name": "line2_B", + "ACLineSegmentPhase.phase": "SinglePhaseKind.B", + "ACLineSegmentPhase.sequenceNumber": 2, + "PowerSystemResource.Location": "Location::'line2_Loc'" + }, + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "_1CFA79DC-393D-4F62-BE02-23EDA5542A72", + "IdentifiedObject.name": "line2_C", + "ACLineSegmentPhase.phase": "SinglePhaseKind.C", + "ACLineSegmentPhase.sequenceNumber": 3, + "PowerSystemResource.Location": "Location::'line2_Loc'" + } + ] + } + } + }, + "Switch": { + "switch": { + "Ravens.CimObjectType": "LoadBreakSwitch", + "IdentifiedObject.mRID": "_3E3C08FF-B3E1-44E7-B5EA-DB922C485D57", + "IdentifiedObject.name": "switch", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4000'", + "ProtectedSwitch.breakingCapacity": 325, + "Switch.ratedCurrent": 325, + "Switch.normalOpen": "false", + "Switch.open": "false", + "Switch.retained": "true", + "PowerSystemResource.Location": "Location::'switch_Loc'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "_9294CBC6-783E-4840-8196-357BFF6BA45A", + "IdentifiedObject.name": "switch_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.ConnectivityNode": "ConnectivityNode::'b1'", + "Terminal.phases": "PhaseCode.ABC" + }, + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "_E1443DD5-526D-47E3-A87A-0C1F0A9B2DDC", + "IdentifiedObject.name": "switch_T2", + "ACDCTerminal.sequenceNumber": 2, + "Terminal.ConnectivityNode": "ConnectivityNode::'x2'", + "Terminal.phases": "PhaseCode.ABC" + } + ] + } + } + } + } + }, + "LoadResponseCharacteristic": { + "Constant kVA": { + "Ravens.CimObjectType": "LoadResponseCharacteristic", + "IdentifiedObject.mRID": "_289E6326-E370-4C24-A190-53BFCC2C8848", + "IdentifiedObject.name": "Constant kVA", + "LoadResponseCharacteristic.exponentModel": "false", + "LoadResponseCharacteristic.pConstantImpedance": 0, + "LoadResponseCharacteristic.pConstantCurrent": 0, + "LoadResponseCharacteristic.pConstantPower": 100, + "LoadResponseCharacteristic.qConstantImpedance": 0, + "LoadResponseCharacteristic.qConstantCurrent": 0, + "LoadResponseCharacteristic.qConstantPower": 100, + "LoadResponseCharacteristic.pVoltageExponent": 0, + "LoadResponseCharacteristic.qVoltageExponent": 0, + "LoadResponseCharacteristic.pFrequencyExponent": 0, + "LoadResponseCharacteristic.qFrequencyExponent": 0 + }, + "Constant Z": { + "Ravens.CimObjectType": "LoadResponseCharacteristic", + "IdentifiedObject.mRID": "_A48E7B14-EF00-4F4D-A66E-0A92D0D5FD79", + "IdentifiedObject.name": "Constant Z", + "LoadResponseCharacteristic.exponentModel": "false", + "LoadResponseCharacteristic.pConstantImpedance": 100, + "LoadResponseCharacteristic.pConstantCurrent": 0, + "LoadResponseCharacteristic.pConstantPower": 0, + "LoadResponseCharacteristic.qConstantImpedance": 100, + "LoadResponseCharacteristic.qConstantCurrent": 0, + "LoadResponseCharacteristic.qConstantPower": 0, + "LoadResponseCharacteristic.pVoltageExponent": 0, + "LoadResponseCharacteristic.qVoltageExponent": 0, + "LoadResponseCharacteristic.pFrequencyExponent": 0, + "LoadResponseCharacteristic.qFrequencyExponent": 0 + }, + "Motor": { + "Ravens.CimObjectType": "LoadResponseCharacteristic", + "IdentifiedObject.mRID": "_F9289DA6-1EE6-4075-A5BE-BA990ABA3B40", + "IdentifiedObject.name": "Motor", + "LoadResponseCharacteristic.exponentModel": "false", + "LoadResponseCharacteristic.pConstantImpedance": 0, + "LoadResponseCharacteristic.pConstantCurrent": 0, + "LoadResponseCharacteristic.pConstantPower": 100, + "LoadResponseCharacteristic.qConstantImpedance": 100, + "LoadResponseCharacteristic.qConstantCurrent": 0, + "LoadResponseCharacteristic.qConstantPower": 0, + "LoadResponseCharacteristic.pVoltageExponent": 0, + "LoadResponseCharacteristic.qVoltageExponent": 0, + "LoadResponseCharacteristic.pFrequencyExponent": 0, + "LoadResponseCharacteristic.qFrequencyExponent": 0 + }, + "Mix Motor/Res": { + "Ravens.CimObjectType": "LoadResponseCharacteristic", + "IdentifiedObject.mRID": "_EDC6EAFB-A22C-45F1-AF5C-9DE0CCAA51EC", + "IdentifiedObject.name": "Mix Motor/Res", + "LoadResponseCharacteristic.exponentModel": "true", + "LoadResponseCharacteristic.pConstantImpedance": 0, + "LoadResponseCharacteristic.pConstantCurrent": 0, + "LoadResponseCharacteristic.pConstantPower": 0, + "LoadResponseCharacteristic.qConstantImpedance": 0, + "LoadResponseCharacteristic.qConstantCurrent": 0, + "LoadResponseCharacteristic.qConstantPower": 0, + "LoadResponseCharacteristic.pVoltageExponent": 1, + "LoadResponseCharacteristic.qVoltageExponent": 2, + "LoadResponseCharacteristic.pFrequencyExponent": 0, + "LoadResponseCharacteristic.qFrequencyExponent": 0 + }, + "Constant I": { + "Ravens.CimObjectType": "LoadResponseCharacteristic", + "IdentifiedObject.mRID": "_585ED09B-E47D-4EB9-9DB5-FD74719C3125", + "IdentifiedObject.name": "Constant I", + "LoadResponseCharacteristic.exponentModel": "false", + "LoadResponseCharacteristic.pConstantImpedance": 0, + "LoadResponseCharacteristic.pConstantCurrent": 100, + "LoadResponseCharacteristic.pConstantPower": 0, + "LoadResponseCharacteristic.qConstantImpedance": 0, + "LoadResponseCharacteristic.qConstantCurrent": 100, + "LoadResponseCharacteristic.qConstantPower": 0, + "LoadResponseCharacteristic.pVoltageExponent": 0, + "LoadResponseCharacteristic.qVoltageExponent": 0, + "LoadResponseCharacteristic.pFrequencyExponent": 0, + "LoadResponseCharacteristic.qFrequencyExponent": 0 + }, + "Variable P, Fixed Q": { + "Ravens.CimObjectType": "LoadResponseCharacteristic", + "IdentifiedObject.mRID": "_72B0F5AF-3B37-4467-82B5-C425210463B1", + "IdentifiedObject.name": "Variable P, Fixed Q", + "LoadResponseCharacteristic.exponentModel": "false", + "LoadResponseCharacteristic.pConstantImpedance": 0, + "LoadResponseCharacteristic.pConstantCurrent": 0, + "LoadResponseCharacteristic.pConstantPower": 100, + "LoadResponseCharacteristic.qConstantImpedance": 0, + "LoadResponseCharacteristic.qConstantCurrent": 0, + "LoadResponseCharacteristic.qConstantPower": 100, + "LoadResponseCharacteristic.pVoltageExponent": 0, + "LoadResponseCharacteristic.qVoltageExponent": 0, + "LoadResponseCharacteristic.pFrequencyExponent": 0, + "LoadResponseCharacteristic.qFrequencyExponent": 0 + }, + "Variable P, Fixed X": { + "Ravens.CimObjectType": "LoadResponseCharacteristic", + "IdentifiedObject.mRID": "_A5CAED93-49D2-4F4F-AD82-524C76A76AC5", + "IdentifiedObject.name": "Variable P, Fixed X", + "LoadResponseCharacteristic.exponentModel": "false", + "LoadResponseCharacteristic.pConstantImpedance": 0, + "LoadResponseCharacteristic.pConstantCurrent": 0, + "LoadResponseCharacteristic.pConstantPower": 100, + "LoadResponseCharacteristic.qConstantImpedance": 100, + "LoadResponseCharacteristic.qConstantCurrent": 0, + "LoadResponseCharacteristic.qConstantPower": 0, + "LoadResponseCharacteristic.pVoltageExponent": 0, + "LoadResponseCharacteristic.qVoltageExponent": 0, + "LoadResponseCharacteristic.pFrequencyExponent": 0, + "LoadResponseCharacteristic.qFrequencyExponent": 0 + } + }, + "PerLengthLineParameter": { + "PerLengthImpedance": { + "PerLengthPhaseImpedance": { + "zabc": { + "Ravens.CimObjectType": "PerLengthPhaseImpedance", + "IdentifiedObject.mRID": "_6DB02495-150A-479A-A9A5-8429B6E4DA8E", + "IdentifiedObject.name": "zabc", + "PerLengthPhaseImpedance.conductorCount": 3, + "PerLengthPhaseImpedance.PhaseImpedanceData": [ + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 1, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.00022721762, + "PhaseImpedanceData.x": 0.00087932601, + "PhaseImpedanceData.b": 0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 2, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 5.9217624e-05, + "PhaseImpedanceData.x": 0.00054106971, + "PhaseImpedanceData.b": 0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 2, + "PhaseImpedanceData.column": 2, + "PhaseImpedanceData.r": 0.00022721762, + "PhaseImpedanceData.x": 0.00087932601, + "PhaseImpedanceData.b": 0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 5.9217624e-05, + "PhaseImpedanceData.x": 0.0004755458, + "PhaseImpedanceData.b": 0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 2, + "PhaseImpedanceData.r": 5.9217624e-05, + "PhaseImpedanceData.x": 0.00051653344, + "PhaseImpedanceData.b": 0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 3, + "PhaseImpedanceData.r": 0.00022721762, + "PhaseImpedanceData.x": 0.00087932601, + "PhaseImpedanceData.b": 0 + } + ] + }, + "goab_disswitch_3_8_3_5": { + "Ravens.CimObjectType": "PerLengthPhaseImpedance", + "IdentifiedObject.mRID": "_E4EED264-402C-4DF0-A23D-0D289762C4A3", + "IdentifiedObject.name": "goab_disswitch_3_8_3_5", + "PerLengthPhaseImpedance.conductorCount": 3, + "PerLengthPhaseImpedance.PhaseImpedanceData": [ + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 1, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 1e-06, + "PhaseImpedanceData.x": 1e-06, + "PhaseImpedanceData.b": 1.3193042e-09 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 2, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0, + "PhaseImpedanceData.x": 0, + "PhaseImpedanceData.b": -4.1228239e-11 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 2, + "PhaseImpedanceData.column": 2, + "PhaseImpedanceData.r": 1e-06, + "PhaseImpedanceData.x": 1e-06, + "PhaseImpedanceData.b": 1.3193042e-09 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0, + "PhaseImpedanceData.x": 0, + "PhaseImpedanceData.b": -4.1228239e-11 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 2, + "PhaseImpedanceData.r": 0, + "PhaseImpedanceData.x": 0, + "PhaseImpedanceData.b": -4.1228239e-11 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 3, + "PhaseImpedanceData.r": 1e-06, + "PhaseImpedanceData.x": 1e-06, + "PhaseImpedanceData.b": 1.3193042e-09 + } + ] + } + } + } + } +} diff --git a/test/opf_ravens.jl b/test/opf_ravens.jl new file mode 100644 index 000000000..4b8a80484 --- /dev/null +++ b/test/opf_ravens.jl @@ -0,0 +1,70 @@ +@info "running optimal power flow (opf) tests using RAVENS data" + +@testset "test opf ravens" begin + + @testset "ravens case 3 with gens" begin + pmd_model = instantiate_mc_model_ravens(ravens_case3_withgens, ACPUPowerModel, build_mc_opf) + result = optimize_model!( + pmd_model, + relax_integrality=false, + optimizer=ipopt_solver, + solution_processors=Function[] + ) + @test result["termination_status"] == LOCALLY_SOLVED + end + + @testset "ravens case 3 with PV and storage" begin + pmd_model = instantiate_mc_model_ravens(ravens_case3_withpvandstorage, ACPUPowerModel, build_mc_opf) + result = optimize_model!( + pmd_model, + relax_integrality=false, + optimizer=ipopt_solver, + solution_processors=Function[] + ) + @test result["termination_status"] == LOCALLY_SOLVED + end + + @testset "ravens case 3 with subxf" begin + pmd_model = instantiate_mc_model_ravens(ravens_case3_withsubxf, ACPUPowerModel, build_mc_opf) + result = optimize_model!( + pmd_model, + relax_integrality=false, + optimizer=ipopt_solver, + solution_processors=Function[] + ) + @test result["termination_status"] == LOCALLY_SOLVED + end + + @testset "ravens case 3 with capacitor" begin + pmd_model = instantiate_mc_model_ravens(ravens_case3_withcap, ACPUPowerModel, build_mc_opf) + result = optimize_model!( + pmd_model, + relax_integrality=false, + optimizer=ipopt_solver, + solution_processors=Function[] + ) + @test result["termination_status"] == LOCALLY_SOLVED + end + + @testset "ravens test with switches 3w" begin + pmd_model = instantiate_mc_model_ravens(ravens_test_switch_3w, ACPUPowerModel, build_mc_opf) + result = optimize_model!( + pmd_model, + relax_integrality=false, + optimizer=ipopt_solver, + solution_processors=Function[] + ) + @test result["termination_status"] == LOCALLY_SOLVED + end + + # @testset "ravens test with switches 1w" begin + # pmd_model = instantiate_mc_model_ravens(ravens_test_switch_1w, ACPUPowerModel, build_mc_opf) + # result = optimize_model!( + # pmd_model, + # relax_integrality=false, + # optimizer=ipopt_solver, + # solution_processors=Function[] + # ) + # @test result["termination_status"] == LOCALLY_SOLVED + # end +end diff --git a/test/runtests.jl b/test/runtests.jl index 167b4f52b..405ce41dd 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -66,4 +66,6 @@ include("test_cases.jl") include("en_pf_native_validation.jl") include("line_constants.jl") + + include("opf_ravens.jl") end diff --git a/test/test_cases.jl b/test/test_cases.jl index 1d3e03cb6..a6a476a9a 100644 --- a/test/test_cases.jl +++ b/test/test_cases.jl @@ -68,3 +68,11 @@ dist_transformer = parse_file("../test/data/opendss/dist_transformer.dss") # IEEE13 Feeder IEEE13_Feeder_engr = parse_file("../test/data/opendss/ieee13_feeder.dss", multinetwork=true, time_series="daily", transformations=[remove_line_limits!, remove_transformer_limits!]) + +# RAVENS +ravens_case3_withgens = parse_file("../test/data/ravens/ravens_case3_withgens.json") +ravens_case3_withpvandstorage = parse_file("../test/data/ravens/ravens_case3_withpvandstorage.json") +ravens_case3_withsubxf = parse_file("../test/data/ravens/ravens_case3_withsubxf.json") +ravens_case3_withcap = parse_file("../test/data/ravens/ravens_case3_withcap.json") +ravens_test_switch_3w = parse_file("../test/data/ravens/ravens_test_switch_3w.json") +# ravens_test_switch_1w = parse_file("../test/data/ravens/ravens_test_switch_1w.json") From 70b5b74ca37f273cbc11f9b9b20da647b530bb97 Mon Sep 17 00:00:00 2001 From: jjospina Date: Thu, 30 Jan 2025 13:13:43 -0700 Subject: [PATCH 27/27] ADD: support for basic multinetwork functionality using RAVENS schema based on BasicIntervalSchedule. --- src/data_model/transformations/ravens2math.jl | 223 ++++-- src/data_model/utils_ravens.jl | 16 + src/io/common.jl | 30 +- src/prob/common.jl | 2 +- .../data/ravens/ravens_case3_withgens_mn.json | 737 ++++++++++++++++++ test/opf_ravens.jl | 12 + test/test_cases.jl | 1 + 7 files changed, 947 insertions(+), 74 deletions(-) create mode 100644 test/data/ravens/ravens_case3_withgens_mn.json diff --git a/src/data_model/transformations/ravens2math.jl b/src/data_model/transformations/ravens2math.jl index fb56328fb..045a98ddc 100644 --- a/src/data_model/transformations/ravens2math.jl +++ b/src/data_model/transformations/ravens2math.jl @@ -43,13 +43,9 @@ function transform_data_model_ravens( current_data_model = get(data, "data_model", MATHEMATICAL) - ## TODO - # if multinetwork && !ismultinetwork(data) - # data = make_multinetwork(data; global_keys=global_keys) - # end - data_math = _map_ravens2math( data; + multinetwork=multinetwork, kron_reduce=kron_reduce, phase_project=phase_project, ravens2math_extensions=ravens2math_extensions, @@ -68,6 +64,7 @@ end "base function for converting ravens model to mathematical model" function _map_ravens2math( data_ravens::Dict{String,<:Any}; + multinetwork::Bool=false, kron_reduce::Bool=true, phase_project::Bool=false, ravens2math_extensions::Vector{<:Function}=Function[], @@ -86,24 +83,69 @@ function _map_ravens2math( "vbases_default" => Dict{String,Real}() ) - ## TODO: Multinetwork - if ismultinetwork(data_ravens) + # Multinetwork + if multinetwork data_math = Dict{String,Any}( "name" => get(_data_ravens, "name", ""), "data_model" => MATHEMATICAL, - "nw" => Dict{String,Any}( - n => Dict{String,Any}( - "per_unit" => get(_data_ravens, "per_unit", false), - "is_projected" => get(nw, "is_projected", false), - "is_kron_reduced" => get(nw, "is_kron_reduced", true), # TODO: Kron reduction? - "settings" => deepcopy(_settings), - "time_elapsed" => get(nw, "time_elapsed", 1.0), - ) for (n,nw) in _data_ravens["nw"] - ), - "multinetwork" => ismultinetwork(data_ravens), - [k => data_ravens[k] for k in global_keys if haskey(data_ravens, k)]... + "multinetwork" => multinetwork, + "nw" => Dict{String,Any}() ) - else + + if haskey(data_ravens, "BasicIntervalSchedule") + schdls = get(data_ravens, "BasicIntervalSchedule", Dict{String,Any}()) # Get schedules/timeseries + + # Check for shortest timeseries. Use that length for mn + min_length = Inf + for (name, ravens_obj) in schdls + if haskey(ravens_obj, "EnergyConsumerSchedule.RegularTimePoints") + points = ravens_obj["EnergyConsumerSchedule.RegularTimePoints"] + length_points = length(points) + + if length_points < min_length + min_length = length_points + end + end + end + + # Throw error if no schedule/timeseries is found. + if min_length == Inf + throw("Minimum length is equal to Inf. Cannot do multinetwork with Inf timepoints.") + end + + # Vector to store nws dictionaries + nws_vect = Vector{Dict{String,Any}}(undef, min_length) + + # Multithreaded loop to create each nw dictionary. Store them in vector (to allow multithreading) + Threads.@threads for n=1:1:min_length + nw_dict = Dict{String,Any}( + string(n) => Dict{String,Any}( + "per_unit" => get(_data_ravens, "per_unit", false), + "is_projected" => get(_data_ravens, "is_projected", false), + "is_kron_reduced" => get(_data_ravens, "is_kron_reduced", true), # TODO: Kron reduction? + "settings" => deepcopy(_settings), + "time_elapsed" => get(_data_ravens, "time_elapsed", 1.0), + ) + ) + + # Store nw dict in vector + nws_vect[n] = nw_dict + + # Perform conversion ravens2math + apply_pmd!(_map_ravens2math_nw!, nws_vect[n], _data_ravens; ravens2math_passthrough=ravens2math_passthrough, ravens2math_extensions=ravens2math_extensions, nw=n) + + end + + # Merge dict in vector into data_math dictionary (other for loop to allow multithreading) + for nw_dict in nws_vect + merge!(data_math["nw"], nw_dict) + end + + else + @error("No timeseries and/or multinetwork information detected.") + end + + else # No multinetwork data_math = Dict{String,Any}( "name" => get(_data_ravens, "name", ""), "per_unit" => get(_data_ravens, "per_unit", false), @@ -113,11 +155,11 @@ function _map_ravens2math( "settings" => deepcopy(_settings), "time_elapsed" => get(_data_ravens, "time_elapsed", 1.0), ) + apply_pmd!(_map_ravens2math_nw!, data_math, _data_ravens; ravens2math_passthrough=ravens2math_passthrough, ravens2math_extensions=ravens2math_extensions) end - apply_pmd!(_map_ravens2math_nw!, data_math, _data_ravens; ravens2math_passthrough=ravens2math_passthrough, ravens2math_extensions=ravens2math_extensions) - - if ismultinetwork(data_ravens) + # multinetwork collections + if multinetwork _collect_nw_maps!(data_math) _collect_nw_bus_lookups!(data_math) end @@ -128,32 +170,65 @@ end """ """ -function _map_ravens2math_nw!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; ravens2math_passthrough::Dict{String,Vector{String}}=Dict{String,Vector{String}}(), ravens2math_extensions::Vector{<:Function}=Function[]) - data_math["map"] = Vector{Dict{String,Any}}([ - Dict{String,Any}("unmap_function" => "_map_math2ravens_root!") - ]) - - _init_base_components!(data_math) - - ## TODO - # for property in get(ravens2math_passthrough, "root", String[]) - # if haskey(data_ravens, property) - # data_math[property] = deepcopy(data_ravens[property]) - # end - # end - - for type in pmd_ravens_asset_types - getfield(PowerModelsDistribution, Symbol("_map_ravens2math_$(type)!"))(data_math, data_ravens; pass_props=get(ravens2math_passthrough, type, String[])) - end +function _map_ravens2math_nw!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; ravens2math_passthrough::Dict{String,Vector{String}}=Dict{String,Vector{String}}(), ravens2math_extensions::Vector{<:Function}=Function[], nw::Int=nw_id_default) - # Custom ravens2math transformation functions - for ravens2math_func! in ravens2math_extensions - ravens2math_func!(data_math, data_ravens) - end + if nw==0 - find_conductor_ids!(data_math) - _map_conductor_ids!(data_math) - _map_settings_vbases_default!(data_math) + data_math["map"] = Vector{Dict{String,Any}}([ + Dict{String,Any}("unmap_function" => "_map_math2ravens_root!") + ]) + + _init_base_components!(data_math) + + ## TODO + # for property in get(ravens2math_passthrough, "root", String[]) + # if haskey(data_ravens, property) + # data_math[property] = deepcopy(data_ravens[property]) + # end + # end + + for type in pmd_ravens_asset_types + getfield(PowerModelsDistribution, Symbol("_map_ravens2math_$(type)!"))(data_math, data_ravens; pass_props=get(ravens2math_passthrough, type, String[])) + end + + # Custom ravens2math transformation functions + for ravens2math_func! in ravens2math_extensions + ravens2math_func!(data_math, data_ravens) + end + + find_conductor_ids!(data_math) + _map_conductor_ids!(data_math) + _map_settings_vbases_default!(data_math) + + else + + data_math[string(nw)]["map"] = Vector{Dict{String,Any}}([ + Dict{String,Any}("unmap_function" => "_map_math2ravens_root!") + ]) + + _init_base_components!(data_math[string(nw)]) + + ## TODO + # for property in get(ravens2math_passthrough, "root", String[]) + # if haskey(data_ravens, property) + # data_math[property] = deepcopy(data_ravens[property]) + # end + # end + + for type in pmd_ravens_asset_types + getfield(PowerModelsDistribution, Symbol("_map_ravens2math_$(type)!"))(data_math[string(nw)], data_ravens; pass_props=get(ravens2math_passthrough, type, String[]), nw=nw) + end + + # Custom ravens2math transformation functions + for ravens2math_func! in ravens2math_extensions + ravens2math_func!(data_math[string(nw)], data_ravens) + end + + find_conductor_ids!(data_math[string(nw)]) + _map_conductor_ids!(data_math[string(nw)]) + _map_settings_vbases_default!(data_math[string(nw)]) + + end end @@ -161,7 +236,7 @@ end """ Converts ravens connectivity_node components into mathematical bus components. """ -function _map_ravens2math_connectivity_node!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) +function _map_ravens2math_connectivity_node!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[], nw::Int=nw_id_default) voltage_scale_factor_sqrt3 = data_math["settings"]["voltage_scale_factor"] * sqrt(3) connectivity_nodes = get(data_ravens, "ConnectivityNode", Dict{String,Any}()) @@ -206,7 +281,7 @@ end """ Converts ravens conductors (e.g., ACLineSegments) into mathematical branches. """ -function _map_ravens2math_conductor!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) +function _map_ravens2math_conductor!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[], nw::Int=nw_id_default) conductors = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["Conductor"] for (name, ravens_obj) in get(conductors, "ACLineSegment", Dict{Any,Dict{String,Any}}()) @@ -276,7 +351,7 @@ end # TODO: Transformers need a lot of changes/refactors!!! "converts ravens n-winding transformers into mathematical ideal 2-winding lossless transformer branches and impedance branches to represent the loss model" -function _map_ravens2math_power_transformer!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) +function _map_ravens2math_power_transformer!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[], nw::Int=nw_id_default) conducting_equipment = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"] power_scale_factor = data_math["settings"]["power_scale_factor"] @@ -467,7 +542,7 @@ end """ Converts ravens load components into mathematical load components. """ -function _map_ravens2math_energy_consumer!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) +function _map_ravens2math_energy_consumer!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[], nw::Int=nw_id_default) energy_connections = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"] power_scale_factor = data_math["settings"]["power_scale_factor"] voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] @@ -502,9 +577,41 @@ function _map_ravens2math_energy_consumer!(data_math::Dict{String,<:Any}, data_r math_obj["model"] = POWER end - # Set p and q - math_obj["pd"] = [ravens_obj["EnergyConsumer.p"] / power_scale_factor] - math_obj["qd"] = [ravens_obj["EnergyConsumer.q"] / power_scale_factor] + # Set p and q (w/ multinetwork support) + + if nw==0 + math_obj["pd"] = [ravens_obj["EnergyConsumer.p"] / power_scale_factor] + math_obj["qd"] = [ravens_obj["EnergyConsumer.q"] / power_scale_factor] + else + + # Get timeseries schedule + if haskey(ravens_obj, "EnergyConsumer.LoadForecast") + schdl_name = _extract_name(ravens_obj["EnergyConsumer.LoadForecast"]) + schdl = data_ravens["BasicIntervalSchedule"][schdl_name] + + # TODO: Define other types of timeseries (e.g., multipliers, etc.) + # units and multiplier modifiers + value1_multiplier = _multipliers_map[schdl["BasicIntervalSchedule.value1Multiplier"]] + value2_multiplier = _multipliers_map[schdl["BasicIntervalSchedule.value2Multiplier"]] + value1_unit = schdl["BasicIntervalSchedule.value1Unit"] + value2_unit = schdl["BasicIntervalSchedule.value2Unit"] + + if value1_unit == "W" + math_obj["pd"] = [schdl["EnergyConsumerSchedule.RegularTimePoints"][nw]["RegularTimePoint.value1"] * value1_multiplier / power_scale_factor] + end + if value1_unit == "VAr" + math_obj["qd"] = [schdl["EnergyConsumerSchedule.RegularTimePoints"][nw]["RegularTimePoint.value1"] * value1_multiplier / power_scale_factor] + end + if value2_unit == "W" + math_obj["pd"] = [schdl["EnergyConsumerSchedule.RegularTimePoints"][nw]["RegularTimePoint.value2"] * value2_multiplier / power_scale_factor] + end + if value2_unit == "VAr" + math_obj["qd"] = [schdl["EnergyConsumerSchedule.RegularTimePoints"][nw]["RegularTimePoint.value2"] * value2_multiplier / power_scale_factor] + end + else + @error("No timeseries, load forecast or multinetwork information found!") + end + end # Set the nominal voltage base_voltage_ref = _extract_name(ravens_obj["ConductingEquipment.BaseVoltage"]) @@ -597,7 +704,7 @@ end """ Converts ravens voltage sources into mathematical generators and (if needed) impedance branches to represent the loss model. """ -function _map_ravens2math_energy_source!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) +function _map_ravens2math_energy_source!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[], nw::Int=nw_id_default) energy_connections = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"] voltage_scale_factor = data_math["settings"]["voltage_scale_factor"] voltage_scale_factor_sqrt3 = voltage_scale_factor * sqrt(3) @@ -734,7 +841,7 @@ end "converts engineering generators into mathematical generators" -function _map_ravens2math_rotating_machine!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) +function _map_ravens2math_rotating_machine!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[], nw::Int=nw_id_default) energy_connections = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"] if haskey(energy_connections, "RegulatingCondEq") @@ -823,7 +930,7 @@ end "converts ravens power_electronics units such as PVs and Batteries into mathematical components" -function _map_ravens2math_power_electronics!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) +function _map_ravens2math_power_electronics!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[], nw::Int=nw_id_default) energy_connections = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"] if haskey(energy_connections, "RegulatingCondEq") @@ -995,7 +1102,7 @@ end "converts ravens switches into mathematical switches and (if neeed) impedance branches to represent loss model" -function _map_ravens2math_switch!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) +function _map_ravens2math_switch!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[], nw::Int=nw_id_default) conducting_equipment = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"] for (name, ravens_obj) in get(conducting_equipment, "Switch", Dict{Any,Dict{String,Any}}()) @@ -1074,7 +1181,7 @@ end "converts ravens generic shunt components into mathematical shunt components" -function _map_ravens2math_shunt_compensator!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[]) +function _map_ravens2math_shunt_compensator!(data_math::Dict{String,<:Any}, data_ravens::Dict{String,<:Any}; pass_props::Vector{String}=String[], nw::Int=nw_id_default) energy_connections = data_ravens["PowerSystemResource"]["Equipment"]["ConductingEquipment"]["EnergyConnection"] if haskey(energy_connections, "RegulatingCondEq") diff --git a/src/data_model/utils_ravens.jl b/src/data_model/utils_ravens.jl index 7091e60ae..f3e2e688f 100644 --- a/src/data_model/utils_ravens.jl +++ b/src/data_model/utils_ravens.jl @@ -9,6 +9,22 @@ const _phasecode_map = Dict( ) +const _multipliers_map = Dict( + "m" => 1e-3, + "c" => 1e-2, + "d" => 1e-1, + "da" => 1e1, + "h" => 1e2, + "k" => 1e3, + "M" => 1e6, + "G" => 1e9, + "T" => 1e12, + "P" => 1e15, + "E" => 1e18, + "Z" => 1e21 +) + + "initializes the base math object of any type" function _init_math_obj_ravens(obj_type::String, eng_id::Any, eng_obj::Dict{String,<:Any}, index::Int; pass_props::Vector{String}=String[])::Dict{String,Any} math_obj = Dict{String,Any}( diff --git a/src/io/common.jl b/src/io/common.jl index 6df3b742d..6a8a72252 100644 --- a/src/io/common.jl +++ b/src/io/common.jl @@ -105,22 +105,22 @@ function parse_file( ) end elseif filetype == "json" - if multinetwork && !ismultinetwork(pmd_data) - pmd_data = make_multinetwork(pmd_data; global_keys=global_keys) - end - if data_model == MATHEMATICAL && !ismath(pmd_data) - pmd_data = transform_data_model(pmd_data; - make_pu=make_pu, - make_pu_extensions=make_pu_extensions, - kron_reduce=kron_reduce, - phase_project=phase_project, - multinetwork=multinetwork, - global_keys=global_keys, - eng2math_extensions=eng2math_extensions, - eng2math_passthrough=eng2math_passthrough, - ) - end + ## TODO: may not be needed + # if data_model == MATHEMATICAL && !ismath(pmd_data) + # pmd_data = transform_data_model(pmd_data; + # make_pu=make_pu, + # make_pu_extensions=make_pu_extensions, + # kron_reduce=kron_reduce, + # phase_project=phase_project, + # multinetwork=multinetwork, + # global_keys=global_keys, + # eng2math_extensions=eng2math_extensions, + # eng2math_passthrough=eng2math_passthrough, + # ) + # end + + else error("only .dss and .json files are supported") end diff --git a/src/prob/common.jl b/src/prob/common.jl index 3ab55c1f6..1d0145694 100644 --- a/src/prob/common.jl +++ b/src/prob/common.jl @@ -138,7 +138,7 @@ function instantiate_mc_model_ravens( model_type::Type, build_method::Function; ref_extensions::Vector{<:Function}=Function[], - multinetwork::Bool=ismultinetwork(data), + multinetwork::Bool=false, global_keys::Set{String}=Set{String}(), ravens2math_extensions::Vector{<:Function}=Function[], ravens2math_passthrough::Dict{String,<:Vector{<:String}}=Dict{String,Vector{String}}(), diff --git a/test/data/ravens/ravens_case3_withgens_mn.json b/test/data/ravens/ravens_case3_withgens_mn.json new file mode 100644 index 000000000..e1eb5c059 --- /dev/null +++ b/test/data/ravens/ravens_case3_withgens_mn.json @@ -0,0 +1,737 @@ +{ + "PerLengthLineParameter": { + "PerLengthImpedance": { + "PerLengthPhaseImpedance": { + "4/0quad": { + "Ravens.CimObjectType": "PerLengthPhaseImpedance", + "IdentifiedObject.mRID": "88bc7e59-e9ce-4600-a949-3e2cecbc2fda", + "IdentifiedObject.name": "4/0quad", + "PerLengthPhaseImpedance.conductorCount": 3, + "PerLengthPhaseImpedance.PhaseImpedanceData": [ + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 2, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.0467, + "PhaseImpedanceData.x": 0.0267, + "PhaseImpedanceData.b": -0.0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 1, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.1167, + "PhaseImpedanceData.x": 0.0667, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 2, + "PhaseImpedanceData.r": 0.0467, + "PhaseImpedanceData.x": 0.0267, + "PhaseImpedanceData.b": -0.0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 3, + "PhaseImpedanceData.r": 0.1167, + "PhaseImpedanceData.x": 0.0667, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 2, + "PhaseImpedanceData.column": 2, + "PhaseImpedanceData.r": 0.1167, + "PhaseImpedanceData.x": 0.0667, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.0467, + "PhaseImpedanceData.x": 0.0267, + "PhaseImpedanceData.b": -0.0 + } + ] + }, + "556mcm": { + "Ravens.CimObjectType": "PerLengthPhaseImpedance", + "IdentifiedObject.mRID": "d6879f7a-124f-4e82-987a-46f5ba3e2f9d", + "IdentifiedObject.name": "556mcm", + "PerLengthPhaseImpedance.conductorCount": 3, + "PerLengthPhaseImpedance.PhaseImpedanceData": [ + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 3, + "PhaseImpedanceData.r": 0.1, + "PhaseImpedanceData.x": 0.0583, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.04, + "PhaseImpedanceData.x": 0.0233, + "PhaseImpedanceData.b": -0.0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 2, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.04, + "PhaseImpedanceData.x": 0.0233, + "PhaseImpedanceData.b": -0.0 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 2, + "PhaseImpedanceData.column": 2, + "PhaseImpedanceData.r": 0.1, + "PhaseImpedanceData.x": 0.0583, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 1, + "PhaseImpedanceData.column": 1, + "PhaseImpedanceData.r": 0.1, + "PhaseImpedanceData.x": 0.0583, + "PhaseImpedanceData.b": 1.6000000000000003e-05 + }, + { + "Ravens.CimObjectType": "PhaseImpedanceData", + "PhaseImpedanceData.row": 3, + "PhaseImpedanceData.column": 2, + "PhaseImpedanceData.r": 0.04, + "PhaseImpedanceData.x": 0.0233, + "PhaseImpedanceData.b": -0.0 + } + ] + } + } + } + }, + "PowerSystemResource": { + "Equipment": { + "ConductingEquipment": { + "EnergyConnection": { + "RegulatingCondEq": { + "RotatingMachine": { + "gen2": { + "Ravens.CimObjectType": "SynchronousMachine", + "IdentifiedObject.mRID": "c657d8a1-32c2-402f-8403-9b06c112318a", + "IdentifiedObject.name": "gen2", + "RotatingMachine.p": 1000.0, + "RotatingMachine.q": 484.3221048378525, + "RotatingMachine.ratedS": 1200.0, + "RotatingMachine.ratedU": 461.88021535170066, + "Equipment.inService": "true", + "RotatingMachine.ratedPowerFactor": 0.9, + "GeneratingUnit.minOperatingP": 0.0, + "GeneratingUnit.maxOperatingP": 1080.0, + "SynchronousMachine.maxQ": 523.0678732248807, + "SynchronousMachine.minQ": -523.0678732248807, + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "012eb2d2-f4d8-4cc9-825f-b634c66e5d84", + "IdentifiedObject.name": "gen2_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'primary'" + } + ] + }, + "gen1": { + "Ravens.CimObjectType": "SynchronousMachine", + "IdentifiedObject.mRID": "3f2267a8-4f0c-4ac5-9415-8568d7d414b2", + "IdentifiedObject.name": "gen1", + "RotatingMachine.p": 2000.0, + "RotatingMachine.q": 968.644209675705, + "RotatingMachine.ratedS": 2400.0, + "RotatingMachine.ratedU": 461.88021535170066, + "Equipment.inService": "true", + "RotatingMachine.ratedPowerFactor": 0.9, + "GeneratingUnit.minOperatingP": 0.0, + "GeneratingUnit.maxOperatingP": 2160.0, + "SynchronousMachine.maxQ": 1046.1357464497614, + "SynchronousMachine.minQ": -1046.1357464497614, + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "20cd756e-faae-47d9-a177-b605e6ae55fb", + "IdentifiedObject.name": "gen1_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ] + } + } + }, + "EnergySource": { + "source": { + "Ravens.CimObjectType": "EnergySource", + "IdentifiedObject.mRID": "494c011a-7640-4ed7-a3d5-2cd1a55413c0", + "IdentifiedObject.name": "source", + "EnergySource.nominalVoltage": 400.0, + "EnergySource.voltageMagnitude": 398.36, + "EnergySource.voltageAngle": 0.0, + "EnergySource.r": 3.880570000581328e-08, + "EnergySource.x": 1.5522280002325312e-07, + "EnergySource.r0": 5.069596039676399e-08, + "EnergySource.x0": 1.5208788119029196e-07, + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "327a6ba6-06c2-40ff-a0cc-550dd50d824d", + "IdentifiedObject.name": "source_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'sourcebus'" + } + ] + } + }, + "EnergyConsumer": { + "l2": { + "Ravens.CimObjectType": "EnergyConsumer", + "IdentifiedObject.mRID": "f227af26-b8ae-47b3-97cc-4d1e5d6bbfd3", + "IdentifiedObject.name": "l2", + "EnergyConsumer.p": 6000.0, + "EnergyConsumer.q": 3000.0, + "EnergyConsumer.customerCount": 1, + "EnergyConsumer.grounded": "true", + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "EnergyConsumer.phaseConnection": "PhaseShuntConnectionKind.Y", + "EnergyConsumer.LoadResponseCharacteristic": "LoadResponseCharacteristic::'Constant kVA'", + "EnergyConsumer.LoadForecast": "EnergyConsumerSchedule::'load_shape'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "9f8d612e-85f8-4757-9ff8-f9ae5947ddd8", + "IdentifiedObject.name": "l2_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.B", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ], + "EnergyConsumer.EnergyConsumerPhase": [ + { + "Ravens.CimObjectType": "EnergyConsumerPhase", + "IdentifiedObject.mRID": "f3cd189c-bd31-4fd4-beed-8967142aa0ea", + "IdentifiedObject.name": "l2_B", + "EnergyConsumerPhase.p": 6000.0, + "EnergyConsumerPhase.q": 3000.0, + "EnergyConsumerPhase.phase": "SinglePhaseKind.B" + } + ] + }, + "l1": { + "Ravens.CimObjectType": "EnergyConsumer", + "IdentifiedObject.mRID": "8bff0407-deee-4f99-92fa-1dee4047621e", + "IdentifiedObject.name": "l1", + "EnergyConsumer.p": 6000.0, + "EnergyConsumer.q": 3000.0, + "EnergyConsumer.customerCount": 1, + "EnergyConsumer.grounded": "true", + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "EnergyConsumer.phaseConnection": "PhaseShuntConnectionKind.Y", + "EnergyConsumer.LoadResponseCharacteristic": "LoadResponseCharacteristic::'Constant kVA'", + "EnergyConsumer.LoadForecast": "EnergyConsumerSchedule::'load_shape'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "4c93404d-1381-4fb2-b2db-36da5d6a0583", + "IdentifiedObject.name": "l1_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.A", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ], + "EnergyConsumer.EnergyConsumerPhase": [ + { + "Ravens.CimObjectType": "EnergyConsumerPhase", + "IdentifiedObject.mRID": "d4f8dc3a-8a95-4361-968a-1d841de4d7d1", + "IdentifiedObject.name": "l1_A", + "EnergyConsumerPhase.p": 6000.0, + "EnergyConsumerPhase.q": 3000.0, + "EnergyConsumerPhase.phase": "SinglePhaseKind.A" + } + ] + }, + "l3": { + "Ravens.CimObjectType": "EnergyConsumer", + "IdentifiedObject.mRID": "f8e9430c-56a5-44c3-8b53-98464182dec3", + "IdentifiedObject.name": "l3", + "EnergyConsumer.p": 6000.0, + "EnergyConsumer.q": 3000.0, + "EnergyConsumer.customerCount": 1, + "EnergyConsumer.grounded": "true", + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "EnergyConsumer.phaseConnection": "PhaseShuntConnectionKind.Y", + "EnergyConsumer.LoadResponseCharacteristic": "LoadResponseCharacteristic::'Constant kVA'", + "EnergyConsumer.LoadForecast": "EnergyConsumerSchedule::'load_shape'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "ec5de9d0-8f3a-409c-afaa-5dd15969842f", + "IdentifiedObject.name": "l3_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.C", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ], + "EnergyConsumer.EnergyConsumerPhase": [ + { + "Ravens.CimObjectType": "EnergyConsumerPhase", + "IdentifiedObject.mRID": "cdb85d03-72cd-4c1a-aa27-ee985895d65c", + "IdentifiedObject.name": "l3_C", + "EnergyConsumerPhase.p": 6000.0, + "EnergyConsumerPhase.q": 3000.0, + "EnergyConsumerPhase.phase": "SinglePhaseKind.C" + } + ] + } + } + }, + "Conductor": { + "ACLineSegment": { + "ohline": { + "Ravens.CimObjectType": "ACLineSegment", + "IdentifiedObject.mRID": "357e3f68-a996-4ef9-8e29-5a9701da50f5", + "IdentifiedObject.name": "ohline", + "Conductor.length": 1.0, + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "ACLineSegment.PerLengthImpedance": "PerLengthPhaseImpedance::'556mcm'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "262a28c0-79c8-46f8-be2f-48baba94b09b", + "IdentifiedObject.name": "ohline_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'sourcebus'" + }, + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "20c1e2b3-faab-4f16-9d28-1438cf5adc31", + "IdentifiedObject.name": "ohline_T2", + "ACDCTerminal.sequenceNumber": 2, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'primary'" + } + ], + "ACLineSegment.ACLineSegmentPhase": [ + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "43a9f788-638f-48c5-9211-437795fad9da", + "IdentifiedObject.name": "ohline_A", + "ACLineSegmentPhase.phase": "SinglePhaseKind.A", + "ACLineSegmentPhase.sequenceNumber": 1 + }, + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "939db8dd-1631-44e8-aa9d-cb391f06136d", + "IdentifiedObject.name": "ohline_B", + "ACLineSegmentPhase.phase": "SinglePhaseKind.B", + "ACLineSegmentPhase.sequenceNumber": 2 + }, + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "8a764636-52d0-470f-abcd-9cee75f114de", + "IdentifiedObject.name": "ohline_C", + "ACLineSegmentPhase.phase": "SinglePhaseKind.C", + "ACLineSegmentPhase.sequenceNumber": 3 + } + ] + }, + "quad": { + "Ravens.CimObjectType": "ACLineSegment", + "IdentifiedObject.mRID": "b0c876f2-8724-4b1d-9bb8-16ad6dc08866", + "IdentifiedObject.name": "quad", + "Conductor.length": 1.0, + "Equipment.inService": "true", + "ConductingEquipment.BaseVoltage": "BaseVoltage::'BaseV_0.4'", + "ACLineSegment.PerLengthImpedance": "PerLengthPhaseImpedance::'4/0quad'", + "ConductingEquipment.Terminals": [ + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "fba92277-7b25-42e3-8782-10e01ebf3ccf", + "IdentifiedObject.name": "quad_T1", + "ACDCTerminal.sequenceNumber": 1, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'primary'" + }, + { + "Ravens.CimObjectType": "Terminal", + "IdentifiedObject.mRID": "7a7bd627-5599-4139-bd71-a659a313fafc", + "IdentifiedObject.name": "quad_T2", + "ACDCTerminal.sequenceNumber": 2, + "Terminal.phases": "PhaseCode.ABC", + "Terminal.ConnectivityNode": "ConnectivityNode::'loadbus'" + } + ], + "ACLineSegment.ACLineSegmentPhase": [ + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "06ccbe19-290d-4808-8edb-40afc7e7c41e", + "IdentifiedObject.name": "quad_A", + "ACLineSegmentPhase.phase": "SinglePhaseKind.A", + "ACLineSegmentPhase.sequenceNumber": 1 + }, + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "79df9209-3379-4ce7-bd5b-2f927daccd8a", + "IdentifiedObject.name": "quad_B", + "ACLineSegmentPhase.phase": "SinglePhaseKind.B", + "ACLineSegmentPhase.sequenceNumber": 2 + }, + { + "Ravens.CimObjectType": "ACLineSegmentPhase", + "IdentifiedObject.mRID": "27dfc4e3-829a-4c4a-abb2-dab081e599c7", + "IdentifiedObject.name": "quad_C", + "ACLineSegmentPhase.phase": "SinglePhaseKind.C", + "ACLineSegmentPhase.sequenceNumber": 3 + } + ] + } + } + } + } + } + }, + "OperationalLimitSet": { + "OpLimV_360.00000000000006-440.00000000000006": { + "Ravens.CimObjectType": "OperationalLimitSet", + "IdentifiedObject.mRID": "1fd3801e-4bc9-4995-a833-b8a934a51856", + "IdentifiedObject.name": "OpLimV_360.00000000000006-440.00000000000006", + "OperationalLimitSet.OperationalLimitValue": [ + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "e2cbc64e-5a29-4df5-b214-f9ed9aa5cb5d", + "IdentifiedObject.name": "OpLimV_360.00000000000006-440.00000000000006_RangeAlow", + "VoltageLimit.value": 360.00000000000006, + "VoltageLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'lowType_5000000000.0s'" + }, + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "27d3baf8-3d5e-4465-9e84-3e52708211f1", + "IdentifiedObject.name": "OpLimV_360.00000000000006-440.00000000000006_RangeAhigh", + "VoltageLimit.value": 440.00000000000006, + "VoltageLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'highType_5000000000.0s'" + } + ] + }, + "OpLimV_380.0-420.00000000000006": { + "Ravens.CimObjectType": "OperationalLimitSet", + "IdentifiedObject.mRID": "35e30ea0-641e-43b7-a1e4-0e15e42334e1", + "IdentifiedObject.name": "OpLimV_380.0-420.00000000000006", + "OperationalLimitSet.OperationalLimitValue": [ + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "cce047bb-3dc5-4f08-85ae-401c93562f34", + "IdentifiedObject.name": "OpLimV_380.0-420.00000000000006_RangeAhigh", + "VoltageLimit.value": 420.00000000000006, + "VoltageLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'highType_5000000000.0s'" + }, + { + "Ravens.CimObjectType": "VoltageLimit", + "IdentifiedObject.mRID": "88c7ce0d-859b-4dda-bb25-64d33ba36831", + "IdentifiedObject.name": "OpLimV_380.0-420.00000000000006_RangeAlow", + "VoltageLimit.value": 380.0, + "VoltageLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'lowType_5000000000.0s'" + } + ] + }, + "OpLimI_400.0_600.0": { + "Ravens.CimObjectType": "OperationalLimitSet", + "IdentifiedObject.mRID": "47ba5a2e-b0e0-469d-b456-b74d90a89598", + "IdentifiedObject.name": "OpLimI_400.0_600.0", + "OperationalLimitSet.OperationalLimitValue": [ + { + "Ravens.CimObjectType": "CurrentLimit", + "IdentifiedObject.mRID": "ce6d7dcd-e426-44cb-ab33-9e8a6de1b60f", + "IdentifiedObject.name": "OpLimI_400.0_600.0_Emerg", + "CurrentLimit.value": 600.0, + "CurrentLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'absoluteValueType_86400.0s'" + }, + { + "Ravens.CimObjectType": "CurrentLimit", + "IdentifiedObject.mRID": "a301065e-a50e-4dd7-856b-c7035e9ea52f", + "IdentifiedObject.name": "OpLimI_400.0_600.0_Norm", + "CurrentLimit.value": 400.0, + "CurrentLimit.normalValue": 400.0, + "OperationalLimit.OperationalLimitType": "OperationalLimitType::'absoluteValueType_5000000000.0s'" + } + ] + } + }, + "Location": { + "primary_Location": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "db2f0d86-da66-46ac-adc1-6eec717cf555", + "IdentifiedObject.name": "primary_Location", + "Location.PositionPoints": [ + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 1, + "PositionPoint.xPosition": 0.0, + "PositionPoint.yPosition": 0.0 + } + ] + }, + "loadbus_Location": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "76056310-0c84-49e6-9d92-c0a3cce574e4", + "IdentifiedObject.name": "loadbus_Location", + "Location.PositionPoints": [ + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 1, + "PositionPoint.xPosition": 0.0, + "PositionPoint.yPosition": 0.0 + } + ] + }, + "sourcebus_Location": { + "Ravens.CimObjectType": "Location", + "IdentifiedObject.mRID": "4c73c3dd-7250-4f6a-af69-d203960b0a34", + "IdentifiedObject.name": "sourcebus_Location", + "Location.PositionPoints": [ + { + "Ravens.CimObjectType": "PositionPoint", + "PositionPoint.sequenceNumber": 1, + "PositionPoint.xPosition": 0.0, + "PositionPoint.yPosition": 0.0 + } + ] + } + }, + "Versions": { + "IEC61970CIMVersion": { + "Ravens.CimObjectType": "IEC61970CIMVersion", + "IEC61970CIMVersion.version": "IEC61970CIM100", + "IEC61970CIMVersion.date": "2019-04-01" + } + }, + "ConnectivityNode": { + "loadbus": { + "Ravens.CimObjectType": "ConnectivityNode", + "IdentifiedObject.mRID": "4ac8da05-a223-4bf6-b372-12c9479c495a", + "IdentifiedObject.name": "loadbus", + "ConnectivityNode.OperationalLimitSet": "OperationalLimitSet::'OpLimV_360.00000000000006-440.00000000000006'" + }, + "primary": { + "Ravens.CimObjectType": "ConnectivityNode", + "IdentifiedObject.mRID": "3e877b8a-ef33-4e18-8c80-1b05050bfc40", + "IdentifiedObject.name": "primary", + "ConnectivityNode.OperationalLimitSet": "OperationalLimitSet::'OpLimV_360.00000000000006-440.00000000000006'" + }, + "sourcebus": { + "Ravens.CimObjectType": "ConnectivityNode", + "IdentifiedObject.mRID": "d192d550-1fc0-489f-8e47-72209fa989e7", + "IdentifiedObject.name": "sourcebus" + } + }, + "OperationalLimitType": { + "absoluteValueType_86400.0s": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "d60da1eb-6a60-41ba-99df-7313cad312fa", + "IdentifiedObject.name": "absoluteValueType_86400.0s", + "OperationalLimitType.direction": "OperationalLimitDirectionKind.absoluteValue", + "OperationalLimitType.acceptableDuration": 86400.0 + }, + "highType_5000000000.0s": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "a1a82ad0-e426-4ecb-816a-5a58f034756b", + "IdentifiedObject.name": "highType_5000000000.0s", + "OperationalLimitType.direction": "OperationalLimitDirectionKind.high", + "OperationalLimitType.acceptableDuration": 5000000000.0 + }, + "lowType_5000000000.0s": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "1eaf0044-6272-4146-bf43-5c5310023469", + "IdentifiedObject.name": "lowType_5000000000.0s", + "OperationalLimitType.direction": "OperationalLimitDirectionKind.low", + "OperationalLimitType.acceptableDuration": 5000000000.0 + }, + "absoluteValueType_5000000000.0s": { + "Ravens.CimObjectType": "OperationalLimitType", + "IdentifiedObject.mRID": "1a39544c-2df7-46a9-a6c0-cfb28ab6eaab", + "IdentifiedObject.name": "absoluteValueType_5000000000.0s", + "OperationalLimitType.direction": "OperationalLimitDirectionKind.absoluteValue", + "OperationalLimitType.acceptableDuration": 5000000000.0 + } + }, + "LoadResponseCharacteristic": { + "Constant kVA": { + "Ravens.CimObjectType": "LoadResponseCharacteristic", + "IdentifiedObject.mRID": "777f5c7c-dea1-4a88-8db0-e5bd71a2fd4b", + "IdentifiedObject.name": "Constant kVA", + "LoadResponseCharacteristic.pConstantPower": 100, + "LoadResponseCharacteristic.qConstantPower": 100 + } + }, + "BaseVoltage": { + "BaseV_0.4": { + "Ravens.CimObjectType": "BaseVoltage", + "IdentifiedObject.mRID": "93c27318-44cd-41b7-a873-f9001d1b831f", + "IdentifiedObject.name": "BaseV_0.4", + "BaseVoltage.nominalVoltage": 400.0 + } + }, + "BasicIntervalSchedule": { + "load_shape": { + "EnergyConsumerSchedule.startDay": "Monday", + "BasicIntervalSchedule.value2Multiplier": "k", + "BasicIntervalSchedule.value1Multiplier": "k", + "Ravens.cimObjectType": "EnergyConsumerSchedule", + "BasicIntervalSchedule.value2Unit": "VAr", + "BasicIntervalSchedule.value1Unit": "W", + "EnergyConsumerSchedule.RegularTimePoints": [ + { + "RegularTimePoint.sequenceNumber": 1, + "RegularTimePoint.value2": 2.85, + "RegularTimePoint.value1": 6.0 + }, + { + "RegularTimePoint.sequenceNumber": 2, + "RegularTimePoint.value2": 3.19, + "RegularTimePoint.value1": 6.5 + }, + { + "RegularTimePoint.sequenceNumber": 3, + "RegularTimePoint.value2": 2.85, + "RegularTimePoint.value1": 6.0 + }, + { + "RegularTimePoint.sequenceNumber": 4, + "RegularTimePoint.value2": 2.90, + "RegularTimePoint.value1": 5.7 + }, + { + "RegularTimePoint.sequenceNumber": 5, + "RegularTimePoint.value2": 3.10, + "RegularTimePoint.value1": 6.8 + }, + { + "RegularTimePoint.sequenceNumber": 6, + "RegularTimePoint.value2": 2.95, + "RegularTimePoint.value1": 5.9 + }, + { + "RegularTimePoint.sequenceNumber": 7, + "RegularTimePoint.value2": 3.01, + "RegularTimePoint.value1": 6.1 + }, + { + "RegularTimePoint.sequenceNumber": 8, + "RegularTimePoint.value2": 2.89, + "RegularTimePoint.value1": 7.0 + }, + { + "RegularTimePoint.sequenceNumber": 9, + "RegularTimePoint.value2": 3.18, + "RegularTimePoint.value1": 5.6 + }, + { + "RegularTimePoint.sequenceNumber": 10, + "RegularTimePoint.value2": 2.94, + "RegularTimePoint.value1": 7.8 + }, + { + "RegularTimePoint.sequenceNumber": 11, + "RegularTimePoint.value2": 3.05, + "RegularTimePoint.value1": 5.4 + }, + { + "RegularTimePoint.sequenceNumber": 12, + "RegularTimePoint.value2": 2.88, + "RegularTimePoint.value1": 7.3 + }, + { + "RegularTimePoint.sequenceNumber": 13, + "RegularTimePoint.value2": 3.02, + "RegularTimePoint.value1": 6.5 + }, + { + "RegularTimePoint.sequenceNumber": 14, + "RegularTimePoint.value2": 2.92, + "RegularTimePoint.value1": 7.2 + }, + { + "RegularTimePoint.sequenceNumber": 15, + "RegularTimePoint.value2": 3.00, + "RegularTimePoint.value1": 5.8 + }, + { + "RegularTimePoint.sequenceNumber": 16, + "RegularTimePoint.value2": 2.98, + "RegularTimePoint.value1": 7.4 + }, + { + "RegularTimePoint.sequenceNumber": 17, + "RegularTimePoint.value2": 3.03, + "RegularTimePoint.value1": 5.9 + }, + { + "RegularTimePoint.sequenceNumber": 18, + "RegularTimePoint.value2": 2.91, + "RegularTimePoint.value1": 7.1 + }, + { + "RegularTimePoint.sequenceNumber": 19, + "RegularTimePoint.value2": 3.06, + "RegularTimePoint.value1": 5.7 + }, + { + "RegularTimePoint.sequenceNumber": 20, + "RegularTimePoint.value2": 2.99, + "RegularTimePoint.value1": 6.0 + }, + { + "RegularTimePoint.sequenceNumber": 21, + "RegularTimePoint.value2": 3.08, + "RegularTimePoint.value1": 5.6 + }, + { + "RegularTimePoint.sequenceNumber": 22, + "RegularTimePoint.value2": 2.97, + "RegularTimePoint.value1": 7.0 + }, + { + "RegularTimePoint.sequenceNumber": 23, + "RegularTimePoint.value2": 3.09, + "RegularTimePoint.value1": 5.8 + }, + { + "RegularTimePoint.sequenceNumber": 24, + "RegularTimePoint.value2": 2.96, + "RegularTimePoint.value1": 7.2 + } + ], + "IdentifiedObject.mRID": "95941138-5523-4e82-9ffa-d19e6f6acf70", + "EnergyConsumerSchedule.timeStep": 3600 + } + } +} diff --git a/test/opf_ravens.jl b/test/opf_ravens.jl index 4b8a80484..eacd32e8a 100644 --- a/test/opf_ravens.jl +++ b/test/opf_ravens.jl @@ -67,4 +67,16 @@ # ) # @test result["termination_status"] == LOCALLY_SOLVED # end + + @testset "ravens case 3 with gens multinetwork" begin + pmd_model = instantiate_mc_model_ravens(ravens_case3_withgens_mn, ACPUPowerModel, build_mn_mc_opf; multinetwork=true) + result = optimize_model!( + pmd_model, + relax_integrality=false, + optimizer=ipopt_solver, + solution_processors=Function[] + ) + @test result["termination_status"] == LOCALLY_SOLVED + end + end diff --git a/test/test_cases.jl b/test/test_cases.jl index a6a476a9a..3ff2c6436 100644 --- a/test/test_cases.jl +++ b/test/test_cases.jl @@ -76,3 +76,4 @@ ravens_case3_withsubxf = parse_file("../test/data/ravens/ravens_case3_withsubxf. ravens_case3_withcap = parse_file("../test/data/ravens/ravens_case3_withcap.json") ravens_test_switch_3w = parse_file("../test/data/ravens/ravens_test_switch_3w.json") # ravens_test_switch_1w = parse_file("../test/data/ravens/ravens_test_switch_1w.json") +ravens_case3_withgens_mn = parse_file("../test/data/ravens/ravens_case3_withgens_mn.json")