Skip to content

Commit 666ea8e

Browse files
some fixes for release (#253)
* add additional testing and remove info print * add local dev call to .clauderc * bump min test version * change claude implementation * update claude files * update base sienna.md * Update test/PowerNetworkMatricesTests.jl Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 65ed224 commit 666ea8e

6 files changed

Lines changed: 397 additions & 286 deletions

File tree

.claude/Sienna.md

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# Sienna Programming Practices
2+
3+
This document describes general programming practices and conventions that apply across all Sienna packages (PowerSystems.jl, PowerSimulations.jl, PowerFlows.jl, PowerNetworkMatrices.jl, InfrastructureSystems.jl, etc.).
4+
5+
## Performance Requirements
6+
7+
**Priority:** Critical. See the [Julia Performance Tips](https://docs.julialang.org/en/v1/manual/performance-tips/).
8+
9+
### Anti-Patterns to Avoid
10+
11+
#### Type instability
12+
13+
Functions must return consistent concrete types. Check with `@code_warntype`.
14+
15+
- Bad: `f(x) = x > 0 ? 1 : 1.0`
16+
- Good: `f(x) = x > 0 ? 1.0 : 1.0`
17+
18+
#### Abstract field types
19+
20+
Struct fields must have concrete types or be parameterized.
21+
22+
- Bad: `struct Foo; data::AbstractVector; end`
23+
- Good: `struct Foo{T<:AbstractVector}; data::T; end`
24+
25+
#### Untyped containers
26+
27+
- Bad: `Vector{Any}()`, `Vector{Real}()`
28+
- Good: `Vector{Float64}()`, `Vector{Int}()`
29+
30+
#### Non-const globals
31+
32+
- Bad: `THRESHOLD = 0.5`
33+
- Good: `const THRESHOLD = 0.5`
34+
35+
#### Unnecessary allocations
36+
37+
- Use views instead of copies (`@view`, `@views`)
38+
- Pre-allocate arrays instead of `push!` in loops
39+
- Use in-place operations (functions ending with `!`)
40+
41+
#### Captured variables
42+
43+
Avoid closures that capture variables causing boxing. Pass variables as function arguments instead.
44+
45+
#### Splatting penalty
46+
47+
Avoid splatting (`...`) in performance-critical code.
48+
49+
#### Abstract return types
50+
51+
Avoid returning `Union` types or abstract types.
52+
53+
### Best Practices
54+
55+
- Use `@inbounds` when bounds are verified
56+
- Use broadcasting (dot syntax) for element-wise operations
57+
- Avoid `try-catch` in hot paths
58+
- Use function barriers to isolate type instability
59+
60+
> Apply these guidelines with judgment. Not every function is performance-critical. Focus optimization efforts on hot paths and frequently called code.
61+
62+
## Code Conventions
63+
64+
Style guide: <https://nrel-sienna.github.io/InfrastructureSystems.jl/stable/style/>
65+
66+
Formatter (JuliaFormatter): Use the formatter script provided in each package.
67+
68+
Key rules:
69+
70+
- Constructors: use `function Foo()` not `Foo() = ...`
71+
- Asserts: prefer `InfrastructureSystems.@assert_op` over `@assert`
72+
- Globals: `UPPER_CASE` for constants
73+
- Exports: all exports in main module file
74+
- Comments: complete sentences, describe why not how
75+
76+
## Documentation Practices and Requirements
77+
78+
Framework: [Diataxis](https://diataxis.fr/)
79+
80+
Sienna guide: <https://nrel-sienna.github.io/InfrastructureSystems.jl/stable/docs_best_practices/explanation/>
81+
82+
Docstring requirements:
83+
84+
- Scope: all elements of public interface (IS is selective about exports)
85+
- Include: function signatures and arguments list
86+
- Automation: `DocStringExtensions.TYPEDSIGNATURES` (`TYPEDFIELDS` used sparingly in IS)
87+
- See also: add links for functions with same name (multiple dispatch)
88+
89+
API docs:
90+
91+
- Public: typically in `docs/src/api/public.md` using `@autodocs` with `Public=true, Private=false`
92+
- Internals: typically in `docs/src/api/internals.md`
93+
94+
## Design Principles
95+
96+
- Elegance and concision in both interface and implementation
97+
- Fail fast with actionable error messages rather than hiding problems
98+
- Validate invariants explicitly in subtle cases
99+
- Avoid over-adherence to backwards compatibility for internal helpers
100+
101+
## Contribution Workflow
102+
103+
Branch naming: `feature/description` or `fix/description`
104+
105+
1. Create feature branch
106+
2. Follow style guide and run formatter
107+
3. Ensure tests pass
108+
4. Submit pull request
109+
110+
## AI Agent Guidance
111+
112+
**Key priorities:** Read existing patterns first, maintain consistency, use concrete types in hot paths, run formatter, add docstrings to public API, ensure tests pass.
113+
114+
**Critical rules:**
115+
- Always use `julia --project=<env>` (never bare `julia`)
116+
- Never edit auto-generated files directly
117+
- Verify type stability with `@code_warntype` for performance-critical code
118+
- Consider downstream package impact
119+
120+
## Julia Environment Best Practices
121+
122+
**CRITICAL:** Always use `julia --project=<env>` when running Julia code in Sienna repositories. **NEVER** use bare `julia` or `julia --project` without specifying the environment. Each package typically defines dependencies in `test/Project.toml` for testing.
123+
124+
Common patterns:
125+
126+
```sh
127+
# Run tests (using test environment)
128+
julia --project=test test/runtests.jl
129+
130+
# Run specific test
131+
julia --project=test test/runtests.jl test_file_name
132+
133+
# Run expression
134+
julia --project=test -e 'using PackageName; ...'
135+
136+
# Instantiate environment
137+
julia --project=test -e 'using Pkg; Pkg.instantiate()'
138+
139+
# Build docs (using docs environment)
140+
julia --project=docs docs/make.jl
141+
```
142+
143+
**Why this matters:** Running without `--project=<env>` will fail because required packages won't be available in the default environment. The test/docs environments contain all necessary dependencies for their respective tasks.
144+
145+
## Troubleshooting
146+
147+
**Type instability**
148+
- Symptom: Poor performance, many allocations
149+
- Diagnosis: `@code_warntype` on suspect function
150+
- Solution: See performance anti-patterns above
151+
152+
**Formatter fails**
153+
- Symptom: Formatter command returns error
154+
- Solution: Run the formatter script provided in the package (e.g., `julia -e 'include("scripts/formatter/formatter_code.jl")'`)
155+
156+
**Test failures**
157+
- Symptom: Tests fail unexpectedly
158+
- Solution: `julia --project=test -e 'using Pkg; Pkg.instantiate()'`

.claude/claude.md

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
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

Comments
 (0)