0001 function [mpc, warns] = psse_convert(warns, data, verbose)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 [PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ...
0034 VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus;
0035 [F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ...
0036 TAP, SHIFT, BR_STATUS, PF, QF, PT, QT, MU_SF, MU_ST, ...
0037 ANGMIN, ANGMAX, MU_ANGMIN, MU_ANGMAX] = idx_brch;
0038 [GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, ...
0039 MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, ...
0040 QC2MIN, QC2MAX, RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = idx_gen;
0041
0042
0043 sort_buses = 1;
0044
0045
0046 if nargin < 3
0047 verbose = 0;
0048 end
0049 haveVlims = 0;
0050 Vmin = 0.9;
0051 Vmax = 1.1;
0052
0053
0054 baseMVA = data.id.SBASE;
0055 rev = data.id.REV;
0056
0057
0058 numbus = data.bus.num;
0059 [nb, ncols] = size(numbus);
0060 bus = zeros(nb, VMIN);
0061 if rev < 24
0062 bus_name_col = 10;
0063 else
0064 bus_name_col = 2;
0065 end
0066 if sort_buses
0067 [numbus, i] = sortrows(numbus, 1);
0068 bus_name = data.bus.txt(i, bus_name_col);
0069 else
0070 bus_name = data.bus.txt(:, bus_name_col);
0071 end
0072 if rev < 24
0073 bus(:, [BUS_I BUS_TYPE PD QD GS BS BUS_AREA VM VA BASE_KV ZONE]) = ...
0074 numbus(:, [1:9 11:12]);
0075 elseif rev < 31
0076 bus(:, [BUS_I BASE_KV BUS_TYPE GS BS BUS_AREA ZONE VM VA]) = ...
0077 numbus(:, [1 3 4 5 6 7 8 9 10]);
0078 else
0079 bus(:, [BUS_I BASE_KV BUS_TYPE BUS_AREA ZONE VM VA]) = ...
0080 numbus(:, [1 3 4 5 6 8 9]);
0081 if ncols >= 11 && all(all(~isnan(numbus(:, [10 11]))))
0082 haveVlims = 1;
0083 bus(:, [VMAX VMIN]) = numbus(:, [10 11]);
0084 end
0085 end
0086 if ~haveVlims
0087 warns{end+1} = sprintf('Using default voltage magnitude limits: VMIN = %g p.u., VMAX = %g p.u.', Vmin, Vmax);
0088 if verbose
0089 fprintf('WARNING: No bus voltage magnitude limits provided.\n Using defaults: VMIN = %g p.u., VMAX = %g p.u.\n', Vmin, Vmax);
0090 end
0091 bus(:, VMIN) = Vmin;
0092 bus(:, VMAX) = Vmax;
0093 end
0094
0095
0096 i2e = bus(:, BUS_I);
0097 e2i = sparse(i2e, ones(nb, 1), 1:nb, max(i2e), 1);
0098
0099
0100 if rev >= 24
0101 nld = size(data.load.num, 1);
0102 loadbus = e2i(data.load.num(:,1));
0103
0104
0105
0106
0107
0108
0109 Pd = data.load.num(:,6) + data.load.num(:,8) .* bus(loadbus, VM) ...
0110 + data.load.num(:,10) .* bus(loadbus, VM).^2;
0111 Qd = data.load.num(:,7) + data.load.num(:,9) .* bus(loadbus, VM) ...
0112 - data.load.num(:,11) .* bus(loadbus, VM).^2;
0113 Cld = sparse(1:nld, loadbus, data.load.num(:,3), nld, nb);
0114 bus(:, [PD QD]) = Cld' * [Pd Qd];
0115 end
0116
0117
0118 if isfield(data, 'shunt')
0119 nsh = size(data.shunt.num, 1);
0120 shuntbus = e2i(data.shunt.num(:,1));
0121 Csh = sparse(1:nsh, shuntbus, data.shunt.num(:,3), nsh, nb);
0122 bus(:, [GS BS]) = Csh' * data.shunt.num(:, 4:5);
0123 end
0124
0125
0126 nswsh = size(data.swshunt.num, 1);
0127 swshuntbus = e2i(data.swshunt.num(:,1));
0128 Cswsh = sparse(1:nswsh, swshuntbus, 1, nswsh, nb);
0129 if rev <= 27
0130 bus(:, BS) = bus(:, BS) + Cswsh' * data.swshunt.num(:, 6);
0131 elseif rev <= 29
0132 bus(:, BS) = bus(:, BS) + Cswsh' * data.swshunt.num(:, 7);
0133 elseif rev < 32
0134 bus(:, BS) = bus(:, BS) + Cswsh' * data.swshunt.num(:, 8);
0135 else
0136 bus(:, BS) = bus(:, BS) + Cswsh' * data.swshunt.num(:, 10);
0137 end
0138
0139
0140 nbr = size(data.branch.num, 1);
0141 branch = zeros(nbr, ANGMAX);
0142 branch(:, ANGMIN) = -360;
0143 branch(:, ANGMAX) = 360;
0144 branch(:, [F_BUS BR_R BR_X BR_B RATE_A RATE_B RATE_C]) = ...
0145 data.branch.num(:, [1 4 5 6 7 8 9]);
0146 branch(:, T_BUS) = abs(data.branch.num(:, 2));
0147 if rev <= 27
0148 branch(:, BR_STATUS) = data.branch.num(:, 16);
0149 branch(~isnan(data.branch.num(:, 10)), TAP) = ...
0150 data.branch.num(~isnan(data.branch.num(:, 10)), 10);
0151 branch(~isnan(data.branch.num(:, 11)), SHIFT) = ...
0152 data.branch.num(~isnan(data.branch.num(:, 11)), 11);
0153 else
0154 branch(:, BR_STATUS) = data.branch.num(:, 14);
0155 end
0156
0157 ibr = (1:nbr)';
0158 fbus = e2i(branch(:, F_BUS));
0159 tbus = e2i(branch(:, T_BUS));
0160 nzf = find(fbus);
0161 nzt = find(tbus);
0162 if length(nzf) < nbr
0163 warns{end+1} = sprintf('%d branches have bad ''from'' bus numbers', nbr-length(nzf));
0164 if verbose
0165 fprintf('WARNING: %d branches have bad ''from'' bus numbers\n', nbr-length(nzf));
0166 end
0167 end
0168 if length(nzt) < nbr
0169 warns{end+1} = sprintf('%d branches have bad ''to'' bus numbers', nbr-length(nzt));
0170 if verbose
0171 fprintf('WARNING: %d branches have bad ''to'' bus numbers\n', nbr-length(nzt));
0172 end
0173 end
0174 Cf = sparse(ibr(nzf), fbus(nzf), branch(nzf, BR_STATUS), nbr, nb);
0175 Ct = sparse(ibr(nzt), tbus(nzt), branch(nzt, BR_STATUS), nbr, nb);
0176 if rev <= 27
0177 bus(:, [GS BS]) = bus(:, [GS BS]) + ...
0178 Cf' * data.branch.num(:, 12:13)*baseMVA + ...
0179 Ct' * data.branch.num(:, 14:15)*baseMVA;
0180 else
0181 bus(:, [GS BS]) = bus(:, [GS BS]) + ...
0182 Cf' * data.branch.num(:, 10:11)*baseMVA + ...
0183 Ct' * data.branch.num(:, 12:13)*baseMVA;
0184 end
0185
0186
0187 ng = size(data.gen.num, 1);
0188 genbus = e2i(data.gen.num(:,1));
0189 gen = zeros(ng, APF);
0190 gen = zeros(ng, MU_QMIN);
0191 gen(:, [GEN_BUS PG QG QMAX QMIN VG MBASE GEN_STATUS PMAX PMIN]) = ...
0192 data.gen.num(:, [1 3 4 5 6 7 9 15 17 18]);
0193
0194
0195 if rev > 27
0196 [transformer, bus, warns, bus_name] = psse_convert_xfmr(warns, data.trans2.num, data.trans3.num, verbose, baseMVA, bus, bus_name);
0197 branch = [branch; transformer];
0198 end
0199
0200
0201 dcline = psse_convert_hvdc(data.twodc.num, bus);
0202
0203
0204 mpc = struct( ...
0205 'baseMVA', baseMVA, ...
0206 'bus', bus, ...
0207 'bus_name', {bus_name}, ...
0208 'branch', branch, ...
0209 'gen', gen ...
0210 );
0211 if ~isempty(dcline)
0212 mpc.dcline = dcline;
0213 mpc = toggle_dcline(mpc, 'on');
0214 end