0001 function mpc = toggle_dcline(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 if strcmp(upper(on_off), 'ON')
0061
0062 c = idx_dcline;
0063
0064
0065 if ~isfield(mpc, 'dcline') || size(mpc.dcline, 2) < c.LOSS1
0066 error('toggle_dcline: case must contain a ''dcline'' field, an ndc x %d matrix.', c.LOSS1);
0067 end
0068 if isfield(mpc, 'dclinecost') && size(mpc.dcline, 1) ~= size(mpc.dclinecost, 1)
0069 error('toggle_dcline: number of rows in ''dcline'' field (%d) and ''dclinecost'' field (%d) do not match.', ...
0070 size(mpc.dcline, 1), size(mpc.dclinecost, 1));
0071 end
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081 mpc = add_userfcn(mpc, 'ext2int', @userfcn_dcline_ext2int);
0082 mpc = add_userfcn(mpc, 'formulation', @userfcn_dcline_formulation);
0083 mpc = add_userfcn(mpc, 'int2ext', @userfcn_dcline_int2ext);
0084 mpc = add_userfcn(mpc, 'printpf', @userfcn_dcline_printpf);
0085 mpc = add_userfcn(mpc, 'savecase', @userfcn_dcline_savecase);
0086 mpc.userfcn.status.dcline = 1;
0087 elseif strcmp(upper(on_off), 'OFF')
0088 mpc = remove_userfcn(mpc, 'savecase', @userfcn_dcline_savecase);
0089 mpc = remove_userfcn(mpc, 'printpf', @userfcn_dcline_printpf);
0090 mpc = remove_userfcn(mpc, 'int2ext', @userfcn_dcline_int2ext);
0091 mpc = remove_userfcn(mpc, 'formulation', @userfcn_dcline_formulation);
0092 mpc = remove_userfcn(mpc, 'ext2int', @userfcn_dcline_ext2int);
0093 mpc.userfcn.status.dcline = 0;
0094 elseif strcmp(upper(on_off), 'STATUS')
0095 if isfield(mpc, 'userfcn') && isfield(mpc.userfcn, 'status') && ...
0096 isfield(mpc.userfcn.status, 'dcline')
0097 mpc = mpc.userfcn.status.dcline;
0098 else
0099 mpc = 0;
0100 end
0101 else
0102 error('toggle_dcline: 2nd argument must be ''on'', ''off'' or ''status''');
0103 end
0104
0105
0106
0107 function mpc = userfcn_dcline_ext2int(mpc, args)
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120 [PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ...
0121 VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus;
0122 [GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, ...
0123 MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, ...
0124 QC2MIN, QC2MAX, RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = idx_gen;
0125 [PW_LINEAR, POLYNOMIAL, MODEL, STARTUP, SHUTDOWN, NCOST, COST] = idx_cost;
0126 c = idx_dcline;
0127
0128
0129 if isfield(mpc, 'dclinecost')
0130 havecost = 1;
0131 else
0132 havecost = 0;
0133 end
0134
0135
0136 mpc.order.ext.dcline = mpc.dcline;
0137 if havecost
0138 mpc.order.ext.dclinecost = mpc.dclinecost;
0139 end
0140
0141
0142 mpc.order.dcline.status.on = find(mpc.dcline(:, c.BR_STATUS) > 0);
0143 mpc.order.dcline.status.off = find(mpc.dcline(:, c.BR_STATUS) <= 0);
0144
0145
0146 dc = mpc.dcline(mpc.order.dcline.status.on, :);
0147 if havecost
0148 dcc = mpc.dclinecost(mpc.order.dcline.status.on, :);
0149 mpc.dclinecost = dcc;
0150 end
0151 ndc = size(dc, 1);
0152 o = mpc.order;
0153
0154
0155 dc(:, c.F_BUS) = o.bus.e2i(dc(:, c.F_BUS));
0156 dc(:, c.T_BUS) = o.bus.e2i(dc(:, c.T_BUS));
0157 mpc.dcline = dc;
0158
0159
0160
0161
0162 dc(:, c.PT) = dc(:, c.PF) - (dc(:, c.LOSS0) + dc(:, c.LOSS1) .* dc(:, c.PF));
0163
0164
0165 fg = zeros(ndc, size(mpc.gen, 2));
0166 fg(:, MBASE) = 100;
0167 fg(:, GEN_STATUS) = dc(:, c.BR_STATUS);
0168 fg(:, PMIN) = -Inf;
0169 fg(:, PMAX) = Inf;
0170 tg = fg;
0171 fg(:, GEN_BUS) = dc(:, c.F_BUS);
0172 tg(:, GEN_BUS) = dc(:, c.T_BUS);
0173 fg(:, PG) = -dc(:, c.PF);
0174 tg(:, PG) = dc(:, c.PT);
0175 fg(:, QG) = dc(:, c.QF);
0176 tg(:, QG) = dc(:, c.QT);
0177 fg(:, VG) = dc(:, c.VF);
0178 tg(:, VG) = dc(:, c.VT);
0179 k = find(dc(:, c.PMIN) >= 0);
0180 if ~isempty(k)
0181 fg(k, PMAX) = -dc(k, c.PMIN);
0182 end
0183 k = find(dc(:, c.PMAX) >= 0);
0184 if ~isempty(k)
0185 fg(k, PMIN) = -dc(k, c.PMAX);
0186 end
0187 k = find(dc(:, c.PMIN) < 0);
0188 if ~isempty(k)
0189 tg(k, PMIN) = dc(k, c.PMIN);
0190 end
0191 k = find(dc(:, c.PMAX) < 0);
0192 if ~isempty(k)
0193 tg(k, PMAX) = dc(k, c.PMAX);
0194 end
0195 fg(:, QMIN) = dc(:, c.QMINF);
0196 fg(:, QMAX) = dc(:, c.QMAXF);
0197 tg(:, QMIN) = dc(:, c.QMINT);
0198 tg(:, QMAX) = dc(:, c.QMAXT);
0199
0200
0201
0202 fg(isload(fg), PMAX) = -1e-6;
0203 tg(isload(tg), PMAX) = -1e-6;
0204
0205
0206 refbus = find(mpc.bus(:, BUS_TYPE) == REF);
0207 mpc.bus(dc(:, c.F_BUS), BUS_TYPE) = PV;
0208 mpc.bus(dc(:, c.T_BUS), BUS_TYPE) = PV;
0209 mpc.bus(refbus, BUS_TYPE) = REF;
0210
0211
0212 nb = size(mpc.bus, 1);
0213 ng = size(mpc.gen, 1);
0214 if isfield(mpc, 'A') && ~isempty(mpc.A)
0215 [mA, nA] = size(mpc.A);
0216 if nA >= 2*nb + 2*ng
0217 mpc.A = [ mpc.A(:, 1:2*nb+ng) sparse(mA, 2*ndc) ...
0218 mpc.A(:, 2*nb+ng+(1:ng)) sparse(mA, 2*ndc) ...
0219 mpc.A(:, (2*nb+2*ng+1:nA)) ];
0220 else
0221 mpc.A = [ mpc.A(:, 1:nb+ng) sparse(mA, 2*ndc) ...
0222 mpc.A(:, (nb+ng+1:nA)) ];
0223 end
0224 end
0225 if isfield(mpc, 'N') && ~isempty(mpc.N)
0226 [mN, nN] = size(mpc.N);
0227 if nN >= 2*nb + 2*ng
0228 mpc.N = [ mpc.N(:, 1:2*nb+ng) sparse(mN, 2*ndc) ...
0229 mpc.N(:, 2*nb+ng+(1:ng)) sparse(mN, 2*ndc) ...
0230 mpc.N(:, (2*nb+2*ng+1:nN)) ];
0231 else
0232 mpc.N = [ mpc.N(:, 1:nb+ng) sparse(mN, 2*ndc) ...
0233 mpc.N(:, (nb+ng+1:nN)) ];
0234 end
0235 end
0236
0237
0238 mpc.gen = [mpc.gen; fg; tg];
0239
0240
0241 if isfield(mpc, 'gencost') && ~isempty(mpc.gencost)
0242 [ngcr, ngcc] = size(mpc.gencost);
0243 if havecost
0244 ndccc = size(dcc, 2);
0245 ccc = max([ngcc; ndccc]);
0246 if ccc > ngcc
0247 mpc.gencost = [mpc.gencost zeros(ngcr, ccc-ngcc)];
0248 end
0249
0250
0251
0252 for k = 1:ndc
0253 if dcc(k, MODEL) == POLYNOMIAL
0254 nc = dcc(k, NCOST);
0255 temp = dcc(k, NCOST+(1:nc));
0256
0257
0258
0259 temp((nc-1):-2:1) = -temp((nc-1):-2:1);
0260 else
0261 nc = dcc(k, NCOST);
0262 temp = dcc(k, NCOST+(1:2*nc));
0263
0264 xx = -temp(1:2:2*nc);
0265 yy = temp(2:2:2*nc);
0266 temp(1:2:2*nc) = xx(end:-1:1);
0267 temp(2:2:2*nc) = yy(end:-1:1);
0268 end
0269 padding = zeros(1, ccc-NCOST-length(temp));
0270 gck = [dcc(k, 1:NCOST) temp padding];
0271
0272
0273 mpc.gencost = [mpc.gencost; gck];
0274 end
0275
0276 tgc = ones(ndc, 1) * [2 0 0 2 zeros(1, ccc-4)];
0277 mpc.gencost = [mpc.gencost; tgc];
0278 else
0279
0280 dcgc = ones(2*ndc, 1) * [2 0 0 2 zeros(1, ngcc-4)];
0281 mpc.gencost = [mpc.gencost; dcgc];
0282 end
0283 end
0284
0285
0286
0287 function om = userfcn_dcline_formulation(om, args)
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313 c = idx_dcline;
0314
0315
0316 mpc = get_mpc(om);
0317 dc = mpc.dcline;
0318 ndc = size(dc, 1);
0319 ng = size(mpc.gen, 1) - 2*ndc;
0320
0321
0322 nL0 = -dc(:, c.LOSS0) / mpc.baseMVA;
0323 L1 = dc(:, c.LOSS1);
0324 Adc = [sparse(ndc, ng) spdiags(1-L1, 0, ndc, ndc) speye(ndc, ndc)];
0325
0326
0327 om = add_constraints(om, 'dcline', Adc, nL0, nL0, {'Pg'});
0328
0329
0330
0331 function results = userfcn_dcline_int2ext(results, args)
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347 [GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, ...
0348 MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, ...
0349 QC2MIN, QC2MAX, RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = idx_gen;
0350 c = idx_dcline;
0351
0352
0353 o = results.order;
0354 k = find(o.ext.dcline(:, c.BR_STATUS));
0355 ndc = length(k);
0356 ng = size(results.gen, 1) - 2*ndc;
0357 nb = size(results.bus, 1);
0358
0359
0360 fg = results.gen(ng +(1:ndc), :);
0361 tg = results.gen(ng+ndc+(1:ndc), :);
0362
0363
0364 results.gen = results.gen(1:ng, :);
0365 if isfield(results, 'gencost') && ~isempty(results.gencost)
0366 results.gencost = results.gencost(1:ng, :);
0367 end
0368
0369
0370 if isfield(results, 'A') && ~isempty(results.A)
0371 [mA, nA] = size(results.A);
0372 if nA >= 2*nb + 2*ng + 4*ndc
0373 results.A = results.A(:, [1:2*nb+ng 2*nb+ng+2*ndc+(1:ng) 2*nb+2*ng+4*ndc+1:nA]);
0374 else
0375 results.A = results.A(:, [1:nb+ng nb+ng+2*ndc+1:nA]);
0376 end
0377 end
0378 if isfield(results, 'N') && ~isempty(results.N)
0379 [mN, nN] = size(results.N);
0380 if nN >= 2*nb + 2*ng + 4*ndc
0381 results.N = results.N(:, [1:2*nb+ng 2*nb+ng+2*ndc+(1:ng) 2*nb+2*ng+4*ndc+1:nN]);
0382 else
0383 results.N = results.N(:, [1:nb+ng nb+ng+2*ndc+1:nN]);
0384 end
0385 end
0386
0387
0388 results.dcline(:, c.PF) = -fg(:, PG);
0389 results.dcline(:, c.PT) = tg(:, PG);
0390 results.dcline(:, c.QF) = fg(:, QG);
0391 results.dcline(:, c.QT) = tg(:, QG);
0392 results.dcline(:, c.VF) = fg(:, VG);
0393 results.dcline(:, c.VT) = tg(:, VG);
0394 if size(fg, 2) >= MU_QMIN
0395 results.dcline(:, c.MU_PMIN ) = fg(:, MU_PMAX) + tg(:, MU_PMIN);
0396 results.dcline(:, c.MU_PMAX ) = fg(:, MU_PMIN) + tg(:, MU_PMAX);
0397 results.dcline(:, c.MU_QMINF) = fg(:, MU_QMIN);
0398 results.dcline(:, c.MU_QMAXF) = fg(:, MU_QMAX);
0399 results.dcline(:, c.MU_QMINT) = tg(:, MU_QMIN);
0400 results.dcline(:, c.MU_QMAXT) = tg(:, MU_QMAX);
0401 end
0402
0403
0404 results.order.int.dcline = results.dcline;
0405
0406 o.ext.dcline(k, c.PF:c.VT) = results.dcline(:, c.PF:c.VT);
0407 if size(results.dcline, 2) == c.MU_QMAXT
0408 o.ext.dcline(k, c.MU_PMIN:c.MU_QMAXT) = results.dcline(:, c.MU_PMIN:c.MU_QMAXT);
0409 end
0410 results.dcline = o.ext.dcline;
0411
0412
0413
0414 function results = userfcn_dcline_printpf(results, fd, mpopt, args)
0415
0416
0417
0418
0419
0420
0421
0422
0423 c = idx_dcline;
0424
0425
0426 SUPPRESS = mpopt.out.suppress_detail;
0427 if SUPPRESS == -1
0428 if size(bus, 1) > 500
0429 SUPPRESS = 1;
0430 else
0431 SUPPRESS = 0;
0432 end
0433 end
0434 OUT_ALL = mpopt.out.all;
0435 OUT_BRANCH = OUT_ALL == 1 || (OUT_ALL == -1 && ~SUPPRESS && mpopt.out.branch);
0436 if OUT_ALL == -1
0437 OUT_ALL_LIM = ~SUPPRESS * mpopt.out.lim.all;
0438 elseif OUT_ALL == 1
0439 OUT_ALL_LIM = 2;
0440 else
0441 OUT_ALL_LIM = 0;
0442 end
0443 if OUT_ALL_LIM == -1
0444 OUT_LINE_LIM = ~SUPPRESS * mpopt.out.lim.line;
0445 else
0446 OUT_LINE_LIM = OUT_ALL_LIM;
0447 end
0448 ctol = mpopt.opf.violation;
0449 ptol = 1e-4;
0450
0451
0452 dc = results.dcline;
0453 ndc = size(dc, 1);
0454 kk = find(dc(:, c.BR_STATUS) ~= 0);
0455 if OUT_BRANCH
0456 fprintf(fd, '\n================================================================================');
0457 fprintf(fd, '\n| DC Line Data |');
0458 fprintf(fd, '\n================================================================================');
0459 fprintf(fd, '\n Line From To Power Flow Loss Reactive Inj (MVAr)');
0460 fprintf(fd, '\n # Bus Bus From (MW) To (MW) (MW) From To ');
0461 fprintf(fd, '\n------ ------ ------ --------- --------- --------- --------- ---------');
0462 loss = 0;
0463 for k = 1:ndc
0464 if dc(k, c.BR_STATUS)
0465 fprintf(fd, '\n%5d%8d%8d%11.2f%11.2f%11.2f%11.2f%11.2f', ...
0466 k, dc(k, c.F_BUS:c.T_BUS), dc(k, c.PF:c.PT), ...
0467 dc(k, c.PF) - dc(k, c.PT), dc(k, c.QF:c.QT) );
0468 loss = loss + dc(k, c.PF) - dc(k, c.PT);
0469 else
0470 fprintf(fd, '\n%5d%8d%8d%11s%11s%11s%11s%11s', ...
0471 k, dc(k, c.F_BUS:c.T_BUS), '- ', '- ', '- ', '- ', '- ');
0472 end
0473 end
0474 fprintf(fd, '\n ---------');
0475 fprintf(fd, '\n Total:%11.2f\n', loss);
0476 end
0477
0478 if OUT_LINE_LIM == 2 || (OUT_LINE_LIM == 1 && ...
0479 (any(dc(kk, c.PF) > dc(kk, c.PMAX) - ctol) || ...
0480 any(dc(kk, c.MU_PMIN) > ptol) || ...
0481 any(dc(kk, c.MU_PMAX) > ptol)))
0482 fprintf(fd, '\n================================================================================');
0483 fprintf(fd, '\n| DC Line Constraints |');
0484 fprintf(fd, '\n================================================================================');
0485 fprintf(fd, '\n Line From To Minimum Actual Flow Maximum');
0486 fprintf(fd, '\n # Bus Bus Pmin mu Pmin (MW) Pmax Pmax mu ');
0487 fprintf(fd, '\n------ ------ ------ --------- --------- --------- --------- ---------');
0488 for k = 1:ndc
0489 if OUT_LINE_LIM == 2 || (OUT_LINE_LIM == 1 && ...
0490 (dc(k, c.PF) > dc(k, c.PMAX) - ctol || ...
0491 dc(k, c.MU_PMIN) > ptol || ...
0492 dc(k, c.MU_PMAX) > ptol))
0493 if dc(k, c.BR_STATUS)
0494 fprintf(fd, '\n%5d%8d%8d', k, dc(k, c.F_BUS:c.T_BUS) );
0495 if dc(k, c.MU_PMIN) > ptol
0496 fprintf(fd, '%11.3f', dc(k, c.MU_PMIN) );
0497 else
0498 fprintf(fd, '%11s', '- ' );
0499 end
0500 fprintf(fd, '%11.2f%11.2f%11.2f', ...
0501 dc(k, c.PMIN), dc(k, c.PF), dc(k, c.PMAX) );
0502 if dc(k, c.MU_PMAX) > ptol
0503 fprintf(fd, '%11.3f', dc(k, c.MU_PMAX) );
0504 else
0505 fprintf(fd, '%11s', '- ' );
0506 end
0507 else
0508 fprintf(fd, '\n%5d%8d%8d%11s%11s%11s%11s%11s', ...
0509 k, dc(k, c.F_BUS:c.T_BUS), '- ', '- ', '- ', '- ', '- ');
0510 end
0511 end
0512 end
0513 fprintf(fd, '\n');
0514 end
0515
0516
0517
0518 function mpc = userfcn_dcline_savecase(mpc, fd, prefix, args)
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528 c = idx_dcline;
0529
0530
0531 ncols = size(mpc.dcline, 2);
0532 fprintf(fd, '\n%%%%----- DC Line Data -----%%%%\n');
0533 if ncols < c.MU_QMAXT
0534 fprintf(fd, '%%\tfbus\ttbus\tstatus\tPf\tPt\tQf\tQt\tVf\tVt\tPmin\tPmax\tQminF\tQmaxF\tQminT\tQmaxT\tloss0\tloss1\n');
0535 else
0536 fprintf(fd, '%%\tfbus\ttbus\tstatus\tPf\tPt\tQf\tQt\tVf\tVt\tPmin\tPmax\tQminF\tQmaxF\tQminT\tQmaxT\tloss0\tloss1\tmuPmin\tmuPmax\tmuQminF\tmuQmaxF\tmuQminT\tmuQmaxT\n');
0537 end
0538 template = '\t%d\t%d\t%d\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g\t%.9g';
0539 if ncols == c.MU_QMAXT
0540 template = [template, '\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f'];
0541 end
0542 template = [template, ';\n'];
0543 fprintf(fd, '%sdcline = [\n', prefix);
0544 fprintf(fd, template, mpc.dcline.');
0545 fprintf(fd, '];\n');
0546
0547
0548