Give all loads a carrier; rename heat buses; fix district h losses

Heat buses renamed to:

rural (for low-density areas where district heating not possible)

urban decentral (for high-density areas without district heating and
individual heating technologies) (used to be called "urban")

urban central (for high-density areas with district heating) (used to
be called "central")

District heating losses applied only to urban central.
This commit is contained in:
Tom Brown 2019-07-16 16:00:21 +02:00
parent 6cc676d6cf
commit ddca9afcc7
5 changed files with 267 additions and 240 deletions

View File

@ -2,15 +2,15 @@ logging_level: INFO
results_dir: 'results/'
summary_dir: results
run: '190516-decentral-noH2network'
run: '190712-test_district'
scenario:
sectors: [E] # ,E+EV,E+BEV,E+BEV+V2G] # [ E+EV, E+BEV, E+BEV+V2G ]
simpl: ['']
lv: [1.0]#, 1.125, 1.25, 1.5, 2.0]# or opt
lv: [1.0,1.25,2.0]#, 1.125, 1.25, 1.5, 2.0]# or opt
clusters: [128] #[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-decentral-noH2network-solar100,Co2L0p1-3H-T-H-B-I-decentral-noH2network-solar100,Co2L0p2-3H-T-H-B-I-decentral-noH2network-solar100,Co2L0p3-3H-T-H-B-I-decentral-noH2network-solar100,Co2L0p4-3H-T-H-B-I-decentral-noH2network-solar100]#,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,Co2L0-3H-T-H-B-I-nodistrict]#,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
@ -57,7 +57,7 @@ sector:
'ICE_upper_degree_factor' : 1.6
'EV_lower_degree_factor' : 0.98
'EV_upper_degree_factor' : 0.63
'district_heating_loss' : 0.1
'district_heating_loss' : 0.15
'bev' : True #turns on EV battery
'bev_availability' : 0.5 #How many cars do smart charging
'v2g' : True #allows feed-in to grid from EV battery
@ -242,6 +242,10 @@ plotting:
"Heat load" : "r"
"Transport load" : "grey"
"heat" : "darkred"
"rural heat" : "#880000"
"central heat" : "#b22222"
"decentral heat" : "#800000"
"process heat" : "#FF3333"
"heat demand" : "darkred"
"electric demand" : "k"
"Li ion" : "grey"
@ -252,10 +256,14 @@ plotting:
"V2G" : "grey"
"transport" : "grey"
"electricity" : "k"
"industry new electricity" : "#222222"
"process emissions to stored" : "#444444"
"process emissions to atmosphere" : "#888888"
"transport fuel cell" : "#AAAAAA"
"biogas" : "#800000"
"solid biomass" : "#DAA520"
"today" : "#D2691E"
"shipping" : "#6495ED"
nice_names:
# OCGT: "Gas"
# OCGT marginal: "Gas (marginal)"

View File

@ -41,17 +41,9 @@ override_component_attrs["Link"].loc["p3"] = ["series","MW",0.,"3rd bus output",
def assign_carriers(n):
if "carrier" not in n.loads:
n.loads["carrier"] = "electricity"
for carrier in ["transport","heat","urban heat"]:
n.loads.loc[n.loads.index.str.contains(carrier),"carrier"] = carrier
if "carrier" not in n.lines:
n.lines["carrier"] = "AC"
if n.stores.loc["EU gas Store","carrier"] == "":
n.stores.loc["EU gas Store","carrier"] = "gas Store"
def assign_locations(n):
for c in n.iterate_components(n.one_port_components|n.branch_components):

View File

@ -13,53 +13,46 @@ import matplotlib.pyplot as plt
#consolidate and rename
def rename_techs(label):
if label[:8] == "central ":
label = label[8:]
if label[:6] == "urban ":
label = label[6:]
if "retrofitting" in label:
label = "building retrofitting"
if "H2" in label:
label = "hydrogen storage"
if "CHP" in label:
label = "CHP"
if "water tank" in label:
label = "water tanks"
if label=="water tanks":
label = "hot water storage"
if "gas" in label and label not in ["gas boiler","biogas"]:
label = "natural gas"
if "solar thermal" in label:
label = "solar thermal"
if label == "solar":
label = "solar PV"
if label == "heat pump":
label = "air heat pump"
if label == "Sabatier":
label = "methanation"
if label == "offwind":
label = "offshore wind"
if label == "offwind-ac":
label = "offshore wind (AC)"
if label == "offwind-dc":
label = "offshore wind (DC)"
if label == "onwind":
label = "onshore wind"
if label == "ror":
label = "hydroelectricity"
if label == "hydro":
label = "hydroelectricity"
if label == "PHS":
label = "hydroelectricity"
if label == "co2 Store":
label = "DAC"
if label == "co2 stored":
label = "CO2 sequestration"
if "battery" in label:
label = "battery storage"
if label in ["AC","DC","B2B"]:
label = "transmission lines"
prefix_to_remove = ["central ","urban "]
rename_if_contains = ["CHP","gas boiler","biogas","solar thermal","air heat pump","ground heat pump","resistive heater"]
rename_if_contains_dict = {"water tanks" : "hot water storage",
"retrofitting" : "building retrofitting",
"H2" : "hydrogen storage",
"battery" : "battery storage"}
rename = {"solar" : "solar PV",
"Sabatier" : "methanation",
"offwind" : "offshore wind",
"offwind-ac" : "offshore wind (AC)",
"offwind-dc" : "offshore wind (DC)",
"onwind" : "onshore wind",
"ror" : "hydroelectricity",
"hydro" : "hydroelectricity",
"PHS" : "hydroelectricity",
"co2 Store" : "DAC",
"co2 stored" : "CO2 sequestration",
"AC" : "transmission lines",
"DC" : "transmission lines",
"B2B" : "transmission lines"}
for ptr in prefix_to_remove:
if label[:len(ptr)] == ptr:
label = label[len(ptr):]
for rif in rename_if_contains:
if rif in label:
label = rif
for old,new in rename_if_contains_dict.items():
if old in label:
label = new
for old,new in rename.items():
if old == label:
label = new
return label

View File

@ -632,6 +632,7 @@ def add_transport(network):
nodes,
suffix=" transport",
bus=nodes + " EV battery",
carrier="transport",
p_set=(1-options['transport_fuel_cell_share'])*(transport[nodes]+shift_df(transport[nodes],1)+shift_df(transport[nodes],2))/3.)
p_nom = nodal_transport_data["number cars"]*0.011*(1-options['transport_fuel_cell_share']) #3-phase charger with 11 kW * x% of time grid-connected
@ -684,6 +685,7 @@ def add_transport(network):
nodes,
suffix=" transport fuel cell",
bus=nodes + " H2",
carrier="transport fuel cell",
p_set=options['transport_fuel_cell_share']/0.58*transport[nodes])
@ -692,78 +694,102 @@ def add_transport(network):
def add_heat(network):
print("adding heat")
nodes = pop_layout.index
network.add("Carrier","heat")
network.add("Carrier","water tanks")
#rural are areas with low heating density
#urban are areas with high heating density
#urban can be split into district heating (central) and individual heating (decentral)
rural = pop_layout.index
urban = pop_layout.index
network.add("Carrier","rural heat")
network.add("Carrier","urban central heat")
network.add("Carrier","urban decentral heat")
network.add("Carrier","rural water tanks")
network.add("Carrier","urban central water tanks")
network.add("Carrier","urban decentral water tanks")
#urban are high density locations
if options["central"]:
urban_ct = pd.Index(["ES","GR","PT","IT","BG"])
urban = pop_layout.index[pop_layout.ct.isin(urban_ct)]
urban_decentral_ct = pd.Index(["ES","GR","PT","IT","BG"])
urban_decentral = pop_layout.index[pop_layout.ct.isin(urban_decentral_ct)]
else:
urban = nodes
urban_decentral = urban
#NB: must add costs of central heating afterwards (EUR 400 / kWpeak, 50a, 1% FOM from Fraunhofer ISE)
#central are urban nodes with district heating
central = nodes ^ urban
urban_central = urban ^ urban_decentral
urban_fraction = options['central_fraction']*pop_layout["urban"]/(pop_layout[["urban","rural"]].sum(axis=1))
network.madd("Bus",
nodes + " heat",
carrier="heat")
rural + " rural heat",
carrier="rural heat")
network.madd("Bus",
nodes + " urban heat",
carrier="heat")
urban_central + " urban central heat",
carrier="urban central heat")
network.madd("Bus",
urban_decentral + " urban decentral heat",
carrier="urban decentral heat")
network.madd("Load",
nodes,
suffix=" heat",
bus=nodes + " heat",
p_set= heat_demand[nodes].multiply((1-urban_fraction)))
rural,
suffix=" rural heat",
bus=rural + " rural heat",
carrier="rural heat",
p_set= heat_demand[rural].multiply((1-urban_fraction[rural])))
network.madd("Load",
nodes,
suffix=" urban heat",
bus=nodes + " urban heat",
p_set= heat_demand[nodes].multiply(urban_fraction).divide((1-options['district_heating_loss'])))
urban_central,
suffix=" urban central heat",
bus=urban_central + " urban central heat",
carrier="urban central heat",
p_set= heat_demand[urban_central].multiply(urban_fraction[urban_central]*(1+options['district_heating_loss'])))
network.madd("Load",
urban_decentral,
suffix=" urban decentral heat",
bus=urban_decentral + " urban decentral heat",
carrier="urban decentral heat",
p_set= heat_demand[urban_decentral].multiply(urban_fraction[urban_decentral]))
network.madd("Link",
urban,
suffix=" urban heat pump",
bus0=urban,
bus1=urban + " urban heat",
carrier="urban heat pump",
efficiency=ashp_cop[urban] if options["time_dep_hp_cop"] else costs.at['decentral air-sourced heat pump','efficiency'],
urban_decentral,
suffix=" urban decentral air heat pump",
bus0=urban_decentral,
bus1=urban_decentral + " urban decentral heat",
carrier="urban decentral air heat pump",
efficiency=ashp_cop[urban_decentral] if options["time_dep_hp_cop"] else costs.at['decentral air-sourced heat pump','efficiency'],
capital_cost=costs.at['decentral air-sourced heat pump','efficiency']*costs.at['decentral air-sourced heat pump','fixed'],
p_nom_extendable=True)
network.madd("Link",
central,
suffix=" central heat pump",
bus0=central,
bus1=central + " urban heat",
carrier="central heat pump",
efficiency=ashp_cop[central] if options["time_dep_hp_cop"] else costs.at['central air-sourced heat pump','efficiency'],
urban_central,
suffix=" urban central air heat pump",
bus0=urban_central,
bus1=urban_central + " urban central heat",
carrier="urban central air heat pump",
efficiency=ashp_cop[urban_central] if options["time_dep_hp_cop"] else costs.at['central air-sourced heat pump','efficiency'],
capital_cost=costs.at['central air-sourced heat pump','efficiency']*costs.at['central air-sourced heat pump','fixed'],
p_nom_extendable=True)
network.madd("Link",
nodes,
suffix=" ground heat pump",
bus0=nodes,
bus1=nodes + " heat",
carrier="ground heat pump",
efficiency=gshp_cop[nodes] if options["time_dep_hp_cop"] else costs.at['decentral ground-sourced heat pump','efficiency'],
rural,
suffix=" rural ground heat pump",
bus0=rural,
bus1=rural + " rural heat",
carrier="rural ground heat pump",
efficiency=gshp_cop[rural] if options["time_dep_hp_cop"] else costs.at['decentral ground-sourced heat pump','efficiency'],
capital_cost=costs.at['decentral ground-sourced heat pump','efficiency']*costs.at['decentral ground-sourced heat pump','fixed'],
p_nom_extendable=True)
#NB: this currently doesn't work for pypsa-eur model
if options['retrofitting']:
retro_nodes = pd.Index(["DE"])
@ -827,94 +853,94 @@ def add_heat(network):
if options["tes"]:
network.madd("Bus",
nodes + " water tanks",
carrier="water tanks")
rural + " rural water tanks",
carrier="rural water tanks")
network.madd("Link",
nodes + " water tanks charger",
bus0=nodes + " heat",
bus1=nodes + " water tanks",
rural + " rural water tanks charger",
bus0=rural + " rural heat",
bus1=rural + " rural water tanks",
efficiency=costs.at['water tank charger','efficiency'],
carrier="water tanks charger",
carrier="rural water tanks charger",
p_nom_extendable=True)
network.madd("Link",
nodes + " water tanks discharger",
bus0=nodes + " water tanks",
bus1=nodes + " heat",
carrier="water tanks discharger",
rural + " rural water tanks discharger",
bus0=rural + " rural water tanks",
bus1=rural + " rural heat",
carrier="rural water tanks discharger",
efficiency=costs.at['water tank discharger','efficiency'],
p_nom_extendable=True)
network.madd("Store",
nodes + " water tank",
bus=nodes + " water tanks",
rural + " rural water tanks",
bus=rural + " rural water tanks",
e_cyclic=True,
e_nom_extendable=True,
carrier="water tank",
carrier="rural water tanks",
standing_loss=1-np.exp(-1/(24.*options["tes_tau"])), # [HP] 180 day time constant for centralised, 3 day for decentralised
capital_cost=costs.at['decentral water tank storage','fixed']/(1.17e-3*40)) #conversion from EUR/m^3 to EUR/MWh for 40 K diff and 1.17 kWh/m^3/K
network.madd("Bus",
urban + " urban water tanks",
carrier="water tanks")
urban_decentral + " urban decentral water tanks",
carrier="urban decentral water tanks")
network.madd("Link",
urban + " urban water tanks charger",
bus0=urban + " urban heat",
bus1=urban + " urban water tanks",
carrier="urban water tanks charger",
urban_decentral + " urban decentral water tanks charger",
bus0=urban_decentral + " urban decentral heat",
bus1=urban_decentral + " urban decentral water tanks",
carrier="urban decentral water tanks charger",
efficiency=costs.at['water tank charger','efficiency'],
p_nom_extendable=True)
network.madd("Link",
urban + " urban water tanks discharger",
bus0=urban + " urban water tanks",
bus1=urban + " urban heat",
carrier="urban water tanks discharger",
urban_decentral + " urban decentral water tanks discharger",
bus0=urban_decentral + " urban decentral water tanks",
bus1=urban_decentral + " urban decentral heat",
carrier="urban decentral water tanks discharger",
efficiency=costs.at['water tank discharger','efficiency'],
p_nom_extendable=True)
network.madd("Store",
urban + " urban water tank",
bus=urban + " urban water tanks",
urban_decentral + " urban decentral water tanks",
bus=urban_decentral + " urban decentral water tanks",
e_cyclic=True,
e_nom_extendable=True,
carrier="urban water tank",
carrier="urban decentral water tanks",
standing_loss=1-np.exp(-1/(24.*options["tes_tau"])), # [HP] 180 day time constant for centralised, 3 day for decentralised
capital_cost=costs.at['decentral water tank storage','fixed']/(1.17e-3*40)) #conversion from EUR/m^3 to EUR/MWh for 40 K diff and 1.17 kWh/m^3/K
network.madd("Bus",
central + " central water tanks",
carrier="water tanks")
urban_central + " urban central water tanks",
carrier="urban central water tanks")
network.madd("Link",
central + " central water tanks charger",
bus0=central + " urban heat",
bus1=central + " central water tanks",
urban_central + " urban central water tanks charger",
bus0=urban_central + " urban central heat",
bus1=urban_central + " urban central water tanks",
p_nom_extendable=True,
carrier="central water tanks charger",
carrier="urban central water tanks charger",
efficiency=costs.at['water tank charger','efficiency'])
network.madd("Link",
central + " central water tanks discharger",
bus0=central + " central water tanks",
bus1=central + " urban heat",
carrier="central water tanks discharger",
urban_central + " urban central water tanks discharger",
bus0=urban_central + " urban central water tanks",
bus1=urban_central + " urban central heat",
carrier="urban central water tanks discharger",
p_nom_extendable=True,
efficiency=costs.at['water tank discharger','efficiency'])
network.madd("Store",
central,
suffix=" central water tank",
bus=central + " central water tanks",
urban_central,
suffix=" urban central water tanks",
bus=urban_central + " urban central water tanks",
e_cyclic=True,
carrier="central water tank",
carrier="urban central water tanks",
e_nom_extendable=True,
standing_loss=1-np.exp(-1/(24.*180.)), # [HP] 180 day time constant for centralised, 3 day for decentralised
capital_cost=costs.at['central water tank storage','fixed']/(1.17e-3*40)) #convert EUR/m^3 to EUR/MWh for 40 K diff and 1.17 kWh/m^3/K
@ -924,61 +950,61 @@ def add_heat(network):
if options["boilers"]:
network.madd("Link",
nodes + " resistive heater",
bus0=nodes,
bus1=nodes + " heat",
carrier="resistive heater",
rural + " rural resistive heater",
bus0=rural,
bus1=rural + " rural heat",
carrier="rural resistive heater",
efficiency=costs.at['decentral resistive heater','efficiency'],
capital_cost=costs.at['decentral resistive heater','efficiency']*costs.at['decentral resistive heater','fixed'],
p_nom_extendable=True)
network.madd("Link",
urban + " urban resistive heater",
bus0=urban,
bus1=urban + " urban heat",
carrier="urban resistive heater",
urban_decentral + " urban decentral resistive heater",
bus0=urban_decentral,
bus1=urban_decentral + " urban decentral heat",
carrier="urban decentral resistive heater",
efficiency=costs.at['decentral resistive heater','efficiency'],
capital_cost=costs.at['decentral resistive heater','efficiency']*costs.at['decentral resistive heater','fixed'],
p_nom_extendable=True)
network.madd("Link",
central + " central resistive heater",
bus0=central,
bus1=central + " urban heat",
urban_central + " urban central resistive heater",
bus0=urban_central,
bus1=urban_central + " urban central heat",
p_nom_extendable=True,
carrier="central resistive heater",
carrier="urban central resistive heater",
capital_cost=costs.at['central resistive heater','efficiency']*costs.at['central resistive heater','fixed'],
efficiency=costs.at['central resistive heater','efficiency'])
network.madd("Link",
nodes + " gas boiler",
rural + " gas boiler",
p_nom_extendable=True,
bus0=["EU gas"]*len(nodes),
bus1=nodes + " heat",
bus0=["EU gas"]*len(rural),
bus1=rural + " rural heat",
bus2="co2 atmosphere",
carrier="gas boiler",
carrier="rural gas boiler",
efficiency=costs.at['decentral gas boiler','efficiency'],
efficiency2=costs.at['gas','CO2 intensity'],
capital_cost=costs.at['decentral gas boiler','efficiency']*costs.at['decentral gas boiler','fixed'])
network.madd("Link",
urban + " urban gas boiler",
urban_decentral + " urban decentral gas boiler",
p_nom_extendable=True,
bus0=["EU gas"]*len(urban),
bus1=urban + " urban heat",
bus0=["EU gas"]*len(urban_decentral),
bus1=urban_decentral + " urban decentral heat",
bus2="co2 atmosphere",
carrier="urban gas boiler",
carrier="urban decentral gas boiler",
efficiency=costs.at['decentral gas boiler','efficiency'],
efficiency2=costs.at['gas','CO2 intensity'],
capital_cost=costs.at['decentral gas boiler','efficiency']*costs.at['decentral gas boiler','fixed'])
network.madd("Link",
central + " central gas boiler",
bus0=["EU gas"]*len(central),
bus1=central + " urban heat",
urban_central + " urban central gas boiler",
bus0=["EU gas"]*len(urban_central),
bus1=urban_central + " urban central heat",
bus2="co2 atmosphere",
carrier="central gas boiler",
carrier="urban central gas boiler",
p_nom_extendable=True,
capital_cost=costs.at['central gas boiler','efficiency']*costs.at['central gas boiler','fixed'],
efficiency2=costs.at['gas','CO2 intensity'],
@ -988,13 +1014,13 @@ def add_heat(network):
#additional bus, to which we can also connect biomass
network.madd("Bus",
central + " central CHP",
carrier="chp")
urban_central + " urban central CHP",
carrier="urban central CHP")
network.madd("Link",
central + " gas to central CHP",
urban_central + " gas to urban central CHP",
bus0="EU gas",
bus1=central + " central CHP",
bus1=urban_central + " urban central CHP",
bus2="co2 atmosphere",
bus3="co2 stored",
efficiency2=costs.at['gas','CO2 intensity']*(1-options["ccs_fraction"]),
@ -1003,19 +1029,19 @@ def add_heat(network):
p_nom_extendable=True)
network.madd("Link",
central + " central CHP electric",
bus0=central + " central CHP",
bus1=central,
carrier="central CHP electric",
urban_central + " urban central CHP electric",
bus0=urban_central + " urban central CHP",
bus1=urban_central,
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",
central + " central CHP heat",
bus0=central + " central CHP",
bus1=central + " urban heat",
carrier="central CHP heat",
urban_central + " urban central CHP heat",
bus0=urban_central + " urban central CHP",
bus1=urban_central + " urban central heat",
carrier="urban central CHP heat",
p_nom_extendable=True,
efficiency=options['chp_parameters']['eta_elec']/options['chp_parameters']['c_v'])
@ -1025,32 +1051,32 @@ def add_heat(network):
network.add("Carrier","solar thermal")
network.madd("Generator",
nodes,
suffix=" solar thermal collector",
bus=nodes + " heat",
carrier="solar thermal",
rural,
suffix=" rural solar thermal collector",
bus=rural + " rural heat",
carrier="rural solar thermal",
p_nom_extendable=True,
capital_cost=costs.at['decentral solar thermal','fixed'],
p_max_pu=solar_thermal[nodes])
p_max_pu=solar_thermal[rural])
network.madd("Generator",
urban,
suffix=" urban solar thermal collector",
bus=urban + " urban heat",
carrier="solar thermal",
urban_decentral,
suffix=" urban decentral solar thermal collector",
bus=urban_decentral + " urban decentral heat",
carrier="urban decentral solar thermal",
p_nom_extendable=True,
capital_cost=costs.at['decentral solar thermal','fixed'],
p_max_pu=solar_thermal[urban])
p_max_pu=solar_thermal[urban_decentral])
network.madd("Generator",
central,
suffix=" central solar thermal collector",
bus=central + " urban heat",
carrier="solar thermal",
urban_central,
suffix=" urban central solar thermal collector",
bus=urban_central + " urban central heat",
carrier="urban central solar thermal",
p_nom_extendable=True,
capital_cost=costs.at['central solar thermal','fixed'],
p_max_pu=solar_thermal[central])
p_max_pu=solar_thermal[urban_central])
def add_biomass(network):
@ -1061,20 +1087,6 @@ def add_biomass(network):
#biomass distributed at country level - i.e. transport within country allowed
cts = pop_layout.ct.value_counts().index
#urban are high density locations
if options["central"]:
urban_cts = pd.Index(["ES","GR","PT","IT","BG"])
urban = pop_layout.index[pop_layout.ct.isin(urban_cts)]
else:
urban_cts = cts
urban = nodes
#central are urban nodes with district heating
central = nodes ^ urban
#central_cts are urban countries with district heating
central_cts = cts ^ urban_cts
biomass_potentials = pd.read_csv(snakemake.input.biomass_potentials,
index_col=0)
@ -1112,21 +1124,27 @@ def add_biomass(network):
bus0=cts + " biogas",
bus1="EU gas",
bus2="co2 atmosphere",
carrier="biogas",
carrier="biogas to gas",
efficiency2=-costs.at['gas','CO2 intensity'],
p_nom_extendable=True)
#with BECCS
network.madd("Link",
central + " solid biomass to CHP",
bus0=central.str[:2] + " solid biomass",
bus1=central + " central CHP",
bus2="co2 atmosphere",
bus3="co2 stored",
efficiency2=-costs.at['solid biomass','CO2 intensity']*options["ccs_fraction"],
efficiency3=costs.at['solid biomass','CO2 intensity']*options["ccs_fraction"],
carrier="solid biomass",
p_nom_extendable=True)
#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")]
#with BECCS
network.madd("Link",
urban_central + " solid biomass to urban central CHP",
bus0=urban_central.str[:2] + " solid biomass",
bus1=urban_central + " urban central CHP",
bus2="co2 atmosphere",
bus3="co2 stored",
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)
def add_industry(network):
@ -1146,6 +1164,7 @@ def add_industry(network):
nodes,
suffix=" process heat",
bus=nodes + " process heat",
carrier="process heat",
p_set = industrial_demand.loc[nodes,"industry process heat"]/8760.)
#with BECCS
@ -1182,6 +1201,7 @@ def add_industry(network):
nodes,
suffix=" shipping",
bus=nodes + " H2",
carrier="shipping",
p_set = industrial_demand.loc[nodes,"shipping H2"]/8760.)
network.add("Bus",
@ -1231,41 +1251,47 @@ def add_industry(network):
efficiency2=costs.at["oil",'CO2 intensity'],
p_nom_extendable=True)
network.add("Load",
"Fischer-Tropsch",
bus="Fischer-Tropsch-demand",
p_set = industrial_demand.loc[nodes,["aviation kerosene","naphtha feedstock"]].sum().sum()/8760.)
network.madd("Load",
["Fischer-Tropsch"],
bus="Fischer-Tropsch-demand",
carrier="Fischer-Tropsch",
p_set = industrial_demand.loc[nodes,["aviation kerosene","naphtha feedstock"]].sum().sum()/8760.)
network.madd("Load",
nodes,
suffix=" industry new electricity",
bus=nodes,
carrier="industry new electricity",
p_set = industrial_demand.loc[nodes,"industry new electricity"]/8760.)
network.add("Load",
"process emissions to atmosphere",
bus="co2 atmosphere",
p_set = -industrial_demand.loc[nodes,"process emissions"].sum()*(1-options["ccs_fraction"])/8760.)
network.madd("Load",
["process emissions to atmosphere"],
bus="co2 atmosphere",
carrier="process emissions to atmosphere",
p_set = -industrial_demand.loc[nodes,"process emissions"].sum()*(1-options["ccs_fraction"])/8760.)
network.add("Load",
"process emissions to stored",
bus="co2 stored",
p_set = -industrial_demand.loc[nodes,"process emissions"].sum()*options["ccs_fraction"]/8760.)
network.madd("Load",
["process emissions to stored"],
bus="co2 stored",
carrier="process emissions to stored",
p_set = -industrial_demand.loc[nodes,"process emissions"].sum()*options["ccs_fraction"]/8760.)
def add_waste_heat(network):
print("adding possibility to use industrial waste heat in district heating")
#AC buses with district heating
central_buses = n.buses.index[n.buses.index.str.contains("central CHP")].str[:-12]
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")]
if options['use_fischer_tropsch_waste_heat']:
n.links.loc[central_buses + " Fischer-Tropsch","bus3"] = central_buses + " urban heat"
n.links.loc[central_buses + " Fischer-Tropsch","efficiency3"] = 0.95 - n.links.loc[central_buses + " Fischer-Tropsch","efficiency"]
if options['use_fischer_tropsch_waste_heat']:
n.links.loc[urban_central + " Fischer-Tropsch","bus3"] = urban_central + " urban central heat"
n.links.loc[urban_central + " Fischer-Tropsch","efficiency3"] = 0.95 - n.links.loc[urban_central + " Fischer-Tropsch","efficiency"]
if options['use_fuel_cell_waste_heat']:
n.links.loc[central_buses + " H2 Fuel Cell","bus2"] = central_buses + " urban heat"
n.links.loc[central_buses + " H2 Fuel Cell","efficiency2"] = 0.95 - n.links.loc[central_buses + " H2 Fuel Cell","efficiency"]
if options['use_fuel_cell_waste_heat']:
n.links.loc[urban_central + " H2 Fuel Cell","bus2"] = urban_central + " urban central heat"
n.links.loc[urban_central + " H2 Fuel Cell","efficiency2"] = 0.95 - n.links.loc[urban_central + " H2 Fuel Cell","efficiency"]
def restrict_technology_potential(n,tech,limit):
@ -1338,6 +1364,8 @@ if __name__ == "__main__":
remove_elec_base_techs(n)
n.loads["carrier"] = "electricity"
add_co2_tracking(n)
add_generation(n)
@ -1347,6 +1375,9 @@ if __name__ == "__main__":
nodal_energy_totals, heat_demand, space_heat_demand, water_heat_demand, ashp_cop, gshp_cop, solar_thermal, transport, avail_profile, dsm_profile, co2_totals, nodal_transport_data = prepare_data(n)
if "nodistrict" in opts:
options["central"] = False
if "T" in opts:
add_transport(n)

