How pnnl/ll-risk-assessment works
1. What this repository is
This is a batch Python workflow around PSS/E for assessing risk from large dynamic digital loads (LDDLs). It is not a web service or library package; the architecture is a sequence of standalone scripts that pass files between stages.
2. Primary boundary: Python orchestration vs. PSS/E simulation engine
The Python scripts call into PSS/E v35 to read power-flow and dynamic cases, modify models, run time-domain simulations, and extract channel outputs. The main external dependency is the local PSS/E installation configured in psse_config.py.
3. Input case layer
Network models live in PSSE_Cases/ as .sav, .raw, and .dyr files. These are the base system artifacts that every stage reads and/or clones. The repo includes a WECC 240-bus example plus legacy/demo cases in RATLLE_v1.0/PSSE_Cases/.
4. Configuration-driven control plane
User choices are not hardcoded into the pipeline; they come from CSVs:
- Pre_Screening_config.csv for screening and modal prep
- modal_analysis_config.csv for impulse and mode estimation
- simulation_config.csv for oscillation scenario definition
These configs determine case name, bus, load size, oscillation shape, frequency, and amplitude.
5. Stage 1: case extraction and system summaries
Step1_extract_case_info.py reads the base PSS/E case and writes structured summaries into Processing/:
buses, branches, generators, loads, and areas. These CSVs become the data foundation for later selection, monitoring, and reporting steps.
6. Module 1: pre-screening for vulnerable locations
Step2a_locational_sensitivity.py computes local sensitivity metrics such as dV/dP, dV/dQ, and dθ/dP by applying small fictitious injections at candidate buses.
Step2b_load_impulse.py injects a load impulse at a selected bus and records the ringdown response.
Step2c_mode_estimates.py analyzes that response to identify excitable oscillatory modes.
Together, these scripts narrow the search space from “entire system” to “specific risky buses and frequencies.”
7. Module 2: simulation model preparation
Step3a_simsetup_loadadd.py transforms a chosen load into an LDDL scenario by modifying the case, creating LLmod.sav, LLmod.snp, and a modified .dyr. It also adds the oscillation injection block.
Step3b_simsetup_monitoredqty.py generates the monitored bus/branch/load/generator lists used for channel logging during simulation.
This stage is the main model-boundary transition from screening artifacts to executable dynamic simulation setup.
8. Stage 4: dynamic simulation execution
Step4_runsim.py runs the PSS/E time-domain simulation using the scenario parameters from simulation_config.csv.
The outputs are scenario-tagged and stored in results/ as simulation traces, typically a .out file plus a CSV export. The naming convention keeps multiple runs side-by-side without overwriting.
9. Module 3: post-simulation risk analysis
Step5_analyze_sim.py reads simulation time series and computes risk metrics for buses, generators, lines, loads, and LDDL-related quantities. It produces summary and detail CSVs for threshold violations, worst elements, and time-series metrics.
This is the main data-reduction boundary: dense simulation traces become decision-oriented risk reports.
10. Visualization and engineering checks
Step6_metrics_visualization.py turns analysis outputs into a self-contained HTML dashboard in results/, making the risk output directly reviewable without rerunning PSS/E.
Step7a_distance_z3_reach.py adds a protection-oriented boundary check by comparing apparent impedance trajectories against a Zone 3 distance relay reach.
Step7b_RAS_check.py evaluates simple remedial action scheme trigger rules against the simulated time series.
11. Working directories and artifact flow
Processing/ is the intermediate workspace for extracted case data, sensitivities, impulse responses, and monitored-element lists.
results/ is the final output workspace for simulation traces, metrics, violation tables, and dashboards.
The overall flow is: base case → extracted summaries → pre-screening/modal analysis → modified LDDL case + monitored channels → dynamic run → metrics/visualization/protection checks.
12. Legacy/packaged subproject
RATLLE_v1.0/ is a self-contained version of the same workflow with its own case examples, input configs, scripts, and documentation. Architecturally it mirrors the root-level pipeline, so you can treat it as an older packaged distribution rather than a separate subsystem.
Main entry points: Processing Processing · results Results · Step2a_locational_sensitivity.py Sensitivity · Step2b_load_impulse.py Impulse test
Components 23
Root workflow
Current batch pipeline for PSS/E-based LDDL risk assessment
- PSS/E config · Local engine configuration and import setup
psse_config.py - Screen config · Pre-screening and modal-analysis parameters
Pre_Screening_config.csv - Modal config · Impulse and mode-estimation parameters
modal_analysis_config.csv - Sim config · Dynamic scenario definition for simulation runs
simulation_config.csv - Base cases · Source power-flow and dynamic cases
PSSE_Cases - Extract case · Reads the base case and writes buses, branches, generators, loads, and areas
Step1_extract_case_info.py - Processing · Intermediate artifacts for summaries, sensitivities, impulse responses, and monitored lists
Processing - Sensitivity · Computes local voltage and angle sensitivities around candidate buses
Step2a_locational_sensitivity.py - Impulse test · Injects a load impulse and records ringdown response
Step2b_load_impulse.py - Mode estimates · Extracts excitable oscillatory modes from impulse response
Step2c_mode_estimates.py - Build LDDL · Modifies the case into an LDDL scenario and writes modified case artifacts
Step3a_simsetup_loadadd.py - Monitor setup · Generates monitored buses, branches, loads, and generators for simulation logging
Step3b_simsetup_monitoredqty.py - Run sim · Executes the PSS/E time-domain run and exports scenario-tagged traces
Step4_runsim.py - Results · Final simulation traces, metrics, violation tables, and dashboards
results - Analyze risk · Computes risk metrics and violation summaries from simulation time series
Step5_analyze_sim.py - Visualize metrics · Builds a self-contained HTML risk dashboard
Step6_metrics_visualization.py - Zone 3 check · Tests apparent-impedance trajectories against distance relay reach
Step7a_distance_z3_reach.py - RAS check · Evaluates remedial action scheme trigger rules against simulation output
Step7b_RAS_check.py
Legacy package
Older packaged distribution that mirrors the root workflow
- RATLLE v1.0 · Older self-contained distribution of the same workflow
RATLLE_v1.0 - Legacy main · Legacy end-to-end risk assessment driver
RATLLE_v1.0/main_LL_risk_assessment.py - Legacy summary · Legacy case summary generator
RATLLE_v1.0/system_summary.py - Legacy viz · Legacy plotting and visualization helpers
RATLLE_v1.0/LDDL_Viz_Functions.py
External engine
Local PSS/E installation used to read cases, run dynamics, and export channels
- PSS/E v35 · External dynamic simulation and case-processing engine
Connections 35
- PSS/E config → PSS/E v35: configures · Sets up access to the local PSS/E installation
- Base cases → Extract case: input · Base cases are summarized into structured system data
- PSS/E v35 → Extract case: reads · PSS/E reads the case model during extraction
- Extract case → Processing: writes · Exports bus, branch, generator, load, and area summaries
- Screen config → Sensitivity: drives · Provides pre-screening choices and candidate-bus parameters
- Processing → Sensitivity: reads · Uses extracted system summaries for sensitivity calculations
- PSS/E v35 → Sensitivity: simulates · Applies fictitious injections through PSS/E
- Sensitivity → Processing: writes · Stores sensitivity metrics for later selection
- Modal config → Impulse test: drives · Provides impulse and modal-analysis settings
- Sensitivity → Impulse test: selects · Narrows the candidate bus for impulse testing
- PSS/E v35 → Impulse test: simulates · Runs the impulse perturbation and ringdown capture
- Impulse test → Processing: writes · Stores impulse traces and response data
- Impulse test → Mode estimates: feeds · Impulse response is analyzed for oscillatory modes
- Modal config → Mode estimates: drives · Provides frequency and analysis settings
- Mode estimates → Processing: writes · Stores modal estimates and dominant frequencies
- Sim config → Build LDDL: drives · Selects scenario bus, load size, oscillation shape, frequency, and amplitude
- Processing → Build LDDL: reads · Uses selected bus and monitored context for case modification
- Base cases → Build LDDL: clones · Creates modified LDDL case artifacts from the base model
- Build LDDL → Processing: writes · Creates modified case files such as LLmod.sav and LLmod.snp
- Monitor setup → Processing: writes · Exports monitored buses, lines, loads, and generators
- Sim config → Run sim: drives · Provides the scenario parameters for the run
- Build LDDL → Run sim: inputs · Supplies the modified dynamic case for execution
- Monitor setup → Run sim: inputs · Supplies channel lists for logging
- PSS/E v35 → Run sim: runs · Executes the time-domain simulation in PSS/E
- Run sim → Results: writes · Stores run traces and scenario-tagged outputs
- Results → Analyze risk: reads · Consumes simulation traces for risk scoring
- Analyze risk → Results: writes · Produces metrics, violations, and worst-element summaries
- Analyze risk → Visualize metrics: feeds · Analysis outputs are turned into a dashboard
- Results → Visualize metrics: reads · Uses metrics and time-series outputs for visualization
- Results → Zone 3 check: reads · Uses simulation trajectories for relay reach evaluation
- Results → RAS check: reads · Uses simulation trajectories for RAS rule evaluation
- RATLLE v1.0 → Legacy main: contains · Packaged legacy end-to-end workflow
- Legacy main → Legacy summary: uses · Legacy driver relies on system summaries
- Legacy main → Legacy viz: uses · Legacy driver relies on visualization helpers
- RATLLE v1.0 → Base cases: ships cases · Legacy package includes example PSS/E cases