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