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

📄 off2case.m

📁 MATPOWER 一款基于MATLAB的电力系统潮流计算及优化的程序
💻 M
字号:
function [gen, gencost] = off2case(gen, gencost, offers, bids, lim)%OFF2CASE  Updates case variables gen & gencost from quantity & price offers.%   [gen, gencost] = off2case(gen, gencost, offers, bids, lim) updates%   gen & gencost variables based on the offers and bids supplied, where each%   is a struct (or bids can be an empty matrix) with field 'P' (active power%   offer/bid) and optional field 'Q' (reactive power offer/bid), each of which%   is another struct with fields 'qty' and 'prc', m x n matrices of quantity%   and price offers/bids, respectively. There are m offers with n blocks each.%   For offers, m can be equal to the number of actual generators (not including%   dispatchable loads) or the total number of rows in the gen matrix (including%   dispatchable loads). For bids, m can be equal to the number of dispatchable%   loads or the total number of rows in the gen matrix. Non-zero offer (bid)%   quantities for gen matrix entries where Pmax <= 0 (Pmin >= 0) produce an%   error. Similarly for Q.%   %   E.g.%       offers.P.qty - m x n, active power quantity offers, m offers, n blocks%               .prc - m x n, active power price offers%             .Q.qty - m x n, reactive power quantity offers%               .prc - m x n, reactive power price offers%%   These values are used to update PMIN, PMAX, QMIN, QMAX and GEN_STATUS%   columns of the gen matrix and all columns of the gencost matrix except%   STARTUP and SHUTDOWN.%%   The last argument, lim is a struct with the following fields,%   all of which are optional:%       lim.P.min_bid%            .max_offer%          .Q.min_bid%            .max_offer%   Any price offers (bids) for real power above (below) lim.P.max_offer%   (lim.P.min_bid) will be treated as being withheld. Likewise for Q.%   MATPOWER%   $Id: off2case.m,v 1.18 2006/04/18 13:39:34 ray Exp $%   by Ray Zimmerman, PSERC Cornell%   Copyright (c) 1996-2006 by Power System Engineering Research Center (PSERC)%   See http://www.pserc.cornell.edu/matpower/ for more info.%% define named indices into data matrices[GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, ...    MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, ...    QC2MIN, QC2MAX, RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = idx_gen;[PW_LINEAR, POLYNOMIAL, MODEL, STARTUP, SHUTDOWN, NCOST, COST] = idx_cost;%% default args and stuffif nargin < 5    lim = [];    if nargin < 4        bids = [];    endendif isfield(offers, 'Q') | isfield(bids, 'Q')    haveQ = 1;else    haveQ = 0;endlim = pricelimits(lim, haveQ);if isempty(bids)    bids = struct( 'P', struct('qty', [], 'prc', []));endif haveQ    if ~isfield(bids, 'Q')        bids.Q = struct('qty', [], 'prc', []);    elseif ~isfield(offers, 'Q')        offers.Q = struct('qty', [], 'prc', []);    endend%% indexes and sizesngc = size(gencost, 2);G = find( ~isload(gen) );       %% real generatorsL = find(  isload(gen) );       %% dispatchable loadsnGL = size(gen, 1);[idxPo, idxPb, idxQo, idxQb] = idx_vecs(offers, bids, G, L, haveQ);if haveQ    if size(gencost, 1) == nGL        %% set all reactive costs to zero if not provided        gencost = [ ...            gencost;            [PW_LINEAR * ones(nGL, 1) gencost(:,[STARTUP SHUTDOWN]) 2*ones(nGL,1) zeros(nGL,ngc-4) ]        ];        gencost(G+nGL, COST+2) =  1;        gencost(L+nGL, COST)   = -1;    elseif size(gencost, 1) ~= 2 * nGL        error(sprintf('gencost should have either %d or %d rows', nGL, 2*nGL));    endend%% number of points to define piece-wise linear costif any(idxPo & idxPb)    np = size(offers.P.qty, 2) + size(bids.P.qty, 2);else    np = max([ size(offers.P.qty, 2) size(bids.P.qty, 2) ]);endif haveQ    if any(idxQo & idxQb)        np = max([ np size(offers.Q.qty, 2) + size(bids.Q.qty, 2) ]);    else        np = max([ np size(offers.Q.qty, 2) size(bids.Q.qty, 2) ]);    endendnp = np + 1;if any(idxPo + idxPb == 0)  %% some gens have no offer or bid, use original cost    np = max([ np ceil(ngc-NCOST)/2 ]);end%% initialize new cost matricesPgencost            = zeros(nGL, COST + 2*np - 1);Pgencost(:, MODEL)  = PW_LINEAR * ones(nGL, 1);Pgencost(:, [STARTUP SHUTDOWN]) = gencost(1:nGL, [STARTUP SHUTDOWN]);if haveQ    Qgencost = Pgencost;    Qgencost(:, [STARTUP SHUTDOWN]) = gencost(nGL+[1:nGL], [STARTUP SHUTDOWN]);endfor i = 1:nGL    %% convert active power bids & offers into piecewise linear segments    if idxPb(i)     %% there is a bid for this unit        if gen(i, PMIN) >= 0 & any(bids.P.qty(idxPb(i), :))            error(sprintf('Pmin >= 0, bid not allowed for gen %d', i));        end        [xxPb, yyPb, nPb] = offbid2pwl(bids.P.qty(idxPb(i), :), bids.P.prc(idxPb(i), :), 1, lim.P.min_bid);    else        nPb = 0;    end    if idxPo(i)     %% there is an offer for this unit        if gen(i, PMAX) <= 0 & any(offers.P.qty(idxPo(i), :))            error(sprintf('Pmax <= 0, offer not allowed for gen %d', i));        end        [xxPo, yyPo, nPo] = offbid2pwl(offers.P.qty(idxPo(i), :), offers.P.prc(idxPo(i), :), 0, lim.P.max_offer);    else        nPo = 0;    end    %% convert reactive power bids & offers into piecewise linear segments    if haveQ        if idxQb(i)     %% there is a bid for this unit            if gen(i, QMIN) >= 0 & any(bids.Q.qty(idxQb(i), :))                error(sprintf('Qmin >= 0, reactive bid not allowed for gen %d', i));            end            [xxQb, yyQb, nQb] = offbid2pwl(bids.Q.qty(idxQb(i), :), bids.Q.prc(idxQb(i), :), 1, lim.Q.min_bid);        else            nQb = 0;        end        if idxQo(i)     %% there is an offer for this unit            if gen(i, QMAX) <= 0 & any(offers.Q.qty(idxQo(i), :))                error(sprintf('Qmax <= 0, reactive offer not allowed for gen %d', i));            end            [xxQo, yyQo, nQo] = offbid2pwl(offers.Q.qty(idxQo(i), :), offers.Q.prc(idxQo(i), :), 0, lim.Q.max_offer);        else            nQo = 0;        end    else        nQb = 0;        nQo = 0;    end    %% collect the pwl segments for active power    if nPb > 1 & nPo > 1            %% bid and offer (positive and negative qtys)        if xxPb(end) | yyPb(end) | xxPo(1) | yyPo(1)            error(fprintf('Oops ... these 4 numbers should be zero: %g %g %g %g\n', ...                xxPb(end), yyPb(end), xxPo(1), yyPo(1)));        end        xxP = [xxPb xxPo(2:end)];        yyP = [yyPb yyPo(2:end)];        npP = nPb + nPo - 1;    elseif  nPb <= 1 & nPo > 1  %% offer only        xxP = xxPo;        yyP = yyPo;        npP = nPo;    elseif  nPb > 1 & nPo <= 1  %% bid only        xxP = xxPb;        yyP = yyPb;        npP = nPb;    else        npP = 0;    end    %% collect the pwl segments for reactive power    if nQb > 1 & nQo > 1            %% bid and offer (positive and negative qtys)        if xxQb(end) | yyQb(end) | xxQo(1) | yyQo(1)            error(fprintf('Oops ... these 4 numbers should be zero: %g %g %g %g\n', ...                xxQb(end), yyQb(end), xxQo(1), yyQo(1)));        end        xxQ = [xxQb xxQo(2:end)];        yyQ = [yyQb yyQo(2:end)];        npQ = nQb + nQo - 1;    elseif  nQb <= 1 & nQo > 1  %% offer only        xxQ = xxQo;        yyQ = yyQo;        npQ = nQo;    elseif  nQb > 1 & nQo <= 1  %% bid only        xxQ = xxQb;        yyQ = yyQb;        npQ = nQb;    else        npQ = 0;    end    %% initialize new gen limits    Pmin = gen(i, PMIN);    Pmax = gen(i, PMAX);    Qmin = gen(i, QMIN);    Qmax = gen(i, QMAX);    %% update real part of gen and gencost    if npP        %% update gen limits        if gen(i, PMAX) > 0            Pmax = max(xxP);            if Pmax < gen(i, PMIN) | Pmax > gen(i, PMAX)                error(sprintf('offer quantity (%g) must be between max(0,PMIN) (%g) and PMAX (%g)', ...                    Pmax, max([0,gen(i, PMIN)]), gen(i, PMAX)));            end        end        if gen(i, PMIN) < 0            Pmin = min(xxP);            if Pmin >= gen(i, PMIN) & Pmin <= gen(i, PMAX)                if isload(gen(i, :))                    Qmin = gen(i, QMIN) * Pmin / gen(i, PMIN);                    Qmax = gen(i, QMAX) * Pmin / gen(i, PMIN);                end            else                error(sprintf('bid quantity (%g) must be between max(0,-PMAX) (%g) and -PMIN (%g)', ...                    -Pmin, max([0 -gen(i, PMAX)]), -gen(i, PMIN)));            end        end        %% update gencost        Pgencost(i, NCOST) = npP;        Pgencost(i,      COST:2:( COST + 2*npP - 2 )) = xxP;        Pgencost(i,  (COST+1):2:( COST + 2*npP - 1 )) = yyP;    else        %% no capacity bid/offered for active power        if npQ & ~isload(gen(i,:)) & gen(i, PMIN) <= 0 & gen(i, PMAX) >= 0            %% but we do have a reactive bid/offer and we can dispatch            %% at zero real power without shutting down            Pmin = 0;            Pmax = 0;            Pgencost(i, 1:ngc) = gencost(i, 1:ngc);        else            %% none for reactive either            %% shut down the unit            gen(i, GEN_STATUS) = 0;        end    end    %% update reactive part of gen and gencost    if npQ        %% update gen limits        if gen(i, QMAX) > 0            Qmax = min([ Qmax max(xxQ) ]);            if Qmax >= gen(i, QMIN) & Qmax <= gen(i, QMAX)                if isload(gen(i, :))                    Pmin = gen(i, PMIN) * Qmax / gen(i, QMAX);                end            else                error(sprintf('reactive offer quantity (%g) must be between max(0,QMIN) (%g) and QMAX (%g)', ...                    Qmax, max([0,gen(i, QMIN)]), gen(i, QMAX)));            end        end        if gen(i, QMIN) < 0            Qmin = max([ Qmin min(xxQ) ]);            if Qmin >= gen(i, QMIN) & Qmin <= gen(i, QMAX)                if isload(gen(i, :))                    Pmin = gen(i, PMIN) * Qmin / gen(i, QMIN);                end            else                error(sprintf('reactive bid quantity (%g) must be between max(0,-QMAX) (%g) and -QMIN (%g)', ...                    -Qmin, max([0 -gen(i, QMAX)]), -gen(i, QMIN)));            end        end        %% update gencost        Qgencost(i, NCOST) = npQ;        Qgencost(i,      COST:2:( COST + 2*npQ - 2 )) = xxQ;        Qgencost(i,  (COST+1):2:( COST + 2*npQ - 1 )) = yyQ;    else        %% no capacity bid/offered for reactive power        if haveQ            if npP & gen(i, QMIN) <= 0 & gen(i, QMAX) >= 0                %% but we do have an active bid/offer and we might be able to                %% dispatch at zero reactive power without shutting down                if isload(gen(i, :)) & (gen(i, QMAX) > 0 | gen(i, QMIN) < 0)                    %% load w/non-unity power factor, zero Q => must shut down                    gen(i, GEN_STATUS) = 0;                else    %% can dispatch at zero reactive without shutting down                    Qmin = 0;                    Qmax = 0;                end                Qgencost(i, 1:ngc) = gencost(nGL+i, 1:ngc);            else            %% none for reactive either                %% shut down the unit                gen(i, GEN_STATUS) = 0;            end        end    end    if gen(i, GEN_STATUS)       %% running        gen(i, PMIN) = Pmin;    %% update limits        gen(i, PMAX) = Pmax;        gen(i, QMIN) = Qmin;        gen(i, QMAX) = Qmax;    else                        %% shut down        %% do not modify cost        Pgencost(i, 1:ngc) = gencost(i, 1:ngc);        if haveQ            Qgencost(i, 1:ngc) = gencost(nGL+i, 1:ngc);        end    endendif ~haveQ    Qgencost = zeros(0, size(Pgencost, 2));endnp = max([ Pgencost(:, NCOST); Qgencost(:, NCOST) ]);ngc = NCOST + 2*np;gencost = [ Pgencost(:, 1:ngc); Qgencost(:, 1:ngc) ];return;%%-----  offbid2pwl()  -----function [xx, yy, n] = offbid2pwl(qty, prc, isbid, lim)if any(qty < 0)    error('offer/bid quantities must be non-negative');end%% strip zero quantities and optionally strip prices beyond limif nargin < 4 | isempty(lim)    valid = find(qty);else    if isbid        valid = find(qty & prc >= lim);    else        valid = find(qty & prc <= lim);    endendif isbid        n = length(valid);    qq = qty(valid(n:-1:1));    %% row vector of quantities    pp = prc(valid(n:-1:1));    %% row vector of priceselse    qq = qty(valid);            %% row vector of quantities    pp = prc(valid);            %% row vector of pricesendn = length(qq) + 1;             %% number of points to define pwl function%% form piece-wise linear total cost functionif n > 1        %% otherwise, leave all cost info zero (specifically NCOST)    xx = [0 cumsum(qq)];    yy = [0 cumsum(pp .* qq)];    if isbid        xx = xx - xx(end);        yy = yy - yy(end);    endelse    xx = [];    yy = [];endreturn;%%-----  idx_vecs()  -----function [idxPo, idxPb, idxQo, idxQb] = idx_vecs(offers, bids, G, L, haveQ)nG = length(G);nL = length(L);nGL = nG + nL;idxPo = zeros(nGL, 1);idxPb = zeros(nGL, 1);idxQo = zeros(nGL, 1);idxQb = zeros(nGL, 1);%% numbers of offers/bids submittednPo = size(offers.P.qty, 1);nPb = size(  bids.P.qty, 1);if haveQ    nQo = size(offers.Q.qty, 1);    nQb = size(  bids.Q.qty, 1);end%% make sure dimensions of qty and prc offers/bids matchif any(size(offers.P.qty) ~= size(offers.P.prc))    error(sprintf('dimensions of offers.P.qty (%d x %d) and offers.P.prc (%d x %d) do not match',...        size(offers.P.qty), size(offers.P.prc)));endif any(size(bids.P.qty) ~= size(bids.P.prc))    error(sprintf('dimensions of bids.P.qty (%d x %d) and bids.P.prc (%d x %d) do not match',...        size(bids.P.qty), size(bids.P.prc)));endif haveQ    if any(size(offers.Q.qty) ~= size(offers.Q.prc))        error(sprintf('dimensions of offers.Q.qty (%d x %d) and offers.Q.prc (%d x %d) do not match',...            size(offers.Q.qty), size(offers.Q.prc)));    end    if any(size(bids.Q.qty) ~= size(bids.Q.prc))        error(sprintf('dimensions of bids.Q.qty (%d x %d) and bids.Q.prc (%d x %d) do not match',...            size(bids.Q.qty), size(bids.Q.prc)));    endend%% active power offer indicesif nPo == nGL    idxPo = [1:nGL]';elseif nPo == nG    idxPo(G) = [1:nG]';elseif nPo ~= 0    error('number of real power offers must be zero or match either the number of generators or the total number of rows in gen');end%% active power bid indicesif nPb == nGL    idxPb = [1:nGL]';elseif nPb == nL    idxPb(L) = [1:nL]';elseif nPb ~= 0    error('number of real power bids must be zero or match the number of dispatchable loads or the total number of rows in gen');endif haveQ    %% reactive power offer indices    if nQo == nGL        idxQo = [1:nGL]';    elseif nQo == nG        idxQo(G) = [1:nG]';    elseif nQo ~= 0        error('number of reactive power offers must be zero or match the number of generators or the total number of rows in gen');    end        %% reactive power bid indices    if nQb == nGL        idxQb = [1:nGL]';    elseif nQb ~= 0        error('number of reactive power bids must be zero or match the total number of rows in gen');    endendreturn;

⌨️ 快捷键说明

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