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

Remove the splitting of deltacap to two time steps #1238

Merged
Merged
Show file tree
Hide file tree
Changes from 10 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
7 changes: 7 additions & 0 deletions core/bounds.gms
Original file line number Diff line number Diff line change
Expand Up @@ -519,5 +519,12 @@ $IFTHEN.transpGDPscale not "%cm_transpGDPscale%" == "on"
vm_transpGDPscale.fx(t,regi) = 1;
$ENDIF.transpGDPscale

***----------------------------------------------------------------------------
*' Limit slack variable and uncontrolled variable values for adj costs that limit changes to reference in cm_startyear
***----------------------------------------------------------------------------

v_changeProdStartyearSlack.up(t,regi,te)$( (t.val gt 2005) AND (t.val eq cm_startyear ) ) = + c_SlackMultiplier * p_adj_seed_reg(t,regi) * p_adj_seed_te(t,regi,te) ;
v_changeProdStartyearSlack.lo(t,regi,te)$( (t.val gt 2005) AND (t.val eq cm_startyear ) ) = - c_SlackMultiplier * p_adj_seed_reg(t,regi) * p_adj_seed_te(t,regi,te) ;


*** EOF ./core/bounds.gms
19 changes: 19 additions & 0 deletions core/datainput.gms
Original file line number Diff line number Diff line change
Expand Up @@ -1534,5 +1534,24 @@ $endif.cm_rcp_scen_build
*** initialize global target deviation scalar
sm_globalBudget_dev = 1;

*' load production values from reference gdx to allow penalizing changes vs reference run in the first time step via q_changeProdStartyearCost/q21_taxrevChProdStartYear
if (cm_startyear gt 2005,
execute_load "input_ref.gdx", p_prodSeReference = vm_prodSe.l;
execute_load "input_ref.gdx", p_prodFEReference = vm_prodFE.l;
execute_load "input_ref.gdx", p_prodUeReference = vm_prodUe.l;
execute_load "input_ref.gdx", p_co2CCSReference = vm_co2CCS.l;
);

p_prodAllReference(t,regi,te) =
sum(pe2se(enty,enty2,te), p_prodSeReference(t,regi,enty,enty2,te) )
+ sum(se2se(enty,enty2,te), p_prodSeReference(t,regi,enty,enty2,te) )
+ sum(se2fe(enty,enty2,te), p_prodFEReference(t,regi,enty,enty2,te) )
+ sum(fe2ue(enty,enty2,te), p_prodUeReference(t,regi,enty,enty2,te) )
+ sum(ccs2te(enty,enty2,te), sum(teCCS2rlf(te,rlf), p_co2CCSReference(t,regi,enty,enty2,te,rlf) ) )
;

*' initialize vm_changeProdStartyearCost for tax calculation
vm_changeProdStartyearCost.l(t,regi,te) = 0;

*** EOF ./core/datainput.gms

20 changes: 19 additions & 1 deletion core/declarations.gms
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,14 @@ pm_share_CCS_CCO2(ttot,all_regi) "share of stored CO2 from

pm_delta_histCap(tall,all_regi,all_te) "parameter to store data of historic capacity additions [TW/yr]"

p_prodSeReference(ttot,all_regi,all_enty,all_enty,all_te) "read from gdx the output value in the reference run"
robertpietzcker marked this conversation as resolved.
Show resolved Hide resolved
p_prodFEReference(ttot,all_regi,all_enty,all_enty,all_te) "read from gdx the output value in the reference run"
p_prodUeReference(ttot,all_regi,all_enty,all_enty,all_te) "read from gdx the output value in the reference run"
p_co2CCSReference(ttot,all_regi,all_enty,all_enty,all_te,rlf) "read from gdx the output value in the reference run"
p_prodAllReference(ttot,all_regi,all_te) "read from gdx the output value in the reference run"



