diff --git a/main.gms b/main.gms index 6303f8d64..9c90c452e 100755 --- a/main.gms +++ b/main.gms @@ -392,8 +392,8 @@ $setglobal emicapregi none !! def = none *' * (NPi): National Policies Implemented, extrapolation of historical (until 2020) carbon prices *' * (none): no tax policy (combined with all emiscens except emiscen = 9) -*** (exponential) is superseded by (functionalForm): For a globally uniform, exponentially increasing carbonprice path until end of century [in combination with cm_iterative_target_adj = 0 or 5], set cm_taxCO2_functionalForm = exponential, cm_taxCO2_regiDiff = none, cm_taxCO2_interpolation = off, cm_taxCO2_lowerBound_path_gdx_ref = off, cm_peakBudgYr = 2110, and choose the initial carbonprice in cm_startyear via cm_taxCO2_startyear. -*** (linear) is superseded by (functionalForm): For a globally uniform, linearly increasing carbonprice path until end of century [in combination with cm_iterative_target_adj = 0 or 5], set cm_taxCO2_functionalForm = linear, cm_taxCO2_regiDiff = none, cm_taxCO2_interpolation = off, cm_taxCO2_lowerBound_path_gdx_ref = off, cm_peakBudgYr = 2110, and choose the initial carbonprice in cm_startyear via cm_taxCO2_startyear. [Adjust historical reference point (cm_taxCO2_historicalYr, cm_taxCO2_historical) if needed.] +*** (exponential) is superseded by (functionalForm): For a globally uniform, exponentially increasing carbonprice path until end of century [in combination with cm_iterative_target_adj = 0 or 5], set cm_taxCO2_functionalForm = exponential, cm_taxCO2_regiDiff = none, cm_taxCO2_interpolation = off, cm_taxCO2_lowerBound_path_gdx_ref = off, cm_peakBudgYr = 2100, and choose the initial carbonprice in cm_startyear via cm_taxCO2_startyear. +*** (linear) is superseded by (functionalForm): For a globally uniform, linearly increasing carbonprice path until end of century [in combination with cm_iterative_target_adj = 0 or 5], set cm_taxCO2_functionalForm = linear, cm_taxCO2_regiDiff = none, cm_taxCO2_interpolation = off, cm_taxCO2_lowerBound_path_gdx_ref = off, cm_peakBudgYr = 2100, and choose the initial carbonprice in cm_startyear via cm_taxCO2_startyear. [Adjust historical reference point (cm_taxCO2_historicalYr, cm_taxCO2_historical) if needed.] $setglobal carbonprice none !! def = none *'--------------------- 46_carbonpriceRegi --------------------------------- diff --git a/modules/45_carbonprice/NDC/not_used.txt b/modules/45_carbonprice/NDC/not_used.txt index f55431927..7186a99c3 100644 --- a/modules/45_carbonprice/NDC/not_used.txt +++ b/modules/45_carbonprice/NDC/not_used.txt @@ -21,7 +21,6 @@ pm_gdp,input,questionnaire cm_peakBudgYr,input,added by codeCheck fm_taxCO2eqHist,input,not needed sm_budgetCO2eqGlob,input,no iterative target adjustment -sm_globalBudget_dev,input,no iterative target adjustment vm_emiTe,input,no iterative target adjustment vm_emiCdr,input,no iterative target adjustment vm_emiMac,input,no iterative target adjustment @@ -35,3 +34,4 @@ cm_taxCO2_IncAfterPeakBudgYr,input,added by codeCheck cm_budgetCO2from2020,input,no iterative target adjustment pm_taxCO2eq_anchor_iterationdiff,input,no iterative target adjustment pm_taxCO2eq_anchor_iterationdiff_tmp,input,no iterative target adjustment +sm_globalBudget_dev,input,no target adjustement diff --git a/modules/45_carbonprice/NPi/not_used.txt b/modules/45_carbonprice/NPi/not_used.txt index 70c968d89..418cf7ed9 100644 --- a/modules/45_carbonprice/NPi/not_used.txt +++ b/modules/45_carbonprice/NPi/not_used.txt @@ -29,7 +29,6 @@ cm_startyear,input,added by codeCheck cm_peakBudgYr,input,added by codeCheck fm_taxCO2eqHist,input,not needed sm_budgetCO2eqGlob,input,no iterative target adjustment -sm_globalBudget_dev,input,no iterative target adjustment vm_emiTe,input,no iterative target adjustment vm_emiCdr,input,no iterative target adjustment vm_emiMac,input,no iterative target adjustment @@ -43,3 +42,4 @@ cm_taxCO2_IncAfterPeakBudgYr,input,added by codeCheck cm_budgetCO2from2020,input,no iterative target adjustment pm_taxCO2eq_anchor_iterationdiff,input,no iterative target adjustment pm_taxCO2eq_anchor_iterationdiff_tmp,input,no iterative target adjustment +sm_globalBudget_dev,input,no target adjustement diff --git a/modules/45_carbonprice/NPi2025/datainput.gms b/modules/45_carbonprice/NPi2025/datainput.gms index e858e41c4..0df1afaca 100755 --- a/modules/45_carbonprice/NPi2025/datainput.gms +++ b/modules/45_carbonprice/NPi2025/datainput.gms @@ -18,6 +18,6 @@ loop(ext_regi$sameas(ext_regi, "EUR_regi"), pm_taxCO2eq(t,regi)$(t.val ge 2030 AND regi_group(ext_regi,regi)) = (fm_taxCO2eqHist("2030",regi)+ (t.val - 2030) * (20/75)) * sm_DptCO2_2_TDpGtC; ); -pm_taxCO2eq(t,regi)$(t.val gt 2110) = pm_taxCO2eq("2110",regi); !! to prevent huge taxes after 2110 and the resulting convergence problems, set taxes after 2110 equal to 2110 value +pm_taxCO2eq(t,regi)$(t.val gt 2100) = pm_taxCO2eq("2100",regi); !! to prevent huge taxes after 2100 and the resulting convergence problems, set taxes after 2100 equal to 2100 value *** EOF ./modules/45_carbonprice/NPi2025/datainput.gms diff --git a/modules/45_carbonprice/NPi2025/not_used.txt b/modules/45_carbonprice/NPi2025/not_used.txt index 5bcbd0b85..eefae6532 100755 --- a/modules/45_carbonprice/NPi2025/not_used.txt +++ b/modules/45_carbonprice/NPi2025/not_used.txt @@ -29,7 +29,6 @@ pm_emifac,input,questionnaire cm_peakBudgYr,input,not needed sm_D2005_2_D2017,input,not needed sm_budgetCO2eqGlob,input,added by codeCheck -sm_globalBudget_dev,input,added by codeCheck vm_emiTe,input,added by codeCheck vm_emiCdr,input,added by codeCheck vm_emiMac,input,added by codeCheck @@ -43,3 +42,4 @@ cm_taxCO2_startyear,input,added by codeCheck cm_taxCO2_expGrowth,input,added by codeCheck cm_budgetCO2from2020,input,added by codeCheck cm_taxCO2_IncAfterPeakBudgYr,input,added by codeCheck +sm_globalBudget_dev,input,no target adjustement diff --git a/modules/45_carbonprice/NPi2025expo/datainput.gms b/modules/45_carbonprice/NPi2025expo/datainput.gms index 394c63083..dccbc659d 100755 --- a/modules/45_carbonprice/NPi2025expo/datainput.gms +++ b/modules/45_carbonprice/NPi2025expo/datainput.gms @@ -18,6 +18,6 @@ loop(ext_regi$sameas(ext_regi, "EUR_regi"), pm_taxCO2eq(t,regi)$(t.val ge 2030 AND regi_group(ext_regi,regi)) = fm_taxCO2eqHist("2030",regi) * sm_DptCO2_2_TDpGtC * cm_taxCO2_expGrowth**(t.val - 2030); ); -pm_taxCO2eq(t,regi)$(t.val gt 2110) = pm_taxCO2eq("2110",regi); !! to prevent huge taxes after 2110 and the resulting convergence problems, set taxes after 2110 equal to 2110 value +pm_taxCO2eq(t,regi)$(t.val gt 2100) = pm_taxCO2eq("2100",regi); !! to prevent huge taxes after 2100 and the resulting convergence problems, set taxes after 2100 equal to 2100 value *** EOF ./modules/45_carbonprice/NPi2025expo/datainput.gms diff --git a/modules/45_carbonprice/NPi2025expo/not_used.txt b/modules/45_carbonprice/NPi2025expo/not_used.txt index ef3c5f10e..cfd59fed7 100755 --- a/modules/45_carbonprice/NPi2025expo/not_used.txt +++ b/modules/45_carbonprice/NPi2025expo/not_used.txt @@ -29,7 +29,6 @@ pm_emifac,input,questionnaire cm_peakBudgYr,input,not needed sm_D2005_2_D2017,input,not needed sm_budgetCO2eqGlob,input,no iterative target adjustment -sm_globalBudget_dev,input,no iterative target adjustment vm_emiTe,input,no iterative target adjustment vm_emiCdr,input,no iterative target adjustment vm_emiMac,input,no iterative target adjustment @@ -42,3 +41,4 @@ cm_taxCO2_IncAfterPeakBudgYr,input,added by codeCheck cm_budgetCO2from2020,input,no iterative target adjustment pm_taxCO2eq_anchor_iterationdiff,input,no iterative target adjustment pm_taxCO2eq_anchor_iterationdiff_tmp,input,no iterative target adjustment +sm_globalBudget_dev,input,no target adjustement diff --git a/modules/45_carbonprice/NPiexpo/datainput.gms b/modules/45_carbonprice/NPiexpo/datainput.gms index 00ce621b9..04ef89033 100644 --- a/modules/45_carbonprice/NPiexpo/datainput.gms +++ b/modules/45_carbonprice/NPiexpo/datainput.gms @@ -15,7 +15,7 @@ Execute_Loadpoint "input_ref" pm_taxCO2eq = pm_taxCO2eq; *** calculate pm_taxCO2eq for year before startyear pm_taxCO2eq(t,regi) = sum(ttot, pm_taxCO2eq(ttot,regi)$(ttot.val eq smax(ttot2$( ttot2.val lt cm_startyear ), ttot2.val))) * cm_taxCO2_expGrowth**(t.val-smax(ttot2$( ttot2.val lt cm_startyear ), ttot2.val)); -pm_taxCO2eq(t,regi)$(t.val gt 2110) = pm_taxCO2eq("2110",regi); !! to prevent huge taxes after 2110 and the resulting convergence problems, set taxes after 2110 equal to 2110 value +pm_taxCO2eq(t,regi)$(t.val gt 2100) = pm_taxCO2eq("2100",regi); !! to prevent huge taxes after 2100 and the resulting convergence problems, set taxes after 2100 equal to 2100 value *** EOF ./modules/45_carbonprice/NPiexpo/datainput.gms diff --git a/modules/45_carbonprice/NPiexpo/not_used.txt b/modules/45_carbonprice/NPiexpo/not_used.txt index be908a924..6f185a95a 100644 --- a/modules/45_carbonprice/NPiexpo/not_used.txt +++ b/modules/45_carbonprice/NPiexpo/not_used.txt @@ -30,7 +30,6 @@ cm_peakBudgYr,input,added by codeCheck fm_taxCO2eqHist,input,not needed sm_D2005_2_D2017,input,not needed sm_budgetCO2eqGlob,input,no iterative target adjustment -sm_globalBudget_dev,input,no iterative target adjustment vm_emiTe,input,no iterative target adjustment vm_emiCdr,input,no iterative target adjustment vm_emiMac,input,no iterative target adjustment @@ -43,3 +42,4 @@ cm_taxCO2_IncAfterPeakBudgYr,input,added by codeCheck cm_budgetCO2from2020,input,no iterative target adjustment pm_taxCO2eq_anchor_iterationdiff,input,no iterative target adjustment pm_taxCO2eq_anchor_iterationdiff_tmp,input,no iterative target adjustment +sm_globalBudget_dev,input,no target adjustement diff --git a/modules/45_carbonprice/exogenous/not_used.txt b/modules/45_carbonprice/exogenous/not_used.txt index 1c046562f..5e413153f 100644 --- a/modules/45_carbonprice/exogenous/not_used.txt +++ b/modules/45_carbonprice/exogenous/not_used.txt @@ -29,7 +29,6 @@ cm_peakBudgYr,input,added by codeCheck sm_D2005_2_D2017,input,not needed fm_taxCO2eqHist,input,not needed sm_budgetCO2eqGlob,input,no iterative target adjustment -sm_globalBudget_dev,input,no iterative target adjustment vm_emiTe,input,no iterative target adjustment vm_emiCdr,input,no iterative target adjustment vm_emiMac,input,no iterative target adjustment @@ -43,3 +42,4 @@ cm_taxCO2_IncAfterPeakBudgYr,input,added by codeCheck cm_budgetCO2from2020,input,no iterative target adjustment pm_taxCO2eq_anchor_iterationdiff,input,no iterative target adjustment pm_taxCO2eq_anchor_iterationdiff_tmp,input,no iterative target adjustment +sm_globalBudget_dev,input,no target adjustement diff --git a/modules/45_carbonprice/expoLinear/not_used.txt b/modules/45_carbonprice/expoLinear/not_used.txt index 6262db85f..419ccd566 100644 --- a/modules/45_carbonprice/expoLinear/not_used.txt +++ b/modules/45_carbonprice/expoLinear/not_used.txt @@ -26,7 +26,6 @@ cm_peakBudgYr,input,added by codeCheck sm_D2005_2_D2017,input,not needed fm_taxCO2eqHist,input,not needed sm_budgetCO2eqGlob,input,no iterative target adjustment -sm_globalBudget_dev,input,no iterative target adjustment vm_emiTe,input,no iterative target adjustment vm_emiCdr,input,no iterative target adjustment vm_emiMac,input,no iterative target adjustment @@ -38,3 +37,4 @@ cm_taxCO2_IncAfterPeakBudgYr,input,added by codeCheck cm_budgetCO2from2020,input,no iterative target adjustment pm_taxCO2eq_anchor_iterationdiff,input,no iterative target adjustment pm_taxCO2eq_anchor_iterationdiff_tmp,input,no iterative target adjustment +sm_globalBudget_dev,input,no target adjustement diff --git a/modules/45_carbonprice/functionalForm/datainput.gms b/modules/45_carbonprice/functionalForm/datainput.gms index b55afb1c6..e8f3864a6 100644 --- a/modules/45_carbonprice/functionalForm/datainput.gms +++ b/modules/45_carbonprice/functionalForm/datainput.gms @@ -83,7 +83,7 @@ $endIf.taxCO2globalAnchor *** Part II (Post-peak behaviour): The global anchor trajectory can be adjusted after reaching the peak of global CO2 emissions in cm_peakBudgYr. *** The (initial) choice of cm_peakBudgYr is endogenously adjusted if cm_iterative_target_adj is set to 7 or 9. *** (with iterative_target_adj = 0): after cm_peakBudgYr, the global anchor trajectory increases linearly with fixed annual increase given by cm_taxCO2_IncAfterPeakBudgYr (default = 0, i.e. constant), -*** set cm_peakBudgYr = 2110 to avoid adjustment +*** set cm_peakBudgYr = 2100 to avoid adjustment *** (with iterative_target_adj = 5): no adjustment to the functional form after cm_peakBudgYr *** (with iterative_target_adj = 7): after cm_peakBudgYr, the global anchor trajectory is adjusted so that global net CO2 emissions stay close to zero *** (with iterative_target_adj = 9): after cm_peakBudgYr, the global anchor trajectory increases linearly with fixed annual increase given by cm_taxCO2_IncAfterPeakBudgYr (default = 0, i.e. constant) @@ -98,8 +98,8 @@ if((cm_iterative_target_adj = 0) or (cm_iterative_target_adj = 9), + (t.val - cm_peakBudgYr) * cm_taxCO2_IncAfterPeakBudgYr * sm_DptCO2_2_TDpGtC; !! increase by cm_taxCO2inc_after_peakBudgYr per year ); -*** Always set carbon price constant after 2110 to prevent huge taxes after 2110 and the resulting convergence problems -p45_taxCO2eq_anchor(t)$(t.val gt 2110) = p45_taxCO2eq_anchor("2110"); +*** Always set carbon price constant after 2100 to prevent huge taxes after 2100 and the resulting convergence problems +p45_taxCO2eq_anchor(t)$(t.val gt 2100) = p45_taxCO2eq_anchor("2100"); display p45_taxCO2eq_anchor_until2150, p45_taxCO2eq_anchor; ***----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/modules/45_carbonprice/functionalForm/declarations.gms b/modules/45_carbonprice/functionalForm/declarations.gms index 35a5a9837..f6ec7d913 100644 --- a/modules/45_carbonprice/functionalForm/declarations.gms +++ b/modules/45_carbonprice/functionalForm/declarations.gms @@ -59,15 +59,17 @@ $endIf.taxCO2interpolation1 scalars s45_actualbudgetco2 "actual level of 2020-2100 cumulated emissions, including all CO2 for last iteration" s45_actualbudgetco2_last "actual level of 2020-2100 cumulated emissions for previous iteration" /0/ +s45_factorRescale_taxCO2_exponent_before10 "exponent determining sensitivity before iteration 10" +s45_factorRescale_taxCO2_exponent_from10 "exponent determining sensitivity of CO2 price adjustment to CO2 budget deviation from iteration 10" ; *** Parameters only used in functionForm/postsolve.gms parameters p45_actualbudgetco2(ttot) "actual level of cumulated emissions starting from 2020 [GtCO2]" -p45_taxCO2eq_iteration(iteration,ttot,all_regi) "save pm_taxCO2eq from each iteration for debugging" -p45_taxCO2eq_anchor_iteration(iteration,ttot) "save p45_taxCO2eq_anchor from each iteration for debugging" -o45_taxCO2eq_anchor_iterDiff_Itr(iteration) "track pm_taxCO2eq_anchor_iterationdiff over iterations" +p45_taxCO2eq_iteration(iteration,ttot,all_regi) "save pm_taxCO2eq in each iteration (before entering functionalForm/postsolve.gms) for debugging" +p45_taxCO2eq_anchor_iteration(iteration,ttot) "save p45_taxCO2eq_anchor in each iteration (before entering functionalForm/postsolve.gms) for debugging" +o45_taxCO2eq_anchor_iterDiff_Itr(iteration) "track pm_taxCO2eq_anchor_iterationdiff in 2100 over iterations" o45_diff_to_Budg(iteration) "Difference between actual CO2 budget and target CO2 budget" o45_totCO2emi_peakBudgYr(iteration) "Total CO2 emissions in the peakBudgYr" diff --git a/modules/45_carbonprice/functionalForm/postsolve.gms b/modules/45_carbonprice/functionalForm/postsolve.gms index 9755f0fb2..13a94630c 100644 --- a/modules/45_carbonprice/functionalForm/postsolve.gms +++ b/modules/45_carbonprice/functionalForm/postsolve.gms @@ -6,92 +6,250 @@ *** | Contact: remind@pik-potsdam.de *** SOF ./modules/45_carbonprice/functionalForm/postsolve.gms -*** Only run postsolve if cm_iterative_target_adj is not equal to 0. -if((cm_iterative_target_adj ne 0), +***----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +*** Part 0 (Actual CO2 budget): If iterative_target_adj = 0, 7 or 9, compute actual CO2 peak budget in current iteration. If iterative_target_adj = 5, compute actual CO2 end-of-century budget in current iteration. +***----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +*** `p45_actualbudgetco2(ttot)` includes emissions from 2020 to `ttot` (inclusive). +p45_actualbudgetco2(ttot)$( 2020 lt ttot.val ) + = sum((regi,ttot2)$( 2020 le ttot2.val AND ttot2.val le ttot.val ), + ( vm_emiTe.l(ttot2,regi,"co2") + vm_emiCdr.l(ttot2,regi,"co2") + vm_emiMac.l(ttot2,regi,"co2")) + * ( (0.5 + pm_ts(ttot2) / 2)$( ttot2.val eq 2020 ) !! second half of the 2020 period (mid 2020 - end 2022) plus 0.5 to account fo beginning 2020 - mid 2020 + + (pm_ts(ttot2))$( 2020 lt ttot2.val AND ttot2.val lt ttot.val ) !! entire middle periods + + ((pm_ttot_val(ttot) - pm_ttot_val(ttot-1)) / 2 + 0.5)$(ttot2.val eq ttot.val ) !! first half of the final period plus 0.5 to account fo mid - end of final year + ) + ) + * sm_c_2_co2; + +if(cm_iterative_target_adj = 5, !! End-of-century budget + s45_actualbudgetco2 = sum(t$(t.val eq 2100),p45_actualbudgetco2(t)); +else !! Peak budget + s45_actualbudgetco2 = smax(t$(t.val le cm_peakBudgYr AND t.val le 2100),p45_actualbudgetco2(t)); + o45_peakBudgYr_Itr(iteration) = cm_peakBudgYr; +); + +display p45_actualbudgetco2, s45_actualbudgetco2; + +*** Copied from postsolve algorithm for cm_iterative_target_adj = 5. TODO: Check where cm_emiscen eq 6 is used and if this should be kept. +if ((cm_emiscen eq 6) AND (cm_iterative_target_adj eq 5), + if(o_modelstat eq 2 AND ord(iteration) 2020), (sum(regi, (vm_emiTe.l(ttot,regi,"co2") + vm_emiCdr.l(ttot,regi,"co2") + vm_emiMac.l(ttot,regi,"co2"))) * sm_c_2_co2 * pm_ts(ttot))) - + sum(regi, vm_emiTe.l("2100",regi,"co2") + vm_emiCdr.l("2100",regi,"co2") + vm_emiMac.l("2100",regi,"co2")) * sm_c_2_co2 * (10 - pm_ts("2090")/2 + 0.5) - + sum(regi, vm_emiTe.l("2020",regi,"co2") + vm_emiCdr.l("2020",regi,"co2") + vm_emiMac.l("2020",regi,"co2")) * sm_c_2_co2 * (pm_ts("2020")/2 + 0.5); -display s45_actualbudgetco2; - - if (cm_emiscen eq 6, - if(o_modelstat eq 2 AND ord(iteration) 0 AND abs(cm_budgetCO2from2020 - s45_actualbudgetco2) ge 0.5, !!only for optimal iterations, and not after the last one, and only if budget still possitive, and only if target not yet reached - sm_globalBudget_dev = s45_actualbudgetco2 / cm_budgetCO2from2020; -*** make sure that iteration converges: -*** use multiplicative for budgets higher than 1200 Gt; for lower budgets, use multiplicative adjustment only for first 3 iterations, - if(ord(iteration) lt 3 or cm_budgetCO2from2020 > 1200, - !! change in CO2 price through adjustment: new price - old price; needed for adjustment option 2 - pm_taxCO2eq_anchor_iterationdiff(t) = p45_taxCO2eq_anchor(t) * min(max((s45_actualbudgetco2/cm_budgetCO2from2020)** (25/(2 * iteration.val + 23)),0.5+iteration.val/208),2 - iteration.val/102) - p45_taxCO2eq_anchor(t); - p45_taxCO2eq_anchor(t) = p45_taxCO2eq_anchor(t) + pm_taxCO2eq_anchor_iterationdiff(t) ; -*** then switch to triangle-approximation based on last two iteration data points - else -*** change in CO2 price through adjustment: new price - old price; the two instances of p45_taxCO2eq_anchor cancel out -> only the difference term - pm_taxCO2eq_anchor_iterationdiff_tmp(t) = - max(pm_taxCO2eq_anchor_iterationdiff(t) * min(max((cm_budgetCO2from2020 - s45_actualbudgetco2)/(s45_actualbudgetco2 - s45_actualbudgetco2_last),-2),2),-p45_taxCO2eq_anchor(t)/2); - p45_taxCO2eq_anchor(t) = p45_taxCO2eq_anchor(t) + - max(pm_taxCO2eq_anchor_iterationdiff(t) * min(max((cm_budgetCO2from2020 - s45_actualbudgetco2)/(s45_actualbudgetco2 - s45_actualbudgetco2_last),-2),2),-p45_taxCO2eq_anchor(t)/2); - pm_taxCO2eq_anchor_iterationdiff(t) = pm_taxCO2eq_anchor_iterationdiff_tmp(t); - ); - o45_taxCO2eq_anchor_iterDiff_Itr(iteration) = pm_taxCO2eq_anchor_iterationdiff("2100"); - else - if(s45_actualbudgetco2 > 0 or abs(cm_budgetCO2from2020 - s45_actualbudgetco2) < 2, !! if model was not optimal, or if budget already reached, keep tax constant - p45_taxCO2eq_anchor(t) = p45_taxCO2eq_anchor(t); - o45_taxCO2eq_anchor_iterDiff_Itr(iteration) = 0; - else -*** if budget has turned negative, reduce CO2 price by 20% - pm_taxCO2eq_anchor_iterationdiff(t) = -0.2*p45_taxCO2eq_anchor(t); - p45_taxCO2eq_anchor(t) = p45_taxCO2eq_anchor(t) + pm_taxCO2eq_anchor_iterationdiff(t); - o45_taxCO2eq_anchor_iterDiff_Itr(iteration) = pm_taxCO2eq_anchor_iterationdiff("2100"); - ); - ); - display o45_taxCO2eq_anchor_iterDiff_Itr; -*** If functionalForm is linear, re-adjust global anchor trajectory to go through the point (cm_taxCO2_historicalYr, cm_taxCO2_historical) -$ifThen.taxCO2functionalForm2 "%cm_taxCO2_functionalForm%" == "linear" -p45_taxCO2eq_anchor(t)$(t.val lt 2110) = s45_taxCO2_historical - + (p45_taxCO2eq_anchor("2110") - s45_taxCO2_historical) / (2110 - s45_taxCO2_historicalYr) !! Yearly increase of CO2 price that interpolates between cm_taxCO2_historical in cm_taxCO2_historicalYr and p45_taxCO2eq_anchor in 2110 +*** --------ALGORITHM for cm_iterative_target_adj eq 5 or 9 ---------------------------------------------------------------------------------------- +*** --------A: calculate the new CO2 price path, beginning with the CO2 tax rescale factor---------------------------------------------------------- +*** -------- this step applies for peak budget and end-of-century budget targets ----------------------------------------------------------------- +if((cm_iterative_target_adj eq 5) OR (cm_iterative_target_adj eq 9), + + if(cm_iterative_target_adj eq 9, !! stronger sensitivity of CO2 price adjustment to CO2 budget deviation for peak budget targets + s45_factorRescale_taxCO2_exponent_before10 = 3; + s45_factorRescale_taxCO2_exponent_from10 = 2; + else !! less sensitivity of CO2 price adjustment to CO2 budget deviation for peak budget targets + s45_factorRescale_taxCO2_exponent_before10 = 2; + s45_factorRescale_taxCO2_exponent_from10 = 1; + ); + + if( (o_modelstat ne 2) OR (abs(sm_globalBudget_dev -1) le 0.01) OR (ord(iteration) = cm_iteration_max), + !! keep CO2 tax constant if model was not optimal, if maximal number of iterations is reached, or if budget already reached + p45_factorRescale_taxCO2(iteration) = 1; + p45_factorRescale_taxCO2_Funneled(iteration) = p45_factorRescale_taxCO2(iteration); + else !! adjust CO2 tax + if (s45_actualbudgetco2 > 0, !! if budget positive + + !! if end-of-century budget is higher than budget at peak point, AND end-of-century budget is already in the range of the target budget (+/- 50 GtC), treat as end-of-century budget + !! for this iteration. Only do this rough approach (jump to 2100) for the first iterations - at later iterations the slower adjustment of the peaking time should work better + if( (cm_iterative_target_adj eq 9) AND ( p45_actualbudgetco2("2100") > 1.1 * s45_actualbudgetco2 ) AND ( abs(cm_budgetCO2from2020 - s45_actualbudgetco2) < 50 ) AND (iteration.val < 12), + display iteration; + display "this is likely an end-of-century budget with no net negative emissions at all. Shift cm_peakBudgYr to 2100"; + cm_peakBudgYr = 2100; + !! due to the potential strong jump in cm_peakBudgYr, which implies that the CO2 price will increase over a longer time horizon, + !! take the average of the budget at the old peak time and the new peak time + s45_actualbudgetco2 = 0.5 * (p45_actualbudgetco2("2100") + s45_actualbudgetco2); + ); + + !! CO2 tax rescale factor + if(iteration.val lt 10, + p45_factorRescale_taxCO2(iteration) = max(0.1, (s45_actualbudgetco2/cm_budgetCO2from2020) ) ** s45_factorRescale_taxCO2_exponent_before10; + else + p45_factorRescale_taxCO2(iteration) = max(0.1, (s45_actualbudgetco2/cm_budgetCO2from2020) ) ** s45_factorRescale_taxCO2_exponent_from10; + ); + p45_factorRescale_taxCO2_Funneled(iteration) + = max(min( 2 * EXP( -0.15 * iteration.val ) + 1.01 ,p45_factorRescale_taxCO2(iteration)), + 1/ ( 2 * EXP( -0.15 * iteration.val ) + 1.01) + ); + else !! if budget has turned negative, reduce CO2 price by 20% + !! CO2 tax rescale factor + p45_factorRescale_taxCO2(iteration) = 0.8; + p45_factorRescale_taxCO2_Funneled(iteration) = p45_factorRescale_taxCO2(iteration); + ); + display p45_taxCO2eq_anchor, p45_taxCO2eq_anchor_until2150, p45_factorRescale_taxCO2, p45_factorRescale_taxCO2_Funneled; + + !! Apply CO2 tax rescale factor + p45_taxCO2eq_anchor_until2150(t) = max(1* sm_DptCO2_2_TDpGtC, p45_taxCO2eq_anchor_until2150(t) * p45_factorRescale_taxCO2_Funneled(iteration) ); + display p45_taxCO2eq_anchor_until2150; + + !! If functionalForm is linear, re-adjust global anchor trajectory to go through the point (cm_taxCO2_historicalYr, cm_taxCO2_historical) +$ifThen.taxCO2functionalForm4 "%cm_taxCO2_functionalForm%" == "linear" + p45_taxCO2eq_anchor_until2150(t) = s45_taxCO2_historical + + (sum(t2$(t2.val eq cm_peakBudgYr), p45_taxCO2eq_anchor_until2150(t2)) - s45_taxCO2_historical) / (cm_peakBudgYr - s45_taxCO2_historicalYr) !! Yearly increase of CO2 price that interpolates between cm_taxCO2_historical in cm_taxCO2_historicalYr and p45_taxCO2eq_anchor_until2150 in peak year * (t.val - s45_taxCO2_historicalYr) ; -p45_taxCO2eq_anchor(t)$(t.val gt 2110) = p45_taxCO2eq_anchor("2110"); -$endIf.taxCO2functionalForm2 - ); -); + display p45_taxCO2eq_anchor_until2150; +$endIf.taxCO2functionalForm4 + + !! Use rescaled p45_taxCO2eq_anchor_until2150 as starting point for re-defining p45_taxCO2eq_anchor + p45_taxCO2eq_anchor(t) = p45_taxCO2eq_anchor_until2150(t); + + if(cm_iterative_target_adj = 9, !! After cm_peakBudgYr, the global anchor trajectory increases linearly with fixed annual increase given by cm_taxCO2_IncAfterPeakBudgYr + p45_taxCO2eq_anchor(t)$(t.val gt cm_peakBudgYr) = sum(t2$(t2.val eq cm_peakBudgYr), p45_taxCO2eq_anchor_until2150(t2)) !! CO2 tax in peak budget year + + (t.val - cm_peakBudgYr) * cm_taxCO2_IncAfterPeakBudgYr * sm_DptCO2_2_TDpGtC; !! increase by cm_taxCO2inc_after_peakBudgYr per year + ); + !! Always set carbon price constant after 2100 to prevent huge taxes after 2100 and the resulting convergence problems + p45_taxCO2eq_anchor(t)$(t.val gt 2100) = p45_taxCO2eq_anchor("2100"); + + !! Compute difference for debugging + pm_taxCO2eq_anchor_iterationdiff(t) = p45_taxCO2eq_anchor(t) - p45_taxCO2eq_anchor_iteration(iteration,t); + o45_taxCO2eq_anchor_iterDiff_Itr(iteration) = pm_taxCO2eq_anchor_iterationdiff("2100"); + display p45_taxCO2eq_anchor, pm_taxCO2eq_anchor_iterationdiff, o45_taxCO2eq_anchor_iterDiff_Itr; + + ); !! if( (o_modelstat ne 2) OR (abs(sm_globalBudget_dev -1) le 0.01) OR (ord(iteration) = cm_iteration_max), +); !! if((cm_iterative_target_adj eq 5) OR (cm_iterative_target_adj eq 9), + + +*** -------B: checking the peak timing, if cm_peakBudgYr is still correct or needs to be shifted----------------------- +*** -------- this step only applies for peak budget targets----------------------------------------------------------- +if(cm_iterative_target_adj eq 9, + o45_diff_to_Budg(iteration) = (cm_budgetCO2from2020 - s45_actualbudgetco2); + o45_totCO2emi_peakBudgYr(iteration) = sum(t$(t.val = cm_peakBudgYr), sum(regi2, vm_emiAll.l(t,regi2,"co2")) ); + o45_totCO2emi_allYrs(t,iteration) = sum(regi2, vm_emiAll.l(t,regi2,"co2") ); + + !! calculate how fast emissions are changing around the peaking time to get an idea how close it is possible to get to 0 due to the 5(10) year time steps + o45_change_totCO2emi_peakBudgYr(iteration) = sum(ttot$(ttot.val = cm_peakBudgYr), (o45_totCO2emi_allYrs(ttot-1,iteration) - o45_totCO2emi_allYrs(ttot+1,iteration) )/4 ); !! Only gives a tolerance range, exact value not important. Division by 4 somewhat arbitrary - could be 3 or 5 as well. + + display cm_peakBudgYr, o45_diff_to_Budg, o45_peakBudgYr_Itr, o45_totCO2emi_allYrs, o45_totCO2emi_peakBudgYr, o45_change_totCO2emi_peakBudgYr; + + + !!----B1: check if cm_peakBudgYr should be shifted left or right: + if( abs(o45_diff_to_Budg(iteration)) < 20, !! only think about shifting peakBudgYr if the budget is close enough to target budget + display "close enough to target budget to check timing of peak year"; + + !! check if the target year was just shifted back left after being shifted right before + if ( (iteration.val > 2) AND ( o45_peakBudgYr_Itr(iteration - 1) > o45_peakBudgYr_Itr(iteration) ) AND ( o45_peakBudgYr_Itr(iteration - 2) = o45_peakBudgYr_Itr(iteration) ), + o45_pkBudgYr_flipflop(iteration) = 1; + display "flipflop observed (before loop)"; + ); + + loop(ttot$(ttot.val = cm_peakBudgYr), !! look at the peak timing + if( ( (o45_totCO2emi_peakBudgYr(iteration) < -(0.1 + o45_change_totCO2emi_peakBudgYr(iteration)) ) AND (cm_peakBudgYr > 2040) ), !! no peaking time before 2040 + display "shift peakBudgYr left"; + o45_peakBudgYr_Itr(iteration+1) = pm_ttot_val(ttot - 1); + p45_taxCO2eq_anchor(t)$(t.val gt pm_ttot_val(ttot - 1)) = p45_taxCO2eq_anchor_until2150(ttot-1) + (t.val - pm_ttot_val(ttot - 1)) * cm_taxCO2_IncAfterPeakBudgYr * sm_DptCO2_2_TDpGtC; !! increase by cm_taxCO2_IncAfterPeakBudgYr per year after peakBudgYr + + elseif (( o45_totCO2emi_peakBudgYr(iteration) > (0.1 + o45_change_totCO2emi_peakBudgYr(iteration)) ) AND (cm_peakBudgYr < 2100)), !! if peaking time would be after 2100, keep 2100 budget year + if( (o45_pkBudgYr_flipflop(iteration) eq 1), !! if the target year was just shifted left after being shifted right, and would now be shifted right again + display "peakBudgYr was left, right, left and is now supposed to be shifted right again -> flipflop, thus go into separate loop"; + o45_peakBudgYr_Itr(iteration+1) = o45_peakBudgYr_Itr(iteration); !! don't shift right again immediately, but go into a different loop: + o45_delay_increase_peakBudgYear(iteration) = 1; + elseif ( o45_delay_increase_peakBudgYear(iteration) eq 1 ), + display "still in separate loop trying to resolve flip-flop behavior"; + o45_peakBudgYr_Itr(iteration+1) = o45_peakBudgYr_Itr(iteration); !! keep current peakBudgYr, + else + display "shift peakBudgYr right"; + o45_peakBudgYr_Itr(iteration+1) = pm_ttot_val(ttot + 1); !! ttot+1 is the new peakBudgYr + loop(t$(t.val ge pm_ttot_val(ttot + 1)), + p45_taxCO2eq_anchor(t) = p45_taxCO2eq_anchor_until2150(ttot+1) + + (t.val - pm_ttot_val(ttot + 1)) * cm_taxCO2_IncAfterPeakBudgYr * sm_DptCO2_2_TDpGtC; !! increase by cm_taxCO2_IncAfterPeakBudgYr per year + ); + ); + + else !! don't do anything if the peakBudgYr is already at the corner values (2040, 2100) or if the emissions in the peakBudgYr are close enough to 0 (within the range of +/- o45_change_totCO2emi_peakBudgYr) + o45_peakBudgYr_Itr(iteration+1) = o45_peakBudgYr_Itr(iteration) + ); + ); + cm_peakBudgYr = o45_peakBudgYr_Itr(iteration+1); + display cm_peakBudgYr; + ); + p45_taxCO2eq_anchor(t)$(t.val le cm_peakBudgYr) = p45_taxCO2eq_anchor_until2150(t); !! until peakBudgYr, take the contiuous price trajectory + + !!-----B2: if there was a flip-floping of cm_peakBudgYr in the previous iterations, try to overome this by adjusting the CO2 price path after the peaking year + if (o45_delay_increase_peakBudgYear(iteration) = 1, + display "not shifting peakBudgYr right, instead adjusting CO2 price for following year"; + loop(ttot$(ttot.val eq cm_peakBudgYr), !! set ttot to the current peakBudgYr + loop(t2$(t2.val eq pm_ttot_val(ttot+1)), !! set t2 to the following time step + o45_factorRescale_taxCO2_afterPeakBudgYr(iteration) = 1 + max(sum(regi2,vm_emiAll.l(ttot,regi2,"co2"))/sum(regi2,vm_emiAll.l("2015",regi2,"co2")),-0.75) ; + !! this was inspired by Christoph's approach. This value is 1 if emissions in the peakBudgYr are 0; goes down to 0.25 if emissions are <0 and approaching the size of 2015 emissions, and > 1 if emissions > 0. + + !! in case the normal linear extension still is not enough to get emissions to 0 after the peakBudgYr, shift peakBudgYr right again: + if( ( o45_reached_until2150pricepath(iteration-1) eq 1 ) AND ( o45_totCO2emi_peakBudgYr(iteration) > (0.1 + o45_change_totCO2emi_peakBudgYr(iteration)) ), + display "price in following year reached original path in previous iteration and is still not enough -> shift peakBudgYr to right"; + o45_delay_increase_peakBudgYear(iteration+1) = 0; !! probably is not necessary + o45_reached_until2150pricepath(iteration) = 0; + o45_peakBudgYr_Itr(iteration+1) = t2.val; !! shift PeakBudgYear to the following time step + p45_taxCO2eq_anchor(t2) = p45_taxCO2eq_anchor_until2150(t2) ; !! set CO2 price in t2 to value in the "continuous path" + + elseif ( ( o45_reached_until2150pricepath(iteration-1) eq 1 ) AND ( o45_totCO2emi_peakBudgYr(iteration) < (0.1 + o45_change_totCO2emi_peakBudgYr(iteration)) ) ), + display "New intermediate price in timestep after cm_peakBudgYr is sufficient to stabilize peaking year - go back to normal loop"; + o45_delay_increase_peakBudgYear(iteration+1) = 0; !! probably is not necessary + o45_reached_until2150pricepath(iteration) = 0; + o45_peakBudgYr_Itr(iteration+1) = o45_peakBudgYr_Itr(iteration); + + else !! either didn't reach the continued "until2150"-price path in last iteration, or the increase was high enough to get emissions to 0. + !! in this case, keep PeakBudgYr, and adjust the price in the year after the peakBudgYr to get emissions close to 0, + o45_delay_increase_peakBudgYear(iteration+1) = 1; !! make sure next iteration peakBudgYr is not shifted right again + o45_peakBudgYr_Itr(iteration+1) = o45_peakBudgYr_Itr(iteration); + p45_taxCO2eq_anchor(t2) = max(p45_taxCO2eq_anchor(ttot), !! at least as high as the price in the peakBudgYr + p45_taxCO2eq_anchor(t2) * (o45_factorRescale_taxCO2_afterPeakBudgYr(iteration) / p45_factorRescale_taxCO2_Funneled(iteration) ) !! the full path was already rescaled by p45_factorRescale_taxCO2_Funneled, so adjust the second rescaling + ); + loop(regi, !! this loop is necessary to allow the <-comparison in the next if statement + if( p45_taxCO2eq_anchor_until2150(t2) < p45_taxCO2eq_anchor(t2) , !! check if new price would be higher than the price if the peakBudgYr would be one timestep later + display "price increase reached price from path with cm_peakBudgYr one timestep later - downscale to 99%"; + p45_taxCO2eq_anchor(t2) = 0.99 * p45_taxCO2eq_anchor_until2150(t2); !! reduce the new CO2 price to 99% of the price that it would be if the peaking year was one timestep later. The next iteration will show if this is enough, otherwise cm_peakBudgYr will be shifted right + o45_reached_until2150pricepath(iteration) = 1; !! upward CO2 price correction reached the continued price path - check in next iteration if this is high enough. + ); + ); + ); + + display o45_factorRescale_taxCO2_afterPeakBudgYr; + p45_taxCO2eq_anchor(t)$(t.val gt t2.val) = p45_taxCO2eq_anchor(t2) + (t.val - t2.val) * cm_taxCO2_IncAfterPeakBudgYr * sm_DptCO2_2_TDpGtC; !! increase by cm_taxCO2_IncAfterPeakBudgYr per year + ); !! loop t2$(t2.val eq pm_ttot_val(ttot+1)), !! set t2 to the following time step + ); !! loop ttot$(ttot.val eq cm_peakBudgYr), !! set ttot to the current peakBudgYr + cm_peakBudgYr = o45_peakBudgYr_Itr(iteration+1); !! this has to happen outside the loop, otherwise the loop condition might be true twice + ); !! if o45_delay_increase_peakBudgYear(iteration) = 1, !! if there was a flip-floping in the previous iterations, try to solve this + display p45_taxCO2eq_anchor, p45_taxCO2eq_anchor_until2150, o45_delay_increase_peakBudgYear, o45_reached_until2150pricepath, o45_peakBudgYr_Itr, o45_pkBudgYr_flipflop, cm_peakBudgYr; +); !! if cm_iterative_target_adj eq 9, + +*** --------ALGORITHM for cm_iterative_target_adj eq 7 ---------------------------------------------------------------------------------------- *** Algorithm for ENGAGE peakBudg formulation that results in a peak budget with zero net CO2 emissions afterwards if(cm_iterative_target_adj eq 7, -*JeS/CB* Iteratively update regional CO2 tax trajectories / regional CO2 budget to reach the target for global peak budget, but make sure CO2 emissions afterward are close to zero on the global level -*KK* p45_actualbudgetco2 for ttot > 2020. It includes emissions from 2020 to ttot (including ttot). -*** (ttot.val - (ttot - 1).val)/2 and pm_ts("2020")/2 are the time periods that haven't been taken into account in the sum over ttot2. -*** 0.5 year of emissions is added for the two boundaries, such that the budget includes emissions in ttot. -p45_actualbudgetco2(ttot)$(ttot.val > 2020) = sum(ttot2$(ttot2.val < ttot.val AND ttot2.val > 2020), (sum(regi, (vm_emiTe.l(ttot2,regi,"co2") + vm_emiCdr.l(ttot2,regi,"co2") + vm_emiMac.l(ttot2,regi,"co2"))) * sm_c_2_co2 * pm_ts(ttot2))) - + sum(regi, (vm_emiTe.l(ttot,regi,"co2") + vm_emiCdr.l(ttot,regi,"co2") + vm_emiMac.l(ttot,regi,"co2"))) * sm_c_2_co2 * ((pm_ttot_val(ttot)-pm_ttot_val(ttot-1))/2 + 0.5) - + sum(regi, (vm_emiTe.l("2020",regi,"co2") + vm_emiCdr.l("2020",regi,"co2") + vm_emiMac.l("2020",regi,"co2"))) * sm_c_2_co2 * (pm_ts("2020")/2 + 0.5); -s45_actualbudgetco2 = smax(t$(t.val le cm_peakBudgYr AND t.val le 2100),p45_actualbudgetco2(t)); - -o45_peakBudgYr_Itr(iteration) = cm_peakBudgYr; - -display s45_actualbudgetco2, p45_actualbudgetco2; - - if (cm_emiscen eq 9, if(o_modelstat eq 2 AND ord(iteration) 0 AND abs(cm_budgetCO2from2020 - s45_actualbudgetco2) ge 0.5, !!only for optimal iterations, and not after the last one, and only if budget still possitive, and only if target not yet reached display p45_taxCO2eq_anchor; *** make sure that iteration converges: @@ -170,223 +328,16 @@ display s45_actualbudgetco2, p45_actualbudgetco2; ); *** If functionalForm is linear, re-adjust global anchor trajectory to go through the point (cm_taxCO2_historicalYr, cm_taxCO2_historical) $ifThen.taxCO2functionalForm3 "%cm_taxCO2_functionalForm%" == "linear" -p45_taxCO2eq_anchor_until2150(t) = s45_taxCO2_historical + p45_taxCO2eq_anchor_until2150(t) = s45_taxCO2_historical + (sum(t2$(t2.val eq cm_peakBudgYr), p45_taxCO2eq_anchor_until2150(t2)) - s45_taxCO2_historical) / (cm_peakBudgYr - s45_taxCO2_historicalYr) !! Yearly increase of CO2 price that interpolates between cm_taxCO2_historical in cm_taxCO2_historicalYr and p45_taxCO2eq_anchor_until2150 in peak year * (t.val - s45_taxCO2_historicalYr) ; -p45_taxCO2eq_anchor(t)$(t.val le cm_peakBudgYr) = p45_taxCO2eq_anchor_until2150(t); -p45_taxCO2eq_anchor(t)$(t.val gt 2110) = p45_taxCO2eq_anchor("2110"); -***TODO: CHECK IF ALGORITHM DOES WHAT IS EXPECTED. CURRENTLY NO RE-ADJUSTMENT OF GLOBAL ANCHOR TRAJECTORY BETWEEN PEAK YEAR AND 2110 AS NO SUCH ADJUSTMENT WAS CONTAINED IN ORIGINAL ALGORITHM + p45_taxCO2eq_anchor(t)$(t.val le cm_peakBudgYr) = p45_taxCO2eq_anchor_until2150(t); + p45_taxCO2eq_anchor(t)$(t.val gt 2100) = p45_taxCO2eq_anchor("2100"); +***TODO: CHECK IF ALGORITHM DOES WHAT IS EXPECTED. CURRENTLY NO RE-ADJUSTMENT OF GLOBAL ANCHOR TRAJECTORY BETWEEN PEAK YEAR AND 2100 AS NO SUCH ADJUSTMENT WAS CONTAINED IN ORIGINAL ALGORITHM $endIf.taxCO2functionalForm3 - ); - display p45_taxCO2eq_anchor_until2150, p45_taxCO2eq_anchor; -); - -*** Algorithm for new peakBudg formulation that results in a peak budget with linear increase given by cm_taxCO2_IncAfterPeakBudgYr -if (cm_iterative_target_adj eq 9, -*' Iteratively update regional CO2 tax trajectories / regional CO2 budget to reach the target for global peak budget, with a linear increase afterwards given by cm_taxCO2_IncAfterPeakBudgYr. The -*' peak budget year is determined automatically (within the time window 2040--2100) - -*' `p45_actualbudgetco2(ttot)` includes emissions from 2020 to `ttot` (inclusive). - p45_actualbudgetco2(ttot)$( 2020 lt ttot.val ) - = sum((regi,ttot2)$( 2020 le ttot2.val AND ttot2.val le ttot.val ), - ( vm_emiTe.l(ttot2,regi,"co2") - + vm_emiCdr.l(ttot2,regi,"co2") - + vm_emiMac.l(ttot2,regi,"co2") - ) - * ( !! second half of the 2020 period: 2020-22 - (pm_ts(ttot2) / 2 + 0.5)$( ttot2.val eq 2020 ) - !! entire middle periods - + (pm_ts(ttot2))$( 2020 lt ttot2.val AND ttot2.val lt ttot.val ) - !! first half of the final period, until the end of the middle year - + ((pm_ttot_val(ttot) - pm_ttot_val(ttot-1)) / 2 + 0.5)$( - ttot2.val eq ttot.val ) - ) - ) - * sm_c_2_co2; - - s45_actualbudgetco2 = smax(t$( t.val le cm_peakBudgYr ), p45_actualbudgetco2(t)); - - o45_peakBudgYr_Itr(iteration) = cm_peakBudgYr; - - display s45_actualbudgetco2, p45_actualbudgetco2; - - if(cm_emiscen eq 9, - -*** --------A: calculate the new CO2 price path, the CO2 tax rescale factor---------------------------------------------------------- - - if(o_modelstat eq 2 AND ord(iteration) < cm_iteration_max AND s45_actualbudgetco2 > 0 AND abs(cm_budgetCO2from2020 - s45_actualbudgetco2) ge 2, !!only for optimal iterations, and not after the last one, and only if budget still possitive, and only if target not yet reached - display p45_taxCO2eq_anchor; - - if( ( ( p45_actualbudgetco2("2100") > 1.1 * s45_actualbudgetco2 ) AND ( abs(cm_budgetCO2from2020 - s45_actualbudgetco2) < 50 ) AND (iteration.val < 12) ), - display iteration; -*** if end-of-century budget is higher than budget at peak point, AND end-of-century budget is already in the range of the target budget (+/- 50 GtC), treat as end-of-century budget -*** for this iteration. Only do this rough approach (jump to 2100) for the first iterations - at later iterations the slower adjustment of the peaking time should work better - display "this is likely an end-of-century budget with no net negative emissions at all. Shift cm_peakBudgYr to 2100"; - s45_actualbudgetco2 = 0.5 * (p45_actualbudgetco2("2100") + s45_actualbudgetco2); !! due to the potential strong jump in cm_peakBudgYr, which implies that the CO2 price -*** will increase over a longer time horizon, take the average of the budget at the old peak time and the new peak time - cm_peakBudgYr = 2100; - ); - -*** --------A1: for that, calculate the CO2 tax rescale factor--- - - if(iteration.val lt 10, - p45_factorRescale_taxCO2(iteration) = max(0.1, (s45_actualbudgetco2/cm_budgetCO2from2020) ) ** 3; - else - p45_factorRescale_taxCO2(iteration) = max(0.1, (s45_actualbudgetco2/cm_budgetCO2from2020) ) ** 2; - ); - p45_factorRescale_taxCO2_Funneled(iteration) = - max(min( 2 * EXP( -0.15 * iteration.val ) + 1.01 ,p45_factorRescale_taxCO2(iteration)), - 1/ ( 2 * EXP( -0.15 * iteration.val ) + 1.01) - ); - - pm_taxCO2eq_anchor_iterationdiff(t) = max(1* sm_DptCO2_2_TDpGtC, p45_taxCO2eq_anchor(t) * p45_factorRescale_taxCO2_Funneled(iteration) ) - p45_taxCO2eq_anchor(t); - p45_taxCO2eq_anchor_until2150(t) = max(1* sm_DptCO2_2_TDpGtC, p45_taxCO2eq_anchor_until2150(t) * p45_factorRescale_taxCO2_Funneled(iteration) ); - p45_taxCO2eq_anchor(t) = max(1* sm_DptCO2_2_TDpGtC, p45_taxCO2eq_anchor(t) * p45_factorRescale_taxCO2_Funneled(iteration) ); !! rescale co2tax - loop(t2$(t2.val eq cm_peakBudgYr), -*** Note: Adjustment of starting point linear curve is done at the end - p45_taxCO2eq_anchor(t)$(t.val gt cm_peakBudgYr) = p45_taxCO2eq_anchor_until2150(t2) + (t.val - t2.val) * cm_taxCO2_IncAfterPeakBudgYr * sm_DptCO2_2_TDpGtC; !! increase by cm_taxCO2_IncAfterPeakBudgYr per year - ); - - display p45_factorRescale_taxCO2, p45_factorRescale_taxCO2_Funneled; - - o45_taxCO2eq_anchor_iterDiff_Itr(iteration) = pm_taxCO2eq_anchor_iterationdiff("2100"); - - display o45_taxCO2eq_anchor_iterDiff_Itr; - - - else !! if(o_modelstat eq 2 AND ord(iteration) 0 AND abs(cm_budgetCO2from2020 )) - if(s45_actualbudgetco2 > 0 or abs(cm_budgetCO2from2020 - s45_actualbudgetco2) < 2, !! if model was not optimal, or if budget already reached, keep tax constant - p45_factorRescale_taxCO2(iteration) = 1; - p45_factorRescale_taxCO2_Funneled(iteration) = 1; - p45_taxCO2eq_anchor_until2150(t) = p45_taxCO2eq_anchor_until2150(t); !! nothing changes - else -*** if budget has turned negative, reduce CO2 price by 20% - p45_factorRescale_taxCO2(iteration) = 0.8; - p45_factorRescale_taxCO2_Funneled(iteration) = p45_factorRescale_taxCO2(iteration); - - p45_taxCO2eq_anchor_until2150(t) = p45_factorRescale_taxCO2(iteration) * p45_taxCO2eq_anchor_until2150(t); - p45_taxCO2eq_anchor(t) = p45_factorRescale_taxCO2(iteration) * p45_taxCO2eq_anchor(t); - ); - ); !! if(o_modelstat eq 2 AND ord(iteration) 0 AND abs(cm_budgetCO2from2020 - s45_actualbudgetco2) ge 2, - - display p45_taxCO2eq_anchor, p45_taxCO2eq_anchor_until2150; - - -*** -------B: checking the peak timing, if cm_peakBudgYr is still correct or needs to be shifted----------------------- - - o45_diff_to_Budg(iteration) = (cm_budgetCO2from2020 - s45_actualbudgetco2); - o45_totCO2emi_peakBudgYr(iteration) = sum(t$(t.val = cm_peakBudgYr), sum(regi2, vm_emiAll.l(t,regi2,"co2")) ); - o45_totCO2emi_allYrs(t,iteration) = sum(regi2, vm_emiAll.l(t,regi2,"co2") ); - -*RP* calculate how fast emissions are changing around the peaking time to get an idea how close it is possible to get to 0 due to the 5(10) year time steps - o45_change_totCO2emi_peakBudgYr(iteration) = sum(ttot$(ttot.val = cm_peakBudgYr), (o45_totCO2emi_allYrs(ttot-1,iteration) - o45_totCO2emi_allYrs(ttot+1,iteration) )/4 ); !! Only gives a tolerance range, exact value not important. Division by 4 somewhat arbitrary - could be 3 or 5 as well. - - display cm_peakBudgYr, o45_diff_to_Budg, o45_peakBudgYr_Itr, o45_totCO2emi_allYrs, o45_totCO2emi_peakBudgYr, o45_change_totCO2emi_peakBudgYr; - - -*** ----B1: check if cm_peakBudgYr should be shifted left or right: - if( abs(o45_diff_to_Budg(iteration)) < 20, !! only think about shifting peakBudgYr if the budget is close enough to target budget - display "close enough to target budget to check timing of peak year"; - - !! check if the target year was just shifted back left after being shifted right before - if ( (iteration.val > 2) AND ( o45_peakBudgYr_Itr(iteration - 1) > o45_peakBudgYr_Itr(iteration) ) AND ( o45_peakBudgYr_Itr(iteration - 2) = o45_peakBudgYr_Itr(iteration) ), - o45_pkBudgYr_flipflop(iteration) = 1; - display "flipflop observed (before loop)"; - ); - - loop(ttot$(ttot.val = cm_peakBudgYr), !! look at the peak timing - if( ( (o45_totCO2emi_peakBudgYr(iteration) < -(0.1 + o45_change_totCO2emi_peakBudgYr(iteration)) ) AND (cm_peakBudgYr > 2040) ), !! no peaking time before 2040 - display "shift peakBudgYr left"; - o45_peakBudgYr_Itr(iteration+1) = pm_ttot_val(ttot - 1); - p45_taxCO2eq_anchor(t)$(t.val gt pm_ttot_val(ttot - 1)) = p45_taxCO2eq_anchor_until2150(ttot-1) + (t.val - pm_ttot_val(ttot - 1)) * cm_taxCO2_IncAfterPeakBudgYr * sm_DptCO2_2_TDpGtC; !! increase by cm_taxCO2_IncAfterPeakBudgYr per year after peakBudgYr - - elseif ( ( o45_totCO2emi_peakBudgYr(iteration) > (0.1 + o45_change_totCO2emi_peakBudgYr(iteration)) ) AND (cm_peakBudgYr < 2100) ), !! if peaking time would be after 2100, keep 2100 budget year - if( (o45_pkBudgYr_flipflop(iteration) eq 1), !! if the target year was just shifted left after being shifted right, and would now be shifted right again - display "peakBudgYr was left, right, left and is now supposed to be shifted right again -> flipflop, thus go into separate loop"; - o45_peakBudgYr_Itr(iteration+1) = o45_peakBudgYr_Itr(iteration); !! don't shift right again immediately, but go into a different loop: - o45_delay_increase_peakBudgYear(iteration) = 1; - elseif ( o45_delay_increase_peakBudgYear(iteration) eq 1 ), - display "still in separate loop trying to resolve flip-flop behavior"; - o45_peakBudgYr_Itr(iteration+1) = o45_peakBudgYr_Itr(iteration); !! keep current peakBudgYr, - else - display "shift peakBudgYr right"; - o45_peakBudgYr_Itr(iteration+1) = pm_ttot_val(ttot + 1); !! ttot+1 is the new peakBudgYr - loop(t$(t.val ge pm_ttot_val(ttot + 1)), - p45_taxCO2eq_anchor(t) = p45_taxCO2eq_anchor_until2150(ttot+1) - + (t.val - pm_ttot_val(ttot + 1)) * cm_taxCO2_IncAfterPeakBudgYr * sm_DptCO2_2_TDpGtC; !! increase by cm_taxCO2_IncAfterPeakBudgYr per year - ); - ); - - else !! don't do anything if the peakBudgYr is already at the corner values (2040, 2100) or if the emissions in the peakBudgYr are close enough to 0 (within the range of +/- o45_change_totCO2emi_peakBudgYr) - o45_peakBudgYr_Itr(iteration+1) = o45_peakBudgYr_Itr(iteration) - ); - ); - cm_peakBudgYr = o45_peakBudgYr_Itr(iteration+1); - display cm_peakBudgYr; - ); -*** Note: Adjustment of starting point linear curve is done at the end - p45_taxCO2eq_anchor(t)$(t.val le cm_peakBudgYr) = p45_taxCO2eq_anchor_until2150(t); !! until peakBudgYr, take the contiuous price trajectory - -*** -----B2: if there was a flip-floping of cm_peakBudgYr in the previous iterations, try to overome this by adjusting the CO2 price path after the peaking year - if (o45_delay_increase_peakBudgYear(iteration) = 1, - display "not shifting peakBudgYr right, instead adjusting CO2 price for following year"; - loop(ttot$(ttot.val eq cm_peakBudgYr), !! set ttot to the current peakBudgYr - loop(t2$(t2.val eq pm_ttot_val(ttot+1)), !! set t2 to the following time step - o45_factorRescale_taxCO2_afterPeakBudgYr(iteration) = 1 + max(sum(regi2,vm_emiAll.l(ttot,regi2,"co2"))/sum(regi2,vm_emiAll.l("2015",regi2,"co2")),-0.75) ; - !! this was inspired by Christoph's approach. This value is 1 if emissions in the peakBudgYr are 0; goes down to 0.25 if emissions are <0 and approaching the size of 2015 emissions, and > 1 if emissions > 0. - - !! in case the normal linear extension still is not enough to get emissions to 0 after the peakBudgYr, shift peakBudgYr right again: - if( ( o45_reached_until2150pricepath(iteration-1) eq 1 ) AND ( o45_totCO2emi_peakBudgYr(iteration) > (0.1 + o45_change_totCO2emi_peakBudgYr(iteration)) ), - display "price in following year reached original path in previous iteration and is still not enough -> shift peakBudgYr to right"; - o45_delay_increase_peakBudgYear(iteration+1) = 0; !! probably is not necessary - o45_reached_until2150pricepath(iteration) = 0; - o45_peakBudgYr_Itr(iteration+1) = t2.val; !! shift PeakBudgYear to the following time step - p45_taxCO2eq_anchor(t2) = p45_taxCO2eq_anchor_until2150(t2) ; !! set CO2 price in t2 to value in the "continuous path" - - elseif ( ( o45_reached_until2150pricepath(iteration-1) eq 1 ) AND ( o45_totCO2emi_peakBudgYr(iteration) < (0.1 + o45_change_totCO2emi_peakBudgYr(iteration)) ) ), - display "New intermediate price in timestep after cm_peakBudgYr is sufficient to stabilize peaking year - go back to normal loop"; - o45_delay_increase_peakBudgYear(iteration+1) = 0; !! probably is not necessary - o45_reached_until2150pricepath(iteration) = 0; - o45_peakBudgYr_Itr(iteration+1) = o45_peakBudgYr_Itr(iteration); - else !! either didn't reach the continued "until2150"-price path in last iteration, or the increase was high enough to get emissions to 0. - !! in this case, keep PeakBudgYr, and adjust the price in the year after the peakBudgYr to get emissions close to 0, - o45_delay_increase_peakBudgYear(iteration+1) = 1; !! make sure next iteration peakBudgYr is not shifted right again - o45_peakBudgYr_Itr(iteration+1) = o45_peakBudgYr_Itr(iteration); - p45_taxCO2eq_anchor(t2) = max(p45_taxCO2eq_anchor(ttot), !! at least as high as the price in the peakBudgYr - p45_taxCO2eq_anchor(t2) * (o45_factorRescale_taxCO2_afterPeakBudgYr(iteration) / p45_factorRescale_taxCO2_Funneled(iteration) ) !! the full path was already rescaled by p45_factorRescale_taxCO2_Funneled, so adjust the second rescaling - ); - loop(regi, !! this loop is necessary to allow the <-comparison in the next if statement - if( p45_taxCO2eq_anchor_until2150(t2) < p45_taxCO2eq_anchor(t2) , !! check if new price would be higher than the price if the peakBudgYr would be one timestep later - display "price increase reached price from path with cm_peakBudgYr one timestep later - downscale to 99%"; - p45_taxCO2eq_anchor(t2) = 0.99 * p45_taxCO2eq_anchor_until2150(t2); !! reduce the new CO2 price to 99% of the price that it would be if the peaking year was one timestep later. The next iteration will show if this is enough, otherwise cm_peakBudgYr will be shifted right - o45_reached_until2150pricepath(iteration) = 1; !! upward CO2 price correction reached the continued price path - check in next iteration if this is high enough. - ); - ); - ); - - display o45_factorRescale_taxCO2_afterPeakBudgYr; - p45_taxCO2eq_anchor(t)$(t.val gt t2.val) = p45_taxCO2eq_anchor(t2) + (t.val - t2.val) * cm_taxCO2_IncAfterPeakBudgYr * sm_DptCO2_2_TDpGtC; !! increase by cm_taxCO2_IncAfterPeakBudgYr per year - - ); !! loop t2$(t2.val eq pm_ttot_val(ttot+1)), !! set t2 to the following time step - ); !! loop ttot$(ttot.val eq cm_peakBudgYr), !! set ttot to the current peakBudgYr - cm_peakBudgYr = o45_peakBudgYr_Itr(iteration+1); !! this has to happen outside the loop, otherwise the loop condition might be true twice - ); !! if o45_delay_increase_peakBudgYear(iteration) = 1, !! if there was a flip-floping in the previous iterations, try to solve this - -*** If functionalForm is linear, re-adjust global anchor trajectory to go through the point (cm_taxCO2_historicalYr, cm_taxCO2_historical) -$ifThen.taxCO2functionalForm4 "%cm_taxCO2_functionalForm%" == "linear" -p45_taxCO2eq_anchor_until2150(t) = s45_taxCO2_historical - + (sum(t2$(t2.val eq cm_peakBudgYr), p45_taxCO2eq_anchor(t2)) - s45_taxCO2_historical) / (cm_peakBudgYr - s45_taxCO2_historicalYr) !! Yearly increase of CO2 price that interpolates between cm_taxCO2_historical in cm_taxCO2_historicalYr and p45_taxCO2eq_anchor in peak year - * (t.val - s45_taxCO2_historicalYr) ; -p45_taxCO2eq_anchor(t)$(t.val le cm_peakBudgYr) = p45_taxCO2eq_anchor_until2150(t); -p45_taxCO2eq_anchor(t)$(t.val gt cm_peakBudgYr) = sum(t2$(t2.val eq cm_peakBudgYr), p45_taxCO2eq_anchor_until2150(t2)) !! CO2 tax in peak budget year - + (t.val - cm_peakBudgYr) * cm_taxCO2_IncAfterPeakBudgYr * sm_DptCO2_2_TDpGtC; !! increase by cm_taxCO2inc_after_peakBudgYr per year -p45_taxCO2eq_anchor(t)$(t.val gt 2110) = p45_taxCO2eq_anchor("2110"); -$endIf.taxCO2functionalForm4 - - display p45_taxCO2eq_anchor, p45_taxCO2eq_anchor_until2150, o45_delay_increase_peakBudgYear, o45_reached_until2150pricepath, o45_peakBudgYr_Itr, o45_pkBudgYr_flipflop, cm_peakBudgYr; - ); !! if cm_emiscen eq 9, -); !! if cm_iterative_target_adj eq 9, +display p45_taxCO2eq_anchor_until2150, p45_taxCO2eq_anchor; +); !! if(cm_iterative_target_adj eq 7, *** Save s45_actualbudgetco2 for having it available in next iteration: s45_actualbudgetco2_last = s45_actualbudgetco2; @@ -420,9 +371,5 @@ $ifthen.lowerBound "%cm_taxCO2_lowerBound_path_gdx_ref%" == "on" $endIf.lowerBound display pm_taxCO2eq; -*** Save pm_taxCO2eq and p45_taxCO2eq_anchor over iterations for debugging -p45_taxCO2eq_iteration(iteration,ttot,regi) = pm_taxCO2eq(ttot,regi); -p45_taxCO2eq_anchor_iteration(iteration,t) = p45_taxCO2eq_anchor(t); - -); +); !! if((cm_emiscen eq 9) AND ((cm_iterative_target_adj eq 5) OR (cm_iterative_target_adj eq 7) OR (cm_iterative_target_adj eq 9)), *** EOF ./modules/45_carbonprice/functionalForm/postsolve.gms diff --git a/modules/45_carbonprice/functionalForm/realization.gms b/modules/45_carbonprice/functionalForm/realization.gms index 106d3250c..01adef33b 100644 --- a/modules/45_carbonprice/functionalForm/realization.gms +++ b/modules/45_carbonprice/functionalForm/realization.gms @@ -20,7 +20,7 @@ *' Part II (Post-peak behaviour): The global anchor trajectory can be adjusted after reaching the peak of global CO2 emissions in cm_peakBudgYr. *' The (initial) choice of cm_peakBudgYr is endogenously adjusted if cm_iterative_target_adj is set to 7 or 9. *' (with iterative_target_adj = 0): after cm_peakBudgYr, the global anchor trajectory increases linearly with fixed annual increase given by cm_taxCO2_IncAfterPeakBudgYr (default = 0, i.e. constant), -*' set cm_peakBudgYr = 2110 to avoid adjustment +*' set cm_peakBudgYr = 2100 to avoid adjustment *' (with iterative_target_adj = 5): no adjustment to the functional form after cm_peakBudgYr *' (with iterative_target_adj = 7): after cm_peakBudgYr, the global anchor trajectory is adjusted so that global net CO2 emissions stay close to zero *' (with iterative_target_adj = 9): after cm_peakBudgYr, the global anchor trajectory increases linearly with fixed annual increase given by cm_taxCO2_IncAfterPeakBudgYr (default = 0, i.e. constant) diff --git a/modules/45_carbonprice/none/not_used.txt b/modules/45_carbonprice/none/not_used.txt index 138db4c18..4021ac8f6 100644 --- a/modules/45_carbonprice/none/not_used.txt +++ b/modules/45_carbonprice/none/not_used.txt @@ -31,7 +31,6 @@ cm_peakBudgYr,input,added by codeCheck sm_D2005_2_D2017,input,not needed fm_taxCO2eqHist,input,not needed sm_budgetCO2eqGlob,input,no iterative target adjustment -sm_globalBudget_dev,input,no iterative target adjustment vm_emiTe,input,no iterative target adjustment vm_emiCdr,input,no iterative target adjustment vm_emiMac,input,no iterative target adjustment @@ -45,3 +44,4 @@ cm_taxCO2_IncAfterPeakBudgYr,input,added by codeCheck cm_budgetCO2from2020,input,no iterative target adjustment pm_taxCO2eq_anchor_iterationdiff,input,no iterative target adjustment pm_taxCO2eq_anchor_iterationdiff_tmp,input,no iterative target adjustment +sm_globalBudget_dev,input,no target adjustement diff --git a/modules/45_carbonprice/temperatureNotToExceed/not_used.txt b/modules/45_carbonprice/temperatureNotToExceed/not_used.txt index 346ec7493..7f79dc042 100644 --- a/modules/45_carbonprice/temperatureNotToExceed/not_used.txt +++ b/modules/45_carbonprice/temperatureNotToExceed/not_used.txt @@ -23,7 +23,6 @@ cm_peakBudgYr,input,added by codeCheck sm_D2005_2_D2017,input,not needed fm_taxCO2eqHist,input,not needed sm_budgetCO2eqGlob,input,no iterative target adjustment -sm_globalBudget_dev,input,no iterative target adjustment vm_emiTe,input,no iterative target adjustment vm_emiCdr,input,no iterative target adjustment vm_emiMac,input,no iterative target adjustment @@ -37,3 +36,4 @@ cm_taxCO2_IncAfterPeakBudgYr,input,added by codeCheck cm_budgetCO2from2020,input,no iterative target adjustment pm_taxCO2eq_anchor_iterationdiff,input,no iterative target adjustment pm_taxCO2eq_anchor_iterationdiff_tmp,input,no iterative target adjustment +sm_globalBudget_dev,input,no target adjustement