) i8 ~. f( c5 u0 mPSSE30提供了Python的API接口,使在PSSE中使用Python脚本语言成为了可能,这不仅使PSSE批量运行,同时可以根据你的Python代码,使处理功能更强大,更灵活。 , j& V" a d; E我没有找到很好的关于在PSSE中使用Pyhton的资料,我把我能找到的东西写在这里供初学者入门。4 W3 _* E7 b1 N' W
前面的一些资料能在使用说明书USERS.pdf的第12章找到,其他资料是通过API.pdf和IPLAN.pdf综合而来的,可以从中找到。 9 t+ Z) B; c m* |7 ?2 E# u我发现使用Adobe的搜索功能非常有用,你可以根据一个关键词同时搜索在一个文件夹下面的所有的pdf文件,这样寻找某个函数的IPLAN和API的描述遍得很简单。IPLAN的描述一般在查找详细描述“某些传递数据的参数”的解释时非常有用。IPLAN函数的名称同API文档中Python的那些函数相同,只是后者是大写字母而已。 9 U( X [! ?' w我使用的是30版本的PSSE,和2.3版的Pyhton,这篇文章的前提是你了解一些基本的Python,Mack Lutz和David Ascher写的《Learning Pyhon》非常不错。 9 s! r, e: Q- U0 n: ~' W6 S. RPython4 F* L3 x. ~8 v6 F: B Python.org homepage 9 y; \$ m( G! \0 d9 n8 a PSSE: G w9 j7 q+ G* i! C- M' j7 [ Power System Simulator for Engineering. 0 U/ a" A X& H; u
0 e4 H- Y: H1 V! X8 w Y9 Y 在PSSE中使用Python简介1 j Z! a' I( K; R5 d
PSSE说明文档说:根据你在PSSE中的操作可以生成Python代码。这花了我一段时间才理解,因为我是PSSE和Python的初学者。根据以下步骤,可以生成你的第一个python代码,用来进行潮流计算分析。前提是你有一个包含有网络信息的.raw文件,格式符合PSSE30要求。% |1 G0 E4 Z/ r$ c: ^0 n
1、 Z! c9 v' S; D: Q! `& s- |7 r打开PSSE。7 I% \/ C1 H! V, p2 J' F3 b1 x4 S
2、 - M* q: D. N. C$ W选择“I/O Control”中的“Start Recording”菜单,输入一个PSSE写入的文件名。PSSE会自动地添加.py后缀。" q: [* e* h6 `2 H3 H5 S
3、& y/ @0 i3 o" R0 B
使用“File”菜单中的“Open”按钮,读入网络信息。将文件类型设定为.raw告诉PSSE你在给他的是raw文件(不知道是原文傻还是我翻译的傻:’() G# h4 r0 y# r' O8 y4、 0 g/ D' }6 U0 X# m* Y: {. h选择“Power Flow”中“Solution”,选择“Solve”,运行潮流计算。选择所需要的设置模式,点击“Solve”按钮。 / s( {8 L* x9 }/ ]6 T5、; s0 S% ~8 p% A
选择“File”菜单中的“Save or Show”保存运算结果。选择“Power Flow Raw Data”选项卡,点击“Data File”单选按钮,并在旁边的文本框中输入文件名。点击OK按钮。0 j, t( U$ ^7 B- y6 X4 v
使用你最喜欢的python浏览器查看生成的python代码。8 f$ h& q* a$ l5 i
# File:"C:\Documents and Settings\jbo\MySensibleFolderName\pssetest.py", generated on TUE, FEB 08 2005 14:11 psspy.read(0,r"""C:\Documents and Settings\jbo\MySensibleFolderName\testCase_30EV30test.raw"""): a0 D1 D5 S( s$ m/ R' u, P; p
psspy.fdns([0,0,0,1,1,0,99,0])2 @* R- m; T) [" I, m
psspy.rawd(0,1,[1,1,1,0,0,0],0,r"""C:\Documents and Settings\jbo\MySensibleFolderName\SOLVEDtestCase_30EV30test.raw""")
注意,所有的方法都是通过一个叫做psspy的对象调用的。这个对象包括所有可用的方法和对象。他们看起来只不过是通过一个列表来组织的。我还没有写任何接口对象来组织和调用psspy方法时,就是这么想的。(瞎翻译的): |8 \! c8 e9 _. F! j# l* G
注意声称路径字符串的方法,这不是python提倡的格式,下面的写法更好:5 A K2 r1 p& O; _/ Q
"C:\\Documents and Settings\\jbo\\MySensibleFolderName\\testCase_30EV30test.raw".
* J# N3 |: J) u& t/ K7 q$ j% p/ \! m怎样来运行python代码0 I! [; b3 Y. K% r. J: D: M
我试过三种方式% p/ x* ~8 c( q! `( f5 f
1、 ]1 Y: M& h0 Z7 a4 W在PSSE中打开命令输入窗口(command line input, CLI)任务。/ h8 K2 Z- `5 Z9 W% h6 b) @
2、 : z. K- t- V2 g/ B% u6 }5 b在PSSE中选择“Run Automation File”按钮运行一个python文件。 + s+ U% g* g% Q0 t3 }" o3、 0 a6 i6 W& ]9 {! ~在PSSE30中python文件作为一个命令行变量。你可以指定图形界面只有在完成之后才出现。这可以为机器节省内存。在这种情况下,你可以指定仿真的母线数量。可以参照PSSE Users Manual中的PSSE Overview。/ J2 o+ {2 E3 R4 Z, h! |% i. L 在PSSE中打开CLI : n" h! \* T9 @2 t3 S) s1、" G' \: f- W! n# n+ m, _0 D
在“I/O Control”菜单中选择“Begin command line input session”。% J' R. c1 N$ K* M) a5 P# _1 o
2、+ l* w' w) Q; ]5 b1 h- d% l# [: ]
使用“Command Language”选择框将语言更改为python。 " V* u6 F3 U' P( ? q8 W& i3、& d' C+ C: y$ ?9 R3 P& R
选择“RunAuto”按钮并选择一个python文件,PSSE会运行那个文件。! {! Q. h+ n F( t/ w
注意python命令可以直接在控制台输入。控制台动作同编译python的交互式平台不同,它不自动显示调用方法所返回的结果。要想显示的话必须使用python的print命令,例如:print(psspy.aMethod(myParameters))。/ I8 |9 M q9 ^2 O
一个重要的点是所有列出的方法都是psspy方法。所以使用要使用totbus方法返回母线数量时,输入CLI时不能使用ival=totbus(),而应该使用ival=psspy.totbus()。在CLI中使用print(ival)来显示ival。Python语法也可以使其简化,如:from psspy import * 。采用何种编程风格由用户决定。 0 T9 q& _7 o' Y4 w1 E. [ + I6 y$ N! G% M' ~% z" u在IDLE编译平台测试python代码6 x+ `1 u+ v- w( F$ `. z U
我花了让人崩溃的长时间来寻找下面这个加入到python路径的方法。2 _7 d p; s, w U* h
当你想将自己写的一个模块导入python,或者要把一个处在其他文件夹下的模块加入到python文件中去,那么下面的方法就大有用啦: 9 c! d" c( e0 I1、1 a/ |2 a* T0 B
创建一个扩展名为.pth的文件。我们起个很漂亮比尔盖茨又很喜欢的名字myconfig.pth。当你在使用记事本之类的编辑器时就要小心了,不要保存成myconfig.pth.txt哦。 9 H; C- E1 G3 L0 Y! K3 Z! `5 w. E; h% y$ P2、 : z- c# p/ c4 m( j% p把这个文件放到python根目录下面去,比如我的就是C:\Python23。! e+ v, `9 B7 D% v
3、) k8 N# B5 y7 w, g2 _% V! `
把每个你想加入PYTHONPATH的文件夹全路径,单独一行的加入到这个文件中去。例如,第一行可能就是:C:\aFolder\work\Python。 8 v; B" @7 H2 J6 H# x! [这样可以解决下面的错误,当你导入Spam这个模块的时候就不会出现:ImportError: No module named Spam.; x$ j, x( y; f+ p$ \
·$ d6 {! L6 {' Y8 L2 I& v! o
runSimulation4 W$ m. ?6 D6 F- |1 {
运行一个潮流计算.
·8 Q$ J, Y* L5 C: s m
saveResults ^4 K7 d/ e+ C; r3 _存储重要的数据到文件中.
你可以从Python解释器中手动调用这些函数。 & l- _( w a I7 j同样的,你可以使用__init__ ; t, ?) |0 Q* j7 |5 c: c0 `9 x函数仅按顺序包含所有你想执行的脚本。这些命令就像是初始化PSSE和你想使用的任何Python对象。最终这些命令会使PSSE进行一些例如潮流的计算。. U# X+ v( n2 K y- ]/ I9 [& W
# n5 v2 D7 ^7 x: w$ Y) C) J处理数组 $ {1 U: t+ E! G. @; z9 c. A o我逐渐能熟练处理数组和数字矩阵了。不在重复强调使用列表类型,而使用数字类型,这样会比使用列表快的多,而且你的程序读起来也更直观。它同在MATLAB里面使用一样方便,数字类型不仅仅是一个Python模块,也与最优化并且与编译的矩阵运算代码相关。 1 T! Q+ |9 e/ n* o- _3 V: `与数字类型相关的信息可以在这里找到 # h8 R2 } j# o/ y7 [0 Z在导入数字类型(Numeric)之前必须进行安装。使用在Python中导入模块的标准方法进行导入,你可以通过dir(Numeric)命令观察可用的方法及类结构。 ) s* c8 U4 a( g* {. h我使用的最多的方法是:+ a8 j: @8 N/ b1 J
Array3 v2 \( Q) c8 r+ V: B( D; j
使用这种方法从一个列表里创建数组可以包含一个数字或者一列数字。加些参数就可以使数组包含浮点数等等。例如:Numeric.array([1,2,3],'f')可以返回一个包含有浮点数1,2和3的数组。 8 C% I5 } R% r& {- T1 ]Arrange 8 g* T8 }( ]0 t) M$ f/ F# }. t这个方法根据你的描述来产生一个范围的等差数字,例如:Numeric.arange(0,0.5,0.1)返回 ) z7 f# d1 C n( W+ ~+ B0 {array([ 0. , 0.1, 0.2, 0.3, 0.4]). 注意数组中不包括最终值。 * l4 {- ^2 t1 o: D) W; ?% X& j: OTranspose * ~. c1 L. Q% N# ~. j Z1 D给定a=array([array([0,1,2]),array([3,4,5])]), 那么transpose(a)可以返回: + G3 h# U. q9 N, ^
0 N4 U6 h! ?0 g) m4 q& R8 B( h
/ f2 i% M( A% T$ t, H. D) x" I0 v5 U
4 n' l" o& ^( s' E
array([[0, 3],1 M5 b0 e8 [$ E4 e! N5 {7 g
* ?, V: N/ a' X: @9 Q" S$ F
[1, 4], 1 b5 i9 N6 R9 t; h3 r[2, 5]])数字数组中最有用的功能是数字定义了标准的操作如何执行例如加法,乘法和逻辑运算。 保存数据以便在MATLAB中使用导入数据到MATLAB中有多种方法,广义来说主要有以下三种:l* E( y. i, a5 F' I+ v
MATLAB格式.mat文件l . a p/ m, r" o# |2 {* ~ASCII编码数据文件l 5 X0 Y& [; a. S k文本文件MATLAB格式.mat文件这个格式需要各种文件头。我不知道有没有pythond的模块可以执行保存为.mat文件,但是在这个文件中细节描述了这种格式。ASCII编码数据文件就我所注意到的,这些文件只能存储数字信息。这些值按照行列来组织,每一行的列数必须相等。列之间可以使用各种字符隔开,比较常用的选择就是使用tab建或者空格键键入的空格。行使用转行分开,这样他们在文本编辑器中显示新的一行。下面是一个例子:
from Numeric import *m = array([1,10,2,20])m = reshape(m,(2,2))f = open('test.dat','w')for r in m:8 _) z8 f3 K8 _2 q) S" l7 w
for c in r: & ^. S) S5 g y) Kf.write("%i "), w4 |9 E, }0 a' E$ |& Y
f.write("\n")f.close()
在MATLAB里面,下面的语句就可以装载test.dat文件并把它作为一个变量test。文本文件最强大的,看起来可以被容易执行的方法,就是生成一个文本字符串,当执行的时候可以生成需要的对象或者在MATLAB中的对象。但是我想这可能不是最有效的办法。例如,设想一个bus类含有fields, voltage, load 和 generation over time,如下所示:
class Bus:% [7 K& g% M: {
number=None # k) K8 A; b r3 X) P, \Pgen=[]; r- i. ^2 F" n$ j E3 E
Pload=[]) Q" B0 [0 M) g" z p) L
V=[] " D: X4 h" W* I' y: I& F/ bdef __init__(self,number):' K/ [; ~9 a: V& e/ a9 Z ]
# y& z' G3 r0 R! t& r" |self.number = number : Z9 N; s3 n8 L' A5 v$ s1 ?% T6 u3 }
def storeStepData(self,g,l,v):2 ~7 [4 O# l: Z
5 A4 r' \/ G8 u! q/ T8 s) x6 u0 N
self.Pgen.append(g)# r+ ]: i9 z S$ I0 Q* W+ Y% s v
self.Pload.append(l) 3 T/ R% c' h! P& P! ~2 mself.V.append(v)
结构“bus10”现在可以在键入的matlab代码中起到作用。其中“10”部分是根据bus和母线节点号在matlabSring()函数中生成的。- `% R* j, U; |! a- @
& u% h G* }" k7 A6 e1 | 异常处理: p6 a, X( r2 D: ?2 ^
异常处理,是现代编程语言中使用的一种错误处理和诊断的方法。例如,没有必要在其他返回值再增加一个错误代码,而是如果有错误发生的话直接引发一个异常。这样做的好处是,错误不会被默认忽略。如果不检查错误代码的话,这个方法的失败就可能不被发现,可能会造成跟踪程序错误的困难。/ @8 W% I8 \$ _6 ]' B) _1 H
在python.org有一个异常处理的手册,它同样包含有用户自定义异常。5 M; i. \- l) c6 Z0 h! R
% y) Z$ {7 ^( l6 u @9 Y7 `( U
但是PSSE提供的API接口不适用异常处理,这样你在每次调用API时,都要严格检查错误代码变得很重要。我建立了一个与PSSE交互的特殊类来解决这个问题,所有API的调用都要适用这些类。每个API调用的时候都跟随错误代码检查。如果错误代码只是的是失败,则就引发一个异常,根据具体的错误代码使用合适的,定制的异常和信息。7 d% Z0 U8 J3 M; k' @; H
: P1 Y# {( S& ?+ J; x 使用Python模块random 5 M- c( z5 N( r8 |0 VRandom模块可以根据不同的分布状态产生随机数,并允许控制产生的状态。使用在Python中引入模块的标准方法,导入random。你可以通过dir(random)函数查看可用的方法和类的构造。 9 r( \( U1 ^0 Q; j+ U, n: y我用的最多的方法是:/ l/ G m. a, g/ G" V
Getstate' P" T5 h1 h1 H
这个方法返回产生随机数的当前状态。这个状态可以保存并在稍后用来设置模块的状态回到以前状态,具体方法可以查看下面的setstate,例如:savedState = random.getstate(). % P# a/ k% j; `7 wJumpahead$ T( u- d+ v( `' B) R
这个方法用来改变当前状态,只要模块不会产生一系列数字覆盖在执行jumping ahead命令之前的状态。例如random.jumpahead(42)* h. f. U3 k: E
normalvariate和uniform 0 ^1 p8 g; U: o1 [, X这些方法是少数返回随即数的方法的两个,他们分别返回符合正态分布和平均分布的随机数。方法mormalvariate需要平均值和标准偏差两个参数,方法uniform需要最大值最小值得范围rang[min, max)。 Y7 R" w- Q, S' C3 `
例如:random.normalvariate(0,1)和random.normalvariate(0,10).4 o) _" T$ K2 q- x7 h
Seed' D/ h- Z6 z$ T4 Z {5 A
这种方法可以使用任何不规则格式设置随机数产生器的状态,例如字符串。这样,不必要首先在文件系统中存储一个状态类就可以设置状态了。例如:random.seed("My! I do like coding, it's such fun!").7 n Q( U9 y' ]7 N
Setstate - N V0 }) M R* J+ |5 e这种方法使随机数产生器的状态设置为之前使用getstate保存的状态,例如:random.setstate(saveState)。9 r. h$ B& N- M! U; K
我发现在使用random模块时创建自己的类是十分有用的,在其中,产生随机数的方法保证了random模块的状态不发生变化。这可能被忽略了,但是一次只有一个random模块导入。那样我就可以创建多个自定义的random模块来产生随机数字,没有必要干涉每个产生器的状态。 + ?% h9 N$ D8 ~; t0 D9 a & T! Z: O: S( A% B- g其他注意事项1 e8 p( B2 T' H2 F
l) k- B- S6 `$ B" N u* t
我也写了一些实现以下功能的python代码: : }9 h7 B9 u0 ]6 @- @- p- d5 I² 7 ^6 i6 l2 ^( g/ {* h潮流运算和获取网络所有的数据。 & x' F V7 V) [7 ^² . U) s+ e) `% [) J- p. F; b, F基本的低/高/带通滤波器。 I3 k' ]6 G7 n) p6 S²# G2 e5 c q4 r, r$ X9 ^7 q0 w
梯形三角形模糊逻辑7 |7 d: B: o4 L* y$ P7 N
²1 o2 z, v8 i9 P1 ]! Z
如下所说的我不能使用scipy,基本的插补类 ! s% v1 G9 x2 {" Kl' a( c4 P( B0 ~
我在PSSE CLI或者在CLI运行代码时,使用import scipy时出现了问题,当我从Fortran machine里导入时,出现了浮点数溢出的现象,所以我尝试了很多次重建wheel因为我不能使用。 $ {! {7 l% q, Z) f: ?l4 z3 V! U& L' p: d8 z& a8 `
我又碰到浮点数溢出的现象了,这次是当我把自己的模糊逻辑模块应应用为PSSE扩展脚本的一部分时出现的,我想这是甚至因为我再scipy只引入了interp部分造成的。如果只在python解释器下测试的话就不会出现这个问题。) ^# Y% T3 q2 d$ C+ v/ U
l8 I+ r6 c1 ]5 l# M0 C8 H7 f: n
我碰到了一个Fortran的错误,可能是由Python引起的。我忘记了它是不是被零除过,还是因为我试图当作一个list来读取数字,或者这两个方面都有。这里的课程可能会在Python没有抛出异常的地方出现问题,结果造成了不良的运行时错误,但是原因可能很简单而且错误能确定。9 a0 p0 U0 T9 {9 V) `
l 3 H) e& k3 N6 C$ t/ ?) g5 T在潮流运行完毕之后需要使用solved()来检验潮流是不是收敛了。如果潮流没有收敛,一些网络可能从步参数比默认参数小100或者更多(-_-)受益。当先减小补偿时,代数限制应该也要放宽。 ' {3 U8 a- E2 g! [. Tl ( i) \* X# s4 l1 V1 L读一下说明书。他有不同求解方法的正面和反面介绍。2 e2 t4 X: X6 [7 ?4 x3 U) J
l ! |1 {6 m, t$ X+ {# D在我的版本中GSLV会让电脑崩溃,更郁闷的是他在我的工程里运行比在MSLV中运行的好,而我只能呢个使用MSLV进行扩展仿真。 \; w! R$ ~* Tl }& w) u0 T- L) N$ }
警告。逐步备份你的.raw文件。PSSE有个坏习惯,覆盖的时候没有警告,即使那个模式已经关掉。PSSE还可能把不能自动调节的变压器,做成能自动调节的变压器模型。我不确定什么时候会发生这种情况,但是我已经被这个问题浪费了一些时间了。 6 w. _$ H! ?! Hl 2 i+ L' g8 Q E" d# m# ~一个不错的网站,关于Python的。: A$ o- P* k- |6 B' j+ g
! O4 F, H8 _% _2 z, Z, ?建议和评论1 K3 w" j N/ @: \# x
如果有任何建议或者改进欢迎发Email给我,我可以分别把具体的PSSE功能性的使用和详细地执行信息联系起来。Email jbo at ee ed ac uk。& o2 E, s* a) j: s5 n
发邮件给我的任何问题或者在AQ网页里的问题我都会回答的。 % w. V8 X- _( g+ M. l2 n" W' h m% K/ j