Static OPF

ExaModelsPower.jl can model large-scale optimal power flow (OPF) problems using the ExaModels package to generate models that can be solved using either CPU or GPU. This tutorial will demonstrate how ExaModelsPower.jl can be leveraged to solve different versions of the OPF, and how the user can customize the solving technique to better match their needs. Currently, all models generated by ExaModelsPower represent the full, AC version of the OPF formulation without any simplifications.

The latest version of ExaModelsPower can be installed in julia as so. Additionally, in order to develop models that can be solved on the GPU, CUDA is required.

using ExaModelsPower, CUDA
Precompiling packages...
   2622.8 ms  ✓ LLVMExtra_jll
   3569.5 ms  ✓ StringManipulation
   5949.5 ms  ✓ CUDA_Runtime_jll
   3890.6 ms  ✓ CUDA_Compiler_jll
  16998.6 ms  ✓ StaticArrays
   1282.0 ms  ✓ StaticArrays → StaticArraysStatisticsExt
   1263.2 ms  ✓ Adapt → AdaptStaticArraysExt
  16948.8 ms  ✓ LLVM
   2185.5 ms  ✓ LLVM → BFloat16sExt
   2682.4 ms  ✓ GPUToolbox
   3368.2 ms  ✓ UnsafeAtomics → UnsafeAtomicsLLVM
   8562.7 ms  ✓ KernelAbstractions
   1439.7 ms  ✓ KernelAbstractions → LinearAlgebraExt
   1987.4 ms  ✓ KernelAbstractions → SparseArraysExt
  35014.6 ms  ✓ PrettyTables
  13677.9 ms  ✓ GPUArrays
  45422.2 ms  ✓ GPUCompiler
 107119.6 ms  ✓ CUDA
   8461.1 ms  ✓ Atomix → AtomixCUDAExt
  19 dependencies successfully precompiled in 184 seconds. 70 already precompiled.
Precompiling packages...
   3892.4 ms  ✓ ExaModels → ExaModelsKernelAbstractions
  1 dependency successfully precompiled in 4 seconds. 34 already precompiled.
Precompiling packages...
   8019.3 ms  ✓ LinearOperators → LinearOperatorsCUDAExt
  1 dependency successfully precompiled in 12 seconds. 92 already precompiled.
Precompiling packages...
   8094.8 ms  ✓ ExaModels → ExaModelsCUDA
  1 dependency successfully precompiled in 9 seconds. 99 already precompiled.

In order to solve the ExaModels developed by ExaModelsPower, an NLP solver is required. ExaModels is compatible with MadNLP and Ipopt, but this tutorial will focus on MadNLP to demonstrate GPU solving capabilities.

using MadNLP, MadNLPGPU #, NLPModelsIpopt
Precompiling packages...
  49743.1 ms  ✓ MadNLP
  1 dependency successfully precompiled in 50 seconds. 45 already precompiled.
Precompiling packages...
   3849.1 ms  ✓ CUDSS_jll
  10215.5 ms  ✓ CUDSS
  12490.3 ms  ✓ MadNLPGPU
  3 dependencies successfully precompiled in 28 seconds. 108 already precompiled.

Finally, we install ExaModels to allow solved models to be unpacked.

using ExaModels

We will begin by constructing and solving a static OPF using the function opf_model. For the static OPF, the only input required is the filename for the OPF matpower file. The file does not need to be locally installed, and it will be automatically downloaded from power-grid-library if the file is not found in the user's data folder. If keywords are not specified, the numerical type will default to Float64, the backend will default to nothing (used on CPU) and the form will default to polar coordinates.

model, vars, cons = ac_opf_model(
    "pglib_opf_case118_ieee.m";
    backend = CUDABackend(),
    form = :polar,
    T = Float64
);
model
An ExaModel{Float64, CUDA.CuArray{Float64, 1, CUDA.DeviceMemory}, ...}

  Problem name: Generic
   All variables: ████████████████████ 1088   All constraints: ████████████████████ 1539  
            free: ███⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 118               free: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0     
           lower: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0                lower: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0     
           upper: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0                upper: █████⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 372   
         low/upp: ██████████████████⋅⋅ 935            low/upp: ███⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 186   
           fixed: █⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 35               fixed: █████████████⋅⋅⋅⋅⋅⋅⋅ 981   
          infeas: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0               infeas: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0     
            nnzh: ( 98.57% sparsity)   8474            linear: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0     
                                                    nonlinear: ████████████████████ 1539  
                                                         nnzj: ( 99.65% sparsity)   5925  
                                                     lin_nnzj: (------% sparsity)         
                                                     nln_nnzj: ( 99.65% sparsity)   5925  

Once the model is built, we can generate a solution using MadNLP.

result = madnlp(model; tol=1e-6)
"Execution stats: Optimal Solution Found (tol = 1.0e-06)."

Once a solution has been generated, the values of any of the variables in the model can be unpacked using the vars NamedTuple.

solution(result, vars.vm)[1:10]
10-element CUDA.CuArray{Float64, 1, CUDA.DeviceMemory}:
 1.02241390373351
 1.0292793230167676
 1.030273141859491
 1.0600010135870543
 1.058072514718105
 1.0519359527784349
 1.0473387353827157
 1.0459655545742539
 1.060001046633101
 1.0555993881471655

Result also stores the objective value.

result.objective
97210.50257420528

ExaModelsPower supports solving the OPF in either polar or rectangular coordinates.

model, vars, cons = ac_opf_model(
    "pglib_opf_case118_ieee.m";
    form = :rect
)
result = madnlp(model; tol=1e-6)
result.objective
97213.60754650853

In this case, the objective value and performance speed is comparable. However, for some cases, MadNLP can only solve the problem on one of the two available coordinate systems.


This page was generated using Literate.jl.