Skip to content

API Reference

The pyramses.cfg class defines a simulation scenario: data files, disturbance file, output files, observables, and runtime options.


Create an empty configuration or load one from a previously saved command file:

import pyramses
case = pyramses.cfg() # empty configuration
case = pyramses.cfg("cmd.txt") # load from command file

Load multiple cases in a loop:

import pyramses
list_of_cases = []
for i in range(12):
list_of_cases.append(pyramses.cfg('cmd' + str(i) + '.txt'))

Save the current configuration to a command file. Useful for reproducing a run later.

case.writeCmdFile('cmd.txt')

Save multiple cases in a loop:

for i in range(12):
list_of_cases[i].writeCmdFile('cmd' + str(i) + '.txt')

Data files describe the network topology, dynamic models, and solver settings. At least one must be provided.

Add a data file to the case.

case.addData('dyn_A.dat')
case.addData('settings1.dat')

Remove a specific data file from the case.

case.delData('dyn_A.dat')

Return the list of currently registered data files.

files = case.getData()

Remove all data files from the case.

case.clearData()

Specifies where the simulator writes initialization procedure output.

case.addInit('init.trace')

Return the currently registered initialization file path.

path = case.getInit()

Describes the disturbances to be simulated (generator trips, faults, parameter changes, etc.).

case.addDst('events.dst')

Return the currently registered disturbance file path.

path = case.getDst()

Remove the disturbance file from the case.

case.clearDst()

Specifies the file where time-series simulation results (trajectories) are saved for post-processing. This file is used by pyramses.extractor to access results after the simulation completes.

case.addTrj('output.trj')

Return the currently registered trajectory file path.

path = case.getTrj()

Defines which components and quantities are recorded in the trajectory file.

case.addObs('obs.dat')

Return the currently registered observables file path.

path = case.getObs()

Set the main output trace file for simulation progress logging.

case.addOut('output.trace')

Return the currently registered output trace file path.

path = case.getOut()

Set the continuous trace file. Records Newton solver convergence information at each step. Useful for debugging but can slow down the simulation.

case.addCont('cont.trace')

Return the currently registered continuous trace file path.

path = case.getCont()

Set the discrete trace file. Records discrete events: switching actions from disturbance files, discrete controllers, or discrete variables in injector/torque/exciter/two-port models.

case.addDisc('disc.trace')

Return the currently registered discrete trace file path.

path = case.getDisc()

Remove the discrete trace file from the case.

case.clearDisc()

Runtime observables are displayed live during simulation using Gnuplot.

Add a runtime observable. The following observable types are supported:

BV BUSNAME — Voltage magnitude of a bus:

case.addRunObs('BV 1041')

MS MACHINE_NAME — Rotor speed of a synchronous machine:

case.addRunObs('MS g1')

BPE / BQE / BPO / BQO BRANCH_NAME — Active (P) or reactive (Q) power at the origin (O) or extremity (E) of a branch:

case.addRunObs('BPE 1041-01') # active power at origin of branch 1041-01
case.addRunObs('BQE 1041-01') # reactive power at origin
case.addRunObs('BPO 1041-01') # active power at extremity
case.addRunObs('BQO 1041-01') # reactive power at extremity

ON INJECTOR_NAME OBSERVABLE_NAME — Named observable from an injector model:

case.addRunObs('ON WT1a Pw') # observable Pw from injector WT1a

TO TORQUE_NAME OBSERVABLE_NAME — Named observable from a governor/torque model:

case.addRunObs('TO g1 Pm') # mechanical power from governor of g1

RT RT — Real-time versus simulated-time plot (useful to gauge simulation speed):

case.addRunObs('RT RT')

Remove all runtime observables.

case.clearRunObs()

The pyramses.sim class runs simulations. It wraps the RAMSES dynamic library and supports start/pause/continue, runtime queries, and disturbance injection.


import pyramses
ram = pyramses.sim() # use bundled RAMSES libraries
ram = pyramses.sim(custLibDir='/path/to/') # use custom library directory
ParameterTypeDescription
custLibDirstr or NoneCustom path to the RAMSES library directory. Default: use bundled libraries.

A properly configured pyramses.cfg test case is required before running a simulation.

ram.execSim(case)

execSim(case, t) — start and pause at time t

Section titled “execSim(case, t) — start and pause at time t”

Start the simulation and pause at a specific time (in seconds):

ram.execSim(case, 10.0) # start and pause at t = 10 s

Resume a paused simulation until a specified time:

ram.contSim(20.0) # resume until t = 20 s
ram.contSim(ram.getSimTime() + 60.0) # advance by 60 s from current time
ram.contSim(ram.getInfTime()) # run to the end of the time horizon

Terminate the simulation before reaching the time horizon:

ram.endSim()

When the simulation is paused, the following methods query the current system state.

Return the current simulation time in seconds.

