📄 fm_spf.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 + -