Skip to content

Commit

Permalink
Merge pull request remindmodel#1777 from katarkow/OAE_0db5204
Browse files Browse the repository at this point in the history
Add ocean alklinity enhancement
  • Loading branch information
katarkow authored Aug 21, 2024
2 parents ba7fd37 + 978e10c commit 18a8032
Show file tree
Hide file tree
Showing 18 changed files with 240 additions and 151 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- **testthat** fail if manipulating main.gms with default cfg drops/changes switches and comments
[[#1764](https://github.com/remindmodel/remind/pull/1764)] and
[[#1767](https://github.com/remindmodel/remind/pull/1767)]
- **33_CDR** added ocean alkalinity enhancement to the CDR portfolio (OAE is turned off by default)
[[#1777](https://github.com/remindmodel/remind/pull/1777)]

### fixed
- included CCS from plastic waste incineration in CCS mass flows so it is
Expand Down
7 changes: 7 additions & 0 deletions core/datainput.gms
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,9 @@ p_inco0(ttot,regi,te) = s_DpKW_2_TDpTW * p_inco0(ttot,regi,t
fm_dataglob("inco0","csp") = 0.7 * fm_dataglob("inco0","csp");
fm_dataglob("incolearn","csp") = 0.7 * fm_dataglob("incolearn","csp");

*KK* adjust costs for oae from USD/GtCaO to USD/GtC
fm_dataglob("inco0", "oae_ng") = fm_dataglob("inco0", "oae_ng") / (cm_33_OAE_eff / sm_c_2_co2);
fm_dataglob("inco0", "oae_el") = fm_dataglob("inco0", "oae_el") / (cm_33_OAE_eff / sm_c_2_co2);

*** --------------------------------------------------------------------------------
*** Regionalize technology investment cost data
Expand Down Expand Up @@ -1202,6 +1205,8 @@ loop(ttot$(ttot.val ge 2005),
p_adj_seed_te(ttot,regi,"coalftcrec") = 0.25;
p_adj_seed_te(ttot,regi,"coaltr") = 4.00;
p_adj_seed_te(ttot,regi,'dac') = 0.25;
p_adj_seed_te(ttot,regi,'oae_ng') = 0.25;
p_adj_seed_te(ttot,regi,'oae_el') = 0.25;
p_adj_seed_te(ttot,regi,'geohe') = 0.33;
$ifthen.cm_subsec_model_steel "%cm_subsec_model_steel%" == "processes"
p_adj_seed_te(ttot,regi,"bfcc") = 0.05;
Expand Down Expand Up @@ -1249,6 +1254,8 @@ $ifthen.WindOff %cm_wind_offshore% == "1"
$endif.WindOff

p_adj_coeff(ttot,regi,"dac") = 0.8;
p_adj_coeff(ttot,regi,'oae_ng') = 0.8;
p_adj_coeff(ttot,regi,'oae_el') = 0.8;
p_adj_coeff(ttot,regi,teGrid) = 0.3;
p_adj_coeff(ttot,regi,teStor) = 0.05;
);
Expand Down
23 changes: 12 additions & 11 deletions core/equations.gms
Original file line number Diff line number Diff line change
Expand Up @@ -740,18 +740,19 @@ q_emiMac(t,regi,emiMac) ..
***--------------------------------------------------
q_emiCdrAll(t,regi)..
vm_emiCdrAll(t,regi)
=e= !! BECC + DACC
(sum(emiBECCS2te(enty,enty2,te,enty3),vm_emiTeDetail(t,regi,enty,enty2,te,enty3))
+ sum(teCCS2rlf(te,rlf), vm_ccs_cdr(t,regi,"cco2","ico2","ccsinje",rlf)))
!! scaled by the fraction that gets stored geologically
* (sum(teCCS2rlf(te,rlf),
vm_co2CCS(t,regi,"cco2","ico2",te,rlf)) /
(sum(teCCS2rlf(te,rlf),
vm_co2capture(t,regi,"cco2","ico2","ccsinje",rlf))+sm_eps))
=e=
( !! BECC + DACC
sum(emiBECCS2te(enty,enty2,te,enty3),vm_emiTeDetail(t,regi,enty,enty2,te,enty3))
- vm_emiCdrTeDetail(t, regi, "dac") !! this is a negative value
)
* ( !! scaled by the fraction that gets stored geologically
sum(teCCS2rlf(te, rlf), vm_co2CCS(t, regi, "cco2", "ico2", te, rlf))
/ (sum(teCCS2rlf(te, rlf), vm_co2capture(t, regi, "cco2", "ico2", "ccsinje", rlf)) + sm_eps)
)
!! net negative emissions from co2luc
- p_macBaseMagpieNegCo2(t,regi)
!! negative emissions from the cdr module that are not stored geologically
- (vm_emiCdr(t,regi,"co2") + sum(teCCS2rlf(te,rlf), vm_ccs_cdr(t,regi,"cco2","ico2","ccsinje",rlf)))
!! negative emissions from the cdr module that are not stored geologically
- (vm_emiCdr(t,regi,"co2") - vm_emiCdrTeDetail(t, regi, "dac"))
;


Expand Down Expand Up @@ -838,7 +839,7 @@ q_balcapture(t,regi,ccs2te(ccsCo2(enty),enty2,te)) ..
vm_emiTeDetail(t,regi,enty3,enty4,te2,enty)
)
!! carbon captured from CDR technologies in CDR module
+ sum(teCCS2rlf(te,rlf), vm_ccs_cdr(t,regi,enty,enty2,te,rlf))
+ sum(teCCS2rlf(te,rlf), vm_co2capture_cdr(t,regi,enty,enty2,te,rlf))
!! carbon captured from industry
+ sum(emiInd37, vm_emiIndCCS(t,regi,emiInd37))
+ sum((sefe(entySe,entyFe),emiMkt)$(
Expand Down
2 changes: 1 addition & 1 deletion core/postsolve.gms
Original file line number Diff line number Diff line change
Expand Up @@ -756,7 +756,7 @@ o_capture_energy_other(ttot,regi,"co2")$(ttot.val ge 2005) =
***Carbon Management|Carbon Capture|Process|Direct Air Capture (Mt CO2/yr)
o_capture_cdr(ttot,regi,"co2")$(ttot.val ge 2005) =
sum(teCCS2rlf("ccsinje",rlf),
vm_ccs_cdr.l(ttot,regi,"cco2","ico2","ccsinje",rlf)
vm_co2capture_cdr.l(ttot,regi,"cco2","ico2","ccsinje",rlf)
)*o_emi_conv("co2");

***Carbon Management|Carbon Capture|Process|Industrial Processes (Mt CO2/yr)
Expand Down
33 changes: 32 additions & 1 deletion main.gms
Original file line number Diff line number Diff line change
Expand Up @@ -863,6 +863,37 @@ parameter
*' * (1): enhanced weathering is included
*' * (0): not included
*'
parameter
cm_33OAE "choose whether OAE (ocean alkalinity enhancement) should be included into the CDR portfolio. 0 = OAE not used, 1 = used"
;
cm_33OAE = 0; !! def = 0
*' Since OAE is quite a cheap CDR option, runs might not converge because the model tries to deploy
*' a lot of OAE. In this case, use a quantity target to limit OAE by adding something like:
*' (2070,2080,2090,2100).GLO.tax.t.oae.all 5000 to cm_implicitQttyTarget in your config file,
*' starting from the year in which OAE is deployed above 5000 MtCO2 / yr. This will limit the global
*' deployment to 5000 Mt / yr in timesteps 2070-2100.
*' * (1): ocean alkalinity enhancement is included
*' * (0): not included
*'
parameter
cm_33_OAE_eff "OAE efficiency measured in tCO2 uptaken by the ocean per tCaO. Typically between 0.9-1.4 (which corresponds to 1.2-1.8 molCO2/molCaO). [tCO2/tCaO]"
;
cm_33_OAE_eff = 1.2; !! def = 1.2
*'
parameter
cm_33_OAE_scen "OAE distribution scenarios"
;
cm_33_OAE_scen = 1; !! def = 1
*' * (0): pessimistic: a rather low discharge rate (30 tCaO per h), corresponding to high distribution costs
*' * (1): optimistic: a high discharge rate (250 tCaO per h), corresponding to lower distribution costs
*'
parameter
cm_33_OAE_startyr "The year when OAE could start being deployed [year]"
;
cm_33_OAE_startyr = 2030; !! def = 2030 !! regexp = 20[3-9](0|5)
*' * (2030): earliest year when OAE could be deployed
*' * (....): later timesteps
*'
parameter
cm_gs_ew "grain size (for enhanced weathering, CDR module) [micrometre]"
;
Expand Down Expand Up @@ -1320,7 +1351,7 @@ $setGlobal cm_proNucRegiPol off !! def = off
$setGlobal cm_CCSRegiPol off !! def = off
*** cm_vehiclesSubsidies - If "on" applies country specific BEV and FCEV subsidies from 2020 onwards
$setGlobal cm_vehiclesSubsidies off !! def = off
*** cm_implicitQttyTarget - Define quantity target for primary, secondary, final energy or CCS (PE, SE and FE in TWa, or CCS in Mt CO2) per target group (total, biomass, fossil, VRE, renewables, synthetic, ...).
*** cm_implicitQttyTarget - Define quantity target for primary, secondary, final energy or CCS (PE, SE and FE in TWa, or CCS and OAE in Mt CO2) per target group (total, biomass, fossil, VRE, renewables, synthetic, ...).
*** The target is achieved by an endogenous calculated markup in the form or a tax or subsidy in between iterations.
*** If cm_implicitQttyTargetType is set to "config", the quantity targets will be defined directly in this switch. Check below for examples on how to do this.
*** If cm_implicitQttyTargetType is set to "scenario", you should define the list of pre-defined scenarios hard-coded in module '47_regipol' that should be active for the current run (this avoids reaching the 255 characters limit in more complex definitions).
Expand Down
2 changes: 1 addition & 1 deletion modules/33_CDR/module.gms
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
*'
*' @description The 33_CDR module adds further options to remove CO2 from the atmosphere beyond BECCS
*' and afforestation, which are calculated in the core. Currently, direct air carbon capture and storage (DACCS)
*' and enhanced weathering of rocks (EW) are available, ocean alkalinization will follow soon.
*' and enhanced weathering of rocks (EW) are available, ocean alkalinization (OAE) implemented as ocean liming.
*' All options can be switched on and off individually via the switches called cm_33[option abbreviation].
*' The module calculates capacities, emissions (including captured carbon), energy demand & supply, costs,
*' and limitations associated with the different options.
Expand Down
23 changes: 16 additions & 7 deletions modules/33_CDR/portfolio/bounds.gms
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ if(card(te_used33) eq 0,

*** Fix CCS from CDR if there're no technologies that require CCS
if(card(te_ccs33) eq 0,
vm_ccs_cdr.fx(t,regi,enty,enty2,te,rlf)$ccs2te(enty,enty2,te) = 0;
vm_co2capture_cdr.fx(t,regi,enty,enty2,te,rlf)$ccs2te(enty,enty2,te) = 0;
);

*** Fix negative emissions and FE demand to zero for all the technologies that are not used
vm_emiCdrTeDetail.fx(t,regi,te_all33)$(not te_used33(te_all33)) = 0;
v33_FEdemand.fx(t,regi,entyFe,entyFe2,te_all33)$(not te_used33(te_all33) and fe2cdr(entyFe,entyFe2,te_all33)) = 0;
*** Fix non atmospheric emissions from CDR for all technologies that are not used
v33_co2emi_non_atm_gas.fx(t,regi,te_all33)$(not te_ccs33(te_all33)) = 0;

*** Fix all CDR-related variables to zero for early time steps t< 2025 (no CDR in the real world)
*** to reduce unnecessary freedom (and likelyhood of spontaneous solver infeasibilities)
Expand All @@ -30,9 +32,10 @@ v33_FEdemand.fx(t,regi,entyFe,entyFe2,te_used33)$(fe2cdr(entyFe,entyFe2,te_used3
vm_emiCdr.fx(t,regi,"co2")$(t.val lt 2025) = 0;
vm_omcosts_cdr.fx(t,regi)$((t.val lt 2025)) = 0;
vm_cap.fx(t,regi,"weathering",rlf)$(t.val lt 2025) = 0;
v33_co2emi_non_atm_gas.fx(t,regi,te_used33)$(t.val lt 2025) = 0;
v33_co2emi_non_atm_calcination.fx(t,regi,te_oae33)$(t.val lt 2025) = 0;
*** vm_cap for dac is fixed for t<2025 in core/bounds.gms (tech_stat eq 4)
vm_ccs_cdr.fx(t,regi,enty,enty2,te,rlf)$(ccs2te(enty,enty2,te) AND t.val lt 2025) = 0;

vm_co2capture_cdr.fx(t,regi,enty,enty2,te,rlf)$(ccs2te(enty,enty2,te) AND t.val lt 2025) = 0;

*** Set minimum DAC capacities (if available) to help the solver find the technology
if (te_used33("dac"),
Expand All @@ -47,12 +50,18 @@ if(te_used33("weathering"),
!! if cm_startyear > 2025 and input_ref.gdx used EW, this fixing will be overwritten in submit.R
v33_EW_onfield.fx(ttot,regi,rlf_cz33,rlf)$(ttot.val lt max(2025,cm_startyear)) = 0.0; !!
v33_EW_onfield_tot.fx(ttot,regi,rlf_cz33,rlf)$(ttot.val lt max(2025,cm_startyear)) = 0.0; !!
);

*** Bounds if enhanced weathering is not in the portfolio
if(not te_used33("weathering"),
else
vm_omcosts_cdr.fx(t,regi) = 0;
vm_cap.fx(t,regi,"weathering",rlf) = 0;
);

*** Bounds for OAE
if(card(te_oae33) ne 0,
!! OAE starts in cm_33_OAE_startyear
vm_cap.fx(t, regi, te_oae33, rlf)$(t.val lt cm_33_OAE_startyr) = 0;
else
v33_co2emi_non_atm_calcination.fx(t, regi, "oae_ng") = 0;
v33_co2emi_non_atm_calcination.fx(t, regi, "oae_el") = 0;
);

*** EOF ./modules/33_CDR/portfolio/bounds.gms
21 changes: 21 additions & 0 deletions modules/33_CDR/portfolio/datainput.gms
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,26 @@ p33_fedem("weathering", "fedie") = 0.3;

*' Factor distributing the global rock limit across regions according to population
p33_LimRock(regi) = pm_pop("2005",regi) / sum(regi2,pm_pop("2005",regi2));

*** ocean alkalinity enhancement input data (Kowalczyk et al., 2024)

!! An assumption; generally the efficiency might vary between 0.9-1.4 tCO2/tCaO (1.2-1.8 molCO2/molCaO),
!! depending on e.g., ocean chemistry and currents in a given region
s33_OAE_efficiency = cm_33_OAE_eff / sm_c_2_co2; !! GtC (ocean uptake) per unit of GtCaO

!! 0.78 tCO2 are emitted in the decomposition of limestone to produce 1 tCaO
s33_OAE_chem_decomposition = 0.78 / sm_c_2_co2 / s33_OAE_efficiency; !! GtC from decomposition per 1GtC taken by the ocean, 0.78 t/tCaO

p33_fedem(te_oae33, "feels") = 1.0 / s33_OAE_efficiency; !! 996 MJ/tCaO, used for grinding, air separation, CO2 compression
p33_fedem(te_oae33, "fehes") = 3.1 / s33_OAE_efficiency; !! 3100 MJ/tCaO, used for calcination

if(cm_33_OAE_scen = 0, !! pessimistic scenario for distribution, high diesel demand
p33_fedem(te_oae33, "fedie") = 2.6 / s33_OAE_efficiency; !! 2600 MJ/tCaO (corresponds to discharge rate of 30 t/h)
); !! fedie is used for inland transport of the material and maritime transport to distribute the material in the ocean

if(cm_33_OAE_scen = 1, !! optimistic scenario for distribution, lower diesel demand
p33_fedem(te_oae33, "fedie") = 0.77 / s33_OAE_efficiency; !! 770 MJ/tCaO (corresponds to the discharge rate of 100 t/h)
);

*' @stop
*** EOF ./modules/33_CDR/portfolio/datainput.gms
22 changes: 18 additions & 4 deletions modules/33_CDR/portfolio/declarations.gms
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,17 @@
*** | Contact: [email protected]
*** SOF ./modules/33_CDR/portfolio/declarations.gms
scalars
s33_capture_rate "CO2 capture rate for capturing emissions, e.g., from burning natural gas" / 0.9 /

s33_co2_rem_pot "specific carbon removal potential [Gt C per Gt ground rock]"
s33_co2_rem_rate "carbon removal rate [fraction of annual reduction of total carbon removal potential]"
s33_costs_fix "fixed costs for mining, grinding, spreading [T$/Gt stone]"
s33_step "size of bins in v33_weathering_onfield [Gt stone]"
*JeS* GJ/tCO2 = EJ/Gt CO2 = 44/12 EJ/Gt C.

s33_OAE_efficiency "the amount of rock required to sequester 1GtC [Gt rock / GtC]"
s33_OAE_chem_decomposition "the fraction of CO2 that comes from chemical decomposition in the calcination process"
s33_OAE_glo_limit "global limit for OAE [tC / a]"
;

parameters
Expand All @@ -23,27 +29,35 @@ positive variables
v33_EW_onfield(ttot,all_regi,rlf,rlf) "amount of ground rock spread on fields in each timestep [Gt]"
v33_EW_onfield_tot(ttot,all_regi,rlf,rlf) "total amount of ground rock on fields, for each climate zone and transportation distance [Gt]"
v33_FEdemand(ttot,all_regi,all_enty,all_enty,all_te) "FE demand of each technology [TWa]"
vm_ccs_cdr(ttot,all_regi,all_enty,all_enty,all_te,rlf) "total emissions captured through technologies in the CDR module that enter the CCUS chain + captured emissions from associated FE demand [GtC / a]"
vm_co2capture_cdr(ttot,all_regi,all_enty,all_enty,all_te,rlf) "total emissions captured through technologies in the CDR module that enter the CCUS chain + captured emissions from associated FE demand [GtC / a]"
v33_co2emi_non_atm_gas(ttot,all_regi,all_te) "CO2 from CDR-related acitivites that comes from energy demand [GtC / a]"
v33_co2emi_non_atm_calcination(ttot,all_regi,all_te) "CO2 from calcination [GtC / a]"
;

negative variables
vm_emiCdrTeDetail(ttot,all_regi,all_te) "(negative) emissions from CDR technologies in the CDR module by technology. Includes all atmospheric CO2 that enter the CCUS chain (i.e. CO2 stored (CDR) AND used (not CDR)) [GtC / a]"
vm_emiCdrTeDetail(ttot,all_regi,all_te) "gross (negative) emissions from CDR technologies in the CDR module by technology. Includes all atmospheric CO2 that enter the CCUS chain (i.e. CO2 stored (CDR) AND used (not CDR)) [GtC / a]"
;

equations
q33_demFeCDR(ttot,all_regi,all_enty) "CDR demand balance for final energy"
q33_emiCDR(ttot,all_regi) "aggregates the (negative) emissions captured by the CDR technologies"
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_DAC_emi(ttot,all_regi) "calculates amount of carbon captured by DAC"
q33_capconst(ttot,all_regi,all_te) "calculates amount of carbon captured by DAC and OAE"
q33_co2emi_non_atm_gas(ttot,all_regi,all_te) "calculates the share 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_DAC_FEdemand(ttot,all_regi,all_enty) "calculates final energy demand from DAC"
q33_DAC_ccsbal(ttot,all_regi,all_enty,all_enty,all_te) "calculates CCS emissions from CDR technologies"

q33_EW_capconst(ttot,all_regi) "calculates amount of ground rock spread on fields"
q33_EW_onfield_tot(ttot,all_regi,rlf,rlf) "total amount of ground rock on fields"
q33_EW_omcosts(ttot,all_regi) "calculates O&M costs for spreading ground rocks on fields"
q33_EW_FEdemand(ttot,all_regi,all_enty) "calculates final energy demand from enhanced weathering"
q33_EW_potential(ttot,all_regi,rlf) "limits the total potential of EW per region and grade"
q33_EW_emi(ttot,all_regi) "calculates amount of carbon captured by EW"
q33_EW_LimEmi(ttot,all_regi) "limits EW to a maximal annual amount of ground rock of cm_LimRock"

q33_OAE_FEdemand(ttot,all_regi,all_enty,all_te) "calculates final energy demand for ocean alkalinity enhancement"
q33_OAE_co2emi_non_atm_calcination(ttot,all_regi,all_te) "calculates the CO2 that comes from calcination (limestone decomposition)"
;

*** EOF ./modules/33_CDR/portfolio/declarations.gms
Loading

0 comments on commit 18a8032

Please sign in to comment.