0001 function insolvable = insolvablepfsos(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 define_constants;
0044
0045 if nargin < 2
0046 mpopt = mpoption;
0047 end
0048
0049
0050 ignore_angle_lim = mpopt.opf.ignore_angle_lim;
0051 verbose = mpopt.verbose;
0052 enforce_Qlimits = mpopt.pf.enforce_q_lims;
0053
0054 if enforce_Qlimits > 0
0055 enforce_Qlimits = 1;
0056 end
0057
0058 if ~have_fcn('yalmip')
0059 error('insolvablepfsos: The software package YALMIP is required to run insolvablepfsos. See http://users.isy.liu.se/johanl/yalmip/');
0060 end
0061
0062
0063 sdpopts = yalmip_options([], mpopt);
0064
0065
0066
0067
0068
0069
0070 if enforce_Qlimits
0071 if verbose > 0
0072 fprintf('Generator reactive power limits are enforced. Using function insolvablepfsos_limitQ.\n');
0073 end
0074 insolvable = insolvablepfsos_limitQ(mpc,mpopt);
0075 return;
0076 end
0077
0078
0079
0080 mpc = loadcase(mpc);
0081 mpc = ext2int(mpc);
0082
0083 if toggle_dcline(mpc, 'status')
0084 error('insolvablepfsos: DC lines are not implemented in insolvablepf');
0085 end
0086
0087 if ~ignore_angle_lim && (any(mpc.branch(:,ANGMIN) ~= -360) || any(mpc.branch(:,ANGMAX) ~= 360))
0088 warning('insolvablepfsos: Angle difference constraints are not implemented. Ignoring angle difference constraints.');
0089 end
0090
0091 nbus = size(mpc.bus,1);
0092 ngen = size(mpc.gen,1);
0093
0094
0095
0096
0097 for i=1:ngen
0098 busidx = find(mpc.bus(:,BUS_I) == mpc.gen(i,GEN_BUS));
0099 if isempty(busidx) || ~(mpc.bus(busidx,BUS_TYPE) == PV || mpc.bus(busidx,BUS_TYPE) == REF)
0100 mpc.bus(busidx,BUS_TYPE) = PV;
0101 if verbose >= 1
0102 warning('insolvablepfsos: Bus %s has generator(s) but is listed as a PQ bus. Changing to a PV bus.',int2str(busidx));
0103 end
0104 end
0105 end
0106
0107
0108
0109 for i=1:nbus
0110 if mpc.bus(i,BUS_TYPE) == PV
0111 genidx = find(mpc.gen(:,GEN_BUS) == mpc.bus(i,BUS_I), 1);
0112 if isempty(genidx)
0113 mpc.bus(i,BUS_TYPE) = PQ;
0114 if verbose >= 1
0115 warning('insolvablepfsos: PV bus %i has no associated generator! Changing these buses to PQ.',i);
0116 end
0117 end
0118 end
0119 end
0120
0121 pq = find(mpc.bus(:,2) == PQ);
0122 pv = find(mpc.bus(:,2) == PV);
0123 ref = find(mpc.bus(:,2) == REF);
0124
0125 refpv = sort([ref; pv]);
0126 pvpq = sort([pv; pq]);
0127
0128 Y = makeYbus(mpc);
0129 G = real(Y);
0130 B = imag(Y);
0131
0132
0133 S = makeSbus(mpc.baseMVA, mpc.bus, mpc.gen);
0134 P = real(S);
0135 Q = imag(S);
0136
0137 Vmag = zeros(nbus,1);
0138 Vmag(mpc.gen(:,GEN_BUS)) = mpc.gen(:,VG);
0139
0140
0141
0142
0143
0144 if verbose >= 2
0145 fprintf('Creating variables.\n');
0146 end
0147
0148 Vd = sdpvar(nbus,1);
0149 Vq = sdpvar(nbus,1);
0150
0151 V = [1; Vd; Vq];
0152
0153
0154
0155 if verbose >= 2
0156 fprintf('Creating polynomials.\n');
0157 end
0158
0159 deg = 0;
0160
0161
0162 for i=1:nbus-1
0163 [l,lc] = polynomial(V,deg,0);
0164 lambda(i) = l;
0165 clambda{i} = lc;
0166 end
0167
0168
0169 for i=1:length(pq)
0170 [g,gc] = polynomial(V,deg,0);
0171 gamma(i) = g;
0172 cgamma{i} = gc;
0173 end
0174
0175
0176 for i=1:length(refpv)
0177 [m,mc] = polynomial(V,deg,0);
0178 mu(i) = m;
0179 cmu{i} = mc;
0180 end
0181
0182
0183 [delta, cdelta] = polynomial(V,deg,0);
0184
0185
0186
0187
0188 if verbose >= 2
0189 fprintf('Creating power flow equations.\n');
0190 end
0191
0192
0193 for k=1:nbus-1
0194 i = pvpq(k);
0195
0196
0197
0198
0199 y = find(G(:,i) | B(:,i));
0200 for m=1:length(y)
0201 if exist('fp','var') && length(fp) == k
0202 fp(k) = fp(k) + Vd(i) * (G(y(m),i)*Vd(y(m)) - B(y(m),i)*Vq(y(m))) + Vq(i) * (B(y(m),i)*Vd(y(m)) + G(y(m),i)*Vq(y(m)));
0203 else
0204 fp(k) = Vd(i) * (G(y(m),i)*Vd(y(m)) - B(y(m),i)*Vq(y(m))) + Vq(i) * (B(y(m),i)*Vd(y(m)) + G(y(m),i)*Vq(y(m)));
0205 end
0206 end
0207
0208 end
0209
0210
0211 for k=1:length(pq)
0212 i = pq(k);
0213
0214
0215
0216
0217 y = find(G(:,i) | B(:,i));
0218 for m=1:length(y)
0219 if exist('fq','var') && length(fq) == k
0220 fq(k) = fq(k) + Vd(i) * (-B(y(m),i)*Vd(y(m)) - G(y(m),i)*Vq(y(m))) + Vq(i) * (G(y(m),i)*Vd(y(m)) - B(y(m),i)*Vq(y(m)));
0221 else
0222 fq(k) = Vd(i) * (-B(y(m),i)*Vd(y(m)) - G(y(m),i)*Vq(y(m))) + Vq(i) * (G(y(m),i)*Vd(y(m)) - B(y(m),i)*Vq(y(m)));
0223 end
0224 end
0225 end
0226
0227
0228 for k=1:length(refpv)
0229 i = refpv(k);
0230 fv(k) = Vd(i)^2 + Vq(i)^2;
0231 end
0232
0233
0234
0235
0236 if verbose >= 2
0237 fprintf('Forming the test polynomial.\n');
0238 end
0239
0240 sospoly = 1;
0241
0242
0243 for i=1:nbus-1
0244 sospoly = sospoly + lambda(i) * (fp(i) - P(pvpq(i)));
0245 end
0246
0247
0248 for i=1:length(pq)
0249 sospoly = sospoly + gamma(i) * (fq(i) - Q(pq(i)));
0250 end
0251
0252
0253 for i=1:length(refpv)
0254 sospoly = sospoly + mu(i) * (fv(i) - Vmag(refpv(i))^2);
0255 end
0256
0257
0258 sospoly = sospoly + delta * Vq(ref);
0259
0260 sospoly = -sospoly;
0261
0262
0263
0264 if verbose >= 2
0265 fprintf('Solving the sum of squares problem.\n');
0266 end
0267
0268 sosopts = sdpsettings(sdpopts,'sos.newton',1,'sos.congruence',1);
0269
0270 constraints = sos(sospoly);
0271
0272 pvec = cdelta(:).';
0273
0274 for i=1:length(lambda)
0275 pvec = [pvec clambda{i}(:).'];
0276 end
0277
0278 for i=1:length(gamma)
0279 pvec = [pvec cgamma{i}(:).'];
0280 end
0281
0282 for i=1:length(mu)
0283 pvec = [pvec cmu{i}(:).'];
0284 end
0285
0286
0287 S = warning;
0288
0289 sol = solvesos(constraints,[],sosopts,pvec);
0290
0291 warning(S);
0292
0293 if verbose >= 2
0294 fprintf('Solver exit message: %s\n',sol.info);
0295 end
0296
0297 if sol.problem
0298
0299 insolvable = 0;
0300 elseif sol.problem == 0
0301
0302 insolvable = 1;
0303 end