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