Skip to content

Commit

Permalink
Merge pull request #453 from PyPSA/issue-452
Browse files Browse the repository at this point in the history
Sector Updates
  • Loading branch information
trevorb1 authored Nov 21, 2024
2 parents 9de3439 + af7ab55 commit a0d1dd9
Show file tree
Hide file tree
Showing 33 changed files with 4,082 additions and 1,797 deletions.
10 changes: 5 additions & 5 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ repos:
hooks:
- id: snakefmt

- repo: https://github.com/PyCQA/docformatter
rev: v1.7.5
hooks:
- id: docformatter
args: ["--in-place", "--make-summary-multi-line", "--pre-summary-newline"]
# - repo: https://github.com/PyCQA/docformatter
# rev: v1.7.5
# hooks:
# - id: docformatter
# args: ["--in-place", "--make-summary-multi-line", "--pre-summary-newline"]


- repo: https://github.com/keewis/blackdoc
Expand Down
19 changes: 19 additions & 0 deletions docs/source/datatables/sector_natural_gas.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Configuration Option,Configuration Value ,Description,Constraint ,Applied to
``import.min``,0,No import requirement,Σ(p) >= 0,S2 S1 gas trade
,0.5,Import at least half of historical year value ,Σ(p) >= 5000,S2 S1 gas trade
,1,Import at least half of historical year value ,Σ(p) >= 10000,S2 S1 gas trade
,2,Import at least double the historical year value ,Σ(p) >= 20000,S2 S1 gas trade
``import.max``,0,No imports allowed,Σ(p) <= 0,S2 S1 gas trade
,0.5,Import up to half of historical year value ,Σ(p) <= 5000,S2 S1 gas trade
,1,Import up to the full historical year value ,Σ(p) <= 10000,S2 S1 gas trade
,2,Import up to double the historical year value ,Σ(p) <= 20000,S2 S1 gas trade
,inf,Unlimited Imports ,No constraint added,S2 S1 gas trade
``export.min``,0,No exports requirement,Σ(p) >= 0,S1 S2 gas trade
,0.5,Export at least half of historical year value ,Σ(p) >= 5000,S1 S2 gas trade
,1,Export at least half of historical year value ,Σ(p) >= 10000,S1 S2 gas trade
,2,Export at least double the historical year value ,Σ(p) >= 20000,S1 S2 gas trade
``export.max``,0,No exports allowed,Σ(p) <= 0,S1 S2 gas trade
,0.5,Export up to half of historical year value ,Σ(p) <= 5000,S1 S2 gas trade
,1,Exportup to the historical year value ,Σ(p) <= 10000,S1 S2 gas trade
,2,Export up to double the historical year value ,Σ(p) <= 20000,S1 S2 gas trade
,inf,Unlimited Export ,No constraint added,S1 S2 gas trade
104 changes: 21 additions & 83 deletions workflow/Snakefile
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ configfile: "config/config.api.yaml"
configfile: "config/config.sector.yaml"


# configfile: "config/config.default.yaml"


run = config.get("run", {})
RDIR = run["name"] + "/" if run.get("name") else ""
CDIR = RDIR if not run.get("shared_cutouts") else ""
Expand Down Expand Up @@ -169,8 +172,6 @@ def sector_figures(wildcards):

figs = []

states = INTERCONNECT_2_STATE[config["scenario"]["interconnect"][0]]

if "G" in config["scenario"]["sector"].split("-"):
figs.append(
expand(
Expand All @@ -180,15 +181,6 @@ def sector_figures(wildcards):
figure=FIGURES_SECTOR_NATURAL_GAS,
)
)
figs.append(
expand(
RESULTS
+ "{interconnect}/figures/s{simpl}_c{clusters}/l{ll}_{opts}_{sector}/{s}/emissions/{figure}.png",
**config["scenario"],
figure=FIGURES_SECTOR_EMISSIONS,
s=states,
)
)
figs.append(
expand(
RESULTS
Expand All @@ -200,89 +192,35 @@ def sector_figures(wildcards):
figs.append(
expand(
RESULTS
+ "{interconnect}/figures/s{simpl}_c{clusters}/l{ll}_{opts}_{sector}/{s}/production/{figure}.png",
+ "{interconnect}/figures/s{simpl}_c{clusters}/l{ll}_{opts}_{sector}/system/production/res/{figure}.png",
**config["scenario"],
figure=FIGURES_SECTOR_PRODUCTION,
s=states,
)
)
figs.append(
expand(
RESULTS
+ "{interconnect}/figures/s{simpl}_c{clusters}/l{ll}_{opts}_{sector}/system/production/{figure}.png",
**config["scenario"],
figure=FIGURES_SECTOR_PRODUCTION,
)
)
figs.append(
expand(
RESULTS
+ "{interconnect}/figures/s{simpl}_c{clusters}/l{ll}_{opts}_{sector}/{s}/capacity/{figure}.png",
**config["scenario"],
figure=FIGURES_SECTOR_CAPACITY,
s=states,
)
)
figs.append(
expand(
RESULTS
+ "{interconnect}/figures/s{simpl}_c{clusters}/l{ll}_{opts}_{sector}/system/capacity/{figure}.png",
+ "{interconnect}/figures/s{simpl}_c{clusters}/l{ll}_{opts}_{sector}/system/capacity/res/{figure}.png",
**config["scenario"],
figure=FIGURES_SECTOR_CAPACITY,
)
)
figs.append(
expand(
RESULTS
+ "{interconnect}/figures/s{simpl}_c{clusters}/l{ll}_{opts}_{sector}/{s}/loads/{figure}.png",
**config["scenario"],
figure=FIGURES_SECTOR_LOADS,
s=states,
)
)
figs.append(
expand(
RESULTS
+ "{interconnect}/figures/s{simpl}_c{clusters}/l{ll}_{opts}_{sector}/system/loads/{figure}.png",
**config["scenario"],
figure=FIGURES_SECTOR_LOADS,
)
)
"""
figs.append(
expand(
RESULTS
+ "{interconnect}/figures/s{simpl}_c{clusters}/l{ll}_{opts}_{sector}/{s}/validate/{figure}.png",
**config["scenario"],
figure=FIGURES_SECTOR_VALIDATE,
s=states,
)
)
figs.append(
expand(
RESULTS
+ "{interconnect}/figures/s{simpl}_c{clusters}/l{ll}_{opts}_{sector}/system/validate/{figure}.png",
**config["scenario"],
figure=FIGURES_SECTOR_VALIDATE,
)
)
figs.append(
expand(
RESULTS
+ "{interconnect}/figures/s{simpl}_c{clusters}/l{ll}_{opts}_{sector}/system/validate/{figure}.png",
**config["scenario"],
figure=FIGURES_SYSTEM_VALIDATION,
)
)
"""
figs.append(
expand(
RESULTS
+ "{interconnect}/figures/s{simpl}_c{clusters}/l{ll}_{opts}_{sector}/system/production/{figure}.png",
**config["scenario"],
figure=FIGURES_SYSTEM_PRODUCTION,
)
)
# figs.append(
# expand(
# RESULTS
# + "{interconnect}/figures/s{simpl}_c{clusters}/l{ll}_{opts}_{sector}/system/loads/{figure}.png",
# **config["scenario"],
# figure=FIGURES_SECTOR_LOADS,
# )
# )
# figs.append(
# expand(
# RESULTS
# + "{interconnect}/figures/s{simpl}_c{clusters}/l{ll}_{opts}_{sector}/system/validate/{figure}.png",
# **config["scenario"],
# figure=FIGURES_SECTOR_VALIDATE,
# )
# )
return list(chain(*figs))
return figs

Expand Down
209 changes: 209 additions & 0 deletions workflow/notebooks/docs/service/clustered-load.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import geopandas as gpd\n",
"import pandas as pd\n",
"import pypsa"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"gdf = gpd.read_file(\"Geospatial/regions_onshore_s20_4m.geojson\").set_index(\"name\")\n",
"gdf[\"p\"] = gdf.geometry.centroid\n",
"gdf.plot()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"n = pypsa.Network(\"elec_s20_c4m_ec_lv1.0_8760SEG_E-G.nc\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df = n.loads[n.loads.carrier.str.startswith(\"res\")].copy()\n",
"df[\"cluster\"] = df.bus.map(lambda x: x.split(\" res\")[0])\n",
"loads = df.index.to_list()\n",
"load_map = df[\"cluster\"].to_dict()\n",
"clusters = list(set([x for _, x in load_map.items()]))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"summed_loads = n.loads_t.p_set[df.index].rename(columns=load_map).T.groupby(level=0).sum().T\n",
"summed_loads = summed_loads.sum().to_frame(name=\"load\")\n",
"l = gdf.join(summed_loads)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"l.p.iloc[0].coords[0]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"\n",
"fig, axd = plt.subplot_mosaic(\n",
" [[\"left\", \"top_mid\", \"top_right\"], [\"left\", \"bot_mid\", \"bot_right\"]], figsize=(16, 8), layout=\"constrained\"\n",
")\n",
"\n",
"l.plot(\"load\", ax=axd[\"left\"], legend=True, legend_kwds={\"label\": \"Yearly Energy Load (MWh)\", \"location\": \"left\"})\n",
"\n",
"for idx, row in l.iterrows():\n",
" axd[\"left\"].annotate(text=idx, xy=row[\"p\"].coords[0], horizontalalignment=\"center\")\n",
"\n",
"carrier_map = {\"elec\": \"Electricity\", \"space-heat\": \"Space Heating\", \"water-heat\": \"Water Heating\", \"cool\": \"Cooling\"}\n",
"\n",
"for ax_name, carrier in zip(\n",
" [\"top_mid\", \"top_right\", \"bot_mid\", \"bot_right\"], [\"elec\", \"space-heat\", \"water-heat\", \"cool\"]\n",
"):\n",
" df1 = n.loads_t.p_set[[x for x in loads if x.endswith(carrier)]]\n",
" df1 = df1.rename(columns={x: x.split(\" \")[0] for x in df1.columns})\n",
" df1 = df1.T.groupby(level=0).sum().T\n",
" df1.loc[2030].resample(\"D\").mean().plot(title=carrier_map[carrier], ax=axd[ax_name], xlabel=\"\")\n",
" axd[ax_name].legend(loc=\"upper right\", title=\"Cluster\")\n",
"\n",
"fig.savefig(\"clusterd-load.png\", dpi=300)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import seaborn as sns"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def get_hp_cop(n):\n",
" cops = n.links_t.efficiency\n",
"\n",
" ashp = cops[[x for x in cops.columns if x.endswith(\"ashp\")]]\n",
" gshp = cops[[x for x in cops.columns if x.endswith(\"gshp\")]]\n",
"\n",
" return ashp.join(gshp)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def plot_hp_cop(n: pypsa.Network, state: str = None, **kwargs) -> tuple:\n",
" \"\"\"\n",
" Plots gshp and ashp cops.\n",
" \"\"\"\n",
"\n",
" investment_period = n.investment_periods[0]\n",
"\n",
" cops = get_hp_cop(n).loc[investment_period]\n",
" cops.index = cops.index.map(lambda x: x.replace(year=2018))\n",
"\n",
" fig, axs = plt.subplots(\n",
" nrows=1,\n",
" ncols=2,\n",
" figsize=(16, 6),\n",
" sharey=True,\n",
" )\n",
"\n",
" mapper = {\"ashp\": \"Air Source Heat Pump\", \"gshp\": \"Ground Source Heat Pump\"}\n",
"\n",
" for i, hp in enumerate([\"ashp\", \"gshp\"]):\n",
"\n",
" df = cops[[x for x in cops if x.endswith(hp)]]\n",
" avg = df.mean(axis=1)\n",
"\n",
" palette = sns.color_palette([\"lightgray\"], df.shape[1])\n",
"\n",
" try:\n",
"\n",
" sns.lineplot(\n",
" df,\n",
" color=\"lightgray\",\n",
" legend=False,\n",
" palette=palette,\n",
" ax=axs[i],\n",
" )\n",
" sns.lineplot(avg, ax=axs[i])\n",
"\n",
" axs[i].set_xlabel(\"\")\n",
" axs[i].set_ylabel(\"COP\")\n",
" axs[i].set_title(mapper[hp])\n",
"\n",
" except TypeError: # no numeric data to plot\n",
" # logger.warning(f\"No COP data to plot for {state}\")\n",
" pass\n",
"\n",
" return fig, axs"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"fig, ax = plot_hp_cop(n)\n",
"fig.tight_layout()\n",
"fig.savefig(\"COP\", dpi=300)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "pypsa-usa",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Loading

0 comments on commit a0d1dd9

Please sign in to comment.