Skip to content

Commit

Permalink
Merge pull request #1707 from Renato-Rodrigues/2040_update
Browse files Browse the repository at this point in the history
yet another set of improvements to the emission market convergence algorithm and debugging information
  • Loading branch information
Renato-Rodrigues authored Jul 5, 2024
2 parents 20ad564 + 263ac04 commit 72abc95
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 34 deletions.
5 changes: 5 additions & 0 deletions modules/47_regipol/regiCarbonPrice/datainput.gms
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ p47_taxemiMkt_init(ttot,regi,emiMkt)$(p47_taxCO2eq_ref(ttot,regi) and (NOT(p47_t
);
);

*** initialize required parameter for cm_emiMktTarget slope calculation. This is necessary to allow logical if statement checks not trowing an error before the parameter is assigned for the first time in the postsolve code.
p47_factorRescaleSlope_iter("1","2020","2030",ext_regi,emiMktExt) = 0;
*** initialize required parameter for cm_emiMktTarget rescale oscillation dampening.
p47_factorRescaleemiMktCO2Tax_iter("1","2020","2030",ext_regi,emiMktExt) = 0;

$ENDIF.emiMkt

***---------------------------------------------------------------------------
Expand Down
5 changes: 3 additions & 2 deletions modules/47_regipol/regiCarbonPrice/declarations.gms
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,9 @@ $endif.emiMktTargetType
p47_slopeReferenceIteration_iter(iteration,ttot,ext_regi) "auxiliary parameter to store reference iteration used for calculating slope of current mititgation cost [#]"
pm_factorRescaleemiMktCO2Tax(ttot,ttot2,ext_regi,emiMktExt) "multiplicative tax rescale factor that rescales emiMkt carbon price from iteration to iteration to reach regipol targets [%]"
p47_factorRescaleemiMktCO2Tax_iter(iteration,ttot,ttot2,ext_regi,emiMktExt) "parameter to save rescale factor across iterations for debugging purposes [%]"
p47_clampedRescaleSlope(iteration,ttot,ttot2,ext_regi,emiMktExt) "auxiliary parameter to save the slope value before clamping for debugging purposes [#]"

p47_clampedRescaleSlope_iter(iteration,ttot,ttot2,ext_regi,emiMktExt) "auxiliary parameter to save the slope value before clamping. Useful for debugging purposes [#]"
p47_dampedFactorRescaleemiMktCO2Tax_iter(iteration,ttot,ttot2,ext_regi,emiMktExt) "auxiliary parameter to save the rescale factor value before dampening. Useful for debugging purposes [#]"

*** Parameters necessary to define the CO2 tax curve shape
p47_targetConverged(ttot,ext_regi) "boolean to store if emission target has converged [0 or 1]"
p47_targetConverged_iter(iteration,ttot,ext_regi) "parameter to save p47_targetConverged across iterations [0 or 1]"
Expand Down
97 changes: 66 additions & 31 deletions modules/47_regipol/regiCarbonPrice/postsolve.gms
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,6 @@ loop((ext_regi,ttot)$regiANDperiodEmiMktTarget_47(ttot,ext_regi),
);
);



