0001 function [r, chgs] = make_opf_feasible(mpc, mpopt)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 [PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ...
0026 VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus;
0027 [F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ...
0028 TAP, SHIFT, BR_STATUS, PF, QF, PT, QT, MU_SF, MU_ST, ...
0029 ANGMIN, ANGMAX, MU_ANGMIN, MU_ANGMAX] = idx_brch;
0030 [GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, ...
0031 MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, ...
0032 QC2MIN, QC2MAX, RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = idx_gen;
0033
0034
0035 if nargin < 2
0036 mpopt = mpoption();
0037 end
0038
0039
0040 msg = '';
0041 done = 0;
0042 rc = 0;
0043
0044
0045 ig = find(~isload(mpc.gen) & mpc.gen(:, GEN_STATUS) > 0);
0046 total_Pmax = sum(mpc.gen(ig, PMAX));
0047 total_Pd = total_load(mpc.bus, [], 'all');
0048 if total_Pmax <= total_Pd
0049 msg = sprintf('%stotal fixed load (%g MW) > total on-line generation capacity (%g MW)\n', ...
0050 msg, total_Pd, total_Pmax);
0051 r = mpc;
0052 r.success = 0;
0053 r.f = NaN;
0054 rc = -2;
0055 done = 1;
0056 end
0057
0058
0059 if ~done
0060
0061 g = find(mpc.gen(:, PMIN) > mpc.gen(:, PMAX) & mpc.gen(:, GEN_STATUS) > 0);
0062 if ~isempty(g)
0063 for k = 1:length(g)
0064 msg = sprintf('%sPmax (%g) < Pmin (%g) for generator %d at bus %d, ', ...
0065 msg, mpc.gen(g(k), PMAX), mpc.gen(g(k), PMIN), g(k), mpc.gen(g(k), GEN_BUS));
0066
0067 if mpc.gen(g(k), PG) >= mpc.gen(g(k), PMIN)
0068 mpc.gen(g(k), PMAX) = mpc.gen(g(k), PMIN);
0069 msg = sprintf('%smove Pmax\n', msg);
0070 elseif mpc.gen(g(k), PG) <= mpc.gen(g(k), PMAX)
0071 mpc.gen(g(k), PMAX) = mpc.gen(g(k), PMIN);
0072 msg = sprintf('%smove Pmax\n', msg);
0073 else
0074 tmp = mpc.gen(g(k), PMAX);
0075 mpc.gen(g(k), PMAX) = mpc.gen(g(k), PMIN);
0076 mpc.gen(g(k), PMIN) = tmp;
0077 msg = sprintf('%sswap Pmin and Pmax\n', msg);
0078 end
0079 end
0080 rc = 2;
0081 end
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096 r = runopf(mpc, mpopt);
0097 if r.success
0098 done = 1;
0099 end
0100 end
0101
0102
0103 if ~done
0104
0105 rate_a = mpc.branch(:, RATE_A);
0106 rate_b = mpc.branch(:, RATE_B);
0107 rate_c = mpc.branch(:, RATE_C);
0108 rate_a(rate_a == 0) = Inf;
0109 rate_b(rate_b == 0) = Inf;
0110 rate_c(rate_c == 0) = Inf;
0111
0112
0113 rating = max([rate_a rate_b], [], 2);
0114 rating(isinf(rating)) = 0;
0115 mpc.branch(:, RATE_A) = rating;
0116 r = runopf(mpc, mpopt);
0117 if r.success
0118 done = 1;
0119 rc = 7;
0120 msg = sprintf('%susing short-term branch ratings\n', msg);
0121 end
0122 end
0123
0124
0125 if ~done
0126
0127 rating = max([rate_a rate_b rate_c], [], 2);
0128 rating(isinf(rating)) = 0;
0129 mpc.branch(:, RATE_A) = rating;
0130 r = runopf(mpc, mpopt);
0131
0132 if r.success
0133 done = 1;
0134 rc = 8;
0135 msg = sprintf('%susing emergency branch ratings\n', msg);
0136 end
0137 end
0138
0139
0140 if ~done
0141
0142 mpc.branch(:, RATE_A) = 0;
0143 r = runopf(mpc, mpopt);
0144
0145 if ~r.success
0146 done = 1;
0147 msg = sprintf('%sstill infeasible without line limits\n', msg);
0148 else
0149
0150
0151 msg = sprintf('%susing no branch limits\n', msg);
0152 rc = 9;
0153 end
0154 end
0155
0156
0157 if ~done
0158
0159 end
0160
0161
0162 r.msg = msg;
0163 r.rc = rc;
0164 if mpopt.verbose
0165 fprintf('%s', r.msg);
0166 end