Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documenting learning equations #1937

Merged
merged 2 commits into from
Dec 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 25 additions & 30 deletions core/datainput.gms
Original file line number Diff line number Diff line change
Expand Up @@ -323,9 +323,10 @@ fm_dataglob("inco0",te) = (1 + sum(regi, p_tkpremused(regi,te))/sum(regi,
pm_data(regi,"floorcost",teLearn(te)) = pm_data(regi,"inco0",te) - pm_data(regi,"incolearn",te);

*** report old floor costs pre manipulation in non-default scenario
$ifthen.floorscen NOT %cm_floorCostScen% == "default"
p_oldFloorCostdata(regi,teLearn(te)) = pm_data(regi,"inco0",te) - pm_data(regi,"incolearn",te);
$ifthen.floorscen not %cm_floorCostScen% == "default"
p_oldFloorCostdata(regi,teLearn(te)) = pm_data(regi,"floorcost",te);
$endif.floorscen

*** calculate floor costs for learning technologies if historical price structure prevails
$ifthen.floorscen %cm_floorCostScen% == "pricestruc"
*** compute maximum tech cost in 2015 for a given tech among regions
Expand Down Expand Up @@ -358,51 +359,45 @@ $ifthen.REG_techcosts not "%cm_techcosts%" == "GLO" !! cm_techcosts is REG or
$endif.REG_techcosts

*** -------------------------------------------------------------------------------
*** Calculate learning parameters:
*** Calculate learning parameters
*** See equations.gms for documentation of learning equations and floor costs
*** -------------------------------------------------------------------------------
*** global exponent
*** parameter calculation for global level, that regional values can gradually converge to
fm_dataglob("learnExp_woFC",teLearn(te)) = log(1 - fm_dataglob("learn",te)) / log(2);
*RP* adjust exponent parameter learnExp_woFC to take floor costs into account
fm_dataglob("learnExp_wFC",teLearn(te)) = fm_dataglob("inco0",te) / fm_dataglob("incolearn",te) * fm_dataglob("learnExp_woFC",te);

*** regional exponent
pm_data(regi,"learnExp_woFC",teLearn(te)) = log(1 - pm_data(regi,"learn",te)) / log(2);
pm_data(regi,"learnExp_wFC",teLearn(te)) = pm_data(regi,"inco0",te) / pm_data(regi,"incolearn",te) * pm_data(regi,"learnExp_woFC",te);

*** global factor
*** parameter calculation for global level, that regional values can gradually converge to
fm_dataglob("learnMult_wFC",teLearn(te)) = fm_dataglob("incolearn",te) / (fm_dataglob("ccap0",te) ** fm_dataglob("learnExp_wFC", te));
*** global parameters: calculation for global level, that regional values can gradually converge to
*** b' = \frac{I_0}{I_0 - F} b = \frac{I_0}{I_0 - F} \log_2(1-\lambda)
fm_dataglob("learnExp_wFC",teLearn(te)) = fm_dataglob("inco0",te) / fm_dataglob("incolearn",te) * log(1 - fm_dataglob("learn",te)) / log(2);
*** a' = \frac{I_0 - F}{C_0^{b'}}
fm_dataglob("learnMult_wFC",teLearn(te)) = fm_dataglob("incolearn",te) / (fm_dataglob("ccap0",te) ** fm_dataglob("learnExp_wFC", te));

*** regional factor
*NB* read in vm_capCum(t0,regi,teLearn) from input.gdx to have info available for the recalibration of 2005 investment costs
Execute_Loadpoint 'input' p_capCum = vm_capCum.l;
*** FS: in case technologies did not exist in gdx, set intial capacities to global initial value
p_capCum(tall,regi,te)$( NOT p_capCum(tall,regi,te)) = fm_dataglob("ccap0",te)/card(regi);
*RP overwrite p_capCum by exogenous values for 2020
p_capCum("2020",regi,"spv") = 0.6 / card(regi2); !! roughly 600GW in 2020
*** regional parameters
pm_data(regi,"learnExp_wFC",teLearn(te)) = pm_data(regi,"inco0",te) / pm_data(regi,"incolearn",te) * log(1 - pm_data(regi,"learn",te)) / log(2);

