{
"cells": [
{
"cell_type": "markdown",
"source": [
"# Introduction to [PowerSystems.jl](https://github.com/NREL-SIIP/PowerSystems.jl)"
],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"**Originally Contributed by**: Clayton Barrows and Jose Daniel Lara"
],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"## Introduction"
],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"This notebook is intended to show a power system data specification framework that exploits the\n",
"capabilities of Julia to improve performance and allow modelers to develop modular software\n",
"to create problems with different complexities and enable large scale analysis. The\n",
"[PowerSystems documentation](https://nrel-siip.github.io/PowerSystems.jl/stable/) is also\n",
"an excellent resource.\n",
"\n",
"### Objective\n",
"PowerSystems.jl provides a type specification for bulk power system data.\n",
"The objective is to exploit Julia's integration of dynamic types to enable efficient data\n",
"handling and enable functional dispatch in modeling and analysis applications\n",
"As explained in Julia's documentation:\n",
"\n",
"\"Julia’s type system is dynamic, but gains some of the advantages of static type systems\n",
"by making it possible to indicate that certain values are of specific types. This can be\n",
"of great assistance in generating efficient code, but even more significantly, it allows\n",
"method dispatch on the types of function arguments to be deeply integrated with the language.\"\n",
"\n",
"For more details on Julia types, refer to the [documentation](https://docs.julialang.org/en/v1/)\n",
"\n",
"\n",
"## Environment and packages\n",
"\n",
"PowerSystems.jl relies on a framework for data handling established in\n",
"[InfrastructureSystems.jl](https://github.com/NREL-SIIP/InfrastructureSystems.jl).\n",
"Users of PowerSystems.jl should not need to interact directly with InfrastructureSystems.jl.\n",
"However, it's worth recognizing that InfrastructureSystems provides much of the back end\n",
"code for managing and accessing data, especially time series data."
],
"metadata": {}
},
{
"outputs": [],
"cell_type": "code",
"source": [
"using SIIPExamples;\n",
"using PowerSystems;"
],
"metadata": {},
"execution_count": 1
},
{
"cell_type": "markdown",
"source": [
"Normally, I'd add the following two lines to configure logging behavior, but something about\n",
"Literate.jl makes this fail, so these examples only work with the default log configuration.\n",
"```julia\n",
"using Logging\n",
"logger = configure_logging(console_level = Logging.Error, file_level = Logging.Info, filename = \"ex.log\")\n",
"````"
],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"## Types in PowerSystems\n",
"PowerSystems.jl provides a type hierarchy for specifying power system data. Data that\n",
"describes infrastructure components is held in `struct`s. For example, a `Bus` is defined\n",
"as follows with fields for the parameters required to describe a bus (along with an\n",
"`internal` field used by InfrastructureSystems to improve the efficiency of handling data)."
],
"metadata": {}
},
{
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"mutable struct PowerSystems.Bus\n",
" number::Int64\n",
" name::String\n",
" bustype::Union{Nothing, PowerSystems.BusTypesModule.BusTypes}\n",
" angle::Union{Nothing, Float64}\n",
" magnitude::Union{Nothing, Float64}\n",
" voltage_limits::Union{Nothing, NamedTuple{(:min, :max), Tuple{Float64, Float64}}}\n",
" base_voltage::Union{Nothing, Float64}\n",
" area::Union{Nothing, PowerSystems.Area}\n",
" load_zone::Union{Nothing, PowerSystems.LoadZone}\n",
" ext::Dict{String, Any}\n",
" internal::InfrastructureSystems.InfrastructureSystemsInternal\n",
"end\n"
]
}
],
"cell_type": "code",
"source": [
"print_struct(Bus)"
],
"metadata": {},
"execution_count": 2
},
{
"cell_type": "markdown",
"source": [
"### Type Hierarchy\n",
"PowerSystems is intended to organize data containers by the behavior of the devices that\n",
"the data represents. To that end, a type hierarchy has been defined with several levels of\n",
"abstract types starting with `InfrastructureSystemsType`. There are a bunch of subtypes of\n",
"`InfrastructureSystemsType`, but the important ones to know about are:\n",
"- `Component`: includes all elements of power system data\n",
" - `Topology`: includes non physical elements describing network connectivity\n",
" - `Service`: includes descriptions of system requirements (other than energy balance)\n",
" - `Device`: includes descriptions of all the physical devices in a power system\n",
"- `InfrastructureSystems.DeviceParameter`: includes structs that hold data describing the\n",
" dynamic, or economic capabilities of `Device`.\n",
"- `TimeSeriesData`: Includes all time series types\n",
" - `Forecast`: includes structs to define time series of forecasted data where multiple\n",
"values can represent each time stamp\n",
" - `StaticTimeSeries`: includes structs to define time series with a single value for each\n",
"time stamp\n",
"- `System`: collects all of the `Component`s"
],
"metadata": {}
},
{
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"InfrastructureSystemsType\n",
"├─ DeviceParameter\n",
"│ ├─ ActivePowerControl\n",
"│ │ ├─ ActivePowerDroop\n",
"│ │ ├─ ActivePowerPI\n",
"│ │ ├─ ActiveRenewableControllerAB\n",
"│ │ └─ VirtualInertia\n",
"│ ├─ DynamicComponent\n",
"│ │ ├─ DynamicGeneratorComponent\n",
"│ │ │ ├─ AVR\n",
"│ │ │ │ ├─ AVRFixed\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ AVRSimple\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ AVRTypeI\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ AVRTypeII\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ ESAC1A\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ ESAC6A\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ ESDC1A\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ ESDC2A\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ ESST1A\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ ESST4B\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ EXAC1\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ EXAC1A\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ EXAC2\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ EXPIC1\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ IEEET1\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ SCRX\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ └─ SEXS\n",
"│ │ │ │ ⋮\n",
"│ │ │ │ \n",
"│ │ │ ├─ Machine\n",
"│ │ │ │ ├─ AndersonFouadMachine\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ BaseMachine\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ FullMachine\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ MarconatoMachine\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ OneDOneQMachine\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ RoundRotorExponential\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ RoundRotorMachine\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ RoundRotorQuadratic\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ SalientPoleExponential\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ SalientPoleMachine\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ SalientPoleQuadratic\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ SimpleAFMachine\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ SimpleFullMachine\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ └─ SimpleMarconatoMachine\n",
"│ │ │ │ ⋮\n",
"│ │ │ │ \n",
"│ │ │ ├─ PSS\n",
"│ │ │ │ ├─ IEEEST\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ PSSFixed\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ └─ PSSSimple\n",
"│ │ │ │ ⋮\n",
"│ │ │ │ \n",
"│ │ │ ├─ Shaft\n",
"│ │ │ │ ├─ FiveMassShaft\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ └─ SingleMass\n",
"│ │ │ │ ⋮\n",
"│ │ │ │ \n",
"│ │ │ └─ TurbineGov\n",
"│ │ │ ├─ GasTG\n",
"│ │ │ │ ⋮\n",
"│ │ │ │ \n",
"│ │ │ ├─ GeneralGovModel\n",
"│ │ │ │ ⋮\n",
"│ │ │ │ \n",
"│ │ │ ├─ HydroTurbineGov\n",
"│ │ │ │ ⋮\n",
"│ │ │ │ \n",
"│ │ │ ├─ IEEETurbineGov1\n",
"│ │ │ │ ⋮\n",
"│ │ │ │ \n",
"│ │ │ ├─ SteamTurbineGov1\n",
"│ │ │ │ ⋮\n",
"│ │ │ │ \n",
"│ │ │ ├─ TGFixed\n",
"│ │ │ │ ⋮\n",
"│ │ │ │ \n",
"│ │ │ ├─ TGTypeI\n",
"│ │ │ │ ⋮\n",
"│ │ │ │ \n",
"│ │ │ └─ TGTypeII\n",
"│ │ │ ⋮\n",
"│ │ │ \n",
"│ │ ├─ DynamicInverterComponent\n",
"│ │ │ ├─ Converter\n",
"│ │ │ │ ├─ AverageConverter\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ └─ RenewableEnergyConverterTypeA\n",
"│ │ │ │ ⋮\n",
"│ │ │ │ \n",
"│ │ │ ├─ DCSource\n",
"│ │ │ │ ├─ FixedDCSource\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ └─ ZeroOrderBESS\n",
"│ │ │ │ ⋮\n",
"│ │ │ │ \n",
"│ │ │ ├─ Filter\n",
"│ │ │ │ ├─ LCFilter\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ LCLFilter\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ └─ RLFilter\n",
"│ │ │ │ ⋮\n",
"│ │ │ │ \n",
"│ │ │ ├─ FrequencyEstimator\n",
"│ │ │ │ ├─ FixedFrequency\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ KauraPLL\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ └─ ReducedOrderPLL\n",
"│ │ │ │ ⋮\n",
"│ │ │ │ \n",
"│ │ │ ├─ InnerControl\n",
"│ │ │ │ ├─ CurrentModeControl\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ ├─ RECurrentControlB\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ └─ VoltageModeControl\n",
"│ │ │ │ ⋮\n",
"│ │ │ │ \n",
"│ │ │ └─ OuterControl\n",
"│ │ └─ InverterComponent\n",
"│ ├─ OperationalCost\n",
"│ │ ├─ MarketBidCost\n",
"│ │ ├─ MultiStartCost\n",
"│ │ ├─ StorageManagementCost\n",
"│ │ ├─ ThreePartCost\n",
"│ │ └─ TwoPartCost\n",
"│ └─ ReactivePowerControl\n",
"│ ├─ ReactivePowerDroop\n",
"│ ├─ ReactivePowerPI\n",
"│ └─ ReactiveRenewableControllerAB\n",
"├─ ForecastParameters\n",
"├─ InfrastructureSystemsComponent\n",
"│ ├─ AdditionalTestComponent\n",
"│ ├─ TestComponent\n",
"│ ├─ TimeSeriesData\n",
"│ │ ├─ Forecast\n",
"│ │ │ ├─ AbstractDeterministic\n",
"│ │ │ │ ├─ Deterministic\n",
"│ │ │ │ │ ⋮\n",
"│ │ │ │ │ \n",
"│ │ │ │ └─ DeterministicSingleTimeSeries\n",
"│ │ │ │ ⋮\n",
"│ │ │ │ \n",
"│ │ │ ├─ Probabilistic\n",
"│ │ │ └─ Scenarios\n",
"│ │ └─ StaticTimeSeries\n",
"│ │ └─ SingleTimeSeries\n",
"│ └─ Component\n",
"│ ├─ Device\n",
"│ │ ├─ Branch\n",
"│ │ │ ├─ ACBranch\n",
"│ │ │ │ ⋮\n",
"│ │ │ │ \n",
"│ │ │ └─ DCBranch\n",
"│ │ │ ⋮\n",
"│ │ │ \n",
"│ │ ├─ DynamicInjection\n",
"│ │ │ ├─ DynamicGenerator\n",
"│ │ │ │ ⋮\n",
"│ │ │ │ \n",
"│ │ │ ├─ DynamicInverter\n",
"│ │ │ │ ⋮\n",
"│ │ │ │ \n",
"│ │ │ └─ PeriodicVariableSource\n",
"│ │ │ ⋮\n",
"│ │ │ \n",
"│ │ ├─ RegulationDevice\n",
"│ │ └─ StaticInjection\n",
"│ │ ├─ ElectricLoad\n",
"│ │ │ ⋮\n",
"│ │ │ \n",
"│ │ ├─ Generator\n",
"│ │ │ ⋮\n",
"│ │ │ \n",
"│ │ ├─ Source\n",
"│ │ │ ⋮\n",
"│ │ │ \n",
"│ │ ├─ StaticInjectionSubsystem\n",
"│ │ │ ⋮\n",
"│ │ │ \n",
"│ │ └─ Storage\n",
"│ │ ⋮\n",
"│ │ \n",
"│ ├─ Service\n",
"│ │ ├─ AGC\n",
"│ │ ├─ AbstractReserve\n",
"│ │ │ ├─ Reserve\n",
"│ │ │ │ ⋮\n",
"│ │ │ │ \n",
"│ │ │ └─ ReserveNonSpinning\n",
"│ │ │ ⋮\n",
"│ │ │ \n",
"│ │ ├─ StaticReserveGroup\n",
"│ │ └─ Transfer\n",
"│ └─ Topology\n",
"│ ├─ AggregationTopology\n",
"│ │ ├─ Area\n",
"│ │ │ ⋮\n",
"│ │ │ \n",
"│ │ └─ LoadZone\n",
"│ │ ⋮\n",
"│ │ \n",
"│ ├─ Arc\n",
"│ └─ Bus\n",
"├─ InfrastructureSystemsInternal\n",
"├─ SystemData\n",
"├─ TimeSeriesKey\n",
"├─ TimeSeriesMetadata\n",
"│ ├─ ForecastMetadata\n",
"│ │ ├─ DeterministicMetadata\n",
"│ │ ├─ ProbabilisticMetadata\n",
"│ │ └─ ScenariosMetadata\n",
"│ └─ StaticTimeSeriesMetadata\n",
"│ └─ SingleTimeSeriesMetadata\n",
"├─ TimeSeriesParameters\n",
"├─ PowerSystemCaseBuilderType\n",
"│ ├─ SystemBuildStats\n",
"│ ├─ SystemCategory\n",
"│ │ ├─ MatPowerTestSystems\n",
"│ │ ├─ PSIDTestSystems\n",
"│ │ ├─ PSITestSystems\n",
"│ │ ├─ PSSETestSystems\n",
"│ │ ├─ PSYTestSystems\n",
"│ │ └─ SIIPExampleSystems\n",
"│ └─ SystemDescriptor\n",
"└─ System\n"
]
}
],
"cell_type": "code",
"source": [
"print_tree(PowerSystems.IS.InfrastructureSystemsType)"
],
"metadata": {},
"execution_count": 3
},
{
"cell_type": "markdown",
"source": [
"### `TimeSeriesData`\n",
"[_Read the Docs!_](https://nrel-siip.github.io/PowerSystems.jl/stable/modeler_guide/time_series/)\n",
"Every `Component` has a `time_series_container::InfrastructureSystems.TimeSeriesContainer`\n",
"field. `TimeSeriesData` are used to hold time series information that describes the\n",
"temporally dependent data of fields within the same struct. For example, the\n",
"`ThermalStandard.time_series_container` field can\n",
"describe other fields in the struct (`available`, `activepower`, `reactivepower`)."
],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"`TimeSeriesData`s themselves can take the form of the following:"
],
"metadata": {}
},
{
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"TimeSeriesData\n",
"├─ Forecast\n",
"│ ├─ AbstractDeterministic\n",
"│ │ ├─ Deterministic\n",
"│ │ └─ DeterministicSingleTimeSeries\n",
"│ ├─ Probabilistic\n",
"│ └─ Scenarios\n",
"└─ StaticTimeSeries\n",
" └─ SingleTimeSeries\n"
]
}
],
"cell_type": "code",
"source": [
"print_tree(TimeSeriesData)"
],
"metadata": {},
"execution_count": 4
},
{
"cell_type": "markdown",
"source": [
"In each case, the time series contains fields for `scaling_factor_multiplier` and `data`\n",
"to identify the details of th `Component` field that the time series describes, and the\n",
"time series `data`. For example: we commonly want to use a time series to\n",
"describe the maximum active power capability of a renewable generator. In this case, we\n",
"can create a `SingleTimeSeries` with a `TimeArray` and an accessor function to the\n",
"maximum active power field in the struct describing the generator. In this way, we can\n",
"store a scaling factor time series that will get multiplied by the maximum active power\n",
"rather than the magnitudes of the maximum active power time series."
],
"metadata": {}
},
{
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"mutable struct InfrastructureSystems.Deterministic\n",
" name::String\n",
" data::Union{DataStructures.SortedDict{Dates.DateTime, Vector{Vector{Tuple{Float64, Float64}}}}, DataStructures.SortedDict{Dates.DateTime, Vector{Float64}}, DataStructures.SortedDict{Dates.DateTime, Vector{Tuple{Float64, Float64}}}}\n",
" resolution::Dates.Period\n",
" scaling_factor_multiplier::Union{Nothing, Function}\n",
" internal::InfrastructureSystems.InfrastructureSystemsInternal\n",
"end\n"
]
}
],
"cell_type": "code",
"source": [
"print_struct(Deterministic)"
],
"metadata": {},
"execution_count": 5
},
{
"cell_type": "markdown",
"source": [
"Examples of how to create and add time series to system can be found in the\n",
"[Add Time Series Example](https://nbviewer.jupyter.org/github/NREL-SIIP/SIIPExamples.jl/blob/master/notebook/2_PowerSystems_examples/05_add_forecasts.ipynb)"
],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"### System\n",
"The `System` object collects all of the individual components into a single struct along\n",
"with some metadata about the system itself (e.g. `base_power`)"
],
"metadata": {}
},
{
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"mutable struct PowerSystems.System\n",
" data::InfrastructureSystems.SystemData\n",
" frequency::Float64\n",
" bus_numbers::Set{Int64}\n",
" runchecks::Base.RefValue{Bool}\n",
" units_settings::InfrastructureSystems.SystemUnitsSettings\n",
" internal::InfrastructureSystems.InfrastructureSystemsInternal\n",
"end\n"
]
}
],
"cell_type": "code",
"source": [
"print_struct(System)"
],
"metadata": {},
"execution_count": 6
},
{
"cell_type": "markdown",
"source": [
"## Basic example\n",
"PowerSystems contains a few basic data files (mostly for testing and demonstration)."
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "5-element Vector{PowerSystems.Bus}:\n Bus(1, nodeA, PowerSystems.BusTypesModule.BusTypes.PV = 3, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}())\n Bus(2, nodeB, PowerSystems.BusTypesModule.BusTypes.PQ = 2, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}())\n Bus(3, nodeC, PowerSystems.BusTypesModule.BusTypes.PV = 3, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}())\n Bus(4, nodeD, PowerSystems.BusTypesModule.BusTypes.REF = 4, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}())\n Bus(5, nodeE, PowerSystems.BusTypesModule.BusTypes.PV = 3, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}())"
},
"metadata": {},
"execution_count": 7
}
],
"cell_type": "code",
"source": [
"BASE_DIR = abspath(joinpath(dirname(Base.find_package(\"PowerSystems\")), \"..\"))\n",
"include(joinpath(BASE_DIR, \"test\", \"data_5bus_pu.jl\")) #.jl file containing 5-bus system data\n",
"nodes_5 = nodes5() # function to create 5-bus buses"
],
"metadata": {},
"execution_count": 7
},
{
"cell_type": "markdown",
"source": [
"### Create a `System`"
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "System\n┌───────────────────┬─────────────┐\n│ Property │ Value │\n├───────────────────┼─────────────┤\n│ System Units Base │ SYSTEM_BASE │\n│ Base Power │ 100.0 │\n│ Base Frequency │ 60.0 │\n│ Num Components │ 28 │\n└───────────────────┴─────────────┘\n\nStatic Components\n┌───────────────────┬───────┬────────────────────────┬───────────────┐\n│ Type │ Count │ Has Static Time Series │ Has Forecasts │\n├───────────────────┼───────┼────────────────────────┼───────────────┤\n│ Arc │ 6 │ false │ false │\n│ Bus │ 5 │ false │ false │\n│ Line │ 6 │ false │ false │\n│ PowerLoad │ 3 │ false │ false │\n│ RenewableDispatch │ 3 │ false │ false │\n│ ThermalStandard │ 5 │ false │ false │\n└───────────────────┴───────┴────────────────────────┴───────────────┘\n\n",
"text/html": [
"\n",
"\n",
"\n",
"\n",
"
\n",
"\n",
" System\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" System Units Base | \n",
" SYSTEM_BASE | \n",
"
\n",
" \n",
" Base Power | \n",
" 100.0 | \n",
"
\n",
" \n",
" Base Frequency | \n",
" 60.0 | \n",
"
\n",
" \n",
" Num Components | \n",
" 28 | \n",
"
\n",
" \n",
"
\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
" Static Components\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" Arc | \n",
" 6 | \n",
" false | \n",
" false | \n",
"
\n",
" \n",
" Bus | \n",
" 5 | \n",
" false | \n",
" false | \n",
"
\n",
" \n",
" Line | \n",
" 6 | \n",
" false | \n",
" false | \n",
"
\n",
" \n",
" PowerLoad | \n",
" 3 | \n",
" false | \n",
" false | \n",
"
\n",
" \n",
" RenewableDispatch | \n",
" 3 | \n",
" false | \n",
" false | \n",
"
\n",
" \n",
" ThermalStandard | \n",
" 5 | \n",
" false | \n",
" false | \n",
"
\n",
" \n",
"
\n",
"\n",
"\n",
"\n"
]
},
"metadata": {},
"execution_count": 8
}
],
"cell_type": "code",
"source": [
"sys = System(\n",
" 100.0,\n",
" nodes_5,\n",
" vcat(thermal_generators5(nodes_5), renewable_generators5(nodes_5)),\n",
" loads5(nodes_5),\n",
" branches5(nodes_5),\n",
")"
],
"metadata": {},
"execution_count": 8
},
{
"cell_type": "markdown",
"source": [
"### Accessing `System` Data\n",
"PowerSystems provides functional interfaces to all data. The following examples outline\n",
"the intended approach to accessing data expressed using PowerSystems."
],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"PowerSystems enforces unique `name` fields between components of a particular concrete type.\n",
"So, in order to retrieve a specific component, the user must specify the type of the component\n",
"along with the name and system"
],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"#### Accessing components"
],
"metadata": {}
},
{
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"get_component(Bus, sys, \"nodeA\") = Bus(1, nodeA, PowerSystems.BusTypesModule.BusTypes.PV = 3, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}())\n",
"get_component(Line, sys, \"1\") = Line(1, true, 0.0, 0.0, Arc(Bus(1, nodeA, PowerSystems.BusTypesModule.BusTypes.PV = 3, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}()), Bus(2, nodeB, PowerSystems.BusTypesModule.BusTypes.PQ = 2, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}())), 0.00281, 0.0281, (from = 0.00356, to = 0.00356), 2.0, (min = -0.7, max = 0.7), PowerSystems.Service[], Dict{String, Any}())\n"
]
},
{
"output_type": "execute_result",
"data": {
"text/plain": "1 (PowerSystems.Line):\n name: 1\n available: true\n active_power_flow: 0.0\n reactive_power_flow: 0.0\n arc: nodeA -> nodeB (PowerSystems.Arc)\n r: 0.00281\n x: 0.0281\n b: (from = 0.00356, to = 0.00356)\n rate: 2.0\n angle_limits: (min = -0.7, max = 0.7)\n services: 0-element Vector{PowerSystems.Service}\n ext: Dict{String, Any}()\n time_series_container: InfrastructureSystems.TimeSeriesContainer: 0\n InfrastructureSystems.SystemUnitsSettings:\n base_value: 100.0\n unit_system: InfrastructureSystems.UnitSystemModule.UnitSystem.SYSTEM_BASE = 0"
},
"metadata": {},
"execution_count": 9
}
],
"cell_type": "code",
"source": [
"@show get_component(Bus, sys, \"nodeA\")\n",
"@show get_component(Line, sys, \"1\")"
],
"metadata": {},
"execution_count": 9
},
{
"cell_type": "markdown",
"source": [
"Similarly, you can access all the components of a particular type: *note: the return type\n",
"of get_components is a `FlattenIteratorWrapper`, so call `collect` to get an `Array`"
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "5-element Vector{PowerSystems.Bus}:\n Bus(1, nodeA, PowerSystems.BusTypesModule.BusTypes.PV = 3, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}())\n Bus(3, nodeC, PowerSystems.BusTypesModule.BusTypes.PV = 3, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}())\n Bus(5, nodeE, PowerSystems.BusTypesModule.BusTypes.PV = 3, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}())\n Bus(2, nodeB, PowerSystems.BusTypesModule.BusTypes.PQ = 2, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}())\n Bus(4, nodeD, PowerSystems.BusTypesModule.BusTypes.REF = 4, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}())"
},
"metadata": {},
"execution_count": 10
}
],
"cell_type": "code",
"source": [
"get_components(Bus, sys) |> collect"
],
"metadata": {},
"execution_count": 10
},
{
"cell_type": "markdown",
"source": [
"`get_components` also works on abstract types:"
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "6-element Vector{PowerSystems.Branch}:\n Line(4, true, 0.0, 0.0, Arc(Bus(2, nodeB, PowerSystems.BusTypesModule.BusTypes.PQ = 2, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}()), Bus(3, nodeC, PowerSystems.BusTypesModule.BusTypes.PV = 3, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}())), 0.00108, 0.0108, (from = 0.00926, to = 0.00926), 11.148, (min = -0.7, max = 0.7), PowerSystems.Service[], Dict{String, Any}())\n Line(1, true, 0.0, 0.0, Arc(Bus(1, nodeA, PowerSystems.BusTypesModule.BusTypes.PV = 3, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}()), Bus(2, nodeB, PowerSystems.BusTypesModule.BusTypes.PQ = 2, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}())), 0.00281, 0.0281, (from = 0.00356, to = 0.00356), 2.0, (min = -0.7, max = 0.7), PowerSystems.Service[], Dict{String, Any}())\n Line(5, true, 0.0, 0.0, Arc(Bus(3, nodeC, PowerSystems.BusTypesModule.BusTypes.PV = 3, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}()), Bus(4, nodeD, PowerSystems.BusTypesModule.BusTypes.REF = 4, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}())), 0.00297, 0.0297, (from = 0.00337, to = 0.00337), 40.53, (min = -0.7, max = 0.7), PowerSystems.Service[], Dict{String, Any}())\n Line(2, true, 0.0, 0.0, Arc(Bus(1, nodeA, PowerSystems.BusTypesModule.BusTypes.PV = 3, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}()), Bus(4, nodeD, PowerSystems.BusTypesModule.BusTypes.REF = 4, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}())), 0.00304, 0.0304, (from = 0.00329, to = 0.00329), 2.0, (min = -0.7, max = 0.7), PowerSystems.Service[], Dict{String, Any}())\n Line(6, true, 0.0, 0.0, Arc(Bus(4, nodeD, PowerSystems.BusTypesModule.BusTypes.REF = 4, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}()), Bus(5, nodeE, PowerSystems.BusTypesModule.BusTypes.PV = 3, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}())), 0.00297, 0.0297, (from = 0.00337, to = 0.00337), 2.0, (min = -0.7, max = 0.7), PowerSystems.Service[], Dict{String, Any}())\n Line(3, true, 0.0, 0.0, Arc(Bus(1, nodeA, PowerSystems.BusTypesModule.BusTypes.PV = 3, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}()), Bus(5, nodeE, PowerSystems.BusTypesModule.BusTypes.PV = 3, 0.0, 1.0, (min = 0.9, max = 1.05), 230.0, nothing, nothing, Dict{String, Any}())), 0.00064, 0.0064, (from = 0.01563, to = 0.01563), 18.812, (min = -0.7, max = 0.7), PowerSystems.Service[], Dict{String, Any}())"
},
"metadata": {},
"execution_count": 11
}
],
"cell_type": "code",
"source": [
"get_components(Branch, sys) |> collect"
],
"metadata": {},
"execution_count": 11
},
{
"cell_type": "markdown",
"source": [
"The fields within a component can be accessed using the `get_*` functions:\n",
"*It's highly recommended that users avoid using the `.` to access fields since we make no\n",
"guarantees on the stability field names and locations. We do however promise to keep the\n",
"accessor functions stable.*"
],
"metadata": {}
},
{
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"get_name(bus1) = \"nodeA\"\n",
"get_magnitude(bus1) = 1.0\n"
]
}
],
"cell_type": "code",
"source": [
"bus1 = get_component(Bus, sys, \"nodeA\")\n",
"@show get_name(bus1);\n",
"@show get_magnitude(bus1);"
],
"metadata": {},
"execution_count": 12
},
{
"cell_type": "markdown",
"source": [
"#### Accessing `TimeSeries`"
],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"First we need to add some time series to the `System`"
],
"metadata": {}
},
{
"outputs": [],
"cell_type": "code",
"source": [
"loads = collect(get_components(PowerLoad, sys))\n",
"for (l, ts) in zip(loads, load_timeseries_DA[2])\n",
" add_time_series!(\n",
" sys,\n",
" l,\n",
" Deterministic(\n",
" \"activepower\",\n",
" Dict(TimeSeries.timestamp(load_timeseries_DA[2][1])[1] => ts),\n",
" ),\n",
" )\n",
"end"
],
"metadata": {},
"execution_count": 13
},