t = ram.getSimTime()

Return the value used as “infinity” (i.e., the end of the simulation time horizon). Pass this to contSim() to run to completion.

t_inf = ram.getInfTime()
ram.contSim(ram.getInfTime())

Return a list of all component names of the given type.

buses = ram.getAllCompNames('BUS') # list of all bus names
gens = ram.getAllCompNames('SYNC') # list of all generator names
injs = ram.getAllCompNames('INJ') # list of all injector names
dctls = ram.getAllCompNames('DCTL') # list of all discrete controller names
branches = ram.getAllCompNames('BRANCH') # list of all branch names
twops = ram.getAllCompNames('TWOP') # list of all two-port names
shunts = ram.getAllCompNames('SHUNT') # list of all shunt names
loads = ram.getAllCompNames('LOAD') # list of all load names

Supported component types: BUS, SYNC, INJ, DCTL, BRANCH, TWOP, SHUNT, LOAD.

Return voltage magnitudes (in pu) for a list of bus names.

ram.execSim(case, 10.0)
bus_names = ['g1', 'g2', '4032']
voltages = ram.getBusVolt(bus_names)

Return voltage phase angles (in radians) for a list of bus names.

phases = ram.getBusPha(bus_names)

Return power flows for a list of branch names. Each entry is [P_from, Q_from, P_to, Q_to] in MW and Mvar.

powers = ram.getBranchPow(['1041-01'])
# powers[0] == [P_from, Q_from, P_to, Q_to]

Get the current value of named observables for a list of components. Lists must be the same length.

comp_type = ['INJ', 'EXC', 'TOR']
comp_name = ['L_11', 'g2', 'g3']
obs_name = ['P', 'vf', 'Pm']
obs = ram.getObs(comp_type, comp_name, obs_name)

Supported model types: EXC (exciter), TOR (governor), INJ (injector), TWOP (two-port), DCTL (discrete controller), SYN (synchronous generator).

Get parameter values for a list of components. Lists must be the same length.

comp_type = ['EXC', 'EXC']
comp_name = ['g1', 'g2']
prm_name = ['V0', 'KPSS']
prms = ram.getPrm(comp_type, comp_name, prm_name)

Disturbances can be added dynamically while the simulation is paused, enabling interactive scenario analysis.

Schedule a disturbance to occur at a given simulation time.

The disturbance description string follows the same syntax as the disturbance file format. See Disturbances for the complete reference.

ram.execSim(case, 80.0)
# Trip generator g7 at t = 100 s
ram.addDisturb(100.0, 'BREAKER SYNC_MACH g7 0')
# Apply a 3-phase fault at bus 4032 and clear it 100 ms later
ram.addDisturb(100.0, 'FAULT BUS 4032 0. 0.')
ram.addDisturb(100.1, 'CLEAR BUS 4032')
# Step change in an LTC setpoint
ram.addDisturb(100.0, 'CHGPRM DCTL 1-1041 Vsetpt -0.05 0')
ram.contSim(ram.getInfTime())

Export the system Jacobian matrix in descriptor form (E, A matrices) at the current pause point. Writes four files to the working directory:

FileContents
jac_val.datNon-zero values
jac_eqs.datEquation names
jac_var.datVariable names
jac_struc.datSparsity structure
ram.execSim(case, 10.0)
ram.getJac()

These files can be used for small-signal stability analysis with the RAMSES Eigenanalysis tool.


The pyramses.extractor class extracts and visualises time-series results from a trajectory file produced during simulation.


Pass the trajectory file path to the extractor:

import pyramses
case = pyramses.cfg('cmd.txt')
# ... run simulation ...
ext = pyramses.extractor(case.getTrj())

Or provide the file path directly:

ext = pyramses.extractor('output.trj')

All extraction methods return objects whose attributes are curve objects (pyramses.cur named tuples). Every curve object has:

AttributeTypeDescription
timenumpy.ndarrayTime values in seconds
valuenumpy.ndarrayObservable values
msgstrDescription string (used as plot legend label)

Display the curve using Matplotlib:

bus = ext.getBus('4044')
bus.mag.plot()

Retrieve voltage time series for a bus. Returns an object with:

AttributeDescription
.magVoltage magnitude (pu)
.phaVoltage phase angle (rad)
bus = ext.getBus('4044')
bus.mag.plot() # voltage magnitude (pu)
bus.pha.plot() # voltage phase angle (rad)

Retrieve the full set of synchronous machine observables. Returns an object with:

