0001 function mpc = toggle_iflims(mpc, on_off)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042 if strcmp(upper(on_off), 'ON')
0043
0044 if ~isfield(mpc, 'if') || ~isstruct(mpc.if) || ...
0045 ~isfield(mpc.if, 'map') || ...
0046 ~isfield(mpc.if, 'lims')
0047 error('toggle_iflims: case must contain an ''if'' field, a struct defining ''map'' and ''lims''');
0048 end
0049
0050
0051
0052
0053 mpc = add_userfcn(mpc, 'ext2int', @userfcn_iflims_ext2int);
0054 mpc = add_userfcn(mpc, 'formulation', @userfcn_iflims_formulation);
0055 mpc = add_userfcn(mpc, 'int2ext', @userfcn_iflims_int2ext);
0056 mpc = add_userfcn(mpc, 'printpf', @userfcn_iflims_printpf);
0057 mpc = add_userfcn(mpc, 'savecase', @userfcn_iflims_savecase);
0058 mpc.userfcn.status.iflims = 1;
0059 elseif strcmp(upper(on_off), 'OFF')
0060 mpc = remove_userfcn(mpc, 'savecase', @userfcn_iflims_savecase);
0061 mpc = remove_userfcn(mpc, 'printpf', @userfcn_iflims_printpf);
0062 mpc = remove_userfcn(mpc, 'int2ext', @userfcn_iflims_int2ext);
0063 mpc = remove_userfcn(mpc, 'formulation', @userfcn_iflims_formulation);
0064 mpc = remove_userfcn(mpc, 'ext2int', @userfcn_iflims_ext2int);
0065 mpc.userfcn.status.iflims = 0;
0066 elseif strcmp(upper(on_off), 'STATUS')
0067 if isfield(mpc, 'userfcn') && isfield(mpc.userfcn, 'status') && ...
0068 isfield(mpc.userfcn.status, 'iflims')
0069 mpc = mpc.userfcn.status.iflims;
0070 else
0071 mpc = 0;
0072 end
0073 else
0074 error('toggle_iflims: 2nd argument must be ''on'', ''off'' or ''status''');
0075 end
0076
0077
0078
0079 function mpc = userfcn_iflims_ext2int(mpc, mpopt, args)
0080
0081
0082
0083
0084
0085
0086
0087
0088 ifmap = mpc.if.map;
0089 o = mpc.order;
0090 nl0 = size(o.ext.branch, 1);
0091 nl = size(mpc.branch, 1);
0092
0093
0094 mpc.order.ext.ifmap = ifmap;
0095
0096
0097 e2i = zeros(nl0, 1);
0098 e2i(o.branch.status.on) = (1:nl)';
0099 d = sign(ifmap(:, 2));
0100 br = abs(ifmap(:, 2));
0101 ifmap(:, 2) = d .* e2i(br);
0102 ifmap(ifmap(:, 2) == 0, :) = [];
0103
0104 mpc.if.map = ifmap;
0105
0106
0107
0108 function om = userfcn_iflims_formulation(om, mpopt, args)
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118 [F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ...
0119 TAP, SHIFT, BR_STATUS, PF, QF, PT, QT, MU_SF, MU_ST, ...
0120 ANGMIN, ANGMAX, MU_ANGMIN, MU_ANGMAX] = idx_brch;
0121
0122
0123 mpc = om.get_mpc();
0124 [baseMVA, bus, branch] = deal(mpc.baseMVA, mpc.bus, mpc.branch);
0125 ifmap = mpc.if.map;
0126 iflims = mpc.if.lims;
0127
0128
0129 [B, Bf, Pbusinj, Pfinj] = makeBdc(baseMVA, bus, branch);
0130 n = size(Bf, 2);
0131
0132
0133 ifidx = unique(iflims(:, 1));
0134 nifs = length(ifidx);
0135 Aif = sparse(nifs, n);
0136 lif = zeros(nifs, 1);
0137 uif = zeros(nifs, 1);
0138 for k = 1:nifs
0139
0140 br = ifmap(ifmap(:, 1) == ifidx(k), 2);
0141 if isempty(br)
0142 error('userfcn_iflims_formulation: interface %d has no in-service branches', k);
0143 end
0144 d = sign(br);
0145 br = abs(br);
0146 Ak = sparse(1, n);
0147 bk = 0;
0148 for i = 1:length(br)
0149 Ak = Ak + d(i) * Bf(br(i), :);
0150 bk = bk + d(i) * Pfinj(br(i));
0151 end
0152 Aif(k, :) = Ak;
0153 lif(k) = iflims(k, 2) / baseMVA - bk;
0154 uif(k) = iflims(k, 3) / baseMVA - bk;
0155 end
0156
0157
0158 om.add_lin_constraint('iflims', Aif, lif, uif, {'Va'});
0159
0160
0161
0162 function results = userfcn_iflims_int2ext(results, mpopt, args)
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174 [F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ...
0175 TAP, SHIFT, BR_STATUS, PF, QF, PT, QT, MU_SF, MU_ST, ...
0176 ANGMIN, ANGMAX, MU_ANGMIN, MU_ANGMAX] = idx_brch;
0177
0178
0179 ifmap = results.if.map;
0180 iflims = results.if.lims;
0181
0182
0183 results.if.map = results.order.ext.ifmap;
0184
0185
0186 ifidx = unique(iflims(:, 1));
0187 nifs = length(ifidx);
0188 results.if.P = zeros(nifs, 1);
0189 for k = 1:nifs
0190
0191 br = ifmap(ifmap(:, 1) == ifidx(k), 2);
0192 d = sign(br);
0193 br = abs(br);
0194 results.if.P(k) = sum( d .* results.branch(br, PF) );
0195 end
0196 results.if.mu.l = results.lin.mu.l.iflims / results.baseMVA;
0197 results.if.mu.u = results.lin.mu.u.iflims / results.baseMVA;
0198
0199
0200
0201 function results = userfcn_iflims_printpf(results, fd, mpopt, args)
0202
0203
0204
0205
0206
0207
0208
0209
0210 [F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ...
0211 TAP, SHIFT, BR_STATUS, PF, QF, PT, QT, MU_SF, MU_ST, ...
0212 ANGMIN, ANGMAX, MU_ANGMIN, MU_ANGMAX] = idx_brch;
0213
0214
0215 ptol = 1e-6;
0216 isOPF = isfield(results, 'f') && ~isempty(results.f);
0217 SUPPRESS = mpopt.out.suppress_detail;
0218 if SUPPRESS == -1
0219 if size(results.bus, 1) > 500
0220 SUPPRESS = 1;
0221 else
0222 SUPPRESS = 0;
0223 end
0224 end
0225 OUT_ALL = mpopt.out.all;
0226 OUT_FORCE = mpopt.out.force;
0227 OUT_BRANCH = OUT_ALL == 1 || (OUT_ALL == -1 && ~SUPPRESS && mpopt.out.branch);
0228
0229 if isOPF && OUT_BRANCH && (results.success || OUT_FORCE)
0230 iflims = results.if.lims;
0231 fprintf(fd, '\n================================================================================');
0232 fprintf(fd, '\n| Interface Flow Limits |');
0233 fprintf(fd, '\n================================================================================');
0234 fprintf(fd, '\n Interface Shadow Prc Lower Lim Flow Upper Lim Shadow Prc');
0235 fprintf(fd, '\n # ($/MW) (MW) (MW) (MW) ($/MW) ');
0236 fprintf(fd, '\n---------- ---------- ---------- ---------- ---------- -----------');
0237 ifidx = unique(iflims(:, 1));
0238 nifs = length(ifidx);
0239 for k = 1:nifs
0240 fprintf(fd, '\n%6d ', iflims(k, 1));
0241 if results.if.mu.l(k) > ptol
0242 fprintf(fd, '%14.3f', results.if.mu.l(k));
0243 else
0244 fprintf(fd, ' - ');
0245 end
0246 fprintf(fd, '%12.2f%12.2f%12.2f', iflims(k, 2), results.if.P(k), iflims(k, 3));
0247 if results.if.mu.u(k) > ptol
0248 fprintf(fd, '%13.3f', results.if.mu.u(k));
0249 else
0250 fprintf(fd, ' - ');
0251 end
0252 end
0253 fprintf(fd, '\n');
0254 end
0255
0256
0257
0258 function mpc = userfcn_iflims_savecase(mpc, fd, prefix, args)
0259
0260
0261
0262
0263
0264
0265
0266
0267 ifmap = mpc.if.map;
0268 iflims = mpc.if.lims;
0269
0270 fprintf(fd, '\n%%%%----- Interface Flow Limit Data -----%%%%\n');
0271 fprintf(fd, '%%%% interface<->branch map data\n');
0272 fprintf(fd, '%%\tifnum\tbranchidx (negative defines opposite direction)\n');
0273 fprintf(fd, '%sif.map = [\n', prefix);
0274 fprintf(fd, '\t%d\t%d;\n', ifmap');
0275 fprintf(fd, '];\n');
0276
0277 fprintf(fd, '\n%%%% interface flow limit data (based on DC model)\n');
0278 fprintf(fd, '%%%% (lower limit should be negative for opposite direction)\n');
0279 fprintf(fd, '%%\tifnum\tlower\tupper\n');
0280 fprintf(fd, '%sif.lims = [\n', prefix);
0281 fprintf(fd, '\t%d\t%g\t%g;\n', iflims');
0282 fprintf(fd, '];\n');
0283
0284
0285 if isfield(mpc.if, 'P')
0286 if exist('serialize', 'file') == 2
0287 fprintf(fd, '\n%%%% solved values\n');
0288 fprintf(fd, '%sif.P = %s\n', prefix, serialize(mpc.if.P));
0289 fprintf(fd, '%sif.mu.l = %s\n', prefix, serialize(mpc.if.mu.l));
0290 fprintf(fd, '%sif.mu.u = %s\n', prefix, serialize(mpc.if.mu.u));
0291 else
0292 url = 'https://www.mathworks.com/matlabcentral/fileexchange/12063-serialize';
0293 warning('MATPOWER:serialize', ...
0294 'userfcn_iflims_savecase: Cannot save the ''iflims'' output fields without the ''serialize'' function, which is available as a free download from:\n<%s>\n\n', url);
0295 end
0296 end