You are on page 1of 16

PSSe runs in parallel

ERCOT
José Conto

NATF Modeling Practices Group Workshop


June 3-4, 2015 Dallas, TX

No Representation or Warranty
The NATF makes no representation or warranty, either express or implied, as to the accuracy or completeness of the information
contained in this document.
main.py

Processes in Series Scenario

Apply Event
Scenario

PSSe Module + Reports


Apply Contingency run.py

Load Flow Y
More Events?

Reports N

done Y
More Scenarios?

done
2
3
4
Processes in Parallel
Study data

Jobs manager

CPU 1 CPU 2 CPU N

Scenario Scenario Scenario

Apply Contingency i+1 Apply Contingency i+2 Apply Contingency i+n

… Load Flow
Load Flow Load Flow

Reports Reports Reports

done done done

5
PSSe Dynamics in Parallel

CPU 1
*.out
run_E1.py *.log
Study data
*.ini input CPU 2
Case, dyr,… *.out
run_E2.py
*.log

MPjobs .
.
.
CPU N
*.out
run_EN.py
*.log
Events

6
MPjobs.py
/mpjobs.ini
import multiprocessing case = CASES\savnw_flat33
import JCtools Script = SCRIPTs\run_faults.py
Xfile = events\P1.lst
def run_py(My):
#call py code to exec a single process run
Channels = scripts\channels.idv
execfile(My['SCRIPT'],globals(),locals()) Outspath = OUTs\
return simtime = 10.0
PssePath = ….
def main():
My = JCtools.readIni(sys.argv[1])
/P1.lst
pool= multiprocessing.Pool()
for xvar in open(My['XFILE']): SB1_b152.idv
My['XVAR'] = … SB1_b153.idv
pool.apply_async(run_py, args = (My, ), ) SB2_b154.idv
time.sleep(1) …
pool.close()
pool.join() /SB1_b152.idv
RUN
1.0,99,15,0
BAT_DIST_BUS_FAULT, 152, …
….
7
Large Network test
Tn
PSSe v33,
7000-bus dynamic case,
16 normal clearing faults
for 5 sec. simulation,
1/4 cycle step size,
busdim = 80k,
3249 channels
[Win7, 8 Gb ram, 8 cpu]

CPU’s
time sec CPU Time norm.
3386.13 1 1
1234.89 2 0.36
786.64 4 0.23
581.68 8 0.17
8
Python code – running in the GUI
# run0.py
#_____________________________________________
#psspy.progress_output(2,"LOGs\SB1_b152.log",[2,0])
psspy.case("CASEs\savnw_flat33_cnv.sav")
psspy.rstr("CASEs\savnw_flat33.snp")
psspy.runrspnsfile('SCRIPTs\channels.idv')
psspy.dynamics_solution_params([99,_i,_i,_i,_i,_i,_i,_i],
[ _f,_f, 0.004, 0.016,_f,_f,_f,_f],"")
psspy.set_relang(1,101,r"""1""")
psspy.strt(1,"OUTs\SB1_b152.out")
psspy.runrspnsfile('EVENTs\SB1_b152')
psspy.run(0, 5.0,99,9,0)

