Contingency Analysis (CA) is a basic study process to test the
reliability of a network.
For a base case that solves (it means that it converges to a load flow run), the test consists in executing some
network changes like opening a transmission line (a contingency), followed by
a load flow solution and then a process to identify the network elements with
thermal overload or voltage violations.
NERC TPL Standards (TPL-001-4) requires system planners to test the network with
specific type of contingencies (P1 to P7 categories).
|
In PSSe, the activity ACCC allows the execution of
contingency analysis as a process. Check
the PSSe manual for more information.
For a base case, additional data files are prepared prior to
customize the study (minimum set of files):
- *.con file – a text file with all the contingencies to be studied, like all P1 contingencies.
- *.mon file – a text file with the definition of system data to be monitored, like bus voltages and lines overload limits.
- *.sub file – a text file with definition of the group of network elements that will participate in the contingency definition file or the monitoring definition file.
Now, a touch of reality. Contingency analysis are done for multiple base
case (seasonal cases or future year cases) and for different loading conditions
like peak and off-peak loading, as well as for expansion projects or new
generation interconnection studies, or under outage conditions (n-1-1). In
other word, there is a need to run multiple CA runs all the time.
MPjobs is a python-based tool, capable to start multiple
PSSe instances. For a CA study, each PSSe instance would run the same python script to execute the required ACCC
activities but with customized data for each individual run. In this exercise, a
new PSSe instance is activated per base case name (let’us assume that each base
case represents a different loading) with the same CON, MON, SUB files.
The code below (not the final code in the MPjobs release) will run a
single ACCC process, running not in the PSSe GUI but in python, calling all
needed PSSe activities with API calls. A module JCtools, included with the MPjobs release, provides common python function like read a file, process strings, etc. The CA run outcome will be a *.acc binary file from which monitoring data can
be extracted later using other PSSe tools like pssearrays.py:
# run_accc1.py
#***************************************************
#***************************************************
#** Set paths,
import modules, define run vars
#{-group0 – to be
commented/deleted when using with MPjobs----------}
import os, sys
import time
sys.path.append('SCRIPTs\\')
import JCtools
My =
JCtools.readIni('mpaccc.ini')
My['XVAR'] = 'savnw'
#{-end of group0------------------------------------------------------------------}
time1 = time.clock()
import JCtools
if
My['PSSEVERSION']==34:
import psse34
else:
sys.path.append(My['PSSEPATH'])
for x in sys.path:
print x
import psspy
psspy.psseinit(My['BUSDIM'])
#import redirect
#redirect.psse2py()
#__________________________________________________________________
def
DFXmake(MySUB,MyMON,MyCON,MyDFX,dxoption):
import psspy
psspy.dfax(dxoption,MySUB,MyMON,MyCON,MyDFX)
return
def
ACCArun(tolerance,lfoption,MyDFX,MyACC):
import psspy
#psspy.accc(0.5,[1, 0, 1, 1, 1, 0,
0],MyDFX,MyACC,"")
psspy.accc(tolerance,lfoption,MyDFX,MyACC,"")
return
##################################################################
# main:
#MySAV = My['MYSAV']
MySUB = My['MYSUB']
MyMON = My['MYMON']
MyCON = My['MYCON']
#MyDFX = My['MYDFX']
#MyACC = My['MYACC']
dxoption = My['DXOPTION']
tolerance =
My['TOLERANCE']
lfoption = My['LFOPTION']
iterations=
My['ITERATIONS']
#__________________________________________________________________
_i =
psspy.getdefaultint()
_f =
psspy.getdefaultreal()
_s =
psspy.getdefaultchar()
zyxvars = JCtools.ZYXvars(My) #XYZ vars=
[studyi,[xvarpath,xvarkey],[yvarpath,yvarkey],[zvarpath,zvarkey],zyxmsg]
studyi=
zyxvars[0][0]
xvarpath =
zyxvars[1][0]
xvarkey = zyxvars[1][1]
zyxmsg = zyxvars[-1]
#***************************************************
#** Set file names:
My['MYSAV'] = '%s%s'%(xvarpath,My['XVAR'])
My['MYDFX'] = '%s%s.dfx'%(My['ACCCPATH'],studyi)
My['MYACC'] = '%s%s.acc'%(My['ACCCPATH'],studyi)
MySAV = My['MYSAV']
MyDFX = My['MYDFX']
MyACC = My['MYACC']
My['LOGFILE']=
'%s%s.log'%(My['LOGSPATH'],studyi)
#***************************************************
psspy.progress_output(2,My['LOGFILE'],[0,0])
psspy.prompt_output(2,My['LOGFILE'],[0,0])
#***************************************************
# run a simulation:
print zyxmsg
psspy.time(0)
psspy.case(MySAV) # basecase name
psspy.solv()
#prepare a DFX file
if not
os.path.isfile(MyDFX):
DFXmake(MySUB,MyMON,MyCON,MyDFX,dxoption)
#update solution
parameters
psspy.solution_parameters_2([_i,iterations,_i],
[_f,_f,_f,_f,_f,_f,_f,_f,_f,_f,_f,_f,_f,_f,_f,_f,_f,_f])
#execute a ACCA run
ACCArun(tolerance,lfoption,MyDFX,MyACC)
psspy.time(0)
My['RETURN'] =
'%12.3f'%(time.clock() - time1)
To run it, open a DOS window and at the prompt (>), enter:
python SCRIPTs\runACCC1.py
python SCRIPTs\runACCC1.py
[or if the python path is not defined in the system PATH
c:\python27\python SCRIPTs\runACCC1.py
]
c:\python27\python SCRIPTs\runACCC1.py
]
Some code modifications will be done to make it usable with MPjobs:
- All study variables are ‘inherited’ when MPjobs calls this script, therefore the code block group0 that reads data in will be commented.
- A base case name variable value is assigned to the X-variable, My['XVAR'] , the changing variable within the multiple MPjobs runs.
Because this code will run outside the PSSe GUI, the PSSPY
module is loaded explicitly.
The modified code, ready for use with MPjobs is saved as
SCRIPTs\run_ACCC1D.py
# run_accc1D.py
#***************************************************
#***************************************************
#** Set paths,
import modules, define run vars
#{----------------------------------------------------------------------------}
#import os, sys
#import time
#sys.path.append('SCRIPTs\\')
#import JCtools
#My =
JCtools.readIni('mpaccc.ini')
#My['XVAR'] =
'savnw'
#{----------------------------------------------------------------------------}
time1 = time.clock()
import JCtools
if My['PSSEVERSION']==33:
import psse33
elif My['PSSEVERSION']==34:
import psse34
else:
import psse33
elif My['PSSEVERSION']==34:
import psse34
else:
sys.path.append(My['PSSEPATH'])
#for x in sys.path: print x
import psspy
psspy.psseinit(My['BUSDIM'])
#import redirect
#redirect.psse2py()
#______________________________________________________________
def
DFXmake(MySUB,MyMON,MyCON,MyDFX,dxoption):
import psspy
psspy.dfax(dxoption,MySUB,MyMON,MyCON,MyDFX)
return
def
ACCArun(tolerance,lfoption,MyDFX,MyACC):
import psspy
#psspy.accc(0.5,[1, 0, 1, 1, 1, 0,
0],MyDFX,MyACC,"")
psspy.accc(tolerance,lfoption,MyDFX,MyACC,"")
return
###############################################################
# main:
#MySAV = My['MYSAV']
MySUB = My['MYSUB']
MyMON = My['MYMON']
MyCON = My['MYCON']
#MyDFX = My['MYDFX']
#MyACC = My['MYACC']
dxoption = My['DXOPTION']
tolerance =
My['TOLERANCE']
lfoption = My['LFOPTION']
iterations=
My['ITERATIONS']
#______________________________________________________________
_i =
psspy.getdefaultint()
_f =
psspy.getdefaultreal()
_s = psspy.getdefaultchar()
zyxvars = JCtools.ZYXvars(My) #XYZ vars=
[studyi,[xvarpath,xvarkey],[yvarpath,yvarkey],[zvarpath,zvarkey],zyxmsg]
studyi=
zyxvars[0][0]
xvarpath =
zyxvars[1][0]
xvarkey = zyxvars[1][1]
zyxmsg = zyxvars[-1]
#***************************************************
#** Set file names:
My['MYSAV'] = '%s%s'%(xvarpath,My['XVAR'])
My['MYDFX'] = '%s%s.dfx'%(My['ACCCPATH'],studyi)
My['MYACC'] = '%s%s.acc'%(My['ACCCPATH'],studyi)
MySAV = My['MYSAV']
MyDFX = My['MYDFX']
MyACC = My['MYACC']
My['LOGFILE']=
'%s%s.log'%(My['LOGSPATH'],studyi)
#***************************************************
psspy.progress_output(2,My['LOGFILE'],[0,0])
psspy.prompt_output(2,My['LOGFILE'],[0,0])
#***************************************************
# run a simulation:
print zyxmsg
psspy.time(0)
psspy.case(MySAV) # basecase name
psspy.solv()
#prepare a DFX file
if not
os.path.isfile(MyDFX):
DFXmake(MySUB,MyMON,MyCON,MyDFX,dxoption)
#update solution
parameters
psspy.solution_parameters_2([_i,iterations,_i],
[_f,_f,_f,_f,_f,_f,_f,_f,_f,_f,_f,_f,_f,_f,_f,_f,_f,_f])
#execute a ACCA run
ACCArun(tolerance,lfoption,MyDFX,MyACC)
psspy.time(0)
My['RETURN'] =
'%12.3f'%(time.clock() - time1)
The ‘mpACCC.ini’
file has the input data needed for this run, including the name of the target
python script that performs the CA study:
/mpACCC.ini for mpjobs + run_accc1D.py
/run accc
[scenario]
title1
= SAVNW
title2
= SB ctgs
studyname= SAVNW
StudyType= accc
CPU = 2
[myvars]
//path ending with '\' required
//Yfile
= CASEs\cases.lst
Xfile
= CASEs\sav.lst
Script
= SCRIPTs\run_accc1D.py
ACCCpath = ACCC\
LOGspath = LOGs\
//Xvecfc = 0.1
//MySAV = CASEs\SAVNW.sav
MySUB = ACCC\SAVNW.sub
MyMON = ACCC\SAVNW.mon
MyCON = ACCC\SAVNW.con
//MyDFX = ACCC\SAVNW.dfx
//MyACC = ACCC\SAVNW.acc
dxoption
= [1,1]
tolerance = 0.5
lfoption
= [1,0,0,0,0,0,0]
iterations= 30
BusDim
= 80000
PsseVersion= 33
PssePath
= C:\Program Files (x86)\PTI\PSSE33\PSSBIN
[notes]
/comments start with or from /
/path ending with '\' required
/in-line comments are stripped before reading
keyword value
/string shall be empty, not set to be =''
which is read to has two chars of '
A text file ‘sav.lst ’ (declared as XFILE in the INI file) contains the names of the base cases to be used:
Sav.lst:
Savnw
Savnw32
File names can have
full paths or new vars can be defined to hold those path values.
MPjobs will read the
INI file, and from the ‘Xfile’ variable, open the list of base cases, assigning
each base case name entry to the My['XVAR'] variable and then call the target script.
Now the target python
script (‘run_accc1D.py’) contains the code to run PSSe activities [execution of
DFAX and ACCC activities], and uses the data made available by MPjobs throught
the dictionary ‘My’. This target python code is able to parse data and
create new variables based on the received independents variable, like creating
unique file names to output data:
xvarpath=
os.path.dirname(My['XFILE'])
#=CASEs\
xvarkey,xext =
os.path.splitext(My['XVAR']) #= savnw & ‘’
..
My['MYSAV'] = '%s\%s'%(xvarpath,My['XVAR']) # = CASEs\ savnw
With all this information, we are able to locate the base case to open it for a PSSe CA run.
To run this demo, open a DOS window and type command + inifile, without extension:
C:..>mpjobs mpaccc
Once the parallel runs
are completed, some output files, *.dfx, *.acc, will be created in the “ACCC”
folder.
[You can download the code from: MPjobs at my Google Drive site Once you select “MPjobs_jconto_xxxx.zip”, an icon on the top-center screen will perform the download. The demo data are set for PSSe v.33 but an update of the "psseversion" and "pssepath" in the INI file will make it usable for v. 34]