-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfm_atc.m
357 lines (308 loc) · 8.95 KB
/
fm_atc.m
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
function fm_atc
%FM_ATC determine the Available Transfer Capability (ATC)
% by means of an iterative OPF/CPF method or a power
% flow sensitivity analysis
%
%FM_ATC
%
%see OPF and CPF structures for settings
%
%Author: Federico Milano
%Date: 11-Nov-2002
%Version: 1.0.0
%
%E-mail: [email protected]
%Web-site: faraday1.ucd.ie/psat.html
%
% Copyright (C) 2002-2019 Federico Milano
fm_var
if ~autorun('ATC analysis',0)
return
end
fm_disp
if ~Demand.n
fm_disp('ATC computations requires the definition of "Demand" data',2)
return
end
if ~Supply.n
fm_disp('ATC computations requires the definition of "Supply" data',2)
return
end
switch OPF.type
case 4
fm_disp('Determination of ATC by means of an iterative OPF-CPF method')
case 5
fm_disp('Determination of ATC by means of a power flow sensitivity analysis')
end
tempo1 = clock;
OPF.show = 0;
Settings.show = 0;
% Continuation Power Flow settings
% -------------------------------------------------------------------------
CPFold = CPF;
CPF.show = 0;
CPF.method = 1;
CPF.flow = OPF.flow;
CPF.type = 3;
CPF.sbus = 0;
CPF.vlim = 1;
CPF.ilim = 1;
CPF.qlim = 1;
% ===================================================================
% Determination of "antennas", i.e. lines that connects
% a PQ or a PV bus to the rest of the network
% ===================================================================
[busidx,lineidx] = findantennas(Line);
if ishandle(Fig.main)
fm_disp
if ishandle(Hdl.status)
delete(Hdl.status)
Hdl.status = -1;
end
hdl = findobj(Fig.main,'Tag','PushClose');
set(hdl,'String','Stop');
set(Fig.main,'UserData',1);
end
sp = ' * ';
CPFold = CPF;
% bus voltage limits
[Vmax,Vmin] = fm_vlim(1.2,0.8);
% Continuation Power Flow settings
% -----------------------------------------------------------------------
CPF.method = 1;
CPF.flow = 1;
CPF.type = 3;
CPF.sbus = 0;
CPF.vlim = 1;
CPF.ilim = 1;
CPF.qlim = 1;
CPF.linit = 0;
% =======================================================================
% First OPF solution without contingencies
% =======================================================================
fm_disp('First OPF solution without faults.')
fm_opfsdr
if ~OPF.conv && ishandle(Fig.main)
set(Fig.main,'UserData',0)
end
if strcmp(History.text{end},'Optimization routine interrupted.')
return
end
fm_disp([sp,'ATC = ', num2str(OPF.atc)])
idx_old = 0;
atc_old = 0;
y_old = DAE.y;
MVA = Settings.mva;
[busP,idxP,idxQ] = intersect(PQ.bus,Demand.bus);
tgphi = tanphi(PQ,idxP);
% =======================================================================
% Continuation Power Flow loop for the (N-1) contingency evaluations
% =======================================================================
while 1
if ishandle(Fig.main)
if ~get(Fig.main,'UserData'), break, end
end
lcrit = [];
Supply = pgset(Supply);
Demand = pqset(Demand,tgphi);
%fm_disp('Continuation Power Flow Computations')
switch OPF.type
case 4 % (N-1) contingency analysis
for i = 1:Line.n
if ishandle(Fig.main)
if ~get(Fig.main,'UserData'), break, end
end
fm_disp('Continuation Power Flow Computations')
if isempty(find(lineidx==i))
fm_disp(['Line #',fvar(i,4)])
fm_disp([sp,'from bus #',fvar(Line.fr(i),5), ...
' to bus #',fvar(Line.to(i),5)])
DAE.y(1:DAE.m) = OPF.yc;
length(Snapshot.y);
DAE.x = Snapshot(1).x;
status = Line.u(i);
% set line outage
Line = setstatus(Line,i,0);
idx = find(abs(DAE.y(Bus.v)-Vmax) < 1e-5);
if ~isempty(idx), DAE.y(idx+Bus.n) = Vmax(idx)-1e-2; end
CPF.init = 0;
OPF.init = 0;
a = fm_cpf('atc');
if ~isempty(a)
lcrit = [lcrit; [(a*totp(Demand)+totp(PQ))*MVA, i]];
else
lcrit = [lcrit; [NaN, 0]];
end
fm_disp([sp,'ATC = ', num2str(lcrit(end,1))])
% reset line outage
Line.u(i) = status;
end
end
% reset admittance matrix
Line = build_y(Line);
case 5 % sensitivity analysis: ranking (dPij/dlambda) & (Pij)
fm_disp
fm_disp('Sensitivity analysis.')
lambda = OPF.guess(end-4*Bus.n);
kg = OPF.guess(end-4*Bus.n-1-PV.n-SW.n);
lambda = lambda - 1e-6;
% active power flows in transmission lines
[Fij,Fji] = flows(Line,'active');
Pflow1 = max(Fij,Fji);
PQ = pqmul(PQ,'all',1+lambda);
pqsum(Demand,1+lambda);
PV = pvmul(PV,'all',1+lambda+kg);
pgsum(Supply,1+lambda+kg);
PV = setvg(PV,'all',OPF.yc(PV.vbus));
pg = SW.pg;
SW = setvg(SW,'all',OPF.yc(SW.vbus));
DAE.y = OPF.yc;
fm_spf
fm_disp
% active power flows in transmission lines
[Fij,Fji] = flows(Line,'active');
Pflow2 = max(Fij,Fji);
% sensitivity coefficients
dPdl = (Pflow1-Pflow2)/1e-6;
fm_disp(['Line |Pij(lambda)| ', ...
'|Pij(lambda-dl)| |Pij|*|d Pij/d lambda|'])
for i = 1:Line.n
fm_disp([fvar(i,4),' ',fvar(Line.fr(i),4),' -> ', ...
fvar(Line.to(i),4),' ',fvar(Pflow1(i),19), ...
fvar(Pflow2(i),19),fvar(Pflow1(i)*abs(dPdl(i)),19)])
end
PQ = pqreset(PQ,'all');
PV = pvreset(PV,'all');
SW = restore(SW);
SW = setpg(SW,'all',pg);
end
fm_disp
switch OPF.type
case 4
[atc,idx] = min(lcrit(:,1));
OPF.line = lcrit(idx,2);
fm_disp(['Critical Line #',num2str(idx), ...
' from bus #',fvar(Line.fr(idx),5), ...
' to bus #',fvar(Line.to(idx),5)])
fm_disp([sp,'ATC = ', num2str(lcrit(idx,1))])
case 5
if lineidx, dPdl(lineidx) = 0; end
pfactor = Pflow1.*abs(dPdl);
[pfactor, pfactor_idx] = sort(pfactor);
CPF.Pij = Pflow1;
CPF.dPdl = dPdl;
fm_disp('OPF solution without contingencies:')
fm_disp([sp,'max(Pij*|dPij/dlambda)| = ', num2str(pfactor(end)), ...
' (Line # ',fvar(pfactor_idx(end),4),')'])
fm_disp([sp,'lambda = ',num2str(lambda)])
fm_disp([sp,'ATC = ',num2str(OPF.atc)])
end
fm_disp
%======================================================================
% OPF with inclusion of a fault on the critical line
%======================================================================
fm_disp('OPF with contingencies')
switch OPF.type
case 4
CPF.init = 0;
DAE.y = Snapshot(1).y;
DAE.x = Snapshot(1).x;
fm_spf
fm_opfsdr
if ishandle(Fig.main) && ~OPF.conv, set(Fig.main,'UserData',0), end
case 5
nopf = min(5,length(pfactor_idx));
atc = zeros(nopf,1);
rep = cell(nopf,1);
for i = 1:nopf
OPF.init = 0;
CPF.init = 0;
if ishandle(Fig.main)
if ~get(Fig.main,'UserData'), break, end
end
OPF.line = pfactor_idx(end-(i-1));
DAE.y = Snapshot(1).y;
DAE.x = Snapshot(1).x;
fm_spf
fm_disp(['OPF computation with contingency on Line # ', ...
num2str(pfactor_idx(end-(i-1)))])
fm_opfsdr
if ishandle(Fig.main) && ~OPF.conv, set(Fig.main,'UserData',0), end
atc(i) = OPF.atc;
rep{i} = OPF.report;
fm_disp([sp,'ATC = ', num2str(OPF.atc)])
end
[atc, idx_atc] = min(atc);
OPF.report = rep{idx_atc};
fm_disp
idxc = pfactor_idx(end-(idx_atc-1));
fm_disp(['Critical Line #',num2str(idxc),' from bus #', ...
fvar(Line.fr(idxc),5), ...
' to bus #',fvar(Line.to(idxc),5)])
fm_disp([sp,'ATC = ',num2str(atc)])
end
% ====================================================================
% Convergency Criteria
% ====================================================================
% stop if the method uses sensitivity analysis
if OPF.type == 5, break, end
% stop if ATC level has not changed
if abs(OPF.atc - atc) < 1e-2, break, end
% stop if the worst line is always the same
if idx == idx_old(end), break, end
idx_old = [idx_old, idx];
if OPF.type == 4,
if ~isempty(OPF.report)
rep_old(:,length(idx_old)-1) = OPF.report;
end
atc_old = [atc_old, OPF.atc];
end
% stop if the worst lines are always the same two
% and chose the solution which has the lowest ATC
if length(idx_old) > 3
if idx_old(end) == idx_old(end-2),
fm_disp
if atc_old(end) > atc_old(end-1),
OPF.report = rep_old(:,end-1);
idxc = idx_old(end-1);
else
idxc = idx_old(end);
end
fm_disp(['Critical Line #',num2str(idxc), ...
' from bus #',fvar(Line.fr(idxc),5), ...
' to bus #',fvar(Line.to(idxc),5)])
break
end
end
end
CPF = CPFold;
% restore components
Line = build_y(Line);
islands(Line)
PV = pvreset(PV,'all');
SW = restore(SW);
PQ = pqreset(PQ,'all');
Demand = restore(Demand);
Supply = restore(Supply);
if ishandle(Fig.main), set(hdl,'String','Close'); end
Settings.show = 1;
OPF.show = 1;
OPF.line = 0;
CPF = CPFold;
CPF.show = 1;
CPF.init = 2;
OPF.init = 0;
LIB.init = 0;
SNB.init = 0;
if ishandle(Fig.main)
if get(Fig.main,'UserData'),
History.text = [History.text; ...
{' '; 'Final OPF Solution:'; ' '}; ...
OPF.report];
fm_disp(['ATC = ',num2str(atc)])
fm_disp(['ATC computation completed in ', ...
num2str(etime(clock,tempo1)),' s'])
else
fm_disp('ATC computation interrupted.')
end
end