0001 function [out, bsh] = sgvm_add_shunts(mpc, mpopt, opt)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 if nargin < 3
0016 opt = struct();
0017 if nargin < 2
0018
0019 mpopt = sg_options();
0020 mpopt = mpopt.mpopt;
0021 end
0022 elseif isempty(mpopt)
0023
0024 mpopt = sg_options();
0025 mpopt = mpopt.mpopt;
0026 end
0027 opt = opt_default(opt);
0028 tmag = opt.tmag;
0029 shift_in = opt.shift_in;
0030 shunt_max = opt.shunt_max;
0031 soft_ratea= opt.soft_ratea;
0032 mpopt.opf.softlims.default = 0;
0033
0034 [PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ...
0035 VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus;
0036 [GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, ...
0037 MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, ...
0038 QC2MIN, QC2MAX, RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = idx_gen;
0039 [PW_LINEAR, POLYNOMIAL, MODEL, STARTUP, SHUTDOWN, NCOST, COST] = idx_cost;
0040
0041 nb = size(mpc.bus,1);
0042 ng = size(mpc.gen,1);
0043
0044 if any(mpc.bus(:,BUS_I) ~= (1:nb)')
0045 error('sgvm_add_shunts: bus matrix needs to have consecutive bus numbering.')
0046 end
0047 out = mpc;
0048
0049
0050 mpc.bus(:,VMAX) = mpc.bus(:,VMAX) - shift_in;
0051 mpc.bus(:,VMIN) = mpc.bus(:,VMIN) + shift_in;
0052
0053
0054 tmpgen = (1:nb)';
0055 ngtmp = nb;
0056 new_gen = zeros(ngtmp, size(mpc.gen,2));
0057 new_gen(:,[GEN_BUS, VG, MBASE, GEN_STATUS]) = [tmpgen, ones(ngtmp,1), mpc.baseMVA*ones(ngtmp,1), ones(ngtmp,1)];
0058 mpc.gen = [mpc.gen; new_gen];
0059
0060 new_gencost = zeros(ngtmp, size(mpc.gencost,2));
0061 new_gencost(:,[MODEL, NCOST, COST]) = [2*ones(ngtmp,1), 2*ones(ngtmp,1), zeros(ngtmp,1)];
0062
0063 mpc.gencost = [mpc.gencost; new_gencost];
0064 if isfield(mpc, 'genfuel')
0065 mpc.genfuel = vertcat(mpc.genfuel, ...
0066 cellfun(@(x) 'other', num2cell(1:ngtmp), 'UniformOutput', 0).');
0067 end
0068 if isfield(mpc, 'gentype')
0069 mpc.gentype = vertcat(mpc.gentype, ...
0070 cellfun(@(x) 'OT', num2cell(1:ngtmp), 'UniformOutput', 0).');
0071 end
0072
0073
0074 if isfield(mpc, 'softlims')
0075 mpc = rmfield(mpc, 'softlims');
0076 end
0077 if soft_ratea
0078 mpc.softlims.RATE_A.hl_mod = 'remove';
0079 end
0080 current_shunt = mpc.bus(:, BS);
0081 qmax_lim = shunt_max - current_shunt;
0082 idx = find(qmax_lim > 0);
0083 mpc.softlims.QMAX = struct('hl_mod', 'replace', 'idx', ng+idx, 'hl_val', qmax_lim(idx));
0084
0085 qmin_lim = current_shunt - shunt_max;
0086 idx = find(qmin_lim < 0);
0087 mpc.softlims.QMIN = struct('hl_mod', 'replace', 'idx', ng+idx, 'hl_val', qmin_lim(idx));
0088
0089
0090
0091
0092 if ~toggle_softlims(mpc, 'status')
0093 mpc = toggle_softlims(mpc,'on');
0094 end
0095 r = runopf(mpc,mpopt);
0096
0097 if ~r.success
0098 if ~isinf(shunt_max)
0099 warning('sgvm_add_shunts: OPF with Qg softlimits failed to converge. Removing shunt limits.')
0100 opt.shunt_max = Inf;
0101 [out, bsh] = sgvm_add_shunts(out, mpopt, opt);
0102 return
0103 elseif ~soft_ratea
0104 warning('sgvm_add_shunts: OPF with Qg softlimits failed to converge. Adding soft branch limits.')
0105 opt.soft_ratea = 1;
0106 [out, bsh] = sgvm_add_shunts(out, mpopt, opt);
0107 return
0108 end
0109 warning('sgvm_add_shunts: No possible solution found! (Inf shunt limits and branch limits attempted).')
0110 out = r;
0111 bsh = zeros(nb,1);
0112 return
0113 end
0114
0115 if opt.verbose > 1
0116 fprintf('Result in sgvm_add_shunts:\n')
0117 printpf(r)
0118 end
0119
0120 bsh = (r.softlims.QMAX.overload(ng+1:end) - r.softlims.QMIN.overload(ng+1:end))./r.bus(:,VM).^2;
0121
0122
0123 mask = (abs(bsh) > 0) & (abs(bsh) < tmag);
0124 bsh(mask) = sign(bsh(mask))*tmag;
0125
0126
0127
0128 r.bus(:,BS) = r.bus(:,BS) + bsh;
0129
0130
0131 out = update_out(out, r, ng);
0132
0133
0134 function opt = opt_default(opt)
0135
0136 optdef = sgvm_shuntsopts();
0137
0138 if ~isempty(opt)
0139 opt = nested_struct_copy(optdef, opt);
0140 else
0141 opt = optdef;
0142 end
0143
0144 function out = update_out(out, r, ng)
0145
0146 define_constants;
0147
0148 r.bus(:,[VMAX, VMIN] ) = out.bus(:,[VMAX, VMIN]);
0149 r.gen = r.gen(1:ng,:);
0150 r.gencost = r.gencost(1:ng, :);
0151 out = r;
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161