
{
"cell_type": "markdown",
"source": [
"If we want to access a specific time series for a specific component, we need to specify:\n",
" - time series type\n",
" - `component`\n",
" - initial_time\n",
" - label\n",
"\n",
"We can find the initial time of all the time series in the system:"
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "1-element Vector{Dates.DateTime}:\n 2024-01-02T00:00:00"
},
"metadata": {},
"execution_count": 14
}
],
"cell_type": "code",
"source": [
"get_forecast_initial_times(sys)"
],
"metadata": {},
"execution_count": 14
},
{
"cell_type": "markdown",
"source": [
"We can find the names of all time series attached to a component:"
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "1-element Vector{String}:\n \"activepower\""
},
"metadata": {},
"execution_count": 15
}
],
"cell_type": "code",
"source": [
"ts_names = get_time_series_names(Deterministic, loads[1])"
],
"metadata": {},
"execution_count": 15
},
{
"cell_type": "markdown",
"source": [
"We can access a specific time series for a specific component:"
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "24×1 TimeSeries.TimeArray{Float64, 1, Dates.DateTime, SubArray{Float64, 1, Vector{Float64}, Tuple{UnitRange{Int64}}, true}} 2024-01-02T00:00:00 to 2024-01-02T23:00:00\n│ │ A │\n├─────────────────────┼────────┤\n│ 2024-01-02T00:00:00 │ 0.8901 │\n│ 2024-01-02T01:00:00 │ 0.7728 │\n│ 2024-01-02T02:00:00 │ 0.7634 │\n│ 2024-01-02T03:00:00 │ 0.6964 │\n│ 2024-01-02T04:00:00 │ 0.7597 │\n│ 2024-01-02T05:00:00 │ 0.6844 │\n│ 2024-01-02T06:00:00 │ 0.7188 │\n│ 2024-01-02T07:00:00 │ 0.7945 │\n│ ⋮ │ ⋮ │\n│ 2024-01-02T17:00:00 │ 0.9164 │\n│ 2024-01-02T18:00:00 │ 1.0162 │\n│ 2024-01-02T19:00:00 │ 1.0919 │\n│ 2024-01-02T20:00:00 │ 1.0407 │\n│ 2024-01-02T21:00:00 │ 1.0151 │\n│ 2024-01-02T22:00:00 │ 0.9756 │\n│ 2024-01-02T23:00:00 │ 0.8975 │"
},
"metadata": {},
"execution_count": 16
}
],
"cell_type": "code",
"source": [
"ta = get_time_series_array(Deterministic, loads[1], ts_names[1])"
],
"metadata": {},
"execution_count": 16
},
{
"cell_type": "markdown",
"source": [
"Or, we can just get the values of the time series:"
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "24-element view(::Vector{Float64}, 1:24) with eltype Float64:\n 0.8900534951404266\n 0.7727964273707415\n 0.7633821930260857\n 0.6963567083409643\n 0.7597162088709701\n 0.6843790958436067\n 0.7188038207731461\n 0.7944910514718007\n 0.8349778461938684\n 0.803120154154377\n ⋮\n 0.9062616868035502\n 0.92274505678347\n 0.9164149163200961\n 1.016151080389699\n 1.0919104343657873\n 1.040720873359067\n 1.0150733148097077\n 0.9755756388186618\n 0.8974771634770712"
},
"metadata": {},
"execution_count": 17
}
],
"cell_type": "code",
"source": [
"ts = get_time_series_values(Deterministic, loads[1], ts_names[1])"
],
"metadata": {},
"execution_count": 17
},
{
"cell_type": "markdown",
"source": [
"---\n",
"\n",
"*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*"
],
"metadata": {}
}
],
"nbformat_minor": 3,
"metadata": {
"language_info": {
"file_extension": ".jl",
"mimetype": "application/julia",
"name": "julia",
"version": "1.7.2"
},
"kernelspec": {
"name": "julia-1.7",
"display_name": "Julia 1.7.2",
"language": "julia"
}
},
"nbformat": 4
}