⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fm_snb.m

📁 电力系统的psat
💻 M
字号:
function fm_snb% FM_SNB compute Saddle-node Bifurcation%        by means of a Direct Method%% FM_SNB%%System Equations:%       g(y,kg,lambda) = 0   ->  operating point%       dg/dy'*ro = 0        ->  transversality condition%       |ro| - 1 = 0         ->  non-trivial condition%%       where:  g = load flow equations%               y = [theta; V]%               ro = right eigenvector%               lambda = loading parameter%% Options:%          SNB.slack:  1  ->  distribuited slack bus%                      0  ->  single slack bus%% Output:  SNB.lambda: saddle node value of lambda%          SNB.dldp:   sensitivity factors%%Author:    Federico Milano%Date:      11-Nov-2002%Update:    11-Feb-2003%Version:   1.0.2%%E-mail:    fmilano@thunderbox.uwaterloo.ca%Web-site:  http://thunderbox.uwaterloo.ca/~fmilano%% Copyright (C) 2002-2005 Federico Milano%% This toolbox is free software; you can redistribute it and/or modify% it under the terms of the GNU General Public License as published by% the Free Software Foundation; either version 2.0 of the License, or% (at your option) any later version.%% This toolbox is distributed in the hope that it will be useful, but% WITHOUT ANY WARRANTY; without even the implied warranty of% MERCHANDABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU% General Public License for more details.%% You should have received a copy of the GNU General Public License% along with this toolbox; if not, write to the Free Software% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,% USA.fm_varif ~autorun('SNB Direct Method')  returnend% check for continuation power flow solution% lambda the maximum lambda obtained with the CPF analysis% or 1e-3 if no CPF analysis has been performed.if ~CPF.init & ~clpsat.init  Settings.ok = 0;  uiwait(fm_choice(['It is strongly recommended running a CPF to get ' ...      'a solution close to the SNB point. Run CPF?'],1))  if Settings.ok    cpf_old = CPF;    CPF.vlim = 0;    CPF.ilim = 0;    CPF.qlim = 0;    CPF.type = 2;    CPF.linit = 0;    CPF.nump = 50;    fm_cpf('snb');    lambda = CPF.lambda;     CPF = cpf_old;  else    lambda = 1e-3;  endelse  lambda = CPF.lambda;   enddistr = SNB.slack;% check for loaded componentsif Mn.n, mn = sum(~Mn.con(:,8));  else, mn = 0; endif Pl.n, pl = sum(~Pl.con(:,11)); else, pl = 0; endncload = mn + pl + Lines.n + Tcsc.n;if ncload | DAE.n  fm_disp('only PV, PQ and SW buses are allowed for SNB computations.')  returnendfm_dispif distr  fm_disp('Direct Method for SNB Computation - Distribuited Slack Bus')else  fm_disp('Direct Method for SNB Computation - Single Slack Bus')endfm_disp('                                  - Right Eigenvector')fm_dispfm_disp(['Data file "',Path.data,File.data,'"'])fm_displength(Snapshot.V);%DAE.V = Snapshot(1).V;%DAE.a = Snapshot(1).ang;%DAE.x = Snapshot(1).x;%DAE.Jlfv = Snapshot(1).Jlfv;Vmax_old = PQ.con(:,6);Vmin_old = PQ.con(:,7);PQold = PQ;PVold = PV;SWold = SW;noDem = 0;noSup = 0;PQ.con(:,6) = 10000*ones(PQ.n,1);PQ.con(:,7) = -10000*ones(PQ.n,1);bus_gen = [SW.bus; PV.bus];n_gen = PV.n+SW.n;% for the slack bus, the power injection obtained by the power flow is usedfor i = 1:SW.n,  k = SW.bus(i);  if ~isempty(Snapshot(1).Pg)    pg = Snapshot(1).Pg;    if pg(k) ~= 0      SW.con(i,10) = pg(k);    end  endend% if no Demand.con is imposed, the load power direction% is assumed to be the one defined by the PQ loadsif Demand.n  no_dpq = find(Demand.con(:,3) == 0 & Demand.con(:,4) == 0);  if ~isempty(no_dpq),    fm_disp    for i = 1:length(no_dpq)      fm_disp(['No power direction found in "Demand.con" for Bus ', ...               Varname.bus{Demand.bus(no_dpq(i))}])    end    fm_disp('Continuation load flow routine may have convergence problems.',2)    fm_disp  endelse  noDem = 1;  Ppos = find(PQ.con(:,4) > 0);  Demand.con = zeros(length(Ppos),14);  Demand.n = length(Ppos);  Demand.bus = PQ.bus(Ppos);  Demand.con(:,[1 2 3 4]) = PQ.con(Ppos,[1 2 4 5]);  Demand.con(:,14) = 1;  PQ.con(Ppos,[4 5]) = 0;end% if no Supply.con is imposed, the generator power direction% is assumed to be equal to the PV oneif Supply.n  no_sp = find(Supply.con(:,3) == 0);  if ~isempty(no_sp),    fm_disp    if length(no_sp) == Supply.n      fm_disp(['No power directions found in "Supply.con" for all buses.'])      fm_disp('Remove "Supply" components or set power directions.')      fm_disp('Continuation power flow interrupted',2)      if CPF.show, set(Fig.main,'Pointer','arrow'); end      return    else      for i = 1:length(no_sp)        fm_disp(['No power direction found in "Supply.con" for Bus ', ...                 Varname.bus{Supply.bus(no_sp(i))}])      end      fm_disp('Continuation power flow routine may have convergence problems.',2)      fm_disp    end  endelse  noSup = 1;  if PV.n    Ppos = find(PV.con(:,4) > 0);    Supply.con = zeros(length(Ppos),14);    Supply.n = length(Ppos);    Supply.bus = PV.bus(Ppos);    Supply.con(:,[1 2 3]) = PV.con(Ppos,[1 2 4]);    Supply.con(:,14) = 1;    PV.con(Ppos,4) = 0;  end  if SW.n    Ppos = find(SW.con(:,10) > 0);    Supply.n = Supply.n+length(Ppos);    Supply.bus = [Supply.bus; SW.bus(Ppos)];    Supply.con(end+[1:length(Ppos)],[1 2 3]) = SW.con(Ppos,[1 2 10]);    Supply.con((end-length(Ppos)+1):end,14) = 1;    SW.con(Ppos,10) = 0;  endend% vector and matrix initializationif Settings.octave  Gl = zeros(2*Bus.n,1);  Gk = zeros(2*Bus.n,1);  Nrow = zeros(1,2*Bus.n);  Ncol = zeros(2*Bus.n,1);  Nmat = zeros(2*Bus.n,2*Bus.n);else  Gl = sparse(2*Bus.n,1);  Gk = sparse(2*Bus.n,1);  Nrow = sparse(1,2*Bus.n);  Ncol = sparse(2*Bus.n,1);  Nmat = sparse(2*Bus.n,2*Bus.n);endfor i = 1:Demand.n  k = Demand.bus(i);  Gl(k,1) = Demand.con(i,3);  Gl(k+Bus.n,1) = Demand.con(i,4);endfor i = 1:Supply.n  k = Supply.bus(i);  Gl(k,1) = -Supply.con(i,3);  Gk(k,1) = -Supply.con(i,3);endif distr == 0, Gl(SW.bus) = 0; end[Vect,D] = eig(full(DAE.Jlfv));diagD = diag(D);idx = find(diagD == 1);if ~isempty(idx)  diagD(idx) = 1e6;end[val,idx] = min(abs(diagD));Vect = inv(Vect.');M = real(Vect(1:Bus.n,idx))+1e-4;W = real(Vect(Bus.n+1:2*Bus.n,idx))+1e-4;iter_max = Settings.lfmit;iteration = 0;tol = Settings.lftol;g1=ones(2*Bus.n,1);if DAE.n == 0, dynordold = 0; DAE.n = 1; end%  Direct Methodticfm_status('snb','init',iter_max,{'r'},{'-'},{'g'})G = real(Line.Y);B = imag(Line.Y);%lambda = CPF.lambda; kg = CPF.kg;if distr, j = 1; else, j = 0; enda_old = DAE.a;v_old = DAE.V;l_old = lambda;k_old = kg;m_old = M;w_old = W;err_max = tol+1;err_max_old = err_max + 1;robust = 1;while err_max > tol  if (iteration > iter_max), break, end  if Fig.main    if ~get(Fig.main,'UserData'), break, end  end  if isempty(Line.Y)    DAE.gp = zeros(Bus.n,1);    DAE.gq = zeros(Bus.n,1);    if Settings.octave      DAE.J11 = zeros(Bus.n,Bus.n);      DAE.J21 = zeros(Bus.n,Bus.n);      DAE.J12 = zeros(Bus.n,Bus.n);      DAE.J22 = zeros(Bus.n,Bus.n);    else      DAE.J11 = sparse(Bus.n,Bus.n);      DAE.J21 = sparse(Bus.n,Bus.n);      DAE.J12 = sparse(Bus.n,Bus.n);      DAE.J22 = sparse(Bus.n,Bus.n);    end  end  % Jlfv computation  if distr    fm_lf(1); fm_pq(1); fm_pv(1); fm_lf(2); fm_pv(2);    for i = 1:SW.n,      k = SW.bus(i);      DAE.gp(k) = DAE.gp(k) - SW.con(i,10);      DAE.gq(k) = 0;      DAE.J21(k,:)=zeros(1,Bus.n);      DAE.J22(k,:)=zeros(1,Bus.n);      DAE.J12(:,k)=zeros(Bus.n,1);      DAE.J22(:,k)=zeros(Bus.n,1);      DAE.J22(k,k)=1;    end    DAE.Jlfv = [DAE.J11, DAE.J12; DAE.J21, DAE.J22];  else    fm_call('l')  end  % dF/dlambda computation  for i = 1:Demand.n    k = Demand.bus(i);    if isempty(find(SW.bus == k))      DAE.gp(k) = lambda*Demand.con(i,3) + DAE.gp(k);    end    if isempty(find(bus_gen == k))      DAE.gq(k) = lambda*Demand.con(i,4) + DAE.gq(k);    end  end  if distr    for i = 1:Supply.n      k = Supply.bus(i);      DAE.gp(k) = DAE.gp(k) - (lambda+kg)*Supply.con(i,3);    end  else    for i = 1:Supply.n      k = Supply.bus(i);      if isempty(find(SW.bus == k))        DAE.gp(k) = DAE.gp(k) - lambda*Supply.con(i,3);      end    end  end  % non-trivial condition ||w|| = 1  norm_eq = norm([M', W']);  Vjac = [M', W']/norm_eq;  if distr    gy = [DAE.Jlfv, Gk]'*[M; W];  else    gy = DAE.Jlfv'*[M; W];  end  DAE.gp(SW.bus) = 0;  % complete Jacobian matrix  if distr    AC = [[fm_hessian([M;W]),Ncol;Nrow,0],[DAE.Jlfv,Gk]', ...          [Ncol;0];DAE.Jlfv,Gk,Nmat,Gl;Nrow,0,Vjac,0];  else    AC = [fm_hessian([M;W]),DAE.Jlfv',Ncol; ...          DAE.Jlfv,Nmat,Gl;Nrow,Vjac,0];  end  AC(SW.bus,:) = 0;  AC(:,SW.bus) = 0;  AC(SW.bus,SW.bus) = 1;  gy(SW.bus) = 0;  for i = 1:n_gen    k = bus_gen(i);    AC(k+Bus.n,:) = 0;    AC(:,k+Bus.n) = 0;    AC(k+Bus.n,k+Bus.n) = 1;    AC(k+3*Bus.n+j,:) = 0;    AC(:,k+3*Bus.n+j) = 0;    AC(k+3*Bus.n+j,k+3*Bus.n+j) = 1;  end  AC(SW.bus+2*Bus.n+j,:) = 0;  AC(:,SW.bus+2*Bus.n+j) = 0;  AC(SW.bus+2*Bus.n+j,SW.bus+2*Bus.n+j) = 1;  gy(Bus.n+bus_gen) = 0;  DAE.gp(SW.bus) = 0;  inc = -robust*(AC\[gy; DAE.gp; DAE.gq; norm_eq-1]);  err_max = max(abs(inc));  if err_max > 2*err_max_old & iteration    DAE.a  = a_old;    DAE.V  = v_old;    lambda = l_old;    kg = k_old;    M  = m_old;    W  = w_old;    robust = 0.5*robust;    if robust < tol, iteration = iter_max+1; break, end  else    a_old = DAE.a;    v_old = DAE.V;    l_old = lambda;    k_old = kg;    m_old = M;    w_old = W;    DAE.a = DAE.a + inc(1:Bus.n);         idx = Bus.n;    DAE.V = DAE.V + inc(idx+1:idx+Bus.n); idx = idx + Bus.n;    if distr, kg = kg + inc(idx+1);       idx = idx + 1; end    M = M + inc(idx+1:idx+Bus.n);         idx = idx + Bus.n;    W = W + inc(idx+1:idx+Bus.n);         idx = idx + Bus.n;    lambda = lambda + inc(idx+1);    err_max_old = err_max;    iteration = iteration + 1;    if Settings.show      fm_disp(['iteration = ', int2str(iteration), ...               ';   lambda = ',num2str(lambda), ...               '   err = ',num2str(err_max)])    end    fm_status('snb','update',[iteration, err_max],iteration)  endend% ===========================================================================%                                  d lambda |% sensistivity coefficients        -------- |%                                     d p   |c% ===========================================================================W = [M; W];if Settings.octave  Dpfc = zeros(2*Bus.n,Demand.n+Supply.n);else  Dpfc = sparse(2*Bus.n,Demand.n+Supply.n);endfor i = 1:Supply.n  k = Supply.bus(i);  Dpfc(k,i) = -(lambda+j*kg);endfor i = 1:Demand.n  k = Demand.bus(i);  Dpfc(k,Supply.n+i) = lambda;enddl_dp = full(-W'*Dpfc/(W'*Gl))';% Update Demand.con & Supply.con%____________________________________________________________________________Demand.con(:,7) = lambda*Demand.con(:,3);Supply.con(:,6) = lambda*Supply.con(:,3);% Display results% ===========================================================================fm_dispfm_disp(['Lambda Critical = ',num2str(lambda)],1)fm_dispfm_disp('Sensitivity Coefficients',1)fm_dispfor i = 1:Supply.n  fm_disp([fvar(['dLambda/dPs',int2str(Supply.con(i,1)),' = '],20), ...           fvar(dl_dp(i),8)],1);endfm_dispfor i = 1:Demand.n  fm_disp([fvar(['dLambda/dPd',int2str(Demand.con(i,1)),' = '],20), ...           fvar(dl_dp(i+Supply.n),8)],1);endfm_dispserv_test{1,1} = [fvar('Lambda Critical = ',20),fvar(lambda,8)];serv_test{2,1} = '  ';if distr,  serv_test{3,1} = [fvar('Kg = ',20),fvar(lambda,8)];  serv_test{4,1} = '  ';endfor i = 1:Supply.n  serv_test{i+2,1} = [fvar(['dLambda/dPs',int2str(Supply.con(i,1)),' = '],20),fvar(dl_dp(i),8)];endserv_test{end+1,1} = ' ';for i = 1:Demand.n  serv_test{i+3+Supply.n,1} = [fvar(['dLambda/dPd',int2str(Demand.con(i,1)),' = '],20),fvar(dl_dp(i+Supply.n),8)];endDAE.n = dynordold;Settings.iter = iteration;Settings.lftime = toc;if robust < tol  fm_disp('Increment step below threshold. Bad initial point. SNB routine stopped.',2)elseif iteration >= iter_max  fm_disp(['Reached maximum number of iterations for Direct Method for SNB computation without convergence'],2)else  fm_disp(['Direct Method for SNB computation completed in ',num2str(toc),' s'])  if Settings.showlf == 1, fm_stat(serv_test), endendSNB.lambda = lambda;SNB.dldp = dl_dp;SNB.bus = strvcat(strcat('s_',num2str(Supply.bus)), strcat('d_',num2str(Demand.bus)));% restore original data% ===========================================================================fm_status('snb','close')PQ = PQold;PV = PVold;SW = SWold;if noDem  Demand.con = [];  Demand.n = 0;  Demand.bus = [];endif noSup  Supply.con = [];  Supply.n = 0;  Supply.bus = [];endSNB.init = 1;LIB.init = 0;CPF.init = 0;OPF.init = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -