Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adaptations to industry demand #317

Merged
merged 26 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
045b0a8
adapt carrier aggregation method
hazemakhalek May 28, 2024
0600f44
Merge branch 'main' into adaptations_to_industry_demand
hazemakhalek May 31, 2024
31a3354
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 31, 2024
e870f90
enhance the industry scripts and adapt the fuel aggregation
hazemakhalek Jun 18, 2024
d410171
Merge branch 'main' into adaptations_to_industry_demand
hazemakhalek Jun 18, 2024
f504501
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 18, 2024
3944831
Update build_base_industry_totals.py
hazemakhalek Jun 24, 2024
2a965ad
Update build_base_energy_totals.py
hazemakhalek Jun 24, 2024
e9cd429
minor bug in build_base_energy_totals
hazemakhalek Jul 17, 2024
a690b66
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 17, 2024
c812db1
Update build_base_industry_totals.py
hazemakhalek Jul 17, 2024
3233fa7
adapt build_base_energy and build_base_industry to params
hazemakhalek Jul 17, 2024
3219a68
add missing param in snakefile
hazemakhalek Jul 17, 2024
eaacba4
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 17, 2024
ab04ea8
fix param in snakefile
hazemakhalek Jul 17, 2024
cfb9d7b
Merge branch 'main' into adaptations_to_industry_demand
hazemakhalek Jul 17, 2024
2a7972e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 17, 2024
92b3c19
reset config.pypsa-earth.yaml
hazemakhalek Jul 17, 2024
68e8888
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 17, 2024
698bda7
Update Snakefile
hazemakhalek Jul 17, 2024
da82c5e
handle exception to avoid reference before assignment error
hazemakhalek Jul 17, 2024
b0cee2a
Update config.test_myopic.yaml to include new parameter
hazemakhalek Jul 18, 2024
e847f45
Update build_base_industry_totals.py
hazemakhalek Jul 19, 2024
230e173
Update Snakefile
hazemakhalek Jul 19, 2024
d73648f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 19, 2024
5f1cac9
Update build_base_industry_totals.py
hazemakhalek Jul 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Snakefile
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ rule build_base_energy_totals:
update_data=config["demand_data"]["update_data"],
base_year=config["demand_data"]["base_year"],
countries=config["countries"],
shift_coal_to_elec=config["sector"]["coal"]["shift_to_elec"],
input:
unsd_paths="data/demand/unsd/paths/Energy_Statistics_Database.xlsx",
output:
Expand Down Expand Up @@ -740,6 +741,7 @@ rule build_base_industry_totals: #default data
#industrial_production_per_country="data/industrial_production_per_country.csv",
#unsd_path="data/demand/unsd/data/",
energy_totals_base="data/energy_totals_base.csv",
transactions_path="data/unsd_transactions.csv",
output:
base_industry_totals="resources/demand/base_industry_totals_{planning_horizons}_{demand}.csv",
threads: 1
Expand Down
2 changes: 2 additions & 0 deletions config.default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ sector:
set_color_shares: false
blue_share: 0.40
pink_share: 0.05
coal:
shift_to_elec: true # If true, residential and services demand of coal is shifted to electricity. If false, the final energy demand of coal is disregarded

international_bunkers: false #Whether or not to count the emissions of international aviation and navigation

Expand Down
39 changes: 39 additions & 0 deletions data/unsd_transactions.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
Transaction;clean_name
consumption not elsewhere specified (industry);other
consumption by food and tobacco ;food and tobacco
consumption by non-metallic minerals ;non-metallic minerals
consumption by non-ferrous metals;non-ferrous metals
consumption by non-metallic minerals;non-metallic minerals
consumption by iron and steel;iron and steel
consumption by paper, pulp and print;paper pulp and print
consumption by food and tobacco;food and tobacco
consumption by chemical and petrochemical;chemical and petrochemical
consumption by machinery;machinery
consumption by textile and leather;textile and leather
consumption by construction;construction
consumption by mining and quarrying;mining and quarrying
consumption by transport equipment ;transport equipment
consumption by non-ferrous metals ;non-ferrous metals
consumption by wood and wood products ;wood and wood products
consumption by machinery ;machinery
consumption by mining and quarrying ;mining and quarrying
consumption by construction ;construction
consumption by textile and leather ;textile and leather
consumption by chemical and petrochemical industry;chemical and petrochemical
consumption by industries not elsewhere specified;other
consumption by non-ferrous metals industry;non-ferrous metals
consumption by non-metallic minerals industry;non-metallic minerals
consumption by mining and quarrying industry;mining and quarrying
consumption by food, beverage and tobacco industry;food and tobacco
consumption by iron and steel industry;iron and steel
consumption by transport equipment industry;transport equipment
consumption by machinery industry;machinery
consumption by wood and wood products industry;wood and wood products
consumption by construction industry;construction
consumption by wood and wood products;wood and wood products
consumption by transport equipment;transport equipment
consumption by food and tobacco industry;food and tobacco
consumption by textile and leather industry;textile and leather
consumption by other manufacturing, construction and non-fuel;other
consumption by chemical and petrochemicalindustry;chemical and petrochemical
consumption by chemical industry;chemical and petrochemical
213 changes: 141 additions & 72 deletions scripts/build_base_energy_totals.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@
import pandas as pd
import py7zr
import requests
from helpers import sets_path_to_root, three_2_two_digits_country
from helpers import (
aggregate_fuels,
get_conv_factors,
sets_path_to_root,
three_2_two_digits_country,
)

_logger = logging.getLogger(__name__)

Expand All @@ -26,20 +31,34 @@ def calc_sector(sector):
# print(country, sector)
df_co = df_yr[df_yr.country == country]

if sector != "navigation":
if sector == "navigation":
hazemakhalek marked this conversation as resolved.
Show resolved Hide resolved
df_sector = df_co.loc[
df["Commodity - Transaction"].str.lower().str.contains(sector)
(df_co["Commodity - Transaction"].str.lower().str.contains(sector))
| (
df_co["Commodity - Transaction"]
.str.lower()
.str.contains("marine bunkers")
)
]
# assert df_yr[df_yr["Commodity - Transaction"].str.contains(sector)]["Unit"].unique() == 'Metric tons, thousand', "Not all quantities have the expected unit: {}".format(expected_unit)
else:

elif sector == "non energy use":
df_sector = df_co.loc[
(df["Commodity - Transaction"].str.lower().str.contains(sector))
(df_co["Transaction"].str.lower().str.contains(sector))
| (
df["Commodity - Transaction"]
df_co["Transaction"]
.str.replace("-", " ")
.str.replace("uses", "use")
.str.lower()
.str.contains("marine bunkers")
.str.contains(sector)
)
]
elif sector == "other energy":
df_sector = df_co.loc[df_co["Transaction"].isin(other_energy)]
else:
df_sector = df_co.loc[
df_co["Commodity - Transaction"].str.lower().str.contains(sector)
]
# assert df_yr[df_yr["Commodity - Transaction"].str.contains(sector)]["Unit"].unique() == 'Metric tons, thousand', "Not all quantities have the expected unit: {}".format(expected_unit)

if df_sector.empty:
if sector == "consumption by households":
Expand Down Expand Up @@ -113,12 +132,15 @@ def calc_sector(sector):
sectors_dfs[sector] = df_sector.copy()

if sector == "consumption by households":
if snakemake.params.shift_coal_to_elec:
condition = (df_sector.Commodity == "Electricity") | (
df_sector.Commodity.isin(coal_fuels)
)
else:
condition = df_sector.Commodity == "Electricity"

energy_totals_base.at[country, "electricity residential"] = round(
df_sector[
(df_sector.Commodity == "Electricity")
| df_sector.Commodity.isin(other_fuels)
].Quantity_TWh.sum(),
4,
df_sector[condition].Quantity_TWh.sum(), 4
)
energy_totals_base.at[country, "residential oil"] = round(
df_sector[df_sector.Commodity.isin(oil_fuels)].Quantity_TWh.sum(), 4
Expand All @@ -143,11 +165,15 @@ def calc_sector(sector):
) * (1 - snakemake.params.space_heat_share)

elif sector == "services":
if snakemake.params.shift_coal_to_elec:
condition = (df_sector.Commodity == "Electricity") | (
df_sector.Commodity.isin(coal_fuels)
)
else:
condition = df_sector.Commodity == "Electricity"

energy_totals_base.at[country, "services electricity"] = round(
df_sector[
(df_sector.Commodity == "Electricity")
| df_sector.Commodity.isin(other_fuels)
].Quantity_TWh.sum(),
df_sector[condition].Quantity_TWh.sum(),
4,
)
energy_totals_base.at[country, "services oil"] = round(
Expand Down Expand Up @@ -176,12 +202,27 @@ def calc_sector(sector):
energy_totals_base.at[country, "total road"] = round(
df_sector.Quantity_TWh.sum(), 4
)
energy_totals_base.at[country, "road electricity"] = round(
df_sector[df_sector.Commodity == "Electricity"].Quantity_TWh.sum(),
4,
)
energy_totals_base.at[country, "road gas"] = round(
df_sector[df_sector.Commodity.isin(gas_fuels)].Quantity_TWh.sum(), 4
)
energy_totals_base.at[country, "road biomass"] = round(
df_sector[
df_sector.Commodity.isin(biomass_fuels)
].Quantity_TWh.sum(),
4,
)
energy_totals_base.at[country, "road oil"] = round(
df_sector[df_sector.Commodity.isin(oil_fuels)].Quantity_TWh.sum(), 4
)

elif sector == "agriculture":
energy_totals_base.at[country, "agriculture electricity"] = round(
df_sector[
(df_sector.Commodity == "Electricity")
| df_sector.Commodity.isin(other_fuels)
].Quantity_TWh.sum(),
4,
)
Expand All @@ -194,6 +235,10 @@ def calc_sector(sector):
].Quantity_TWh.sum(),
4,
)
energy_totals_base.at[country, "agriculture coal"] = round(
df_sector[df_sector.Commodity.isin(coal_fuels)].Quantity_TWh.sum(),
4,
)
# energy_totals_base.at[country, "electricity rail"] = round(df_house[(df_house.Commodity=="Electricity")].Quantity_TWh.sum(), 4)

elif sector == "rail":
Expand Down Expand Up @@ -243,7 +288,64 @@ def calc_sector(sector):
].Quantity_TWh.sum(),
4,
)
elif sector == "other energy":
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These part may be improved (now or in the future) to be more compact code-wise.

if snakemake.params.shift_coal_to_elec:
condition = (df_sector.Commodity == "Electricity") | (
df_sector.Commodity.isin(coal_fuels)
)
else:
condition = df_sector.Commodity == "Electricity"

energy_totals_base.at[country, "other electricity"] = round(
df_sector[condition].Quantity_TWh.sum(), 4
)

energy_totals_base.at[country, "other oil"] = round(
df_sector[df_sector.Commodity.isin(oil_fuels)].Quantity_TWh.sum(), 4
)
energy_totals_base.at[country, "other biomass"] = round(
df_sector[
df_sector.Commodity.isin(biomass_fuels)
].Quantity_TWh.sum(),
4,
)
energy_totals_base.at[country, "other gas"] = round(
df_sector[df_sector.Commodity.isin(gas_fuels)].Quantity_TWh.sum(),
4,
)
energy_totals_base.at[country, "other heat"] = round(
df_sector[df_sector.Commodity.isin(heat)].Quantity_TWh.sum(),
4,
)
elif sector == "non energy use":
if snakemake.params.shift_coal_to_elec:
condition = (df_sector.Commodity == "Electricity") | (
df_sector.Commodity.isin(coal_fuels)
)
else:
condition = df_sector.Commodity == "Electricity"

energy_totals_base.at[country, "non energy electricity"] = round(
df_sector[condition].Quantity_TWh.sum(), 4
)

energy_totals_base.at[country, "non energy oil"] = round(
df_sector[df_sector.Commodity.isin(oil_fuels)].Quantity_TWh.sum(), 4
)
energy_totals_base.at[country, "non energy biomass"] = round(
df_sector[
df_sector.Commodity.isin(biomass_fuels)
].Quantity_TWh.sum(),
4,
)
energy_totals_base.at[country, "non energy gas"] = round(
df_sector[df_sector.Commodity.isin(gas_fuels)].Quantity_TWh.sum(),
4,
)
energy_totals_base.at[country, "non energy heat"] = round(
df_sector[df_sector.Commodity.isin(heat)].Quantity_TWh.sum(),
4,
)
else:
print("wrong sector")

Expand All @@ -257,8 +359,8 @@ def calc_sector(sector):
snakemake = mock_snakemake(
"build_base_energy_totals",
simpl="",
clusters=10,
demand="DF",
clusters=19,
demand="AB",
planning_horizons=2030,
)
sets_path_to_root("pypsa-earth-sec")
Expand Down Expand Up @@ -323,49 +425,11 @@ def calc_sector(sector):
df = df[~df.country.str.contains(",", na=False)].reset_index(drop=True)

# Create a dictionary with all the conversion factors from ktons or m3 to TWh based on https://unstats.un.org/unsd/energy/balance/2014/05.pdf
fuels_conv_toTWh = {
"Gas Oil/ Diesel Oil": 0.01194,
"Motor Gasoline": 0.01230,
"Kerosene-type Jet Fuel": 0.01225,
"Aviation gasoline": 0.01230,
"Biodiesel": 0.01022,
"Natural gas liquids": 0.01228,
"Biogasoline": 0.007444,
"Bitumen": 0.01117,
"Fuel oil": 0.01122,
"Liquefied petroleum gas (LPG)": 0.01313,
"Liquified Petroleum Gas (LPG)": 0.01313,
"Lubricants": 0.01117,
"Naphtha": 0.01236,
"Fuelwood": 0.00254,
"Charcoal": 0.00819,
"Patent fuel": 0.00575,
"Brown coal briquettes": 0.00575,
"Hard coal": 0.007167,
"Other bituminous coal": 0.005556,
"Anthracite": 0.005,
"Peat": 0.00271,
"Peat products": 0.00271,
"Lignite": 0.003889,
"Brown coal": 0.003889,
"Sub-bituminous coal": 0.005555,
"Coke-oven coke": 0.0002778,
"Coke oven coke": 0.0002778,
"Coke Oven Coke": 0.0002778,
"Gasoline-type jet fuel": 0.01230,
"Conventional crude oil": 0.01175,
"Brown Coal Briquettes": 0.00575,
"Refinery Gas": 0.01375,
"Petroleum coke": 0.009028,
"Coking coal": 0.007833,
"Peat Products": 0.00271,
"Petroleum Coke": 0.009028,
}
fuels_conv_toTWh = get_conv_factors("industry")

# Fetch country list and demand base year from the config file
year = snakemake.params.base_year
countries = snakemake.params.countries
# countries = ["NG", "BJ"]

# Filter for the year and country
df_yr = df[df.Year == year]
Expand All @@ -376,21 +440,24 @@ def calc_sector(sector):
energy_totals_base = pd.DataFrame(columns=energy_totals_cols, index=countries)

# Lists that combine the different fuels in the dataset to the model's carriers
oil_fuels = [
"Patent fuel",
"Gas Oil/ Diesel Oil",
"Motor Gasoline",
"Liquefied petroleum gas (LPG)",
]
gas_fuels = [
"Natural gas (including LNG)",
"Gasworks Gas",
"Natural Gas (including LNG)",
(
gas_fuels,
oil_fuels,
biomass_fuels,
coal_fuels,
heat,
electricity,
) = aggregate_fuels("industry")

other_energy = [
"consumption not elsewhere specified (other)",
"consumption not elsewhere specified (other)"
"Consumption not elsewhere specified (other)",
"Consumption by other consumers not elsewhere specified",
"consumption by other consumers not elsewhere specified",
]
biomass_fuels = ["Biodiesel", "Biogases", "Fuelwood", "Biogasoline"]
other_fuels = ["Charcoal", "Brown coal briquettes", "Other bituminous coal"]
heat = ["Heat", "Direct use of geothermal heat", "Direct use of solar thermal heat"]

# non_energy = ['non energy uses', 'non-energy uses', 'consumption for non-energy uses', 'Consumption for non-energy uses', 'non-energy use']
# Create a dictionary to save the data if need to be checked
sectors_dfs = {}

Expand All @@ -403,6 +470,8 @@ def calc_sector(sector):
"navigation",
"agriculture",
"services",
"other energy",
"non energy use",
]
for sector in sectors:
calc_sector(sector)
Expand Down
Loading
Loading