From a4182755bfee93ba4f85a48ce0268bb89fa43492 Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Wed, 1 Jul 2026 18:12:57 +0300 Subject: [PATCH 01/37] Revisit hydrogen module --- modules/03_RestOfEnergy/legacy/equations.gms | 3 +- modules/05_Hydrogen/legacy/declarations.gms | 20 +- modules/05_Hydrogen/legacy/equations.gms | 200 ++++--------------- modules/05_Hydrogen/legacy/input.gms | 4 +- modules/05_Hydrogen/legacy/postsolve.gms | 3 - modules/05_Hydrogen/legacy/preloop.gms | 24 +-- modules/06_CO2/legacy/equations.gms | 3 +- 7 files changed, 51 insertions(+), 206 deletions(-) diff --git a/modules/03_RestOfEnergy/legacy/equations.gms b/modules/03_RestOfEnergy/legacy/equations.gms index 775c1988..4e8c8229 100644 --- a/modules/03_RestOfEnergy/legacy/equations.gms +++ b/modules/03_RestOfEnergy/legacy/equations.gms @@ -174,8 +174,7 @@ Q03ConsFiEneSec(allCy,SSBS,EFS,YTIME)$(TIME(YTIME)$(runCy(allCy))).. V03OutTotTransf(allCy,SSBS,EFS2,YTIME) + V03ProdPrimary(allCy,EFS2,YTIME)$(not PGRENEF(EFS2)) ) - )$(not sameas("H2P",SSBS)) + - VmConsFuelH2Prod(allCy,EFS,YTIME)$sameas("H2P",SSBS); + )$(not sameas("H2P",SSBS)); Q03FinalEnergy(allCy,DSBS,EFS,YTIME)$(TIME(YTIME)$(runCy(allCy))$(SECtoEF(DSBS,EFS))$(not sameas("ICT",DSBS))).. VmFinalEnergy(allCy,DSBS,EFS,YTIME) diff --git a/modules/05_Hydrogen/legacy/declarations.gms b/modules/05_Hydrogen/legacy/declarations.gms index 5e061276..96a86032 100644 --- a/modules/05_Hydrogen/legacy/declarations.gms +++ b/modules/05_Hydrogen/legacy/declarations.gms @@ -2,18 +2,13 @@ *' @code Variables -V05GapShareH2Tech1(allCy, H2TECH, YTIME) "Shares of H2 production technologies in new market competition 1" -V05GapShareH2Tech2(allCy, H2TECH, YTIME) "Shares of H2 production technologies in new market competition 2" +V05GapShareH2Tech(allCy, H2TECH, YTIME) "Shares of H2 production technologies in new market competition 1" V05CapScrapH2ProdTech(allCy, H2TECH, YTIME) "Decommissioning of capacity by H2 production technology" V05PremRepH2Prod(allCy, H2TECH, YTIME) "Premature replacement of H2 production technologies" V05ScrapLftH2Prod(allCy, H2TECH, YTIME) "Scrapping of equipment due to lifetime (normal scrapping)" V05DemGapH2(allCy, YTIME) "Demand for H2 to be covered by new equipment in mtoe" V05CostProdH2Tech(allCy, H2TECH, YTIME) "Hydrogen production cost per technology in US$2015 per toe of hydrogen" V05CostVarProdH2Tech(allCy, H2TECH, YTIME) "Variable cost (including fuel cost) for hydrogen production by technology in US$2015 per toe" -V05ShareCCSH2Prod(allCy, H2TECH, YTIME) "Share of CCS technology in the decision tree between CCS and no CCS" -V05ShareNoCCSH2Prod(allCy, H2TECH, YTIME) "Share of technology without CCS in the decision tree between CCS and no CCS" -V05AcceptCCSH2Tech(allCy, YTIME) "Acceptance of investment in CCS technologies" -V05CostProdCCSNoCCSH2Prod(allCy, H2TECH, YTIME) "Production cost of the composite technology with and without CCS in Euro per toe" VmCostAvgProdH2(allCy, YTIME) "Average production cost of hydrogen in Euro per toe" V05CaptRateH2(allCy,H2TECH,YTIME) @@ -39,26 +34,17 @@ $offtext *' **Interdependent Variables** VmDemTotH2(allCy, YTIME) "Hydrogen production requirement in Mtoe for meeting final demand" VmProdH2(allCy, H2TECH, YTIME) "Hydrogen Production by technology in Mtoe" -VmConsFuelTechH2Prod(allCy, H2TECH, EF, YTIME) "Fuel consumption by hydrogen production technology in Mtoe" -VmDemSecH2(allCy, SBS, YTIME) "Demand for H2 by sector in mtoe" VmCostAvgProdH2(allCy, YTIME) "Average production cost of hydrogen in Euro per toe" -VmConsFuelH2Prod(allCy, EF, YTIME) "Total fuel consumption for hydrogen production in Mtoe" ; Equations -Q05GapShareH2Tech1(allCy, H2TECH, YTIME) "Equation for calculating the shares of technologies in hydrogen gap using Weibull equations 1" -Q05GapShareH2Tech2(allCy, H2TECH, YTIME) "Equation for calculating the shares of technologies in hydrogen gap using Weibull equations 2" +Q05GapShareH2Tech(allCy, H2TECH, YTIME) "Equation for calculating the shares of technologies in hydrogen gap using Weibull equations 1" Q05CapScrapH2ProdTech(allCy, H2TECH, YTIME) "Equation for decommissioning of capacity by H2 production technology" Q05PremRepH2Prod(allCy, H2TECH, YTIME) "Equation for premature replacement of H2 production technologies" Q05ScrapLftH2Prod(allCy, H2TECH, YTIME) "Equation for scrapping of equipment due to lifetime (normal scrapping)" Q05DemGapH2(allCy, YTIME) "Equation for gap in hydrogen demand" Q05CostProdH2Tech(allCy, H2TECH, YTIME) "Equation for hydrogen production cost per technology" Q05CostVarProdH2Tech(allCy, H2TECH, YTIME) "Equation for variable cost (including fuel cost) for hydrogen production by technology in Euro per toe" -Q05ShareCCSH2Prod(allCy, H2TECH, YTIME) "Equation for share of CCS technology in the decision tree between CCS and no CCS" -Q05ShareNoCCSH2Prod(allCy, H2TECH, YTIME) "Equation for share of technology without CCS in the decision tree between CCS and no CCS" -Q05AcceptCCSH2Tech(allCy, YTIME) "Equation for acceptance in CCS technologies" -Q05ConsFuelH2Prod(allCy, EF, YTIME) "Equation for total fuel consumption for hydrogen production" -Q05CostProdCCSNoCCSH2Prod(allCy, H2TECH, YTIME) "Equation for calculating the production cost of the composite technology with and without CCS" Q05CostAvgProdH2(allCy, YTIME) "Equation for average production cost of hydrogen in Euro per toe" Q05CaptRateH2(allCy,H2TECH,YTIME) $ontext @@ -80,8 +66,6 @@ $offtext *' **Interdependent Equations** Q05DemTotH2(allCy, YTIME) "Equation for total hydrogen demand in a country in Mtoe" Q05ProdH2(allCy, H2TECH, YTIME) "Equation for H2 production by technology" -Q05ConsFuelTechH2Prod(allCy, H2TECH, EF, YTIME) "Equation for fuel consumption by technology for hydrogen production" -Q05DemSecH2(allCy, SBS, YTIME) "Equation for demand of H2 by sector in mtoe" ; Scalars diff --git a/modules/05_Hydrogen/legacy/equations.gms b/modules/05_Hydrogen/legacy/equations.gms index f3a48c07..edc810c1 100644 --- a/modules/05_Hydrogen/legacy/equations.gms +++ b/modules/05_Hydrogen/legacy/equations.gms @@ -7,43 +7,13 @@ Q05DemTotH2(allCy,YTIME)$(TIME(YTIME)$(runCy(allCy))).. VmDemTotH2(allCy,YTIME) =E= V03ConsGrssInl(allCy,"H2F",YTIME) - VmImpNetEneBrnch(allCy,"H2F",YTIME); -$ontext - sum(SBS$SECtoEF(SBS,"H2F"), - VmDemSecH2(allCy,SBS, YTIME) / - prod(INFRTECH$H2INFRSBS(INFRTECH,SBS), - i05EffH2Transp(allCy,INFRTECH,YTIME)* - (1-i05ConsSelfH2Transp(allCy,INFRTECH,YTIME)) - ) - ) !! increase the demand due to transportation losses -$offtext - -*' This equation calculates the sectoral hydrogen demand (VmDemSecH2) for each demand subsector (DSBS), year, and region. -*' It sums up hydrogen consumption from both industrial/tertiary sectors (using VmConsFuel) and transport sectors (using VmDemFinEneTranspPerFuel), -*' ensuring each subsector receives only the relevant demand. -Q05DemSecH2(allCy,SBS,YTIME)$(TIME(YTIME)$(runCy(allCy))).. - VmDemSecH2(allCy,SBS,YTIME) - =E= - 0;!! Unnecessary variable? author = mmadianos - !!sum(INDDOM$SAMEAS(INDDOM,SBS), VmConsFuel(allCy,INDDOM,"H2F",YTIME)) + - !!sum(TRANSE$SAMEAS(TRANSE,SBS), VmDemFinEneTranspPerFuel(allCy,TRANSE,"H2F",YTIME)) + - !!VmConsFuelCDRProd(allCy,"H2F",YTIME)$sameas("DAC",SBS) + - !!VmConsFuelCDRProd(allCy,"H2F",YTIME)$sameas("EW",SBS) + - !!VmConsFuelElecProd(allCy,"H2F",YTIME)$sameas("PG",SBS); *' This equation defines the amount of hydrogen production capacity that is scrapped due to the expiration of the useful life of plants. *' It considers the remaining lifetime of hydrogen production facilities and the impact of past production gaps. Q05ScrapLftH2Prod(allCy,H2TECH,YTIME)$(TIME(YTIME)$(runCy(allCy))).. - V05ScrapLftH2Prod(allCy,H2TECH,YTIME) - =E= - (1/i05ProdLftH2(H2TECH,YTIME))$(ord(YTIME)>14+i05ProdLftH2(H2TECH,YTIME)) -$ontext - ( - V05GapShareH2Tech1(allCy,H2TECH,YTIME-i05ProdLftH2(H2TECH,YTIME)) * - V05DemGapH2(allCy,YTIME-i05ProdLftH2(H2TECH,YTIME)) / - (VmProdH2(allCy,H2TECH,YTIME-1) + 1e-6) - )$(ord(YTIME)>14+i05ProdLftH2(H2TECH,YTIME)) -$offtext -; + V05ScrapLftH2Prod(allCy,H2TECH,YTIME) + =E= + (1/i05ProdLftH2(H2TECH,YTIME))$(ord(YTIME)>14+i05ProdLftH2(H2TECH,YTIME)); *' This equation models the premature replacement of hydrogen production capacity. It adjusts for the need to replace aging *' or inefficient hydrogen production technologies before their expected end of life based on economic factors such as cost, @@ -77,23 +47,23 @@ Q05CapScrapH2ProdTech(allCy,H2TECH,YTIME)$(TIME(YTIME)$(runCy(allCy))).. *' The hydrogen demand gap equation defines the difference between the total hydrogen demand (calculated in Q05DemTotH2) and *' the actual hydrogen production capacity. It ensures that the gap value is non-negative, preventing overproduction or underproduction of hydrogen. -Q05DemGapH2(allCy, YTIME)$(TIME(YTIME)$(runCy(allCy))).. - V05DemGapH2(allCy, YTIME) - =E= - ( - VmDemTotH2(allCy,YTIME) - - sum(H2TECH, - (1-V05CapScrapH2ProdTech(allCy,H2TECH,YTIME)) * - VmProdH2(allCy,H2TECH,YTIME-1) - ) + - SQRT( SQR( - VmDemTotH2(allCy,YTIME) - - sum(H2TECH, - (1-V05CapScrapH2ProdTech(allCy,H2TECH,YTIME)) * - VmProdH2(allCy,H2TECH,YTIME-1) - ) - )) )/2 -; +Q05DemGapH2(allCy,YTIME)$(TIME(YTIME)$(runCy(allCy))).. + V05DemGapH2(allCy,YTIME) + =E= + ( + VmDemTotH2(allCy,YTIME) - + sum(H2TECH, + (1-V05CapScrapH2ProdTech(allCy,H2TECH,YTIME)) * + VmProdH2(allCy,H2TECH,YTIME-1) + ) + + SQRT(SQR( + VmDemTotH2(allCy,YTIME) - + sum(H2TECH, + (1-V05CapScrapH2ProdTech(allCy,H2TECH,YTIME)) * + VmProdH2(allCy,H2TECH,YTIME-1) + ) + )) + ) / 2; *' This equation calculates the production costs of hydrogen, including both fixed costs (e.g., capital investment) *' and variable costs (e.g., operational expenses). The costs are typically differentiated by hydrogen production @@ -103,114 +73,44 @@ Q05CostProdH2Tech(allCy,H2TECH,YTIME)$(TIME(YTIME)$(runCy(allCy))).. =E= ( imDisc(allCy,"H2P",YTIME) * - exp(imDisc(allCy,"H2P",YTIME)* i05ProdLftH2(H2TECH,YTIME)) / + exp(imDisc(allCy,"H2P",YTIME) * i05ProdLftH2(H2TECH,YTIME)) / (exp(imDisc(allCy,"H2P",YTIME) * i05ProdLftH2(H2TECH,YTIME))-1) * ( i05CostCapH2Prod(allCy,H2TECH,YTIME) + - i05CostFOMH2Prod(allCy,H2TECH,YTIME) + - i05CostVOMH2Prod(allCy,H2TECH,YTIME) + i05CostFOMH2Prod(allCy,H2TECH,YTIME) ) + - (V04CapexFixCostPG(allCy,"PGSOL",YTIME))$sameas(H2TECH,"wes") + - (V04CapexFixCostPG(allCy,"PGAWNO",YTIME))$sameas(H2TECH,"wew") + V04CapexFixCostPG(allCy,"PGSOL",YTIME)$sameas(H2TECH,"wes") + + V04CapexFixCostPG(allCy,"PGAWNO",YTIME)$sameas(H2TECH,"wew") ) / (i05AvailH2Prod(allCy,H2TECH,YTIME) * smGwToTwhPerYear(YTIME) * smTWhToMtoe) + V05CostVarProdH2Tech(allCy,H2TECH,YTIME); - + *' This equation models the variable costs associated with hydrogen production, factoring in fuel prices (e.g., electricity or natural gas), *' CO₂ emission costs, and the efficiency of the production technology. This helps to understand the fluctuating costs based on market conditions. Q05CostVarProdH2Tech(allCy,H2TECH,YTIME)$(TIME(YTIME)$(runCy(allCy))).. V05CostVarProdH2Tech(allCy,H2TECH,YTIME) =E= sum(EF$H2TECHEFtoEF(H2TECH,EF), - ( - VmPriceFuelSubsecCarVal(allCy,"H2P",EF,YTIME) * 1e3 + - V05CaptRateH2(allCy,H2TECH,YTIME) * (imCo2EmiFac(allCy,"H2P",EF,YTIME) + 4.17$(sameas("BMSWAS", EF))) * VmCstCO2SeqCsts(allCy,YTIME) + - (1-V05CaptRateH2(allCy,H2TECH,YTIME)) * imCo2EmiFac(allCy,"H2P",EF,YTIME) * sum(NAP$NAPtoALLSBS(NAP,"H2P"),VmCarVal(allCy,NAP,YTIME)) - ) - )$(not H2TECHREN(H2TECH)) / i05EffH2Prod(allCy,H2TECH,YTIME) + - (i04VarCost("PGSOL",YTIME) / (smTWhToMtoe))$(sameas(H2TECH,"wes")) + - (i04VarCost("PGAWNO",YTIME) / (smTWhToMtoe))$(sameas(H2TECH,"wew")) -; - -*' This equation models the acceptance of carbon capture and storage (CCS) technologies in hydrogen production. -*' It evaluates the economic feasibility of adding CCS to the hydrogen production process, considering cost, -*' environmental policies, and technology readiness. -Q05AcceptCCSH2Tech(allCy,YTIME)$(TIME(YTIME)$(runCy(allCy))).. - V05AcceptCCSH2Tech(allCy,YTIME) - =E= - i05WBLGammaH2Prod(allCy,YTIME)*2 + - EXP(-0.06*((sum(NAP$NAPtoALLSBS(NAP,"H2P"),VmCarVal(allCy,NAP,YTIME -1))))) -; - -*' This equation determines the share of hydrogen produced using CCS technologies compared to those produced without CCS. -*' The share is calculated based on relative costs, technological feasibility, and policy incentives supporting CCS. -Q05ShareCCSH2Prod(allCy,H2TECH,YTIME)$(TIME(YTIME) $H2CCS(H2TECH) $(runCy(allCy))).. - V05ShareCCSH2Prod(allCy,H2TECH,YTIME) - =E= - 1.5 * - iWBLShareH2Prod(allCy,H2TECH,YTIME) * - (V05CostProdH2Tech(allCy,H2TECH,YTIME-1) + 1e-3)**(-V05AcceptCCSH2Tech(allCy,YTIME)) / - ( - 1.5 * - iWBLShareH2Prod(allCy,H2TECH,YTIME) * - (V05CostProdH2Tech(allCy,H2TECH,YTIME-1) + 1e-3)**(-V05AcceptCCSH2Tech(allCy,YTIME)) + - - sum(H2TECH2$H2CCS_NOCCS(H2TECH,H2TECH2), - - 1 * - iWBLShareH2Prod(allCy,H2TECH2,YTIME) * - (V05CostProdH2Tech(allCy,H2TECH,YTIME-1) + 1e-3)**(-V05AcceptCCSH2Tech(allCy,YTIME))) - ) -; - -*' Similar to Q05ShareCCSH2Prod, this equation models the share of hydrogen produced without CCS technologies. -*' It calculates the proportion of production from non-CCS methods like electrolysis or SMR without CO₂ capture. -Q05ShareNoCCSH2Prod(allCy,H2TECH,YTIME)$(TIME(YTIME) $H2NOCCS(H2TECH) $(runCy(allCy))).. - V05ShareNoCCSH2Prod(allCy,H2TECH,YTIME) - =E= - 1 - sum(H2TECH2$H2CCS_NOCCS(H2TECH2,H2TECH) , V05ShareCCSH2Prod(allCy,H2TECH2,YTIME) ) -; - -*' This equation computes the weighted average production cost of hydrogen, incorporating both CCS and non-CCS production methods. -*' It provides an overall cost perspective, helping to assess which production methods dominate the market based on cost-efficiency. -Q05CostProdCCSNoCCSH2Prod(allCy,H2TECH,YTIME)$(TIME(YTIME) $H2NOCCS(H2TECH) $(runCy(allCy))) .. - V05CostProdCCSNoCCSH2Prod(allCy,H2TECH,YTIME) - =E= - V05ShareNoCCSH2Prod(allCy,H2TECH,YTIME)*V05CostProdH2Tech(allCy,H2TECH,YTIME)+ - sum(H2CCS$H2CCS_NOCCS(H2CCS,H2TECH), V05ShareCCSH2Prod(allCy,H2CCS,YTIME)*V05CostProdH2Tech(allCy,H2CCS,YTIME)) -; - -*' This equation calculates the market share of different hydrogen production technologies, considering factors -*' like cost competitiveness, policy support, and fuel availability. It adjusts market shares based on technological -*' performance and shifting cost dynamics. -Q05GapShareH2Tech2(allCy,H2TECH,YTIME)$(TIME(YTIME)$(runCy(allCy))).. - V05GapShareH2Tech2(allCy,H2TECH,YTIME) - =E= - ( - iWBLShareH2Prod(allCy,H2TECH,YTIME) * - ( - V05CostProdH2Tech(allCy,H2TECH,YTIME-1)$(not H2NOCCS(H2TECH)) + - V05CostProdCCSNoCCSH2Prod(allCy,H2TECH,YTIME-1)$H2NOCCS(H2TECH) - )**(-i05WBLGammaH2Prod(allCy,YTIME)) / - sum(H2TECH2$(not H2CCS(H2TECH2)), - iWBLShareH2Prod(allCy,H2TECH2,YTIME) * - ( - V05CostProdH2Tech(allCy,H2TECH2,YTIME-1)$(not H2NOCCS(H2TECH2)) + - V05CostProdCCSNoCCSH2Prod(allCy,H2TECH2,YTIME-1)$H2NOCCS(H2TECH2) - )**(-i05WBLGammaH2Prod(allCy,YTIME)) - ) - )$(not H2CCS(H2TECH)) + - sum(H2NOCCS$H2CCS_NOCCS(H2TECH,H2NOCCS), V05GapShareH2Tech2(allCy,H2NOCCS,YTIME))$H2CCS(H2TECH); + VmPriceFuelSubsecCarVal(allCy,"H2P",EF,YTIME) * 1e3 + + V05CaptRateH2(allCy,H2TECH,YTIME) * (imCo2EmiFac(allCy,"H2P",EF,YTIME) + 4.17$(sameas("BMSWAS", EF))) * VmCstCO2SeqCsts(allCy,YTIME) + + (1-V05CaptRateH2(allCy,H2TECH,YTIME)) * imCo2EmiFac(allCy,"H2P",EF,YTIME) * sum(NAP$NAPtoALLSBS(NAP,"H2P"),VmCarVal(allCy,NAP,YTIME)) + ) / i05EffH2Prod(allCy,H2TECH,YTIME) + + i05CostVOMH2Prod(allCy,H2TECH,YTIME) + + (i04VarCost("PGSOL",YTIME) / smTWhToMtoe)$(sameas(H2TECH,"wes")) + + (i04VarCost("PGAWNO",YTIME) / smTWhToMtoe)$(sameas(H2TECH,"wew")); *' This equation further adjusts the market share of hydrogen technologies, particularly considering *' the relative competitiveness between CCS and non-CCS technologies. It helps to model the transition *' between different production technologies over time. -Q05GapShareH2Tech1(allCy,H2TECH,YTIME)$(TIME(YTIME)$(runCy(allCy))).. - V05GapShareH2Tech1(allCy,H2TECH,YTIME) +Q05GapShareH2Tech(allCy,H2TECH,YTIME)$(TIME(YTIME)$(runCy(allCy))).. + V05GapShareH2Tech(allCy,H2TECH,YTIME) =E= - V05GapShareH2Tech2(allCy,H2TECH,YTIME)$((not H2CCS(H2TECH)) $(not H2NOCCS(H2TECH))) + - V05GapShareH2Tech2(allCy,H2TECH,YTIME)*(V05ShareCCSH2Prod(allCy,H2TECH,YTIME)$H2CCS(H2TECH) + V05ShareNoCCSH2Prod(allCy,H2TECH,YTIME)$H2NOCCS(H2TECH)) -; + i05MatFacH2(allCy,H2TECH,YTIME) * + V05CostProdH2Tech(allCy,H2TECH,YTIME-1) ** (-2) / + SUM(H2TECH2, + i05MatFacH2(allCy,H2TECH2,YTIME) * + V05CostProdH2Tech(allCy,H2TECH2,YTIME-1) ** (-2) + ); *' This equation defines the actual hydrogen production levels, considering both scrapped capacity and the demand gap. *' It allocates production from different technologies to meet the overall demand, adjusting for changes in capacity and technology availability. @@ -218,7 +118,7 @@ Q05ProdH2(allCy,H2TECH,YTIME)$(TIME(YTIME)$(runCy(allCy))).. VmProdH2(allCy,H2TECH,YTIME) =E= (1-V05CapScrapH2ProdTech(allCy,H2TECH,YTIME)) * VmProdH2(allCy,H2TECH,YTIME-1) + - V05GapShareH2Tech1(allCy,H2TECH,YTIME) * V05DemGapH2(allCy,YTIME); + V05GapShareH2Tech(allCy,H2TECH,YTIME) * V05DemGapH2(allCy,YTIME); *' This equation calculates the average cost of hydrogen production across all technologies in the system. *' It accounts for varying costs of different technologies (e.g., electrolysis vs. SMR) to provide an overall assessment of hydrogen production cost. @@ -231,24 +131,6 @@ Q05CostAvgProdH2(allCy,YTIME)$(TIME(YTIME)$(runCy(allCy))).. ) / sum(H2TECH,VmProdH2(allCy,H2TECH,YTIME) + 1e-6); -*' This equation calculates the fuel consumption for each hydrogen production technology, considering -*' the efficiency of the technology and the amount of fuel required for producing a unit of hydrogen. -*' It provides insight into fuel demand for hydrogen production. -Q05ConsFuelTechH2Prod(allCy,H2TECH,EF,YTIME)$(TIME(YTIME) $H2TECHEFtoEF(H2TECH,EF) $(runCy(allCy))).. - VmConsFuelTechH2Prod(allCy,H2TECH,EF,YTIME) - =E= -* VmConsFuelTechH2Prod(allCy,H2TECH,EF,YTIME-1)+ - VmProdH2(allCy,H2TECH,YTIME)/i05EffH2Prod(allCy,H2TECH,YTIME)!!- -* (VmProdH2(allCy,H2TECH,YTIME-1)/i05EffH2Prod(allCy,H2TECH,YTIME-1)) -; - -*' This equation aggregates the total fuel consumption across all hydrogen production technologies in the system, -*' summing up the fuel requirements from all sources. It helps track the total fuel demand for hydrogen production. -Q05ConsFuelH2Prod(allCy,EF,YTIME)$(TIME(YTIME)$H2PRODEF(EF)$(runCy(allCy))).. - VmConsFuelH2Prod(allCy,EF,YTIME) - =E= - sum(H2TECH$H2TECHEFtoEF(H2TECH,EF),VmConsFuelTechH2Prod(allCy,H2TECH,EF,YTIME)) -; $ontext !! diff --git a/modules/05_Hydrogen/legacy/input.gms b/modules/05_Hydrogen/legacy/input.gms index 19cded6d..b189ed67 100644 --- a/modules/05_Hydrogen/legacy/input.gms +++ b/modules/05_Hydrogen/legacy/input.gms @@ -56,6 +56,7 @@ i05EffNetH2Transp(allCy,INFRTECH,YTIME) "Total efficiency of the distributio i05CostAvgWeight(allCy,YTIME) "Weight for pricing in average cost or in marginal cost" iWBLShareH2Prod(allCy,H2TECH,YTIME) "Maturity factors for H2 technologies" iWBLPremRepH2Prod(allCy,H2TECH,YTIME) "Maturity factors for premature replacement of H2 technologies" +i05MatFacH2(allCy,H2TECH,YTIME) ; *--- iWBLShareH2Prod(runCy,H2TECH,YTIME) = iTechShareH2Prod(H2TECH,YTIME); @@ -130,4 +131,5 @@ i05CostAvgWeight(runCy,YTIME) = 1; loop YTIME$(An(YTIME)) do i05CostAvgWeight(runCy,YTIME) = -1/19+i05CostAvgWeight(runCy,YTIME-1); endloop; -*--- \ No newline at end of file +*--- +i05MatFacH2(allCy,H2TECH,YTIME) = 1; \ No newline at end of file diff --git a/modules/05_Hydrogen/legacy/postsolve.gms b/modules/05_Hydrogen/legacy/postsolve.gms index 96537ac4..2165cace 100644 --- a/modules/05_Hydrogen/legacy/postsolve.gms +++ b/modules/05_Hydrogen/legacy/postsolve.gms @@ -5,14 +5,11 @@ * Hydrogen Module *--- -VmConsFuelTechH2Prod.FX(runCyL,H2TECH,EF,YTIME)$TIME(YTIME) = VmConsFuelTechH2Prod.L(runCyL,H2TECH,EF,YTIME)$TIME(YTIME); -V05GapShareH2Tech1.FX(runCyL,H2TECH,YTIME)$TIME(YTIME) = V05GapShareH2Tech1.L(runCyL,H2TECH,YTIME)$TIME(YTIME); VmProdH2.FX(runCyL,H2TECH,YTIME)$TIME(YTIME) = VmProdH2.L(runCyL,H2TECH,YTIME)$TIME(YTIME); V05DemGapH2.FX(runCyL,YTIME)$TIME(YTIME) = V05DemGapH2.L(runCyL,YTIME)$TIME(YTIME); VmCostAvgProdH2.FX(runCyL,YTIME)$TIME(YTIME) = VmCostAvgProdH2.L(runCyL,YTIME)$TIME(YTIME); V05CaptRateH2.FX(runCyL,H2TECH,YTIME)$TIME(YTIME) = V05CaptRateH2.L(runCyL,H2TECH,YTIME)$TIME(YTIME); V05CostProdH2Tech.FX(runCyL,H2TECH,YTIME)$TIME(YTIME) = V05CostProdH2Tech.L(runCyL,H2TECH,YTIME)$TIME(YTIME); -V05CostProdCCSNoCCSH2Prod.FX(runCyL,H2TECH,YTIME)$TIME(YTIME) = V05CostProdCCSNoCCSH2Prod.L(runCyL,H2TECH,YTIME)$TIME(YTIME); V05CostVarProdH2Tech.FX(runCyL,H2TECH,YTIME)$TIME(YTIME) = V05CostVarProdH2Tech.L(runCyL,H2TECH,YTIME)$TIME(YTIME); *V05DelivH2InfrTech.FX(runCyL,INFRTECH,YTIME)$TIME(YTIME) = V05DelivH2InfrTech.L(runCyL,INFRTECH,YTIME)$TIME(YTIME); *--- \ No newline at end of file diff --git a/modules/05_Hydrogen/legacy/preloop.gms b/modules/05_Hydrogen/legacy/preloop.gms index e3d36975..6ec878f6 100644 --- a/modules/05_Hydrogen/legacy/preloop.gms +++ b/modules/05_Hydrogen/legacy/preloop.gms @@ -9,8 +9,8 @@ *V05CostTotH2.FX(runCy,INDDOM,YTIME)$(not An(YTIME)) = imFuelPrice(runCy,INDDOM,"STE1AH2F",YTIME)$(not An(YTIME)); *display V05CostTotH2.L; *--- -V05GapShareH2Tech1.UP(runCy,H2TECH,YTIME) = 1; -V05GapShareH2Tech1.LO(runCy,H2TECH,YTIME) = 0; +V05GapShareH2Tech.UP(runCy,H2TECH,YTIME) = 1; +V05GapShareH2Tech.LO(runCy,H2TECH,YTIME) = 0; *--- V05DemGapH2.LO(runCy,YTIME) = 0; V05DemGapH2.L(runCy,YTIME) = 10; @@ -24,19 +24,11 @@ VmProdH2.LO(runCy,H2TECH, YTIME) = 0; VmProdH2.L(runCy,H2TECH, YTIME) = 0.5; VmProdH2.FX(runCy,H2TECH, YTIME)$DATAY(YTIME) = 0; *--- -*VmConsFuelTechH2Prod.L(runCy,H2TECH,EF,YTIME)$(not An(YTIME)$H2TECHEFtoEF(H2TECH,EF)) = 0; -VmConsFuelTechH2Prod.FX(runCy,H2TECH,EF,"%fBaseY%")$(H2TECHEFtoEF(H2TECH,EF)) = (VmProdH2.L(runCy,H2TECH,"%fBaseY%")/i05EffH2Prod(runCy,H2TECH,"%fBaseY%")); -display i05EffH2Prod; -display VmConsFuelTechH2Prod.L; -*--- *V05DelivH2InfrTech.L(runCy,INFRTECH,YTIME) = 2; *V05DelivH2InfrTech.FX(runCy,INFRTECH,YTIME)$(not An(YTIME)) = 1e-5; *V05DelivH2InfrTech.FX(runCy,INFRTECH,"%fBaseY%") = 0; *display V05DelivH2InfrTech.L; *--- -V05GapShareH2Tech2.LO(runCy,H2TECH,YTIME) = 0; -V05GapShareH2Tech2.UP(runCy,H2TECH,YTIME) = 1; -*--- V05CapScrapH2ProdTech.LO(runCy,H2TECH,YTIME) = 0; V05CapScrapH2ProdTech.UP(runCy,H2TECH,YTIME) = 1; *--- @@ -78,18 +70,6 @@ V05CostProdH2Tech.FX(runCy,H2TECH,YTIME)$DATAY(YTIME) = (i05AvailH2Prod(runCy,H2TECH,YTIME) * smGwToTwhPerYear(YTIME) * smTWhToMtoe) + V05CostVarProdH2Tech.L(runCy,H2TECH,YTIME); *--- -V05ShareCCSH2Prod.LO(runCy,H2TECH,YTIME) = 0; -V05ShareCCSH2Prod.UP(runCy,H2TECH,YTIME) = 1; -*--- -V05ShareNoCCSH2Prod.LO(runCy,H2TECH,YTIME) = 0; -V05ShareNoCCSH2Prod.UP(runCy,H2TECH,YTIME) = 1; -*--- -VmConsFuelH2Prod.FX(runCy,EF,YTIME)$(DATAY(YTIME) and H2PRODEF(EF)) = sum(H2TECH$H2TECHEFtoEF(H2TECH,EF),VmConsFuelTechH2Prod.L(runCy,H2TECH,EF,YTIME)); -VmConsFuelH2Prod.FX(runCy,EF,YTIME)$(not H2PRODEF(EF)) = 0; -*--- -V05CostProdCCSNoCCSH2Prod.LO(runCy,H2TECH,YTIME) = epsilon6; -V05CostProdCCSNoCCSH2Prod.L(runCy,H2TECH,YTIME) = 2; -*--- VmCostAvgProdH2.LO(runCy,YTIME) = 0; VmCostAvgProdH2.L(runCy,YTIME) = 1; VmCostAvgProdH2.FX(runCy,YTIME)$DATAY(YTIME) = diff --git a/modules/06_CO2/legacy/equations.gms b/modules/06_CO2/legacy/equations.gms index 1a39a7d6..75a634c9 100644 --- a/modules/06_CO2/legacy/equations.gms +++ b/modules/06_CO2/legacy/equations.gms @@ -21,7 +21,8 @@ Q06CO2CaptureCCS(allCy,SBS,EFS,YTIME)$(TIME(YTIME)$(runCy(allCy))$SECtoEF(SBS,EF V04CO2CaptRate(allCy,PGALL,YTIME) )$sameas("PG", SBS) + sum(H2TECH$H2TECHEFtoEF(H2TECH,EFS), - VmConsFuelTechH2Prod(allCy,H2TECH,EFS,YTIME) * + VmProdH2(allCy,H2TECH,YTIME) / + i05EffH2Prod(allCy,H2TECH,YTIME) * V05CaptRateH2(allCy,H2TECH,YTIME) )$sameas("H2P", SBS) + sum(DSBS$sameas(DSBS,SBS), From c77835f9a7a6d3cdd5131891a030835fe999dc8a Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Thu, 2 Jul 2026 15:30:42 +0300 Subject: [PATCH 02/37] Disaggregate between transformations and own energy use in the hydrogen module. --- modules/03_RestOfEnergy/legacy/equations.gms | 6 ++++-- modules/05_Hydrogen/legacy/equations.gms | 8 ++++---- modules/05_Hydrogen/legacy/input.gms | 13 ++++++------ modules/05_Hydrogen/legacy/preloop.gms | 4 ++-- modules/05_Hydrogen/legacy/sets.gms | 15 ++++++++++---- modules/06_CO2/legacy/equations.gms | 4 ++-- modules/07_Emissions/legacy/preloop.gms | 21 ++++---------------- 7 files changed, 34 insertions(+), 37 deletions(-) diff --git a/modules/03_RestOfEnergy/legacy/equations.gms b/modules/03_RestOfEnergy/legacy/equations.gms index 4e8c8229..6736326f 100644 --- a/modules/03_RestOfEnergy/legacy/equations.gms +++ b/modules/03_RestOfEnergy/legacy/equations.gms @@ -65,7 +65,8 @@ Q03InpTotTransf(allCy,SSBS,EFS,YTIME)$(TIME(YTIME)$(runCy(allCy))$SECtoEF(SSBS,E ( i03InputEffSupply(allCy,SSBS,EFS,"%fBaseY%") * SUM(EFS2, V03OutTotTransf(allCy,SSBS,EFS2,YTIME)) - )$(sameas(SSBS,"GAS") or sameas(SSBS,"SLD") or sameas(SSBS,"LQD")); + )$(sameas(SSBS,"GAS") or sameas(SSBS,"SLD") or sameas(SSBS,"LQD")) + + (SUM(H2TECH$H2TECHtoFEEDSTOCK(H2TECH,EFS),VmProdH2(allCy,H2TECH,YTIME) / i05EffH2ProdFeed(allCy,H2TECH,YTIME)))$sameas("H2P",SSBS); *' The equation calculates the total transformation output for a specific energy branch in a given scenario and year. *' The result is obtained by summing the transformation outputs from different sources, including thermal power stations, District Heating Plants, @@ -174,7 +175,8 @@ Q03ConsFiEneSec(allCy,SSBS,EFS,YTIME)$(TIME(YTIME)$(runCy(allCy))).. V03OutTotTransf(allCy,SSBS,EFS2,YTIME) + V03ProdPrimary(allCy,EFS2,YTIME)$(not PGRENEF(EFS2)) ) - )$(not sameas("H2P",SSBS)); + )$(not sameas("H2P",SSBS)) + + (SUM(H2TECH$H2TECHtoENERGY(H2TECH,EFS),VmProdH2(allCy,H2TECH,YTIME) / i05EffH2ProdEnergy(allCy,H2TECH,YTIME)))$sameas("H2P",SSBS); Q03FinalEnergy(allCy,DSBS,EFS,YTIME)$(TIME(YTIME)$(runCy(allCy))$(SECtoEF(DSBS,EFS))$(not sameas("ICT",DSBS))).. VmFinalEnergy(allCy,DSBS,EFS,YTIME) diff --git a/modules/05_Hydrogen/legacy/equations.gms b/modules/05_Hydrogen/legacy/equations.gms index edc810c1..b6573efc 100644 --- a/modules/05_Hydrogen/legacy/equations.gms +++ b/modules/05_Hydrogen/legacy/equations.gms @@ -90,14 +90,14 @@ Q05CostProdH2Tech(allCy,H2TECH,YTIME)$(TIME(YTIME)$(runCy(allCy))).. Q05CostVarProdH2Tech(allCy,H2TECH,YTIME)$(TIME(YTIME)$(runCy(allCy))).. V05CostVarProdH2Tech(allCy,H2TECH,YTIME) =E= - sum(EF$H2TECHEFtoEF(H2TECH,EF), + sum(EF$(H2TECHtoFEEDSTOCK(H2TECH,EF) or H2TECHtoENERGY(H2TECH,EF)), VmPriceFuelSubsecCarVal(allCy,"H2P",EF,YTIME) * 1e3 + V05CaptRateH2(allCy,H2TECH,YTIME) * (imCo2EmiFac(allCy,"H2P",EF,YTIME) + 4.17$(sameas("BMSWAS", EF))) * VmCstCO2SeqCsts(allCy,YTIME) + (1-V05CaptRateH2(allCy,H2TECH,YTIME)) * imCo2EmiFac(allCy,"H2P",EF,YTIME) * sum(NAP$NAPtoALLSBS(NAP,"H2P"),VmCarVal(allCy,NAP,YTIME)) - ) / i05EffH2Prod(allCy,H2TECH,YTIME) + + ) / (i05EffH2ProdFeed(allCy,H2TECH,YTIME) + i05EffH2ProdEnergy(allCy,H2TECH,YTIME)) + i05CostVOMH2Prod(allCy,H2TECH,YTIME) + - (i04VarCost("PGSOL",YTIME) / smTWhToMtoe)$(sameas(H2TECH,"wes")) + - (i04VarCost("PGAWNO",YTIME) / smTWhToMtoe)$(sameas(H2TECH,"wew")); + (i04VarCost("PGSOL",YTIME) / smTWhToMtoe)$sameas(H2TECH,"wes") + + (i04VarCost("PGAWNO",YTIME) / smTWhToMtoe)$sameas(H2TECH,"wew"); *' This equation further adjusts the market share of hydrogen technologies, particularly considering *' the relative competitiveness between CCS and non-CCS technologies. It helps to model the transition diff --git a/modules/05_Hydrogen/legacy/input.gms b/modules/05_Hydrogen/legacy/input.gms index b189ed67..227606ad 100644 --- a/modules/05_Hydrogen/legacy/input.gms +++ b/modules/05_Hydrogen/legacy/input.gms @@ -36,7 +36,8 @@ i05CostCapH2Prod(allCy,H2TECH,YTIME) "Capital cost of hydrogen production i05CostFOMH2Prod(allCy,H2TECH,YTIME) "Fixed operating and maintenance costs of hydrogen production technologies in US$2015 per kW output H2" i05CostVOMH2Prod(allCy,H2TECH,YTIME) "Variable operating and maintenance costs of hydrogen production technologies in US$2015 per kW output H2" i05AvailH2Prod(allCy,H2TECH,YTIME) "Availability of hydrogen production technologies" -i05EffH2Prod(allCy,H2TECH,YTIME) "Efficiency of hydrogen production technologies" +i05EffH2ProdFeed(allCy,H2TECH,YTIME) +i05EffH2ProdEnergy(allCy,H2TECH,YTIME) i05CostInvH2Transp(allCy,INFRTECH,YTIME) "Investment cost of infrastructure technology" !! - Turnpike pipeline in Euro per km !! - Low pressure urban pipeline in Euro per km @@ -90,12 +91,12 @@ i05CostVOMH2Prod(runCy,"wes",YTIME) = i05H2Production("VC","weg",YTIME); i05CostVOMH2Prod(runCy,"wew",YTIME) = i05H2Production("VC","weg",YTIME); *--- i05AvailH2Prod(runCy,H2TECH,YTIME) = i05H2Production("AVAIL",H2TECH,YTIME); -i05AvailH2Prod(runCy,"wes",YTIME) = min(i05AvailH2Prod(runCy,"weg",YTIME),i04AvailRate(runCy,"PGSOL",YTIME)); -i05AvailH2Prod(runCy,"wew",YTIME) = min(i05AvailH2Prod(runCy,"weg",YTIME),i04AvailRate(runCy,"PGAWNO",YTIME)); +i05AvailH2Prod(runCy,"wes",YTIME) = i04AvailRate(runCy,"PGSOL",YTIME); +i05AvailH2Prod(runCy,"wew",YTIME) = i04AvailRate(runCy,"PGAWNO",YTIME); *--- -i05EffH2Prod(runCy,H2TECH,YTIME) = i05H2Production("EFF",H2TECH,YTIME); -i05EffH2Prod(runCy,"wes",YTIME) = i05H2Production("EFF","weg",YTIME); -i05EffH2Prod(runCy,"wew",YTIME) = i05H2Production("EFF","weg",YTIME); +i05EffH2ProdFeed(runCy,H2TECH,YTIME) = i05H2Production("EFF",H2TECH,YTIME); +i05EffH2ProdFeed(runCy,"wes",YTIME) = i05H2Production("EFF","weg",YTIME); +i05EffH2ProdFeed(runCy,"wew",YTIME) = i05H2Production("EFF","weg",YTIME); *--- i05CostInvH2Transp(runCy,INFRTECH,YTIME) = i05H2InfrCapCosts("IC",INFRTECH,YTIME); *--- diff --git a/modules/05_Hydrogen/legacy/preloop.gms b/modules/05_Hydrogen/legacy/preloop.gms index 6ec878f6..cf1660de 100644 --- a/modules/05_Hydrogen/legacy/preloop.gms +++ b/modules/05_Hydrogen/legacy/preloop.gms @@ -42,12 +42,12 @@ V05ScrapLftH2Prod.FX(runCy,H2TECH,YTIME)$DATAY(YTIME) = 1/i05ProdLftH2(H2TECH,YT V05CostVarProdH2Tech.LO(runCy,H2TECH,YTIME) = 0; V05CostVarProdH2Tech.L(runCy,H2TECH,YTIME) = 2; V05CostVarProdH2Tech.FX(runCy,H2TECH,YTIME)$DATAY(YTIME) = -sum(EF$H2TECHEFtoEF(H2TECH,EF), +sum(EF$(H2TECHtoFEEDSTOCK(H2TECH,EF) or H2TECHtoENERGY(H2TECH,EF)), VmPriceFuelSubsecCarVal.L(runCy,"H2P",EF,YTIME) * 1e3 + V05CaptRateH2.L(runCy,H2TECH,YTIME) * (imCo2EmiFac(runCy,"H2P",EF,YTIME) + 4.17$(sameas("BMSWAS", EF))) * VmCstCO2SeqCsts.L(runCy,YTIME) + (1-V05CaptRateH2.L(runCy,H2TECH,YTIME)) * (imCo2EmiFac(runCy,"H2P",EF,YTIME)) * sum(NAP$NAPtoALLSBS(NAP,"H2P"),VmCarVal.L(runCy,NAP,YTIME)) -)$(not H2TECHREN(H2TECH)) / i05EffH2Prod(runCy,H2TECH,YTIME) + +) / (i05EffH2ProdFeed(allCy,H2TECH,YTIME) + i05EffH2ProdEnergy(allCy,H2TECH,YTIME)) + (i04VarCost("PGSOL",YTIME) / (smTWhToMtoe))$(sameas(H2TECH,"wes")) + (i04VarCost("PGAWNO",YTIME) / (smTWhToMtoe))$(sameas(H2TECH,"wew")); *--- diff --git a/modules/05_Hydrogen/legacy/sets.gms b/modules/05_Hydrogen/legacy/sets.gms index 2ef68bdb..939d63b5 100644 --- a/modules/05_Hydrogen/legacy/sets.gms +++ b/modules/05_Hydrogen/legacy/sets.gms @@ -90,18 +90,25 @@ LPIPU SSGG / *--- -H2TECHEFtoEF(H2TECH,EF) "Mapping between production technologies and fuels" +H2TECHtoFEEDSTOCK(H2TECH,EFS) "Mapping between production technologies and feedstock fuels for processes" / (gsr,gss).ngs !! ,smr (cgf,cgs).hcl (bgfls,bgfl).BMSWAS !! bpy,bgfs, *sht.SOL *(nht,wen).NUC -weg.ELC -wes.ELC -wew.ELC +wes.SOL +wew.WND *(opo,ops).RFO / + +H2TECHtoENERGY(H2TECH,EFS) "Mapping between production technologies and fuels for energy use (combustion)" +/ +(gsr,gss).ngs +(cgf,cgs).hcl +(bgfls,bgfl).BMSWAS +weg.ELC +/ *--- $ontext H2TECHtoPGALL(H2TECH,PGALL) "Mapping between hydrogen production technologies and power generation technologies used for water electrolysis" diff --git a/modules/06_CO2/legacy/equations.gms b/modules/06_CO2/legacy/equations.gms index 75a634c9..e4343ffd 100644 --- a/modules/06_CO2/legacy/equations.gms +++ b/modules/06_CO2/legacy/equations.gms @@ -20,9 +20,9 @@ Q06CO2CaptureCCS(allCy,SBS,EFS,YTIME)$(TIME(YTIME)$(runCy(allCy))$SECtoEF(SBS,EF imPlantEffByType(allCy,PGALL,"effELC",YTIME) * V04CO2CaptRate(allCy,PGALL,YTIME) )$sameas("PG", SBS) + - sum(H2TECH$H2TECHEFtoEF(H2TECH,EFS), + sum(H2TECH$(H2TECHtoFEEDSTOCK(H2TECH,EFS) or H2TECHtoENERGY(H2TECH,EFS)), VmProdH2(allCy,H2TECH,YTIME) / - i05EffH2Prod(allCy,H2TECH,YTIME) * + (i05EffH2ProdFeed(allCy,H2TECH,YTIME) + i05EffH2ProdEnergy(allCy,H2TECH,YTIME)) * V05CaptRateH2(allCy,H2TECH,YTIME) )$sameas("H2P", SBS) + sum(DSBS$sameas(DSBS,SBS), diff --git a/modules/07_Emissions/legacy/preloop.gms b/modules/07_Emissions/legacy/preloop.gms index 4cbb4c34..49c92f8c 100644 --- a/modules/07_Emissions/legacy/preloop.gms +++ b/modules/07_Emissions/legacy/preloop.gms @@ -7,23 +7,10 @@ V07GrossEmissCO2Supply.LO(runCy,SSBS,YTIME) = 0; V07GrossEmissCO2Supply.FX(runCy,"H2INFR",YTIME) = 0; V07GrossEmissCO2Supply.FX(runCy,SSBS,YTIME)$DATAY(YTIME) = SUM(EFS, - ( - (-i03InpTotTransfProcess(runCy,SSBS,EFS,YTIME))$SSBSEMIT(SSBS) + - i03DataOwnConsEne(runCy,SSBS,EFS,YTIME) - - SUM(CCS$PGALLtoEF(CCS,EFS), - SUM(PGEF$sameas(PGEF,EFS), - i04ShareFuels(runCy,CCS,PGEF)) * - VmProdElec.L(runCy,CCS,YTIME) * smTWhToMtoe / - imPlantEffByType(runCy,CCS,"effELC",YTIME) * - V04CO2CaptRate.L(runCy,CCS,YTIME) - )$sameas("PG",SSBS) - - SUM(H2CCS$H2TECHEFtoEF(H2CCS,EFS), - VmProdH2.L(runCy,H2CCS,YTIME) / - i05EffH2Prod(runCy,H2CCS,YTIME) * - V05CaptRateH2.L(runCy,H2CCS,YTIME) - )$sameas("H2P",SSBS) - ) * - imCo2EmiFac(runCy,"PG",EFS,YTIME) + ( + V03InpTotTransf.L(allCy,SSBS,EFS,YTIME)$SSBSEMIT(SSBS) + + VmConsFiEneSec.L(allCy,SSBS,EFS,YTIME) + ) * imCo2EmiFac(allCy,SSBS,EFS,YTIME) ); *--- V07GrossEmissCO2Demand.LO(runCy,DSBS,YTIME) = 0; From 2e7da8e90e67449cb8a6ff94debb87e1308c2cd2 Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Fri, 3 Jul 2026 18:07:41 +0300 Subject: [PATCH 03/37] Add vapacity variable and update efficiencies in hydogen module. --- modules/03_RestOfEnergy/legacy/equations.gms | 4 +- modules/05_Hydrogen/legacy/declarations.gms | 7 +++- modules/05_Hydrogen/legacy/equations.gms | 40 +++++++++++++++----- modules/05_Hydrogen/legacy/input.gms | 16 ++++---- modules/05_Hydrogen/legacy/postsolve.gms | 1 + modules/05_Hydrogen/legacy/preloop.gms | 26 +++++++++---- modules/05_Hydrogen/legacy/sets.gms | 31 ++++++++++++--- modules/06_CO2/legacy/equations.gms | 2 +- modules/07_Emissions/legacy/declarations.gms | 2 + modules/07_Emissions/legacy/equations.gms | 12 +++++- modules/07_Emissions/legacy/preloop.gms | 6 +-- modules/07_Emissions/legacy/sets.gms | 2 +- 12 files changed, 108 insertions(+), 41 deletions(-) diff --git a/modules/03_RestOfEnergy/legacy/equations.gms b/modules/03_RestOfEnergy/legacy/equations.gms index 6736326f..20aa267b 100644 --- a/modules/03_RestOfEnergy/legacy/equations.gms +++ b/modules/03_RestOfEnergy/legacy/equations.gms @@ -66,7 +66,7 @@ Q03InpTotTransf(allCy,SSBS,EFS,YTIME)$(TIME(YTIME)$(runCy(allCy))$SECtoEF(SSBS,E i03InputEffSupply(allCy,SSBS,EFS,"%fBaseY%") * SUM(EFS2, V03OutTotTransf(allCy,SSBS,EFS2,YTIME)) )$(sameas(SSBS,"GAS") or sameas(SSBS,"SLD") or sameas(SSBS,"LQD")) + - (SUM(H2TECH$H2TECHtoFEEDSTOCK(H2TECH,EFS),VmProdH2(allCy,H2TECH,YTIME) / i05EffH2ProdFeed(allCy,H2TECH,YTIME)))$sameas("H2P",SSBS); + (SUM(H2TECH$H2TECHtoFEEDSTOCK(H2TECH,EFS),VmProdH2(allCy,H2TECH,YTIME) * i05InputOverOutH2ProdFeed(allCy,H2TECH,EFS,YTIME)))$sameas("H2P",SSBS); *' The equation calculates the total transformation output for a specific energy branch in a given scenario and year. *' The result is obtained by summing the transformation outputs from different sources, including thermal power stations, District Heating Plants, @@ -176,7 +176,7 @@ Q03ConsFiEneSec(allCy,SSBS,EFS,YTIME)$(TIME(YTIME)$(runCy(allCy))).. V03ProdPrimary(allCy,EFS2,YTIME)$(not PGRENEF(EFS2)) ) )$(not sameas("H2P",SSBS)) + - (SUM(H2TECH$H2TECHtoENERGY(H2TECH,EFS),VmProdH2(allCy,H2TECH,YTIME) / i05EffH2ProdEnergy(allCy,H2TECH,YTIME)))$sameas("H2P",SSBS); + (SUM(H2TECH$H2TECHtoENERGY(H2TECH,EFS),VmProdH2(allCy,H2TECH,YTIME) * i05InputOverOutH2ProdEnergy(allCy,H2TECH,EFS,YTIME)))$sameas("H2P",SSBS); Q03FinalEnergy(allCy,DSBS,EFS,YTIME)$(TIME(YTIME)$(runCy(allCy))$(SECtoEF(DSBS,EFS))$(not sameas("ICT",DSBS))).. VmFinalEnergy(allCy,DSBS,EFS,YTIME) diff --git a/modules/05_Hydrogen/legacy/declarations.gms b/modules/05_Hydrogen/legacy/declarations.gms index 96a86032..f8ea8320 100644 --- a/modules/05_Hydrogen/legacy/declarations.gms +++ b/modules/05_Hydrogen/legacy/declarations.gms @@ -11,7 +11,7 @@ V05CostProdH2Tech(allCy, H2TECH, YTIME) "Hydrogen production cost per V05CostVarProdH2Tech(allCy, H2TECH, YTIME) "Variable cost (including fuel cost) for hydrogen production by technology in US$2015 per toe" VmCostAvgProdH2(allCy, YTIME) "Average production cost of hydrogen in Euro per toe" V05CaptRateH2(allCy,H2TECH,YTIME) - +V05UtilRate(allCy,H2TECH,YTIME) $ontext *' **Infrastructure Variables** V05H2InfrArea(allCy, YTIME) "Number of stylised areas covered by H2 infrastructure" @@ -34,6 +34,7 @@ $offtext *' **Interdependent Variables** VmDemTotH2(allCy, YTIME) "Hydrogen production requirement in Mtoe for meeting final demand" VmProdH2(allCy, H2TECH, YTIME) "Hydrogen Production by technology in Mtoe" +VmCapH2(allCy, H2TECH, YTIME) "Hydrogen capacity by technology in kw-output" VmCostAvgProdH2(allCy, YTIME) "Average production cost of hydrogen in Euro per toe" ; @@ -47,6 +48,7 @@ Q05CostProdH2Tech(allCy, H2TECH, YTIME) "Equation for hydrogen product Q05CostVarProdH2Tech(allCy, H2TECH, YTIME) "Equation for variable cost (including fuel cost) for hydrogen production by technology in Euro per toe" Q05CostAvgProdH2(allCy, YTIME) "Equation for average production cost of hydrogen in Euro per toe" Q05CaptRateH2(allCy,H2TECH,YTIME) +Q05UtilRate(allCy,H2TECH,YTIME) $ontext *' **Infrastructure Equations** Q05H2InfrArea(allCy, YTIME) "Equation for infrastructure area" @@ -65,7 +67,8 @@ Q05CostTotH2(allCy, SBS, YTIME) "Equation of total hydrogen co $offtext *' **Interdependent Equations** Q05DemTotH2(allCy, YTIME) "Equation for total hydrogen demand in a country in Mtoe" -Q05ProdH2(allCy, H2TECH, YTIME) "Equation for H2 production by technology" +Q05ProdH2(allCy,H2TECH,YTIME) "Equation for H2 production by technology" +Q05CapH2(allCy,H2TECH,YTIME) "Equation for H2 capacity by technology" ; Scalars diff --git a/modules/05_Hydrogen/legacy/equations.gms b/modules/05_Hydrogen/legacy/equations.gms index b6573efc..062b7529 100644 --- a/modules/05_Hydrogen/legacy/equations.gms +++ b/modules/05_Hydrogen/legacy/equations.gms @@ -54,13 +54,15 @@ Q05DemGapH2(allCy,YTIME)$(TIME(YTIME)$(runCy(allCy))).. VmDemTotH2(allCy,YTIME) - sum(H2TECH, (1-V05CapScrapH2ProdTech(allCy,H2TECH,YTIME)) * - VmProdH2(allCy,H2TECH,YTIME-1) + VmCapH2(allCy,H2TECH,YTIME-1) * + i05AvailH2Prod(allCy,H2TECH,YTIME) * smGwToTwhPerYear(YTIME) * smTWhToMtoe ) + SQRT(SQR( VmDemTotH2(allCy,YTIME) - sum(H2TECH, (1-V05CapScrapH2ProdTech(allCy,H2TECH,YTIME)) * - VmProdH2(allCy,H2TECH,YTIME-1) + VmCapH2(allCy,H2TECH,YTIME-1) * + i05AvailH2Prod(allCy,H2TECH,YTIME) * smGwToTwhPerYear(YTIME) * smTWhToMtoe ) )) ) / 2; @@ -91,11 +93,13 @@ Q05CostVarProdH2Tech(allCy,H2TECH,YTIME)$(TIME(YTIME)$(runCy(allCy))).. V05CostVarProdH2Tech(allCy,H2TECH,YTIME) =E= sum(EF$(H2TECHtoFEEDSTOCK(H2TECH,EF) or H2TECHtoENERGY(H2TECH,EF)), - VmPriceFuelSubsecCarVal(allCy,"H2P",EF,YTIME) * 1e3 + - V05CaptRateH2(allCy,H2TECH,YTIME) * (imCo2EmiFac(allCy,"H2P",EF,YTIME) + 4.17$(sameas("BMSWAS", EF))) * VmCstCO2SeqCsts(allCy,YTIME) + - (1-V05CaptRateH2(allCy,H2TECH,YTIME)) * imCo2EmiFac(allCy,"H2P",EF,YTIME) * sum(NAP$NAPtoALLSBS(NAP,"H2P"),VmCarVal(allCy,NAP,YTIME)) - ) / (i05EffH2ProdFeed(allCy,H2TECH,YTIME) + i05EffH2ProdEnergy(allCy,H2TECH,YTIME)) + - i05CostVOMH2Prod(allCy,H2TECH,YTIME) + + ( + VmPriceFuelSubsecCarVal(allCy,"H2P",EF,YTIME) * 1e3 + + V05CaptRateH2(allCy,H2TECH,YTIME) * (imCo2EmiFac(allCy,"H2P",EF,YTIME) + 4.17$(sameas("BMSWAS", EF))) * VmCstCO2SeqCsts(allCy,YTIME) + + (1-V05CaptRateH2(allCy,H2TECH,YTIME)) * imCo2EmiFac(allCy,"H2P",EF,YTIME) * sum(NAP$NAPtoALLSBS(NAP,"H2P"),VmCarVal(allCy,NAP,YTIME)) + ) * (i05InputOverOutH2ProdFeed(allCy,H2TECH,EF,YTIME) + i05InputOverOutH2ProdEnergy(allCy,H2TECH,EF,YTIME)) + ) + + !!i05CostVOMH2Prod(allCy,H2TECH,YTIME) + (i04VarCost("PGSOL",YTIME) / smTWhToMtoe)$sameas(H2TECH,"wes") + (i04VarCost("PGAWNO",YTIME) / smTWhToMtoe)$sameas(H2TECH,"wew"); @@ -112,13 +116,31 @@ Q05GapShareH2Tech(allCy,H2TECH,YTIME)$(TIME(YTIME)$(runCy(allCy))).. V05CostProdH2Tech(allCy,H2TECH2,YTIME-1) ** (-2) ); +*' This equation defines the actual hydrogen production levels, considering both scrapped capacity and the demand gap. +*' It allocates production from different technologies to meet the overall demand, adjusting for changes in capacity and technology availability. +Q05CapH2(allCy,H2TECH,YTIME)$(TIME(YTIME)$(runCy(allCy))).. + VmCapH2(allCy,H2TECH,YTIME) + =E= + (1-V05CapScrapH2ProdTech(allCy,H2TECH,YTIME)) * VmCapH2(allCy,H2TECH,YTIME-1) + + V05GapShareH2Tech(allCy,H2TECH,YTIME) * V05DemGapH2(allCy,YTIME) / (i05AvailH2Prod(allCy,H2TECH,YTIME) * smGwToTwhPerYear(YTIME) * smTWhToMtoe); + +Q05UtilRate(allCy,H2TECH,YTIME)$(TIME(YTIME)$(runCy(allCy))).. + V05UtilRate(allCy,H2TECH,YTIME) + =E= + VmDemTotH2(allCy,YTIME) / + SUM(H2TECH2, + VmCapH2(allCy,H2TECH2,YTIME) * + i05AvailH2Prod(allCy,H2TECH2,YTIME) * smGwToTwhPerYear(YTIME) * smTWhToMtoe + ); + *' This equation defines the actual hydrogen production levels, considering both scrapped capacity and the demand gap. *' It allocates production from different technologies to meet the overall demand, adjusting for changes in capacity and technology availability. Q05ProdH2(allCy,H2TECH,YTIME)$(TIME(YTIME)$(runCy(allCy))).. VmProdH2(allCy,H2TECH,YTIME) =E= - (1-V05CapScrapH2ProdTech(allCy,H2TECH,YTIME)) * VmProdH2(allCy,H2TECH,YTIME-1) + - V05GapShareH2Tech(allCy,H2TECH,YTIME) * V05DemGapH2(allCy,YTIME); + V05UtilRate(allCy,H2TECH,YTIME) * + VmCapH2(allCy,H2TECH,YTIME) * + i05AvailH2Prod(allCy,H2TECH,YTIME) * smGwToTwhPerYear(YTIME) * smTWhToMtoe; *' This equation calculates the average cost of hydrogen production across all technologies in the system. *' It accounts for varying costs of different technologies (e.g., electrolysis vs. SMR) to provide an overall assessment of hydrogen production cost. diff --git a/modules/05_Hydrogen/legacy/input.gms b/modules/05_Hydrogen/legacy/input.gms index 227606ad..591bbd38 100644 --- a/modules/05_Hydrogen/legacy/input.gms +++ b/modules/05_Hydrogen/legacy/input.gms @@ -2,7 +2,7 @@ *' @code *--- -table i05H2Production(ECONCHARHY,H2TECH,YTIME) "Data for Hydrogen production" +table i05H2Production(ECONCHARHY2,H2TECH,YTIME) "Data for Hydrogen production" $ondelim $include"./iH2Production.csv" $offdelim @@ -36,8 +36,8 @@ i05CostCapH2Prod(allCy,H2TECH,YTIME) "Capital cost of hydrogen production i05CostFOMH2Prod(allCy,H2TECH,YTIME) "Fixed operating and maintenance costs of hydrogen production technologies in US$2015 per kW output H2" i05CostVOMH2Prod(allCy,H2TECH,YTIME) "Variable operating and maintenance costs of hydrogen production technologies in US$2015 per kW output H2" i05AvailH2Prod(allCy,H2TECH,YTIME) "Availability of hydrogen production technologies" -i05EffH2ProdFeed(allCy,H2TECH,YTIME) -i05EffH2ProdEnergy(allCy,H2TECH,YTIME) +i05InputOverOutH2ProdFeed(allCy,H2TECH,EF,YTIME) +i05InputOverOutH2ProdEnergy(allCy,H2TECH,EF,YTIME) i05CostInvH2Transp(allCy,INFRTECH,YTIME) "Investment cost of infrastructure technology" !! - Turnpike pipeline in Euro per km !! - Low pressure urban pipeline in Euro per km @@ -69,8 +69,6 @@ i05ProdLftH2("wes",YTIME) = i05H2Production("LFT","weg",YTIME); i05ProdLftH2("wew",YTIME) = i05H2Production("LFT","weg",YTIME); *--- i05CaptRateH2Prod(H2TECH) = i05H2Production("CR",H2TECH,"%fBaseY%"); -i05CaptRateH2Prod("wes") = i05CaptRateH2Prod("weg"); -i05CaptRateH2Prod("wew") = i05CaptRateH2Prod("weg"); i05CaptRateH2Prod(H2TECH)$(not H2CCS(H2TECH)) = 0; *--- i05H2Adopt(runCy,"b",YTIME) = i05H2Parameters(runCy,"B"); @@ -94,9 +92,11 @@ i05AvailH2Prod(runCy,H2TECH,YTIME) = i05H2Production("AVAIL",H2TECH,YTIME); i05AvailH2Prod(runCy,"wes",YTIME) = i04AvailRate(runCy,"PGSOL",YTIME); i05AvailH2Prod(runCy,"wew",YTIME) = i04AvailRate(runCy,"PGAWNO",YTIME); *--- -i05EffH2ProdFeed(runCy,H2TECH,YTIME) = i05H2Production("EFF",H2TECH,YTIME); -i05EffH2ProdFeed(runCy,"wes",YTIME) = i05H2Production("EFF","weg",YTIME); -i05EffH2ProdFeed(runCy,"wew",YTIME) = i05H2Production("EFF","weg",YTIME); +i05InputOverOutH2ProdFeed(runCy,H2TECH,EFS,YTIME)$H2TECHtoFEEDSTOCK(H2TECH,EFS) = 0.7 * i05H2Production("INOUT_HEAT",H2TECH,YTIME); +i05InputOverOutH2ProdEnergy(runCy,H2TECH,EFS,YTIME)$(H2TECHtoENERGY(H2TECH,EFS) and not sameas("ELC",EFS)) = 0.3 * i05H2Production("INOUT_HEAT",H2TECH,YTIME); +i05InputOverOutH2ProdEnergy(runCy,H2TECH,EFS,YTIME)$(H2TECHtoENERGY(H2TECH,EFS) and sameas("ELC",EFS)) = i05H2Production("INOUT_ELC",H2TECH,YTIME); +i05InputOverOutH2ProdFeed(runCy,"wes",EFS,YTIME)$H2TECHtoFEEDSTOCK("wes",EFS) = i05InputOverOutH2ProdEnergy(runCy,"weg","ELC",YTIME); +i05InputOverOutH2ProdFeed(runCy,"wew",EFS,YTIME)$H2TECHtoFEEDSTOCK("wew",EFS) = i05InputOverOutH2ProdEnergy(runCy,"weg","ELC",YTIME); *--- i05CostInvH2Transp(runCy,INFRTECH,YTIME) = i05H2InfrCapCosts("IC",INFRTECH,YTIME); *--- diff --git a/modules/05_Hydrogen/legacy/postsolve.gms b/modules/05_Hydrogen/legacy/postsolve.gms index 2165cace..e03b5e4c 100644 --- a/modules/05_Hydrogen/legacy/postsolve.gms +++ b/modules/05_Hydrogen/legacy/postsolve.gms @@ -6,6 +6,7 @@ *--- VmProdH2.FX(runCyL,H2TECH,YTIME)$TIME(YTIME) = VmProdH2.L(runCyL,H2TECH,YTIME)$TIME(YTIME); +VmCapH2.FX(runCyL,H2TECH,YTIME)$TIME(YTIME) = VmCapH2.L(runCyL,H2TECH,YTIME)$TIME(YTIME); V05DemGapH2.FX(runCyL,YTIME)$TIME(YTIME) = V05DemGapH2.L(runCyL,YTIME)$TIME(YTIME); VmCostAvgProdH2.FX(runCyL,YTIME)$TIME(YTIME) = VmCostAvgProdH2.L(runCyL,YTIME)$TIME(YTIME); V05CaptRateH2.FX(runCyL,H2TECH,YTIME)$TIME(YTIME) = V05CaptRateH2.L(runCyL,H2TECH,YTIME)$TIME(YTIME); diff --git a/modules/05_Hydrogen/legacy/preloop.gms b/modules/05_Hydrogen/legacy/preloop.gms index cf1660de..dcaef254 100644 --- a/modules/05_Hydrogen/legacy/preloop.gms +++ b/modules/05_Hydrogen/legacy/preloop.gms @@ -20,9 +20,17 @@ VmDemTotH2.LO(runCy,YTIME) = 0; VmDemTotH2.L(runCy,YTIME) = (i03DataGrossInlCons(runCy,"H2F","%fBaseY%") - imFuelTrade(runCy,"IMPORTS","H2F","%fBaseY%") + imFuelTrade(runCy,"EXPORTS","H2F","%fBaseY%")) + 1; VmDemTotH2.FX(runCy,YTIME)$DATAY(YTIME) = (i03DataGrossInlCons(runCy,"H2F",YTIME) - imFuelTrade(runCy,"IMPORTS","H2F",YTIME) + imFuelTrade(runCy,"EXPORTS","H2F",YTIME)); *--- -VmProdH2.LO(runCy,H2TECH, YTIME) = 0; -VmProdH2.L(runCy,H2TECH, YTIME) = 0.5; -VmProdH2.FX(runCy,H2TECH, YTIME)$DATAY(YTIME) = 0; +VmProdH2.LO(runCy,H2TECH,YTIME) = 0; +VmProdH2.L(runCy,H2TECH,YTIME) = 1; +VmProdH2.FX(runCy,H2TECH,YTIME)$DATAY(YTIME) = 0; +*--- +V05UtilRate.LO(runCy,H2TECH,YTIME) = 0; +V05UtilRate.L(runCy,H2TECH,YTIME) = 1; +V05UtilRate.FX(runCy,H2TECH,YTIME)$DATAY(YTIME) = 1; +*--- +VmCapH2.LO(runCy,H2TECH,YTIME) = 0; +VmCapH2.L(runCy,H2TECH,YTIME) = 1; +VmCapH2.FX(runCy,H2TECH,YTIME)$DATAY(YTIME) = 0; *--- *V05DelivH2InfrTech.L(runCy,INFRTECH,YTIME) = 2; *V05DelivH2InfrTech.FX(runCy,INFRTECH,YTIME)$(not An(YTIME)) = 1e-5; @@ -43,11 +51,13 @@ V05CostVarProdH2Tech.LO(runCy,H2TECH,YTIME) = 0; V05CostVarProdH2Tech.L(runCy,H2TECH,YTIME) = 2; V05CostVarProdH2Tech.FX(runCy,H2TECH,YTIME)$DATAY(YTIME) = sum(EF$(H2TECHtoFEEDSTOCK(H2TECH,EF) or H2TECHtoENERGY(H2TECH,EF)), - VmPriceFuelSubsecCarVal.L(runCy,"H2P",EF,YTIME) * 1e3 + - V05CaptRateH2.L(runCy,H2TECH,YTIME) * (imCo2EmiFac(runCy,"H2P",EF,YTIME) + 4.17$(sameas("BMSWAS", EF))) * VmCstCO2SeqCsts.L(runCy,YTIME) + - (1-V05CaptRateH2.L(runCy,H2TECH,YTIME)) * (imCo2EmiFac(runCy,"H2P",EF,YTIME)) * - sum(NAP$NAPtoALLSBS(NAP,"H2P"),VmCarVal.L(runCy,NAP,YTIME)) -) / (i05EffH2ProdFeed(allCy,H2TECH,YTIME) + i05EffH2ProdEnergy(allCy,H2TECH,YTIME)) + + ( + VmPriceFuelSubsecCarVal.L(runCy,"H2P",EF,YTIME) * 1e3 + + V05CaptRateH2.L(runCy,H2TECH,YTIME) * (imCo2EmiFac(runCy,"H2P",EF,YTIME) + 4.17$(sameas("BMSWAS", EF))) * VmCstCO2SeqCsts.L(runCy,YTIME) + + (1-V05CaptRateH2.L(runCy,H2TECH,YTIME)) * (imCo2EmiFac(runCy,"H2P",EF,YTIME)) * + sum(NAP$NAPtoALLSBS(NAP,"H2P"),VmCarVal.L(runCy,NAP,YTIME)) + ) * (i05InputOverOutH2ProdFeed(runCy,H2TECH,EF,YTIME) + i05InputOverOutH2ProdEnergy(runCy,H2TECH,EF,YTIME)) +) + (i04VarCost("PGSOL",YTIME) / (smTWhToMtoe))$(sameas(H2TECH,"wes")) + (i04VarCost("PGAWNO",YTIME) / (smTWhToMtoe))$(sameas(H2TECH,"wew")); *--- diff --git a/modules/05_Hydrogen/legacy/sets.gms b/modules/05_Hydrogen/legacy/sets.gms index 939d63b5..a6f0f525 100644 --- a/modules/05_Hydrogen/legacy/sets.gms +++ b/modules/05_Hydrogen/legacy/sets.gms @@ -90,7 +90,7 @@ LPIPU SSGG / *--- -H2TECHtoFEEDSTOCK(H2TECH,EFS) "Mapping between production technologies and feedstock fuels for processes" +H2TECHtoFEEDSTOCK(H2TECH,EF) "Mapping between production technologies and feedstock fuels for processes" / (gsr,gss).ngs !! ,smr (cgf,cgs).hcl @@ -102,11 +102,11 @@ wew.WND *(opo,ops).RFO / -H2TECHtoENERGY(H2TECH,EFS) "Mapping between production technologies and fuels for energy use (combustion)" +H2TECHtoENERGY(H2TECH,EF) "Mapping between production technologies and fuels for energy use (combustion)" / -(gsr,gss).ngs -(cgf,cgs).hcl -(bgfls,bgfl).BMSWAS +(gsr,gss).(ngs,elc) +(cgf,cgs).(hcl,elc) +(bgfls,bgfl).(BMSWAS,elc) weg.ELC / *--- @@ -207,6 +207,27 @@ B mid CR / + +ECONCHARHY2 "Technical - Economic characteristics for demand technologies Hydrogen" +/ +IC +FC +VC +INOUT_ELC +INOUT_HEAT +SELF +AVAIL +LFT +H2KMTOE +mpips +lpipu +mpipu +AREA +MAXAREA +B +mid +CR +/ *--- INFRTECHLAB(INFRTECH,ECONCHARHY) / diff --git a/modules/06_CO2/legacy/equations.gms b/modules/06_CO2/legacy/equations.gms index e4343ffd..2cd6454d 100644 --- a/modules/06_CO2/legacy/equations.gms +++ b/modules/06_CO2/legacy/equations.gms @@ -22,7 +22,7 @@ Q06CO2CaptureCCS(allCy,SBS,EFS,YTIME)$(TIME(YTIME)$(runCy(allCy))$SECtoEF(SBS,EF )$sameas("PG", SBS) + sum(H2TECH$(H2TECHtoFEEDSTOCK(H2TECH,EFS) or H2TECHtoENERGY(H2TECH,EFS)), VmProdH2(allCy,H2TECH,YTIME) / - (i05EffH2ProdFeed(allCy,H2TECH,YTIME) + i05EffH2ProdEnergy(allCy,H2TECH,YTIME)) * + (i05InputOverOutH2ProdFeed(allCy,H2TECH,EFS,YTIME) + i05InputOverOutH2ProdEnergy(allCy,H2TECH,EFS,YTIME)) * V05CaptRateH2(allCy,H2TECH,YTIME) )$sameas("H2P", SBS) + sum(DSBS$sameas(DSBS,SBS), diff --git a/modules/07_Emissions/legacy/declarations.gms b/modules/07_Emissions/legacy/declarations.gms index f820bff1..75157f5e 100644 --- a/modules/07_Emissions/legacy/declarations.gms +++ b/modules/07_Emissions/legacy/declarations.gms @@ -21,6 +21,7 @@ Q07EmiActBySrcRegTim(E07SrcMacAbate, allCy, YTIME) "Calculate remaining a Q07GrossEmissCO2Demand(allCy,DSBS,YTIME) "Calculate gross emissions of demand subsectors" Q07EmissionsNet(allCy,YTIME) "Calculate net emissions after abatement" Q07EmissionsNetPart(allCy,YTIME) "Calculate the fraction of the regional net emissions to the global net emissions" +Q07GrossEmissCO2Processes(allCy,SSBS,YTIME) ; Variables @@ -35,4 +36,5 @@ V07CostAbateBySrcRegTim(E07SrcMacAbate,allCy,YTIME) "Total abatement cost" V07GrossEmissCO2Demand(allCy,DSBS,YTIME) "Gross emissions of demand subsectors" V07EmissionsNet(allCy,YTIME) "Net emissions after abatement" V07EmissionsNetPart(allCy,YTIME) "Fraction of regional net emissions to global net emissions" +V07GrossEmissCO2Processes(allCy,SSBS,YTIME) *; \ No newline at end of file diff --git a/modules/07_Emissions/legacy/equations.gms b/modules/07_Emissions/legacy/equations.gms index 90fa224d..e13e7080 100644 --- a/modules/07_Emissions/legacy/equations.gms +++ b/modules/07_Emissions/legacy/equations.gms @@ -74,11 +74,19 @@ Q07GrossEmissCO2Supply(allCy,SSBS,YTIME)$(TIME(YTIME)$runCy(allCy)).. =E= SUM(EFS, ( - V03InpTotTransf(allCy,SSBS,EFS,YTIME)$SSBSEMIT(SSBS) + + V03InpTotTransf(allCy,SSBS,EFS,YTIME)$SSBSENERGY(SSBS) + VmConsFiEneSec(allCy,SSBS,EFS,YTIME) ) * imCo2EmiFac(allCy,SSBS,EFS,YTIME) ); - + +Q07GrossEmissCO2Processes(allCy,SSBS,YTIME)$(TIME(YTIME)$runCy(allCy)).. + V07GrossEmissCO2Processes(allCy,SSBS,YTIME) + =E= + SUM(EFS, + V03InpTotTransf(allCy,SSBS,EFS,YTIME) * + imCo2EmiFac(allCy,SSBS,EFS,YTIME) + )$sameas(SSBS,"H2P"); + *' This equation calculates the total absolute abatement of non-CO2 emissions for a specific source, country, and time period. *' The determination is based on the Marginal Abatement Cost (MAC) curves, the exogenous carbon price, and specific unit conversion factors. The equation *' identifies the maximum abatement potential by scanning the MAC curve steps and selecting the highest reduction level where the implementation cost is less than or diff --git a/modules/07_Emissions/legacy/preloop.gms b/modules/07_Emissions/legacy/preloop.gms index 49c92f8c..8df30f25 100644 --- a/modules/07_Emissions/legacy/preloop.gms +++ b/modules/07_Emissions/legacy/preloop.gms @@ -8,9 +8,9 @@ V07GrossEmissCO2Supply.FX(runCy,"H2INFR",YTIME) = 0; V07GrossEmissCO2Supply.FX(runCy,SSBS,YTIME)$DATAY(YTIME) = SUM(EFS, ( - V03InpTotTransf.L(allCy,SSBS,EFS,YTIME)$SSBSEMIT(SSBS) + - VmConsFiEneSec.L(allCy,SSBS,EFS,YTIME) - ) * imCo2EmiFac(allCy,SSBS,EFS,YTIME) + V03InpTotTransf.L(runCy,SSBS,EFS,YTIME)$SSBSENERGY(SSBS) + + VmConsFiEneSec.L(runCy,SSBS,EFS,YTIME) + ) * imCo2EmiFac(runCy,SSBS,EFS,YTIME) ); *--- V07GrossEmissCO2Demand.LO(runCy,DSBS,YTIME) = 0; diff --git a/modules/07_Emissions/legacy/sets.gms b/modules/07_Emissions/legacy/sets.gms index 52768778..127cf2c4 100644 --- a/modules/07_Emissions/legacy/sets.gms +++ b/modules/07_Emissions/legacy/sets.gms @@ -3,7 +3,7 @@ sets *--- -SSBSEMIT(SSBS) Supply Subsectors emitting inputs /PG,H2P,CHP,STEAMP/ +SSBSENERGY(SSBS) Supply Subsectors with energy processes /PG,CHP,STEAMP/ E07MAC "Cost categories for Marginal abatement costs curves (MACC) -2010$/tC for CH4,N20 and 2005$/tC for F-gases" / 0, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260, 280, 300, From 455545178b44ca43bd3c4103fcc106f43b49010d Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Mon, 6 Jul 2026 12:21:40 +0300 Subject: [PATCH 04/37] Update hydrogen price calculations --- core/input.gms | 1 - core/preloop.gms | 3 ++- modules/03_RestOfEnergy/legacy/equations.gms | 15 +++++---------- modules/03_RestOfEnergy/legacy/input.gms | 1 + modules/05_Hydrogen/legacy/input.gms | 5 ++++- modules/05_Hydrogen/legacy/preloop.gms | 12 +++--------- modules/08_Prices/legacy/equations.gms | 2 +- 7 files changed, 16 insertions(+), 23 deletions(-) diff --git a/core/input.gms b/core/input.gms index 47d063ae..d18e3fa0 100644 --- a/core/input.gms +++ b/core/input.gms @@ -167,7 +167,6 @@ imFuelPrice(runCy,TRANSE,"RFO",YTIME) = imFuelPrice(runCy,"BU","RFO",YTIME); imFuelPrice(runCy,TRANSE,"OGS",YTIME) = imFuelPrice(runCy,TRANSE,"NGS",YTIME); imFuelPrice(runCy,TRANSE,"OLQ",YTIME) = imFuelPrice(runCy,TRANSE,"GDO",YTIME); imFuelPrice(runCy,TRANSE,"H2F",YTIME) = 2 * imFuelPrice(runCy,TRANSE,"H2F",YTIME); -imFuelPrice(runCy,"PA","H2F",YTIME) = 2 * imFuelPrice(runCy,"PA","KRS",YTIME); imFuelPrice(runCy,"ICT",EFS,YTIME)$SECtoEF("ICT",EFS) = imFuelPrice(runCy,"SE",EFS,YTIME); *--- table imPriceFuelsIntBase(WEF,YTIME) "International Fuel Prices USED IN BASELINE SCENARIO ($2015/toe)" diff --git a/core/preloop.gms b/core/preloop.gms index ace4ebd8..126899e3 100644 --- a/core/preloop.gms +++ b/core/preloop.gms @@ -47,7 +47,7 @@ VmPriceFuelSubsecCarVal.L(runCy,SBS,EF,YTIME)$SECtoEF(SBS,EF) = 1; $IFTHEN %softLinkMAgPIE% == on VmPriceFuelSubsecCarVal.FX(runCy,SBS,"BMSWAS",YTIME)$(An(YTIME)) = iPricesMagpie(runCy,SBS,YTIME); $ENDIF -VmPriceFuelSubsecCarVal.FX(runCy,SBS,EF,YTIME)$(SECtoEF(SBS,EF) and not sameas("NUC",EF) and DATAY(YTIME)) = imFuelPrice(runCy,SBS,EF,YTIME); +VmPriceFuelSubsecCarVal.FX(runCy,SBS,EF,YTIME)$(SECtoEF(SBS,EF) and not sameas("NUC",EF) and not sameas("H2F",EF) and DATAY(YTIME)) = imFuelPrice(runCy,SBS,EF,YTIME); * Alternative fuel prices are set explicitly below instead of using ALTMAP * FIXME: VmPriceFuelSubsecCarVal (NUC/MET/ETH/BGDO) should be computed endogenously after startYear, and with mrprom before startYear * author=giannou @@ -60,6 +60,7 @@ VmPriceFuelSubsecCarVal.FX(runCy,"H2P",EF,YTIME)$(SECtoEF("H2P",EF)$DATAY(YTIME) VmPriceFuelSubsecCarVal.FX(runCy,"STEAMP",EF,YTIME)$(SECtoEF("STEAMP",EF)$DATAY(YTIME)) = imFuelPrice(runCy,"PG",EF,YTIME); VmPriceFuelSubsecCarVal.FX(runCy,SBS,"CRO",YTIME) = imFuelPrice(runCy,SBS,"CRO",YTIME); VmPriceFuelSubsecCarVal.FX(runCy,SBS,"STE",YTIME)$(SECtoEF(SBS,"STE") and DATAY(YTIME)) = imFuelPrice(runCy,"OI","ELC",YTIME); +VmPriceFuelSubsecCarVal.FX(runCy,SBS,"H2F",YTIME)$(SECtoEF(SBS,"H2F") and DATAY(YTIME)) = 1.5 * imFuelPrice(runCy,"OI","ELC",YTIME); *--- VmPriceFuelAvgSub.LO(runCy,DSBS,YTIME) = 0; VmPriceFuelAvgSub.L(runCy,DSBS,YTIME) = 1; diff --git a/modules/03_RestOfEnergy/legacy/equations.gms b/modules/03_RestOfEnergy/legacy/equations.gms index 20aa267b..8086ad49 100644 --- a/modules/03_RestOfEnergy/legacy/equations.gms +++ b/modules/03_RestOfEnergy/legacy/equations.gms @@ -17,18 +17,13 @@ Q03LossesDistr(allCy,EFS,YTIME)$(TIME(YTIME)$(runCy(allCy))).. VmLossesDistr(allCy,EFS,YTIME) =E= + imRateLossesFinCons(allCy,EFS,YTIME) * ( - imRateLossesFinCons(allCy,EFS,YTIME) * - ( - SUM(DSBS,VmFinalEnergy(allCy,DSBS,EFS,YTIME)) + - V03ProdPrimary(allCy,EFS,YTIME)$sameas(EFS,"CRO") - ) - )$(not H2EF(EFS)) + + SUM(DSBS,VmFinalEnergy(allCy,DSBS,EFS,YTIME)) + + V03ProdPrimary(allCy,EFS,YTIME)$sameas(EFS,"CRO") + ) !! FIXME: Do we need to add LQD,GAS,SLD here too? - ( - 0!!VmDemTotH2(allCy,YTIME) - - !!sum(SBS$SECtoEF(SBS,"H2F"), VmDemSecH2(allCy,SBS,YTIME)) - )$H2EF(EFS); +; $ontext *' The equation calculates the refineries' capacity for a given scenario and year. diff --git a/modules/03_RestOfEnergy/legacy/input.gms b/modules/03_RestOfEnergy/legacy/input.gms index 367806bf..a26fc63c 100644 --- a/modules/03_RestOfEnergy/legacy/input.gms +++ b/modules/03_RestOfEnergy/legacy/input.gms @@ -98,6 +98,7 @@ imRateLossesFinCons(runCy,EFS,YTIME) = (sum(DSBS,imFuelCons(runCy,DSBS,EFS,YTIME)) + i03PrimProd(runCy,"CRO",YTIME)$sameas("CRO",EFS)) ]$(sum(DSBS,imFuelCons(runCy,DSBS,EFS,YTIME)) + i03PrimProd(runCy,"CRO",YTIME)$sameas("CRO",EFS)); imRateLossesFinCons(runCy,EFS,YTIME)$AN(YTIME) = imRateLossesFinCons(runCy,EFS,"%fBaseY%"); +imRateLossesFinCons(runCy,"H2F",YTIME) = imRateLossesFinCons(runCy,"ELC",YTIME); *--- i03RatioPrimaryFuels(runCy,EFS,YTIME)$DATAY(YTIME) = ( diff --git a/modules/05_Hydrogen/legacy/input.gms b/modules/05_Hydrogen/legacy/input.gms index 591bbd38..154dbe6e 100644 --- a/modules/05_Hydrogen/legacy/input.gms +++ b/modules/05_Hydrogen/legacy/input.gms @@ -77,6 +77,8 @@ i05H2Adopt(runCy,"mid",YTIME) = i05H2Parameters(runCy,"mid"); i05TranspLftH2(INFRTECH,YTIME) = i05H2InfrCapCosts("LFT",INFRTECH,YTIME); *--- i05CostCapH2Prod(runCy,H2TECH,YTIME) = i05H2Production("IC",H2TECH,YTIME); +i05CostCapH2Prod("CHA","cgf",YTIME) = 0.5 * i05CostCapH2Prod("CHA","cgf",YTIME); +i05CostCapH2Prod("CHA","cgs",YTIME) = 0.54 * i05CostCapH2Prod("CHA","cgs",YTIME); i05CostCapH2Prod(runCy,"wes",YTIME) = i05H2Production("IC","weg",YTIME); i05CostCapH2Prod(runCy,"wew",YTIME) = i05H2Production("IC","weg",YTIME); *--- @@ -133,4 +135,5 @@ loop YTIME$(An(YTIME)) do i05CostAvgWeight(runCy,YTIME) = -1/19+i05CostAvgWeight(runCy,YTIME-1); endloop; *--- -i05MatFacH2(allCy,H2TECH,YTIME) = 1; \ No newline at end of file +i05MatFacH2(allCy,H2TECH,YTIME) = 1; +i05MatFacH2(allCy,H2TECH,YTIME)$(H2CCS(H2TECH) and ord(YTIME)<18) = 0; diff --git a/modules/05_Hydrogen/legacy/preloop.gms b/modules/05_Hydrogen/legacy/preloop.gms index dcaef254..5d0154a9 100644 --- a/modules/05_Hydrogen/legacy/preloop.gms +++ b/modules/05_Hydrogen/legacy/preloop.gms @@ -58,6 +58,7 @@ sum(EF$(H2TECHtoFEEDSTOCK(H2TECH,EF) or H2TECHtoENERGY(H2TECH,EF)), sum(NAP$NAPtoALLSBS(NAP,"H2P"),VmCarVal.L(runCy,NAP,YTIME)) ) * (i05InputOverOutH2ProdFeed(runCy,H2TECH,EF,YTIME) + i05InputOverOutH2ProdEnergy(runCy,H2TECH,EF,YTIME)) ) + +i05CostVOMH2Prod(runCy,H2TECH,YTIME) + (i04VarCost("PGSOL",YTIME) / (smTWhToMtoe))$(sameas(H2TECH,"wes")) + (i04VarCost("PGAWNO",YTIME) / (smTWhToMtoe))$(sameas(H2TECH,"wew")); *--- @@ -70,8 +71,7 @@ V05CostProdH2Tech.FX(runCy,H2TECH,YTIME)$DATAY(YTIME) = (exp(imDisc(runCy,"H2P",YTIME) * i05ProdLftH2(H2TECH,YTIME))-1) * ( i05CostCapH2Prod(runCy,H2TECH,YTIME) + - i05CostFOMH2Prod(runCy,H2TECH,YTIME) + - i05CostVOMH2Prod(runCy,H2TECH,YTIME) + i05CostFOMH2Prod(runCy,H2TECH,YTIME) ) + V04CapexFixCostPG.L(runCy,"PGSOL",YTIME)$sameas(H2TECH,"wes") + V04CapexFixCostPG.L(runCy,"PGAWNO",YTIME)$sameas(H2TECH,"wew") @@ -82,13 +82,7 @@ V05CostVarProdH2Tech.L(runCy,H2TECH,YTIME); *--- VmCostAvgProdH2.LO(runCy,YTIME) = 0; VmCostAvgProdH2.L(runCy,YTIME) = 1; -VmCostAvgProdH2.FX(runCy,YTIME)$DATAY(YTIME) = -sum(H2TECH, - (VmProdH2.L(runCy,H2TECH,YTIME) + 1e-6) * - V05CostProdH2Tech.L(runCy,H2TECH,YTIME) -) / -sum(H2TECH,VmProdH2.L(runCy,H2TECH,YTIME) + 1e-6); - +VmCostAvgProdH2.FX(runCy,YTIME)$DATAY(YTIME) = V05CostProdH2Tech.L(runCy,"gsr",YTIME); *--- *V05InvNewReqH2Infra.L(runCy,INFRTECH,YTIME) = 2; diff --git a/modules/08_Prices/legacy/equations.gms b/modules/08_Prices/legacy/equations.gms index 093bb820..4b8df93a 100644 --- a/modules/08_Prices/legacy/equations.gms +++ b/modules/08_Prices/legacy/equations.gms @@ -106,7 +106,7 @@ $IFTHEN %bmswasPriceMode% == curve $ELSE VmPriceFuelSubsecCarVal(allCy,SBS,EFS,YTIME-1) * (1 + (VmCostPowGenAvgLng(allCy,YTIME-1) / VmCostPowGenAvgLng(allCy,YTIME-2) - 1)$sameas("ELC",EFS)) * - (1 + (VmCostAvgProdH2(allCy,YTIME-1) / VmCostAvgProdH2(allCy,YTIME-2) - 1)$sameas("H2F",EFS)) * + (1 + ((VmCostAvgProdH2(allCy,YTIME) / VmCostAvgProdH2(allCy,YTIME-1)) ** 0.7 - 1)$sameas("H2F",EFS)) * (1 + (VmCostAvgProdSte(allCy,YTIME-1) / VmCostAvgProdSte(allCy,YTIME-2) - 1)$sameas("STE",EFS)) * (1 + ((VmPriceFuelSubsecCarVal(allCy,SBS,"CRO",YTIME) / VmPriceFuelSubsecCarVal(allCy,SBS,"CRO",YTIME-1)) ** 0.4 - 1)$sameas("NGS",EFS)) * (1 + ((VmPriceFuelSubsecCarVal(allCy,SBS,"CRO",YTIME) / VmPriceFuelSubsecCarVal(allCy,SBS,"CRO",YTIME-1)) ** 0.8 - 1)$SECtoEFPROD("LQD",EFS)) * From 614cc4bafcbf984c5c0359b9b81b104a63ad01d2 Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Mon, 6 Jul 2026 13:08:27 +0300 Subject: [PATCH 05/37] update h2 matfacs --- modules/05_Hydrogen/legacy/input.gms | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/05_Hydrogen/legacy/input.gms b/modules/05_Hydrogen/legacy/input.gms index 154dbe6e..ed41e4a6 100644 --- a/modules/05_Hydrogen/legacy/input.gms +++ b/modules/05_Hydrogen/legacy/input.gms @@ -136,4 +136,5 @@ loop YTIME$(An(YTIME)) do endloop; *--- i05MatFacH2(allCy,H2TECH,YTIME) = 1; -i05MatFacH2(allCy,H2TECH,YTIME)$(H2CCS(H2TECH) and ord(YTIME)<18) = 0; +i05MatFacH2(allCy,H2TECH,YTIME)$(H2CCS(H2TECH) and ord(YTIME)<=20) = 0; +i05MatFacH2(allCy,H2TECH,YTIME)$(H2CCS(H2TECH) and (ord(YTIME) = 20)) = 0.5; From 91660fb9af642b28aac610dc9a705e37b135a9dd Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Mon, 6 Jul 2026 13:38:30 +0300 Subject: [PATCH 06/37] Add BECCS refunding based on carbon tax for hydrogen production --- modules/05_Hydrogen/legacy/equations.gms | 37 +++++++++++++++++------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/modules/05_Hydrogen/legacy/equations.gms b/modules/05_Hydrogen/legacy/equations.gms index 062b7529..ac175a8c 100644 --- a/modules/05_Hydrogen/legacy/equations.gms +++ b/modules/05_Hydrogen/legacy/equations.gms @@ -92,16 +92,33 @@ Q05CostProdH2Tech(allCy,H2TECH,YTIME)$(TIME(YTIME)$(runCy(allCy))).. Q05CostVarProdH2Tech(allCy,H2TECH,YTIME)$(TIME(YTIME)$(runCy(allCy))).. V05CostVarProdH2Tech(allCy,H2TECH,YTIME) =E= - sum(EF$(H2TECHtoFEEDSTOCK(H2TECH,EF) or H2TECHtoENERGY(H2TECH,EF)), - ( - VmPriceFuelSubsecCarVal(allCy,"H2P",EF,YTIME) * 1e3 + - V05CaptRateH2(allCy,H2TECH,YTIME) * (imCo2EmiFac(allCy,"H2P",EF,YTIME) + 4.17$(sameas("BMSWAS", EF))) * VmCstCO2SeqCsts(allCy,YTIME) + - (1-V05CaptRateH2(allCy,H2TECH,YTIME)) * imCo2EmiFac(allCy,"H2P",EF,YTIME) * sum(NAP$NAPtoALLSBS(NAP,"H2P"),VmCarVal(allCy,NAP,YTIME)) - ) * (i05InputOverOutH2ProdFeed(allCy,H2TECH,EF,YTIME) + i05InputOverOutH2ProdEnergy(allCy,H2TECH,EF,YTIME)) - ) + - !!i05CostVOMH2Prod(allCy,H2TECH,YTIME) + - (i04VarCost("PGSOL",YTIME) / smTWhToMtoe)$sameas(H2TECH,"wes") + - (i04VarCost("PGAWNO",YTIME) / smTWhToMtoe)$sameas(H2TECH,"wew"); + ( + sum(EF$(H2TECHtoFEEDSTOCK(H2TECH,EF) or H2TECHtoENERGY(H2TECH,EF)), + ( + VmPriceFuelSubsecCarVal(allCy,"H2P",EF,YTIME) * 1e3 + + V05CaptRateH2(allCy,H2TECH,YTIME) * (imCo2EmiFac(allCy,"H2P",EF,YTIME) + 4.17$(sameas("BMSWAS", EF))) * VmCstCO2SeqCsts(allCy,YTIME) + + (1-V05CaptRateH2(allCy,H2TECH,YTIME)) * imCo2EmiFac(allCy,"H2P",EF,YTIME) * sum(NAP$NAPtoALLSBS(NAP,"H2P"),VmCarVal(allCy,NAP,YTIME)) - + V05CaptRateH2(allCy,H2TECH,YTIME) * (4.17$sameas("BMSWAS", EF)) * sum(NAP$NAPtoALLSBS(NAP,"H2P"), VmCarVal(allCy,NAP,YTIME)) + ) * (i05InputOverOutH2ProdFeed(allCy,H2TECH,EF,YTIME) + i05InputOverOutH2ProdEnergy(allCy,H2TECH,EF,YTIME)) + ) + + i05CostVOMH2Prod(allCy,H2TECH,YTIME) + + (i04VarCost("PGSOL",YTIME) / smTWhToMtoe)$sameas(H2TECH,"wes") + + (i04VarCost("PGAWNO",YTIME) / smTWhToMtoe)$sameas(H2TECH,"wew") + + + SQRT(SQR( + sum(EF$(H2TECHtoFEEDSTOCK(H2TECH,EF) or H2TECHtoENERGY(H2TECH,EF)), + ( + VmPriceFuelSubsecCarVal(allCy,"H2P",EF,YTIME) * 1e3 + + V05CaptRateH2(allCy,H2TECH,YTIME) * (imCo2EmiFac(allCy,"H2P",EF,YTIME) + 4.17$(sameas("BMSWAS", EF))) * VmCstCO2SeqCsts(allCy,YTIME) + + (1-V05CaptRateH2(allCy,H2TECH,YTIME)) * imCo2EmiFac(allCy,"H2P",EF,YTIME) * sum(NAP$NAPtoALLSBS(NAP,"H2P"),VmCarVal(allCy,NAP,YTIME)) - + V05CaptRateH2(allCy,H2TECH,YTIME) * (4.17$sameas("BMSWAS", EF)) * sum(NAP$NAPtoALLSBS(NAP,"H2P"), VmCarVal(allCy,NAP,YTIME)) + ) * (i05InputOverOutH2ProdFeed(allCy,H2TECH,EF,YTIME) + i05InputOverOutH2ProdEnergy(allCy,H2TECH,EF,YTIME)) + ) + + i05CostVOMH2Prod(allCy,H2TECH,YTIME) + + (i04VarCost("PGSOL",YTIME) / smTWhToMtoe)$sameas(H2TECH,"wes") + + (i04VarCost("PGAWNO",YTIME) / smTWhToMtoe)$sameas(H2TECH,"wew") + )) + ) / 2 + 1e-3; *' This equation further adjusts the market share of hydrogen technologies, particularly considering *' the relative competitiveness between CCS and non-CCS technologies. It helps to model the transition From eff6fc5e52b14835b282d3d3b2129dc08a768e8c Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Mon, 6 Jul 2026 16:51:12 +0300 Subject: [PATCH 07/37] Update premature scrapping --- modules/05_Hydrogen/legacy/equations.gms | 20 +++++++++----------- modules/05_Hydrogen/legacy/input.gms | 2 +- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/modules/05_Hydrogen/legacy/equations.gms b/modules/05_Hydrogen/legacy/equations.gms index ac175a8c..a3bc5d32 100644 --- a/modules/05_Hydrogen/legacy/equations.gms +++ b/modules/05_Hydrogen/legacy/equations.gms @@ -23,17 +23,15 @@ Q05PremRepH2Prod(allCy,H2TECH,YTIME)$(TIME(YTIME)$(runCy(allCy))$H2TECHPM(H2TECH =E= V05CostVarProdH2Tech(allCy,H2TECH,YTIME-1)**(-i05WBLGammaH2Prod(allCy,YTIME)) / ( + V05CostVarProdH2Tech(allCy,H2TECH,YTIME-1)**(-i05WBLGammaH2Prod(allCy,YTIME)) + iWBLPremRepH2Prod(allCy,H2TECH,YTIME) * - ( - sum(H2TECH2$(not sameas(H2TECH,H2TECH2)), - V05CostProdH2Tech(allCy,H2TECH2,YTIME-1) - !!V05GapShareH2Tech1(allCy,H2TECH2,YTIME)* - !!(1/i05AvailH2Prod(allCy,H2TECH,YTIME)* - !!V05CostProdH2Tech(allCy,H2TECH2,YTIME) + - !!(1-1/i05AvailH2Prod(allCy,H2TECH,YTIME)) * V05CostVarProdH2Tech(allCy,H2TECH2,YTIME)) - ) - )**(-i05WBLGammaH2Prod(allCy,YTIME)) + - V05CostVarProdH2Tech(allCy,H2TECH,YTIME-1)**(-i05WBLGammaH2Prod(allCy,YTIME)) + sum(H2TECH2$(not sameas(H2TECH,H2TECH2)), + V05CostProdH2Tech(allCy,H2TECH2,YTIME-1)**(-i05WBLGammaH2Prod(allCy,YTIME)) + !!V05GapShareH2Tech1(allCy,H2TECH2,YTIME)* + !!(1/i05AvailH2Prod(allCy,H2TECH,YTIME)* + !!V05CostProdH2Tech(allCy,H2TECH2,YTIME) + + !!(1-1/i05AvailH2Prod(allCy,H2TECH,YTIME)) * V05CostVarProdH2Tech(allCy,H2TECH2,YTIME)) + ) ); *' This equation calculates the total hydrogen production capacity that is scrapped as part of the premature replacement @@ -65,7 +63,7 @@ Q05DemGapH2(allCy,YTIME)$(TIME(YTIME)$(runCy(allCy))).. i05AvailH2Prod(allCy,H2TECH,YTIME) * smGwToTwhPerYear(YTIME) * smTWhToMtoe ) )) - ) / 2; + ) / 2 + 1e-6; *' This equation calculates the production costs of hydrogen, including both fixed costs (e.g., capital investment) *' and variable costs (e.g., operational expenses). The costs are typically differentiated by hydrogen production diff --git a/modules/05_Hydrogen/legacy/input.gms b/modules/05_Hydrogen/legacy/input.gms index ed41e4a6..e05ea6ca 100644 --- a/modules/05_Hydrogen/legacy/input.gms +++ b/modules/05_Hydrogen/legacy/input.gms @@ -122,7 +122,7 @@ i05HabAreaCountry(runCy) = i05H2Parameters(runCy,"AREA"); *--- i05EffNetH2Transp(runCy,INFRTECH,YTIME) = i05EffH2Transp(runCy,INFRTECH,YTIME)*(1-i05ConsSelfH2Transp(runCy,INFRTECH,YTIME)); *--- -iWBLPremRepH2Prod(runCy,H2TECH,YTIME) = 0.1 ; +iWBLPremRepH2Prod(runCy,H2TECH,YTIME) = 0.01 ; *--- loop H2EFFLOOP do loop INFRTECH2$H2NETWORK(INFRTECH2,H2EFFLOOP) do From 22158f7e729b23e2ba4b0191b17918a6d55628a3 Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Mon, 6 Jul 2026 18:25:36 +0300 Subject: [PATCH 08/37] Bugfix --- modules/03_RestOfEnergy/legacy/input.gms | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/03_RestOfEnergy/legacy/input.gms b/modules/03_RestOfEnergy/legacy/input.gms index a26fc63c..9864e1ad 100644 --- a/modules/03_RestOfEnergy/legacy/input.gms +++ b/modules/03_RestOfEnergy/legacy/input.gms @@ -53,7 +53,7 @@ i03FeedTransfr(allCy,EFS,YTIME) = 0; !!FIXME: i03DataGrossInlCons must be correc i03DataGrossInlCons(allCy,EFS,YTIME)$DATAY(YTIME) = sum(DSBS,imFuelCons(allCy,DSBS,EFS,YTIME)) + SUM(SSBS, - i03DataOwnConsEne(allCy,SSBS,EFS,YTIME) - + i03DataOwnConsEne(allCy,SSBS,EFS,YTIME) + i03InpTotTransfProcess(allCy,SSBS,EFS,YTIME) ) + imDistrLosses(allCy,EFS,YTIME) - From a037312e3a01b4481af5f25d4da08066c0a796ce Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Tue, 7 Jul 2026 11:41:36 +0300 Subject: [PATCH 09/37] minor --- modules/08_Prices/legacy/equations.gms | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/08_Prices/legacy/equations.gms b/modules/08_Prices/legacy/equations.gms index 92a1ca33..970ef7e0 100644 --- a/modules/08_Prices/legacy/equations.gms +++ b/modules/08_Prices/legacy/equations.gms @@ -89,7 +89,7 @@ $ENDIF *' BMSWAS and this reproduces both legacy-static and emulator-curve exactly.) VmPriceFuelSubsecCarVal(allCy,SBS,EFS,YTIME-1) * (1 + (VmCostPowGenAvgLng(allCy,YTIME-1) / VmCostPowGenAvgLng(allCy,YTIME-2) - 1)$sameas("ELC",EFS)) * - (1 + ((VmCostAvgProdH2(allCy,YTIME) / VmCostAvgProdH2(allCy,YTIME-1)) ** 0.7 - 1)$sameas("H2F",EFS)) * + (1 + ((VmCostAvgProdH2(allCy,YTIME-1) / VmCostAvgProdH2(allCy,YTIME-2)) ** 0.7 - 1)$sameas("H2F",EFS)) * (1 + (VmCostAvgProdSte(allCy,YTIME-1) / VmCostAvgProdSte(allCy,YTIME-2) - 1)$sameas("STE",EFS)) * (1 + (V08IndexBioSupply(allCy,YTIME) ** i08PriceTransElast(EFS,"BMSWAS") - 1)$(BIOFUELS(EFS) or sameas("BMSWAS",EFS))) * (1 + ((VmPriceFuelSubsecCarVal(allCy,SBS,"CRO",YTIME) / VmPriceFuelSubsecCarVal(allCy,SBS,"CRO",YTIME-1)) ** i08PriceTransElast(EFS,"CRO") - 1)$sameas("NGS",EFS)) * From 110bf4893fdbbd6f0150ba51aace277e4d8beff3 Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Tue, 7 Jul 2026 11:47:06 +0300 Subject: [PATCH 10/37] Bugfix --- modules/06_CO2/legacy/equations.gms | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/06_CO2/legacy/equations.gms b/modules/06_CO2/legacy/equations.gms index 2cd6454d..bafd95db 100644 --- a/modules/06_CO2/legacy/equations.gms +++ b/modules/06_CO2/legacy/equations.gms @@ -21,7 +21,7 @@ Q06CO2CaptureCCS(allCy,SBS,EFS,YTIME)$(TIME(YTIME)$(runCy(allCy))$SECtoEF(SBS,EF V04CO2CaptRate(allCy,PGALL,YTIME) )$sameas("PG", SBS) + sum(H2TECH$(H2TECHtoFEEDSTOCK(H2TECH,EFS) or H2TECHtoENERGY(H2TECH,EFS)), - VmProdH2(allCy,H2TECH,YTIME) / + VmProdH2(allCy,H2TECH,YTIME) * (i05InputOverOutH2ProdFeed(allCy,H2TECH,EFS,YTIME) + i05InputOverOutH2ProdEnergy(allCy,H2TECH,EFS,YTIME)) * V05CaptRateH2(allCy,H2TECH,YTIME) )$sameas("H2P", SBS) + From 61400a16163fe35b9b48e8dbc45e5df686485a22 Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Tue, 14 Jul 2026 11:14:27 +0300 Subject: [PATCH 11/37] Bugfix --- modules/03_RestOfEnergy/legacy/input.gms | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/03_RestOfEnergy/legacy/input.gms b/modules/03_RestOfEnergy/legacy/input.gms index 9864e1ad..a26fc63c 100644 --- a/modules/03_RestOfEnergy/legacy/input.gms +++ b/modules/03_RestOfEnergy/legacy/input.gms @@ -53,7 +53,7 @@ i03FeedTransfr(allCy,EFS,YTIME) = 0; !!FIXME: i03DataGrossInlCons must be correc i03DataGrossInlCons(allCy,EFS,YTIME)$DATAY(YTIME) = sum(DSBS,imFuelCons(allCy,DSBS,EFS,YTIME)) + SUM(SSBS, - i03DataOwnConsEne(allCy,SSBS,EFS,YTIME) + + i03DataOwnConsEne(allCy,SSBS,EFS,YTIME) - i03InpTotTransfProcess(allCy,SSBS,EFS,YTIME) ) + imDistrLosses(allCy,EFS,YTIME) - From 7b3e484e84a03a8335fa8a8846638172e81fa140 Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Tue, 14 Jul 2026 17:11:40 +0300 Subject: [PATCH 12/37] Add custom biomass supply curve as default. --- modules/06_CO2/legacy/input.gms | 2 +- modules/08_Prices/legacy/equations.gms | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/06_CO2/legacy/input.gms b/modules/06_CO2/legacy/input.gms index 2aa4b4c9..6346d735 100644 --- a/modules/06_CO2/legacy/input.gms +++ b/modules/06_CO2/legacy/input.gms @@ -14,7 +14,7 @@ seq_max 900 parameter i06MatFacDAC(CDRTECH) "Maturity factor of DAC technology expressing its elasticity in implementation regarding its financial sustainability" / HTDAC 0.60, -H2DAC 0.9, +H2DAC 0.3, LTDAC 1, TEW 0.7 / ; diff --git a/modules/08_Prices/legacy/equations.gms b/modules/08_Prices/legacy/equations.gms index 970ef7e0..f38a3dea 100644 --- a/modules/08_Prices/legacy/equations.gms +++ b/modules/08_Prices/legacy/equations.gms @@ -69,7 +69,7 @@ $IFTHEN.mode %bmswasPriceMode% == curve $ELSEIF.mode %bmswasPriceMode% == softfx VmPriceFuelSubsecCarVal(allCy,"PG","BMSWAS",YTIME) / VmPriceFuelSubsecCarVal(allCy,"PG","BMSWAS",YTIME-1) $ELSE.mode - 1 + EXP(0.7 * (SUM(allCy2,V03ProdPrimary(allCy2,"BMSWAS",YTIME-1)) / (150 * 23.88458966275)) ** 4) $ENDIF.mode ; From f20a0b3aa192f595dfd7c76c37bf47fb65d0aa2d Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Wed, 15 Jul 2026 11:54:31 +0300 Subject: [PATCH 13/37] Bugfix --- modules/08_Prices/legacy/equations.gms | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/08_Prices/legacy/equations.gms b/modules/08_Prices/legacy/equations.gms index f38a3dea..768eeb10 100644 --- a/modules/08_Prices/legacy/equations.gms +++ b/modules/08_Prices/legacy/equations.gms @@ -69,7 +69,8 @@ $IFTHEN.mode %bmswasPriceMode% == curve $ELSEIF.mode %bmswasPriceMode% == softfx VmPriceFuelSubsecCarVal(allCy,"PG","BMSWAS",YTIME) / VmPriceFuelSubsecCarVal(allCy,"PG","BMSWAS",YTIME-1) $ELSE.mode - EXP(0.7 * (SUM(allCy2,V03ProdPrimary(allCy2,"BMSWAS",YTIME-1)) / (150 * 23.88458966275)) ** 4) + EXP(0.9 * (SUM(runCy2,V03ProdPrimary(runCy2,"BMSWAS",YTIME-1)) / (150 * 23.88458966275)) ** 4) / + EXP(0.9 * (SUM(runCy2,V03ProdPrimary(runCy2,"BMSWAS",YTIME-2)) / (150 * 23.88458966275)) ** 4) $ENDIF.mode ; @@ -98,8 +99,7 @@ $ENDIF 1e-3 * ( VmCarVal(allCy,"TRADE",YTIME) * imCo2EmiFac(allCy,SBS,EFS,YTIME) - VmCarVal(allCy,"TRADE",YTIME-1) * imCo2EmiFac(allCy,SBS,EFS,YTIME-1) - )$DSBS(SBS) - ; + )$DSBS(SBS); Q08PriceFuelSepCarbonWght(allCy,DSBS,EF,YTIME)$(SECtoEF(DSBS,EF) $TIME(YTIME) $runCy(allCy)).. V08PriceFuelSepCarbonWght(allCy,DSBS,EF,YTIME) From 0962c3cc5eb03ace8988829bc0caa0be4f2a3e07 Mon Sep 17 00:00:00 2001 From: Christos Koumparakis <91853620+kubachri@users.noreply.github.com> Date: Wed, 22 Jul 2026 16:01:05 +0300 Subject: [PATCH 14/37] Update CO2 emission factors and adjust transport equation parameters --- core/input.gms | 22 +++++++++++----------- modules/01_Transport/simple/equations.gms | 8 ++++---- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/core/input.gms b/core/input.gms index 0d6f422c..c41d4423 100644 --- a/core/input.gms +++ b/core/input.gms @@ -100,18 +100,18 @@ imDisc(runCy,"PC",YTIME) = 0.11; * FIXME: Drive the emission factors with mrprom * author=giannou parameter iCo2EmiFacAllSbs(EF) "CO2 emission factors (kgCO2/kgoe fuel burned)" / -CRO 2.76 -LGN 4.15330622, -HCL 3.941453651, +CRO 3.2 +LGN 4.2, +HCL 4.2, *SLD 4.438008647, -GSL 2.872144882, -GDO 3.068924588, -LPG 2.612562612, -KRS 2.964253636, -RFO 3.207089028, -OLQ 3.207089028, -NGS 2.336234395, -OGS 2.336234395, +GSL 3.2, +GDO 3.2, +LPG 3.2, +KRS 3.2, +RFO 3.2, +OLQ 3.2, +NGS 2.5, +OGS 2.5, BMSWAS 0/; *--- imCo2EmiFac(runCy,SBS,EF,YTIME)$(not (sameas("NEN",SBS) or sameas("PCH",SBS))) = iCo2EmiFacAllSbs(EF); diff --git a/modules/01_Transport/simple/equations.gms b/modules/01_Transport/simple/equations.gms index 6e0e45a1..e1b2531f 100644 --- a/modules/01_Transport/simple/equations.gms +++ b/modules/01_Transport/simple/equations.gms @@ -286,12 +286,12 @@ Q01PremScrp(allCy,TRANSE,TTECH,YTIME)$(TIME(YTIME)$SECTTECH(TRANSE,TTECH)$runCy( V01PremScrp(allCy,TRANSE,TTECH,YTIME) =E= 1 - - (V01CostFuel(allCy,TRANSE,TTECH,YTIME-1)) ** (-2) / + (V01CostFuel(allCy,TRANSE,TTECH,YTIME-1)) ** (-1) / ( - V01CostFuel(allCy,TRANSE,TTECH,YTIME-1) ** (-2) + - 0.05*i01PremScrpFac(allCy,TRANSE,TTECH,YTIME) * + V01CostFuel(allCy,TRANSE,TTECH,YTIME-1) ** (-1) + + 0.02*i01PremScrpFac(allCy,TRANSE,TTECH,YTIME) * SUM(TTECH2$(not sameas(TTECH2,TTECH) and SECTTECH(TRANSE,TTECH2)), - V01CostTranspPerMeanConsSize(allCy,TRANSE,TTECH2,YTIME-1) ** (-2) + V01CostTranspPerMeanConsSize(allCy,TRANSE,TTECH2,YTIME-1) ** (-1) ) ); From 852526bfe9ed6b86f18e5ed7b521cf62216fdaa0 Mon Sep 17 00:00:00 2001 From: Fsioutas Date: Wed, 22 Jul 2026 17:29:28 +0300 Subject: [PATCH 15/37] Update emissions calculation to include time-based conditions for abatement potential --- modules/07_Emissions/legacy/equations.gms | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/07_Emissions/legacy/equations.gms b/modules/07_Emissions/legacy/equations.gms index 90fa224d..eb75d979 100644 --- a/modules/07_Emissions/legacy/equations.gms +++ b/modules/07_Emissions/legacy/equations.gms @@ -83,7 +83,7 @@ Q07GrossEmissCO2Supply(allCy,SSBS,YTIME)$(TIME(YTIME)$runCy(allCy)).. *' The determination is based on the Marginal Abatement Cost (MAC) curves, the exogenous carbon price, and specific unit conversion factors. The equation *' identifies the maximum abatement potential by scanning the MAC curve steps and selecting the highest reduction level where the implementation cost is less than or *' equal to the adjusted carbon price. This ensures that the model adopts all abatement measures that are economically viable given the current carbon price. -Q07RedAbsBySrcRegTim(E07SrcMacAbate, allCy, YTIME)$(TIME(YTIME)$(runCy(allCy))).. +Q07RedAbsBySrcRegTim(E07SrcMacAbate, allCy, YTIME)$(TIME(YTIME)$(runCy(allCy))$(ord(YTIME) > 17)).. V07RedAbsBySrcRegTim(E07SrcMacAbate, allCy, YTIME) =E= smax(E07MAC$(p07MacCost(E07MAC) <= iCarbValYrExog(allCy, YTIME) * p07UnitConvFactor(E07SrcMacAbate)), From ddc01ce80c294a8deef04997758025e700df7282 Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Thu, 23 Jul 2026 12:02:45 +0300 Subject: [PATCH 16/37] Fix for decarbonization of Industry --- core/equations.gms | 2 +- modules/02_Industry/technology/equations.gms | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/equations.gms b/core/equations.gms index 96020038..c9a2087e 100644 --- a/core/equations.gms +++ b/core/equations.gms @@ -71,7 +71,7 @@ qDummyObjINDDOMShares(allCy,YTIME,DSBS)$(TIME(YTIME) and runCy(allCy) and (INDDO ) / SUM(EFS$SECtoEF(DSBS,EFS), 1) )$((INDSE(DSBS) or sameas("NEN",DSBS) or sameas("PCH",DSBS)) and t02FinalEnergyINDSE(allCy,DSBS,YTIME)) + SUM(ITECH$SECTTECH(DSBS,ITECH), - 1e-5 * SQR( + 1e-3 * SQR( i02ScaleEndogScrap(allCy,DSBS,ITECH,YTIME) - i02ScaleEndogScrap(allCy,DSBS,ITECH,YTIME-1) ) ) / card(ITECH); diff --git a/modules/02_Industry/technology/equations.gms b/modules/02_Industry/technology/equations.gms index e2cfef67..e212dd23 100644 --- a/modules/02_Industry/technology/equations.gms +++ b/modules/02_Industry/technology/equations.gms @@ -46,13 +46,13 @@ Q02RatioRem(allCy,DSBS,ITECH,YTIME)$(TIME(YTIME)$(SECTTECH(DSBS,ITECH) and (INDD Q02PremScrpIndu(allCy,DSBS,ITECH,YTIME)$(TIME(YTIME)$(SECTTECH(DSBS,ITECH) and (INDDOM(DSBS) or NENSE(DSBS)))$runCy(allCy)).. V02PremScrpIndu(allCy,DSBS,ITECH,YTIME) =E= - 1 - (V02VarCostTech(allCy,DSBS,ITECH,YTIME-1) * i02util(allCy,DSBS,ITECH,YTIME-1) + 1e-3) ** (-2) / + 1 - (V02VarCostTech(allCy,DSBS,ITECH,YTIME-1) * i02util(allCy,DSBS,ITECH,YTIME-1) + 1e-3) ** (-1) / ( - (V02VarCostTech(allCy,DSBS,ITECH,YTIME-1) * i02util(allCy,DSBS,ITECH,YTIME-1) + 1e-3) ** (-2) + + (V02VarCostTech(allCy,DSBS,ITECH,YTIME-1) * i02util(allCy,DSBS,ITECH,YTIME-1) + 1e-3) ** (-1) + i02ScaleEndogScrap(allCy,DSBS,ITECH,YTIME) * sum(ITECH2$(not sameas(ITECH2,ITECH) and SECTTECH(DSBS,ITECH2)), - V02CostTech(allCy,DSBS,ITECH2,YTIME-1) + V02VarCostTech(allCy,DSBS,ITECH2,YTIME-1) - ) ** (-2) + (V02CostTech(allCy,DSBS,ITECH2,YTIME-1) + 1e-3) ** (-1) + ) ); *'NEW EQUATION' - kind of --> substitutes Q02ConsRemSubEquipSubSec From f0fe30c86404ca36453776d13cad34c890bd82a8 Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Thu, 23 Jul 2026 12:05:27 +0300 Subject: [PATCH 17/37] New fix --- modules/02_Industry/technology/equations.gms | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/02_Industry/technology/equations.gms b/modules/02_Industry/technology/equations.gms index e212dd23..dcaa90d2 100644 --- a/modules/02_Industry/technology/equations.gms +++ b/modules/02_Industry/technology/equations.gms @@ -49,7 +49,7 @@ Q02PremScrpIndu(allCy,DSBS,ITECH,YTIME)$(TIME(YTIME)$(SECTTECH(DSBS,ITECH) and ( 1 - (V02VarCostTech(allCy,DSBS,ITECH,YTIME-1) * i02util(allCy,DSBS,ITECH,YTIME-1) + 1e-3) ** (-1) / ( (V02VarCostTech(allCy,DSBS,ITECH,YTIME-1) * i02util(allCy,DSBS,ITECH,YTIME-1) + 1e-3) ** (-1) + - i02ScaleEndogScrap(allCy,DSBS,ITECH,YTIME) * + 0.01 * i02ScaleEndogScrap(allCy,DSBS,ITECH,YTIME) * sum(ITECH2$(not sameas(ITECH2,ITECH) and SECTTECH(DSBS,ITECH2)), (V02CostTech(allCy,DSBS,ITECH2,YTIME-1) + 1e-3) ** (-1) ) From a848592e700c40125cbd23bb84ed82d57d94c20f Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Thu, 23 Jul 2026 13:56:33 +0300 Subject: [PATCH 18/37] Apply Carbon price after 2027 for DOMSE and transport. --- core/input.gms | 10 +++++----- modules/01_Transport/simple/input.gms | 1 + modules/02_Industry/technology/preloop.gms | 12 ++++++++---- modules/08_Prices/legacy/equations.gms | 5 ++++- modules/08_Prices/legacy/input.gms | 1 + 5 files changed, 19 insertions(+), 10 deletions(-) diff --git a/core/input.gms b/core/input.gms index c41d4423..bc6be4de 100644 --- a/core/input.gms +++ b/core/input.gms @@ -387,8 +387,8 @@ SE.TNGS 0.2244 6.8 20 0.88 SE.TOGS 0.2244 10.88 20 0.8 *SE.PGTSOL 0.86224 1.36 20 0.85 SE.TBMSWAS 0.323544 10.88 20 0.5 -SE.TELC 0.3 8.976 12 0.85 -SE.THEATPUMP 0.432 12.9254 20 1.848 +SE.TELC 0.3 8.976 12 0.97 +SE.THEATPUMP 0.432 12.9254 20 3.2 SE.TSOL 0.432 12.9254 20 1 SE.TGEO 0.432 12.9254 20 0.5 AG.THCL 0.323544 10.88 20 0.7 @@ -403,7 +403,7 @@ AG.TNGS 0.2244 6.8 20 0.88 AG.TOGS 0.2244 10.88 20 0.8 *AG.PGTSOL 0.86224 1.36 20 0.85 AG.TBMSWAS 0.323544 10.88 20 0.5 -AG.TELC 0.3 8.976 12 0.85 +AG.TELC 0.3 8.976 12 0.9 AG.THEATPUMP 0.432 12.9254 20 1.848 AG.TSOL 0.432 12.9254 20 1 AG.TGEO 0.432 12.9254 20 0.5 @@ -419,8 +419,8 @@ HOU.TNGS 0.2244 6.8 20 0.88 HOU.TOGS 0.2244 10.88 20 0.8 *HOU.PGTSOL 0.86224 1.36 20 0.85 HOU.TBMSWAS 0.323544 10.88 20 0.5 -HOU.TELC 0.3 8.976 12 0.85 -HOU.THEATPUMP 0.432 12.9254 20 1.848 +HOU.TELC 0.3 8.976 12 0.97 +HOU.THEATPUMP 0.432 12.9254 20 3.2 HOU.TSOL 0.432 12.9254 20 1 HOU.TGEO 0.432 12.9254 20 0.5 ; diff --git a/modules/01_Transport/simple/input.gms b/modules/01_Transport/simple/input.gms index 946644c6..37cfa123 100644 --- a/modules/01_Transport/simple/input.gms +++ b/modules/01_Transport/simple/input.gms @@ -230,6 +230,7 @@ i01AvgVehCapLoadFac(runCy,TRANSE,TRANSUSE,YTIME) = i01CapDataLoadFacEachTransp(T ** Transport Sector i01TechLft(runCy,TRANSE,TTECH,YTIME) = imDataTransTech(TRANSE,TTECH,"LFT",YTIME); i01TechLft(runCy,TRANSE,TTECH,YTIME) = 20; +i01TechLft(runCy,DOMSE,"TELC",YTIME) = 20; *--- ** Industrial Sector i01TechLft(runCy,INDSE,ITECH,YTIME) = imDataIndTechnology(INDSE,ITECH,"LFT"); diff --git a/modules/02_Industry/technology/preloop.gms b/modules/02_Industry/technology/preloop.gms index a1a7523e..5a4a0b9a 100644 --- a/modules/02_Industry/technology/preloop.gms +++ b/modules/02_Industry/technology/preloop.gms @@ -66,10 +66,14 @@ V02VarCostTech.FX(runCy,DSBS,ITECH,YTIME)$(DATAY(YTIME) and (INDDOM(DSBS) or NEN ( sum(EF$ITECHtoEF(ITECH,EF), i02ShareBlend(runCy,DSBS,ITECH,EF,YTIME) * - VmPriceFuelSubsecCarVal.L(runCy,DSBS,EF,YTIME) + - imCO2CaptRateIndustry(runCy,ITECH,YTIME) * VmCstCO2SeqCsts.L(runCy,YTIME) * 1e-3 * (imCo2EmiFac(runCy,DSBS,EF,YTIME) + 4.17$(sameas("BMSWAS", EF))) + - (1-imCO2CaptRateIndustry(runCy,ITECH,YTIME)) * 1e-3 * (imCo2EmiFac(runCy,DSBS,EF,YTIME) + 4.17$(sameas("BMSWAS", EF))) * - (sum(NAP$NAPtoALLSBS(NAP,"PG"), VmCarVal.L(runCy,NAP,YTIME))) + ( + ( + VmPriceFuelSubsecCarVal.L(runCy,DSBS,EF,YTIME) + + imCO2CaptRateIndustry(runCy,ITECH,YTIME) * VmCstCO2SeqCsts.L(runCy,YTIME) * 1e-3 * imCo2EmiFac(runCy,DSBS,EF,YTIME) + + (1-imCO2CaptRateIndustry(runCy,ITECH,YTIME)) * 1e-3 * imCo2EmiFac(runCy,DSBS,EF,YTIME) * + sum(NAP$NAPtoALLSBS(NAP,"PG"), VmCarVal.L(runCy,NAP,YTIME)) + ) + ) ) + imVarCostTech(runCy,DSBS,ITECH,YTIME) / sUnitToKUnit ) / imUsfEneConvSubTech(runCy,DSBS,ITECH,YTIME); diff --git a/modules/08_Prices/legacy/equations.gms b/modules/08_Prices/legacy/equations.gms index 4e55e999..abc2f4a6 100644 --- a/modules/08_Prices/legacy/equations.gms +++ b/modules/08_Prices/legacy/equations.gms @@ -98,7 +98,10 @@ $ENDIF 1e-3 * ( VmCarVal(allCy,"TRADE",YTIME) * imCo2EmiFac(allCy,SBS,EFS,YTIME) - VmCarVal(allCy,"TRADE",YTIME-1) * imCo2EmiFac(allCy,SBS,EFS,YTIME-1) - )$DSBS(SBS) + )$(DSBS(SBS) and not DOMSE1(SBS)) + + 1e-3 * ( + VmCarVal(allCy,"TRADE",YTIME) * imCo2EmiFac(allCy,SBS,EFS,YTIME) + )$((DOMSE1(SBS) or TRANS1(SBS)) and ord(YTIME) > 17) ; Q08PriceFuelSepCarbonWght(allCy,DSBS,EF,YTIME)$(SECtoEF(DSBS,EF) $TIME(YTIME) $runCy(allCy)).. diff --git a/modules/08_Prices/legacy/input.gms b/modules/08_Prices/legacy/input.gms index 33132781..a8cc2ffe 100644 --- a/modules/08_Prices/legacy/input.gms +++ b/modules/08_Prices/legacy/input.gms @@ -12,6 +12,7 @@ $ondelim $include "iPriceTransElast.csv" $offdelim ; +i08PriceTransElast(EFS,"CRO")$SECtoEFPROD("LQD",EFS) = 0.65; *--- $IFTHEN %softLinkMAgPIE% == on table iPricesMagpie(allCy,SBS,YTIME) "Prices of biomass per subsector (k$2015/toe)" From f81ac85358f71ec28379928d4876642702ed2133 Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Thu, 23 Jul 2026 15:35:59 +0300 Subject: [PATCH 19/37] Add separate variable of carbon price. --- modules/08_Prices/legacy/declarations.gms | 2 ++ modules/08_Prices/legacy/equations.gms | 16 ++++++++-------- modules/08_Prices/legacy/postsolve.gms | 1 + modules/08_Prices/legacy/preloop.gms | 4 ++++ 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/modules/08_Prices/legacy/declarations.gms b/modules/08_Prices/legacy/declarations.gms index 96bccc34..708236ac 100644 --- a/modules/08_Prices/legacy/declarations.gms +++ b/modules/08_Prices/legacy/declarations.gms @@ -12,6 +12,7 @@ Q08PriceFuelSubsecCarVal(allCy,SBS,EF,YTIME) "Compute fuel prices Q08PriceFuelAvgSub(allCy,DSBS,YTIME) "Compute average fuel price per subsector" *Q08PriceFuelSubsecCHP(allCy,DSBS,EF,YTIME) "Compute fuel prices per subsector and fuel especially for chp plants" Q08PriceElecInd(allCy,TCHP,YTIME) "Compute electricity industry prices" +Q08PriceCarbon(allCy,SBS,EFS,YTIME) ; Variables @@ -25,6 +26,7 @@ VmPriceFuelSubsecCarVal(allCy,SBS,EF,YTIME) "Fuel prices per subs VmPriceFuelAvgSub(allCy,DSBS,YTIME) "Average fuel prices per subsector (k$2015/toe)" * VmPriceFuelSubsecCHP(allCy,DSBS,EF,YTIME) "Fuel prices per subsector and fuel for CHP plants (kUS$2015/toe)" VmPriceElecInd(allCy,TCHP,YTIME) "Electricity index - a function of industry price (1)" +VmPriceCarbon(allCy,SBS,EFS,YTIME) *' *** Miscellaneous *V08FuelPriSubNoCarb(allCy,SBS,EF,YTIME) "Fuel prices per subsector and fuel without carbon value (kUS$2015/toe)" diff --git a/modules/08_Prices/legacy/equations.gms b/modules/08_Prices/legacy/equations.gms index abc2f4a6..cf0c710d 100644 --- a/modules/08_Prices/legacy/equations.gms +++ b/modules/08_Prices/legacy/equations.gms @@ -95,14 +95,7 @@ $ENDIF (1 + ((VmPriceFuelSubsecCarVal(allCy,SBS,"CRO",YTIME) / VmPriceFuelSubsecCarVal(allCy,SBS,"CRO",YTIME-1)) ** i08PriceTransElast(EFS,"CRO") - 1)$sameas("NGS",EFS)) * (1 + ((VmPriceFuelSubsecCarVal(allCy,SBS,"CRO",YTIME) / VmPriceFuelSubsecCarVal(allCy,SBS,"CRO",YTIME-1)) ** i08PriceTransElast(EFS,"CRO") - 1)$SECtoEFPROD("LQD",EFS)) * (1 + ((VmPriceFuelSubsecCarVal(allCy,SBS,"CRO",YTIME) / VmPriceFuelSubsecCarVal(allCy,SBS,"CRO",YTIME-1)) ** i08PriceTransElast(EFS,"CRO") - 1)$(sameas("HCL",EFS) or sameas("LGN",EFS))) + - 1e-3 * ( - VmCarVal(allCy,"TRADE",YTIME) * imCo2EmiFac(allCy,SBS,EFS,YTIME) - - VmCarVal(allCy,"TRADE",YTIME-1) * imCo2EmiFac(allCy,SBS,EFS,YTIME-1) - )$(DSBS(SBS) and not DOMSE1(SBS)) + - 1e-3 * ( - VmCarVal(allCy,"TRADE",YTIME) * imCo2EmiFac(allCy,SBS,EFS,YTIME) - )$((DOMSE1(SBS) or TRANS1(SBS)) and ord(YTIME) > 17) - ; + VmPriceCarbon(allCy,SBS,EFS,YTIME) - VmPriceCarbon(allCy,SBS,EFS,YTIME-1); Q08PriceFuelSepCarbonWght(allCy,DSBS,EF,YTIME)$(SECtoEF(DSBS,EF) $TIME(YTIME) $runCy(allCy)).. V08PriceFuelSepCarbonWght(allCy,DSBS,EF,YTIME) @@ -112,6 +105,13 @@ V08PriceFuelSepCarbonWght(allCy,DSBS,EF,YTIME) SUM(EFS2$SECtoEF(DSBS,EFS2), (VmFinalEnergy(allCy,DSBS,EFS2,YTIME) - V02FinalElecNonSubIndTert(allCy,DSBS,YTIME)$ELCEF(EFS2)) + 1e-6) ); +Q08PriceCarbon(allCy,SBS,EFS,YTIME)$(TIME(YTIME)$(runCy(allCy))).. + VmPriceCarbon(allCy,SBS,EFS,YTIME) + =E= + 1e-3 * ( + VmCarVal(allCy,"TRADE",YTIME)$(INDSE1(SBS) or ((DOMSE1(SBS) or TRANS1(SBS)) and ord(YTIME) > 17)) + ) * imCo2EmiFac(allCy,SBS,EFS,YTIME); + *' The equation calculates the average fuel price per subsector. These average prices are used to further compute electricity prices in industry *' (using the OI "other industry" avg price), as well as the aggregate fuel demand (of substitutable fuels) per subsector. *' In the transport sector they feed into the calculation of the activity levels. diff --git a/modules/08_Prices/legacy/postsolve.gms b/modules/08_Prices/legacy/postsolve.gms index e58f3f1f..4852f8eb 100644 --- a/modules/08_Prices/legacy/postsolve.gms +++ b/modules/08_Prices/legacy/postsolve.gms @@ -8,6 +8,7 @@ VmPriceFuelAvgSub.FX(runCyL,DSBS,YTIME)$TIME(YTIME) = VmPriceFuelAvgSub.L(runCyL VmPriceFuelSubsecCarVal.FX(runCyL,SBS,EF,YTIME)$TIME(YTIME) = VmPriceFuelSubsecCarVal.L(runCyL,SBS,EF,YTIME)$TIME(YTIME); VmPriceElecInd.FX(runCyL,TCHP,YTIME)$TIME(YTIME) = VmPriceElecInd.L(runCyL,TCHP,YTIME)$TIME(YTIME); V08PriceFuelSepCarbonWght.FX(runCyL,DSBS,EF,YTIME)$TIME(YTIME) = V08PriceFuelSepCarbonWght.L(runCyL,DSBS,EF,YTIME)$TIME(YTIME); +VmPriceCarbon.FX(runCyL,SBS,EFS,YTIME)$TIME(YTIME) = VmPriceCarbon.L(runCyL,SBS,EFS,YTIME)$TIME(YTIME); *--- *' ============================================================ *' Land-use emulator emission accounting (landEmiMode == curve only) diff --git a/modules/08_Prices/legacy/preloop.gms b/modules/08_Prices/legacy/preloop.gms index 0afc6862..a4c19fa3 100644 --- a/modules/08_Prices/legacy/preloop.gms +++ b/modules/08_Prices/legacy/preloop.gms @@ -20,3 +20,7 @@ $offtext V08IndexBioSupply.LO(runCy,YTIME) = 0; V08IndexBioSupply.L(runCy,YTIME) = 1; *--- +VmPriceCarbon.LO(runCy,SBS,EFS,YTIME) = 0; +VmPriceCarbon.FX(runCy,SBS,EFS,YTIME)$DATAY(YTIME) = 1e-3 * ( + iCarbValYrExog(runCy,YTIME)$(INDSE1(SBS) or ((DOMSE1(SBS) or TRANS1(SBS)) and ord(YTIME) > 17)) + ) * imCo2EmiFac(runCy,SBS,EFS,YTIME); \ No newline at end of file From ba8449758073bc6bdf3ecb4cb659ac1a9592fef8 Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Thu, 23 Jul 2026 16:04:13 +0300 Subject: [PATCH 20/37] Add elc price reduction --- modules/04_PowerGeneration/simple/equations.gms | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/04_PowerGeneration/simple/equations.gms b/modules/04_PowerGeneration/simple/equations.gms index 5c6451bc..c9e0d660 100644 --- a/modules/04_PowerGeneration/simple/equations.gms +++ b/modules/04_PowerGeneration/simple/equations.gms @@ -261,7 +261,7 @@ Q04ShareSatPG(allCy,PGALL,YTIME)$(TIME(YTIME)$(runCy(allCy))$(PGREN(PGALL))).. Q04CostPowGenAvgLng(allCy,YTIME)$(TIME(YTIME)$(runCy(allCy))).. VmCostPowGenAvgLng(allCy,YTIME) =E= - SUM(PGALL,(VmProdElec(allCy,PGALL,YTIME) + 1e-6) * + 0.8 * SUM(PGALL,(VmProdElec(allCy,PGALL,YTIME) + 1e-6) * ( (V04CostCapTech(allCy,PGALL,YTIME) + V04CostVarTech(allCy,PGALL,YTIME)) + i04FIT(allCy,PGALL,YTIME) + From d98970c74379759114a2187d91fdc2e36c382416 Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Thu, 23 Jul 2026 17:19:43 +0300 Subject: [PATCH 21/37] Fixes --- core/equations.gms | 2 +- core/input.gms | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/core/equations.gms b/core/equations.gms index c9a2087e..e6cc19f1 100644 --- a/core/equations.gms +++ b/core/equations.gms @@ -31,7 +31,7 @@ qDummyObjPGALL(allCy,YTIME)$(TIME(YTIME) and runCy(allCy)).. 1e-5 * SQR( i04MatFacPlaAvailCap(allCy,PGALL,YTIME) - i04MatFacPlaAvailCap(allCy,PGALL,YTIME-1) ) + - 0 * SQR( + 1e-4 * SQR( i04ScaleEndogScrap(allCy,PGALL,YTIME) - i04ScaleEndogScrap(allCy,PGALL,YTIME-1) ) ) / CARD(PGALL); diff --git a/core/input.gms b/core/input.gms index bc6be4de..daeabcc9 100644 --- a/core/input.gms +++ b/core/input.gms @@ -820,9 +820,10 @@ imUsfEneConvSubTech(runCy,DOMSE,TECH,YTIME) = imDataDomTech(DOMSE,TECH,"USC"); imFixOMCostTech(runCy,NENSE,TECH,YTIME)= imDataNonEneSec(NENSE,TECH,"FC"); imVarCostTech(runCy,NENSE,TECH,YTIME) = imDataNonEneSec(NENSE,TECH,"VC"); imUsfEneConvSubTech(runCy,NENSE,TECH,YTIME) = imDataNonEneSec(NENSE,TECH,"USC"); -imUsfEneConvSubTech(runCy,"BU","TH2F",YTIME) = 0.7; -imUsfEneConvSubTech(runCy,"BU","TNGS",YTIME) = 0.6; +imUsfEneConvSubTech(runCy,"BU","TH2F",YTIME) = 0.8; +imUsfEneConvSubTech(runCy,"BU","TNGS",YTIME) = 0.5; imUsfEneConvSubTech(runCy,"BU","TGSL",YTIME) = 0.5; +imCapCostTech(runCy,"BU",TECH,YTIME)$SECTTECH("BU",TECH) = imCapCostTech(runCy,"GN","TGDO",YTIME); imCapCostTech(runCy,"BU","TH2F",YTIME) = 1.5 * imCapCostTech(runCy,"BU","TGDO",YTIME); *--- ** CDR From 27db32bb901dd37a0c37678b5d30934a66fd9a6e Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Thu, 23 Jul 2026 17:38:48 +0300 Subject: [PATCH 22/37] minor update premature scrapping hydrogen --- modules/05_Hydrogen/legacy/equations.gms | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/05_Hydrogen/legacy/equations.gms b/modules/05_Hydrogen/legacy/equations.gms index f3a48c07..7531851b 100644 --- a/modules/05_Hydrogen/legacy/equations.gms +++ b/modules/05_Hydrogen/legacy/equations.gms @@ -53,16 +53,16 @@ Q05PremRepH2Prod(allCy,H2TECH,YTIME)$(TIME(YTIME)$(runCy(allCy))$H2TECHPM(H2TECH =E= V05CostVarProdH2Tech(allCy,H2TECH,YTIME-1)**(-i05WBLGammaH2Prod(allCy,YTIME)) / ( - iWBLPremRepH2Prod(allCy,H2TECH,YTIME) * + 0.03 * iWBLPremRepH2Prod(allCy,H2TECH,YTIME) * ( sum(H2TECH2$(not sameas(H2TECH,H2TECH2)), - V05CostProdH2Tech(allCy,H2TECH2,YTIME-1) + V05CostProdH2Tech(allCy,H2TECH2,YTIME-1) ** (-i05WBLGammaH2Prod(allCy,YTIME)) !!V05GapShareH2Tech1(allCy,H2TECH2,YTIME)* !!(1/i05AvailH2Prod(allCy,H2TECH,YTIME)* !!V05CostProdH2Tech(allCy,H2TECH2,YTIME) + !!(1-1/i05AvailH2Prod(allCy,H2TECH,YTIME)) * V05CostVarProdH2Tech(allCy,H2TECH2,YTIME)) ) - )**(-i05WBLGammaH2Prod(allCy,YTIME)) + + ) + V05CostVarProdH2Tech(allCy,H2TECH,YTIME-1)**(-i05WBLGammaH2Prod(allCy,YTIME)) ); From 0cdd5141340a7a916918dc763d9c5abf412ac31f Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Thu, 23 Jul 2026 17:47:29 +0300 Subject: [PATCH 23/37] change BECCS maturity factor --- modules/04_PowerGeneration/simple/input.gms | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/04_PowerGeneration/simple/input.gms b/modules/04_PowerGeneration/simple/input.gms index dda34954..182bb74d 100644 --- a/modules/04_PowerGeneration/simple/input.gms +++ b/modules/04_PowerGeneration/simple/input.gms @@ -100,6 +100,7 @@ $ELSE.calib parameter i04MatFacPlaAvailCap(allCy,PGALL,YTIME) "Maturity factor related to plant available capacity (1)"; parameter i04ScaleEndogScrap(allCy,PGALL,YTIME) "Scale parameter for endogenous scrapping applied to the sum of full costs (1)"; i04MatFacPlaAvailCap(runCy,PGALL,YTIME) = iMatFacPlaAvailCapData(runCy,PGALL,YTIME); +i04MatFacPlaAvailCap(runCy,"ATHBMSCCS",YTIME)$(ord(YTIME) > 22) = 0.1; i04ScaleEndogScrap(runCy,PGALL,YTIME) = iScaleEndogScrapData(runCy,PGALL,YTIME); $ENDIF.calib *--- From f3ba9367601297e2015ce195710844b824e63b58 Mon Sep 17 00:00:00 2001 From: Christos Koumparakis <91853620+kubachri@users.noreply.github.com> Date: Fri, 24 Jul 2026 10:26:27 +0300 Subject: [PATCH 24/37] Enhance carbon price optimization: add last tested policy tracking and improve feasibility probing --- scripts/tasks/findCarbonPrice.R | 149 +++++++++++++++++++++----------- 1 file changed, 97 insertions(+), 52 deletions(-) diff --git a/scripts/tasks/findCarbonPrice.R b/scripts/tasks/findCarbonPrice.R index 9e4e1279..85aa6310 100644 --- a/scripts/tasks/findCarbonPrice.R +++ b/scripts/tasks/findCarbonPrice.R @@ -76,7 +76,9 @@ suppressPackageStartupMessages({ inputCsvPath <- "data/iEnvPolicies.csv" outputCsvPath <- "data/iEnvPolicies_updated.csv" backupCsvPath <- "data/iEnvPolicies_backup.csv" +lastTestedCsvPath <- "data/iEnvPolicies_last_tested.csv" # last policy tested before a failure workDir <- getwd() +lastTestedPolicy <- NULL # most recent policy table sent to OPEN-PROM # One-time backup of the original canonical file if (file.exists(inputCsvPath) && !file.exists(backupCsvPath)) { @@ -172,7 +174,9 @@ emissionsOPENPROM <- function(envWide, yearCols, alpha, targetRegion, targetYear if (file.exists(backupCsvPath)) file.copy(backupCsvPath, canonicalCsv, overwrite = TRUE) }, add = TRUE) - fwrite(applyAlpha(envWide, yearCols, alpha, targetRegion), canonicalCsv, na = "NA") + # Remember the exact policy table sent to GAMS so it can be recovered if this run fails. + lastTestedPolicy <<- applyAlpha(envWide, yearCols, alpha, targetRegion) + fwrite(lastTestedPolicy, canonicalCsv, na = "NA") ok <- run_gams(gms = gms, args = gamsArgs, log = log, echo_on_success = echo_on_success) if (!ok) stop("OPEN-PROM run failed for alpha=", alpha) @@ -226,35 +230,52 @@ alphaSeedLinear <- function(alpha0, E0, alphar, Er, Etarget, warn = TRUE, stopIf alpha0 + (Etarget - E0) * (alphar - alpha0) / (Er - E0) } -autoBracketFromSeed <- function(seedAlpha, budgetTarget, envWide, yearCols, targetRegion, targetYear, +autoBracketFromSeed <- function(seedAlpha, budgetTarget, envWide, yearCols, targetRegion, targetYear, minAlpha = 0.0, maxAlpha = 5.0, expandFactor = 1.35, maxProbes = 20, verbose = TRUE) { - if (verbose) message(sprintf("Seeding bracket near alpha ≈ %.4f", seedAlpha)) probe <- function(a) emissionsOPENPROM(envWide, yearCols, a, targetRegion, targetYear) + # --- Feasibility probe: test the maximum carbon price first --- + # If even the highest allowed price cannot pull emissions down to the target, the + # target is unreachable — stop now (one run) instead of climbing toward it probe by probe. + if (verbose) message(sprintf("Feasibility probe at maxAlpha=%.4f", maxAlpha)) + Emax <- probe(maxAlpha) + if (verbose) message(sprintf("maxAlpha: alpha=%.4f -> E=%.6f (target=%.6f)", maxAlpha, Emax, budgetTarget)) + if (Emax > budgetTarget) { + stop(sprintf( + "maxAlpha too low: at alpha=%.4f emissions are %.6f, still above target %.6f. Increase maxAlpha.", + maxAlpha, Emax, budgetTarget)) + } + + if (verbose) message(sprintf("maxAlpha feasible; seeding bracket near alpha %.4f", seedAlpha)) Eseed <- probe(seedAlpha) if (verbose) message(sprintf("Seed: alpha=%.4f → E=%.6f (target=%.6f)", seedAlpha, Eseed, budgetTarget)) if (Eseed <= budgetTarget) { - aU <- seedAlpha; EU <- Eseed - aL <- max(minAlpha, seedAlpha / expandFactor); tries <- 0 - repeat { - EL <- probe(aL); tries <- tries + 1 - if (verbose) message(sprintf("Down probe: alpha=%.4f → E=%.6f", aL, EL)) - if (EL > budgetTarget || tries >= maxProbes || aL <= minAlpha + 1e-9) break - aL <- max(minAlpha, aL / expandFactor) + # Seed already meets the target. Check whether unchanged prices (alpha = 0) meet it + # too — if so there is nothing to optimize, so keep the original prices and skip. + E0 <- probe(0) + if (verbose) message(sprintf("No-change probe: alpha=0.0000 -> E=%.6f (target=%.6f)", E0, budgetTarget)) + if (E0 <= budgetTarget) { + if (verbose) message("Region already meets target with unchanged carbon prices; skipping optimization.") + return(list(alreadyMet = TRUE, alpha = 0, + lowerAlpha = 0, upperAlpha = 0, EL = E0, EU = E0)) } - if (EL <= budgetTarget) stop("No failing lower bound; decrease minAlpha or revisit monotonicity.") + # alpha = 0 fails but the seed passes → [0, seed] brackets the target. + aL <- 0; EL <- E0 + aU <- seedAlpha; EU <- Eseed } else { + # Seed exceeds the target → expand upward toward the (already feasible) maxAlpha. aL <- seedAlpha; EL <- Eseed aU <- min(maxAlpha, seedAlpha * expandFactor); tries <- 0 repeat { + if (aU >= maxAlpha - 1e-9) { aU <- maxAlpha; EU <- Emax; break } # reuse feasibility probe EU <- probe(aU); tries <- tries + 1 if (verbose) message(sprintf("Up probe: alpha=%.4f → E=%.6f", aU, EU)) - if (EU <= budgetTarget || tries >= maxProbes || aU >= maxAlpha - 1e-9) break + if (EU <= budgetTarget || tries >= maxProbes) break aU <- min(maxAlpha, aU * expandFactor) } - if (EU > budgetTarget) stop("No passing upper bound; increase maxAlpha or revisit monotonicity.") + if (EU > budgetTarget) { aU <- maxAlpha; EU <- Emax } # probes exhausted: fall back to feasible max } list(lowerAlpha = aL, upperAlpha = aU, EL = EL, EU = EU) } @@ -348,10 +369,21 @@ extractEmissions <- function(dataMagpie) { # Run # ---------------------------- start_time <- Sys.time() -GAMSCmdArgs <- c("--DevMode=0", "--GenerateInput=off", "lo=4", "idir=./data", "--CountrySolveMode=parallel") -selectedYear <- 2100 +selectedYear <- 2030 changeCarbonPriceFromYear <- 2026 +# Model scenario passed to GAMS via --fScenario (overrides $evalGlobal fScenario in main.gms): +# 0 = No carbon price, 1 = NPi_Default, 2 = 1.5C, 3 = 2C +selectedScenario <- 2 + +# --fEndY caps the solve horizon at selectedYear instead of always running to 2100, so +# shortening a run is just a matter of lowering selectedYear (use --fEndY, never +# fEndHorizon, which triggers domain-violation errors). --fScenario selects the scenario. +GAMSCmdArgs <- c("--DevMode=0", "--GenerateInput=off", "lo=4", "idir=./data", + "--CountrySolveMode=parallel", + paste0("--fEndY=", selectedYear), + paste0("--fScenario=", selectedScenario)) + # --- Emissions variable to track --- # Set emissionsVariable to any variable name returned by reportEmissions(). # Set emissionsScale so that after multiplication the unit matches your budget targets. @@ -360,8 +392,8 @@ changeCarbonPriceFromYear <- 2026 # "Emissions|CO2|Cumulated.Gt CO2" * 1000 -> Mt CO2 (cumulated) # "Emissions|CO2.Mt CO2/yr" * 1 -> Mt CO2/yr # "Emissions|Kyoto Gases.Mt CO2-equiv/yr" * 1 -> Mt CO2-equiv/yr -emissionsVariable <- "Emissions|CO2|Cumulated.Gt CO2" -emissionsScale <- 1000 # Gt -> Mt +emissionsVariable <- "Emissions|Kyoto Gases.Mt CO2-equiv/yr" +emissionsScale <- 1 # Gt -> Mt # EU27 member regions — share a single carbon price in iEnvPolicies.csv. # Never optimised individually; always solved as one aggregated group. @@ -380,19 +412,19 @@ EU27_REGIONS <- c("AUT","BEL","BGR","CYP","CZE","DEU","DNK","ESP","EST", # Current unit: cumulated Mt CO2 (Emissions|CO2|Cumulated.Gt CO2 * 1000) targetList <- list( #"WORLD" = 1257571, # optional: comment out to skip world run - "EU27" = 92917, # sum of all 27 EU member budgets - "CAZ" = 22517, - "CHA" = 307728, - "GBR" = 14692, - "IND" = 223711, - "JPN" = 29285, - "LAM" = 117008, - "MEA" = 102029, - "NEU" = 22276, - "OAS" = 220646, - "REF" = 64216, - "SSA" = 175989, - "USA" = 100855 + # "EU27" = 1425 # sum of all 27 EU member budgets - 2035 + "CAZ" = 840, + "CHA" = 13447, + "GBR" = 263, + "IND" = 3981, + "JPN" = 766, + "LAM" = 3618, + "MEA" = 4868, + "NEU" = 842, + "OAS" = 5244, + "REF" = 3119, + "SSA" = 3733 + # "USA" = 100855 ) logFilePath <- "Carbon_price_optimization.log" @@ -421,6 +453,7 @@ resultsLog <- list() for (regName in names(targetList)) { + lastTestedPolicy <- NULL # don't carry a previous region's tested policy into this run bg <- targetList[[regName]] if (regName == "WORLD") { @@ -452,32 +485,37 @@ for (regName in names(targetList)) { targetRegion = actualRegion, targetYear = selectedYear, minAlpha = -0.5, # Allow price reduction up to -50% if needed - maxAlpha = 10.0, # Allow up to +1000% increase - expandFactor = 3.0, + maxAlpha = 40.0, # Allow up to +1000% increase + expandFactor = 4.0, maxProbes = 7, verbose = TRUE ) - # C. Solve - solveResult <- findAlphaForBudget( - envWide = currentEnvWide, - yearCols = yearCols, - budgetTarget = bg, - targetRegion = actualRegion, # Passes NULL if global - targetYear = selectedYear, - lowerAlpha = brkt$lowerAlpha, - upperAlpha = brkt$upperAlpha, - eLow = brkt$EL, - eHigh = brkt$EU, - tolAlphaRel = 1e-2, - tolEmisAbs = 1e+1, - maxIter = 60, - verbose = TRUE, - writeFinalCsv = FALSE - ) - - finalAlpha <- solveResult$alpha - message(sprintf(" -> Converged %s: Alpha=%.3f", displayName, finalAlpha)) + # C. Solve (skip the root-find when the region already meets its target unchanged) + if (isTRUE(brkt$alreadyMet)) { + finalAlpha <- 0 + message(sprintf(" -> %s already meets target; carbon prices left unchanged (Alpha=0).", displayName)) + } else { + solveResult <- findAlphaForBudget( + envWide = currentEnvWide, + yearCols = yearCols, + budgetTarget = bg, + targetRegion = actualRegion, # Passes NULL if global + targetYear = selectedYear, + lowerAlpha = brkt$lowerAlpha, + upperAlpha = brkt$upperAlpha, + eLow = brkt$EL, + eHigh = brkt$EU, + tolAlphaRel = 1e-2, + tolEmisAbs = 1e+1, + maxIter = 60, + verbose = TRUE, + writeFinalCsv = FALSE + ) + + finalAlpha <- solveResult$alpha + message(sprintf(" -> Converged %s: Alpha=%.3f", displayName, finalAlpha)) + } # Apply converged alpha and persist as the new baseline for subsequent regions currentEnvWide <- applyAlpha(currentEnvWide, yearCols, finalAlpha, actualRegion) @@ -487,6 +525,13 @@ for (regName in names(targetList)) { }, error = function(e) { message(sprintf(" !! FAILURE for %s: %s", displayName, e$message)) + # Preserve the carbon prices that were being tested when the run failed, in a + # region-specific file, so each failing region's last-tested policy survives. + if (!is.null(lastTestedPolicy)) { + regionLastTestedCsvPath <- sub("\\.csv$", paste0("_", regName, ".csv"), lastTestedCsvPath) + fwrite(lastTestedPolicy, regionLastTestedCsvPath, na = "NA") + message(sprintf(" -> Saved last-tested policy to %s", regionLastTestedCsvPath)) + } message(" -> Reverting to last good state and skipping.") if (file.exists(backupCsvPath)) file.copy(backupCsvPath, inputCsvPath, overwrite = TRUE) resultsLog[[regName]] <<- list(status = "FAILED", error = e$message) From 624ddd4b6f441698c410f7480d0174bd12776799 Mon Sep 17 00:00:00 2001 From: alextsimp Date: Fri, 24 Jul 2026 18:31:27 +0300 Subject: [PATCH 25/37] Enhance carbon price optimization: support per-region end years and flexible target list formats --- scripts/tasks/findCarbonPrice.R | 59 ++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/scripts/tasks/findCarbonPrice.R b/scripts/tasks/findCarbonPrice.R index 85aa6310..0715d449 100644 --- a/scripts/tasks/findCarbonPrice.R +++ b/scripts/tasks/findCarbonPrice.R @@ -384,6 +384,9 @@ GAMSCmdArgs <- c("--DevMode=0", "--GenerateInput=off", "lo=4", "idir=./data", paste0("--fEndY=", selectedYear), paste0("--fScenario=", selectedScenario)) +# Keep an unmodified template of the GAMS args so we can substitute per-region end years +GAMSCmdArgsTemplate <- GAMSCmdArgs + # --- Emissions variable to track --- # Set emissionsVariable to any variable name returned by reportEmissions(). # Set emissionsScale so that after multiplication the unit matches your budget targets. @@ -402,7 +405,9 @@ EU27_REGIONS <- c("AUT","BEL","BGR","CYP","CZE","DEU","DNK","ESP","EST", "LVA","MLT","NLD","POL","PRT","ROU","SVK","SVN","SWE") # --- Target list --- -# Each entry is a named budget in the unit of emissionsVariable * emissionsScale. +# Each entry is one of: +# - a scalar numeric budget (backwards compatible): targetList$REGION = BUDGET +# - a named list with budget and year: targetList$REGION = list(budget = BUDGET, year = YYYY) # Special keys: # "EU27" -> shared alpha applied to all 27 EU member rows; emissions summed over members. # "WORLD" -> alpha applied to all region rows; emissions summed globally. @@ -411,20 +416,21 @@ EU27_REGIONS <- c("AUT","BEL","BGR","CYP","CZE","DEU","DNK","ESP","EST", # # Current unit: cumulated Mt CO2 (Emissions|CO2|Cumulated.Gt CO2 * 1000) targetList <- list( - #"WORLD" = 1257571, # optional: comment out to skip world run - # "EU27" = 1425 # sum of all 27 EU member budgets - 2035 - "CAZ" = 840, - "CHA" = 13447, - "GBR" = 263, - "IND" = 3981, - "JPN" = 766, - "LAM" = 3618, - "MEA" = 4868, - "NEU" = 842, - "OAS" = 5244, - "REF" = 3119, - "SSA" = 3733 - # "USA" = 100855 + # Examples (mix-and-match supported): + # WORLD = 1257571, # optional: comment out to skip world run + EU27 = list(budget = 3000, year = 2027), + CAZ = list(budget = 1300, year = 2028) + # CHA = list(budget = 13447, year = 2032), + # GBR = list(budget = 263, year = 2030), + # IND = list(budget = 3981, year = 2040), + # JPN = list(budget = 766, year = 2030), + # LAM = list(budget = 3618, year = 2035), + # MEA = list(budget = 4868, year = 2030), + # NEU = list(budget = 842, year = 2030), + # OAS = list(budget = 5244, year = 2040), + # REF = list(budget = 3119, year = 2035), + # SSA = list(budget = 3733, year = 2030) + # USA = 100855 # numeric form still supported: interpreted as budget with fallback year = selectedYear ) logFilePath <- "Carbon_price_optimization.log" @@ -454,7 +460,17 @@ resultsLog <- list() for (regName in names(targetList)) { lastTestedPolicy <- NULL # don't carry a previous region's tested policy into this run - bg <- targetList[[regName]] + entry <- targetList[[regName]] + # Support two formats: numeric (budget only) or list(budget=..., year=...) + if (is.list(entry) && !is.null(entry$budget)) { + bg <- as.numeric(entry$budget) + regionTargetYear <- if (!is.null(entry$year)) as.integer(entry$year) else selectedYear + } else if (is.numeric(entry) && length(entry) == 1) { + bg <- as.numeric(entry) + regionTargetYear <- selectedYear + } else { + stop(sprintf("Invalid targetList entry for '%s' — must be numeric or list(budget=..., year=...)", regName)) + } if (regName == "WORLD") { actualRegion <- NULL # NULL -> alpha applied to all region rows @@ -467,7 +483,7 @@ for (regName in names(targetList)) { displayName <- regName } - message(sprintf("\n--- Optimizing %s (Target: %.4f) ---", displayName, bg)) + message(sprintf("\n--- Optimizing %s (Target: %.4f, Year: %d) ---", displayName, bg, regionTargetYear)) skipRegion <- FALSE tryCatch({ @@ -477,13 +493,18 @@ for (regName in names(targetList)) { configureGamsFile("main.gms", actualRegion) } + # Ensure GAMS runs use the region-specific solve horizon (end year) + GAMSCmdArgs <- GAMSCmdArgsTemplate + i_endy <- grep("^--fEndY=", GAMSCmdArgs) + if (length(i_endy)) GAMSCmdArgs[i_endy] <- paste0("--fEndY=", regionTargetYear) else GAMSCmdArgs <- c(GAMSCmdArgs, paste0("--fEndY=", regionTargetYear)) + brkt <- autoBracketFromSeed( seedAlpha = 0.1, budgetTarget = bg, envWide = currentEnvWide, yearCols = yearCols, targetRegion = actualRegion, - targetYear = selectedYear, + targetYear = regionTargetYear, minAlpha = -0.5, # Allow price reduction up to -50% if needed maxAlpha = 40.0, # Allow up to +1000% increase expandFactor = 4.0, @@ -501,7 +522,7 @@ for (regName in names(targetList)) { yearCols = yearCols, budgetTarget = bg, targetRegion = actualRegion, # Passes NULL if global - targetYear = selectedYear, + targetYear = regionTargetYear, lowerAlpha = brkt$lowerAlpha, upperAlpha = brkt$upperAlpha, eLow = brkt$EL, From 207d13d12992dd5d4d3502050c61b90d096ab1ef Mon Sep 17 00:00:00 2001 From: Christos Koumparakis <91853620+kubachri@users.noreply.github.com> Date: Sun, 26 Jul 2026 14:33:50 +0300 Subject: [PATCH 26/37] Refine carbon price optimization: tighten lower bound logic and update target years --- scripts/tasks/findCarbonPrice.R | 35 +++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/scripts/tasks/findCarbonPrice.R b/scripts/tasks/findCarbonPrice.R index 0715d449..75fbb1d3 100644 --- a/scripts/tasks/findCarbonPrice.R +++ b/scripts/tasks/findCarbonPrice.R @@ -273,9 +273,14 @@ autoBracketFromSeed <- function(seedAlpha, budgetTarget, envWide, yearCols, targ EU <- probe(aU); tries <- tries + 1 if (verbose) message(sprintf("Up probe: alpha=%.4f → E=%.6f", aU, EU)) if (EU <= budgetTarget || tries >= maxProbes) break + # Still above target: this probe is a tighter lower bound than the seed, so keep + # it instead of leaving aL stuck at seedAlpha (e.g. bracket [0.4, 1.6], not [0.1, 1.6]). + aL <- aU; EL <- EU aU <- min(maxAlpha, aU * expandFactor) } - if (EU > budgetTarget) { aU <- maxAlpha; EU <- Emax } # probes exhausted: fall back to feasible max + # Probes exhausted with the last one still above target: it is a valid lower bound too, + # so promote it before falling back to the known-feasible max. + if (EU > budgetTarget) { aL <- aU; EL <- EU; aU <- maxAlpha; EU <- Emax } } list(lowerAlpha = aL, upperAlpha = aU, EL = EL, EU = EU) } @@ -369,7 +374,7 @@ extractEmissions <- function(dataMagpie) { # Run # ---------------------------- start_time <- Sys.time() -selectedYear <- 2030 +selectedYear <- 2050 changeCarbonPriceFromYear <- 2026 # Model scenario passed to GAMS via --fScenario (overrides $evalGlobal fScenario in main.gms): @@ -418,19 +423,19 @@ EU27_REGIONS <- c("AUT","BEL","BGR","CYP","CZE","DEU","DNK","ESP","EST", targetList <- list( # Examples (mix-and-match supported): # WORLD = 1257571, # optional: comment out to skip world run - EU27 = list(budget = 3000, year = 2027), - CAZ = list(budget = 1300, year = 2028) - # CHA = list(budget = 13447, year = 2032), - # GBR = list(budget = 263, year = 2030), - # IND = list(budget = 3981, year = 2040), - # JPN = list(budget = 766, year = 2030), - # LAM = list(budget = 3618, year = 2035), - # MEA = list(budget = 4868, year = 2030), - # NEU = list(budget = 842, year = 2030), - # OAS = list(budget = 5244, year = 2040), - # REF = list(budget = 3119, year = 2035), - # SSA = list(budget = 3733, year = 2030) - # USA = 100855 # numeric form still supported: interpreted as budget with fallback year = selectedYear + # EU27 = list(budget = 1710, year = 2045), + # CAZ = list(budget = 1008, year = 2050), + # CHA = list(budget = 13447, year = 2050), + # GBR = list(budget = 315, year = 2040), + # IND = list(budget = 4778, year = 2050), + # JPN = list(budget = 920, year = 2040), + # LAM = list(budget = 3618, year = 2050), + # MEA = list(budget = 4868, year = 2060), + # NEU = list(budget = 842, year = 2040), + # OAS = list(budget = 5244, year = 2050), + # REF = list(budget = 3119, year = 2060), + # SSA = list(budget = 3733, year = 2050) + USA = 0 # numeric form still supported: interpreted as budget with fallback year = selectedYear ) logFilePath <- "Carbon_price_optimization.log" From f62c487b69d177a3f132ae7374ca3e049a9fa156 Mon Sep 17 00:00:00 2001 From: Christos Koumparakis <91853620+kubachri@users.noreply.github.com> Date: Sun, 26 Jul 2026 15:48:45 +0300 Subject: [PATCH 27/37] Enhance carbon price optimization: add fromYear parameter for flexible price scaling --- scripts/tasks/findCarbonPrice.R | 77 +++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 32 deletions(-) diff --git a/scripts/tasks/findCarbonPrice.R b/scripts/tasks/findCarbonPrice.R index 75fbb1d3..0d6ef401 100644 --- a/scripts/tasks/findCarbonPrice.R +++ b/scripts/tasks/findCarbonPrice.R @@ -102,10 +102,10 @@ readEnvPolicies <- function(csvPath = inputCsvPath) { list(envWide = envWide, envLong = envLong, yearCols = yearCols) } -applyAlpha <- function(envWide, yearCols, alpha, targetRegion) { +applyAlpha <- function(envWide, yearCols, alpha, targetRegion, fromYear = changeCarbonPriceFromYear) { x <- data.table::copy(envWide) - yearColsFuture <- yearCols[as.integer(yearCols) >= changeCarbonPriceFromYear] + yearColsFuture <- yearCols[as.integer(yearCols) >= fromYear] if (is.null(targetRegion)) { # GLOBAL: apply to all regions @@ -121,10 +121,11 @@ applyAlpha <- function(envWide, yearCols, alpha, targetRegion) { } writeFinalPolicyFiles <- function(envWide, yearCols, alphaFinal, region, + fromYear = changeCarbonPriceFromYear, canonicalPath = file.path("data","iEnvPolicies.csv"), updatedPath = file.path("data","iEnvPolicies_updated.csv"), alsoTimestamped = TRUE) { - envFinal <- applyAlpha(envWide, yearCols, alphaFinal, region) + envFinal <- applyAlpha(envWide, yearCols, alphaFinal, region, fromYear) dir.create(dirname(canonicalPath), showWarnings = FALSE, recursive = TRUE) dir.create(dirname(updatedPath), showWarnings = FALSE, recursive = TRUE) fwrite(envFinal, canonicalPath, na = "NA") @@ -164,6 +165,7 @@ run_gams <- function(gms = "main.gms", # Runs OPEN-PROM for a given alpha and returns the tracked emissions value. emissionsOPENPROM <- function(envWide, yearCols, alpha, targetRegion, targetYear, + fromYear = changeCarbonPriceFromYear, dataDir = "data", gms = "main.gms", gamsArgs = GAMSCmdArgs, @@ -175,7 +177,7 @@ emissionsOPENPROM <- function(envWide, yearCols, alpha, targetRegion, targetYear }, add = TRUE) # Remember the exact policy table sent to GAMS so it can be recovered if this run fails. - lastTestedPolicy <<- applyAlpha(envWide, yearCols, alpha, targetRegion) + lastTestedPolicy <<- applyAlpha(envWide, yearCols, alpha, targetRegion, fromYear) fwrite(lastTestedPolicy, canonicalCsv, na = "NA") ok <- run_gams(gms = gms, args = gamsArgs, log = log, echo_on_success = echo_on_success) if (!ok) stop("OPEN-PROM run failed for alpha=", alpha) @@ -231,9 +233,10 @@ alphaSeedLinear <- function(alpha0, E0, alphar, Er, Etarget, warn = TRUE, stopIf } autoBracketFromSeed <- function(seedAlpha, budgetTarget, envWide, yearCols, targetRegion, targetYear, + fromYear = changeCarbonPriceFromYear, minAlpha = 0.0, maxAlpha = 5.0, expandFactor = 1.35, maxProbes = 20, verbose = TRUE) { - probe <- function(a) emissionsOPENPROM(envWide, yearCols, a, targetRegion, targetYear) + probe <- function(a) emissionsOPENPROM(envWide, yearCols, a, targetRegion, targetYear, fromYear) # --- Feasibility probe: test the maximum carbon price first --- # If even the highest allowed price cannot pull emissions down to the target, the @@ -288,19 +291,20 @@ autoBracketFromSeed <- function(seedAlpha, budgetTarget, envWide, yearCols, targ findAlphaForBudget <- function(envWide, yearCols, budgetTarget, lowerAlpha, upperAlpha, eLow = NULL, eHigh = NULL, targetRegion, targetYear, + fromYear = changeCarbonPriceFromYear, tolAlphaRel = 1e-3, tolEmisAbs = 1e-3, maxIter = 60, verbose = TRUE, writeFinalCsv = TRUE) { # Evaluate bounds if not already provided by autoBracketFromSeed. - if (is.null(eLow)) eLow <- emissionsOPENPROM(envWide, yearCols, lowerAlpha, targetRegion, targetYear) - if (is.null(eHigh)) eHigh <- emissionsOPENPROM(envWide, yearCols, upperAlpha, targetRegion, targetYear) + if (is.null(eLow)) eLow <- emissionsOPENPROM(envWide, yearCols, lowerAlpha, targetRegion, targetYear, fromYear) + if (is.null(eHigh)) eHigh <- emissionsOPENPROM(envWide, yearCols, upperAlpha, targetRegion, targetYear, fromYear) if (verbose) message(sprintf( "Initial: aL=%.6f -> E=%.6f; aU=%.6f -> E=%.6f; target=%.6f", lowerAlpha, eLow, upperAlpha, eHigh, budgetTarget)) if (eLow <= budgetTarget) { - if (writeFinalCsv) writeFinalPolicyFiles(envWide, yearCols, lowerAlpha, targetRegion) + if (writeFinalCsv) writeFinalPolicyFiles(envWide, yearCols, lowerAlpha, targetRegion, fromYear) return(list(alpha = lowerAlpha, emissions = eLow, converged = TRUE, iters = 0)) } if (eHigh > budgetTarget) stop("upperAlpha still exceeds budget. Increase it or check monotonicity.") @@ -328,12 +332,12 @@ findAlphaForBudget <- function(envWide, yearCols, budgetTarget, } prevAM <- aM - emisM <- emissionsOPENPROM(envWide, yearCols, aM, targetRegion, targetYear) + emisM <- emissionsOPENPROM(envWide, yearCols, aM, targetRegion, targetYear, fromYear) if (verbose) message(sprintf("Iter %02d: aM=%.6f -> E=%.6f (target=%.6f)", it, aM, emisM, budgetTarget)) if (abs(emisM - budgetTarget) < tolEmisAbs || abs(aU - aL) / max(1.0, abs(aM)) < tolAlphaRel) { if (verbose) message("Converged.") - if (writeFinalCsv) writeFinalPolicyFiles(envWide, yearCols, aM, targetRegion) + if (writeFinalCsv) writeFinalPolicyFiles(envWide, yearCols, aM, targetRegion, fromYear) return(list(alpha = aM, emissions = emisM, converged = TRUE, iters = it)) } @@ -345,7 +349,7 @@ findAlphaForBudget <- function(envWide, yearCols, budgetTarget, } warning("Max iterations reached without strict tolerance convergence.") - if (writeFinalCsv) writeFinalPolicyFiles(envWide, yearCols, aU, targetRegion) + if (writeFinalCsv) writeFinalPolicyFiles(envWide, yearCols, aU, targetRegion, fromYear) list(alpha = aU, emissions = emisU, converged = FALSE, iters = it) } configureGamsFile <- function(gmsPath, targetRegion) { @@ -374,8 +378,8 @@ extractEmissions <- function(dataMagpie) { # Run # ---------------------------- start_time <- Sys.time() -selectedYear <- 2050 -changeCarbonPriceFromYear <- 2026 +selectedYear <- 2050 # default target year, overridable per region via targetList `year` +changeCarbonPriceFromYear <- 2026 # default first year the price is scaled, overridable per region via targetList `fromYear` # Model scenario passed to GAMS via --fScenario (overrides $evalGlobal fScenario in main.gms): # 0 = No carbon price, 1 = NPi_Default, 2 = 1.5C, 3 = 2C @@ -412,7 +416,12 @@ EU27_REGIONS <- c("AUT","BEL","BGR","CYP","CZE","DEU","DNK","ESP","EST", # --- Target list --- # Each entry is one of: # - a scalar numeric budget (backwards compatible): targetList$REGION = BUDGET -# - a named list with budget and year: targetList$REGION = list(budget = BUDGET, year = YYYY) +# - a named list: targetList$REGION = list(budget = BUDGET, year = YYYY, fromYear = YYYY) +# * budget = emissions budget the region must reach. +# * year = year by which the budget must be met (optional; defaults to selectedYear). +# * fromYear = first year whose carbon price is scaled (optional; defaults to +# changeCarbonPriceFromYear). Set it per region to change the price +# from a different start year than the global default. # Special keys: # "EU27" -> shared alpha applied to all 27 EU member rows; emissions summed over members. # "WORLD" -> alpha applied to all region rows; emissions summed globally. @@ -423,19 +432,19 @@ EU27_REGIONS <- c("AUT","BEL","BGR","CYP","CZE","DEU","DNK","ESP","EST", targetList <- list( # Examples (mix-and-match supported): # WORLD = 1257571, # optional: comment out to skip world run - # EU27 = list(budget = 1710, year = 2045), - # CAZ = list(budget = 1008, year = 2050), + EU27 = list(budget = 0, year = 2050), + CAZ = list(budget = 0, year = 2050), # CHA = list(budget = 13447, year = 2050), - # GBR = list(budget = 315, year = 2040), - # IND = list(budget = 4778, year = 2050), - # JPN = list(budget = 920, year = 2040), - # LAM = list(budget = 3618, year = 2050), - # MEA = list(budget = 4868, year = 2060), - # NEU = list(budget = 842, year = 2040), - # OAS = list(budget = 5244, year = 2050), - # REF = list(budget = 3119, year = 2060), - # SSA = list(budget = 3733, year = 2050) - USA = 0 # numeric form still supported: interpreted as budget with fallback year = selectedYear + GBR = list(budget = 0, year = 2050), + IND = list(budget = 0, year = 2070), + JPN = list(budget = 0, year = 2050), + LAM = list(budget = 703, year = 2050), + MEA = list(budget = 3245, year = 2060), + NEU = list(budget = 101, year = 2050), + OAS = list(budget = 1186, year = 2060), + REF = list(budget = 355, year = 2060), + SSA = list(budget = 2238, year = 2050), + USA = list(budget = 0, year = 2050) # numeric form still supported: interpreted as budget with fallback year = selectedYear ) logFilePath <- "Carbon_price_optimization.log" @@ -466,15 +475,17 @@ for (regName in names(targetList)) { lastTestedPolicy <- NULL # don't carry a previous region's tested policy into this run entry <- targetList[[regName]] - # Support two formats: numeric (budget only) or list(budget=..., year=...) + # Support two formats: numeric (budget only) or list(budget=..., year=..., fromYear=...) if (is.list(entry) && !is.null(entry$budget)) { bg <- as.numeric(entry$budget) - regionTargetYear <- if (!is.null(entry$year)) as.integer(entry$year) else selectedYear + regionTargetYear <- if (!is.null(entry$year)) as.integer(entry$year) else selectedYear + regionFromYear <- if (!is.null(entry$fromYear)) as.integer(entry$fromYear) else changeCarbonPriceFromYear } else if (is.numeric(entry) && length(entry) == 1) { bg <- as.numeric(entry) regionTargetYear <- selectedYear + regionFromYear <- changeCarbonPriceFromYear } else { - stop(sprintf("Invalid targetList entry for '%s' — must be numeric or list(budget=..., year=...)", regName)) + stop(sprintf("Invalid targetList entry for '%s' — must be numeric or list(budget=..., year=..., fromYear=...)", regName)) } if (regName == "WORLD") { @@ -488,7 +499,7 @@ for (regName in names(targetList)) { displayName <- regName } - message(sprintf("\n--- Optimizing %s (Target: %.4f, Year: %d) ---", displayName, bg, regionTargetYear)) + message(sprintf("\n--- Optimizing %s (Target: %.4f, Year: %d, From: %d) ---", displayName, bg, regionTargetYear, regionFromYear)) skipRegion <- FALSE tryCatch({ @@ -510,8 +521,9 @@ for (regName in names(targetList)) { yearCols = yearCols, targetRegion = actualRegion, targetYear = regionTargetYear, + fromYear = regionFromYear, minAlpha = -0.5, # Allow price reduction up to -50% if needed - maxAlpha = 40.0, # Allow up to +1000% increase + maxAlpha = 40, # Allow up to +1000% increase expandFactor = 4.0, maxProbes = 7, verbose = TRUE @@ -528,6 +540,7 @@ for (regName in names(targetList)) { budgetTarget = bg, targetRegion = actualRegion, # Passes NULL if global targetYear = regionTargetYear, + fromYear = regionFromYear, lowerAlpha = brkt$lowerAlpha, upperAlpha = brkt$upperAlpha, eLow = brkt$EL, @@ -544,7 +557,7 @@ for (regName in names(targetList)) { } # Apply converged alpha and persist as the new baseline for subsequent regions - currentEnvWide <- applyAlpha(currentEnvWide, yearCols, finalAlpha, actualRegion) + currentEnvWide <- applyAlpha(currentEnvWide, yearCols, finalAlpha, actualRegion, regionFromYear) fwrite(currentEnvWide, inputCsvPath, na = "NA") file.copy(inputCsvPath, backupCsvPath, overwrite = TRUE) resultsLog[[regName]] <- list(status = "OK", alpha = finalAlpha) From fbbd0bf9c5e2011db9b595a88f7b061bb80e27eb Mon Sep 17 00:00:00 2001 From: Dion-Pram Date: Mon, 27 Jul 2026 16:22:37 +0300 Subject: [PATCH 28/37] changes for uptake scenarios --- core/input.gms | 7 ++++++- main.gms | 4 ++-- modules/04_PowerGeneration/simple/equations.gms | 3 ++- modules/05_Hydrogen/legacy/input.gms | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/core/input.gms b/core/input.gms index a5731f64..9372fba7 100644 --- a/core/input.gms +++ b/core/input.gms @@ -712,6 +712,7 @@ parameters !!imFacSubsiCapCostSupply(SSBS,STECH) !!State subsidy (%) factor in technology capex (supply side) !!imGrantCapCostSupply(SSBS,STECH) !!State granting in technology capex (supply side) imCapCostTechMin(allCy,DSBS,TECH,YTIME) !!Factor for the minimum capex of a demand technology after the state subsidy +imCostCapTechDisc(YTIME) !!Discount rate for capital costs of power generation technologies ; $ontext @@ -868,4 +869,8 @@ imPlantEffByType(runCy,STECH,"effHeat",YTIME)$(not PGALL(STECH))= imPlantEffByTy *--- ** Conversion of GW mean power into TWh/y, depending on whether it's a leap year smGwToTwhPerYear(YTIME) = 8.76 + 0.024 $ (mod(YTIME.val,4) = 0 and mod (YTIME.val,100) <> 0); -*-- \ No newline at end of file +*-- +imCostCapTechDisc(YTIME) = 0; +imCostCapTechDisc(YTIME)$(ord(YTIME) = 20) = 0.75; +imCostCapTechDisc(YTIME)$(ord(YTIME) > 20 and ord(YTIME) <= 40) = 0.75 + (ord(YTIME) - 20) * (0.5 - 0.75) / (40 - 20); +imCostCapTechDisc(YTIME)$(ord(YTIME) > 40) = 0.5; \ No newline at end of file diff --git a/main.gms b/main.gms index 247606ba..ec71efd4 100644 --- a/main.gms +++ b/main.gms @@ -214,7 +214,7 @@ $setglobal OPENGEM off !! on or off *' *** legacy = no emulator (exogenous static price + external emission source) *' *** globiom = GLOBIOM-derived curves *' *** magpie = MAgPIE-derived curves -$setglobal landUseEmulator globiom +$setglobal landUseEmulator magpie *' *** emulatorGHGScen: active carbon-price row in the emulator coefficient tables *' *** (used when landUseEmulator != legacy and softLinkMAgPIE == off) *' *** Options: GHG000 GHG010 GHG020 GHG050 GHG100 (GHG price in $/tCO2) @@ -266,7 +266,7 @@ $evalGlobal fEndHorizon 2100 $evalGlobal fEndY 2100 $evalGlobal fStartY 2024 $evalGlobal fBaseY %fStartY% - %fPeriodOfYears% -$evalGlobal fScenario 1 !! Setting the model scenario: 0 is No carbon price, 1 is NPi_Default, 2 is 1.5C and 3 is 2C +$evalGlobal fScenario 2 !! Setting the model scenario: 0 is No carbon price, 1 is NPi_Default, 2 is 1.5C and 3 is 2C *** end of dollar commands section, no further flag definitions allowed diff --git a/modules/04_PowerGeneration/simple/equations.gms b/modules/04_PowerGeneration/simple/equations.gms index 5c6451bc..436cc567 100644 --- a/modules/04_PowerGeneration/simple/equations.gms +++ b/modules/04_PowerGeneration/simple/equations.gms @@ -53,7 +53,8 @@ Q04CostCapTech(allCy,PGALL,YTIME)$(time(YTIME) $runCy(allCy)).. V04CostCapTech(allCy,PGALL,YTIME) =E= V04CapexRESRate(allCy,PGALL,YTIME) * V04CapexFixCostPG(allCy,PGALL,YTIME) / - (i04AvailRate(allCy,PGALL,YTIME) * smGwToTwhPerYear(YTIME) * 1000); + (i04AvailRate(allCy,PGALL,YTIME) * smGwToTwhPerYear(YTIME) * 1000) * + (imCostCapTechDisc(YTIME)$(sameas(PGALL,"ATHBMSCCS")) + 1$(not sameas(PGALL,"ATHBMSCCS"))); *' Compute the variable cost of each power plant technology for every region, *' By utilizing the gross cost, fuel prices, CO2 emission factors & capture, and plant efficiency. diff --git a/modules/05_Hydrogen/legacy/input.gms b/modules/05_Hydrogen/legacy/input.gms index e86dbc09..0a2f051a 100644 --- a/modules/05_Hydrogen/legacy/input.gms +++ b/modules/05_Hydrogen/legacy/input.gms @@ -76,7 +76,7 @@ i05H2Adopt(runCy,"mid",YTIME) = i05H2Parameters(runCy,"mid"); *--- i05TranspLftH2(INFRTECH,YTIME) = i05H2InfrCapCosts("LFT",INFRTECH,YTIME); *--- -i05CostCapH2Prod(runCy,H2TECH,YTIME) = i05H2Production("IC",H2TECH,YTIME); +i05CostCapH2Prod(runCy,H2TECH,YTIME) = i05H2Production("IC",H2TECH,YTIME) * (imCostCapTechDisc(YTIME)$(sameas(H2TECH,"bgfls")) + 1$(not sameas(H2TECH,"bgfls"))); i05CostCapH2Prod(runCy,"wes",YTIME) = i05H2Production("IC","weg",YTIME); i05CostCapH2Prod(runCy,"wew",YTIME) = i05H2Production("IC","weg",YTIME); *--- From e1f198584c99b2b0fe1a535713640be517ef785a Mon Sep 17 00:00:00 2001 From: Dion-Pram Date: Tue, 28 Jul 2026 13:53:18 +0300 Subject: [PATCH 29/37] no_UPT_vers --- core/input.gms | 10 +++++----- main.gms | 4 ++-- modules/04_PowerGeneration/simple/equations.gms | 5 +++-- modules/05_Hydrogen/legacy/input.gms | 4 +++- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/core/input.gms b/core/input.gms index 3a7b634d..897e7d98 100644 --- a/core/input.gms +++ b/core/input.gms @@ -712,7 +712,7 @@ parameters !!imFacSubsiCapCostSupply(SSBS,STECH) !!State subsidy (%) factor in technology capex (supply side) !!imGrantCapCostSupply(SSBS,STECH) !!State granting in technology capex (supply side) imCapCostTechMin(allCy,DSBS,TECH,YTIME) !!Factor for the minimum capex of a demand technology after the state subsidy -imCostCapTechDisc(YTIME) !!Discount rate for capital costs of power generation technologies +#UPT imCostCapTechDisc(YTIME) !!Discount rate for capital costs of power generation technologies ; $ontext @@ -871,7 +871,7 @@ imPlantEffByType(runCy,STECH,"effHeat",YTIME)$(not PGALL(STECH))= imPlantEffByTy ** Conversion of GW mean power into TWh/y, depending on whether it's a leap year smGwToTwhPerYear(YTIME) = 8.76 + 0.024 $ (mod(YTIME.val,4) = 0 and mod (YTIME.val,100) <> 0); *-- -imCostCapTechDisc(YTIME) = 0; -imCostCapTechDisc(YTIME)$(ord(YTIME) = 20) = 0.75; -imCostCapTechDisc(YTIME)$(ord(YTIME) > 20 and ord(YTIME) <= 40) = 0.75 + (ord(YTIME) - 20) * (0.5 - 0.75) / (40 - 20); -imCostCapTechDisc(YTIME)$(ord(YTIME) > 40) = 0.5; \ No newline at end of file +#UPT imCostCapTechDisc(YTIME) = 0; +#UPT imCostCapTechDisc(YTIME)$(ord(YTIME) = 20) = 0.75; +#UPT imCostCapTechDisc(YTIME)$(ord(YTIME) > 20 and ord(YTIME) <= 40) = 0.75 + (ord(YTIME) - 20) * (0.5 - 0.75) / (40 - 20); +#UPT imCostCapTechDisc(YTIME)$(ord(YTIME) > 40) = 0.5; \ No newline at end of file diff --git a/main.gms b/main.gms index a85ae7f7..75dd5973 100644 --- a/main.gms +++ b/main.gms @@ -214,7 +214,7 @@ $setglobal OPENGEM off !! on or off *' *** legacy = no emulator (exogenous static price + external emission source) *' *** globiom = GLOBIOM-specific BMSWAS and AFOLU functions *' *** magpie = MAgPIE-specific H12 price and effective-2G-biomass functions -$setglobal landUseEmulator magpie +$setglobal landUseEmulator globiom *' *** emulatorCarbonPriceScenario: active carbon-price/policy row in the *' *** selected emulator's coefficient tables *' *** (used when landUseEmulator != legacy and softLinkMAgPIE == off) @@ -278,7 +278,7 @@ $evalGlobal fEndHorizon 2100 $evalGlobal fEndY 2100 $evalGlobal fStartY 2024 $evalGlobal fBaseY %fStartY% - %fPeriodOfYears% -$evalGlobal fScenario 2 !! Setting the model scenario: 0 is No carbon price, 1 is NPi_Default, 2 is 1.5C and 3 is 2C +$evalGlobal fScenario 1 !! Setting the model scenario: 0 is No carbon price, 1 is NPi_Default, 2 is 1.5C and 3 is 2C *** end of dollar commands section, no further flag definitions allowed diff --git a/modules/04_PowerGeneration/simple/equations.gms b/modules/04_PowerGeneration/simple/equations.gms index 8c0b22b8..cfbb59f6 100644 --- a/modules/04_PowerGeneration/simple/equations.gms +++ b/modules/04_PowerGeneration/simple/equations.gms @@ -53,8 +53,9 @@ Q04CostCapTech(allCy,PGALL,YTIME)$(time(YTIME) $runCy(allCy)).. V04CostCapTech(allCy,PGALL,YTIME) =E= V04CapexRESRate(allCy,PGALL,YTIME) * V04CapexFixCostPG(allCy,PGALL,YTIME) / - (i04AvailRate(allCy,PGALL,YTIME) * smGwToTwhPerYear(YTIME) * 1000) * - (imCostCapTechDisc(YTIME)$(sameas(PGALL,"ATHBMSCCS")) + 1$(not sameas(PGALL,"ATHBMSCCS"))); + (i04AvailRate(allCy,PGALL,YTIME) * smGwToTwhPerYear(YTIME) * 1000) + #UPT * (imCostCapTechDisc(YTIME)$(sameas(PGALL,"ATHBMSCCS")) + 1$(not sameas(PGALL,"ATHBMSCCS"))) + ; *' Compute the variable cost of each power plant technology for every region, *' By utilizing the gross cost, fuel prices, CO2 emission factors & capture, and plant efficiency. diff --git a/modules/05_Hydrogen/legacy/input.gms b/modules/05_Hydrogen/legacy/input.gms index 0a2f051a..55326da3 100644 --- a/modules/05_Hydrogen/legacy/input.gms +++ b/modules/05_Hydrogen/legacy/input.gms @@ -76,7 +76,9 @@ i05H2Adopt(runCy,"mid",YTIME) = i05H2Parameters(runCy,"mid"); *--- i05TranspLftH2(INFRTECH,YTIME) = i05H2InfrCapCosts("LFT",INFRTECH,YTIME); *--- -i05CostCapH2Prod(runCy,H2TECH,YTIME) = i05H2Production("IC",H2TECH,YTIME) * (imCostCapTechDisc(YTIME)$(sameas(H2TECH,"bgfls")) + 1$(not sameas(H2TECH,"bgfls"))); +i05CostCapH2Prod(runCy,H2TECH,YTIME) = i05H2Production("IC",H2TECH,YTIME) +#UPT* (imCostCapTechDisc(YTIME)$(sameas(H2TECH,"bgfls")) + 1$(not sameas(H2TECH,"bgfls"))) +; i05CostCapH2Prod(runCy,"wes",YTIME) = i05H2Production("IC","weg",YTIME); i05CostCapH2Prod(runCy,"wew",YTIME) = i05H2Production("IC","weg",YTIME); *--- From 59831f8a15b21fdc5bae6458f828c97e7e9722d0 Mon Sep 17 00:00:00 2001 From: Dion-Pram Date: Tue, 28 Jul 2026 18:33:11 +0300 Subject: [PATCH 30/37] !!#UPT --- core/input.gms | 10 +++++----- modules/04_PowerGeneration/simple/equations.gms | 2 +- modules/05_Hydrogen/legacy/input.gms | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/input.gms b/core/input.gms index 897e7d98..09d97055 100644 --- a/core/input.gms +++ b/core/input.gms @@ -712,7 +712,7 @@ parameters !!imFacSubsiCapCostSupply(SSBS,STECH) !!State subsidy (%) factor in technology capex (supply side) !!imGrantCapCostSupply(SSBS,STECH) !!State granting in technology capex (supply side) imCapCostTechMin(allCy,DSBS,TECH,YTIME) !!Factor for the minimum capex of a demand technology after the state subsidy -#UPT imCostCapTechDisc(YTIME) !!Discount rate for capital costs of power generation technologies +!!#UPT imCostCapTechDisc(YTIME) !!Discount rate for capital costs of power generation technologies ; $ontext @@ -871,7 +871,7 @@ imPlantEffByType(runCy,STECH,"effHeat",YTIME)$(not PGALL(STECH))= imPlantEffByTy ** Conversion of GW mean power into TWh/y, depending on whether it's a leap year smGwToTwhPerYear(YTIME) = 8.76 + 0.024 $ (mod(YTIME.val,4) = 0 and mod (YTIME.val,100) <> 0); *-- -#UPT imCostCapTechDisc(YTIME) = 0; -#UPT imCostCapTechDisc(YTIME)$(ord(YTIME) = 20) = 0.75; -#UPT imCostCapTechDisc(YTIME)$(ord(YTIME) > 20 and ord(YTIME) <= 40) = 0.75 + (ord(YTIME) - 20) * (0.5 - 0.75) / (40 - 20); -#UPT imCostCapTechDisc(YTIME)$(ord(YTIME) > 40) = 0.5; \ No newline at end of file +!!#UPT imCostCapTechDisc(YTIME) = 0; +!!#UPT imCostCapTechDisc(YTIME)$(ord(YTIME) = 20) = 0.75; +!!#UPT imCostCapTechDisc(YTIME)$(ord(YTIME) > 20 and ord(YTIME) <= 40) = 0.75 + (ord(YTIME) - 20) * (0.5 - 0.75) / (40 - 20); +!!#UPT imCostCapTechDisc(YTIME)$(ord(YTIME) > 40) = 0.5; \ No newline at end of file diff --git a/modules/04_PowerGeneration/simple/equations.gms b/modules/04_PowerGeneration/simple/equations.gms index cfbb59f6..a52ef518 100644 --- a/modules/04_PowerGeneration/simple/equations.gms +++ b/modules/04_PowerGeneration/simple/equations.gms @@ -54,7 +54,7 @@ Q04CostCapTech(allCy,PGALL,YTIME)$(time(YTIME) $runCy(allCy)).. =E= V04CapexRESRate(allCy,PGALL,YTIME) * V04CapexFixCostPG(allCy,PGALL,YTIME) / (i04AvailRate(allCy,PGALL,YTIME) * smGwToTwhPerYear(YTIME) * 1000) - #UPT * (imCostCapTechDisc(YTIME)$(sameas(PGALL,"ATHBMSCCS")) + 1$(not sameas(PGALL,"ATHBMSCCS"))) + !!#UPT * (imCostCapTechDisc(YTIME)$(sameas(PGALL,"ATHBMSCCS")) + 1$(not sameas(PGALL,"ATHBMSCCS"))) ; *' Compute the variable cost of each power plant technology for every region, diff --git a/modules/05_Hydrogen/legacy/input.gms b/modules/05_Hydrogen/legacy/input.gms index 55326da3..8859c357 100644 --- a/modules/05_Hydrogen/legacy/input.gms +++ b/modules/05_Hydrogen/legacy/input.gms @@ -77,7 +77,7 @@ i05H2Adopt(runCy,"mid",YTIME) = i05H2Parameters(runCy,"mid"); i05TranspLftH2(INFRTECH,YTIME) = i05H2InfrCapCosts("LFT",INFRTECH,YTIME); *--- i05CostCapH2Prod(runCy,H2TECH,YTIME) = i05H2Production("IC",H2TECH,YTIME) -#UPT* (imCostCapTechDisc(YTIME)$(sameas(H2TECH,"bgfls")) + 1$(not sameas(H2TECH,"bgfls"))) +!!#UPT* (imCostCapTechDisc(YTIME)$(sameas(H2TECH,"bgfls")) + 1$(not sameas(H2TECH,"bgfls"))) ; i05CostCapH2Prod(runCy,"wes",YTIME) = i05H2Production("IC","weg",YTIME); i05CostCapH2Prod(runCy,"wew",YTIME) = i05H2Production("IC","weg",YTIME); From a5a91ae32ccb5590602d95e5f9b9c06fdac04386 Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Wed, 29 Jul 2026 10:23:44 +0300 Subject: [PATCH 31/37] Update maturity factors for INDDOM --- core/input.gms | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/input.gms b/core/input.gms index 09d97055..b471c444 100644 --- a/core/input.gms +++ b/core/input.gms @@ -696,8 +696,8 @@ $offtext $ELSE.calib variable imMatrFactor(allCy,DSBS,TECH,YTIME) "Maturity factor per technology and subsector for all countries (1)"; -imMatrFactor.LO(runCy,DSBS,TECH,YTIME) = 1e-6; -imMatrFactor.UP(runCy,DSBS,TECH,YTIME) = 10; +imMatrFactor.LO(runCy,DSBS,TECH,YTIME) = 1e-2; +imMatrFactor.UP(runCy,DSBS,TECH,YTIME) = 1; imMatrFactor.L(runCy,DSBS,TECH,YTIME) = iMatrFactorData(runCy,DSBS,TECH,YTIME); imMatrFactor.FX(runCy,DSBS,TECH,YTIME)$(not (sameas(DSBS,"PC") or sameas(DSBS,"PB") or sameas(DSBS,"GU") or INDDOM(DSBS) or sameas("NEN",DSBS) or sameas("PCH",DSBS))) = iMatrFactorData(runCy,DSBS,TECH,YTIME); imMatrFactor.FX(runCy,DSBS,TECH,YTIME)$(sameas(DSBS,"AG") and not EU28(runCy)) = iMatrFactorData(runCy,DSBS,TECH,YTIME); From c3bb8a3e0546a38fa80493fdbf0d0a5b5e70c649 Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Thu, 30 Jul 2026 14:01:53 +0300 Subject: [PATCH 32/37] Add biomass supply curve and add carbon price for BU. --- modules/08_Prices/legacy/equations.gms | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/08_Prices/legacy/equations.gms b/modules/08_Prices/legacy/equations.gms index ae55ea72..5bb70f23 100644 --- a/modules/08_Prices/legacy/equations.gms +++ b/modules/08_Prices/legacy/equations.gms @@ -52,6 +52,7 @@ $ENDIF.magpieQuantityEquation Q08BmswasPriceFactor(allCy,YTIME)$(TIME(YTIME) $runCy(allCy)).. V08BmswasPriceFactor(allCy,YTIME) =E= +( $IFTHEN.mode %bmswasPriceMode% == curve $IFTHEN.emulatorCurve %landUseEmulator% == globiom ( 1e-3 + sum(activeGlobiomScen, i08BmswasSupplyCoefGlobiom(activeGlobiomScen,allCy,"a",YTIME)) @@ -80,6 +81,9 @@ $ELSEIF.mode %bmswasPriceMode% == softfx $ELSE.mode 1 $ENDIF.mode +) * +EXP(0.1 * (SUM(runCy2,V03ProdPrimary(runCy2,"BMSWAS",YTIME-1)) / (150 * 23.88458966275)) ** 10) / +EXP(0.1 * (SUM(runCy2,V03ProdPrimary(runCy2,"BMSWAS",YTIME-2)) / (150 * 23.88458966275)) ** 10) ; Q08PriceFuelSubsecCarVal(allCy,SBS,EFS,YTIME)$(SECtoEF(SBS,EFS) $(not sameas("CRO",EFS)) $TIME(YTIME) @@ -132,7 +136,7 @@ Q08PriceCarbon(allCy,SBS,EFS,YTIME)$(TIME(YTIME)$(runCy(allCy))).. VmPriceCarbon(allCy,SBS,EFS,YTIME) =E= 1e-3 * ( - VmCarVal(allCy,"TRADE",YTIME)$(INDSE1(SBS) or ((DOMSE1(SBS) or TRANS1(SBS)) and ord(YTIME) > 17)) + VmCarVal(allCy,"TRADE",YTIME)$(INDSE1(SBS) or ((DOMSE1(SBS) or TRANS1(SBS) or sameas("BU", SBS)) and ord(YTIME) > 17)) ) * imCo2EmiFac(allCy,SBS,EFS,YTIME); *' The equation calculates the average fuel price per subsector. These average prices are used to further compute electricity prices in industry From 4c02b52eefe97b9185f385f8e30122f306d0c269 Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Fri, 31 Jul 2026 10:22:27 +0300 Subject: [PATCH 33/37] Update global biomass curve --- modules/08_Prices/legacy/equations.gms | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/08_Prices/legacy/equations.gms b/modules/08_Prices/legacy/equations.gms index 5bb70f23..7ba18244 100644 --- a/modules/08_Prices/legacy/equations.gms +++ b/modules/08_Prices/legacy/equations.gms @@ -82,9 +82,9 @@ $ELSE.mode 1 $ENDIF.mode ) * -EXP(0.1 * (SUM(runCy2,V03ProdPrimary(runCy2,"BMSWAS",YTIME-1)) / (150 * 23.88458966275)) ** 10) / -EXP(0.1 * (SUM(runCy2,V03ProdPrimary(runCy2,"BMSWAS",YTIME-2)) / (150 * 23.88458966275)) ** 10) - ; +EXP(0.7 * (SUM(runCy2,V03ProdPrimary(runCy2,"BMSWAS",YTIME-1)) / (140 * 23.88458966275)) ** 6) / +EXP(0.7 * (SUM(runCy2,V03ProdPrimary(runCy2,"BMSWAS",YTIME-2)) / (140 * 23.88458966275)) ** 6) +; Q08PriceFuelSubsecCarVal(allCy,SBS,EFS,YTIME)$(SECtoEF(SBS,EFS) $(not sameas("CRO",EFS)) $TIME(YTIME) $IFTHEN %softLinkMAgPIE% == on From 93de4524c33a82a65dd13d31c481bf1dda8db8af Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Fri, 31 Jul 2026 10:58:33 +0300 Subject: [PATCH 34/37] minor --- modules/04_PowerGeneration/simple/equations.gms | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/04_PowerGeneration/simple/equations.gms b/modules/04_PowerGeneration/simple/equations.gms index a52ef518..2a38b98a 100644 --- a/modules/04_PowerGeneration/simple/equations.gms +++ b/modules/04_PowerGeneration/simple/equations.gms @@ -263,7 +263,7 @@ Q04ShareSatPG(allCy,PGALL,YTIME)$(TIME(YTIME)$(runCy(allCy))$(PGREN(PGALL))).. Q04CostPowGenAvgLng(allCy,YTIME)$(TIME(YTIME)$(runCy(allCy))).. VmCostPowGenAvgLng(allCy,YTIME) =E= - 0.8 * SUM(PGALL,(VmProdElec(allCy,PGALL,YTIME) + 1e-6) * + SUM(PGALL,(VmProdElec(allCy,PGALL,YTIME) + 1e-6) * ( (V04CostCapTech(allCy,PGALL,YTIME) + V04CostVarTech(allCy,PGALL,YTIME)) + i04FIT(allCy,PGALL,YTIME) + From e906484d0747f6fa7f4cd00367e2e90375d0ab78 Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Fri, 31 Jul 2026 11:08:23 +0300 Subject: [PATCH 35/37] Bugfixes --- modules/05_Hydrogen/legacy/input.gms | 4 ++-- modules/08_Prices/legacy/equations.gms | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/modules/05_Hydrogen/legacy/input.gms b/modules/05_Hydrogen/legacy/input.gms index f737db8f..8038abfc 100644 --- a/modules/05_Hydrogen/legacy/input.gms +++ b/modules/05_Hydrogen/legacy/input.gms @@ -136,5 +136,5 @@ loop YTIME$(An(YTIME)) do endloop; *--- i05MatFacH2(allCy,H2TECH,YTIME) = 1; -i05MatFacH2(allCy,H2TECH,YTIME)$(H2CCS(H2TECH) and ord(YTIME)<=20) = 0; -i05MatFacH2(allCy,H2TECH,YTIME)$(H2CCS(H2TECH) and (ord(YTIME) = 20)) = 0.5; +i05MatFacH2(allCy,H2TECH,YTIME)$(H2CCS(H2TECH) and ord(YTIME) <= 25) = 0.5; +i05MatFacH2(allCy,H2TECH,YTIME)$(H2CCS(H2TECH) and ord(YTIME) <= 20) = 0; diff --git a/modules/08_Prices/legacy/equations.gms b/modules/08_Prices/legacy/equations.gms index bd5281ba..28ee829a 100644 --- a/modules/08_Prices/legacy/equations.gms +++ b/modules/08_Prices/legacy/equations.gms @@ -79,12 +79,11 @@ $ENDIF.emulatorCurve $ELSEIF.mode %bmswasPriceMode% == softfx VmPriceFuelSubsecCarVal(allCy,"PG","BMSWAS",YTIME) / VmPriceFuelSubsecCarVal(allCy,"PG","BMSWAS",YTIME-1) $ELSE.mode - EXP(0.9 * (SUM(runCy2,V03ProdPrimary(runCy2,"BMSWAS",YTIME-1)) / (150 * 23.88458966275)) ** 4) / - EXP(0.9 * (SUM(runCy2,V03ProdPrimary(runCy2,"BMSWAS",YTIME-2)) / (150 * 23.88458966275)) ** 4) +1 $ENDIF.mode ) * -EXP(0.7 * (SUM(runCy2,V03ProdPrimary(runCy2,"BMSWAS",YTIME-1)) / (140 * 23.88458966275)) ** 6) / -EXP(0.7 * (SUM(runCy2,V03ProdPrimary(runCy2,"BMSWAS",YTIME-2)) / (140 * 23.88458966275)) ** 6) +EXP(1.5 * (SUM(runCy2,V03ProdPrimary(runCy2,"BMSWAS",YTIME-1)) / (140 * 23.88458966275)) ** 3) / +EXP(1.5 * (SUM(runCy2,V03ProdPrimary(runCy2,"BMSWAS",YTIME-2)) / (140 * 23.88458966275)) ** 3) ; Q08PriceFuelSubsecCarVal(allCy,SBS,EFS,YTIME)$(SECtoEF(SBS,EFS) $(not sameas("CRO",EFS)) $TIME(YTIME) From d7d60f636b59a2e7375a7d5de853a407f35c2a93 Mon Sep 17 00:00:00 2001 From: Michael Madianos Date: Fri, 31 Jul 2026 11:47:05 +0300 Subject: [PATCH 36/37] Revisit dac parameters --- modules/06_CO2/legacy/declarations.gms | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/06_CO2/legacy/declarations.gms b/modules/06_CO2/legacy/declarations.gms index ecd33962..b80e99fb 100644 --- a/modules/06_CO2/legacy/declarations.gms +++ b/modules/06_CO2/legacy/declarations.gms @@ -44,6 +44,6 @@ Scalars *' Proposed values for S06EmissPercCDR between 0.005 - 0.02. *' S06CapFacMinNewCDR is responsible for the minimum deployment of CDR technologies. In ambitious scenarios, this reflects the post-net-zero phase. *' Proposed values for S06CapFacMinNewCDR between 0.005 - 0.025. -S06EmissPercCDR "The percentage of emissions that needs to be captured by new CDR equipment" /0.003/ -S06CapFacMinNewCDR "The minimum level of CDR capacity expansion as a percentage of last year's capacity" /0.015/ +S06EmissPercCDR "The percentage of emissions that needs to be captured by new CDR equipment" /0.004/ +S06CapFacMinNewCDR "The minimum level of CDR capacity expansion as a percentage of last year's capacity" /0.03/ ; \ No newline at end of file From 46da37ecf35eb01f963eb907dede505c87c5f48c Mon Sep 17 00:00:00 2001 From: Songmin Date: Fri, 31 Jul 2026 23:14:02 +0800 Subject: [PATCH 37/37] Change landUseEmulator from globiom to magpie --- main.gms | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.gms b/main.gms index 75dd5973..a4d3b19e 100644 --- a/main.gms +++ b/main.gms @@ -214,7 +214,7 @@ $setglobal OPENGEM off !! on or off *' *** legacy = no emulator (exogenous static price + external emission source) *' *** globiom = GLOBIOM-specific BMSWAS and AFOLU functions *' *** magpie = MAgPIE-specific H12 price and effective-2G-biomass functions -$setglobal landUseEmulator globiom +$setglobal landUseEmulator magpie *' *** emulatorCarbonPriceScenario: active carbon-price/policy row in the *' *** selected emulator's coefficient tables *' *** (used when landUseEmulator != legacy and softLinkMAgPIE == off)