make sequestration options configurable

This commit is contained in:
Fabian Neumann 2023-02-16 17:21:58 +01:00
parent 6b8e69cf81
commit ccde2e7f93
5 changed files with 39 additions and 31 deletions

4
.gitignore vendored
View File

@ -51,3 +51,7 @@ doc/_build
*.xls
*.geojson
*.ipynb
data/costs_*

View File

@ -288,7 +288,7 @@ else:
build_biomass_transport_costs_output = {}
if config["sector"].get("sequestration_potential", False):
if config["sector"]["regional_co2_sequestration_potential"]["enable"]:
rule build_sequestration_potentials:
input:
sequestration_potential=HTTP.remote("https://raw.githubusercontent.com/ericzhou571/Co2Storage/main/resources/complete_map_2020_unit_Mt.geojson", keep_local=True),

View File

@ -250,8 +250,15 @@ sector:
coal_cc: false
dac: true
co2_vent: false
allam_cycle: false
SMR: true
sequestration_potential: true # geological co2 storage potential
regional_co2_sequestration_potential:
enable: false # enable regionally resolved geological co2 storage potential
attribute: 'conservative estimate Mt'
include_onshore: false # include onshore sequestration potentials
min_size: 3 # Gt, sites with lower potential will be excluded
max_size: 25 # Gt, max sequestration potential for any one site, TODO research suitable value
years_of_storage: 25 # years until potential exhausted at optimised annual rate
co2_sequestration_potential: 200 #MtCO2/a sequestration potential for Europe
co2_sequestration_cost: 10 #EUR/tCO2 for sequestration of CO2
co2_spatial: false
@ -281,8 +288,8 @@ sector:
gas_network_connectivity_upgrade: 1 # https://networkx.org/documentation/stable/reference/algorithms/generated/networkx.algorithms.connectivity.edge_augmentation.k_edge_augmentation.html#networkx.algorithms.connectivity.edge_augmentation.k_edge_augmentation
gas_distribution_grid: true
gas_distribution_grid_cost_factor: 1.0 #multiplies cost in data/costs.csv
biomass_spatial: false # biomass transport between nodes
biomass_transport: false # biomass transport between nodes
biomass_spatial: false # regionally resolve biomass (e.g. potentials)
biomass_transport: false # allow transport of solid biomass between nodes
conventional_generation: # generator : carrier
OCGT: gas
biomass_to_liquid: false

View File

@ -27,22 +27,17 @@ if __name__ == "__main__":
clusters="181"
)
# TODO move to config.yaml
threshold = 3
include_onshore = False
cf = snakemake.config["sector"]["regional_co2_sequestration_potential"]
gdf = gpd.read_file(snakemake.input.sequestration_potential[0])
regions = gpd.read_file(snakemake.input.regions_offshore)
if include_onshore:
if cf["include_onshore"]:
onregions = gpd.read_file(snakemake.input.regions_onshore)
regions = pd.concat([regions, onregions]).dissolve(by='name').reset_index()
attr = snakemake.config['sector']["sequestration_potential"]
kwargs = dict(attr=attr, threshold=threshold) if isinstance(attr, str) else {}
s = allocate_sequestration_potential(gdf, regions, attr=cf["attribute"], threshold=cf["min_size"])
s = allocate_sequestration_potential(gdf, regions, **kwargs)
s = s.where(s>threshold).dropna()
s = s.where(s>cf["min_size"]).dropna()
s.to_csv(snakemake.output.sequestration_potential)

View File

@ -517,10 +517,9 @@ def add_co2_tracking(n, options):
unit="t_co2"
)
if options["sequestration_potential"]:
# TODO make configurable options
upper_limit = 25000 # Mt
annualiser = 25 # TODO research suitable value
if options["regional_co2_sequestration_potential"]["enable"]:
upper_limit = options["regional_co2_sequestration_potential"]["max_size"] * 1e3 # Mt
annualiser = options["regional_co2_sequestration_potential"]["years_of_storage"]
e_nom_max = pd.read_csv(snakemake.input.sequestration_potential, index_col=0).squeeze()
e_nom_max = e_nom_max.reindex(spatial.co2.locations).fillna(0.).clip(upper=upper_limit).mul(1e6) / annualiser # t
e_nom_max = e_nom_max.rename(index=lambda x: x + " co2 stored")
@ -570,24 +569,25 @@ def add_co2_network(n, costs):
def add_allam(n, costs):
logger.info("Adding Allam cycle generators")
logger.info("Adding Allam cycle gas power plants.")
nodes = pop_layout.index
n.madd("Link",
nodes + " allam",
bus0=spatial.gas.df.loc[nodes, "nodes"].values,
bus1=nodes,
bus2=spatial.co2.df.loc[nodes, "nodes"].values,
carrier="allam",
p_nom_extendable=True,
# TODO: add costs to technology-data
capital_cost=0.6*1.5e6*0.1, # efficiency * EUR/MW * annuity
marginal_cost=2,
efficiency=0.6,
efficiency2=costs.at['gas', 'CO2 intensity'],
lifetime=30.,
)
nodes,
suffix=" allam",
bus0=spatial.gas.df.loc[nodes, "nodes"].values,
bus1=nodes,
bus2=spatial.co2.df.loc[nodes, "nodes"].values,
carrier="allam",
p_nom_extendable=True,
# TODO: add costs to technology-data
capital_cost=0.6*1.5e6*0.1, # efficiency * EUR/MW * annuity
marginal_cost=2,
efficiency=0.6,
efficiency2=costs.at['gas', 'CO2 intensity'],
lifetime=30.,
)
def add_dac(n, costs):
@ -2923,6 +2923,8 @@ if __name__ == "__main__":
if options["co2network"]:
add_co2_network(n, costs)
if options["allam_cycle"]:
add_allam(n, costs)
solver_name = snakemake.config["solving"]["solver"]["name"]