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

📄 psat2ieee.m

📁 这是一个很适合研究和学习用的电力系统仿真软件
💻 M
字号:
function check = psat2ieee(varargin)
% PSAT2IEEE converts PSAT data file into IEEE Common Data Format
%
% CHECK = PSAT2IEEE(FILENAME,PATHNAME)
%       FILENAME name of the file to be converted
%       PATHNAME path of the file to be converted
%
%       CHECK = 1 conversion completed
%       CHECK = 0 problem encountered (no data file created)
%
%Author:    Federico Milano
%Date:      11-Nov-2002
%Version:   1.0.0
%
%E-mail:    fmilano@thunderbox.uwaterloo.ca
%Web-site:  http://thunderbox.uwaterloo.ca/~fmilano
%
% Copyright (C) 2002-2006 Federico Milano

if nargin == 2
  filename = varargin{1};
  pathname = varargin{2};
  nopowers = 0;
elseif nargin == 3
  filename = varargin{1};
  pathname = varargin{2};
  nopowers = varargin{3};
else
  check = 0;
  return
end

if strcmp(pathname(end),filesep)
  pathname = pathname(1:end-1);
end
if ~strcmp(pathname,pwd)
  cd(pathname)
end

fm_disp
fm_disp(['Opening PSAT file "',filename,'"...'])

% General Settings
% ----------------------------------------------------------------

check = 1;
b128 = [blanks(128),'\n'];
b12 = blanks(12);

% Defining local data structures
% ----------------------------------------------------------------

DAE = struct('a',[],'V',[]);
Bus = struct('con',[],'n',0,'int',[]);
Twt = struct('con',[],'n',0);
Line = struct('con',[],'n',0);
Shunt = struct('con',[],'bus',[]);
SW = struct('con',[],'n',0,'bus',[]);
PV = struct('con',[],'n',0,'bus',[]);
PQ = struct('con',[],'n',0,'bus',[]);
Varname = struct('bus','');

% Reading Data from PSAT Data File
% ----------------------------------------------------------------

a = exist(filename);
if a == 2,
  eval(filename(1:end-2))
  if nopowers
    if ~isempty(PQ.con)
      PQ.con(:,4) = 0;
      PQ.con(:,5) = 0;
      SW.con(:,10) = 0;
    end
    if ~isempty(PV.con)
      PV.con(:,4) = 0;
    end
  end
else,
  fm_disp(['File "',pathname,filesep,filename,'" not found or not an m-file'],2)
  check = 0;
  return
end

% Completing data settings
% ---------------------------------------------------------------

% Bus
Bus.n = length(Bus.con(:,1));
busmax = max(Bus.con(:,1));
Bus.int = zeros(busmax,1);
for i = 1:Bus.n, Bus.int(round(Bus.con(i,1))) = i; end
DAE.V = ones(Bus.n,1);
DAE.a = zeros(Bus.n,1);

% Bus names
if isempty(Varname.bus)
  Varname.bus = cellstr(strcat('Bus',num2str(Bus.con(:,1))));
end

% Shunt
if ~isempty(Shunt.con)
  Shunt.bus = Bus.int(Shunt.con(:,1));
  Shunt.con(:,5) = 100*Shunt.con(:,5)./Shunt.con(:,2);
  Shunt.con(:,6) = 100*Shunt.con(:,6)./Shunt.con(:,2);
end

% Three-Winding Transformers
if ~isempty(Twt.con)

  % check data
  [n_twt_rows, n_twt_cols] = size(Twt.con);
  if n_twt_cols < 14
    fm_disp(['Three-winding transformer data does not ', ...
             'seems in a valid format',2])
    return
  elseif n_twt_cols < 15
    Twt.con = [Twt.con, ones(n_twt_rows,1), zeros(n_twt_rows,9)];
  elseif n_twt_cols < 24
    Twt.con = [Twt.con, zeros(n_twt_rows,24-n_twt_cols)];
  end

  % modify Bus.con
  twt_bus = busmax+[1:n_twt_rows]';
  twt_Vn = Twt.con(:,7);
  twt_ar = Bus.con(Bus.int(Twt.con(:,2)),[4 5]);
  Bus.con = [Bus.con; [twt_bus, twt_Vn, ...
                      ones(n_twt_rows,1), ...
                      zeros(n_twt_rows,1), twt_ar]];
  Bus.int = [Bus.int; Bus.n+[1:n_twt_rows]'];
  Bus.n = Bus.n + n_twt_rows;
  busmax = busmax + n_twt_rows;

  % check Varname
  if ~isempty(Varname.bus)
    for i = 1:n_twt_rows
      Varname.bus{end+1,1} = ...
          [Varname.bus{Bus.int(Twt.con(i,1))},'(twt)'];
    end
  end

  % compute branch impedances
  r12 = Twt.con(:,9);
  r13 = Twt.con(:,10);
  r23 = Twt.con(:,11);
  r1 = 0.5*(r12+r13-r23);
  r2 = 0.5*(r12+r23-r13);
  r3 = 0.5*(r23+r13-r12);
  x12 = Twt.con(:,12);
  x13 = Twt.con(:,13);
  x23 = Twt.con(:,14);
  x1 = 0.5*(x12+x13-x23);
  x2 = 0.5*(x12+x23-x13);
  x3 = 0.5*(x23+x13-x12);

  % check for zero impedances in the equivalent star
  idx = find(abs(x1) < 1e-5);
  if ~isempty(idx), x1(idx) = 0.0001; end
  idx = find(abs(x2) < 1e-5);
  if ~isempty(idx), x2(idx) = 0.0001; end
  idx = find(abs(x3) < 1e-5);
  if ~isempty(idx), x3(idx) = 0.0001; end

  % check Line.con column number
  if ~isempty(Line.con)
    ncol = length(Line.con(1,:));
    if ncol < 15,
      Line.con = [Line.con, zeros(Line.n,15-ncol)];
    end
    if ncol > 15,
      Line.con = Line.con(:,[1:15]);
    end
  end

  % modify Line.con
  line1 = [Twt.con(:,1),twt_bus, Twt.con(:,[4,6,5]),zeros(n_twt_rows,1), ...
           Twt.con(:,6)./Twt.con(:,7), r1,x1,zeros(n_twt_rows,1), ...
           Twt.con(:,15), zeros(n_twt_rows,1),Twt.con(:,[17,19,22])];
  line2 = [twt_bus,Twt.con(:,[2,4,7,5]),zeros(n_twt_rows,2), r2,x2, ...
           zeros(n_twt_rows,1), ones(n_twt_rows,1), ...
           zeros(n_twt_rows,1),Twt.con(:,[18,20,23])];
  line3 = [twt_bus,Twt.con(:,[3,4,7,5]),zeros(n_twt_rows,1), ...
           Twt.con(:,7)./Twt.con(:,8),r3,x3, zeros(n_twt_rows,1), ...
           ones(n_twt_rows,1), zeros(n_twt_rows,1),Twt.con(:,[19,21,24])];
  Line.con = [Line.con; line1; line2; line3];

  % clear Twt.con
  Twt.con = [];
end

% take into account initial guess
if length(Bus.con(1,:) > 2) & max(Bus.con(:,3) < 2)
  DAE.V = Bus.con(:,3);
end
if length(Bus.con(1,:) > 3) & max(Bus.con(:,4) < pi)
  DAE.a = Bus.con(:,4);
end

% Line
if isempty(Line.con)
  fm_disp(['The selected data file has no Lines, ', ...
           'which are required in IEEE-CDF.'],2)
  check = 0;
  return
else
  Line.n = length(Line.con(:,1));
  Line.con(:,1) = Bus.int(round(Line.con(:,1)));
  Line.con(:,2) = Bus.int(round(Line.con(:,2)));
end

% Swing generators
if isempty(SW.con)
  fm_disp(['The selected data file has no slack bus, ', ...
           'which is required in IEEE-CDF.'],2)
  check = 0;
  return
else
  SW.n = length(SW.con(:,1));
  SW.bus = Bus.int(round(SW.con(:,1)));
  if length(SW.con(1,:)) < 8
    SW.con = [SW.con(:,1),100*ones(SW.n,1),ones(SW.n,1), ...
              SW.con(:,[2:end])];
  end
  if length(SW.con(1,:)) == 5
    SW.con = [SW.con, 999*ones(SW.n,1), -999*ones(SW.n,1), ...
              1.1*ones(SW.n,1), 0.9*ones(SW.n,1)];
  end
  DAE.V(SW.bus) = SW.con(:,4);
  DAE.a(SW.bus) = SW.con(:,5);
  SW.con(:,6)  = SW.con(:,6).*SW.con(:,2)/100;
  SW.con(:,7)  = SW.con(:,7).*SW.con(:,2)/100;
  SW.con(:,10) = SW.con(:,10).*SW.con(:,2)/100;
end

% PV generators
if ~isempty(PV.con)
  PV.n = length(PV.con(:,1));
  PV.bus = Bus.int(round(PV.con(:,1)));
  DAE.V(PV.bus) = PV.con(:,5);
  if length(PV.con(1,:)) == 5
    PV.con = [PV.con, 999*ones(PV.n,1), -999*ones(PV.n,1), ...
              1.1*ones(PV.n,1), 0.9*ones(PV.n,1), ones(PV.n,1)];
  end
  PV.con(:,4) = PV.con(:,4).*PV.con(:,2)/100;
  PV.con(:,6) = PV.con(:,6).*PV.con(:,2)/100;
  PV.con(:,7) = PV.con(:,7).*PV.con(:,2)/100;
end

% PQ loads
if ~isempty(PQ.con)
  PQ.n = length(PQ.con(:,1));
  PQ.bus = Bus.int(round(PQ.con(:,1)));
  if length(PQ.con(1,:)) == 5
    PQ.con = [PQ.con, 1.2*ones(PQ.n,1), 0.8*ones(PQ.n,1), ...
              zeros(PQ.n,1)];
  elseif length(PQ.con(1,:)) == 7
    PQ.con = [PQ.con, zeros(PQ.n,1)];
  end
  for i = 1:PQ.n
    if PQ.con(i,6) == 0, PQ.con(i,6) = 1.2; end
    if PQ.con(i,7) == 0, PQ.con(i,7) = 0.8; end
  end
  PQ.con(:,4) = PQ.con(:,4).*PQ.con(:,2)/100;
  PQ.con(:,5) = PQ.con(:,5).*PQ.con(:,2)/100;
end

% Checking max bus number
% ----------------------------------------------------------------------

if Bus.n > 9999 & Bus.n <= 99999
  fm_disp(['The number of buses is > 9999. Extended IEEE CDF will be ' ...
           'used.'])
end
if Bus.n > 99999
  fm_disp(['Network dimension is too big for IEEE-CDF (max bus number ' ...
           '= 99999).'],2)
  check = 0;
  return
end

% Opening File
% ----------------------------------------------------------------------

newfile = [filename(1:end-2),'.cf'];
fm_disp(['Writing IEEE CDF file "',newfile,'"...'])
fid = fopen([pathname,filesep, newfile], 'wt');

% Title Data
% ----------------------------------------------------------------------
card_I = b128;
card_I(2:9)   = datestr(now,2);           % date MM/DD/YY
card_I(11:22) = 'PSAT ARCHIVE';           % originator name
card_I(32:37) = '100.00';                 % MVA base
card_I(39:42) = datestr(now,10);          % year YYYY
s = str2num(datestr(now,5));
if s > 3 & s < 10, card_I(44) = 'S'; else, card_I(44) = 'W'; end % Season
a1 = [num2str(Bus.n),'-Bus ',num2str(Line.n),'-Line System',blanks(28)];
card_I(46:73) = a1(1:28);                           % Case Identification
count = fprintf(fid,card_I);

% Bus Data
% ---------------------------------------------------------------------

% Section Start card
card_b = b128;
card_b(1:15) = 'BUS DATA FOLLOW';
nbus = [num2str(Bus.n),' ITEMS'];
card_b(41:41+length(nbus)-1) = nbus;
count = fprintf(fid,card_b);
idxPV = [];
idxPQ = [];
idxSW = [];
idxSH = [];

% Bus Data Cards
for i = 1:Bus.n

  if PV.n, idxPV = find(PV.bus == i); end
  if PQ.n, idxPQ = find(PQ.bus == i); end
  if SW.n, idxSW = find(SW.bus == i); end
  if ~isempty(Shunt.con), idxSH = find(Shunt.bus == i); end

  a1 = sprintf('%5d',Bus.int(Bus.con(i,1)));
  if strcmp(a1(1),' ')
    a1 = [a1(2:5),' '];
  end
  a2 = [Varname.bus{i},b12];
  a2 = a2(1:11);

  if ~isempty(idxSW),
    a3 = '3';
    a6 = sprintf('%8.3f%8.3f',100*[SW.con(idxSW,10), 0.000]);
    a8 = sprintf('%6.4f',DAE.V(i));
    qmax = 100*SW.con(idxSW,6);
    qmin = 100*SW.con(idxSW,7);
    if qmax > 9999,  qmax = 9999; end
    if qmin < -9999, qmin = -9999; end
    a9 = sprintf('%8.2f%8.2f',[qmax, qmin]);
  elseif ~isempty(idxPV),
    a3 = '2';
    a6 = sprintf('%8.3f%8.3f',100*[PV.con(idxPV,4),0.000]);
    a8 = sprintf('%6.4f',DAE.V(i));
    qmax = 100*PV.con(idxPV,6);
    qmin = 100*PV.con(idxPV,7);
    if qmax > 9999,  qmax = 9999; end
    if qmin < -9999, qmin = -9999; end
    a9 = sprintf('%8.2f%8.2f',[qmax, qmin]);
  elseif ~isempty(idxPQ),
    a3 = '1';
    a6 = sprintf('%8.3f%8.3f',[0.000, 0.000]);
    a8 = sprintf('%6.4f',1.00);
    a9 = sprintf('%8.2f%8.2f',[0.000, 0.000]);
  else,
    a3 = '0';
    a6 = sprintf('%8.3f%8.3f',[0.000, 0.000]);
    a8 = sprintf('%6.4f',1.00);
    a9 = sprintf('%8.2f%8.2f',[0.000, 0.000]);
  end

  a4 = sprintf('%6.4f%7.3f',[DAE.V(i),180*DAE.a(i)/pi]);

  if ~isempty(idxPQ)
    a5 = sprintf('%9.4f%10.4f',100*PQ.con(idxPQ,[4,5]));
  else
    a5 = sprintf('%9.4f%10.4f',[0.0000, 0.0000]);
  end

  a7 = sprintf('%7.2f',Bus.con(i,2));

  if ~isempty(idxSH)
    a10 = sprintf('%8.4f%8.4f',Shunt.con(idxSH,[5,6]));
  else
    a10 = sprintf('%8.4f%8.4f',[0.0000, 0.0000]);
  end

  a11 = sprintf('%4d',i);

  card = [a1,' ',a2,'  1  0  ',a3,' ',a4,a5,a6,' ',a7,' ',a8,a9,a10,' ',a11,'\n'];
  count = fprintf(fid,card);
end

% Section End Card
count = fprintf(fid,'-999\n');

% Branch Data
% --------------------------------------------------------------------

% Section Start card
card_l = b128;
card_l(1:18) = 'BRANCH DATA FOLLOW';
nline = [num2str(Line.n),' ITEMS'];
card_l(41:41+length(nline)-1) = nline;
count = fprintf(fid,card_l);

% Line Data Cards
for i = 1:Line.n
  a1 = sprintf('%4d %4d  1 1  1 ',Line.con(i,[1 2]));
  tap = Line.con(i,11);
  if tap == 1, tap = 0; end
  if Line.con(i,7) | tap | Line.con(i,12)
    if tap == 0, tap = 1; end
    a2 = '1';
    a5 = sprintf('%4d 0  %6.4f %7.3f%7.4f%7.4f %6.4f ', ...
                 [Line.con(i,2),tap,Line.con(i,12),0,0,0]);
  else
    a2 = '0';
    a5 = sprintf('%4d 0  %6.4f %7.3f%7.4f%7.4f %6.4f ', ...
                 [0,tap,Line.con(i,12),0,0,0]);
  end
  a3 = sprintf(' %9.7f %10.8f %9.7f',Line.con(i,[8 9 10]));
  Ilim = round(Line.con(i,13)*100);
  %Ilims = [num2str(Ilim),'     '];
  %Ilims = Ilims([1:5]);
  %a4 = sprintf([Ilims,' %5d %5d '],[0 0]);
  a4 = sprintf('%5d %5d %5d ',[Ilim 0 0]);
  a6 = sprintf('%7.4f%7.4f',[0.0000, 0.0000]);
  card = [a1,a2,a3,a4,a5,a6];
  count = fprintf(fid,[card,'\n']);
end

% Section End Card
count = fprintf(fid,'-999\n');

% Loss Zone Data
% --------------------------------------------------------------------

% Section Start card
card_l = b128;
card_l(1:17) = 'LOSS ZONES FOLLOW';
card_l(41:47) = '1 ITEMS';
count = fprintf(fid,card_l);

% Loss Zone Cards
a1 = [num2str(Bus.n),'-Bus',b12];
a1 = a1(1:12);
count = fprintf(fid,['  1 ',a1,'\n']);

% Section End Card
count = fprintf(fid,'-99\n');

% Interchange Data
% ------------------------------------------------------------------

% Section Start card
card_l = b128;
card_l(1:23) = 'INTERCHANGE DATA FOLLOW';
card_l(41:47) = '1 ITEMS';
count = fprintf(fid,card_l);

% Interchange Data Cards
a1 = sprintf('%4d',Bus.int(Bus.con(SW.bus(1),1)));
a2 = [Varname.bus{SW.bus(1)},b12];
a2 = a2(1:12);
a3 = sprintf('%8.2f %6.2f  ',[0.00 999.99]);
a4 = [num2str(Bus.n),'Bus   '];
a4 = a4(1:6);
a5 = [num2str(Bus.n),'-Bus ',num2str(Line.n),'-Line System',blanks(30)];
a5 = a5(1:30);
count = fprintf(fid,[' 1 ',a1,' ',a2,a3,a4,'  ',a5,'\n']);

% Section End Card
count = fprintf(fid,'-9\n');

% Tie Line Data
% -----------------------------------------------------------------

% Section Start card
card_l = b128;
card_l(1:16) = 'TIE LINES FOLLOW';
card_l(41:47) = '0 ITEMS';
count = fprintf(fid,card_l);

% Tie Line Cards
% NO DATA

% Section End Card
count = fprintf(fid,'-999\n');
count = fprintf(fid,'END OF DATA ');

% Closing the file
% ----------------------------------------------------------------

fclose(fid);
fm_disp('Conversion completed.')

⌨️ 快捷键说明

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