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

ELEVATE WP4.4 in modul 21 a) import tax extension to carbon-content of imported PEs #1495

Merged
merged 9 commits into from
Dec 22, 2023

Conversation

RahelMA
Copy link
Contributor

@RahelMA RahelMA commented Dec 5, 2023

…priced with national or average carbon price b) revenue recycling; c) no technology learning spill-over (modul 80 nash optimization)

Purpose of this PR

ELEVATE WP4.4 "Energy autarchy and the green technology race - is climate the winner?​"

Protectionist measures:

modules/21_tax:

Import tax: extension of import tax q21_taxrevImport that enables import tax of traded PE with world market prices

Introduces possibility to tax imported PEs based on their carbon-content. (i.e emissions associated with imports of energy carriers) with carbon prices.

  1. with the regional carbon price; Switch: set cm_import_tax to CO2taxmarkup
  2. maximum value between regional carbon price or average global carbon price; Switch: set cm_import_tax to avCO2taxmarkup

Note: This option leads to double taxation of imported PEs (import tax at border + REMIND's normal CO2 tax).

Revenue recycling of import tax for additional investments in renewables
Narrative: Extra revenues from the import tax are used for extra investment in green and low-carbon technologies.

Implementation: Investments in wind, solar and storage equal investments from reference scenario with tax and no revenue recycling plus the revenues received from the tax.

Switch: Set cm_taxrc_RE to REdirect

no technology learning spill-over (modules/80_optimization/nash)

Narrative: Technology autarchy (total shut-down of global technology spillover effects)​

Implementation: Fixing the level of pm_capCumForeign to the value from year 2020. After 2020, technology learning based only on regional capacity.

Switch: Set cm_LearningSpillover to 0

Type of change

(Make sure to delete from the Type-of-change list the items not relevant to your PR)

  • Bug fix
  • Refactoring
  • New feature
  • Minor change (default scenarios show only small differences)
  • Fundamental change
  • This change requires a documentation update

Checklist:

  • My code follows the coding etiquette
  • I performed a self-review of my own code
  • I explained my changes within the PR, particularly in hard-to-understand areas
  • I checked that the in-code documentation is up-to-date
  • I adjusted the reporting in remind2 where it was needed
  • I adjusted forbiddenColumnNames in readCheckScenarioConfig.R in case the PR leads to deprecated switches
  • All automated model tests pass (FAIL 0 in the output of make test)
  • The changelog CHANGELOG.md has been updated correctly

Further information (optional):

  • Test runs are here:
    \clusterfs\tmp\rahelma\ElevateWP4\remind3.2\CarbonPricing\remind\output

Import tax

  • Comparison of results (what changes by this PR?):
    image
    Note. Emissions reduction by import tax on carbon content of imported fossil fuels. The effect is further enhanced if revenues are used for additional investments in renewables & storage (revenue recycling).

no technology learning spill-over
image
If tax on carbon-content of PE imports is combined with no further technology cooperation as of 2020 (NDC_avtax_nTecC: only regional learning) emissions are lower than in the NDC only case, but higher than in the NDC_avtax case with global learning.

Investment costs solar PV
image

rahelMA and others added 3 commits December 5, 2023 16:17
…priced with national or average carbon price b) revenue recycling; modul 80 nash optimization no technology learning (fix foreign cap to 2020 level)
@sophiefuchs sophiefuchs changed the title ELEVATE WP4.4 in modul 21 a) import tax extention to imported carbon … ELEVATE WP4.4 in modul 21 a) import tax extension to carbon-content of imported PEs Dec 8, 2023
@RahelMA RahelMA self-assigned this Dec 8, 2023
Copy link
Contributor

@orichters orichters left a comment

Choose a reason for hiding this comment

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

Fine from my side, but I did not check the latest latest version.

I did:

  • the regexp adjustments, correcting errors
  • delete engage config
  • adjustments in prepare.R and checkFixCfg

@@ -1370,11 +1378,18 @@ $setglobal cm_steel_secondary_max_share_scenario off !! def off , switch on for
*** cm_import_tax
*** set tax on imports for specific regions on traded energy carriers
*** as a fraction of import price
*** example: "EUR.pebiolc 0.5" means bioenergy imports to EUR see 50% tax on top of world market price.
*** example: "EUR.worldPricemarkup.pebiolc 0.5" means bioenergy imports to EUR see 50% tax on top of world market price.
Copy link
Contributor

Choose a reason for hiding this comment

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

