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

📄 fm_spf.m

📁 基于PSAT 软件的多目标最优潮流计算用于中小型电力系统的分析和管理
💻 M
字号:
function fm_spf% FM_SPF solve standard power flow by means of the NR method%       and fast decoupled power flow (XB and BX variations)%       with either a single or distributed slack bus model.%% FM_SPF%%see the properties of the Settings structure for options.%%Author:    Federico Milano%Date:      11-Nov-2002%Update:    09-Jul-2003%Version:   1.0.1%%E-mail:    fmilano@thunderbox.uwaterloo.ca%Web-site:  http://thunderbox.uwaterloo.ca/~fmilano%% Copyright (C) 2002-2006 Federico Milanofm_varfm_dispfm_disp('Newton-Raphson Method for Power Flow Computation')if Settings.show  fm_disp(['Data file "',Path.data,File.data,'"'])endnodyn = 0;% these computations are needed only the first time the power flow is runif ~Settings.init  % bus type initialization  fm_ncomp  if ~Settings.ok, return, end  % report components parameters to system bases  if Settings.conv, fm_base, end  % create the admittance matrix  fm_y  % create the FM_CALL FUNCTION  if Settings.show, fm_disp('Writing file "fm_call" ...',1), end  fm_wcall;  Settings.refbus = SW.bus(1); % reference bus (for phase angle)  fm_dynlf; % indicization of components used in power flow computationsend% memory allocation for equations and Jacobiansif (DAE.n~=0)  DAE.f = ones(DAE.n,1);  % differential equations  DAE.x = ones(DAE.n,1);  % state variables  fm_xfirst;  DAE.Fx = sparse(DAE.n,DAE.n);   % df/dx  DAE.Fy = sparse(DAE.n,2*Bus.n); % df/dy  DAE.Gx = sparse(2*Bus.n,DAE.n); % dg/dxelse  % no dynamic elements  nodyn = 1;  DAE.n = 1;  DAE.f = 0;  DAE.x = 0;  DAE.Fx = 1;  DAE.Fy = sparse(1,2*Bus.n);  DAE.Gx = sparse(2*Bus.n,1);end% check PF solver methodFDPF = Settings.pfsolver;if FDPF > 1  if Mn.n, mn = sum(~Mn.con(:,8));  else, mn = 0; end  if Pl.n, pl = sum(~Pl.con(:,11)); else, pl = 0; end  ncload = mn + pl + Lines.n + (~nodyn);  if ncload | Settings.distrsw,    FDPF = 1; % force using standard NR method  else    fm_b    no_sw = 1:Bus.n;    no_sw(SW.bus) = [];    no_g = 1:Bus.n;    no_g([SW.bus; PV.bus]) = [];    Bp = Line.Bp(no_sw,no_sw);    Bpp = Line.Bpp(no_g,no_g);    [Lp, Up, Pp] = lu(Bp);    [Lpp, Upp, Ppp] = lu(Bpp);  endendswitch FDPF case 1, fm_disp('PF solver: Newton-Raphson method') case 2, fm_disp('PF solver: XB fast decoupled power flow method') case 3, fm_disp('PF solver: BX fast decoupled power flow method')endif Settings.distrsw  DAE.Fk = sparse(DAE.n,1);  DAE.Gk = sparse(2*Bus.n,1);  Jrow = sparse(1,DAE.n+SW.bus,1,1,DAE.n+2*Bus.n+1);  DAE.kg = 0;  if ~swgamma(SW,'sum')    fm_disp('Slack buses have zero power loss participation factor.')    fm_disp('Single slack bus model will be used')    Setting.distrsw = 0;  end  if totp(SW) == 0    SW = setpg(totp(PQ)-totp(PV),1);    fm_disp('Slack buses have zero generated power.')    fm_disp('P_slack = sum(P_load)-sum(P_gen) will be used.')    fm_disp('Only PQ loads and PV generators are used.')    fm_disp('If there are convergence problems, use the single slack bus model.')  end  Gkcall(SW);  Gkcall(PV);endswitch Settings.distrsw case 1  fm_disp('Distributed slack bus model') case 0  fm_disp('Single slack bus model')endif FDPF > 1, fm_call('fdpf'), enditer_max = Settings.lfmit;if iter_max < 2, iter_max = 2; enditeration = 0;tol = Settings.lftol;err_max = tol+1;err_vec = [];alfatry = 1;alfa = 1;safety = 0.9;pgrow = -0.2;pshrnk = -0.25;try  errcon = (5/safety)^(1/pgrow);catch  errcon = 1.89e-4;end% Graphical settingsfm_status('pf','init',iter_max,{'r'},{'-'},{Theme.color11})fm_connectivity(0,'islands')%  Newton-Raphson routinet0 = clock;while (err_max > tol) & (iteration <= iter_max) & (alfa > 1e-5)  if Fig.main    if ~get(Fig.main,'UserData'), break, end  end  if FDPF == 1   % Standard NR technique    refreshJac;    % component calls    if Settings.distrsw      fm_call('kgpf');      glambda(SW,1,DAE.kg);      DAE.g(Bus.n+SW.bus) = 0;      Gbus = Bus.n+[SW.bus;PV.bus];      DAE.Jlfv(Gbus,:) = 0;      DAE.Jlfv(:,Gbus) = 0;      DAE.Jlfv(:,SW.bus) = 0;      DAE.Jlfv(Gbus,Gbus) = speye(PV.n+SW.n);      DAE.Fy(:,SW.bus) = 0;      DAE.Gx(SW.bus,:) = 0;      if nodyn, DAE.Fx = 1; end      inc = -[[DAE.Fx, DAE.Fy; DAE.Gx, DAE.Jlfv],[DAE.Fk;DAE.Gk];Jrow]\ ...            [DAE.f; DAE.g; 0];      DAE.x = DAE.x + inc(1:DAE.n);      DAE.a = DAE.a + inc(1+DAE.n:Bus.n+DAE.n);      DAE.V = DAE.V + inc(1+DAE.n+Bus.n:DAE.n+2*Bus.n);      DAE.kg = DAE.kg + inc(end);    elseif Settings.robust      xold = DAE.x;      aold = DAE.a;      Vold = DAE.V;      while 1        refreshJac;        fm_call('l');        refreshGen(nodyn);        k1 = -alfa*[DAE.Fx, DAE.Fy; DAE.Gx, DAE.Jlfv]\[DAE.f; DAE.g];        DAE.x = xold + 0.5*k1(1:DAE.n);        DAE.a = aold + 0.5*k1(1+DAE.n:Bus.n+DAE.n);        DAE.V = Vold + 0.5*k1(1+DAE.n+Bus.n:DAE.n+2*Bus.n);        refreshJac;        fm_call('l');        refreshGen(nodyn);        k2 = -alfa*[DAE.Fx, DAE.Fy; DAE.Gx, DAE.Jlfv]\[DAE.f; DAE.g];        DAE.x = xold + 0.5*k2(1:DAE.n);        DAE.a = aold + 0.5*k2(1+DAE.n:Bus.n+DAE.n);        DAE.V = Vold + 0.5*k2(1+DAE.n+Bus.n:DAE.n+2*Bus.n);        refreshJac;        fm_call('l');        refreshGen(nodyn);        k3 = -alfa*[DAE.Fx, DAE.Fy; DAE.Gx, DAE.Jlfv]\[DAE.f; DAE.g];        DAE.x = xold + k3(1:DAE.n);        DAE.a = aold + k3(1+DAE.n:Bus.n+DAE.n);        DAE.V = Vold + k3(1+DAE.n+Bus.n:DAE.n+2*Bus.n);        refreshJac;        fm_call('l');        refreshGen(nodyn);        k4 = -alfa*[DAE.Fx, DAE.Fy; DAE.Gx, DAE.Jlfv]\[DAE.f; DAE.g];        % compute RK4 increment of variables        inc = (k1+2*(k2+k3)+k4)/6;        % to estimate RK error, use the RK2:Dy and RK4:Dy.        yerr = max(abs(abs(k2)-abs(inc)));        if yerr > 0.01          alfa = max(0.985*alfa,0.9);        else          alfa = min(1.015*alfa,1.1);        end        DAE.x = xold + inc(1:DAE.n);        DAE.a = aold + inc(1+DAE.n:Bus.n+DAE.n);        DAE.V = Vold + inc(1+DAE.n+Bus.n:DAE.n+2*Bus.n);        break      end      %disp(['alpha = ',num2str(alfa)])    else % standard Newton-Raphson method      % complete Jacobian matrix      fm_call('l');      refreshGen(nodyn)      inc = -[DAE.Fx, DAE.Fy; DAE.Gx, DAE.Jlfv]\[DAE.f; DAE.g];      DAE.x = DAE.x + inc(1:DAE.n);      DAE.a = DAE.a + inc(1+DAE.n:Bus.n+DAE.n);      DAE.V = DAE.V + inc(1+DAE.n+Bus.n:DAE.n+2*Bus.n);    end  else % Fast Decoupled Power Flow    % P-theta    da = -(Up\(Lp\(Pp*DAE.gp(no_sw))));    DAE.a(no_sw) = DAE.a(no_sw) + da;    Vc = DAE.V.*exp(j*DAE.a);    fm_call('fdpf')    normP = norm(DAE.gp,inf);    normQ = norm(DAE.gq,inf);    if normP < tol & normQ < tol, break, end    % Q-V    dV = -(Upp\(Lpp\(Ppp*DAE.gq(no_g))));    DAE.V(no_g) = DAE.V(no_g)+dV;    Vc = DAE.V.*exp(j*DAE.a);    fm_call('fdpf')    normP = norm(DAE.gp,inf);    normQ = norm(DAE.gq,inf);    if normP < tol & normQ < tol, break, end    inc = [normP; normQ];    % recompute Bpp if some PV bus has been switched to PQ bus    if Settings.pv2pq & strmatch('Switch',History.text{end})      fm_disp('Recomputing Bpp matrix for FDPF')      no_g = 1:Bus.n;      no_g([SW.bus; PV.bus]) = [];      Bpp = Line.Bpp(no_g,no_g);      [Lpp, Upp, Ppp] = lu(Bpp);    end  end  iteration = iteration + 1;  err_max = max(abs(inc));  err_vec(iteration) = err_max;    fm_status('pf','update',[iteration, err_max],iteration)  if Settings.show    if err_max == Inf, err_max = 1e3; end    fm_disp(['Iteration = ', num2str(iteration), ...             '     Maximum Convergency Error = ', ...             num2str(err_max)],1)  end  % stop if the error increases too much   if iteration > 4    if err_vec(iteration) > 1000*err_vec(1)      fm_disp('The error is increasing too much.')      fm_disp('Convergence is likely not reachable.')      break    end  endendSettings.lftime = etime(clock,t0);Settings.iter = iteration;if iteration > iter_max  fm_disp(['Reached Maximum number of iteration for NR Routine without ' ...           'Convergence'],2)end% Total power injections and consumptions at network buses% Pl and Ql computation (shunts only)DAE.gp = zeros(Bus.n,1);DAE.gq = zeros(Bus.n,1);fm_call('pq');Bus.Pl = DAE.gp;Bus.Ql = DAE.gq;%Pg and Qg computationif Line.n, fm_lf(1), endDAE.gp = zeros(Bus.n,1);DAE.gq = zeros(Bus.n,1);fm_call('1');Bus.Pg = DAE.gp + DAE.glfp;Bus.Qg = DAE.gq + DAE.glfq;SW = setpg(SW,'all',Bus.Pg(SW.bus));% memory allocation for dynamic variables & state variables indicizationif nodyn == 1; DAE.x = []; DAE.f = []; DAE.n = 0; endDAE.npf = DAE.n;fm_dynidx;if (DAE.n~=0)  DAE.f = [DAE.f; ones(DAE.n-DAE.npf,1)];  % differential equations  DAE.x = [DAE.x; ones(DAE.n-DAE.npf,1)];  % state variables  DAE.Fx = sparse(DAE.n,DAE.n); % state Jacobian df/dx  DAE.Fy = sparse(DAE.n,2*Bus.n); % state Jacobian df/dy  DAE.Gx = sparse(2*Bus.n,DAE.n); % algebraic Jacobian dg/dxend%  build cell arrays of variable namesfm_idx(1)if (Settings.vs == 1), fm_idx(2), end% initializations of state variables and componentsif Settings.static  fm_disp('* * * Dynamic components are not initialized * * *')endSettings.init = 1;fm_synitfm_excinfm_call('0');% start up of induction machinesif Mot.n > 0, fm_mot(5), end% refresh PQ powers% PQ = pqactual(PQ,'all');% power flow result visualizationfm_disp(['Power Flow completed in ',num2str(Settings.lftime),' s'])if Settings.showlf == 1 | Fig.stat  fm_stat;else  if Settings.beep, beep, endend% initialization of all equations & JacobiansrefreshJacfm_call('i');% build structure "Snapshot"if isempty(Settings.t0) & Fig.main  hdl = findobj(Fig.main,'Tag','EditText3');  Settings.t0 = str2num(get(hdl,'String'));endif ~Settings.locksnap & Bus.n <= 5000 & DAE.n < 5000  Snapshot = struct( ...      'name','Power Flow Results', ...      'time',Settings.t0, ...      'V',DAE.V, ...      'ang',DAE.a, ...      'x',DAE.x,...      'Y',Line.Y, ...      'Pg',Bus.Pg, ...      'Qg',Bus.Qg, ...      'Pl',Bus.Pl, ...      'Ql',Bus.Ql, ...      'vfd',Syn.vf, ...      'pmech',Syn.pm, ...      'Jlf',DAE.Jlf, ...      'Jlfv',DAE.Jlfv, ...      'Fx',DAE.Fx, ...      'Fy',DAE.Fy, ...      'Gx',DAE.Gx, ...      'Ploss',sum(DAE.glfp), ...      'Qloss',sum(DAE.glfq), ...      'it',1);else  if Bus.n > 5000    fm_disp(['Snapshots are disabled for networks with more than 5000 ' ...             'buses.'])  end  if DAE.n > 5000    fm_disp(['Snapshots are disabled for networks with more than 5000 ' ...             'state variables.'])  end  endfm_status('pf','close')LIB.selbus = min(LIB.selbus,Bus.n);if Fig.lib,  set(findobj(Fig.lib,'Tag','Listbox1'), ...      'String',Varname.bus, ...      'Value',LIB.selbus);end% -----------------------------------------------function refreshJacglobal DAE BusDAE.gp = sparse(Bus.n,1);DAE.gq = sparse(Bus.n,1);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);% -----------------------------------------------function refreshGen(nodyn)global DAE Bus SW PVDAE.Fy(:,SW.bus) = 0;DAE.Gx(SW.bus,:) = 0;DAE.Fy(:,Bus.n+SW.bus) = 0;DAE.Gx(Bus.n+SW.bus,:) = 0;DAE.Fy(:,Bus.n+PV.bus) = 0;DAE.Gx(Bus.n+PV.bus,:) = 0;if nodyn, DAE.Fx = 1; end % check for islanded busesif ~isempty(Bus.island)  k = Bus.island;  DAE.Jlfv(k,:) = 0;  DAE.Jlfv(:,k) = 0;  DAE.Jlfv(:,k+Bus.n) = 0;  DAE.Jlfv(k+Bus.n,:) = 0;  DAE.Jlfv(k,k) = speye(length(k));  DAE.Jlfv(k+Bus.n,k+Bus.n) = speye(length(k));  DAE.g(k) = 0;  DAE.g(k+Bus.n) = 0;  DAE.V(k) = 1e-6;  DAE.a(k) = 0;end

⌨️ 快捷键说明

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