package_role: >
  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.

julia_compat: "^1.9"

design_objectives:
  primary: performance
  description: >
    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.

  principles:
    - Elegance and concision in both interface and implementation
    - Fail fast with actionable error messages rather than hiding problems
    - Validate invariants explicitly in subtle cases
    - Avoid over-adherence to backwards compatibility for internal helpers
    - Support multiple electrical islands (subnetworks) transparently
    - Provide both dense and memory-efficient virtual matrix options

performance_requirements:
  priority: critical
  reference: https://docs.julialang.org/en/v1/manual/performance-tips/

  anti_patterns_to_avoid:
    type_instability:
      description: Functions must return consistent concrete types
      bad: "f(x) = x > 0 ? 1 : 1.0"
      good: "f(x) = x > 0 ? 1.0 : 1.0"
      check: "@code_warntype"

    abstract_field_types:
      description: Struct fields must have concrete types or be parameterized
      bad: "struct Foo; data::AbstractVector; end"
      good: "struct Foo{T<:AbstractVector}; data::T; end"

    untyped_containers:
      bad: "Vector{Any}(), Vector{Real}()"
      good: "Vector{Float64}(), Vector{Int}()"

    non_const_globals:
      bad: "THRESHOLD = 0.5"
      good: "const THRESHOLD = 0.5"

    unnecessary_allocations:
      patterns:
        - use views instead of copies (@view, @views)
        - pre-allocate arrays instead of push! in loops
        - use in-place operations (functions ending with !)

    captured_variables:
      description: Avoid closures that capture variables causing boxing
      solution: pass variables as function arguments instead

    splatting_penalty:
      description: Avoid splatting (...) in performance-critical code

    abstract_return_types:
      description: Avoid returning Union types or abstract types

  best_practices:
    - use @inbounds when bounds are verified
    - use broadcasting (dot syntax) for element-wise operations
    - avoid try-catch in hot paths
    - use function barriers to isolate type instability
    - use sparse matrix operations throughout (SparseMatrixCSC)
    - leverage KLU factorization for sparse linear solves

  note: >
    Apply these guidelines with judgment. Not every function is performance-critical.
    Focus optimization efforts on hot paths and frequently called code.

file_structure:
  src/:
    PowerNetworkMatrices.jl: main module, exports, includes
    definitions.jl: constants (solvers, cache limits, tolerances)
    common.jl: shared utility functions and getters
    system_utils.jl: PowerSystems integration helpers
    serialization.jl: HDF5 I/O support
    network_matrices/:
      PowerNetworkMatrix.jl: abstract base type implementing array interface
      Ybus.jl: nodal admittance matrix (Complex, sparse)
      IncidenceMatrix.jl: bus-branch connectivity (Int8, sparse)
      AdjacencyMatrix.jl: bus connectivity structure
      BA_Matrix.jl: branch susceptance weighted incidence
      ABA_Matrix.jl: susceptance matrix for DC power flow
      ArcAdmittanceMatrix.jl: arc-level admittance
      PTDF.jl: power transfer distribution factors
      LODF.jl: line outage distribution factors
      VirtualPTDF.jl: on-demand PTDF with row caching
      VirtualLODF.jl: on-demand LODF with row caching
      row_cache.jl: LRU caching for virtual matrices
      ptdf_calculations.jl: PTDF computation (KLU, Dense, MKL, Apple)
      lodf_calculations.jl: LODF calculation from PTDF
      virtual_ptdf_calculations.jl: on-demand PTDF row computation
      virtual_lodf_calculations.jl: on-demand LODF row computation
    network_reduction/:
      NetworkReduction.jl: abstract base for reductions
      NetworkReductionData.jl: tracks bus/branch mappings
      radial_reduction.jl: eliminates dangling buses
      degree_two_reduction.jl: eliminates degree-2 buses
      ward_reduction.jl: preserves study area, reduces external
      BranchesParallel.jl: parallel branch equivalencing
      BranchesSeries.jl: series chain compression
      ThreeWindingTransformerWinding.jl: 3-winding transformer support
      EquivalentBranch.jl: equivalent branch representation
    connectivity/:
      connectivity_checks.jl: electrical island detection
      subnetworks.jl: multi-island handling
  ext/:
    MKLPardisoExt.jl: MKL-Pardiso sparse solver (Windows/Linux)
    AppleAccelerateExt.jl: native macOS BLAS acceleration
  test/: test files validating against PSS/E and Matpower cases
  docs/: documentation source

consumed_by:
  - PowerSimulations.jl: production cost modeling, unit commitment, economic dispatch
  - PowerFlows.jl: power flow analysis
  - PowerSystemsInvestmentsPortfolios.jl: capacity expansion portfolios

dependencies:
  primary:
    - PowerSystems.jl: power system data structures and components
    - InfrastructureSystems.jl: shared utilities for NREL packages
  computational:
    - KLU.jl: default sparse LU factorization solver
    - SparseArrays: sparse matrix storage (stdlib)
    - LinearAlgebra: matrix operations (stdlib)
  data:
    - HDF5.jl: matrix serialization
    - DataStructures.jl: SortedDict and utilities
  optional_extensions:
    - MKL + Pardiso: high-performance sparse factorization
    - AppleAccelerate: native macOS dense linear algebra

core_abstractions:
  base_type:
    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.

  matrix_types:
    network_model:
      - Ybus: "N_buses × N_buses complex sparse nodal admittance matrix"
      - IncidenceMatrix: "N_branches × N_buses Int8 sparse bus-branch connectivity"
      - AdjacencyMatrix: "N_buses × N_buses Int8 sparse bus connectivity"
      - BA_Matrix: "N_buses × N_branches Float64 sparse susceptance-weighted incidence"
      - ABA_Matrix: "N_buses × N_buses Float64 sparse factorized susceptance matrix"
      - ArcAdmittanceMatrix: "N_arcs × N_buses complex sparse arc admittance"

    sensitivity_analysis:
      - PTDF: "N_arcs × N_buses power transfer distribution factors (transposed storage)"
      - LODF: "N_arcs × N_arcs line outage distribution factors (diagonal = -1.0)"
      - VirtualPTDF: "on-demand PTDF with LRU row caching for memory efficiency"
      - VirtualLODF: "on-demand LODF with LRU row caching"

  network_reduction:
    - NetworkReduction: abstract base for reduction strategies
    - RadialReduction: eliminates radial (dangling) buses
    - DegreeTwoReduction: eliminates degree-two buses
    - WardReduction: preserves study area while reducing external network
    - NetworkReductionData: tracks all reduction mappings and equivalents

  key_patterns:
    indexing: "matrix[bus_num, branch_tuple] auto-maps to internal indices"
    subnetworks: "subnetwork_axes Dict maps reference buses to island components"
    caching: "VirtualPTDF/LODF use LRU cache (default 100 MiB) for row storage"
    solvers: "KLU (default), Dense, MKLPardiso, AppleAccelerate via extensions"

test_patterns:
  location: test/
  runner: julia --project=test test/runtests.jl
  test_data: uses PowerSystemCaseBuilder.jl for standard IEEE/Matpower cases
  validation: results compared against PSS/E and Matpower reference implementations

code_conventions:
  style_guide_url: https://nrel-sienna.github.io/InfrastructureSystems.jl/stable/style/
  formatter:
    tool: JuliaFormatter
    command: julia -e 'include("scripts/formatter/formatter_code.jl")'
  key_rules:
    constructors: use function Foo() not Foo() = ...
    asserts: prefer InfrastructureSystems.@assert_op over @assert
    globals: UPPER_CASE for constants
    exports: all exports in main module file
    comments: complete sentences, describe why not how
    sparse_matrices: use SparseMatrixCSC throughout, avoid dense when possible

documentation_practices:
  framework: Diataxis (https://diataxis.fr/)
  sienna_guide: https://nrel-sienna.github.io/InfrastructureSystems.jl/stable/docs_best_practices/explanation/

  docstring_requirements:
    scope: all elements of public interface
    include: function signatures and arguments list
    automation: DocStringExtensions.TYPEDSIGNATURES
    see_also: add links for functions with same name (multiple dispatch)

  api_docs:
    public: docs/src/api/public.md using @autodocs with Public=true, Private=false
    internals: docs/src/api/internals.md

common_tasks:
  run_tests: julia --project=test test/runtests.jl
  build_docs: julia --project=docs docs/make.jl
  format_code: julia -e 'include("scripts/formatter/formatter_code.jl")'
  check_format: git diff --exit-code
  instantiate_test: julia --project=test -e 'using Pkg; Pkg.instantiate()'

contribution_workflow:
  branch_naming: feature/description or fix/description (branches in main repo)
  main_branch: main
  pr_process:
    - Create a feature branch in the main repo
    - Make changes following the style guide
    - Run formatter before committing
    - Ensure tests pass
    - Submit pull request

troubleshooting:
  type_instability:
    symptom: Poor performance, many allocations
    diagnosis: "@code_warntype on suspect function"
    solution: See performance_requirements.anti_patterns_to_avoid

  formatter_fails:
    symptom: Formatter command returns error
    solution: julia -e 'include("scripts/formatter/formatter_code.jl")'

  test_failures:
    symptom: Tests fail unexpectedly
    solution: julia --project=test -e 'using Pkg; Pkg.instantiate()'

  subnetwork_errors:
    symptom: Matrix construction fails with disconnected network
    diagnosis: check for isolated buses or multiple electrical islands
    solution: use find_subnetworks() to identify islands, ensure each has reference bus

  memory_issues:
    symptom: Out of memory for large PTDF/LODF matrices
    solution: use VirtualPTDF/VirtualLODF with row caching instead

ai_agent_guidance:
  code_generation_priorities:
    - Performance matters - use concrete types in hot paths
    - Use sparse matrices (SparseMatrixCSC) by default
    - Apply anti-patterns list with judgment (not exhaustively everywhere)
    - Run formatter on all changes
    - Add docstrings to public interface elements
    - Consider type stability in performance-critical functions

  domain_knowledge:
    - PTDF[i,j] represents sensitivity of flow on arc i to injection at bus j
    - LODF[i,j] represents flow redistribution on arc i when arc j trips
    - Ybus diagonal elements are sum of admittances connected to that bus
    - Network reductions preserve electrical equivalence at retained buses
    - Virtual matrices trade computation time for memory efficiency

  when_modifying_code:
    - Read existing code patterns before making changes
    - Maintain consistency with existing style
    - Prefer failing fast with clear errors over silent failures
    - Consider impact on subnetwork handling (multiple islands)
    - Test with both single-island and multi-island systems
