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