pm_data(regi,"learnMult_woFC",teLearn(te)) = pm_data(regi,"incolearn",te)/sum(regi2,(pm_data(regi2,"ccap0",te))**(pm_data(regi,"learnExp_woFC",te)));
*RP* adjust parameter learnMult_woFC to take floor costs into account
$ifthen %cm_techcosts% == "GLO"
pm_data(regi,"learnMult_wFC",teLearn(te)) = pm_data(regi,"incolearn",te) / (sum(regi2,pm_data(regi2,"ccap0",te)) ** pm_data(regi,"learnExp_wFC",te));
pm_data(regi,"learnMult_wFC",teLearn(te)) = pm_data(regi,"incolearn",te) / (sum(regi2,pm_data(regi2,"ccap0",te)) ** pm_data(regi,"learnExp_wFC",te));

$else
!! cm_techcosts is REG or REG2040
*NB* read in vm_capCum(t0,regi,teLearn) from input.gdx to have info available for the recalibration of 2005 investment costs
Execute_Loadpoint 'input' p_capCum = vm_capCum.l;
*** FS: in case technologies did not exist in gdx, set intial capacities to global initial value
p_capCum(tall,regi,te)$(not p_capCum(tall,regi,te)) = fm_dataglob("ccap0",te) / card(regi);
*RP overwrite p_capCum by exogenous values for 2020
p_capCum("2020",regi,"spv") = 0.6 / card(regi2); !! roughly 600GW in 2020 globally
*NB* this is the correction of the original parameter calibration
pm_data(regi,"learnMult_wFC",teLearn(te)) = pm_data(regi,"incolearn",te) / (sum(regi2,p_capCum("2015",regi2,te)) ** pm_data(regi,"learnExp_wFC",te));
pm_data(regi,"learnMult_wFC",teLearn(te)) = pm_data(regi,"incolearn",te) / (sum(regi2,p_capCum("2015",regi2,te)) ** pm_data(regi,"learnExp_wFC",te));
*** initialize spv learning curve in 2020
pm_data(regi,"learnMult_wFC","spv") = pm_data(regi,"incolearn","spv") / (sum(regi2,p_capCum("2020",regi2,"spv")) ** pm_data(regi,"learnExp_wFC","spv"));
pm_data(regi,"learnMult_wFC","spv") = pm_data(regi,"incolearn","spv") / (sum(regi2,p_capCum("2020",regi2,"spv")) ** pm_data(regi,"learnExp_wFC","spv"));
display p_capCum;
$endif

*FS* initialize learning curve for most advanced technologies as defined by tech_stat = 4 in generisdata_tech.prn (with very small real-world capacities in 2020)
*** equally for all regions based on global cumulate capacity of ccap0 and incolearn (difference between initial investment cost and floor cost)
*** equally for all regions based on global cumulative capacity of ccap0 and incolearn (difference between initial investment cost and floor cost)
pm_data(regi,"learnMult_wFC",te)$( pm_data(regi,"tech_stat",te) eq 4 )
= pm_data(regi,"incolearn",te)
/ ( fm_dataglob("ccap0",te)
** pm_data(regi,"learnExp_wFC",te)
);

display p_capCum;
display pm_data;
*** -------------------------------------------------------------------------------
*** end learning parameters
Expand Down Expand Up @@ -1559,7 +1554,7 @@ pm_fedemand(tall,all_regi,in) = f_fedemand(tall,all_regi,"%cm_demScen%",in);
pm_fedemand(tall,all_regi,ppfen_no_ces_use) = f_fedemand(tall,all_regi,"%cm_demScen%",ppfen_no_ces_use);

*** RCP-dependent demands in buildings (climate impact)
$ifthen.cm_rcp_scen_build NOT "%cm_rcp_scen_build%" == "none"
$ifthen.cm_rcp_scen_build not "%cm_rcp_scen_build%" == "none"
Parameter f_fedemand_build(tall,all_regi,all_demScen,all_rcp_scen,all_in) "RCP-dependent final energy demand in buildings"
/
$ondelim
Expand Down
38 changes: 38 additions & 0 deletions core/equations.gms
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,44 @@ q_limitGeopot(t,regi,peReComp(enty),rlf)..
*' Learning curve for investment costs:
*' (deactivate learning for tech_stat 4 technologies before 2025 as they are not built before)
***---------------------------------------------------------------------------

