Skip to content

Commit

Permalink
Merge pull request #55 from Margherita-Capitani/Demand_Update_Modeling_
Browse files Browse the repository at this point in the history
Update Model Energy Demand and Fix Problem of Submodels
  • Loading branch information
davide-f authored Nov 12, 2024
2 parents c5832b1 + 0e47cfd commit d800196
Show file tree
Hide file tree
Showing 16 changed files with 363 additions and 294 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci-linux.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,12 @@ jobs:
id: cache
with:
path: ${{ matrix.prefix }}
key: ${{ matrix.label }}-conda-${{ hashFiles('pypsa-earth/envs/environment.yaml') }}-${{ env.DATE }}-${{ env.CACHE_NUMBER }}
key: ${{ matrix.label }}-conda-${{ hashFiles('envs/environment.yaml') }}-${{ env.DATE }}-${{ env.CACHE_NUMBER }}

- name: Update environment due to outdated or unavailable cache
if: steps.cache.outputs.cache-hit != 'true'
run: |
mamba env update -n pypsa-earth -f pypsa-earth/envs/environment.yaml
mamba env update -n pypsa-earth -f envs/environment.yaml
conda activate pypsa-earth
pip install rampdemand
Expand Down
3 changes: 2 additions & 1 deletion Snakefile
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ rule ramp_build_demand_profile:
rule build_demand:
params:
tier=config["tier"],
snapshots=config["snapshots"],
build_demand_model=config["build_demand_type"],
input:
**{
Expand Down Expand Up @@ -225,7 +226,7 @@ rule build_renewable_profiles:
"data/copernicus/PROBAV_LC100_global_v3.0.1_2019-nrt_Discrete-Classification-map_EPSG-4326.tif"
),
gebco=pypsaearth("data/gebco/GEBCO_2021_TID.nc"),
country_shapes=pypsaearth("resources/shapes/country_shapes.geojson"),
country_shapes="resources/shapes/microgrid_shapes.geojson",
offshore_shapes=pypsaearth("resources/shapes/offshore_shapes.geojson"),
hydro_capacities="pypsa-earth/data/hydro_capacities.csv",
eia_hydro_generation="pypsa-earth/data/eia_hydro_annual_generation.csv",
Expand Down
12 changes: 6 additions & 6 deletions config.distribution.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ countries: ["NG"]
year: "2019" # Year setting allows the choice of which data to download (es. Worldpop_data)

snapshots:
start: "2013-01-01"
end: "2014-01-01"
start: "2013-03-01"
end: "2013-03-07"
inclusive: "left" # end is not inclusive

ramp:
Expand All @@ -58,9 +58,9 @@ house_area_limit:
build_demand_type:
type: 0
# type allows to select the mode by which the microgrid demand profile is generated.
# 1 = a predetermined hourly profile is used
# 2 = an average hourly profile is calculated by exploiting the ramp tool
# 3 = an average hourly profile and its standard deviation is calculated using the ramp tool,
# 0 = a predetermined hourly profile is used
# 1 = an average hourly profile is calculated by exploiting the ramp tool
# 2 = an average hourly profile and its standard deviation is calculated using the ramp tool,
# and both quantities are used to calculate demand.

# definition of the Coordinate Reference Systems
Expand All @@ -79,7 +79,7 @@ electricity:
H2: 168

extendable_carriers:
Generator: [solar, onwind]
Generator: [solar, onwind, diesel]
StorageUnit: ["lithium", "lead acid"]
conventional_carriers: [diesel]

Expand Down
12 changes: 10 additions & 2 deletions data/costs.csv
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,9 @@ battery inverter,2030,lifetime,20,years,budischak2013;
battery inverter,2030,efficiency,0.9,per unit charge/discharge,budischak2013; Lund and Kempton (2008) http://dx.doi.org/10.1016/j.enpol.2008.06.007
battery inverter,2030,FOM,3,%/year,budischak2013;
lithium,2030,investment,192,USD/kWh,budischak2013;
lead acid,2030,lifetime,15,years,budischak2013;
lithium,2030,lifetime,15,years,b;
lead acid,2030,lifetime,5,years,b;
lead acid,2030,investment,150,USD/kWh,bu;
decentral air-sourced heat pump,2030,investment,1050,EUR/kWth,HP; Palzer thesis
decentral air-sourced heat pump,2030,lifetime,20,years,HP; Palzer thesis
decentral air-sourced heat pump,2030,FOM,3.5,%/year,Palzer thesis;
Expand Down Expand Up @@ -193,4 +195,10 @@ HVDC submarine,2030,FOM,2,%/year,Hagspiel;
HVDC inverter pair,2030,investment,150000,EUR/MW,Hagspiel;
HVDC inverter pair,2030,lifetime,40,years,Hagspiel;
HVDC inverter pair,2030,FOM,2,%/year,Hagspiel;
diesel,2030,investment,400,EUR/kWel,DIW DataDoc http://hdl.handle.net/10419/80348;
diesel,2030,investment,400,EUR/kWel,DIW;
diesel,2030,efficiency,0.30,per unit,DIW ;
diesel,2030,VOM,0.5,EUR/MWhel,DIW;
diesel,2030,fuel,100,USD/MWhth,DIW;
MVAC overhead,2030,investment,40,EUR/MW/km, ;
MVAC overhead,2030,lifetime,40,years, ;
MVAC overhead,2030,FOM,2,%/year, ;
Binary file modified data/ramp/Tier1.xlsx
Binary file not shown.
Binary file modified data/ramp/Tier2.xlsx
Binary file not shown.
Binary file modified data/ramp/Tier3.xlsx
Binary file not shown.
Binary file modified data/ramp/Tier4.xlsx
Binary file not shown.
Binary file modified data/ramp/Tier5.xlsx
Binary file not shown.
91 changes: 91 additions & 0 deletions envs/environment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# SPDX-FileCopyrightText: PyPSA-Earth and PyPSA-Eur Authors
#
# SPDX-License-Identifier: AGPL-3.0-or-later

name: pypsa-earth
channels:
- conda-forge
- bioconda
- gurobi
dependencies:
- python>=3.8
- pip
- mamba # esp for windows build

- pypsa>=0.24, <0.25
# - atlite>=0.2.4 # until https://github.com/PyPSA/atlite/issues/244 is not merged
- dask
- powerplantmatching
- earth-osm>=2.1
- atlite

# Dependencies of the workflow itself
- xlrd
- openpyxl
- seaborn
- snakemake-minimal<8
- memory_profiler
- ruamel.yaml<=0.17.26
- pytables
- lxml
- numpy
- pandas
- geopandas>=0.11.0, <=0.14.3
- fiona<1.10.0
- xarray>=2023.11.0, <2023.12.0
- netcdf4
- networkx
- scipy
- pydoe2
- shapely!=2.0.4
- pre-commit
- pyomo
- matplotlib<=3.5.2
- reverse-geocode
- country_converter
- pyogrio
- numba
- py7zr

# Keep in conda environment when calling ipython
- ipython
# Jupyter notebook requirement
- ipykernel
- jupyterlab

# GIS dependencies:
- cartopy
- descartes
- rasterio!=1.2.10, <=1.3.11
- rioxarray

# Plotting
- geoviews
- hvplot
- graphviz
- contextily
- graphviz

# PyPSA-Eur-Sec Dependencies
- geopy
- tqdm
- pytz
- country_converter

# Cloud download
# - googledrivedownloader # Commented until https://github.com/ndrplz/google-drive-downloader/pull/28 is merged: PR installed using pip

# Default solver for tests (required for CI)
- glpk
- ipopt
- gurobi

- pip:
- earth-osm>=2.2 # until conda release it out
- powerplantmatching>=0.5.19 # until conda release it out
- rampdemand
- git+https://github.com/davide-f/google-drive-downloader@master # google drive with fix for virus scan
- git+https://github.com/FRESNA/vresutils@master # until new pip release > 0.3.1 (strictly)
- tsam>=1.1.0
- chaospy # lastest version only available on pip
- fake_useragent
2 changes: 1 addition & 1 deletion resources/powerplants.csv
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
,Name,Fueltype,Technology,Set,Country,Capacity,Efficiency,Duration,Volume_Mm3,DamHeight_m,StorageCapacity_MWh,DateIn,DateRetrofit,DateOut,lat,lon,EIC,projectID,bus
1,New_Diesel_Generator,Diesel,,PP,SL,14.0,,0.0,0.0,0.0,0.0,1986,1986.0,2031,-21.1667,27.5167,{nan},{'GPD': {'WRI1023018'}},bus_9
1,New_Diesel_Generator,Diesel,,PP,SL,0.0,,0.0,0.0,0.0,0.0,1986,1986.0,2031,-21.1667,27.5167,{nan},{'GPD': {'WRI1023018'}},bus_9
46 changes: 26 additions & 20 deletions scripts/add_electricity.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,20 @@ def _add_missing_carriers_from_costs(n, costs, carriers):

def load_costs(tech_costs, config, elec_config, Nyears=1):
"""
set all asset costs and other parameters
Set all asset costs and other parameters.
"""
idx = pd.IndexSlice
costs = pd.read_csv(tech_costs, index_col=list(range(3))).sort_index()

