471 lines
15 KiB
Python
471 lines
15 KiB
Python
|
|
|
|
import sys
|
|
import os
|
|
|
|
path_PF = r"C:\Program Files\DIgSILENT\PowerFactory 2021 SP2\Python\3.10"
|
|
os.environ['PATH'] = path_PF + ";" + os.environ['PATH']
|
|
os.add_dll_directory(path_PF)
|
|
sys.path.append(path_PF)
|
|
|
|
import powerfactory as pf
|
|
|
|
app = pf.GetApplication()
|
|
|
|
print(app)
|
|
|
|
user = app.GetCurrentuser()
|
|
project = app.ActivateProject('Nine-bus System') # Nombre del proyecto
|
|
prj = app.GetActiveProject()
|
|
|
|
|
|
|
|
|
|
import sys
|
|
import os
|
|
|
|
path = r'C:\Program Files\DIgSILENT\PowerFactory 2021 SP2\Python\3.10'
|
|
os.environ['PATH'] += (";" + path)
|
|
sys.path.append(path)
|
|
|
|
import powerfactory as pf
|
|
|
|
app = pf.GetApplication()
|
|
if app is None:
|
|
raise Exception('getting Powerfactory application failed')
|
|
|
|
# app.Show()
|
|
|
|
user = app.GetCurrentUser()
|
|
projects = user.GetContents('*.IntPrj', 0)
|
|
names = [pro.GetAttribute("loc_name") for pro in projects]
|
|
|
|
res = app.ActivateProject("ProyectoPrueba")
|
|
if res == 1: # no existe y hay crearlo
|
|
proj = app.CreateProject("ProyectoPrueba", "GridNueva")
|
|
else:
|
|
proj = app.GetActiveProject()
|
|
|
|
#########
|
|
# MODEL #
|
|
#########
|
|
# Network model
|
|
netmod = app.GetProjectFolder('netmod')
|
|
# Network data
|
|
netdata = app.GetProjectFolder('netdat')
|
|
# Diagrams
|
|
diag_fold = app.GetProjectFolder('dia')
|
|
# Variations
|
|
var_fold = app.GetProjectFolder('scheme')
|
|
|
|
###########
|
|
# LIBRARY #
|
|
###########
|
|
# Equipment library
|
|
equip = app.GetProjectFolder('equip')
|
|
# lines_fold = equip.GetContents('Lines')[0][0]
|
|
# User defined models
|
|
main_lib = equip.GetParent()
|
|
# udm = main_lib.GetContents('User Defined Models*')[0][0]
|
|
# Script library
|
|
script_lib = app.GetProjectFolder('script')
|
|
# Template library
|
|
templ_lib = app.GetProjectFolder('templ')
|
|
# Operational library
|
|
oplib = app.GetProjectFolder('oplib')
|
|
# Characteristics
|
|
# opchar = oplib.GetContents('Characteristics')[0][0]
|
|
# Thermal ratings
|
|
therm_fold = app.GetProjectFolder('therm')
|
|
# MVAr limit curves
|
|
mvar_fold = app.GetProjectFolder('mvar')
|
|
|
|
##############
|
|
# STUDY CASE #
|
|
##############
|
|
# Study cases
|
|
op_scen = app.GetProjectFolder('scen')
|
|
# Operational scenarios
|
|
sc_fold = app.GetProjectFolder('study')
|
|
|
|
# Diagramas:
|
|
schemas = diag_fold.GetContents('*.IntGrfnet', 0)
|
|
sch = None
|
|
for obj in schemas:
|
|
if obj.loc_name == "miEsquema":
|
|
sch = obj
|
|
break
|
|
|
|
if sch is None:
|
|
sch = diag_fold.CreateObject("IntGrfnet", "miEsquema")
|
|
|
|
# redes:
|
|
print(netdata)
|
|
grids = netdata.GetContents('*.ElmNet', 0)
|
|
grid = grids[0]
|
|
ln = grid.GetContents('*.ElmLne', 0)[0]
|
|
print(ln)
|
|
# print(ln.type_id)
|
|
print(f"Terminal 1 de la línea {ln.loc_name}: {ln.bus1}")
|
|
print(f"Terminal 2 de la línea {ln.loc_name}: {ln.bus2}")
|
|
|
|
|
|
def createCable(name):
|
|
''''''
|
|
cable = equip.CreateObject("TypCab", name)
|
|
cable.uline
|
|
cable.typCon = "cmp" # Forma (cmp: Macizo, hol: orificio, seg: sermento)
|
|
cable.diaCon = 5.0 # diámetro externo (double) (mm)
|
|
|
|
# Capas condutoras: conductor, funda, blindaje
|
|
cable.cHasEl = [1, 1, 1] # Existe
|
|
cable.materialCond = [] # Material ()
|
|
cable.crho = [] # Resistividad 20ºC (double) (uOhm*cm)
|
|
cable.my = [] # Premeabilidad relativa (double)
|
|
cable.cThEl = [] # Espesor (dobule) (mm)
|
|
cable.Cf = [] # Factor de Relleno (double) (%)
|
|
cable.rpha = [] # Resistenca DC 20ºC Ohm/km
|
|
|
|
# Capas de aislamiento: Aislamiento, Funda Exterior, Cubierta
|
|
cable.cHasIns = [0, 0, 0] # Existe
|
|
cable.materialIns = [] # Material
|
|
cable.ctand = [] # Factor de Pérdidas Dieléctricas
|
|
cable.cepsr = [] # Permeavilidad relativa
|
|
cable.thlns = [] # Espesor (mm)
|
|
|
|
# Capas semicoductoras: Nucleo, Aislamiento
|
|
cable.cHasSc = [] # Existe
|
|
cable.thSc = [] # Espesor (mm)
|
|
cable.cAdvSc = [] # Avanzado
|
|
cable.rhoSc = [] # Resistividad uOhm*cm
|
|
cable.mySc = [] # Permeabilidad relativa
|
|
cable.epsrSC = [] # Premitividad relativa
|
|
|
|
cable.manuf = "" # fabricante
|
|
|
|
# 1 Flujo de carga
|
|
cable.tmax = 90.0 # Máx. temperatura (ºC)
|
|
|
|
# 2. Cortocircuito VDE/IEC
|
|
cable.rtemp = 80.0 # temperatura final máxima (ºC)
|
|
cable.Ithr = 0.0 # Corriente de corta duración 1s (kA)
|
|
|
|
# 3. Análisis de Cables
|
|
cable.tmax_screen = 70.0 # max. temparatura operación (ºC)
|
|
cable.eps_emiss = 0.9 # coeficiente de emisión en la superficie
|
|
cable.iopt_treated = True # Secado e impregnado
|
|
cable.tshc = 1.0 # Cálculo de cortocircuito adiabático - Duración de la falla (s)
|
|
|
|
return cable
|
|
|
|
|
|
def createLine(name):
|
|
elmlne = p.CreateObject("ElmPvsys", name)
|
|
elmlne.type_id = "" # Tipo
|
|
elmlne.bus1 = "" # terminal i
|
|
elmlne.bus2 = "" # terminal j
|
|
elmlne.nlnum = 1 # líneas en paralelo
|
|
elmlne.dline = 0.8 # longitud de la línea (double) (km)
|
|
elmlne.fline = 1.0 # factor de reduccion (double)
|
|
elmlne.inAir = 0 # Medio (0: Tierra, 1: Aérea)
|
|
elmlne.i_dist = 0 # Modelo de la línea (0: Parámetros Concentrados, 1: Parámetros Distribuidos)
|
|
|
|
return elmlne
|
|
|
|
|
|
def createPVPanel(name):
|
|
typpvpanel = equip.CreateObject("TypPvPanel", name)
|
|
typpvpanel.Ppk = 500.0 # Potencia Pico MPP (double) (W)
|
|
typpvpanel.Umpp = 80.0 # Tensión nominal MPP (double) (V)
|
|
typpvpanel.Impp = 6.0 # Corriente nominal MPP (double) (A)
|
|
typpvpanel.Uoc = 90.0 # Tensión de Circuito Abierto (double) (V)
|
|
typpvpanel.Isc = 7.0 # Corriente de cortocircuito (double) (A)
|
|
typpvpanel.material = 0 # Material: 0:mono-SI, 1:poli-Si, 2:samor-SI, 3: CIS, 4:CdTe, 5: otro
|
|
typpvpanel.usetval = 1 # Usar valores típicos
|
|
typpvpanel.cT = -0.4 # Coeficiente de tenperatura P (double) (%/Cº)
|
|
typpvpanel.noct = 45.0 # SINTC (double) (Cº)
|
|
|
|
typpvpanel.manuf = "" # Fabricante
|
|
typpvpanel.chr_name = "" # Nombre característico
|
|
typpvpanel.appr_status = 1 # Estado: 0: No aprobado, 1: aprobado
|
|
|
|
return typpvpanel
|
|
|
|
|
|
def createPV(name):
|
|
elmpvsys = grid.CreateObject("ElmPvsys", name)
|
|
elmpvsys.typ_id = None
|
|
elmpvsys.bus1 = None # terminal ()
|
|
elmpvsys.mode_pgi = 0 # modelo (0:Entrada de potencia Activa, 1: Cálculo solar)
|
|
elmpvsys.phtech = 0 # tecnología (0: 3F, 1: 3F-T, 2:1F F-T, 3:1F F-N)
|
|
elmpvsys.ngnum = 1 # Inversores en paralelo (int)
|
|
elmpvsys.npnum = 1 # Paneles por incersro (int)
|
|
elmpvsys.sgn = 1.0 # Potencia aparente (double) (kVA)
|
|
elmpvsys.cosn = 0.8 # Factor de Potencia nominal (double)
|
|
# elmpvsys.
|
|
return elmpvsys
|
|
|
|
|
|
def createBarra(name, uknom=33.0):
|
|
typbar = equip.CreateObject("TypBar", name)
|
|
typbar.uknow = uknom
|
|
|
|
# 1. Cortocircuito VDE/IEC
|
|
typbar.Ithlim = 0 # Corriente Nominal de Corto tiempo (kA)
|
|
typbar.Tkr = 1 # tiempo Corriente Nominal de Corto tiempo (s)
|
|
typbar.Iplim = 0 # Corriente Pico de cortocircuito (kA)
|
|
|
|
return typbar
|
|
|
|
|
|
def createTerminal(name):
|
|
elmterm = grid.CreateObject("ElmTerm", name)
|
|
elmterm.systype = 0 # Tipo de sistema (0: AC, 1: DC, 2: AC/BI)
|
|
elmterm.iUsage = 0 # Uso (0:Busbar, 1:Junction, Node 2: Internal node)
|
|
elmterm.phtech = "ABC" # Tecnología de Fases: ABC, ABC-N, BI, BI-N, 2F, 2F-N, 1F, 1F-N, N
|
|
elmterm.uknom = 33.0 # Tensión Nominal Línea-Línea (double)
|
|
elmterm.iEarth = False # Aterrizado (bool)
|
|
# Load Flow:
|
|
# 1. Control de tensión:
|
|
elmterm.vtarget = 1.0 # Tensión destino (double) (p.u.)
|
|
elmterm.Vtarget = 0.0 # Tensión destino (double) (kV)
|
|
elmterm.dvmax = 0.0 # Max delta V (double) (%)
|
|
elmterm.dvmin = 0.0 # Min delta V (double) (%)
|
|
elmterm.ivpriority = -1 # prioriddad
|
|
# 2. Límite de tensión del estado estable
|
|
elmterm.vmax = 1.05 # Límite superior de tensión (p.u.)
|
|
elmterm.vmin = 0.0 # Límite inferior de tensión (p.u.)
|
|
# 3. Límites del cambio del paso de tensión
|
|
elmterm.vstep_change = True # Límites del cambio del paso de tensión (bool)
|
|
elmterm.vstep_n1 = 6.0 # n-1 (%)
|
|
elmterm.vstep_n2 = 12.0 # n-2 (%)
|
|
elmterm.vstep_bus = 12.0 # falla de barra (%)
|
|
# Análisis de Arco Eléctrico:
|
|
elmterm.iAccessLoc = False # Ubicación Accesible (bool)
|
|
elmterm.isSoftConstr = False # Restrinción blanda (bool)
|
|
|
|
crearCelda()
|
|
|
|
return elmterm
|
|
|
|
|
|
def createCubic(parent, name):
|
|
stacubic = parent.CreateObject("StaCubic", name)
|
|
stacubic.cterm = parent
|
|
# stacubic.obj_id =
|
|
# stacubic.plntObjs =
|
|
return stacubic
|
|
|
|
|
|
def createSwitch(name):
|
|
staswitch = ""
|
|
|
|
|
|
def createTransformer(name):
|
|
|
|
|
|
#
|
|
|
|
def createTransformerType(name):
|
|
typTr3 = equip.CreateObject("TypTr3", name)
|
|
typTr3.nt3ph = 3 # Tecnología (2: Monofásico, 3: trifásico)
|
|
|
|
# Potencia Nominal:
|
|
typTr3.strn3_h = 1.0 # Lado AT (double) (MVA)
|
|
typTr3.strn3_m = 1.0 # Lado MT (double) (MVA)
|
|
typTr3.strn3_l = 1.0 # Lado BT (double) (MVA)
|
|
|
|
# Tensión nominal:
|
|
typTr3.utrn3_h = 0.0 # Lado AT (double) (kV)
|
|
typTr3.utrn3_m = 0.0 # Lado MT (double) (kV)
|
|
typTr3.utrn3_l = 0.0 # Lado BT (double) (kV)
|
|
|
|
# Grupo Vectorial:
|
|
typTr3.tr3cn_h = "YN" # Lado AT (Y, YN, Z, ZN, D)
|
|
typTr3.nt3ag_h = 0.0 # Lado AT - Ángulo de desfase (double) (*30deg)
|
|
typTr3.tr3cn_m = "YN" # Lado MT (Y, YN, Z, ZN, D)
|
|
typTr3.nt3ag_m = 0.0 # Lado MT - Ángulo de desfase (double) (*30deg)
|
|
typTr3.tr3cn_l = "YN" # Lado BT (Y, YN, Z, ZN, D)
|
|
typTr3.nt3ag_l = 0.0 # Lado BT - Ángulo de desfase (double) (*30deg)
|
|
|
|
# Impedancia de secuencia positiva
|
|
# Tensión de Cortocircuito uk:
|
|
typTr3.uktr3_h = 3.0 # AT-MT (double) (%)
|
|
typTr3.uktr3_m = 3.0 # MT-BT (double) (%)
|
|
typTr3.uktr3_l = 3.0 # BT-AT (double) (%)
|
|
|
|
# Pérdidas en el Cobre
|
|
typTr3.pcut3_h = 0.0 # AT-MT (double) (kW)
|
|
typTr3.pcut3_m = 0.0 # MT-BT (double) (kW)
|
|
typTr3.pcut3_l = 0.0 # BT-AT (double) (kW)
|
|
|
|
# Impedancia de secuencia cero
|
|
# Tensión de Cortocircuito uk0:
|
|
typTr3.uk0hm = 3.0 # AT-MT (double) (%)
|
|
typTr3.uk0ml = 3.0 # MT-BT (double) (%)
|
|
typTr3.uk0hl = 3.0 # BT-AT (double) (%)
|
|
|
|
# Pérdidas en el Cobre
|
|
typTr3.ur0hm = 0.0 # AT-MT (double) (kW)
|
|
typTr3.ur0ml = 0.0 # MT-BT (double) (kW)
|
|
typTr3.ur0hl = 0.0 # BT-AT (double) (kW)
|
|
|
|
|
|
# print(dir(app))
|
|
# print(dir(app.CreateProject))
|
|
|
|
|
|
cable = equip.GetContents('*.TypCab', 0)[0]
|
|
print(dir(cable))
|
|
print(cable.cHasEl)
|
|
print(cable.materialCond)
|
|
print(cable.tab_con)
|
|
|
|
'''
|
|
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
|
|
|
|
|
|
#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
|
|
|
|
#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
|
|
|
|
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()
|
|
'''
|
|
|
|
## Graphical objects:
|
|
|
|
|
|
|