*' Learning technologies follow a “one-factor learning curve”[^1] (or “experience curve”).
*' This widely-used formulation derives from empirical observations across different energy
*' technologies of a log-linear relationship between the unit cost $I$ of the technology and its
*' cumulative production or installed capacity $C$ (see for example empirical paper[^2]).
*' [^1]: Edward S. Rubin, Iness M.L. Azevedo, Paulina Jaramillo, and Sonia Yeh. A review of learning rates for electricity supply technologies. Energy Policy, 86:198-218, 2015.
*' [^2]: Alan McDonald and Leo Schrattenholzer. Learning rates for energy technologies. Energy Policy, 29(4):255–261, 2001.

*' Learning rate $\lambda$ is defined as the fractional reduction in cost associated with a doubling of cumulative capacity.
*' Let $I_0$ be the initial cost when cumulative capacity is $C_0$, and $I_d$ be the cost when cumulative capacity is
*' $C_d=2\times C_0$, then the learning rate is defined as:
*' $$ \lambda = 1 - \frac{I_d}{I_0} \in [0,1] $$
*' Hence \textbf{Wright's law} relating investment cost $I$ and cumulative capacity $C$:
*' $$ \frac{I}{I_0} = \left(1-\lambda \right)^{\log_2\left(\frac{C}{C_0}\right)} = \left(\frac{C}{C_0}\right)^{\log_2(1-\lambda )} $$
*' Defining the learning exponent $b = \log_2(1-\lambda)$ and the cost of the first unit $a = \frac{I_0}{C_0^b}$,
*' the learning equation simplifies into:
*' $$ I = a \times C^{b} $$

*' Now suppose there is a floor cost $F$ such that $I\geq F\geq 0$, irrespective of the capacity.
*' Then the learning only applies to learnable costs $I'=I-F$, and the learning equation becomes
*' $$ I = a'\times C^{b'} + F $$ with $a' = \frac{I_0 - F}{C_0^{b'}}$.
*' By design, REMIND learning equations ensure that the initial slope of learning is independent of the floor cost.
*' Mathematically, the slopes are given by the derivative of $I$ and $I'$ with respect to $C$:
*' $$ \frac{dI}{dC} = a \times b \times C^{b-1} = I_0 \times b \times \left(\frac{C}{C_0}\right)^{b-1} $$
*' $$ \frac{dI'}{dC} = a' \times b' \times C^{b'-1} = (I_0-F) \times b' \times \left(\frac{C}{C_0}\right)^{b'-1} $$
*' For the two curves to have the same slope initially, we want the two derivatives to be equal for $C=C_0$.
*' This means $I_0 \times b = (I_0-F) \times b'$, that we rewrite as:
*' $$ b' = \frac{I_0}{I_0-F}b $$

*' In datainput.gms, `fm_dataglob` external data provides the observed learning rate `learn` ($\lambda$),
*' the initial investment costs `inco0` ($I_0$), the learnable cost `incolearn` ($I'_0=I_0-F$) and
*' the cumulative capacity in 2015 `ccap0` ($C_0$).
*' The other learning parameters are computed using the equations described above:
*' `learnExp_wFC` ($b'$), `learnMult_wFC` ($a'$).

*' In equations.gms, the investment costs equation `q_costTeCapital` corresponds to $I = a'\times C^{b'} + F$,
*' with variations depending on time period and floor cost scenarios.

q_costTeCapital(t,regi,teLearn)$(NOT (pm_data(regi,"tech_stat",teLearn) eq 4 AND t.val le 2020)) ..
vm_costTeCapital(t,regi,teLearn)
=e=
Expand Down
4 changes: 1 addition & 3 deletions core/sets.gms
Original file line number Diff line number Diff line change
Expand Up @@ -2233,9 +2233,7 @@ char "characteristics of technologies"
tlt "techical life time"
delta "depreciation rate"
learn "learning rate"
learnMult_woFC "multiplicative parameter in learning equation (without taking into account floor costs)"
learnExp_woFC "exponent in learning equation (without taking into account floor costs)"
learnMult_wFC "multiplicative parameter in learning equation, adjusted to take floor costs into account"
learnMult_wFC "multiplicative parameter in learning equation, adjusted to take Floor Costs into account"
learnExp_wFC "exponent in learning equation, adjusted to take Floor Costs into account"
bgrl "lower bound on growth rate"
bgru "upper bound on growth rate"
Expand Down