PMU可观性分析

首页摘要:

本文旨在说明任意数量、位置的PMU安装在电网中,这些PMU的可观性如何。基本规则由实验室师弟周挺分析得到,具体编程工作由本人实现,聊以一份说明书记录。

PMU_1.png

PMU_2.png

PMU_3.png

具体实现代码如下(python)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#-*- coding: utf-8 -*-
# ----------------------------------------------------
# Description: Find Optimal Feature Set algorithm
# Created by: Bendong Tan
# Created time: Saturday, August 04, 2018
# Last Modified: Monday, September 11, 2018
# Wuhan University
# ----------------------------------------------------
##############输入输出说明###############
# 所有矩阵均采用0-1编码
# 节点矩阵 bus_mat
# 线路矩阵 branch_mat
# pmu位置矩阵 pmu_loc

import numpy as np


class PMU_Place(object):
def __init__(self, bus_mat=None, branch_mat=None, load_mat=None, gen_mat=None, pmu_loc=np.array([8])):
if bus_mat == None or branch_mat == None or pmu_loc == None:
# 默认新英格兰39节点系统,输入请按照下述格式构造
# 节点矩阵,节点编号
self.bus_mat = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39])
# 线路矩阵,线路首端和末端编号
self.branch_mat = np.array([[1, 2], [1, 39], [2, 3], [2, 25],
[2, 30], [3, 4], [3, 18], [4, 5],
[4, 14], [5, 6], [5, 8], [6, 7],
[6, 11], [6, 31], [7, 8], [8, 9],
[9, 39], [10, 11], [10, 13], [10, 32],
[12, 11], [12, 13], [13, 14], [14, 15],
[15, 16], [16, 17], [16, 19], [16, 21],
[16, 24], [17, 18], [17, 27], [19, 20],
[19, 33], [20, 34], [21, 22], [22, 23],
[22, 35], [23, 24], [23, 36], [25, 26],
[25, 37], [26, 27], [26, 28], [26, 29],
[28, 29], [29, 38]])
# 负荷矩阵,负荷所在节点编号
self.load_mat = np.array([3, 4, 7, 8, 12, 15, 16, 18, 20, 21, 23, 24, 25, 26, 27, 28, 29, 31, 39])
# 发电机矩阵,发电机所在节点编号
self.gen_mat = np.array([30, 31, 32, 33, 34, 35, 36, 37, 38, 39])
# pmu位置矩阵,PMU所在节点编号
self.pmu_loc = pmu_loc
else:
self.bus_mat = bus_mat
self.branch_mat = branch_mat
self.pmu_loc = pmu_loc

# 构造邻接矩阵、pmu位置数组、零注入节点数组
def Construct_matrix(self):
# 初始化
N = len(self.bus_mat)
link_array = np.zeros((N, N))
pmu_array = np.zeros((N, 1))
ZIB_array = np.ones((N, 1))
# 构造邻接矩阵
branch = self.branch_mat
for i in range(len(branch)):
link_array[branch[i, 0] - 1, branch[i, 1] - 1] = 1
link_array[branch[i, 1] - 1, branch[i, 0] - 1] = 1
# 构造pmu位置数组
pmu_array[self.pmu_loc - 1] = 1 # 减1是因为numpy从0数起
# 构造零注入节点数组,除去发电机以及负荷节点之外的节点
ZIB_array[self.load_mat - 1] = 0
ZIB_array[self.gen_mat - 1] = 0
return link_array, pmu_array, ZIB_array

def Observation(self, link_array, pmu_array, ZIB_array):
# 初始化
N = len(self.bus_mat)
V = np.zeros((N, 1)) # 电压矩阵
I = np.zeros((N, N)) # 电流矩阵,电流已知那么线路功率也是已知的
G = np.zeros((len(self.gen_mat), 1)) # 发电机矩阵
L = np.zeros((len(self.load_mat), 1)) # 负荷矩阵

