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

📄 fm_spf.m

📁 用于电力系统的一个很好的分析软件
💻 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:    Federico.Milano@uclm.es%Web-site:  http://www.uclm.es/area/gsee/Web/Federico%% Copyright (C) 2002-2008 Federico Milanoglobal DAE Pl Mn Lines Line SW PV PQ Busglobal History Theme Fig Settings LIB Snapshot Path Filefm_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  Line = build_y(Line);  % create the FM_CALL FUNCTION  if Settings.show, fm_disp('Writing file "fm_call" ...',1), end  fm_wcall;  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,DAE.m); % df/dy  DAE.Gx = sparse(DAE.m,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,DAE.m);  DAE.Gx = sparse(DAE.m,1);end% check PF solver methodPFmethod = Settings.pfsolver;ncload = getnum(Mn) + getnum(Pl) + getnum(Lines) + (~nodyn);if (ncload | Settings.distrsw) & (PFmethod == 2 | PFmethod == 3)  if ncload    fm_disp('Fast Decoupled PF cannot be used with dynamic components')  end  if Settings.distrsw    fm_disp('Fast Decoupled PF cannot be used with distributed slack bus model')  end  PFmethod = 1; % force using standard NR methodendswitch PFmethod case 1, fm_disp('PF solver: Newton-Raphson method') case 2, fm_disp('PF solver: XB fast decoupled method') case 3, fm_disp('PF solver: BX fast decoupled method') case 4, fm_disp('PF solver: Runge-Kutta method') case 5, fm_disp('PF solver: Iwamoto method') case 6, fm_disp('PF solver: Robust power flow method') case 7, fm_disp('PF solver: DC power flow')endDAE.lambda = 1;Jrow = 0;if Settings.distrsw  DAE.Fk = sparse(DAE.n,1);  DAE.Gk = sparse(DAE.m,1);  Jrow = sparse(1,DAE.n+SW.refbus,1,1,DAE.n+DAE.m+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')enditer_max = Settings.lfmit;convergence = 1;if iter_max < 2, iter_max = 2; enditeration = 0;tol = Settings.lftol;err_max = tol+1;err_max_old = 1e6;err_vec = [];alfatry = 1;alfa = 1; %0.85;safety = 0.9;pgrow = -0.2;pshrnk = -0.25;robust = 1;try  errcon = (5/safety)^(1/pgrow);catch  errcon = 1.89e-4;end% Graphical settingsfm_status('pf','init',iter_max,{'r'},{'-'},{Theme.color11})islands(Line)%  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  switch PFmethod   case 1 % Standard Newton-Raphson method    inc = calcInc(nodyn,Jrow);    DAE.x = DAE.x + inc(1:DAE.n);    DAE.y = DAE.y + inc(1+DAE.n:DAE.m+DAE.n);    if Settings.distrsw, DAE.kg = DAE.kg + inc(end); end   case {2,3} % Fast Decoupled Power Flow    if ~iteration % initialize variables      Line = build_b(Line);      no_sw = Bus.a;      no_sw(getbus(SW)) = [];      no_g = Bus.a;      no_g([getbus(SW); getbus(PV)]) = [];      Bp = Line.Bp(no_sw,no_sw);      Bpp = Line.Bpp(no_g,no_g);      [Lp, Up, Pp] = lu(Bp);      [Lpp, Upp, Ppp] = lu(Bpp);      no_g = no_g + Bus.n;      fm_call('fdpf')    end    % P-theta    da = -(Up\(Lp\(Pp*DAE.g(no_sw))));    DAE.y(no_sw) = DAE.y(no_sw) + da;    Vc = DAE.y(Bus.v).*exp(j*DAE.y(Bus.a));    fm_call('fdpf')    normP = norm(DAE.g,inf);    % Q-V    dV = -(Upp\(Lpp\(Ppp*DAE.g(no_g))));    DAE.y(no_g) = DAE.y(no_g)+dV;    Vc = DAE.y(Bus.v).*exp(j*DAE.y(Bus.a));    fm_call('fdpf')    normQ = norm(DAE.g,inf);    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 Fast Decoupled PF')      no_g = Bus.a;      no_g([getbus(SW); getbus(PV)]) = [];      Bpp = Line.Bpp(no_g,no_g);      [Lpp, Upp, Ppp] = lu(Bpp);      no_g = no_g + Bus.n;    end   case 4 % Runge-Kutta method    xold = DAE.x;    yold = DAE.y;    kold = DAE.kg;    k1 = alfa*calcInc(nodyn,Jrow);    Jac = -[DAE.Fx, DAE.Fy; DAE.Gx, DAE.Gy];    DAE.x = xold + 0.5*k1(1:DAE.n);    DAE.y = yold + 0.5*k1(1+DAE.n:DAE.m+DAE.n);    if Settings.distrsw, DAE.kg = kold + 0.5*k1(end); end    k2 = alfa*calcInc(nodyn,Jrow);    DAE.x = xold + 0.5*k2(1:DAE.n);    DAE.y = yold + 0.5*k2(1+DAE.n:DAE.m+DAE.n);    if Settings.distrsw, DAE.kg = kold + 0.5*k2(end); end    k3 = alfa*calcInc(nodyn,Jrow);    DAE.x = xold + k3(1:DAE.n);    DAE.y = yold + k3(1+DAE.n:DAE.m+DAE.n);    if Settings.distrsw, DAE.kg = kold + k3(end); end    k4 = alfa*calcInc(nodyn,Jrow);    % 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.75);    else      alfa = min(1.015*alfa,0.75);    end    DAE.x = xold + inc(1:DAE.n);    DAE.y = yold + inc(1+DAE.n:DAE.m+DAE.n);    if Settings.distrsw, DAE.kg = kold + inc(end); end   case 5 % Iwamoto method    xold = DAE.x;    yold = DAE.y;    kold = DAE.kg;    inc = calcInc(nodyn,Jrow);    vec_a = -[DAE.Fx, DAE.Fy; DAE.Gx, DAE.Gy]*inc;    vec_b = -vec_a;    DAE.x = inc(1:DAE.n);    DAE.y = inc(1+DAE.n:DAE.m+DAE.n);    if Settings.distrsw      DAE.kg = inc(end);      fm_call('kgpf');      if nodyn, DAE.Fx = 1; end      vec_c = -[DAE.f; DAE.g; DAE.y(SW.refbus)];    else      refreshJac;      fm_call('l');      refreshGen(nodyn);      vec_c = -[DAE.f; DAE.g];    end    g0 = (vec_a')*vec_b;    g1 = sum(vec_b.*vec_b + 2*vec_a.*vec_c);    g2 = 3*(vec_b')*vec_c;    g3 = 2*(vec_c')*vec_c;    pp = -g2/3/g3;    qq = pp^3 + (g2*g1-3*g3*g0)/6/g3/g3;    rr = g1/3/g3;    mu = (qq+sqrt(qq*qq+(rr-pp*pp)^3))^(1/3) + ...         (qq-sqrt(qq*qq+(rr-pp*pp)^3))^(1/3) + pp;    mu = min(abs(mu),0.75);    DAE.x = xold + mu*inc(1:DAE.n);    DAE.y = yold + mu*inc(1+DAE.n:DAE.n+DAE.m);    if Settings.distrsw, DAE.kg = kold + mu*inc(end); end   case 6 % simple robust power flow method    inc = robust*calcInc(nodyn,Jrow);    err_max = max(abs(inc));    if err_max > 1.5*err_max_old & iteration      robust = 0.25*robust;      if robust < tol        fm_disp('The otpimal multiplier is too small.')        iteration = iter_max+1;        break      end    else      DAE.x = DAE.x + inc(1:DAE.n);      DAE.y = DAE.y + inc(1+DAE.n:DAE.m+DAE.n);      if Settings.distrsw, DAE.kg = DAE.kg + inc(end); end      err_max_old = err_max;      robust = 1;    end  end  iteration = iteration + 1;  err_max = max(abs(inc));  err_vec(iteration) = err_max;  if err_max < 1e-2 & PFmethod > 3 & Settings.switch2nr    fm_disp('Switch to standard Newton-Raphson method.')    PFmethod = 1;  end  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.')      convergence = 0;      break    end  endendSettings.lftime = etime(clock,t0);Settings.iter = iteration;if iteration > iter_max  fm_disp(['Reached maximum number of iteration of NR routine without ' ...           'convergence'],2)  convergence = 0;end% Total power injections and consumptions at network buses% Pl and Ql computation (shunts only)DAE.g = zeros(DAE.m,1);fm_call('load0');Bus.Pl = DAE.g(Bus.a);Bus.Ql = DAE.g(Bus.v);%Pg and Qg computationfm_call('gen0');Bus.Pg = DAE.g(Bus.a);Bus.Qg = DAE.g(Bus.v);if ~Settings.distrsw  SW = setpg(SW,'all',Bus.Pg(SW.bus));end% adjust powers in case of PQ generatorsadjgen(PQ)% 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,DAE.m); % state Jacobian df/dy  DAE.Gx = sparse(DAE.m,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 * * *')endif convergence  Settings.init = 1;else  Settings.init = -1;endfm_rmgen(-1); % initialize function for removing static generatorsfm_call('0'); % compute inital state variables% 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, endendif Fig.threed, fm_threed('update'), end% 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, ...      'y',DAE.y, ...      'x',DAE.x,...      'Ybus',Line.Y, ...      'Pg',Bus.Pg, ...      'Qg',Bus.Qg, ...      'Pl',Bus.Pl, ...      'Ql',Bus.Ql, ...      'Gy',DAE.Gy, ...      'Fx',DAE.Fx, ...      'Fy',DAE.Fy, ...      'Gx',DAE.Gx, ...      'Ploss',sum(Bus.Pg)-sum(Bus.Pl), ...      'Qloss',sum(Bus.Qg)-sum(Bus.Ql), ...      '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.'])  endendfm_status('pf','close')LIB.selbus = min(LIB.selbus,Bus.n);if Fig.lib,  set(findobj(Fig.lib,'Tag','Listbox1'), ...      'String',Bus.names, ...      'Value',LIB.selbus);end% -----------------------------------------------function refreshJacglobal DAEDAE.g = zeros(DAE.m,1);% -----------------------------------------------function refreshGen(nodyn)global DAE SW PVif nodyn, DAE.Fx = 1; endFxcall(SW,'full')Fxcall(PV)% -----------------------------------------------function inc = calcInc(nodyn,Jrow)global DAE Settings SW PVDAE.g = zeros(DAE.m,1);if Settings.distrsw % distributed slack bus  fm_call('kgpf');  if nodyn, DAE.Fx = 1; end  inc = -[DAE.Fx,DAE.Fy,DAE.Fk;DAE.Gx,DAE.Gy,DAE.Gk;Jrow]\ ...        [DAE.f; DAE.g; DAE.y(SW.refbus)];else % single slack bus  fm_call('l');  if nodyn, DAE.Fx = 1; end  Fxcall(SW,'full')  Fxcall(PV)  inc = -[DAE.Fx, DAE.Fy; DAE.Gx, DAE.Gy]\[DAE.f; DAE.g];end

⌨️ 快捷键说明

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