# correct units to MW and EUR
costs.loc[costs.unit.str.contains("/kW"), "value"] *= 1e3
costs.loc[costs.unit.str.contains("USD"), "value"] *= config["USD2013_to_EUR2013"]
costs.loc[
costs.unit.str.contains("/kWel"), "value"
] *= 1e3 # Convert EUR/kW to EUR/MW
costs.loc[
costs.unit.str.contains("/kWh"), "value"
] *= 1e3 # Convert EUR/kWh to EUR/MWh
costs.loc[costs.unit.str.contains("USD"), "value"] *= config[
"USD2013_to_EUR2013"
] # Convert USD to EUR

costs = (
costs.loc[idx[:, config["year"], :], "value"]
Expand Down Expand Up @@ -149,17 +156,13 @@ def costs_for_storage(store, link1, link2=None, max_hours=1.0):

max_hours = elec_config["max_hours"]
costs.loc["battery"] = costs_for_storage(
costs.loc[
"lithium"
], # line 119 in file costs.csv' which was battery storage was modified into lithium (same values left)
costs.loc["lithium"],
costs.loc["battery inverter"],
max_hours=max_hours["battery"],
)
max_hours = elec_config["max_hours"]

costs.loc["battery"] = costs_for_storage(
costs.loc[
"lead acid"
], # line 120 in file 'costs.csv' which was battery storage was modified into lithium (same values left)
costs.loc["lead acid"],
costs.loc["battery inverter"],
max_hours=max_hours["battery"],
)
Expand Down Expand Up @@ -260,33 +263,28 @@ def attach_conventional_generators(
conventional_config,
conventional_inputs,
):
# Create a set of all conventional and extendable carriers
carriers = set(conventional_carriers) | set(extendable_carriers["Generator"])

# Add any missing carriers from the costs data to the "carriers" variable
_add_missing_carriers_from_costs(n, costs, carriers)

# Filter the ppl dataframe to only include the relevant carriers
ppl = (
ppl.query("carrier in @carriers")
.join(costs, on="carrier", rsuffix="_r")
.rename(index=lambda s: "C" + str(s))
)
ppl["efficiency"] = ppl.efficiency.fillna(ppl.efficiency)

# Get the index of the buses in the power network
buses_i = n.buses.index

# Add conventional generators to each bus in the power network (one for microgrid)

n.madd(
"Generator",
ppl.index,
carrier=ppl.carrier,
bus=ppl.bus,
p_nom_min=ppl.p_nom.where(ppl.carrier.isin(conventional_carriers), 0),
p_nom=ppl.p_nom.where(ppl.carrier.isin(conventional_carriers), 0),
p_nom_extendable=ppl.carrier.isin(extendable_carriers["Generator"]),
p_nom_extendable=ppl.carrier.isin(extendable_carriers["Generator"])
| (ppl.carrier == "diesel"),
efficiency=ppl.efficiency,
marginal_cost=ppl.marginal_cost,
capital_cost=ppl.capital_cost,
Expand All @@ -295,7 +293,7 @@ def attach_conventional_generators(
)

for carrier in conventional_config:
# Generators with technology affected
# Generatori con tecnologia influenzata
idx = n.generators.query("carrier == @carrier").index

for attr in list(set(conventional_config[carrier]) & set(n.generators)):
Expand All @@ -310,7 +308,7 @@ def attach_conventional_generators(
n.generators.loc[idx].bus.map(bus_values).dropna()
)
else:
# Single value affecting all generators of technology k indiscriminately of country
# Single value affecting all k technology generators regardless of country.
n.generators.loc[idx, attr] = values


Expand Down Expand Up @@ -357,6 +355,12 @@ def attach_load(n, load_file, tech_modelling):
n.madd("Load", demand_df.columns, bus=demand_df.columns, p_set=demand_df)


def update_transmission_costs(n, costs, length_factor=1.0, simple_hvdc_costs=False):
n.lines["capital_cost"] = (
n.lines["length"] * length_factor * costs.at["MVAC overhead", "capital_cost"]
)


if __name__ == "__main__":
if "snakemake" not in globals():
from _helpers_dist import mock_snakemake
Expand Down Expand Up @@ -419,4 +423,6 @@ def attach_load(n, load_file, tech_modelling):
snakemake.config["tech_modelling"]["load_carriers"],
)

update_transmission_costs(n, costs, length_factor=1.0, simple_hvdc_costs=False)

n.export_to_netcdf(snakemake.output[0])
Loading

0 comments on commit d800196

Please sign in to comment.