Power Flow Computations

The typical goal of PowerModelsDistribution is to build a JuMP model that is used to solve distribution power network optimization problems. The JuMP model abstraction enables PowerModelsDistribution to have state-of-the-art performance on a wide range of problem formulations. That said, for the specific case of power flow computations, in some specific applications performance gains can be had by avoiding the JuMP model abstraction and solving the problem more directly. To that end, PowerModelsDistribution includes Julia-native solvers for AC power flow in rectangular voltage coordinates. This section provides an overview of the different power flow options that are available in PowerModelsDistribution and under what circumstances they may be beneficial.

Generic Power Flow

The general purpose power flow solver in PowerModelsDistribution is,

This function builds a JuMP model for a wide variety of unbalanced power flow formulations supported by PowerModelsDistribution. For example it supports,

  • ACPUPowerModel - a non-convex nonlinear AC unbalanced power flow using complex voltages in polar coordinates
  • ACRPowerModel - a non-convex nonlinear AC unbalanced power flow using complex voltages in rectangular coordinates
  • ACRENPowerModel - a non-convex nonlinear AC unbalanced power flow using complex voltages in rectangular coordinates with explicit neutral conductor
  • IVRUPowerModel - a non-convex nonlinear AC power unbalanced flow using current voltage variables in rectangular coordinates
  • IVRENPowerModel - a non-convex nonlinear AC unbalanced power flow using current voltage variables in rectangular coordinates with explicit neutral conductor

The solve_mc_pf solution method is both formulation and solver agnostic and can leverage the wide range of solvers that are available in the JuMP ecosystem. Many of these solvers are commercial-grade, which in turn makes solve_mc_pf the most reliable power flow solution method in PowerModelsDistribution.

Warm Starting

In some applications an initial guess of the power flow solution may be available. In such a case, this information may be able to decrease a solver's time to convergence, especially when solving systems of nonlinear equations. The _start postfix can be used in the network data to initialize the solver's variables and provide a suitable solution guess. The most common values are as follows,

For each generator,

  • pg_start - active power injection starting point
  • qg_start - reactive power injection starting point

For each bus,

  • vm_start - voltage magnitude starting point for the ACPUPowerModel model
  • va_start - voltage angle starting point for the ACPUPowerModel model
  • vr_start - real voltage starting point for the IVRUPowerModel model
  • vi_start - imaginary voltage starting point for the IVRUPowerModel model

The following helper function can be used to use the solution point in the network data as the starting point for solve_mc_pf.

PowerModelsDistribution.add_start_voltage!Function
add_start_voltage!(
    data_math::Dict{String,Any};
    coordinates=:rectangular,
    uniform_v_start=missing,
    vr_default=0.0,
    vi_default=0.0,
    vm_default=0.0,
    va_default=0.0,
    epsilon::Number=1E-3,
)::Dict{String,Any}

Adds start values for the voltage to the buses. For a multinetwork data model, you can calculate the start voltages for a representative network through 'calcstartvoltage', and pass the result as 'uniformvstart' to use the same values for all networks and avoid recalculating it for each network. The argument 'epsilon' controls the offset added to ungrounded terminals which would otherwise be set to zero.

source
Warning

Warm starting a solver is a very delicate task and can easily result in degraded performance. Using PowerModelsDistribution' default flat-start values is recommended before experimenting with warm starting a solver.

Native Power Flow

The AC Unbalanced Power Flow problem is ubiquitous in power system analysis. The problem requires solving a system of nonlinear equations, usually via a Newton-Raphson type of algorithm. In PowerModelsDistribution, the standard Julia library is used for solving this system of nonlinear equations. The following function is used to solve Unbalanced Power Flow problem with voltages in rectangular coordinates.

PowerModelsDistribution.compute_mc_pfFunction
compute_mc_pf(
    data::Dict{String,<:Any};
    explicit_neutral::Bool=false,
    max_iter::Int=100,
    v_start::Union{Dict{<:Any,<:Any},Missing}=missing,
    stat_tol::Real=1e-8,
    verbose::Bool=false,
    kron_reduce::Bool=true,
    phase_project::Bool=false,
    multinetwork::Bool=false,
    global_keys::Set{String}=Set{String}(),
    eng2math_extensions::Vector{<:Function}=Function[],
    eng2math_passthrough::Dict{String,<:Vector{<:String}}=Dict{String,Vector{String}}(),
    make_pu_extensions::Vector{<:Function}=Function[],
    map_math2eng_extensions::Dict{String,<:Function}=Dict{String,Function}(),
    make_si::Bool=!get(data, "per_unit", false),
    make_si_extensions::Vector{<:Function}=Function[],
    dimensionalize_math_extensions::Dict{String,Dict{String,Vector{String}}}=Dict{String,Dict{String,Vector{String}}}(),
)::Dict{String,Any}

Takes data in either the ENGINEERING or MATHEMATICAL model, a model type (e.g., ACRUPowerModel), and model builder function (e.g., build_mc_opf), and returns a solution in the original data model defined by data.

Technical description of the native power flow can be found at https://arxiv.org/abs/2305.04405 where implementation fo the fixed-point current injection algorithm, inspired by the existing open-source implementation in OpenDSS. The current injection method is commonly conceived as a system of nonlinear equalities solved by Newton’s method. However, the fixed point iteration variant commonly outperforms most methods, while supporting meshed topologies from the ground up

If make_si is false, data will remain in per-unit.

For an explanation of multinetwork and global_keys, see make_multinetwork

For an explanation of eng2math_extensions and eng2math_passthrough, see transform_data_model

For an explanation of make_pu_extensions, see make_per_unit!

For an explanation of ref_extensions, see instantiate_mc_model

For an explanation of map_math2eng_extensions, make_si, make_si_extensions, and dimensionalize_math_extensions, see solution_make_si

source
compute_mc_pf(
  pdf::PowerFlowData,
  max_iter::Int,
  stat_tol::Float,
  verbose::Bool
)

Computes native power flow and requires PowerFlowData (See https://arxiv.org/abs/2305.04405).

source

compute_mc_pf is based on the current injection method and is inspired by OpenDSS's algorithm. compute_mc_pf will typically provide an identical result to solve_mc_pf. However, the existence of solution degeneracy around generator injection assignments and multiple power flow solutions can yield different results. The primary advantage of compute_mc_pf over solve_mc_pf is that it does not require building a JuMP model. If the initial point for the Unbalanced Power Flow solution is near-feasible then compute_mc_pf can result in a significant runtime saving by converging quickly and reducing data-wrangling and memory allocation overheads. This initial guess is provided using the standard _start values. The add_start_voltage! function provides a convenient way of setting a suitable starting point.

Tip

If compute_mc_pf fails to converge try solve_mc_pf instead.

The table below reports the accuracy of the native power flow with respect to OpenDSS native solver tested on three IEEE testcases: | IEEE testcases | maximum voltage p.u difference with OpenDSS power flow solver | | –––––––-| ––––––––––––––––––––––––––––––- | | IEEE13 | 3.765096388188572e-6 | | IEEE34 | 6.805369850332029e-8 | | IEEE123 | 4.021326251365659e-8 |

Input arguments

compute_mc_pf receives input arguments as follows,

  • data_math - network data in MATHEMATICAL format
  • explicit_neutral - a boolean input indication wether or not the neutral is explicitly modelled
  • v_start - warm start if different from in-built initialization algorithm
  • max_iter - maximum iterations
  • stat_tol - statistical tolerance

Outputs

compute_mc_pf provides the following outputs,

  • solution - solution dictionary
  • iterations - number of iterations
  • time_build - time spent on building the power flow data
  • time_solve - time spent on solving the native power flow
  • time_post - time spent to generate solutions
  • time_total - total time
  • termination_status - termination status

Limitations

compute_mc_pf has the following limitations,

  • starting from the math dictionary means that transformer decomposition is already done, which is different from what OpenDSS does
  • we calculate the primitive admittance matrix in p.u. whereas OpenDSS algorithm works with actual units
  • no load model relaxation is performed
  • inspired by OpenDSS, we add small ppm values to certain component primitive admittance values to avoid singularity issues
  • inspired by OpenDSS, switch primitive admittance has specific values

Network Admittance Matrix

Internally compute_mc_pf utilizes an admittance matrix representation of the network data, which may be useful in other contexts. The foundational type for the admittance matrix representations is SparseMatrixCSC.

The following function can be used to compute the admittance matrix from PowerModelsDistribution network data.