AttributeDescription
.PActive power (MW)
.QReactive power (Mvar)
.SRotor speed (pu)
.ARotor angle w.r.t. COI (deg)
.FVField voltage (pu)
.FCField current (pu)
.TMechanical torque (pu)
.ETElectromagnetic torque (pu)
.FWField winding flux
.DDd1 damper flux
.QDq1 damper flux
.QWq2 winding flux
.SCCOI speed
gen = ext.getSync('g1')
gen.P.plot() # active power (MW)
gen.Q.plot() # reactive power (Mvar)
gen.S.plot() # rotor speed (pu)
gen.A.plot() # rotor angle w.r.t. COI (deg)
gen.FV.plot() # field voltage (pu)
gen.FC.plot() # field current (pu)
gen.T.plot() # mechanical torque (pu)
gen.ET.plot() # electromagnetic torque (pu)

Retrieve exciter observables. Available observables depend on the exciter model.

AttributeDescription
.obsdictdict mapping observable name → description
(model-dependent)Access by observable name, e.g. .vf
exc = ext.getExc('g1')
print(exc.obsdict) # list available observables for this model
exc.vf.plot() # field voltage (model-dependent name)

Retrieve governor/torque model observables. Available observables depend on the governor model.

AttributeDescription
.obsdictdict mapping observable name → description
(model-dependent)Access by observable name, e.g. .Pm
gov = ext.getTor('g1')
print(gov.obsdict) # list available observables for this model
gov.Pm.plot() # mechanical power (pu)

Retrieve injector observables. Injectors include renewable energy sources (wind, PV, BESS), loads, and other single-bus components.

AttributeDescription
.obsdictdict mapping observable name → description
(model-dependent)Access by observable name, e.g. .Pw
inj = ext.getInj('WT1a')
print(inj.obsdict) # list available observables
inj.Pw.plot() # wind power (model-dependent name)

Retrieve two-port model observables. Two-port models include HVDC links (LCC and VSC), SVCs, and DC systems.

AttributeDescription
.obsdictdict mapping observable name → description
(model-dependent)Access by observable name, e.g. .P1, .P2
twop = ext.getTwop('hvdc1')
print(twop.obsdict) # list available observables
twop.P1.plot() # active power at terminal 1
twop.P2.plot() # active power at terminal 2

Retrieve discrete controller observables. Discrete controllers include LTC transformers, under-voltage load shedding, phase shifters, etc.

AttributeDescription
.obsdictdict mapping observable name → description
dctl = ext.getDctl('1-1041')
print(dctl.obsdict) # list available observables

Retrieve branch (line/transformer) power flow time series.

AttributeDescription
.PFActive power at FROM end (MW)
.QFReactive power at FROM end (Mvar)
.PTActive power at TO end (MW)
.QTReactive power at TO end (Mvar)
.RMTransformer ratio magnitude
.RATransformer phase angle (deg)
branch = ext.getBranch('1041-01')
branch.PF.plot() # active power at FROM end (MW)
branch.QF.plot() # reactive power at FROM end (Mvar)
branch.PT.plot() # active power at TO end (MW)
branch.QT.plot() # reactive power at TO end (Mvar)
branch.RM.plot() # transformer ratio magnitude
branch.RA.plot() # transformer phase angle (deg)

Display multiple curve objects on the same axes. Each curve’s msg field is used as the legend label.

import pyramses
ext = pyramses.extractor(case.getTrj())
curves = [
ext.getSync('g1').S,
ext.getSync('g2').S,
ext.getSync('g3').S,
]
pyramses.curplot(curves)

import pyramses
# --- Build test case ---
case = pyramses.cfg()
case.addData('dyn_A.dat')
case.addData('settings1.dat')
case.addInit('init.trace')
case.addDst('events.dst')
case.addTrj('output.trj')
case.addObs('obs.dat')
case.addOut('output.trace')
case.addCont('cont.trace')
case.addDisc('disc.trace')
# Runtime observables (Gnuplot required)
case.addRunObs('BV 1041')
case.addRunObs('MS g1')
case.addRunObs('RT RT')
# Save configuration
case.writeCmdFile('cmd.txt')
# --- Run simulation ---
ram = pyramses.sim()
# Start and pause at t = 80 s
ram.execSim(case, 80.0)
# Inject a disturbance dynamically
ram.addDisturb(100.0, 'FAULT BUS 4032 0. 0.')
ram.addDisturb(100.1, 'CLEAR BUS 4032')
# Export Jacobian at this operating point
ram.getJac()
# Run to end
ram.contSim(ram.getInfTime())
# --- Extract results ---
ext = pyramses.extractor(case.getTrj())
# Bus voltages
ext.getBus('4044').mag.plot()
# Generator observables
gen = ext.getSync('g1')
gen.S.plot() # rotor speed
gen.A.plot() # rotor angle
# Branch flows
ext.getBranch('1041-01').PF.plot()
# Plot multiple rotor speeds together
pyramses.curplot([
ext.getSync('g1').S,
ext.getSync('g2').S,
ext.getSync('g3').S,
])
  • Examples — Practical simulation examples and workflows
  • Test Systems — Ready-to-run benchmark systems