From 2814590d033c9eb16b390aee0fcef06fefaa29c5 Mon Sep 17 00:00:00 2001 From: SutubraResearch <81306560+SutubraResearch@users.noreply.github.com> Date: Thu, 14 Sep 2023 17:39:14 -0300 Subject: [PATCH] Add Endogenous Retirements to Temoa (#48) This commit adds an endogenous retirement feature to Temoa. Users can add a list of technologies for which they would like to enable endogenous retirements to the 'tech_retirement' set. Prior to this commit, the decision variables of Temoa were: - Capacity additions - Operational decision at the time step level This commit adds an additional decision variable of - Retirement decisions Keep in mind that enabling the endogenous retirement feature will add to model size, complexity and compute time. As a result, users are advised to only include technologies for which they explicitly want to enable endogenous retirements to the 'tech_retirement' set. --- data_files/temoa_schema.sql | 35 ++++++++- data_files/temoa_schema.sqlite | Bin 192512 -> 688128 bytes data_files/temoa_test_system.sql | 40 ++++++++++- data_files/temoa_test_system.sqlite | Bin 495616 -> 524288 bytes data_files/temoa_utopia.sql | 36 +++++++++- data_files/temoa_utopia.sqlite | Bin 495616 -> 581632 bytes temoa_model/pformat_results.py | 48 ++++++++++--- temoa_model/temoa_config.py | 3 + temoa_model/temoa_initialize.py | 12 +++- temoa_model/temoa_model.py | 25 ++++--- temoa_model/temoa_myopic.py | 13 ++-- temoa_model/temoa_rules.py | 107 +++++++++++++++++----------- 12 files changed, 247 insertions(+), 72 deletions(-) diff --git a/data_files/temoa_schema.sql b/data_files/temoa_schema.sql index 58852650..2755cc17 100644 --- a/data_files/temoa_schema.sql +++ b/data_files/temoa_schema.sql @@ -77,6 +77,12 @@ CREATE TABLE IF NOT EXISTS "tech_groups" ( FOREIGN KEY("tech") REFERENCES "technologies"("tech"), FOREIGN KEY("group_name") REFERENCES "groups"("group_name") ); +CREATE TABLE "tech_retirement" ( + "tech" text, + "notes" TEXT, + PRIMARY KEY("tech"), + FOREIGN KEY("tech") REFERENCES "technologies"("tech") +); CREATE TABLE "sector_labels" ( "sector" text, PRIMARY KEY("sector") @@ -175,8 +181,21 @@ CREATE TABLE "RampUp" ( PRIMARY KEY("regions", "tech"), FOREIGN KEY("tech") REFERENCES "technologies"("tech") ); - CREATE TABLE "Output_V_Capacity" ( + "regions" text, + "scenario" text, + "sector" text, + "t_periods" integer, + "tech" text, + "vintage" integer, + "capacity" real, + FOREIGN KEY("t_periods") REFERENCES "time_periods"("t_periods"), + FOREIGN KEY("sector") REFERENCES "sector_labels"("sector"), + FOREIGN KEY("vintage") REFERENCES "time_periods"("t_periods"), + FOREIGN KEY("tech") REFERENCES "technologies"("tech"), + PRIMARY KEY("regions","scenario","t_periods","tech","vintage") +); +CREATE TABLE "Output_V_NewCapacity" ( "regions" text, "scenario" text, "sector" text, @@ -188,6 +207,20 @@ CREATE TABLE "Output_V_Capacity" ( FOREIGN KEY("tech") REFERENCES "technologies"("tech"), FOREIGN KEY("vintage") REFERENCES "time_periods"("t_periods") ); +CREATE TABLE "Output_V_RetiredCapacity" ( + "regions" text, + "scenario" text, + "sector" text, + "t_periods" integer, + "tech" text, + "vintage" integer, + "capacity" real, + FOREIGN KEY("t_periods") REFERENCES "time_periods"("t_periods"), + FOREIGN KEY("sector") REFERENCES "sector_labels"("sector"), + FOREIGN KEY("vintage") REFERENCES "time_periods"("t_periods"), + FOREIGN KEY("tech") REFERENCES "technologies"("tech"), + PRIMARY KEY("regions","scenario","t_periods","tech","vintage") +); CREATE TABLE "Output_VFlow_Out" ( "regions" text, "scenario" text, diff --git a/data_files/temoa_schema.sqlite b/data_files/temoa_schema.sqlite index d8f73b6c6ad0b3e9aa008412393b46c679bcf43b..2bd24f46bf01076a0bbf3e8932726cc1c7cff78d 100644 GIT binary patch delta 8468 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 HhyMQoI8iGk delta 5877 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 diff --git a/data_files/temoa_test_system.sql b/data_files/temoa_test_system.sql index 880aafb5..35767f2a 100644 --- a/data_files/temoa_test_system.sql +++ b/data_files/temoa_test_system.sql @@ -97,6 +97,12 @@ CREATE TABLE "tech_annual" ( PRIMARY KEY("tech"), FOREIGN KEY("tech") REFERENCES "technologies"("tech") ); +CREATE TABLE "tech_retirement" ( + "tech" text, + "notes" TEXT, + PRIMARY KEY("tech"), + FOREIGN KEY("tech") REFERENCES "technologies"("tech") +); CREATE TABLE "sector_labels" ( "sector" text, PRIMARY KEY("sector") @@ -231,14 +237,42 @@ CREATE TABLE "Output_V_Capacity" ( "regions" text, "scenario" text, "sector" text, + "t_periods" integer, "tech" text, "vintage" integer, "capacity" real, - PRIMARY KEY("regions","scenario","tech","vintage"), + FOREIGN KEY("t_periods") REFERENCES "time_periods"("t_periods"), + FOREIGN KEY("sector") REFERENCES "sector_labels"("sector"), + FOREIGN KEY("vintage") REFERENCES "time_periods"("t_periods"), FOREIGN KEY("tech") REFERENCES "technologies"("tech"), + PRIMARY KEY("regions","scenario","t_periods","tech","vintage") +); +CREATE TABLE "Output_V_NewCapacity" ( + "regions" text, + "scenario" text, + "sector" text, + "tech" text, + "vintage" integer, + "capacity" real, + PRIMARY KEY("regions","scenario","tech","vintage"), FOREIGN KEY("sector") REFERENCES "sector_labels"("sector"), + FOREIGN KEY("tech") REFERENCES "technologies"("tech"), FOREIGN KEY("vintage") REFERENCES "time_periods"("t_periods") ); +CREATE TABLE "Output_V_RetiredCapacity" ( + "regions" text, + "scenario" text, + "sector" text, + "t_periods" integer, + "tech" text, + "vintage" integer, + "capacity" real, + FOREIGN KEY("t_periods") REFERENCES "time_periods"("t_periods"), + FOREIGN KEY("sector") REFERENCES "sector_labels"("sector"), + FOREIGN KEY("vintage") REFERENCES "time_periods"("t_periods"), + FOREIGN KEY("tech") REFERENCES "technologies"("tech"), + PRIMARY KEY("regions","scenario","t_periods","tech","vintage") +); CREATE TABLE "Output_VFlow_Out" ( "regions" text, "scenario" text, @@ -358,7 +392,7 @@ CREATE TABLE "Output_CapacityByPeriodAndTech" ( ); CREATE TABLE "MyopicBaseyear" ( "year" real - "notes" text + "notes" text ); CREATE TABLE "MinGenGroupWeight" ( "regions" text, @@ -1034,7 +1068,7 @@ CREATE TABLE "MaxResource" ( CREATE TABLE "LinkedTechs" ( "primary_region" text, "primary_tech" text, - "emis_comm" text, + "emis_comm" text, "linked_tech" text, "tech_linked_notes" text, FOREIGN KEY("primary_tech") REFERENCES "technologies"("tech"), diff --git a/data_files/temoa_test_system.sqlite b/data_files/temoa_test_system.sqlite index 5a7bb560a51ca37884d79e0813a3e8ec563ed437..c83a410cdf0e3c6b15b7a989d9b39c738675e409 100644 GIT binary patch delta 2908 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 delta 4836 zcmZ`d3wTt;xjS>_%-OT&F}s9hv%7gL2|@xPWC;Nw#E=jmKte(iAP5-pSdul#Zb*U` zsx%}aV8J35?SFlsP>X`1p~iARK%lMosE<%Tv0|;S+ae-~-g~WD^wK$dxJc{Q&Bs48 z|7+%d&HRUrCsQ}>PTJueVM8{XZ9V_@|G(UOGA1Q(Z06j3BFBmByh&+hm)YOg7wj{3 ze!%5#W3F3jIkvcxgDEpO7?U}0nduv)FWC?~&n^$R%HL)lD!5Qv2Z;`Kf+#T5hKa!B z_Gfm>PWR*N5eDpTwuODko?{o-d#sq!$e>{e*Aa&(eG!K zx-bfb!VPOXI@?3FEtCnVs6E&bY6ylq`C2r|^^w-rV0%4Z5=}@(o$a;Zj~$vSRk!$`S%Q^KqJoy9ke@ z9vl-RukDPqg=!^}&auy&M1IP?w)t(tAkD<%6R9em5m$&4$WgLg_+046=kTMpVcS7l zhpod8!D>93u&?RRPM3cgpV;#GBvg2kP7iZln8rPi&3H-{#1y)B&pk%0DmvU8JskB7LJHM>dyB7su$wNHMU3Awsq75 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 diff --git a/temoa_model/pformat_results.py b/temoa_model/pformat_results.py index 81114c22..ce60b7c2 100644 --- a/temoa_model/pformat_results.py +++ b/temoa_model/pformat_results.py @@ -235,16 +235,40 @@ def collect_result_data( cgroup, clist, epsilon): # Extract optimal decision variable values related to capacity: if hasattr(options, 'file_location') and os.path.join('temoa_model', 'config_sample_myopic') not in options.file_location: - for r, t, v in m.V_Capacity: - val = value( m.V_Capacity[r, t, v] ) + for r, p, t, v in m.V_Capacity: + val = value( m.V_Capacity[r, p, t, v] ) if abs(val) < capacity_epsilon: continue - svars['V_Capacity'][r, t, v] = val + svars['V_Capacity'][r, p, t, v] = val else: - for r, t, v in m.V_Capacity: + for r, p, t, v in m.V_Capacity: + if p in m.time_optimize: + val = value( m.V_Capacity[r, p, t, v] ) + if abs(val) < capacity_epsilon: continue + svars['V_Capacity'][r, p, t, v] = val + + if hasattr(options, 'file_location') and os.path.join('temoa_model', 'config_sample_myopic') not in options.file_location: + for r, t, v in m.V_NewCapacity: + val = value( m.V_NewCapacity[r, t, v] ) + if abs(val) < capacity_epsilon: continue + svars['V_NewCapacity'][r, t, v] = val + else: + for r, t, v in m.V_NewCapacity: if v in m.time_optimize: - val = value( m.V_Capacity[r, t, v] ) + val = value( m.V_NewCapacity[r, t, v] ) + if abs(val) < capacity_epsilon: continue + svars['V_NewCapacity'][r, t, v] = val + + if hasattr(options, 'file_location') and os.path.join('temoa_model', 'config_sample_myopic') not in options.file_location: + for r, p, t, v in m.V_RetiredCapacity: + val = value( m.V_RetiredCapacity[r, p, t, v] ) + if abs(val) < capacity_epsilon: continue + svars['V_RetiredCapacity'][r, p, t, v] = val + else: + for r, p, t, v in m.V_RetiredCapacity: + if p in m.time_optimize: + val = value( m.V_RetiredCapacity[r, p, t, v] ) if abs(val) < capacity_epsilon: continue - svars['V_Capacity'][r, t, v] = val + svars['V_RetiredCapacity'][r, p, t, v] = val for r, p, t in m.V_CapacityAvailableByPeriodAndTech: val = value( m.V_CapacityAvailableByPeriodAndTech[r, p, t] ) @@ -260,7 +284,7 @@ def collect_result_data( cgroup, clist, epsilon): for r, t, v in m.CostInvest.sparse_iterkeys(): # Returns only non-zero values - icost = value( m.V_Capacity[r, t, v] ) + icost = value( m.V_NewCapacity[r, t, v] ) if abs(icost) < epsilon: continue icost *= value( m.CostInvest[r, t, v] )*( ( @@ -281,7 +305,7 @@ def collect_result_data( cgroup, clist, epsilon): for r, p, t, v in m.CostFixed.sparse_iterkeys(): - fcost = value( m.V_Capacity[r, t, v] ) + fcost = value( m.V_Capacity[r, p, t, v] ) if abs(fcost) < epsilon: continue fcost *= value( m.CostFixed[r, p, t, v] ) @@ -332,11 +356,11 @@ def collect_result_data( cgroup, clist, epsilon): # assumption 3: Unlike other output tables in which Ri-Rj and Rj-Ri entries # are allowed in the region column, for the Output_Costs table the region #to the right of the hyphen sign gets the costs. - for i in m.RegionalExchangeCapacityConstraint_rrtv.iterkeys(): + for i in m.RegionalExchangeCapacityConstraint_rrptv.iterkeys(): reg_dir1 = i[0]+"-"+i[1] reg_dir2 = i[1]+"-"+i[0] - tech = i[2] - vintage = i[3] + tech = i[3] + vintage = i[4] key = (reg_dir1, tech, vintage) try: act_dir1 = value (sum(m.V_FlowOut[reg_dir1, p, s, d, S_i, tech, vintage, S_o] @@ -429,6 +453,8 @@ def make_var_list ( variables ): "V_FlowOut" : "Output_VFlow_Out", \ "V_Curtailment" : "Output_Curtailment", \ "V_Capacity" : "Output_V_Capacity", \ + "V_NewCapacity" : "Output_V_NewCapacity", \ + "V_RetiredCapacity" : "Output_V_RetiredCapacity", \ "V_CapacityAvailableByPeriodAndTech" : "Output_CapacityByPeriodAndTech", \ "V_EmissionActivityByPeriodAndProcess" : "Output_Emissions", \ "Objective" : "Output_Objective", \ diff --git a/temoa_model/temoa_config.py b/temoa_model/temoa_config.py index b4ca2529..1d40cb07 100644 --- a/temoa_model/temoa_config.py +++ b/temoa_model/temoa_config.py @@ -128,6 +128,7 @@ def query_table (t_properties, f): ['set', 'tech_groups', '', '', 2], ['set', 'tech_annual', '', '', 0], ['set', 'tech_variable', '', '', 0], + ['set', 'tech_retirement', '', '', 0], ['set', 'groups', '', '', 0], ['param','LinkedTechs', '', '', 3], ['param','SegFrac', '', '', 2], @@ -211,6 +212,8 @@ def query_table (t_properties, f): cur.execute("DELETE FROM Output_VFlow_In WHERE scenario="+"'"+str(options.scenario)+"'") cur.execute("DELETE FROM Output_VFlow_Out WHERE scenario="+"'"+str(options.scenario)+"'") cur.execute("DELETE FROM Output_V_Capacity WHERE scenario="+"'"+str(options.scenario)+"'") + cur.execute("DELETE FROM Output_V_NewCapacity WHERE scenario="+"'"+str(options.scenario)+"'") + cur.execute("DELETE FROM Output_V_RetiredCapacity WHERE scenario="+"'"+str(options.scenario)+"'") cur.execute("DELETE FROM Output_Curtailment WHERE scenario="+"'"+str(options.scenario)+"'") cur.execute("DELETE FROM Output_Duals WHERE scenario="+"'"+str(options.scenario)+"'") cur.execute("VACUUM") diff --git a/temoa_model/temoa_initialize.py b/temoa_model/temoa_initialize.py index 750d8e05..7a4ce2c9 100644 --- a/temoa_model/temoa_initialize.py +++ b/temoa_model/temoa_initialize.py @@ -940,6 +940,16 @@ def LifetimeLoanProcessIndices ( M ): def CapacityVariableIndices ( M ): return M.activeCapacity_rtv +def RetiredCapacityVariableIndices ( M ): + return set( + (r, p, t, v) + + for r,p,t in M.processVintages.keys() + if t in M.tech_retirement + for v in M.processVintages[ r, p, t ] + if p > v + ) + def CapacityAvailableVariableIndices ( M ): return M.activeCapacityAvailable_rpt @@ -1071,7 +1081,7 @@ def BaseloadDiurnalConstraintIndices ( M ): def RegionalExchangeCapacityConstraintIndices ( M ): indices = set( - (r_e, r_i, t, v) + (r_e, r_i, p, t, v) for r_e, p, i in M.exportRegions.keys() for r_i, t, v, o in M.exportRegions[r_e, p, i] diff --git a/temoa_model/temoa_model.py b/temoa_model/temoa_model.py index 9b7e48fd..ef847bfa 100755 --- a/temoa_model/temoa_model.py +++ b/temoa_model/temoa_model.py @@ -80,6 +80,7 @@ def temoa_create_model(name="Temoa"): M.tech_groups = Set(within=M.RegionalIndices * M.groups * M.tech_all) M.tech_annual = Set(within=M.tech_all) # Define techs with constant output M.tech_variable = Set(within=M.tech_all) # Define techs for use with TechInputSplitAverage constraint, where techs have variable annual output but the user wishes to constrain them annually + M.tech_retirement = Set(within=M.tech_all) # Define techs for which economic retirement is an option # Define commodity-related sets M.commodity_demand = Set() @@ -285,8 +286,14 @@ def temoa_create_model(name="Temoa"): # Derived decision variables - M.CapacityVar_rtv = Set(dimen=3, initialize=CapacityVariableIndices) - M.V_Capacity = Var(M.CapacityVar_rtv, domain=NonNegativeReals) + M.CapacityVar_rptv = Set(dimen=4, initialize=CostFixedIndices) + M.V_Capacity = Var(M.CapacityVar_rptv, domain=NonNegativeReals) + + M.NewCapacityVar_rtv = Set(dimen=3, initialize=CapacityVariableIndices) + M.V_NewCapacity = Var(M.NewCapacityVar_rtv, domain=NonNegativeReals, initialize=0) + + M.RetiredCapacityVar_rptv = Set(dimen=4, initialize=RetiredCapacityVariableIndices) + M.V_RetiredCapacity = Var(M.RetiredCapacityVar_rptv, domain=NonNegativeReals, initialize=0) M.CapacityAvailableVar_rpt = Set( dimen=3, initialize=CapacityAvailableVariableIndices @@ -322,11 +329,11 @@ def temoa_create_model(name="Temoa"): M.CapacityAvailableVar_rpt, rule=CapacityAvailableByPeriodAndTech_Constraint ) - M.ExistingCapacityConstraint_rtv = Set( - dimen=3, initialize=lambda M: M.ExistingCapacity.sparse_iterkeys() + M.RetiredCapacityConstraint = Constraint( + M.RetiredCapacityVar_rptv, rule=RetiredCapacity_Constraint ) - M.ExistingCapacityConstraint = Constraint( - M.ExistingCapacityConstraint_rtv, rule=ExistingCapacity_Constraint + M.AdjustedCapacityConstraint = Constraint( + M.CostFixed_rptv, rule=AdjustedCapacity_Constraint ) # Declare core model constraints that ensure proper system functioning @@ -370,11 +377,11 @@ def temoa_create_model(name="Temoa"): M.BaseloadDiurnalConstraint_rpsdtv, rule=BaseloadDiurnal_Constraint ) - M.RegionalExchangeCapacityConstraint_rrtv = Set( - dimen=4, initialize=RegionalExchangeCapacityConstraintIndices + M.RegionalExchangeCapacityConstraint_rrptv = Set( + dimen=5, initialize=RegionalExchangeCapacityConstraintIndices ) M.RegionalExchangeCapacityConstraint = Constraint( - M.RegionalExchangeCapacityConstraint_rrtv, rule=RegionalExchangeCapacity_Constraint) + M.RegionalExchangeCapacityConstraint_rrptv, rule=RegionalExchangeCapacity_Constraint) # This set works for all the storage-related constraints M.StorageConstraints_rpsdtv = Set(dimen=6, initialize=StorageVariableIndices) diff --git a/temoa_model/temoa_myopic.py b/temoa_model/temoa_myopic.py index afd4767c..70ed8a99 100644 --- a/temoa_model/temoa_myopic.py +++ b/temoa_model/temoa_myopic.py @@ -223,16 +223,18 @@ def myopic_db_generator_solver ( self ): cur_org.execute(query) # --------------------------------------------------------------- - # Add the buildups from the previous period to the ExistingCapacity + # Add the buildups and retirements from the previous period to the ExistingCapacity # table. The data is stored in the Output_V_Capacity of the con_org # --------------------------------------------------------------- if i!=(N-1): df_new_ExistingCapacity = pd.read_sql_query("SELECT regions, tech, vintage, capacity FROM Output_V_Capacity \ WHERE scenario="+"'"+str(self.options.scenario)+"' AND \ - vintage < "+str(time_periods[i-(N-1)][0])+";", con_org) + t_periods <= "+str(time_periods[i-(N-1)][0])+";", con_org) df_new_ExistingCapacity.columns = ['regions','tech','vintage','exist_cap'] - df_new_ExistingCapacity.to_sql('ExistingCapacity',con, if_exists='append', index=False) + # Need to remove technologies that have been age-based retired. + + df_new_ExistingCapacity.to_sql('ExistingCapacity',con, if_exists='replace', index=False) #Create a copy of the first time period vintages for the two current vintage #to prevent infeasibility (if it is not an 'existing' vintage in the @@ -260,14 +262,15 @@ def myopic_db_generator_solver ( self ): iterval+=1 if iterval>10: break - # Discard the results associated with time_periods[i-N][0] P time_periods[i-N][0] period in rolling horizon fashion. Otherwise, UNIQUE CONSTRAINT error is thrown. # Re Output_Costs, a delete is not needed because in pformat_results.py, future periods costs get added to what is already in the table cur_org.execute("DELETE FROM Output_CapacityByPeriodAndTech WHERE scenario="+"'"+str(self.options.scenario)+"' AND t_periods>"+str(time_periods[i-N][0])) cur_org.execute("DELETE FROM Output_Emissions WHERE scenario="+"'"+str(self.options.scenario)+"' AND t_periods>"+str(time_periods[i-N][0])) cur_org.execute("DELETE FROM Output_VFlow_In WHERE scenario="+"'"+str(self.options.scenario)+"' AND t_periods>"+str(time_periods[i-N][0])) cur_org.execute("DELETE FROM Output_VFlow_Out WHERE scenario="+"'"+str(self.options.scenario)+"' AND t_periods>"+str(time_periods[i-N][0])) - cur_org.execute("DELETE FROM Output_V_Capacity WHERE scenario="+"'"+str(self.options.scenario)+"' AND vintage>"+str(time_periods[i-N][0])) + cur_org.execute("DELETE FROM Output_V_Capacity WHERE scenario="+"'"+str(self.options.scenario)+"' AND t_periods>"+str(time_periods[i-N][0])) + cur_org.execute("DELETE FROM Output_V_NewCapacity WHERE scenario="+"'"+str(self.options.scenario)+"' AND vintage>"+str(time_periods[i-N][0])) + cur_org.execute("DELETE FROM Output_V_RetiredCapacity WHERE scenario="+"'"+str(self.options.scenario)+"' AND t_periods>"+str(time_periods[i-N][0])) cur_org.execute("DELETE FROM Output_Curtailment WHERE scenario="+"'"+str(self.options.scenario)+"' AND t_periods>"+str(time_periods[i-N][0])) con_org.commit() diff --git a/temoa_model/temoa_rules.py b/temoa_model/temoa_rules.py index 089b2e20..47ceb328 100644 --- a/temoa_model/temoa_rules.py +++ b/temoa_model/temoa_rules.py @@ -30,6 +30,26 @@ # and constraints below. # --------------------------------------------------------------- +def AdjustedCapacity_Constraint(M, r, p, t, v): + r""" +This constraint updates the capacity of a process by taking into account retirements. +For a given :code:`(r,p,t,v)` index, this constraint sets the capacity equal to +the amount installed in period :code:`v` and subtracts from it any and all retirements +that occured up until the period in question, :code:`p`. +""" + if t not in M.tech_retirement: + if v in M.time_exist: + return M.V_Capacity[r, p, t, v] == M.ExistingCapacity[r, t, v] + else: + return M.V_Capacity[r, p, t, v] == M.V_NewCapacity[r, t, v] + + else: + retired_cap = sum(M.V_RetiredCapacity[r, S_p, t, v] for S_p in M.time_optimize if S_p <= p and S_p > v) + if v in M.time_exist: + return M.V_Capacity[r, p, t, v] == M.ExistingCapacity[r, t, v] - retired_cap + else: + return M.V_Capacity[r, p, t, v] == M.V_NewCapacity[r, t, v] - retired_cap + def Capacity_Constraint(M, r, p, s, d, t, v): r""" This constraint ensures that the capacity of a given process is sufficient @@ -81,7 +101,7 @@ def Capacity_Constraint(M, r, p, s, d, t, v): return value(M.CapacityFactorProcess[r, s, d, t, v]) \ * value(M.CapacityToActivity[r, t]) * value(M.SegFrac[s, d]) \ * value(M.ProcessLifeFrac[r, p, t, v]) \ - * M.V_Capacity[r, t, v] == useful_activity + sum( \ + * M.V_Capacity[r, p, t, v] == useful_activity + sum( \ M.V_Curtailment[r, p, s, d, S_i, t, v, S_o] \ for S_i in M.processInputs[r, p, t, v] \ for S_o in M.ProcessOutputsByInput[r, p, t, v, S_i]) @@ -90,7 +110,7 @@ def Capacity_Constraint(M, r, p, s, d, t, v): * value(M.CapacityToActivity[r, t]) \ * value(M.SegFrac[s, d]) \ * value(M.ProcessLifeFrac[r, p, t, v]) \ - * M.V_Capacity[r, t, v] >= useful_activity + * M.V_Capacity[r, p, t, v] >= useful_activity def CapacityAnnual_Constraint(M, r, p, t, v): @@ -130,7 +150,7 @@ def CapacityAnnual_Constraint(M, r, p, t, v): return CF \ * value(M.CapacityToActivity[r, t]) \ * value(M.ProcessLifeFrac[r, p, t, v]) \ - * M.V_Capacity[r, t, v] >= activity_rptv + * M.V_Capacity[r, p, t, v] >= activity_rptv def ActivityByTech_Constraint(M, t): @@ -194,36 +214,40 @@ def CapacityAvailableByPeriodAndTech_Constraint(M, r, p, t): .. math:: :label: CapacityAvailable - \textbf{CAPAVL}_{r, p, t} = \sum_{V} {PLF}_{r, p, t, v} \cdot \textbf{CAP}_{r, t, v} + \textbf{CAPAVL}_{r, p, t} = \sum_{v, p_i \leq p} {PLF}_{r, p, t, v} \cdot \left ( \textbf{CAP}_{r, t, v} - \textbf{CAPRET}_{r, p_i, t, v} \right ) \\ \forall p \in \text{P}^o, r \in R, t \in T """ cap_avail = sum( - value(M.ProcessLifeFrac[r, p, t, S_v]) * M.V_Capacity[r, t, S_v] + value(M.ProcessLifeFrac[r, p, t, S_v]) * M.V_Capacity[r, p, t, S_v] for S_v in M.processVintages[r, p, t] ) expr = M.V_CapacityAvailableByPeriodAndTech[r, p, t] == cap_avail return expr -def ExistingCapacity_Constraint(M, r, t, v): +def RetiredCapacity_Constraint(M, r, p, t, v): r""" -Temoa treats existing capacity installed prior to the beginning of the model's -optimization horizon as regular processes that require the same parameter -specification as do new vintage technologies, except for the :code:`CostInvest` -parameter. This constraint sets the capacity of processes for model periods -that exist prior to the optimization horizon to user-specified values. +Temoa allows for the economic retirement of technologies presented in the +:code:`tech_retirement` set. This constraint sets the upper limit of retired +capacity to the total installed capacity. +In the equation below, we set the upper bound of the retired capacity to the +previous period's total installed capacity (CAPAVL) .. math:: - :label: ExistingCapacity - - \textbf{CAP}_{r, t, v} = ECAP_{r, t, v} + :label: RetiredCapacity - \forall \{r, t, v\} \in \Theta_{\text{ExistingCapacity}} + \textbf{CAPRET}_{r, p, t, v} \leq \sum_{V} {PLF}_{r, p, t, v} \cdot \textbf{CAP}_{r, t, v} + \\ + \forall \{r, p, t, v\} \in \Theta_{\text{RetiredCapacity}} """ - expr = M.V_Capacity[r, t, v] == M.ExistingCapacity[r, t, v] + if p == M.time_optimize.first(): + cap_avail = M.ExistingCapacity[r, t, v] + else: + cap_avail = M.V_Capacity[r, M.time_optimize.prev(p), t, v] + expr = M.V_RetiredCapacity[r, p, t, v] <= cap_avail return expr # --------------------------------------------------------------- @@ -320,7 +344,7 @@ def PeriodCost_rule(M, p): loan_costs = sum( - M.V_Capacity[r, S_t, S_v] + M.V_NewCapacity[r, S_t, S_v] * ( value(M.CostInvest[r, S_t, S_v]) * value(M.LoanAnnualize[r, S_t, S_v]) @@ -343,7 +367,7 @@ def PeriodCost_rule(M, p): ) fixed_costs = sum( - M.V_Capacity[r, S_t, S_v] + M.V_Capacity[r, p, S_t, S_v] * ( value(M.CostFixed[r, p, S_t, S_v]) * ( @@ -825,7 +849,7 @@ def BaseloadDiurnal_Constraint(M, r, p, s, d, t, v): return expr -def RegionalExchangeCapacity_Constraint(M, r_e, r_i, t, v): +def RegionalExchangeCapacity_Constraint(M, r_e, r_i, p, t, v): r""" This constraint ensures that the process (t,v) connecting regions @@ -842,7 +866,7 @@ def RegionalExchangeCapacity_Constraint(M, r_e, r_i, t, v): \forall \{r_e, r_i, t, v\} \in \Theta_{\text{RegionalExchangeCapacity}} """ - expr = M.V_Capacity[r_e+"-"+r_i, t, v] == M.V_Capacity[r_i+"-"+r_e, t, v] + expr = M.V_Capacity[r_e+"-"+r_i, p, t, v] == M.V_Capacity[r_i+"-"+r_e, p, t, v] return expr @@ -982,7 +1006,7 @@ def StorageEnergyUpperBound_Constraint(M, r, p, s, d, t, v): """ energy_capacity = ( - M.V_Capacity[r, t, v] + M.V_Capacity[r, p, t, v] * M.CapacityToActivity[r, t] * (M.StorageDuration[r, t] / 8760) * M.SegFracPerSeason[s] * 365 @@ -1019,7 +1043,7 @@ def StorageChargeRate_Constraint(M, r, p, s, d, t, v): # Maximum energy charge in each time slice max_charge = ( - M.V_Capacity[r, t, v] + M.V_Capacity[r, p, t, v] * M.CapacityToActivity[r, t] * M.SegFrac[s, d] * value(M.ProcessLifeFrac[r, p, t, v]) @@ -1056,7 +1080,7 @@ def StorageDischargeRate_Constraint(M, r, p, s, d, t, v): # Maximum energy discharge in each time slice max_discharge = ( - M.V_Capacity[r, t, v] + M.V_Capacity[r, p, t, v] * M.CapacityToActivity[r, t] * M.SegFrac[s, d] * value(M.ProcessLifeFrac[r, p, t, v]) @@ -1101,7 +1125,7 @@ def StorageThroughput_Constraint(M, r, p, s, d, t, v): throughput = charge + discharge max_throughput = ( - M.V_Capacity[r, t, v] + M.V_Capacity[r, p, t, v] * M.CapacityToActivity[r, t] * M.SegFrac[s, d] * value(M.ProcessLifeFrac[r, p, t, v]) @@ -1138,11 +1162,12 @@ def StorageInit_Constraint( M, r, t, v ): s = M.time_season.first() energy_capacity = ( - M.V_Capacity[r, t, v] + M.V_Capacity[r, p, t, v] * M.CapacityToActivity[r, t] * (M.StorageDuration[r, t] / 8760) * sum(M.SegFrac[s,S_d] for S_d in M.time_of_day) * 365 * value(M.ProcessLifeFrac[r, v, t, v]) + for p in M.time_optimize if p >= v ) expr = M.V_StorageInit[r, t, v] == energy_capacity * M.StorageInitFrac[r, t, v] @@ -1215,7 +1240,7 @@ def RampUpDay_Constraint(M, r, p, s, d, t, v): activity_sd / value(M.SegFrac[s, d]) - activity_sd_prev / value(M.SegFrac[s, d_prev]) ) / value(M.CapacityToActivity[r,t]) - expr_right = M.V_Capacity[r, t, v] * value(M.RampUp[r, t]) + expr_right = M.V_Capacity[r, p, t, v] * value(M.RampUp[r, t]) expr = expr_left <= expr_right else: return Constraint.Skip @@ -1266,7 +1291,7 @@ def RampDownDay_Constraint(M, r, p, s, d, t, v): activity_sd / value(M.SegFrac[s, d]) - activity_sd_prev / value(M.SegFrac[s, d_prev]) ) / value(M.CapacityToActivity[r,t]) - expr_right = -(M.V_Capacity[r, t, v] * value(M.RampDown[r, t])) + expr_right = -(M.V_Capacity[r, p, t, v] * value(M.RampDown[r, t])) expr = expr_left >= expr_right else: return Constraint.Skip @@ -1320,7 +1345,7 @@ def RampUpSeason_Constraint(M, r, p, s, t, v): activity_sd_first / M.SegFrac[s, d_first] - activity_s_prev_d_last / M.SegFrac[s_prev, d_last] ) / value(M.CapacityToActivity[r,t]) - expr_right = M.V_Capacity[r, t, v] * value(M.RampUp[r, t]) + expr_right = M.V_Capacity[r, p, t, v] * value(M.RampUp[r, t]) expr = expr_left <= expr_right else: return Constraint.Skip @@ -1375,7 +1400,7 @@ def RampDownSeason_Constraint(M, r, p, s, t, v): activity_sd_first / value(M.SegFrac[s, d_first]) - activity_s_prev_d_last / value(M.SegFrac[s_prev, d_last]) ) / value(M.CapacityToActivity[r,t]) - expr_right = -(M.V_Capacity[r, t, v] * value(M.RampDown[r, t])) + expr_right = -(M.V_Capacity[r, p, t, v] * value(M.RampDown[r, t])) expr = expr_left >= expr_right else: return Constraint.Skip @@ -1489,7 +1514,7 @@ def ReserveMargin_Constraint(M, r, p, s, d): cap_avail = sum( value(M.CapacityCredit[r, p, t, v]) * M.ProcessLifeFrac[r, p, t, v] - * M.V_Capacity[r, t, v] + * M.V_Capacity[r, p, t, v] * value(M.CapacityToActivity[r, t]) * value(M.SegFrac[s, d]) for t in M.tech_reserve @@ -1521,7 +1546,7 @@ def ReserveMargin_Constraint(M, r, p, s, d): cap_avail += sum( value(M.CapacityCredit[r1r2, p, t, v]) * M.ProcessLifeFrac[r1r2, p, t, v] - * M.V_Capacity[r1r2, t, v] + * M.V_Capacity[r1r2, p, t, v] * value(M.CapacityToActivity[r1r2, t]) * value(M.SegFrac[s, d]) for t in M.tech_reserve @@ -1939,7 +1964,7 @@ def MaxNewCapacity_Constraint(M, r, p, t): \textbf{CAP}_{r, t, p} \le MAX_{r, p, t} """ max_cap = value(M.MaxNewCapacity[r, p, t]) - expr = M.V_Capacity[r, t, p] <= max_cap + expr = M.V_NewCapacity[r, t, p] <= max_cap return expr def MaxCapacity_Constraint(M, r, p, t): @@ -2024,7 +2049,7 @@ def MinNewCapacity_Constraint(M, r, p, t): \textbf{CAP}_{r, t, p} \ge MIN_{r, p, t} """ min_cap = value(M.MinNewCapacity[r, p, t]) - expr = M.V_Capacity[r, t, p] >= min_cap + expr = M.V_NewCapacity[r, t, p] >= min_cap return expr @@ -2066,7 +2091,7 @@ def MinNewCapacityGroup_Constraint(M, r, p, g): """ min_new_cap = value(M.MinNewCapacityGroup[r, p, g]) agg_new_cap = sum( - M.V_Capacity[r, t, p] + M.V_NewCapacity[r, t, p] for _r, _g, t in M.tech_groups if _r == r and _g == g and (r, p, t) in M.V_CapacityAvailableByPeriodAndTech.keys() ) expr = agg_new_cap >= min_new_cap @@ -2079,7 +2104,7 @@ def MaxNewCapacityGroup_Constraint(M, r, p, g): """ max_new_cap = value(M.MaxNewCapacityGroup[r, p, g]) agg_new_cap = sum( - M.V_Capacity[r, t, p] + M.V_NewCapacity[r, t, p] for _r, _g, t in M.tech_groups if _r == r and _g == g and (r, p, t) in M.V_CapacityAvailableByPeriodAndTech.keys() ) expr = max_new_cap >= agg_new_cap @@ -2257,11 +2282,11 @@ def MinNewCapacityShare_Constraint(M, r, p, t, g): that no less than 10% of new LDV purchases in a given year must be of a certain type. """ - capacity_t = M.V_Capacity[r, t, p] + capacity_t = M.V_NewCapacity[r, t, p] capacity_group = sum( - M.V_Capacity[r, S_t, p] + M.V_NewCapacity[r, S_t, p] for (S_r, S_g, S_t) in M.tech_groups.keys() - if S_r == r and S_g == g and (r, S_t, p) in M.V_Capacity.keys() + if S_r == r and S_g == g and (r, S_t, p) in M.V_NewCapacity.keys() ) min_cap_share = value(M.MinNewCapacityShare[r, p, t, g]) @@ -2278,11 +2303,11 @@ def MaxNewCapacityShare_Constraint(M, r, p, t, g): that no more than 10% of LDV purchases in a given year must be of a certain type. """ - capacity_t = M.V_Capacity[r, t, p] + capacity_t = M.V_NewCapacity[r, t, p] capacity_group = sum( - M.V_Capacity[r, S_t, p] + M.V_NewCapacity[r, S_t, p] for (S_r, S_g, S_t) in M.tech_groups.keys() - if S_r == r and S_g == g and (r, S_t, p) in M.V_Capacity.keys() + if S_r == r and S_g == g and (r, S_t, p) in M.V_NewCapacity.keys() ) max_cap_share = value(M.MaxNewCapacityShare[r, p, t, g])