REMIND - REgional Model of INvestments and Development

3.5.2

created with goxygen 1.4.6

Model Assumptions (00_model_assumptions)

Description

Model Bounds and Assumptions

1. Conopt optimisation bounds

Set lower bounds on variables otherwise the conopt solver doesn’t see a benefit from changing variable value away from 0 These lower bounds are set so low that they do not restrict the results Lower limit on all P2SE technologies capacities to 100 kW of all technologies and all time steps

loop(pe2se(enty,enty2,te) $ (
    (not sameas(te,"biotr")) and
    (not sameas(te,"biodiesel")) and
    (not sameas(te,"bioeths")) and
    (not sameas(te,"gasftcrec")) and
    (not sameas(te,"gasftrec")) and
    (not sameas(te,"tnrs")) and
    (not teBiopyr(te))
  ),
  vm_cap.lo(t,regi,te,"1") $ (t.val >= 2030 and t.val <= 2070) = 1e-7;
  if(not teCCS(te), 
    vm_deltaCap.lo(t,regi,te,"1") $ (t.val >= 2030 and t.val <= 2070) = 1e-8;
  );
);

Make sure that the model also sees the se2se technologies (seel <–> seh2)

loop(se2se(enty,enty2,te),
  vm_cap.lo(t,regi,te,"1") $ (t.val >= 2030) = 1e-7;
);

Lower bound of 10 kW on each of the different grades for renewables with multiple resource grades

loop(teRe2rlfDetail(te,rlf),
  loop(regi $ (pm_dataren(regi,"maxprod",rlf,te) > 0),
    v_capDistr.lo(t,regi,te,rlf) $ (t.val >= 2015) = 1e-8;
    v_capDistr.lo("2015",regi,te,rlf) = 0.9 / max(1, p_aux_capacityFactorHistOverREMIND(regi,te)) * p_aux_capThisGrade(regi,te,rlf);
    v_capDistr.lo("2020",regi,te,rlf) = 0.9 / max(1, p_aux_capacityFactorHistOverREMIND(regi,te)) * p_aux_capThisGrade(regi,te,rlf);
  );
);

2. Historical and near-term capacities

Capacity for fossils and renewables
loop(t $ (t.val >= 2015 and t.val <= 2025),
  vm_cap.lo(t,regi,teVRE(te),"1") $ pm_histCap(t,regi,te) = 0.95 * pm_histCap(t,regi,te);
  if(t.val <= 2020, !! TODO: activate 2025 upper-bound when consolidated data available
    vm_cap.up(t,regi,teVRE(te),"1") $ pm_histCap(t,regi,te) = 1.05 * pm_histCap(t,regi,te);
  );
  loop(te $ (sameas(te, "hydro") or sameas(te, "geohdr")),
    vm_cap.lo(t,regi,te,"1") $ pm_histCap(t,regi,te) = 0.7 * pm_histCap(t,regi,te);
    vm_cap.up(t,regi,te,"1") $ pm_histCap(t,regi,te) = 1.4 * pm_histCap(t,regi,te);
  );
  loop(te $ (sameas(te,"ngcc") or sameas(te,"ngt") or sameas(te,"gaschp")),
    vm_cap.lo(t,regi,te,"1") $ pm_histCap(t,regi,te) = 0.95 * pm_histCap(t,regi,te);
  );
);
loop(regi $ regi_group("EUR_regi",regi),

bounds on 2025 variable renewables generation in Europe based on historical growth rates

  vm_prodSe.up("2025",regi,"pewin","seel","windon") = p_histProdSe("2023",regi,"seel","windon") * power((p_maxhistProdSeGrowthRate(regi,"seel","windon") * 1.3 + 1), 2);
  vm_prodSe.up("2025",regi,"pesol","seel","spv")    = p_histProdSe("2023",regi,"seel","spv")    * power((p_maxhistProdSeGrowthRate(regi,"seel","spv")    * 1.3 + 1), 2);

no investment into oil turbines in Europe

  vm_deltaCap.up(t,regi,"dot","1") $ (t.val > 2005) = 1e-6;
);
vm_prodSe.lo("2020",regi,"pecoal","seel","coalchp") = 0.8 * pm_IO_output("2020",regi,"pecoal","seel","coalchp") ;
vm_prodSe.up("2020",regi,"pegas","seel","gaschp") = 1e-4 + 1.3 * pm_IO_output("2020",regi,"pegas","seel","gaschp") ;
Near-term capacity for electrolysis and hydrogen

set lower and upper bounds for 2025 and 2030 based on projects annoucements from IEA Hydryogen project database: https://www.iea.org/data-and-statistics/data-product/hydrogen-production-and-infrastructure-projects-database distribute to regions via GDP share of 2025 (we do not use later time steps as they may have different GDPs depending on the scenario) in future this should be differentiated by region based on regionalized input data of project announcements 2 GW(el) at least globally in 2025, about operational capacity as of 2023

vm_cap.lo("2025",regi,"elh2","1") =   2e-3 * pm_eta_conv("2025",regi,"elh2") * pm_gdp("2025",regi) / sum(regi2,pm_gdp("2025",regi2));

20 GW(el) at maximum globally in 2025 (be more generous to not overconstrain regions which scale-up fastest)

vm_cap.up("2025",regi,"elh2","1") =  20e-3 * pm_eta_conv("2025",regi,"elh2") * pm_gdp("2025",regi) / sum(regi2,pm_gdp("2025",regi2));

