-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpostproc_maxloadlim.m
74 lines (68 loc) · 2.9 KB
/
postproc_maxloadlim.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
function results = postproc_maxloadlim(results,dir_mll)
% POSTPROC_MAXLOADLIM Performs some post processing on the results returned
% by the ACOPF run in MATPOWER.
% RESULTS = POSTPROC_MAXLOADLIM(RESULTS,DIR_MLL) transforms the dispatchable
% loads back to normal loads and parse the results in the struct RESULTS
% to provide contextual information on the maximum loadability point
% found in the direction of load increase defined by DIR_MLL. It returns
% the updated struct RESULTS.
% MATPOWER
% Copyright (c) 2015-2016, Power Systems Engineering Research Center (PSERC)
% by Camille Hamon
%
% This file is part of MATPOWER.
% Covered by the 3-clause BSD License (see LICENSE file for details).
% See http://www.pserc.cornell.edu/matpower/ for more info.
define_constants;
% Transforming the dispatchable gen back to loads
idx_gen_load_disp = isload(results.gen);
idx_bus_load_disp = results.gen(idx_gen_load_disp,GEN_BUS);
results.bus(idx_bus_load_disp ,[PD QD]) = -results.gen(idx_gen_load_disp,[PG QG]);
results.gen(idx_gen_load_disp,:) = [];
results.gencost(idx_gen_load_disp,:) = [];
% Removing the shadow prices corresponding to dispatchable loads
results.var.mu.u.Pg(idx_gen_load_disp) = [];
results.var.mu.l.Pg(idx_gen_load_disp) = [];
results.var.mu.u.Qg(idx_gen_load_disp) = [];
results.var.mu.l.Qg(idx_gen_load_disp) = [];
% If all gens at bus have non zero reactive power shadow prices, this bus
% is PQ
for bb = 1:size(results.bus,1)
gen_list_at_bb = results.gen(:,GEN_BUS) == bb;
if all(results.var.mu.u.Qg(gen_list_at_bb)>0)
results.bus(bb,BUS_TYPE) = PQ;
end
end
% Create a new field for the stability margin in load increase
results.stab_marg = results.var.val.alpha;
% Create a new field for the stability margin in gen change
if isfield(results.var.val,'beta')
results.gen_stab_marg = results.var.val.beta;
end
% Remove the cost for the printpf function to consider the results as load
% flow results.
results.f = [];
% Direction defined over all buses (not only over nonzero loads)
results.dir_mll = dir_mll;
% Determining the type of bifurcation (SNB or SLL)
% SLL is characterized by having both reactive power limit and voltage
% limit binding at one generator
shadow_price_Qg = results.var.mu.u.Qg;
shadow_price_Vm = results.var.mu.u.Vm;
% Map the shadow price of bus voltage magnitude to generators
shadow_price_Vg = shadow_price_Vm(results.gen(:,GEN_BUS));
idx_bus_sll = shadow_price_Qg & shadow_price_Vg;
if sum(idx_bus_sll) > 0
results.bif.short_name = 'LIB';
results.bif.full_name = 'limit-induced bifurcation';
results.bif.gen_sll = find(idx_bus_sll);
else
results.bif.short_name = 'SNB';
results.bif.full_name = 'saddle-node bifurcation';
end
% Building the sets of gens that reached their Q lims and of gens that did
% not
gen_a = shadow_price_Vm(results.gen(:,GEN_BUS))~= 0;
gen_b = shadow_price_Qg ~= 0;
results.bif.gen_a = gen_a;
results.bif.gen_b = gen_b;