Showing preview only (4,183K chars total). Download the full file or copy to clipboard to get everything.
Repository: NREL-SIIP/PowerSystems.jl
Branch: main
Commit: 667b5762ce2f
Files: 365
Total size: 3.9 MB
Directory structure:
gitextract_d2nxsq6e/
├── .claude/
│ ├── Sienna.md
│ └── claude.md
├── .devcontainer/
│ └── devcontainer.json
├── .editorconfig
├── .github/
│ ├── copilot-setup-steps.yml
│ ├── pull_request_template.md
│ └── workflows/
│ ├── TagBot.yml
│ ├── cross-package-test.yml
│ ├── doc-preview-cleanup.yml
│ ├── docs.yml
│ ├── fix-docs-on-failure.yml
│ ├── format-check.yml
│ ├── main-tests.yml
│ └── pr_testing.yml
├── .gitignore
├── .pre-commit-config.yaml
├── CHANGELOG.md
├── CITATION.cff
├── CONTRIBUTING.md
├── LICENSE
├── Project.toml
├── README.md
├── codecov.yml
├── docs/
│ ├── Makefile
│ ├── Project.toml
│ ├── make.jl
│ ├── make_model_library.jl
│ ├── make_tutorials.jl
│ └── src/
│ ├── api/
│ │ ├── citation.md
│ │ ├── developer_guidelines.md
│ │ ├── enumerated_types.md
│ │ ├── glossary.md
│ │ ├── internal.md
│ │ ├── psse_models.md
│ │ ├── public.md
│ │ ├── static_injection_subtypes.md
│ │ ├── type_tree.md
│ │ └── valuecurve_options.md
│ ├── explanation/
│ │ ├── buses_type_explanation.md
│ │ ├── conforming_and_non_conforming_loads.md
│ │ ├── dynamic_data.md
│ │ ├── per_unit.md
│ │ ├── plant_attributes.md
│ │ ├── power_concepts.md
│ │ ├── supplemental_attributes.md
│ │ ├── system.md
│ │ ├── time_series.md
│ │ ├── transformer_per_unit_models.md
│ │ └── type_structure.md
│ ├── generate_input_config_table.jl
│ ├── generate_validation_table.jl
│ ├── how_to/
│ │ ├── add_component_natural_units.md
│ │ ├── add_cost_curve.md
│ │ ├── add_fuel_curve_timeseries.md
│ │ ├── add_new_types.md
│ │ ├── adding_additional_fields.md
│ │ ├── build_system_with_files.md
│ │ ├── create_hydro_datasets.md
│ │ ├── create_system_with_source_import_export_cost.md
│ │ ├── handle_3W_transformers.md
│ │ ├── improve_ts_performance.md
│ │ ├── jump.md
│ │ ├── market_bid_cost.md
│ │ ├── migrating_to_psy5.md
│ │ ├── parse_dynamic_data.md
│ │ ├── parse_matpower_psse.md
│ │ ├── parse_ts_from_csvs.md
│ │ ├── reduce_repl_printing.md
│ │ ├── serialize_data.md
│ │ └── use_context_managers.md
│ ├── index.md
│ ├── model_library/
│ │ ├── dynamic_branch.md
│ │ ├── dynamic_generator.md
│ │ ├── dynamic_inverter.md
│ │ ├── hybrid_system.md
│ │ ├── hydro_generation_cost.md
│ │ ├── hydro_reservoir.md
│ │ ├── hydro_reservoir_cost.md
│ │ ├── import_export_cost.md
│ │ ├── load_cost.md
│ │ ├── market_bid_cost.md
│ │ ├── offer_curve_cost.md
│ │ ├── outer_control.md
│ │ ├── renewable_generation_cost.md
│ │ ├── reserves.md
│ │ ├── storage_cost.md
│ │ └── thermal_generation_cost.md
│ └── tutorials/
│ ├── add_dynamic_data.jl
│ ├── creating_system.jl
│ ├── manipulating_datasets.jl
│ ├── tutorials_data/
│ │ ├── RTS-GMLC.RAW
│ │ ├── RTS_GMLC.m
│ │ ├── TestGENCLS.dyr
│ │ ├── case5.m
│ │ └── case5_re.m
│ ├── utils/
│ │ └── docs_utils.jl
│ └── working_with_time_series.jl
├── scripts/
│ ├── formatter/
│ │ ├── Project.toml
│ │ └── formatter_code.jl
│ ├── generate_config_file.py
│ └── generate_validation_config_file.py
├── src/
│ ├── PowerSystems.jl
│ ├── base.jl
│ ├── component_selector.jl
│ ├── component_selector_interface.jl
│ ├── contingencies.jl
│ ├── data_format_conversions.jl
│ ├── definitions.jl
│ ├── deprecated.jl
│ ├── descriptors/
│ │ ├── power_system_inputs.json
│ │ └── power_system_structs.json
│ ├── get_components_interface.jl
│ ├── impedance_correction.jl
│ ├── models/
│ │ ├── HybridSystem.jl
│ │ ├── OuterControl.jl
│ │ ├── RoundRotorExponential.jl
│ │ ├── RoundRotorQuadratic.jl
│ │ ├── SalientPoleExponential.jl
│ │ ├── SalientPoleQuadratic.jl
│ │ ├── branches.jl
│ │ ├── components.jl
│ │ ├── cost_function_timeseries.jl
│ │ ├── cost_functions/
│ │ │ ├── HydroGenerationCost.jl
│ │ │ ├── HydroReservoirCost.jl
│ │ │ ├── ImportExportCost.jl
│ │ │ ├── LoadCost.jl
│ │ │ ├── MarketBidCost.jl
│ │ │ ├── OfferCurveCost.jl
│ │ │ ├── RenewableGenerationCost.jl
│ │ │ ├── StorageCost.jl
│ │ │ ├── ThermalGenerationCost.jl
│ │ │ └── operational_cost.jl
│ │ ├── devices.jl
│ │ ├── dynamic_branch.jl
│ │ ├── dynamic_generator.jl
│ │ ├── dynamic_generator_components.jl
│ │ ├── dynamic_inverter.jl
│ │ ├── dynamic_inverter_components.jl
│ │ ├── dynamic_loads.jl
│ │ ├── dynamic_machines.jl
│ │ ├── dynamic_models.jl
│ │ ├── generated/
│ │ │ ├── ACBus.jl
│ │ │ ├── AGC.jl
│ │ │ ├── AVRFixed.jl
│ │ │ ├── AVRSimple.jl
│ │ │ ├── AVRTypeI.jl
│ │ │ ├── AVRTypeII.jl
│ │ │ ├── ActiveConstantPowerLoad.jl
│ │ │ ├── ActivePowerDroop.jl
│ │ │ ├── ActivePowerPI.jl
│ │ │ ├── ActiveRenewableControllerAB.jl
│ │ │ ├── ActiveVirtualOscillator.jl
│ │ │ ├── AggregateDistributedGenerationA.jl
│ │ │ ├── AndersonFouadMachine.jl
│ │ │ ├── Arc.jl
│ │ │ ├── Area.jl
│ │ │ ├── AreaInterchange.jl
│ │ │ ├── AverageConverter.jl
│ │ │ ├── BaseMachine.jl
│ │ │ ├── CSVGN1.jl
│ │ │ ├── ConstantReserve.jl
│ │ │ ├── ConstantReserveGroup.jl
│ │ │ ├── ConstantReserveNonSpinning.jl
│ │ │ ├── CurrentModeControl.jl
│ │ │ ├── DCBus.jl
│ │ │ ├── DEGOV.jl
│ │ │ ├── DEGOV1.jl
│ │ │ ├── DiscreteControlledACBranch.jl
│ │ │ ├── DynamicExponentialLoad.jl
│ │ │ ├── ESAC1A.jl
│ │ │ ├── ESAC6A.jl
│ │ │ ├── ESAC8B.jl
│ │ │ ├── ESDC1A.jl
│ │ │ ├── ESDC2A.jl
│ │ │ ├── ESST1A.jl
│ │ │ ├── ESST4B.jl
│ │ │ ├── EX4VSA.jl
│ │ │ ├── EXAC1.jl
│ │ │ ├── EXAC1A.jl
│ │ │ ├── EXAC2.jl
│ │ │ ├── EXPIC1.jl
│ │ │ ├── EXST1.jl
│ │ │ ├── EnergyReservoirStorage.jl
│ │ │ ├── ExponentialLoad.jl
│ │ │ ├── FACTSControlDevice.jl
│ │ │ ├── FiveMassShaft.jl
│ │ │ ├── FixedAdmittance.jl
│ │ │ ├── FixedDCSource.jl
│ │ │ ├── FixedFrequency.jl
│ │ │ ├── FullMachine.jl
│ │ │ ├── GasTG.jl
│ │ │ ├── GeneralGovModel.jl
│ │ │ ├── GenericArcImpedance.jl
│ │ │ ├── GenericDER.jl
│ │ │ ├── HybridOutputCurrentLimiter.jl
│ │ │ ├── HydroDispatch.jl
│ │ │ ├── HydroPumpTurbine.jl
│ │ │ ├── HydroReservoir.jl
│ │ │ ├── HydroTurbine.jl
│ │ │ ├── HydroTurbineGov.jl
│ │ │ ├── IEEEST.jl
│ │ │ ├── IEEET1.jl
│ │ │ ├── IEEETurbineGov1.jl
│ │ │ ├── InstantaneousOutputCurrentLimiter.jl
│ │ │ ├── InterconnectingConverter.jl
│ │ │ ├── InterruptiblePowerLoad.jl
│ │ │ ├── InterruptibleStandardLoad.jl
│ │ │ ├── KauraPLL.jl
│ │ │ ├── LCFilter.jl
│ │ │ ├── LCLFilter.jl
│ │ │ ├── Line.jl
│ │ │ ├── LoadZone.jl
│ │ │ ├── MagnitudeOutputCurrentLimiter.jl
│ │ │ ├── MarconatoMachine.jl
│ │ │ ├── MonitoredLine.jl
│ │ │ ├── MotorLoad.jl
│ │ │ ├── OneDOneQMachine.jl
│ │ │ ├── PIDGOV.jl
│ │ │ ├── PSS2A.jl
│ │ │ ├── PSS2B.jl
│ │ │ ├── PSS2C.jl
│ │ │ ├── PSSFixed.jl
│ │ │ ├── PSSSimple.jl
│ │ │ ├── PeriodicVariableSource.jl
│ │ │ ├── PhaseShiftingTransformer.jl
│ │ │ ├── PhaseShiftingTransformer3W.jl
│ │ │ ├── PowerLoad.jl
│ │ │ ├── PriorityOutputCurrentLimiter.jl
│ │ │ ├── RECurrentControlB.jl
│ │ │ ├── RLFilter.jl
│ │ │ ├── ReactivePowerDroop.jl
│ │ │ ├── ReactivePowerPI.jl
│ │ │ ├── ReactiveRenewableControllerAB.jl
│ │ │ ├── ReactiveVirtualOscillator.jl
│ │ │ ├── ReducedOrderPLL.jl
│ │ │ ├── RenewableDispatch.jl
│ │ │ ├── RenewableEnergyConverterTypeA.jl
│ │ │ ├── RenewableEnergyVoltageConverterTypeA.jl
│ │ │ ├── RenewableNonDispatch.jl
│ │ │ ├── ReserveDemandCurve.jl
│ │ │ ├── RoundRotorMachine.jl
│ │ │ ├── SCRX.jl
│ │ │ ├── SEXS.jl
│ │ │ ├── ST6B.jl
│ │ │ ├── ST8C.jl
│ │ │ ├── STAB1.jl
│ │ │ ├── SalientPoleMachine.jl
│ │ │ ├── SaturationOutputCurrentLimiter.jl
│ │ │ ├── SauerPaiMachine.jl
│ │ │ ├── ShiftablePowerLoad.jl
│ │ │ ├── SimpleAFMachine.jl
│ │ │ ├── SimpleFullMachine.jl
│ │ │ ├── SimpleMarconatoMachine.jl
│ │ │ ├── SimplifiedSingleCageInductionMachine.jl
│ │ │ ├── SingleCageInductionMachine.jl
│ │ │ ├── SingleMass.jl
│ │ │ ├── Source.jl
│ │ │ ├── StandardLoad.jl
│ │ │ ├── SteamTurbineGov1.jl
│ │ │ ├── SwitchedAdmittance.jl
│ │ │ ├── SynchronousCondenser.jl
│ │ │ ├── TGFixed.jl
│ │ │ ├── TGSimple.jl
│ │ │ ├── TGTypeI.jl
│ │ │ ├── TGTypeII.jl
│ │ │ ├── TModelHVDCLine.jl
│ │ │ ├── TapTransformer.jl
│ │ │ ├── ThermalMultiStart.jl
│ │ │ ├── ThermalStandard.jl
│ │ │ ├── Transformer2W.jl
│ │ │ ├── Transformer3W.jl
│ │ │ ├── TransmissionInterface.jl
│ │ │ ├── TwoTerminalGenericHVDCLine.jl
│ │ │ ├── TwoTerminalLCCLine.jl
│ │ │ ├── TwoTerminalVSCLine.jl
│ │ │ ├── VariableReserve.jl
│ │ │ ├── VariableReserveNonSpinning.jl
│ │ │ ├── VirtualInertia.jl
│ │ │ ├── VoltageModeControl.jl
│ │ │ ├── WPIDHY.jl
│ │ │ ├── ZeroOrderBESS.jl
│ │ │ └── includes.jl
│ │ ├── generation.jl
│ │ ├── injection.jl
│ │ ├── loads.jl
│ │ ├── reserves.jl
│ │ ├── serialization.jl
│ │ ├── services.jl
│ │ ├── static_injection_subsystem.jl
│ │ ├── static_models.jl
│ │ ├── storage.jl
│ │ ├── supplemental_accessors.jl
│ │ ├── supplemental_constructors.jl
│ │ ├── supplemental_setters.jl
│ │ └── topological_elements.jl
│ ├── outages.jl
│ ├── parsers/
│ │ ├── common.jl
│ │ ├── enums.jl
│ │ ├── generator_mapping_cdm.yaml
│ │ ├── generator_mapping_pm.yaml
│ │ ├── im_io/
│ │ │ ├── LICENSE.md
│ │ │ ├── common.jl
│ │ │ ├── data.jl
│ │ │ └── matlab.jl
│ │ ├── im_io.jl
│ │ ├── pm_io/
│ │ │ ├── LICENSE.md
│ │ │ ├── common.jl
│ │ │ ├── data.jl
│ │ │ ├── matpower.jl
│ │ │ ├── psse.jl
│ │ │ └── pti.jl
│ │ ├── pm_io.jl
│ │ ├── power_models_data.jl
│ │ ├── power_system_table_data.jl
│ │ ├── powerflowdata_data.jl
│ │ ├── psse_dynamic_data.jl
│ │ ├── psse_dynamic_mapping.yaml
│ │ └── psse_metadata_reimport.jl
│ ├── plant_attribute.jl
│ ├── subsystems.jl
│ └── utils/
│ ├── IO/
│ │ ├── base_checks.jl
│ │ ├── branchdata_checks.jl
│ │ └── system_checks.jl
│ ├── conversion.jl
│ ├── generate_struct_files.jl
│ ├── logging.jl
│ ├── print.jl
│ ├── print_pt_v2.jl
│ └── print_pt_v3.jl
└── test/
├── Project.toml
├── common.jl
├── runtests.jl
├── test_base_checks.jl
├── test_base_power.jl
├── test_branchchecks_testing.jl
├── test_busnumberchecks.jl
├── test_component_selector.jl
├── test_constructors.jl
├── test_cost_functions.jl
├── test_devices.jl
├── test_dynamic_generator.jl
├── test_dynamic_inverter.jl
├── test_dynamic_loads.jl
├── test_dynamics_source.jl
├── test_generate_structs.jl
├── test_hybrid_system.jl
├── test_hydro_reservoir.jl
├── test_internal.jl
├── test_logging.jl
├── test_outages.jl
├── test_parse_dynamics.jl
├── test_parse_matpower.jl
├── test_parse_psse.jl
├── test_plant_attributes.jl
├── test_power_system_table_data.jl
├── test_powersystemconstructors.jl
├── test_printing.jl
├── test_read_time_series.jl
├── test_serialization.jl
├── test_services.jl
├── test_subsystems.jl
├── test_supplemental_accessors.jl
├── test_system.jl
├── test_topology.jl
└── test_validation.jl
================================================
FILE CONTENTS
================================================
================================================
FILE: .claude/Sienna.md
================================================
# Sienna Programming Practices
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.).
## Performance Requirements
**Priority:** Critical. See the [Julia Performance Tips](https://docs.julialang.org/en/v1/manual/performance-tips/).
### Anti-Patterns to Avoid
#### Type instability
Functions must return consistent concrete types. Check with `@code_warntype`.
- Bad: `f(x) = x > 0 ? 1 : 1.0`
- Good: `f(x) = x > 0 ? 1.0 : 1.0`
#### Abstract field types
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
- Use views instead of copies (`@view`, `@views`)
- Pre-allocate arrays instead of `push!` in loops
- Use in-place operations (functions ending with `!`)
#### Captured variables
Avoid closures that capture variables causing boxing. Pass variables as function arguments instead.
#### Splatting penalty
Avoid splatting (`...`) in performance-critical code.
#### Abstract return types
Avoid returning `Union` types or abstract types.
#### Using `isa` in function logic
**ABSOLUTELY FORBIDDEN unless the user explicitly asks for it.** Never write code that uses `isa` checks for type-based branching. This is always wrong — use multiple dispatch instead.
- Bad: `if x isa Float64 ... elseif x isa Int ... end`
- Good: Use multiple dispatch with specific type signatures
- Bad: `function f(x); if x isa AbstractVector return sum(x) else return x end; end`
- Good: `f(x::AbstractVector) = sum(x); f(x::Number) = x`
**Why this matters:** `isa` checks force the compiler to handle multiple code paths at runtime, losing type information and preventing specialization. Multiple dispatch allows the compiler to generate optimized code for each type. Using `isa` is an anti-pattern that defeats Julia's core design.
### 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
> Apply these guidelines with judgment. Not every function is performance-critical. Focus optimization efforts on hot paths and frequently called code.
## Code Conventions
Style guide: <https://sienna-platform.github.io/InfrastructureSystems.jl/stable/style/>
Formatter (JuliaFormatter): Use the formatter script provided in each package.
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
## Documentation Practices and Requirements
Framework: [Diataxis](https://diataxis.fr/)
Sienna guide: <https://sienna-platform.github.io/InfrastructureSystems.jl/stable/docs_best_practices/explanation/>
Docstring requirements:
- Scope: all elements of public interface (IS is selective about exports)
- Include: function signatures and arguments list
- Automation: `DocStringExtensions.TYPEDSIGNATURES` (`TYPEDFIELDS` used sparingly in IS)
- See also: add links for functions with same name (multiple dispatch)
API docs:
- Public: typically in `docs/src/api/public.md` using `@autodocs` with `Public=true, Private=false`
- Internals: typically in `docs/src/api/internals.md`
## Design 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
## Contribution Workflow
Branch naming: `feature/description` or `fix/description`
1. Create feature branch
2. Follow style guide and run formatter
3. Ensure tests pass
4. Submit pull request
## AI Agent Guidance
**Key priorities:** Read existing patterns first, maintain consistency, use concrete types in hot paths, run formatter, add docstrings to public API, ensure tests pass.
**Critical rules:**
- Always use `julia --project=<env>` (never bare `julia`)
- **NEVER use `isa` in function logic** — use multiple dispatch instead. This is absolutely forbidden unless the user explicitly asks for it.
- Never edit auto-generated files directly
- Verify type stability with `@code_warntype` for performance-critical code
- Consider downstream package impact
## Julia Environment Best Practices
**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.
Common patterns:
```sh
# Run tests (using test environment)
julia --project=test test/runtests.jl
# Run specific test
julia --project=test test/runtests.jl test_file_name
# Run expression
julia --project=test -e 'using PackageName; ...'
# Instantiate environment
julia --project=test -e 'using Pkg; Pkg.instantiate()'
# Build docs (using docs environment)
julia --project=docs docs/make.jl
```
**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.
## Troubleshooting
**Type instability**
- Symptom: Poor performance, many allocations
- Diagnosis: `@code_warntype` on suspect function
- Solution: See performance anti-patterns above
**Formatter fails**
- Symptom: Formatter command returns error
- Solution: Run the formatter script provided in the package (e.g., `julia -e 'include("scripts/formatter/formatter_code.jl")'`)
**Test failures**
- Symptom: Tests fail unexpectedly
- Solution: `julia --project=test -e 'using Pkg; Pkg.instantiate()'`
================================================
FILE: .claude/claude.md
================================================
# PowerSystems.jl
Data model library for power system simulation and optimization. Julia compat: `^1.10`.
> **General Sienna Programming Practices:** For information on performance requirements, code conventions, documentation practices, and contribution workflows that apply across all Sienna packages, see [Sienna.md](Sienna.md).
## Design Objectives
**Primary goal:** Performance and expressiveness.
Comprehensive data model library for power system simulation, optimization, and dynamics analysis. Provides the `System` container and all component types (generators, loads, branches, storage, dynamic models). Consumed by PowerSimulations.jl, PowerFlows.jl, PowerNetworkMatrices.jl, and other Sienna packages. All code must be written with performance in mind.
## File Structure
### `src/`
Key files:
- `PowerSystems.jl` -- main module, exports, and includes
- `base.jl` -- `System` type definition and core methods
- `definitions.jl` -- core type definitions and enums
- `deprecated.jl` -- deprecated function warnings
- `subsystems.jl` -- subsystem management
- `contingencies.jl` -- contingency definitions
- `outages.jl` -- outage modeling
- `component_selector.jl` -- component selection utilities
- `data_format_conversions.jl` -- format conversion methods
#### `models/`
Core component models and definitions:
- `components.jl` -- base component methods
- `devices.jl` -- device implementations
- `branches.jl` -- branch/transmission line definitions
- `topological_elements.jl` -- buses and topology
- `generation.jl` -- generation component definitions
- `storage.jl` -- storage/battery definitions
- `loads.jl` -- load component definitions
- `reserves.jl` -- reserve ancillary services
- `services.jl` -- all kinds of ancillary services (supertype to reserves)
- `static_models.jl` -- static component definitions
- `dynamic_generator.jl` -- dynamic generator models
- `dynamic_inverter.jl` -- dynamic inverter models
- `dynamic_branch.jl` -- dynamic branch models
- `dynamic_loads.jl` -- dynamic load models
- `HybridSystem.jl` -- hybrid renewable + storage systems
- `serialization.jl` -- component serialization
- `supplemental_constructors.jl` -- additional constructors
- `supplemental_accessors.jl` -- getter methods
- `supplemental_setters.jl` -- setter methods
- `generated/` -- auto-generated component type files (**DO NOT EDIT directly**)
- `cost_functions/` -- operational cost types (ThermalGenerationCost, StorageCost, etc.)
#### `parsers/`
Data parsing and import functionality:
- `common.jl` -- shared parsing utilities
- `power_system_table_data.jl` -- CSV/table-based data parsing
- `power_models_data.jl` -- PowerModels.jl format support
- `psse_dynamic_data.jl` -- PSS/E dynamic data parsing
- `pm_io/` -- PowerModels I/O (matpower.jl, psse.jl, pti.jl)
- `im_io/` -- InteractiveModels I/O (matlab.jl)
#### `utils/`
Utility functions:
- `print.jl` -- enhanced console display
- `generate_struct_files.jl` -- generate component definitions
- `logging.jl` -- logging configuration
- `conversion.jl` -- unit and format conversions
- `IO/` -- data validation (system_checks.jl, branchdata_checks.jl, base_checks.jl)
#### `descriptors/`
JSON schema and metadata:
- `power_system_structs.json` -- component structure definitions
- `power_system_inputs.json` -- input specifications
### Other top-level directories
- `test/` -- test suite
- `docs/` -- documentation source
- `scripts/` -- utility scripts (formatter)
## Auto-Generation
Component structs are auto-generated from JSON descriptors (`src/descriptors/power_system_structs.json`). Generated files are in `src/models/generated/` and should **NOT** be edited directly. Over 140 component types are auto-generated.
Generator: `src/utils/generate_struct_files.jl`
Workflow:
1. Edit `src/descriptors/power_system_structs.json` to define/modify struct fields
2. Run the generation script
3. Generated files include docstrings, constructors, and accessors automatically
## Downstream Packages
- **PowerSimulations.jl** -- production cost modeling and unit commitment
- **PowerFlows.jl** -- power flow analysis
- **PowerNetworkMatrices.jl** -- network matrix calculations
- **PowerSystemsInvestmentsPortfolios.jl** -- capacity expansion portfolios
## Dependencies
- **InfrastructureSystems.jl** -- base types, system data management, time series
- **PowerFlowData.jl** -- power flow data handling
- **DataFrames.jl** -- tabular data processing
- **TimeSeries.jl** -- time series data management
- **PrettyTables.jl** -- enhanced console output
## Core Abstractions
### System
Main container for power system data. Defined in `src/base.jl`.
Fields:
- `data` -- `IS.SystemData` for storing components and time series
- `frequency` -- system frequency (Hz)
- `bus_numbers` -- set of bus numbers for validation
- `runchecks` -- flag for data validation
- `units_settings` -- unit system settings (`SYSTEM_BASE`, `DEVICE_BASE`, `NATURAL_UNITS`)
Key methods: `add_component!`, `remove_component!`, `get_component`, `get_components`, `get_bus`, `set_units_base_system!`
### Component
Abstract base type for all power system elements.
Hierarchy:
- **Topology** -- network topology elements: `Bus` (`ACBus`, `DCBus`), `Arc`, `Area`, `LoadZone`
- **Device** -- physical equipment: `StaticInjection` (generators, loads, storage), `Branch` (lines, transformers)
- **Service** -- ancillary services (reserves, AGC)
- **DynamicComponent** -- dynamic models for stability analysis
### StaticInjection
Static injection devices (generators, loads, storage).
- **Generator:** `ThermalStandard`, `ThermalMultiStart`, `HydroDispatch`, `RenewableDispatch`, `RenewableNonDispatch`
- **Storage:** `EnergyReservoirStorage`, `HybridSystem`
- **ElectricLoad:** `PowerLoad`, `StandardLoad`, `InterruptiblePowerLoad`, `ControllableLoad`
- **StaticInjectionSubsystem:** grouped injection components
### Branch
Transmission elements connecting buses. Branches that contain Arcs with ACBuses are AC Branches and branches with DCBuses are DC Branches.
- **ACBranch:** `Line`, `TwoWindingTransformer`, `PhaseShiftingTransformer`, `TapTransformer`, `TwoTerminalHVDCLine`, `MonitoredLine`
- **DCBranch:** `TModelHVDCLine`
- **ControlledBranch:** `DiscreteControlledACBranch`
### DynamicInjection
Dynamic models for transient stability.
- **DynamicGenerator** -- synchronous machines with AVR, PSS, TurbineGovernor
- **DynamicInverter** -- inverter-based resources with converter, filter, controls
### Service
Ancillary services and system requirements.
- **Reserve:** `ConstantReserve`, `VariableReserve`, `ReserveDemandCurve`
- **AGC** -- automatic generation control
- **TransmissionInterface** -- interface flow limits
### OperationalCost
Cost structures for component operations.
- **ThermalGenerationCost** -- thermal unit costs with fuel, startup, variable O&M
- **HydroGenerationCost** -- hydro unit costs
- **RenewableGenerationCost** -- renewable unit costs
- **StorageCost** -- storage operation costs
- **MarketBidCost** -- market bid/offer curves
### TimeSeriesData
Time-varying data attached to components.
- **SingleTimeSeries** -- single scenario time series
- **Deterministic** -- deterministic forecast
- **Probabilistic** -- probabilistic forecast with scenarios
## Common Tasks
```sh
# Dev local copy
julia --project=test -e 'using Pkg; Pkg.develop(path = ".")'
# Run all tests
julia --project=test test/runtests.jl
# Run specific tests (without extension)
julia --project=test test/runtests.jl <test_file_name_without_extension>
# Example:
julia --project=test test/runtests.jl test_plant_attributes
# Build docs
julia --project=docs docs/make.jl
# Format code
julia -e 'include("scripts/formatter/formatter_code.jl")'
# Check formatting
git diff --exit-code
# Instantiate test environment
julia --project=test -e 'using Pkg; Pkg.instantiate()'
# Generate structs
julia --project=test -e "using InfrastructureSystems; InfrastructureSystems.generate_structs(\"./src/descriptors/power_system_structs.json\", \"./src/models/generated\")"
```
## PowerSystems.jl Specific Guidelines
### Julia Environment
**Always use `julia --project=test`** when running Julia code in this repository. See [Sienna.md](Sienna.md) for general Julia environment best practices. The `test/Project.toml` defines all required dependencies including PowerSystems, PowerSystemCaseBuilder, and InfrastructureSystems.
### Working with Auto-Generated Code
Component structs are auto-generated from `src/descriptors/power_system_structs.json`. Over 140 component types are auto-generated.
**DO NOT** edit files in `src/models/generated/` directly. Instead:
1. Edit `src/descriptors/power_system_structs.json` to define/modify struct fields
2. Run the generation script: `julia --project=test -e "using InfrastructureSystems; InfrastructureSystems.generate_structs(\"./src/descriptors/power_system_structs.json\", \"./src/models/generated\")"`
3. Generated files include docstrings, constructors, and accessors automatically
### PowerSystems-Specific Patterns
- **Component addition:** Use `add_component!(sys, component)` not direct insertion
- **Component retrieval:** Use `get_component(Type, sys, name)` or `get_components(Type, sys)`
- **Time series:** Always attach to components, never store standalone
- **Units:** Be mindful of `SYSTEM_BASE`, `DEVICE_BASE`, `NATURAL_UNITS` settings
- **Validation:** Use `runchecks=true` during development to catch issues early
- **Bus numbers:** Must be unique across system; validated on add
================================================
FILE: .devcontainer/devcontainer.json
================================================
{
"extensions": [
"julialang.language-julia"
],
"image": "ghcr.io/julia-vscode/julia-devcontainer"
}
================================================
FILE: .editorconfig
================================================
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
# Julia files
[*.jl]
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
================================================
FILE: .github/copilot-setup-steps.yml
================================================
name: "Copilot Setup Steps"
on: workflow_dispatch
jobs:
copilot-setup:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Julia
uses: julia-actions/setup-julia@v2
with:
version: "1"
- name: Install documentation dependencies
run: |
julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
================================================
FILE: .github/pull_request_template.md
================================================
Thanks for opening a PR to PowerSystems.jl, please take note of the following when making a PR:
Check the [contributor guidelines](https://sienna-platform.github.io/PowerSystems.jl/stable/api/developer_guidelines/)
1. Add a description of the changes proposed in the pull request.
2. Is my PR fixing an open issue? Add the reference to the related issue
3. If you are contributing a new struct: please refer to the [testing requirements for new structs](https://sienna-platform.github.io/PowerSystems.jl/stable/how_to/add_new_types/#Testing-the-addition-of-new-struct-to-the-code-base)
================================================
FILE: .github/workflows/TagBot.yml
================================================
name: TagBot
on:
issue_comment:
types:
- created
workflow_dispatch:
jobs:
TagBot:
if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot'
runs-on: ubuntu-latest
steps:
- uses: JuliaRegistries/TagBot@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
ssh: ${{ secrets.DOCUMENTER_KEY }}
================================================
FILE: .github/workflows/cross-package-test.yml
================================================
name: CrossPackageTest
on:
push:
branches: [main]
tags: [v*]
pull_request:
jobs:
test:
name: Julia v${{ matrix.julia-version }} - ${{ matrix.package_name }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
julia-version: [1]
os: [ubuntu-latest]
package_name: [PowerSimulations, PowerSystemCaseBuilder, PowerNetworkMatrices, PowerFlows]
continue-on-error: true
steps:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@v2
with:
version: ${{ matrix.julia-version }}
arch: x64
- uses: julia-actions/julia-buildpkg@latest
- name: Clone ${{matrix.package_name}}
uses: actions/checkout@v2
with:
repository: Sienna-Platform/${{matrix.package_name}}.jl
path: downstream
- name: Run the tests
shell: julia --project=downstream {0}
run: |
using Pkg
try
# Force it to use this PR's version of the package
Pkg.develop(PackageSpec(path=".")) # resolver may fail with main deps
Pkg.update()
Pkg.test() # resolver may fail with test time deps
catch err
err isa Pkg.Resolve.ResolverError || rethrow()
# If we can't resolve that means this is incompatible by SemVer, and this is fine.
# It means we marked this as a breaking change, so we don't need to worry about
# mistakenly introducing a breaking change as we have intentionally made one.
@info "Not compatible with this release. No problem." exception=err
exit(0) # Exit immediately, as a success
end
================================================
FILE: .github/workflows/doc-preview-cleanup.yml
================================================
name: Doc Preview Cleanup
on:
pull_request:
types: [closed]
# Ensure that only one "Doc Preview Cleanup" workflow is force pushing at a time
concurrency:
group: doc-preview-cleanup
cancel-in-progress: false
jobs:
doc-preview-cleanup:
runs-on: ubuntu-latest
if: github.event.pull_request.head.repo.fork == false
# This workflow pushes to gh-pages; permissions are per-job and independent of docs.yml
permissions:
contents: write
steps:
- name: Checkout gh-pages branch
uses: actions/checkout@v4
with:
ref: gh-pages
- name: Delete preview and history + push changes
run: |
if [ -d "${preview_dir}" ]; then
git config user.name "Documenter.jl"
git config user.email "documenter@juliadocs.github.io"
git rm -rf "${preview_dir}"
git commit -m "delete preview"
git branch gh-pages-new "$(echo "delete history" | git commit-tree "HEAD^{tree}")"
git push --force origin gh-pages-new:gh-pages
fi
env:
preview_dir: previews/PR${{ github.event.number }}
================================================
FILE: .github/workflows/docs.yml
================================================
name: Documentation
on:
push:
branches:
- main
- 'release-'
tags: '*'
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@v2
with:
version: '1'
- name: Install dependencies
run: julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
- name: Set DOCUMENTER_CURRENT_VERSION for tutorial download links
run: |
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
echo "DOCUMENTER_CURRENT_VERSION=previews/PR${{ github.event.pull_request.number }}" >> "$GITHUB_ENV"
elif [[ "${{ github.ref }}" == refs/tags/* ]]; then
echo "DOCUMENTER_CURRENT_VERSION=${GITHUB_REF_NAME}" >> "$GITHUB_ENV"
elif [[ "${{ github.ref }}" == "refs/heads/main" ]] || [[ "${{ github.ref }}" =~ ^refs/heads/release- ]]; then
echo "DOCUMENTER_CURRENT_VERSION=dev" >> "$GITHUB_ENV"
fi
- name: Build and deploy
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }}
run: julia --project=docs --color=yes docs/make.jl
================================================
FILE: .github/workflows/fix-docs-on-failure.yml
================================================
name: Auto-fix Documentation Failures
on:
workflow_run:
workflows: ["Documentation"]
types:
- completed
branches:
- main
permissions:
issues: write
actions: read
pull-requests: read
jobs:
open-copilot-issue:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'failure' }}
steps:
- name: Create or update Copilot issue for docs failure
uses: actions/github-script@v7
with:
script: |
const runId = context.payload.workflow_run.id;
const runUrl = context.payload.workflow_run.html_url;
const headSha = context.payload.workflow_run.head_sha;
const owner = context.repo.owner;
const repo = context.repo.repo;
// --- Gather failure logs ---
const { data: jobsData } = await github.rest.actions.listJobsForWorkflowRun({
owner, repo, run_id: runId, filter: 'latest',
});
let failureSummary = '';
for (const job of jobsData.jobs) {
if (job.conclusion === 'failure') {
failureSummary += `### Job: ${job.name}\n`;
failureSummary += `- **Status:** ${job.conclusion}\n`;
failureSummary += `- **URL:** ${job.html_url}\n\n`;
try {
const logResponse = await github.rest.actions.downloadJobLogsForWorkflowRun({
owner, repo, job_id: job.id,
});
const logLines = logResponse.data.split('\n');
const tail = logLines.slice(-200).join('\n');
failureSummary += '<details><summary>Log tail (last 200 lines)</summary>\n\n```\n' + tail + '\n```\n</details>\n\n';
} catch (e) {
failureSummary += `_Could not fetch logs: ${e.message}_\n\n`;
}
}
}
// --- Check for an existing open issue ---
const { data: issues } = await github.rest.issues.listForRepo({
owner, repo,
labels: 'documentation,copilot',
state: 'open',
per_page: 5,
});
const existingIssue = issues.find(i =>
i.title.startsWith('[Copilot] Fix documentation build failure')
);
// --- Check for open PRs (including drafts) already addressing docs failures ---
const { data: openPRs } = await github.rest.pulls.list({
owner, repo,
state: 'open',
per_page: 30,
});
const docFixPRs = openPRs.filter(pr => {
const title = pr.title.toLowerCase();
const body = (pr.body || '').toLowerCase();
const labels = pr.labels.map(l => l.name.toLowerCase());
return (
labels.includes('documentation') ||
title.includes('documentation') ||
/\bdocs?\b/.test(title) ||
body.includes('documentation build failure') ||
body.includes('docs/make.jl')
);
});
let prSection = '';
if (docFixPRs.length > 0) {
prSection = '### Existing PRs that may address this failure\n\n';
prSection += 'Check these open PRs (including drafts) before starting work — they may already fix some or all of the errors:\n\n';
for (const pr of docFixPRs) {
const draft = pr.draft ? ' (draft)' : '';
prSection += `- #${pr.number}${draft}: ${pr.title}\n`;
}
prSection += '\nIf an existing PR already resolves the failure, close this issue. Otherwise, coordinate with or build on the existing PR.\n\n';
}
// --- Build issue body ---
const body = [
'## Documentation build failed on `main`',
'',
`The [Documentation workflow run](${runUrl}) (run ID: \`${runId}\`) failed at commit \`${headSha}\`.`,
'',
prSection,
'### Task',
'Please investigate the documentation build failure and open a PR to fix it.',
"The documentation is built with Julia's Documenter.jl package. The build script is at `docs/make.jl`.",
'',
'### Cross-repo documentation context',
'',
'PowerSystems.jl docs are linked to other Sienna packages via [DocumenterInterLinks.jl](https://github.com/JuliaDocumenter/DocumenterInterLinks.jl).',
'The `docs/make.jl` file configures `InterLinks` to resolve `@extref` cross-references to other repos in the **Sienna-Platform** (and **NLR-Sienna**) GitHub orgs.',
'',
'**Common cross-repo causes of documentation failures:**',
'- Missing or renamed docstrings in a dependency (e.g., `InfrastructureSystems.jl`) that are referenced via `@extref`',
'- Ambiguous docstrings that are imported from another package and re-exported by PowerSystems.jl — these need disambiguation in the `@autodocs` or `@docs` blocks',
'- Broken `InterLinks` URLs when a dependency has reorganized or redeployed its documentation',
'- `ExternalFallbacks` in `docs/make.jl` that reference symbols no longer present in the upstream package',
'',
'**If the fix belongs in another repository:**',
'- Open a PR in the appropriate **Sienna-Platform/** or **NLR-Sienna/** repo (e.g., `InfrastructureSystems.jl`) to fix the upstream docstring or export',
'- Link the upstream PR in this issue and in any PowerSystems.jl PR',
'- If a temporary workaround is possible in PowerSystems.jl (e.g., updating `ExternalFallbacks`), include it and note the upstream PR that provides the permanent fix',
'',
'### Other common causes',
'- Docstring errors or missing exports in this repo',
'- Broken cross-references or links',
'- Literate.jl script errors in `docs/src/`',
'- Dependency issues in `docs/Project.toml`',
'',
'### Documentation guidelines',
'',
'Follow these guidelines when making documentation changes:',
'- [Sienna documentation practices](https://github.com/Sienna-Platform/InfrastructureSystems.jl/blob/main/.claude/Sienna.md) (see "Documentation Practices and Requirements")',
'- [Sienna docs best practices](https://sienna-platform.github.io/InfrastructureSystems.jl/stable/docs_best_practices/explanation/)',
'- [Diataxis framework](https://diataxis.fr/)',
'',
'### Failure Details',
failureSummary,
].join('\n');
if (existingIssue) {
// Update the existing issue with new failure info
const comment = [
'## New documentation build failure',
'',
`A new failure occurred at commit \`${headSha}\`.`,
'',
`[Workflow run](${runUrl})`,
'',
prSection,
failureSummary,
].join('\n');
await github.rest.issues.createComment({
owner, repo,
issue_number: existingIssue.number,
body: comment,
});
console.log(`Updated existing issue #${existingIssue.number}`);
} else if (docFixPRs.length > 0) {
// There are already open PRs that may fix this — don't create a duplicate issue,
// just add a comment on the most recent relevant PR
const targetPR = docFixPRs[0];
await github.rest.issues.createComment({
owner, repo,
issue_number: targetPR.number,
body: [
'## Documentation build still failing on `main`',
'',
`The [Documentation workflow](${runUrl}) failed at commit \`${headSha}\`.`,
'This PR may already address the failure — please verify.',
'',
failureSummary,
].join('\n'),
});
console.log(`Commented on existing docs PR #${targetPR.number}`);
} else {
// Ensure labels exist
for (const label of ['documentation', 'copilot']) {
try {
await github.rest.issues.getLabel({ owner, repo, name: label });
} catch {
const colors = { documentation: '0075ca', copilot: 'c2e0c6' };
const descriptions = {
documentation: 'Improvements or additions to documentation',
copilot: 'Copilot agent task',
};
await github.rest.issues.createLabel({
owner, repo, name: label,
color: colors[label],
description: descriptions[label],
});
}
}
// Create a new issue
const { data: issue } = await github.rest.issues.create({
owner, repo,
title: `[Copilot] Fix documentation build failure (${headSha.slice(0, 7)})`,
body: body,
labels: ['documentation', 'copilot'],
});
// Assign the issue to Copilot to trigger the coding agent
try {
await github.rest.issues.addAssignees({
owner, repo,
issue_number: issue.number,
assignees: ['copilot'],
});
console.log(`Created issue #${issue.number} and assigned to Copilot`);
} catch (e) {
// If assigning fails, mention @copilot in a comment as fallback
console.log(`Could not assign to copilot: ${e.message}`);
await github.rest.issues.createComment({
owner, repo,
issue_number: issue.number,
body: '@copilot',
});
console.log(`Created issue #${issue.number} and mentioned @copilot in comment`);
}
}
================================================
FILE: .github/workflows/format-check.yml
================================================
name: Format Check
on:
push:
branches:
- 'main'
- 'release-'
tags: '*'
pull_request:
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
julia-version: [1]
julia-arch: [x86]
os: [ubuntu-latest]
steps:
- uses: julia-actions/setup-julia@latest
with:
version: ${{ matrix.julia-version }}
- uses: actions/checkout@v4
- name: Install JuliaFormatter and format
run: |
julia -e 'include("scripts/formatter/formatter_code.jl")'
- uses: reviewdog/action-suggester@v1
if: github.event_name == 'pull_request'
with:
tool_name: JuliaFormatter
fail_on_error: true
- name: Format check
run: |
julia -e '
out = Cmd(`git diff --name-only`) |> read |> String
if out == ""
exit(0)
else
@error "Some files have not been formatted !!!"
write(stdout, out)
exit(1)
end'
================================================
FILE: .github/workflows/main-tests.yml
================================================
name: Main - CI
on:
schedule:
- cron: "0 0 * * 1-5"
push:
branches:
- main
jobs:
test:
name: Julia ${{ matrix.julia-version }} - ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
julia-version: ['1', 'nightly']
julia-arch: [x64]
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@latest
with:
version: ${{ matrix.julia-version }}
arch: ${{ matrix.julia-arch }}
- uses: julia-actions/julia-buildpkg@latest
env:
PYTHON: ""
- uses: julia-actions/julia-runtest@latest
continue-on-error: ${{ matrix.julia-version == 'nightly' }}
env:
PYTHON: ""
- uses: julia-actions/julia-processcoverage@v1
- uses: codecov/codecov-action@v1
with:
file: ./lcov.info
flags: unittests
name: codecov-umbrella
fail_ci_if_error: false
token: ${{ secrets.CODECOV_TOKEN }}
================================================
FILE: .github/workflows/pr_testing.yml
================================================
name: Test-CI
on:
pull_request:
types: [opened, synchronize, reopened]
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
test:
name: Julia ${{ matrix.julia-version }} - ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
julia-version: ['1']
julia-arch: [x64]
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@latest
with:
version: ${{ matrix.julia-version }}
arch: ${{ matrix.julia-arch }}
- uses: julia-actions/julia-buildpkg@latest
env:
PYTHON: ""
- uses: julia-actions/julia-runtest@latest
env:
PYTHON: ""
- uses: julia-actions/julia-processcoverage@v1
- uses: codecov/codecov-action@v4
with:
file: ./lcov.info
flags: unittests
name: codecov-umbrella
fail_ci_if_error: false
token: ${{ secrets.CODECOV_TOKEN }}
================================================
FILE: .gitignore
================================================
#Files generated by invoking Julia with --code-coverage
*.jl.cov
*.jl.*.cov
*.log
_*.jl
# Files generated by invoking Julia with --track-allocation
*.jl.mem
## Autogenerated code during the documentation process
generated*.md
docs/src/tutorials/generated/
*.raw
# Test data
data
# System-specific files and directories generated by the BinaryProvider and BinDeps packages
# They contain absolute paths specific to the host computer, and so should not be committed
deps/deps.jl
deps/build.log
deps/downloads/
deps/usr/
deps/src/
# Build artifacts for creating documentation generated by the Documenter package
docs/build/
docs/site/
#Jupyter Ignores
.ipynb_checkpoints/
.ipynb_checkpoints
#Mac temp ignores
.DS_Store
#Figures
*.pdf
*.ipynb
Manifest.toml
.vscode
*.h5
################################################################################
# Operating systems #
################################################################################
########################################
# Linux #
########################################
*~
# temporary files which can be created if a process still has a handle open of
# a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
########################################
# macOS #
########################################
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
########################################
# Windows #
########################################
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
## Acknowledgements
# Many thanks to `https://gitignore.io/`, written and maintained by Joe Blau, which contributed much material to this gitignore file.
================================================
FILE: .pre-commit-config.yaml
================================================
repos:
- repo: local
hooks:
- id: julia-formatter
name: Run Julia formatter
entry: julia scripts/formatter/formatter_code.jl
language: system
types: [file]
pass_filenames: false
================================================
FILE: CHANGELOG.md
================================================
# PowerSystems Change Log
## 1.0.0 Announcement
After 1.0.0 release, the manual Changelog will no longer be maintained. Please refer to the [releases page](https://github.com/Sienna-Platform/PowerSystems.jl/releases) to follow up with the changes.
## 0.28.0
- Export additional methods
- Change System constructor that takes iterable arguments
## 0.27.0
- Change errors to warnings when validating impedance values in AC Branches
- Add Support for non-spinning reserve (Thanks @andrewrosemberg)
- Add costs to reserve products (Thanks @andrewrosemberg)
- Improvements to documentation
- Extend parsing of PSS/e dyr files
- Modifications to dynamic structs to support (min, max) tuples
## 0.26.0
- Add conversion field to HydroStorage
- Bug fix in add_component for RegulationDevice
- Add StaticReserveGroup object (Thanks @andrewrosemberg)
## 0.25.0
- Bug fix in units settings when parsing TableData
- Add defaults for ThermalStandard Fuel and Prime Mover (Thanks @raphaelsaavedra)
- Bug Fix cost data in TableData Parsing
- Bump IS version and remove type inputs to setter functions
## 0.24.1
- Add pss/e .dyr file parsing support
- Bug fixes in staturation data GENROU and GENROE
- Bug fixes in TableData parsing
## 0.24.0
- Change the use of @forward macros to avoid world of age errors
- Change DynamicMachines constructors to avoid de-serialization errors
- Change implementation of DynamicBranches
- Change implementation of RegulatioDevices
## 0.23.3
- Bug fixes in TableDataParsing
- Improvements in RegulationDevice getter functions
- Addition of get_max_reactive_power for RenewableDispatch
## 0.23.2
- Bug fixes in TableDataParsing
- Add get_max_reactive_power for RenewableGeneration with PowerFactor
## 0.23.1
- Fix bug in DynamicGenerator constructor
- Add additional get_value methods for ThermalStandard ramps
- Improve testing
## 0.23.0
- Addition of get_max_active_power, get_max_reactive_power accessor functions
- Enable serialization of DynamicLines
- Islanding detection in PTDF, LODF and Ybus calculations
- Remove MVABase field from DynamicInverter
## 0.22.0
- Addition of DynamicLines Struct
- Renames of Fields in Structs to match code guidelines
- Store RAW Electric Source Data (Z) in Thermal Generators
- Implement UnitsInfo to return data in different bases accordingly
- Update Autogeneration of structs.
## 0.21.0
- Improvements to Power Flow solve: Add Jacobian Function, add a method that modifies the system and one that returns results
- Improvements to TableData Parsing
- Add new methods to get admittance from branches
- Add Monitored Line to PTDF
## 0.20.1
- Add AC1A, ST1A, GasTG structs for dynamic modeling.
- Implement heuristic in pwl data to avoid NaN
- Bug fixes with Regulation Devices
- Improved testing.
## 0.20.0
- Add Support for MultiStart Thermal Generation (a.k.a. PGLIB Model)
- Performance updates to Power Flow.
- Remove Make PF function.
- Fixin forecast handling of composed structs
- Update to IS v0.11
- Add SalientPoleGenerator and RoundRotorGenerator with saturation variants
- Add regulation device composed with generators
- Add Basepower field to InjectionDevices in system's per unit
- Add readonly option for seralization of time series
## 0.19.0
- Update for IS 0.9
- Change behaviour of get_component
## 0.18.5
- Bug fix for serialization
## 0.18.4
- Add deepcopy method for system
## 0.18.3
- Bug fix in serialization to folder
## 0.18.2
- Fix potential miscalculation of PWL upper bound limits
## 0.18.1
- Remove warning PWL get_slope function
## 0.18.0
- Add functions to to get breakpoints and slopes from PWL cost functions
- Add getter function support for generated structs
- Enable addition of DynamicInjections to StaticInjection components and associated methods
## 0.17.2
- Add DemandCurveReserve
- Add functions to manipilate pwl cost functions
## 0.17.1
- Fix bug with frequency de-serialization
## 0.17.0
- Fix Serialization of DynamicInverter
- Fix remove_component for Area
- Add available fields for Reserves
## 0.16.0
- Changes to DynamicInverter and DynamicGenerator structs
- Bugfix in solve_powerflow!
- add option to set store location of hdf5 file
## v0.15.2
- add get_available_components method
## v0.15.1
- add has_forecasts method
## v0.15.0
- Add filtering function to get_components
- Add Parser for Texas A&M models
- Add tiime_at_status field in ThermalStandard
## v0.14.1
- Update InfrastructureSystems dependency
## v0.14.0
- Update names and contents of Dynamic Structs, RenewableGen, HydroGen and ThermalGen
## v0.13.1
- Update CSV dependency to v0.6
## v0.13.0
- Change uses of Load Zone and Area
- Add AGC service
- Remove unnecessary fields in transfer service
- Add participation factor field in TechThermal
## v0.12.0
- Make LoadZone and Area optional Bus Inputs
## v0.11.2
- Reduce warning print for unsupported columns outs when parsing data
## v0.11.1
- Change device internal forecasts field name
## v0.11.0
- Add support for Load Zones and Areas
- Add return status for power flows
- Change behavior of Matpower and PTI files parsing
## v0.10.0
- Update PTI parsing code from PM and IM
- Modify the user's interface for enums
## v0.9.1
- Update Struct autogeneration code
## v0.9.0
- Update Hydropower structs naming
## v0.8.6
- Add missing getter functions for DynamicInverter and DynamicGenerator
- Add missing getter functions for System fields.
- Add frequency field to System and DEFAULT_SYSTEM_FREQUENCY
## v0.8.5
- Add functions to handle DynamicInjection components
## v0.8.4
- Fix 7z error in Julia 1.3 and Windows
- Bugfix in pu conversion in HVDC Table Data
- Improve testing
## v0.8.3
- Update DynamicGenerator and DynamicInverter to comply with PSY
- Change get_components to support parametrized structs
- Improve testing of dynamic structs
## v0.8.2
- Update package dependencies compatibility
- Add range to struct docstrings
- Hydropower data parsing improvements
## v0.8.1
- Bugfix TableData HydroStorage
## v0.8.0
- Updated HydroDispatch and removed HydroStorage
## v0.7.1
- Bugfix services removal
## v0.7.0
- Make codebase consistent with the style guides.
- Add Dynamic Data capabilities.
- Change the use of services and store them inside of devices.
- Add ext field to devices
- Add ext field to the system
## v0.6.2
- Downgrade compatible version of CSV to 0.5.13 to avoid tab-complete hang.
- Bug Fix in docstrings autogeneration code
- Contiguous forecasts function added
## v0.6.1
- Remove bin from auto-generation code
- Updated docstrings
## v0.6.0
- Use accessor functions instead of labels to get forecasts
- Bug Fix in code autogeneration
## v0.5.2
- Enforce unique bus numbers
- Set min version of IS to 0.2.4
## v0.5.1
- Bugfix in generate_initial_times
- Bug fixes on SystemTable Data
## v0.5.0
- Store and access forecast data from Disk
## v0.4.3
- Fix Parsing bug in Table data #362
- Enable custom validation descriptors when parsing PSS/e and MATPOWER files
- Enable multiple loads per bus when parsing PSS/e and MATPOWER files
- Support multiple generators per bus and non-sequential bus indexing in power flow
## v0.4.2
- Fix printing of forecasts #350 fixing #343
## v0.1.1
- Update to Julia-v0.7
## v0.1.0
- Initial implementation
================================================
FILE: CITATION.cff
================================================
cff-version: 1.2.0
message: "If you use this software, please cite it as below."
authors:
- family-names: "Lara"
given-names: "José Daniel"
- family-names: "Barrows"
given-names: "Clayton"
- family-names: "Thom"
given-names: "Daniel"
- family-names: "Krishnamurthy"
given-names: "Dheepak"
- family-names: "Callaway"
given-names: "Duncan"
title: "PowerSystems.jl — A power system data management package for large scale modeling"
version: 1.0.0
doi: 10.5281/zenodo.1234
date-released: 2021-09-21
url: "https://github.com/Sienna-Platform/PowerSystems.jl"
preferred-citation:
type: article
authors:
- family-names: "Lara"
given-names: "José Daniel"
- family-names: "Barrows"
given-names: "Clayton"
- family-names: "Thom"
given-names: "Daniel"
- family-names: "Krishnamurthy"
given-names: "Dheepak"
- family-names: "Callaway"
given-names: "Duncan"
title: "PowerSystems.jl — A power system data management package for large scale modeling"
journal: "SoftwareX"
volume: 15
month: 7
doi: "https://doi.org/10.1016/j.softx.2021.100747"
url: "https://www.sciencedirect.com/science/article/pii/S2352711021000765"
year: 2021
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing
Community driven development of this package is encouraged. To maintain code quality standards, please adhere to the following guidlines when contributing:
- To get started, <a href="https://www.clahub.com/agreements/NREL/PowerSystems.jl">sign the Contributor License Agreement</a>.
- Please do your best to adhere to our [coding style guide](https://sienna-platform.github.io/InfrastructureSystems.jl/latest/style).
- To submit code contributions, [fork](https://help.github.com/articles/fork-a-repo/) the repository, commit your changes, and [submit a pull request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/).
================================================
FILE: LICENSE
================================================
BSD 3-Clause License
Copyright (c) 2018, 2023 Alliance for Sustainable Energy, LLC and The Regents of the University of California
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: Project.toml
================================================
name = "PowerSystems"
uuid = "bcd98974-b02a-5e2f-9ee0-a103f5c450dd"
authors = ["Jose Daniel Lara", "Daniel Thom", "Rodrigo Henriquez-Auba", "Gabriel Konar-Steenberg", "Clayton Barrows"]
version = "5.9.1"
[deps]
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
InfrastructureSystems = "2cd47ed4-ca9b-11e9-27f2-ab636a7671f1"
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
PowerFlowData = "dd99e9e3-7471-40fc-b48d-a10501125371"
PrettyTables = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"
TimeSeries = "9e3dc215-6440-5c97-bce1-76c03772f85e"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
Unicode = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"
YAML = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6"
[compat]
CSV = "~0.10"
DataFrames = "1"
DataStructures = "^0.19"
Dates = "1"
DocStringExtensions = "0.8, 0.9.2"
InfrastructureSystems = "^3.5"
InteractiveUtils = "1"
JSON3 = "1"
LinearAlgebra = "1"
Logging = "1"
PowerFlowData = "^1.5"
PrettyTables = "2.4, 3.1"
TimeSeries = "0.25"
UUIDs = "1"
Unicode = "1"
YAML = "~0.4"
julia = "^1.10"
================================================
FILE: README.md
================================================
# PowerSystems.jl
[](https://github.com/Sienna-Platform/PowerSystems.jl/actions/workflows/main-tests.yml)
[](https://codecov.io/gh/Sienna-Platform/PowerSystems.jl)
[](https://github.com/Sienna-Platform/PowerSystems.jl/actions/workflows/docs.yml)
[](https://doi.org/10.5281/zenodo.17703517)
[<img src="https://img.shields.io/badge/slack-@Sienna/PSY-sienna.svg?logo=slack">](https://join.slack.com/t/core-sienna/shared_invite/zt-glam9vdu-o8A9TwZTZqqNTKHa7q3BpQ)
[](http://juliapkgstats.com/pkg/PowerSystems)
The `PowerSystems.jl` package provides a rigorous data model using Julia structures to enable power systems analysis and modeling. In addition to stand-alone system analysis tools and data model building, the `PowerSystems.jl` package is used as the foundational data container for the [PowerSimulations.jl](https://github.com/Sienna-Platform/PowerSimulations.jl) and [PowerSimulationsDynamics.jl](https://github.com/Sienna-Platform/PowerSimulationsDynamics.jl) packages. `PowerSystems.jl` supports a limited number of data file formats for parsing.
## Version Advisory
- PowerSystems will work with Julia v1.6+.
## Device data enabled in PowerSystems
- Generators (Thermal, Renewable and Hydro)
- Transmission (Lines, and Transformers)
- Active Flow control devices (DC Lines and Phase Shifting Transformers)
- TwoTerminal and Multiterminal HVDC
- Topological elements (Buses, Arcs, Areas)
- Storage (Batteries)
- Load (Static, and Curtailable)
- Services (Reserves, Transfers)
- TimeSeries (Deterministic, Scenarios, Probabilistic)
- Dynamic Generators Models
- Dynamic Inverter Models
For information on using the package and a more extensive list of device data enabled, see the [stable documentation](https://sienna-platform.github.io/PowerSystems.jl/stable/). Use the [in-development documentation](https://sienna-platform.github.io/PowerSystems.jl/dev/) for the version of the documentation which contains the unreleased features.
## Parsing capabilities in PowerSystems
- MATPOWER CaseFormat
- PSS/e - PTI Format v30 (partial support), v33, v35 (.raw and .dyr files)
- [RTS-GMLC](https://github.com/GridMod/RTS-GMLC/tree/master/RTS_Data/SourceData) table data format
## Development
Contributions to the development and enhancement of PowerSystems are welcome. Please see
[CONTRIBUTING.md](https://github.com/NREL/PowerSystems.jl/blob/main/CONTRIBUTING.md) for
code contribution guidelines.
## Citing PowerSystems.jl
[Paper describing `PowerSystems.jl`](https://www.sciencedirect.com/science/article/pii/S2352711021000765)
```bibtex
@article{LARA2021100747,
title = {PowerSystems.jl — A power system data management package for large scale modeling},
journal = {SoftwareX},
volume = {15},
pages = {100747},
year = {2021},
issn = {2352-7110},
doi = {https://doi.org/10.1016/j.softx.2021.100747},
url = {https://www.sciencedirect.com/science/article/pii/S2352711021000765},
author = {José Daniel Lara and Clayton Barrows and Daniel Thom and Dheepak Krishnamurthy and Duncan Callaway},
keywords = {Power Systems, Julia, Energy}
}
```
## License
PowerSystems is released under a BSD [license](https://github.com/NREL/PowerSystems.jl/blob/main/LICENSE).
PowerSystems has been developed as part of the Scalable Integrated Infrastructure Planning (SIIP)
initiative at the U.S. Department of Energy's National Laboratory of the Rockies ([NLR](https://www.nlr.gov/), formerly NREL) Software Record SWR-23-105.
================================================
FILE: codecov.yml
================================================
codecov:
require_ci_to_pass: yes
coverage:
precision: 2
round: down
range: "70...100"
status:
project: # measuring the overall project coverage
default: # context, you can create multiple ones with custom titles
enabled: yes # must be yes|true to enable this status
target: auto # specify the target coverage for each commit status
# option: "auto" (must increase from parent commit or pull request base)
# option: "X%" a static target percentage to hit
threshold: 5 # allowed to drop X% and still result in a "success" commit status
if_not_found: success # if parent is not found report status as success, error, or failure
if_ci_failed: error # if ci fails report status as success, error, or failure
patch:
default:
target: 70
parsers:
gcov:
branch_detection:
conditional: yes
loop: yes
method: no
macro: no
comment:
layout: "reach,diff,flags,tree"
behavior: default
require_changes: no
ignore:
- "src/parsers/pm_io/"
- "src/parsers/im_io/"
================================================
FILE: docs/Makefile
================================================
BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
html:
julia make.jl
github: html
-git branch -D gh-pages
-git push origin --delete gh-pages
ghp-import -n -b gh-pages -m "Update documentation" ./build
git checkout gh-pages
git push --set-upstream origin gh-pages
git checkout ${BRANCH}
all: github
================================================
FILE: docs/Project.toml
================================================
[deps]
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
DocumenterInterLinks = "d12716ef-a0f6-4df4-a9f1-a5a34e75c656"
DocumenterMermaid = "a078cd44-4d9c-4618-b545-3ab9d77f9177"
InfrastructureSystems = "2cd47ed4-ca9b-11e9-27f2-ab636a7671f1"
Ipopt = "b6b21f68-93f8-5de0-b562-5493be1d77c9"
JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
PowerSystemCaseBuilder = "f00506e0-b84f-492a-93c2-c0a9afc4364e"
PowerSystems = "bcd98974-b02a-5e2f-9ee0-a103f5c450dd"
PrettyTables = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"
TimeSeries = "9e3dc215-6440-5c97-bce1-76c03772f85e"
TypeTree = "04da0e3b-1cad-4b2c-a963-fc1602baf1af"
[compat]
CSV = "~0.10"
Documenter = "=1.15.0"
julia = "^1.10"
================================================
FILE: docs/make.jl
================================================
using Documenter, PowerSystems
import DataStructures: OrderedDict
using Literate
using DocumenterInterLinks
using DocumenterMermaid
links = InterLinks(
"InfrastructureSystems" => "https://sienna-platform.github.io/InfrastructureSystems.jl/stable/",
# Sometimes IS docstrings @extref to PSY, and sometimes those IS docstrings are included
# in the PSY reference, so we can have PSY @extref-ing to itself:
"PowerSystems" => "https://sienna-platform.github.io/PowerSystems.jl/stable/",
)
# This is a fallback for the docstrings that are referenced within IS docstrings
fallbacks = ExternalFallbacks(
"ComponentContainer" => "@extref InfrastructureSystems.ComponentContainer",
"InfrastructureSystemsComponent" => "@extref InfrastructureSystems.InfrastructureSystemsComponent"
)
# This is commented out because the output is not user-friendly. Deliberation on how to best
# communicate this information to users is ongoing.
#include(joinpath(@__DIR__, "src", "generate_validation_table.jl"))
include(joinpath(@__DIR__, "make_model_library.jl"))
include(joinpath(@__DIR__, "make_tutorials.jl"))
pages = OrderedDict(
"Welcome Page" => "index.md",
"Tutorials" => Any[
"Create and Explore a Power `System`" => "tutorials/generated_creating_system.md",
"Manipulating Data Sets" => "tutorials/generated_manipulating_datasets.md",
"Working with Time Series" => "tutorials/generated_working_with_time_series.md",
"Adding Data for Dynamic Simulations" => "tutorials/generated_add_dynamic_data.md",
],
"How to..." => Any[
"...import data" => Any[
"Parse a MATPOWER or PSS/e file" => "how_to/parse_matpower_psse.md",
"Parse PSS/e dynamic data" => "how_to/parse_dynamic_data.md",
"Build a `System` using .csv files" => "how_to/build_system_with_files.md",
"Save and read data with a JSON" => "how_to/serialize_data.md",
],
"...add a component using natural units (MW)" => "how_to/add_component_natural_units.md",
"...use context managers for bulk operations" => "how_to/use_context_managers.md",
"...add additional data to a component" => "how_to/adding_additional_fields.md",
"...add time-series data" => Any[
"Parse time series data from .csv files" => "how_to/parse_ts_from_csvs.md",
"Improve performance with time series data" => "how_to/improve_ts_performance.md",
],
"...add cost data" => Any[
"Add an Operating Cost" => "how_to/add_cost_curve.md",
"Add a market bid" => "how_to/market_bid_cost.md",
"Add costs for imported/exported power" => "how_to/create_system_with_source_import_export_cost.md",
"Add time series fuel costs" => "how_to/add_fuel_curve_timeseries.md",
],
"...customize or add a new Type" => "how_to/add_new_types.md",
"...define hydro generators with reservoirs" => "how_to/create_hydro_datasets.md",
"...handle 3-Winding Transformers" => "how_to/handle_3W_transformers.md",
"...use PowerSystems.jl with JuMP.jl" => "how_to/jump.md",
"...reduce REPL printing" => "how_to/reduce_repl_printing.md",
"...update to a new `PowerSystems.jl` version" => Any[
"Migrate from version 4.0 to 5.0" => "how_to/migrating_to_psy5.md",
],
],
"Explanation" =>
Any[
"explanation/system.md",
"explanation/type_structure.md",
"explanation/buses_type_explanation.md",
"explanation/per_unit.md",
"explanation/power_concepts.md",
"explanation/conforming_and_non_conforming_loads.md",
"explanation/transformer_per_unit_models.md",
"explanation/time_series.md",
"explanation/dynamic_data.md",
"explanation/supplemental_attributes.md",
"explanation/plant_attributes.md",
],
"Model Library" => Any[],
"Reference" =>
Any["Public API" => "api/public.md",
"Glossary and Acronyms" => "api/glossary.md",
"Type Tree" => "api/type_tree.md",
"`ValueCurve` Options" => "api/valuecurve_options.md",
"Specifying the category of..." => "api/enumerated_types.md",
"Supported PSS/e Models" => "api/psse_models.md",
"Comparison of Load, Generator, and Storage Types" => "api/static_injection_subtypes.md",
"Citation" => "api/citation.md",
"Developers" => ["Developer Guidelines" => "api/developer_guidelines.md",
"Internals" => "api/internal.md"]
]
)
pages["Model Library"] = make_model_library(
categories = [
Topology,
StaticInjection,
Service,
Branch,
DynamicInjection,
],
exceptions = [PSY.DynamicComponent,
PSY.ActivePowerControl,
PSY.ReactivePowerControl,
PSY.DynamicBranch,
PSY.HybridSystem,
PSY.OperationalCost,
PSY.DynamicInverter,
PSY.DynamicGenerator,
],
manual_additions =
Dict("Service" => ["Reserves" => "model_library/reserves.md"],
"StaticInjection" => ["HybridSystem" => "model_library/hybrid_system.md"],
"DynamicInjection" => ["Dynamic Inverter" => "model_library/dynamic_inverter.md",
"Dynamic Generator" => "model_library/dynamic_generator.md",
],
"Branch" => ["Dynamic Lines" => "model_library/dynamic_branch.md"],
"Operating Costs" => ["ThermalGenerationCost" =>"model_library/thermal_generation_cost.md",
"HydroGenerationCost" =>"model_library/hydro_generation_cost.md",
"HydroReservoirCost" =>"model_library/hydro_reservoir_cost.md",
"RenewableGenerationCost" =>"model_library/renewable_generation_cost.md",
"StorageCost" =>"model_library/storage_cost.md",
"LoadCost" =>"model_library/load_cost.md",
"MarketBidCost" =>"model_library/market_bid_cost.md",
"ImportExportCost" =>"model_library/import_export_cost.md",
"OfferCurveCost" =>"model_library/offer_curve_cost.md"],
"HydroReservoir" => "model_library/hydro_reservoir.md",
)
)
# clean_old_generated_files and insert_md are now defined in make_tutorials.jl
# They are used here for other sections (Model Library, Explanation, How to...)
# This code performs the automated addition of Literate - Generated Markdowns. The desired
# section name should be the name of the file for instance network_matrices.jl -> Network Matrices
julia_file_filter = x -> occursin(".jl", x)
folders = Dict(
"Model Library" => filter(julia_file_filter, readdir("docs/src/model_library")),
"Explanation" => filter(julia_file_filter, readdir("docs/src/explanation")),
"How to..." => filter(julia_file_filter, readdir("docs/src/how_to")),
)
# Clean up old generated files in folders before Literate generates new ones
# Note: model_library is cleaned by make_model_library.jl before it generates files,
# so we only clean explanation and how_to directories here
for (section, folder) in folders
# Skip model_library as it's already cleaned by make_model_library()
section == "Model Library" && continue
section_folder_name = lowercase(replace(section, " " => "_"))
outputdir = joinpath(pwd(), "docs", "src", "$section_folder_name")
clean_old_generated_files(outputdir)
end
# Process other sections (Model Library, Explanation, How to...)
for (section, folder) in folders
for file in folder
@show file
section_folder_name = lowercase(replace(section, " " => "_"))
inputfile = joinpath("$section_folder_name", "$file")
infile_path = joinpath(pwd(), "docs", "src", inputfile)
execute = occursin("EXECUTE = TRUE", uppercase(readline(infile_path))) ? true : false
execute && include(infile_path)
outputdir = joinpath(pwd(), "docs", "src", "$section_folder_name")
outputfile = string("generated_", replace("$file", ".jl" => ""))
# Generate markdown
Literate.markdown(infile_path,
outputdir;
name = outputfile,
credit = false,
flavor = Literate.DocumenterFlavor(),
documenter = true,
postprocess = insert_md,
execute = execute)
subsection = titlecase(replace(split(file, ".")[1], "_" => " "))
push!(pages[section], ("$subsection" => joinpath("$section_folder_name", "$(outputfile).md")))
end
end
# Process tutorials separately with Literate
make_tutorials()
makedocs(
modules = [PowerSystems],
format = Documenter.HTML(
prettyurls = haskey(ENV, "GITHUB_ACTIONS"),
size_threshold = nothing,),
sitename = "PowerSystems.jl",
authors = "Jose Daniel Lara, Daniel Thom, Kate Doubleday, Rodrigo Henriquez-Auba, and Clayton Barrows",
pages = Any[p for p in pages],
draft = false,
plugins = [links, fallbacks],
)
deploydocs(
repo = "github.com/Sienna-Platform/PowerSystems.jl.git",
target = "build",
branch = "gh-pages",
devbranch = "main",
devurl = "dev",
push_preview=true,
versions = ["stable" => "v^", "v#.#"],
)
================================================
FILE: docs/make_model_library.jl
================================================
using InteractiveUtils
import InfrastructureSystems as IS
import PowerSystems as PSY
function _clean_old_generated_files(dir::String)
# Remove old generated_*.md files before creating new ones
if !isdir(dir)
@warn "Directory does not exist: $dir"
return
end
generated_files = filter(f -> startswith(f, "generated_") && endswith(f, ".md"), readdir(dir))
for file in generated_files
rm(joinpath(dir, file), force=true)
@info "Removed old generated file: $file"
end
end
function _check_exception(T, exceptions::Vector)
for type_exception in exceptions
if T <: type_exception
return true
end
end
return false
end
function _write_first_level_markdown(c::String)
file_name = "model_library/generated_$(c).md"
open(joinpath("docs/src", file_name), "w") do io
print(
io,
"""
# $(c)
```@autodocs
Modules = [PowerSystems]
Pages = ["generated/$(c).jl"]
Order = [:type, :function]
Public = true
Private = false
```
""",
)
end
return file_name
end
function _write_second_level_markdown(input::DataType, subtypes::Vector{DataType}, exceptions)
c = string(nameof(input))
file_name = "model_library/generated_$(c).md"
open(joinpath("docs/src", file_name), "w") do io
print(io, "# $input\n\n")
for T_ in subtypes
_check_exception(T_, exceptions) && continue
T = string(nameof(T_))
print(
io,
"""
## $(T)
```@autodocs
Modules = [PowerSystems]
Pages = ["/$(T).jl"]
Order = [:type, :function]
Public = true
Private = false
```
""",
)
end
end
return file_name
end
function make_dynamics_library!(model_library;
dyn_categories =[
PSY.DynamicGeneratorComponent,
PSY.DynamicInverterComponent,
],
exceptions = [PSY.OuterControl,
PSY.ActivePowerControl,
PSY.ReactivePowerControl,],
manual_additions = Dict{String, Any}("DynamicInverterComponent" => Any["OuterControl" => "model_library/outer_control.md"])
)
for abstract_type in dyn_categories
@info "Making entries for subtypes of $abstract_type"
abstract_type_string = string(nameof(abstract_type))
addition = Dict{String, Any}()
internal_index = Any[]
for c_ in subtypes(abstract_type)
c_string = string(nameof(c_))
_check_exception(c_, exceptions) && continue
concretes = IS.get_all_concrete_subtypes(c_)
file_name = _write_second_level_markdown(c_,
concretes, exceptions)
push!(internal_index, c_string => file_name)
end
push!(model_library, abstract_type_string => internal_index)
if haskey(manual_additions, abstract_type_string)
addition = get(manual_additions, abstract_type_string, nothing)
push!(model_library[abstract_type_string], addition...)
end
end
end
function make_model_library(;
categories = [],
exceptions = [],
manual_additions = Dict{String, Any}()
)
# Clean up old generated files before creating new ones
_clean_old_generated_files(joinpath("docs", "src", "model_library"))
model_library = Dict{String, Any}()
for abstract_type in categories
@info "Making entries for subtypes of $abstract_type"
internal_index = Any[]
concrete = IS.get_all_concrete_subtypes(abstract_type)
for c_ in concrete
_check_exception(c_, exceptions) && continue
c = string(nameof(c_))
file_name = _write_first_level_markdown(c)
push!(internal_index, c => file_name)
end
isempty(internal_index) && continue
model_library[string(nameof(abstract_type))] = internal_index
end
make_dynamics_library!(model_library)
for (k, v) in manual_additions
if haskey(model_library, k)
push!(model_library[k], v...)
else
model_library[k] = v
end
end
return Any[p for p in model_library]
end
================================================
FILE: docs/make_tutorials.jl
================================================
using Pkg
using Literate
using DataFrames
using PrettyTables
# Limit DataFrame rendering during docs generation to avoid huge literal outputs.
# Notes:
# - Environment-variable approaches tested (`DATAFRAMES_ROWS`, `DATAFRAMES_COLUMNS`,
# `LINES`, `COLUMNS`) did not constrain DataFrames output in this pipeline.
# - We keep a docs-local Base.show override as a fallback and accept `kwargs...`
# so explicit show(...; kwargs) calls do not error on unsupported keywords.
function _env_int(name::String, default::Int)
parsed = tryparse(Int, get(ENV, name, string(default)))
return something(parsed, default)
end
const _DF_MAX_ROWS = _env_int("SIENNA_DOCS_DF_MAX_ROWS", 10)
const _DF_MAX_COLS = _env_int("SIENNA_DOCS_DF_MAX_COLS", 80)
function Base.show(io::IO, mime::MIME"text/plain", df::DataFrame; kwargs...)
# Keep docs output bounded while allowing explicit caller kwargs.
PrettyTables.pretty_table(io, df;
backend = :text,
maximum_number_of_rows = _DF_MAX_ROWS,
maximum_number_of_columns = _DF_MAX_COLS,
show_omitted_cell_summary = true,
compact_printing = false,
limit_printing = true,
kwargs...)
end
function Base.show(io::IO, mime::MIME"text/html", df::DataFrame; kwargs...)
PrettyTables.pretty_table(io, df;
backend = :html,
maximum_number_of_rows = _DF_MAX_ROWS,
maximum_number_of_columns = _DF_MAX_COLS,
show_omitted_cell_summary = true,
compact_printing = false,
limit_printing = true,
kwargs...)
end
# Remove previously generated tutorial artifacts so a docs build only reflects
# current source tutorials.
#
# Input:
# - dir: tutorial output directory that can contain generated_*.md/ipynb.
# Output:
# - Deletes matching files in-place and logs each deletion.
function clean_old_generated_files(dir::String)
if !isdir(dir)
@warn "Directory does not exist: $dir"
return
end
generated_files = filter(
f ->
startswith(f, "generated_") &&
(endswith(f, ".md") || endswith(f, ".ipynb")),
readdir(dir),
)
for file in generated_files
rm(joinpath(dir, file); force = true)
@info "Removed old generated file: $file"
end
end
#########################################################
# Literate post-processing functions for tutorial generation
#########################################################
# Compute docs base URL from Documenter deploy context.
#
# Behavior:
# - previews/PR123 -> .../previews/PR123
# - dev (or custom DOCUMENTER_DEVURL) -> .../dev
# - tagged versions like v0.9 -> .../v0.9
# - fallback -> .../stable
#
# This keeps generated download/view-online links correct across preview, dev,
# tagged, and stable deployments.
function _compute_docs_base_url()
base = "https://sienna-platform.github.io/PowerSystems.jl"
current_version = get(ENV, "DOCUMENTER_CURRENT_VERSION", "")
# Preview builds (e.g. "previews/PR123")
if startswith(current_version, "previews/PR")
return "$base/$current_version"
end
# Dev builds
if current_version == "dev"
dev_suffix = get(ENV, "DOCUMENTER_DEVURL", "dev")
return "$base/$dev_suffix"
end
# Tagged/versioned builds (e.g. "v0.9", "v1.2.3")
if !isempty(current_version) && current_version != "stable"
return "$base/$current_version"
end
# Default to stable
return "$base/stable"
end
const _DOCS_BASE_URL = _compute_docs_base_url()
"""
Choose how tutorial download links are written in generated markdown.
- **Absolute** (under `_DOCS_BASE_URL/tutorials/`): CI / Documenter context (`GITHUB_ACTIONS` or
non-empty `DOCUMENTER_CURRENT_VERSION`) so previews, `dev`, and versioned URLs match
`_compute_docs_base_url()`.
- **Relative** (bare filenames): local/offline builds; files sit next to `generated_*.md`
under `docs/src/tutorials/`.
Override: `SIENNA_DOCS_DOWNLOAD_LINKS`=`absolute` or `relative`.
"""
function _downloads_use_absolute_urls()
o = get(ENV, "SIENNA_DOCS_DOWNLOAD_LINKS", "")
o == "absolute" && return true
o == "relative" && return false
haskey(ENV, "GITHUB_ACTIONS") && return true
!isempty(get(ENV, "DOCUMENTER_CURRENT_VERSION", "")) && return true
return false
end
# Replace APPEND_MARKDOWN("path/to/file.md") placeholders with file contents.
#
# Sample input:
# "Before\nAPPEND_MARKDOWN(\"docs/src/tutorials/_snippet.md\")\nAfter"
# Sample output:
# "Before\n<contents of _snippet.md>\nAfter"
#
# Notes:
# - Uses a non-greedy-safe capture (`[^\"]*`) so multiple placeholders can be
# replaced independently.
function insert_md(content)
pattern = r"APPEND_MARKDOWN\(\"([^\"]*)\"\)"
if occursin(pattern, content)
content = replace(content, pattern => m -> read(m.captures[1], String))
end
return content
end
# Default display titles for Documenter admonition types when no custom title is given.
# See https://documenter.juliadocs.org/stable/showcase/#Admonitions
const _ADMONITION_DISPLAY_NAMES = Dict{String, String}(
"note" => "Note",
"info" => "Info",
"tip" => "Tip",
"warning" => "Warning",
"danger" => "Danger",
"compat" => "Compat",
"todo" => "TODO",
"details" => "Details",
)
# Preprocess Literate source to convert Documenter-style admonitions into Jupyter-friendly
# blockquotes. Used only for notebook output; markdown keeps `!!! type` and is rendered by
# Documenter. Admonitions are not recognized by common mark or Jupyter; see
# https://fredrikekre.github.io/Literate.jl/v2/tips/#admonitions-compatibility
function preprocess_admonitions_for_notebook(str::AbstractString)
lines = split(str, '\n'; keepempty = true)
out = String[]
i = 1
n = length(lines)
admonition_start =
r"^# !!! (note|info|tip|warning|danger|compat|todo|details)(?:\s+\"([^\"]*)\")?\s*$"
content_line = r"^# (.*)$" # Documenter admonition body: # then 4 spaces
blank_comment = r"^#\s*$" # # or # with only spaces
while i <= n
line = lines[i]
m = match(admonition_start, line)
if m !== nothing
typ = lowercase(m.captures[1])
custom_title = m.captures[2]
title = if custom_title !== nothing && !isempty(custom_title)
custom_title
else
get(_ADMONITION_DISPLAY_NAMES, typ, titlecase(typ))
end
push!(out, "# > *$(title)*")
push!(out, "# >")
i += 1
# Consume blank comment lines and content lines
while i <= n
l = lines[i]
if match(blank_comment, l) !== nothing
push!(out, "# >")
i += 1
elseif (cm = match(content_line, l)) !== nothing
push!(out, "# > " * cm.captures[1])
i += 1
else
break
end
end
continue
end
push!(out, line)
i += 1
end
return join(out, '\n')
end
# Inject a short "download tutorial files" sentence after the first markdown
# heading in generated tutorial pages.
#
# Sample input:
# "# Title\nBody..."
# Sample output (conceptual):
# "# Title\n\n*To follow along... [Julia script](.../tutorial.jl)...*\n\nBody..."
#
# Download links:
# - **Deployed / CI**: absolute URLs under `_DOCS_BASE_URL` when `_downloads_use_absolute_urls()` is true.
# - **Local**: bare filenames (siblings of `generated_*.md` in `docs/src/tutorials/`).
function add_download_links(content, jl_file, ipynb_file)
script_link, notebook_link = if _downloads_use_absolute_urls()
("$_DOCS_BASE_URL/tutorials/$(jl_file)", "$_DOCS_BASE_URL/tutorials/$(ipynb_file)")
else
(jl_file, ipynb_file)
end
download_section = """
*To follow along, you can download this tutorial as a [Julia script (.jl)]($(script_link)) or [Jupyter notebook (.ipynb)]($(notebook_link)).*
"""
# Insert after the first heading (which should be the title)
# Match the first heading line and replace it with heading + download section
m = match(r"^(#+ .+)$"m, content)
if m !== nothing
heading = m.match
content = replace(content, r"^(#+ .+)$"m => heading * download_section; count = 1)
end
return content
end
# Insert a setup preface and captured `Pkg.status()` into the first markdown
# cell of a generated notebook, immediately after the first heading.
#
# Sample effect:
# - First markdown cell gains a "Set up" blockquote and an embedded code block
# containing package versions from the docs build environment.
function add_pkg_status_to_notebook(nb::Dict)
cells = get(nb, "cells", [])
if isempty(cells)
return nb
end
# Find the first markdown cell
first_markdown_idx = nothing
for (i, cell) in enumerate(cells)
if get(cell, "cell_type", "") == "markdown"
first_markdown_idx = i
break
end
end
if first_markdown_idx === nothing
return nb # No markdown cell found, return unchanged
end
first_cell = cells[first_markdown_idx]
cell_source = get(first_cell, "source", [])
# Convert source array to string to find the first heading
source_text = join(cell_source)
# Find the first heading (lines starting with #)
heading_pattern = r"^(#+\s+.+?)$"m
heading_match = match(heading_pattern, source_text)
if heading_match === nothing
return nb # No heading found, return unchanged
end
# Capture Pkg.status() output at build time
io = IOBuffer()
Pkg.status(; io = io)
pkg_status_output = String(take!(io))
# Create the content to insert: blockquote "Set up" with setup instructions and pkg.status()
# Blockquote title and body; hyperlinks for IJulia and create an environment
preface_lines = [
"\n",
"> **Set up**\n",
">\n",
"> To run this notebook, first install the Julia kernel for Jupyter Notebooks using [IJulia](https://julialang.github.io/IJulia.jl/stable/manual/installation/), then [create an environment](https://pkgdocs.julialang.org/v1/environments/) for this tutorial with the packages listed with `using <PackageName>` further down.\n",
">\n",
"> This tutorial has demonstrated compatibility with these package versions. If you run into any errors, first check your package versions for consistency using `Pkg.status()`.\n",
">\n",
]
# Format Pkg.status() output as a code block inside the blockquote
pkg_status_lines = split(pkg_status_output, '\n'; keepempty = true)
pkg_status_block = [" > ```\n"]
for line in pkg_status_lines
push!(pkg_status_block, " > " * line * "\n")
end
push!(pkg_status_block, " > ```\n", "\n")
# Find the first heading line in the source array
heading_line_idx = nothing
for (i, line) in enumerate(cell_source)
if match(heading_pattern, line) !== nothing
heading_line_idx = i
break
end
end
if heading_line_idx === nothing
return nb # Couldn't find heading line
end
# Build new source array
new_source = String[]
# Add all lines up to and including the heading line
for i in 1:heading_line_idx
push!(new_source, cell_source[i])
end
# Add the preface and pkg.status content right after the heading
append!(new_source, preface_lines)
append!(new_source, pkg_status_block)
# Add all remaining lines after the heading
for i in (heading_line_idx + 1):length(cell_source)
push!(new_source, cell_source[i])
end
# Update the cell source
first_cell["source"] = new_source
cells[first_markdown_idx] = first_cell
nb["cells"] = cells
return nb
end
# Add italicized "view online" comment after each image from ```@raw html ... ``` (or
# the raw HTML / markdown form Literate writes). Used as a postprocess in Literate.notebook.
# Literate strips the backtick wrapper and outputs raw HTML; we match that multi-line block.
# Sample effect:
# - If a markdown cell contains one or more image fragments, append exactly one
# "view online" fallback note at the end of that cell.
# - If the note already exists in the cell, no change is applied.
function add_image_links(nb::Dict, outputfile_base::AbstractString)
tutorial_url = "$_DOCS_BASE_URL/tutorials/$(outputfile_base)/"
msg = "_If image is not available when viewing in a Jupyter notebook, view the tutorial online [here]($tutorial_url)._"
cells = get(nb, "cells", [])
for (idx, cell) in enumerate(cells)
get(cell, "cell_type", "") != "markdown" && continue
source = get(cell, "source", [])
isempty(source) && continue
text = join(source)
# Check if this cell already has the "view online" message to avoid duplicates
contains(text, "If image is not available when viewing in a Jupyter notebook") &&
continue
suffix = "\n\n" * msg * "\n"
# If the cell has any of the image shapes below, we append one "view online" note.
# We build one alternation pattern from sub-patterns (each line is one case).
#
# HTML paragraph wrapping an <img> (Literate often emits <p>…<img>…</p>).
# <p[^>]*> — opening <p> and attributes
# [\s\S]*? — any chars, non-greedy, up to the first <img
# <img…</p> — from <img through closing </p>
p_with_img_pattern = r"<p[^>]*>[\s\S]*?<img[\s\S]*?</p>"
# Documenter @raw html chunk that Literate inlines in the notebook (backticks removed in output).
# ```@raw html — start marker
# [\s\S]*? — block body, non-greedy
# ``` — end fence
raw_html_block_pattern = r"```@raw html[\s\S]*?```"
# Standard markdown image: 
# !\[…\] — alt in brackets; \(…\) — path in parens
markdown_image_pattern = r"!\[[^\]]*\]\([^\)]*\)"
# A bare <img ...> not already covered by the <p>…<img>…</p> case above.
# <img — tag start; [^>]*? — attributes; /?> — self-closing or >
standalone_img_pattern = r"<img[^>]*?/?>"
# Union of the four cases: (?: A | B | C | D )
image_fragment_pattern = Regex(
"(?:" *
p_with_img_pattern.pattern * "|" *
raw_html_block_pattern.pattern * "|" *
markdown_image_pattern.pattern * "|" *
standalone_img_pattern.pattern * ")",
)
if occursin(image_fragment_pattern, text)
text *= suffix
end
# Convert back to notebook source array (lines, last without trailing \n if non-empty)
lines = split(text, "\n"; keepempty = true)
new_source = String[]
for i in 1:length(lines)
if i < length(lines)
push!(new_source, lines[i] * "\n")
else
isempty(lines[i]) || push!(new_source, lines[i])
end
end
cell["source"] = new_source
cells[idx] = cell
end
nb["cells"] = cells
return nb
end
#########################################################
# Process tutorials with Literate
#########################################################
# Generate tutorial markdown + notebook artifacts from literate .jl sources.
#
# Pipeline:
# 1) discover tutorial .jl files (excluding helper files starting with "_")
# 2) generate Documenter-flavored markdown with injected download links
# 3) generate notebook with admonition conversion, setup preface, and image note
function make_tutorials()
tutorials_dir = abspath(joinpath(@__DIR__, "src", "tutorials"))
# Exclude helper scripts that start with "_"
if isdir(tutorials_dir)
tutorial_files =
filter(
x -> endswith(x, ".jl") && !startswith(x, "_"),
readdir(tutorials_dir),
)
if !isempty(tutorial_files)
# Clean up old generated tutorial files
tutorial_outputdir = tutorials_dir
clean_old_generated_files(tutorial_outputdir)
for file in tutorial_files
@show file
infile_path = joinpath(tutorials_dir, file)
execute =
if occursin("EXECUTE = TRUE", uppercase(readline(infile_path)))
true
else
false
end
outputfile = string("generated_", replace("$file", ".jl" => ""))
# Generate markdown
Literate.markdown(infile_path,
tutorial_outputdir;
name = outputfile,
credit = false,
flavor = Literate.DocumenterFlavor(),
documenter = true,
postprocess = (
content -> add_download_links(
insert_md(content),
file,
string(outputfile, ".ipynb"),
)
),
execute = execute)
# Generate notebook (chain add_image_links after add_pkg_status_to_notebook).
# preprocess_admonitions_for_notebook converts Documenter admonitions to blockquotes
# so they render in Jupyter; markdown output keeps !!! style for Documenter.
Literate.notebook(infile_path,
tutorial_outputdir;
name = outputfile,
credit = false,
execute = false,
preprocess = preprocess_admonitions_for_notebook,
postprocess = nb ->
add_image_links(add_pkg_status_to_notebook(nb), outputfile))
end
end
end
end
================================================
FILE: docs/src/api/citation.md
================================================
### Citation
Users are requested to please cite the
[following paper:](https://www.sciencedirect.com/science/article/pii/S2352711021000765)
```bibtex
@article{LARA2021100747,
title = {PowerSystems.jl — A power system data management package for large scale modeling},
journal = {SoftwareX},
volume = {15},
pages = {100747},
year = {2021},
issn = {2352-7110},
doi = {https://doi.org/10.1016/j.softx.2021.100747},
url = {https://www.sciencedirect.com/science/article/pii/S2352711021000765},
author = {José Daniel Lara and Clayton Barrows and Daniel Thom and Dheepak Krishnamurthy and Duncan Callaway},
keywords = {Power Systems, Julia, Energy},
```
PowerSystems has been developed as part of the [Sienna platform](https://www.nlr.gov/analysis/sienna.html)
by the U.S. Department of Energy's National Laboratory of the Rockies
([NLR](https://www.nlr.gov/), formerly NREL).
================================================
FILE: docs/src/api/developer_guidelines.md
================================================
# Developer Guidelines
In order to contribute to `PowerSystems.jl` repository please read the following sections of
[`InfrastructureSystems.jl`](https://github.com/Sienna-Platform/InfrastructureSystems.jl)
documentation in detail:
1. [Style Guide](https://sienna-platform.github.io/InfrastructureSystems.jl/stable/style/)
2. [Contributing Guidelines](https://github.com/Sienna-Platform/PowerSystems.jl/blob/main/CONTRIBUTING.md)
Pull requests are always welcome to fix bugs or add additional modeling capabilities.
**All the code contributions need to include tests with a minimum coverage of 70%**
================================================
FILE: docs/src/api/enumerated_types.md
================================================
# Specifying the type of...
Some fields in PowerSystems.jl are specified with an option from a pre-defined list
(Specified with [`IS.scoped_enums`](https://sienna-platform.github.io/InfrastructureSystems.jl/stable/InfrastructureSystems/#InfrastructureSystems.@scoped_enum-Tuple%7BAny,%20Vararg%7BAny,%20N%7D%20where%20N%7D)).
Example syntax:
```
set_fuel!(gen, ThermalFuels.COAL)
```
These predefined lists are below:
## [AC Buses](@id acbustypes_list)
`ACBusTypes` categorize buses for modeling activities and denote which quantities are specified
for load flow calculations. `ACBusTypes` has the options:
| Name | Description |
|:---------- |:---------------------------------------------------------- |
| `ISOLATED` | Disconnected from network |
| `PQ` | Active and reactive power defined (load bus) |
| `PV` | Active power and voltage magnitude defined (generator bus) |
| `REF` | Reference bus (θ = 0) |
| `SLACK` | Slack bus |
## [Prime Movers](@id pm_list)
Each generator contains a field for `prime_mover::PrimeMovers`, based on the options in
[EIA form 923](https://www.eia.gov/survey/form/eia_923/instructions.pdf).
`PrimeMovers` has the options:
| Name | Description |
|:----- |:------------------------------------------------------------------------------------------------------ |
| `BA` | Energy Storage, Battery |
| `BT` | Turbines Used in a Binary Cycle (including those used for geothermal applications) |
| `CA` | Combined-Cycle – Steam Part |
| `CC` | Combined-Cycle - Aggregated Plant *augmentation of EIA |
| `CE` | Energy Storage, Compressed Air |
| `CP` | Energy Storage, Concentrated Solar Power |
| `CS` | Combined-Cycle Single-Shaft Combustion turbine and steam turbine share a single generator |
| `CT` | Combined-Cycle Combustion Turbine Part |
| `ES` | Energy Storage, Other |
| `FC` | Fuel Cell |
| `FW` | Energy Storage, Flywheel |
| `GT` | Combustion (Gas) Turbine (including jet engine design) |
| `HA` | Hydrokinetic, Axial Flow Turbine |
| `HB` | Hydrokinetic, Wave Buoy |
| `HK` | Hydrokinetic, Other |
| `HY` | Hydraulic Turbine (including turbines associated with delivery of water by pipeline) |
| `IC` | Internal Combustion (diesel, piston, reciprocating) Engine |
| `PS` | Energy Storage, Reversible Hydraulic Turbine (Pumped Storage) |
| `OT` | Other |
| `ST` | Steam Turbine (including nuclear, geothermal and solar steam; does not include combined-cycle turbine) |
| `PVe` | Photovoltaic \(*Note*: renaming from EIA PV to PVe to avoid conflict with `ACBusType.PV`\) |
| `WT` | Wind Turbine, Onshore |
| `WS` | Wind Turbine, Offshore |
## [Fuels for Thermal Generators](@id tf_list)
Each [`ThermalGen`](@ref) generator has a field for `fuel::ThermalFuels` where `ThermalFuels`
are intended to reflect the options in the
[Aggregated Fuel Codes](https://www.eia.gov/survey/form/eia_923/instructions.pdf) from the
EIA Annual Energy Review. `ThermalFuels` has the options:
| Name | EIA Fuel Code | Description |
|:---------------------------------------------------------------------------------------------------------------------------------- |:------------- |:----------------------------------------------------------------------------------------------------------------------------------- |
| `ANTHRACITE_COAL` | ANT | Anthracite Coal |
| `BITUMINOUS_COAL` | BIT | Bituminous Coal |
| `LIGNITE_COAL` | LIG | Lignite Coal |
| `SUBBITUMINOUS_COAL` | SUB | Subbituminous Coal |
| `WASTE_COAL` | WC | Waste/Other Coal (including anthracite culm, bituminous gob, fine coal, lignite waste, waste coal) |
| `REFINED_COAL` | RC | Refined Coal (A coal product that improves heat content and reduces emissions. Excludes coal processed by coal preparation plants.) |
| `SYNTHESIS_GAS_COAL` | SGC | Coal-Derived Synthesis Gas |
| `DISTILLATE_FUEL_OIL` | DFO | Distillate Fuel Oil (including diesel, No. 1, No. 2, and No. 4 fuel oils) |
| `JET_FUEL` | JF | Jet Fuel |
| `KEROSENE` | KER | Kerosene |
| `PETROLEUM_COKE` | PC | Petroleum Coke |
| `RESIDUAL_FUEL_OIL` | RFO | Residual Fuel Oil (including No. 5 and No. 6 fuel oils, and bunker C fuel oil) |
| `PROPANE` | PG | Propane, gaseous |
| `SYNTHESIS_GAS_PETROLEUM_COKE` | SGP | Petroleum Coke Derived Synthesis Gas |
| `WASTE_OIL` | WO | Waste/Other Oil (including crude oil, liquid butane, liquid propane, naphtha, oil waste, re-refined motor oil, sludge oil, tar oil) |
| `BLASTE_FURNACE_GAS` | BFG | Blast Furnace Gas |
| `NATURAL_GAS` | NG | Natural Gas |
| `OTHER_GAS` | OG | Other Gas |
| `AG_BYPRODUCT` | AB | Agricultural By-products |
| `MUNICIPAL_WASTE` | MSW | Municipal Solid Waste |
| `OTHER_BIOMASS_SOLIDS` | OBS | Other Biomass Solids |
| `WOOD_WASTE_SOLIDS` | WDS | Wood/Wood Waste Solids (including paper, pellets, railroad ties, utility poles, wood chips, bark, and wood waste solids) |
| `OTHER_BIOMASS_LIQUIDS` | OBL | Other Biomass Liquids |
| `SLUDGE_WASTE` | SLW | Sludge Waste |
| `BLACK_LIQUOR` | BLQ | Black Liquor |
| `WOOD_WASTE_LIQUIDS` | WDL | Wood Waste Liquids excluding Black Liquor (includes red liquor, sludge wood, spent sulfite liquor, and other wood-based liquids) |
| `LANDFILL_GAS` | LFG | Landfill Gas |
| `OTHEHR_BIOMASS_GAS` | OBG | Other Biomass Gas (includes digester gas, methane, and other biomass gasses) |
| `NUCLEAR` | NUC | Nuclear Uranium, Plutonium, Thorium |
| `WASTE_HEAT` | WH | Waste heat not directly attributed to a fuel source |
| `TIREDERIVED_FUEL` | TDF | Tire-derived Fuels |
| `COAL`* | N/A | General Coal Fuels |
| `Geothermal`* | GEO | Geothermal Fuels |
| `OTHER` | OTH | Other type of fuel |
| *Asterisk denotes fuel codes not directly from the current EIA 923 form but kept for compatibility with older versions of the form | | |
## [Energy Storage](@id storagetech_list)
`StorageTech` defines the storage technology used in an energy [`Storage`](@ref) system, based
on the options in [EIA form 923](https://www.eia.gov/survey/form/eia_923/instructions.pdf).
`StorageTech` has the options:
| Name | Description |
|:------------- |:----------------------------- |
| `PTES` | Pumped thermal energy storage |
| `LIB` | LiON Battery |
| `LAB` | Lead Acid Battery |
| `FLWB` | Redox Flow Battery |
| `SIB` | Sodium Ion Battery |
| `ZIB` | Zinc Ion Battery |
| `HGS` | Hydrogen Gas Storage |
| `LAES` | Liquid Air Storage |
| `OTHER_CHEM` | Other Chemical Storage |
| `OTHER_MECH` | Other Mechanical Storage |
| `OTHER_THERM` | Other Thermal Storage |
## [Hydro Reservoir Units](@id hydroreservoir_list)
`ReservoirDataType` specifies which units of measurement for a
[`HydroReservoir`](@ref)'s `level`-related parameters (e.g., `level_targets`,
`storage_level_limits`). It defines the units used to perform energy balance
calculations for a [`HydroReservoir`](@ref) and affects how the totals and targets are calculated.
The user is responsible for correctly managing data conversions when switching between
the different alternatives of `ReservoirDataType`, which has the options:
| Name | Units | Description |
|:--------------- |:----- |:------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `USABLE_VOLUME` | m^3 | The volume of water that can be stored for levels between the penstock intake and the top reservoir level |
| `TOTAL_VOLUME` | m^3 | The total volume of the reservoir considering a total depletion of the water levels. This unit system usually requires the specification of a valid minimum volume level |
| `HEAD` | m | The difference in elevations between the top water levels. It requires a valid conversion constant to go from head to potential energy stored. |
| `ENERGY` | MWh | Uses energy units in MWh to approximate the water storage as a generic energy reservoir. |
## [Facts Control Devices](@id factsmodes_list)
`FACTSOperationModes` define the operation modes of a [`FACTSControlDevice`](@ref).
`FACTSOperationModes` has the options:
| Name | Description |
|:----- |:----------------------------------------------------------------------------------------------- |
| `OOS` | Out-Of-Service (i.e., Series and Shunt links open) |
| `NML` | Normal mode of operation, where Series and Shunt links are operating |
| `BYP` | Series link is bypassed (i.e., like a zero impedance line) and Shunt link operates as a STATCOM |
## [Load Conformity](@id loadconform_list)
`LoadConformity` defines whether a load is
[conforming or non-nonforming](@ref conf_loads). `LoadConformity` has the options:
| Name | Description |
|:---------------- |:----------------------------------------------------------------- |
| `NON_CONFORMING` | Non-conforming load |
| `CONFORMING` | Conforming load |
| `UNDEFINED` | Undefined or unknown whether load is conforming or non-conforming |
## [Tranformer Control Objectives](@id xtf_crtl)
`TransformerControlObjective` is used to select the control objective for a transformer's
tap changer, which can be used to determine the tap position during power flow calculations.
| Name | Description |
|:--------------------------------------- |:------------------------------------------------------------------------- |
| `UNDEFINED` | Undefined |
| `VOLTAGE_DISABLED` | Has voltage control capabilities, which are disabled |
| `REACTIVE_POWER_FLOW_DISABLED` | Has reactive power flow control capabilities, which are disabled |
| `ACTIVE_POWER_FLOW_DISABLED` | Has active power flow control capabilities, which are disabled |
| `CONTROL_OF_DC_LINE_DISABLED` | Has capabilities to control a DC line quantity, which are disabled |
| `ASYMMETRIC_ACTIVE_POWER_FLOW_DISABLED` | Has asymmetric active power flow control capabilities, which are disabled |
| `FIXED` | Fixed tap and fixed phase shift |
| `VOLTAGE` | Voltage control |
| `REACTIVE_POWER_FLOW` | Reactive power flow control |
| `ACTIVE_POWER_FLOW` | Active power flow control |
| `CONTROL_OF_DC_LINE` | Control of a DC line quantity |
| `ASYMMETRIC_ACTIVE_POWER_FLOW` | Asymmetric active power flow control |
## [Dynamic States](@id states_list)
`StateTypes` are used to denote the type of dynamic equation a specific [state](@ref S) is subject
to in [`PowerSimulationsDynamics.jl`](https://sienna-platform.github.io/PowerSimulationsDynamics.jl/stable/).
`StateTypes` has the options:
| Name | Description |
|:-------------- |:-------------------------------------------------------------------------------- |
| `Differential` | State evolves over time via a differential equation ``\dot{x} = f(x)`` |
| `Algebraic` | State evolves over time by satisfying an algebraic equation ``0 = g(x)`` |
| `Hybrid` | Depending on specific parameters, the state can be `Differential` or `Algebraic` |
## [Angle Units](@id angleunits_list)
`AngleUnits` can be specified in:
| Name |
|:--------- |
| `DEGREES` |
| `RADIANS` |
## [Motor Load Technologies](@id motor_list)
| Name |
|:-------------- |
| `INDUCTION` |
| `SYNCHRONOUS` |
| `UNDETERMINED` |
================================================
FILE: docs/src/api/glossary.md
================================================
# Glossary and Acronyms
[A](@ref) | [D](@ref) | [E](@ref) | [F](@ref) | [H](@ref) | [I](@ref) | [O](@ref) | [P](@ref) | [R](@ref) |
[S](@ref) | [V](@ref) | [W](@ref) | [Z](@ref)
### A
- *AC*: Alternating current
- *ACE*: Area control error
- *AGC*: Automatic generation control
- *AVR*: Automatic Voltage Regulator
### D
- *DC*: Direct current
- *DERA1*:
- *Dynamic*: Refers to data and simulations for power system transient simulations using differential
equations. Common examples include signal stability analysis to verify the power system will
maintain stability in the few seconds following an unexpected fault or generator trip. For contrast,
see the definition for [Static](@ref S) data.
### E
- *EMF*: Electromotive force
- *ESAC*: IEEE Type AC Excitation System model
- *ESDC*: IEEE Type DC Excitation System model
- *EXAC*: IEEE Type AC Excitation System (modified) model
- *EXPIC*: Proportional/Integral Excitation System from PSS/E
- *EXST*: IEEE Type ST (Static) Excitation System model
- *EX4VSA*: IEEE Excitation System for Voltage Security Assessment with Over-Excitation Limits.
### F
- *Forecast*: Predicted values of a time-varying quantity that commonly features
a look-ahead and can have multiple data values representing each time period.
This data is used in simulation with receding horizons or data generated from
forecasting algorithms. See the article on [`Time Series Data`](@ref ts_data).
- *Forecast window*: Represents the forecasted value starting at a particular initial time.
See the article on [`Time Series Data`](@ref ts_data).
### H
- *Horizon*: Is the duration of all time steps in one forecast. As of PowerSystems.jl
version 4.0, all horizons in `PowerSystems.jl` are represented as a `Dates.Period`.
For instance, many Day-ahead markets will have an hourly-[resolution](@ref R) forecast
for the next day, which would have a horizon of `Dates.Hour(24)` or `Dates.Day(1)`. If the
forecast included the next day plus a 24-hour lookahead window, the horizon would be
`Dates.Hour(48)` or `Dates.Day(2)`. See the article on [`Time Series Data`](@ref ts_data).
- *HVDC*: High-voltage DC
### I
- *IEEET*: IEEE Type I Excitation System.
- *Injector* or *Injection*: Injectors refer to models that represent how a generator or storage
device *injects* power or current into the power system. Loads are negative injectors. In
`PowerSystems.jl`, some components can accept data for both [`StaticInjection`](@ref) and
[`DynamicInjection`](@ref) models for both [static](@ref S) and [dynamic](@ref D) modeling.
- *Interval*: The period of time between forecast initial times. In `PowerSystems.jl` all
intervals are represented using `Dates.Period` types. For instance, in a Day-Ahead market
simulation, the interval is usually `Hour(24)`.
- *Initial time*: The first time-stamp in a forecast window. See the article on
[`Time Series Data`](@ref ts_data).
- *IPC*: Interconnecting power converter
### L
- *LCC*: Line Commutated Converter HVDC line
### O
- *OEL*: Over Excitation Limiter
### P
- *PLL*: Phase-locked loop
- *PSS*: Power System Stabilizer
- *PSSE* or *PSS/E*: Siemens' PSS®E Power System Simulator for Engineering
- *PPA*: Power purchase agreement
- *PSI*: [`PowerSimulations.jl`](https://sienna-platform.github.io/PowerSimulations.jl/latest/)
- *PSID*: [`PowerSimulationsDynamics.jl`](https://sienna-platform.github.io/PowerSimulationsDynamics.jl/stable/)
- *PSLF*: GE Vernova's Positive Sequence Load Flow Software
- *PSY*: `PowerSystems.jl` (this package)
- *pu* or *p.u.*: Per-unit
### R
- *REECB1*: Renewable Energy Electric Controller Type B1
- *REPCA1*: REPCA1: Renewable Energy Power Controller Type A1
- *Resolution*: The period of time between each discrete value in a time series. All resolutions
are represented using `Dates.Period` types. For instance, a Day-ahead market data set usually
has a resolution of `Hour(1)`, a Real-Time market data set usually has a resolution of `Minute(5)`.
### S
- *SCRX*: Bus Fed or Solid Fed Static Exciter
- *SEXS*: Simplified Excitation System model from PSS/E
- *SIL*: Surge impedance loading
- *States*: Correspond to the set of inputs, outputs or variables, that evolve dynamically in
[`PowerSimulationsDynamics.jl`](https://sienna-platform.github.io/PowerSimulationsDynamics.jl/stable/),
commonly via a differential-algebraic system of equations. In `PowerSystems.jl`, a component
associated to a `DynamicInjector` (for example an AVR) specifies the set of states that specific
component requires to be modeled accurately.
- *Static*: Typically refers to steady state data or models where the power system
and each of its components are assumed to be operating at a steady state equilibrium point. This
includes both power flow data for a single time point simulation as well as quasi-static time
series data and models, where the power system is at an equilibrium point at each time step.
Static data can be used as the input to single time point power flow models and production
cost models with, for example, 5-minute, 15-minute, or 1-hour [Resolution](@ref R).
For contrast, see the definition for [Dynamic](@ref D) data.
- *STAB*: Speed Sensitive Stabilizing PSS Model
### V
- *VSCLine*: Voltage-Source Converter HVDC Line
- *VSM*: Virtual Synchronous Machine
### W
- *Window*: A forecast window is one forecast run that starts at one [initial time](@ref I)
and extends through the forecast [horizon](@ref H). Typically, a forecast data set
contains multiple forecast windows, with sequential initial times. For example, a
year-long data set of day-ahead forecasts contains 365 forecast windows
### Z
- *ZIP load*: A ZIP load model accounts for the voltage-dependency of a load and is primarily used
for dynamics modeling. It includes three kinds of load: constant impedance (Z), constant current (I),
and constant power (P), though many dynamics models just use the constant impedance model.
[`StandardLoad`](@ref) and [`ExponentialLoad`](@ref) are both ZIP load models:
[`StandardLoad`](@ref) breaks up the load into each of its three components, while
[`ExponentialLoad`](@ref) expresses the load as an exponential equation.
================================================
FILE: docs/src/api/internal.md
================================================
```@meta
CollapsedDocStrings = true
```
# Internal API
```@autodocs
Modules = [PowerSystems]
Public = false
```
================================================
FILE: docs/src/api/psse_models.md
================================================
# [Supported PSS/e Models](@id psse_models_ref)
PSS/e's dynamic model library is extensive. `PowerSystems.jl` currently supports parsing the following models for version 5.0:
## Dynamic Generator Models
### Machine Models
| PSS/e Model | PowerSystems Component |
|:----------- |:-------------------------------- |
| GENSAE | [`SalientPoleExponential`](@ref) |
| GENSAL | [`SalientPoleQuadratic`](@ref) |
| GENROE | [`RoundRotorExponential`](@ref) |
| GENCLS | [`BaseMachine`](@ref) |
| GENROU | [`RoundRotorQuadratic`](@ref) |
### Automatic Voltage Regulator (AVR) Models
| PSS/e Model | PowerSystems Component |
|:----------- |:---------------------- |
| IEEET1 | [`IEEET1`](@ref) |
| ESDC1A | [`ESDC1A`](@ref) |
| ESDC2A | [`ESDC2A`](@ref) |
| ESAC1A | [`ESAC1A`](@ref) |
| ESAC6A | [`ESAC6A`](@ref) |
| ESAC8B | [`ESAC8B`](@ref) |
| EXAC1 | [`EXAC1`](@ref) |
| EXAC1A | [`EXAC1A`](@ref) |
| EXAC2 | [`EXAC2`](@ref) |
| EXPIC1 | [`EXPIC1`](@ref) |
| ESST1A | [`ESST1A`](@ref) |
| ESST4B | [`ESST4B`](@ref) |
| SCRX | [`SCRX`](@ref) |
| SEXS | [`SEXS`](@ref) |
| EXST1 | [`EXST1`](@ref) |
| ST6B | [`ST6B`](@ref) |
| ST8C | [`ST8C`](@ref) |
### Turbine Governor Models
| PSS/e Model | PowerSystems Component |
|:----------- |:-------------------------- |
| GAST | [`GasTG`](@ref) |
| GGOV1 | [`GeneralGovModel`](@ref) |
| HYGOV | [`HydroTurbineGov`](@ref) |
| IEEEG1 | [`IEEETurbineGov1`](@ref) |
| TGOV1 | [`SteamTurbineGov1`](@ref) |
| TGOV1DU | [`SteamTurbineGov1`](@ref) |
| DEGOV1 | [`DEGOV1`](@ref) |
| PIDGOV | [`PIDGOV`](@ref) |
| WPIDHY | [`WPIDHY`](@ref) |
### Power System Stabilizer (PSS) Models
| PSS/e Model | PowerSystems Component |
|:----------- |:---------------------- |
| IEEEST | [`IEEEST`](@ref) |
| STAB1 | [`STAB1`](@ref) |
## Dynamic Inverter Models
### Converter Models
| PSS/e Model | PowerSystems Component |
|:----------- |:--------------------------------------- |
| REGCA1 | [`RenewableEnergyConverterTypeA`](@ref) |
### Active and Reactive Power Control Models
| PSS/e Model | PowerSystems Component |
|:----------- |:----------------------------------------------------------------------------------------------------------- |
| REECB1 | [`ActiveRenewableControllerAB`](@ref), [`ReactiveRenewableControllerAB`](@ref), [`RECurrentControlB`](@ref) |
| REPCA1 | [`ActiveRenewableControllerAB`](@ref), [`ReactiveRenewableControllerAB`](@ref) |
## Additional Models
| PSS/e Model | PowerSystems Component |
|:----------- |:----------------------------------------- |
| DERA1 | [`AggregateDistributedGenerationA`](@ref) |
## See also
- Parsing [PSS/e dynamic data](@ref dyr_data)
- Parsing [Matpower or PSS/e RAW Files](@ref pm_data)
================================================
FILE: docs/src/api/public.md
================================================
# Public API Reference
## Modeling
```@autodocs
Modules = [PowerSystems]
Pages = ["PowerSystems.jl",
"branches.jl",
"components.jl",
"injection.jl",
"devices.jl",
"loads.jl",
"supplemental_constructors",
"generation.jl",
"reserves.jl",
"storage.jl",
"services.jl",
"topological_elements.jl",
"dynamic_models.jl",
"static_models.jl",
"subsystems.jl",
"static_injection_subsystem.jl",
"dynamic_models.jl",
"operational_cost.jl",
"cost_function_timeseries.jl",
"definitions.jl"
]
Public = true
Private = false
```
## Supplemental Attributes
```@autodocs
Modules = [PowerSystems]
Pages = ["outages.jl",
"contingencies.jl",
"impedance_correction.jl",
"plant_attribute.jl"
]
Public = true
Private = false
```
```@autodocs
Modules = [IS]
Pages = ["geographic_supplemental_attribute.jl"
]
Order = [:type, :function]
Filter = t -> nameof(t) in names(PowerSystems)
```
## Operating Costs
```@autodocs
Modules = [IS]
Pages = ["production_variable_cost_curve.jl",
"cost_aliases.jl",
"value_curve.jl",
]
Order = [:type, :function]
Filter = t -> nameof(t) in names(PowerSystems)
```
## Time Series
```@autodocs
Modules = [IS]
Pages = ["abstract_time_series.jl",
"deterministic.jl",
"deterministic_single_time_series.jl",
"probabilistic.jl",
"scenarios.jl",
"static_time_series.jl",
"single_time_series.jl",
"forecasts.jl",
]
Order = [:type, :function]
Filter = t -> nameof(t) in names(PowerSystems)
```
```@autodocs
Modules = [IS]
Pages = ["time_series_cache.jl",
"time_series_interface.jl",
"time_series_structs.jl",
"time_series_storage.jl",
"time_series_parser.jl",
"utils/print.jl"]
Order = [:type, :function]
Filter = t -> nameof(t) in names(PowerSystems)
```
## System
```@autodocs
Modules = [PowerSystems]
Pages = ["get_components_interface.jl", "base.jl"]
Public = true
Private = false
Filter = t -> t ∈ [System]
```
```@autodocs
Modules = [PowerSystems]
Pages = ["get_components_interface.jl", "base.jl"]
Public = true
Private = false
Filter = t -> t ∉ [System]
```
```@autodocs
Modules = [PowerSystems]
Pages = ["utils/print.jl",
"utils/generate_struct_files.jl"]
Public = true
Private = false
Filter = t -> t ∉ [System]
```
## Advanced Component Selection
The primary way to retrieve components in PowerSystems.jl is with the [`get_components`](@ref) and similar `get_*` methods above. The following `ComponentSelector` interface offers advanced, repeatable component selection primarily for multi-scenario post-processing analytics. See [`PowerAnalytics.jl`](https://sienna-platform.github.io/PowerAnalytics.jl/stable/).
```@autodocs
Modules = [IS]
Pages = ["component_selector.jl"]
Filter = t -> !(t isa AbstractString) && nameof(t) in names(PowerSystems) && getproperty(PowerSystems, nameof(t)) === t && !(nameof(t) in [:SingularComponentSelector, :PluralComponentSelector, :DynamicallyGroupedComponentSelector, :subtype_to_string, :component_to_qualified_string])
```
```@autodocs
Modules = [PowerSystems]
Pages = ["component_selector_interface.jl"]
Public = true
Private = false
```
```@autodocs
Modules = [IS]
Pages = ["component_selector.jl"]
Filter = t -> !(t isa AbstractString) && nameof(t) in names(PowerSystems) && getproperty(PowerSystems, nameof(t)) === t && (nameof(t) in [:SingularComponentSelector, :PluralComponentSelector, :DynamicallyGroupedComponentSelector, :subtype_to_string, :component_to_qualified_string])
```
## Additional Component Methods
```@autodocs
Modules = [PowerSystems]
Pages = ["supplemental_accessors.jl",
"supplemental_setters.jl"]
Public = true
Private = false
```
## [Deprecated Methods](@id deprecated)
```@autodocs
Modules = [PowerSystems]
Pages = ["deprecated.jl"]
Public = true
Private = false
```
## Parsing
```@autodocs
Modules = [PowerSystems]
Pages = ["parsers/power_system_table_data.jl",
"parsers/power_models_data.jl",
"parsers/TAMU_data.jl",
"parsers/psse_dynamic_data.jl",
"parsers/pm_io/common.jl",
"parsers/im_io/matlab.jl"]
Public = true
Private = false
Filter = t -> t ∉ [System]
```
## [Logging](@id logging)
```@autodocs
Modules = [PowerSystems]
Pages = ["utils/logging.jl"]
Public = true
Private = false
```
================================================
FILE: docs/src/api/static_injection_subtypes.md
================================================
# StaticInjection Subtypes Comparison
This document summarizes the similarities and differences between [`StaticInjection`](@ref) subtypes in PowerSystems.jl, with emphasis on generators, loads, storage, and sources. Some control-related subtypes--like FACTS devices--are omitted from the below charts, simply because they have very little in common with the other subtypes. For all subtypes of [`StaticInjection`](@ref), see [Type Tree](@ref "Type Tree").
* * *
## Power Limits Fields Comparison
### Generators
| Type | `active_power_limits` | `max_active_power` | `reactive_power_limits` | `max_reactive_power` |
|:------------------------------ |:--------------------- |:------------------ |:----------------------- |:-------------------- |
| [`ThermalStandard`](@ref) | ✅ `MinMax` | ❌ | ✅ `MinMax` (optional) | ❌ |
| [`ThermalMultiStart`](@ref) | ✅ `MinMax` | ❌ | ✅ `MinMax` (optional) | ❌ |
| [`RenewableDispatch`](@ref) | ❌ | ❌ ¹ | ✅ `MinMax` (optional) | ❌ |
| [`RenewableNonDispatch`](@ref) | ❌ | ❌ | ❌ | ❌ |
| [`HydroDispatch`](@ref) | ✅ `MinMax` | ❌ | ✅ `MinMax` (optional) | ❌ |
| [`HydroTurbine`](@ref) | ✅ `MinMax` | ❌ | ✅ `MinMax` (optional) | ❌ |
| [`HydroPumpTurbine`](@ref) | ✅ `MinMax` | ❌ | ✅ `MinMax` (optional) | ❌ |
### Loads
| Type | `active_power_limits` | `max_active_power` | `reactive_power_limits` | `max_reactive_power` |
|:----------------------------------- |:--------------------- |:------------------ |:----------------------- |:-------------------- |
| [`PowerLoad`](@ref) | ❌ | ✅ `Float64` | ❌ | ✅ `Float64` |
| [`StandardLoad`](@ref) | ❌ | ⊕ | ❌ | ⊕ |
| [`ExponentialLoad`](@ref) | ❌ | ✅ `Float64` | ❌ | ✅ `Float64` |
| [`MotorLoad`](@ref) | ❌ | ✅ `Float64` | ✅ `MinMax` (optional) | ❌ |
| [`InterruptiblePowerLoad`](@ref) | ❌ | ✅ `Float64` | ❌ | ✅ `Float64` |
| [`InterruptibleStandardLoad`](@ref) | ❌ | ⊕ | ❌ | ⊕ |
| [`ShiftablePowerLoad`](@ref) | ✅ `MinMax` | ✅ `Float64` | ❌ | ✅ `Float64` |
### Storage & Source
| Type | `active_power_limits` | `max_active_power` | `reactive_power_limits` | `max_reactive_power` |
|:-------------------------------- |:--------------------- |:------------------ |:----------------------- |:-------------------- |
| [`EnergyReservoirStorage`](@ref) | ❌ ² | ❌ | ✅ `MinMax` (optional) | ❌ |
| [`Source`](@ref) | ✅ `MinMax` | ❌ | ✅ `MinMax` (optional) | ❌ |
¹ Uses `rating * power_factor` dynamically; no stored field
² EnergyReservoirStorage uses `input_active_power_limits` and `output_active_power_limits` instead
Here, "`MinMax` (optional)" means `Union{MinMax, Nothing}`, with `nothing` repesenting "no limits" and being the default.
⊕ = Split across 3 ZIP fields: `*_constant_*`, `*_impedance_*`, `*_current_*`
* * *
## Generator-Specific Fields
| Field | Thermal* | [`RenewableDispatch`](@ref) | [`RenewableNonDispatch`](@ref) | [`HydroDispatch`](@ref) | [`HydroTurbine`](@ref) | [`HydroPumpTurbine`](@ref) |
|:------------------ |:-------- |:--------------------------- |:------------------------------ |:----------------------- |:---------------------- |:-------------------------- |
| `rating` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| `prime_mover_type` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| `fuel` | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| `status` | ✅ | ❌ | ❌ | ✅ | ❌ | ✅ |
| `must_run` | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ |
| `ramp_limits` | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ |
| `time_limits` | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ |
| `power_factor` | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
| `efficiency` | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ |
| `operation_cost` | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ |
\* Thermal = [`ThermalStandard`](@ref), [`ThermalMultiStart`](@ref)
* * *
## Load-Specific Fields
| Field | [`PowerLoad`](@ref) | [`StandardLoad`](@ref) | [`ExponentialLoad`](@ref) | [`MotorLoad`](@ref) | Interruptible* | Shiftable |
|:----------------------- |:------------------- |:---------------------- |:------------------------- |:------------------- |:-------------- |:--------- |
| `active_power` | ✅ | ⊕ | ✅ | ✅ | ✅ | ✅ |
| `reactive_power` | ✅ | ⊕ | ✅ | ✅ | ✅ | ✅ |
| `conformity` | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ |
| `operation_cost` | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ |
| `rating` | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
| `α`, `β` (voltage exp.) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ |
\* Interruptible = [`InterruptiblePowerLoad`](@ref), [`InterruptibleStandardLoad`](@ref); Shiftable = [`ShiftablePowerLoad`](@ref)
* * *
## Universal Fields (All StaticInjection)
| Field | Present in ALL |
|:------------------ |:-------------- |
| `name` | ✅ |
| `available` | ✅ |
| `bus` | ✅ |
| `base_power` | ✅ |
| `services` | ✅ |
| `dynamic_injector` | ✅ |
| `ext` | ✅ |
| `internal` | ✅ |
* * *
## Operation Cost Types by Device
| Device Category | Cost Type |
|:-------------------------- |:------------------------------------------------------------ |
| [`ThermalGen`](@ref) | [`ThermalGenerationCost`](@ref) or [`MarketBidCost`](@ref) |
| [`HydroGen`](@ref) | [`HydroGenerationCost`](@ref) or [`MarketBidCost`](@ref) |
| [`RenewableGen`](@ref) | [`RenewableGenerationCost`](@ref) or [`MarketBidCost`](@ref) |
| [`ControllableLoad`](@ref) | [`LoadCost`](@ref) or [`MarketBidCost`](@ref) |
| [`Storage`](@ref) | [`StorageCost`](@ref) or [`MarketBidCost`](@ref) |
| [`Source`](@ref) | [`ImportExportCost`](@ref) |
* * *
================================================
FILE: docs/src/api/type_tree.md
================================================
# Type Tree
Here is the complete `PowerSystems.jl` type hierarchy:
```@repl types
using PowerSystems #hide
import TypeTree: tt #hide
docs_dir = joinpath(pkgdir(PowerSystems), "docs", "src", "tutorials", "utils"); #hide
include(joinpath(docs_dir, "docs_utils.jl")); #hide
print(join(tt(PowerSystems.IS.InfrastructureSystemsType), "")) #hide
```
================================================
FILE: docs/src/api/valuecurve_options.md
================================================
# [`ValueCurve` Options](@id curve_table)
Operating cost data typically includes both fixed and variable costs. See the how-to on [Adding an Operating Cost](@ref cost_how_to) for a demonstration of defining an operating cost.
In PowerSystems.jl, the *variable* portion of the operating cost can be represented as linear, quadratic, or piecewise input-output curves; potentially piecewise marginal heat rates; average heat rates; and more, as best fits the input data. This is done by constructing various subtypes of [`ValueCurve`](@ref).
This summary table shows each way to construct a `ValueCurve` with the user-friendly subtype aliases. The `ValueCurve`s make no assumption about units; the example interpretation given here assumes that the variable cost `ValueCurve` will be wrapped in a [`CostCurve`](@ref) with natural units. Note that all four `Piecewise` options here fundamentally represent the same curve. More information and explanatory plots are provided for each subtype alias in the subheadings below.
| Description | Example | Example interpretation |
|:------------------------------------------------------------------------------------------------------------------------- |:-------------------------------------------------------------------- |:------------------------------------------------------------------------------------------------------------------------ |
| Linear input-output curve with *zero* no-load cost (constant average rate) | `LinearCurve(5.0)` | \$5/MWh |
| Linear input-output curve with potentially *nonzero* no-load cost (constant marginal rate) | `LinearCurve(5.0, 15.0)` | \$5/MWh + \$15/hr |
| Quadratic input-output curve with potentially nonzero no-load cost | `QuadraticCurve(1.0, 1.0, 18.0)` | $C(P) = 1 P^2 + 1 P + 18$ where $C$ is \$/hr, $P$ is MW |
| Piecewise linear curve specified by cost values at production points | `PiecewisePointCurve([(1.0, 20.0), (2.0, 24.0), (3.0, 30.0)])` | \$20/hr @ 1 MW, \$24/hr @ 2 MW, \$30/hr @ 3 MW, linear \$/hr interpolation between these points |
| Piecewise linear curve specified by initial value and marginal rates (slopes) between production points | `PiecewiseIncrementalCurve(20.0, [1.0, 2.0, 3.0], [4.0, 6.0])` | \$20/hr @ 1 MW plus additional \$4/MWh from 1 MW to 2 MW plus additional \$6/MWh from 2 MW to 3 MW |
| No-load cost plus piecewise linear curve specified by initial value and marginal rates (slopes) between production points | `PiecewiseIncrementalCurve(18.0, 20.0, [1.0, 2.0, 3.0], [4.0, 6.0])` | \$18/hr no-load cost; \$20/hr @ 1 MW plus additional \$4/MWh from 1 MW to 2 MW plus additional \$6/MWh from 2 MW to 3 MW |
| Piecewise linear curve specified by initial value and average rates between production points | `PiecewiseAverageCurve(20.0, [1.0, 2.0, 3.0], [12.0, 10.0])` | \$20/hr @ 1 MW, \$12/MWh @ 2 MW, \$10/MWh @ 3 MW, linear \$/hr interpolation between these points |
## [`LinearCurve`](@ref)
Specify the marginal cost of production $M$ and optionally the no-load cost $C$, which defaults to zero. Here is a graphical representation:
```@raw html
<img src="../../assets/cost_plot_drawings/LinearCurve.png" width="75%"/>
```
## [`QuadraticCurve`](@ref)
Specify the quadratic ($Q$), proportional ($M$), and constant ($C$) terms of a function that defines the input-output curve:
```@raw html
<img src="../../assets/cost_plot_drawings/QuadraticCurve.png" width="75%"/>
```
## [`PiecewisePointCurve`](@ref)
Specify a vector of $K$ (production, cost) pairs (i.e., $(P_k, C_k)$ for $k = 1, \dots, K$) to define the input-output curve:
```@raw html
<img src="../../assets/cost_plot_drawings/PiecewisePointCurve.png" width="75%"/>
```
## [`PiecewiseIncrementalCurve`](@ref)
Specify the cost $C_1$ at the least production point given (NOT the cost at zero production), a vector of $K$ production points $P_1, \dots, P_k$, and a vector of $K-1$ marginal rates $M_1, \dots, M_{k-1}$, that represent the slopes of the curve segments between the points. $C_1$ may be `nothing`, which results in a not-fully-defined curve. The no-load cost $C_0$ can optionally be specified as a first argument; it is not part of the representation of the curve, just another piece of data that may be stored:
```@raw html
<img src="../../assets/cost_plot_drawings/PiecewiseIncrementalCurve.png" width="75%"/>
```
## [`PiecewiseAverageCurve`](@ref)
Specify the cost $C_1$ at the least production point given (NOT the cost at zero production), a vector of $K$ production points $P_1, \dots, P_k$, and a vector of $K-1$ average rates $R_1, \dots, R_{k-1}$ at the $K-1$ latter production points:
```@raw html
<img src="../../assets/cost_plot_drawings/PiecewiseAverageCurve.png" width="75%"/>
```
================================================
FILE: docs/src/explanation/buses_type_explanation.md
================================================
# [Understanding ACBusTypes](@id bustypes)
`PowerSystems.jl` supports multiple types of AC buses, [listed here](@ref acbustypes_list).
When creating nodal datasets, the definitions for AC Buses can have a significant impact on the
topology logic for the network.
## Voltage Control Types
- `PQ`:
+ **Known:** Real Power Injection ($P$) and Reactive Power Injection ($Q$). These are typically the loads at that bus or fixed power factor generators.
+ **Unknown:** Voltage Magnitude ($|V|$) and Voltage Angle ($\delta$).
+ Represents a bus where the voltage magnitude and angle are free to vary based on the system conditions.
- `PV`:
+ **Known:** Real Power Injection ($P$) and Voltage Magnitude ($|V|$).
+ **Unknown:** Reactive Power Injection ($Q$) and Voltage Angle ($\delta$).
+ Typically represents a bus with an injector connected, where the injector controls the reactive power output and regulates the bus voltage magnitude to a setpoint.
## Reference and Slack Buses
There is a nuanced distinction between a slack bus and a reference bus. In most small test sytems and academic discussions, the system has a single slack bus which is also the reference bus. However, for large interconnected cases or cases with a very radial structure, having a single bus that takes on all the real power mistmatch in the system can lead to erroneous results. In PowerSystems.jl we distinguish the posibility of having slacks and reference buses. Is up to the modeler to decide how to handle the classifications inside of the applications. In other words, wether a reference bus is also a slack or viceversa is left to the application developer.
- `SLACK`:
+ Known: Voltage Magnitude ($|V|$) and Voltage Angle ($\delta$) **when the slack and the reference are the same bus, otherwise is unknown**.
+ Unknown: Real Power ($P$) and Reactive Power ($Q$). These values are calculated as residuals after the power flow solution converges to account for system losses and imbalances and are allocated using participation factors in the model formulation.
+ This kind of bus absorbs or supplies the difference between the total generation and total load plus losses in the system. There can be several slack buses in a system.
- Ref:
+ Known: Voltage Magnitude ($|V|$) and Voltage Angle ($\delta$). Typically, the angle is set to 0 degrees for simplicity, and the voltage is set to a fixed value per unit.0 degrees for simplicity and the voltage is set to a fixed value per unit.
+ Unknown: Real Power ($P$) and Reactive Power ($Q$). These values are calculated as residuals after the power flow solution converges to account for system losses and imbalances when there is a single slack bus that matches the reference bus.
+ Serves as the "reference" for all other bus voltage angles in the AC interconnected system.
For the study of large interconnected areas that include different asynchronous AC networks connected through HVDC, the system can contain multiple reference buses. Since not all modeling efforts require a properly set reference bus, e.g., Zonal Modeling, **PowerSystems.jl does not perform a verification that the system buses are adequately set. This feature is implemented in [`PowerNetworkMatrices.jl`](https://sienna-platform.github.io/PowerNetworkMatrices.jl/stable/).**
## Isolated Buses and the `available` field
In certain modeling applications, particularly power flow modeling tools, the designation of
"isolated" is used to signal that the bus is temporarily disconnected from the network, as are any other components attached to it. However, in `PowerSystems.jl`, a bus and its components can be excluded from an analysis or optimization without changing the underlying network topology by setting the `available` field to false: `set_available!(bus, false)`.
In PowerSystems.jl the `ISOLATED` type means exactly that: The bus is not connected to the network. In
resource analysis where systems contain isolated subsystems that can be ignored for the purposes of the power flow but are relevant when performing optimization, the `ISOLATED` designation provides the capability to describe those situations in precise terms. `ISOLATED` buses can also be made unavailable to make the components attached to them also unavailable.
================================================
FILE: docs/src/explanation/conforming_and_non_conforming_loads.md
================================================
# [Conforming and Non-Conforming Loads](@id conf_loads)
The difference between conforming and non-conforming loads is not particularly significant for how PowerSystems.jl manages data, as loads can be assigned either aggregate or individual time series.
## Definitions and use cases
At its core, the distinction is about forecastability. The De Facto-Criteria and Practical Uses of this distinction comes from CAISO's Energy Imbalance Market (EIM) definitions. This section draws from the [CAISO EIM's "Non-Conforming Load FAQ"](https://www.westerneim.com/Documents/EIM-Non-Conforming-Load-FAQ.pdf) document.
Conforming loads are the typically residential and commercial loads that, in aggregate, follow a predictable daily and seasonal pattern influenced by factors like time of day, day of the week, and weather conditions. This predictability allows modelers to use aggregate forecasts of the total area load with a high degree of accuracy and then desagregate the curve using participation factors.
Non-conforming loads, on the other hand have patterns of consumption that don't follow the aggregate behavior. Their consumption does not follow typical patterns and can fluctuate with different rates as the total system load. These are often large industrial processes with unique operational cycles. For example:
- Electric Arc Furnaces: Used in steel manufacturing, electric arc furnaces cause massive, sudden spikes in power demand when they are in operation. Depending on the time-scale of modeling these loads can require a consumption pattern that mathches the underlying industrial process.
- Large Data Centers: While having a relatively constant base load, the computational demands of large data centers almost never change with the patterns from the rest of the system. These loads tend to be flat and in some advanced models include the behavior of compute load dispatch algorithms that conduct geographic price arbitrage.
- Traction Loads for Railways: The movement of electric trains results in fluctuating power demand along the railway lines based on the transportation demand.
- Pumping Loads: Similarly to tranction loads, pumping loads can change according to water or gas demand and supply needs and not system level behavior. In its data collection manuals, WECC specifies that pumping loads are typically modeled as non-conforming in power flow cases.
## Modeling using PowerSystems.jl
Drawing again from CAISO's EIM procedures, the management of non-conforming loads involves:
1. **Segregated Data Submission**: The historical consumption data for the non-conforming load must be separated from the general, or "conforming," load data. This "cleanses" the historical data used to train weather-based load forecasting models, thereby improving their accuracy for the bulk of the system's load.
2. **Independent Forecasting**: While the system operator forecasts the aggregate conforming load, the entity responsible for the non-conforming load is often required to submit its own forecast or schedule.
3. **Specialized Modeling**: In market and operational models, non-conforming loads are often treated as a type of resource. For instance, in the CAISO market, they are represented as "Dispatchable Demand Response" (DDR) resources, which are essentially modeled as negative generation. This allows their behavior to be explicitly accounted for in market clearing and dispatch instructions.
If a modeler wants to account for the differences in behavior between various loads, they only need to assign a distinct time series to each load. In `PowerSystems.jl`, we keep track of data related to "conformity" for monitoring purposes. This data is defined in the `conformity` field for concrete subtypes of [`StaticLoad`](@ref) and has the [options listed here](@ref loadconform_list). However, the behavioral variations described in the literature are already taken into consideration through the ways modelers can manage these time series assignments.
### See also:
- Parsing [time series](@ref parsing_time_series)
================================================
FILE: docs/src/explanation/dynamic_data.md
================================================
# Dynamic Devices
## Static and Dynamic Data Layers
`PowerSystems.jl` uses two categories to define data for dynamic simulations:
1. [Static](@ref S) components, which includes the data needed to run a power flow problem
2. [Dynamic](@ref D) components are those that define differential equations to run a transient simulation. These dynamic
data are attached to the static components.
Although `PowerSystems.jl` is not constrained to only PSS/e files, commonly the data for a
dynamic simulation comes in a pair of files: One for the static data power flow case (e.g.,
`.raw` file) and a second one with the dynamic components information (e.g., `.dyr` file).
However, `PowerSystems.jl` is able to take any power flow case and specify dynamic
components to it. The two data layers in `PowerSystems.jl` are similar to the data
division between those two files.
### Layer 1: Static Components
The first data layer contains all the information necessary to run a power flow problem:
- Vector of `Bus` elements, that define all the buses in the network.
- Vector of `Branch` elements, that define all the branches elements (that connect two buses) in the network.
- Vector of `StaticInjection` elements, that define all the devices connected to buses that can inject (or withdraw) power. These static devices, typically generators, in `PowerSimulationsDynamics` are used to solve the Power Flow problem that determines the active and reactive power provided for each device.
- Vector of `PowerLoad` elements, that define all the loads connected to buses that can withdraw current. These are also used to solve the Power Flow.
- Vector of `Source` elements, that define source components behind a reactance that can inject or withdraw current.
- The base of power used to define per unit values, in MVA as a `Float64` value.
- The base frequency used in the system, in Hz as a `Float64` value.
### Layer 2: Dynamic Components
The second data layer contains the *additional* information describing the dynamic response
of certain components in the `System`. This data is all attached to components defined in
the static data layer:
- (Optional) Selecting which of the `Lines` (of the `Branch` vector) elements must be modeled of `DynamicLines` elements, that can be used to model lines with differential equations.
- Vector of `DynamicInjection` elements. These components must be attached to a `StaticInjection` that connects the power flow solution to the dynamic formulation of such device.
`DynamicInjection` can be `DynamicGenerator` or `DynamicInverter`, and its specific formulation (i.e. differential equations) will depend on the specific components that define each device (see the sections below). As
a result, it is possible to flexibly define dynamic data models and methods according to
the analysis requirements. [`DynamicInjection`](@ref) components use a parametric
type pattern to materialize the full specification of the dynamic injection model with
parameters. This design enable the use of parametric methods to specify the mathematical
model of the dynamic components separately.
[`DynamicInjection`](@ref) components also implement some additional information useful for
the modeling, like the usual states assumed by the model and the number of states. These values are
derived from the documentation associated with the model, for instance PSS/e models provide
parameters, states and variables. Although `PowerSystems.jl` doesn't assume a specific
mathematical model for the components, the default values for these parameters are derived
directly from the data model source.
## Dynamic Generator Structure
Each generator is a data structure that is defined by the following components:
- [Machine](@ref Machine): That defines the stator electro-magnetic dynamics.
- [Shaft](@ref Shaft): That describes the rotor electro-mechanical dynamics.
- [Automatic Voltage Regulator](@ref AVR): Electromotive dynamics to model an AVR controller.
- [Power System Stabilizer](@ref PSS): Control dynamics to define an stabilization signal for the AVR.
- [Prime Mover and Turbine Governor](@ref TurbineGov): Thermo-mechanical dynamics and associated controllers.
```@raw html
<img src="../../assets/gen_metamodel.png" width="75%"/>
```
## Dynamic Inverter Structure
Each inverter is a data structure that is defined by the following components:
- [DC Source](@ref DCSource): Defines the dynamics of the DC side of the converter.
- [Frequency Estimator](@ref FrequencyEstimator): That describes how the frequency of the grid
can be estimated using the grid voltages. Typically a phase-locked loop (PLL).
- [Outer Loop Control](@ref OuterControl): That describes the active and reactive power
control dynamics.
- [Inner Loop Control](@ref InnerControl): That can describe virtual impedance,
voltage control and current control dynamics.
- [Converter](@ref Converter): That describes the dynamics of the pulse width modulation (PWM)
or space vector modulation (SVM).
- [Filter](@ref Filter): Used to connect the converter output to the grid.
```@raw html
<img src="../../assets/inv_metamodel.png" width="75%"/>
``` ⠀
```
================================================
FILE: docs/src/explanation/per_unit.md
================================================
# [Per-unit Conventions](@id per_unit)
It is often useful to express power systems data in relative terms using per-unit conventions.
`PowerSystems.jl` supports the automatic conversion of data between three different unit systems:
1. `"NATURAL_UNITS"`: The naturally defined units of each parameter (typically MW).
2. `"SYSTEM_BASE"`: Parameter values are divided by the system `base_power`.
3. `"DEVICE_BASE"`: Parameter values are divided by the device `base_power`.
`PowerSystems.jl` supports these unit systems because different power system tools and data
sets use different units systems by convention, such as:
- Dynamics data is often defined in device base
- Network data (e.g., reactance, resistance) is often defined in system base
- Production cost modeling data is often gathered from variety of data sources,
which are typically defined in natural units
These three unit bases allow easy conversion between unit systems.
This allows `PowerSystems.jl` users to input data in the formats they have available,
as well as view data in the unit system that is most intuitive to them.
You can get and set the unit system setting of a `System` with [`get_units_base`](@ref) and
[`set_units_base_system!`](@ref). To support a less stateful style of programming,
`PowerSystems.jl` provides the `Logging.with_logger`-inspired "context manager"-type
function [`with_units_base`](@ref), which sets the unit system to a particular value,
performs some action, then automatically sets the unit system back to its previous value.
Conversion between unit systems does not change
the stored parameter values. Instead, unit system conversions are made when accessing
parameters using the [accessor functions](@ref dot_access), thus making it
imperative to utilize the accessor functions instead of the "dot" accessor methods to
ensure the return of the correct values. The units of the parameter values stored in each
struct are defined in `src/descriptors/power_system_structs.json`.
There are some unit system conventions in `PowerSystems.jl` when defining new components.
Currently, when you define components that aren't attached to a `System`,
you must define all fields in `"DEVICE_BASE"`, except for certain components that don't
have their own `base_power` rating, such as [`Line`](@ref)s, where the `rating` must be
defined in `"SYSTEM_BASE"`.
In the future, `PowerSystems.jl` hopes to support defining components in natural units.
For now, if you want to define data in natural units, you must first
set the system units to `"NATURAL_UNITS"`, define an empty component, and then use the
[accessor functions](@ref dot_access) (e.g., getters and setters), to define each field
within the component. The accessor functions will then do the data conversion from your
input data in natural units (e.g., MW or MVA) to per-unit.
By default, `PowerSystems.jl` uses `"SYSTEM_BASE"` because many optimization problems won't
converge when using natural units. If you change the unit setting, it's suggested that you
switch back to `"SYSTEM_BASE"` before solving an optimization problem (for example in
[`PowerSimulations.jl`](https://sienna-platform.github.io/PowerSimulations.jl/stable/)).
!!! note
Check the [`Transformers per unit explanation`](@ref transformers_pu) for details on how
the per-unit is managed
================================================
FILE: docs/src/explanation/plant_attributes.md
================================================
# [Plant Attributes](@id plant_attributes)
## The Unit vs. Plant Aggregation Problem
In power systems modeling, there is a fundamental tension between different levels of aggregation.
Real-world power plants often consist of multiple generating units that share physical infrastructure,
but data sources and modeling requirements vary in how they represent this relationship:
- **Unit-level data**: Individual generators with their own capacity, cost curves, and operational constraints
- **Plant-level data**: Aggregated capacity and characteristics representing an entire facility
For interoperable analysis across different tools and datasets, it is often necessary to track
**both** the plant and the individual units within it. This is particularly important when:
1. **Data integration**: Combining datasets that use different aggregation levels
2. **Shared infrastructure constraints**: Units on the same shaft, penstock, or point of common coupling
have operational dependencies that must be modeled together
3. **Market operations**: ISOs may require unit-level bidding while planning studies use plant-level data
4. **Regulatory reporting**: Different reports require different aggregation levels
PowerSystems.jl addresses this challenge through **Plant Attributes**, which are
[`SupplementalAttribute`](@ref supplemental_attributes) types that group individual generator
components into logical plant structures while preserving the detailed unit-level information.
## Plant Attribute Types
PowerSystems.jl provides five specialized plant attribute types, each designed for a specific
generation technology:
```mermaid
classDiagram
SupplementalAttribute <|-- PowerPlant
PowerPlant <|-- ThermalPowerPlant
PowerPlant <|-- CombinedCycleBlock
PowerPlant <|-- CombinedCycleFractional
PowerPlant <|-- HydroPowerPlant
PowerPlant <|-- RenewablePowerPlant
```
### ThermalPowerPlant
Represents conventional thermal power plants with synchronous generators. Multiple units can
share a common **shaft**, which is relevant for modeling mechanical coupling constraints.
| Field | Type | Description |
|:------------------- |:------------------------- |:---------------------------------------------- |
| `name` | `String` | Name of the power plant |
| `shaft_map` | `Dict{Int, Vector{UUID}}` | Mapping of shaft numbers to unit UUIDs |
| `reverse_shaft_map` | `Dict{UUID, Int}` | Reverse mapping from unit UUID to shaft number |
### CombinedCycleBlock
Represents combined cycle plants using a block configuration. Models the relationship between
combustion turbines (CTs) and steam turbines through the Heat Recovery Steam Generator (HRSG).
| Field | Type | Description |
|:------------------------------- |:---------------------------- |:-------------------------------------------- |
| `name` | `String` | Name of the combined cycle block |
| `configuration` | `CombinedCycleConfiguration` | Configuration type (see below) |
| `heat_recovery_to_steam_factor` | `Float64` | Factor for heat recovery to steam conversion |
| `hrsg_ct_map` | `Dict{Int, Vector{UUID}}` | HRSG to CT unit mappings (inputs) |
| `hrsg_ca_map` | `Dict{Int, Vector{UUID}}` | HRSG to CA unit mappings (outputs) |
| `ct_hrsg_map` | `Dict{UUID, Vector{Int}}` | Reverse CT to HRSG mapping |
| `ca_hrsg_map` | `Dict{UUID, Vector{Int}}` | Reverse CA to HRSG mapping |
The `CombinedCycleConfiguration` enum describes the plant layout. Combined cycle plants are
typically described using a "CTs x STs" notation (e.g., 2x1 means two combustion turbines
feeding one steam turbine through a Heat Recovery Steam Generator). However, the EIA
[prime mover codes](@ref pm_list) employ CT and CA to distinguish between the combustion
turbine units and the steam portion of the combined cycle respectively.
```@raw html
<figure>
<img src="https://www.eia.gov/todayinenergy/images/2022.04.25/main.svg" alt="Combined cycle configurations" style="max-width: 100%;"/>
<figcaption>Combined cycle power plant configurations. Source: <a href="https://www.eia.gov/todayinenergy/detail.php?id=52158">U.S. Energy Information Administration</a></figcaption>
</figure>
```
| Value | Configuration | Description |
|:------------------------------ |:------------------ |:---------------------------------------- |
| `SingleShaftCombustionSteam` | 1x1 (single shaft) | Single CT + single ST on one shaft |
| `SeparateShaftCombustionSteam` | 1x1 (multi-shaft) | Single CT + single ST on separate shafts |
| `DoubleCombustionOneSteam` | 2x1 | Two CTs feeding one ST via HRSG |
| `TripleCombustionOneSteam` | 3x1 | Three CTs feeding one ST via HRSG |
| `Other` | Various | Other configurations (e.g., 4x1, 2x2) |
For more information on combined cycle configurations, see the
[U.S. Energy Information Administration article on combined-cycle plants](https://www.eia.gov/todayinenergy/detail.php?id=52158).
### CombinedCycleFractional
Represents combined cycle generation when each unit represents a specific configuration with
an aggregate heat rate. Unlike [`CombinedCycleBlock`](@ref), which models the CT/CA relationship
through the HRSG, the fractional representation uses **operation exclusion groups** to define
which units can operate simultaneously. Only generators with the `CC` (combined cycle)
[prime mover type](@ref pm_list) can be added.
| Field | Type | Description |
|:--------------------------------- |:---------------------------- |:-------------------------------------------------------- |
| `name` | `String` | Name of the combined cycle fractional plant |
| `configuration` | `CombinedCycleConfiguration` | Configuration type (see table above) |
| `operation_exclusion_map` | `Dict{Int, Vector{UUID}}` | Mapping of exclusion group numbers to unit UUIDs |
| `inverse_operation_exclusion_map` | `Dict{UUID, Int}` | Reverse mapping from unit UUID to exclusion group number |
### HydroPowerPlant
Represents hydroelectric plants where multiple turbines may share a common **penstock**
(the pipe that delivers water to the turbines). Shared penstocks create operational
dependencies between units.
| Field | Type | Description |
|:---------------------- |:------------------------- |:------------------------------------------------- |
| `name` | `String` | Name of the hydro power plant |
| `penstock_map` | `Dict{Int, Vector{UUID}}` | Mapping of penstock numbers to unit UUIDs |
| `reverse_penstock_map` | `Dict{UUID, Int}` | Reverse mapping from unit UUID to penstock number |
### RenewablePowerPlant
Represents renewable energy plants (wind farms, solar farms) where multiple generators or
storage devices connect through a common **Point of Common Coupling (PCC)** to the grid.
| Field | Type | Description |
|:----------------- |:------------------------- |:-------------------------------------------- |
| `name` | `String` | Name of the renewable power plant |
| `pcc_map` | `Dict{Int, Vector{UUID}}` | Mapping of PCC numbers to unit UUIDs |
| `reverse_pcc_map` | `Dict{UUID, Int}` | Reverse mapping from unit UUID to PCC number |
## Creating Plant Attributes
### Basic Construction
All plant attributes can be created with just a name; the infrastructure mappings are populated
when units are added:
```julia
# Create empty plant attributes
thermal_plant = ThermalPowerPlant(; name = "Coal Plant A")
hydro_plant = HydroPowerPlant(; name = "Dam Complex")
renewable_plant = RenewablePowerPlant(; name = "Wind Farm North")
cc_block = CombinedCycleBlock(;
name = "CC Unit 1",
configuration = CombinedCycleConfiguration.DoubleCombustionOneSteam,
)
cc_fractional = CombinedCycleFractional(;
name = "CC Fractional 1",
configuration = CombinedCycleConfiguration.DoubleCombustionOneSteam,
)
```
### Adding Units to Plants
Units are added to plants using [`add_supplemental_attribute!`](@ref), which requires
specifying the infrastructure number (shaft, penstock, PCC, or HRSG):
```julia
# Add thermal generators to a plant (shaft_number is required)
add_supplemental_attribute!(sys, gen1, thermal_plant; shaft_number = 1)
add_supplemental_attribute!(sys, gen2, thermal_plant; shaft_number = 1) # Same shaft
add_supplemental_attribute!(sys, gen3, thermal_plant; shaft_number = 2) # Different shaft
# Add hydro turbines to a plant (penstock_number is required)
add_supplemental_attribute!(sys, turbine1, hydro_plant, 1) # Penstock 1
add_supplemental_attribute!(sys, turbine2, hydro_plant, 1) # Same penstock
add_supplemental_attribute!(sys, turbine3, hydro_plant, 2) # Penstock 2
# Add renewable generators to a plant (pcc_number is required)
add_supplemental_attribute!(sys, wind_gen1, renewable_plant, 1) # PCC 1
add_supplemental_attribute!(sys, battery, renewable_plant, 1) # Same PCC
# Add CT and CA units to combined cycle block (hrsg_number is required)
# Note: Only CT (combustion turbine) and CA (combined cycle steam part) prime movers are allowed
add_supplemental_attribute!(sys, ct_unit, cc_block; hrsg_number = 1)
add_supplemental_attribute!(sys, steam_unit, cc_block; hrsg_number = 1)
# Add CC units to combined cycle fractional (exclusion_group is required)
# Note: Only CC (combined cycle) prime mover type is allowed
add_supplemental_attribute!(sys, cc_config1, cc_fractional; exclusion_group = 1)
add_supplemental_attribute!(sys, cc_config2, cc_fractional; exclusion_group = 1)
add_supplemental_attribute!(sys, cc_config3, cc_fractional; exclusion_group = 2)
```
## Querying Plant Information
### Getting All Units in a Plant
Use [`get_associated_components`](@ref) to retrieve all units associated with a plant:
```julia
# Get all generators in a thermal plant
for gen in get_associated_components(sys, thermal_plant; component_type = ThermalGen)
@show get_name(gen)
end
```
### Getting Units by Infrastructure
Query units connected to specific infrastructure elements:
```julia
# Get all generators on shaft 1
gens_on_shaft_1 = get_components_in_shaft(sys, thermal_plant, 1)
# Get all turbines on penstock 2
turbines_on_penstock_2 = get_components_in_penstock(sys, hydro_plant, 2)
# Get all generators/storage at PCC 1
components_at_pcc_1 = get_components_in_pcc(sys, renewable_plant, 1)
# Get all generators in exclusion group 1
gens_in_group_1 = get_components_in_exclusion_group(sys, cc_fractional, 1)
```
### Accessing Infrastructure Maps
Direct access to the mapping dictionaries is available through accessor functions:
```julia
# ThermalPowerPlant
shaft_map = get_shaft_map(thermal_plant) # Dict{Int, Vector{UUID}}
reverse_map = get_reverse_shaft_map(thermal_plant) # Dict{UUID, Int}
# HydroPowerPlant
penstock_map = get_penstock_map(hydro_plant)
reverse_map = get_reverse_penstock_map(hydro_plant)
# RenewablePowerPlant
pcc_map = get_pcc_map(renewable_plant)
reverse_map = get_reverse_pcc_map(renewable_plant)
# CombinedCycleBlock
ct_map = get_hrsg_ct_map(cc_block) # HRSG -> CTs
ca_map = get_hrsg_ca_map(cc_block) # HRSG -> CAs
config = get_configuration(cc_block) # CombinedCycleConfiguration
factor = get_heat_recovery_to_steam_factor(cc_block)
# CombinedCycleFractional
exclusion_map = get_operation_exclusion_map(cc_fractional)
inverse_map = get_inverse_operation_exclusion_map(cc_fractional)
config = get_configuration(cc_fractional) # CombinedCycleConfiguration
```
## Removing Units from Plants
Units can be removed from plants while preserving both the unit and the plant:
```julia
remove_supplemental_attribute!(sys, gen1, thermal_plant)
remove_supplemental_attribute!(sys, turbine1, hydro_plant)
remove_supplemental_attribute!(sys, wind_gen1, renewable_plant)
remove_supplemental_attribute!(sys, ct_unit, cc_block)
remove_supplemental_attribute!(sys, cc_config1, cc_fractional)
```
## Complete Example
Here is a complete example demonstrating the workflow for a thermal power plant:
```julia
using PowerSystems
# Create a system with thermal generators
sys = System(100.0) # 100 MVA base
bus = ACBus(;
number = 1,
name = "Bus1",
bustype = ACBusTypes.REF,
angle = 0.0,
magnitude = 1.0,
voltage_limits = (min = 0.9, max = 1.1),
base_voltage = 230.0,
)
add_component!(sys, bus)
# Create three thermal units
gen1 = ThermalStandard(;
name = "Unit1",
available = true,
status = true,
bus = bus,
active_power = 100.0,
reactive_power = 0.0,
rating = 120.0,
active_power_limits = (min = 30.0, max = 100.0),
reactive_power_limits = (min = -50.0, max = 50.0),
ramp_limits = nothing,
operation_cost = ThermalGenerationCost(nothing),
base_power = 100.0,
time_limits = nothing,
prime_mover_type = PrimeMovers.ST,
fuel = ThermalFuels.COAL,
)
gen2 = ThermalStandard(;
name = "Unit2",
available = true,
status = true,
bus = bus,
active_power = 100.0,
reactive_power = 0.0,
rating = 120.0,
active_power_limits = (min = 30.0, max = 100.0),
reactive_power_limits = (min = -50.0, max = 50.0),
ramp_limits = nothing,
operation_cost = ThermalGenerationCost(nothing),
base_power = 100.0,
time_limits = nothing,
prime_mover_type = PrimeMovers.ST,
fuel = ThermalFuels.COAL,
)
gen3 = ThermalStandard(;
name = "Unit3",
available = true,
status = true,
bus = bus,
active_power = 50.0,
reactive_power = 0.0,
rating = 60.0,
active_power_limits = (min = 15.0, max = 50.0),
reactive_power_limits = (min = -25.0, max = 25.0),
ramp_limits = nothing,
operation_cost = ThermalGenerationCost(nothing),
base_power = 50.0,
time_limits = nothing,
prime_mover_type = PrimeMovers.ST,
fuel = ThermalFuels.COAL,
)
add_component!(sys, gen1)
add_component!(sys, gen2)
add_component!(sys, gen3)
# Create a plant attribute
plant = ThermalPowerPlant(; name = "Coal Plant Alpha")
# Add the plant to the system (optional, for serialization)
add_supplemental_attribute!(sys, plant)
# Associate generators with the plant
# Units 1 and 2 share shaft 1, Unit 3 is on shaft 2
add_supplemental_attribute!(sys, gen1, plant; shaft_number = 1)
add_supplemental_attribute!(sys, gen2, plant; shaft_number = 1)
add_supplemental_attribute!(sys, gen3, plant; shaft_number = 2)
# Query generators on shaft 1
shaft_1_gens = get_components_in_shaft(sys, plant, 1)
println("Generators on Shaft 1:")
for gen in shaft_1_gens
println(" - $(get_name(gen)): $(get_active_power_limits(gen).max) MW")
end
# Get total plant capacity
all_gens = collect(get_associated_components(sys, plant; component_type = ThermalGen))
total_capacity = sum(get_active_power_limits(g).max for g in all_gens)
println("Total plant capacity: $total_capacity MW")
```
## Supported Component Types
Each plant attribute type supports specific component types:
| Plant Type | Supported Components |
|:------------------------- |:-------------------------------------------------------- |
| `ThermalPowerPlant` | `ThermalGen` (all subtypes) |
| `CombinedCycleBlock` | `ThermalGen` with `CT` or `CA` prime mover only |
| `CombinedCycleFractional` | `ThermalGen` with `CC` prime mover only |
| `HydroPowerPlant` | `HydroTurbine`, `HydroPumpTurbine` (not `HydroDispatch`) |
| `RenewablePowerPlant` | `RenewableGen`, `EnergyReservoirStorage` |
## Serialization
Plant attributes are fully serializable with the system. The infrastructure mappings (UUIDs)
are preserved during JSON serialization and correctly restored on deserialization, maintaining
the plant-unit relationships across save/load cycles.
## See Also
- [`SupplementalAttribute`](@ref supplemental_attributes) - Base concept for supplemental data
- [`ThermalPowerPlant`](@ref) - API reference
- [`CombinedCycleBlock`](@ref) - API reference
- [`CombinedCycleFractional`](@ref) - API reference
- [`HydroPowerPlant`](@ref) - API reference
- [`RenewablePowerPlant`](@ref) - API reference
================================================
FILE: docs/src/explanation/power_concepts.md
================================================
# [Power Concepts: Base Power, Rating, and Max Active Power](@id power_concepts)
When working with generators in PowerSystems.jl, it's important to understand the distinction between three key power concepts: base power, rating, and maximum active power. These concepts serve different purposes and are stored using different unit conventions.
## Base Power
**Base power** is the reference power value used for per-unitization of a specific device.
- **Purpose**: Serves as the denominator when converting device parameters to per-unit values
- **Units**: Always stored in **natural units** (MVA)
- **Typical value**: The nameplate capacity of the device
- **Access**: Retrieved using `get_base_power(device)`
Base power is a fundamental parameter for the per-unit system and represents the natural scale of the device. For more details on per-unitization, see the [Per-unit Conventions](@ref per_unit) page.
## Rating
**Rating** represents the maximum AC side output power rating of the synchronous machine or generator.
- **Purpose**: Defines the maximum apparent power (MVA) that the generator's electrical components can safely handle
- **Units**: Stored in per-unit using **device base** (i.e., divided by the device's `base_power`)
- **Physical meaning**: The maximum MVA output considering electrical constraints such as:
+ Stator winding thermal limits
+ Rotor field winding limits
+ Cooling system capacity
- **Access**: Retrieved using `get_rating(device)`
The rating is typically determined by the electrical design and thermal limits of the synchronous machine itself. It represents the maximum capability of the electrical generator, independent of the prime mover.
## Maximum Active Power
**Maximum active power** represents the maximum real power output of the prime mover.
- **Purpose**: Defines the maximum real power (MW) that the prime mover can deliver
- **Units**: Stored in per-unit using **device base** (i.e., divided by the device's `base_power`)
- **Physical meaning**: The maximum MW output considering prime mover constraints such as:
+ Turbine capacity (for steam, gas, or hydro turbines)
+ Combustion chamber limits (for gas turbines)
+ Boiler capacity (for steam generators)
+ Fuel flow limitations
- **Access**: Retrieved using `get_max_active_power(device)`
The maximum active power is determined by the mechanical system that drives the generator. This is often less than the rating when considering only real power production.
## Key Distinctions
### Storage Convention Summary
| Concept | Storage Units | Accessor Function |
|:---------------- |:------------------- |:------------------------ |
| Base Power | Natural units (MVA) | `get_base_power()` |
| Rating | Device base (p.u.) | `get_rating()` |
| Max Active Power | Device base (p.u.) | `get_max_active_power()` |
### Physical Interpretation
The relationship between these three quantities can be understood as follows:
- **Base Power**: "What is the natural scale of this device?"
- **Rating**: "What is the maximum apparent power the electrical generator can produce?"
- **Max Active Power**: "What is the maximum real power the prime mover can deliver?"
### Example
Consider a thermal generator with:
- `base_power = 100.0` MVA (stored in natural units)
- `rating = 1.0` p.u. (equals 100 MVA when converted to natural units)
- `max_active_power = 0.95` p.u. (equals 95 MW when converted to natural units)
In this example:
- The generator's electrical components can handle up to 100 MVA
- The prime mover (e.g., steam turbine) can deliver up to 95 MW of real power
- The difference accounts for the fact that the turbine's mechanical power limit is slightly below the generator's electrical rating
### Unit System Conversions
When you access these values through the PowerSystems.jl accessor functions, they are automatically converted based on the current unit system setting:
```julia
# Assuming base_power = 100 MVA, rating = 1.0 p.u., max_active_power = 0.95 p.u.
sys = System(100.0) # System base power = 100 MVA
gen = get_component(ThermalStandard, sys, "gen1")
# In DEVICE_BASE
set_units_base_system!(sys, "DEVICE_BASE")
get_base_power(gen) # Returns: 100.0 MVA (always natural units)
get_rating(gen) # Returns: 1.0 p.u. (on device base)
get_max_active_power(gen) # Returns: 0.95 p.u. (on device base)
# In NATURAL_UNITS
set_units_base_system!(sys, "NATURAL_UNITS")
get_base_power(gen) # Returns: 100.0 MVA (always natural units)
get_rating(gen) # Returns: 100.0 MVA (converted from p.u.)
get_max_active_power(gen) # Returns: 95.0 MW (converted from p.u.)
# In SYSTEM_BASE
set_units_base_system!(sys, "SYSTEM_BASE")
get_base_power(gen) # Returns: 100.0 MVA (always natural units)
get_rating(gen) # Returns: 1.0 p.u. (on system base, assuming system base = device base)
get_max_active_power(gen) # Returns: 0.95 p.u. (on system base)
```
!!! note
Base power is **always** returned in natural units (MVA) regardless of the unit system setting. The rating and maximum active power are stored in device base but are automatically converted when accessed based on the current unit system setting.
## See Also
- [Per-unit Conventions](@ref per_unit) - Detailed explanation of unit systems in PowerSystems.jl
- [`ThermalStandard`](@ref) - Generator type with these power parameters
- [`get_units_base`](@ref) and [`set_units_base_system!`](@ref) - Functions for managing unit systems
================================================
FILE: docs/src/explanation/supplemental_attributes.md
================================================
# [Supplemental Attributes](@id supplemental_attributes)
While the [`ext` field is a mechanism](@ref additional_fields) for adding arbitrary metadata. PowerSystems.jl, has moved towards a more structured and formalized way of handling supplemental data using `SupplementalAttribute` structs. This is designed to store metadata in a more organized fashion than a generic dictionary. These attributes are intended to be attached to a [`Component`](@ref) types.
Supplemmental attributes can be shared between components or have 1-1 relationships. This is particularly
useful to represent components in the same geographic location or outages for multiple components. Conversely, components can contain many attributes.
```mermaid
flowchart LR
A["Attribute A"] --> B["Component 1"]
A --> C["Component2"]
D["Attribute B"] --> C["Component 2"]
E["Attribute C"] --> F["Component 3"]
```
Supplemental attributes can also contain timeseries in the same fashion that a component can allowing the user to model time varying attributes like outage time series or weather dependent probabilities. See the section [`Working with Time Series Data`](@ref tutorial_time_series) for details on time series handling.
## Getting the attributes in a system
You can retrieve the attributes in a system using the function [`get_supplemental_attributes`](@ref).
You must pass a supplemental attribute type, which can be concrete or abstract. If you pass an abstract type, all concrete types
that are subtypes of the abstract type will be returned.
```julia
for outage in get_supplemental_attributes(FixedForcedOutage, system)
@show summary(outage)
end
```
You can optionally pass a filter function to reduce the returned attributes. This example will
return only FixedForcedOutage instances that have a mean time to recovery greater than or equal to 0.5.
```julia
for outage in get_supplemental_attributes(
x -> get_mean_time_to_recovery(x) >= 0.5,
FixedForcedOutage,
system,
)
@show summary(outage)
end
```
## Getting the attributes associated with a component
You can retrieve the attributes associated with a component using the function [`get_supplemental_attributes`](@ref).
This method signatures are identical to the versions above that operate on a system; just swap the system for a component.
You must pass a supplemental attribute type, which can be concrete or abstract. If you pass an abstract type, all concrete types
that are subtypes of the abstract type will be returned.
```julia
gen1 = get_component(ThermalStandard, system, "gen1")
for outage in get_supplemental_attributes(FixedForcedOutage, gen)
@show summary(outage)
end
```
You can optionally pass a filter function to reduce the returned attributes. This example will
return only FixedForcedOutage instances that have a mean time to recovery greater than or equal to 0.5.
```julia
for outage in get_supplemental_attributes(
x -> get_mean_time_to_recovery(x) >= 0.5,
gen,
FixedForcedOutage,
)
@show summary(outage)
end
```
## Getting the attributes associated with a component type
You can retrieve the attributes associated with any component of a given type
using the function [`get_associated_supplemental_attributes`](@ref). If one attribute is attached to
multiple components of the given type, it will still only appear once in the result.
1. Get all the attributes associated with all components of a given type.
```julia
for outage in get_associated_supplemental_attributes(system, ThermalStandard)
@show summary(outage)
end
```
2. Same as #1, but filter the results by attribute type, which can be concrete or abstract.
```julia
for outage in
get_associated_supplemental_attributes(
system,
ThermalStandard;
attribute_type = FixedForcedOutage,
)
@show summary(outage)
end
```
## Getting the components associated with an attribute
You can retrieve the components associated with a single supplemental attribute using the
function [`get_associated_components`](@ref).
1. Get all components associated with a single supplemental attribute.
```julia
outage = first(get_supplemental_attributes(FixedForcedOutage, system))
for component in get_associated_components(system, outage)
@show summary(component)
end
```
2. Same as #1, but filter the results by component type, which can be concrete or abstract.
```julia
outage = first(get_supplemental_attributes(FixedForcedOutage, system))
for component in get_associated_components(system, outage; component_type = ThermalStandard)
@show summary(component)
end
```
## Getting the components associated with an attribute type
You can retrieve the components associated with any supplemental attribute of a given type
using the function [`get_associated_components`](@ref).
1. Get all components associated with any supplemental attribute of a given type.
```julia
for component in get_associated_components(system, FixedForcedOutage)
@show summary(component)
end
```
2. Same as #1, but filter the results by component type, which can be concrete or abstract.
```julia
for component in
get_associated_components(system, FixedForcedOutage; component_type = ThermalStandard)
@show summary(component)
end
```
## Getting component / supplemental attribute pairs
The function [`get_component_supplemental_attribute_pairs`](@ref) returns a vector of component / supplemental
attribute pairs based on types and optional filters. This can be more efficient than double for loops
that iterate over components and their associated attributes independently.
```julia
for (gen, outage) in get_component_supplemental_attribute_pairs(
ThermalStandard,
FixedForcedOutage,
system,
)
@show summary(gen) summary(outage)
end
```
## Adding Time Series to an attribute
## Existing Supplemental Attributes in PowerSystems
- [`GeographicInfo`](@ref)
- [`ImpedanceCorrectionData`](@ref)
### Contingency Attributes
- [`FixedForcedOutage`](@ref)
- [`GeometricDistributionForcedOutage`](@ref)
- [`PlannedOutage`](@ref)
### Plant Attributes
Plant attributes are a specialized category of supplemental attributes for grouping individual
generator units into logical plant structures. See [Plant Attributes](@ref plant_attributes)
for detailed documentation.
- [`ThermalPowerPlant`](@ref) - Thermal plants with shared shafts
- [`CombinedCycleBlock`](@ref) - Combined cycle plants with HRSG configurations
- [`CombinedCycleFractional`](@ref) - Combined cycle plants with aggregate heat rate and exclusion groups
- [`HydroPowerPlant`](@ref) - Hydro plants with shared penstocks
- [`RenewablePowerPlant`](@ref) - Renewable plants with shared PCCs
================================================
FILE: docs/src/explanation/system.md
================================================
# [System](@id system_doc)
The `System` is the main container of components and the time series data references.
`PowerSystems.jl` uses a hybrid approach to data storage, where the component data and time
series references are stored in volatile memory while the actual time series data is stored
in an HDF5 file. This design loads into memory the portions of the data that are relevant
at time of the query, and so avoids overwhelming the memory resources.
```@raw html
<img src="../../assets/System.png" width="50%"/>
```
## Accessing components stored in the `System`
`PowerSystems.jl` implements a wide variety of methods to search for components to
aid in data manipulation. Most of these use the [Type Structure](@ref type_structure) to
retrieve all components of a certain `Type`.
For example, the most common search function is [`get_components`](@ref), which
takes a desired device `Type` (concrete or abstract) and retrieves all components in that
category from the `System`. It also accepts filter functions for a more
refined search.
Given the potential size of the return,
`PowerSystems.jl` returns Julia iterators in order to avoid unnecessary memory allocations.
The container is optimized for iteration over abstract or concrete component
types as described by the [Type Structure](@ref type_structure).
## [Accessing data stored in a component](@id dot_access)
__Using the "dot" access to get a parameter value from a component is actively discouraged, use "getter" functions instead__
Using code autogeneration, `PowerSystems.jl` implements accessor (or "getter") functions to
enable the retrieval of parameters defined in the component struct fields. Julia syntax enables
access to this data using the "dot" access (e.g. `component.field`), however
_this is actively discouraged_ for two reasons:
1. We make no guarantees on the stability of component structure definitions. We will maintain version stability on the accessor methods.
2. Per-unit conversions are made in the return of data from the accessor functions. (see the [per-unit section](@ref per_unit) for more details)
## [Using subsystems](@id subsystems)
For certain applications, such as those that employ dispatch coordination methods or decomposition approaches, it is useful to be able to split components into subsystems based upon user-defined criteria. The `System` provides `subsystem` containers for this purpose. Each subsystem is defined by a name and can hold references to any number of components.
The following commands demonstrate how to create subsystems and add components.
```@repl subsystem
using PowerSystems;
using PowerSystemCaseBuilder;
sys = build_system(PSISystems, "c_sys5_pjm")
add_subsystem!(sys, "1")
add_subsystem!(sys, "2")
```
Devices in the system can be assigned to the subsystems in the following way using the function [`add_component_to_subsystem!`](@ref)
```@repl subsystem
g = get_component(ThermalStandard, sys, "Alta")
add_component_to_subsystem!(sys, "1", g)
g = get_component(ThermalStandard, sys, "Sundance")
add_component_to_subsystem!(sys, "2", g)
```
To retrieve components assigned to a specific subsystem, add the `subsystem_name` keyword argument to `get_components`.
```@repl subsystem
gens_1 = get_components(ThermalStandard, sys; subsystem_name = "1")
get_name.(gens_1)
gens_2 = get_components(ThermalStandard, sys; subsystem_name = "2")
get_name.(gens_2)
```
One useful feature that requires care when used is generating a new [`System`](@ref) from a `subsystem` assignment.
The function [`from_subsystem`](@ref) will allow the user to produce a new [`System`](@ref) that can be used or exported.
This functionality requires careful subsystem assignemnt of the devices and its dependencies. Following from the example in this document, you can export a system as follows:
```@repl subsystem
from_subsystem(sys, "1")
```
!!! warning
The system is invalid because the bus connected to the Alta generator is not part of the subsystem. We can add it, and then run [`from_subsystem`](@ref) again
```@repl subsystem
g = get_component(ThermalStandard, sys, "Alta")
b = get_bus(g)
add_component_to_subsystem!(sys, "1", b)
from_subsystem(sys, "1")
```
Advanced users can use the keyword `runchecks=false` and avoid any topological check in the process.
It is highly recommended that users only do this if they clearly understand how to validate the resulting system before using it for modeling.
================================================
FILE: docs/src/explanation/time_series.md
================================================
# [Time Series Data](@id ts_data)
## Categories of Time Series
The bulk of the data in many power system models is time series data. Given the potential
complexity, `PowerSystems.jl` has a set of definitions to organize this data and
enable consistent modeling.
`PowerSystems.jl` supports two categories of time series data depending on the
process to obtain the data and its interpretation:
- [Static Time Series Data](@ref)
- [Forecasts](@ref)
These categories are are all subtypes of `TimeSeriesData` and fall within this time series
type hierarchy:
```@repl
using PowerSystems #hide
import TypeTree: tt #hide
docs_dir = joinpath(pkgdir(PowerSystems), "docs", "src", "tutorials", "utils"); #hide
include(joinpath(docs_dir, "docs_utils.jl")); #hide
print(join(tt(TimeSeriesData), "")) #hide
```
### Static Time Series Data
A static time series data is a single column of data where each time period has a single
value assigned to a component field, such as its maximum active power. This data commonly
is obtained f
gitextract_d2nxsq6e/
├── .claude/
│ ├── Sienna.md
│ └── claude.md
├── .devcontainer/
│ └── devcontainer.json
├── .editorconfig
├── .github/
│ ├── copilot-setup-steps.yml
│ ├── pull_request_template.md
│ └── workflows/
│ ├── TagBot.yml
│ ├── cross-package-test.yml
│ ├── doc-preview-cleanup.yml
│ ├── docs.yml
│ ├── fix-docs-on-failure.yml
│ ├── format-check.yml
│ ├── main-tests.yml
│ └── pr_testing.yml
├── .gitignore
├── .pre-commit-config.yaml
├── CHANGELOG.md
├── CITATION.cff
├── CONTRIBUTING.md
├── LICENSE
├── Project.toml
├── README.md
├── codecov.yml
├── docs/
│ ├── Makefile
│ ├── Project.toml
│ ├── make.jl
│ ├── make_model_library.jl
│ ├── make_tutorials.jl
│ └── src/
│ ├── api/
│ │ ├── citation.md
│ │ ├── developer_guidelines.md
│ │ ├── enumerated_types.md
│ │ ├── glossary.md
│ │ ├── internal.md
│ │ ├── psse_models.md
│ │ ├── public.md
│ │ ├── static_injection_subtypes.md
│ │ ├── type_tree.md
│ │ └── valuecurve_options.md
│ ├── explanation/
│ │ ├── buses_type_explanation.md
│ │ ├── conforming_and_non_conforming_loads.md
│ │ ├── dynamic_data.md
│ │ ├── per_unit.md
│ │ ├── plant_attributes.md
│ │ ├── power_concepts.md
│ │ ├── supplemental_attributes.md
│ │ ├── system.md
│ │ ├── time_series.md
│ │ ├── transformer_per_unit_models.md
│ │ └── type_structure.md
│ ├── generate_input_config_table.jl
│ ├── generate_validation_table.jl
│ ├── how_to/
│ │ ├── add_component_natural_units.md
│ │ ├── add_cost_curve.md
│ │ ├── add_fuel_curve_timeseries.md
│ │ ├── add_new_types.md
│ │ ├── adding_additional_fields.md
│ │ ├── build_system_with_files.md
│ │ ├── create_hydro_datasets.md
│ │ ├── create_system_with_source_import_export_cost.md
│ │ ├── handle_3W_transformers.md
│ │ ├── improve_ts_performance.md
│ │ ├── jump.md
│ │ ├── market_bid_cost.md
│ │ ├── migrating_to_psy5.md
│ │ ├── parse_dynamic_data.md
│ │ ├── parse_matpower_psse.md
│ │ ├── parse_ts_from_csvs.md
│ │ ├── reduce_repl_printing.md
│ │ ├── serialize_data.md
│ │ └── use_context_managers.md
│ ├── index.md
│ ├── model_library/
│ │ ├── dynamic_branch.md
│ │ ├── dynamic_generator.md
│ │ ├── dynamic_inverter.md
│ │ ├── hybrid_system.md
│ │ ├── hydro_generation_cost.md
│ │ ├── hydro_reservoir.md
│ │ ├── hydro_reservoir_cost.md
│ │ ├── import_export_cost.md
│ │ ├── load_cost.md
│ │ ├── market_bid_cost.md
│ │ ├── offer_curve_cost.md
│ │ ├── outer_control.md
│ │ ├── renewable_generation_cost.md
│ │ ├── reserves.md
│ │ ├── storage_cost.md
│ │ └── thermal_generation_cost.md
│ └── tutorials/
│ ├── add_dynamic_data.jl
│ ├── creating_system.jl
│ ├── manipulating_datasets.jl
│ ├── tutorials_data/
│ │ ├── RTS-GMLC.RAW
│ │ ├── RTS_GMLC.m
│ │ ├── TestGENCLS.dyr
│ │ ├── case5.m
│ │ └── case5_re.m
│ ├── utils/
│ │ └── docs_utils.jl
│ └── working_with_time_series.jl
├── scripts/
│ ├── formatter/
│ │ ├── Project.toml
│ │ └── formatter_code.jl
│ ├── generate_config_file.py
│ └── generate_validation_config_file.py
├── src/
│ ├── PowerSystems.jl
│ ├── base.jl
│ ├── component_selector.jl
│ ├── component_selector_interface.jl
│ ├── contingencies.jl
│ ├── data_format_conversions.jl
│ ├── definitions.jl
│ ├── deprecated.jl
│ ├── descriptors/
│ │ ├── power_system_inputs.json
│ │ └── power_system_structs.json
│ ├── get_components_interface.jl
│ ├── impedance_correction.jl
│ ├── models/
│ │ ├── HybridSystem.jl
│ │ ├── OuterControl.jl
│ │ ├── RoundRotorExponential.jl
│ │ ├── RoundRotorQuadratic.jl
│ │ ├── SalientPoleExponential.jl
│ │ ├── SalientPoleQuadratic.jl
│ │ ├── branches.jl
│ │ ├── components.jl
│ │ ├── cost_function_timeseries.jl
│ │ ├── cost_functions/
│ │ │ ├── HydroGenerationCost.jl
│ │ │ ├── HydroReservoirCost.jl
│ │ │ ├── ImportExportCost.jl
│ │ │ ├── LoadCost.jl
│ │ │ ├── MarketBidCost.jl
│ │ │ ├── OfferCurveCost.jl
│ │ │ ├── RenewableGenerationCost.jl
│ │ │ ├── StorageCost.jl
│ │ │ ├── ThermalGenerationCost.jl
│ │ │ └── operational_cost.jl
│ │ ├── devices.jl
│ │ ├── dynamic_branch.jl
│ │ ├── dynamic_generator.jl
│ │ ├── dynamic_generator_components.jl
│ │ ├── dynamic_inverter.jl
│ │ ├── dynamic_inverter_components.jl
│ │ ├── dynamic_loads.jl
│ │ ├── dynamic_machines.jl
│ │ ├── dynamic_models.jl
│ │ ├── generated/
│ │ │ ├── ACBus.jl
│ │ │ ├── AGC.jl
│ │ │ ├── AVRFixed.jl
│ │ │ ├── AVRSimple.jl
│ │ │ ├── AVRTypeI.jl
│ │ │ ├── AVRTypeII.jl
│ │ │ ├── ActiveConstantPowerLoad.jl
│ │ │ ├── ActivePowerDroop.jl
│ │ │ ├── ActivePowerPI.jl
│ │ │ ├── ActiveRenewableControllerAB.jl
│ │ │ ├── ActiveVirtualOscillator.jl
│ │ │ ├── AggregateDistributedGenerationA.jl
│ │ │ ├── AndersonFouadMachine.jl
│ │ │ ├── Arc.jl
│ │ │ ├── Area.jl
│ │ │ ├── AreaInterchange.jl
│ │ │ ├── AverageConverter.jl
│ │ │ ├── BaseMachine.jl
│ │ │ ├── CSVGN1.jl
│ │ │ ├── ConstantReserve.jl
│ │ │ ├── ConstantReserveGroup.jl
│ │ │ ├── ConstantReserveNonSpinning.jl
│ │ │ ├── CurrentModeControl.jl
│ │ │ ├── DCBus.jl
│ │ │ ├── DEGOV.jl
│ │ │ ├── DEGOV1.jl
│ │ │ ├── DiscreteControlledACBranch.jl
│ │ │ ├── DynamicExponentialLoad.jl
│ │ │ ├── ESAC1A.jl
│ │ │ ├── ESAC6A.jl
│ │ │ ├── ESAC8B.jl
│ │ │ ├── ESDC1A.jl
│ │ │ ├── ESDC2A.jl
│ │ │ ├── ESST1A.jl
│ │ │ ├── ESST4B.jl
│ │ │ ├── EX4VSA.jl
│ │ │ ├── EXAC1.jl
│ │ │ ├── EXAC1A.jl
│ │ │ ├── EXAC2.jl
│ │ │ ├── EXPIC1.jl
│ │ │ ├── EXST1.jl
│ │ │ ├── EnergyReservoirStorage.jl
│ │ │ ├── ExponentialLoad.jl
│ │ │ ├── FACTSControlDevice.jl
│ │ │ ├── FiveMassShaft.jl
│ │ │ ├── FixedAdmittance.jl
│ │ │ ├── FixedDCSource.jl
│ │ │ ├── FixedFrequency.jl
│ │ │ ├── FullMachine.jl
│ │ │ ├── GasTG.jl
│ │ │ ├── GeneralGovModel.jl
│ │ │ ├── GenericArcImpedance.jl
│ │ │ ├── GenericDER.jl
│ │ │ ├── HybridOutputCurrentLimiter.jl
│ │ │ ├── HydroDispatch.jl
│ │ │ ├── HydroPumpTurbine.jl
│ │ │ ├── HydroReservoir.jl
│ │ │ ├── HydroTurbine.jl
│ │ │ ├── HydroTurbineGov.jl
│ │ │ ├── IEEEST.jl
│ │ │ ├── IEEET1.jl
│ │ │ ├── IEEETurbineGov1.jl
│ │ │ ├── InstantaneousOutputCurrentLimiter.jl
│ │ │ ├── InterconnectingConverter.jl
│ │ │ ├── InterruptiblePowerLoad.jl
│ │ │ ├── InterruptibleStandardLoad.jl
│ │ │ ├── KauraPLL.jl
│ │ │ ├── LCFilter.jl
│ │ │ ├── LCLFilter.jl
│ │ │ ├── Line.jl
│ │ │ ├── LoadZone.jl
│ │ │ ├── MagnitudeOutputCurrentLimiter.jl
│ │ │ ├── MarconatoMachine.jl
│ │ │ ├── MonitoredLine.jl
│ │ │ ├── MotorLoad.jl
│ │ │ ├── OneDOneQMachine.jl
│ │ │ ├── PIDGOV.jl
│ │ │ ├── PSS2A.jl
│ │ │ ├── PSS2B.jl
│ │ │ ├── PSS2C.jl
│ │ │ ├── PSSFixed.jl
│ │ │ ├── PSSSimple.jl
│ │ │ ├── PeriodicVariableSource.jl
│ │ │ ├── PhaseShiftingTransformer.jl
│ │ │ ├── PhaseShiftingTransformer3W.jl
│ │ │ ├── PowerLoad.jl
│ │ │ ├── PriorityOutputCurrentLimiter.jl
│ │ │ ├── RECurrentControlB.jl
│ │ │ ├── RLFilter.jl
│ │ │ ├── ReactivePowerDroop.jl
│ │ │ ├── ReactivePowerPI.jl
│ │ │ ├── ReactiveRenewableControllerAB.jl
│ │ │ ├── ReactiveVirtualOscillator.jl
│ │ │ ├── ReducedOrderPLL.jl
│ │ │ ├── RenewableDispatch.jl
│ │ │ ├── RenewableEnergyConverterTypeA.jl
│ │ │ ├── RenewableEnergyVoltageConverterTypeA.jl
│ │ │ ├── RenewableNonDispatch.jl
│ │ │ ├── ReserveDemandCurve.jl
│ │ │ ├── RoundRotorMachine.jl
│ │ │ ├── SCRX.jl
│ │ │ ├── SEXS.jl
│ │ │ ├── ST6B.jl
│ │ │ ├── ST8C.jl
│ │ │ ├── STAB1.jl
│ │ │ ├── SalientPoleMachine.jl
│ │ │ ├── SaturationOutputCurrentLimiter.jl
│ │ │ ├── SauerPaiMachine.jl
│ │ │ ├── ShiftablePowerLoad.jl
│ │ │ ├── SimpleAFMachine.jl
│ │ │ ├── SimpleFullMachine.jl
│ │ │ ├── SimpleMarconatoMachine.jl
│ │ │ ├── SimplifiedSingleCageInductionMachine.jl
│ │ │ ├── SingleCageInductionMachine.jl
│ │ │ ├── SingleMass.jl
│ │ │ ├── Source.jl
│ │ │ ├── StandardLoad.jl
│ │ │ ├── SteamTurbineGov1.jl
│ │ │ ├── SwitchedAdmittance.jl
│ │ │ ├── SynchronousCondenser.jl
│ │ │ ├── TGFixed.jl
│ │ │ ├── TGSimple.jl
│ │ │ ├── TGTypeI.jl
│ │ │ ├── TGTypeII.jl
│ │ │ ├── TModelHVDCLine.jl
│ │ │ ├── TapTransformer.jl
│ │ │ ├── ThermalMultiStart.jl
│ │ │ ├── ThermalStandard.jl
│ │ │ ├── Transformer2W.jl
│ │ │ ├── Transformer3W.jl
│ │ │ ├── TransmissionInterface.jl
│ │ │ ├── TwoTerminalGenericHVDCLine.jl
│ │ │ ├── TwoTerminalLCCLine.jl
│ │ │ ├── TwoTerminalVSCLine.jl
│ │ │ ├── VariableReserve.jl
│ │ │ ├── VariableReserveNonSpinning.jl
│ │ │ ├── VirtualInertia.jl
│ │ │ ├── VoltageModeControl.jl
│ │ │ ├── WPIDHY.jl
│ │ │ ├── ZeroOrderBESS.jl
│ │ │ └── includes.jl
│ │ ├── generation.jl
│ │ ├── injection.jl
│ │ ├── loads.jl
│ │ ├── reserves.jl
│ │ ├── serialization.jl
│ │ ├── services.jl
│ │ ├── static_injection_subsystem.jl
│ │ ├── static_models.jl
│ │ ├── storage.jl
│ │ ├── supplemental_accessors.jl
│ │ ├── supplemental_constructors.jl
│ │ ├── supplemental_setters.jl
│ │ └── topological_elements.jl
│ ├── outages.jl
│ ├── parsers/
│ │ ├── common.jl
│ │ ├── enums.jl
│ │ ├── generator_mapping_cdm.yaml
│ │ ├── generator_mapping_pm.yaml
│ │ ├── im_io/
│ │ │ ├── LICENSE.md
│ │ │ ├── common.jl
│ │ │ ├── data.jl
│ │ │ └── matlab.jl
│ │ ├── im_io.jl
│ │ ├── pm_io/
│ │ │ ├── LICENSE.md
│ │ │ ├── common.jl
│ │ │ ├── data.jl
│ │ │ ├── matpower.jl
│ │ │ ├── psse.jl
│ │ │ └── pti.jl
│ │ ├── pm_io.jl
│ │ ├── power_models_data.jl
│ │ ├── power_system_table_data.jl
│ │ ├── powerflowdata_data.jl
│ │ ├── psse_dynamic_data.jl
│ │ ├── psse_dynamic_mapping.yaml
│ │ └── psse_metadata_reimport.jl
│ ├── plant_attribute.jl
│ ├── subsystems.jl
│ └── utils/
│ ├── IO/
│ │ ├── base_checks.jl
│ │ ├── branchdata_checks.jl
│ │ └── system_checks.jl
│ ├── conversion.jl
│ ├── generate_struct_files.jl
│ ├── logging.jl
│ ├── print.jl
│ ├── print_pt_v2.jl
│ └── print_pt_v3.jl
└── test/
├── Project.toml
├── common.jl
├── runtests.jl
├── test_base_checks.jl
├── test_base_power.jl
├── test_branchchecks_testing.jl
├── test_busnumberchecks.jl
├── test_component_selector.jl
├── test_constructors.jl
├── test_cost_functions.jl
├── test_devices.jl
├── test_dynamic_generator.jl
├── test_dynamic_inverter.jl
├── test_dynamic_loads.jl
├── test_dynamics_source.jl
├── test_generate_structs.jl
├── test_hybrid_system.jl
├── test_hydro_reservoir.jl
├── test_internal.jl
├── test_logging.jl
├── test_outages.jl
├── test_parse_dynamics.jl
├── test_parse_matpower.jl
├── test_parse_psse.jl
├── test_plant_attributes.jl
├── test_power_system_table_data.jl
├── test_powersystemconstructors.jl
├── test_printing.jl
├── test_read_time_series.jl
├── test_serialization.jl
├── test_services.jl
├── test_subsystems.jl
├── test_supplemental_accessors.jl
├── test_system.jl
├── test_topology.jl
└── test_validation.jl
SYMBOL INDEX (8 symbols across 2 files) FILE: scripts/generate_config_file.py function read_json_data (line 22) | def read_json_data(filename): function generate_config (line 28) | def generate_config(input_file): function generate_file (line 46) | def generate_file(output_file, input_file=POWER_SYSTEM_DESCRIPTOR_FILE): function main (line 55) | def main(): FILE: scripts/generate_validation_config_file.py function read_json_data (line 15) | def read_json_data(filename): function generate_config (line 21) | def generate_config(input_file): function generate_file (line 45) | def generate_file(input_file, output_file): function main (line 55) | def main():
Condensed preview — 365 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (4,354K chars).
[
{
"path": ".claude/Sienna.md",
"chars": 6202,
"preview": "# Sienna Programming Practices\n\nThis document describes general programming practices and conventions that apply across "
},
{
"path": ".claude/claude.md",
"chars": 9548,
"preview": "# PowerSystems.jl\n\nData model library for power system simulation and optimization. Julia compat: `^1.10`.\n\n> **General "
},
{
"path": ".devcontainer/devcontainer.json",
"chars": 121,
"preview": "{\n \"extensions\": [\n \"julialang.language-julia\"\n ],\n \"image\": \"ghcr.io/julia-vscode/julia-devcontainer\"\n}"
},
{
"path": ".editorconfig",
"chars": 237,
"preview": "# top-most EditorConfig file\nroot = true\n\n# Unix-style newlines with a newline ending every file\n[*]\nend_of_line = lf\nin"
},
{
"path": ".github/copilot-setup-steps.yml",
"chars": 458,
"preview": "name: \"Copilot Setup Steps\"\n\non: workflow_dispatch\n\njobs:\n copilot-setup:\n runs-on: ubuntu-latest\n steps:\n -"
},
{
"path": ".github/pull_request_template.md",
"chars": 588,
"preview": "Thanks for opening a PR to PowerSystems.jl, please take note of the following when making a PR:\n\nCheck the [contributor "
},
{
"path": ".github/workflows/TagBot.yml",
"chars": 362,
"preview": "name: TagBot\non:\n issue_comment:\n types:\n - created\n workflow_dispatch:\njobs:\n TagBot:\n if: github.event_n"
},
{
"path": ".github/workflows/cross-package-test.yml",
"chars": 1684,
"preview": "name: CrossPackageTest\n\non:\n push:\n branches: [main]\n tags: [v*]\n pull_request:\n\njobs:\n test:\n name: Julia v"
},
{
"path": ".github/workflows/doc-preview-cleanup.yml",
"chars": 1152,
"preview": "name: Doc Preview Cleanup\n\non:\n pull_request:\n types: [closed]\n\n# Ensure that only one \"Doc Preview Cleanup\" workflo"
},
{
"path": ".github/workflows/docs.yml",
"chars": 1248,
"preview": "name: Documentation\n\non:\n push:\n branches:\n - main\n - 'release-'\n tags: '*'\n pull_request:\n\njobs:\n bu"
},
{
"path": ".github/workflows/fix-docs-on-failure.yml",
"chars": 10464,
"preview": "name: Auto-fix Documentation Failures\n\non:\n workflow_run:\n workflows: [\"Documentation\"]\n types:\n - completed"
},
{
"path": ".github/workflows/format-check.yml",
"chars": 1040,
"preview": "name: Format Check\n\non:\n push:\n branches:\n - 'main'\n - 'release-'\n tags: '*'\n pull_request:\n\njobs:\n b"
},
{
"path": ".github/workflows/main-tests.yml",
"chars": 1057,
"preview": "name: Main - CI\n\non:\n schedule:\n - cron: \"0 0 * * 1-5\"\n push:\n branches:\n - main\n\njobs:\n test:\n name: Jul"
},
{
"path": ".github/workflows/pr_testing.yml",
"chars": 1091,
"preview": "name: Test-CI\n\non:\n pull_request:\n types: [opened, synchronize, reopened]\n\nconcurrency:\n group: ${{ github.workflow"
},
{
"path": ".gitignore",
"chars": 2535,
"preview": "#Files generated by invoking Julia with --code-coverage\n*.jl.cov\n*.jl.*.cov\n*.log\n_*.jl\n# Files generated by invoking Ju"
},
{
"path": ".pre-commit-config.yaml",
"chars": 230,
"preview": "repos:\n - repo: local\n hooks:\n - id: julia-formatter\n name: Run Julia formatter\n entry: julia scr"
},
{
"path": "CHANGELOG.md",
"chars": 7311,
"preview": "# PowerSystems Change Log\n\n## 1.0.0 Announcement\n\nAfter 1.0.0 release, the manual Changelog will no longer be maintained"
},
{
"path": "CITATION.cff",
"chars": 1171,
"preview": "cff-version: 1.2.0\nmessage: \"If you use this software, please cite it as below.\"\nauthors:\n- family-names: \"Lara\"\n given"
},
{
"path": "CONTRIBUTING.md",
"chars": 659,
"preview": "# Contributing\n\nCommunity driven development of this package is encouraged. To maintain code quality standards, please a"
},
{
"path": "LICENSE",
"chars": 1589,
"preview": "BSD 3-Clause License\n\nCopyright (c) 2018, 2023 Alliance for Sustainable Energy, LLC and The Regents of the University of"
},
{
"path": "Project.toml",
"chars": 1386,
"preview": "name = \"PowerSystems\"\nuuid = \"bcd98974-b02a-5e2f-9ee0-a103f5c450dd\"\nauthors = [\"Jose Daniel Lara\", \"Daniel Thom\", \"Rodri"
},
{
"path": "README.md",
"chars": 3998,
"preview": "# PowerSystems.jl\n\n[]("
},
{
"path": "codecov.yml",
"chars": 1198,
"preview": "codecov:\n require_ci_to_pass: yes\n\ncoverage:\n precision: 2\n round: down\n range: \"70...100\"\n\n status:\n project: "
},
{
"path": "docs/Makefile",
"chars": 310,
"preview": "BRANCH := $(shell git rev-parse --abbrev-ref HEAD)\n\nhtml:\n\tjulia make.jl\n\ngithub: html\n\t-git branch -D gh-pages\n\t-git pu"
},
{
"path": "docs/Project.toml",
"chars": 970,
"preview": "[deps]\nCSV = \"336ed68f-0bac-5ca0-87d4-7b16caf5d00b\"\nDataFrames = \"a93c6f00-e57d-5684-b7b6-d8193f3e46c0\"\nDataStructures ="
},
{
"path": "docs/make.jl",
"chars": 9586,
"preview": "using Documenter, PowerSystems\nimport DataStructures: OrderedDict\nusing Literate\nusing DocumenterInterLinks\nusing Docume"
},
{
"path": "docs/make_model_library.jl",
"chars": 4638,
"preview": "using InteractiveUtils\nimport InfrastructureSystems as IS\nimport PowerSystems as PSY\n\nfunction _clean_old_generated_file"
},
{
"path": "docs/make_tutorials.jl",
"chars": 17996,
"preview": "using Pkg\nusing Literate\nusing DataFrames\nusing PrettyTables\n\n# Limit DataFrame rendering during docs generation to avoi"
},
{
"path": "docs/src/api/citation.md",
"chars": 873,
"preview": "### Citation\n\nUsers are requested to please cite the\n[following paper:](https://www.sciencedirect.com/science/article/pi"
},
{
"path": "docs/src/api/developer_guidelines.md",
"chars": 605,
"preview": "# Developer Guidelines\n\nIn order to contribute to `PowerSystems.jl` repository please read the following sections of\n[`I"
},
{
"path": "docs/src/api/enumerated_types.md",
"chars": 22077,
"preview": "# Specifying the type of...\n\nSome fields in PowerSystems.jl are specified with an option from a pre-defined list\n(Specif"
},
{
"path": "docs/src/api/glossary.md",
"chars": 6428,
"preview": "# Glossary and Acronyms\n\n[A](@ref) | [D](@ref) | [E](@ref) | [F](@ref) | [H](@ref) | [I](@ref) | [O](@ref) | [P](@ref) |"
},
{
"path": "docs/src/api/internal.md",
"chars": 114,
"preview": "```@meta\nCollapsedDocStrings = true\n```\n\n# Internal API\n\n```@autodocs\nModules = [PowerSystems]\nPublic = false\n```\n"
},
{
"path": "docs/src/api/psse_models.md",
"chars": 3238,
"preview": "# [Supported PSS/e Models](@id psse_models_ref)\n\nPSS/e's dynamic model library is extensive. `PowerSystems.jl` currently"
},
{
"path": "docs/src/api/public.md",
"chars": 4647,
"preview": "# Public API Reference\n\n## Modeling\n\n```@autodocs\nModules = [PowerSystems]\nPages = [\"PowerSystems.jl\",\n \"bra"
},
{
"path": "docs/src/api/static_injection_subtypes.md",
"chars": 8687,
"preview": "# StaticInjection Subtypes Comparison\n\nThis document summarizes the similarities and differences between [`StaticInjecti"
},
{
"path": "docs/src/api/type_tree.md",
"chars": 346,
"preview": "# Type Tree\n\nHere is the complete `PowerSystems.jl` type hierarchy:\n\n```@repl types\nusing PowerSystems #hide\nimport Type"
},
{
"path": "docs/src/api/valuecurve_options.md",
"chars": 5712,
"preview": "# [`ValueCurve` Options](@id curve_table)\n\nOperating cost data typically includes both fixed and variable costs. See the"
},
{
"path": "docs/src/explanation/buses_type_explanation.md",
"chars": 4340,
"preview": "# [Understanding ACBusTypes](@id bustypes)\n\n`PowerSystems.jl` supports multiple types of AC buses, [listed here](@ref ac"
},
{
"path": "docs/src/explanation/conforming_and_non_conforming_loads.md",
"chars": 4071,
"preview": "# [Conforming and Non-Conforming Loads](@id conf_loads)\n\nThe difference between conforming and non-conforming loads is n"
},
{
"path": "docs/src/explanation/dynamic_data.md",
"chars": 5207,
"preview": "# Dynamic Devices\n\n## Static and Dynamic Data Layers\n\n`PowerSystems.jl` uses two categories to define data for dynamic s"
},
{
"path": "docs/src/explanation/per_unit.md",
"chars": 3342,
"preview": "# [Per-unit Conventions](@id per_unit)\n\nIt is often useful to express power systems data in relative terms using per-uni"
},
{
"path": "docs/src/explanation/plant_attributes.md",
"chars": 17109,
"preview": "# [Plant Attributes](@id plant_attributes)\n\n## The Unit vs. Plant Aggregation Problem\n\nIn power systems modeling, there "
},
{
"path": "docs/src/explanation/power_concepts.md",
"chars": 5738,
"preview": "# [Power Concepts: Base Power, Rating, and Max Active Power](@id power_concepts)\n\nWhen working with generators in PowerS"
},
{
"path": "docs/src/explanation/supplemental_attributes.md",
"chars": 6855,
"preview": "# [Supplemental Attributes](@id supplemental_attributes)\n\nWhile the [`ext` field is a mechanism](@ref additional_fields)"
},
{
"path": "docs/src/explanation/system.md",
"chars": 4458,
"preview": "# [System](@id system_doc)\n\nThe `System` is the main container of components and the time series data references.\n`Power"
},
{
"path": "docs/src/explanation/time_series.md",
"chars": 6591,
"preview": "# [Time Series Data](@id ts_data)\n\n## Categories of Time Series\n\nThe bulk of the data in many power system models is tim"
},
{
"path": "docs/src/explanation/transformer_per_unit_models.md",
"chars": 4215,
"preview": "# [Transformer per unit transformations](@id transformers_pu)\n\nThe per-unit (p.u.) system is a fundamental tool in power"
},
{
"path": "docs/src/explanation/type_structure.md",
"chars": 2786,
"preview": "# [Type Structure](@id type_structure)\n\nPowerSystems.jl provides a type hierarchy to contain power system data.\n\n## Type"
},
{
"path": "docs/src/generate_input_config_table.jl",
"chars": 2098,
"preview": "@info \"Generating Input Configuration Descriptor Table\"\nfunction create_md()\n descriptor = PowerSystems._read_config_"
},
{
"path": "docs/src/generate_validation_table.jl",
"chars": 1727,
"preview": "@info \"Generating Validation Table\"\nfunction generate_validation_table(filepath::AbstractString)\n descriptor = Infras"
},
{
"path": "docs/src/how_to/add_component_natural_units.md",
"chars": 3033,
"preview": "# Add a Component in Natural Units\n\n```@setup add_in_nu\nusing PowerSystems; #hide\nusing PowerSystemCaseBuilder #hide\nsys"
},
{
"path": "docs/src/how_to/add_cost_curve.md",
"chars": 4606,
"preview": "# [Adding an Operating Cost](@id cost_how_to)\n\nThis how-to guide covers the steps to select and add an operating cost to"
},
{
"path": "docs/src/how_to/add_fuel_curve_timeseries.md",
"chars": 6075,
"preview": "# [Add Time Series Fuel Cost Data](@id fuel_curve_timeseries)\n\nThis how-to guide demonstrates how to add time-varying fu"
},
{
"path": "docs/src/how_to/add_new_types.md",
"chars": 8665,
"preview": "# Add a New or Custom Type\n\nThis page describes how developers should add types to `PowerSystems.jl`\n\n## Type Hierarchy\n"
},
{
"path": "docs/src/how_to/adding_additional_fields.md",
"chars": 1331,
"preview": "# [Add additional data to a component](@id additional_fields)\n\nAll `PowerSystems.jl` components have an `ext` field that"
},
{
"path": "docs/src/how_to/build_system_with_files.md",
"chars": 27798,
"preview": "# [Building a System from CSV Files](@id system_from_csv)\n\nIf you have input data on the component specifications and ti"
},
{
"path": "docs/src/how_to/create_hydro_datasets.md",
"chars": 10471,
"preview": "# [Define Hydro Generators with Reservoirs](@id hydro_resv)\n\nIn the current version of `PowerSystems.jl` there is suppor"
},
{
"path": "docs/src/how_to/create_system_with_source_import_export_cost.md",
"chars": 3991,
"preview": "# Add costs for imported/exported power\n\nThis how-to guide explains how to add an [`ImportExportCost`](@ref) to a [`Sour"
},
{
"path": "docs/src/how_to/handle_3W_transformers.md",
"chars": 4799,
"preview": "# [Handle 3-winding transformer data](@id 3wtdata)\n\nPowerSystems.jl stores the topological data for the [`Transformer3W`"
},
{
"path": "docs/src/how_to/improve_ts_performance.md",
"chars": 4379,
"preview": "# Improve Performance with Time Series Data\n\nUse the steps here to improve performance with small or large data sets, bu"
},
{
"path": "docs/src/how_to/jump.md",
"chars": 3732,
"preview": "# [Modeling with JuMP](@id modeling_with_jump)\n\nThis guide is for users who are interested in writing custom optimizatio"
},
{
"path": "docs/src/how_to/market_bid_cost.md",
"chars": 6035,
"preview": "# Add a Market Bid\n\nA [`MarketBidCost`](@ref) is an `OperationalCost` data structure that allows the user to run a produ"
},
{
"path": "docs/src/how_to/migrating_to_psy5.md",
"chars": 5528,
"preview": "# [Migrating from version 4.0 to 5.0](@id psy5_migration)\n\nThis guide outlines the code updates required to upgrade from"
},
{
"path": "docs/src/how_to/parse_dynamic_data.md",
"chars": 4781,
"preview": "# [Parsing PSS/e dynamic data](@id dyr_data)\n\nA `PowerSystems.jl` system can be created using a .RAW and a .DYR file. Fo"
},
{
"path": "docs/src/how_to/parse_matpower_psse.md",
"chars": 6828,
"preview": "# [Parsing MATPOWER or PSS/e Files](@id pm_data)\n\nThe following code will create a System from a MATPOWER .m or PSS/e .r"
},
{
"path": "docs/src/how_to/parse_ts_from_csvs.md",
"chars": 3600,
"preview": "# [Parse Time Series Data from .csv's](@id parsing_time_series)\n\nThis example shows how to parse time series data from ."
},
{
"path": "docs/src/how_to/reduce_repl_printing.md",
"chars": 811,
"preview": "# Reduce REPL printing\n\nBy default `PowerSystems.jl` outputs to the REPL all Logging statements, which can be\noverwhelmi"
},
{
"path": "docs/src/how_to/serialize_data.md",
"chars": 3296,
"preview": "# Write, View, and Load Data with a JSON\n\n`PowerSystems.jl` provides functionality to serialize an entire [`System`](@re"
},
{
"path": "docs/src/how_to/use_context_managers.md",
"chars": 8425,
"preview": "# Use Context Managers for Efficient Bulk Operations\n\n`PowerSystems.jl` provides several \"context manager\" functions tha"
},
{
"path": "docs/src/index.md",
"chars": 3938,
"preview": "# Welcome to PowerSystems.jl\n\n```@meta\nCurrentModule = PowerSystems\n```\n\n!!! tip \"Announcement\"\n\n PowerSystems.jl upg"
},
{
"path": "docs/src/model_library/dynamic_branch.md",
"chars": 156,
"preview": "# Dynamic Branch\n\n```@autodocs\nModules = [PowerSystems]\nPages = [\"models/dynamic_branch.jl\"]\nOrder = [:type, :function"
},
{
"path": "docs/src/model_library/dynamic_generator.md",
"chars": 138,
"preview": "# DynamicGenerator\n\n```@autodocs\nModules = [PowerSystems]\nPages = [\"dynamic_generator.jl\"]\nOrder = [:type, :function]\n"
},
{
"path": "docs/src/model_library/dynamic_inverter.md",
"chars": 136,
"preview": "# DynamicInverter\n\n```@autodocs\nModules = [PowerSystems]\nPages = [\"dynamic_inverter.jl\"]\nOrder = [:type, :function]\nPu"
},
{
"path": "docs/src/model_library/hybrid_system.md",
"chars": 148,
"preview": "### Hybrid System\n\n```@autodocs\nModules = [PowerSystems]\nPages = [\"HybridSystem.jl\"]\nOrder = [:type, :function]\nPublic"
},
{
"path": "docs/src/model_library/hydro_generation_cost.md",
"chars": 174,
"preview": "# HydroGenerationCost\n\n```@autodocs\nModules = [PowerSystems]\nPages = [\"cost_functions/HydroGenerationCost.jl\"]\nOrder ="
},
{
"path": "docs/src/model_library/hydro_reservoir.md",
"chars": 153,
"preview": "### `HydroReservoir`\n\n```@autodocs\nModules = [PowerSystems]\nPages = [\"HydroReservoir.jl\"]\nOrder = [:type, :function]\nP"
},
{
"path": "docs/src/model_library/hydro_reservoir_cost.md",
"chars": 176,
"preview": "### `HydroReservoirCost`\n\n```@autodocs\nModules = [PowerSystems]\nPages = [\"cost_functions/HydroReservoirCost.jl\"]\nOrder"
},
{
"path": "docs/src/model_library/import_export_cost.md",
"chars": 168,
"preview": "# ImportExportCost\n\n```@autodocs\nModules = [PowerSystems]\nPages = [\"cost_functions/ImportExportCost.jl\"]\nOrder = [:typ"
},
{
"path": "docs/src/model_library/load_cost.md",
"chars": 152,
"preview": "# LoadCost\n\n```@autodocs\nModules = [PowerSystems]\nPages = [\"cost_functions/LoadCost.jl\"]\nOrder = [:type, :function]\nPu"
},
{
"path": "docs/src/model_library/market_bid_cost.md",
"chars": 162,
"preview": "# MarketBidCost\n\n```@autodocs\nModules = [PowerSystems]\nPages = [\"cost_functions/MarketBidCost.jl\"]\nOrder = [:type, :fu"
},
{
"path": "docs/src/model_library/offer_curve_cost.md",
"chars": 164,
"preview": "# OfferCurveCost\n\n```@autodocs\nModules = [PowerSystems]\nPages = [\"cost_functions/OfferCurveCost.jl\"]\nOrder = [:type, :"
},
{
"path": "docs/src/model_library/outer_control.md",
"chars": 1894,
"preview": "# OuterControl\n\nThe outer control is composed by the ReactivePowerControl and the ActivePowerControl types.\n\n```@autodoc"
},
{
"path": "docs/src/model_library/renewable_generation_cost.md",
"chars": 182,
"preview": "# RenewableGenerationCost\n\n```@autodocs\nModules = [PowerSystems]\nPages = [\"cost_functions/RenewableGenerationCost.jl\"]"
},
{
"path": "docs/src/model_library/reserves.md",
"chars": 577,
"preview": "# Reserves\n\n## Constant Reserve\n\n```@autodocs\nModules = [PowerSystems]\nPages = [\"generated/ConstantReserve.jl\"]\nPublic"
},
{
"path": "docs/src/model_library/storage_cost.md",
"chars": 158,
"preview": "# StorageCost\n\n```@autodocs\nModules = [PowerSystems]\nPages = [\"cost_functions/StorageCost.jl\"]\nOrder = [:type, :functi"
},
{
"path": "docs/src/model_library/thermal_generation_cost.md",
"chars": 178,
"preview": "# ThermalGenerationCost\n\n```@autodocs\nModules = [PowerSystems]\nPages = [\"cost_functions/ThermalGenerationCost.jl\"]\nOrd"
},
{
"path": "docs/src/tutorials/add_dynamic_data.jl",
"chars": 13600,
"preview": "# # Adding Data for Dynamic Simulations\n# In this tutorial, we are going to add dynamic data to a power [`System`](@ref)"
},
{
"path": "docs/src/tutorials/creating_system.jl",
"chars": 12587,
"preview": "# # Create and Explore a Power `System`\n# Welcome to PowerSystems.jl!\n# In this tutorial, we will create a power system "
},
{
"path": "docs/src/tutorials/manipulating_datasets.jl",
"chars": 12588,
"preview": "# # Manipulating Datasets\n# `PowerSystems` provides function interfaces to all data, and in this tutorial we will explor"
},
{
"path": "docs/src/tutorials/tutorials_data/RTS-GMLC.RAW",
"chars": 73017,
"preview": " 0, 100.00, 33, 0, 0, 60.00 / November 07, 2017 19:41:38; Simulator Version 19; BuildDate 2017_9_5\n\n\n 101,'ABE"
},
{
"path": "docs/src/tutorials/tutorials_data/RTS_GMLC.m",
"chars": 52315,
"preview": "function mpc = RTS_GMLC\n\n %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% RTS-GMLC Test Case %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n %%%%%%"
},
{
"path": "docs/src/tutorials/tutorials_data/TestGENCLS.dyr",
"chars": 315,
"preview": " 101 'GENROE' 1 8.000000 0.030000 0.400000 0.050000 6.500000 0.000000 1.800000\n 1.700000 0.300000 0.550000 "
},
{
"path": "docs/src/tutorials/tutorials_data/case5.m",
"chars": 2789,
"preview": "% NESTA v0.6.0\n% used in tests of,\n% - non-contiguous bus ids\n% - tranformer orentation swapping\n% - dual values\n%\n\nfunc"
},
{
"path": "docs/src/tutorials/tutorials_data/case5_re.m",
"chars": 3648,
"preview": "% NESTA v0.6.0\n% extended to include renewable generators\n% used in tests of,\n% - non-contiguous bus ids\n% - tranformer "
},
{
"path": "docs/src/tutorials/utils/docs_utils.jl",
"chars": 296,
"preview": "\"\"\"\n`print_struct()`\n\nPrints the definition of a struct.\n\"\"\"\nfunction print_struct(type)\n mutable = ismutable(type) ?"
},
{
"path": "docs/src/tutorials/working_with_time_series.jl",
"chars": 16504,
"preview": "# # [Working with Time Series Data](@id tutorial_time_series)\n# In this tutorial, we will manually add, retrieve, and in"
},
{
"path": "scripts/formatter/Project.toml",
"chars": 254,
"preview": "uuid = \"c6367ca8-164d-4469-afe3-c91cf8860505\"\nauthors = [\"Jose Daniel Lara <jdlara@berkeley.edu>\"]\n\n[deps]\nJuliaFormatte"
},
{
"path": "scripts/formatter/formatter_code.jl",
"chars": 957,
"preview": "using Pkg\nPkg.activate(@__DIR__)\nPkg.instantiate()\nPkg.update()\n\nusing JuliaFormatter\n\nmain_paths = [\"./src\", \"./test\", "
},
{
"path": "scripts/generate_config_file.py",
"chars": 1545,
"preview": "#!/usr/bin/env python\n\n\"\"\"Generates a user descriptor file for parsing power system raw data.\"\"\"\n\n# Note: This is writt"
},
{
"path": "scripts/generate_validation_config_file.py",
"chars": 2277,
"preview": "#!/usr/bin/env python\n\n\"\"\"Generates a validation configuration file from JSON struct data\"\"\"\n\n# Note: This is written i"
},
{
"path": "src/PowerSystems.jl",
"chars": 24125,
"preview": "isdefined(Base, :__precompile__) && __precompile__()\n\n\"\"\"\nModule for constructing self-contained power system objects.\n\""
},
{
"path": "src/base.jl",
"chars": 111315,
"preview": "\nconst SKIP_PM_VALIDATION = false\n\nconst SYSTEM_KWARGS = Set((\n :area_name_formatter,\n :branch_name_formatter,\n "
},
{
"path": "src/component_selector.jl",
"chars": 2712,
"preview": "# Most of the `ComponentSelector` functionality in PowerSystems.jl is implemented by\n# wrapping the InfrastructureSystem"
},
{
"path": "src/component_selector_interface.jl",
"chars": 5476,
"preview": "# A continuation of `get_components_interface.jl` to facilitate neater documentation of\n# `ComponentSelector`. See the l"
},
{
"path": "src/contingencies.jl",
"chars": 224,
"preview": "\"\"\"\nSupertype for contingency events that can be attached to components as supplemental\nattributes.\n\nConcrete subtypes i"
},
{
"path": "src/data_format_conversions.jl",
"chars": 9569,
"preview": "# This file contains code to convert serialized data from old formats to work with newer\n# code.\n\n#\n# In version 1.0.1 t"
},
{
"path": "src/definitions.jl",
"chars": 24373,
"preview": "const MinMax = NamedTuple{(:min, :max), Tuple{Float64, Float64}}\nconst UpDown = NamedTuple{(:up, :down), Tuple{Float64, "
},
{
"path": "src/deprecated.jl",
"chars": 5352,
"preview": "# BEGIN 4.0.0 deprecations\nexport TwoTerminalHVDCLine\n\n\"\"\"\nDeprecated method for the old TwoTerminalHVDCLine that retur"
},
{
"path": "src/descriptors/power_system_inputs.json",
"chars": 38402,
"preview": "{\n \"dc_branch\": [\n {\n \"name\": \"name\",\n \"description\": \"Unique ID\"\n },\n {\n "
},
{
"path": "src/descriptors/power_system_structs.json",
"chars": 895531,
"preview": "{\n \"auto_generated_structs\": [\n {\n \"struct_name\": \"Area\",\n \"docstring\": \"A collection of"
},
{
"path": "src/get_components_interface.jl",
"chars": 7544,
"preview": "# The longstanding status quo in Sienna has been for `PSY.get_components` to be distinct\n# from `IS.get_components`, mos"
},
{
"path": "src/impedance_correction.jl",
"chars": 3202,
"preview": "\"\"\"\nAttribute that contains information regarding the Impedance Correction Table (ICT) rows defined in the Table.\n\n# Arg"
},
{
"path": "src/models/HybridSystem.jl",
"chars": 14044,
"preview": "\"\"\"\n mutable struct HybridSystem <: StaticInjectionSubsystem\n name::String\n available::Bool\n sta"
},
{
"path": "src/models/OuterControl.jl",
"chars": 2849,
"preview": "\"\"\"\n mutable struct OuterControl{\n A <: ActivePowerControl,\n R <: ReactivePowerControl\n } <: Dynamic"
},
{
"path": "src/models/RoundRotorExponential.jl",
"chars": 2600,
"preview": "\"\"\"\n mutable struct RoundRotorExponential <: Machine\n base_machine::RoundRotorMachine\n saturation_coeff"
},
{
"path": "src/models/RoundRotorQuadratic.jl",
"chars": 2561,
"preview": "\"\"\"\n mutable struct RoundRotorQuadratic <: Machine\n base_machine::RoundRotorMachine\n saturation_coeffs:"
},
{
"path": "src/models/SalientPoleExponential.jl",
"chars": 2192,
"preview": "\"\"\"\n mutable struct SalientPoleExponential <: Machine\n base_machine::SalientPoleMachine\n saturation_coe"
},
{
"path": "src/models/SalientPoleQuadratic.jl",
"chars": 2155,
"preview": "\"\"\"\n mutable struct SalientPoleQuadratic <: Machine\n base_machine::SalientPoleMachine\n saturation_coeff"
},
{
"path": "src/models/branches.jl",
"chars": 990,
"preview": "\"\"\" Supertype for all branches\"\"\"\nabstract type Branch <: Device end\n\n\"\"\" Supertype for all AC branches (branches connec"
},
{
"path": "src/models/components.jl",
"chars": 11854,
"preview": "function get_system_base_power(c::Component)\n return get_internal(c).units_info.base_value\nend\n\n\"\"\"\nDefault behavior "
},
{
"path": "src/models/cost_function_timeseries.jl",
"chars": 36707,
"preview": "# VALIDATORS\nfunction _validate_market_bid_cost(cost, context)\n (cost isa MarketBidCost) || throw(TypeError(\n "
},
{
"path": "src/models/cost_functions/HydroGenerationCost.jl",
"chars": 1456,
"preview": "\"\"\"\n$(TYPEDEF)\n$(TYPEDFIELDS)\n\n HydroGenerationCost(variable, fixed)\n HydroGenerationCost(; variable, fixed)\n\nAn o"
},
{
"path": "src/models/cost_functions/HydroReservoirCost.jl",
"chars": 1710,
"preview": "\"\"\"\n$(TYPEDEF)\n$(TYPEDFIELDS)\n\n HydroReservoirCost(level_shortage_cost, level_surplus_cost, spillage_cost)\n Storag"
},
{
"path": "src/models/cost_functions/ImportExportCost.jl",
"chars": 9326,
"preview": "\"\"\"\n$(TYPEDEF)\n$(TYPEDFIELDS)\n\n ImportExportCost(import_offer_curves, export_offer_curves, energy_import_weekly_limit"
},
{
"path": "src/models/cost_functions/LoadCost.jl",
"chars": 1026,
"preview": "\"\"\"\n$(TYPEDEF)\n$(TYPEDFIELDS)\n\n LoadCost(variable, fixed)\n LoadCost(; variable, fixed)\n\nAn operational cost for co"
},
{
"path": "src/models/cost_functions/MarketBidCost.jl",
"chars": 10689,
"preview": "\"\"\"\n$(TYPEDEF)\n$(TYPEDFIELDS)\n\n MarketBidCost(no_load_cost, start_up, shut_down, incremental_offer_curves, decrementa"
},
{
"path": "src/models/cost_functions/OfferCurveCost.jl",
"chars": 449,
"preview": "\"\"\"\n OfferCurveCost\n\nAbstract type for representing cost curves used in market bidding and offer mechanisms.\n\nThis se"
},
{
"path": "src/models/cost_functions/RenewableGenerationCost.jl",
"chars": 1963,
"preview": "\"\"\"\n$(TYPEDEF)\n$(TYPEDFIELDS)\n\n RenewableGenerationCost(variable, curtailment_cost, fixed)\n RenewableGenerationCos"
},
{
"path": "src/models/cost_functions/StorageCost.jl",
"chars": 3716,
"preview": "const STORAGE_OPERATION_MODES = NamedTuple{(:charge, :discharge), NTuple{2, Float64}}\n\n\"\"\"\n$(TYPEDEF)\n$(TYPEDFIELDS)\n\n "
},
{
"path": "src/models/cost_functions/ThermalGenerationCost.jl",
"chars": 2126,
"preview": "\"\"\"\n$(TYPEDEF)\n$(TYPEDFIELDS)\n\n ThermalGenerationCost(variable, fixed, start_up, shut_down)\n ThermalGenerationCost"
},
{
"path": "src/models/cost_functions/operational_cost.jl",
"chars": 681,
"preview": "\"\"\"\nSupertype for operational cost representations\n\nCurrent abstract type for representing operational costs associated "
},
{
"path": "src/models/devices.jl",
"chars": 6117,
"preview": "\"\"\"\nThis function add a service to the component without checking if the component and the service are attached to the s"
},
{
"path": "src/models/dynamic_branch.jl",
"chars": 4368,
"preview": "\"\"\"\nExtends the branch type to add the information required for dynamic modeling of branches. Includes the fields for th"
},
{
"path": "src/models/dynamic_generator.jl",
"chars": 7217,
"preview": "\"\"\"\n mutable struct DynamicGenerator{\n M <: Machine,\n S <: Shaft,\n A <: AVR,\n TG <: Turbi"
},
{
"path": "src/models/dynamic_generator_components.jl",
"chars": 2899,
"preview": "abstract type DynamicGeneratorComponent <: DynamicComponent end\n\n\"\"\"\nSupertype for all Automatic Voltage Regulator (AVR)"
},
{
"path": "src/models/dynamic_inverter.jl",
"chars": 10006,
"preview": "abstract type InverterComponent <: DynamicComponent end\n\n\"\"\"\n mutable struct DynamicInverter{\n C <: Converter,"
},
{
"path": "src/models/dynamic_inverter_components.jl",
"chars": 1883,
"preview": "abstract type DynamicInverterComponent <: DynamicComponent end\n\n\"\"\"\nSupertype for all power electronic converter models "
},
{
"path": "src/models/dynamic_loads.jl",
"chars": 933,
"preview": "function get_GenericDER_states(Qref_Flag::Int)\n if Qref_Flag == 1\n return [:x1, :x2, :x3, :x4, :x5, :x6, :x7, "
},
{
"path": "src/models/dynamic_machines.jl",
"chars": 1207,
"preview": "\"\"\"\nObtain coefficients (A, B) of the function Se = B(x - A)^2/x for\nSe(1.2) = B(1.2 - A)^2/1.2 and Se(1.0) = B(1.0 - A)"
},
{
"path": "src/models/dynamic_models.jl",
"chars": 1362,
"preview": "\"\"\"\nAbstract type for all components used to compose a [`DynamicInjection`](@ref) device\n\"\"\"\nabstract type DynamicCompon"
},
{
"path": "src/models/generated/ACBus.jl",
"chars": 7114,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct ACBus <: Bus\n number::Int"
},
{
"path": "src/models/generated/AGC.jl",
"chars": 5673,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct AGC <: Service\n name::Str"
},
{
"path": "src/models/generated/AVRFixed.jl",
"chars": 3438,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct AVRFixed <: AVR\n Vf::Floa"
},
{
"path": "src/models/generated/AVRSimple.jl",
"chars": 3432,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct AVRSimple <: AVR\n Kv::Flo"
},
{
"path": "src/models/generated/AVRTypeI.jl",
"chars": 6787,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct AVRTypeI <: AVR\n Ka::Floa"
},
{
"path": "src/models/generated/AVRTypeII.jl",
"chars": 6742,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct AVRTypeII <: AVR\n K0::Flo"
},
{
"path": "src/models/generated/ActiveConstantPowerLoad.jl",
"chars": 12523,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct ActiveConstantPowerLoad <: Dynam"
},
{
"path": "src/models/generated/ActivePowerDroop.jl",
"chars": 3139,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct ActivePowerDroop <: ActivePowerC"
},
{
"path": "src/models/generated/ActivePowerPI.jl",
"chars": 3469,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct ActivePowerPI <: ActivePowerCont"
},
{
"path": "src/models/generated/ActiveRenewableControllerAB.jl",
"chars": 12153,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct ActiveRenewableControllerAB <: A"
},
{
"path": "src/models/generated/ActiveVirtualOscillator.jl",
"chars": 3444,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct ActiveVirtualOscillator <: Activ"
},
{
"path": "src/models/generated/AggregateDistributedGenerationA.jl",
"chars": 24164,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct AggregateDistributedGenerationA "
},
{
"path": "src/models/generated/AndersonFouadMachine.jl",
"chars": 7598,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct AndersonFouadMachine <: Machine\n"
},
{
"path": "src/models/generated/Arc.jl",
"chars": 1501,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct Arc <: Topology\n from::Bu"
},
{
"path": "src/models/generated/Area.jl",
"chars": 4041,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct Area <: AggregationTopology\n "
},
{
"path": "src/models/generated/AreaInterchange.jl",
"chars": 5638,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct AreaInterchange <: Branch\n "
},
{
"path": "src/models/generated/AverageConverter.jl",
"chars": 2749,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct AverageConverter <: Converter\n "
},
{
"path": "src/models/generated/BaseMachine.jl",
"chars": 3228,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct BaseMachine <: Machine\n R"
},
{
"path": "src/models/generated/CSVGN1.jl",
"chars": 7018,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct CSVGN1 <: DynamicInjection\n "
},
{
"path": "src/models/generated/ConstantReserve.jl",
"chars": 7496,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct ConstantReserve{T <: ReserveDire"
},
{
"path": "src/models/generated/ConstantReserveGroup.jl",
"chars": 5337,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct ConstantReserveGroup{T <: Reserv"
},
{
"path": "src/models/generated/ConstantReserveNonSpinning.jl",
"chars": 8001,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct ConstantReserveNonSpinning <: Re"
},
{
"path": "src/models/generated/CurrentModeControl.jl",
"chars": 3481,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct CurrentModeControl <: InnerContr"
},
{
"path": "src/models/generated/DCBus.jl",
"chars": 5399,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct DCBus <: Bus\n number::Int"
},
{
"path": "src/models/generated/DEGOV.jl",
"chars": 6020,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct DEGOV <: TurbineGov\n T1::"
},
{
"path": "src/models/generated/DEGOV1.jl",
"chars": 6933,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct DEGOV1 <: TurbineGov\n dro"
},
{
"path": "src/models/generated/DiscreteControlledACBranch.jl",
"chars": 8508,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct DiscreteControlledACBranch <: AC"
},
{
"path": "src/models/generated/DynamicExponentialLoad.jl",
"chars": 6126,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct DynamicExponentialLoad <: Dynami"
},
{
"path": "src/models/generated/ESAC1A.jl",
"chars": 9934,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct ESAC1A <: AVR\n Tr::Float6"
},
{
"path": "src/models/generated/ESAC6A.jl",
"chars": 11376,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct ESAC6A <: AVR\n Tr::Float6"
},
{
"path": "src/models/generated/ESAC8B.jl",
"chars": 8495,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct ESAC8B <: AVR\n Tr::Float6"
},
{
"path": "src/models/generated/ESDC1A.jl",
"chars": 9075,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct ESDC1A <: AVR\n Tr::Float6"
},
{
"path": "src/models/generated/ESDC2A.jl",
"chars": 9212,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct ESDC2A <: AVR\n Tr::Float6"
},
{
"path": "src/models/generated/ESST1A.jl",
"chars": 9946,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct ESST1A <: AVR\n UEL_flags:"
},
{
"path": "src/models/generated/ESST4B.jl",
"chars": 9397,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct ESST4B <: AVR\n Tr::Float6"
},
{
"path": "src/models/generated/EX4VSA.jl",
"chars": 6546,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct EX4VSA <: AVR\n Iflim::Flo"
},
{
"path": "src/models/generated/EXAC1.jl",
"chars": 9408,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct EXAC1 <: AVR\n Tr::Float64"
},
{
"path": "src/models/generated/EXAC1A.jl",
"chars": 9925,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct EXAC1A <: AVR\n Tr::Float6"
},
{
"path": "src/models/generated/EXAC2.jl",
"chars": 11416,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct EXAC2 <: AVR\n Tr::Float64"
},
{
"path": "src/models/generated/EXPIC1.jl",
"chars": 11094,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct EXPIC1 <: AVR\n Tr::Float6"
},
{
"path": "src/models/generated/EXST1.jl",
"chars": 6076,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct EXST1 <: AVR\n Tr::Float64"
},
{
"path": "src/models/generated/EnergyReservoirStorage.jl",
"chars": 18297,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct EnergyReservoirStorage <: Storag"
},
{
"path": "src/models/generated/ExponentialLoad.jl",
"chars": 9475,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct ExponentialLoad <: StaticLoad\n "
},
{
"path": "src/models/generated/FACTSControlDevice.jl",
"chars": 7025,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct FACTSControlDevice <: StaticInje"
},
{
"path": "src/models/generated/FiveMassShaft.jl",
"chars": 10288,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct FiveMassShaft <: Shaft\n H"
},
{
"path": "src/models/generated/FixedAdmittance.jl",
"chars": 4681,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct FixedAdmittance <: ElectricLoad\n"
},
{
"path": "src/models/generated/FixedDCSource.jl",
"chars": 2543,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct FixedDCSource <: DCSource\n "
},
{
"path": "src/models/generated/FixedFrequency.jl",
"chars": 2058,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct FixedFrequency <: FrequencyEstim"
},
{
"path": "src/models/generated/FullMachine.jl",
"chars": 10271,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct FullMachine <: Machine\n R"
},
{
"path": "src/models/generated/GasTG.jl",
"chars": 6046,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct GasTG <: TurbineGov\n R::F"
},
{
"path": "src/models/generated/GeneralGovModel.jl",
"chars": 17958,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct GeneralGovModel <: TurbineGov\n "
},
{
"path": "src/models/generated/GenericArcImpedance.jl",
"chars": 6683,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct GenericArcImpedance <: ACTransmi"
},
{
"path": "src/models/generated/GenericDER.jl",
"chars": 22318,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct GenericDER <: DynamicInjection\n "
},
{
"path": "src/models/generated/HybridOutputCurrentLimiter.jl",
"chars": 2526,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct HybridOutputCurrentLimiter <: Ou"
},
{
"path": "src/models/generated/HydroDispatch.jl",
"chars": 12439,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct HydroDispatch <: HydroGen\n "
},
{
"path": "src/models/generated/HydroPumpTurbine.jl",
"chars": 19914,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct HydroPumpTurbine <: HydroUnit\n "
},
{
"path": "src/models/generated/HydroReservoir.jl",
"chars": 12416,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct HydroReservoir <: Device\n "
},
{
"path": "src/models/generated/HydroTurbine.jl",
"chars": 14965,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct HydroTurbine <: HydroUnit\n "
},
{
"path": "src/models/generated/HydroTurbineGov.jl",
"chars": 7562,
"preview": "#=\nThis file is auto-generated. Do not edit.\n=#\n\n#! format: off\n\n\"\"\"\n mutable struct HydroTurbineGov <: TurbineGov\n "
}
]
// ... and 165 more files (download for full content)
About this extraction
This page contains the full source code of the NREL-SIIP/PowerSystems.jl GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 365 files (3.9 MB), approximately 1.0M tokens, and a symbol index with 8 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.