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