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.
<img src="../../assets/System.png" width="50%"/>
PowerSystems.jl
implements a wide variety of methods to search for components to
aid in the development of models. The code block shows an example of
retrieving components through the type hierarchy with the get_components
function and exploiting the type hierarchy for modeling purposes.
The default implementation of the function get_components
takes the desired device
type (concrete or abstract) and the system and it also accepts filter functions for a more
refined search. The container is optimized for iteration over abstract or concrete component
types as described by the [Type Structure](@ref type_structure). Given the potential size of the return,
PowerSystems.jl
returns Julia iterators in order to avoid unnecessary memory allocations.
using PowerSystems
file_dir = joinpath(pkgdir(PowerSystems), "docs", "src", "tutorials", "tutorials_data")
system = System(joinpath(file_dir, "RTS_GMLC.m"));
thermal_gens = get_components(ThermalStandard, system)
It is also possible to execute get_components
with abstract types from the
[abstract tree](@ref type_structure). For instance, it is possible to retrieve all renewable
generators
thermal_gens = get_components(RenewableGen, system)
The most common filtering requirement is by component name and for this case the method
get_component
returns a single component taking the device type, system and name as arguments.
my_thermal_gen = get_component(ThermalStandard, system, "323_CC_1")
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:
- We make no guarantees on the stability of component structure definitions. We will maintain version stability on the accessor methods.
- 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)
For example, the my_thermal_gen.active_power_limits
parameter of a thermal generator should be accessed as follows:
get_active_power_limits(my_thermal_gen)
You can also view data from all instances of a concrete type in one table with the function show_components
. It provides a few options:
- View the standard fields by accepting the defaults.
- Pass a dictionary where the keys are column names and the values are functions that accept a component as a single argument.
- Pass a vector of symbols that are field names of the type.
show_components(system, ThermalStandard)
show_components(system, ThermalStandard, Dict("has_time_series" => x -> has_time_series(x)))
show_components(system, ThermalStandard, [:active_power, :reactive_power])
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:
- Natural Units: The naturally defined units of each parameter (typically MW).
- System Base: Parameter values are divided by the system
base_power
. - Device Base: Parameter values are divided by the device
base_mva
.
To see the unit system setting of a System
:
get_units_base(system)
To change the unit system setting of a System
:
set_units_base_system!(system, "DEVICE_BASE")
The units of the parameter values stored in each struct are defined in
src/descriptors/power_system_structs.json
. Conversion between unit systems does not change
the stored parameter values. Instead, unit system conversions are made when accessing
parameters using the accessor functions ([see above](@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.
PowerSystems.jl
provides functionality to serialize an entire system to a JSON
file and then deserialize it back to a system. The main benefit is that
deserializing is significantly faster than reconstructing the system from raw
data files.
The function that serializes the system to_json
requires the system and a file name
to_json(system, "system.json")
The serialization process stores 3 files
- System data file (
*.json
file) - Validation data file (
*.json
file) - Time Series data file (
*.h5
file)
To deserialize:
system2 = System("system.json")
PowerSystems generates UUIDs for the System and all components in order to have a way to uniquely identify objects. During deserialization it restores the same UUIDs. If you will modify the System or components after deserialization then it is recommended that you set this flag to generate new UUIDs.
system2 = System("system.json", assign_new_uuids = true)
By default PowerSystems.jl
outputs to the REPL all Logging values, this can be overwhelming
in some cases. Use configure_logging
to create a logger with your preferences
(console and/or file, levels, etc.). For more detail refer to [Logging](@ref logging).
Example: Set log output to only error messages
using PowerSystems
using Logging
configure_logging(console_level = Logging.Error)
Note: log messages are not automatically flushed to files. Call
flush(logger)
to make this happen.
Refer to this page for more logging configuration options. Note that it describes how to enable debug logging for some log messages but not others.
PowerSystems data can be serialized and deserialized in JSON. This section shows how to explore the data outside of Julia using.
system = System("system.json")
It can be useful to view and filter the PowerSystems data in this format. There are many tools available to browse JSON data.
Here is an example GUI tool that is available online in a browser.
The command line utility jq offers even more features. The rest of this document provides example commands.
- View the entire file pretty-printed
jq . system.json
- View the PowerSystems component types
jq '.data.components | .[] | .__metadata__ | .type' system.json | sort | uniq
- View specific components
jq '.data.components | .[] | select(.__metadata__.type == "ThermalStandard")' system.json
- Get the count of a component type
# There is almost certainly a better way.
jq '.data.components | .[] | select(.__metadata__.type == "ThermalStandard")' system.json | grep -c ThermalStandard
- View specific component by name
jq '.data.components | .[] | select(.__metadata__.type == "ThermalStandard" and .name == "107_CC_1")' system.json
- Filter on a field value
jq '.data.components | .[] | select(.__metadata__.type == "ThermalStandard" and .active_power > 2.3)' system.json
- View the time series metadata for a component.
jq '.data.components | .[] | select(.__metadata__.type == "RenewableDispatch") | .time_series_container' system.json