100 GW(el) at maximum globally in 2030 (upper end of feasibility range in Odenweller et al. 2022, https://doi.org/10.1038/s41560-022-01097-4, Fig. 4)

vm_cap.up("2030",regi,"elh2","1") = 100e-3 * pm_eta_conv("2025",regi,"elh2") * pm_gdp("2025",regi) / sum(regi2,pm_gdp("2025",regi2));

upper bound of 0.5 EJ/yr to prevent building too much grey hydrogen before 2020, distributed to regions via GDP share

vm_cap.up("2020",regi,"gash2","1")  = 0.5 * sm_EJ_2_TWa * pm_gdp("2020",regi) / sum(regi2, pm_gdp("2020",regi2));

Set upper bounds on biomass gasification for hydrogen production, which is not deployed as of 2025 allow for small production of at most 0.1 EJ/yr by 2030 for each technology globally, distributed to regions by GDP share in 2025

vm_cap.up("2030",regi,"bioh2","1")  = 0.1 * sm_EJ_2_TWa * pm_gdp("2025",regi) / sum(regi2, pm_gdp("2025",regi2));
vm_cap.up("2030",regi,"bioh2c","1") = 0.1 * sm_EJ_2_TWa * pm_gdp("2025",regi) / sum(regi2, pm_gdp("2025",regi2));

allow zero vm_deltaCap for bio-hydrogen up to 2030 to be consistent with above bounds

vm_deltaCap.lo(t,regi,"bioh2","1")  $ (t.val <= 2030) = 0;
vm_deltaCap.lo(t,regi,"bioh2c","1") $ (t.val <= 2030) = 0;
Technologies depending on learning and tech_stat
vm_costTeCapital.fx(ttot,regi,teNoLearn) = pm_inco0_t("2005",regi,teNoLearn); !! use 2005 value for the past
vm_costTeCapital.fx(t,   regi,teNoLearn) = pm_inco0_t(t,regi,teNoLearn);
vm_costTeCapital.lo(t,regi,teLearn) = 0.2 * pm_data(regi,"floorcost",teLearn);

No battery storage in 2010

vm_cap.up("2010",regi,teStor,"1") = 0;
vm_capCum.lo(ttot,regi,teLearn) $ (ttot.val >= cm_startyear) = pm_data(regi,"ccap0",teLearn);
vm_capCum.lo(ttot,regi,teLearn) $ (pm_data(regi,"tech_stat",teLearn) = 4 and ttot.val <= 2020) = 0;

Advanced technologies shouldn’t be built prior to 2015/2020

loop(regi,
  loop(teNoLearn(te) $ (pm_data(regi,"tech_stat",te) = 2),
    vm_deltaCap.fx("2010",regi,te,rlf) = 0;
    vm_cap.lo("2010",regi,te,rlf) = 0;
    vm_cap.lo("2015",regi,te,rlf) = 0;
  );
  loop(teNoLearn(te) $ (pm_data(regi,"tech_stat",te) = 3),
    vm_deltaCap.fx("2010",regi,te,rlf) = 0;
    vm_deltaCap.fx("2015",regi,te,rlf) = 0;
    vm_cap.lo("2010",regi,te,rlf) = 0;
    vm_cap.lo("2015",regi,te,rlf) = 0;
    vm_cap.lo("2020",regi,te,rlf) = 0;
  );
);

no technologies with tech_stat 4 before 2025

vm_cap.fx(t,regi,te,rlf) $ (t.val <= 2020 and pm_data(regi,"tech_stat",te) = 4) = 0;
vm_capCum.fx(t0,regi,teLearn) $ (pm_data(regi,"tech_stat",teLearn) = 4) = 0;
vm_costTeCapital.fx(t,regi,teLearn) $ (t.val <= 2020 and pm_data(regi,"tech_stat",teLearn) = 4) = fm_dataglob("inco0",teLearn);
vm_deltaCap.fx(t,regi,te,rlf) $ (t.val <= 2025 and pm_data(regi,"tech_stat",te) = 5) = 0;
Capacity for nuclear energy
if(cm_startyear <= 2015,
  p_CapFixFromRWfix("2015",regi,"tnrs") = max( pm_aux_capLowerLimit("tnrs",regi,"2015") , pm_NuclearConstraint("2015",regi,"tnrs") );
  p_deltaCapFromRWfix("2015",regi,"tnrs") = ( p_CapFixFromRWfix("2015",regi,"tnrs") - pm_aux_capLowerLimit("tnrs",regi,"2015") )
                                    / 7.5;  !! this parameter is currently only for display and not further used to fix anything
  p_deltaCapFromRWfix("2010",regi,"tnrs") = ( p_CapFixFromRWfix("2015",regi,"tnrs") - pm_aux_capLowerLimit("tnrs",regi,"2015") )
                                    / 7.5; !! this parameter is currently only for display and not further used to fix anything
  vm_cap.fx("2015",regi,"tnrs","1") = p_CapFixFromRWfix("2015",regi,"tnrs");
);
if(cm_startyear <= 2020, !! require the realization of at least 70% of the plants that are currently under construction and thus might be finished until 2020 - should be updated with real-world 2020 numbers
   vm_deltaCap.lo("2020",regi,"tnrs","1") = 0.70 * pm_NuclearConstraint("2020",regi,"tnrs") / 5;
   vm_deltaCap.up("2020",regi,"tnrs","1") = pm_NuclearConstraint("2020",regi,"tnrs") / 5;
);
if(cm_startyear <= 2025, !! upper bound calculated in mrremind/R/calcCapacityNuclear.R: 50% of planned and 30% of proposed plants, plus extra for lifetime extension and newcomers
   vm_deltaCap.up("2025",regi,"tnrs","1") = pm_NuclearConstraint("2025",regi,"tnrs") / 5;
);
if(cm_startyear <= 2030, !! upper bound calculated in mrremind/R/calcCapacityNuclear.R: 50% of planned and 70% of proposed plants, plus extra for lifetime extension and newcomers
   vm_deltaCap.up("2030",regi,"tnrs","1") = pm_NuclearConstraint("2030",regi,"tnrs") / 5;
);
display p_CapFixFromRWfix, p_deltaCapFromRWfix;

switch to prevent new nuclear capacities after 2020, until then all currently planned plants are built

if(cm_nucscen = 5,
  vm_deltaCap.up(t,regi_nucscen,"tnrs",rlf) $ (t.val > 2020) = 1e-6;
  vm_cap.lo(t,regi_nucscen,"tnrs",rlf) $ (t.val > 2015) = 0;
);

3. Assumptions on biomass

Traditional biomass use is phased out on an exogeneous time path Developed regions phase out quickly (no new capacities)

vm_deltaCap.fx(t,regi,"biotr",rlf) $ (t.val > 2005) = 0;

Developing regions (defined by GDP PPP threshold) phase out more slowly (+ varied by SSP)

loop(regi,
  if( (pm_gdp("2005",regi) / pm_pop("2005",regi) / pm_shPPPMER(regi)) < 4,
    vm_deltaCap.fx("2010",regi,"biotr","1") = 1.3  * vm_deltaCap.lo("2005",regi,"biotr","1");
    vm_deltaCap.fx("2015",regi,"biotr","1") = 0.9  * vm_deltaCap.lo("2005",regi,"biotr","1");
    vm_deltaCap.fx("2020",regi,"biotr","1") = 0.7  * vm_deltaCap.lo("2005",regi,"biotr","1");
$ifthen not %cm_tradbio_phaseout% == "fast" !! cm_tradbio_phaseout
    vm_deltaCap.fx("2025",regi,"biotr","1") = 0.5  * vm_deltaCap.lo("2005",regi,"biotr","1");
    vm_deltaCap.fx("2030",regi,"biotr","1") = 0.4  * vm_deltaCap.lo("2005",regi,"biotr","1");
    vm_deltaCap.fx("2035",regi,"biotr","1") = 0.3  * vm_deltaCap.lo("2005",regi,"biotr","1");
    vm_deltaCap.fx("2040",regi,"biotr","1") = 0.2  * vm_deltaCap.lo("2005",regi,"biotr","1");
    vm_deltaCap.fx("2045",regi,"biotr","1") = 0.15 * vm_deltaCap.lo("2005",regi,"biotr","1");
    vm_deltaCap.fx("2050",regi,"biotr","1") = 0.1  * vm_deltaCap.lo("2005",regi,"biotr","1");
    vm_deltaCap.fx("2055",regi,"biotr","1") = 0.1  * vm_deltaCap.lo("2005",regi,"biotr","1");
$endif
  );
);

Quick phaseout in SSP1 and SSP5

$if %cm_GDPpopScen% == "SSP1"   vm_deltaCap.fx(t,regi,"biotr","1") $ (t.val > 2020) = 0.5 * vm_deltaCap.lo(t,regi,"biotr","1");
$if %cm_GDPpopScen% == "SSP5"   vm_deltaCap.fx(t,regi,"biotr","1") $ (t.val > 2020) = 0.5 * vm_deltaCap.lo(t,regi,"biotr","1");

Quickest phaseout in SDP scenarios (no new capacities allowed)

$if %cm_GDPpopScen% == "SDP"    vm_deltaCap.up(t,regi,"biotr","1") $ (t.val > 2020) = 0;
$if %cm_GDPpopScen% == "SDP_EI" vm_deltaCap.up(t,regi,"biotr","1") $ (t.val > 2020) = 0;
$if %cm_GDPpopScen% == "SDP_MC" vm_deltaCap.up(t,regi,"biotr","1") $ (t.val > 2020) = 0;
$if %cm_GDPpopScen% == "SDP_RC" vm_deltaCap.up(t,regi,"biotr","1") $ (t.val > 2020) = 0;

Switch to deactivate technologies that produce liquids from lignocellulosic biomass

if(c_bioliqscen = 0, !! no bioliquids technologies
  vm_deltaCap.up(t,regi,"bioftrec",rlf)  $ (t.val > 2005) = 1e-6;
  vm_deltaCap.up(t,regi,"bioftcrec",rlf) $ (t.val > 2005) = 1e-6;
  vm_deltaCap.up(t,regi,"bioethl",rlf)   $ (t.val > 2005) = 1e-6;
  vm_deltaCap.up(t,regi,"biopyrliq",rlf) $ (t.val > 2025) = 1e-8;
);

Switch to prevent new capacities of 1st generation biofuel technologies after 2030, allowing more cost-efficient and more sustainable new generation of biofuel technologies free entrance to the market

if(cm_1stgen_phaseout = 1,
   vm_deltaCap.up(t,regi,"bioeths",rlf)   $ (t.val > 2030) = 0;
   vm_deltaCap.up(t,regi,"biodiesel",rlf) $ (t.val > 2030) = 0;
);

Switch to deactivate technologies that produce hydrogen from lignocellulosic biomass

if(c_bioh2scen = 0, !! no bioh2 technologies
  vm_deltaCap.up(t,regi,"bioh2",rlf)  $ (t.val > 2005) = 1e-6;
  vm_deltaCap.up(t,regi,"bioh2c",rlf) $ (t.val > 2005) = 1e-6;
);

Switches to activate pyrolysis technologies

loop(teBiopyr(te) $ (not sameas(te, "biopyrliq")), !! established industrial technologies
  vm_cap.fx(t,regi,te,rlf) $ (t.val <= 2015) = 0; 
  if(c_biopyrEstablished = 0,
    vm_deltaCap.fx(t,regi,te,rlf) $ (t.val >= cm_startyear) = 0; 
  else
    vm_cap.up("2020",regi,te,rlf) = p_boundCapBiochar("2020",regi) * sm_tBC_2_TWa / 3; 
    vm_cap.lo("2025",regi,te,rlf) = p_boundCapBiochar("2025",regi) * sm_tBC_2_TWa / 3; 
    !! set upper bound to 70% above the lower bound which is based on 2024 values    
    vm_cap.up("2025",regi,te,rlf) = 1.7 * p_boundCapBiochar("2025",regi) * sm_tBC_2_TWa / 3;                      
  );
);
loop(te $ sameas(te, "biopyrliq"), !! does not yet exist commercially
  vm_cap.fx(t,regi,"biopyrliq",rlf)  $ (t.val <= 2025) = 0;
  vm_deltaCap.lo(t,regi,"biopyrliq",rlf) $ (t.val > cm_startyear) = 1e-8; !! initiate a negligible increase to help model find the technology
  vm_deltaCap.up(t,regi,"biopyrliq",rlf) $ (t.val > cm_startyear) = inf; !! revert fixing to small values above
  if(c_biopyrliq = 0,
    vm_deltaCap.fx(t,regi,"biopyrliq",rlf) $ (t.val >= cm_startyear) = 0; 
  );
);

4. Assumptions on carbon management

vm_emiTe.lo(ttot,regi,"cco2") = 0;

no CCS at all in 2010

vm_cap.fx("2010",regi,teCCS,rlf) = 0;

no BECCS in 2020

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;
);

