Quick Start Guide

This page provides a brief overview of the features of PowerModels.jl.

Setup

This page uses the following packages:

julia> using PowerModels
julia> using Ipopt

This page also uses various input files. In this build of the documentation, we use the files in:

julia> DATA_DIR = joinpath(pkgdir(PowerModels), "test", "data");

but there are many public instances that you can use, for example, by going to pglib-opf.

Solving the basic Optimal Power Flow

Once PowerModels is installed, Ipopt is installed, and a network data file (e.g., "case3.m" or "case3.raw") has been acquired, an AC Optimal Power Flow can be executed with:

julia> solve_ac_opf(joinpath(DATA_DIR, "matpower", "case3.m"), Ipopt.Optimizer)
******************************************************************************
This program contains Ipopt, a library for large-scale nonlinear optimization.
 Ipopt is released as open source code under the Eclipse Public License (EPL).
         For more information visit https://github.com/coin-or/Ipopt
******************************************************************************

This is Ipopt version 3.14.19, running with linear solver MUMPS 5.9.0.

Number of nonzeros in equality constraint Jacobian...:       84
Number of nonzeros in inequality constraint Jacobian.:       18
Number of nonzeros in Lagrangian Hessian.............:      134

Total number of variables............................:       27
                     variables with only lower bounds:        0
                variables with lower and upper bounds:       24
                     variables with only upper bounds:        0
Total number of equality constraints.................:       20
Total number of inequality constraints...............:        9
        inequality constraints with only lower bounds:        0
   inequality constraints with lower and upper bounds:        3
        inequality constraints with only upper bounds:        6

iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
   0  6.3949934e+00 1.20e+00 2.54e+01  -1.0 0.00e+00    -  0.00e+00 0.00e+00   0
   1  3.7786723e+03 2.38e-01 1.40e+02  -1.0 1.80e+00    -  5.79e-03 8.01e-01h  1
   2  4.1854574e+03 1.83e-01 1.08e+02  -1.0 4.16e-01    -  6.49e-01 2.33e-01h  1
   3  4.3122875e+03 1.67e-01 9.87e+01  -1.0 3.13e-01    -  2.84e-01 8.82e-02h  1
   4  5.1593473e+03 8.73e-02 1.60e+02  -1.0 4.26e-01    -  2.12e-01 5.98e-01h  1
   5  5.5669007e+03 3.75e-02 3.71e+01  -1.0 2.04e-01    -  8.47e-01 6.39e-01h  1
   6  5.6334313e+03 3.43e-02 5.77e+01  -1.0 1.07e-01    -  9.90e-01 2.67e-01h  1
   7  5.6639586e+03 4.30e-02 1.31e+02  -1.0 1.86e-01    -  2.87e-01 1.57e-01h  1
   8  5.6670493e+03 4.39e-02 2.28e+02  -1.0 1.44e-01    -  4.23e-02 1.76e-02h  1
   9  5.9038108e+03 2.24e-03 1.71e+02  -1.0 1.28e-01    -  2.16e-01 1.00e+00h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  10  5.9095024e+03 1.02e-05 4.37e-01  -1.0 4.21e-03    -  1.00e+00 1.00e+00h  1
  11  5.9074978e+03 4.66e-06 5.75e-03  -1.7 2.96e-03    -  1.00e+00 1.00e+00f  1
  12  5.9068858e+03 2.13e-07 3.57e-04  -3.8 7.95e-04    -  1.00e+00 1.00e+00f  1
  13  5.9068795e+03 3.64e-11 5.98e-08  -5.7 1.21e-05    -  1.00e+00 1.00e+00h  1
  14  5.9068794e+03 1.53e-15 3.00e-12  -8.6 7.05e-08    -  1.00e+00 1.00e+00h  1

Number of Iterations....: 14

                                   (scaled)                 (unscaled)
Objective...............:   1.1813758833436350e+03    5.9068794167181750e+03
Dual infeasibility......:   3.0001291516432019e-12    1.5000645758216010e-11
Constraint violation....:   1.5265566588595902e-15    1.5265566588595902e-15
Variable bound violation:   1.0962198482289409e-08    1.0962198482289409e-08
Complementarity.........:   2.5073461206267809e-09    1.2536730603133905e-08
Overall NLP error.......:   2.5073461206267809e-09    1.2536730603133905e-08


Number of objective function evaluations             = 15
Number of objective gradient evaluations             = 15
Number of equality constraint evaluations            = 15
Number of inequality constraint evaluations          = 15
Number of equality constraint Jacobian evaluations   = 15
Number of inequality constraint Jacobian evaluations = 15
Number of Lagrangian Hessian evaluations             = 14
Total seconds in IPOPT                               = 3.871

EXIT: Optimal Solution Found.
Dict{String, Any} with 8 entries:
  "objective_lb"       => -Inf
  "termination_status" => LOCALLY_SOLVED
  "objective"          => 5906.88
  "primal_status"      => FEASIBLE_POINT
  "dual_status"        => FEASIBLE_POINT
  "optimizer"          => "Ipopt"
  "solve_time"         => 3.87245
  "solution"           => Dict{String, Any}("baseMVA"=>100.0, "multinetwork"=>f…

Pass options to the solver using JuMP's optimizer_with_attributes:

julia> solve_dc_opf(
           joinpath(DATA_DIR, "matpower", "case3.m"),
           optimizer_with_attributes(Ipopt.Optimizer, "print_level" => 0),
       )Dict{String, Any} with 8 entries:
  "objective_lb"       => -Inf
  "termination_status" => LOCALLY_SOLVED
  "objective"          => 5782.03
  "primal_status"      => FEASIBLE_POINT
  "dual_status"        => FEASIBLE_POINT
  "optimizer"          => "Ipopt"
  "solve_time"         => 0.01215
  "solution"           => Dict{String, Any}("baseMVA"=>100.0, "multinetwork"=>f…

Similarly, a DC Optimal Power Flow can be executed with:

julia> solve_dc_opf(
           joinpath(DATA_DIR, "matpower", "case3.m"),
           optimizer_with_attributes(Ipopt.Optimizer, "print_level" => 0),
       )Dict{String, Any} with 8 entries:
  "objective_lb"       => -Inf
  "termination_status" => LOCALLY_SOLVED
  "objective"          => 5782.03
  "primal_status"      => FEASIBLE_POINT
  "dual_status"        => FEASIBLE_POINT
  "optimizer"          => "Ipopt"
  "solve_time"         => 0.00286794
  "solution"           => Dict{String, Any}("baseMVA"=>100.0, "multinetwork"=>f…

PTI .raw files in the PSS(R)E v33 specification can be run similarly, for example, in the case of an AC Optimal Power Flow:

julia> solve_ac_opf(
           joinpath(DATA_DIR, "pti", "case3.raw"),
           optimizer_with_attributes(Ipopt.Optimizer, "print_level" => 0),
       )Dict{String, Any} with 8 entries:
  "objective_lb"       => -Inf
  "termination_status" => LOCALLY_SOLVED
  "objective"          => 317.38
  "primal_status"      => FEASIBLE_POINT
  "dual_status"        => FEASIBLE_POINT
  "optimizer"          => "Ipopt"
  "solve_time"         => 0.00452805
  "solution"           => Dict{String, Any}("baseMVA"=>100.0, "multinetwork"=>f…

Getting Results

The run commands in PowerModels return detailed results data in the form of a dictionary. Results dictionaries from either Matpower .m or PTI .raw files will be identical in format. This dictionary can be saved for further processing as follows,

julia> result = solve_ac_opf(
           joinpath(DATA_DIR, "matpower", "case3.m"),
           optimizer_with_attributes(Ipopt.Optimizer, "print_level" => 0),
       )Dict{String, Any} with 8 entries:
  "objective_lb"       => -Inf
  "termination_status" => LOCALLY_SOLVED
  "objective"          => 5906.88
  "primal_status"      => FEASIBLE_POINT
  "dual_status"        => FEASIBLE_POINT
  "optimizer"          => "Ipopt"
  "solve_time"         => 0.00482416
  "solution"           => Dict{String, Any}("baseMVA"=>100.0, "multinetwork"=>f…

For example, the algorithm's runtime and final objective value can be accessed with:

julia> result["solve_time"]0.004824161529541016
julia> result["objective"]5906.879416718175

The "solution" field contains detailed information about the solution produced by the run method. For example, the following dictionary comprehension can be used to inspect the bus voltage angles in the solution:

julia> Dict(name => data["va"] for (name, data) in result["solution"]["bus"])Dict{String, Float64} with 3 entries:
  "3" => -0.301368
  "1" => -2.40793e-37
  "2" => 0.12669

The print_summary(result["solution"]) function can be used show an table-like overview of the solution data.

julia> print_summary(result["solution"])Metadata
  baseMVA: 100.000
  multiinfrastructure: false
  multinetwork: false
  per_unit: true

Table Counts
  bus: 3
  gen: 3
  branch: 3
  dcline: 1


Table: bus
            vm,     va
      1: 1.100, -0.000
      2: 0.926,  0.127
      3: 0.900, -0.301


Table: gen
            pg,     qg,  pg_cost
      1: 1.581,  0.302, 3538.701
      2: 1.600, -0.049, 2368.179
      3: 0.000, -0.048,    0.000


Table: branch
             pf,     qf,     pt,     qt
      1:  0.513,  0.101, -0.491, -0.349
      2: -0.459, -0.199,  0.465, -0.183
      3: -0.132,  0.046,  0.135, -0.305


Table: dcline
            pf,     qf,     pt,    qt, p_dc_cost
      1: 0.100, -0.245, -0.100, 0.039,     0.000

For more information about PowerModels result data, see the PowerModels Result Data Format section.

Using a different optimizer

PowerModels supports any solver compatible with JuMP. In the examples above, we used Ipopt.jl. Another option, which can be faster particularly on large-scale problems, is ExaModels.jl.

julia> import ExaModels
julia> import NLPModelsIpopt
julia> result = solve_ac_opf( joinpath(DATA_DIR, "matpower", "case3.m"), () -> ExaModels.Optimizer(NLPModelsIpopt.ipopt), )This is Ipopt version 3.14.19, running with linear solver MUMPS 5.9.0. Number of nonzeros in equality constraint Jacobian...: 84 Number of nonzeros in inequality constraint Jacobian.: 18 Number of nonzeros in Lagrangian Hessian.............: 134 Total number of variables............................: 27 variables with only lower bounds: 0 variables with lower and upper bounds: 24 variables with only upper bounds: 0 Total number of equality constraints.................: 20 Total number of inequality constraints...............: 9 inequality constraints with only lower bounds: 0 inequality constraints with lower and upper bounds: 3 inequality constraints with only upper bounds: 6 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 0 6.3949934e+00 1.20e+00 2.54e+01 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0 1 3.7786723e+03 2.38e-01 1.40e+02 -1.0 1.80e+00 - 5.79e-03 8.01e-01h 1 2 4.1854574e+03 1.83e-01 1.08e+02 -1.0 4.16e-01 - 6.49e-01 2.33e-01h 1 3 4.3122875e+03 1.67e-01 9.87e+01 -1.0 3.13e-01 - 2.84e-01 8.82e-02h 1 4 5.1593473e+03 8.73e-02 1.60e+02 -1.0 4.26e-01 - 2.12e-01 5.98e-01h 1 5 5.5669007e+03 3.75e-02 3.71e+01 -1.0 2.04e-01 - 8.47e-01 6.39e-01h 1 6 5.6334313e+03 3.43e-02 5.77e+01 -1.0 1.07e-01 - 9.90e-01 2.67e-01h 1 7 5.6639586e+03 4.30e-02 1.31e+02 -1.0 1.86e-01 - 2.87e-01 1.57e-01h 1 8 5.6670493e+03 4.39e-02 2.28e+02 -1.0 1.44e-01 - 4.23e-02 1.76e-02h 1 9 5.9038108e+03 2.24e-03 1.71e+02 -1.0 1.28e-01 - 2.16e-01 1.00e+00h 1 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 10 5.9095024e+03 1.02e-05 4.37e-01 -1.0 4.21e-03 - 1.00e+00 1.00e+00h 1 11 5.9074978e+03 4.66e-06 5.75e-03 -1.7 2.96e-03 - 1.00e+00 1.00e+00f 1 12 5.9068858e+03 2.13e-07 3.57e-04 -3.8 7.95e-04 - 1.00e+00 1.00e+00f 1 13 5.9068795e+03 3.64e-11 5.98e-08 -5.7 1.21e-05 - 1.00e+00 1.00e+00h 1 14 5.9068794e+03 1.48e-15 3.00e-12 -8.6 7.05e-08 - 1.00e+00 1.00e+00h 1 Number of Iterations....: 14 (scaled) (unscaled) Objective...............: 1.1813758833436355e+03 5.9068794167181768e+03 Dual infeasibility......: 3.0001291474080372e-12 1.5000645737040186e-11 Constraint violation....: 1.4849232954361469e-15 1.4849232954361469e-15 Variable bound violation: 1.0962198482289409e-08 1.0962198482289409e-08 Complementarity.........: 2.5073461206267834e-09 1.2536730603133916e-08 Overall NLP error.......: 2.5073461206267834e-09 1.2536730603133916e-08 Number of objective function evaluations = 15 Number of objective gradient evaluations = 15 Number of equality constraint evaluations = 15 Number of inequality constraint evaluations = 15 Number of equality constraint Jacobian evaluations = 15 Number of inequality constraint Jacobian evaluations = 15 Number of Lagrangian Hessian evaluations = 14 Total seconds in IPOPT = 1.258 EXIT: Optimal Solution Found. Dict{String, Any} with 8 entries: "objective_lb" => -Inf "termination_status" => LOCALLY_SOLVED "objective" => 5906.88 "primal_status" => FEASIBLE_POINT "dual_status" => FEASIBLE_POINT "optimizer" => "ipopt running with ExaModels" "solve_time" => 1.82354 "solution" => Dict{String, Any}("baseMVA"=>100.0, "multinetwork"=>f…

A benefit of ExaModels is that it supports MadNLP, which can run on a GPU:

julia> import CUDA, CUDSS, MadNLP, MadNLPGPU

julia> result = solve_ac_opf(
           joinpath(DATA_DIR, "matpower", "case3.m"),
           () -> ExaModels.Optimizer(MadNLP.madnlp, CUDA.CUDABackend()),
       );

Accessing Different Formulations

The functions solve_ac_opf and solve_dc_opf are shorthands for a more general formulation-independent OPF execution, solve_opf. For example, solve_ac_opf is equivalent to:

julia> solve_opf(
           joinpath(DATA_DIR, "matpower", "case3.m"),
           ACPPowerModel,
           optimizer_with_attributes(Ipopt.Optimizer, "print_level" => 0),
       )Dict{String, Any} with 8 entries:
  "objective_lb"       => -Inf
  "termination_status" => LOCALLY_SOLVED
  "objective"          => 5906.88
  "primal_status"      => FEASIBLE_POINT
  "dual_status"        => FEASIBLE_POINT
  "optimizer"          => "Ipopt"
  "solve_time"         => 4.45315
  "solution"           => Dict{String, Any}("baseMVA"=>100.0, "multinetwork"=>f…

where ACPPowerModel indicates an AC formulation in polar coordinates. This more generic solve_opf() allows one to solve an OPF problem with any power network formulation implemented in PowerModels. For example, an SOC Optimal Power Flow can be run with:

julia> solve_opf(
           joinpath(DATA_DIR, "matpower", "case3.m"),
           SOCWRPowerModel,
           optimizer_with_attributes(Ipopt.Optimizer, "print_level" => 0),
       )Dict{String, Any} with 8 entries:
  "objective_lb"       => -Inf
  "termination_status" => LOCALLY_SOLVED
  "objective"          => 5746.72
  "primal_status"      => FEASIBLE_POINT
  "dual_status"        => FEASIBLE_POINT
  "optimizer"          => "Ipopt"
  "solve_time"         => 0.00581098
  "solution"           => Dict{String, Any}("baseMVA"=>100.0, "multinetwork"=>f…

Formulation Details provides a list of available formulations.

Modifying Network Data

The following example demonstrates one way to perform multiple PowerModels solves while modifing the network data in Julia:

julia> network_data = PowerModels.parse_file(joinpath(DATA_DIR, "matpower", "case3.m"))Dict{String, Any} with 22 entries:
  "baseMVA"           => 100.0
  "storage"           => Dict{String, Any}()
  "name"              => "case3"
  "switch"            => Dict{String, Any}()
  "const_int"         => 123
  "areas_cells"       => Dict{String, Any}("1"=>Dict{String, Any}("col_3"=>987,…
  "component"         => Dict{String, Any}("1"=>Dict{String, Any}("number"=>100…
  "const_float"       => 4.56
  "bus"               => Dict{String, Any}("3"=>Dict{String, Any}("number"=>3, …
  "shunt"             => Dict{String, Any}()
  "source_type"       => "matpower"
  "per_unit"          => true
  "dcline"            => Dict{String, Any}("1"=>Dict{String, Any}("pt"=>-0.1, "…
  "gen"               => Dict{String, Any}("3"=>Dict{String, Any}("gen_bus"=>3,…
  "areas_named"       => Dict{String, Any}("1"=>Dict{String, Any}("source_id"=>…
  "load"              => Dict{String, Any}("3"=>Dict{String, Any}("qd"=>0.5, "l…
  "areas_named_cells" => Dict{String, Any}("1"=>Dict{String, Any}("refbus_name"…
  "const_str"         => "a string"
  "source_version"    => "2"
  ⋮                   => ⋮
julia> solve_opf( network_data, ACPPowerModel, optimizer_with_attributes(Ipopt.Optimizer, "print_level" => 0), )Dict{String, Any} with 8 entries: "objective_lb" => -Inf "termination_status" => LOCALLY_SOLVED "objective" => 5906.88 "primal_status" => FEASIBLE_POINT "dual_status" => FEASIBLE_POINT "optimizer" => "Ipopt" "solve_time" => 0.00492406 "solution" => Dict{String, Any}("baseMVA"=>100.0, "multinetwork"=>f…
julia> network_data["load"]["3"]["pd"] = 0.0;
julia> network_data["load"]["3"]["qd"] = 0.0;
julia> solve_opf( network_data, ACPPowerModel, optimizer_with_attributes(Ipopt.Optimizer, "print_level" => 0), )Dict{String, Any} with 8 entries: "objective_lb" => -Inf "termination_status" => LOCALLY_SOLVED "objective" => 2937.16 "primal_status" => FEASIBLE_POINT "dual_status" => FEASIBLE_POINT "optimizer" => "Ipopt" "solve_time" => 0.00427198 "solution" => Dict{String, Any}("baseMVA"=>100.0, "multinetwork"=>f…

Network data parsed from PTI .raw files supports data extensions, that is, data fields that are within the PSS(R)E specification, but not used by PowerModels for calculation. This can be achieved by:

julia> filename = joinpath(DATA_DIR, "pti", "case3.raw")"/home/runner/work/PowerModels.jl/PowerModels.jl/test/data/pti/case3.raw"
julia> network_data = PowerModels.parse_file(filename; import_all = true)Dict{String, Any} with 22 entries: "baseMVA" => 100.0 "storage" => Dict{String, Any}() "name" => "case3" "owner" => Dict{String, Any}("1"=>Dict{String, Any}("owname"=>"1",… "nxfrat" => 0 "xfrrat" => 0 "comment_line_2" => "this case does not have an HVDC line that occurs in th… "basfrq" => 60.0 "switch" => Dict{String, Any}() "zone" => Dict{String, Any}("1"=>Dict{String, Any}("i"=>1, "zonam… "bus" => Dict{String, Any}("3"=>Dict{String, Any}("evhi"=>1.1, "… "shunt" => Dict{String, Any}() "area interchange" => Dict{String, Any}("1"=>Dict{String, Any}("isw"=>0, "i"=… "source_type" => "pti" "per_unit" => true "ic" => 0 "dcline" => Dict{String, Any}() "comment_line_1" => "tests basic network fetures" "gen" => Dict{String, Any}("3"=>Dict{String, Any}("zr"=>0.0, "gt… ⋮ => ⋮

This network data can be modified in the same way as the previous Matpower .m file example.

For additional details about the network data, see the PowerModels Network Data Format section.

Inspecting AC and DC branch flow results

The flow AC and DC branch results are written to the result by default. The following can be used to inspect the flow results:

julia> result = solve_opf(
           joinpath(DATA_DIR, "matpower", "case5_dc.m"),
           ACPPowerModel,
           optimizer_with_attributes(Ipopt.Optimizer, "print_level" => 0),
       )Dict{String, Any} with 8 entries:
  "objective_lb"       => -Inf
  "termination_status" => LOCALLY_SOLVED
  "objective"          => 18156.2
  "primal_status"      => FEASIBLE_POINT
  "dual_status"        => FEASIBLE_POINT
  "optimizer"          => "Ipopt"
  "solve_time"         => 0.0105369
  "solution"           => Dict{String, Any}("baseMVA"=>100.0, "multinetwork"=>f…
julia> result["solution"]["dcline"]["1"]Dict{String, Any} with 5 entries: "pt" => -0.089 "p_dc_cost" => 400.0 "qf" => -1.0 "pf" => 0.1 "qt" => 0.108245
julia> result["solution"]["branch"]["2"]Dict{String, Any} with 4 entries: "pt" => -1.86988 "qf" => 0.394971 "pf" => 1.8798 "qt" => -0.303066

The losses of an AC or DC branch can be derived:

julia> loss_ac = Dict(
           name => data["pt"]+data["pf"]
           for (name, data) in result["solution"]["branch"]
       )Dict{String, Float64} with 6 entries:
  "3" => 0.00530134
  "4" => 0.00370667
  "1" => 0.0175942
  "2" => 0.00992406
  "5" => 0.00947219
  "6" => 0.0154276
julia> loss_dc = Dict( name => data["pt"]+data["pf"] for (name, data) in result["solution"]["dcline"] )Dict{String, Float64} with 1 entry: "1" => 0.011

Building PowerModels from Network Data Dictionaries

The following example demonstrates how to break a solve_opf call into separate model building and solving steps. This allows inspection of the JuMP model created by PowerModels for the AC-OPF problem,

julia> pm = instantiate_model(
           joinpath(DATA_DIR, "matpower", "case3.m"),
           ACPPowerModel,
           PowerModels.build_opf,
       );
julia> pm.modelA JuMP Model ├ solver: none ├ objective_sense: MIN_SENSE │ └ objective_function_type: JuMP.QuadExpr ├ num_variables: 28 ├ num_constraints: 79 │ ├ JuMP.NonlinearExpr in MOI.EqualTo{Float64}: 12 │ ├ JuMP.AffExpr in MOI.EqualTo{Float64}: 8 │ ├ JuMP.AffExpr in MOI.Interval{Float64}: 3 │ ├ JuMP.QuadExpr in MOI.LessThan{Float64}: 6 │ ├ JuMP.VariableRef in MOI.GreaterThan{Float64}: 25 │ └ JuMP.VariableRef in MOI.LessThan{Float64}: 25 └ Names registered in the model: none
julia> print(pm.model)Min 850.0000000000001 0_pg[2]² + 1100 0_pg[1]² + 120 0_pg[2] + 500 0_pg[1] Subject to 0_p[(3, 1, 2)] - ((0.05173917542536994 0_vm[1]²) + -0.05173917542536994 * ((0_vm[1]*0_vm[2]) * cos(-0_va[2] + 0_va[1])) + 1.1086966162579273 * ((0_vm[1]*0_vm[2]) * sin(-0_va[2] + 0_va[1]))) = 0 0_q[(3, 1, 2)] - (((0.9586966162579272 0_vm[1]²) - 1.1086966162579273 * ((0_vm[1]*0_vm[2]) * cos(-0_va[2] + 0_va[1]))) + -0.05173917542536994 * ((0_vm[1]*0_vm[2]) * sin(-0_va[2] + 0_va[1]))) = 0 0_p[(3, 2, 1)] - ((0.05173917542536994 0_vm[2]²) + -0.05173917542536994 * ((0_vm[2]*0_vm[1]) * cos(0_va[2] - 0_va[1])) + 1.1086966162579273 * ((0_vm[2]*0_vm[1]) * sin(0_va[2] - 0_va[1]))) = 0 0_q[(3, 2, 1)] - (((0.9586966162579272 0_vm[2]²) - 1.1086966162579273 * ((0_vm[2]*0_vm[1]) * cos(0_va[2] - 0_va[1]))) + -0.05173917542536994 * ((0_vm[2]*0_vm[1]) * sin(0_va[2] - 0_va[1]))) = 0 0_p[(2, 3, 2)] - ((0.044395116537180916 0_vm[3]²) + -0.044395116537180916 * ((0_vm[3]*0_vm[2]) * cos(0_va[3] - 0_va[2])) + 1.3318534961154274 * ((0_vm[3]*0_vm[2]) * sin(0_va[3] - 0_va[2]))) = 0 0_q[(2, 3, 2)] - (((0.9818534961154274 0_vm[3]²) - 1.3318534961154274 * ((0_vm[3]*0_vm[2]) * cos(0_va[3] - 0_va[2]))) + -0.044395116537180916 * ((0_vm[3]*0_vm[2]) * sin(0_va[3] - 0_va[2]))) = 0 0_p[(2, 2, 3)] - ((0.044395116537180916 0_vm[2]²) + -0.044395116537180916 * ((0_vm[2]*0_vm[3]) * cos(-0_va[3] + 0_va[2])) + 1.3318534961154274 * ((0_vm[2]*0_vm[3]) * sin(-0_va[3] + 0_va[2]))) = 0 0_q[(2, 2, 3)] - (((0.9818534961154274 0_vm[2]²) - 1.3318534961154274 * ((0_vm[2]*0_vm[3]) * cos(-0_va[3] + 0_va[2]))) + -0.044395116537180916 * ((0_vm[2]*0_vm[3]) * sin(-0_va[3] + 0_va[2]))) = 0 0_p[(1, 1, 3)] - ((0.16725635252492763 0_vm[1]²) + -0.16725635252492763 * ((0_vm[1]*0_vm[3]) * cos(-0_va[3] + 0_va[1])) + 1.5953682856223865 * ((0_vm[1]*0_vm[3]) * sin(-0_va[3] + 0_va[1]))) = 0 0_q[(1, 1, 3)] - (((1.3703682856223864 0_vm[1]²) - 1.5953682856223865 * ((0_vm[1]*0_vm[3]) * cos(-0_va[3] + 0_va[1]))) + -0.16725635252492763 * ((0_vm[1]*0_vm[3]) * sin(-0_va[3] + 0_va[1]))) = 0 0_p[(1, 3, 1)] - ((0.16725635252492763 0_vm[3]²) + -0.16725635252492763 * ((0_vm[3]*0_vm[1]) * cos(0_va[3] - 0_va[1])) + 1.5953682856223865 * ((0_vm[3]*0_vm[1]) * sin(0_va[3] - 0_va[1]))) = 0 0_q[(1, 3, 1)] - (((1.3703682856223864 0_vm[3]²) - 1.5953682856223865 * ((0_vm[3]*0_vm[1]) * cos(0_va[3] - 0_va[1]))) + -0.16725635252492763 * ((0_vm[3]*0_vm[1]) * sin(0_va[3] - 0_va[1]))) = 0 0_va[1] = 0 -0_pg[3] + 0_p[(2, 3, 2)] + 0_p[(1, 3, 1)] = -0.95 -0_qg[3] + 0_q[(2, 3, 2)] + 0_q[(1, 3, 1)] = -0.5 -0_pg[2] + 0_p[(3, 2, 1)] + 0_p[(2, 2, 3)] + 0_p_dc[(1, 2, 1)] = -1.1 -0_qg[2] + 0_q[(3, 2, 1)] + 0_q[(2, 2, 3)] + 0_q_dc[(1, 2, 1)] = -0.4 -0_pg[1] + 0_p[(3, 1, 2)] + 0_p[(1, 1, 3)] + 0_p_dc[(1, 1, 2)] = -1.1 -0_qg[1] + 0_q[(3, 1, 2)] + 0_q[(1, 1, 3)] + 0_q_dc[(1, 1, 2)] = -0.4 0_p_dc[(1, 1, 2)] + 0_p_dc[(1, 2, 1)] = 0 -0_va[2] + 0_va[1] ∈ [-0.5235987755982988, 0.5235987755982988] 0_va[3] - 0_va[2] ∈ [-0.5235987755982988, 0.5235987755982988] -0_va[3] + 0_va[1] ∈ [-0.5235987755982988, 0.5235987755982988] 0_p[(3, 1, 2)]² + 0_q[(3, 1, 2)]² ≤ 8100 0_p[(3, 2, 1)]² + 0_q[(3, 2, 1)]² ≤ 8100 0_p[(2, 3, 2)]² + 0_q[(2, 3, 2)]² ≤ 0.25 0_p[(2, 2, 3)]² + 0_q[(2, 2, 3)]² ≤ 0.25 0_p[(1, 1, 3)]² + 0_q[(1, 1, 3)]² ≤ 8100 0_p[(1, 3, 1)]² + 0_q[(1, 3, 1)]² ≤ 8100 0_vm[3] ≥ 0.9 0_vm[2] ≥ 0.9 0_vm[1] ≥ 0.9 0_pg[3] ≥ 0 0_pg[2] ≥ 0 0_pg[1] ≥ 0 0_qg[3] ≥ -10 0_qg[2] ≥ -10 0_qg[1] ≥ -10 0_p[(3, 1, 2)] ≥ -90 0_p[(2, 3, 2)] ≥ -0.5 0_p[(1, 1, 3)] ≥ -90 0_p[(3, 2, 1)] ≥ -90 0_p[(2, 2, 3)] ≥ -0.5 0_p[(1, 3, 1)] ≥ -90 0_q[(3, 1, 2)] ≥ -90 0_q[(2, 3, 2)] ≥ -0.5 0_q[(1, 1, 3)] ≥ -90 0_q[(3, 2, 1)] ≥ -90 0_q[(2, 2, 3)] ≥ -0.5 0_q[(1, 3, 1)] ≥ -90 0_p_dc[(1, 1, 2)] ≥ 0.1 0_p_dc[(1, 2, 1)] ≥ -9 0_q_dc[(1, 1, 2)] ≥ -9 0_q_dc[(1, 2, 1)] ≥ -9 0_vm[3] ≤ 1.1 0_vm[2] ≤ 1.1 0_vm[1] ≤ 1.1 0_pg[3] ≤ 0 0_pg[2] ≤ 15 0_pg[1] ≤ 20 0_qg[3] ≤ 10 0_qg[2] ≤ 10 0_qg[1] ≤ 10 0_p[(3, 1, 2)] ≤ 90 0_p[(2, 3, 2)] ≤ 0.5 0_p[(1, 1, 3)] ≤ 90 0_p[(3, 2, 1)] ≤ 90 0_p[(2, 2, 3)] ≤ 0.5 0_p[(1, 3, 1)] ≤ 90 0_q[(3, 1, 2)] ≤ 90 0_q[(2, 3, 2)] ≤ 0.5 0_q[(1, 1, 3)] ≤ 90 0_q[(3, 2, 1)] ≤ 90 0_q[(2, 2, 3)] ≤ 0.5 0_q[(1, 3, 1)] ≤ 90 0_p_dc[(1, 1, 2)] ≤ 9 0_p_dc[(1, 2, 1)] ≤ -0.1 0_q_dc[(1, 1, 2)] ≤ 9 0_q_dc[(1, 2, 1)] ≤ 9
julia> result = optimize_model!( pm; optimizer = optimizer_with_attributes(Ipopt.Optimizer, "print_level" => 0), )Dict{String, Any} with 8 entries: "objective_lb" => -Inf "termination_status" => LOCALLY_SOLVED "objective" => 5906.88 "primal_status" => FEASIBLE_POINT "dual_status" => FEASIBLE_POINT "optimizer" => "Ipopt" "solve_time" => 0.00504518 "solution" => Dict{String, Any}("baseMVA"=>100.0, "multinetwork"=>f…

Alternatively, you can further break it up by parsing a file into a network data dictionary, before passing it on to instantiate_model() like so:

julia> network_data = PowerModels.parse_file(
           joinpath(DATA_DIR, "matpower", "case3.m"),
       );
julia> pm = instantiate_model(network_data, ACPPowerModel, PowerModels.build_opf);
julia> result = optimize_model!( pm; optimizer = optimizer_with_attributes(Ipopt.Optimizer, "print_level" => 0), )Dict{String, Any} with 8 entries: "objective_lb" => -Inf "termination_status" => LOCALLY_SOLVED "objective" => 5906.88 "primal_status" => FEASIBLE_POINT "dual_status" => FEASIBLE_POINT "optimizer" => "Ipopt" "solve_time" => 0.00480199 "solution" => Dict{String, Any}("baseMVA"=>100.0, "multinetwork"=>f…