*** resetting rescale factor for the next iteration
p47_factorRescaleSlope(ttot,ttot2,ext_regi,emiMktExt) = 0;
pm_factorRescaleemiMktCO2Tax(ttot,ttot2,ext_regi,emiMktExt) = 0;
Expand All @@ -268,9 +266,12 @@ loop(ext_regi$regiEmiMktTarget(ext_regi),
loop((ttot,emiMktExt,target_type_47,emi_type_47)$(pm_emiMktTarget(ttot,ttot2,ext_regi,emiMktExt,target_type_47,emi_type_47)),
loop(emiMkt$emiMktGroup(emiMktExt,emiMkt),
loop(regi$regiEmiMktTarget2regi_47(ext_regi,regi),
*** if rescale factor was already calculated for ext_regi, there is no need to recalculate it
continue$(pm_factorRescaleemiMktCO2Tax(ttot,ttot2,ext_regi,emiMktExt));
*** calculating the rescale factor
loop(iteration2$((iteration2.val le iteration.val) and (iteration2.val eq p47_slopeReferenceIteration_iter(iteration,ttot2,ext_regi))), !!reference iteration for slope calculation
*** if it is the first iteration or the reference iteration changed, initialize the rescale factor based on remaining deviation
if(iteration.val - p47_slopeReferenceIteration_iter(iteration,ttot,ext_regi) eq 0,
if((iteration.val - iteration2.val) eq 0,
regiEmiMktRescaleType(iteration,ttot,ttot2,ext_regi,emiMktExt,"squareDev_firstIteration") = YES;
pm_factorRescaleemiMktCO2Tax(ttot,ttot2,ext_regi,emiMktExt) = power(1+pm_emiMktTarget_dev(ttot,ttot2,ext_regi,emiMktExt), 2);
*** else if for the extreme case of a perfect match with no change between the two iterations emisssion taxes used in the slope calculation, in order to avoid a division by zero error assume the rescale factor based on remaining deviation
Expand All @@ -285,48 +286,82 @@ loop(ext_regi$regiEmiMktTarget(ext_regi),
(abs(pm_taxemiMkt_iteration(iteration,ttot2,regi,emiMkt) - pm_taxemiMkt_iteration("1",ttot2,regi,emiMkt)) lt 1e-2)),
regiEmiMktRescaleType(iteration,ttot,ttot2,ext_regi,emiMktExt,"squareDev_smallChange") = YES;
pm_factorRescaleemiMktCO2Tax(ttot,ttot2,ext_regi,emiMktExt) = power(1+pm_emiMktTarget_dev(ttot,ttot2,ext_regi,emiMktExt), 2);
*** else, use previous iteration information to define rescale factor
*** else, calculate rescale factor using quantities and prices slope changes
else
*** if denominator is not close to zero, calculate the price slope in relation to the previous iteration mitigation and price levels
if(NOT(pm_taxemiMkt_iteration(iteration,ttot2,regi,emiMkt) - pm_taxemiMkt_iteration(iteration2,ttot2,regi,emiMkt) eq 0) OR
NOT(abs(pm_taxemiMkt_iteration(iteration,ttot2,regi,emiMkt) - pm_taxemiMkt_iteration(iteration2,ttot2,regi,emiMkt)) lt 1e-2),
regiEmiMktRescaleType(iteration,ttot,ttot2,ext_regi,emiMktExt,"slope_prevIteration") = YES;
*** if denominator in relation to reference is not close to zero, calculate the price slope in relation to the reference iteration mitigation and price levels
if(NOT(abs(pm_taxemiMkt_iteration(iteration,ttot2,regi,emiMkt) - pm_taxemiMkt_iteration(iteration2,ttot2,regi,emiMkt)) lt 1e-2),
regiEmiMktRescaleType(iteration,ttot,ttot2,ext_regi,emiMktExt,"slope_refIteration") = YES;
p47_factorRescaleSlope(ttot,ttot2,ext_regi,emiMktExt) =
(p47_emiMktCurrent_iter(iteration,ttot,ttot2,ext_regi,emiMktExt) - p47_emiMktCurrent_iter(iteration2,ttot,ttot2,ext_regi,emiMktExt))
/
(pm_taxemiMkt_iteration(iteration,ttot2,regi,emiMkt) - pm_taxemiMkt_iteration(iteration2,ttot2,regi,emiMkt));
*** else, calculate the price slope in relation to the first iteration mitigation and price levels
else
regiEmiMktRescaleType(iteration,ttot,ttot2,ext_regi,emiMktExt,"slope_firstIteration") = YES;
p47_factorRescaleSlope(ttot,ttot2,ext_regi,emiMktExt) =
(p47_emiMktCurrent_iter(iteration,ttot,ttot2,ext_regi,emiMktExt) - p47_emiMktCurrent_iter("1",ttot,ttot2,ext_regi,emiMktExt))
/
(pm_taxemiMkt_iteration(iteration,ttot2,regi,emiMkt) - pm_taxemiMkt_iteration("1",ttot2,regi,emiMkt));

);
*** if the slope is positive, recalculate the slope based on the initial iteration instead of the reference one because we assume a trade-off between tax and emission levels
if(p47_factorRescaleSlope(ttot,ttot2,ext_regi,emiMktExt) gt 0,
regiEmiMktRescaleType(iteration,ttot,ttot2,ext_regi,emiMktExt,rescaleType) = NO;
*** else if denominator in relation to first iteration is not close to zero, calculate the price slope in relation to the first iteration mitigation and price levels instead
elseif(NOT(abs(pm_taxemiMkt_iteration(iteration,ttot2,regi,emiMkt) - pm_taxemiMkt_iteration("1",ttot2,regi,emiMkt)) lt 1e-2)),
regiEmiMktRescaleType(iteration,ttot,ttot2,ext_regi,emiMktExt,"slope_firstIteration") = YES;
p47_factorRescaleSlope(ttot,ttot2,ext_regi,emiMktExt) =
(p47_emiMktCurrent_iter(iteration,ttot,ttot2,ext_regi,emiMktExt) - p47_emiMktCurrent_iter("1",ttot,ttot2,ext_regi,emiMktExt))
/
(pm_taxemiMkt_iteration(iteration,ttot2,regi,emiMkt) - pm_taxemiMkt_iteration("1",ttot2,regi,emiMkt));
*** else if there is a previous iteration calculated slope, repeat the previous iteration slope
elseif((iteration.val gt 1) and (p47_slopeReferenceIteration_iter(iteration,ttot,ext_regi) - p47_slopeReferenceIteration_iter(iteration-1,ttot,ext_regi) eq 0)),
regiEmiMktRescaleType(iteration,ttot,ttot2,ext_regi,emiMktExt,"slope_repeatPrev") = YES;
p47_factorRescaleSlope(ttot,ttot2,ext_regi,emiMktExt) = p47_factorRescaleSlope_iter(iteration-1,ttot,ttot2,ext_regi,emiMktExt);
*** else slope is not available, set the rescale factor based on remaining deviation
else
regiEmiMktRescaleType(iteration,ttot,ttot2,ext_regi,emiMktExt,"squareDev_noSlope") = YES;
pm_factorRescaleemiMktCO2Tax(ttot,ttot2,ext_regi,emiMktExt) = power(1+pm_emiMktTarget_dev(ttot,ttot2,ext_regi,emiMktExt), 2);
);
*** clamp slopes values to avoid extreme changes (or no change) on a single iteration (avoid corner cases where other parts of the model changes causing undesirable fluctuations on the calculated slope)
if((p47_factorRescaleSlope(ttot,ttot2,ext_regi,emiMktExt) gt -0.3) OR (p47_factorRescaleSlope(ttot,ttot2,ext_regi,emiMktExt) lt -5),
p47_clampedRescaleSlope(iteration,ttot,ttot2,ext_regi,emiMktExt) = p47_factorRescaleSlope(ttot,ttot2,ext_regi,emiMktExt);
*** if we are using the slope
if(NOT(regiEmiMktRescaleType(iteration,ttot,ttot2,ext_regi,emiMktExt,"squareDev_noSlope")),
*** if the slope is positive
if(p47_factorRescaleSlope(ttot,ttot2,ext_regi,emiMktExt) gt 0,
regiEmiMktRescaleType(iteration,ttot,ttot2,ext_regi,emiMktExt,rescaleType) = NO;
*** if there is a previous iteration calculated slope, repeat the previous iteration slope to avoid the positive value because we assume a trade-off between tax and emission levels
if((iteration.val gt 1) and (p47_slopeReferenceIteration_iter(iteration,ttot,ext_regi) - p47_slopeReferenceIteration_iter(iteration-1,ttot,ext_regi) eq 0),
regiEmiMktRescaleType(iteration,ttot,ttot2,ext_regi,emiMktExt,"slope_repeatPrev_positiveSlope") = YES;
p47_factorRescaleSlope(ttot,ttot2,ext_regi,emiMktExt) = p47_factorRescaleSlope_iter(iteration-1,ttot,ttot2,ext_regi,emiMktExt);
*** else slope is not available, set the rescale factor based on remaining deviation
else
regiEmiMktRescaleType(iteration,ttot,ttot2,ext_regi,emiMktExt,"squareDev_noNonPositiveSlope") = YES;
pm_factorRescaleemiMktCO2Tax(ttot,ttot2,ext_regi,emiMktExt) = power(1+pm_emiMktTarget_dev(ttot,ttot2,ext_regi,emiMktExt), 2);
);
);
*** if we are still using the slope
if(NOT(regiEmiMktRescaleType(iteration,ttot,ttot2,ext_regi,emiMktExt,"squareDev_noNonPositiveSlope")),
*** clamp slopes values to avoid extreme changes (or no change) on a single iteration (avoid corner cases where other parts of the model changes causing undesirable fluctuations on the calculated slope)
if((p47_factorRescaleSlope(ttot,ttot2,ext_regi,emiMktExt) gt -0.3) OR (p47_factorRescaleSlope(ttot,ttot2,ext_regi,emiMktExt) lt -5),
p47_clampedRescaleSlope_iter(iteration,ttot,ttot2,ext_regi,emiMktExt) = p47_factorRescaleSlope(ttot,ttot2,ext_regi,emiMktExt);
);
p47_factorRescaleSlope(ttot,ttot2,ext_regi,emiMktExt) = max(-5,min(-0.3, p47_factorRescaleSlope(ttot,ttot2,ext_regi,emiMktExt)));
*** calculate the tax rescale factor using the above calculated slope
pm_factorRescaleemiMktCO2Tax(ttot,ttot2,ext_regi,emiMktExt) =
(
(pm_emiMktTarget(ttot,ttot2,ext_regi,emiMktExt,target_type_47,emi_type_47) - p47_emiMktCurrent_iter(iteration,ttot,ttot2,ext_regi,emiMktExt))
/
(p47_factorRescaleSlope(ttot,ttot2,ext_regi,emiMktExt) * pm_taxemiMkt_iteration(iteration,ttot2,regi,emiMkt))
) + 1;
);
);
p47_factorRescaleSlope(ttot,ttot2,ext_regi,emiMktExt) = max(-5,min(-0.3, p47_factorRescaleSlope(ttot,ttot2,ext_regi,emiMktExt)));
*** calculate the tax rescale factor using the above calculated slope
pm_factorRescaleemiMktCO2Tax(ttot,ttot2,ext_regi,emiMktExt) =
(
(pm_emiMktTarget(ttot,ttot2,ext_regi,emiMktExt,target_type_47,emi_type_47) - p47_emiMktCurrent_iter(iteration,ttot,ttot2,ext_regi,emiMktExt))
/
(p47_factorRescaleSlope(ttot,ttot2,ext_regi,emiMktExt) * pm_taxemiMkt_iteration(iteration,ttot2,regi,emiMkt))
) + 1;
);
);
*** dampen if rescale oscillates
if( (iteration.val > 3) ,
if ( (
( ( ( p47_factorRescaleemiMktCO2Tax_iter(iteration-1,ttot,ttot2,ext_regi,emiMktExt) - 1 )
* ( pm_factorRescaleemiMktCO2Tax(ttot,ttot2,ext_regi,emiMktExt) - 1 ) ) < 0
) AND !! test if rescale changed from >1 to <1 or vice versa between iteration -1 and current iteration
( ( ( p47_factorRescaleemiMktCO2Tax_iter(iteration-1,ttot,ttot2,ext_regi,emiMktExt) - 1 )
* ( p47_factorRescaleemiMktCO2Tax_iter(iteration-2,ttot,ttot2,ext_regi,emiMktExt) -1 ) ) < 0
) !! test if rescale changed from >1 to <1 or vice versa between iteration -2 and iteration -1
) ,
p47_dampedFactorRescaleemiMktCO2Tax_iter(iteration,ttot,ttot2,ext_regi,emiMktExt) = pm_factorRescaleemiMktCO2Tax(ttot,ttot2,ext_regi,emiMktExt);
pm_factorRescaleemiMktCO2Tax(ttot,ttot2,ext_regi,emiMktExt) =
1 + ( ( pm_factorRescaleemiMktCO2Tax(ttot,ttot2,ext_regi,emiMktExt) - 1 ) / 2 )
; !! this brings the value closer to one. The formulation works reasonably well within the range of 0.5..2
put_utility "msg" / "Reducing pm_factorRescaleemiMktCO2Tax due to oscillation in the previous 3 iterations: ";
put_utility "msg" / ttot.tl " " ttot2.tl " " ext_regi.tl " " emiMktExt.tl " " pm_factorRescaleemiMktCO2Tax(ttot,ttot2,ext_regi,emiMktExt):10:3;
);
);
);
);
);
Expand Down
5 changes: 4 additions & 1 deletion modules/47_regipol/regiCarbonPrice/sets.gms
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ $ifThen.emiMkt not "%cm_emiMktTarget%" == "off"
regiEmiMktTarget(ext_regi) "regions with emiMkt targets" / /
regiANDperiodEmiMktTarget_47(ttot,ext_regi) "regions and periods with emiMkt targets" / /
regiEmiMktTarget2regi_47(ext_regi,all_regi) "regions controlled by emiMkt market set to ext_regi" / /
rescaleType "carbon price scaling types" / "squareDev_firstIteration", "squareDev_perfectMatch", "squareDev_smallChange", "squareDev_noChange", "slope_prevIteration", "slope_firstIteration"/
rescaleType "emi mkt carbon price scaling factor calculation methods" /
"squareDev_firstIteration", "squareDev_perfectMatch", "squareDev_smallChange", "squareDev_noChange",
"slope_refIteration", "slope_firstIteration", "slope_repeatPrev", "slope_repeatPrev_positiveSlope",
"squareDev_noSlope", "squareDev_noNonPositiveSlope"/
regiEmiMktRescaleType(iteration,ttot,ttot,ext_regi,emiMktExt,rescaleType) "saving scaling type used in iteration" / /
convergenceType "emiMkt target non convergence reason" / "lowerThanTolerance", "smallPrice" /
regiEmiMktconvergenceType(iteration,ttot,ttot,ext_regi,emiMktExt,convergenceType) "saving convergence type in iteration" / /
Expand Down

0 comments on commit 72abc95

Please sign in to comment.