Run DIgSILENT PowerFactory through the Python API – kickstart your PowerFactory automatization
Most people who work with DIgSILENT PowerFactory know that sometimes it is convenient to automatize certain tasks to avoid tedious manual work. However, automatization is also key if you want to carry out a large number of simulations with varying parameters. Luckily, DIgSILENT PowerFactory comes with an API interface for Python to do precisely that.
This post gives a short overview of the Python API for DIgSILENT and provides the basic Python code to jump-start your DIgSILENT PowerFactory automatization.
Before we continue…
For the demonstration, I use a standard nine-bus system as shown below. The nine-bus system is available in the example projects in PowerFactory.
Install Python (if not installed yet)
For users who have not yet installed Python, I recommend installing the Anaconda distribution. It comes with all the needed packages including Spyder, which is a convenient editor to use with Python.
Advantages: open-source, easy to install, includes the most important packages
Load the PowerFactory application with Python
At the beginning of every Python script, you need to load the PowerFactory application. The code below loads the PowerFactory application and throws an error if unsuccessful. Important: a) replace the path (shown in red) with the path to the Python directory of your PowerFactory installation as indicated, b) close PowerFactory before running the script (it is not possible to run the script when an instance of PowerFactory is open).
import sys
sys.path.append(r'C:\Program Files\DIgSILENT\PowerFactory 2021 SP1\Python\3.8')
if __name__ == "__main__":
import powerfactory as pf
app = pf.GetApplication()
if app is None:
raise Exception('getting Powerfactory application failed')
Run a load flow
The next step is to define the project name and study case. Then the script is basically ready to run a load flow.
#define project name and study case
projName = '_TSI_Nine-bus System'
study_case = '01_Study_Case.IntCase'
#activate project
project = app.ActivateProject(projName)
proj = app.GetActiveProject()
#get the study case folder and activate project
oFolder_studycase = app.GetProjectFolder('study')
oCase = oFolder_studycase.GetContents(study_case)[0]
oCase.Activate()
#get load flow object and execute
oLoadflow=app.GetFromStudyCase('ComLdf') #get load flow object
oLoadflow.Execute() #execute load flow
Print the results for generators, lines, and buses
Running a load flow is quite useless without seeing any results, right? That is why below you can find code on how to get and print the load flow results of generators, lines, and buses. Results for other elements can be added similarly.
#get the generators and their active/reactive power and loading
Generators = app.GetCalcRelevantObjects('*.ElmSym')
for gen in Generators: #loop through list
name = getattr(gen, 'loc_name') # get name of the generator
actPower = getattr(gen,'c:p') #get active power
reacPower = getattr(gen,'c:q') #get reactive power
genloading = getattr(gen,'c:loading') #get loading
#print results
print('%s: P = %.2f MW, Q = %.2f MVAr, loading = %.0f percent' %(name,actPower,reacPower,genloading))
print('-----------------------------------------')
#get the lines and print their loading
Lines=app.GetCalcRelevantObjects('*.ElmLne')
for line in Lines: #loop through list
name = getattr(line, 'loc_name') # get name of the line
value = getattr(line, 'c:loading') #get value for the loading
#print results
print('Loading of the line: %s = %.2f percent' %(name,value))
print('-----------------------------------------')
#get the buses and print their voltage
Buses=app.GetCalcRelevantObjects('*.ElmTerm')
for bus in Buses: #loop through list
name = getattr(bus, 'loc_name') # get name of the bus
amp = getattr(bus, 'm:u1') #get voltage magnitude
phase = getattr(bus, 'm:phiu') #get voltage angle
#print results
print('Voltage at %s = %.2f pu %.2f deg' %(name,amp,phase))
Run an RMS simulation
In the following, I will show you how to run RMS simulations via the Python API. Just adapt the project name and the study case and you are ready to go.
#define project name and study case
projName = '_TSI_nine_bus_system'
study_case = '01_Study_Case.IntCase'
#activate project
project = app.ActivateProject(projName)
proj = app.GetActiveProject()
#get the study case folder and activate project
oFolder_studycase = app.GetProjectFolder('study')
oCase = oFolder_studycase.GetContents(study_case)[0]
oCase.Activate()
# calculate initial conditions
oInit = app.GetFromStudyCase('ComInc') #get initial condition calculation object
oInit.Execute()
#run RMS-simulation
oRms = app.GetFromStudyCase('ComSim') #get RMS-simulation object
oRms.Execute()
Retrieve RMS results from PowerFactory in Python
In this part, I will show you how to retrieve the results of the RMS simulation as pandas dataframe in Python. This can be very handy (for example) if you want to change the parameters of the PowerFactory model based on the RMS simulation results.
The script below shows a function to retrieve the results from the RMS simulation as pandas dataframe. The function also uses numpy and pandas commands, therefore, don’t forget to import them before.
The function retrieves the following variables:
- simulation time
- active/reactive power of generator 1
- terminal voltage of generator 1
- voltage of bus 1
- loading of line 4-5
If you want to retrieve other variables, simply adapt the code as needed.
import numpy as np
import pandas as pd
def getResults():
#get result file
elmRes = app.GetFromStudyCase('*.ElmRes')
app.ResLoadData(elmRes)
#Get number of rows and columns
NrRow = app.ResGetValueCount(elmRes,0)
#get objects of interest
oSG1 = app.GetCalcRelevantObjects('G1.ElmSym')[0]
oBus1 = app.GetCalcRelevantObjects('Bus 1.ElmTerm')[0]
oLine4_5 = app.GetCalcRelevantObjects('Line 4-5.ElmLne')[0]
#Get index of variable of interest
ColIndex_time = app.ResGetIndex(elmRes,elmRes,'b:tnow')
ColIndex_ut = app.ResGetIndex(elmRes,oSG1,'s:ut')
ColIndex_P = app.ResGetIndex(elmRes,oSG1,'s:P1')
ColIndex_Q = app.ResGetIndex(elmRes,oSG1,'s:Q1')
ColIndex_speed = app.ResGetIndex(elmRes,oSG1,'s:xspeed')
ColIndex_u_bus1 = app.ResGetIndex(elmRes,oBus1,'m:u')
ColIndex_loading_line_4_5 = app.ResGetIndex(elmRes,oLine4_5,'c:loading')
#pre-allocate result variables
result_time = np.zeros((NrRow,))
result_ut = np.zeros((NrRow))
result_P = np.zeros((NrRow))
result_Q = np.zeros((NrRow))
result_speed = np.zeros((NrRow))
result_u_bus1 = np.zeros((NrRow))
result_loading_line_4_5 = np.zeros((NrRow))
#get results for each time step
for i in range(NrRow):
result_time[i] = app.ResGetData(elmRes,i,ColIndex_time)[1]
result_ut[i] = app.ResGetData(elmRes,i,ColIndex_ut)[1]
result_P[i] = app.ResGetData(elmRes,i,ColIndex_P)[1]
result_Q[i] = app.ResGetData(elmRes,i,ColIndex_Q)[1]
result_speed[i] = app.ResGetData(elmRes,i,ColIndex_speed)[1]
result_u_bus1[i] = app.ResGetData(elmRes,i,ColIndex_u_bus1)[1]
result_loading_line_4_5[i] = app.ResGetData(elmRes,i,ColIndex_loading_line_4_5)[1]
results = pd.DataFrame()
results['time'] = result_time
results['P'] = result_P
results['Q'] = result_Q
results['ut'] = result_ut
results['speed'] = result_speed
results['u_bus1'] = result_u_bus1
results['loading_line_4_5'] = result_loading_line_4_5
return results
#query results
RES = getResults()
The following screenshot shows an example of the pandas dataframe with the results of the RMS simulation. So all the variables defined in the getResults() function are available neatly in tabular format.
You can download the complete Python script of this post by clicking the banner at the end of the post.
I hope you find this article insightful. Consider leaving a comment to let me know your thoughts on the topic.
More insights within energy are to follow in the next article.
Btw, have you also checked how to query data from the ENTSO-E transparency platform? If not, find it here: Query data from ENTSO-E transparency platform
Michael
Nice! I’m trying to use the files but I only have acces to 2018 PowerFactory version. Could you share the .pdf in this version? I will appreciate it.
Regards,
Hi Francisco, now I am using PF 2021 where it is not possible to export to version 2018.
The easiest way for you would be to just load the nine-bus system from PF 2018. It is available there as well.
All the best,
Michael
How do you run for all three generator at the same time?
Hi Michael,
the load flow and the RMS calculation automatically consider all components that are in-service.
All the best,
Michael
The RMS simulation displays result for Generator 1 only.
My question is how can you create a “for loop” to display result for all 3 generators at the same time
In the function “def getResults():” at the beginning of script it is defined which variables to retrieve from the RMS simulation from PowerFactory. There you can define all desired variables. For generators you can follow the example of the definition for G1.
thanks alot.
I sent you an email
Hey, I’m getting an error at the ‘oCase = oFolder_studycase.GetContents(study_case)[0]’ line: AttributeError: ‘NoneType’ object has no attribute ‘GetContents’… any idea what’s causing this/how to fix this? Thx!
Hi Meg, sorry for the late reply. The error means that the study case folder could not be found. Maybe the project could not be loaded…