首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >潮流分析中的仿真数据处理

潮流分析中的仿真数据处理
EN

Code Review用户
提问于 2016-08-02 07:14:42
回答 1查看 2.2K关注 0票数 4

介绍有点长。如果您不感兴趣,那么请阅读更新,并看看我突出显示的具体部分。

我对任何改进都很感兴趣,但您可以假设以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()开始。
    • 我应该在循环之外做这个吗?如果是的话,如何简单地做到这一点呢?

  • 我可以简化创建数据表和编写Excel的方式吗?
  • 我是否像在最后3行中一样使用enumerateIzero_3是一个np.array。

Explanation:

下面的代码调用一个模拟软件(称为电力系统工程模拟器),并使用模块psspy (PSS/E到Python)运行潮流分析。

代码工作正常,但不幸的是,您现在无法运行它,因为软件不是一个免费的程序,而且您没有电力系统模型。我提供了可以使用的示例输入变量,而不是函数调用(只有几行必须更改)。这样,就可以正确地测试代码的下半部分。我还将概述仿真工具提供的不同输出,以及它是如何工作的:

导入psspy时,将在模拟工具中打开会话。所有对该模块(psspy.function_name)中函数的调用都将在该程序和该会话中运行一个命令。为了打开一个新的会话,我必须对模块进行reload。然后,上一次会议(如果有的话)将结束。

大多数函数提供一个或多个输出。第一个总是错误代码。0意味着没有错误。一般来说,我对错误消息不感兴趣(因为它们通常只是信息,而不是实际的错误)。然而,有一些错误消息,这意味着我正在处理的情况是不好的。对于这些情况,我只做了sys.exit("Some message")

要测试函数,只需用变量赋值替换所讨论的行。必须进行的替换是:用这些行替换内环的内容。注意,内环中调用的函数必须在循环中执行,因此我无法在实际代码中删除该循环。

代码语言:javascript
复制
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的调用可以替换为:

代码语言:javascript
复制
carray = [['Node from    ', 'Node to      ']]

ierr = psspy.scdone()可以移除。

Izero_1I_zero_2Izero_dum包含21个相似的值。最后还包括了来自print Izero_1的输出。但是,您可以只对循环中的所有调用使用上面的值。

我相信下一段之后的每一件事都是可以测试的,如果上面的替换已经完成的话。

代码语言:javascript
复制
#==============================================================================
# Start doing the fault analysis.
#==============================================================================

完整代码:

请注意,它可能看起来很长。这主要是因为我试着写一些好的和描述性的评论。

代码语言:javascript
复制
# 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的输出是:

代码语言:javascript
复制
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)]
EN

回答 1

Code Review用户

发布于 2016-08-02 07:44:28

作为一个非python程序员,我只能看到一件事:

代码语言:javascript
复制
if ierr == 0:
    print "Case loaded: " + CASE

if ierr != 0:
    sys.exit("Case could not load. Check name and folder!")

您可以在这里使用else

代码语言:javascript
复制
if ierr == 0:
    print "Case loaded: " + CASE
else:
    sys.exit("Case could not load. Check name and folder!")
票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/136618

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档