Connection DSL

NetworkBuilder represents an electrical connection with one named row for each connected element terminal. The four input fields are:

  • node: the explicit network-node name;
  • element: the name of the element in the element named tuple;
  • side: the physical element side, numbered from 1;
  • terminal: the conductor or transformed coordinate on that side, numbered from 1.

Repeating a node name joins all listed terminals at one multiway node. Rows remain separate so their input order, terminal identity, and electrical domain can be inspected after construction.

Sources, machines, converters, transformed components, and multiconductor components identify their AC or DC domain directly. A one-conductor passive element inherits a fixed domain through its connected nodes and otherwise retains the DC interpretation. Scalar passive d/q terminations are valid for frequency-domain calculations; use transformed three-phase elements when a power flow is required.

using PowerImpedance
using PowerImpedance.NetworkBuilder: Grid, NetworkTopology, define, solve;

Scalar DC network

A one-conductor impedance has one terminal on each of its two physical sides. The explicit :gnd node identifies the reference side.

dc_elements = (
    source = dc_source(setpoint = Setpoint(Vdc = 240.0)),
    branch = impedance(z = 2.0, pins = 1),
    load = impedance(z = 10.0, pins = 1)
);

dc_connections = (
    (node = :source_bus, element = :source, side = 1, terminal = 1),
    (node = :source_bus, element = :branch, side = 1, terminal = 1),
    (node = :load_bus, element = :branch, side = 2, terminal = 1),
    (node = :load_bus, element = :load, side = 1, terminal = 1),
    (node = :gnd, element = :load, side = 2, terminal = 1)
);

dc_network = define(dc_elements, dc_connections);
dc_network.topology.connections
Table with 6 columns and 5 rows:
     node        bus  element  side  terminal  domain
   ┌─────────────────────────────────────────────────
 1 │ source_bus  1    source   1     1         2
 2 │ source_bus  1    branch   1     1         2
 3 │ load_bus    2    branch   2     1         2
 4 │ load_bus    2    load     1     1         2
 5 │ gnd         0    load     2     1         2

The ideal source has one physical external terminal. It therefore receives one row; no artificial source-to-ground row is part of NetworkTopology. During small-signal construction the ideal source terminal is placed in the grounded-node selection because an ideal voltage source is a short circuit for perturbations.

