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