bound on maximum annual carbon storage by region

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);
  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 * (
        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);
  );
);

switch to deactivate carbon capture technologies

if(cm_emiscen = 1,
  vm_cap.fx(t,regi,teCCS,rlf) = 0;
);
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;
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
  loop(emi2te(enty,"seel",te,"cco2") $ ( sum(regi_capturescen, pm_emifac("2020",regi_capturescen,enty,"seel",te,"cco2")) > 0 ),
    loop(te2rlf(te,rlf),
      vm_cap.fx(t,regi_capturescen,te,rlf) = 0;
    );
  );
);

Fix capacities of technologies with carbon capture to zero if there are no CCS projects in the pipeline in that region

loop(regi,
  loop(t $ (t.val <= 2030),
    if( ((p_boundCapCCS(t,regi,"operational") + p_boundCapCCS(t,regi,"construction") + p_boundCapCCS(t,regi,"planned")) = 0),
      vm_cap.fx(t,regi,teCCS,rlf) = 0;
    );
  );
);
loop(regi $ (p_boundCapCCSindicator(regi) = 0),
  vm_cap.fx("2025",regi,teCCS,rlf) = 0;
  vm_cap.fx("2030",regi,teCCS,rlf) = 0;
);
v_co2capturevalve.up(t,regi) = 1 * s_MtCO2_2_GtC;