dc_solution = solve(dc_network);
dc_solution.powerflow
[ Info: Network only consists of linear elements. Skipping power flow.

Transformed AC coordinates and multiway nodes

Three-phase elements with transformation=true expose d and q coordinates as terminals 1 and 2. Both belong to one AC power-flow bus, while their distinct node names preserve the two small-signal coordinates.

ac_elements = (
    grid = ac_source(
        setpoint = Setpoint(Vac = 220 * sqrt(2/3)),
        pins = 3,
        transformation = true
    ),
    branch_1 = impedance(
        z = 0.2 + 0.8im,
        pins = 3,
        transformation = true
    ),
    branch_2 = impedance(
        z = 0.4 + 1.2im,
        pins = 3,
        transformation = true
    )
);

ac_connections = (
    (node = :bus_d, element = :grid, side = 1, terminal = 1),
    (node = :bus_d, element = :branch_1, side = 1, terminal = 1),
    (node = :bus_d, element = :branch_2, side = 1, terminal = 1),
    (node = :bus_q, element = :grid, side = 1, terminal = 2),
    (node = :bus_q, element = :branch_1, side = 1, terminal = 2),
    (node = :bus_q, element = :branch_2, side = 1, terminal = 2),
    (node = :remote_1_d, element = :branch_1, side = 2, terminal = 1),
    (node = :remote_1_q, element = :branch_1, side = 2, terminal = 2),
    (node = :remote_2_d, element = :branch_2, side = 2, terminal = 1),
    (node = :remote_2_q, element = :branch_2, side = 2, terminal = 2)
);

ac_topology = NetworkTopology(ac_elements, ac_connections);
ac_topology.connections
Table with 6 columns and 10 rows:
      node        bus  element   side  terminal  domain
    ┌──────────────────────────────────────────────────
 1  │ bus_d       1    grid      1     1         1
 2  │ bus_d       1    branch_1  1     1         1
 3  │ bus_d       1    branch_2  1     1         1
 4  │ bus_q       1    grid      1     2         1
 5  │ bus_q       1    branch_1  1     2         1
 6  │ bus_q       1    branch_2  1     2         1
 7  │ remote_1_d  2    branch_1  2     1         1
 8  │ remote_1_q  2    branch_1  2     2         1
 9  │ remote_2_d  3    branch_2  2     1         1
 10 │ remote_2_q  3    branch_2  2     2         1

The first three rows share :bus_d, and the next three share :bus_q. NetworkTopology assigns bus indices independently in the AC and DC domains.

Multiconductor lines

Without a d/q transformation, a three-conductor line exposes terminals 1, 2, and 3 on both physical sides. Mutual terms remain in the dense component matrices; connection rows do not reduce the line to independent phases.

multiconductor_elements = (
    line = overhead_line(
    length = 1e3,
    conductors = Conductors(organization = :flat, nᵇ = 3)
),
);

multiconductor_connections = (
    (node = :sending_a, element = :line, side = 1, terminal = 1),
    (node = :sending_b, element = :line, side = 1, terminal = 2),
    (node = :sending_c, element = :line, side = 1, terminal = 3),
    (node = :receiving_a, element = :line, side = 2, terminal = 1),
    (node = :receiving_b, element = :line, side = 2, terminal = 2),
    (node = :receiving_c, element = :line, side = 2, terminal = 3)
);

multiconductor_topology = NetworkTopology(
    multiconductor_elements,
    multiconductor_connections
);
multiconductor_topology.connections
Table with 6 columns and 6 rows:
     node         bus  element  side  terminal  domain
   ┌──────────────────────────────────────────────────
 1 │ sending_a    1    line     1     1         2
 2 │ sending_b    1    line     1     2         2
 3 │ sending_c    1    line     1     3         2
 4 │ receiving_a  2    line     2     1         2
 5 │ receiving_b  2    line     2     2         2
 6 │ receiving_c  2    line     2     3         2

Passive component families

The following AC chain uses the same engineering parameters as the topology tests. It covers transformers, analytical overhead lines and cables, and imported black-box line data. Each transformed element has d and q terminals on sides 1 and 2.

passive_elements = (
    transformer = transformer(
        pins = 3,
        n = 1.0,
        Rₚ = 0.1,
        Lₚ = 1e-3,
        Rₛ = 0.1,
        Lₛ = 1e-3,
        transformation = true
    ),
    overhead = overhead_line(
        length = 1e3,
        conductors = Conductors(organization = :flat, nᵇ = 3),
        transformation = true
    ),
    cable = cable(
        length = 1e3,
        positions = [(-1.0, 1.0), (0.0, 1.0), (1.0, 1.0)],
        C1 = Conductor(rₒ = 0.01),
        transformation = true
    ),
    blackbox_line = blackbox_line(
        data_type = :Ztool,
        n = 3,
        transformation = true
    )
);

passive_connections = (
    (node = :p1_d, element = :transformer, side = 1, terminal = 1),
    (node = :p1_q, element = :transformer, side = 1, terminal = 2),
    (node = :p2_d, element = :transformer, side = 2, terminal = 1),
    (node = :p2_q, element = :transformer, side = 2, terminal = 2),
    (node = :p2_d, element = :overhead, side = 1, terminal = 1),
    (node = :p2_q, element = :overhead, side = 1, terminal = 2),
    (node = :p3_d, element = :overhead, side = 2, terminal = 1),
    (node = :p3_q, element = :overhead, side = 2, terminal = 2),
    (node = :p3_d, element = :cable, side = 1, terminal = 1),
    (node = :p3_q, element = :cable, side = 1, terminal = 2),
    (node = :p4_d, element = :cable, side = 2, terminal = 1),
    (node = :p4_q, element = :cable, side = 2, terminal = 2),
    (node = :p4_d, element = :blackbox_line, side = 1, terminal = 1),
    (node = :p4_q, element = :blackbox_line, side = 1, terminal = 2),
    (node = :p5_d, element = :blackbox_line, side = 2, terminal = 1),
    (node = :p5_q, element = :blackbox_line, side = 2, terminal = 2)
);

passive_topology = NetworkTopology(passive_elements, passive_connections);
passive_topology.connections
Table with 6 columns and 16 rows:
      node  bus  element        side  terminal  domain
    ┌─────────────────────────────────────────────────
 1  │ p1_d  1    transformer    1     1         1
 2  │ p1_q  1    transformer    1     2         1
 3  │ p2_d  2    transformer    2     1         1
 4  │ p2_q  2    transformer    2     2         1
 5  │ p2_d  2    overhead       1     1         1
 6  │ p2_q  2    overhead       1     2         1
 7  │ p3_d  3    overhead       2     1         1
 8  │ p3_q  3    overhead       2     2         1
 9  │ p3_d  3    cable          1     1         1
 10 │ p3_q  3    cable          1     2         1
 11 │ p4_d  4    cable          2     1         1
 12 │ p4_q  4    cable          2     2         1
 13 │ p4_d  4    blackbox_line  1     1         1
 14 │ p4_q  4    blackbox_line  1     2         1
 15 │ p5_d  5    blackbox_line  2     1         1
 16 │ p5_q  5    blackbox_line  2     2         1

Converter sides

MMC, two-level, and black-box converter models use side 1 for DC and side 2 for AC. The DC side has one terminal. A transformed AC side has d and q terminals. These definitions follow the same side ordering used by the validated PowerModelsACDC conversion.

delta_control = ΔdqControlGFL(
    outer_active = NoOuterActiveControl(),
    outer_reactive = NoOuterReactiveControl(),
    occ = NoInnerCurrentControl()
);

converter_elements = (
    dc_grid = dc_source(setpoint = Setpoint(Vdc = 240.0)),
    ac_grid = ac_source(pins = 3, transformation = true),
    mmc = mmc(
        sync = NoSynchronization(),
        delta_control = delta_control,
        sigma_control = ΣdqzControlTEC()
    ),
    tlc = tlc(),
    blackbox_converter = PowerImpedance.Element(
        input_pins = 1,
        output_pins = 2,
        element_model = PowerImpedance.Blackbox_MMC()
    )
);

converter_connections = (
    (node = :dc_bus, element = :dc_grid, side = 1, terminal = 1),
    (node = :dc_bus, element = :mmc, side = 1, terminal = 1),
    (node = :dc_bus, element = :tlc, side = 1, terminal = 1),
    (node = :dc_bus, element = :blackbox_converter, side = 1, terminal = 1),
    (node = :ac_bus_d, element = :ac_grid, side = 1, terminal = 1),
    (node = :ac_bus_d, element = :mmc, side = 2, terminal = 1),
    (node = :ac_bus_d, element = :tlc, side = 2, terminal = 1),
    (node = :ac_bus_d, element = :blackbox_converter, side = 2, terminal = 1),
    (node = :ac_bus_q, element = :ac_grid, side = 1, terminal = 2),
    (node = :ac_bus_q, element = :mmc, side = 2, terminal = 2),
    (node = :ac_bus_q, element = :tlc, side = 2, terminal = 2),
    (node = :ac_bus_q, element = :blackbox_converter, side = 2, terminal = 2)
);

converter_topology = NetworkTopology(converter_elements, converter_connections);
converter_topology.connections
Table with 6 columns and 12 rows:
      node      bus  element             side  terminal  domain
    ┌──────────────────────────────────────────────────────────
 1  │ dc_bus    1    dc_grid             1     1         2
 2  │ dc_bus    1    mmc                 1     1         2
 3  │ dc_bus    1    tlc                 1     1         2
 4  │ dc_bus    1    blackbox_converter  1     1         2
 5  │ ac_bus_d  1    ac_grid             1     1         1
 6  │ ac_bus_d  1    mmc                 2     1         1
 7  │ ac_bus_d  1    tlc                 2     1         1
 8  │ ac_bus_d  1    blackbox_converter  2     1         1
 9  │ ac_bus_q  1    ac_grid             1     2         1
 10 │ ac_bus_q  1    mmc                 2     2         1
 11 │ ac_bus_q  1    tlc                 2     2         1
 12 │ ac_bus_q  1    blackbox_converter  2     2         1

Synchronous and induction machines

Machine models expose one physical AC side. Transformed d and q coordinates are terminals 1 and 2 on that side.

machine_elements = (
    synchronous = synchronousmachine(),
    induction = inductionmachine()
);

machine_connections = (
    (node = :machine_bus_d, element = :synchronous, side = 1, terminal = 1),
    (node = :machine_bus_q, element = :synchronous, side = 1, terminal = 2),
    (node = :machine_bus_d, element = :induction, side = 1, terminal = 1),
    (node = :machine_bus_q, element = :induction, side = 1, terminal = 2)
);

machine_topology = NetworkTopology(machine_elements, machine_connections);
machine_topology.connections
Table with 6 columns and 4 rows:
     node           bus  element      side  terminal  domain
   ┌────────────────────────────────────────────────────────
 1 │ machine_bus_d  1    synchronous  1     1         1
 2 │ machine_bus_q  1    synchronous  1     2         1
 3 │ machine_bus_d  1    induction    1     1         1
 4 │ machine_bus_q  1    induction    1     2         1

Disconnected elements and validation

An element constructed with connection=false is omitted even if supplied rows mention it. Other malformed rows are rejected while the topology is constructed, before power flow or frequency evaluation begins.

disconnected = impedance(z = 5.0, pins = 1);
disconnected.connection = false;
disconnected_network = define(
    (; disconnected),
    ((node = :ignored, element = :disconnected, side = 1, terminal = 1),)
);
isempty(disconnected_network.topology.connections)

duplicate_terminal_error = try
    NetworkTopology(
        (branch = impedance(z = 2.0, pins = 1),),
        (
            (node = :first, element = :branch, side = 1, terminal = 1),
            (node = :second, element = :branch, side = 1, terminal = 1)
        )
    )
catch error
    error
end;
duplicate_terminal_error
ArgumentError("element :branch side 1 terminal 1 is assigned more than once")

Validation also rejects unknown elements, invalid side or terminal numbers, and a node name shared between AC and DC terminals. Nodes are never generated implicitly.

Deterministic parameter grids

Only the parameters receiving Grid values vary. The connection rows remain ordinary fixed data for each stochastic study case.

grid_elements = (
    branch = impedance(
        Grid;
        z = Grid([1.0, 2.0, 5.0]),
        pins = 1
    ),
    load = impedance(Grid; z = 10.0, pins = 1)
);

grid_connections = (
    (node = :bus, element = :branch, side = 1, terminal = 1),
    (node = :bus, element = :load, side = 1, terminal = 1),
    (node = :gnd, element = :branch, side = 2, terminal = 1),
    (node = :gnd, element = :load, side = 2, terminal = 1)
);

network_space = define(grid_elements, grid_connections);
length(network_space)

grid_problems = PowerImpedanceProblem(
    network_space;
    nodes = [:bus],
    frequency_range = (1.0, 1e3, 40)
);
grid_impedance = compute(
    ParametricProblem(grid_problems),
    Combinatorial(NodalImpedance())
);
grid_impedance
ParametricResult{FrequencyResponseResult{NodalImpedance{PowerImpedance.PIACDC}, Array{ComplexF64, 3}, Vector{ComplexF64}, Vector{Symbol}, PowerImpedance.NetworkBuilder.NetworkModel{ComplexF64}, @NamedTuple{linearization::LinearizationResult{AdmittanceLinearization{PowerImpedance.PIACDC}, PowerImpedance.NetworkBuilder.NetworkModel{ComplexF64}, @NamedTuple{powerflow_required::Bool, active_elements::Int64, passive_elements::Int64}}}}, Combinatorial{NodalImpedance{PowerImpedance.PIACDC}, PowerImpedance.PIACDC, :error}, Vector{FrequencyResponseResult{NodalImpedance{PowerImpedance.PIACDC}, Array{ComplexF64, 3}, Vector{ComplexF64}, Vector{Symbol}, PowerImpedance.NetworkBuilder.NetworkModel{ComplexF64}, @NamedTuple{linearization::LinearizationResult{AdmittanceLinearization{PowerImpedance.PIACDC}, PowerImpedance.NetworkBuilder.NetworkModel{ComplexF64}, @NamedTuple{powerflow_required::Bool, active_elements::Int64, passive_elements::Int64}}}}}, Vector{@NamedTuple{network::@NamedTuple{elements::@NamedTuple{branch::@NamedTuple{z::Float64, pins::Int64}, load::@NamedTuple{z::Float64, pins::Int64}}, options::@NamedTuple{}}}}, @NamedTuple{manifest::@NamedTuple{version::Int64, package::Symbol, formulation::DataType, backend::DataType, options::@NamedTuple{}, configurations::Vector{@NamedTuple{network::@NamedTuple{elements::@NamedTuple{branch::@NamedTuple{z::Float64, pins::Int64}, load::@NamedTuple{z::Float64, pins::Int64}}, options::@NamedTuple{}}}}}, failures::@NamedTuple{items::Vector{Any}}, source_space::Gridspace{PowerImpedanceProblem{PowerImpedance.NetworkBuilder.NetworkState, Vector{Symbol}, Vector{Symbol}, Tuple{Float64, Float64, Int64}}, PowerImpedance._PowerImpedanceProblemMaterializer{Vector{Symbol}, Vector{Symbol}, Tuple{Float64, Float64, Int64}}, Tuple{Gridspace{PowerImpedance.NetworkBuilder.NetworkState, PowerImpedance.NetworkBuilder._BuilderMaterializer{NTuple{4, @NamedTuple{node::Symbol, element::Symbol, side::Int64, terminal::Int64}}}, Tuple{Gridspace{NamedTuple{(:branch, :load)}, PowerImpedance.NetworkBuilder._NamedTupleMaterializer{(:branch, :load)}, Tuple{Gridspace{PowerImpedance.Element, PowerImpedance.NetworkBuilder._KeywordMaterializer{typeof(impedance), (:z, :pins)}, Tuple{DeterministicGrid{Tuple{Float64, Float64, Float64}, PowerImpedance.Grammar.AutomaticGridKey}, PowerImpedance.Grammar.ConstantAxis{Int64}}, Tuple{Symbol, Symbol}, Val{:product}}, Gridspace{PowerImpedance.Element, PowerImpedance.NetworkBuilder._KeywordMaterializer{typeof(impedance), (:z, :pins)}, Tuple{PowerImpedance.Grammar.ConstantAxis{Float64}, PowerImpedance.Grammar.ConstantAxis{Int64}}, Tuple{Symbol, Symbol}, Val{:product}}}, Tuple{Symbol, Symbol}, Val{:product}}, Gridspace{NamedTuple{()}, PowerImpedance.NetworkBuilder._NamedTupleMaterializer{()}, Tuple{}, Tuple{}, Val{:product}}}, Tuple{Symbol, Symbol}, Val{:product}}}, Tuple{Symbol}, Val{:product}}}}(Combinatorial{NodalImpedance{PowerImpedance.PIACDC}, PowerImpedance.PIACDC, :error}(NodalImpedance{PowerImpedance.PIACDC}(PowerImpedance.PIACDC), PowerImpedance.PIACDC, :error), FrequencyResponseResult{NodalImpedance{PowerImpedance.PIACDC}, Array{ComplexF64, 3}, Vector{ComplexF64}, Vector{Symbol}, PowerImpedance.NetworkBuilder.NetworkModel{ComplexF64}, @NamedTuple{linearization::LinearizationResult{AdmittanceLinearization{PowerImpedance.PIACDC}, PowerImpedance.NetworkBuilder.NetworkModel{ComplexF64}, @NamedTuple{powerflow_required::Bool, active_elements::Int64, passive_elements::Int64}}}}[FrequencyResponseResult{NodalImpedance{PowerImpedance.PIACDC}, Array{ComplexF64, 3}, Vector{ComplexF64}, Vector{Symbol}, PowerImpedance.NetworkBuilder.NetworkModel{ComplexF64}, @NamedTuple{linearization::LinearizationResult{AdmittanceLinearization{PowerImpedance.PIACDC}, PowerImpedance.NetworkBuilder.NetworkModel{ComplexF64}, @NamedTuple{powerflow_required::Bool, active_elements::Int64, passive_elements::Int64}}}}(NodalImpedance{PowerImpedance.PIACDC}(PowerImpedance.PIACDC), :nodal_impedance, ComplexF64[0.9090909090909091 - 0.0im;;; 0.9090909090909091 - 0.0im;;; 0.9090909090909091 - 0.0im;;; … ;;; 0.9090909090909091 - 0.0im;;; 0.9090909090909091 - 0.0im;;; 0.9090909090909091 - 0.0im], ComplexF64[6.283185307179586 + 0.0im, 7.500719855274336 + 0.0im, 8.954184159270191 + 0.0im, 10.689295894946175 + 0.0im, 12.760631755760757 + 0.0im, 15.23334412354667 + 0.0im, 18.185210389887892 + 0.0im, 21.70907938811084 + 0.0im, 25.91579188665106 + 0.0im, 30.93766700581654 + 0.0im  …  1276.063175576075 + 0.0im, 1523.3344123546667 + 0.0im, 1818.5210389887895 + 0.0im, 2170.9079388110836 + 0.0im, 2591.579188665106 + 0.0im, 3093.766700581655 + 0.0im, 3693.266422068319 + 0.0im, 4408.935186293412 + 0.0im, 5263.283840229959 + 0.0im, 6283.185307179586 + 0.0im], [:bus], NetworkModel
------------
Passive elements: 2
Active elements: 0
Grounded nodes: [:gnd]
Retained nodes: Symbol[]
, (linearization = LinearizationResult{AdmittanceLinearization{PowerImpedance.PIACDC}, PowerImpedance.NetworkBuilder.NetworkModel{ComplexF64}, @NamedTuple{powerflow_required::Bool, active_elements::Int64, passive_elements::Int64}}(AdmittanceLinearization{PowerImpedance.PIACDC}(PowerImpedance.PIACDC), NetworkModel
------------
Passive elements: 2
Active elements: 0
Grounded nodes: [:gnd]
Retained nodes: Symbol[]
, OperatingPoint(Dict{Symbol, Setpoint}()), (powerflow_required = false, active_elements = 0, passive_elements = 2)),)), FrequencyResponseResult{NodalImpedance{PowerImpedance.PIACDC}, Array{ComplexF64, 3}, Vector{ComplexF64}, Vector{Symbol}, PowerImpedance.NetworkBuilder.NetworkModel{ComplexF64}, @NamedTuple{linearization::LinearizationResult{AdmittanceLinearization{PowerImpedance.PIACDC}, PowerImpedance.NetworkBuilder.NetworkModel{ComplexF64}, @NamedTuple{powerflow_required::Bool, active_elements::Int64, passive_elements::Int64}}}}(NodalImpedance{PowerImpedance.PIACDC}(PowerImpedance.PIACDC), :nodal_impedance, ComplexF64[1.6666666666666667 - 0.0im;;; 1.6666666666666667 - 0.0im;;; 1.6666666666666667 - 0.0im;;; … ;;; 1.6666666666666667 - 0.0im;;; 1.6666666666666667 - 0.0im;;; 1.6666666666666667 - 0.0im], ComplexF64[6.283185307179586 + 0.0im, 7.500719855274336 + 0.0im, 8.954184159270191 + 0.0im, 10.689295894946175 + 0.0im, 12.760631755760757 + 0.0im, 15.23334412354667 + 0.0im, 18.185210389887892 + 0.0im, 21.70907938811084 + 0.0im, 25.91579188665106 + 0.0im, 30.93766700581654 + 0.0im  …  1276.063175576075 + 0.0im, 1523.3344123546667 + 0.0im, 1818.5210389887895 + 0.0im, 2170.9079388110836 + 0.0im, 2591.579188665106 + 0.0im, 3093.766700581655 + 0.0im, 3693.266422068319 + 0.0im, 4408.935186293412 + 0.0im, 5263.283840229959 + 0.0im, 6283.185307179586 + 0.0im], [:bus], NetworkModel
------------
Passive elements: 2
Active elements: 0
Grounded nodes: [:gnd]
Retained nodes: Symbol[]
, (linearization = LinearizationResult{AdmittanceLinearization{PowerImpedance.PIACDC}, PowerImpedance.NetworkBuilder.NetworkModel{ComplexF64}, @NamedTuple{powerflow_required::Bool, active_elements::Int64, passive_elements::Int64}}(AdmittanceLinearization{PowerImpedance.PIACDC}(PowerImpedance.PIACDC), NetworkModel
------------
Passive elements: 2
Active elements: 0
Grounded nodes: [:gnd]
Retained nodes: Symbol[]
, OperatingPoint(Dict{Symbol, Setpoint}()), (powerflow_required = false, active_elements = 0, passive_elements = 2)),)), FrequencyResponseResult{NodalImpedance{PowerImpedance.PIACDC}, Array{ComplexF64, 3}, Vector{ComplexF64}, Vector{Symbol}, PowerImpedance.NetworkBuilder.NetworkModel{ComplexF64}, @NamedTuple{linearization::LinearizationResult{AdmittanceLinearization{PowerImpedance.PIACDC}, PowerImpedance.NetworkBuilder.NetworkModel{ComplexF64}, @NamedTuple{powerflow_required::Bool, active_elements::Int64, passive_elements::Int64}}}}(NodalImpedance{PowerImpedance.PIACDC}(PowerImpedance.PIACDC), :nodal_impedance, ComplexF64[3.333333333333333 - 0.0im;;; 3.333333333333333 - 0.0im;;; 3.333333333333333 - 0.0im;;; … ;;; 3.333333333333333 - 0.0im;;; 3.333333333333333 - 0.0im;;; 3.333333333333333 - 0.0im], ComplexF64[6.283185307179586 + 0.0im, 7.500719855274336 + 0.0im, 8.954184159270191 + 0.0im, 10.689295894946175 + 0.0im, 12.760631755760757 + 0.0im, 15.23334412354667 + 0.0im, 18.185210389887892 + 0.0im, 21.70907938811084 + 0.0im, 25.91579188665106 + 0.0im, 30.93766700581654 + 0.0im  …  1276.063175576075 + 0.0im, 1523.3344123546667 + 0.0im, 1818.5210389887895 + 0.0im, 2170.9079388110836 + 0.0im, 2591.579188665106 + 0.0im, 3093.766700581655 + 0.0im, 3693.266422068319 + 0.0im, 4408.935186293412 + 0.0im, 5263.283840229959 + 0.0im, 6283.185307179586 + 0.0im], [:bus], NetworkModel
------------
Passive elements: 2
Active elements: 0
Grounded nodes: [:gnd]
Retained nodes: Symbol[]
, (linearization = LinearizationResult{AdmittanceLinearization{PowerImpedance.PIACDC}, PowerImpedance.NetworkBuilder.NetworkModel{ComplexF64}, @NamedTuple{powerflow_required::Bool, active_elements::Int64, passive_elements::Int64}}(AdmittanceLinearization{PowerImpedance.PIACDC}(PowerImpedance.PIACDC), NetworkModel
------------
Passive elements: 2
Active elements: 0
Grounded nodes: [:gnd]
Retained nodes: Symbol[]
, OperatingPoint(Dict{Symbol, Setpoint}()), (powerflow_required = false, active_elements = 0, passive_elements = 2)),))], [(network = (elements = (branch = (z = 1.0, pins = 1), load = (z = 10.0, pins = 1)), options = NamedTuple()),), (network = (elements = (branch = (z = 2.0, pins = 1), load = (z = 10.0, pins = 1)), options = NamedTuple()),), (network = (elements = (branch = (z = 5.0, pins = 1), load = (z = 10.0, pins = 1)), options = NamedTuple()),)], (manifest = (version = 1, package = :PowerImpedance, formulation = NodalImpedance{PowerImpedance.PIACDC}, backend = PowerImpedance.PIACDC, options = NamedTuple(), configurations = [(network = (elements = (branch = (z = 1.0, pins = 1), load = (z = 10.0, pins = 1)), options = NamedTuple()),), (network = (elements = (branch = (z = 2.0, pins = 1), load = (z = 10.0, pins = 1)), options = NamedTuple()),), (network = (elements = (branch = (z = 5.0, pins = 1), load = (z = 10.0, pins = 1)), options = NamedTuple()),)]), failures = (items = Any[],), source_space = Gridspace{PowerImpedanceProblem{PowerImpedance.NetworkBuilder.NetworkState, Vector{Symbol}, Vector{Symbol}, Tuple{Float64, Float64, Int64}}, PowerImpedance._PowerImpedanceProblemMaterializer{Vector{Symbol}, Vector{Symbol}, Tuple{Float64, Float64, Int64}}, Tuple{Gridspace{PowerImpedance.NetworkBuilder.NetworkState, PowerImpedance.NetworkBuilder._BuilderMaterializer{NTuple{4, @NamedTuple{node::Symbol, element::Symbol, side::Int64, terminal::Int64}}}, Tuple{Gridspace{NamedTuple{(:branch, :load)}, PowerImpedance.NetworkBuilder._NamedTupleMaterializer{(:branch, :load)}, Tuple{Gridspace{PowerImpedance.Element, PowerImpedance.NetworkBuilder._KeywordMaterializer{typeof(impedance), (:z, :pins)}, Tuple{DeterministicGrid{Tuple{Float64, Float64, Float64}, PowerImpedance.Grammar.AutomaticGridKey}, PowerImpedance.Grammar.ConstantAxis{Int64}}, Tuple{Symbol, Symbol}, Val{:product}}, Gridspace{PowerImpedance.Element, PowerImpedance.NetworkBuilder._KeywordMaterializer{typeof(impedance), (:z, :pins)}, Tuple{PowerImpedance.Grammar.ConstantAxis{Float64}, PowerImpedance.Grammar.ConstantAxis{Int64}}, Tuple{Symbol, Symbol}, Val{:product}}}, Tuple{Symbol, Symbol}, Val{:product}}, Gridspace{NamedTuple{()}, PowerImpedance.NetworkBuilder._NamedTupleMaterializer{()}, Tuple{}, Tuple{}, Val{:product}}}, Tuple{Symbol, Symbol}, Val{:product}}}, Tuple{Symbol}, Val{:product}}(PowerImpedance._PowerImpedanceProblemMaterializer{Vector{Symbol}, Vector{Symbol}, Tuple{Float64, Float64, Int64}}([:bus], Symbol[], (1.0, 1000.0, 40)), (Gridspace{PowerImpedance.NetworkBuilder.NetworkState, PowerImpedance.NetworkBuilder._BuilderMaterializer{NTuple{4, @NamedTuple{node::Symbol, element::Symbol, side::Int64, terminal::Int64}}}, Tuple{Gridspace{NamedTuple{(:branch, :load)}, PowerImpedance.NetworkBuilder._NamedTupleMaterializer{(:branch, :load)}, Tuple{Gridspace{PowerImpedance.Element, PowerImpedance.NetworkBuilder._KeywordMaterializer{typeof(impedance), (:z, :pins)}, Tuple{DeterministicGrid{Tuple{Float64, Float64, Float64}, PowerImpedance.Grammar.AutomaticGridKey}, PowerImpedance.Grammar.ConstantAxis{Int64}}, Tuple{Symbol, Symbol}, Val{:product}}, Gridspace{PowerImpedance.Element, PowerImpedance.NetworkBuilder._KeywordMaterializer{typeof(impedance), (:z, :pins)}, Tuple{PowerImpedance.Grammar.ConstantAxis{Float64}, PowerImpedance.Grammar.ConstantAxis{Int64}}, Tuple{Symbol, Symbol}, Val{:product}}}, Tuple{Symbol, Symbol}, Val{:product}}, Gridspace{NamedTuple{()}, PowerImpedance.NetworkBuilder._NamedTupleMaterializer{()}, Tuple{}, Tuple{}, Val{:product}}}, Tuple{Symbol, Symbol}, Val{:product}}(PowerImpedance.NetworkBuilder._BuilderMaterializer{NTuple{4, @NamedTuple{node::Symbol, element::Symbol, side::Int64, terminal::Int64}}}(((node = :bus, element = :branch, side = 1, terminal = 1), (node = :bus, element = :load, side = 1, terminal = 1), (node = :gnd, element = :branch, side = 2, terminal = 1), (node = :gnd, element = :load, side = 2, terminal = 1))), (Gridspace{NamedTuple{(:branch, :load)}, PowerImpedance.NetworkBuilder._NamedTupleMaterializer{(:branch, :load)}, Tuple{Gridspace{PowerImpedance.Element, PowerImpedance.NetworkBuilder._KeywordMaterializer{typeof(impedance), (:z, :pins)}, Tuple{DeterministicGrid{Tuple{Float64, Float64, Float64}, PowerImpedance.Grammar.AutomaticGridKey}, PowerImpedance.Grammar.ConstantAxis{Int64}}, Tuple{Symbol, Symbol}, Val{:product}}, Gridspace{PowerImpedance.Element, PowerImpedance.NetworkBuilder._KeywordMaterializer{typeof(impedance), (:z, :pins)}, Tuple{PowerImpedance.Grammar.ConstantAxis{Float64}, PowerImpedance.Grammar.ConstantAxis{Int64}}, Tuple{Symbol, Symbol}, Val{:product}}}, Tuple{Symbol, Symbol}, Val{:product}}(PowerImpedance.NetworkBuilder._NamedTupleMaterializer{(:branch, :load)}(), (Gridspace{PowerImpedance.Element, PowerImpedance.NetworkBuilder._KeywordMaterializer{typeof(impedance), (:z, :pins)}, Tuple{DeterministicGrid{Tuple{Float64, Float64, Float64}, PowerImpedance.Grammar.AutomaticGridKey}, PowerImpedance.Grammar.ConstantAxis{Int64}}, Tuple{Symbol, Symbol}, Val{:product}}(PowerImpedance.NetworkBuilder._KeywordMaterializer{typeof(impedance), (:z, :pins)}(PowerImpedance.impedance), (DeterministicGrid{Tuple{Float64, Float64, Float64}, PowerImpedance.Grammar.AutomaticGridKey}((1.0, 2.0, 5.0), PowerImpedance.Grammar.AutomaticGridKey(Base.RefValue{Nothing}(nothing))), PowerImpedance.Grammar.ConstantAxis{Int64}(1)), (:z, :pins), Val{:product}()), Gridspace{PowerImpedance.Element, PowerImpedance.NetworkBuilder._KeywordMaterializer{typeof(impedance), (:z, :pins)}, Tuple{PowerImpedance.Grammar.ConstantAxis{Float64}, PowerImpedance.Grammar.ConstantAxis{Int64}}, Tuple{Symbol, Symbol}, Val{:product}}(PowerImpedance.NetworkBuilder._KeywordMaterializer{typeof(impedance), (:z, :pins)}(PowerImpedance.impedance), (PowerImpedance.Grammar.ConstantAxis{Float64}(10.0), PowerImpedance.Grammar.ConstantAxis{Int64}(1)), (:z, :pins), Val{:product}())), (:branch, :load), Val{:product}()), Gridspace{NamedTuple{()}, PowerImpedance.NetworkBuilder._NamedTupleMaterializer{()}, Tuple{}, Tuple{}, Val{:product}}(PowerImpedance.NetworkBuilder._NamedTupleMaterializer{()}(), (), (), Val{:product}())), (:elements, :options), Val{:product}()),), (:network,), Val{:product}())))

Lines constructed from LineParameters

LineCableModels interoperability is dormant until LineCableModels.jl is registered and restored as a PowerImpedance weak dependency. A phase-domain, per-metre LineParameters result then replaces only the line model definition; the connection rows are unchanged. The documentation environment does not install LineCableModels, so this executable pattern is shown without importing the optional package:

using LineCableModels
using Measurements

workspace, line_parameters = LineCableModels.compute!(problem, formulation)

line_elements = (
    line = cable(
        Grid,
        line_parameters;
        length = Grid([50e3, 75e3, 100e3]),
        transformation = true,
    ),
)

line_connections = (
    (node = :sending_d, element = :line, side = 1, terminal = 1),
    (node = :sending_q, element = :line, side = 1, terminal = 2),
    (node = :receiving_d, element = :line, side = 2, terminal = 1),
    (node = :receiving_q, element = :line, side = 2, terminal = 2),
)

line_space = define(line_elements, line_connections)

Back to Examples