How to Choose a Linear Solver

To follow along, you can download this tutorial as a Julia script (.jl) or Jupyter notebook (.ipynb).

This guide helps you select the appropriate linear solver for your network matrix computations.

Available Solvers

Pass the solver name as the linear_solver keyword to any matrix constructor (PTDF, LODF, ABA_Matrix, …). PowerNetworkMatrices.jl supports four:

  1. "KLU" - sparse KLU factorization Always available (built-in KLUWrapper submodule); the default off Apple hardware.
  2. "AppleAccelerateLU" - sparse LU via Apple's Accelerate sparse solvers. Always compiled in (built-in AccelerateWrapper submodule) but runtime-gated to macOS 15.5+ on Apple hardware, where it is the default.
  3. "MKLPardiso" - Intel's oneMKL PARDISO, wrapped by Pardiso.jl. A weak-dependency package extension: only loaded once you also add and import Pardiso.jl.
  4. "Dense" - dense LU from Julia's LinearAlgebra stdlib, for small or debugging cases.

The default is platform-dependent: AppleAccelerateLU on macOS 15.5+ (Apple hardware), KLU everywhere else. KLU and Apple Accelerate are always-present submodules — only MKL Pardiso is an optional extension.

The examples below use a small test system loaded with PowerSystemCaseBuilder.build_system:

using PowerNetworkMatrices
import PowerSystemCaseBuilder

sys = PowerSystemCaseBuilder.build_system(
    PowerSystemCaseBuilder.PSITestSystems,
    "c_sys5",
);
[ Info: Loaded time series from storage file existing=/home/runner/.julia/packages/PowerSystemCaseBuilder/zuCHR/data/serialized_system/8584b9e729c8aa68ee5405660c6258cde1f67ed3b68f114823707912e9a0d16c/c_sys5_time_series_storage.h5 new=/tmp/jl_plDTX5 compression=InfrastructureSystems.CompressionSettings(false, InfrastructureSystems.CompressionTypesModule.CompressionTypes.DEFLATE = 1, 3, true)

Choosing the Right Solver

Use KLU When:

  • Working with typical power systems (most cases)
  • System size is medium to large (> 100 buses)
  • You want good performance without special dependencies
  • Running on any platform (Linux, macOS, Windows)

Use PTDF with the KLU solver (the default off Apple hardware):

ptdf_matrix = PTDF(sys)  # platform default
# or explicitly:
ptdf_matrix = PTDF(sys; linear_solver = "KLU");
[ Info: Finding subnetworks via iterative union find
[ Info: Finding subnetworks via iterative union find

Use Apple Accelerate When:

  • Running on Apple-silicon macOS 15.5 or newer
  • You want the platform-tuned sparse LU (it is the default there)

Select it explicitly with the line below. It is shown rather than executed because this manual is built on Linux, where the backend is unavailable:

ptdf_matrix = PTDF(sys; linear_solver = "AppleAccelerateLU");

Use Dense When:

  • System is very small (< 30 buses)
  • You're debugging or validating results
  • Matrix operations are simple and small-scale

Pass it to PTDF the same way:

ptdf_matrix = PTDF(sys; linear_solver = "Dense");
[ Info: Finding subnetworks via iterative union find

Use MKLPardiso When:

  • You have Intel processors
  • Running on Linux or Windows (not available on Apple silicon)
  • Maximum performance is critical
  • Working with very large systems (> 1000 buses)

MKLPardiso lives in a weak-dependency package extension, so first add and import Pardiso.jl to load it, then request the solver. Pardiso.jl is not a dependency of this manual, so these two lines are shown rather than executed:

using Pardiso   # loads the MKLPardisoExt extension
ptdf_matrix = PTDF(sys; linear_solver = "MKLPardiso")

Performance Considerations

System Size

BusesRecommended Solver
< 30Dense or KLU
30-1000KLU
> 1000KLU or MKLPardiso

Platform Availability

SolverLinuxWindowsmacOS
KLU✓✓✓
AppleAccelerateLU✗✗✓ (Apple, 15.5+)
Dense✓✓✓
MKLPardiso✓✓✗

AppleAccelerateLU needs no extra package — it is built in. Only MKLPardiso requires installing and importing Pardiso.jl.

Singular ABA: prefer KLU

The two default solvers differ in how they treat a singular ABA matrix. AppleAccelerateLU silently factorizes a singular matrix and returns garbage, whereas KLU raises. Prefer "KLU" whenever the ABA matrix may be singular — for example a full outage that isolates a bus, such as a 3-winding transformer's zero-injection star bus. Build the PTDF with KLU in that case:

ptdf_safe = PTDF(sys; linear_solver = "KLU");   # safe when singularity is possible
[ Info: Finding subnetworks via iterative union find

Persisting a preferred backend

The active sparse backend can be pinned across Julia sessions with Preferences.jl via the (non-exported) helpers in src/linalg_settings.jl — PowerNetworkMatrices.set_linalg_backend_preference / PowerNetworkMatrices.get_linalg_backend_preference, PowerNetworkMatrices.set_linalg_backend_check / PowerNetworkMatrices.get_linalg_backend_check, and PowerNetworkMatrices.check_linalg_backend (reports the active BLAS/LAPACK library and whether the requested backend is loaded).

Troubleshooting

MKLPardiso Not Available

If you get an error when using MKLPardiso:

  1. Confirm you have added and imported Pardiso.jl (the extension only loads once Pardiso is available)
  2. Verify you're on Linux or Windows (not macOS)
  3. Check that you have Intel processors

Fall back to KLU if MKLPardiso is unavailable — it is always present.