diff --git a/CHANGELOG.md b/CHANGELOG.md index 63a1c694a2..e7da122c53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] ### input data/calibration +- **mrremind** new data source for geological CO2 storage potential (split into onshore/offshore and technical vs. limited potentials), replacing the previous LimitCCS output + [[#788](https://github.com/pik-piam/mrremind/pull/788)] ### changed - **45_carbonprice** Use ScenarioMIP settings as new default for regional carbon price differentiation in 45_carbonprice/functionalForm @@ -16,6 +18,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). [[#2231](https://github.com/remindmodel/remind/pull/2231)] - **scripts** Forward `reporting` dir to `reportEmiForClimateAssessement` [[#2287](https://github.com/remindmodel/remind/pull/2229)] +- **core** Distinguish between onshore and offshore transport and storage of captured CO2 + [[#2296](https://github.com/remindmodel/remind/pull/2296)] +- **reporting** Distinguish between onshore and offshore transport and storage of captured CO2 + [[#777](https://github.com/pik-piam/remind2/pull/777)] ### added - **40_techpol** implement renewable energy share targets for NPi2025 realization based on NewClimate policy protocol diff --git a/DESCRIPTION b/DESCRIPTION index ef40ebc440..d4df51bba4 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -60,7 +60,7 @@ Imports: raster, readr, readxl, - remind2 (>= 1.186.0), + remind2 (>= 2.0.3), remindClimateAssessment (>= 0.1.0), renv (>= 1.1.1), reshape2, diff --git a/config/default.cfg b/config/default.cfg index c1d9b08614..c9c801a2c9 100644 --- a/config/default.cfg +++ b/config/default.cfg @@ -28,10 +28,10 @@ cfg$regionmapping <- "config/regionmappingH12.csv" cfg$extramappings_historic <- "" #### Current input data revision (.) #### -cfg$inputRevision <- "7.81" +cfg$inputRevision <- "7.84" #### Current CES parameter and GDX revision (commit hash) #### -cfg$CESandGDXversion <- "867f557491d5f3e72030799648c5eeac03f40de2" +cfg$CESandGDXversion <- "fb20462c942811c4bd9b668f7d10126640116ff6" #### Path to a renv.lock file to restore a project's dependencies from. If NULL, all R packages in their currently installed version will be used. cfg$UseThisRenvLock <- NULL diff --git a/core/bounds.gms b/core/bounds.gms index ba75e39480..54a04465d5 100755 --- a/core/bounds.gms +++ b/core/bounds.gms @@ -309,7 +309,7 @@ vm_cap.fx("2020",regi,te,rlf) $ (teBio(te) and teCCS(te)) = 0; *' switch to deactivate carbon sequestration if(c_ccsinjecratescen = 0, - vm_co2CCS.fx(t,regi_capturescen,"cco2","ico2","ccsinje","1") = 0; + vm_co2CCS.fx(t,regi_capturescen,"cco2","ico2",te,rlf) $ teCCS2rlf(te,rlf) = 0; ); *' bound on maximum annual carbon storage by region @@ -318,7 +318,8 @@ if(c_ccsinjecratescen > 0, *' DK 20100929: default value (pm_ccsinjecrate= 0.5%) is consistent with Interview Gerling (BGR) *' (http://www.iz-klima.de/aktuelles/archiv/news-2010/mai/news-05052010-2/): *' 12 Gt storage potential in Germany, 50-75 Mt/a injection => 60 Mt/a => 60/12000=0.005 - vm_co2CCS.up(t,regi,"cco2","ico2","ccsinje","1") = pm_dataccs(regi,"quan","1") * pm_ccsinjecrate(regi); + vm_co2CCS.up(t,regi,"cco2","ico2","ccsinjeon","1") = pm_dataccs(regi,"quan","ccsinjeon") * pm_ccsinjecrate(regi); + vm_co2CCS.up(t,regi,"cco2","ico2","ccsinjeoff","1") = pm_dataccs(regi,"quan","ccsinjeoff") * pm_ccsinjecrate(regi); *** Lower limit for 2020-2030 is capacities of all projects that are operational (2020-2030) from project data base *** Upper limit for 2025 and 2030 additionally includes all projects under construction and 30% @@ -328,11 +329,12 @@ if(c_ccsinjecratescen > 0, *** Potential of EU27 regions is pooled and redistributed according to GDP (Only upper limit for 2030) *** Norway and UK announced to store CO2 for EU27 countries. So 50% of Norway and UK potential in 2030 is attributed to EU27-Pool if(not cm_emiscen = 1, !! cm_emiscen 1 = BAU - vm_co2CCS.lo(t,regi,"cco2","ico2","ccsinje","1") $ (t.val <= 2030) = s_MtCO2_2_GtC * p_boundCapCCS(t,regi,"operational") $ (t.val <= 2030); - vm_co2CCS.up(t,regi,"cco2","ico2","ccsinje","1") $ (t.val <= 2030) = s_MtCO2_2_GtC * ( + vm_co2CCS.lo(t,regi,"cco2","ico2","ccsinjeon","1") $ (t.val <= 2030) = s_MtCO2_2_GtC * p_boundCapCCS(t,regi,"operational") $ (t.val <= 2030); + vm_co2CCS.up(t,regi,"cco2","ico2","ccsinjeon","1") $ (t.val <= 2030) = s_MtCO2_2_GtC * ( p_boundCapCCS(t,regi,"operational") $ (t.val <= 2030) + p_boundCapCCS(t,regi,"construction") $ (t.val <= 2030) + p_boundCapCCS(t,regi,"planned") $ (t.val <= 2030) * c_fracRealfromAnnouncedCCScap2030); + !! DKX: assumptions for ccsinjeoff ); ); @@ -344,7 +346,7 @@ if(cm_emiscen = 1, if(cm_ccapturescen = 2, !! no carbon capture at all vm_cap.fx(t,regi_capturescen,teCCS,rlf) = 0; - vm_cap.fx(t,regi_capturescen,"ccsinje",rlf) = 0; + vm_cap.fx(t,regi_capturescen,te,rlf) $ teCCS2rlf(te,rlf) = 0; elseif(cm_ccapturescen = 3), !! no bio carbon capture: vm_cap.fx(t,regi_capturescen,te,rlf) $ (teCCS(te) and teBio(te)) = 0; elseif(cm_ccapturescen = 4), !! no carbon capture in the electricity sector diff --git a/core/datainput.gms b/core/datainput.gms index ce8126ff9e..367be85473 100644 --- a/core/datainput.gms +++ b/core/datainput.gms @@ -161,7 +161,7 @@ fm_dataglob("learn", te)$(sameAs(te, "biopyronly") OR sameAs(te, "biopyrhe") OR $ifthen.c_techAssumptScen "%c_techAssumptScen%" == "SSP1" *** hampers technologies with CCS or FT *** TODO: add industry ccs technologies bfcc and idrcc - loop(te $ (teCCS(te) or teFischerTropsch(te) or sameas(te,"ccsinje")), + loop(te $ (teCCS(te) or teFischerTropsch(te) or teccsinje(te)), !! DKX: assumptions correct? fm_dataglob("inco0",te) = 1.3 * fm_dataglob("inco0",te); ); *** hampers nuclear a lot @@ -212,7 +212,7 @@ $elseif.c_techAssumptScen "%c_techAssumptScen%" == "SSP3" $elseif.c_techAssumptScen "%c_techAssumptScen%" == "SSP5" *** favours technologies with CCS or FT - loop(te $ (teCCS(te) or teFischerTropsch(te) or sameas(te,"ccsinje")), + loop(te $ (teCCS(te) or teFischerTropsch(te) or teccsinje(te)), !! DKX: assumptions correct? fm_dataglob("inco0",te) = 0.9 * fm_dataglob("inco0",te); ); *** hampers nuclear @@ -240,12 +240,16 @@ $endif.c_techAssumptScen ***--------------------------------------------------------------------------- *** cm_ccsinjeCost cost scenarios *** Warning: it applies absolute values; only use it in combination with default c_techAssumptScen SSP2. -*** low estimate: ccsinje cost prior to 03/2024; i.e. ~11 USD/tCO2 in 2025, decreasing to ~7.5USD/tCO2 as of 2035 -$if "%cm_ccsinjeCost%" == "low" fm_dataglob("tech_stat","ccsinje") = 2; -$if "%cm_ccsinjeCost%" == "low" fm_dataglob("inco0","ccsinje") = 220; -$if "%cm_ccsinjeCost%" == "low" fm_dataglob("constrTme","ccsinje") = 0; +*** low estimate: ccsinjeon cost prior to 03/2024; i.e. ~11 USD/tCO2 in 2025, decreasing to ~7.5USD/tCO2 as of 2035 +$if "%cm_ccsinjeCost%" == "low" fm_dataglob("tech_stat","ccsinjeon") = 2; +$if "%cm_ccsinjeCost%" == "low" fm_dataglob("inco0","ccsinjeon") = 220; +$if "%cm_ccsinjeCost%" == "low" fm_dataglob("constrTme","ccsinjeon") = 0; +$if "%cm_ccsinjeCost%" == "low" fm_dataglob("tech_stat","ccsinjeoff") = 2; !! DKX: assumptions +$if "%cm_ccsinjeCost%" == "low" fm_dataglob("inco0","ccsinjeoff") = 330; !! DKX: assumptions +$if "%cm_ccsinjeCost%" == "low" fm_dataglob("constrTme","ccsinjeoff") = 0; !! DKX: assumptions *** high estimate: ~20USD/tCO2 (constant), assuming upper end of storage cost and long transport distances -$if "%cm_ccsinjeCost%" == "high" fm_dataglob("inco0","ccsinje") = 550; +$if "%cm_ccsinjeCost%" == "high" fm_dataglob("inco0","ccsinjeon") = 550; +$if "%cm_ccsinjeCost%" == "high" fm_dataglob("inco0","ccsinjeoff") = 825; !! DKX: assumptions *** cm_VRE_supply_assumptions: Modify learning and floor costs for electricity storage and production of VRE @@ -1180,13 +1184,25 @@ loop(te, teEtaConst(te) = not teEtaIncr(te); display teEtaIncr; -*** import regionalized CCS constraints: -table pm_dataccs(all_regi,char,rlf) "maximum CO2 storage capacity using CCS technology. Unit: GtC" +*** import regionalized storage potential: +table f_geoStorPot(all_regi,char) "different categories of geological storage potential for CO2. Unit: GtC" $ondelim -$include "./core/input/pm_dataccs.cs3r" +$include "./core/input/f_geoStorPot.cs3r" $offdelim ; +*** set onshore and offshore storage potential according to c_geoStorPotScen +if (c_geoStorPotScen eq 1, + pm_dataccs(all_regi, "quan", "ccsinjeon") = f_geoStorPot(all_regi, "potTechOn"); + pm_dataccs(all_regi, "quan", "ccsinjeoff") = f_geoStorPot(all_regi, "potTechOff"); +elseif (c_geoStorPotScen eq 2), + pm_dataccs(all_regi, "quan", "ccsinjeon") = f_geoStorPot(all_regi, "potLimOn"); + pm_dataccs(all_regi, "quan", "ccsinjeoff") = f_geoStorPot(all_regi, "potLimOff"); +elseif (c_geoStorPotScen eq 3), + pm_dataccs(all_regi, "quan", "ccsinjeon") = f_geoStorPot(all_regi, "mixedOld"); + pm_dataccs(all_regi, "quan", "ccsinjeoff") = 0.00001; +); + ***----------------------------------------------------------------------------- *** adjustment cost parameter ***----------------------------------------------------------------------------- @@ -1283,7 +1299,7 @@ $endif.cm_subsec_model_steel p_adj_coeff(ttot,regi,"MeOH") = 0.5; p_adj_coeff(ttot,regi,"h22ch4") = 0.5; *** CO2 storage and CDR technologies - p_adj_coeff(ttot,regi,"ccsinje") = 1.0; + p_adj_coeff(ttot,regi,teccsinje) = 1.0; p_adj_coeff(ttot,regi,"biopyronly") = 0.55; !! like biochp and bioigcc; p_adj_coeff(ttot,regi,"biopyrhe") = 0.55; !! like biochp and bioigcc; p_adj_coeff(ttot,regi,"biopyrchp") = 0.55; !! like biochp and bioigcc; diff --git a/core/declarations.gms b/core/declarations.gms index 48a1fdfff7..ef69faa23d 100644 --- a/core/declarations.gms +++ b/core/declarations.gms @@ -153,7 +153,7 @@ vm_emiAllMkt(tall,all_regi,all_enty,all_emiMkt) "total emissions per emissi *** ------------- Emissions Positive Variables -------------------------------- positive variables -v_co2capture(ttot,all_regi,all_enty,all_enty,all_te,rlf) "total captured CO2 [GtC/year]" +v_co2capture(ttot,all_regi) "total captured CO2 [GtC/year]" vm_co2CCS(ttot,all_regi,all_enty,all_enty,all_te,rlf) "total CO2 injected into geological storage [GtC/a]" v_co2capturevalve(ttot,all_regi) "total CO2 emitted right after capture [GtC/a], note: used in q_balCCUvsCCS to account for different lifetimes of capture and CCU/CCS te and capacities [GtC/year]" v_ccsShare(ttot,all_regi) "fraction of captured CO2 that is stored geologically [share]" @@ -181,7 +181,7 @@ q_emiTeMkt(ttot,all_regi,all_enty,all_emiMkt) "total energy-emissions per q_emiEnFuelEx(ttot,all_regi,all_enty) "energy emissions from fuel extraction" q_emiAllMkt(ttot,all_regi,all_enty,all_emiMkt) "total regional emissions for each emission market" q_emiCdrAll(ttot,all_regi) "summing over all CDR emissions" -q_balcapture(ttot,all_regi,all_enty,all_enty,all_te) "balance equation for carbon capture" +q_balcapture(ttot,all_regi) "balance equation for carbon capture" q_balCCUvsCCS(ttot,all_regi) "balance equation for captured carbon to CCU or CCS or valve" q_ccsShare(ttot,all_regi) "calculate the share of captured CO2 that is stored geologically" ; @@ -556,7 +556,7 @@ $ifthen.tech_CO2capturerate not "%c_tech_CO2capturerate%" == "off" p_tech_co2capturerate(all_te) "Technology specific CO2 capture rate, fraction of carbon from input fuel that is captured [share]" / %c_tech_CO2capturerate% / p_PECarriers_CarbonContent(all_enty) "Carbon content of PE carriers [GtC/TWa]" $endif.tech_CO2capturerate -pm_dataccs(all_regi,char,rlf) "maximum CO2 storage capacity using CCS technology. [GtC]" +pm_dataccs(all_regi,char,all_te) "maximum CO2 storage capacity using CCS technology. [GtC]" pm_ccsinjecrate(all_regi) "Regional CCS injection rate factor. [1/year]." p_extRegiccsinjecrateRegi(ext_regi) "Regional CCS injection rate factor. [1/year]. (extended regions)" ; diff --git a/core/equations.gms b/core/equations.gms index 42d3e93ce1..4b19d20953 100644 --- a/core/equations.gms +++ b/core/equations.gms @@ -142,11 +142,11 @@ q_balSe(t,regi,enty2)$( entySe(enty2) AND (NOT (sameas(enty2,"seel"))) ).. * vm_prodFe(t,regi,enty4,enty5,te) ) + sum(pc2te(enty,enty3,te,enty2), - sum(teCCS2rlf(te,rlf), - pm_prodCouple(regi,enty,enty3,te,enty2) - * vm_co2CCS(t,regi,enty,enty3,te,rlf) - ) - ) + sum(teCCS2rlf(te,rlf), + pm_prodCouple(regi,enty,enty3,te,enty2) + * vm_co2CCS(t,regi,enty,enty3,te,rlf) + ) + ) *** add (reused gas from waste landfills) to segas to not account for CO2 *** emissions - it comes from biomass + ( s_MtCH4_2_TWa @@ -572,7 +572,7 @@ q_emiTe(t,regi,emiTe(enty)).. *' transformations within the chain of CCS steps (Leakage). ***----------------------------------------------------------------------------- q_emiTeDetailMkt(t,regi,enty,enty2,te,enty3,emiMkt)$( - emi2te(enty,enty2,te,enty3) + emi2te(enty,enty2,te,enty3) !! emi2te = cco2.ico2.ccsinje.co2 OR (pe2se(enty,enty2,te) AND sameas(enty3,"cco2")) ) .. vm_emiTeDetailMkt(t,regi,enty,enty2,te,enty3,emiMkt) =e= @@ -581,7 +581,7 @@ q_emiTeDetailMkt(t,regi,enty,enty2,te,enty3,emiMkt)$( pm_emifac(t,regi,enty,enty2,te,enty3) * vm_demPe(t,regi,enty,enty2,te) ) - + sum((ccs2Leak(enty,enty2,te,enty3),teCCS2rlf(te,rlf)), + + sum((ccs2Leak(enty,enty2,te,enty3),teCCS2rlf(te,rlf)), !! ccs2Leak = cco2.ico2.ccsinje.co2 pm_emifac(t,regi,enty,enty2,te,enty3) * vm_co2CCS(t,regi,enty,enty2,te,rlf) ) @@ -773,7 +773,7 @@ q_emiCdrAll(t,regi).. + ( !! pe2se-BECC sum(emiBECCS2te(enty,enty2,te,enty3),vm_emiTeDetail(t,regi,enty,enty2,te,enty3)) !! positive value !! + gross DACC - - sum(teCCS2rlf(te,rlf), vm_emiCdrTeDetail(t, regi, "dac"))) !! negative value + - vm_emiCdrTeDetail(t, regi, "dac")) !! negative value !! scaled by the fraction that gets stored geologically * v_ccsShare(t,regi) !! 2. gross CDR from Enhanced Weathering @@ -880,15 +880,19 @@ q_budgetCO2eqGlob$(cm_emiscen=6).. ***--------------------------------------------------------------------------- *' Definition of carbon capture : ***--------------------------------------------------------------------------- -q_balcapture(t,regi,ccs2te(ccsCo2(enty),enty2,te)) .. - sum(teCCS2rlf(te,rlf), v_co2capture(t,regi,enty,enty2,te,rlf)) + +***q_balcapture(t,regi, enty, enty2, te) +***q_balcapture(t,regi,"cco2","ico2","ccsinjeon") + +q_balcapture(t,regi) .. + v_co2capture(t,regi) =e= !! carbon captured in energy sector - sum(emi2te(enty3,enty4,te2,enty), - vm_emiTeDetail(t,regi,enty3,enty4,te2,enty) + sum(emi2te(enty3,enty4,te2,"cco2"), + vm_emiTeDetail(t,regi,enty3,enty4,te2,"cco2") ) !! carbon captured from CDR technologies in CDR module - + sum(teCCS2rlf(te,rlf), vm_co2capture_cdr(t,regi,enty,enty2,te,rlf)) + + sum(teCCS2rlf(te,rlf), vm_co2capture_cdr(t,regi,"cco2","ico2",te,rlf)) !! carbon captured from industry + sum(emiInd37, vm_emiIndCCS(t,regi,emiInd37)) + sum((sefe(entySe,entyFe),emiMkt)$( @@ -904,7 +908,7 @@ q_balcapture(t,regi,ccs2te(ccsCo2(enty),enty2,te)) .. *' atmosphere) ***--------------------------------------------------------------------------- q_balCCUvsCCS(t,regi) .. - sum(teCCS2rlf(te,rlf), v_co2capture(t,regi,"cco2","ico2",te,rlf)) + v_co2capture(t,regi) =e= sum(teCCS2rlf(te,rlf), vm_co2CCS(t,regi,"cco2","ico2",te,rlf)) + sum(teCCU2rlf(te,rlf), vm_co2CCUshort(t,regi,"cco2","ccuco2short",te,rlf)) @@ -912,7 +916,7 @@ q_balCCUvsCCS(t,regi) .. ; q_ccsShare(t,regi) .. - sum(teCCS2rlf(te, rlf), v_co2capture(t, regi, "cco2", "ico2", "ccsinje", rlf)) * + v_co2capture(t,regi) * v_ccsShare(t,regi) =e= sum(teCCS2rlf(te, rlf), vm_co2CCS(t, regi, "cco2", "ico2", te, rlf)) @@ -922,10 +926,10 @@ q_ccsShare(t,regi) .. *' Definition of the CCS transformation chain: ***--------------------------------------------------------------------------- -q_limitCCS(regi,ccs2te2(enty,"ico2",te),rlf)$teCCS2rlf(te,rlf).. +q_limitCCS(regi,ccs2te(enty,"ico2",te),rlf)$teCCS2rlf(te,rlf).. sum(ttot $(ttot.val ge 2005), pm_ts(ttot) * vm_co2CCS(ttot,regi,enty,"ico2",te,rlf)) =l= - pm_dataccs(regi,"quan",rlf); + pm_dataccs(regi,"quan",te); ***--------------------------------------------------------------------------- diff --git a/core/input/files b/core/input/files index 0461256498..0cabf46930 100644 --- a/core/input/files +++ b/core/input/files @@ -38,7 +38,7 @@ p_macBaseVanv.cs4r p_macPolCO2luc.cs4r p_boundCapCCS.cs4r p_boundCapBiochar.cs4r -pm_dataccs.cs3r +f_geoStorPot.cs3r f_fedemand.cs4r f_fedemand_build.cs4r pm_NuclearConstraint.cs4r diff --git a/core/input/generisdata_tech.prn b/core/input/generisdata_tech.prn index 9f9946f0d6..1d89c09188 100644 --- a/core/input/generisdata_tech.prn +++ b/core/input/generisdata_tech.prn @@ -154,17 +154,17 @@ lifetime 30 30 45 45 45 *** carbon management -+ ccsinje weathering dac oae_ng oae_el -tech_stat 0 4 -inco0 350 0.01 18800 200 400 -floorcost 4800 -constrTme 3 -lifetime 40 20 20 25 25 -mix0 1.00 -eta 1.00 1.00 1.00 1.00 1.00 -omf 0.06 0.84 0.025 0.35 0.17 -ccap0 0.0008 -learn 0.15 ++ ccsinjeon ccsinjeoff weathering dac oae_ng oae_el +tech_stat 0 0 4 +inco0 350 525 0.01 18800 200 400 +floorcost 4800 +constrTme 3 5 +lifetime 40 40 20 20 25 25 +mix0 1.00 1.00 +eta 1.00 1.00 1.00 1.00 1.00 1.00 +omf 0.06 0.12 0.84 0.025 0.35 0.17 +ccap0 0.0008 +learn 0.15 $ifthen.cm_subsec_model_steel "%cm_subsec_model_steel%" == "processes" diff --git a/core/input/generisdata_vintages.prn b/core/input/generisdata_vintages.prn index d79369e3e8..f179c48b2b 100644 --- a/core/input/generisdata_vintages.prn +++ b/core/input/generisdata_vintages.prn @@ -147,8 +147,8 @@ $offtext + storspv storwindon storwindoff storcsp gridspv gridwindon gridwindoff gridcsp 1 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 -+ ccsinje -1 1.0 ++ ccsinjeon ccsinjeoff +1 1.0 1.0 + tdsyngas tdsyngat tdsynhos tdsynpet tdsyndie 1 1.0 1.0 1.0 1.0 1.0 diff --git a/core/postsolve.gms b/core/postsolve.gms index 079224422c..cbcd256080 100644 --- a/core/postsolve.gms +++ b/core/postsolve.gms @@ -103,7 +103,7 @@ pm_PEPrice(ttot,regi,entyPe)$(abs (qm_budget.m(ttot,regi)) gt sm_eps) = q_balPe.m(ttot,regi,entyPe) / qm_budget.m(ttot,regi); *** calculate share of stored CO2 from captured CO2 -pm_share_CCS_CCO2(t,regi) = sum(teCCS2rlf(te,rlf), vm_co2CCS.l(t,regi,"cco2","ico2",te,rlf)) / (sum(teCCS2rlf(te,rlf), v_co2capture.l(t,regi,"cco2","ico2",te,rlf))+sm_eps); +pm_share_CCS_CCO2(t,regi) = sum(teCCS2rlf(te,rlf), vm_co2CCS.l(t,regi,"cco2","ico2",te,rlf)) / (v_co2capture.l(t,regi)+sm_eps); *CG**ML*: capital interest rate diff --git a/core/sets.gms b/core/sets.gms index 9e23165598..160d4df7cc 100755 --- a/core/sets.gms +++ b/core/sets.gms @@ -224,7 +224,8 @@ all_te "all energy technologies, including from modules" tdhes "transmission and distribution for heat to stationary users" tdheb "transmission and distribution for heat to buildings" - ccsinje "injection of co2" + ccsinjeon "transport, injection, and storage of co2 onshore" + ccsinjeoff "transport, injection, and storage of co2 offshore" *** Storage technology: storspv "storage technology for photo voltaic (PV)" storwind "storage technology for wind onshore" @@ -1146,7 +1147,8 @@ te(all_te) "energy technologies" tdh2i "helper technologies (without cost) to avoid sudden H2 use switching in buildings and industry" tdh2b "helper technologies (without cost) to avoid sudden H2 use switching in buildings and industry" - ccsinje "injection of co2, CCS related" + ccsinjeon "transport, injection, and storage of co2 onshore, CCS related" + ccsinjeoff "transport, injection, and storage of co2 offshore, CCS related" storspv "storage technology for photo voltaic" *** storwind "storage technology for wind onshore" @@ -1234,7 +1236,8 @@ teAdj(all_te) "technologies with adjustment costs on capacity addition elh2 "hydrogen elecrolysis" h2turb "hydrogen turbine for electricity production" h2curt "hydrogen production from curtailment" - ccsinje "injection of co2, CCS related" + ccsinjeon "transport, injection, and storage of co2 onshore, CCS related" + ccsinjeoff "transport, injection, and storage of co2 offshore, CCS related" storspv "storage technology for PV" *** storwind "storage technology for wind onshore" @@ -1346,6 +1349,12 @@ te2teCCS(all_te,all_te) "Map an energy technology to its CCS equivalent" bioh2 . bioh2c "biomass to hydrogen" / +teccsinje(all_te) "transport, storage, and injection of ico2" +/ + ccsinjeon + ccsinjeoff +/ + teNoCCS(all_te) "Technologies without CCS" teChp(all_te) "Technologies that produce seel as main output und sehe as secondary output - dynamically defined" @@ -2238,6 +2247,11 @@ char "characteristics of technologies" batteryVREcapRatio "ratio of battery capacity to storage technology capacity" priceLow "biochar price path assumption" priceHigh "biochar price path assumption" + potTechOff "technical geological storage potential Offshore" + potTechOn "technical geological storage potential Onshore" + potLimOff "limited geological storage potential Offshore" + potLimOn "limited geological storage potential Onshore" + mixedOld "old geological storage potential formerly used in REMIND" / ***----------------------------------------------------------------------------- @@ -2544,7 +2558,8 @@ pc2te(all_enty,all_enty,all_te,all_enty) "mapping for own consumption of tech segabio.fegas.tdbiogas.seel segafos.fegas.tdfosgas.seel pegeo.sehe.geohe.seel - cco2.ico2.ccsinje.seel + cco2.ico2.ccsinjeon.seel + cco2.ico2.ccsinjeoff.seel / *NB* mappings for emissions, capture and leakage emi2te(all_enty,all_enty,all_te,all_enty) " map emissions to technologies" @@ -2650,7 +2665,8 @@ emi2te(all_enty,all_enty,all_te,all_enty) " map emissions to technologies" pebiolc.sebiochar.biopyrliq.co2 segabio.fegas.tdbiogas.ch4 segafos.fegas.tdfosgas.ch4 - cco2.ico2.ccsinje.co2 + cco2.ico2.ccsinjeon.co2 + cco2.ico2.ccsinjeoff.co2 pebiolc.seel.bioigccc.co2 pebiolc.seel.bioigccc.cco2 seliqbio.fehos.tdbiohos.bc @@ -2764,12 +2780,14 @@ emi2fuelMine(all_enty,all_enty,rlf) "missions from fossil fuel extraction" / ccs2te(all_enty,all_enty,all_te) "chain for ccs" / - cco2.ico2.ccsinje + cco2.ico2.ccsinjeon + cco2.ico2.ccsinjeoff / ccs2Leak(all_enty,all_enty,all_te,all_enty) "leakage along ccs chain" / - cco2.ico2.ccsinje.co2 + cco2.ico2.ccsinjeon.co2 + cco2.ico2.ccsinjeoff.co2 / pe2rlf(all_enty,rlf) "map exhaustible energy to grades for qm_fuel2pe" @@ -2844,7 +2862,7 @@ teMat2rlf(all_te,rlf) "mapping for material production technologies to grade teCCS2rlf(all_te,rlf) "mapping for CCS technologies to grades" / - (ccsinje) . 1 + (ccsinjeon,ccsinjeoff) . 1 / teNoTransform2rlf(all_te,rlf) "mapping for no transformation technologies to grades" @@ -2903,7 +2921,6 @@ es2ppfen(all_esty,all_in) "matching ES in ESM to ppfEn in MACRO" ***----------------------------------------------------------------------------- ***----------------------------------------------------------------------------- -alias(ccs2te,ccs2te2); alias(pe2se,pe2se2); alias(se2fe,se2fe2); diff --git a/main.gms b/main.gms index 3ff1951440..4355f08a54 100755 --- a/main.gms +++ b/main.gms @@ -903,6 +903,17 @@ parameter *' * (1) reference (90%) *' * (2) increased capture rate (99%) *' + +Parameter c_geoStorPotScen "select the amount of geological storage potential for CO2 offshore and onshore" +; + +c_geoStorPotScen = 3; !! def = 3 !! regexp = [1-3] + +*' This switch determines the upper bound of the total geological storage potential for CO2 (onshore + offshore). +*' * (1) high: technical potential without any exclusion layers applied +*' * (2) low: applying all exclusion layers described in Gidden 2025, Table S1 of https://zenodo.org/records/15657543 +*' * (3) old: formerly used scenario when there was only one grade + parameter c_export_tax_scen "choose which oil export tax is used in the model. 0 = none, 1 = fix" ; @@ -1104,7 +1115,7 @@ parameter cm_carbonprice_temperatureLimit = 1.8; !! def = 1.8 *' parameter - cm_frac_CCS "tax on carbon transport & storage (ccsinje) to reflect risk of leakage, formulated as fraction of ccsinje O&M costs" + cm_frac_CCS "tax on carbon transport & storage (teccsinje) to reflect risk of leakage, formulated as fraction of O&M costs" ; cm_frac_CCS = 10; !! def = 10 *' @@ -1789,7 +1800,7 @@ $setglobal cm_adj_seed_multiplier off $setglobal cm_adj_coeff_multiplier off *** cm_inco0Factor "change investment costs. [factor]." *' * (off): no scale-factor, use default investment costs (inco0) values -*' * (any value ge 0) list of techs with respective factor to change inco0 value by a multiplication factor. (e.g. "ccsinje 0.5,bioigccc 0.66) +*' * (any value ge 0) list of techs with respective factor to change inco0 value by a multiplication factor. (e.g. "ccsinjeon 0.5,bioigccc 0.66) *' Note: if %cm_techcosts% == "GLO", switch will not work for policy runs, i.e. cm_startyear > 2005, for pc, ngt and ngcc as this gets overwritten in 05_initialCap module $setglobal cm_inco0Factor off !! def = off *** cm_inco0RegiFactor "change investment costs regionalized technology values. [factor]." diff --git a/modules/04_PE_FE_parameters/iea2014/datainput.gms b/modules/04_PE_FE_parameters/iea2014/datainput.gms index 31c6c1ed82..f9d940c06b 100644 --- a/modules/04_PE_FE_parameters/iea2014/datainput.gms +++ b/modules/04_PE_FE_parameters/iea2014/datainput.gms @@ -306,7 +306,8 @@ p04_prodCoupleGlob("pebiolc","seliqbio","bioftcrec","seel") = 0.108; p04_prodCoupleGlob("segabio","fegas","tdbiogas","seel") = -0.05; p04_prodCoupleGlob("segafos","fegas","tdfosgas","seel") = -0.05; p04_prodCoupleGlob("pegeo","sehe","geohe","seel") = -0.3; -p04_prodCoupleGlob("cco2","ico2","ccsinje","seel") = -0.005; +p04_prodCoupleGlob("cco2","ico2","ccsinjeon","seel") = -0.005; +p04_prodCoupleGlob("cco2","ico2","ccsinjeoff","seel") = -0.005; !!DKX assumption correct? *** Co-Production based on Dorndorf et al (in review) p04_prodCoupleGlob("pebiolc","sebiochar","biopyronly","seel") = -0.04; !! 2% of biomass input (Fawzy et al., 2022, https://doi.org/10.1016/j.jclepro.2022.133660) diff --git a/modules/21_tax/on/equations.gms b/modules/21_tax/on/equations.gms index f614c22d6d..971c025c04 100644 --- a/modules/21_tax/on/equations.gms +++ b/modules/21_tax/on/equations.gms @@ -317,9 +317,13 @@ q21_taxrevFlex(t,regi)$( t.val ge max(2010, cm_startyear) ) .. ***--------------------------------------------------------------------------- q21_taxrevCCS(t,regi)$(t.val ge max(2010,cm_startyear)).. v21_taxrevCCS(t,regi) - =e= cm_frac_CCS * pm_data(regi,"omf","ccsinje") * pm_inco0_t(t,regi,"ccsinje") - * ( sum(teCCS2rlf(te,rlf), sum(ccs2te(ccsCo2(enty),enty2,te), vm_co2CCS(t,regi,enty,enty2,te,rlf) ) ) ) - * (1/pm_ccsinjecrate(regi)) * sum(teCCS2rlf(te,rlf), sum(ccs2te(ccsCo2(enty),enty2,te), vm_co2CCS(t,regi,enty,enty2,te,rlf) ) ) / pm_dataccs(regi,"quan","1") !! fraction of injection constraint per year + =e= + cm_frac_CCS + * sum(teCCS2rlf(te,rlf), sum(ccs2te(ccsCo2(enty),enty2,te), + pm_data(regi,"omf",te) * pm_inco0_t(t,regi,te) + * vm_co2CCS(t,regi,enty,enty2,te,rlf) + * vm_co2CCS(t,regi,enty,enty2,te,rlf) / (pm_dataccs(regi,"quan",te) * pm_ccsinjecrate(regi)) !! fraction of injection constraint per year + )) - p21_taxrevCCS0(t,regi) ; diff --git a/modules/21_tax/on/postsolve.gms b/modules/21_tax/on/postsolve.gms index b8ea8879ca..d9f8ad42a5 100644 --- a/modules/21_tax/on/postsolve.gms +++ b/modules/21_tax/on/postsolve.gms @@ -21,9 +21,14 @@ OPTION decimals =3; pm_taxrevGHG0(t,regi) = pm_taxCO2eqSum(t,regi) * (vm_co2eq.l(t,regi) - vm_emiMacSector.l(t,regi,"co2luc")$(cm_multigasscen ne 3)); pm_taxrevCO2Sector0(ttot,regi,emi_sectors) = p21_CO2TaxSectorMarkup(ttot,regi,emi_sectors) * pm_taxCO2eqSum(ttot,regi) * vm_emiCO2Sector.l(ttot,regi,emi_sectors); pm_taxrevCO2LUC0(t,regi) = pm_taxCO2eqSum(t,regi) * vm_emiMacSector.l(t,regi,"co2luc")$(cm_multigasscen ne 3); -p21_taxrevCCS0(ttot,regi) = cm_frac_CCS * pm_data(regi,"omf","ccsinje") * pm_inco0_t(ttot,regi,"ccsinje") - * ( sum(teCCS2rlf(te,rlf), sum(ccs2te(ccsCo2(enty),enty2,te), vm_co2CCS.l(ttot,regi,enty,enty2,te,rlf) ) ) ) - * (1/pm_ccsinjecrate(regi)) * sum(teCCS2rlf(te,rlf), sum(ccs2te(ccsCo2(enty),enty2,te), vm_co2CCS.l(ttot,regi,enty,enty2,te,rlf) ) ) / pm_dataccs(regi,"quan","1"); + +p21_taxrevCCS0(ttot,regi) = cm_frac_CCS + * sum(teCCS2rlf(te,rlf), sum(ccs2te(ccsCo2(enty),enty2,te), + pm_data(regi,"omf",te) * pm_inco0_t(ttot,regi,te) + * vm_co2CCS.l(ttot,regi,enty,enty2,te,rlf) + * vm_co2CCS.l(ttot,regi,enty,enty2,te,rlf) / ( pm_dataccs(regi,"quan",te) * pm_ccsinjecrate(regi)) + )); + pm_taxrevNetNegEmi0(ttot,regi) = s21_frac_NetNegEmi * pm_taxCO2eqSum(ttot,regi) * ( (1 - cm_NetNegEmi_calculation) * vm_emiAllco2neg.l(ttot,regi) + cm_NetNegEmi_calculation * v21_emiAllco2neg_acrossIterations.l(ttot,regi) ); p21_taxrevFE0(ttot,regi) = sum((entyFe,sector)$entyFe2Sector(entyFe,sector), ( p21_tau_fe_tax(ttot,regi,sector,entyFe) + p21_tau_fe_sub(ttot,regi,sector,entyFe) ) diff --git a/modules/21_tax/on/presolve.gms b/modules/21_tax/on/presolve.gms index 8f74fcfe58..f52c5bff6a 100644 --- a/modules/21_tax/on/presolve.gms +++ b/modules/21_tax/on/presolve.gms @@ -27,9 +27,14 @@ p21_tau_so2_tax(ttot,regi)$(ttot.val>2100)=p21_tau_so2_tax("2100",regi); pm_taxrevGHG0(t,regi) = pm_taxCO2eqSum(t,regi) * (vm_co2eq.l(t,regi) - vm_emiMacSector.l(t,regi,"co2luc")$(cm_multigasscen ne 3)); pm_taxrevCO2Sector0(ttot,regi,emi_sectors) = p21_CO2TaxSectorMarkup(ttot,regi,emi_sectors) * pm_taxCO2eqSum(ttot,regi) * vm_emiCO2Sector.l(ttot,regi,emi_sectors); pm_taxrevCO2LUC0(t,regi) = pm_taxCO2eqSum(t,regi) * vm_emiMacSector.l(t,regi,"co2luc")$(cm_multigasscen ne 3); -p21_taxrevCCS0(ttot,regi) = cm_frac_CCS * pm_data(regi,"omf","ccsinje") * pm_inco0_t(ttot,regi,"ccsinje") - * ( sum(teCCS2rlf(te,rlf), sum(ccs2te(ccsCo2(enty),enty2,te), vm_co2CCS.l(ttot,regi,enty,enty2,te,rlf) ) ) ) - * (1/pm_ccsinjecrate(regi)) * sum(teCCS2rlf(te,rlf), sum(ccs2te(ccsCo2(enty),enty2,te), vm_co2CCS.l(ttot,regi,enty,enty2,te,rlf) ) ) / pm_dataccs(regi,"quan","1"); + +p21_taxrevCCS0(ttot,regi) = cm_frac_CCS + * sum(teCCS2rlf(te,rlf), sum(ccs2te(ccsCo2(enty),enty2,te), + pm_data(regi,"omf",te) * pm_inco0_t(ttot,regi,te) + * vm_co2CCS.l(ttot,regi,enty,enty2,te,rlf) + * vm_co2CCS.l(ttot,regi,enty,enty2,te,rlf) / ( pm_dataccs(regi,"quan",te) * pm_ccsinjecrate(regi)) + )); + pm_taxrevNetNegEmi0(ttot,regi) = s21_frac_NetNegEmi * pm_taxCO2eqSum(ttot,regi) * ( (1 - cm_NetNegEmi_calculation) * vm_emiAllco2neg.l(ttot,regi) + cm_NetNegEmi_calculation * v21_emiAllco2neg_acrossIterations.l(ttot,regi) ); p21_emiAllco2neg0(ttot,regi) = vm_emiAllco2neg.l(ttot,regi); p21_emiAllco2neg_acrossIterations0(ttot,regi) = v21_emiAllco2neg_acrossIterations.l(ttot,regi); diff --git a/modules/32_power/IntC/equations.gms b/modules/32_power/IntC/equations.gms index 0881ec88a7..840ecef3fc 100644 --- a/modules/32_power/IntC/equations.gms +++ b/modules/32_power/IntC/equations.gms @@ -18,10 +18,10 @@ q32_balSe(t,regi,enty2)$(sameas(enty2,"seel")).. pm_prodCouple(regi,enty,enty3,te,enty2) * vm_prodSe(t,regi,enty,enty3,te) ) + sum(pc2te(enty4,entyFe(enty5),te,enty2), pm_prodCouple(regi,enty4,enty5,te,enty2) * vm_prodFe(t,regi,enty4,enty5,te) ) - + sum(pc2te(enty,enty3,te,enty2), + + sum(pc2te(enty,enty3,te,enty2), sum(teCCS2rlf(te,rlf), pm_prodCouple(regi,enty,enty3,te,enty2) * vm_co2CCS(t,regi,enty,enty3,te,rlf) ) ) - + vm_Mport(t,regi,enty2) + + vm_Mport(t,regi,enty2) =e= sum(se2fe(enty2,enty3,te), vm_demSe(t,regi,enty2,enty3,te) ) + sum(se2se(enty2,enty3,te), vm_demSe(t,regi,enty2,enty3,te) ) diff --git a/modules/33_CDR/portfolio/declarations.gms b/modules/33_CDR/portfolio/declarations.gms index 83e862e81f..c916f7b1a7 100644 --- a/modules/33_CDR/portfolio/declarations.gms +++ b/modules/33_CDR/portfolio/declarations.gms @@ -77,7 +77,7 @@ q33_emiCDR(ttot,all_regi) "aggregates the (negative) emissions captured by the q33_H2bio_lim(ttot,all_regi) "limits H2 from bioenergy to FE - H2 demand from CDR, i.e. no H2 from bioenergy for DAC" q33_capconst(ttot,all_regi,all_te) "calculates amount of carbon captured by DAC and OAE" q33_cco2_cdr_fromFE(ttot,all_regi,all_te) "calculates the amount of captured CO2 that comes from burning gas" -q33_ccsbal(ttot,all_regi,all_enty,all_enty,all_te) "calculates CCS emissions from CDR technologies" +q33_ccsbal(ttot,all_regi) "calculates CCS emissions from CDR technologies" *** DAC q33_DAC_FEdemand(ttot,all_regi,all_enty) "calculates final energy demand from DAC" diff --git a/modules/33_CDR/portfolio/equations.gms b/modules/33_CDR/portfolio/equations.gms index 0208d94da2..b74b8fdec1 100644 --- a/modules/33_CDR/portfolio/equations.gms +++ b/modules/33_CDR/portfolio/equations.gms @@ -74,8 +74,8 @@ q33_cco2_cdr_fromFE(t, regi, te_ccs33).. *' the second part is CO2 captured from energy usage (OAE or DAC) *' the third part is CO2 captured from calcination for OAE ***--------------------------------------------------------------------------- -q33_ccsbal(t, regi, ccs2te(ccsCo2(enty), enty2, te)).. - sum(teCCS2rlf(te, rlf), vm_co2capture_cdr(t, regi, enty, enty2, te, rlf)) +q33_ccsbal(t, regi).. + sum(teCCS2rlf(te, rlf), vm_co2capture_cdr(t, regi, "cco2", "ico2", te, rlf)) =e= - vm_emiCdrTeDetail(t, regi, "dac") + sm_capture_rate_cdrmodule * ( diff --git a/modules/47_regipol/none/bounds.gms b/modules/47_regipol/none/bounds.gms index 87585ad1f3..60d4c3d867 100644 --- a/modules/47_regipol/none/bounds.gms +++ b/modules/47_regipol/none/bounds.gms @@ -21,7 +21,7 @@ loop(regi$(sameAs(regi,"DEU")), *** only small amount of co2 injection ccs until 2030 in Germany -vm_co2CCS.up(t,regi,"cco2","ico2",te,rlf)$((t.val le 2030) AND (sameas(regi,"DEU"))) = 1e-3; +vm_co2CCS.up(t,regi,"cco2","ico2",te,rlf)$((t.val le 2030) AND (sameas(regi,"DEU"))) = 1e-3; !! DKX assumptions for ccsinjeoff *** no Pe2Se fossil CCS in Germany, if c_noPeFosCCDeu = 1 chosen vm_emiTeDetail.up(t,regi,peFos,entySe,teFosCCS,"cco2")$((sameas(regi,"DEU")) AND (cm_noPeFosCCDeu = 1)) = 1e-4; *** limit German CDR amount (Energy system BECCS, DACCS, EW and negative Landuse Change emissions), conversion from MtCO2 to GtC