Merge branch 'nomopyomo'
This commit is contained in:
commit
105aeba215
@ -219,7 +219,7 @@ rule solve_network:
|
||||
memory="logs/" + config['run'] + "/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_memory.log"
|
||||
benchmark: "benchmarks/solve_network/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}"
|
||||
threads: 4
|
||||
resources: mem=120000 #memory in MB; 40 GB enough for 45+B+I; 100 GB based on RESI usage for 128
|
||||
resources: mem=50000 #memory in MB; 40 GB enough for 45+B+I; 100 GB based on RESI usage for 128
|
||||
# group: "solve" # with group, threads is ignored https://bitbucket.org/snakemake/snakemake/issues/971/group-job-description-does-not-contain
|
||||
script: "scripts/solve_network.py"
|
||||
|
||||
|
@ -2,7 +2,7 @@ logging_level: INFO
|
||||
|
||||
results_dir: 'results/'
|
||||
summary_dir: results
|
||||
run: '191108-h2_pipeline_network'
|
||||
run: '191212-ccs'
|
||||
|
||||
scenario:
|
||||
sectors: [E] # ,E+EV,E+BEV,E+BEV+V2G] # [ E+EV, E+BEV, E+BEV+V2G ]
|
||||
@ -10,7 +10,7 @@ scenario:
|
||||
lv: [1.0]#, 1.125, 1.25, 1.5, 2.0]# or opt
|
||||
clusters: [50] #[90, 128, 181] #[45, 64, 90, 128, 181, 256] #, 362] # (2**np.r_[5.5:9:.5]).astype(int) minimum is 37
|
||||
opts: [''] #for pypsa-eur
|
||||
sector_opts: [Co2L0-3H-T-H-B-I,Co2L0-5H-T-H-B-I]#,Co2L0p1-3H-T-H-B-I,Co2L0p25-3H-T-H-B-I,Co2L0p5-3H-T-H-B-I]#[Co2L0-3H-T-H-B-I-onwind0-solar3,Co2L0-3H-T-H-B-I-onwind0p125-solar3,Co2L0-3H-T-H-B-I-onwind0p25-solar3,Co2L0-3H-T-H-B-I-onwind0p50-solar3,Co2L0-3H-T-H-B-I-solar3]#,Co2L0-3H-T-H-B-I-onwind0p25-solar3]#,Co2L0p05-3H-T-H-B-I,Co2L0p10-3H-T-H-B-I,Co2L0p20-3H-T-H-B-I,Co2L0p30-3H-T-H-B-I,Co2L0p50-3H-T-H-B-I]#[Co2L-3H-T-H,Co2L0p10-3H-T-H,Co2L0-3H-T-H,Co2L0p20-3H-T-H] #Co2L-3H-T-H,Co2L0p10-3H-T-H,Co2L0p20-3H-T-HCo2L-3H-T-H,Co2L0p10-3H-T-H,Co2L0p30-3H-T-H,Co2L0p50-3H-T-H] #Co2L-3H,Co2L-3H-T,, LC-FL, LC-T, Ep-T, Co2L-T]
|
||||
sector_opts: [Co2L0-3H-T-H-B-I,Co2L0p2-3H-T-H-B-I,Co2L0p5-3H-T-H-B-I]#,Co2L0p1-3H-T-H-B-I,Co2L0p25-3H-T-H-B-I,Co2L0p5-3H-T-H-B-I]#[Co2L0-3H-T-H-B-I-onwind0-solar3,Co2L0-3H-T-H-B-I-onwind0p125-solar3,Co2L0-3H-T-H-B-I-onwind0p25-solar3,Co2L0-3H-T-H-B-I-onwind0p50-solar3,Co2L0-3H-T-H-B-I-solar3]#,Co2L0-3H-T-H-B-I-onwind0p25-solar3]#,Co2L0p05-3H-T-H-B-I,Co2L0p10-3H-T-H-B-I,Co2L0p20-3H-T-H-B-I,Co2L0p30-3H-T-H-B-I,Co2L0p50-3H-T-H-B-I]#[Co2L-3H-T-H,Co2L0p10-3H-T-H,Co2L0-3H-T-H,Co2L0p20-3H-T-H] #Co2L-3H-T-H,Co2L0p10-3H-T-H,Co2L0p20-3H-T-HCo2L-3H-T-H,Co2L0p10-3H-T-H,Co2L0p30-3H-T-H,Co2L0p50-3H-T-H] #Co2L-3H,Co2L-3H-T,, LC-FL, LC-T, Ep-T, Co2L-T]
|
||||
# Co2L will give default (5%); Co2L0p25 will give 25% CO2 emissions; Co2Lm0p05 will give 5% negative emissions
|
||||
|
||||
|
||||
@ -73,11 +73,6 @@ sector:
|
||||
'tes_tau' : 3.
|
||||
'boilers' : True
|
||||
'chp' : True
|
||||
'chp_parameters':
|
||||
'eta_elec' : 0.468 #electrical efficiency with no heat output
|
||||
'c_v' : 0.15 #loss of fuel for each addition of heat
|
||||
'c_m' : 0.75 #backpressure ratio
|
||||
'p_nom_ratio' : 1. #ratio of max heat output to max electrical output
|
||||
'solar_thermal' : True
|
||||
'solar_cf_correction': 0.788457 # = >>> 1/1.2683
|
||||
'marginal_cost_storage' : 0. #1e-4
|
||||
|
@ -73,15 +73,15 @@ CCGT,2030,efficiency,0.5,per unit,DIW DataDoc http://hdl.handle.net/10419/80348
|
||||
biomass,2030,efficiency,0.468,per unit,DIW DataDoc http://hdl.handle.net/10419/80348
|
||||
geothermal,2030,efficiency,0.239,per unit,DIW DataDoc http://hdl.handle.net/10419/80348
|
||||
nuclear,2030,efficiency,0.337,per unit,DIW DataDoc http://hdl.handle.net/10419/80348
|
||||
gas,2030,CO2 intensity,0.187,tCO2/MWth,https://www.eia.gov/environment/emissions/co2_vol_mass.php
|
||||
gas,2030,CO2 intensity,0.187,tCO2/MWhth,https://www.eia.gov/environment/emissions/co2_vol_mass.php
|
||||
coal,2030,efficiency,0.464,per unit,DIW DataDoc http://hdl.handle.net/10419/80348 PC (Advanced/SuperC)
|
||||
lignite,2030,efficiency,0.447,per unit,DIW DataDoc http://hdl.handle.net/10419/80348
|
||||
oil,2030,efficiency,0.393,per unit,DIW DataDoc http://hdl.handle.net/10419/80348 CT
|
||||
coal,2030,CO2 intensity,0.354,tCO2/MWth,https://www.eia.gov/environment/emissions/co2_vol_mass.php
|
||||
lignite,2030,CO2 intensity,0.4,tCO2/MWth,German sources
|
||||
oil,2030,CO2 intensity,0.248,tCO2/MWth,https://www.eia.gov/environment/emissions/co2_vol_mass.php
|
||||
geothermal,2030,CO2 intensity,0.026,tCO2/MWth,https://www.eia.gov/environment/emissions/co2_vol_mass.php
|
||||
solid biomass,2030,CO2 intensity,0.3,tCO2/MWth,TODO
|
||||
coal,2030,CO2 intensity,0.354,tCO2/MWhth,https://www.eia.gov/environment/emissions/co2_vol_mass.php
|
||||
lignite,2030,CO2 intensity,0.4,tCO2/MWhth,German sources
|
||||
oil,2030,CO2 intensity,0.248,tCO2/MWhth,https://www.eia.gov/environment/emissions/co2_vol_mass.php
|
||||
geothermal,2030,CO2 intensity,0.026,tCO2/MWhth,https://www.eia.gov/environment/emissions/co2_vol_mass.php
|
||||
solid biomass,2030,CO2 intensity,0.3,tCO2/MWhth,TODO
|
||||
electrolysis,2030,investment,350,EUR/kWel,Palzer Thesis
|
||||
electrolysis,2030,FOM,4,%/year,NREL http://www.nrel.gov/docs/fy09osti/45873.pdf; budischak2013
|
||||
electrolysis,2030,lifetime,18,years,NREL http://www.nrel.gov/docs/fy09osti/45873.pdf; budischak2013
|
||||
@ -109,6 +109,14 @@ SMR,2030,investment,540.56,EUR/kWCH4,https://www.gov.uk/government/publications/
|
||||
SMR,2030,lifetime,25,years,TODO
|
||||
SMR,2030,FOM,5.4,%/year,https://www.gov.uk/government/publications/hydrogen-supply-chain-evidence-base; slide 42 assumption for 2030
|
||||
SMR,2030,efficiency,0.74,per unit,https://www.gov.uk/government/publications/hydrogen-supply-chain-evidence-base; slide 42 assumption for 2030
|
||||
SMR CCS,2030,investment,1032,EUR/kWCH4,https://www.gov.uk/government/publications/hydrogen-supply-chain-evidence-base; slide 42 assumption for 2030; GBP 466 exchange 1.16; CCS costed at 300 EUR/tCO2/a
|
||||
SMR CCS,2030,lifetime,25,years,TODO
|
||||
SMR CCS,2030,FOM,5.4,%/year,https://www.gov.uk/government/publications/hydrogen-supply-chain-evidence-base; slide 42 assumption for 2030
|
||||
SMR CCS,2030,efficiency,0.67,per unit,https://www.gov.uk/government/publications/hydrogen-supply-chain-evidence-base; slide 42 assumption for 2030; CCS uses 10% of gas
|
||||
industry CCS,2030,investment,300,EUR/tCO2/a,Saygin et al 2013 https://doi.org/10.1016/j.ijggc.2013.05.032
|
||||
industry CCS,2030,FOM,2,%/year,Saygin et al 2013 https://doi.org/10.1016/j.ijggc.2013.05.032
|
||||
industry CCS,2030,lifetime,25,years,Saygin et al 2013 https://doi.org/10.1016/j.ijggc.2013.05.032
|
||||
industry CCS,2030,efficiency,0.9,per unit,Saygin et al 2013 https://doi.org/10.1016/j.ijggc.2013.05.032
|
||||
Fischer-Tropsch,2030,investment,677.6,EUR/kWH2,Fasihi doi:10.3390/su9020306 (60 kEUR/bpd = 847 EUR/kWL (1b = 1.7 MWh) 847*0.8 = 677.6)
|
||||
Fischer-Tropsch,2030,lifetime,30,years,doi:10.3390/su9020306
|
||||
Fischer-Tropsch,2030,FOM,3,%/year,doi:10.3390/su9020306
|
||||
@ -118,7 +126,7 @@ DAC,2030,lifetime,30,years,Fasihi
|
||||
DAC,2030,FOM,4,%/year,Fasihi
|
||||
battery inverter,2030,investment,411,USD/kWel,budischak2013
|
||||
battery inverter,2030,lifetime,20,years,budischak2013
|
||||
battery inverter,2030,efficiency,0.81,per unit,budischak2013; Lund and Kempton (2008) http://dx.doi.org/10.1016/j.enpol.2008.06.007
|
||||
battery inverter,2030,efficiency,0.81,per unit,budischak2013; Lund and Kempton (2008) https://doi.org/10.1016/j.enpol.2008.06.007
|
||||
battery inverter,2030,FOM,3,%/year,budischak2013
|
||||
battery storage,2030,investment,192,USD/kWh,budischak2013
|
||||
battery storage,2030,lifetime,15,years,budischak2013
|
||||
@ -175,9 +183,38 @@ decentral CHP,2030,lifetime,25,years,HP
|
||||
decentral CHP,2030,investment,1400,EUR/kWel,HP
|
||||
decentral CHP,2030,FOM,3,%/year,HP
|
||||
decentral CHP,2030,discount rate,0.04,per unit,Palzer thesis
|
||||
central CHP,2030,lifetime,25,years,HP
|
||||
central CHP,2030,investment,650,EUR/kWel,HP
|
||||
central CHP,2030,FOM,3,%/year,HP
|
||||
central gas CHP,2030,lifetime,30,years,DEA
|
||||
central gas CHP,2030,investment,1300,EUR/kWel,DEA
|
||||
central gas CHP,2030,FOM,3,%/year,DEA
|
||||
central gas CHP,2030,efficiency,0.45,per unit,DEA (condensation mode)
|
||||
central gas CHP,2030,c_b,0.7,per unit,DEA (backpressure ratio)
|
||||
central gas CHP,2030,c_v,0.17,per unit,DEA (loss of fuel for additional heat)
|
||||
central gas CHP,2030,p_nom_ratio,1.,per unit,
|
||||
central gas CHP,2030,VOM,0.82,EUR/MWh,DEA
|
||||
central gas CHP CCS,2030,lifetime,30,years,DEA
|
||||
central gas CHP CCS,2030,investment,1900,EUR/kWel,DEA + DIW extra for CCS on gas plant
|
||||
central gas CHP CCS,2030,FOM,3,%/year,DEA
|
||||
central gas CHP CCS,2030,efficiency,0.405,per unit,DEA (condensation mode + efficiency loss due to capture)
|
||||
central gas CHP CCS,2030,c_b,0.7,per unit,DEA (backpressure ratio)
|
||||
central gas CHP CCS,2030,c_v,0.17,per unit,DEA (loss of fuel for additional heat)
|
||||
central gas CHP CCS,2030,p_nom_ratio,1.,per unit,
|
||||
central gas CHP CCS,2030,VOM,0.82,EUR/MWh,DEA
|
||||
central solid biomass CHP,2030,lifetime,40,years,DEA for wood pellets CHP
|
||||
central solid biomass CHP,2030,investment,1990,EUR/kWel,DEA for wood pellets CHP
|
||||
central solid biomass CHP,2030,FOM,3,%/year,DEA for wood pellets CHP
|
||||
central solid biomass CHP,2030,efficiency,0.52,per unit,DEA for wood pellets CHP (condensation mode)
|
||||
central solid biomass CHP,2030,c_b,1.01,per unit,DEA for wood pellets CHP (backpressure ratio)
|
||||
central solid biomass CHP,2030,c_v,0.15,per unit,DEA for wood pellets CHP (loss of fuel for additional heat)
|
||||
central solid biomass CHP,2030,p_nom_ratio,1.,per unit,
|
||||
central solid biomass CHP,2030,VOM,2.2,EUR/MWh,DEA for wood pellets CHP
|
||||
central solid biomass CHP CCS,2030,lifetime,40,years,DEA for wood pellets CHP
|
||||
central solid biomass CHP CCS,2030,investment,2590,EUR/kWel,DEA for wood pellets CHP + DIW extra for CCS on gas plant
|
||||
central solid biomass CHP CCS,2030,FOM,3,%/year,DEA for wood pellets CHP
|
||||
central solid biomass CHP CCS,2030,efficiency,0.468,per unit,DEA for wood pellets CHP (condensation mode + efficiency loss due to capture)
|
||||
central solid biomass CHP CCS,2030,c_b,1.01,per unit,DEA for wood pellets CHP (backpressure ratio)
|
||||
central solid biomass CHP CCS,2030,c_v,0.15,per unit,DEA for wood pellets CHP (loss of fuel for additional heat)
|
||||
central solid biomass CHP CCS,2030,p_nom_ratio,1.,per unit,
|
||||
central solid biomass CHP CCS,2030,VOM,2.2,EUR/MWh,DEA for wood pellets CHP
|
||||
micro CHP,2030,lifetime,20,years,DEA for PEMFC with methane (for unit consuming 2kW CH4)
|
||||
micro CHP,2030,investment,4500,EUR/kWCH4,DEA for PEMFC with methane (for unit consuming 2kW CH4)
|
||||
micro CHP,2030,FOM,6,%/year,DEA for PEMFC with methane (for unit consuming 2kW CH4)
|
||||
|
|
@ -36,6 +36,8 @@ override_component_attrs["Link"].loc["efficiency2"] = ["static or series","per u
|
||||
override_component_attrs["Link"].loc["efficiency3"] = ["static or series","per unit",1.,"3rd bus efficiency","Input (optional)"]
|
||||
override_component_attrs["Link"].loc["p2"] = ["series","MW",0.,"2nd bus output","Output"]
|
||||
override_component_attrs["Link"].loc["p3"] = ["series","MW",0.,"3rd bus output","Output"]
|
||||
override_component_attrs["StorageUnit"].loc["p_dispatch"] = ["series","MW",0.,"Storage discharging.","Output"]
|
||||
override_component_attrs["StorageUnit"].loc["p_store"] = ["series","MW",0.,"Storage charging.","Output"]
|
||||
|
||||
|
||||
|
||||
@ -77,7 +79,7 @@ def calculate_nodal_cfs(n,label,nodal_cfs):
|
||||
cf_c = p_c/capacities_c
|
||||
|
||||
index = pd.MultiIndex.from_tuples([(c.list_name,) + t for t in cf_c.index.to_list()])
|
||||
nodal_cfs = nodal_cfs.reindex(nodal_cfs.index|index)
|
||||
nodal_cfs = nodal_cfs.reindex(index|nodal_cfs.index)
|
||||
nodal_cfs.loc[index,label] = cf_c.values
|
||||
|
||||
return nodal_cfs
|
||||
@ -102,7 +104,7 @@ def calculate_cfs(n,label,cfs):
|
||||
|
||||
cf_c = p_c/capacities_c
|
||||
|
||||
cfs = cfs.reindex(cfs.index|pd.MultiIndex.from_product([[c.list_name],cf_c.index]))
|
||||
cfs = cfs.reindex(pd.MultiIndex.from_product([[c.list_name],cf_c.index])|cfs.index)
|
||||
|
||||
cfs.loc[idx[c.list_name,list(cf_c.index)],label] = cf_c.values
|
||||
|
||||
@ -116,7 +118,7 @@ def calculate_nodal_costs(n,label,nodal_costs):
|
||||
for c in n.iterate_components(n.branch_components|n.controllable_one_port_components^{"Load"}):
|
||||
capital_costs = (c.df.capital_cost*c.df[opt_name.get(c.name,"p") + "_nom_opt"]).groupby((c.df.location,c.df.carrier)).sum()
|
||||
index = pd.MultiIndex.from_tuples([(c.list_name,"capital") + t for t in capital_costs.index.to_list()])
|
||||
nodal_costs = nodal_costs.reindex(nodal_costs.index|index)
|
||||
nodal_costs = nodal_costs.reindex(index|nodal_costs.index)
|
||||
nodal_costs.loc[index,label] = capital_costs.values
|
||||
|
||||
if c.name == "Link":
|
||||
@ -137,7 +139,7 @@ def calculate_nodal_costs(n,label,nodal_costs):
|
||||
|
||||
marginal_costs = (p*c.df.marginal_cost).groupby((c.df.location,c.df.carrier)).sum()
|
||||
index = pd.MultiIndex.from_tuples([(c.list_name,"marginal") + t for t in marginal_costs.index.to_list()])
|
||||
nodal_costs = nodal_costs.reindex(nodal_costs.index|index)
|
||||
nodal_costs = nodal_costs.reindex(index|nodal_costs.index)
|
||||
nodal_costs.loc[index,label] = marginal_costs.values
|
||||
|
||||
return nodal_costs
|
||||
@ -149,7 +151,7 @@ def calculate_costs(n,label,costs):
|
||||
capital_costs = c.df.capital_cost*c.df[opt_name.get(c.name,"p") + "_nom_opt"]
|
||||
capital_costs_grouped = capital_costs.groupby(c.df.carrier).sum()
|
||||
|
||||
costs = costs.reindex(costs.index|pd.MultiIndex.from_product([[c.list_name],["capital"],capital_costs_grouped.index]))
|
||||
costs = costs.reindex(pd.MultiIndex.from_product([[c.list_name],["capital"],capital_costs_grouped.index])|costs.index)
|
||||
|
||||
costs.loc[idx[c.list_name,"capital",list(capital_costs_grouped.index)],label] = capital_costs_grouped.values
|
||||
|
||||
@ -173,7 +175,7 @@ def calculate_costs(n,label,costs):
|
||||
|
||||
marginal_costs_grouped = marginal_costs.groupby(c.df.carrier).sum()
|
||||
|
||||
costs = costs.reindex(costs.index|pd.MultiIndex.from_product([[c.list_name],["marginal"],marginal_costs_grouped.index]))
|
||||
costs = costs.reindex(pd.MultiIndex.from_product([[c.list_name],["marginal"],marginal_costs_grouped.index])|costs.index)
|
||||
|
||||
costs.loc[idx[c.list_name,"marginal",list(marginal_costs_grouped.index)],label] = marginal_costs_grouped.values
|
||||
|
||||
@ -198,7 +200,7 @@ def calculate_nodal_capacities(n,label,nodal_capacities):
|
||||
for c in n.iterate_components(n.branch_components|n.controllable_one_port_components^{"Load"}):
|
||||
nodal_capacities_c = c.df[opt_name.get(c.name,"p") + "_nom_opt"].groupby((c.df.location,c.df.carrier)).sum()
|
||||
index = pd.MultiIndex.from_tuples([(c.list_name,) + t for t in nodal_capacities_c.index.to_list()])
|
||||
nodal_capacities = nodal_capacities.reindex(nodal_capacities.index|index)
|
||||
nodal_capacities = nodal_capacities.reindex(index|nodal_capacities.index)
|
||||
nodal_capacities.loc[index,label] = nodal_capacities_c.values
|
||||
|
||||
return nodal_capacities
|
||||
@ -211,7 +213,7 @@ def calculate_capacities(n,label,capacities):
|
||||
for c in n.iterate_components(n.branch_components|n.controllable_one_port_components^{"Load"}):
|
||||
capacities_grouped = c.df[opt_name.get(c.name,"p") + "_nom_opt"].groupby(c.df.carrier).sum()
|
||||
|
||||
capacities = capacities.reindex(capacities.index|pd.MultiIndex.from_product([[c.list_name],capacities_grouped.index]))
|
||||
capacities = capacities.reindex(pd.MultiIndex.from_product([[c.list_name],capacities_grouped.index])|capacities.index)
|
||||
|
||||
capacities.loc[idx[c.list_name,list(capacities_grouped.index)],label] = capacities_grouped.values
|
||||
|
||||
@ -238,7 +240,7 @@ def calculate_energy(n,label,energy):
|
||||
for port in [col[3:] for col in c.df.columns if col[:3] == "bus"]:
|
||||
c_energies -= c.pnl["p"+port].multiply(n.snapshot_weightings,axis=0).sum().groupby(c.df.carrier).sum()
|
||||
|
||||
energy = energy.reindex(energy.index|pd.MultiIndex.from_product([[c.list_name],c_energies.index]))
|
||||
energy = energy.reindex(pd.MultiIndex.from_product([[c.list_name],c_energies.index])|energy.index)
|
||||
|
||||
energy.loc[idx[c.list_name,list(c_energies.index)],label] = c_energies.values
|
||||
|
||||
@ -246,17 +248,13 @@ def calculate_energy(n,label,energy):
|
||||
|
||||
|
||||
def calculate_supply(n,label,supply):
|
||||
"""calculate the max dispatch of each component at the buses where the loads are attached"""
|
||||
"""calculate the max dispatch of each component at the buses aggregated by carrier"""
|
||||
|
||||
load_types = n.loads.carrier.value_counts().index
|
||||
bus_carriers = n.buses.carrier.unique()
|
||||
|
||||
for i in load_types:
|
||||
|
||||
buses = n.loads.bus[n.loads.carrier == i].values
|
||||
|
||||
bus_map = pd.Series(False,index=n.buses.index)
|
||||
|
||||
bus_map.loc[buses] = True
|
||||
for i in bus_carriers:
|
||||
bus_map = (n.buses.carrier == i)
|
||||
bus_map.at[""] = False
|
||||
|
||||
for c in n.iterate_components(n.one_port_components):
|
||||
|
||||
@ -267,15 +265,15 @@ def calculate_supply(n,label,supply):
|
||||
|
||||
s = c.pnl.p[items].max().multiply(c.df.loc[items,'sign']).groupby(c.df.loc[items,'carrier']).sum()
|
||||
|
||||
supply = supply.reindex(supply.index|pd.MultiIndex.from_product([[i],[c.list_name],s.index]))
|
||||
supply = supply.reindex(pd.MultiIndex.from_product([[i],[c.list_name],s.index])|supply.index)
|
||||
supply.loc[idx[i,c.list_name,list(s.index)],label] = s.values
|
||||
|
||||
|
||||
for c in n.iterate_components(n.branch_components):
|
||||
|
||||
for end in ["0","1"]:
|
||||
for end in [col[3:] for col in c.df.columns if col[:3] == "bus"]:
|
||||
|
||||
items = c.df.index[c.df["bus" + end].map(bus_map)]
|
||||
items = c.df.index[c.df["bus" + end].map(bus_map,na_action=False)]
|
||||
|
||||
if len(items) == 0:
|
||||
continue
|
||||
@ -283,23 +281,20 @@ def calculate_supply(n,label,supply):
|
||||
#lots of sign compensation for direction and to do maximums
|
||||
s = (-1)**(1-int(end))*((-1)**int(end)*c.pnl["p"+end][items]).max().groupby(c.df.loc[items,'carrier']).sum()
|
||||
|
||||
supply = supply.reindex(supply.index|pd.MultiIndex.from_product([[i],[c.list_name],s.index]))
|
||||
supply.loc[idx[i,c.list_name,list(s.index)],label] = s.values
|
||||
supply = supply.reindex(pd.MultiIndex.from_product([[i],[c.list_name],s.index+end])|supply.index)
|
||||
supply.loc[idx[i,c.list_name,list(s.index+end)],label] = s.values
|
||||
|
||||
return supply
|
||||
|
||||
def calculate_supply_energy(n,label,supply_energy):
|
||||
"""calculate the total dispatch of each component at the buses where the loads are attached"""
|
||||
"""calculate the total energy supply/consuption of each component at the buses aggregated by carrier"""
|
||||
|
||||
load_types = n.loads.carrier.value_counts().index
|
||||
|
||||
for i in load_types:
|
||||
bus_carriers = n.buses.carrier.unique()
|
||||
|
||||
buses = n.loads.bus[n.loads.carrier == i].values
|
||||
|
||||
bus_map = pd.Series(False,index=n.buses.index)
|
||||
|
||||
bus_map.loc[buses] = True
|
||||
for i in bus_carriers:
|
||||
bus_map = (n.buses.carrier == i)
|
||||
bus_map.at[""] = False
|
||||
|
||||
for c in n.iterate_components(n.one_port_components):
|
||||
|
||||
@ -308,31 +303,31 @@ def calculate_supply_energy(n,label,supply_energy):
|
||||
if len(items) == 0:
|
||||
continue
|
||||
|
||||
s = c.pnl.p[items].sum().multiply(c.df.loc[items,'sign']).groupby(c.df.loc[items,'carrier']).sum()
|
||||
s = c.pnl.p[items].multiply(n.snapshot_weightings,axis=0).sum().multiply(c.df.loc[items,'sign']).groupby(c.df.loc[items,'carrier']).sum()
|
||||
|
||||
supply_energy = supply_energy.reindex(supply_energy.index|pd.MultiIndex.from_product([[i],[c.list_name],s.index]))
|
||||
supply_energy = supply_energy.reindex(pd.MultiIndex.from_product([[i],[c.list_name],s.index])|supply_energy.index)
|
||||
supply_energy.loc[idx[i,c.list_name,list(s.index)],label] = s.values
|
||||
|
||||
|
||||
for c in n.iterate_components(n.branch_components):
|
||||
|
||||
for end in ["0","1"]:
|
||||
for end in [col[3:] for col in c.df.columns if col[:3] == "bus"]:
|
||||
|
||||
items = c.df.index[c.df["bus" + end].map(bus_map)]
|
||||
items = c.df.index[c.df["bus" + str(end)].map(bus_map,na_action=False)]
|
||||
|
||||
if len(items) == 0:
|
||||
continue
|
||||
|
||||
s = (-1)*c.pnl["p"+end][items].sum().groupby(c.df.loc[items,'carrier']).sum()
|
||||
s = (-1)*c.pnl["p"+end][items].multiply(n.snapshot_weightings,axis=0).sum().groupby(c.df.loc[items,'carrier']).sum()
|
||||
|
||||
supply_energy = supply_energy.reindex(supply_energy.index|pd.MultiIndex.from_product([[i],[c.list_name],s.index]))
|
||||
supply_energy.loc[idx[i,c.list_name,list(s.index)],label] = s.values
|
||||
supply_energy = supply_energy.reindex(pd.MultiIndex.from_product([[i],[c.list_name],s.index+end])|supply_energy.index)
|
||||
supply_energy.loc[idx[i,c.list_name,list(s.index+end)],label] = s.values
|
||||
|
||||
return supply_energy
|
||||
|
||||
def calculate_metrics(n,label,metrics):
|
||||
|
||||
metrics = metrics.reindex(metrics.index|pd.Index(["line_volume","line_volume_limit","line_volume_AC","line_volume_DC","line_volume_shadow","co2_shadow"]))
|
||||
metrics = metrics.reindex(pd.Index(["line_volume","line_volume_limit","line_volume_AC","line_volume_DC","line_volume_shadow","co2_shadow"])|metrics.index)
|
||||
|
||||
metrics.at["line_volume_DC",label] = (n.links.length*n.links.p_nom_opt)[n.links.carrier == "DC"].sum()
|
||||
metrics.at["line_volume_AC",label] = (n.lines.length*n.lines.s_nom_opt).sum()
|
||||
@ -402,7 +397,7 @@ def calculate_weighted_prices(n,label,weighted_prices):
|
||||
if names.empty:
|
||||
continue
|
||||
|
||||
load += n.links_t.p0[names].groupby(n.links.loc[names,"bus0"],axis=1).sum(axis=1)
|
||||
load += n.links_t.p0[names].groupby(n.links.loc[names,"bus0"],axis=1).sum()
|
||||
|
||||
#Add H2 Store when charging
|
||||
#if carrier == "H2":
|
||||
|
@ -32,6 +32,9 @@ override_component_attrs["Link"].loc["efficiency2"] = ["static or series","per u
|
||||
override_component_attrs["Link"].loc["efficiency3"] = ["static or series","per unit",1.,"3rd bus efficiency","Input (optional)"]
|
||||
override_component_attrs["Link"].loc["p2"] = ["series","MW",0.,"2nd bus output","Output"]
|
||||
override_component_attrs["Link"].loc["p3"] = ["series","MW",0.,"3rd bus output","Output"]
|
||||
override_component_attrs["StorageUnit"].loc["p_dispatch"] = ["series","MW",0.,"Storage discharging.","Output"]
|
||||
override_component_attrs["StorageUnit"].loc["p_store"] = ["series","MW",0.,"Storage charging.","Output"]
|
||||
|
||||
|
||||
|
||||
def rename_techs_tyndp(tech):
|
||||
|
@ -623,16 +623,27 @@ def add_storage(network):
|
||||
|
||||
if options['SMR']:
|
||||
network.madd("Link",
|
||||
nodes + " SMR",
|
||||
nodes + " SMR CCS",
|
||||
bus0=["EU gas"]*len(nodes),
|
||||
bus1=nodes+" H2",
|
||||
bus2="co2 atmosphere",
|
||||
bus3="co2 stored",
|
||||
p_nom_extendable=True,
|
||||
carrier="SMR",
|
||||
efficiency=costs.at["SMR","efficiency"],
|
||||
carrier="SMR CCS",
|
||||
efficiency=costs.at["SMR CCS","efficiency"],
|
||||
efficiency2=costs.at['gas','CO2 intensity']*(1-options["ccs_fraction"]),
|
||||
efficiency3=costs.at['gas','CO2 intensity']*options["ccs_fraction"],
|
||||
capital_cost=costs.at["SMR CCS","fixed"])
|
||||
|
||||
network.madd("Link",
|
||||
nodes + " SMR",
|
||||
bus0=["EU gas"]*len(nodes),
|
||||
bus1=nodes+" H2",
|
||||
bus2="co2 atmosphere",
|
||||
p_nom_extendable=True,
|
||||
carrier="SMR",
|
||||
efficiency=costs.at["SMR","efficiency"],
|
||||
efficiency2=costs.at['gas','CO2 intensity'],
|
||||
capital_cost=costs.at["SMR","fixed"])
|
||||
|
||||
|
||||
@ -765,7 +776,7 @@ def add_heat(network):
|
||||
|
||||
network.madd("Load",
|
||||
nodes[name],
|
||||
suffix=" " + name + "heat",
|
||||
suffix=" " + name + " heat",
|
||||
bus=nodes[name] + " " + name + " heat",
|
||||
carrier=name + " heat",
|
||||
p_set=heat_load)
|
||||
@ -868,47 +879,72 @@ def add_heat(network):
|
||||
if options["chp"]:
|
||||
|
||||
if name == "urban central":
|
||||
#additional bus, to which we can also connect biomass
|
||||
network.madd("Bus",
|
||||
nodes[name] + " urban central CHP",
|
||||
carrier="urban central CHP")
|
||||
#add gas CHP; biomass CHP is added in biomass section
|
||||
network.madd("Link",
|
||||
nodes[name] + " urban central gas CHP electric",
|
||||
bus0="EU gas",
|
||||
bus1=nodes[name],
|
||||
bus2="co2 atmosphere",
|
||||
carrier="urban central gas CHP electric",
|
||||
p_nom_extendable=True,
|
||||
capital_cost=costs.at['central gas CHP','fixed']*costs.at['central gas CHP','efficiency'],
|
||||
marginal_cost=costs.at['central gas CHP','VOM'],
|
||||
efficiency=costs.at['central gas CHP','efficiency'],
|
||||
efficiency2=costs.at['gas','CO2 intensity'],
|
||||
c_b=costs.at['central gas CHP','c_b'],
|
||||
c_v=costs.at['central gas CHP','c_v'],
|
||||
p_nom_ratio=costs.at['central gas CHP','p_nom_ratio'])
|
||||
|
||||
network.madd("Link",
|
||||
nodes[name] + " gas to urban central CHP",
|
||||
nodes[name] + " urban central gas CHP heat",
|
||||
bus0="EU gas",
|
||||
bus1=nodes[name] + " urban central CHP",
|
||||
bus1=nodes[name] + " urban central heat",
|
||||
bus2="co2 atmosphere",
|
||||
carrier="urban central gas CHP heat",
|
||||
p_nom_extendable=True,
|
||||
marginal_cost=costs.at['central gas CHP','VOM'],
|
||||
efficiency=costs.at['central gas CHP','efficiency']/costs.at['central gas CHP','c_v'],
|
||||
efficiency2=costs.at['gas','CO2 intensity'])
|
||||
|
||||
network.madd("Link",
|
||||
nodes[name] + " urban central gas CHP CCS electric",
|
||||
bus0="EU gas",
|
||||
bus1=nodes[name],
|
||||
bus2="co2 atmosphere",
|
||||
bus3="co2 stored",
|
||||
carrier="urban central gas CHP CCS electric",
|
||||
p_nom_extendable=True,
|
||||
capital_cost=costs.at['central gas CHP CCS','fixed']*costs.at['central gas CHP CCS','efficiency'],
|
||||
marginal_cost=costs.at['central gas CHP CCS','VOM'],
|
||||
efficiency=costs.at['central gas CHP CCS','efficiency'],
|
||||
efficiency2=costs.at['gas','CO2 intensity']*(1-options["ccs_fraction"]),
|
||||
efficiency3=costs.at['gas','CO2 intensity']*options["ccs_fraction"],
|
||||
carrier="gas to central CHP",
|
||||
p_nom_extendable=True)
|
||||
c_b=costs.at['central gas CHP CCS','c_b'],
|
||||
c_v=costs.at['central gas CHP CCS','c_v'],
|
||||
p_nom_ratio=costs.at['central gas CHP CCS','p_nom_ratio'])
|
||||
|
||||
network.madd("Link",
|
||||
nodes[name] + " urban central CHP electric",
|
||||
bus0=nodes[name] + " urban central CHP",
|
||||
bus1=nodes[name],
|
||||
carrier="urban central CHP electric",
|
||||
p_nom_extendable=True,
|
||||
capital_cost=costs.at['central CHP','fixed']*options['chp_parameters']['eta_elec'],
|
||||
efficiency=options['chp_parameters']['eta_elec'])
|
||||
|
||||
network.madd("Link",
|
||||
nodes[name] + " urban central CHP heat",
|
||||
bus0=nodes[name] + " urban central CHP",
|
||||
nodes[name] + " urban central gas CHP CCS heat",
|
||||
bus0="EU gas",
|
||||
bus1=nodes[name] + " urban central heat",
|
||||
carrier="urban central CHP heat",
|
||||
bus2="co2 atmosphere",
|
||||
bus3="co2 stored",
|
||||
carrier="urban central gas CHP CCS heat",
|
||||
p_nom_extendable=True,
|
||||
efficiency=options['chp_parameters']['eta_elec']/options['chp_parameters']['c_v'])
|
||||
marginal_cost=costs.at['central gas CHP CCS','VOM'],
|
||||
efficiency=costs.at['central gas CHP CCS','efficiency']/costs.at['central gas CHP CCS','c_v'],
|
||||
efficiency2=costs.at['gas','CO2 intensity']*(1-options["ccs_fraction"]),
|
||||
efficiency3=costs.at['gas','CO2 intensity']*options["ccs_fraction"])
|
||||
|
||||
else:
|
||||
network.madd("Link",
|
||||
nodes[name] + " " + name + " micro CHP",
|
||||
nodes[name] + " " + name + " micro gas CHP",
|
||||
p_nom_extendable=True,
|
||||
bus0=["EU gas"]*len(nodes[name]),
|
||||
bus0="EU gas",
|
||||
bus1=nodes[name],
|
||||
bus2=nodes[name] + " " + name + " heat",
|
||||
bus3="co2 atmosphere",
|
||||
carrier=name + " micro CHP",
|
||||
carrier=name + " micro gas CHP",
|
||||
efficiency=costs.at['micro CHP','efficiency'],
|
||||
efficiency2=costs.at['micro CHP','efficiency-heat'],
|
||||
efficiency3=costs.at['gas','CO2 intensity'],
|
||||
@ -1028,20 +1064,61 @@ def add_biomass(network):
|
||||
|
||||
#AC buses with district heating
|
||||
urban_central = n.buses.index[n.buses.carrier == "urban central heat"]
|
||||
if not urban_central.empty:
|
||||
if not urban_central.empty and options["chp"]:
|
||||
urban_central = urban_central.str[:-len(" urban central heat")]
|
||||
|
||||
#with BECCS
|
||||
network.madd("Link",
|
||||
urban_central + " solid biomass to urban central CHP",
|
||||
urban_central + " urban central solid biomass CHP electric",
|
||||
bus0="EU solid biomass",
|
||||
bus1=urban_central + " urban central CHP",
|
||||
bus1=urban_central,
|
||||
carrier="urban central solid biomass CHP electric",
|
||||
p_nom_extendable=True,
|
||||
capital_cost=costs.at['central solid biomass CHP','fixed']*costs.at['central solid biomass CHP','efficiency'],
|
||||
marginal_cost=costs.at['central solid biomass CHP','VOM'],
|
||||
efficiency=costs.at['central solid biomass CHP','efficiency'],
|
||||
c_b=costs.at['central solid biomass CHP','c_b'],
|
||||
c_v=costs.at['central solid biomass CHP','c_v'],
|
||||
p_nom_ratio=costs.at['central solid biomass CHP','p_nom_ratio'])
|
||||
|
||||
|
||||
network.madd("Link",
|
||||
urban_central + " urban central solid biomass CHP heat",
|
||||
bus0="EU solid biomass",
|
||||
bus1=urban_central + " urban central heat",
|
||||
carrier="urban central solid biomass CHP heat",
|
||||
p_nom_extendable=True,
|
||||
marginal_cost=costs.at['central solid biomass CHP','VOM'],
|
||||
efficiency=costs.at['central solid biomass CHP','efficiency']/costs.at['central solid biomass CHP','c_v'])
|
||||
|
||||
network.madd("Link",
|
||||
urban_central + " urban central solid biomass CHP CCS electric",
|
||||
bus0="EU solid biomass",
|
||||
bus1=urban_central,
|
||||
bus2="co2 atmosphere",
|
||||
bus3="co2 stored",
|
||||
carrier="urban central solid biomass CHP CCS electric",
|
||||
p_nom_extendable=True,
|
||||
capital_cost=costs.at['central solid biomass CHP CCS','fixed']*costs.at['central solid biomass CHP CCS','efficiency'],
|
||||
marginal_cost=costs.at['central solid biomass CHP CCS','VOM'],
|
||||
efficiency=costs.at['central solid biomass CHP CCS','efficiency'],
|
||||
efficiency2=-costs.at['solid biomass','CO2 intensity']*options["ccs_fraction"],
|
||||
efficiency3=costs.at['solid biomass','CO2 intensity']*options["ccs_fraction"],
|
||||
carrier="solid biomass to urban central CHP",
|
||||
p_nom_extendable=True)
|
||||
c_b=costs.at['central solid biomass CHP','c_b'],
|
||||
c_v=costs.at['central solid biomass CHP','c_v'],
|
||||
p_nom_ratio=costs.at['central solid biomass CHP','p_nom_ratio'])
|
||||
|
||||
network.madd("Link",
|
||||
urban_central + " urban central solid biomass CHP CCS heat",
|
||||
bus0="EU solid biomass",
|
||||
bus1=urban_central + " urban central heat",
|
||||
bus2="co2 atmosphere",
|
||||
bus3="co2 stored",
|
||||
carrier="urban central solid biomass CHP CCS heat",
|
||||
p_nom_extendable=True,
|
||||
marginal_cost=costs.at['central solid biomass CHP CCS','VOM'],
|
||||
efficiency=costs.at['central solid biomass CHP CCS','efficiency']/costs.at['central solid biomass CHP CCS','c_v'],
|
||||
efficiency2=-costs.at['solid biomass','CO2 intensity']*options["ccs_fraction"],
|
||||
efficiency3=costs.at['solid biomass','CO2 intensity']*options["ccs_fraction"])
|
||||
|
||||
|
||||
def add_industry(network):
|
||||
@ -1057,43 +1134,70 @@ def add_industry(network):
|
||||
solid_biomass_by_country = industrial_demand["solid biomass"].groupby(pop_layout.ct).sum()
|
||||
countries = solid_biomass_by_country.index
|
||||
|
||||
network.madd("Bus",
|
||||
["solid biomass for industry"],
|
||||
carrier="solid biomass for industry")
|
||||
|
||||
network.madd("Load",
|
||||
["solid biomass for industry"],
|
||||
bus="EU solid biomass",
|
||||
bus="solid biomass for industry",
|
||||
carrier="solid biomass for industry",
|
||||
p_set=solid_biomass_by_country.sum()/8760.)
|
||||
|
||||
#Net transfer of CO2 from atmosphere to stored
|
||||
network.madd("Load",
|
||||
["solid biomass for industry co2 from atmosphere"],
|
||||
bus="co2 atmosphere",
|
||||
carrier="solid biomass for industry co2 from atmosphere",
|
||||
p_set=solid_biomass_by_country.sum()*costs.at['solid biomass','CO2 intensity']*options["ccs_fraction"]/8760.)
|
||||
network.madd("Link",
|
||||
["solid biomass for industry"],
|
||||
bus0="EU solid biomass",
|
||||
bus1="solid biomass for industry",
|
||||
carrier="solid biomass for industry",
|
||||
p_nom_extendable=True,
|
||||
efficiency=1.)
|
||||
|
||||
network.madd("Load",
|
||||
["solid biomass for industry co2 to stored"],
|
||||
bus="co2 stored",
|
||||
carrier="solid biomass for industry co2 to stored",
|
||||
p_set=-solid_biomass_by_country.sum()*costs.at['solid biomass','CO2 intensity']*options["ccs_fraction"]/8760.)
|
||||
network.madd("Link",
|
||||
["solid biomass for industry CCS"],
|
||||
bus0="EU solid biomass",
|
||||
bus1="solid biomass for industry",
|
||||
bus2="co2 atmosphere",
|
||||
bus3="co2 stored",
|
||||
carrier="solid biomass for industry CCS",
|
||||
p_nom_extendable=True,
|
||||
capital_cost=costs.at["industry CCS","fixed"]*costs.at['solid biomass','CO2 intensity']*8760, #8760 converts EUR/(tCO2/a) to EUR/(tCO2/h)
|
||||
efficiency=0.9,
|
||||
efficiency2=-costs.at['solid biomass','CO2 intensity']*options["ccs_fraction"],
|
||||
efficiency3=costs.at['solid biomass','CO2 intensity']*options["ccs_fraction"])
|
||||
|
||||
|
||||
network.madd("Bus",
|
||||
["gas for industry"],
|
||||
carrier="gas for industry")
|
||||
|
||||
network.madd("Load",
|
||||
["gas for industry"],
|
||||
bus="EU gas",
|
||||
bus="gas for industry",
|
||||
carrier="gas for industry",
|
||||
p_set=industrial_demand.loc[nodes,"methane"].sum()/8760.)
|
||||
|
||||
network.madd("Load",
|
||||
["gas for industry co2 to atmosphere"],
|
||||
bus="co2 atmosphere",
|
||||
carrier="gas for industry co2 to atmosphere",
|
||||
p_set=-industrial_demand.loc[nodes,"methane"].sum()*costs.at['gas','CO2 intensity']*(1-options["ccs_fraction"])/8760.)
|
||||
network.madd("Link",
|
||||
["gas for industry"],
|
||||
bus0="EU gas",
|
||||
bus1="gas for industry",
|
||||
bus2="co2 atmosphere",
|
||||
carrier="gas for industry",
|
||||
p_nom_extendable=True,
|
||||
efficiency=1.,
|
||||
efficiency2=costs.at['gas','CO2 intensity'])
|
||||
|
||||
network.madd("Load",
|
||||
["gas for industry co2 to stored"],
|
||||
bus="co2 stored",
|
||||
carrier="gas for industry co2 to stored",
|
||||
p_set=-industrial_demand.loc[nodes,"methane"].sum()*costs.at['gas','CO2 intensity']*options["ccs_fraction"]/8760.)
|
||||
network.madd("Link",
|
||||
["gas for industry CCS"],
|
||||
bus0="EU gas",
|
||||
bus1="gas for industry",
|
||||
bus2="co2 atmosphere",
|
||||
bus3="co2 stored",
|
||||
carrier="gas for industry CCS",
|
||||
p_nom_extendable=True,
|
||||
capital_cost=costs.at["industry CCS","fixed"]*costs.at['gas','CO2 intensity']*8760, #8760 converts EUR/(tCO2/a) to EUR/(tCO2/h)
|
||||
efficiency=0.9,
|
||||
efficiency2=costs.at['gas','CO2 intensity']*(1-options["ccs_fraction"]),
|
||||
efficiency3=costs.at['gas','CO2 intensity']*options["ccs_fraction"])
|
||||
|
||||
|
||||
network.madd("Load",
|
||||
@ -1184,17 +1288,37 @@ def add_industry(network):
|
||||
carrier="industry new electricity",
|
||||
p_set = (industrial_demand.loc[nodes,"electricity"]-industrial_demand.loc[nodes,"current electricity"])/8760.)
|
||||
|
||||
network.madd("Load",
|
||||
["process emissions to atmosphere"],
|
||||
bus="co2 atmosphere",
|
||||
carrier="process emissions to atmosphere",
|
||||
p_set = -industrial_demand.loc[nodes,"process emission"].sum()*(1-options["ccs_fraction"])/8760.)
|
||||
network.madd("Bus",
|
||||
["process emissions"],
|
||||
carrier="process emissions")
|
||||
|
||||
#this should be process emissions fossil+feedstock
|
||||
#then need load on atmosphere for feedstock emissions that are currently going to atmosphere via Link Fischer-Tropsch demand
|
||||
network.madd("Load",
|
||||
["process emissions to stored"],
|
||||
bus="co2 stored",
|
||||
carrier="process emissions to stored",
|
||||
p_set = -industrial_demand.loc[nodes,"process emission"].sum()*options["ccs_fraction"]/8760.)
|
||||
["process emissions"],
|
||||
bus="process emissions",
|
||||
carrier="process emissions",
|
||||
p_set = -industrial_demand.loc[nodes,"process emission"].sum()/8760.)
|
||||
|
||||
network.madd("Link",
|
||||
["process emissions"],
|
||||
bus0="process emissions",
|
||||
bus1="co2 atmosphere",
|
||||
carrier="process emissions",
|
||||
p_nom_extendable=True,
|
||||
efficiency=1.)
|
||||
|
||||
#assume enough local waste heat for CCS
|
||||
network.madd("Link",
|
||||
["process emissions CCS"],
|
||||
bus0="process emissions",
|
||||
bus1="co2 atmosphere",
|
||||
bus2="co2 stored",
|
||||
carrier="process emissions CCS",
|
||||
p_nom_extendable=True,
|
||||
capital_cost=costs.at["industry CCS","fixed"]*8760, #8760 converts EUR/(tCO2/a) to EUR/(tCO2/h)
|
||||
efficiency=(1-options["ccs_fraction"]),
|
||||
efficiency2=options["ccs_fraction"])
|
||||
|
||||
|
||||
|
||||
|
@ -1,7 +1,15 @@
|
||||
import os
|
||||
|
||||
os.system("conda config --add channels http://conda.anaconda.org/gurobi")
|
||||
|
||||
os.system("conda install -y gurobi=8.1.0")
|
||||
|
||||
|
||||
import sys
|
||||
|
||||
sys.path = ["/home/vres/data/tom/lib/pypsa"] + sys.path
|
||||
sys.path = ["pypsa"] + sys.path
|
||||
|
||||
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
@ -12,6 +20,8 @@ import os
|
||||
|
||||
import pypsa
|
||||
|
||||
from pypsa.linopt import get_var, linexpr, define_constraints
|
||||
|
||||
from pypsa.descriptors import free_output_series_dataframes
|
||||
|
||||
# Suppress logging of the slack bus choices
|
||||
@ -103,80 +113,74 @@ def add_opts_constraints(n, opts=None):
|
||||
ext_gens_i = n.generators.index[n.generators.carrier.isin(conv_techs) & n.generators.p_nom_extendable]
|
||||
n.model.safe_peakdemand = pypsa.opt.Constraint(expr=sum(n.model.generator_p_nom[gen] for gen in ext_gens_i) >= peakdemand - exist_conv_caps)
|
||||
|
||||
def add_lv_constraint(n):
|
||||
line_volume = getattr(n, 'line_volume_limit', None)
|
||||
if line_volume is not None and not np.isinf(line_volume):
|
||||
n.model.line_volume_constraint = pypsa.opt.Constraint(
|
||||
expr=((sum(n.model.passive_branch_s_nom["Line",line]*n.lines.at[line,"length"]
|
||||
for line in n.lines.index[n.lines.s_nom_extendable]) +
|
||||
sum(n.model.link_p_nom[link]*n.links.at[link,"length"]
|
||||
for link in n.links.index[(n.links.carrier=='DC') &
|
||||
n.links.p_nom_extendable]))
|
||||
<= line_volume)
|
||||
)
|
||||
|
||||
def add_eps_storage_constraint(n):
|
||||
if not hasattr(n, 'epsilon'):
|
||||
n.epsilon = 1e-5
|
||||
fix_sus_i = n.storage_units.index[~ n.storage_units.p_nom_extendable]
|
||||
n.model.objective.expr += sum(n.epsilon * n.model.state_of_charge[su, n.snapshots[0]] for su in fix_sus_i)
|
||||
|
||||
def add_battery_constraints(network):
|
||||
def add_battery_constraints(n):
|
||||
|
||||
nodes = list(network.buses.index[network.buses.carrier == "battery"])
|
||||
nodes = n.buses.index[n.buses.carrier == "battery"]
|
||||
|
||||
def battery(model, node):
|
||||
return model.link_p_nom[node + " charger"] == model.link_p_nom[node + " discharger"]*network.links.at[node + " charger","efficiency"]
|
||||
link_p_nom = get_var(n, "Link", "p_nom")
|
||||
|
||||
network.model.battery = pypsa.opt.Constraint(nodes, rule=battery)
|
||||
lhs = linexpr((1,link_p_nom[nodes + " charger"]),
|
||||
(-n.links.loc[nodes + " discharger", "efficiency"].values,
|
||||
link_p_nom[nodes + " discharger"].values))
|
||||
define_constraints(n, lhs, "=", 0, 'Link', 'charger_ratio')
|
||||
|
||||
|
||||
def add_chp_constraints(n):
|
||||
|
||||
def add_chp_constraints(network):
|
||||
electric = n.links.index[n.links.index.str.contains("urban central") & n.links.index.str.contains("CHP") & n.links.index.str.contains("electric")]
|
||||
heat = n.links.index[n.links.index.str.contains("urban central") & n.links.index.str.contains("CHP") & n.links.index.str.contains("heat")]
|
||||
|
||||
options = snakemake.config["sector"]
|
||||
if not electric.empty:
|
||||
|
||||
if hasattr(network.links.index,"str") and network.links.index.str.contains("CHP").any():
|
||||
link_p_nom = get_var(n, "Link", "p_nom")
|
||||
|
||||
#AC buses with district heating
|
||||
urban_central = n.buses.index[n.buses.carrier == "urban central heat"]
|
||||
if not urban_central.empty:
|
||||
urban_central = urban_central.str[:-len(" urban central heat")]
|
||||
#ratio of output heat to electricity set by p_nom_ratio
|
||||
lhs = linexpr((n.links.loc[electric,"efficiency"]
|
||||
*n.links.loc[electric,'p_nom_ratio'],
|
||||
link_p_nom[electric]),
|
||||
(-n.links.loc[heat,"efficiency"].values,
|
||||
link_p_nom[heat].values))
|
||||
define_constraints(n, lhs, "=", 0, 'chplink', 'fix_p_nom_ratio')
|
||||
|
||||
link_p = get_var(n, "Link", "p")
|
||||
|
||||
def chp_nom(model,node):
|
||||
return network.links.at[node + " urban central CHP electric","efficiency"]*options['chp_parameters']['p_nom_ratio']*model.link_p_nom[node + " urban central CHP electric"] == network.links.at[node + " urban central CHP heat","efficiency"]*options['chp_parameters']['p_nom_ratio']*model.link_p_nom[node + " urban central CHP heat"]
|
||||
#backpressure
|
||||
lhs = linexpr((n.links.loc[electric,'c_b'].values
|
||||
*n.links.loc[heat,"efficiency"],
|
||||
link_p[heat]),
|
||||
(-n.links.loc[electric,"efficiency"].values,
|
||||
link_p[electric].values))
|
||||
|
||||
define_constraints(n, lhs, "<=", 0, 'chplink', 'backpressure')
|
||||
|
||||
network.model.chp_nom = pypsa.opt.Constraint(urban_central,rule=chp_nom)
|
||||
#top_iso_fuel_line
|
||||
lhs = linexpr((1,link_p[heat]),
|
||||
(1,link_p[electric].values),
|
||||
(-1,link_p_nom[electric].values))
|
||||
|
||||
define_constraints(n, lhs, "<=", 0, 'chplink', 'top_iso_fuel_line')
|
||||
|
||||
def backpressure(model,node,snapshot):
|
||||
return options['chp_parameters']['c_m']*network.links.at[node + " urban central CHP heat","efficiency"]*model.link_p[node + " urban central CHP heat",snapshot] <= network.links.at[node + " urban central CHP electric","efficiency"]*model.link_p[node + " urban central CHP electric",snapshot]
|
||||
|
||||
network.model.backpressure = pypsa.opt.Constraint(urban_central,list(network.snapshots),rule=backpressure)
|
||||
|
||||
|
||||
def top_iso_fuel_line(model,node,snapshot):
|
||||
return model.link_p[node + " urban central CHP heat",snapshot] + model.link_p[node + " urban central CHP electric",snapshot] <= model.link_p_nom[node + " urban central CHP electric"]
|
||||
|
||||
network.model.top_iso_fuel_line = pypsa.opt.Constraint(urban_central,list(network.snapshots),rule=top_iso_fuel_line)
|
||||
|
||||
def extra_functionality(n, snapshots):
|
||||
#add_opts_constraints(n, opts)
|
||||
#add_eps_storage_constraint(n)
|
||||
add_chp_constraints(n)
|
||||
add_battery_constraints(n)
|
||||
|
||||
|
||||
|
||||
def fix_branches(n, lines_s_nom=None, links_p_nom=None):
|
||||
if lines_s_nom is not None and len(lines_s_nom) > 0:
|
||||
for l, s_nom in lines_s_nom.iteritems():
|
||||
n.model.passive_branch_s_nom["Line", l].fix(s_nom)
|
||||
if isinstance(n.opt, pypsa.opf.PersistentSolver):
|
||||
n.opt.update_var(n.model.passive_branch_s_nom)
|
||||
|
||||
n.lines.loc[lines_s_nom.index,"s_nom"] = lines_s_nom.values
|
||||
n.lines.loc[lines_s_nom.index,"s_nom_extendable"] = False
|
||||
if links_p_nom is not None and len(links_p_nom) > 0:
|
||||
for l, p_nom in links_p_nom.iteritems():
|
||||
n.model.link_p_nom[l].fix(p_nom)
|
||||
if isinstance(n.opt, pypsa.opf.PersistentSolver):
|
||||
n.opt.update_var(n.model.link_p_nom)
|
||||
n.links.loc[links_p_nom.index,"p_nom"] = links_p_nom.values
|
||||
n.links.loc[links_p_nom.index,"p_nom_extendable"] = False
|
||||
|
||||
def solve_network(n, config=None, solver_log=None, opts=None):
|
||||
if config is None:
|
||||
@ -191,16 +195,6 @@ def solve_network(n, config=None, solver_log=None, opts=None):
|
||||
def run_lopf(n, allow_warning_status=False, fix_zero_lines=False, fix_ext_lines=False):
|
||||
free_output_series_dataframes(n)
|
||||
|
||||
if not hasattr(n, 'opt') or not isinstance(n.opt, pypsa.opf.PersistentSolver):
|
||||
pypsa.opf.network_lopf_build_model(n, formulation=solve_opts['formulation'])
|
||||
add_opts_constraints(n, opts)
|
||||
add_lv_constraint(n)
|
||||
#add_eps_storage_constraint(n)
|
||||
add_battery_constraints(n)
|
||||
add_chp_constraints(n)
|
||||
|
||||
pypsa.opf.network_lopf_prepare_solver(n, solver_name=solver_name)
|
||||
|
||||
if fix_zero_lines:
|
||||
fix_lines_b = (n.lines.s_nom_opt == 0.) & n.lines.s_nom_extendable
|
||||
fix_links_b = (n.links.carrier=='DC') & (n.links.p_nom_opt == 0.) & n.links.p_nom_extendable
|
||||
@ -212,19 +206,19 @@ def solve_network(n, config=None, solver_log=None, opts=None):
|
||||
fix_branches(n,
|
||||
lines_s_nom=n.lines.loc[n.lines.s_nom_extendable, 's_nom_opt'],
|
||||
links_p_nom=n.links.loc[(n.links.carrier=='DC') & n.links.p_nom_extendable, 'p_nom_opt'])
|
||||
|
||||
|
||||
if not fix_ext_lines and hasattr(n.model, 'line_volume_constraint'):
|
||||
|
||||
def extra_postprocessing(n, snapshots, duals):
|
||||
index = list(n.model.line_volume_constraint.keys())
|
||||
cdata = pd.Series(list(n.model.line_volume_constraint.values()),
|
||||
index=index)
|
||||
n.line_volume_limit_dual = -cdata.map(duals).sum()
|
||||
print("line volume limit dual:",n.line_volume_limit_dual)
|
||||
|
||||
if "line_volume_constraint" in n.global_constraints.index:
|
||||
n.global_constraints.drop("line_volume_constraint",inplace=True)
|
||||
else:
|
||||
extra_postprocessing = None
|
||||
if "line_volume_constraint" not in n.global_constraints.index:
|
||||
line_volume = getattr(n, 'line_volume_limit', None)
|
||||
if line_volume is not None and not np.isinf(line_volume):
|
||||
n.add("GlobalConstraint",
|
||||
"line_volume_constraint",
|
||||
type="transmission_volume_expansion_limit",
|
||||
carrier_attribute="AC,DC",
|
||||
sense="<=",
|
||||
constant=line_volume)
|
||||
|
||||
|
||||
# Firing up solve will increase memory consumption tremendously, so
|
||||
# make sure we freed everything we can
|
||||
@ -237,21 +231,25 @@ def solve_network(n, config=None, solver_log=None, opts=None):
|
||||
#sys.exit()
|
||||
|
||||
|
||||
status, termination_condition = \
|
||||
pypsa.opf.network_lopf_solve(n,
|
||||
solver_logfile=solver_log,
|
||||
solver_options=solver_options,
|
||||
formulation=solve_opts['formulation'],
|
||||
extra_postprocessing=extra_postprocessing
|
||||
#keep_files=True
|
||||
#free_memory={'pypsa'}
|
||||
)
|
||||
status, termination_condition = n.lopf(pyomo=False,
|
||||
solver_name=solver_name,
|
||||
solver_logfile=solver_log,
|
||||
solver_options=solver_options,
|
||||
extra_functionality=extra_functionality,
|
||||
formulation=solve_opts['formulation'])
|
||||
#extra_postprocessing=extra_postprocessing
|
||||
#keep_files=True
|
||||
#free_memory={'pypsa'}
|
||||
|
||||
assert status == "ok" or allow_warning_status and status == 'warning', \
|
||||
("network_lopf did abort with status={} "
|
||||
"and termination_condition={}"
|
||||
.format(status, termination_condition))
|
||||
|
||||
if not fix_ext_lines and "line_volume_constraint" in n.global_constraints.index:
|
||||
n.line_volume_limit_dual = n.global_constraints.at["line_volume_constraint","mu"]
|
||||
print("line volume limit dual:",n.line_volume_limit_dual)
|
||||
|
||||
return status, termination_condition
|
||||
|
||||
lines_ext_b = n.lines.s_nom_extendable
|
||||
@ -286,21 +284,6 @@ def solve_network(n, config=None, solver_log=None, opts=None):
|
||||
)
|
||||
logger.debug("lines.num_parallel={}".format(n.lines.loc[lines_ext_typed_b, 'num_parallel']))
|
||||
|
||||
if isinstance(n.opt, pypsa.opf.PersistentSolver):
|
||||
n.calculate_dependent_values()
|
||||
|
||||
assert solve_opts['formulation'] == 'kirchhoff', \
|
||||
"Updating persistent solvers has only been implemented for the kirchhoff formulation for now"
|
||||
|
||||
n.opt.remove_constraint(n.model.cycle_constraints)
|
||||
del n.model.cycle_constraints_index
|
||||
del n.model.cycle_constraints_index_0
|
||||
del n.model.cycle_constraints_index_1
|
||||
del n.model.cycle_constraints
|
||||
|
||||
pypsa.opf.define_passive_branch_flows_with_kirchhoff(n, n.snapshots, skip_vars=True)
|
||||
n.opt.add_constraint(n.model.cycle_constraints)
|
||||
|
||||
iteration = 1
|
||||
|
||||
lines['s_nom_opt'] = lines['s_nom'] * n.lines['num_parallel'].where(n.lines.type != '', 1.)
|
||||
|
Loading…
Reference in New Issue
Block a user