$title An MPSGE Template for Renewable Portfolio Standards
$ontext
An Email Question about Renewable Portfolio Standards
----------------------------------------------------------------
Greetings,
My sincere apologies for bothering you with what must be a trivial
question, namely, the proper interpretation for the level value of an
endogenous subsidy which is greater than unity. Is this merely a sign
that my model ill-posed, or is there some other interpretation?
The back story is that I am trying to simulate a renewable portfolio
standard (RPS) within a CGE model. I have a balanced SAM whose electric
power sector has been disaggregated into various generation
technologies, which I use to calibrate a representative-agent model of
the economy. Recall that an RPS is a two-part instrument in which
qualifying renewables enjoy a subsidy, the revenue for which is raised
through a tax on conventional generation. I implement this using two
scalar auxiliary equations: RPS_SUB, an endogenous subsidy to meet the
target level of renewable penetration (given by RENEWABLE_PORTFOLIO_STD
= 20%), and RPS_TAX, the corresponding endogenous tax on conventional
generation.
Here is the generators' production block:
<lots of MPSGE code>
The first problem is that to meet even a 10% target, the level value
of RPS_SUB is much larger than unity. Even this target is pretty
stringent, as renewables make up only 1.6% of net generation in the
benchmark. To test whether anything is wrong I have simulated the
model with only the subsidy and no tax component (by setting the flag
TAXCOMP to zero), and the value of RPS_SUB is still large. The model
solves normally and the final statistics look OK.
The second problem follows, which is that the level of RPS_TAX which
is required to finance that level of subsidy exceeds 60%! Note that in
the second side-constraint I am assuming that the output price of each
type of generator which MPSGE reports is *net* of any tax or subsidy.
Is this correct?
Any assistance you might be able to provide would be greatly
appreciated.
-----------------------------------------------------------------------------
"Je N'ai fait celle-ci plus longue que parceque je n'ai pas eu le
loisir de la faire plus courte.-- I have only made this letter rather
long because I have not had time to make it shorter." Pascal. Lettres
provinciales, 16, Dec.14,1656. Cassell's Book of Quotations,
London,1912. P.718.
"Not that the story need be long, but it will take a long while to
make it short." Thoreau. Letter to a Friend.
In other words, I don't have time to debug your code, but I can more
easily write a little template model which shows you how I would
implement a portfolio standard. The burden of understanding how this
works then rests with your willingness to go through my code,
something which is a very different burden sharing arrangement than
had I taken the time to go through your model. I am always happy to
point the way, but I often don't have time to go with you step by
step.
Let me begin with the big issue here. MPSGE offers "auxiliary
variables" as a means of coping with exotic challenges which arise in
general equilibrium analysis. These are particularly useful when
dealing with market failures. It is generally a good idea, however,
to work within the standard Arrow-Debreu paradigm whenever possible.
This is one such application in which while it is possible but not
advisable to resort to auxiliary variables.
Now, let me describe my template application.
In this little model electricity generation is associated with 100
generating facilities, each of which has the same capacity. Units
have different operating costs, both associated with their technology
characteristics and other idosyncratic features of each plant. Units
are dispatched in merit order utilizing Mathiesen's complementarity
format to integrate the complementary slackness features directly into
the equilibrium problem. (See this working paper and the
associated GAMS files.)
A two-dimensional set (a "tuple") pt(t,f) associates generating units
t with fuel characteristics f. A renewable portfolio standard is a
constraint which requires that units based on a particular set of
fuels supply a minimum fraction of the delivered power:
sum(pt(t,rps), x(t)) =g= phi * sum(t,x(t));
The trick to implementing this constraint in MPSGE is to identify
which of these coefficients on the $prod:x(t) block are inputs and
which are outputs.
The way to think of this is to imagine a permit system which
implements the RPS policy. Each time that someone generates a KWH of
electricity from a renewable plant, the manager receives a RPS permit.
At the same time, any time that any plant (including a renewable
plant) produces 1 KWH of electricity, they must surrender phi permits,
where phi is the renewable portfolio standard.
In linear programming parlance, the RPS rule introduces a "blending
constraint", and it is notable that blending constraints are linearly
homogeneous -- there is no RHS constant. In economic terms, this
means that the RPS system redistributes funds between power plant
operators, but any impact on household incomes is purely indirect,
operating only through the price of the delivered electricity. In
other words, there are no pure rents produced by the RPS, and perhaps
this is one reason that these sorts of rules are so popular.
$offtext
set f Electric power technologies /coal,gas,nucl,wind,solar,hydro/,
rps(f) Renewable power technologies /wind,solar,hydro/,
t Power plants (for simplicity equal capacity) /p1*p100/,
pt(t,f) An association of plants to fuels (one to one);
$eolcom !
parameter pi(f) Fraction of plants in each type
/coal 0.4
gas 0.2
nucl 0.2
wind 0.05 !
solar 0.05 ! Renewables are only 20% of capacity.
hydro 0.10/; ! Higher targets require idling of capacity.
* Convert the fractions to a cumulative distribution:
loop(f, pi(f) = pi(f-1) + pi(f);); display pi;
* Produce a tuple which maps plants to fuels in numbers
* which are consistent with the plant fractions:
pt(t,f) = yes$(ord(t)/card(t) > pi(f-1) and ord(t)/card(t) <= pi(f));
parameter nplant(f) Number of plants by type;
nplant(f) = sum(pt(t,f),1);
display nplant;
set bug(t);
bug(t) = yes$(1-sum(pt(t,f),1));
display bug;
parameter ac(f) Average cost /
coal 10
gas 20
nucl 10
wind 40
solar 50
hydro 60 /;
parameter tc(t) Technology cost (with random differences);
loop(pt(t,f), tc(t) = ac(f) * normal(1,0.2);); display tc;
parameter rpsout(t) Coefficient for RPS system,
phi RPS target share,
delta(t) Switch for introducing permit system,
limit Target associated with permit system;
* Base year equilibrium has no RPS constraint nor permits:
limit = 0;
delta(t) =0;
phi = 0;
rpsout(t) = 0;
$ontext
$model:aaelec
$sectors:
c ! Consumption of goods and leisure
y ! Other production
x(t) ! Electricity generation
$commodities:
pc ! Price of consumption
py ! Price of output
pe ! Price of energy
pl ! Price of leisure
pk ! Price of capital
pcap(t) ! Price of electricity generating capacity
prps$phi ! Shadow price on renewables
plim$limit ! Shadow price on efficient instrument
$consumers:
ra ! Representative agent
* Final consumption combines goods and leisure:
$prod:c s:1
o:pc q:100
i:pl q:50
i:py q:50
* Macro production trades off energy use with value-added:
$prod:y s:0.5 va:1
o:py q:50
i:pe q:2
i:pl q:30
i:pk q:18
* Electricity generation:
$prod:x(t) s:0
o:pe q:2
i:py q:(tc(t)/100) ! Scaling here to match macro
i:pcap(t) q:1 ! units -- benchmark output approx. = 2
* RPS policy instruments, including both
* input and output coefficients:
o:prps q:rpsout(t)
i:prps q:phi
* Efficient policy instrument:
i:plim q:delta(t)
* Final demand:
$demand:ra
d:pc
e:pk q:18
e:pl q:80
e:pcap(t) q:0.05
* When we have a permit system, rents on the permits
* are return lump-sum:
e:plim q:limit
$offtext
$sysinclude mpsgeset aaelec
* The model is not precisely calibrated. We therefore need to
* solve for a benchmark equilibrium and cannot use the debugging
* trick of setting the iteration limit to zero:
$include AAELEC.GEN
solve aaelec using mcp;
parameter results Summary report;
results("bmk",f) = sum(pt(t,f),x.l(t)*2);
results("bmk","PE") = pe.l/pc.l;
results("bmk","pl") = pl.l/pc.l;
results("bmk","pk") = pk.l/pc.l;
results("bmk","c") = c.l;
results("bmk","e") = sum(t,x.l(t)*2);
display results;
* Set the solvelink to 2 so that GAMS remains in memory
* during the solution process and does not need to reload
* after each solution:
aaelec.solvelink = 2;
* The shadow prices on the RPS is initially omitted from the
* model. We need to set the level value of this price to zero
* so that we properly report the initial price:
prps.l = 0;
* Consider a range of RPS targets from 0% to 50%:
set rpslvl Level of the renewable portfolio standard (%) /0*50/;
loop(rpslvl,
* Establish the target share here:
phi = 0.01*(ord(rpslvl)-1);
$include AAELEC.GEN
solve aaelec using mcp;
* Record results for this RPS target:
results(rpslvl,f) = sum(pt(t,f),x.l(t)*2);
results(rpslvl,"rpssbd") = 100*prps.l/pe.l*(1-phi)/2;
results(rpslvl,"rpstax") = 100*prps.l/pe.l*phi/2;
results(rpslvl,"E") = sum(t, x.l(t)*2);
results(rpslvl,"PE") = pe.l/pc.l;
results(rpslvl,"pl") = pl.l/pc.l;
results(rpslvl,"pk") = pk.l/pc.l;
results(rpslvl,"c") = c.l;
* As part of the reporting, record the emission level from
* the non-RPS plants. These values will permit us to compute
* the excess economic cost of the RPS policy, as we can compare
* it with a first-best permit system (see below):
results(rpslvl,"emit") = sum(pt(t,f)$(not rps(f)), X.L(t));
* Install the RPS output coefficients for those plants
* which are fueled with renewable inputs:
loop(pt(t,rps), rpsout(t) = 1;);
);
* Turn off the RPS instrument:
rpsout(t) = 0; phi = 0;
* Turn on the permit system which simply places an upper
* bound on the non-renewable generation:
loop(pt(t,f)$(not rps(f)), delta(t) = 1;);
* Go back through the same set of emission targets so that
* we can evaluate how the excess cost is related to the
* renewable target:
loop(rpslvl,
limit = results(rpslvl,"emit");
$include AAELEC.GEN
solve aaelec using mcp;
* Record a few characteristics of these equilibria: energy
* price, permit price, and aggregate consumption:
results(rpslvl,"PE*") = pe.l/pc.l;
results(rpslvl,"plim") = 100 * plim.l/pe.l * 1/2;
results(rpslvl,"E*") = sum(t, x.l(t)*2);
results(rpslvl,"c*") = c.l;
);
display results;
* Produce some output using GNUPLOT:
parameter summary Summary of impacts;
* It took a bit of fiddling to determine that these outputs
* provide insights into the economics of the policy measures:
summary(rpslvl,"sbd%") = results(rpslvl,"rpssbd");
summary(rpslvl,"tax%") = results(rpslvl,"rpstax");
summary(rpslvl,"pe") = 100 * (results(rpslvl,"pe")/results("bmk","pe")-1);
summary(rpslvl,"plim") = results(rpslvl,"plim");
summary(rpslvl,"pe*") = 100 * (results(rpslvl,"pe*")/results("bmk","pe")-1);
summary(rpslvl,"e") = 100 * (results(rpslvl,"e")/results("bmk","e")-1);
summary(rpslvl,"e*") = 100 * (results(rpslvl,"e*")/results("bmk","e")-1);
parameter welfare Comparison of Welfare impacts;
welfare(rpslvl,"RPS") = 100 * (results(rpslvl,"c")/ results("bmk","c")-1);
welfare(rpslvl,"Permits") = 100 * (results(rpslvl,"c*")/results("bmk","c")-1);
* Define the domain and the labels for the plots:
set rpslbl(rpslvl) /10,20,30,40,50/;
$setglobal domain rpslvl
$setglobal labels rpslbl
* Issue some GNUPLOT commands to provide a nicer plot:
$setglobal gp_opt0 "set xlabel '% RPS share'"
$setglobal gp_opt1 "set ylabel '% change'"
$setglobal gp_opt2 "set key outside width 3"
$setglobal gp_opt3 "set grid"
$setglobal gp_opt4 "set title 'Economic Impacts of RPS'"
$libinclude plot summary
$setglobal gp_opt4 "set title 'Welfare Impact of RPS'"
$libinclude plot welfare
* After having generated the plots on the screen, generate
* the same plots as PNG files:
$setglobal batch yes
$setglobal gp_opt5 "set term png"
$setglobal gp_opt4 "set title 'Economic Impacts of RPS'"
$setglobal gp_opt6 "set output 'impacts.png'"
$libinclude plot summary
$setglobal gp_opt4 "set title 'Welfare Impact of RPS'"
$setglobal gp_opt6 "set output 'welfare.png'"
$libinclude plot welfare