0001 function mpc = toggle_softlims(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
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 if strcmp(upper(on_off), 'ON')
0073
0074
0075
0076
0077
0078
0079 mpc = add_userfcn(mpc, 'ext2int', @userfcn_softlims_ext2int);
0080 mpc = add_userfcn(mpc, 'formulation', @userfcn_softlims_formulation);
0081 mpc = add_userfcn(mpc, 'int2ext', @userfcn_softlims_int2ext);
0082 mpc = add_userfcn(mpc, 'printpf', @userfcn_softlims_printpf);
0083 mpc = add_userfcn(mpc, 'savecase', @userfcn_softlims_savecase);
0084 mpc.userfcn.status.softlims = 1;
0085 elseif strcmp(upper(on_off), 'OFF')
0086 mpc = remove_userfcn(mpc, 'savecase', @userfcn_softlims_savecase);
0087 mpc = remove_userfcn(mpc, 'printpf', @userfcn_softlims_printpf);
0088 mpc = remove_userfcn(mpc, 'int2ext', @userfcn_softlims_int2ext);
0089 mpc = remove_userfcn(mpc, 'formulation', @userfcn_softlims_formulation);
0090 mpc = remove_userfcn(mpc, 'ext2int', @userfcn_softlims_ext2int);
0091 mpc.userfcn.status.softlims = 0;
0092 elseif strcmp(upper(on_off), 'STATUS')
0093 if isfield(mpc, 'userfcn') && isfield(mpc.userfcn, 'status') && ...
0094 isfield(mpc.userfcn.status, 'softlims')
0095 mpc = mpc.userfcn.status.softlims;
0096 else
0097 mpc = 0;
0098 end
0099 else
0100 error('toggle_softlims: 2nd argument must be ''on'', ''off'' or ''status''');
0101 end
0102
0103
0104
0105 function mpc = userfcn_softlims_ext2int(mpc, args)
0106
0107
0108
0109
0110
0111
0112
0113
0114 [F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ...
0115 TAP, SHIFT, BR_STATUS, PF, QF, PT, QT, MU_SF, MU_ST, ...
0116 ANGMIN, ANGMAX, MU_ANGMIN, MU_ANGMAX] = idx_brch;
0117
0118
0119 default_cost = 1000;
0120 if isfield(mpc, 'softlims')
0121 if ~isfield(mpc.softlims, 'idx')
0122 mpc.softlims.idx = [];
0123 end
0124 if ~isfield(mpc.softlims, 'cost')
0125 mpc.softlims.cost = default_cost;
0126 end
0127 else
0128 mpc.softlims.idx = [];
0129 mpc.softlims.cost = default_cost;
0130 end
0131
0132
0133 s = mpc.softlims;
0134 o = mpc.order;
0135 nl0 = size(o.ext.branch, 1);
0136 nl = size(mpc.branch, 1);
0137
0138
0139 mpc.order.ext.softlims = s;
0140
0141
0142 s = softlims_defaults(s, o.ext.branch);
0143 e2i = zeros(nl0, 1);
0144 e2i(o.branch.status.on) = (1:nl)';
0145 s.idx = e2i(s.idx);
0146 k = find(s.idx == 0);
0147 s.idx(k) = [];
0148 s.cost(k, :) = [];
0149 k = find(mpc.branch(s.idx, RATE_A) <= 0);
0150 s.idx(k) = [];
0151 s.cost(k, :) = [];
0152
0153
0154 s.Pfmax = mpc.branch(s.idx, RATE_A) / mpc.baseMVA;
0155 mpc.branch(s.idx, RATE_A) = 0;
0156
0157 mpc.softlims = s;
0158 mpc.order.int.softlims = s;
0159
0160
0161
0162 function om = userfcn_softlims_formulation(om, args)
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172 [F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ...
0173 TAP, SHIFT, BR_STATUS, PF, QF, PT, QT, MU_SF, MU_ST, ...
0174 ANGMIN, ANGMAX, MU_ANGMIN, MU_ANGMAX] = idx_brch;
0175
0176
0177 mpc = get_mpc(om);
0178 [baseMVA, bus, branch] = deal(mpc.baseMVA, mpc.bus, mpc.branch);
0179 s = mpc.softlims;
0180
0181
0182 [B, Bf, Pbusinj, Pfinj] = makeBdc(baseMVA, bus, branch);
0183 n = size(Bf, 2);
0184
0185
0186
0187
0188 ns = length(s.idx);
0189 I = speye(ns, ns);
0190 As = [-Bf(s.idx, :) -I; Bf(s.idx, :) -I];
0191 ls = -Inf(2*ns, 1);
0192 us = [ Pfinj(s.idx) + s.Pfmax;
0193 -Pfinj(s.idx) + s.Pfmax ];
0194
0195
0196 Cw = s.cost(:, 1) * mpc.baseMVA;
0197
0198
0199 om = add_vars(om, 'flv', ns, zeros(ns, 1), zeros(ns, 1), Inf(ns, 1));
0200 om = add_costs(om, 'vc', struct('N', I, 'Cw', Cw), {'flv'});
0201 om = add_constraints(om, 'softlims', As, ls, us, {'Va', 'flv'});
0202
0203
0204
0205 function results = userfcn_softlims_int2ext(results, args)
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217 [F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ...
0218 TAP, SHIFT, BR_STATUS, PF, QF, PT, QT, MU_SF, MU_ST, ...
0219 ANGMIN, ANGMAX, MU_ANGMIN, MU_ANGMAX] = idx_brch;
0220
0221
0222 s = results.softlims;
0223
0224
0225 o = results.order;
0226 nl0 = size(o.ext.branch, 1);
0227 nl = size(results.branch, 1);
0228 o.branch.status.on;
0229 results.softlims = results.order.ext.softlims;
0230
0231
0232 results.branch(s.idx, RATE_A) = s.Pfmax * results.baseMVA;
0233
0234
0235
0236 n = size(results.lin.mu.u.softlims, 1) / 2;
0237 results.branch(s.idx, MU_ST) = results.lin.mu.u.softlims(1:n) / results.baseMVA;
0238 results.branch(s.idx, MU_SF) = results.lin.mu.u.softlims(n+1:end) / results.baseMVA;
0239
0240 results.softlims.overload = zeros(nl0, 1);
0241 k = find(results.branch(:, RATE_A) & ...
0242 abs(results.branch(:, PF)) > results.branch(:, RATE_A) );
0243 results.softlims.overload(o.branch.status.on(k)) = ...
0244 abs(results.branch(k, PF)) - results.branch(k, RATE_A);
0245 results.softlims.ovl_cost = zeros(size(results.softlims.overload));
0246 results.softlims.ovl_cost(o.branch.status.on(s.idx)) = ...
0247 results.softlims.overload(o.branch.status.on(s.idx)) .* s.cost(:, 1);
0248
0249
0250
0251 function results = userfcn_softlims_printpf(results, fd, mpopt, args)
0252
0253
0254
0255
0256
0257
0258
0259
0260 [F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ...
0261 TAP, SHIFT, BR_STATUS, PF, QF, PT, QT, MU_SF, MU_ST, ...
0262 ANGMIN, ANGMAX, MU_ANGMIN, MU_ANGMAX] = idx_brch;
0263
0264
0265 ptol = 1e-6;
0266 isOPF = isfield(results, 'f') && ~isempty(results.f);
0267 SUPPRESS = mpopt.out.suppress_detail;
0268 if SUPPRESS == -1
0269 if size(results.bus, 1) > 500
0270 SUPPRESS = 1;
0271 else
0272 SUPPRESS = 0;
0273 end
0274 end
0275 OUT_ALL = mpopt.out.all;
0276 OUT_FORCE = mpopt.out.force;
0277 OUT_BRANCH = OUT_ALL == 1 || (OUT_ALL == -1 && ~SUPPRESS && mpopt.out.branch);
0278
0279 if isOPF && OUT_BRANCH && (results.success || OUT_FORCE)
0280 s = softlims_defaults(results.softlims, results.branch);
0281 k = find(s.overload(s.idx) | sum(results.branch(s.idx, MU_SF:MU_ST), 2) > ptol);
0282
0283 fprintf(fd, '\n================================================================================');
0284 fprintf(fd, '\n| Soft Flow Limits |');
0285 fprintf(fd, '\n================================================================================');
0286 fprintf(fd, '\nBrnch From To Flow Limit Overload mu');
0287 fprintf(fd, '\n # Bus Bus (MW) (MW) (MW) ($/MW)');
0288 fprintf(fd, '\n----- ----- ----- -------- -------- -------- ---------');
0289 fprintf(fd, '\n%4d%7d%7d%10.2f%10.2f%10.2f%11.3f', ...
0290 [ s.idx(k), results.branch(s.idx(k), [F_BUS, T_BUS]), ...
0291 results.branch(s.idx(k), [PF, RATE_A]), ...
0292 s.overload(s.idx(k)), ...
0293 sum(results.branch(s.idx(k), [MU_SF:MU_ST]), 2) ...
0294 ]');
0295 fprintf(fd, '\n --------');
0296 fprintf(fd, '\n Total:%10.2f', ...
0297 sum(s.overload(s.idx(k))));
0298 fprintf(fd, '\n');
0299 end
0300
0301
0302
0303 function mpc = userfcn_softlims_savecase(mpc, fd, prefix, args)
0304
0305
0306
0307
0308
0309
0310
0311
0312 if isfield(mpc, 'softlims')
0313 s = mpc.softlims;
0314
0315 fprintf(fd, '\n%%%%----- Soft Flow Limit Data -----%%%%\n');
0316
0317 if isfield(s, 'idx')
0318 fprintf(fd, '%%%% branch indexes\n');
0319 fprintf(fd, '%%\tbranchidx\n');
0320 if isempty(s.idx)
0321 fprintf(fd, '%ssoftlims.idx = [];\n\n', prefix);
0322 else
0323 fprintf(fd, '%ssoftlims.idx = [\n', prefix);
0324 fprintf(fd, '\t%d;\n', s.idx);
0325 fprintf(fd, '];\n\n');
0326 end
0327 end
0328
0329 fprintf(fd, '%%%% violation cost coefficients\n');
0330 fprintf(fd, '%%\trate_a_cost\n');
0331 fprintf(fd, '%ssoftlims.cost = [\n', prefix);
0332 fprintf(fd, '\t%g;\n', s.cost);
0333 fprintf(fd, '];\n');
0334
0335
0336 if isfield(mpc.softlims, 'overload')
0337 fprintf(fd, '\n%%%% overloads\n');
0338 fprintf(fd, '%%\toverload\n');
0339 fprintf(fd, '%ssoftlims.overload = [\n', prefix);
0340 fprintf(fd, '\t%g;\n', s.overload);
0341 fprintf(fd, '];\n');
0342
0343 fprintf(fd, '\n%%%% overload costs\n');
0344 fprintf(fd, '%%\toverload_costs\n');
0345 fprintf(fd, '%ssoftlims.ovl_cost = [\n', prefix);
0346 fprintf(fd, '\t%g;\n', s.ovl_cost);
0347 fprintf(fd, '];\n');
0348 end
0349 end
0350
0351
0352 function s = softlims_defaults(s, branch)
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363 [F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ...
0364 TAP, SHIFT, BR_STATUS, PF, QF, PT, QT, MU_SF, MU_ST, ...
0365 ANGMIN, ANGMAX, MU_ANGMIN, MU_ANGMAX] = idx_brch;
0366
0367 if isempty(s.idx)
0368 s.idx = find(branch(:, BR_STATUS) > 0 & branch(:, RATE_A) > 0);
0369 end
0370 if length(s.cost) == 1 && length(s.idx) > 1
0371 s.cost = s.cost * ones(size(s.idx));
0372 end