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);
);
);
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") ;
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;
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;
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;
);
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;
);
);
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;
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
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;
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;
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);
);
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;
$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
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;
);
);
);
);
);
);
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.).
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;
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;
);
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;
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
Interface plot missing!