5. Early retirement and phase-out of technologies

Switch off coal-h2 hydrogen investments after 2020, and gas-h2 investments after 2030. Our current seh2 hydrogen represents only additional (clean) hydrogen use cases to current ones. However, as we have too high H2 demand in 2025 and 2030 from the input data, we need to allow grey hydrogen for these time periods to meet the hydrogen demand which cannot be fully met by incoming low-carbon H2 techologies. This should be removed once FE H2 industry input data is adapted. It is allowed before 2020 to not make the model infeasible for low demands of hydrogen in that year.

vm_deltaCap.fx(t,regi,"coalh2",rlf) $ (t.val >= 2020) = 0;
vm_deltaCap.fx(t,regi,"gash2",rlf) $ (t.val > 2030) = 0;
vm_cap.lo(t,regi,"coalh2",rlf) $ (t.val >= 2020) = 0;
vm_cap.lo(t,regi,"gash2",rlf) $ (t.val > 2030) = 0;
vm_capEarlyReti.up(t,regi,te) = 1e-6;
vm_capEarlyReti.up(t,regi,teFosNoCCS(te)) = 1;
vm_capEarlyReti.up(t,regi,"tnrs") = 1;
vm_capEarlyReti.up(t,regi,"bioigcc") = 1;
vm_capEarlyReti.up(t,regi,"biohp") = 1;
vm_capEarlyReti.up(t,regi,"biochp") = 1;
$ifthen.tech_earlyreti not "%c_tech_earlyreti_rate%" == "off"
loop((ext_regi,te) $ p_techEarlyRetiRate(ext_regi,te),
  vm_capEarlyReti.up(t,regi,te) $ (regi_group(ext_regi,regi)) = 1;
);
$endif.tech_earlyreti
vm_capEarlyReti.up(ttot,regi,te) $ (ttot.val < 2010 or ttot.val > 2110) = 0;
vm_capEarlyReti.lo(t,regi,te) $ (vm_capEarlyReti.up(t,regi,te) >= 1 and t.val > 2010 and t.val <= 2100) = 1e-4;
vm_capEarlyReti.fx(t,regi,"dot") = 0;
$ifthen %c_SSP_forcing_adjust% == "forcing_SSP1"
  vm_prodSe.up(t,regi,"pecoal","seliqfos","coalftrec")  $ (t.val > 2050) = 1e-5;
  vm_prodSe.up(t,regi,"pecoal","seliqfos","coalftcrec") $ (t.val > 2010) = 1e-5;
  
  vm_deltaCap.up(t,regi,"coalgas",rlf) $ (t.val > 2010) = 1e-5;
$endif
$ifthen %c_SSP_forcing_adjust% == "forcing_SSP2"
if(cm_emiscen > 1,
  vm_prodSe.up(t,regi,"pecoal","seliqfos","coalftcrec") $ (t.val > 2010) = 1e-5;
);
$endif

6. Energy demand sectors and final energy

upper and lower bounds on FE carrier shares

