Building Engineering Data Models with Helper Functions
In this notebook we will demonstrate an easy way to start building new distribution network models in the engineering format using new helper functions add in PowerModelsDistribution v0.9
using PowerModelsDistribution
First, we need a optimizer. In this case we will use Ipopt and initialize it with JuMP's optimizer_with_attributes
, which we have exported from PowerModelsDistribution by default for the user
using LinearAlgebra: diagm
import Ipopt
ipopt_solver = optimizer_with_attributes(Ipopt.Optimizer, "print_level"=>0, "tol"=>1e-6)
MathOptInterface.OptimizerWithAttributes(Ipopt.Optimizer, Pair{MathOptInterface.AbstractOptimizerAttribute, Any}[MathOpt
Interface.RawParameter("print_level") => 0, MathOptInterface.RawParameter("tol") => 1.0e-6])
Initialize an empty ENGINEERING
model
eng = Model()
Dict{String, Any} with 3 entries:
"settings" => Dict{String, Any}("sbase_default"=>1.0, "vbases_default"=>Dic…
"per_unit" => false
"data_model" => ENGINEERING
In this block we build a three bus network, with neutrals grounded at the source and loads.
We start with buses, with the sourcebus and loadbus having 4 terminals, with the last terminal grounded.
Then we add a generation source, in this case a voltage source, which is WYE
configured by default, and therefore expects the last conductor to be a grounded neutral
We add two three phase lines to connect the buses sourcebus
, primary
, and loadbus
. Note that none of the lines have a neutral conductor.
We finally add a three-phase load a the loadbus
bus, but note again that this is a WYE
configured load, and like the voltage source, this implies that the last conductor is a grounded neutral for the purposes of kron reduction (which is required by default until explicit 4-wire modeling is added to PowerModelsDistribution)
Lastly, we need to define the default vbase of the system at the sourcebus
add_bus!(eng, "sourcebus"; terminals=[1,2,3,4], grounded=[4])
add_bus!(eng, "primary"; terminals=[1,2,3])
add_bus!(eng, "loadbus"; terminals=[1,2,3,4], grounded=[4])
add_voltage_source!(eng, "source", "sourcebus", [1,2,3,4]; vm=[1, 1, 1])
add_linecode!(eng, "default", diagm(0=>fill(0.01, 3)), diagm(0=>fill(0.2, 3)))
add_line!(eng, "trunk", "sourcebus", "primary", [1,2,3], [1,2,3]; linecode="default")
add_line!(eng, "primary", "primary", "loadbus", [1,2,3], [1,2,3]; linecode="default")
add_load!(eng, "balanced", "loadbus", [1,2,3,4]; pd_nom=[5, 5, 5], qd_nom=[1, 1, 1])
add_vbase_default!(eng, "sourcebus", 1)
eng
Dict{String, Any} with 8 entries:
"voltage_source" => Dict{Any, Any}("source"=>Dict{String, Any}("source_id"=>"…
"line" => Dict{Any, Any}("primary"=>Dict{String, Any}("length"=>1.0…
"settings" => Dict{String, Any}("sbase_default"=>1.0, "vbases_default"=…
"load" => Dict{Any, Any}("balanced"=>Dict{String, Any}("source_id"=…
"bus" => Dict{Any, Any}("primary"=>Dict{String, Any}("source_id"=>…
"linecode" => Dict{Any, Any}("default"=>Dict{String, Any}("b_fr"=>[0.0 …
"per_unit" => false
"data_model" => ENGINEERING
Running this case with OPF gives the results below
result = solve_mc_opf(eng, ACPPowerModel, ipopt_solver)
Error: BoundsError: attempt to access 3-element Vector{Int64} at index [Bool[1, 1, 1, 0]]
In the following example, we provide examples of a wider range of component types that can be added using helper functions to give a flavor of what is possible in PowerModelsDistribution v0.9
eng2 = deepcopy(eng)
add_bus!(eng2, "ttbus"; terminals=[1,2,3,4], grounded=[4])
add_transformer!(eng2, "tx1", "sourcebus", "ttbus", [1,2,3,4], [1,2,3,4])
add_bus!(eng2, "loadbus2"; terminals=[1,2,3,4], grounded=[4])
add_switch!(eng2, "breaker", "ttbus", "loadbus2", [1,2,3], [1,2,3])
add_load!(eng2, "tload", "loadbus2", [1,2,3,4]; pd_nom=[5, 5, 5], qd_nom=[1, 1, 1])
add_generator!(eng2, "secondary", "loadbus2", [1,2,3,4]; cost_pg_parameters=[0.0, 1.2, 0])
add_shunt!(eng2, "cap", "loadbus2", [1,2,3,4]; bs=diagm(0=>fill(1, 3)))
eng2
Dict{String, Any} with 12 entries:
"bus" => Dict{Any, Any}("primary"=>Dict{String, Any}("source_id"=>…
"settings" => Dict{String, Any}("sbase_default"=>1.0, "vbases_default"=…
"generator" => Dict{Any, Any}("secondary"=>Dict{String, Any}("source_id"…
"switch" => Dict{Any, Any}("breaker"=>Dict{String, Any}("source_id"=>…
"voltage_source" => Dict{Any, Any}("source"=>Dict{String, Any}("source_id"=>"…
"line" => Dict{Any, Any}("primary"=>Dict{String, Any}("length"=>1.0…
"per_unit" => false
"data_model" => ENGINEERING
"transformer" => Dict{Any, Any}("tx1"=>Dict{String, Any}("source_id"=>"tra…
"shunt" => Dict{Any, Any}("cap"=>Dict{String, Any}("source_id"=>"shu…
"load" => Dict{Any, Any}("tload"=>Dict{String, Any}("source_id"=>"l…
"linecode" => Dict{Any, Any}("default"=>Dict{String, Any}("b_fr"=>[0.0 …
result2 = solve_mc_opf(eng2, ACPPowerModel, ipopt_solver)
Error: BoundsError: attempt to access 3-element Vector{Int64} at index [Bool[1, 1, 1, 0]]