View File

@ -138,26 +138,29 @@ def add_chp_constraints(network):
if hasattr(network.links.index,"str") and network.links.index.str.contains("CHP").any():
#also catches central heat buses for district heating
nodes = list(network.links.index[network.links.index.str.contains("CHP electric")].str[:-len(" CHP electric")])
#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")]
def chp_nom(model,node):
return network.links.at[node + " CHP electric","efficiency"]*options['chp_parameters']['p_nom_ratio']*model.link_p_nom[node + " CHP electric"] == network.links.at[node + " CHP heat","efficiency"]*options['chp_parameters']['p_nom_ratio']*model.link_p_nom[node + " CHP heat"]
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"]
network.model.chp_nom = pypsa.opt.Constraint(nodes,rule=chp_nom)
network.model.chp_nom = pypsa.opt.Constraint(urban_central,rule=chp_nom)
def backpressure(model,node,snapshot):
return options['chp_parameters']['c_m']*network.links.at[node + " CHP heat","efficiency"]*model.link_p[node + " CHP heat",snapshot] <= network.links.at[node + " CHP electric","efficiency"]*model.link_p[node + " CHP electric",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(nodes,list(network.snapshots),rule=backpressure)
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 + " CHP heat",snapshot] + model.link_p[node + " CHP electric",snapshot] <= model.link_p_nom[node + " CHP electric"]
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(nodes,list(network.snapshots),rule=top_iso_fuel_line)
network.model.top_iso_fuel_line = pypsa.opt.Constraint(urban_central,list(network.snapshots),rule=top_iso_fuel_line)