Skip to content

About

The repo formulates the flow matrix , PTDF and LODF .

Resources

Stars

0 stars

Watchers

1 watching

Forks

Latest commit

Β 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

⚑ Power System Sensitivity Factors β€” PTDF, LODF & GSF

A production-grade Python toolkit for computing and analyzing network sensitivity factors in electricity markets and transmission planning.
Built by a power systems & market engineer with hands-on experience across ERCOT, MISO, PJM, SPP, and the Australian NEM.


🧭 Overview

Network sensitivity factors are at the heart of transmission planning, security-constrained economic dispatch (SCED), and locational marginal pricing (LMP). Every time a market operator clears energy β€” whether it's AEMO's NEM dispatch engine or PJM's real-time market β€” these linear approximations of power flow govern how generation shift propagates through the network.

This project computes, validates, and visualizes three foundational sensitivity matrices:

Factor Full Name Core Question It Answers
PTDF Power Transfer Distribution Factor "If I shift 1 MW from bus A to bus B, what fraction flows on line k?"
LODF Line Outage Distribution Factor "If line k trips, what fraction of its pre-outage flow diverts onto line m?"
GSF / ISF Generation Shift Factor / Injection Shift Factor "If generator at bus i increases output by 1 MW (slack absorbs), what is the change in flow on line k?"

Together, these factors power:

  • Contingency Analysis (N-1, N-2) β€” rapid screening without full AC power flow
  • Congestion Rent & FTR/CRR Valuation β€” financial transmission rights settlement
  • Interface Limit Monitoring β€” enforcing flowgate constraints in real-time dispatch
  • Integrated System Planning β€” REZ capacity expansion & transmission augmentation studies (e.g., AEMO ISP)
  • Production Cost Modeling β€” PLEXOS and PROMOD constraint formulations

πŸ“ Mathematical Foundations

Network Representation

A power network is represented by its bus admittance matrix $Y_{bus}$ (or its DC approximation). Under the DC power flow linearization (lossless, flat voltage profile, small angle differences):

$$P_{flow} = B_{f} \cdot \theta$$

$$B_{bus} \cdot \theta = P_{inject}$$

Where:

  • $B_{bus} \in \mathbb{R}^{n \times n}$ β€” susceptance matrix (nodal)
  • $B_f \in \mathbb{R}^{l \times n}$ β€” branch susceptance matrix
  • $\theta \in \mathbb{R}^{n}$ β€” voltage angle vector
  • $P_{inject} \in \mathbb{R}^{n}$ β€” net bus injections (generation βˆ’ load)

1️⃣ Power Transfer Distribution Factor (PTDF)

The PTDF matrix $H$ is defined as:

$$H = B_f \cdot B_{bus,red}^{-1}$$

Where $B_{bus,red}$ is the reduced susceptance matrix (reference bus row/column removed). Each element:

$$\text{PTDF}_{k, i \to j} = H_{k,i} - H_{k,j}$$

represents the fraction of a 1 MW transaction from bus $i$ to bus $j$ that flows on branch $k$.

Key properties:

  • $\sum_k \text{PTDF}_{k, i \to j} \neq 1$ (flows split across parallel paths)
  • PTDF is topology-dependent β€” it changes with network switching
  • Used in zonal PTDFs for market clearing (e.g., AEMO's regional reference nodes)

2️⃣ Line Outage Distribution Factor (LODF)

When line $k$ is outaged, the flow redistribution onto line $m$ is:

$$\text{LODF}_{m,k} = \frac{\Delta F_m}{F_k^0}$$

Computed analytically from the PTDF matrix:

$$\text{LODF}_{m,k} = \frac{\text{PTDF}_{m, i(k) \to j(k)}}{1 - \text{PTDF}_{k, i(k) \to j(k)}}$$

Where $i(k)$ and $j(k)$ are the from-bus and to-bus of the outaged line $k$.

Key properties:

  • $\text{LODF}_{k,k} = -1$ (outaged line carries zero flow post-outage)
  • Enables N-1 contingency screening in $O(l^2)$ vs. full power flow per contingency
  • Foundation of post-contingency flow calculation: $F_m^{post} = F_m^{pre} + \text{LODF}_{m,k} \cdot F_k^{pre}$

3️⃣ Generation Shift Factor (GSF) / Injection Shift Factor (ISF)

The GSF for generator at bus $i$ on branch $k$:

$$\text{GSF}_{k,i} = H_{k,i}$$

This is simply the $i$-th column of the PTDF matrix (relative to the slack bus). It answers: "If bus $i$ increases injection by 1 MW with the slack bus absorbing, how does flow on branch $k$ change?"

Relationship between factors:

$$\text{PTDF}_{k, i \to j} = \text{GSF}_{k,i} - \text{GSF}_{k,j}$$

Applications:

  • SCED constraint formulation β€” each generator's impact on monitored flowgates
  • Congestion component of LMP β€” $\lambda_k^{congestion} = \sum_m \mu_m \cdot \text{GSF}_{m,k}$ where $\mu_m$ is the shadow price on constraint $m$
  • Redispatch analysis β€” identifying which generators relieve congestion most efficiently

πŸ—‚οΈ Repository Structure

power-sensitivity-factors/
β”‚
β”œβ”€β”€ data/
β”‚   β”œβ”€β”€ raw/                    # Raw network data (MATPOWER, PSS/E, CSV)
β”‚   β”œβ”€β”€ processed/              # Cleaned bus/branch/gen tables
β”‚   └── test_cases/             # IEEE 14-bus, 30-bus, 118-bus test cases
β”‚
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ network/
β”‚   β”‚   β”œβ”€β”€ __init__.py
β”‚   β”‚   β”œβ”€β”€ admittance.py       # Y_bus, B_bus construction
β”‚   β”‚   β”œβ”€β”€ dc_powerflow.py     # DC power flow solver
β”‚   β”‚   └── topology.py         # Network graph utilities
β”‚   β”‚
β”‚   β”œβ”€β”€ sensitivity/
β”‚   β”‚   β”œβ”€β”€ __init__.py
β”‚   β”‚   β”œβ”€β”€ ptdf.py             # PTDF computation engine
β”‚   β”‚   β”œβ”€β”€ lodf.py             # LODF computation (full & sparse)
β”‚   β”‚   β”œβ”€β”€ gsf.py              # GSF / ISF computation
β”‚   β”‚   └── contingency.py      # N-1 / N-2 screening using LODF
β”‚   β”‚
β”‚   β”œβ”€β”€ market/
β”‚   β”‚   β”œβ”€β”€ lmp_decomposition.py   # Energy + congestion + loss components
β”‚   β”‚   β”œβ”€β”€ ftr_valuation.py       # Financial transmission rights
β”‚   β”‚   └── flowgate_monitor.py    # Real-time interface monitoring
β”‚   β”‚
β”‚   └── visualization/
β”‚       β”œβ”€β”€ network_plot.py     # Networkx / plotly network diagrams
β”‚       β”œβ”€β”€ heatmaps.py         # PTDF/LODF matrix heatmaps
β”‚       └── congestion_map.py   # Geospatial congestion overlays
β”‚
β”œβ”€β”€ notebooks/
β”‚   β”œβ”€β”€ 01_theory_and_derivation.ipynb     # Mathematical walkthrough
β”‚   β”œβ”€β”€ 02_ieee14_ptdf_demo.ipynb          # PTDF on IEEE 14-bus
β”‚   β”œβ”€β”€ 03_n1_contingency_screening.ipynb  # LODF-based contingency analysis
β”‚   β”œβ”€β”€ 04_lmp_decomposition.ipynb         # Congestion pricing example
β”‚   └── 05_nem_interface_monitoring.ipynb  # Australian NEM flowgate case study
β”‚
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ test_ptdf.py
β”‚   β”œβ”€β”€ test_lodf.py
β”‚   β”œβ”€β”€ test_gsf.py
β”‚   └── validate_against_powerworld.py    # Cross-validation with commercial tools
β”‚
β”œβ”€β”€ docs/
β”‚   β”œβ”€β”€ theory.md               # Extended mathematical documentation
β”‚   β”œβ”€β”€ market_applications.md  # How factors are used in market operations
β”‚   └── aemo_case_study.md      # NEM-specific application notes
β”‚
β”œβ”€β”€ requirements.txt
β”œβ”€β”€ environment.yml
└── README.md

πŸš€ Quick Start

Installation

git clone https://github.com/shankar/<repo-name>.git
cd power-sensitivity-factors

# Using pip
pip install -r requirements.txt

# Or using conda (recommended for power systems stack)
conda env create -f environment.yml
conda activate power-sensitivity

Dependencies

numpy>=1.24
scipy>=1.10          # sparse matrix operations (critical for large networks)
pandas>=2.0
networkx>=3.0        # network topology
pandapower>=2.13     # power system modeling & validation
matplotlib>=3.7
plotly>=5.15         # interactive network visualization
pypower              # MATPOWER-compatible DC/AC power flow

Compute PTDF β€” Minimal Example

import numpy as np
from src.network.admittance import build_Bbus
from src.sensitivity.ptdf import compute_ptdf

# Load IEEE 14-bus test case
from pypower.case14 import case14
ppc = case14()

# Build susceptance matrices
Bf, Bbus = build_Bbus(ppc)

# Compute full PTDF matrix [branches x buses]
ptdf = compute_ptdf(Bf, Bbus, ref_bus=0)

print(f"PTDF shape: {ptdf.shape}")  # (20, 14) for IEEE 14-bus
print(f"PTDF[line_1, bus_2β†’bus_5]: {ptdf[0, 1] - ptdf[0, 4]:.4f}")

Compute LODF from PTDF

from src.sensitivity.lodf import compute_lodf

# LODF matrix [branches x branches]
lodf = compute_lodf(ptdf, ppc['branch'])

# Post-contingency flow on line m when line k trips
line_k = 5   # outaged line index
pre_flow = np.array([...])   # pre-contingency flows in MW

post_flow = pre_flow + lodf[:, line_k] * pre_flow[line_k]
print(f"Post-contingency flow on line 3: {post_flow[2]:.2f} MW")

N-1 Contingency Screening

from src.sensitivity.contingency import n1_screening

results = n1_screening(
    base_flows=pre_flow,
    lodf=lodf,
    ratings=ppc['branch'][:, 5],   # thermal ratings in MVA
    threshold=0.95                  # flag at 95% of rating
)

violations = results[results['overload_pct'] > 100]
print(violations[['outaged_line', 'overloaded_line', 'overload_pct']])

πŸ“Š Key Results & Validation

IEEE 14-Bus PTDF Heatmap

The PTDF matrix visually reveals electrical coupling between transactions and branches. High-magnitude cells indicate strong sensitivity β€” a 1 MW shift on that bus pair significantly loads that branch.

πŸ““ See notebooks/02_ieee14_ptdf_demo.ipynb for full visualization

N-1 Contingency Screening Performance

Network Size Full AC Power Flow (per contingency) LODF Screening
14-bus (20 lines) ~400 power flows 1 matrix multiply
118-bus (186 lines) ~34,716 power flows 1 matrix multiply
2000-bus (3,000 lines) ~9M power flows Sparse matrix ops

LODF-based screening provides exact N-1 results under DC assumptions at a fraction of the computational cost β€” which is precisely why real-time market engines (ERCOT SCED, AEMO's dispatch engine) rely on them.

Validation

All sensitivity matrices are cross-validated against:

  • PYPOWER β€” open-source MATPOWER port
  • pandapower β€” for DC power flow cross-checks
  • Analytical hand-calculations β€” on 3-bus and 5-bus toy networks

🌏 Market Applications & Case Studies

Australian NEM β€” Interface Flow Monitoring

AEMO monitors interconnector flows (e.g., Heywood, QNI, Basslink) using sensitivity-based constraint formulations. The Market Constraint Equations in NEMDE (NEM Dispatch Engine) are linear constraint rows of the form:

Ξ£ (GSF_k,i Γ— P_i) ≀ RHS_k    for each monitored element k

This project includes a case study replicating NEM-style interface constraint formulation using publicly available AEMO network data.

πŸ““ See notebooks/05_nem_interface_monitoring.ipynb

LMP Congestion Component Decomposition

The congestion component of an LMP at bus $i$:

$$\lambda_i^{congestion} = -\sum_{k \in \text{binding}} \mu_k \cdot \text{GSF}_{k,i}$$

Where $\mu_k$ is the shadow price (dual variable) on binding constraint $k$. This project demonstrates LMP decomposition on a 5-bus illustrative network.

FTR / CRR Valuation

Financial Transmission Rights settle on the difference in LMPs weighted by the FTR MW quantity. Under the PTDF framework:

$$\text{FTR Revenue} = \text{FTR}_{MW} \times (\lambda_{sink} - \lambda_{source})$$

The project includes utilities for simulating FTR auction value under different congestion scenarios.


πŸ”¬ Implementation Notes

Numerical Stability

  • The $B_{bus}$ matrix inversion uses sparse LU factorization (scipy.sparse.linalg.splu) for large networks β€” critical for real-world systems with thousands of buses
  • Reference bus removal must be handled consistently β€” an off-by-one error here produces silently wrong PTDF values
  • For near-radial networks, some LODF denominators approach zero (radial line has PTDF β‰ˆ 1) β€” these are handled with a configurable threshold

Sparse vs Dense

For networks > 500 buses, dense matrix operations become prohibitive. The lodf.py module offers both:

  • compute_lodf_dense() β€” for small networks and testing
  • compute_lodf_sparse() β€” scipy sparse, suitable for real ISO-scale networks

Sign Convention

This implementation follows the from-bus injection positive convention consistent with MATPOWER and pandapower. Some commercial tools (PowerWorld, PSS/E) may use different sign conventions β€” always verify before cross-validation.


πŸ—ΊοΈ Roadmap

  • AC sensitivity factors (Q-V sensitivity, voltage sensitivity matrix)
  • Multi-period PTDF for time-varying topology (switching, maintenance outages)
  • LODF extension to N-2 contingencies (cascading failure screening)
  • Integration with NEMOSIS / AEMO data API for real NEM network data
  • PLEXOS-compatible constraint export (LP file format)
  • Interactive Plotly dashboard for congestion visualization

πŸ‘€ About the Author

Shankar β€” Simulation Engineer | Power Markets & Transmission Planning

πŸ“š References & Further Reading

  1. Stott, B., Jardim, J., AlsaΓ§, O. (2009). DC Power Flow Revisited. IEEE Transactions on Power Systems.
  2. Wood, A.J., Wollenberg, B.F., SheblΓ©, G.B. β€” Power Generation, Operation and Control (3rd Ed.)
  3. Ott, A. (2010). Experience with PJM Market Operation, System Design, and Implementation β€” IEEE Trans. Power Systems
  4. AEMO β€” Integrated System Plan 2024, Constraint Formulation Guidelines
  5. Kirschen, D., Strbac, G. β€” Fundamentals of Power System Economics
  6. Christie, R.D., Wollenberg, B.F., Wangensteen, I. (2000). Transmission Management in the Deregulated Environment

πŸ“„ License

MIT License β€” see LICENSE for details.


About

The repo formulates the flow matrix , PTDF and LODF .

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages