This example shows how to inspect the data of a loaded test system.
import andes
from andes.utils.paths import get_case
andes.main.config_logger()
To show all the rows and columns, change the pandas configuration with
import pandas as pd
pd.options.display.max_columns = None
pd.options.display.max_rows = None
Let's load the Kundur's system.
The ANDES xlsx file is the best supported format. Other formats can be converted to the xlsx format.
See the link below for more about format conversion. https://github.com/cuihantao/andes/blob/master/README.md#format-converter
As previously shown, test cases can be loaded with andes.run()
:
ss = andes.run(get_case('kundur/kundur_full.xlsx'))
Working directory: "/home/hcui7/repos/andes/examples" Loaded config from file "/home/hcui7/.andes/andes.rc" Using generated Python code. Parsing input file "/home/hcui7/repos/andes/andes/cases/kundur/kundur_full.xlsx"... Input file parsed in 0.2894 seconds. System internal structure set up in 0.0295 seconds. -> System connectivity check results: No islanded bus detected. No islanded areas detected. Each island has a slack bus correctly defined and enabled. -> Power flow calculation Sparse solver: KLU Solution method: NR method Sparse addition: Fast in-place (kvxopt) Power flow initialized. 0: |F(x)| = 14.9282832 1: |F(x)| = 3.608627841 2: |F(x)| = 0.1701107882 3: |F(x)| = 0.002038626956 4: |F(x)| = 3.745103977e-07 Converged in 5 iterations in 0.0172 seconds. Report saved to "kundur_full_out.txt" in 0.0014 seconds.
-> Single process finished in 0.5743 seconds.
Alternatively, one can load a test case without setting up using andes.load(..., setup=False)
. Note that setup=False
option.
It is useful to apply parameter changes to an existing test case.
ss = andes.load(get_case('kundur/kundur_full.xlsx'), setup=False)
Working directory: "/home/hcui7/repos/andes/examples" Loaded config from file "/home/hcui7/.andes/andes.rc" Using generated Python code. Parsing input file "/home/hcui7/repos/andes/andes/cases/kundur/kundur_full.xlsx"... Input file parsed in 0.1064 seconds.
For example, we can toggle the connectivity status u
of Line_1
to 0
using
ss.Line.alter('u', 'Line_1', 0)
When done, remember to set up the system before running calculation routines:
ss.setup()
ss.PFlow.run()
System internal structure set up in 0.0308 seconds. -> System connectivity check results: No islanded bus detected. No islanded areas detected. Each island has a slack bus correctly defined and enabled. -> Power flow calculation Sparse solver: KLU Solution method: NR method Sparse addition: Fast in-place (kvxopt) Power flow initialized. 0: |F(x)| = 14.9282832 1: |F(x)| = 3.601770103 2: |F(x)| = 0.1535494157 3: |F(x)| = 0.001799769945 4: |F(x)| = 3.667672734e-07 Converged in 5 iterations in 0.0161 seconds. Report saved to "kundur_full_out.txt" in 0.0031 seconds.
True
After setting up the system, adding or removing devices are not yet allowed.
ANDES supports loading systems from PSS/E RAW and DYR files.
The PSS/E v32 raw format is best supported.
Note that this feature is experimental. We try out best to support this format, but the compatibility is not guaranteed.
raw_path = get_case('kundur/kundur.raw')
dyr_path = get_case('kundur/kundur_full.dyr')
The raw file is passed to the positional argument, whereas the dyr file is passed to addfile
.
ss = andes.run(raw_path, addfile=dyr_path)
Working directory: "/home/hcui7/repos/andes/examples" Loaded config from file "/home/hcui7/.andes/andes.rc" Using generated Python code. Parsing input file "/home/hcui7/repos/andes/andes/cases/kundur/kundur.raw"... MODIFIED KUNDUR'S TWO-AREA TEST SYSTEM, DISTRIBUTED WITH ANDES SEE THE BOOK "POWER SYSTEM STABILITY AND CONTROL" FOR ORIGINAL DATA Input file parsed in 0.0046 seconds. Parsing additional file "/home/hcui7/repos/andes/andes/cases/kundur/kundur_full.dyr"... Addfile parsed in 0.1473 seconds. System internal structure set up in 0.0283 seconds. -> System connectivity check results: No islanded bus detected. No islanded areas detected. Each island has a slack bus correctly defined and enabled. -> Power flow calculation Sparse solver: KLU Solution method: NR method Sparse addition: Fast in-place (kvxopt) Power flow initialized. 0: |F(x)| = 3.175850023 1: |F(x)| = 3.176155228e-08 Converged in 2 iterations in 0.0067 seconds. Report saved to "kundur_out.txt" in 0.0038 seconds.
-> Single process finished in 0.3241 seconds.
Parameters are stored as attributes of the model. For example, ss.GENROU.M
, the machine starting time constant (2H
), is stored in ss.GENROU.M
.
ss.GENROU.M
NumParam: GENROU.M, v=[117. 117. 111.15 111.15], vin=[13. 13. 12.35 12.35]
It is an instance of NumParam
, which contains fields v
for the values after converting to system-base per unit values.
ss.GENROU.M.v
array([117. , 117. , 111.15, 111.15])
And field vin
is for the original input data.
ss.GENROU.M.vin
array([13. , 13. , 12.35, 12.35])
ANDES provides tabulated view of model parameters by using DataFrame. Each model object has an attribute called cache
for caching the parameter dataframes.
The original parameters from the input file are stored in cache.df_in
of the model object. For GENROU
, do
ss.GENROU.cache.df_in
idx | u | name | bus | gen | coi | Sn | Vn | fn | D | M | ra | xl | xd1 | kp | kw | S10 | S12 | gammap | gammaq | xd | xq | xd2 | xq1 | xq2 | Td10 | Td20 | Tq10 | Tq20 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
uid | |||||||||||||||||||||||||||||
0 | GENROU_1 | 1.0 | GENROU_1 | 1 | 1 | None | 900.0 | 20.0 | 60.0 | 0.0 | 13.00 | 0.0 | 0.06 | 0.3 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 1.0 | 1.8 | 1.7 | 0.25 | 0.55 | 0.25 | 8.0 | 0.03 | 0.4 | 0.05 |
1 | GENROU_2 | 1.0 | GENROU_2 | 2 | 2 | None | 900.0 | 20.0 | 60.0 | 0.0 | 13.00 | 0.0 | 0.06 | 0.3 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 1.0 | 1.8 | 1.7 | 0.25 | 0.55 | 0.25 | 8.0 | 0.03 | 0.4 | 0.05 |
2 | GENROU_3 | 1.0 | GENROU_3 | 3 | 3 | None | 900.0 | 20.0 | 60.0 | 0.0 | 12.35 | 0.0 | 0.06 | 0.3 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 1.0 | 1.8 | 1.7 | 0.25 | 0.55 | 0.25 | 8.0 | 0.03 | 0.4 | 0.05 |
3 | GENROU_4 | 1.0 | GENROU_4 | 4 | 4 | None | 900.0 | 20.0 | 60.0 | 0.0 | 12.35 | 0.0 | 0.06 | 0.3 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 1.0 | 1.8 | 1.7 | 0.25 | 0.55 | 0.25 | 8.0 | 0.03 | 0.4 | 0.05 |
Parameters will be converted to per-unit in the system base after loading. This process have been done if andes.run
is used for loading the data file.
To inspect the converted parameters, check the cache.df
parameter.
ss.GENROU.cache.df
idx | u | name | bus | gen | coi | Sn | Vn | fn | D | M | ra | xl | xd1 | kp | kw | S10 | S12 | gammap | gammaq | xd | xq | xd2 | xq1 | xq2 | Td10 | Td20 | Tq10 | Tq20 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
uid | |||||||||||||||||||||||||||||
0 | GENROU_1 | 1.0 | GENROU_1 | 1 | 1 | None | 900.0 | 20.0 | 60.0 | 0.0 | 117.00 | 0.0 | 0.006667 | 0.033333 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 1.0 | 0.2 | 0.188889 | 0.027778 | 0.061111 | 0.027778 | 8.0 | 0.03 | 0.4 | 0.05 |
1 | GENROU_2 | 1.0 | GENROU_2 | 2 | 2 | None | 900.0 | 20.0 | 60.0 | 0.0 | 117.00 | 0.0 | 0.006667 | 0.033333 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 1.0 | 0.2 | 0.188889 | 0.027778 | 0.061111 | 0.027778 | 8.0 | 0.03 | 0.4 | 0.05 |
2 | GENROU_3 | 1.0 | GENROU_3 | 3 | 3 | None | 900.0 | 20.0 | 60.0 | 0.0 | 111.15 | 0.0 | 0.006667 | 0.033333 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 1.0 | 0.2 | 0.188889 | 0.027778 | 0.061111 | 0.027778 | 8.0 | 0.03 | 0.4 | 0.05 |
3 | GENROU_4 | 1.0 | GENROU_4 | 4 | 4 | None | 900.0 | 20.0 | 60.0 | 0.0 | 111.15 | 0.0 | 0.006667 | 0.033333 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 1.0 | 0.2 | 0.188889 | 0.027778 | 0.061111 | 0.027778 | 8.0 | 0.03 | 0.4 | 0.05 |
One will notice the converted parameters such as M
, xl
, and all other impedances.
It is very important to notice that cache.df
and cache.df_in
are both views. Altering data in these views will NOT alter the underlying parameter values.
To alter values, see the example below.
Parameters can be altered by calling the alter
method on a model instance.
We first look up the original value through get
.
Either v
or vin
can be passed to argument attr
to retrieve the converted or the original data. Here we are retrieving the original input data. If attr
is not provided, get
returns the value after per-unit conversion, which is the value used for calculation, by default.
ss.GENROU.get("M", "GENROU_1", attr='vin')
13.0
To change the M
of GENROU_1
to 10
, do
ss.GENROU.alter("M", "GENROU_1", 10)
The value set through alter
is always the data before per-unit conversion - just like it should have been in an input file. ANDES will perform the conversion and set vin
and v
correctly.
Parameters altered through Model.alter()
can be saved as a new system using
andes.io.xlsx.write(ss, 'new_system.xlsx')
File "new_system.xlsx" already exist. Overwrite? [y/N]y
xlsx file written to "new_system.xlsx"
True
As mentioned, cache.df
and cache.df_in
are cached views and will not be automatically updated for inspection.
This is generally not an issue if one performs the simulation after altering data. However, if one needs to inspect the data again, cache.refresh()
needs to be called manually.
ss.GENROU.cache.refresh()
ss.GENROU.cache.df_in
idx | u | name | bus | gen | coi | Sn | Vn | fn | D | M | ra | xl | xd1 | kp | kw | S10 | S12 | gammap | gammaq | xd | xq | xd2 | xq1 | xq2 | Td10 | Td20 | Tq10 | Tq20 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
uid | |||||||||||||||||||||||||||||
0 | GENROU_1 | 1.0 | GENROU_1 | 1 | 1 | None | 900.0 | 20.0 | 60.0 | 0.0 | 10.00 | 0.0 | 0.06 | 0.3 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 1.0 | 1.8 | 1.7 | 0.25 | 0.55 | 0.25 | 8.0 | 0.03 | 0.4 | 0.05 |
1 | GENROU_2 | 1.0 | GENROU_2 | 2 | 2 | None | 900.0 | 20.0 | 60.0 | 0.0 | 13.00 | 0.0 | 0.06 | 0.3 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 1.0 | 1.8 | 1.7 | 0.25 | 0.55 | 0.25 | 8.0 | 0.03 | 0.4 | 0.05 |
2 | GENROU_3 | 1.0 | GENROU_3 | 3 | 3 | None | 900.0 | 20.0 | 60.0 | 0.0 | 12.35 | 0.0 | 0.06 | 0.3 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 1.0 | 1.8 | 1.7 | 0.25 | 0.55 | 0.25 | 8.0 | 0.03 | 0.4 | 0.05 |
3 | GENROU_4 | 1.0 | GENROU_4 | 4 | 4 | None | 900.0 | 20.0 | 60.0 | 0.0 | 12.35 | 0.0 | 0.06 | 0.3 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 1.0 | 1.8 | 1.7 | 0.25 | 0.55 | 0.25 | 8.0 | 0.03 | 0.4 | 0.05 |
One might also want to check the variable values in a similar way to that for a parameter. Certainly, a variable has a v
attribute which stores values.
It is important to note that v
only holds the values at the last program state. Such program state could be the solution of power flow, the initialization of time-domain simulation, or the end of a simulation disturbances.
Since we have only ran power flow for ss
, ss.Bus.v.v
are the voltage magnitude solutions, where the first v
is for "voltage", and the second v
is the first v
's value attribute.
ss.Bus.v.v
array([1. , 1. , 1. , 1. , 0.98337472, 0.96908585, 0.9562181 , 0.95400018, 0.96856366, 0.98377143])
Variables hold more than values. They have an attribute a
for the addresses indexing into the corresponding type of array.
There are two system-level arrays, ss.dae.x
and ss.dae.y
for the right-hand-side of the differential and algebraic equations, respectively.
type(ss.Bus.v)
andes.core.var.Algeb
ss.Bus.v
is an algebraic variable, thus ss.Bus.v.a
holds the indices into ss.dae.g
.
ss.dae.y[ss.Bus.v.a]
array([1. , 1. , 1. , 1. , 0.98337472, 0.96908585, 0.9562181 , 0.95400018, 0.96856366, 0.98377143])
We can see that these two values are the same.
After a time-domain simulation, the time series of the variables can be retrieved through ss.dae.ts
. Let's first run a simulation.
ss.TDS.run()
-> Time Domain Simulation Summary: Sparse Solver: KLU Simulation time: 0-20.0 s. Fixed step size: h=33.33 ms. Shrink if not converged. Suspect initialization issue! Simulation may crash! Name | Var. Value | Eqn. Mismatch ----------------+------------+-------------- delta GENROU 1 | 2.840 | 753.982 delta GENROU 2 | 2.248 | 753.982 delta GENROU 3 | 1.878 | 753.982 delta GENROU 4 | 2.423 | 753.982 a Bus 1 | 0.570 | -21.804 a Bus 2 | 0.378 | -21.000 a Bus 3 | 0.196 | -21.000 a Bus 4 | 0.378 | -21 v Bus 1 | 1.000 | -3.284 v Bus 2 | 1.000 | -6.841 v Bus 3 | 1.000 | -6.972 v Bus 4 | 1.000 | -3.183 vd GENROU 1 | 1.502 | -1.473 vd GENROU 2 | 1.357 | -0.804 vd GENROU 3 | 1.353 | -0.719 vd GENROU 4 | 1.481 | -1.182 vq GENROU 1 | 1.320 | -3.928 vq GENROU 2 | 1.469 | -3.527 vq GENROU 3 | 1.473 | -3.167 vq GENROU 4 | 1.344 | -3.602 tm GENROU 1 | 14.536 | -14.536 tm GENROU 2 | 14 | -14 tm GENROU 3 | 14.000 | -14.000 tm GENROU 4 | 14.000 | -14.000 te GENROU 1 | 14.536 | 29.072 te GENROU 2 | 14 | 28 te GENROU 3 | 14.000 | 28.000 te GENROU 4 | 14.000 | 28.000 vf GENROU 1 | 3.793 | -3.793 vf GENROU 2 | 4.039 | -4.039 vf GENROU 3 | 4.052 | -4.052 vf GENROU 4 | 3.703 | -3.703 wd TGOV1 1 | 0 | -1 wd TGOV1 2 | 0 | -1 wd TGOV1 3 | 0 | -1 wd TGOV1 4 | 0 | -1 vout EXDC2 1 | 3.793 | 3.793 vout EXDC2 2 | 4.039 | 4.039 vout EXDC2 3 | 4.052 | 4.052 vout EXDC2 4 | 3.703 | 3.703 Initialization for dynamics failed in 0.0418 seconds.
0%| | 0/100 [00:01<?, ?%/s]
Time step reduced to zero. Convergence is not likely. Simulation terminated at t=0.0000 s. Simulation completed in 1.5000 seconds. TimeSeries does not contain any time stamp. Outputs to "kundur_out.lst" and "kundur_out.npz". Outputs written in 0.0073 seconds.
False
ss.dae.ts
<andes.variables.dae.DAETimeSeries at 0x7ff0b18cb4f0>
ss.dae.ts
has four commonly used attributes: t
for time stamps, xy
for variables (differential and then algebraic), z
for discontinuous states, and df
for the dataframe of all.
ss.dae.ts.t
correspond to a row in ss.dae.ts.xy
.ss.dae.ts.xy
correspond to a variable, whose name can be located in ss.dae.xy_name
, for all timestamps.z
is not stored by default unless one enables it before simulation by setting ss.TDS.config.store_z = 1
.df
is not built by default but can be manually triggered after simulation by calling ss.dae.ts.unpack(df=True)
The following are some statistics of the shapes of arrays:
ss.dae.ts.t.shape
(0,)
ss.dae.ts.xy.shape
(0, 0)
len(ss.dae.xy_name)
192
!andes misc -C
_ _ | Version 1.3.4.post6.dev0+g1cc8c20 /_\ _ _ __| |___ ___ | Python 3.8.6 on Linux, 03/18/2021 09:57:48 PM / _ \| ' \/ _` / -_|_-< | /_/ \_\_||_\__,_\___/__/ | This program comes with ABSOLUTELY NO WARRANTY. "/home/hcui7/repos/andes/examples/kundur_full_out.npz" removed. "/home/hcui7/repos/andes/examples/kundur_full_out.lst" removed. "/home/hcui7/repos/andes/examples/kundur_full_out.txt" removed. "/home/hcui7/repos/andes/examples/kundur_out.lst" removed. "/home/hcui7/repos/andes/examples/kundur_out.npz" removed. "/home/hcui7/repos/andes/examples/kundur_out.txt" removed.