Skip to content

1.1. Getting Started

Julius Susanto edited this page Mar 24, 2015 · 14 revisions

Installation

First, make sure you have Python 3.2+, PYPOWER and the SciPy stack installed.

PYPOWER-Dynamics can be installed using Pip:

$ pip install pypower-dynamics

Alternatively, download the package (zip file) and install:

$ python setup.py install

Creating your first study case

A typical PYPOWER-Dynamics study case includes the following files:

  • PYPOWER case (*.py): a base PYPOWER load flow case describing the network and its steady-state conditions
  • Controller file(s) (*.dyn): definitions for dynamic control systems such as AVRs, governors, power system stabilisers, etc
  • Machine file(s) (*.mach): dynamic parameters for synchronous machines
  • Event file (*.evnt): list of events that will occur during the simulation
  • Recorder file (*.rcd): list of signals or state variables that will be recorded during the simulation
  • PYPOWER-Dynamics script (*.py): the main Python script that sets up the PYPOWER-Dynamics case, coordinates the simulation and collects the recorded results

In this short tutorial, we will put together a simple single-machine infinite bus (SMIB) study case, which will highlight the steps required to get a PYPOWER-Dynamics simulation up and running.

Controller File

First let's create a simple AVR comprising summation, lead-lag and lag blocks. This is done by writing a plain-text Controller file, which defines the block structure as well as the initialisation of the signal and state variables.

# Test AVR Model
    
ID = AVR1
    
#########################
# Controller Definition #
#########################
    
Vref = REF()
Vt = INPUT(Vt,GEN1)
N3 = SUM(Vref,-Vt)
N4 = LDLAG(N3,1,10)
N5 = LAG(N4,100,0.1)
Vfd = OUTPUT(N5,GEN1)
    
##################
# Initialisation #
##################
INIT
SIGNAL = N5 = MULT(Vfd,1)
SIGNAL = N4 = MULT(Vfd,0.01)
SIGNAL = Vref = SUM(Vt,N4)
STATE = N5 = MULT(Vfd,0.01)
STATE = N4 = MULT(Vfd,0.01)

Refer to the Controller Files page for more details.

Machine File

Next, we'll define the synchronous machine parameters, again by a plain-text Machine file.

# Test machine parameters
    
ID = GEN1
GEN_NO = 1
MVA_Rating = 100
    
Ra = 0.0
Xa = 0.0
Xd = 2.29
Xq = 2.18
Xdp = 0.25
Xqp = 0.25
Xdpp = 0.18
Xqpp = 0.18
Td0p = 13.1979
Tq0p = 3.2423
Td0pp = 0.0394
Tq0pp = 0.1157
H = 5.8

Refer to the Machine Files page for more details.

Event File

A dynamic simulation should have events, otherwise nothing happens during the simulation run! So let's put a step on the voltage reference of the AVR at t=1s and then remove that step at t=8s. This is done in a plain-text Events file as follows:

# Event Stack for SMIB test case
# Event time (s), Event type, Object ID, [Parameters]
     
1.0, SIGNAL, AVR1, Vref, 1.06
8.0, SIGNAL, AVR1, Vref, 1.00

Refer to the Event Files page for more details.

Recorder File

A lot of data is generated during a dynamic simulation and most of the time, we are only interested in a subset of them. So we can define the variables that we want to monitor using a plain-text Recorder file.

In the example below, we want to record the generator terminal voltage and the generator state variable Ed'':

# Recorder set for SMIB test case
# Record ID, Object ID, Signal Name, Signal/State
    
GEN1-Vt,     GEN1,  Vt,   SIGNAL 
GEN1-Edpp,   GEN1,  Edpp, STATE

Refer to the Recorder Files page for more details.

PYPOWER-Dynamics script

The main PYPOWER-Dynamics script sets up and coordinates the simulation case.

Firstly, let's import the relevant PYPOWER-Dynamics modules:

# Dynamic model classes
from pydyn.controller import controller
from pydyn.sym_order6a import sym_order6a
from pydyn.sym_order4 import sym_order4
from pydyn.ext_grid import ext_grid

# Simulation modules
from pydyn.events import events
from pydyn.recorder import recorder
from pydyn.run_sim import run_sim

Some external modules should also be imported:

# External modules
from pypower.loadcase import loadcase
import matplotlib.pyplot as plt
import numpy as np

Let's now set up the PYPOWER-Dynamics program options:

# Program options
dynopt = {}
dynopt['h'] = 0.01                # step length (s)
dynopt['t_sim'] = 12              # simulation time (s)
dynopt['max_err'] = 0.0001        # Maximum error in network iteration (voltage mismatches)
dynopt['max_iter'] = 25           # Maximum number of network iterations
dynopt['verbose'] = False         # option for verbose messages
dynopt['fn'] = 50                 # Nominal system frequency (Hz)
dynopt['iopt'] = 'runge_kutta'    # Integrator option 

Next, we load the PYPOWER case to get our base network model:

# Load PYPOWER case
ppc = loadcase('smib_case.py')

The dynamic models are now created. We will build the AVR model and the synchronous machine model from the earlier defined Controller and the Machine files respectively. The grid is defined here as a voltage source behind a reactance of 0.1pu (on a 100MVA base) and with a large inertia (99999s).

# Create dynamic model objects
oCtrl = controller('smib.dyn', iopt)
oMach = sym_order6a('smib_round.mach', iopt) 
oGrid = ext_grid('GRID1', 0, 0.1, 99999, iopt)

A dictionary of the dynamic model elements now needs to be built:

# Create dictionary of elements
elements = {}
elements[oCtrl.id] = oCtrl
elements[oMach.id] = oMach
elements[oGrid.id] = oGrid

The Events and Recorder files are imported as follows:

# Create event stack
oEvents = events('smib_events.evnt')
    
# Create recorder object
oRecord = recorder('smib_recorder.rcd')

The simulation is then run and results are captured in the oRecord object:

# Run simulation
oRecord = run_sim(ppc,elements,dynopt,oEvents,oRecord)

Lastly, we can plot the generator voltage using the Matplotlib library as follows:

# Plot variables
plt.plot(oRecord.t_axis,oRecord.results['GEN1:Vt'])
plt.xlabel('Time (s)')
plt.ylabel('GEN1:Vt (pu)')
plt.show()

Run the script and the following plot should appear: