介绍有点长。如果您不感兴趣,那么请阅读更新,并看看我突出显示的具体部分。
我对任何改进都很感兴趣,但您可以假设以psspy.开头的所有调用都是正确的,不能更改。另外,循环中对psspy的调用必须在循环中,我不能用多个输入值调用函数。
代码是用Python2.7编写的。这是因为模拟工具不适用于新版本。
如果代码太长,任何人都无法检查它,我将编写一些可能需要检查的特定行:
branch_string的方式。首先是nodes_from_string = [str(x) for x in nodes_from],其次是branch_string = [nodes_from_string[x] +'-' +nodes_to_string[x] for x in range(0, len(nodes_from))]。nodes_from_string,但是我会在循环中使用nf = nodes_from[branch]和nf_str = str(nf)。fig = plt.figure()开始。enumerate?Izero_3是一个np.array。下面的代码调用一个模拟软件(称为电力系统工程模拟器),并使用模块psspy (PSS/E到Python)运行潮流分析。
代码工作正常,但不幸的是,您现在无法运行它,因为软件不是一个免费的程序,而且您没有电力系统模型。我提供了可以使用的示例输入变量,而不是函数调用(只有几行必须更改)。这样,就可以正确地测试代码的下半部分。我还将概述仿真工具提供的不同输出,以及它是如何工作的:
导入psspy时,将在模拟工具中打开会话。所有对该模块(psspy.function_name)中函数的调用都将在该程序和该会话中运行一个命令。为了打开一个新的会话,我必须对模块进行reload。然后,上一次会议(如果有的话)将结束。
大多数函数提供一个或多个输出。第一个总是错误代码。0意味着没有错误。一般来说,我对错误消息不感兴趣(因为它们通常只是信息,而不是实际的错误)。然而,有一些错误消息,这意味着我正在处理的情况是不好的。对于这些情况,我只做了sys.exit("Some message")。
要测试函数,只需用变量赋值替换所讨论的行。必须进行的替换是:用这些行替换内环的内容。注意,内环中调用的函数必须在循环中执行,因此我无法在实际代码中删除该循环。
Izero_1[x] = (-0.079218775034+0.124398261309j)
Izero_2[x] = (1.59865610333e-16-2.18846208516e-16j)
Izero_dum[x] = (0.0790840312839-0.124262578785j)对psspy.abuschar的调用可以替换为:
carray = [['Node from ', 'Node to ']]ierr = psspy.scdone()可以移除。
Izero_1、I_zero_2和Izero_dum包含21个相似的值。最后还包括了来自print Izero_1的输出。但是,您可以只对循环中的所有调用使用上面的值。
我相信下一段之后的每一件事都是可以测试的,如果上面的替换已经完成的话。
#==============================================================================
# Start doing the fault analysis.
#==============================================================================请注意,它可能看起来很长。这主要是因为我试着写一些好的和描述性的评论。
# coding=utf-8
# The above comment is to ensure that æøå are allowed in the script
#==============================================================================
# This script is used to simulate faults in a power system. The resulting
# currents are calculated with a variable distance from the stations on
# both ends.
#
# It start with a fault at a distance L from node 1, to a distance L from
# node 2, with N steps in between.
#==============================================================================
import os,sys
import xlwt
from datetime import datetime
#==============================================================================
# I'm using Spyder/Anaconda so both numpy and matplotlib.plot are
# pre-loaded. The two statements below are there to avoid the constant
# reminder that numpy and matplotlib aren't loaded.
#==============================================================================
import numpy as np
import matplotlib.pyplot as plt
#==============================================================================
# This is the file path to the simulation tool. The script must
# find this folder for this program to work
#==============================================================================
PSSEPATH = r'C:\Program Files (x86)\PTI\PSSE33\PSSBIN'
MODELFOLDER = r'C:\Program Files (x86)\PTI\PSSE33\EXAMPLE'
sys.path.append(PSSEPATH)
os.environ['PATH'] += ';' + PSSEPATH
#==============================================================================
# Import modules that are used in the script. psspy and redirect
# are part of the simulation tool.
# These import statements are not in the top of the script, since
# psspy and redirect can't be found until PSSPATH is part of the
# path
#==============================================================================
import psspy
import redirect
import excelpy
#==============================================================================
# The psspy module is reloaded to ensure it's empty. If it's not reloaded
# then the simulation tool will give back information that's already
# calculated / found last time the module was used.
#==============================================================================
psspy = reload(psspy)
excelpy = reload(excelpy)
#==============================================================================
# Redirect output from the simulation tool. All output will now be shown
# in the Python console window instead of the simulation tool.
# This way I don't need to have the other program open.
#==============================================================================
redirect.psse2py()
#==============================================================================
# Load case
# CASENAME is a separate variable, so that I can easily change this
# without changing anything else
#==============================================================================
SCENARIO_FILE_PATH = r'\\server_name\model_folder\scenario_folder'
CASENAME = r'\case_name_1'
CASE = SCENARIO_FILE_PATH + CASENAME + r'.sav'
# Initiate the simulation tool with the maximum number of buses
# This is necessary and can't be skipped.
psspy.psseinit(12000)
# Open the case in the simulation tool:
ierr = psspy.case(CASE)
if ierr == 0:
print "Case loaded: " + CASE
if ierr != 0:
sys.exit("Case could not load. Check name and folder!")
#==============================================================================
# Run full load flow. (psspy.fnsl)
#==============================================================================
ierr = psspy.fnsl()
if ierr != 0:
print 'error code fnsl: ', ierr # Don't do sys.exit here!
#==============================================================================
# Check if power flow solution was found. If it's not found then the
# model is corrupt and the simulations must stop. No calls to the program
# will work if it's not solved.
#==============================================================================
ierr = psspy.solved()
if ierr != 0:
sys.exit("Power flow did not converge!")
#==============================================================================
# Start doing the fault analysis.
#==============================================================================
#==============================================================================
#==============================================================================
# Decide how many steps the line shall be split into.
# I will not change this often, so I don't want it as a function argument
#==============================================================================
num_steps = 20 # 20 steps
min_dis = 1 # Minimum distance from node 1 (1/20 = 0.05
max_dis = num_steps # Max distance: (num_steps-1)/num_steps.
dist = [0.001] + [float(x)/num_steps for x in range(min_dis, max_dis)] + [0.999]
#cmpval = [None] * len(dist)
#==============================================================================
# Datetime Will be used when presenting the output to document when the
# simulations were conducted
#==============================================================================
i = datetime.now()
time_str = i.strftime('%Y/%m/%d %H:%M:%S')
#==============================================================================
# Make a list of all lines that are of interest:
# A line goes from node_from[x] to node_to[x]. So 1-2, 2-3, 4-6, 6-8, 12-15
#==============================================================================
nodes_from = [1, 2, 4, 6, 12]
nodes_to = [2, 3, 6, 8, 15]
nodes_from_string = [str(x) for x in nodes_from]
nodes_to_string = [str(x) for x in nodes_to]
branch_string = [nodes_from_string[x] +'-' +nodes_to_string[x] for x in range(0, len(nodes_from))]
#==============================================================================
# Create Excel-file and give names to sheets.
# Sheets will be called 1-2 for faults on lines 1-2, 2-3 for faults on line 2-3 etc.
#==============================================================================
EXCELPATH = SCENARIO_FILE_PATH
sheet_nr = 1
while os.path.exists(EXCELPATH + CASENAME + '_simulation_%s.xls' % sheet_nr) and sheet_nr < 100:
sheet_nr += 1
wbook_name = (EXCELPATH + CASENAME + '_simulation_%s.xls' % sheet_nr)
workbook = xlwt.Workbook(encoding = "UTF-8")
#==============================================================================
# Run the magical loop that does all the hard work
# Outer loop is used to iterate through all the lines
# Inner loop is used to vary the fault location (20 steps)
#==============================================================================
# This line can't be omitted. It has no output.
psspy.sequence_network_setup(1)
for branch in range(0,len(nodes_from)):
nf = nodes_from[branch]
nt = nodes_to[branch]
# Create a subsystem with the two nodes in question.
# This command has no output
psspy.bsys(1,0,[ 0.69, 400.],0,[],2,[nf,nt],0,[],0,[])
# Get names of each of the two nodes, and remove spaces.
# Output is ierr, and carray. I don't care about ierr.
ierr, carray = psspy.abuschar(1,2,'NAME')
names = [name.strip() for name in carray[0]]
nf_str = str(nf) # Convert node number to string
nt_str = str(nt) # Convert node number to string
# Make a name for the end points of the plots (x-axis)
# Format: Node name \n (Node number)
x0_tick = "\n".join([names[0], '(' + nf_str + ')'])
x1_tick = "\n".join([names[1], '(' + nt_str + ')'])
# Initiate list of current values
Izero_1 = len(dist) * [None]
Izero_2 = len(dist) * [None]
Izero_dum = len(dist) * [None] # Dummy variable
# Dummy is actually a descriptive name
for x in range(0,len(dist)):
# The following commands calls the simulation tool. It has no
# outputs except ierr. I'm not interested in ierr unless I'm
# debugging the model
# I have to get one value at a time. It's impossible to fetch
# several results in one call to the program. The loop is therefore
# necessary.
ierr = psspy.scmu(1,[0,0,0,0,0,0,0],[0.0,0.0,0.0,0.0,0.0],"")
#print 'error code scmu1: ', ierr
ierr = psspy.scmu(2,[9,nf,nt,1,1,0,0],[0.0,0.0,0.0,0.0, dist[x]],r"""1""")
#print 'error code scmu2: ', ierr
ierr = psspy.scmu(3,[9,nf,nt,1,1,0,0],[0.0,0.0,0.0,0.0, dist[x]],r"""1""")
#print 'error code scmu3: ', ierr
ierr = psspy.scinit()
#print 'error code scinit: ', ierr
if ierr != 0:
Izero_1[x] = 0
Izero_2[x] = 0
Izero_dum[x] = 0
else:
ierr, Izero_1[x] = psspy.scbrn2(nf, 999999, '1', 'IZERO')
#print 'error code scbrn2: ', ierr
ierr, Izero_2[x] = psspy.scbrn2(nt, 999999, '1', 'IZERO')
#print 'error code scbrn2: ', ierr
ierr, Izero_dum[x] = psspy.scbus2(999999,'FAULTZ')
#print 'error code scbus2: ', ierr
ierr = psspy.scdone()
#print 'error code scdone: ', ierr
#==========================================================================
# Convert currents to positive real numbers instead of complex values
#==========================================================================
Izero_1_3 = 3*np.absolute(Izero_1) # 3I0 in per unit
Izero_2_3 = 3*np.absolute(Izero_2) # 3I0 in per unit
Izero_dum_3 = 3*np.absolute(Izero_dum) # 3I0 in per unit
I_base = 1000e6/130e3/np.sqrt(3)
Izero_1_3 = [I_base * x for x in Izero_1_3] # 3I0 i Ampere
Izero_2_3 = [I_base * x for x in Izero_2_3] # 3I0 i Ampere
Izero_dum_3 = [I_base * x for x in Izero_dum_3] # 3I0 i Ampere
Izero_3 = np.array([Izero_1_3, Izero_2_3, Izero_dum_3])
#==========================================================================
# Plot figures. Also add figure name, title etc.
#==========================================================================
distance = [100*x for x in dist]
fig = plt.figure()
fig.suptitle('Simulation of fault currents', fontsize=10)
line_1 = plt.plot(avstand, Izero_1_3, label = 'Current - '+names[0])
line_2 = plt.plot(avstand, Izero_2_3, label = 'Current - '+names[1])
line_3 = plt.plot(avstand, Izero_dum_3, label = 'Current - Fault location')
plt.ylabel('3I0 [A]')
plt.ylim(ymin = 0)
plt.legend(loc = 'center left', bbox_to_anchor=(1, 0.895), fontsize=10)
#plt.xticks([0, 20, 40, 60, 80, 100], [names[0], '20%', '40%' ,'60%', '80%', names[1]], fontsize=10)
plt.xticks([0, 20, 40, 60, 80, 100], [x0_tick, '20%', '40%' ,'60%', '80%', x1_tick], fontsize=10)
plot_text_1 = 'Current: Fault at different fault locations between {0} and {1}.'.format(*names)
plot_text_2 = '\nX-axis shows percentage distance from {0}.'.format(names[0])
fig.text(0.2, -0.05, plot_text_1 + plot_text_2, bbox=dict(facecolor='none'),fontsize=10)
fig.text(0.95, -0.0, time_str, fontsize=10)
#==========================================================================
# Write to Excel-file
#==========================================================================
worksheet = workbook.add_sheet(branch_string[branch])
worksheet.write(0, 0, label = 'Simulation of fault currents for line ' +names[0] + ' - ' + names[1])
worksheet.write(0, 5, label = 'Line: ' + branch_string[branch])
worksheet.write(1, 5, label = 'Simulation time:')
worksheet.write(2, 5, label = time_str)
worksheet.write(4, 5, label = 'Folder:')
worksheet.write(5, 5, label = SCENARIO_FILE_PATH)
worksheet.write(6, 5, label = 'File name:')
worksheet.write(7, 5, label = CASENAME[1:] + r'.sav')
headers = ['Distance', names[0], names[1], 'Fault location']
for x in range(0, len(headers)):
worksheet.write(1, x, label = headers[x])
for r, row in enumerate(zip(dist)):
for c, col in enumerate(row):
worksheet.write(r+2, c, label = col)
for r, row in enumerate(zip(*Izero_3)):
for c, col in enumerate(row):
worksheet.write(r+2, c+1, label=col)
workbook.save(wbook_name)print Izero_1的输出是:
print Izero_1
[(-0.07938643544912338+0.12485483288764954j), (-0.0792187750339508+0.12439826130867004j), (-0.07901565730571747+0.12390241026878357j), (-0.07881283760070801+0.12340965121984482j), (-0.07861024886369705+0.12292001396417618j), (-0.0784088522195816+0.12243442237377167j), (-0.07820823043584824+0.12195241451263428j), (-0.07800843566656113+0.12147442251443863j), (-0.07780935615301132+0.12099983543157578j), (-0.07761109620332718+0.12052880972623825j), (-0.07741381973028183+0.12006136775016785j), (-0.07721710205078125+0.11959727853536606j), (-0.0770215317606926+0.11913706362247467j), (-0.07682641595602036+0.1186794713139534j), (-0.07663228362798691+0.11822568625211716j), (-0.07643887400627136+0.11777541041374207j), (-0.07624640315771103+0.11732850223779678j), (-0.0760544165968895+0.116884246468544j), (-0.07586311548948288+0.11644333600997925j), (-0.07567299902439117+0.11600597202777863j), (-0.07548230141401291+0.11555929481983185j)]发布于 2016-08-02 07:44:28
作为一个非python程序员,我只能看到一件事:
if ierr == 0:
print "Case loaded: " + CASE
if ierr != 0:
sys.exit("Case could not load. Check name and folder!")您可以在这里使用else。
if ierr == 0:
print "Case loaded: " + CASE
else:
sys.exit("Case could not load. Check name and folder!")https://codereview.stackexchange.com/questions/136618
复制相似问题