v_shfe.up(t,regi,entyFe,sector) $ pm_shfe_up(t,regi,entyFe,sector) = pm_shfe_up(t,regi,entyFe,sector);
v_shfe.lo(t,regi,entyFe,sector) $ pm_shfe_lo(t,regi,entyFe,sector) = pm_shfe_lo(t,regi,entyFe,sector);

upper and lower bounds on gases+liquids share in FE

v_shGasLiq_fe.up(t,regi,sector) $ pm_shGasLiq_fe_up(t,regi,sector) = pm_shGasLiq_fe_up(t,regi,sector);
v_shGasLiq_fe.lo(t,regi,sector) $ pm_shGasLiq_fe_lo(t,regi,sector) = pm_shGasLiq_fe_lo(t,regi,sector);

Set H2 upper bound in buildings for years defined at cm_H2InBuildOnlyAfter

vm_demFeSector.up(t,regi,"seh2","feh2s","build",emiMkt) $ (t.val <= cm_H2InBuildOnlyAfter) = 1e-6;

upper bound on bioliquids as a share of transport liquids

v_shBioTrans.up(t,regi) $ (t.val > 2020) = c_shBioTrans;

7. Assumptions for emissions

vm_emiMacSector.lo(t,regi,enty) = 0;
vm_emiMacSector.lo(t,regi,"co2luc") = -5.0; !! afforestation can lead to negative emissions
vm_emiMacSector.lo(t,regi,"n2ofertsom") = -1; !! small negative emissions can result from human activity
vm_emiMac.fx(t,regi,"so2") = 0;
vm_emiMac.fx(t,regi,"bc") = 0;
vm_emiMac.fx(t,regi,"oc") = 0;
vm_emiFgas.fx(ttot,all_regi,all_enty) = f_emiFgas(ttot,all_regi,"%c_SSP_forcing_adjust%","%cm_rcp_scen%","SPA0",all_enty);
display vm_emiFgas.L;

Other bounds

Bounds on 1st generation biomass annual production

Prescribe upper and lower limit for first generation biomass from 2030 on, so REMIND has some freedom before. After 2030 the production of 1st generation biofuels should be fixed (within a 90-100% range to avoid infeasibilities), since production values are exogenously harmonized with MAgPIE. Note: these bounds need to be updated since they are, in some regions, too strict to be compatible with historically installed capacities, such that the bounds in its current form can only be satisfied in combination with early retirement.

vm_fuExtr.up(t,regi,"pebios","5")$(t.val ge 2030)  = p30_datapebio(regi,"pebios","5","maxprod",t);
vm_fuExtr.up(t,regi,"pebioil","5")$(t.val ge 2030) = p30_datapebio(regi,"pebioil","5","maxprod",t);
if(cm_1stgen_phaseout=0,
    vm_fuExtr.lo(t,regi,"pebios","5")$(t.val ge 2030)  = 0.9 * p30_datapebio(regi,"pebios","5","maxprod",t);
    vm_fuExtr.lo(t,regi,"pebioil","5")$(t.val ge 2030) = 0.9 * p30_datapebio(regi,"pebioil","5","maxprod",t);
else                                                     
    vm_fuExtr.lo(t,regi,"pebios","5")$(t.val eq 2030)  = 0.9 * p30_datapebio(regi,"pebios","5","maxprod",t);
    vm_fuExtr.lo(t,regi,"pebioil","5")$(t.val eq 2030) = 0.9 * p30_datapebio(regi,"pebioil","5","maxprod",t);
);

Bounds on 2nd generation biomass annual production

  1. Bound on residues
p30_maxprod_residue(ttot,regi)     = max(p30_datapebio(regi,"pebiolc","2","maxprod",ttot), sum(teBioPebiolc, pm_pedem_res(ttot,regi,teBioPebiolc)));
vm_fuExtr.up(t,regi,"pebiolc","2") = p30_maxprod_residue(t,regi)*1.0001;
  1. Bound on purpose grown biomass
$ifthen.bioenergymaxscen not %cm_maxProdBiolc% == "off"
p30_max_pebiolc_path_glob(t) = %cm_maxProdBiolc% * sm_EJ_2_TWa;
p30_max_pebiolc_path_glob(t) = p30_max_pebiolc_path_glob(t) - sum(regi, p30_maxprod_residue(t,regi));
display p30_max_pebiolc_path_glob;

Calclate regional bounds with equal marginal costs from global bound

loop(ttot$(ttot.val ge cm_startyear),
     p30_max_pebiolc_dummy = 0;
     p30_pebiolc_price_dummy = 0.01;
     while(p30_max_pebiolc_dummy < p30_max_pebiolc_path_glob(ttot),
           loop(regi$(NOT sameas(regi,'JPN')),
                if( p30_pebiolc_price_dummy > (i30_bioen_price_a(ttot,regi)) * 1.01,
                      p30_fuelex_dummy(regi) = (p30_pebiolc_price_dummy - i30_bioen_price_a(ttot,regi)) / i30_bioen_price_b(ttot,regi);
                 else
                      p30_fuelex_dummy(regi) = 0;
                );
           ); 
           p30_max_pebiolc_dummy = sum(regi, p30_fuelex_dummy(regi));
           p30_pebiolc_price_dummy = p30_pebiolc_price_dummy + 0.001;
     );
     p30_max_pebiolc_path(regi,ttot) = p30_fuelex_dummy(regi);
);
display p30_max_pebiolc_path;

According to EMF guidelines, the upper bound on total (residues+purpose) global biomass production does not include traditional biomass use. Since the demand for traditional biomass is already supplied by the residue grade we expand the purpose-grown grade by the demand for traditional biomass.

vm_fuExtr.up(t,regi,"pebiolc","1") = p30_max_pebiolc_path(regi,t) + pm_pedem_res(t,regi,"biotr");
$endif.bioenergymaxscen

Phase out capacities of bioenergy technologies that use

pebiolc as feedstock, if defined in config

if (cm_phaseoutBiolc eq 1,
    loop(t$(t.val ge max(2025, cm_startyear)),
        loop(regi,
            loop(te(teBioPebiolc),
                loop(rlf,
                    if(vm_deltaCap.up(t,regi,te,rlf) eq INF,
                       vm_deltaCap.up(t,regi,te,rlf) = 1e-6;
                    );
                );
            );
        );
    );
);

Model Bounds in Regipol Module (region-specific bounds with hard-coded regions)

These bounds are only active if in 47_regipol module the realization is regiCarbonPrice. They mostly refer to region-specific fixings of the model in European subregions to better represent historic or near-term values or specific policies of regions (e.g. national coal phase-out plans etc.).

Bounds for Germany
Bounds for Historic and Near-term Alignment

Power Sector

$ifThen.tech_bounds_2025 "%cm_tech_bounds_2025%" == "on"

This limits wind and solar PV capacity additions for 2025 in light of recent slow developments as of 2023. Upper bound is double the historic maximum capacity addition in 2011-2020. In addition: Limit solar PV capacity to 120 GW in 2025 (2023-2027 average) given that we are at only 76 GW PV in 2023

loop(regi$(sameAs(regi,"DEU")),
  vm_deltaCap.up("2025",regi,"windon","1")=2*smax(tall$(tall.val ge 2011 and tall.val le 2020), pm_delta_histCap(tall,regi,"windon"));
  vm_deltaCap.up("2025",regi,"spv","1")=2*smax(tall$(tall.val ge 2011 and tall.val le 2020), pm_delta_histCap(tall,regi,"spv"));
  vm_cap.up("2025",regi,"spv","1")=0.12;
);
$endIf.tech_bounds_2025

These bounds account for historic gas power development. TODO: Historical fixings should be done in the core the via input data from mrremind, this still needs to be moved

v47_prodSEtotal.up("2020",regi,"pegas","seel")$(sameAs(regi,"DEU"))= 0.36*sm_EJ_2_TWa;
$ifThen.tech_bounds_2025 "%cm_tech_bounds_2025%" == "on"
v47_prodSEtotal.up("2025",regi,"pegas","seel")$(sameAs(regi,"DEU"))= 0.4*sm_EJ_2_TWa;
$endIf.tech_bounds_2025

These bounds account for historic coal power development.

vm_cap.up("2020",regi,"pc","1")$((cm_startyear le 2020) and (sameas(regi,"DEU"))) = 38.028/1000;

This limits early retirement of coal power in Germany in 2020s to avoid extremly fast phase-out.

vm_capEarlyReti.up('2025',regi,'pc')$(sameAs(regi,"DEU")) = 0.65;

This aligns 2020 chp capcities for Germany with historic data (AGEB) most of district heating is provided by CHP plants. coal share of chp heat output to be between 20-25% of total district heating demand gas share of chp heat output to be between 50-55% of total district heating demand bio share of chp heat output to be between 15-25% of total district heating demand TODO: Historical fixings should be done in the core via input data from mrremind, this still needs to be moved

loop(regi$(sameAs(regi,"DEU")),
    loop(t$(t.val eq 2020),
        vm_cap.lo(t,regi,"coalchp","1")= 0.2
                                            * (pm_cesdata(t,regi,"feheb","quantity")
                                                + pm_cesdata(t,regi,"feheb","quantity"))
                                            / pm_eta_conv(t,regi,"tdhes")
                                            /  pm_prodCouple(regi,"pecoal","seel","coalchp","sehe")
                                            / pm_cf(t,regi,"coalchp");
        vm_cap.up(t,regi,"coalchp","1")= 0.25
                                            * (pm_cesdata(t,regi,"feheb","quantity")
                                                + pm_cesdata(t,regi,"feheb","quantity"))
                                            / pm_eta_conv(t,regi,"tdhes")
                                            /  pm_prodCouple(regi,"pecoal","seel","coalchp","sehe")
                                            / pm_cf(t,regi,"coalchp");
        vm_cap.lo(t,regi,"gaschp","1")= 0.5
                                            * (pm_cesdata(t,regi,"feheb","quantity")
                                                + pm_cesdata(t,regi,"feheb","quantity"))
                                            / pm_eta_conv(t,regi,"tdhes")
                                            /  pm_prodCouple(regi,"pegas","seel","gaschp","sehe")
                                            / pm_cf(t,regi,"gaschp");
        vm_cap.up(t,regi,"gaschp","1")= 0.55
                                            * (pm_cesdata(t,regi,"feheb","quantity")
                                                + pm_cesdata(t,regi,"feheb","quantity"))
                                            / pm_eta_conv(t,regi,"tdhes")
                                            /  pm_prodCouple(regi,"pegas","seel","gaschp","sehe")
                                            / pm_cf(t,regi,"gaschp");
        vm_cap.lo(t,regi,"biochp","1")= 0.15
                                            * (pm_cesdata(t,regi,"feheb","quantity")
                                                + pm_cesdata(t,regi,"feheb","quantity"))
                                            / pm_eta_conv(t,regi,"tdhes")
                                            /  pm_prodCouple(regi,"pebiolc","seel","biochp","sehe")
                                            / pm_cf(t,regi,"biochp");
        vm_cap.up(t,regi,"biochp","1")= 0.25
                                            * (pm_cesdata(t,regi,"feheb","quantity")
                                                + pm_cesdata(t,regi,"feheb","quantity"))
                                            / pm_eta_conv(t,regi,"tdhes")
                                            /  pm_prodCouple(regi,"pebiolc","seel","biochp","sehe")
                                            / pm_cf(t,regi,"biochp");
    );
);

Carbon Management