please change to EUR.pebiolc.worldPricemarkup.

@@ -67,7 +67,8 @@ checkFixCfg <- function(cfg, remindPath = ".", testmode = FALSE) {
# count errors
if (! is.null(errormsg)) {
errorsfound <- errorsfound + 1
if (testmode) warning(errormsg) else message(errormsg)
message(errormsg)
Copy link
Contributor

Choose a reason for hiding this comment

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

errors were just summarized in "there were 30 warnings" in start.R --> useless

@@ -48,7 +48,7 @@ checkFixCfg <- function(cfg, remindPath = ".", testmode = FALSE) {
# how parameter n is defined in main.gms
paramdef <- paste0("^([ ]*", n, "[ ]*=|\\$setglobal[ ]+", n, " )")
# filter fitting parameter definition from code snippets containing regexp
filtered <- grep(paste0(paramdef, ".*regexp[ ]*=[ ]*"), code, value = TRUE)
filtered <- grep(paste0(paramdef, ".*regexp[ ]*=[ ]*"), code, value = TRUE, ignore.case = TRUE)
if (length(filtered) == 1) {
Copy link
Contributor

Choose a reason for hiding this comment

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

identify setGlobal and setglobal

@@ -1242,7 +1250,7 @@ $setGlobal cm_oil_scen medOil !! def = medOil !! regexp = lowOil|medOi
*** (lowGas): low
*** (medGas): medium
*** (highGas): high
$setGlobal cm_gas_scen medGas !! def = medGas !! regexp = low|medium|high
$setGlobal cm_gas_scen medGas !! def = medGas !! regexp = lowGas|medGas|highGas
Copy link
Contributor

Choose a reason for hiding this comment

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

some fixes to regexp because they were wrong

@RahelMA RahelMA marked this pull request as ready for review December 8, 2023 16:49
;
cm_LearningSpillover = 1; !! def 1 = Learningspillover activated (set to 0 to deactivate)
*'
*' * if Learningspillover is deactivated, foreign capacity is set to the level of 2020 in technology learning.
Copy link
Contributor

Choose a reason for hiding this comment

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

I would add something like: "This means that in the model, each region's learning depends on its OWN additional capacity investment after 2020 in comparison to the GLOBAL cumulative capacity until 2020, so for small regions learning is very slow. This is a very pessimistic interpretation of 'no learning spillovers', as every region has to follow the global learning curve"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you, that is very helpful. Just for my understanding, what do you mean by "every region has to follow the global learning curve"? This would not hold anymore if cm_LearningSpillover = 0, or?

Copy link
Contributor

Choose a reason for hiding this comment

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

with "follow the global learning curve" I mean that in cm_learningSpillover = 0 a country only manages to "double capacity" (which is the moment that the costs are reduced by the learning rate value) when its own capacity addition is equal to the GLOBAL capacity in 2020.

so I think my initial formulation can be misunderstood - maybe "as every region has to climb up the global learning curve all by itself" is better?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great, thank you for the further explanation. We have added your suggestion in main.gms, see last commit.

*' 3. "avCO2taxmarkup" = import tax level * max( national carbon price, average carbonprice) * imported carbon by carrier
* NOTE: In case of "CO2taxmarkup" and "avCO2taxmarkup" there is double-taxation of the CO2-content of the imported energy carrier: Once when being imported (at the border) and once when being converted to Secondary Energy (normal CO2price applied by REMIND)
***---------------------------------------------------------------------------
sum(tax_import_type_21, p21_tau_Import(t, regi, tradePe, tax_import_type_21)$sameas(tax_import_type_21, "worldPricemarkup")
Copy link
Contributor

@robertpietzcker robertpietzcker Dec 13, 2023

Choose a reason for hiding this comment

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

I am confused by the splitting of this code.

If I understand it correctly, the equation has three different right sides, depending on whether tax_import_type_21 is a, b or c.
I would find it clearer to write each of the options individually and put one "$$sameas(tax_import_type_21,a)" behind it, but not have the $ command twice in each version of the right side:
so instead of
p21_tau_Import(t, regi, tradePe, tax_import_type_21)$sameas(tax_import_type_21, "CO2taxmarkup") * pm_taxCO2eqSum(t,regi) * pm_cintraw(tradePe) * vm_Mport(t,regi,tradePe) - p21_taxrevImport0(t,regi,tradePe,tax_import_type_21)$sameas(tax_import_type_21, "CO2taxmarkup")
I would write

+ (  p21_tau_Import(t, regi, tradePe, tax_import_type_21) * pm_taxCO2eqSum(t,regi) * pm_cintraw(tradePe) * vm_Mport(t,regi,tradePe) 
  - p21_taxrevImport0(t,regi,tradePe,tax_import_type_21)
   )$sameas(tax_import_type_21, "CO2taxmarkup")

(and the same for the other two cases.
For me this makes it easier to see that this is really just a way of saying "only one of these 3 versions will be active, and you don't need to look into the contents of the ones that are not active"

Copy link
Contributor

Choose a reason for hiding this comment

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

(and I would add a line break after the initial opening of the sum to show clearly these are three separate cases:

sum(tax_import_type_21, 
  (  p21_tau_Import(t, regi, tradePe, tax_import_type_21) * pm_pvp(t,tradePe) / pm_pvp(t,"good") * vm_Mport(t,regi,tradePe) 
    - p21_taxrevImport0(t,regi,tradePe,tax_import_type_21)
  )$sameas(tax_import_type_21, "worldPricemarkup")

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice code cleaning, thank you! We have changed the equation according to your suggestion, see last commit!

@robertpietzcker
Copy link
Contributor

I added a number of detailed comments - please check/reply.

For future PRs: I think it would be better to have this as 3 different PRs - each one changes an aspect of the code, and together there is so much change that it becomes a bit difficult to review. (Sometimes things are so interconnected that it is impossible to split, but here eg the learning would have been easy to do in a separate branch)

also, to be able to understand if the learning part does what it is supposed to do, it would be great to have a plot with eg PV capital costs in CHA and JPN plotted in two NPi runs that are identical except for once having learning spillovers turned on and turned off.
(and best of all would be a plot of capital costs over cumulative capacity in that region in the two scenarios)

Copy link
Contributor

@robertpietzcker robertpietzcker left a comment

Choose a reason for hiding this comment

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

I added a number of concrete comments and questions

*' 3. "avCO2taxmarkup" = import tax level * max( national carbon price, average carbonprice) * imported carbon by carrier
* NOTE: In case of "CO2taxmarkup" and "avCO2taxmarkup" there is double-taxation of the CO2-content of the imported energy carrier: Once when being imported (at the border) and once when being converted to Secondary Energy (normal CO2price applied by REMIND)
***---------------------------------------------------------------------------
sum(tax_import_type_21, p21_tau_Import(t, regi, tradePe, tax_import_type_21)$sameas(tax_import_type_21, "worldPricemarkup")
Copy link
Contributor

Choose a reason for hiding this comment

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

(and I would add a line break after the initial opening of the sum to show clearly these are three separate cases:

sum(tax_import_type_21, 
  (  p21_tau_Import(t, regi, tradePe, tax_import_type_21) * pm_pvp(t,tradePe) / pm_pvp(t,"good") * vm_Mport(t,regi,tradePe) 
    - p21_taxrevImport0(t,regi,tradePe,tax_import_type_21)
  )$sameas(tax_import_type_21, "worldPricemarkup")

@@ -39,7 +39,7 @@ p21_taxrevBio0(ttot,all_regi) "reference level value of bioen
p21_implicitDiscRate0(ttot,all_regi) "reference level value of implicit tax on energy efficient capital"
p21_taxemiMkt0(ttot,all_regi,all_emiMkt) "reference level value of co2 emission taxes per emission market"
p21_taxrevFlex0(ttot,all_regi) "reference level value of flexibility tax"
p21_taxrevImport0(ttot,all_regi,all_enty) "reference level value of import tax"
p21_taxrevImport0(ttot,all_regi,all_enty,tax_import_type_21) "reference level value of import tax"
Copy link
Contributor

Choose a reason for hiding this comment

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

sorry that everyone else before you got the naming wrong and I just noticed it when you copied it - but let's do it better from here on :-)

p21_taxrevImport0(ttot,all_regi,all_enty,tax_import_type_21) "reference level value of import tax"
-> this should be named something like "tax revenues from import tax in the previous iteration"

also,
v21_taxrevImport(ttot,all_regi,all_enty) "tax on energy imports"
should in fact be
"net change vs. last iteration of tax revenues from energy import tax"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's right, we have changed the naming accordingly! See last commit.

p21_tau_Import(t,regi,tradePe) * pm_pvp(t,tradePe) / pm_pvp(t,"good") * vm_Mport(t,regi,tradePe)
- p21_taxrevImport0(t,regi,tradePe)
***---------------------------------------------------------------------------
*' import taxation: 1. "worldPricemarkup" = import tax level * world market price * tradePE import
Copy link
Contributor

Choose a reason for hiding this comment

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

something seems wrong witht his formulation, just based on the units. if you multiply a world market price (in TUSD/TWa) by a tax level in TUSD/TWa times an import amount in TWa, you don't get TUSD but rather TUSD^2/TWa.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@fschreyer we tried to extend your Import tax. Could you perhaps help us with the units in your original formula, which is based on the world market price?

Copy link
Contributor

Choose a reason for hiding this comment

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

Sry, description of tax rate parameter was wrong. The parameter gives the shares of the world market price. Please subsitute

p21_tau_Import(ttot,all_regi,all_enty) "tax on energy imports, currently only works on primary energy levels as those are traded on nash markets [trUSD/TWa]"

by

p21_tau_Import(ttot,all_regi,all_enty) "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]"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you, Felix! We have applied your change in our last commit.

modules/21_tax/on/equations.gms Show resolved Hide resolved
@RahelMA
Copy link
Contributor Author

RahelMA commented Dec 20, 2023

I added a number of detailed comments - please check/reply.

For future PRs: I think it would be better to have this as 3 different PRs - each one changes an aspect of the code, and together there is so much change that it becomes a bit difficult to review. (Sometimes things are so interconnected that it is impossible to split, but here eg the learning would have been easy to do in a separate branch)

also, to be able to understand if the learning part does what it is supposed to do, it would be great to have a plot with eg PV capital costs in CHA and JPN plotted in two NPi runs that are identical except for once having learning spillovers turned on and turned off. (and best of all would be a plot of capital costs over cumulative capacity in that region in the two scenarios)

@RahelMA RahelMA closed this Dec 20, 2023
@RahelMA
Copy link
Contributor Author

RahelMA commented Dec 20, 2023

I added a number of detailed comments - please check/reply.
For future PRs: I think it would be better to have this as 3 different PRs - each one changes an aspect of the code, and together there is so much change that it becomes a bit difficult to review. (Sometimes things are so interconnected that it is impossible to split, but here eg the learning would have been easy to do in a separate branch)
also, to be able to understand if the learning part does what it is supposed to do, it would be great to have a plot with eg PV capital costs in CHA and JPN plotted in two NPi runs that are identical except for once having learning spillovers turned on and turned off. (and best of all would be a plot of capital costs over cumulative capacity in that region in the two scenarios)

@RahelMA RahelMA reopened this Dec 20, 2023
@RahelMA
Copy link
Contributor Author

RahelMA commented Dec 20, 2023

A great thank you to @robertpietzcker!

We highly appreciate your detailed review and effort! With our last commit "Addressed reviewer comments by Robert and Felix" we have tried to address all the mindful comments. After the last changes, we also rerun make test that resulted in 0 FAIL and 0 WARN.

main.gms Outdated
cm_LearningSpillover = 1; !! def 1 = Learningspillover activated (set to 0 to deactivate)
*'
*' * if Learningspillover is deactivated, foreign capacity is set to the level of 2020 in technology learning.
*' * In combination with endogenous carbon pricing (e.g., in NDC), the deactivated Learningspillover will lead to higher overall carbon prices. Can be solved by setting carbonprice to exogenous (config).
Copy link
Contributor

Choose a reason for hiding this comment

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

sorry that I have a tiny other point - could you change the order of the explanations?

if you have a sentence starting "This means that ..." after "In combination with endogenous ...", one could misunderstand the "this" to refer to the previous sentence, and not the "if Learningspillover is deactivated ..."
so I would put the "In combination with endogenous" at the end of the explanation :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I see your point and have changed the order (commit 9)!

Copy link
Contributor

@robertpietzcker robertpietzcker left a comment

Choose a reason for hiding this comment

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

Great, thanks for the changes, and for doing the extra plot with PV costs!
The results look reasonable - until 2050 there is the global learning curve convergence, which means that small regions which apparently are below the global average in 2020 (NEU) actually see a cost increase because the local capacity additions are so small against the global capacity that the additional learning is more than overcompensated by the "convergence of underlying learning parameters". In JPN, the starting point is higher, so we see the opposite effect. In very large regions (OAS, SSA, CHA, IND) the long-term difference to the spillover case is not so large because they deploy a lot of PV capacity.

@RahelMA RahelMA merged commit c8c9951 into remindmodel:develop Dec 22, 2023
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants