Home > matpower4.1 > extras > smartmarket > smartmkt.m

smartmkt

PURPOSE ^

SMARTMKT Runs the PowerWeb smart market.

SYNOPSIS ^

function [co, cb, r, dispatch, success] =smartmkt(mpc, offers, bids, mkt, mpopt)

DESCRIPTION ^

SMARTMKT  Runs the PowerWeb smart market.
   [CO, CB, RESULTS, DISPATCH, SUCCESS] = SMARTMKT(MPC, ...
       OFFERS, BIDS, MKT, MPOPT) runs the ISO smart market.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function [co, cb, r, dispatch, success] = ...
0002             smartmkt(mpc, offers, bids, mkt, mpopt)
0003 %SMARTMKT  Runs the PowerWeb smart market.
0004 %   [CO, CB, RESULTS, DISPATCH, SUCCESS] = SMARTMKT(MPC, ...
0005 %       OFFERS, BIDS, MKT, MPOPT) runs the ISO smart market.
0006 
0007 %   MATPOWER
0008 %   $Id: smartmkt.m,v 1.34 2011/03/23 18:30:06 cvs Exp $
0009 %   by Ray Zimmerman, PSERC Cornell
0010 %   Copyright (c) 1996-2010 by Power System Engineering Research Center (PSERC)
0011 %
0012 %   This file is part of MATPOWER.
0013 %   See http://www.pserc.cornell.edu/matpower/ for more info.
0014 %
0015 %   MATPOWER is free software: you can redistribute it and/or modify
0016 %   it under the terms of the GNU General Public License as published
0017 %   by the Free Software Foundation, either version 3 of the License,
0018 %   or (at your option) any later version.
0019 %
0020 %   MATPOWER is distributed in the hope that it will be useful,
0021 %   but WITHOUT ANY WARRANTY; without even the implied warranty of
0022 %   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0023 %   GNU General Public License for more details.
0024 %
0025 %   You should have received a copy of the GNU General Public License
0026 %   along with MATPOWER. If not, see <http://www.gnu.org/licenses/>.
0027 %
0028 %   Additional permission under GNU GPL version 3 section 7
0029 %
0030 %   If you modify MATPOWER, or any covered work, to interface with
0031 %   other modules (such as MATLAB code and MEX-files) available in a
0032 %   MATLAB(R) or comparable environment containing parts covered
0033 %   under other licensing terms, the licensors of MATPOWER grant
0034 %   you additional permission to convey the resulting work.
0035 
0036 %%-----  initialization  -----
0037 %% default arguments
0038 if nargin < 5
0039     mpopt = mpoption;       %% use default options
0040 end
0041 
0042 %% options
0043 verbose = mpopt(31);
0044 
0045 %% initialize some stuff
0046 G = find( ~isload(mpc.gen) );       %% real generators
0047 L = find(  isload(mpc.gen) );       %% dispatchable loads
0048 nL = length(L);
0049 if isfield(offers, 'Q') || isfield(bids, 'Q')
0050     haveQ = 1;
0051 else
0052     haveQ = 0;
0053 end
0054 
0055 if haveQ && mkt.auction_type ~= 0 && mkt.auction_type ~= 5
0056     error(['smartmkt: Combined active/reactive power markets ', ...
0057             'are only implemented for auction types 0 and 5']);
0058 end
0059 
0060 %% set power flow formulation based on market
0061 mpopt = mpoption(mpopt, 'PF_DC', strcmp(mkt.OPF, 'DC'));
0062 
0063 %% define named indices into data matrices
0064 [PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ...
0065     VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus;
0066 [GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, ...
0067     MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, ...
0068     QC2MIN, QC2MAX, RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = idx_gen;
0069 [PW_LINEAR, POLYNOMIAL, MODEL, STARTUP, SHUTDOWN, NCOST, COST] = idx_cost;
0070 [QUANTITY, PRICE, FCOST, VCOST, SCOST, PENALTY] = idx_disp;
0071 
0072 %% set up cost info & generator limits
0073 mkt.lim = pricelimits(mkt.lim, isfield(offers, 'Q') || isfield(bids, 'Q'));
0074 [gen, genoffer] = off2case(mpc.gen, mpc.gencost, offers, bids, mkt.lim);
0075 
0076 %% move Pmin and Pmax limits out slightly to avoid problems
0077 %% with lambdas caused by rounding errors when corner point
0078 %% of cost function lies at exactly Pmin or Pmax
0079 if any(find(genoffer(:, MODEL) == PW_LINEAR))
0080     gg = find( ~isload(gen) );      %% skip dispatchable loads
0081     gen(gg, PMIN) = gen(gg, PMIN) - 100 * mpopt(16) * ones(size(gg));
0082     gen(gg, PMAX) = gen(gg, PMAX) + 100 * mpopt(16) * ones(size(gg));
0083 end
0084 
0085 %%-----  solve the optimization problem  -----
0086 %% attempt OPF
0087 mpc2 = mpc;
0088 mpc2.gen = gen;
0089 mpc2.gencost = genoffer;
0090 [r, success] = uopf(mpc2, mpopt);
0091 [bus, gen] = deal(r.bus, r.gen);
0092 if verbose && ~success
0093     fprintf('\nSMARTMARKET: non-convergent UOPF');
0094 end
0095 
0096 %%-----  compute quantities, prices & costs  -----
0097 %% compute quantities & prices
0098 ng = size(gen, 1);
0099 if success      %% OPF solved case fine
0100     %% create map of external bus numbers to bus indices
0101     i2e = bus(:, BUS_I);
0102     e2i = sparse(max(i2e), 1);
0103     e2i(i2e) = (1:size(bus, 1))';
0104 
0105     %% get nodal marginal prices from OPF
0106     gbus    = e2i(gen(:, GEN_BUS));                 %% indices of buses w/gens
0107     nPo     = size(offers.P.qty, 2);
0108     nPb     = size(bids.P.qty, 2);
0109     nP      = max([ nPo nPb ]);
0110     lamP    = sparse(1:ng, 1:ng, bus(gbus, LAM_P), ng, ng) * ones(ng, nP);  %% real power prices
0111     lamQ    = sparse(1:ng, 1:ng, bus(gbus, LAM_Q), ng, ng) * ones(ng, nP);  %% reactive power prices
0112     
0113     %% compute fudge factor for lamP to include price of bundled reactive power
0114     pf   = zeros(length(L), 1);                 %% for loads Q = pf * P
0115     Qlim =  (gen(L, QMIN) == 0) .* gen(L, QMAX) + ...
0116             (gen(L, QMAX) == 0) .* gen(L, QMIN);
0117     pf = Qlim ./ gen(L, PMIN);
0118 
0119     gtee_prc.offer = 1;         %% guarantee that cleared offers are >= offers
0120     Poffer = offers.P;
0121     Poffer.lam = lamP(G,1:nPo);
0122     Poffer.total_qty = gen(G, PG);
0123     
0124     Pbid = bids.P;
0125     Pbid.total_qty = -gen(L, PG);
0126     if haveQ
0127         Pbid.lam = lamP(L,1:nPb);   %% use unbundled lambdas
0128         gtee_prc.bid = 0;       %% allow cleared bids to be above bid price
0129     else
0130         Pbid.lam = lamP(L,1:nPb) + sparse(1:nL, 1:nL, pf, nL, nL) * lamQ(L,1:nPb);  %% bundled lambdas
0131         gtee_prc.bid = 1;       %% guarantee that cleared bids are <= bids
0132     end
0133 
0134     [co.P, cb.P] = auction(Poffer, Pbid, mkt.auction_type, mkt.lim.P, gtee_prc);
0135 
0136     if haveQ
0137         nQo = size(offers.Q.qty, 2);
0138         nQb = size(bids.Q.qty, 2);
0139         nQ  = max([ nQo nQb ]);
0140         
0141         %% get nodal marginal prices from OPF
0142         lamQ    = sparse(1:ng, 1:ng, bus(gbus, LAM_Q), ng, ng) * ones(ng, nQ);  %% reactive power prices
0143 
0144         Qoffer = offers.Q;
0145         Qoffer.lam = lamQ(:,1:nQo);     %% use unbundled lambdas
0146         Qoffer.total_qty = (gen(:, QG) > 0) .* gen(:, QG);
0147         
0148         Qbid = bids.Q;
0149         Qbid.lam = lamQ(:,1:nQb);       %% use unbundled lambdas
0150         Qbid.total_qty = (gen(:, QG) < 0) .* -gen(:, QG);
0151 
0152         %% too complicated to scale with mixed bids/offers
0153         %% (only auction_types 0 and 5 allowed)
0154         [co.Q, cb.Q] = auction(Qoffer, Qbid, mkt.auction_type, mkt.lim.Q, gtee_prc);
0155     end
0156 
0157     quantity    = gen(:, PG);
0158     price       = zeros(ng, 1);
0159     price(G)    = co.P.prc(:, 1);   %% need these for prices for
0160     price(L)    = cb.P.prc(:, 1);   %% gens that are shut down
0161     if nP == 1
0162         k = find( co.P.qty );
0163         price(G(k)) = co.P.prc(k, :);
0164         k = find( cb.P.qty );
0165         price(L(k)) = cb.P.prc(k, :);
0166     else
0167         k = find( sum( co.P.qty' )' );
0168         price(G(k)) = sum( co.P.qty(k, :)' .* co.P.prc(k, :)' )' ./ sum( co.P.qty(k, :)' )';
0169         k = find( sum( cb.P.qty' )' );
0170         price(L(k)) = sum( cb.P.qty(k, :)' .* cb.P.prc(k, :)' )' ./ sum( cb.P.qty(k, :)' )';
0171     end
0172 else        %% did not converge even with imports
0173     quantity    = zeros(ng, 1);
0174     price       = mkt.lim.P.max_offer * ones(ng, 1);
0175     co.P.qty = zeros(size(offers.P.qty));
0176     co.P.prc = zeros(size(offers.P.prc));
0177     cb.P.qty = zeros(size(bids.P.qty));
0178     cb.P.prc = zeros(size(bids.P.prc));
0179     if haveQ
0180         co.Q.qty = zeros(size(offers.Q.qty));
0181         co.Q.prc = zeros(size(offers.Q.prc));
0182         cb.Q.qty = zeros(size(bids.Q.qty));
0183         cb.Q.prc = zeros(size(bids.Q.prc));
0184     end
0185 end
0186 
0187 
0188 %% compute costs in $ (note, NOT $/hr)
0189 fcost   = mkt.t * totcost(mpc.gencost, zeros(ng, 1) );      %% fixed costs
0190 vcost   = mkt.t * totcost(mpc.gencost, quantity     ) - fcost;  %% variable costs
0191 scost   =   (~mkt.u0 & gen(:, GEN_STATUS) >  0) .* ...
0192                 mpc.gencost(:, STARTUP) + ...               %% startup costs
0193             ( mkt.u0 & gen(:, GEN_STATUS) <= 0) .* ...
0194                 mpc.gencost(:, SHUTDOWN);                   %% shutdown costs
0195 
0196 %% store in dispatch
0197 dispatch = zeros(ng, PENALTY);
0198 dispatch(:, [QUANTITY PRICE FCOST VCOST SCOST]) = [quantity price fcost vcost scost];

Generated on Mon 26-Jan-2015 15:00:13 by m2html © 2005