UOPF Solves combined unit decommitment / optimal power flow. [RESULTS, SUCCESS] = UOPF(MPC, MPOPT) Returns either a RESULTS struct and an optional SUCCESS flag, or individual data matrices, the objective function value and a SUCCESS flag. In the latter case, there are additional optional return values. See Examples below for the possible calling syntax options. Examples: Output argument options: results = uopf(...) [results, success] = uopf(...) [bus, gen, branch, f, success] = uopf(...) [bus, gen, branch, f, success, info, et, g, jac, xr, pimul] = uopf(...) Input arguments options: uopf(mpc) uopf(mpc, mpopt) uopf(mpc, userfcn, mpopt) uopf(mpc, A, l, u) uopf(mpc, A, l, u, mpopt) uopf(mpc, A, l, u, mpopt, N, fparm, H, Cw) uopf(mpc, A, l, u, mpopt, N, fparm, H, Cw, z0, zl, zu) uopf(baseMVA, bus, gen, branch, areas, gencost) uopf(baseMVA, bus, gen, branch, areas, gencost, mpopt) uopf(baseMVA, bus, gen, branch, areas, gencost, userfcn, mpopt) uopf(baseMVA, bus, gen, branch, areas, gencost, A, l, u) uopf(baseMVA, bus, gen, branch, areas, gencost, A, l, u, mpopt) uopf(baseMVA, bus, gen, branch, areas, gencost, A, l, u, ... mpopt, N, fparm, H, Cw) uopf(baseMVA, bus, gen, branch, areas, gencost, A, l, u, ... mpopt, N, fparm, H, Cw, z0, zl, zu) See OPF for more information on input and output arguments. Solves a combined unit decommitment and optimal power flow for a single time period. Uses an algorithm similar to dynamic programming. It proceeds through a sequence of stages, where stage N has N generators shut down, starting with N=0. In each stage, it forms a list of candidates (gens at their Pmin limits) and computes the cost with each one of them shut down. It selects the least cost case as the starting point for the next stage, continuing until there are no more candidates to be shut down or no more improvement can be gained by shutting something down. If MPOPT.verbose (see MPOPTION) is true, it prints progress info, if it is > 1 it prints the output of each individual opf. See also OPF, RUNUOPF.
0001 function [bus, gen, branch, f, success, info, et, g, jac, xr, pimul] = ... 0002 uopf(varargin) 0003 %UOPF Solves combined unit decommitment / optimal power flow. 0004 % [RESULTS, SUCCESS] = UOPF(MPC, MPOPT) 0005 % 0006 % Returns either a RESULTS struct and an optional SUCCESS flag, or individual 0007 % data matrices, the objective function value and a SUCCESS flag. In the 0008 % latter case, there are additional optional return values. See Examples 0009 % below for the possible calling syntax options. 0010 % 0011 % Examples: 0012 % Output argument options: 0013 % 0014 % results = uopf(...) 0015 % [results, success] = uopf(...) 0016 % [bus, gen, branch, f, success] = uopf(...) 0017 % [bus, gen, branch, f, success, info, et, g, jac, xr, pimul] = uopf(...) 0018 % 0019 % Input arguments options: 0020 % 0021 % uopf(mpc) 0022 % uopf(mpc, mpopt) 0023 % uopf(mpc, userfcn, mpopt) 0024 % uopf(mpc, A, l, u) 0025 % uopf(mpc, A, l, u, mpopt) 0026 % uopf(mpc, A, l, u, mpopt, N, fparm, H, Cw) 0027 % uopf(mpc, A, l, u, mpopt, N, fparm, H, Cw, z0, zl, zu) 0028 % 0029 % uopf(baseMVA, bus, gen, branch, areas, gencost) 0030 % uopf(baseMVA, bus, gen, branch, areas, gencost, mpopt) 0031 % uopf(baseMVA, bus, gen, branch, areas, gencost, userfcn, mpopt) 0032 % uopf(baseMVA, bus, gen, branch, areas, gencost, A, l, u) 0033 % uopf(baseMVA, bus, gen, branch, areas, gencost, A, l, u, mpopt) 0034 % uopf(baseMVA, bus, gen, branch, areas, gencost, A, l, u, ... 0035 % mpopt, N, fparm, H, Cw) 0036 % uopf(baseMVA, bus, gen, branch, areas, gencost, A, l, u, ... 0037 % mpopt, N, fparm, H, Cw, z0, zl, zu) 0038 % 0039 % See OPF for more information on input and output arguments. 0040 % 0041 % Solves a combined unit decommitment and optimal power flow for a single 0042 % time period. Uses an algorithm similar to dynamic programming. It proceeds 0043 % through a sequence of stages, where stage N has N generators shut down, 0044 % starting with N=0. In each stage, it forms a list of candidates (gens at 0045 % their Pmin limits) and computes the cost with each one of them shut down. 0046 % It selects the least cost case as the starting point for the next stage, 0047 % continuing until there are no more candidates to be shut down or no 0048 % more improvement can be gained by shutting something down. 0049 % If MPOPT.verbose (see MPOPTION) is true, it prints progress 0050 % info, if it is > 1 it prints the output of each individual opf. 0051 % 0052 % See also OPF, RUNUOPF. 0053 0054 % MATPOWER 0055 % Copyright (c) 1996-2015 by Power System Engineering Research Center (PSERC) 0056 % by Ray Zimmerman, PSERC Cornell 0057 % 0058 % $Id: uopf.m 2644 2015-03-11 19:34:22Z ray $ 0059 % 0060 % This file is part of MATPOWER. 0061 % Covered by the 3-clause BSD License (see LICENSE file for details). 0062 % See http://www.pserc.cornell.edu/matpower/ for more info. 0063 0064 %%----- initialization ----- 0065 t0 = clock; %% start timer 0066 0067 %% process input arguments 0068 [mpc, mpopt] = opf_args(varargin{:}); 0069 0070 %% options 0071 if mpopt.verbose %% turn down verbosity one level for calls to opf 0072 mpopt = mpoption(mpopt, 'verbose', mpopt.verbose-1); 0073 end 0074 0075 %% define named indices into bus, gen, branch matrices 0076 [PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ... 0077 VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus; 0078 [GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, ... 0079 MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, ... 0080 QC2MIN, QC2MAX, RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = idx_gen; 0081 0082 %%----- do combined unit commitment/optimal power flow ----- 0083 0084 %% check for sum(Pmin) > total load, decommit as necessary 0085 on = find( mpc.gen(:, GEN_STATUS) > 0 & ~isload(mpc.gen) ); %% gens in service 0086 onld = find( mpc.gen(:, GEN_STATUS) > 0 & isload(mpc.gen) ); %% disp loads in serv 0087 load_capacity = sum(mpc.bus(:, PD)) - sum(mpc.gen(onld, PMIN)); %% total load capacity 0088 Pmin = mpc.gen(on, PMIN); 0089 while sum(Pmin) > load_capacity 0090 %% shut down most expensive unit 0091 avgPmincost = totcost(mpc.gencost(on, :), Pmin) ./ Pmin; 0092 [junk, i] = fairmax(avgPmincost); %% pick one with max avg cost at Pmin 0093 i = on(i); %% convert to generator index 0094 0095 if mpopt.verbose 0096 fprintf('Shutting down generator %d so all Pmin limits can be satisfied.\n', i); 0097 end 0098 0099 %% set generation to zero 0100 mpc.gen(i, [ PG QG GEN_STATUS ]) = 0; 0101 0102 %% update minimum gen capacity 0103 on = find( mpc.gen(:, GEN_STATUS) > 0 & ~isload(mpc.gen) ); %% gens in service 0104 Pmin = mpc.gen(on, PMIN); 0105 end 0106 if ~any(mpc.gen(:, GEN_STATUS) > 0) %% don't bother to run anything if 0107 success = 0; %% everything has been shut down 0108 results0 = mpc; 0109 results0.success = success; 0110 results0.f = NaN; 0111 results0.et = 0; 0112 if mpopt.verbose 0113 fprintf('Infeasible problem, Pmin limits cannot be satisfied without shutting down all generators.\n'); 0114 end 0115 else 0116 %% run initial opf 0117 [results, success] = opf(mpc, mpopt); 0118 0119 %% best case so far 0120 results1 = results; 0121 0122 %% best case for this stage (ie. with n gens shut down, n=0,1,2 ...) 0123 results0 = results1; 0124 mpc.bus = results0.bus; %% use these V as starting point for OPF 0125 0126 while 1 0127 %% get candidates for shutdown 0128 candidates = find(results0.gen(:, MU_PMIN) > 0 & results0.gen(:, PMIN) > 0); 0129 if isempty(candidates) 0130 break; 0131 end 0132 done = 1; %% do not check for further decommitment unless we 0133 %% see something better during this stage 0134 for i = 1:length(candidates) 0135 k = candidates(i); 0136 %% start with best for this stage 0137 mpc.gen = results0.gen; 0138 0139 %% shut down gen k 0140 mpc.gen(k, [ PG QG GEN_STATUS ]) = 0; 0141 0142 %% run opf 0143 if any(mpc.gen(:, GEN_STATUS) > 0) 0144 [results, success] = opf(mpc, mpopt); 0145 else 0146 success = 0; 0147 end 0148 0149 %% something better? 0150 if success && results.f < results1.f 0151 results1 = results; 0152 k1 = k; 0153 done = 0; %% make sure we check for further decommitment 0154 end 0155 end 0156 0157 if done 0158 %% decommits at this stage did not help, so let's quit 0159 break; 0160 else 0161 %% shutting something else down helps, so let's keep going 0162 if mpopt.verbose 0163 fprintf('Shutting down generator %d.\n', k1); 0164 end 0165 0166 results0 = results1; 0167 mpc.bus = results0.bus; %% use these V as starting point for OPF 0168 end 0169 end 0170 end 0171 0172 %% compute elapsed time 0173 et = etime(clock, t0); 0174 0175 %% finish preparing output 0176 if nargout > 0 0177 success = results0.success; 0178 if nargout <= 2 0179 results0.et = et; 0180 bus = results0; 0181 gen = success; 0182 else 0183 [bus, gen, branch, f, info, xr, pimul] = deal(results0.bus, results0.gen, ... 0184 results0.branch, results0.f, results0.raw.info, ... 0185 results0.raw.xr, results0.raw.pimul); 0186 if isfield(results0, 'g') 0187 g = results0.g; 0188 end 0189 if isfield(results0, 'dg') 0190 jac = results0.dg; 0191 end 0192 end 0193 elseif results0.success 0194 results0.et = et; 0195 printpf(results0, 1, mpopt); 0196 end