* Energy carrier Prices
pm_FEPrice(ttot,all_regi,all_enty,sector,emiMkt) "parameter to capture all FE prices across sectors and markets (tr$2005/TWa)"
pm_FEPrice_iter(iteration,ttot,all_regi,all_enty,sector,emiMkt) "parameter to capture all FE prices across sectors and markets (tr$2005/TWa) across iterations"
Expand Down Expand Up @@ -354,7 +362,9 @@ vm_costCESMkup(ttot,all_regi,all_in) "CES markup cost to repres
vm_taxrevimplicitQttyTargetTax(ttot,all_regi) "quantity target bound implemented through implict tax"
vm_taxrevimplicitPriceTax(ttot,all_regi,entySe,all_enty,sector) "final energy price target implemented through implict tax"
vm_taxrevimplicitPePriceTax(ttot,all_regi,all_enty) "primary energy price target implemented through implict tax"

v_changeProdStartyear(ttot,all_regi,all_te) "absolute change of output with respect to the reference run for each te"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you add the units for these variables in between brackets?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

v_relChangeProdStartYear(ttot,all_regi,all_te) "calculating the relative change of output with respect to the reference run for each te"
v_changeProdStartyearSlack(ttot,all_regi,all_te) "slack variable to allow a minimum cost-free change with respect to the reference run"
;

***----------------------------------------------------------------------------------------
Expand Down Expand Up @@ -414,6 +424,9 @@ v_shGasLiq_fe(ttot,all_regi,emi_sectors) "share of gases and liquids

vm_emiCdrAll(ttot,all_regi) "all CDR emissions"

v_changeProdStartyearAdj(ttot,all_regi,all_te) "Absolute effect size of changing output with respect to the reference run for each te"
vm_changeProdStartyearCost(ttot,all_regi,all_te) "Costs for changing output with respect to the reference run for each te"

*** ES layer variables
vm_demFeForEs(ttot,all_regi,all_enty,all_esty,all_teEs) "Final energy which will be used in the ES layer."

Expand Down Expand Up @@ -507,6 +520,11 @@ q_costInvTeAdj(ttot,all_regi,all_te) "calculation of total adju
q_costInvTeDir(ttot,all_regi,all_te) "calculation of total direct investment costs (without adjustment costs) for a technology"
q_eqadj(all_regi,tall,all_te) "calculation of adjustment factor for a technology"

q_changeProdStartyear(ttot,all_regi,all_te) "calculating the absolute change of output with respect to the reference run for each te"
q_relChangeProdStartYear(ttot,all_regi,all_te) "calculating the relative change"
q_changeProdStartyearAdj(ttot,all_regi,all_te) "calculating the absolute effect size"
q_changeProdStartyearCost(ttot,all_regi,all_te) "calculating the resulting costs"