9
Python code – running in Python
# run1.py (continue)
import os, sys psspy.time(0)
psseversion = 34 _i = psspy.getdefaultint()
If psseversion == 34: _f = psspy.getdefaultreal()
import psse34 _s = psspy.getdefaultchar()
else: #_________________________________________
sys.path.append('C:\Program Files (x86)\PTI\PSSE33\ ____
PSSBIN') EVENTFILE= r"""EVENTs\\SB1_b152"""
import psspy CNVFILE = r"""CASEs\savnw_flat33_cnv.sav"""
psspy.psseinit(80000) SNAPFILE = r"""CASEs\savnw_flat33.snp"""
#import redirect CHANNELS = r"""SCRIPTs\channels.idv"""
#redirect.psse2py() LOGFILE = r"""LOGs\SB1_b152.log"""
#_________________________________________ OUTFILE = r"""OUTs\SB1_b152.out"""
__ #_________________________________________
def runscript(myscript): ____
import psspy psspy.progress_output(2,LOGFILE,[2,0])
if os.path.isfile(myscript): psspy.case(CNVFILE)
root,ext = os.path.splitext(myscript) psspy.rstr(SNAPFILE)
if ext.upper()=='.PY': runscript(CHANNELS)
execfile(myscript) psspy.dynamics_solution_params([99,_i,_i,_i,_i,_
elif ext.upper()=='.IDV': i,_i,_i],
psspy.runrspnsfile(myscript) [ _f,_f, 0.004,
elif ext.upper()=='.IRF': 0.016,_f,_f,_f,_f],"")
psspy.runiplanfile(myscript) psspy.set_relang(1,101,r"""1""")
psspy.strt(1,OUTFILE)
psspy.runrspnsfile(EVENTFILE)
psspy.run(0, 5.0,99,9,0) 10
Python code – running in MPjobs

The final code ready to run in MPjobs is run_faults_1D.py

1. The My dictionary contains all study data defined or read by


MPjobs

2. The variable(s) that change with every run are assigned (Xvar,
Yvar, Zvar)

3. Other variables are updated with corresponding My variables

11
Python code – run_faults1D.py
# run_faults1D.py – 4 MPjobs.py & MPjobs.ini (continue)
time1 = time.clock() _i = psspy.getdefaultint()
import JCtools _f = psspy.getdefaultreal()
if My['PSSEVERSION']==34: _s = psspy.getdefaultchar()
import psse34 zyxvars = JCtools.ZYXvars(My)
else: zyxvarkey= zyxvars[0]
sys.path.append(My['PSSEPATH']) xvarpath = zyxvars[1][0]
import psspy xvarkey = zyxvars[1][1]
psspy.psseinit(My['BUSDIM']) zyxmsg = zyxvars[-1]
#import redirect #********************************************
#redirect.psse2py() # Set file names:
#______________________________________ My['CNVFILE'] = '%s_cnv.sav'%My['CASE']
_____ My['SNAPFILE'] = '%s.snp'%My['CASE']
def runscript(myscript): My['EVENTFILE']= '%s%s.idv'%(xvarpath,xvarkey)
import psspy My['OUTFILE'] = '%s%s.out'%
if os.path.isfile(myscript): (My['OUTSPATH'],zyxvarkey)
root,ext = os.path.splitext(myscript) My['LOGFILE'] = '%s%s.log'%
if ext.upper()=='.PY': (My['LOGSPATH'],zyxvarkey)
execfile(myscript) #____________________________________________
elif ext.upper()=='.IDV': _
psspy.runrspnsfile(myscript)
elif ext.upper()=='.IRF':
psspy.runiplanfile(myscript)

12
Python code – run_faults1D.py (continue)
(continue)

psspy.progress_output(2,My['LOGFILE'],[0,0])
psspy.prompt_output(2,My['LOGFILE'],[0,0])
#***************************************************
# run a dynamic simulation:
print zyxmsg
psspy.time(0)
psspy.case(My['CNVFILE'])
psspy.rstr(My['SNAPFILE'])

runscript(My['CHANNELS'])
psspy.dynamics_solution_params([My['ITERATION'],_i,_i,_i,_i,_i,_i,_i],
[My['ACCELERATIONF'],_f,
My['INTEGRATIONSTEP'],My['FREQFACTOR'] ,_f,_f, _f,_f],'')
psspy.set_relang(1,My['GENRELANG'],str(My['GENIDRELANG']))
psspy.strt(0,My['OUTFILE'])
runscript(My['EVENTFILE'])
psspy.run(0,My['SIMTIME'],99,9,0)
psspy.time(0)
My['RETURN'] = '%12.3f'%(time.clock() - time1)

13
1D->2D->3D runs
MPjobs can process up to three loops of Z, Y, X vars:

- 1D runs: a single list of variables, in addition to other study data.


(i.e.: In dynamics runs, a list of faults names = X vars)

- 2D runs: two independent lists of variables


(i.e.: In dynamics runs, a list of faults names = X vars and
a list of base case names = Y vars)

- 3D runs: three independent lists of variables


(i.e.: In dynamics runs, a list of faults names = X vars,
a list of base case names = Y vars, and
a list of a study region load levels = Z vars)

14
demo sets
• Run_accc1D: steady state ACCC runs for several base cases.
run it as C:..>mpjobs mpaccc

• Run_faults_1D: transient runs for several fault locations.


run it as C:..>mpjobs (<- ini file name defaults to
mpjobs.ini)

• Run_faults_2D: transient runs for different fault locations


and for different base cases.
run it as C:..>mpjobs mp2d

• Grun: IEESGO model parameter changed within a range to


get governor response under Grun tests.
run it as C:..>mpjobs grun

15
• do you MPjobs?

José Conto
jconto@ieee.org

16

You might also like