# 中间变量
A = np.zeros((N, N))
B = np.zeros((N, 1))
# 按照规则进行可观性描述
# 先确定安装有PMU的点
# 安装PMU的节点其节点电压和相连支路电流、相连节点电压可观
for i in range(N):
# if pmu_array[i] == 1:
for j in range(N):
if j != i:
V[i] = pmu_array[i] or (pmu_array[j] and link_array[i, j])
I[i, j] = (pmu_array[i] or pmu_array[j]) and link_array[i, j]
I[j, i] = (pmu_array[i] or pmu_array[j]) and link_array[i, j]
for i in range(100): # 进行迭代直至收敛
# 支路两端电压可观,则该支路电流可观
for i in range(N):
for j in range(N):
if j != i:
if V[i] == 1 and V[j] == 1 and I[i, j] == 0 and link_array[i, j] == 1:
I[i, j] = V[i] and V[j]
I[j, i] = V[i] and V[j]

# 支路电流和另一端电压可知,则该支路另一端电压已知
for i in range(N):
for j in range(N):
if j != i and V[i] == 0:
V[i] = V[i] or (I[i, j] and V[j])

# 零注入节点未配置PMU,且仅有一条相连支路电流未知,该支路电流可观
for i in range(N):
if ZIB_array[i] == 1:
for j in range(N):
if i != j:
for k in range(N):
A[k] = link_array[i, k] and I[i, k]
if A.sum(axis=0)[0] == link_array[i, :].sum(axis=0) - 1 and I[i, j] == 0:
I[i, j] = ZIB_array[i] and link_array[i, j]
I[j, i] = ZIB_array[i] and link_array[i, j]
# 零注入节点未配置PMU,且所有相邻节点电压已知,则该节点电压已知
for i in range(N):
if ZIB_array[i] == 1 and V[i] == 0:
for j in range(N):
if i != j:
for k in range(N):
B[k] = link_array[i, k] and V[k]
if B.sum(axis=0)[0] == link_array[i, :].sum(axis=0) and V[i] == 0:
V[i] = ZIB_array[i]

return V, I, G, L
# 物理量索引转换
def Index(self,V, I,link_array):
N = len(self.bus_mat)
G = [] # 发电机矩阵
L = [] # 负荷矩阵

V_Bus = np.nonzero(V)
I_Line = np.nonzero(I)
# 由于Python从0计数,节点电压矩阵元素值+1
for i in range(len(V_Bus[0])):
V_Bus[0][i] += 1
V_Bus = V_Bus[0].tolist()
for i in range(len(I_Line[0])):
I_Line[0][i] += 1
for i in range(len(I_Line[0])):
I_Line[1][i] += 1
I_Line = list(I_Line)
I_Line_1 = I_Line[0].tolist()
I_Line_2 = I_Line[1].tolist()
I_Line_Result = []
for i in range(len(I_Line_1)):
I_Line_Result.append((I_Line_1[i], I_Line_2[i]))
# 由于支路电流会计算两次,这里删去支路两端节点相同的一半元素,把不存在于原线路矩阵中的编号去除
for i in range(len(I_Line_1)):
if [I_Line_1[i],I_Line_2[i]] not in self.branch_mat.tolist():
I_Line_Result.remove((I_Line_1[i], I_Line_2[i]))
for i in range(len(self.gen_mat)):
if V[self.gen_mat[i]-1]!=0 and sum(I[self.gen_mat[i]-1,:])==sum(link_array[self.gen_mat[i]-1,:]):
G.append(self.gen_mat[i])
for i in range(len(self.load_mat)):
if V[self.load_mat[i]-1]!=0 and sum(I[self.load_mat[i]-1,:])==sum(link_array[self.load_mat[i]-1,:]):
L.append(self.load_mat[i])
return V_Bus,I_Line_Result,np.array(G),np.array(L)



if __name__ == '__main__':
PMU = PMU_Place(bus_mat=None, branch_mat=None, load_mat=None, gen_mat=None, pmu_loc=np.array([3,8,10,16,20,23,25,29]))
link_array, pmu_array, ZIB_array = PMU.Construct_matrix()
V, I, G, L = PMU.Observation(link_array, pmu_array, ZIB_array)
V_Bus, I_Line_Result, G, L=PMU.Index(V, I,link_array)
print('电压可观节点总数为:', sum(sum(V)))
print('电压可观节点为:', V_Bus)
print('发电机可观节点为:', G)
print('负荷可观节点为:', L)
print('电流可观支路总数为:', sum(sum(I)) / 2) # 由于支路电流会计算两次,这里删去支路两端节点相同的一半元素
print('电流可观支路两端节点编号为:', I_Line_Result)

2018.10.24补充matlab版代码

(1)定义类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170

classdef PMU_Place % 定义类
properties
bus_mat;
branch_mat;
load_mat;
gen_mat;
pmu_loc;
end
methods %定义方法
function obj=PMU_Place(pmu_loc)
% 默认网络为新英格兰39节点
% 节点矩阵
obj.bus_mat=[1,2,3,4,5,6,7,8,9,10,11,12,13,...
14,15,16,17,18,19,20,21,22,23,24,25,26,...
27,28,29,30,31,32,33,34,35,36,37,38,39];
% 线路矩阵
obj.branch_mat=[1,2; 1,39; 2,3; 2,25;...
2, 30; 3, 4; 3, 18; 4, 5;...
4, 14; 5, 6; 5, 8; 6, 7;...
6, 11; 6, 31; 7, 8; 8, 9;...
9, 39; 10, 11; 10, 13; 10, 32;...
12, 11; 12, 13; 13, 14; 14, 15;...
15, 16; 16, 17; 16, 19; 16, 21;...
16, 24; 17, 18; 17, 27; 19, 20;...
19, 33; 20, 34; 21, 22; 22, 23;...
22, 35; 23, 24; 23, 36; 25, 26;...
25, 37; 26, 27; 26, 28; 26, 29;...
28, 29; 29, 38];
% 负荷矩阵
obj.load_mat=[3,4,7,8,12,15,16,18,20,21,23,24,25,26,27,28,29,31,39];
% 发电机矩阵
obj.gen_mat=[30,31,32,33,34,35,36,37,38,39];
% PMU位置矩阵
obj.pmu_loc=pmu_loc;
end
% 构造邻接矩阵、pmu位置数组、零注入节点数组
function [link_array, pmu_array, ZIB_array]=Construct_matrix(obj)
% 初始化
N = length(obj.bus_mat);
link_array = zeros(N, N);
pmu_array = zeros(N, 1);
ZIB_array = ones(N, 1);
% 构造邻接矩阵
branch=obj.branch_mat;
[BN,BM]=size(obj.branch_mat);
for i = 1:BN
link_array(branch(i, 1), branch(i, 2)) = 1;
link_array(branch(i, 2), branch(i, 1)) = 1;
end
% 构造pmu位置数组
pmu_array(obj.pmu_loc) = 1; % 减1是因为numpy从0数起
% 构造零注入节点数组,除去发电机以及负荷节点之外的节点
ZIB_array(obj.load_mat) = 0;
ZIB_array(obj.gen_mat) = 0;
end
function [V, I]=Observation(obj, link_array, pmu_array, ZIB_array)
% 初始化
N = length(obj.bus_mat);
V = zeros(N, 1); % 电压矩阵
I = zeros(N, N); % 电流矩阵,电流已知那么线路功率也是已知的
G = zeros(length(obj.gen_mat), 1); % 发电机矩阵
L = zeros(length(obj.load_mat), 1); % 负荷矩阵

% 中间变量
A = zeros(N, 1);
B = zeros(N, 1);
% 按照规则进行可观性描述
% 先确定安装有PMU的点
% 安装PMU的节点其节点电压和相连支路电流、相连节点电压可观
for i =1:N
% if pmu_array[i] == 1:
for j =1:N
if j ~= i
V(i) = pmu_array(i) || (pmu_array(j) && link_array(i, j));
I(i, j) = (pmu_array(i) || pmu_array(j)) && link_array(i, j);
I(j, i) = (pmu_array(i) || pmu_array(j)) && link_array(i, j);
end
end
end

