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

Add "other" industry demand #355

Merged
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a2b7d35
Initial addition of 'other' industries
Apr 10, 2024
547f66d
Add chemicals industry subsector
Apr 10, 2024
3d4c3ca
Merge remote-tracking branch 'ivachen/add-industry-module' into ivach…
Apr 11, 2024
0904879
Pre-commit formatting
Apr 11, 2024
1a02a58
Add to CHANGELOG
Apr 11, 2024
bb9b95f
Merge changes in the main industry method
Apr 11, 2024
7acc8c8
Merge remote-tracking branch 'ivachen/ivachen/add-chemical-industry' …
irm-codebase Apr 11, 2024
368be03
Merge remote-tracking branch 'ivachen/add-industry-module' into add-o…
irm-codebase Apr 11, 2024
657b50f
fix configuration file merge conflicts
irm-codebase Apr 11, 2024
34f5c45
Fixed other industry, now it is working
Apr 11, 2024
bffdfbf
Add to CHANGELOG
Apr 11, 2024
16b5995
Merge branch 'add-industry-module' into add-other-industry-demand
irm-codebase Apr 23, 2024
e23a4a4
Convert to xarray and add flexible config.
irm-codebase Apr 26, 2024
dd446c2
Merge remote-tracking branch 'origin/develop' into add-other-industry…
irm-codebase May 14, 2024
e6068a0
Update JRC processing. Add general industry module improvements.
irm-codebase May 15, 2024
7f0165c
Merge remote-tracking branch 'origin/develop' into add-other-industry…
irm-codebase Jun 11, 2024
67bcc6d
Improve configuration naming, improve generic processing
irm-codebase Jun 11, 2024
56306e0
Fixed script names
irm-codebase Jun 11, 2024
de2ba7f
Naming fixes
irm-codebase Jun 11, 2024
f734975
PR fixes: better naming, better rules, more assert checks
irm-codebase Jul 4, 2024
18fd2c9
ensure scripts are re-run for utils changes
irm-codebase Jul 4, 2024
1fdc6ea
Small assert fix, updated filenames
irm-codebase Jul 5, 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: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

### Added (models)

* **ADD** industry module and steel industry energy demand processing. NOT CONNECTED TO THE MAIN WORKFLOW. Industry sectors pending: chemical, "other". (Fixes #308, #310, #347, #345 and #346)
* **ADD** industry module and steel industry energy demand processing. NOT CONNECTED TO THE MAIN WORKFLOW. Industry sectors pending: chemical. (Fixes #308, #309, #310, #347, #345 and #346)
Copy link
Member

Choose a reason for hiding this comment

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

Should this be "ADD industry module including steel and other industry energy demand"?

Copy link
Contributor

Choose a reason for hiding this comment

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

Updated it with a simpler message. I'll add chemical industry once that is done.


* **ADD** Spatial resolution that aligns with the regions defined by the [e-Highway 2050 project](https://cordis.europa.eu/project/id/308908/reporting) (`ehighways`) (#370).

Expand Down
7 changes: 6 additions & 1 deletion modules/industry/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,10 @@ industry:
placeholder-out1:
placeholder-out2:
params:
steel:
non-generic-categories: ["Iron and steel", "Chemicals Industry"]
Copy link
Member

Choose a reason for hiding this comment

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

I'm still concerned that these will cause confusion down the line. How about "discrete-categories" and "merged-categories"?

Copy link
Member

Choose a reason for hiding this comment

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

what about "explicit-categories" or "explicit-subsectors" or even "explicitly-modelled-subsectors"?

Copy link
Member

Choose a reason for hiding this comment

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

I thought of "explicit" initially too. I then had a look in the dictionary and decided it wasn't quite right (it's more about leaving nothing implied). I'm not sure that "discrete" is right either. "separate"? "independent"?

Copy link
Contributor

@irm-codebase irm-codebase Jun 30, 2024

Choose a reason for hiding this comment

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

Hmmm... I also struggled with names. A good name has to do two things:

  • Specify that these are specific / individual to a given category.
  • Imply that all the rests will go to the "other" / generic / merged.

Here are words with the antonym, based on your comments.

  • Specific / generic categories
  • Separate / combined categories < --- I like this one the best.
  • Independent / dependent categories
  • Explicit / implicit categories
  • Discrete / joined categories

I suggest "separate-category-processing" and "combined-category-processing".

Copy link
Member

Choose a reason for hiding this comment

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

I personally think "subsectors" is clearer, because "category" is generic. "category" is also an implementation detail: should we move to a different data source than JRC, that name would change. Anyways, "category" is fine by me.

I like the "separate" and "combined" distinction!

Copy link
Contributor

Choose a reason for hiding this comment

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

@timtroendle : I also do not like category, but keeping the code close to the data helps in this case because JRC-IDEES is already hard to wrap your head around due to the amount of columns it has (sector/category/subcategory/process/energy type...)

A different data source is going to require a different approach. This (and the JRC module above it) are just very tied to how the data was constructed. I think this is unavoidable for things as heterogeneous as industry.

Copy link
Member

Choose a reason for hiding this comment

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

Agreed, "Separate" / "combined" sounds good!

steel-config:
recycled-steel-share: 0.5 # % of recycled scrap steel for H-DRI
generic-config:
Copy link
Member

Choose a reason for hiding this comment

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

"merged-categories-config"?

final-energy-method: "by priority"
final-energy-carriers: ["Electricity", "Natural gas (incl. biogas)", "Diesel oil (incl. biofuels)"]
useful-demands: ["Low enthalpy heat"]
52 changes: 31 additions & 21 deletions modules/industry/industry.smk
Original file line number Diff line number Diff line change
Expand Up @@ -13,36 +13,46 @@ validate(config, "./schema.yaml")

# Ensure rules are defined in order.
# Otherwise commands like "rules.rulename.output" won't work!
rule steel_industry:
message: "Calculate energy demand for the 'Iron and steel' sector in JRC-IDEES."
if "Iron and steel" in config["params"]["non-generic-categories"]:
Copy link
Member

Choose a reason for hiding this comment

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

The condition doesn't seem necessary to me. Instead of making the rule conditional, make the inputs to a rule downstream conditional.

So, if "iron and steel" is in the config, then a downstream rule will require the file f"{BUILD_PATH}/annual_demand_steel.nc". You will need that anyways, right? Would be good to see how this is integrated eventually.

rule steel_processing:
message: "Calculate energy demand for the 'Iron and steel' sector in JRC-IDEES."
conda: CONDA_PATH
params:
steel_config = config["params"]["steel-config"]
input:
Copy link
Member

Choose a reason for hiding this comment

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

You are using both the "filling.py" and "jrc_idees_parser.py" scripts in this rule and Snakemake isn't aware of these dependencies. You should add both scripts to the input of this file so that the rule gets triggered when they are changed.

Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a way to tell snakemake to "monitor" a full folder? hard coding every-single utility file seems very brittle.

Copy link
Member

Choose a reason for hiding this comment

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

I think yes, but you also don't want to monitor a full folder, right? I agree that linking each file individually isn't ideal, but that's all you can do.

That's why we keep scripts as self-contained as possible. If necessary, we move things to the lib, which also circumvents this problem by providing updates through the environment.

Copy link
Contributor

@irm-codebase irm-codebase Jul 3, 2024

Choose a reason for hiding this comment

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

I think moving things to /lib actually makes things worse: it becomes a common dependency across all the environments that use it, diminishing their benefit. You can end up in a situation were one environment requires a /lib update that breaks others.

On the other hand, making self-contained scripts bloats code and leads to repeated functionality.

Copy link
Contributor

Choose a reason for hiding this comment

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

I will add them for now, but this approach worries me.
An alternative is to move stuff out, and import them with a set tag.
If something is broken, then the focus should be in doing another release of that workflow.

module industry_workflow:
    snakefile:
        github("calliope/industry-smk", path="workflow/Snakefile", tag="v1.0.0")
    config: "config/industry.yaml"

use rule * from other_workflow as industry_*

But that's for the future, maybe.

path_energy_balances = config["inputs"]["path-energy-balances"],
path_cat_names = config["inputs"]["path-cat-names"],
path_carrier_names = config["inputs"]["path-carrier-names"],
path_jrc_industry_energy = config["inputs"]["path-jrc-industry-energy"],
path_jrc_industry_production = config["inputs"]["path-jrc-industry-production"],
output:
path_output = f"{BUILD_PATH}/annual_demand_steel.nc"
script: f"{SCRIPT_PATH}/steel_processing.py"

if "Chemicals Industry" in config["params"]["non-generic-categories"]:
Copy link
Member

Choose a reason for hiding this comment

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

As above.

rule chemicals_processing:
message: "."
conda: CONDA_PATH
params:
input:
output:
script: f"{SCRIPT_PATH}/chemicals_processing.py"

rule generic_processing:
message: "Calculate energy demand for all other industry sectors in JRC-IDEES."
brynpickering marked this conversation as resolved.
Show resolved Hide resolved
conda: CONDA_PATH
params:
config_steel = config["params"]["steel"]
non_generic_categories = config["params"]["non-generic-categories"],
generic_config = config["params"]["generic-config"],
input:
Copy link
Member

Choose a reason for hiding this comment

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

As above, this rule needs the scripts that are imported as "input" here.

Copy link
Contributor

Choose a reason for hiding this comment

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

This was added to the "combine" rule.

Copy link
Member

Choose a reason for hiding this comment

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

For the sake of being explicit rather than implicit, I would add them here, too.

Copy link
Member

Choose a reason for hiding this comment

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

Also, the "combine" rule is downstream of this, so this won't work, right? I would definitely make the dependencies explicit, then you do not even have to think about this at all.

path_energy_balances = config["inputs"]["path-energy-balances"],
Copy link
Member

Choose a reason for hiding this comment

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

Since inputs are all paths, I tend to prefer not prepending with path_ here and path- in the config.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd like to keep path to avoid confusion between variables holding data and those holding strings.
A bit more explicit.

Copy link
Member

Choose a reason for hiding this comment

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

but if all inputs hold strings...? How about config["input-paths"]["energy-balances"] etc?

path_cat_names = config["inputs"]["path-cat-names"],
path_carrier_names = config["inputs"]["path-carrier-names"],
path_jrc_industry_energy = config["inputs"]["path-jrc-industry-energy"],
path_jrc_industry_production = config["inputs"]["path-jrc-industry-production"],
output:
path_output = f"{BUILD_PATH}/annual_demand_steel.nc"
script: f"{SCRIPT_PATH}/steel_industry.py"

rule chemical_industry:
message: "."
conda: CONDA_PATH
params:
input:
output:
script: f"{SCRIPT_PATH}/chemicals.py"

rule other_industry:
message: "."
conda: CONDA_PATH
params:
input:
output: f"{BUILD_PATH}/other_industry.csv"
script: f"{SCRIPT_PATH}/other_industry.py"
path_output = f"{BUILD_PATH}/annual_demand_generic.nc"
script: f"{SCRIPT_PATH}/generic_processing.py"
Copy link
Member

Choose a reason for hiding this comment

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

"merged_category_processing.py"? I would always have category added to whatever adjective we choose!

Copy link
Member

Choose a reason for hiding this comment

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

Agree. Why not use "subsector" instead of "category"?

Copy link
Member

Choose a reason for hiding this comment

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

@irm-codebase is using "category" as it aligns with the JRC-IDEES naming convention. I don't really mind if it's subsector or category, so long as it remains the same throughout the whole submodule.

Copy link
Contributor

Choose a reason for hiding this comment

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

@timtroendle: Bryn is right on this one. Category is not a word we use often, but it makes sense int the context of JRC-IDEES data. I'd like to keep it that way.

Copy link
Member

Choose a reason for hiding this comment

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

Will it become subsector at some point in the module, as it gets closer to being a Calliope model input?

Copy link
Contributor

Choose a reason for hiding this comment

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

that would make sense! the idea is:
jrc categories -> specific/combined scripts -> combine/scale/disaggregate scripts -> calliope subsector


# rule combine_and_scale:
# message: "."
Expand Down
36 changes: 35 additions & 1 deletion modules/industry/schema.yaml
Copy link
Contributor

Choose a reason for hiding this comment

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

All the requested name changes show here, too.

Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,14 @@ properties:
additionalProperties: false
description: Parameters allow users to configure module behaviour.
properties:
steel:
non-generic-categories:
type: array
description: "Specifies which JRC industry categories will be processed separately."
uniqueItems: true
items:
type: string
enum: ["Iron and steel", "Chemicals Industry"]
steel-config:
type: object
additionalProperties: false
description: "Parameters specific to the 'Iron and steel' industry category."
Expand All @@ -48,3 +55,30 @@ properties:
description: "Share of recycled metal in the H-DRI steel process."
minimum: 0
maximum: 1
generic-config:
type: object
additionalProperties: false
description: "Parameters for default/generic category processing."
properties:
final-energy-method:
description: |
Processing method for final-demand.
- "by priority": will take the carriers specified in "final-energy-carriers" in order of importance (first subtracts from second, etc.).
- "keep everything": will keep all the final carrier demands with no assumptions.
type: string
enum: ["by priority", "keep everything"]
final-energy-carriers:
type: array
description: "Final energy carriers to take, if relevant."
uniqueItems: true
items:
type: string
useful-demands:
type: array
description: |
Demands to select from 'useful' rather than 'final' energy consumption data.
Accepts any pre-processed JRC IDEES 'subsection' names.
Always subtracted from 'final' energy demand to avoid double-counting.
uniqueItems: true
items:
type: string
142 changes: 142 additions & 0 deletions modules/industry/scripts/generic_processing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
from typing import Optional

import pandas as pd
import xarray as xr
from utils import filling
from utils import jrc_idees_parser as jrc


def get_generic_demand(
non_generic_categories: list,
generic_config: dict,
path_energy_balances: str,
path_cat_names: str,
path_carrier_names: str,
path_jrc_industry_energy: str,
path_jrc_industry_production: str,
path_output: Optional[str] = None,
) -> xr.DataArray:
"""Processing of industry categories not selected for individual processing.

Merges all energy demand into a single `generic` category using a configurable data processing pipeline.

Args:
non_generic_categories (list): categories with separate processing (will be ignored).
generic_config (dict): configuration for generic category processing.
path_energy_balances (str): country energy balances (usually from eurostat).
path_cat_names (str): eurostat category mapping file.
path_carrier_names (str): eurostat carrier name mapping file.
path_jrc_industry_energy (str): jrc country-specific industrial energy demand file.
path_jrc_industry_production (str): jrc country-specific industrial production file.
path_output (str): location of steel demand output file.

Returns:
pd.DataFrame: dataframe with industrial demand per country.
"""
# Load data
energy_balances_df = pd.read_csv(
path_energy_balances, index_col=[0, 1, 2, 3, 4]
).squeeze("columns")
cat_names_df = pd.read_csv(path_cat_names, header=0, index_col=0)
carrier_names_df = pd.read_csv(path_carrier_names, header=0, index_col=0)
jrc_energy = xr.open_dataset(path_jrc_industry_energy)
jrc_prod = xr.open_dataarray(path_jrc_industry_production)

# Remove data from all specifically processed industries
cat_names_df = cat_names_df[~cat_names_df["jrc_idees"].isin(non_generic_categories)]
Copy link
Member

Choose a reason for hiding this comment

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

Would it make sense to explicitly list the "generic_categories"/"generically_modelled_subsectors" instead of using all that are non_generic?

This would (1) document better which subscectors are included here, (2) safe-guard that list to possible changes in the list in the future.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd rather avoid that, because it introduces the risk of not processing an added category.
Besides, JRC-IDESS is unfortunately quite old (2015), and this processing is very tied to it. Do not see this is a future issue.

I have my sights on this other dataset: https://iopscience.iop.org/article/10.1088/2753-3751/ad4e39
but it is going to require a different module with its own steps.

jrc_energy = jrc_energy.drop_sel(cat_name=non_generic_categories)
jrc_prod = jrc_prod.drop_sel(cat_name=non_generic_categories)

# Process data:
# Extract useful dem. -> remove useful dem. from rest -> extract final dem.
Copy link
Member

Choose a reason for hiding this comment

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

dem -> demand

selected_useful = generic_config["useful-demands"]
other_useful_demand = jrc.convert_subsection_demand_to_carrier(
jrc_energy, selected_useful
)

final_method = generic_config["final-energy-method"]
jrc_energy = jrc_energy.drop_sel(subsection=selected_useful)

match final_method:
case "by priority":
other_final_demand = transform_final_demand_by_priority(
jrc_energy, generic_config["final-energy-carriers"]
)
case "keep everything":
Copy link
Member

Choose a reason for hiding this comment

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

I assume this doesn't lead to any double counting?

Copy link
Member

Choose a reason for hiding this comment

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

An assert statement would be helpful.

Copy link
Contributor

Choose a reason for hiding this comment

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

@brynpickering it shouldn't. It's basically "assume nothing, do nothing with the data and just give me the final demand.

If a useful demand is requested, the lines above should remove it. So no double counting is possible.

other_final_demand = jrc_energy["final"].sum(["section", "subsection"])
other_final_demand = jrc.standardize(other_final_demand, "twh")
case _:
raise ValueError(f"Unsupported final energy method: {final_method}.")

# Combine and fill missing countries
other_demand = xr.concat(
[other_useful_demand, other_final_demand], dim="carrier_name"
)

other_demand = filling.fill_missing_countries_years(
energy_balances_df, cat_names_df, carrier_names_df, other_demand
)

other_demand = jrc.standardize(other_demand, "twh")

if path_output:
Copy link
Member

Choose a reason for hiding this comment

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

What is this for? If it's needed, than the typt hint of the return type in the function signature must be updated.

Copy link
Contributor

Choose a reason for hiding this comment

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

if you mean path_output, because the function just returns an xarray (to aid in testing). The file is saved only as an option.

Otherwise, the function would always return a None, making testing it harder.

Copy link
Member

Choose a reason for hiding this comment

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

I needed for testing purposes, I'd recommend to let the function return a dataset which is stored somewhere else, as discussed in the last dev call. Otherwise you increase complexity of the function signature.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm a bit puzzled. That is already what this is doing: the return other_demand is an xarray. You could choose to save it or evaluate it directly in a test.

I'll just remove it.

other_demand.to_netcdf(path_output)

return other_demand


def transform_final_demand_by_priority(
jrc_energy: xr.Dataset, carrier_priority: list[str]
) -> xr.DataArray:
"""Transform final demand of generic categories by giving priority to certain carriers.

Steps:
1. Assume that all demand that could consume a carrier will be met by said carrier.
2. Drop overlapping consumption so that demand is met by carriers with the given priority.
3. Combine.

E.g., if carrier priority is [Electricity, Natural gas, Diesel] then:
- Electricity: if met exclusively or otherwise, it's final electrical demand.
- Natural gas: if met exclusively or otherwise, EXCEPT for overlapping cases with Electricity.
- Diesel: if met exclusively or otherwise, EXCEPT for overlapping cases with all the above.

Args:
jrc_energy (xr.Dataset): JRC energy dataset.
carrier_priority (list[str]): carriers to take in order of priority.

Returns:
xr.DataArray: dataset filled with demands for the given carriers.
"""
carrier_final_dem = {}

for carrier in carrier_priority:
dem_replaced = jrc.replace_final_demand_by_carrier(carrier, jrc_energy)
dem_replaced = dem_replaced.to_dataframe().dropna()
for dem_replaced_prev in carrier_final_dem.values():
dem_replaced = dem_replaced.drop(dem_replaced_prev.index, errors="ignore")
carrier_final_dem[carrier] = dem_replaced

for carrier, df in carrier_final_dem.items():
carrier_final_dem[carrier] = (
df["final"].to_xarray().assign_coords(carrier_name=carrier)
)

final_dem = xr.concat(carrier_final_dem.values(), dim="carrier_name")
final_dem = final_dem.sum(["section", "subsection"])

final_dem = jrc.standardize(final_dem, "twh")

return final_dem


if __name__ == "__main__":
get_generic_demand(
non_generic_categories=snakemake.params.non_generic_categories,
generic_config=snakemake.params.generic_config,
path_energy_balances=snakemake.input.path_energy_balances,
path_cat_names=snakemake.input.path_cat_names,
path_carrier_names=snakemake.input.path_carrier_names,
path_jrc_industry_energy=snakemake.input.path_jrc_industry_energy,
path_jrc_industry_production=snakemake.input.path_jrc_industry_production,
path_output=snakemake.output.path_output,
)
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def _get_h2_to_steel(recycled_steel_share: float) -> float:


def get_steel_demand_df(
config_steel: dict,
steel_config: dict,
path_energy_balances: str,
path_cat_names: str,
path_carrier_names: str,
Expand All @@ -29,7 +29,7 @@ def get_steel_demand_df(
"""Execute the data processing pipeline for the "Iron and steel" sub-sector.

Args:
config_steel (dict): steel sector configuration.
steel_config (dict): steel sector configuration.
path_energy_balances (str): country energy balances (usually from eurostat).
path_cat_names (str): eurostat category mapping file.
path_carrier_names (str): eurostat carrier name mapping file.
Expand All @@ -56,7 +56,7 @@ def get_steel_demand_df(

# Process data
new_steel_demand = transform_jrc_subsector_demand(
jrc_energy, jrc_prod, config_steel
jrc_energy, jrc_prod, steel_config
)
new_steel_demand = filling.fill_missing_countries_years(
energy_balances_df, cat_names_df, carrier_names_df, new_steel_demand
Expand Down Expand Up @@ -99,7 +99,7 @@ def transform_jrc_subsector_demand(
xr.Dataset: processed dataframe with the expected steel energy consumption.
"""
# Gather relevant industrial processes
sintering_intensity = jrc.get_subsection_final_intensity(
sintering_intensity = jrc.get_sec_subsec_final_intensity(
"Integrated steelworks",
"Steel: Sinter/Pellet making",
"Integrated steelworks",
Expand All @@ -109,7 +109,7 @@ def transform_jrc_subsector_demand(
fill_empty=True,
)

eaf_smelting_intensity = jrc.get_subsection_final_intensity(
eaf_smelting_intensity = jrc.get_sec_subsec_final_intensity(
"Electric arc",
"Steel: Smelters",
"Electric arc",
Expand All @@ -118,7 +118,7 @@ def transform_jrc_subsector_demand(
jrc_prod,
fill_empty=True,
)
eaf_intensity = jrc.get_subsection_final_intensity(
eaf_intensity = jrc.get_sec_subsec_final_intensity(
"Electric arc",
"Steel: Electric arc",
"Electric arc",
Expand All @@ -127,7 +127,7 @@ def transform_jrc_subsector_demand(
jrc_prod,
fill_empty=True,
)
refining_intensity = jrc.get_subsection_final_intensity(
refining_intensity = jrc.get_sec_subsec_final_intensity(
"Electric arc",
"Steel: Furnaces, Refining and Rolling",
"Electric arc",
Expand All @@ -136,7 +136,7 @@ def transform_jrc_subsector_demand(
jrc_prod,
fill_empty=True,
)
finishing_intensity = jrc.get_subsection_final_intensity(
finishing_intensity = jrc.get_sec_subsec_final_intensity(
"Electric arc",
"Steel: Products finishing",
"Electric arc",
Expand All @@ -145,7 +145,7 @@ def transform_jrc_subsector_demand(
jrc_prod,
fill_empty=True,
)
auxiliary_intensity = jrc.get_auxiliary_electric_final_intensity(
auxiliary_intensity = jrc.get_sec_final_intensity_auxiliary_electric(
"Electric arc", "Electric arc", jrc_energy, jrc_prod, fill_empty=True
)

Expand Down Expand Up @@ -182,21 +182,22 @@ def transform_jrc_subsector_demand(
electric_intensity = electric_intensity.where(
electric_intensity > 0, other=mean_demand_per_year
)
electric_intensity = electric_intensity.assign_coords(carrier_name="electricity")

# Hydrogen consumption for H-DRI:
# only for country/year that handle iron ore and don't recycle all their steel
h_dri_h2_intensity = H2_LHV_KTOE * _get_h2_to_steel(recycled_share)

h2_intensity = electric_intensity.where(sintering_intensity > 0).fillna(0)
h2_intensity = h2_intensity.where(h2_intensity == 0, h_dri_h2_intensity)
h2_intensity = h2_intensity.assign_coords(carrier_name="hydrogen")
h2_intensity = h2_intensity.assign_coords(carrier_name="Hydrogen")

# Low heat
low_heat_intensity = jrc.get_subsection_useful_intensity(
low_heat_intensity = jrc.get_section_subsection_useful_intensity(
"Electric arc", "Low enthalpy heat", "Electric arc", jrc_energy, jrc_prod
)
low_heat_intensity = low_heat_intensity.assign_coords(carrier_name="space_heat")
low_heat_intensity = low_heat_intensity.assign_coords(
carrier_name="Low enthalpy heat"
)

# Combine and transform to energy demand
total_intensity = xr.concat(
Expand All @@ -213,7 +214,7 @@ def transform_jrc_subsector_demand(

if __name__ == "__main__":
get_steel_demand_df(
config_steel=snakemake.params.config_steel,
steel_config=snakemake.params.steel_config,
path_energy_balances=snakemake.input.path_energy_balances,
path_cat_names=snakemake.input.path_cat_names,
path_carrier_names=snakemake.input.path_carrier_names,
Expand Down
Loading
Loading