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

Update of Hydrogen Modeling: Flexibility Tax and Electrolysis Tax #1612

Merged
merged 10 commits into from
Mar 14, 2024
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- **core** change of preference parameters and associated computation of interest rates/mark ups
- **scripts** add script to automatically check project summations from piamInterfaces
[[#1587](https://github.com/remindmodel/remind/pull/1587)]
- **32_power** extend and reparameterize flexibility tax implementation for electrolysis for hydrogen production
- **21_tax** add SE tax on electricity going into electrolysis for hydrogen production
- **scripts** add compareScenarios section for MAGICC7 AR6 output
[[#1615](https://github.com/remindmodel/remind/pull/1615)

Expand Down
3 changes: 0 additions & 3 deletions core/bounds.gms
Original file line number Diff line number Diff line change
Expand Up @@ -427,9 +427,6 @@ loop(regi,
*** Fixing will produce clearly attributable errors (good for debugging) when using inconsistent data, as the GAMS accuracy when comparing fixed results is very high (< 1e-8).
***vm_prodFe.fx("2005",regi,se2fe(enty,enty2,te)) = sum(fe2ppfEn(enty2,in), pm_cesdata("2005",regi,in,"quantity") );

vm_deltaCap.up(t,regi,"gasftrec",rlf)$(t.val gt 2005) = 0.0;
vm_deltaCap.up(t,regi,"gasftcrec",rlf)$(t.val gt 2005) = 0.0;

$ontext
*** -------------------------------------------------------------
*** *RP* Chinese depoyment of coal power plants and coal use in industry was probably not only demand-driven, but also policy-driven (faster than demand). Therefore, we implement lower bounds on coal power plants and solid coal use:
Expand Down
4 changes: 2 additions & 2 deletions core/datainput.gms
Original file line number Diff line number Diff line change
Expand Up @@ -811,9 +811,9 @@ loop(regi,

*RP* calculate annuity of a technology
p_discountedLifetime(te) = sum(opTimeYr, (sum(regi, pm_omeg(regi,opTimeYr,te))/sum(regi,1)) / 1.06**opTimeYr.val );
p_teAnnuity(te) = 1/p_discountedLifetime(te) ;
pm_teAnnuity(te) = 1/p_discountedLifetime(te) ;

display p_discountedLifetime, p_teAnnuity;
display p_discountedLifetime, pm_teAnnuity;

*** read in data on Nuclear capacities used as bound on vm_cap.fx("2015",regi,"tnrs","1"), vm_deltaCap.fx("2020",regi,"tnrs","1") and vm_deltaCap.up("2025" and "2030")
parameter pm_NuclearConstraint(ttot,all_regi,all_te) "parameter with the real-world capacities, construction and plans"
Expand Down
2 changes: 1 addition & 1 deletion core/declarations.gms
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ p_share_seh2_s(ttot,all_regi) "share of hydrogen used for
p_share_seel_s(ttot,all_regi) "Share of electricity used for stationary sector (feels). [0..1]"

p_discountedLifetime(all_te) "Sum over the discounted (@6%) depreciation factor (omega)"
p_teAnnuity(all_te) "Annuity factor of a technology"
pm_teAnnuity(all_te) "Annuity factor of a technology"

;

Expand Down
2 changes: 1 addition & 1 deletion core/sets.gms
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ all_te "all energy technologies, including from modules"
solhe "solar thermal heat generation"
tnrs "thermal nuclear reactor (simple structure)"
fnrs "fast nuclear reactor (simple structure)"
elh2 "hydrogen elecrolysis"
elh2 "hydrogen electrolysis, using grid electricity"
h2turb "hydrogen turbine for electricity production"
elh2VRE "dummy technology: hydrogen electrolysis; to demonstrate the capacities and SE flows inside the storXXX technologies"
h2turbVRE "dummy technology: hydrogen turbine for electricity production; to demonstrate the capacities and SE flows inside the storXXX technologies"
Expand Down
4 changes: 2 additions & 2 deletions main.gms
Original file line number Diff line number Diff line change
Expand Up @@ -1000,9 +1000,9 @@ parameter
cm_PriceDurSlope_elh2 "slope of price duration curve of electrolysis"
;
cm_PriceDurSlope_elh2 = 15; !! def = 15
*' cm_PriceDurSlope_elh2, slope of price duration curve for electrolysis (increase means more flexibility subsidy for electrolysis H2)
*' cm_PriceDurSlope_elh2, slope of price duration curve for electrolysis (increase means more flexibility subsidy for electrolysis H2)
*' This switch only has an effect if the flexibility tax is on by cm_flex_tax set to 1
*'
*' Default value is based on data from German Langfristszenarien (see ./modules/32_power/IntC/datainput.gms).
parameter
cm_FlexTaxFeedback "switch deciding whether flexibility tax feedback on buildlings and industry electricity prices is on"
;
Expand Down
3 changes: 3 additions & 0 deletions modules/21_tax/off/not_used.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,6 @@ vm_costInvTeDir,input,only needed if tax is on
vm_costInvTeAdj,input,only needed if tax is on
pm_cintraw,input,only needed if tax is on
pm_gdp,input,only needed if tax is on
pm_cf,input,only needed if tax is on
vm_shDemSeel,input,only needed if tax is on
pm_teAnnuity,input,only needed if tax is on
9 changes: 9 additions & 0 deletions modules/21_tax/on/declarations.gms
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ p21_bio_EF(ttot,all_regi) "bioenergy emission factor, which
p21_tau_Import(ttot,all_regi,all_enty,tax_import_type_21) "tax on energy imports, only works on energy carriers traded on nash markets, tax defined as share of world market price pm_pvp [Unit: share]"
pm_tau_pe_tax(ttot,all_regi,all_enty) "pe tax path"
pm_tau_ces_tax(ttot,all_regi,all_in) "ces production tax to implement CES mark-up cost in a budget-neutral way"
p21_tau_SE_tax(ttot,all_regi,all_te) "maximum tax rate for SE electricity tax, used for taxes on electrolysis"
p21_tau_fe_tax(ttot,all_regi,emi_sectors,all_enty) "tax path for final energy"
p21_tau_fe_sub(ttot,all_regi,emi_sectors,all_enty) "subsidy path for final energy"

Expand All @@ -39,6 +40,7 @@ p21_taxemiMkt0(ttot,all_regi,all_emiMkt) "reference level va
p21_taxrevFlex0(ttot,all_regi) "reference level value of flexibility tax"
p21_taxrevImport0(ttot,all_regi,all_enty,tax_import_type_21) "tax revenues from import tax in the previous iteration"
p21_taxrevChProdStartYear0(ttot,all_regi) "reference level value of tax to limit changes compared to reference run in cm_startyear"
p21_taxrevSE0(ttot,all_regi) "reference level value of tax on SE electricity demand"

p21_taxrevGHG_iter(iteration,ttot,all_regi) "reference level value of GHG emission tax revenue"
p21_taxrevCCS_iter(iteration,ttot,all_regi) "reference level value of CCS tax revenue"
Expand All @@ -55,6 +57,7 @@ p21_implicitDiscRate_iter(iteration,ttot,all_regi) "reference level valu
p21_taxrevFlex_iter(iteration,ttot,all_regi) "reference level value of flexibility tax revenue"
p21_taxrevImport_iter(iteration,ttot,all_regi,all_enty) "reference level value of import tax"
p21_taxrevChProdStartYear_iter(iteration,ttot,all_regi) "Difference to tax revenues in last iteration for: tax to limit changes compared to reference run in cm_startyear"
p21_taxrevSE_iter(iteration,ttot,all_regi) "Difference to tax revenues in last iteration for: tax on SE electricity demand"

p21_CO2TaxSectorMarkup(ttot,all_regi,emi_sectors) "CO2 tax markup in building, industry or transport sector"

Expand All @@ -64,6 +67,8 @@ p21_tau_CO2_tax_gdx(ttot,all_regi) "tax path from gdx, may overwrite d
p21_tau_CO2_tax_gdx_bau(ttot,all_regi) "tax path from gdx, may overwrite default values"

p21_implicitDiscRateMarg(ttot,all_regi,all_in) "Difference between the normal discount rate and the implicit discount rate"

p21_tau_SE_tax_rampup(ttot,all_regi,all_te,teSeTax_coeff) "Paramters of logistic function to describe relationship between SE electricity tax rate and share of technology in total electricity demand"
;


Expand Down Expand Up @@ -118,11 +123,13 @@ v21_implicitDiscRate(ttot,all_regi) "implicit tax on energy efficie
v21_taxemiMkt(ttot,all_regi,all_emiMkt) "tax on greenhouse gas emissions"
v21_taxrevImport(ttot,all_regi,all_enty) "net change vs. last iteration of tax revenues from energy import tax"
v21_taxrevChProdStartYear(ttot,all_regi) "tax to limit changes compared to reference run in cm_startyear"
v21_taxrevSE(ttot,all_regi) "tax on SE electricity demand, used for taxes on electrolysis"
;

Positive Variable
v21_emiALLco2neg(ttot,all_regi) "negative part of total CO2 emissions"
v21_emiALLco2neg_slack(ttot,all_regi) "dummy variable to extract negatice CO2 emissions from emiAll"
v21_tau_SE_tax(ttot,all_regi,all_te) "tax rate of tax on SE electricity demand, used for taxes on electrolysis"
;

equations
Expand All @@ -147,6 +154,8 @@ q21_implicitDiscRate(ttot,all_regi) "calculation of the implicit dis
q21_taxemiMkt(ttot,all_regi,all_emiMkt) "calculation of specific emission market tax on CO2 emissions"
q21_taxrevImport(ttot,all_regi,all_enty) "calculation of import tax"
q21_taxrevChProdStartYear(ttot,all_regi) "calculation of tax to limit changes compared to reference run in cm_startyear"
q21_taxrevSE(ttot,all_regi) "calculation of tax on SE electricity demand, used for taxes on electrolysis"
q21_SeTaxRate(ttot,all_regi,all_te) "calculation of SE tax rate, used for taxes on electrolysis"
;

$ifthen.importtaxrc "%cm_taxrc_RE%" == "REdirect"
Expand Down
50 changes: 48 additions & 2 deletions modules/21_tax/on/equations.gms
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ q21_taxrev(t,regi)$(t.val ge max(2010,cm_startyear))..
+ v21_taxrevCCS(t,regi)
+ v21_taxrevNetNegEmi(t,regi)
+ sum(entyPe, v21_taxrevPE(t,regi,entyPe))
+ v21_taxrevSE(t,regi)
+ v21_taxrevFE(t,regi)
+ sum(in, v21_taxrevCES(t,regi,in))
+ v21_taxrevResEx(t,regi)
Expand Down Expand Up @@ -122,6 +123,26 @@ q21_taxrevPE(t,regi,entyPe)$(t.val ge max(2010,cm_startyear))..
v21_taxrevPE(t,regi,entyPe) =e= pm_tau_pe_tax(t,regi,entyPe) * vm_prodPe(t,regi,entyPe)
- p21_taxrevPE0(t,regi,entyPe);


***---------------------------------------------------------------------------
*' Calculation of SE tax: tax rate times secondary energy times secondary energy demand
*' Typically, energy taxes are accounted on FE level. However, this tax is used to
*' account for taxes and grid fees for the electricity input to electrolysis, which is an SE2SE technology.
***---------------------------------------------------------------------------

q21_taxrevSE(t,regi)$( t.val ge max(2010, cm_startyear) ) ..
v21_taxrevSE(t,regi)
=e=
sum(se2se(enty,enty2,te)$(teSeTax(te)),
*** v21_tau_SE_tax is the (endogenous calculated) tax rate,
*** i.e. electricity price increase due to taxes and grid fees
v21_tau_SE_tax(t,regi,te)
* vm_demSe(t,regi,enty,enty2,te)
)
- p21_taxrevSE0(t,regi)
;


***---------------------------------------------------------------------------
*' Calculation of final Energy taxes: effective tax rate (tax - subsidy) times FE use in the specific sector
*' Documentation of overall tax approach is above at q21_taxrev.
Expand Down Expand Up @@ -253,7 +274,7 @@ q21_taxemiMkt(t,regi,emiMkt)$(t.val ge max(2010,cm_startyear))..
;

***---------------------------------------------------------------------------
*' FS: Calculation of tax/subsidy on technologies with inflexible/flexible electricity input
*' Calculation of tax/subsidy on technologies with inflexible/flexible electricity input
*' This is to emulate the effect of lower/higher electricity prices in high VRE systems on flexible/inflexible electricity demands.
***---------------------------------------------------------------------------

Expand All @@ -272,7 +293,7 @@ q21_taxrevFlex(t,regi)$( t.val ge max(2010, cm_startyear) ) ..


***---------------------------------------------------------------------------
*' FS: (PE) import tax
*' (PE) import tax
*' can be used to place taxes on PE energy imports
*' e.g. bioenergy import taxes due to sustainability concerns by importers
***---------------------------------------------------------------------------
Expand Down Expand Up @@ -342,5 +363,30 @@ q21_taxrevChProdStartYear(t,regi)$(t.val ge max(2010,cm_startyear))..
;


*' This calculates the SE tax rate for electricity going into electrolysis.
*' It contains the final energy tax rate for electricity use in industry and
*' grid fees that are assumed be equal to the investment cost of tdfels.
*' We furthermore assume that these taxes and fees are small at low shares
*' of electrolysis in total electricity demand as electrolysis has power system
*' benefits at low shares. The tax rate increases with increasing share of electrolysis
*' following a logistic curve. It starts at close to zero tax rate for a share o 0%, reaches half
*' of the full tax rate at 10% share and is within 1% of the full tax rate above a 25% share of
*' electrolysis electricity demand within total electricity demand. The parameters
*' to define this functional relationsship are set to in the preloop file.
q21_SeTaxRate(t,regi,te)$(teSeTax(te))..
v21_tau_SE_tax(t,regi,te)
=e=
*** maximum electrolysis SE tax rate
p21_tau_SE_tax(t,regi,te)
*** logistic ramp-up function depending on electrolysis share in total electricity demand vm_shDemSeel
/ ( 1 +
(exp(-p21_tau_SE_tax_rampup(t,regi,te,"a")
* (vm_shDemSeel(t,regi,te) * 100
- p21_tau_SE_tax_rampup(t,regi,te,"b"))
)
)
)
;


*** EOF ./modules/21_tax/on/equations.gms
5 changes: 5 additions & 0 deletions modules/21_tax/on/postsolve.gms
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ p21_taxrevImport0(ttot,regi,tradePe,tax_import_type_21) = p21_tau_Import(ttot,r


p21_taxrevChProdStartYear0(t,regi) = sum(en2en(enty,enty2,te), vm_changeProdStartyearCost.l(t,regi,te)$( (t.val gt 2005) AND (t.val eq cm_startyear ) ) );
p21_taxrevSE0(t,regi) = sum(se2se(enty,enty2,te)$(teSeTax(te)),
v21_tau_SE_tax.l(t,regi,te)
* vm_demSe.l(t,regi,enty,enty2,te));


*** Save reference level of tax revenues for each iteration
p21_taxrevGHG_iter(iteration+1,ttot,regi) = v21_taxrevGHG.l(ttot,regi);
Expand All @@ -75,6 +79,7 @@ p21_implicitDiscRate_iter(iteration+1,ttot,regi) = v21_implicitDiscRate.l(ttot,r
p21_taxrevFlex_iter(iteration+1,ttot,regi) = v21_taxrevFlex.l(ttot,regi);
p21_taxrevImport_iter(iteration+1,ttot,regi,tradePe) = v21_taxrevImport.l(ttot,regi,tradePe);
p21_taxrevChProdStartYear_iter(iteration+1,t,regi) = v21_taxrevChProdStartYear.l(t,regi);
p21_taxrevSE_iter(iteration+1,t,regi) = v21_taxrevSE.l(t,regi);

display p21_taxrevFE_iter;

Expand Down
21 changes: 21 additions & 0 deletions modules/21_tax/on/preloop.gms
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,24 @@ display p21_tau_fe_sub;
display p21_tau_fe_tax;
display p21_tau_pe2se_sub, p21_tau_fuEx_sub;

*** SE Tax
*** SE tax is currently used to tax electricity going into electrolysis. There is a maximum tax rate that is assumed
*** to be the sum of the industry electricity FE tax and the investment cost per unit electricity of the grid (grid fee).
*** There is a ramp up of the SE electricity tax for electrolysis depending on the share of electrolysis in total electricity demand
*** described by a logistic function. This results in low taxes for electrolysis at low shares of electrolysis in the power system
*** as the technology has system benefits in this domain. At higher shares this rapidly increases and converges towards the maximum tax rate.
*** See the equations file of the tax module for more information on the SE tax.
*** Parameter datainput needs to happen here because pm_tau_fe_tax, the final energy tax rate, is set in this file and not in the datainput file.
p21_tau_SE_tax(t,regi,"elh2") = p21_tau_fe_tax(t,regi,"indst","feels")
*** calculate grid fees as levelized cost of CAPEX from tdels, the electricity transmission and distribution grid
*** by annualising the CAPEX and dividing by the capacity factor
+ pm_inco0_t(t,regi,"tdels")
* pm_teAnnuity("tdels")
/ pm_cf(t,regi,"tdels");

p21_tau_SE_tax_rampup(t,regi,te,"a") = 0.4;
p21_tau_SE_tax_rampup(t,regi,te,"b") = 10;

*LB* initialization of vm_emiMac
vm_emiMac.l(ttot,regi,enty) = 0;
*LB* initialization of v21_emiALLco2neg
Expand All @@ -159,4 +177,7 @@ v21_taxrevImport.l(t,regi,tradePe) = 0;
*** initialize taxrevImport
v21_taxrevChProdStartYear.l(t,regi) = 0;

*** initialize SE tax rate
v21_tau_SE_tax.l(t,regi,te)=0;

*** EOF ./modules/21_tax/on/preloop.gms
3 changes: 3 additions & 0 deletions modules/21_tax/on/presolve.gms
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,8 @@ p21_taxrevImport0(ttot,regi,tradePe,tax_import_type_21) = p21_tau_Import(ttot,r
p21_tau_Import(ttot, regi, tradePe, tax_import_type_21)$sameas(tax_import_type_21, "avCO2taxmarkup") * max(pm_taxCO2eqSum(ttot,regi), sum(regi2, pm_taxCO2eqSum(ttot,regi2))/(card(regi2))) * pm_cintraw(tradePe) * vm_Mport.l(ttot,regi,tradePe);

p21_taxrevChProdStartYear0(t,regi) = sum(en2en(enty,enty2,te), vm_changeProdStartyearCost.l(t,regi,te)$( (t.val gt 2005) AND (t.val eq cm_startyear ) ) );
p21_taxrevSE0(t,regi) = sum(se2se(enty,enty2,te)$(teSeTax(te)),
v21_tau_SE_tax.l(t,regi,te)
* vm_demSe.l(t,regi,enty,enty2,te));

*** EOF ./modules/21_tax/on/presolve.gms
13 changes: 13 additions & 0 deletions modules/21_tax/on/sets.gms
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,19 @@ $else.regi_bio_EFTax
set regi_bio_EFTax21(all_regi) "regions in which an emission-factor-based bioenergy tax is active" / %cm_regi_bioenergy_EFTax% /;
$endif.regi_bio_EFTax

Sets
teSeTax(all_te) "all technologies which SE electricity demand tax"
/
elh2
/

teSeTax_coeff "coefficients of logistic function to describe relationsship between SE tax rate and share of technology in total SE demand"
/
"a"
"b"
/
;

*** EOF ./modules/21_tax/on/sets.gms

*** Module specific set
Expand Down
1 change: 1 addition & 0 deletions modules/32_power/DTcoup/not_used.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ cm_emiscen,input,questionnaire
cm_ccapturescen,input,questionnaire
pm_boundCapCCS,input,questionnaire
pm_cap0,input,questionnaire
vm_shDemSeel,input,only used in IntC realization
8 changes: 5 additions & 3 deletions modules/32_power/IntC/bounds.gms
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ if ( cm_flex_tax eq 1,
vm_capFac.lo(t,regi,teFlexTax)$(t.val ge 2010) = 0.1;
vm_capFac.up(t,regi,teFlexTax)$(t.val ge 2010) = pm_cf(t,regi,teFlexTax);
else
*** if flexibility tax feedback is off, only flexibliity tax benefit for flexible technologies and 0.5 capacity factor
vm_capFac.fx(t,regi,teFlex)$(t.val ge 2010) = 0.5;
*** electricity price of inflexible technologies the same w/o feedback
*** if flexibility tax feedback is off, flexibility tax benefit only for flexible technologies and capacity factors fixed.
*** Assume capacity factor of flexible electrolysis to be 0.38.
*** The value based on data from German Langfristszenarien (see flexibility tax section in datainput file).
vm_capFac.fx(t,regi,"elh2")$(t.val ge 2010) = 0.38;
*** electricity price of inflexible technologies the same as w/o feedback
v32_flexPriceShare.fx(t,regi,te)$(teFlexTax(te) AND NOT(teFlex(te))) = 1;
);
);
Expand Down
13 changes: 12 additions & 1 deletion modules/32_power/IntC/datainput.gms
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,18 @@ p32_flex_maxdiscount(regi,te) = p32_flex_maxdiscount(regi,te) * sm_TWa_2_MWh * s
display p32_flex_maxdiscount;
$offtext

*** initialize p32_PriceDurSlope parameter
*** Flexibility Tax Parameter

*** Both flexibility tax parameters are based on a regression analysis with hourly dispatch data from high-VRE scenarios of the Langfristszenarien
*** for Germany provided by the Enertile power system model.
*** See: https://langfristszenarien.de/enertile-explorer-de/szenario-explorer/angebot.php

*** This parameter determines by the maximum electricity price reduction for electrolysis at 100% VRE share and 0% share of electrolysis in total electricity demand.
*** Standard value is derived based on the regression of the German Langfristzenarien.
p32_PriceDurSlope(regi,"elh2") = cm_PriceDurSlope_elh2;

*** Slope of increase of electricity price for electrolysis with increasing share of electrolysis in power system
*** The value of 1.1 is derived from the regression of the German Langfristzenarien.
p32_flexSeelShare_slope(t,regi,"elh2") = 1.1;

*** EOF ./modules/32_power/IntC/datainput.gms
Loading
Loading