only start industry carbon capture in Germany by 2030 as status of projects for 2025 unclear, see IEA CCUS database https://www.iea.org/data-and-statistics/data-tools/ccus-projects-explorer

vm_emiIndCCS.up(t,regi,emiInd37)$(sameAs(regi,"DEU") AND t.val lt 2030)=0;
Bounds for Germany-specific Policies (activated by switches)

If c_noPeFosCCDeu = 1 chosen, fossil CCS for energy system technologies (pe2se) is forbidden.

vm_emiTeDetail.up(t,regi,peFos,entySe,teFosCCS,"cco2")$((sameas(regi,"DEU")) AND (cm_noPeFosCCDeu = 1)) = 1e-4;

If cm_deuCDRmax >= 0, limit German CDR amount (Energy system BECCS, DACCS, EW and negative Landuse Change emissions) to cm_deuCDRmax. Convert cm_deuCDRmax from MtCO2/yr to model unit of GtC/yr.

vm_emiCdrAll.up(t,regi)$((cm_deuCDRmax ge 0) AND (sameas(regi,"DEU"))) = cm_deuCDRmax / 1000 / sm_c_2_co2;

Bounds for German Energy Security Scenario (activated by switches) Background: The energy security scenario used for the Ariadne Report on energy sovereignity in 2022 assumes that there is a continued gas crisis after 2022/23 in Germany with higher gas prices (see cm_EnSecScen_price) or limits to gas consumption (see cm_EnSecScen_limit switch) in the medium-term. Moreover, this scenario is characterized by a more pronounced role of coal power in the short-term as well as a greater role of industrial relocation and behavioral and energy efficiency transformations in demand sectors. Bounds in this section refer to energy supply technologies only.  
Policy in energy security scenario for Germany: 5GW(el) electrolysis installed by 2030 in Germany at minimum.

$ifThen.ensec "%cm_Ger_Pol%" == "ensec"
    vm_cap.lo("2030",regi,"elh2","1")$(sameAs(regi,"DEU"))=5*pm_eta_conv("2030",regi,"elh2")/1000;
$endIf.ensec

Policy in energy security scenario for Germany: increase coal power capacity factors and decrease gas power capacity factors until 2030 to account for short-term gas to coal switch under the assumption of a continued gas crisis.

$ifThen.ensec "%cm_Ger_Pol%" == "ensec"
    vm_capFac.up("2025",regi,"pc")$sameas(regi,"DEU") = 0.6;
    vm_capFac.up("2030",regi,"pc")$sameas(regi,"DEU") = 0.6;
    vm_capFac.fx("2025",regi,"ngcc")$sameas(regi,"DEU") = 0.2;
    vm_capFac.lo("2030",regi,"ngcc")$sameas(regi,"DEU") = 0.2;
$endIf.ensec

Policy in energy security scenario for Germany activated by cm_EnSecScen_limit: Limit PE gas demand from 2025 on to cm_EnSecScen_limit (in EJ/yr) gas imports + domestic gas in Germany.

if (cm_EnSecScen_limit gt 0,
    vm_prodPe.up(t,regi,"pegas")$((t.val ge 2025) AND (sameas(regi,"DEU"))) = cm_EnSecScen_limit/pm_conv_TWa_EJ;
);
Bounds for EU subregions
Bounds for historic and near-term Alignment

This account for historic coal power developments. Bounds for UKI region: 2019 capacity = 7TWh, capacity factor = 0.6 -> ~1.35GW -> Assuming no new capacity -> average 2018-2022 = ~ 1GW

vm_cap.up("2020",regi,"pc","1")$((cm_startyear le 2020) and (sameas(regi,"UKI"))) = 1.3/1000; 
Bounds for EU-specific policies (activated by switches)

This accounts for different nuclear power policies that can be chosen for the EU subregions. Basic nuclear policies:

$IFTHEN.NucRegiPol not "%cm_NucRegiPol%" == "off" 

Germany Nuclear phase-out

    vm_cap.up(t,regi,"tnrs","1")$((t.val ge 2025) and (t.val ge cm_startyear) and (sameas(regi,"DEU"))) = 1E-6;

ESC -> no new Nuclear capacity (Italy had a plebiscite for this and Greece should not have any new capacity)

    vm_deltaCap.up(t,regi,"tnrs","1")$((t.val ge 2020) and (t.val ge cm_startyear) and (sameas(regi,"ESC"))) = 0;
$ENDIF.NucRegiPol  

Extended nuclear policies:

$IFTHEN.proNucRegiPol not "%cm_proNucRegiPol%" == "off" 

Pro nuclear countries tend to keep nuclear production by political decision assuming France would keep at least 80% of its 2015 nuclear capacity in the future.

vm_cap.lo(t,regi,"tnrs","1")$((t.val ge cm_startyear) and (sameas(regi,"FRA"))) = 0.8*pm_histCap("2015",regi,"tnrs");

Assuming Czech Republic would keep at least its 2015 nuclear capacity in the future (CZE corresponds to 61.8% of nuclear capacity of ECE in 2015)

vm_cap.lo(t,regi,"tnrs","1")$((t.val ge cm_startyear) and (sameas(regi,"ECE"))) = 0.618*pm_histCap("2015",regi,"tnrs");

Assuming Finland would keep at least its 2015 nuclear capacity in the future (FIN corresponds to 21.6% of nuclear capacity of ENC in 2015)

vm_cap.lo(t,regi,"tnrs","1")$((t.val ge cm_startyear) and (sameas(regi,"ENC"))) = 0.216*pm_histCap("2015",regi,"tnrs");

Assuming Romania would keep at least its 2015 nuclear capacity in the future (ROU corresponds to 22.1% of nuclear capacity of ECS in 2015)

vm_cap.lo(t,regi,"tnrs","1")$((t.val ge cm_startyear) and (sameas(regi,"ECS"))) = 0.221*pm_histCap("2015",regi,"tnrs");
$ENDIF.proNucRegiPol 

This accounts for different CCS policies that can be chosen for the EU subregions.

$IFTHEN.CCSinvestment not "%cm_CCSRegiPol%" == "off" 

earliest investment in Europe, with one timestep split between countries currently exploring - Norway (NEN), Netherlands (EWN) and UK (UKI) - and others

vm_deltaCap.up(t,regi,teCCS,rlf)$( (t.val lt %cm_CCSRegiPol%) AND (sameas(regi,"NEN") OR sameas(regi,"EWN") OR sameas(regi,"UKI"))) = 1e-6; 
vm_deltaCap.up(t,regi,teCCS,rlf)$( (t.val le %cm_CCSRegiPol%) AND (regi_group("EUR_regi",regi)) AND (NOT(sameas(regi,"NEN") OR sameas(regi,"EWN") OR sameas(regi,"UKI")))) = 1e-6;
$ENDIF.CCSinvestment

This accounts for different coal power phase-out policies that can be chosen for the EU subregions. It is based on Beyond Coal 2021 (https://beyond-coal.eu/2021/03/03/overview-of-national-phase-out-announcements-march-2021/), whith adjustment for possible delay in Italy.

$IFTHEN.CoalRegiPol not "%cm_CoalRegiPol%" == "off" 
    vm_cap.up(t,regi,te,"1")$((t.val ge 2025) and (t.val ge cm_startyear) and (sameas(te,"igcc") or sameas(te,"pc") or sameas(te,"coalchp")) and (sameas(regi,"ESW") or sameas(regi,"FRA") )) = 1E-6;
    vm_cap.up(t,regi,te,"1")$((t.val ge 2030) and (t.val ge cm_startyear) and (sameas(te,"igcc") or sameas(te,"pc") or sameas(te,"coalchp")) and (sameas(regi,"ENC") or sameas(regi,"ESC") or sameas(regi,"EWN") )) = 1E-6;

DEU coal-power capacity phase-out, upper bounds following the Kohleausstiegsgesetz from 2020. https://www.bmuv.de/themen/klimaschutz-anpassung/klimaschutz/nationale-klimapolitik/fragen-und-antworten-zum-kohleausstieg-in-deutschland

    vm_capTotal.up("2025",regi,"pecoal","seel")$(sameas(regi,"DEU"))=25/1000;
    vm_capTotal.up("2030",regi,"pecoal","seel")$(sameas(regi,"DEU"))=17/1000;
    vm_capTotal.up("2035",regi,"pecoal","seel")$(sameas(regi,"DEU"))=6/1000;
    vm_capTotal.up("2040",regi,"pecoal","seel")$(sameas(regi,"DEU"))=1E-6;

UK coal capacity phase-out

    vm_cap.up(t,regi,te,"1")$((t.val ge 2025) and (t.val ge cm_startyear) and (sameas(te,"igcc") or sameas(te,"pc") or sameas(te,"coalchp")) and (sameas(regi,"UKI"))) = 1E-6;
$ENDIF.CoalRegiPol  

Represent region-specific renewable power policies with minimum VRE shares over time.

$ifthen.cm_VREminShare not "%cm_VREminShare%" == "off"
  loop((ttot,ext_regi)$(p47_VREminShare(ttot,ext_regi)),
    loop(regi$(regi_group(ext_regi,regi)),
      v47_VREshare.lo(t,regi)$(t.val ge ttot.val) = p47_VREminShare(t,ext_regi);
    )
  )
;
$endIf.cm_VREminShare

This bounds fixes CES function quantity trajectories to exogenous data if cm_exogDem_scen is activated. It is used, for example, to hit specific, steel and cement production trajectories in policy scenarios for project-specific scenarios. It is not necessarily a policy but a different (exogenuous) assumption about future production trajectories than what REMIND produces endogenuously.

$ifthen.exogDemScen NOT "%cm_exogDem_scen%" == "off"
vm_cesIO.fx(t,regi,in)$(pm_exogDemScen(t,regi,"%cm_exogDem_scen%",in))=pm_exogDemScen(t,regi,"%cm_exogDem_scen%",in);
$endif.exogDemScen

This bound avoids hydrogen production from gas in the European region (unlikely to happen after recent gas trade changes)

vm_deltaCap.up(t,regi,"gasftrec",rlf)$((t.val gt 2005) and (regi_group("EUR_regi",regi))) = 0;
vm_deltaCap.up(t,regi,"gasftcrec",rlf)$((t.val gt 2005) and (regi_group("EUR_regi",regi))) = 0;

TODO: Historical fixings should be done in the core the via input data from mrremind, this still needs to be moved

$ifthen.chaCoalBounds not "%cm_chaCoalBounds%" == "off"
loop(regi$(sameAs(regi,"CHA")),
vm_deltaCap.lo("2025",regi,"pc","1") = 20 * 0.78 / 1e3;
vm_deltaCap.lo("2025",regi,"coalchp","1") = 20 * 0.22 / 1e3;
vm_deltaCap.lo("2030",regi,"pc","1") = 20 * 0.78 / 1e3;
vm_deltaCap.lo("2030",regi,"coalchp","1") = 20 * 0.22 / 1e3;
vm_capFac.fx("2020",regi,"pc") = 0.54;
vm_capFac.fx("2025",regi,"pc") = 0.438;
vm_capFac.fx("2030",regi,"pc") = 0.35;
vm_capFac.fx("2020",regi,"coalchp") = 0.54;
vm_capFac.fx("2025",regi,"coalchp") = 0.438;
vm_capFac.fx("2030",regi,"coalchp") = 0.35;
);
$endif.chaCoalBounds

Interfaces

Interface plot missing!

Realizations

References