diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cd9ee1e87..9349c6c1ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -111,7 +111,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - **scripts** enhance output script `reportCEScalib` to include additional plot formats [[#1671](https://github.com/remindmodel/remind/pull/1671)] ### added -- **24_trade** add optinal trade scenario for EUR hydrogen and e-liquids imports [[#1666](https://github.com/remindmodel/remind/pull/1666)] +- **24_trade** add optional trade scenario for EUR hydrogen and e-liquids imports [[#1666](https://github.com/remindmodel/remind/pull/1666)] +- **24_trade** add optional trade scenario for EUR bio-fuels imports [[#1678](https://github.com/remindmodel/remind/pull/1678)] +- **47_regipol** add support for scenario based regional emission targets and add net-zero pledges scenario [[#1674](https://github.com/remindmodel/remind/pull/1674)] +- **47_regipol** add support for loading exogenous CO2 price from the input gdx [[#1698](https://github.com/remindmodel/remind/pull/1698)] ## [3.3.0] - 2024-03-28 diff --git a/core/presolve.gms b/core/presolve.gms index 38954ad664..e9b76671cd 100644 --- a/core/presolve.gms +++ b/core/presolve.gms @@ -124,21 +124,19 @@ loop((enty,enty2)$emiMac2mac(enty,enty2), !! make sure that both mac sectors and ); *** Redefine the MAC price for regions with emission tax defined by the regipol module -$IFTHEN.emiMkt not "%cm_emiMktTarget%" == "off" - loop(ext_regi$regiEmiMktTarget(ext_regi), - loop(regi$regi_groupExt(ext_regi,regi), +$IFTHEN.emiMkt not "%regipol%" == "none" + loop(regi$regiNativeEmiMktTarget(regi), *** average CO2 price aggregated by FE - p_priceCO2(t,regi) = ( (sum(emiMkt, pm_taxemiMkt(t,regi,emiMkt) * sum((entySe,entyFe,sector)$(sefe(entySe,entyFe) AND entyFe2Sector(entyFe,sector) AND sector2emiMkt(sector,emiMkt)),vm_demFeSector.l(t,regi,entySe,entyFe,sector,emiMkt)))) / (sum((entySe,entyFe,sector,emiMkt)$(sefe(entySe,entyFe) AND entyFe2Sector(entyFe,sector) AND sector2emiMkt(sector,emiMkt)),vm_demFeSector.l(t,regi,entySe,entyFe,sector,emiMkt))) )*1000; - loop((enty,emiMkt)$(macSector2emiMkt(enty,emiMkt)), - loop(enty2$emiMac2mac(enty,enty2), !! make sure that both mac sectors and mac curves have prices asigned as both sets are used in calculations below - pm_priceCO2forMAC(t,regi,enty) = pm_taxemiMkt(t,regi,emiMkt)* 1000; - pm_priceCO2forMAC(t,regi,enty2) = pm_taxemiMkt(t,regi,emiMkt)* 1000; - pm_priceCO2forMAC(t,regi,"co2chemicals") = pm_taxemiMkt(t,regi,"ETS")* 1000; - pm_priceCO2forMAC(t,regi,"co2steel") = pm_taxemiMkt(t,regi,"ETS")* 1000; - ); + p_priceCO2(t,regi) = ( (sum(emiMkt, pm_taxemiMkt(t,regi,emiMkt) * sum((entySe,entyFe,sector)$(sefe(entySe,entyFe) AND entyFe2Sector(entyFe,sector) AND sector2emiMkt(sector,emiMkt)),vm_demFeSector.l(t,regi,entySe,entyFe,sector,emiMkt)))) / (sum((entySe,entyFe,sector,emiMkt)$(sefe(entySe,entyFe) AND entyFe2Sector(entyFe,sector) AND sector2emiMkt(sector,emiMkt)),vm_demFeSector.l(t,regi,entySe,entyFe,sector,emiMkt))) )*1000; + loop((enty,emiMkt)$(macSector2emiMkt(enty,emiMkt)), + loop(enty2$emiMac2mac(enty,enty2), !! make sure that both mac sectors and mac curves have prices asigned as both sets are used in calculations below + pm_priceCO2forMAC(t,regi,enty) = pm_taxemiMkt(t,regi,emiMkt)* 1000; + pm_priceCO2forMAC(t,regi,enty2) = pm_taxemiMkt(t,regi,emiMkt)* 1000; + pm_priceCO2forMAC(t,regi,"co2chemicals") = pm_taxemiMkt(t,regi,"ETS")* 1000; + pm_priceCO2forMAC(t,regi,"co2steel") = pm_taxemiMkt(t,regi,"ETS")* 1000; ); ); - ); +); $ENDIF.emiMkt *** The co2 price for land-use entities needs to be reduced by the same factor as in MAgPIE. diff --git a/main.gms b/main.gms index 77e381b793..c8521fa2d5 100755 --- a/main.gms +++ b/main.gms @@ -1319,7 +1319,11 @@ $setglobal c_ccsinjecrateRegi off !! def = "off" *** ("forcing_SSP2") settings consistent with SSP 2 *** ("forcing_SSP5") settings consistent with SSP 5 $setglobal c_SSP_forcing_adjust forcing_SSP2 !! def = forcing_SSP2 !! regexp = forcing_SSP(1|2|3|5) -*** cm_regiExoPrice "set exogenous co2 tax path for specific regions using a switch, require regipol module to be set to regiCarbonPrice (e.g. GLO.(2025 38,2030 49,2035 63,2040 80,2045 102,2050 130,2055 166,2060 212,2070 346,2080 563,2090 917,2100 1494,2110 1494,2130 1494,2150 1494) )" +*** cm_regiExoPrice "set exogenous co2 tax path for specific regions using a switch or load the values from the input gdx. This feature requires regipol module to be set to regiCarbonPrice. +*** ("gdx") CO2 prices will be exogenously fixed to the values found in the input gdx, both for pm_taxCO2eq and pm_taxemiMkt parameters. +*** (". , . " or ".( , ") CO2 prices will be exogenously defined +*** only for the regions, periods and values defined in the switch cm_regiExoPrice +*** e.g. "GLO.(2025 38,2030 49,2035 63,2040 80,2045 102,2050 130,2055 166,2060 212,2070 346,2080 563,2090 917,2100 1494,2110 1494,2130 1494,2150 1494)" $setGlobal cm_regiExoPrice off !! def = off *** cm_emiMktTarget "set a budget or year emission target, for all (all) or specific emission markets (ETS, ESD or other), and specific regions (e.g. DEU) or region groups (e.g. EU27)" *** Example on how to use: diff --git a/modules/21_tax/off/not_used.txt b/modules/21_tax/off/not_used.txt index d50474410d..69d7f4d402 100644 --- a/modules/21_tax/off/not_used.txt +++ b/modules/21_tax/off/not_used.txt @@ -71,4 +71,5 @@ 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 +pm_tau_CO2_tax_gdx,input,questionnaire sm_D2005_2_D2017,input,no conversion needed diff --git a/modules/21_tax/on/declarations.gms b/modules/21_tax/on/declarations.gms index c26eac3bf8..44ea445fc1 100644 --- a/modules/21_tax/on/declarations.gms +++ b/modules/21_tax/on/declarations.gms @@ -60,7 +60,7 @@ p21_CO2TaxSectorMarkup(ttot,all_regi,emi_sectors) "CO2 tax markup in bu p21_deltarev(iteration,all_regi) "convergence criteria for iteration on tax revenue recycling" -p21_tau_CO2_tax_gdx(ttot,all_regi) "tax path from gdx, may overwrite default values" +pm_tau_CO2_tax_gdx(ttot,all_regi) "tax path from gdx, may overwrite default values" 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" diff --git a/modules/21_tax/on/preloop.gms b/modules/21_tax/on/preloop.gms index 05ce6f1238..71bd4e6ad8 100644 --- a/modules/21_tax/on/preloop.gms +++ b/modules/21_tax/on/preloop.gms @@ -13,11 +13,11 @@ pm_taxemiMkt_iteration(iteration,t,regi,emiMkt)$(t.val ge cm_startyear) = 0; ***------------------------------------------------------------------- *** overwrite default targets with gdx values ***------------------------------------------------------------------- -Execute_Loadpoint 'input' p21_tau_CO2_tax_gdx = pm_taxCO2eq; +Execute_Loadpoint 'input' pm_tau_CO2_tax_gdx = pm_taxCO2eq; if (cm_gdximport_target eq 1, *** only if tax rates not all equal to zero -if (smax((t,regi),p21_tau_CO2_tax_gdx(t,regi)$(t.val gt 2030)) gt 0, -pm_taxCO2eq(t,regi) = p21_tau_CO2_tax_gdx(t,regi); +if (smax((t,regi),pm_tau_CO2_tax_gdx(t,regi)$(t.val gt 2030)) gt 0, +pm_taxCO2eq(t,regi) = pm_tau_CO2_tax_gdx(t,regi); ); ); if (cm_emiscen ne 9, diff --git a/modules/47_regipol/none/not_used.txt b/modules/47_regipol/none/not_used.txt index 254d6d59e2..781254aa7f 100644 --- a/modules/47_regipol/none/not_used.txt +++ b/modules/47_regipol/none/not_used.txt @@ -75,6 +75,7 @@ vm_emiTeMkt,input,added by codeCheck pm_emiMktTarget_tolerance,switch,not needed sm_globalBudget_dev,input,questionnaire pm_allTargetsConverged,input,questionnaire +pm_tau_CO2_tax_gdx,input,questionnaire sm_EJ_2_TWa,input,not needed vm_prodSe,input,not needed pm_cesdata,input,not needed diff --git a/modules/47_regipol/regiCarbonPrice/datainput.gms b/modules/47_regipol/regiCarbonPrice/datainput.gms index 1bedcd2587..ad858cbbb8 100644 --- a/modules/47_regipol/regiCarbonPrice/datainput.gms +++ b/modules/47_regipol/regiCarbonPrice/datainput.gms @@ -33,7 +33,10 @@ $IFTHEN.emiMkt not "%cm_emiMktTarget%" == "off" *** Auxiliar parameters based on emission targets information loop((ttot,ttot2,ext_regi,emiMktExt,target_type_47,emi_type_47)$pm_emiMktTarget(ttot,ttot2,ext_regi,emiMktExt,target_type_47,emi_type_47), !!calculated sets that depends on data parameter regiEmiMktTarget(ext_regi) = yes; !! assigning values to set containing extended regions that have regional emission targets - regiANDperiodEmiMktTarget_47(ttot2,ext_regi) = yes; !! assigning values to set containing extended regions and terminal years of regional emission targets + regiANDperiodEmiMktTarget_47(ttot2,ext_regi) = yes; !! assigning values to set containing extended regions and terminal years of regional emission targets + loop(regi$regi_groupExt(ext_regi,regi), + regiNativeEmiMktTarget(regi) = yes; !! assigning values to set containing native regions that have regional emission targets + ); ); *** Calculating set containing regions that should be controlled by a given regional emission target. @@ -359,5 +362,28 @@ $offdelim $endif.exogDemScen +***--------------------------------------------------------------------------- +*** Exogenous CO2 tax level: +***--------------------------------------------------------------------------- +$ifThen.regiExoPrice not "%cm_regiExoPrice%" == "off" +$ifThen.regiExoPriceType "%cm_regiExoPrice%" == "gdx" +*** load emiMkt CO2eq prices from input gdx +Execute_Loadpoint 'input' p47_tau_taxemiMkt = pm_taxemiMkt; +*** assigning values to set containing native regions that have exogenously fixed emission market co2 prices +loop((t,regi,emiMkt)$p47_tau_taxemiMkt(t,regi,emiMkt), + regiNativeEmiMktTarget(regi) = yes; +); +$else.regiExoPriceType +*** assigning values to set containing native regions that have exogenously fixed emission market co2 prices +loop((t,ext_regi)$p47_exoCo2tax(ext_regi,t), + loop(regi$regi_group(ext_regi,regi), + regiNativeEmiMktTarget(regi) = yes; + ); +); +$endIf.regiExoPriceType +$endIf.regiExoPrice + + + *** EOF ./modules/47_regipol/regiCarbonPrice/datainput.gms diff --git a/modules/47_regipol/regiCarbonPrice/declarations.gms b/modules/47_regipol/regiCarbonPrice/declarations.gms index 730c19f735..ef0aef2841 100644 --- a/modules/47_regipol/regiCarbonPrice/declarations.gms +++ b/modules/47_regipol/regiCarbonPrice/declarations.gms @@ -240,9 +240,15 @@ $endIf.cm_CCSmaxBound *** Exogenous CO2 tax level: ***--------------------------------------------------------------------------- $ifThen.regiExoPrice not "%cm_regiExoPrice%" == "off" + Parameter +$ifThen.regiExoPriceType "%cm_regiExoPrice%" == "gdx" + p47_tau_taxemiMkt(ttot,all_regi,emiMkt) "emiMkt CO2eq prices loaded from input gdx, in T$/GtC = $/kgC. To get $/tCO2, multiply with 272 [T$/GtC]" +$else.regiExoPriceType p47_exoCo2tax(ext_regi,ttot) "Exogenous CO2 tax level. Overrides carbon prices in pm_taxCO2eq, only if explicitly defined. Regions and region groups allowed. Format: '. , . ' or '.( , '). [$/tCO2]" / %cm_regiExoPrice% / +$endIf.regiExoPriceType ; + $endIf.regiExoPrice diff --git a/modules/47_regipol/regiCarbonPrice/postsolve.gms b/modules/47_regipol/regiCarbonPrice/postsolve.gms index 700615abee..880edcaf9d 100644 --- a/modules/47_regipol/regiCarbonPrice/postsolve.gms +++ b/modules/47_regipol/regiCarbonPrice/postsolve.gms @@ -145,19 +145,17 @@ p47_emiTargetMkt_iter(iteration,ttot,regi, emiMktExt,emi_type_47) = p47_emiTarge $IFTHEN.emiMkt not "%cm_emiMktTarget%" == "off" *** Removing economy wide co2 tax parameters for regions within the emiMKt controlled targets (this is necessary here to remove any calculation made in other modules after the last run in the postsolve) - loop(ext_regi$regiEmiMktTarget(ext_regi), - loop(regi$regi_groupExt(ext_regi,regi), + loop(regi$regiNativeEmiMktTarget(regi), *** Removing the economy wide co2 tax parameters for regions within the ETS markets - pm_taxCO2eqSum(t,regi) = 0; - pm_taxCO2eq(t,regi) = 0; - pm_taxCO2eqRegi(t,regi) = 0; - pm_taxCO2eqSCC(t,regi) = 0; - - pm_taxrevGHG0(t,regi) = 0; - pm_taxrevCO2Sector0(t,regi,emi_sectors) = 0; - pm_taxrevCO2LUC0(t,regi) = 0; - pm_taxrevNetNegEmi0(t,regi) = 0; - ); + pm_taxCO2eqSum(t,regi) = 0; + pm_taxCO2eq(t,regi) = 0; + pm_taxCO2eqRegi(t,regi) = 0; + pm_taxCO2eqSCC(t,regi) = 0; + + pm_taxrevGHG0(t,regi) = 0; + pm_taxrevCO2Sector0(t,regi,emi_sectors) = 0; + pm_taxrevCO2LUC0(t,regi) = 0; + pm_taxrevNetNegEmi0(t,regi) = 0; ); *** Calculating the current emission levels... @@ -920,25 +918,45 @@ $endIf.cm_implicitPePriceTarget ***--------------------------------------------------------------------------- $ifThen.regiExoPrice not "%cm_regiExoPrice%" == "off" -loop((ttot,ext_regi)$p47_exoCo2tax(ext_regi,ttot), + +*** setting exogenous CO2 prices from the input gdx +$ifThen.regiExoPriceType "%cm_regiExoPrice%" == "gdx" + pm_taxemiMkt(t,regi,emiMkt) = p47_tau_taxemiMkt(t,regi,emiMkt); + pm_taxCO2eq(t,regi) = pm_tau_CO2_tax_gdx(t,regi); + pm_taxCO2eqSum(t,regi) = pm_taxCO2eq(t,regi); +*** Removing additional co2 tax parameters + pm_taxCO2eqRegi(t,regi) = 0; + pm_taxCO2eqSCC(t,regi) = 0; + pm_taxrevGHG0(t,regi) = 0; + pm_taxrevCO2Sector0(t,regi,emi_sectors) = 0; + pm_taxrevCO2LUC0(t,regi) = 0; + pm_taxrevNetNegEmi0(t,regi) = 0; +display 'update of CO2 prices to exogenously given CO2 prices defined in the input gdx', pm_taxCO2eq, pm_taxemiMkt; + +*** setting exogenous CO2 prices from switch cm_regiExoPrice +$else.regiExoPriceType +loop((t,ext_regi)$p47_exoCo2tax(ext_regi,t), + loop(regi$regi_group(ext_regi,regi), *** Removing the existent co2 tax parameters for regions with exogenous set prices - pm_taxCO2eqSum(ttot,regi)$(regi_group(ext_regi,regi) and (ttot.val ge cm_startyear)) = 0; - pm_taxCO2eq(ttot,regi)$(regi_group(ext_regi,regi) and (ttot.val ge cm_startyear)) = 0; - pm_taxCO2eqRegi(ttot,regi)$(regi_group(ext_regi,regi) and (ttot.val ge cm_startyear)) = 0; - pm_taxCO2eqSCC(ttot,regi)$(regi_group(ext_regi,regi) and (ttot.val ge cm_startyear)) = 0; + pm_taxCO2eqSum(t,regi) = 0; + pm_taxCO2eq(t,regi) = 0; + pm_taxCO2eqRegi(t,regi) = 0; + pm_taxCO2eqSCC(t,regi) = 0; - pm_taxrevGHG0(ttot,regi)$(regi_group(ext_regi,regi) and (ttot.val ge cm_startyear)) = 0; - pm_taxrevCO2Sector0(ttot,regi,emi_sectors)$(regi_group(ext_regi,regi) and (ttot.val ge cm_startyear)) = 0; - pm_taxrevCO2LUC0(ttot,regi)$(regi_group(ext_regi,regi) and (ttot.val ge cm_startyear)) = 0; - pm_taxrevNetNegEmi0(ttot,regi)$(regi_group(ext_regi,regi) and (ttot.val ge cm_startyear)) = 0; + pm_taxrevGHG0(t,regi) = 0; + pm_taxrevCO2Sector0(t,regi,emi_sectors) = 0; + pm_taxrevCO2LUC0(t,regi) = 0; + pm_taxrevNetNegEmi0(t,regi) = 0; - pm_taxemiMkt(ttot,regi,emiMkt)$(regi_group(ext_regi,regi) and (ttot.val ge cm_startyear)) = 0; + pm_taxemiMkt(t,regi,emiMkt) = 0; *** setting exogenous CO2 prices - pm_taxCO2eq(ttot,regi)$(regi_group(ext_regi,regi) and (ttot.val ge cm_startyear)) = p47_exoCo2tax(ext_regi,ttot)*sm_DptCO2_2_TDpGtC; - pm_taxCO2eqSum(ttot,regi)$(regi_group(ext_regi,regi) and (ttot.val ge cm_startyear)) = pm_taxCO2eq(ttot,regi); + pm_taxCO2eq(t,regi) = p47_exoCo2tax(ext_regi,t)*sm_DptCO2_2_TDpGtC; + pm_taxCO2eqSum(t,regi) = pm_taxCO2eq(t,regi); + ); ); display 'update of CO2 prices due to exogenously given CO2 prices in p47_exoCo2tax', pm_taxCO2eq; +$endIf.regiExoPriceType $endIf.regiExoPrice *** EOF ./modules/47_regipol/regiCarbonPrice/postsolve.gms diff --git a/modules/47_regipol/regiCarbonPrice/preloop.gms b/modules/47_regipol/regiCarbonPrice/preloop.gms index 3f5989214b..32a1d457fc 100644 --- a/modules/47_regipol/regiCarbonPrice/preloop.gms +++ b/modules/47_regipol/regiCarbonPrice/preloop.gms @@ -120,5 +120,52 @@ pm_eta_conv("2010",regi,"tdsyngas")$(sameAs(regi,"DEU")) = 0.949; pm_eta_conv("2015",regi,"tdsyngas")$(sameAs(regi,"DEU")) = 0.962; pm_eta_conv(t,regi,"tdsyngas")$(sameAs(regi,"DEU") and t.val ge 2020) = 0.975; +***--------------------------------------------------------------------------- +*** Exogenous CO2 tax level: +***--------------------------------------------------------------------------- + +*** initialize exogenous CO2 prices +$ifThen.regiExoPrice not "%cm_regiExoPrice%" == "off" + +*** setting exogenous CO2 prices from the input gdx +$ifThen.regiExoPriceType "%cm_regiExoPrice%" == "gdx" + pm_taxemiMkt(t,regi,emiMkt) = p47_tau_taxemiMkt(t,regi,emiMkt); + pm_taxCO2eq(t,regi) = pm_tau_CO2_tax_gdx(t,regi); + pm_taxCO2eqSum(t,regi) = pm_taxCO2eq(t,regi); +*** Removing additional co2 tax parameters + pm_taxCO2eqRegi(t,regi) = 0; + pm_taxCO2eqSCC(t,regi) = 0; + pm_taxrevGHG0(t,regi) = 0; + pm_taxrevCO2Sector0(t,regi,emi_sectors) = 0; + pm_taxrevCO2LUC0(t,regi) = 0; + pm_taxrevNetNegEmi0(t,regi) = 0; +display 'update of CO2 prices to exogenously given CO2 prices defined in the input gdx', pm_taxCO2eq, pm_taxemiMkt; + +*** setting exogenous CO2 prices from switch cm_regiExoPrice +$else.regiExoPriceType +loop((t,ext_regi)$p47_exoCo2tax(ext_regi,t), + loop(regi$regi_group(ext_regi,regi), +*** Removing the existent co2 tax parameters for regions with exogenous set prices + pm_taxCO2eqSum(t,regi) = 0; + pm_taxCO2eq(t,regi) = 0; + pm_taxCO2eqRegi(t,regi) = 0; + pm_taxCO2eqSCC(t,regi) = 0; + + pm_taxrevGHG0(t,regi) = 0; + pm_taxrevCO2Sector0(t,regi,emi_sectors) = 0; + pm_taxrevCO2LUC0(t,regi) = 0; + pm_taxrevNetNegEmi0(t,regi) = 0; + + pm_taxemiMkt(t,regi,emiMkt) = 0; + +*** setting exogenous CO2 prices + pm_taxCO2eq(t,regi) = p47_exoCo2tax(ext_regi,t)*sm_DptCO2_2_TDpGtC; + pm_taxCO2eqSum(t,regi) = pm_taxCO2eq(t,regi); + ); +); +display 'update of CO2 prices due to exogenously given CO2 prices in p47_exoCo2tax', pm_taxCO2eq; +$endIf.regiExoPriceType +$endIf.regiExoPrice + *** EOF ./modules/47_regipol/regiCarbonPrice/preloop.gms diff --git a/modules/47_regipol/regiCarbonPrice/sets.gms b/modules/47_regipol/regiCarbonPrice/sets.gms index 81a39832fd..8a39f78218 100644 --- a/modules/47_regipol/regiCarbonPrice/sets.gms +++ b/modules/47_regipol/regiCarbonPrice/sets.gms @@ -15,7 +15,8 @@ emi_type_47 "emission type used in regional target" netGHG, netGHG_noBunkers, netGHG_noLULUCF_noBunkers, netGHG_LULUCFGrassi, netGHG_LULUCFGrassi_noBunkers, netGHG_LULUCFGrassi_intraRegBunker, netGHG_noLULUCF, grossEnCO2_noBunkers / - +regiNativeEmiMktTarget(all_regi) "native regions with emiMkt targets" / / + *** Emission markets $ifThen.emiMkt not "%cm_emiMktTarget%" == "off" regiEmiMktTarget(ext_regi) "regions with emiMkt targets" / /