for K =1:10 % 进行迭代直至收敛
% 支路两端电压可观,则该支路电流可观
for i = 1:N
for j = 1:N
if j ~= i
if V(i) == 1 && V(j) == 1 && I(i, j) == 0 && link_array(i, j) == 1
I(i, j) = V(i) && V(j);
I(j, i) = V(i) && V(j);
end
end
end
end


% 支路电流和另一端电压可知,则该支路另一端电压已知
for i = 1:N
for j = 1:N
if j ~= i && V(i) == 0
V(i) = V(i) || (I(i, j) && V(j));
end
end
end

% 零注入节点未配置PMU,且仅有一条相连支路电流未知,该支路电流可观
for i = 1:N
if ZIB_array(i) == 1
for j = 1:N
if i ~= j
for k = 1:N
A(k) = link_array(i, k) && I(i, k);
end
if sum(A) == sum(link_array(i, :)) - 1 && I(i, j) == 0
I(i, j) = ZIB_array(i) && link_array(i, j);
I(j, i) = ZIB_array(i) && link_array(i, j);
end
end
end
end
end

% 零注入节点未配置PMU,且所有相邻节点电压已知,则该节点电压已知
for i = 1:N
if ZIB_array(i) == 1 && V(i) == 0
for j = 1:N
if i ~= j
for k = 1:N
B(k) = link_array(i, k) && V(k);
end
if (sum(B) == sum(link_array(i, :))) && (V(i) == 0)
V(i) = ZIB_array(i);
end
end
end
end
end
end

end
function [V_Bus,I_Line_Result,G,L]=Index(obj,V, I,link_array)
N = length(obj.bus_mat);
G = []; % 发电机矩阵
L = []; % 负荷矩阵

V_Bus = find( V ~= 0 );
[I_Linerow, I_Linecol]= find( I ~= 0 );

I_Line = [];
I_Line_Result = [];
% 由于支路电流会计算两次,这里删去支路两端节点相同的一半元素,把不存在于原线路矩阵中的编号去除
for i =1:length(I_Linerow)
P=[I_Linerow(i), I_Linecol(i)]==obj.branch_mat;
index=find(sum(P,2) == 2);
I_Line_Result=[I_Line_Result;obj.branch_mat(index,:)];
end


for i =1:length(obj.gen_mat)
if V(obj.gen_mat(i))~=0 && sum(I(obj.gen_mat(i),:))==sum(link_array(obj.gen_mat(i),:))
G=[G,obj.gen_mat(i)];
end
end
for i =1:length(obj.load_mat)
if V(obj.load_mat(i))~=0 && sum(I(obj.load_mat(i),:))==sum(link_array(obj.load_mat(i),:))
L=[L,obj.load_mat(i)];
end
end
end
end
end

(2)主程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
clc;clear all
tic
PMU = PMU_Place([3,8,10,16,20,23,25,29]);
[link_array, pmu_array, ZIB_array] = PMU.Construct_matrix();
[V, I] = PMU.Observation(link_array, pmu_array, ZIB_array);
[V_Bus, I_Line_Result, G, L]=PMU.Index(V, I,link_array);
disp('==============计*算*结*果=============')
disp('1、电压可观节点总数为:');
disp(sum(sum(V)))
disp('2、电压可观节点编号为:')
disp(V_Bus')
disp('3、发电机可观节点编号为:')
disp(G)
disp('4、负荷可观节点编号为:')
disp(L)
disp('5、电流可观支路总数为:') % 由于支路电流会计算两次,这里删去支路两端节点相同的一半元素
disp(sum(sum(I)) / 2)
disp('6、电流可观支路两端节点编号(第一行为行编号,第二行为列编号)为:')
disp(I_Line_Result')
toc
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×