SIIP Tutorial

Understanding PowerSystems.jl Components

Originally Contributed by: Clayton Barrows and Jose Daniel Lara

Introduction

This how to guide is intended to show a power system data specification framework that exploits the capabilities of Julia to improve performance and allow modelers to develop modular software to create problems with different complexities and enable large scale analysis. The PowerSystems documentation is also an excellent resource.

Objective

PowerSystems.jl provides a type specification for bulk power system data. The objective is to exploit Julia's integration of dynamic types to enable efficient data handling and enable functional dispatch in modeling and analysis applications As explained in Julia's documentation:

Julia’s type system is dynamic, but gains some of the advantages of static type systems by making it possible to indicate that certain values are of specific types. This can be of great assistance in generating efficient code, but even more significantly, it allows method dispatch on the types of function arguments to be deeply integrated with the language.

For more details on Julia types, refer to the documentation.

Environment and packages

PowerSystems.jl relies on a framework for data handling established in InfrastructureSystems.jl. Users of PowerSystems.jl should not need to interact directly with InfrastructureSystems.jl. However, it's worth recognizing that InfrastructureSystems provides much of the back end code for managing and accessing data, especially time series data.

using PowerSystems;

Normally, I'd add the following two lines to configure logging behavior, but something about Literate.jl makes this fail, so these examples only work with the default log configuration.

using Logging
logger = configure_logging(console_level = Logging.Error, file_level = Logging.Info, filename = "ex.log")

Types in PowerSystems

PowerSystems.jl provides a type hierarchy for specifying power system data. Data that describes infrastructure components is held in structs. For example, a Bus is defined as follows with fields for the parameters required to describe a bus (along with an internal field used by InfrastructureSystems to improve the efficiency of handling data).

using AbstractTrees
AbstractTrees.children(x::Type) = subtypes(x)

"""
`print_struct()`
Prints the definition of a struct.
"""
function print_struct(type)
    mutable = ismutable(type) ? "mutable" : ""
    println("$mutable struct $type")
    for (fn, ft) in zip(fieldnames(type), fieldtypes(type))
        println("  $fn::$ft")
    end
    println("end")
end

print_struct(Bus)
mutable struct PowerSystems.Bus
  number::Int64
  name::String
  bustype::Union{Nothing, PowerSystems.BusTypesModule.BusTypes}
  angle::Union{Nothing, Float64}
  magnitude::Union{Nothing, Float64}
  voltage_limits::Union{Nothing, NamedTuple{(:min, :max), Tuple{Float64, Float64}}}
  base_voltage::Union{Nothing, Float64}
  area::Union{Nothing, PowerSystems.Area}
  load_zone::Union{Nothing, PowerSystems.LoadZone}
  ext::Dict{String, Any}
  internal::InfrastructureSystems.InfrastructureSystemsInternal
end

Type Hierarchy

PowerSystems is intended to organize data containers by the behavior of the devices that the data represents. To that end, a type hierarchy has been defined with several levels of abstract types starting with InfrastructureSystemsType. There are a bunch of subtypes of InfrastructureSystemsType, but the important ones to know about are:

print_tree(PowerSystems.IS.InfrastructureSystemsType)
InfrastructureSystemsType
├─ DeviceParameter
│  ├─ ActivePowerControl
│  │  ├─ ActivePowerDroop
│  │  ├─ ActivePowerPI
│  │  ├─ ActiveRenewableControllerAB
│  │  ├─ ActiveVirtualOscillator
│  │  └─ VirtualInertia
│  ├─ DynamicComponent
│  │  ├─ DynamicGeneratorComponent
│  │  │  ├─ AVR
│  │  │  │  ├─ AVRFixed
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ AVRSimple
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ AVRTypeI
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ AVRTypeII
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ ESAC1A
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ ESAC6A
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ ESDC1A
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ ESDC2A
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ ESST1A
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ ESST4B
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ EX4VSA
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ EXAC1
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ EXAC1A
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ EXAC2
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ EXPIC1
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ EXST1
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ IEEET1
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ SCRX
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  └─ SEXS
│  │  │  │     ⋮
│  │  │  │     
│  │  │  ├─ Machine
│  │  │  │  ├─ AndersonFouadMachine
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ BaseMachine
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ FullMachine
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ MarconatoMachine
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ OneDOneQMachine
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ RoundRotorExponential
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ RoundRotorMachine
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ RoundRotorQuadratic
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ SalientPoleExponential
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ SalientPoleMachine
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ SalientPoleQuadratic
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ SauerPaiMachine
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ SimpleAFMachine
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ SimpleFullMachine
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  └─ SimpleMarconatoMachine
│  │  │  │     ⋮
│  │  │  │     
│  │  │  ├─ PSS
│  │  │  │  ├─ IEEEST
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ PSSFixed
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ PSSSimple
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  └─ STAB1
│  │  │  │     ⋮
│  │  │  │     
│  │  │  ├─ Shaft
│  │  │  │  ├─ FiveMassShaft
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  └─ SingleMass
│  │  │  │     ⋮
│  │  │  │     
│  │  │  └─ TurbineGov
│  │  │     ├─ GasTG
│  │  │     │  ⋮
│  │  │     │  
│  │  │     ├─ GeneralGovModel
│  │  │     │  ⋮
│  │  │     │  
│  │  │     ├─ HydroTurbineGov
│  │  │     │  ⋮
│  │  │     │  
│  │  │     ├─ IEEETurbineGov1
│  │  │     │  ⋮
│  │  │     │  
│  │  │     ├─ SteamTurbineGov1
│  │  │     │  ⋮
│  │  │     │  
│  │  │     ├─ TGFixed
│  │  │     │  ⋮
│  │  │     │  
│  │  │     ├─ TGTypeI
│  │  │     │  ⋮
│  │  │     │  
│  │  │     └─ TGTypeII
│  │  │        ⋮
│  │  │        
│  │  ├─ DynamicInverterComponent
│  │  │  ├─ Converter
│  │  │  │  ├─ AverageConverter
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ RenewableEnergyConverterTypeA
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  └─ RenewableEnergyVoltageConverterTypeA
│  │  │  │     ⋮
│  │  │  │     
│  │  │  ├─ DCSource
│  │  │  │  ├─ FixedDCSource
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  └─ ZeroOrderBESS
│  │  │  │     ⋮
│  │  │  │     
│  │  │  ├─ Filter
│  │  │  │  ├─ LCFilter
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ LCLFilter
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  └─ RLFilter
│  │  │  │     ⋮
│  │  │  │     
│  │  │  ├─ FrequencyEstimator
│  │  │  │  ├─ FixedFrequency
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ KauraPLL
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  └─ ReducedOrderPLL
│  │  │  │     ⋮
│  │  │  │     
│  │  │  ├─ InnerControl
│  │  │  │  ├─ CurrentModeControl
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  ├─ RECurrentControlB
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  └─ VoltageModeControl
│  │  │  │     ⋮
│  │  │  │     
│  │  │  └─ OuterControl
│  │  └─ InverterComponent
│  ├─ OperationalCost
│  │  ├─ MarketBidCost
│  │  ├─ MultiStartCost
│  │  ├─ StorageManagementCost
│  │  ├─ ThreePartCost
│  │  └─ TwoPartCost
│  └─ ReactivePowerControl
│     ├─ ReactivePowerDroop
│     ├─ ReactivePowerPI
│     ├─ ReactiveRenewableControllerAB
│     └─ ReactiveVirtualOscillator
├─ ForecastParameters
├─ InfrastructureSystemsComponent
│  ├─ AdditionalTestComponent
│  ├─ TestComponent
│  ├─ TimeSeriesData
│  │  ├─ Forecast
│  │  │  ├─ AbstractDeterministic
│  │  │  │  ├─ Deterministic
│  │  │  │  │  ⋮
│  │  │  │  │  
│  │  │  │  └─ DeterministicSingleTimeSeries
│  │  │  │     ⋮
│  │  │  │     
│  │  │  ├─ Probabilistic
│  │  │  └─ Scenarios
│  │  └─ StaticTimeSeries
│  │     └─ SingleTimeSeries
│  └─ Component
│     ├─ Device
│     │  ├─ Branch
│     │  │  ├─ ACBranch
│     │  │  │  ⋮
│     │  │  │  
│     │  │  └─ DCBranch
│     │  │     ⋮
│     │  │     
│     │  ├─ DynamicInjection
│     │  │  ├─ AggregateDistributedGenerationA
│     │  │  │  ⋮
│     │  │  │  
│     │  │  ├─ DynamicGenerator
│     │  │  │  ⋮
│     │  │  │  
│     │  │  ├─ DynamicInverter
│     │  │  │  ⋮
│     │  │  │  
│     │  │  ├─ GenericDER
│     │  │  │  ⋮
│     │  │  │  
│     │  │  ├─ PeriodicVariableSource
│     │  │  │  ⋮
│     │  │  │  
│     │  │  ├─ SimplifiedSingleCageInductionMachine
│     │  │  │  ⋮
│     │  │  │  
│     │  │  └─ SingleCageInductionMachine
│     │  │     ⋮
│     │  │     
│     │  ├─ RegulationDevice
│     │  └─ StaticInjection
│     │     ├─ ElectricLoad
│     │     │  ⋮
│     │     │  
│     │     ├─ Generator
│     │     │  ⋮
│     │     │  
│     │     ├─ Source
│     │     │  ⋮
│     │     │  
│     │     ├─ StaticInjectionSubsystem
│     │     │  ⋮
│     │     │  
│     │     └─ Storage
│     │        ⋮
│     │        
│     ├─ Service
│     │  ├─ AGC
│     │  ├─ AbstractReserve
│     │  │  ├─ Reserve
│     │  │  │  ⋮
│     │  │  │  
│     │  │  └─ ReserveNonSpinning
│     │  │     ⋮
│     │  │     
│     │  ├─ StaticReserveGroup
│     │  └─ Transfer
│     └─ Topology
│        ├─ AggregationTopology
│        │  ├─ Area
│        │  │  ⋮
│        │  │  
│        │  └─ LoadZone
│        │     ⋮
│        │     
│        ├─ Arc
│        └─ Bus
├─ InfrastructureSystemsInternal
├─ SystemData
├─ TimeSeriesKey
├─ TimeSeriesMetadata
│  ├─ ForecastMetadata
│  │  ├─ DeterministicMetadata
│  │  ├─ ProbabilisticMetadata
│  │  └─ ScenariosMetadata
│  └─ StaticTimeSeriesMetadata
│     └─ SingleTimeSeriesMetadata
├─ TimeSeriesParameters
├─ PowerSystemCaseBuilderType
│  ├─ SystemBuildStats
│  ├─ SystemCategory
│  │  ├─ MatPowerTestSystems
│  │  ├─ PSIDTestSystems
│  │  ├─ PSITestSystems
│  │  ├─ PSSETestSystems
│  │  ├─ PSYTestSystems
│  │  └─ SIIPExampleSystems
│  └─ SystemDescriptor
└─ System

TimeSeriesData

The time series documentation can be found here.

Every Component has a time_series_container::InfrastructureSystems.TimeSeriesContainer field. TimeSeriesData are used to hold time series information that describes the temporally dependent data of fields within the same struct. For example, the ThermalStandard.time_series_container field can describe other fields in the struct (available, activepower, reactivepower).

TimeSeriesDatas themselves can take the form of the following:

print_tree(TimeSeriesData)
TimeSeriesData
├─ Forecast
│  ├─ AbstractDeterministic
│  │  ├─ Deterministic
│  │  └─ DeterministicSingleTimeSeries
│  ├─ Probabilistic
│  └─ Scenarios
└─ StaticTimeSeries
   └─ SingleTimeSeries

In each case, the time series contains fields for scaling_factor_multiplier and data to identify the details of th Component field that the time series describes, and the time series data. For example: we commonly want to use a time series to describe the maximum active power capability of a renewable generator. In this case, we can create a SingleTimeSeries with a TimeArray and an accessor function to the maximum active power field in the struct describing the generator. In this way, we can store a scaling factor time series that will get multiplied by the maximum active power rather than the magnitudes of the maximum active power time series.

print_struct(Deterministic)
mutable struct InfrastructureSystems.Deterministic
  name::String
  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}}}}
  resolution::Dates.Period
  scaling_factor_multiplier::Union{Nothing, Function}
  internal::InfrastructureSystems.InfrastructureSystemsInternal
end

Examples of how to create and add time series to system can be found in the Add Time Series Example

System

The System object collects all of the individual components into a single struct along with some metadata about the system itself (e.g. base_power)

print_struct(System)
mutable struct PowerSystems.System
  data::InfrastructureSystems.SystemData
  frequency::Float64
  bus_numbers::Set{Int64}
  runchecks::Base.RefValue{Bool}
  units_settings::InfrastructureSystems.SystemUnitsSettings
  internal::InfrastructureSystems.InfrastructureSystemsInternal
end

Basic example

PowerSystems contains a few basic data files (mostly for testing and demonstration).

BASE_DIR = abspath(joinpath(dirname(Base.find_package("PowerSystems")), ".."))
include(joinpath(BASE_DIR, "test", "data_5bus_pu.jl")) # .jl file containing 5-bus system data
nodes_5 = nodes5() # function to create 5-bus buses
5-element Vector{PowerSystems.Bus}:
 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}())
 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}())
 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}())

Create a System

sys = System(
    100.0,
    nodes_5,
    vcat(thermal_generators5(nodes_5), renewable_generators5(nodes_5)),
    loads5(nodes_5),
    branches5(nodes_5),
)
System
Property Value
System Units Base SYSTEM_BASE
Base Power 100.0
Base Frequency 60.0
Num Components 28
Static Components
Type Count Has Static Time Series Has Forecasts
Arc 6 false false
Bus 5 false false
Line 6 false false
PowerLoad 3 false false
RenewableDispatch 3 false false
ThermalStandard 5 false false

Accessing System Data

PowerSystems provides functional interfaces to all data. The following examples outline the intended approach to accessing data expressed using PowerSystems.

PowerSystems enforces unique name fields between components of a particular concrete type. So, in order to retrieve a specific component, the user must specify the type of the component along with the name and system

Accessing components

@show get_component(Bus, sys, "nodeA")
@show get_component(Line, sys, "1")
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}())
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}())

Similarly, you can access all the components of a particular type: note: the return type of getcomponents is a FlattenIteratorWrapper, so call collect to get an Array

get_components(Bus, sys) |> collect
5-element Vector{PowerSystems.Bus}:
 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(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(5, nodeE, 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}())
 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}())

get_components also works on abstract types:

get_components(Branch, sys) |> collect
6-element Vector{PowerSystems.Branch}:
 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}())
 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}())
 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}())
 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}())
 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}())
 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}())

The fields within a component can be accessed using the get_* functions: It's highly recommended that users avoid using the . to access fields since we make no guarantees on the stability field names and locations. We do however promise to keep the accessor functions stable.

bus1 = get_component(Bus, sys, "nodeA")
@show get_name(bus1);
@show get_magnitude(bus1);
get_name(bus1) = "nodeA"
get_magnitude(bus1) = 1.0

Accessing TimeSeries

First we need to add some time series to the System

using TimeSeries
loads = collect(get_components(PowerLoad, sys))
for (l, ts) in zip(loads, load_timeseries_DA[2])
    add_time_series!(
        sys,
        l,
        Deterministic(
            "activepower",
            Dict(TimeSeries.timestamp(load_timeseries_DA[2][1])[1] => ts),
        ),
    )
end

If we want to access a specific time series for a specific component, we need to specify:

We can find the initial time of all the time series in the system:

get_forecast_initial_times(sys)
1-element Vector{Dates.DateTime}:
 2024-01-02T00:00:00

We can find the names of all time series attached to a component:

ts_names = get_time_series_names(Deterministic, loads[1])
1-element Vector{String}:
 "activepower"

We can access a specific time series for a specific component:

ta = get_time_series_array(Deterministic, loads[1], ts_names[1])
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
│                     │ A      │
├─────────────────────┼────────┤
│ 2024-01-02T00:00:00 │ 0.8292 │
│ 2024-01-02T01:00:00 │ 0.7379 │
│ 2024-01-02T02:00:00 │ 0.7593 │
│ 2024-01-02T03:00:00 │ 0.7369 │
│ 2024-01-02T04:00:00 │ 0.7337 │
│ 2024-01-02T05:00:00 │ 0.767  │
│ 2024-01-02T06:00:00 │ 0.7427 │
│ 2024-01-02T07:00:00 │ 0.8014 │
│ ⋮                   │ ⋮      │
│ 2024-01-02T17:00:00 │ 0.9325 │
│ 2024-01-02T18:00:00 │ 1.0756 │
│ 2024-01-02T19:00:00 │ 1.051  │
│ 2024-01-02T20:00:00 │ 1.0893 │
│ 2024-01-02T21:00:00 │ 0.9977 │
│ 2024-01-02T22:00:00 │ 0.9621 │
│ 2024-01-02T23:00:00 │ 0.8972 │

Or, we can just get the values of the time series:

ts = get_time_series_values(Deterministic, loads[1], ts_names[1])
24-element view(::Vector{Float64}, 1:24) with eltype Float64:
 0.8292100696738887
 0.7378744183281478
 0.7593491412366795
 0.7369358606281453
 0.7336906103867356
 0.7670265185263582
 0.7427015306396747
 0.8013904850758673
 0.7946706253681073
 0.8512545788405818
 0.8900994532248012
 0.8479541190007275
 0.915229318301713
 0.8920993707254111
 0.892101307744892
 0.8431522136062516
 0.9139828122062479
 0.9324623402029418
 1.0755989098768957
 1.051047503074154
 1.0892853856499802
 0.9976996422902898
 0.9620585851019077
 0.8972250898292887
CC BY-SA 4.0 "Dheepak Krishnamurthy". Last modified: August 26, 2022. Website built with Franklin.jl and the Julia programming language.