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