|
| 1 | +# PowerNetworkMatrices.jl - Project Guide |
| 2 | + |
| 3 | +> **Note:** For general NREL-Sienna programming practices, conventions, and guidelines, see [Sienna.md](Sienna.md). |
| 4 | +
|
| 5 | +## Package Role |
| 6 | + |
| 7 | +PowerNetworkMatrices.jl constructs classic power systems network matrices (Ybus, PTDF, LODF) for power flow analysis, sensitivity analysis, and contingency studies. Part of the NREL-Sienna ecosystem, it provides computational building blocks for optimization and analysis packages. |
| 8 | + |
| 9 | +## Design Objectives |
| 10 | + |
| 11 | +### Primary: Performance |
| 12 | + |
| 13 | +Efficient computation of power network matrices for large-scale systems. Supports sparse and virtual (on-demand) matrix implementations for memory efficiency. Network reduction algorithms decrease computational complexity by 30-60%. **All code must be written with performance in mind.** |
| 14 | + |
| 15 | +### Package-Specific Design Principles |
| 16 | + |
| 17 | +- Support multiple electrical islands (subnetworks) transparently |
| 18 | +- Provide both dense and memory-efficient virtual matrix options |
| 19 | +- Leverage KLU factorization for sparse linear solves |
| 20 | +- **definitions.jl**: constants (solvers, cache limits, tolerances) |
| 21 | +- **common.jl**: shared utility functions and getters |
| 22 | +- **system_utils.jl**: PowerSystems integration helpers |
| 23 | +- **serialization.jl**: HDF5 I/O support |
| 24 | + |
| 25 | +#### Network Matrices |
| 26 | +- **PowerNetworkMatrix.jl**: abstract base type implementing array interface |
| 27 | +- **Ybus.jl**: nodal admittance matrix (Complex, sparse) |
| 28 | +- **IncidenceMatrix.jl**: bus-branch connectivity (Int8, sparse) |
| 29 | +- **AdjacencyMatrix.jl**: bus connectivity structure |
| 30 | +- **BA_Matrix.jl**: branch susceptance weighted incidence |
| 31 | +- **ABA_Matrix.jl**: susceptance matrix for DC power flow |
| 32 | +- **ArcAdmittanceMatrix.jl**: arc-level admittance |
| 33 | +- **PTDF.jl**: power transfer distribution factors |
| 34 | +- **LODF.jl**: line outage distribution factors |
| 35 | +- **VirtualPTDF.jl**: on-demand PTDF with row caching |
| 36 | +- **VirtualLODF.jl**: on-demand LODF with row caching |
| 37 | +- **row_cache.jl**: LRU caching for virtual matrices |
| 38 | +- **ptdf_calculations.jl**: PTDF computation (KLU, Dense, MKL, Apple) |
| 39 | +- **lodf_calculations.jl**: LODF calculation from PTDF |
| 40 | +- **virtual_ptdf_calculations.jl**: on-demand PTDF row computation |
| 41 | +- **virtual_lodf_calculations.jl**: on-demand LODF row computation |
| 42 | + |
| 43 | +#### Network Reduction |
| 44 | +- **NetworkReduction.jl**: abstract base for reductions |
| 45 | +- **NetworkReductionData.jl**: tracks bus/branch mappings |
| 46 | +- **radial_reduction.jl**: eliminates dangling buses |
| 47 | +- **degree_two_reduction.jl**: eliminates degree-2 buses |
| 48 | +- **ward_reduction.jl**: preserves study area, reduces external |
| 49 | +- **BranchesParallel.jl**: parallel branch equivalencing |
| 50 | +- **BranchesSeries.jl**: series chain compression |
| 51 | +- **ThreeWindingTransformerWinding.jl**: 3-winding transformer support |
| 52 | +- **EquivalentBranch.jl**: equivalent branch representation |
| 53 | + |
| 54 | +#### Connectivity |
| 55 | +- **connectivity_checks.jl**: electrical island detection |
| 56 | +- **subnetworks.jl**: multi-island handling |
| 57 | + |
| 58 | +### `ext/` |
| 59 | +- **MKLPardisoExt.jl**: MKL-Pardiso sparse solver (Windows/Linux) |
| 60 | +- **AppleAccelerateExt.jl**: native macOS BLAS acceleration |
| 61 | + |
| 62 | +### `test/` |
| 63 | +Test files validating against PSS/E and Matpower cases |
| 64 | + |
| 65 | +### `docs/` |
| 66 | +Documentation source |
| 67 | + |
| 68 | +## Consumed By |
| 69 | + |
| 70 | +- **PowerSimulations.jl**: production cost modeling, unit commitment, economic dispatch |
| 71 | +- **PowerFlows.jl**: power flow analysis |
| 72 | +- **PowerSystemsInvestmentsPortfolios.jl**: capacity expansion portfolios |
| 73 | + |
| 74 | +## Dependencies |
| 75 | + |
| 76 | +### Primary |
| 77 | +- **PowerSystems.jl**: power system data structures and components |
| 78 | +- **InfrastructureSystems.jl**: shared utilities for NREL packages |
| 79 | + |
| 80 | +### Computational |
| 81 | +- **KLU.jl**: default sparse LU factorization solver |
| 82 | +- **SparseArrays**: sparse matrix storage (stdlib) |
| 83 | +- **LinearAlgebra**: matrix operations (stdlib) |
| 84 | + |
| 85 | +### Data |
| 86 | +- **HDF5.jl**: matrix serialization |
| 87 | +- **DataStructures.jl**: SortedDict and utilities |
| 88 | + |
| 89 | +### Optional Extensions |
| 90 | +- **MKL + Pardiso**: high-performance sparse factorization |
| 91 | +- **AppleAccelerate**: native macOS dense linear algebra |
| 92 | + |
| 93 | +## Core Abstractions |
| 94 | + |
| 95 | +### Base Type |
| 96 | + |
| 97 | +**`PowerNetworkMatrix{T}`**: Abstract type inheriting from `AbstractArray{T, 2}`. All matrices implement standard Julia array indexing with support for bus numbers and branch identifiers directly. Provides axes, lookup dictionaries, and subnetwork handling. |
| 98 | + |
| 99 | +### Matrix Types |
| 100 | + |
| 101 | +#### Network Model |
| 102 | +- **Ybus**: N_buses × N_buses complex sparse nodal admittance matrix |
| 103 | +- **IncidenceMatrix**: N_branches × N_buses Int8 sparse bus-branch connectivity |
| 104 | +- **AdjacencyMatrix**: N_buses × N_buses Int8 sparse bus connectivity |
| 105 | +- **BA_Matrix**: N_buses × N_branches Float64 sparse susceptance-weighted incidence |
| 106 | +- **ABA_Matrix**: N_buses × N_buses Float64 sparse factorized susceptance matrix |
| 107 | +- **ArcAdmittanceMatrix**: N_arcs × N_buses complex sparse arc admittance |
| 108 | + |
| 109 | +#### Sensitivity Analysis |
| 110 | +- **PTDF**: N_arcs × N_buses power transfer distribution factors (transposed storage) |
| 111 | +- **LODF**: N_arcs × N_arcs line outage distribution factors (diagonal = -1.0) |
| 112 | +- **VirtualPTDF**: on-demand PTDF with LRU row caching for memory efficiency |
| 113 | +- **VirtualLODF**: on-demand LODF with LRU row caching |
| 114 | + |
| 115 | +### Network Reduction |
| 116 | +- **NetworkReduction**: abstract base for reduction strategies |
| 117 | +- **RadialReduction**: eliminates radial (dangling) buses |
| 118 | +- **DegreeTwoReduction**: eliminates degree-two buses |
| 119 | +- **WardReduction**: preserves study area while reducing external network |
| 120 | +- **NetworkReductionData**: tracks all reduction mappings and equivalents |
| 121 | + |
| 122 | +### Key Patterns |
| 123 | + |
| 124 | +- **Indexing**: `matrix[bus_num, branch_tuple]` auto-maps to internal indices |
| 125 | +- **Subnetworks**: `subnetwork_axes` Dict maps reference buses to island components |
| 126 | +- **Caching**: VirtualPTDF/LODF use LRU cache (default 100 MiB) for row storage |
| 127 | +- **Solvers**: KLU (default), Dense, MKLPardiso, AppleAccelerate via extensions |
| 128 | + |
| 129 | +## Test Patterns |
| 130 | + |
| 131 | +- **Location**: `test/` |
| 132 | +- **Dev local**: `julia --project=test -e 'using Pkg; Pkg.develop(path=".")'` |
| 133 | +- **Runner**: `julia --project=test test/runtests.jl` |
| 134 | +- **Test data**: uses PowerSystemCaseBuilder.jl for standard IEEE/Matpower cases |
| 135 | +- **Validation**: results compared against PSS/E and Matpower reference implementations |
| 136 | + |
| 137 | +## Code Conventions |
| 138 | + |
| 139 | +**Style Guide:** [NREL-Sienna Style Guide](https://nrel-sienna.github.io/InfrastructureSystems.jl/stable/style/) |
| 140 | + |
| 141 | +### Formatter |
| 142 | +- **Tool**: JuliaFormatter |
| 143 | +- **Command**: `julia -e 'include("scripts/formatter/formatter_code.jl")'` |
| 144 | + |
| 145 | +### Key Rules |
| 146 | +- **Constructors**: use `function Foo()` not `Foo() = ...` |
| 147 | +- **Asserts**: prefer `InfrastructureSystems.@assert_op` over `@assert` |
| 148 | +- **Globals**: UPPER_CASE for constants |
| 149 | +- **Exports**: all exports in main module file |
| 150 | +- **Comments**: complete sentences, describe why not how |
| 151 | +- **Sparse matrices**: use `SparseMatrixCSC` throughout, avoid dense when possible |
| 152 | + |
| 153 | +## Documentation Practices |
| 154 | + |
| 155 | +**Framework:** [Diataxis](https://diataxis.fr/) |
| 156 | +**Sienna Guide:** [Documentation Best Practices](https://nrel-sienna.github.io/InfrastructureSystems.jl/stable/docs_best_practices/explanation/) |
| 157 | + |
| 158 | +### Docstring Requirements |
| 159 | +- **Scope**: all elements of public interface |
| 160 | +- **Include**: function signatures and arguments list |
| 161 | +- **Automation**: `DocStringExtensions.TYPEDSIGNATURES` |
| 162 | +- **See also**: add links for functions with same name (multiple dispatch) |
| 163 | + |
| 164 | +### API Docs |
| 165 | +- **Public**: `docs/src/api/public.md` using `@autodocs` with `Public=true, Private=false` |
| 166 | +- **Internals**: `docs/src/api/internals.md` |
| 167 | + |
| 168 | +## Common Tasks |
| 169 | + |
| 170 | +```bash |
| 171 | +# Develop locally |
| 172 | +julia --project=test -e 'using Pkg; Pkg.develop(path=".")' |
| 173 | + |
| 174 | +# Run tests |
| 175 | +julia --project=test test/runtests.jl |
| 176 | + |
| 177 | +# Build documentation |
| 178 | +julia --project=docs docs/make.jl |
| 179 | + |
| 180 | +# Format code |
| 181 | +julia -e 'include("scripts/formatter/formatter_code.jl")' |
| 182 | + |
| 183 | +# Check formatting |
| 184 | +git diff --exit-code |
| 185 | + |
| 186 | +# Instantiate test environment |
| 187 | +julia --project=test -e 'using Pkg; Pkg.instantiate()' |
| 188 | +``` |
| 189 | + |
| 190 | +## Contribution Workflow |
| 191 | + |
| 192 | +- **Branch naming**: `feature/description` or `fix/description` (branches in main repo) |
| 193 | +- **Main branch**: `main` |
| 194 | + |
| 195 | +### PR Process |
| 196 | +1. Create a feature branch in the main repo |
| 197 | +2. Make changes following the style guide |
| 198 | +3. Run formatter before committing |
| 199 | +4. Ensure tests pass |
| 200 | +5. Submit pull request |
| 201 | + |
| 202 | +## Package-Specific Troubleshooting |
| 203 | + |
| 204 | +### Subnetwork Errors |
| 205 | +- **Symptom**: Matrix construction fails with disconnected network |
| 206 | +- **Diagnosis**: Check for isolated buses or multiple electrical islands |
| 207 | +- **Solution**: Use `find_subnetworks()` to identify islands, ensure each has reference bus |
| 208 | + |
| 209 | +### Memory Issues |
| 210 | +- **Symptom**: Out of memory for large PTDF/LODF matrices |
| 211 | +- **Solution**: Use `VirtualPTDF`/`VirtualLODF` with row caching instead |
| 212 | + |
| 213 | +## AI Agent Guidance |
| 214 | + |
| 215 | +### Code Generation Priorities |
| 216 | +- Performance matters - use concrete types in hot paths |
| 217 | +- Use sparse matrices (`SparseMatrixCSC`) by default |
| 218 | +- Apply anti-patterns list with judgment (not exhaustively everywhere) |
| 219 | +- Run formatter on all changes |
| 220 | +- Add docstrings to public interface elements |
| 221 | +- Consider type stability in performance-critical functions |
| 222 | + |
| 223 | +### Domain Knowledge |
| 224 | +- PTDF[i,j] represents sensitivity of flow on arc i to injection at bus j |
| 225 | +- LODF[i,j] represents flow redistribution on arc i when arc j trips |
| 226 | +- Ybus diagonal elements are sum of admittances connected to that bus |
| 227 | +- Network reductions preserve electrical equivalence at retained buses |
| 228 | +- Virtual matrices trade computation time for memory efficiency |
| 229 | + |
| 230 | +### When Modifying Code |
| 231 | +- Read existing code patterns before making changes |
| 232 | +- Maintain consistency with existing style |
| 233 | +- Prefer failing fast with clear errors over silent failures |
| 234 | +- Consider impact on subnetwork handling (multiple islands) |
| 235 | +- Test with both single-island and multi-island systems |
0 commit comments