q_limitCapEarlyReti(ttot,all_regi,all_te) "constraint to avoid reactivation of retired capacities"
q_smoothphaseoutCapEarlyReti(ttot,all_regi,all_te) "phase-out constraint for early retirement to avoid immediate retirement"
q_limitBiotrmod(ttot,all_regi) "limit the total amount of modern biomass use for solids to the amount of coal use for solids "
Expand Down
148 changes: 100 additions & 48 deletions core/equations.gms
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,12 @@ q_costInv(t,regi)..
q_costInvTeDir(t,regi,te)..
v_costInvTeDir(t,regi,te)
=e=
vm_costTeCapital(t,regi,te) * sum(te2rlf(te,rlf), vm_deltaCap(t,regi,te,rlf) )
vm_costTeCapital(t,regi,te)
* sum(te2rlf(te,rlf), vm_deltaCap(t,regi,te,rlf))
* (1.02 + pm_prtp(regi) ** (pm_ts(t) / 2) !! This increases the investments as if the money was actually borrowed
!! half a time step earlier, using an interest rate of pm_prtp + 2%, which is close to the model-endogenous interest rate.
!! We do this to reduce the difference to the previous version where the effect of deltacap on capacity was split
!! half to the current and half to the next time.
;


Expand All @@ -66,7 +71,13 @@ v_adjFactorGlob.fx(t,regi,te) = 0;
q_costInvTeAdj(t,regi,teAdj)..
v_costInvTeAdj(t,regi,teAdj)
=e=
vm_costTeCapital(t,regi,teAdj) * ( (p_adj_coeff(t,regi,teAdj) * v_adjFactor(t,regi,teAdj)) + (p_adj_coeff_glob(teAdj) * v_adjFactorGlob(t,regi,teAdj) ) )
vm_costTeCapital(t,regi,teAdj) * (
(p_adj_coeff(t,regi,teAdj) * v_adjFactor(t,regi,teAdj)) + (p_adj_coeff_glob(teAdj) * v_adjFactorGlob(t,regi,teAdj))
)
* (1.02 + pm_prtp(regi) ** (pm_ts(t) / 2) !! This increases the investments as if the money was actually borrowed
!! half a time step earlier, using an interest rate of pm_prtp + 2%, which is close to the model-endogenous interest rate.
!! We do this to reduce the difference to the previous version where the effect of deltacap on capacity was split
!! half to the current and half to the next time.
;

***---------------------------------------------------------------------------
Expand Down Expand Up @@ -159,29 +170,24 @@ q_balSe(t,regi,enty2)$( entySE(enty2) AND (NOT (sameas(enty2,"seel"))) )..
***---------------------------------------------------------------------------
*MLB 05/2008* correction factor included to avoid pre-triangular infeasibility
q_transPe2se(ttot,regi,pe2se(enty,enty2,te))$(ttot.val ge cm_startyear)..
vm_demPe(ttot,regi,enty,enty2,te)
=e=
(1 / pm_eta_conv(ttot,regi,te) * vm_prodSe(ttot,regi,enty,enty2,te))$teEtaConst(te)
+
vm_demPe(ttot,regi,enty,enty2,te)
=e=
(1 / pm_eta_conv(ttot,regi,te) * vm_prodSe(ttot,regi,enty,enty2,te))$teEtaConst(te)
+
***cb early retirement for some fossil technologies
(1 - vm_capEarlyReti(ttot,regi,te))
*

sum(teSe2rlf(teEtaIncr(te),rlf),
vm_capFac(ttot,regi,te)
* (
sum(opTimeYr2te(te,opTimeYr)$(tsu2opTimeYr(ttot,opTimeYr) AND (opTimeYr.val gt 1) ),
pm_ts(ttot-(pm_tsu2opTimeYr(ttot,opTimeYr)-1))
/ pm_dataeta(ttot-(pm_tsu2opTimeYr(ttot,opTimeYr)-1),regi,te)
(1 - vm_capEarlyReti(ttot,regi,te))
*
sum(teSe2rlf(teEtaIncr(te),rlf),
vm_capFac(ttot,regi,te)
* (
sum(opTimeYr2te(te,opTimeYr)$(tsu2opTimeYr(ttot,opTimeYr) AND (opTimeYr.val ge 1)),
pm_ts(ttot-(pm_tsu2opTimeYr(ttot,opTimeYr)-1))
/ pm_dataeta(ttot-(pm_tsu2opTimeYr(ttot,opTimeYr)-1),regi,te)
* pm_omeg(regi,opTimeYr+1,te)
* vm_deltaCap(ttot-(pm_tsu2opTimeYr(ttot,opTimeYr)-1),regi,te,rlf)
)
*LB* add half of the last time step ttot
+ pm_dt(ttot)/2 / pm_dataeta(ttot,regi,te)
* pm_omeg(regi,"2",te)
* vm_deltaCap(ttot,regi,te,rlf)
* vm_deltaCap(ttot-(pm_tsu2opTimeYr(ttot,opTimeYr)-1),regi,te,rlf)
)
);
)
);

***---------------------------------------------------------------------------
*' Transformation from secondary to final energy:
Expand Down Expand Up @@ -300,25 +306,22 @@ q_limitCapCCS(t,regi,ccs2te(enty,enty2,te),rlf)$teCCS2rlf(te,rlf)..
***-----------------------------------------------------------------------------

q_cap(ttot,regi,te2rlf(te,rlf))$(ttot.val ge cm_startyear)..
vm_cap(ttot,regi,te,rlf)
=e=
!! early retirement for some fossil technologies
(1 - vm_capEarlyReti(ttot,regi,te))
*

(sum(opTimeYr2te(te,opTimeYr)$(tsu2opTimeYr(ttot,opTimeYr) AND (opTimeYr.val gt 1) ),
pm_ts(ttot-(pm_tsu2opTimeYr(ttot,opTimeYr)-1))
* pm_omeg(regi,opTimeYr+1,te)
* vm_deltaCap(ttot-(pm_tsu2opTimeYr(ttot,opTimeYr)-1),regi,te,rlf)
)
!! half of the last time step ttot
+ ( pm_dt(ttot) / 2
* pm_omeg(regi,"2",te)
* vm_deltaCap(ttot,regi,te,rlf)
)
)
vm_cap(ttot,regi,te,rlf)
=e=
!! early retirement for some fossil technologies
(1 - vm_capEarlyReti(ttot,regi,te))
* (
sum(opTimeYr2te(te,opTimeYr)$(tsu2opTimeYr(ttot,opTimeYr) AND (opTimeYr.val ge 1)),
pm_ts(ttot-(pm_tsu2opTimeYr(ttot,opTimeYr)-1))
* pm_omeg(regi,opTimeYr+1,te)
* vm_deltaCap(ttot-(pm_tsu2opTimeYr(ttot,opTimeYr)-1),regi,te,rlf)
)

)
;



q_capDistr(t,regi,teReNoBio(te))..
sum(teRe2rlfDetail(te,rlf), vm_capDistr(t,regi,te,rlf) )
=e=
Expand Down Expand Up @@ -838,16 +841,65 @@ q_limitCO2(ttot+1,regi) $((pm_ttot_val(ttot+1) ge max(cm_startyear,2055)) AND (t
=l=
vm_emiTe(ttot,regi,"co2");

***---------------------------------------------------------------------------
*' Adjustment costs - calculation of the relative change to last time step
***---------------------------------------------------------------------------

q_eqadj(regi,ttot,teAdj(te))$(ttot.val ge max(2010, cm_startyear)) ..
v_adjFactor(ttot,regi,te)
=e=
power(
(sum(te2rlf(te,rlf),vm_deltaCap(ttot,regi,te,rlf)) - sum(te2rlf(te,rlf),vm_deltaCap(ttot-1,regi,te,rlf)))/(pm_ttot_val(ttot)-pm_ttot_val(ttot-1))
,2)
/( sum(te2rlf(te,rlf),vm_deltaCap(ttot-1,regi,te,rlf)) + p_adj_seed_reg(ttot,regi) * p_adj_seed_te(ttot,regi,te)
+ p_adj_deltacapoffset("2010",regi,te)$(ttot.val eq 2010) + p_adj_deltacapoffset("2015",regi,te)$(ttot.val eq 2015)
+ p_adj_deltacapoffset("2020",regi,te)$(ttot.val eq 2020) + p_adj_deltacapoffset("2025",regi,te)$(ttot.val eq 2025)
);
v_adjFactor(ttot,regi,te)
=e=
power(
( sum(te2rlf(te,rlf), vm_deltaCap(ttot,regi,te,rlf)) - sum(te2rlf(te,rlf), vm_deltaCap(ttot-1,regi,te,rlf)) )
/ ( pm_ttot_val(ttot) - pm_ttot_val(ttot-1) )
, 2)
/ ( sum(te2rlf(te,rlf), vm_deltaCap(ttot-1,regi,te,rlf)) + p_adj_seed_reg(ttot,regi) * p_adj_seed_te(ttot,regi,te)
+ p_adj_deltacapoffset("2010",regi,te)$(ttot.val eq 2010) + p_adj_deltacapoffset("2015",regi,te)$(ttot.val eq 2015)
+ p_adj_deltacapoffset("2020",regi,te)$(ttot.val eq 2020) + p_adj_deltacapoffset("2025",regi,te)$(ttot.val eq 2025)
)
;

***---------------------------------------------------------------------------
*' Calculate changes to reference in cm_startyear - needed to limit them via refunded adj costs
***---------------------------------------------------------------------------
*' calculating the absolute change of output with respect to the value in reference for each te (counting SE, FE, UE and CCS)
q_changeProdStartyear(t,regi,te)$( (t.val gt 2005) AND (t.val eq cm_startyear ) )..
v_changeProdStartyear(t,regi,te)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is very minor, but as by default you only want to define v_changeProdStartyear to a single year always, you could remove the time dimension from the variable and equation, and use a sum to control the time dimension in vm_prodSe, vm_prodFE, ...
It wouldn't change in any way the way your formulation works, but it would reduce unnecessary dimensions from memory allocation and gdx files.
This is very minor in this case, but I just wanted to mention to keep in mind for alternative formulations in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right. I didn't think about this but just automatically added the time dimension (while trying to make sure that only one entry will ever be filled in a run), but you are right - especially if one loads other gdxes from runs fixed until other times, there might be residual information carried over in the gdx, which would be confusing...

I will check if I can remove the time dimension today

=e=
sum(pe2se(enty,enty2,te), vm_prodSe(t,regi,enty,enty2,te) - p_prodSeReference(t,regi,enty,enty2,te) )
+ sum(se2se(enty,enty2,te), vm_prodSe(t,regi,enty,enty2,te) - p_prodSeReference(t,regi,enty,enty2,te) )
+ sum(se2fe(enty,enty2,te), vm_prodFE(t,regi,enty,enty2,te) - p_prodFEReference(t,regi,enty,enty2,te) )
+ sum(fe2ue(enty,enty2,te), vm_prodUe(t,regi,enty,enty2,te) - p_prodUeReference(t,regi,enty,enty2,te) )
+ sum(ccs2te(enty,enty2,te), sum(teCCS2rlf(te,rlf), vm_co2CCS(t,regi,enty,enty2,te,rlf) - p_co2CCSReference(t,regi,enty,enty2,te,rlf) ) )
;

*' calculating the relative change
q_relChangeProdStartYear(t,regi,te)$( (t.val gt 2005) AND (t.val eq cm_startyear ) )..
Renato-Rodrigues marked this conversation as resolved.
Show resolved Hide resolved
v_relChangeProdStartYear(t,regi,te)
*
( p_prodAllReference(t,regi,te)
+ p_adj_seed_reg(t,regi) * p_adj_seed_te(t,regi,te) !! taking into account the region and technology-specific seed values
)
=e=
( v_changeProdStartyear(t,regi,te) - v_changeProdStartyearSlack(t,regi,te) ) !! always allow some change (depending on .up / .lo of the slack variable)
;

*' calculating the absolute effect size: (relative change)^2 * value in the reference run * construction time (as proxy for "how easy to change on short notice")
q_changeProdStartyearAdj(t,regi,te)$( (t.val gt 2005) AND (t.val eq cm_startyear ) )..
v_changeProdStartyearAdj(t,regi,te)
=e=
power( v_relChangeProdStartYear(t,regi,te), 2 ) !! taking the square to a) treat increase and decrease the same; b) to penalize larger changes
* ( p_prodAllReference(t,regi,te) + p_adj_seed_reg(t,regi) * p_adj_seed_te(t,regi,te) ) !! tie back to the absolute change
* ( pm_data(regi,"constrTme",te)$(pm_data(regi,"constrTme",te) gt 0) + 2$(pm_data(regi,"constrTme",te) eq 0)) !! take construction time
;

*' calculating the resulting costs (which are applied as a tax in module 21, so they have no budget effect but only incluence REMIND choices)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
*' calculating the resulting costs (which are applied as a tax in module 21, so they have no budget effect but only incluence REMIND choices)
*' calculating the resulting costs (which are applied as a tax in module 21, so they have no budget effect but only influence REMIND choices)

q_changeProdStartyearCost(t,regi,te)$( (t.val gt 2005) AND (t.val eq cm_startyear ) ) ..
vm_changeProdStartyearCost(t,regi,te)
=e=
c_changeProdCost * sm_DpGJ_2_TDpTWa
* p_adj_coeff(t,regi,te)
* v_changeProdStartyearAdj(t,regi,te)
;

***---------------------------------------------------------------------------
*' The use of early retirement is restricted by the following equations:
Expand Down
10 changes: 10 additions & 0 deletions main.gms
Original file line number Diff line number Diff line change
Expand Up @@ -1095,6 +1095,16 @@ parameter
*' * (0) default, equals "off", no limit imposed
*' * (any other number) limit of gas demand from 2025 on in Germany in EJ/yr
*'
parameter
c_SlackMultiplier "sets the slack size for v_changeProdStartyearSlack"
;
c_SlackMultiplier = 1; !! def 1
*'
parameter
c_changeProdCost "sets the cost for vm_changeProdStartyearCost"
;
c_changeProdCost = 5; !! def 5
*'
***-----------------------------------------------------------------------------
*' #### FLAGS
***-----------------------------------------------------------------------------
Expand Down
Loading