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 chemicals industry (new) #418

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from

Conversation

tud-mchen6
Copy link

Fixes #311. This is the newer version; discarding #348. Everything works, but still in progress of prettifying.

Checklist

Any checks which are not relevant to the PR can be pre-checked by the PR creator. All others should be checked by the reviewer. You can add extra checklist items here if required by the PR.

  • CHANGELOG updated
  • Minimal workflow tests pass
  • Tests added to cover contribution
  • Documentation updated
  • Configuration schema updated

@tud-mchen6
Copy link
Author

My high-level questions, just to confirm:

  1. Do we only consider energy demand? During the process of extracting electricity demand (and assuming all demands that could possibly be met by electricity are met by electricity), some demands that cannot be met by electricity will be filtered out.
  2. Do we assume that all low enthalpy heat demand cannot be met by electricity?
  3. Regarding the "energy demand" of Basic chemicals: what carriers are they?
  4. On the one hand, we estimate electricity demand from jrc_energy, while on the other hand, we estimate Basic chemicals related demand from jrc_prod. Will there be overlap or double-counting?

Copy link
Contributor

@irm-codebase irm-codebase left a comment

Choose a reason for hiding this comment

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

Nice job! However, I have several suggestions.

Biggest one is that I feel like you are not using the correct JRC function for the electricity consumption stuff. See the specific comment. Feel free to comment if you think I got something wrong!

message: "Calculate energy demand for the 'Chemicals Industry' sector in JRC-IDEES."
conda: CONDA_PATH
# params:
# config = config["params"]["config-chemicals-industry"]
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider looking at which parameters should be user configurable and bring them to this level.

"""
# Get the electricity consumption (assuming every demand that could be met by electricity is met by electricity)
electrical_consumption = (
(jrc.replace_carrier_final_demand("Electricity", jrc_energy))
Copy link
Contributor

Choose a reason for hiding this comment

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

I feel in my bones that this is not the function you want to call here.
Check get_section_final_intensity_auxiliary_electric, which is what the steel sector uses.

This function gets electricity demand for stuff like motor drives, pumps and lighting.

Copy link
Contributor

Choose a reason for hiding this comment

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

The best way to answer this is probably looking at what the old code does for both chemicals and steel here, not "other" industry, which is unique.

Copy link
Author

Choose a reason for hiding this comment

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

I feel in my bones that this is not the function you want to call here. Check get_section_final_intensity_auxiliary_electric, which is what the steel sector uses.

This function gets electricity demand for stuff like motor drives, pumps and lighting.

As I understand, the function you suggest is giving an intensity value, i.e. twh/t. But what's needed here, at least according to the old code, is the absolute value of energy in twh (just an example of unit).

chem_co2_consumption = chem_co2_consumption.assign_attrs(units="t").assign_coords(
carrier_name="co2"
)
# TODO: find out how co2 is called in jrc
Copy link
Contributor

Choose a reason for hiding this comment

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

As far as I remember, CO2 is not present in JRC, same with "methanol" above.
Instead, follow the same naming convention JRC uses (capital letters, etc).

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, this is why we provide CO2 demand as constants in a dictionary earlier in the script.

)
chem_energy_consumption = chem_energy_consumption.assign_attrs(
units="twh"
).assign_coords(carrier_name="electricity")
Copy link
Contributor

Choose a reason for hiding this comment

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

Please keep the same JRC naming convention. See the iron and steel sector.

.sum(dim=["section", "carrier_name"])
.drop_vars(["subsection", "cat_name"])
.assign_attrs(units="twh")
.assign_coords(carrier_name="space_heat")
Copy link
Contributor

@irm-codebase irm-codebase Jul 25, 2024

Choose a reason for hiding this comment

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

More naming conventions. Please keep "Low enthalpy heat".

)

# Prettify
total_consumption = jrc.standardize(total_consumption, "twh, t", "demand")
Copy link
Contributor

@irm-codebase irm-codebase Jul 25, 2024

Choose a reason for hiding this comment

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

Since Chemicals industry is unique in that it also outputs demand in tonnes, please create a separate xarray variable for it with a clear and short name (see the jrc_energy dataset as an example).

This is to avoid ambiguous units: right now you cannot know were twh or tonnes apply unless you ask the person who made the code!

useful_dem_tot = jrc_energy["useful"].sum("carrier_name")
useful_dem_tot = jrc_energy["useful"].sum(
"carrier_name"
) # MC note: including all carriers
Copy link
Contributor

Choose a reason for hiding this comment

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

Please remove these comments.
If the function is not descriptive enough, improve the docstring.

Easier to maintain down the line (and avoids black creating extra lines because of the comment).

assert useful_dem_tot.sum() < carrier_final_demand.sum(), "Creating energy!"

# assert useful_dem_tot.sum() < carrier_final_demand.sum(), "Creating energy!" # MC note: but useful_dem_tot includes all carrier demands while carrier_final_demand only contains the demand related to one specific carrier. Surely this is fair comparison?
# MC note: commented out because this is not correct for chemicals industry. but need to coordinate with Ivan regarding how this function should be written.
Copy link
Contributor

@irm-codebase irm-codebase Jul 25, 2024

Choose a reason for hiding this comment

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

See my comment in the "other industry" PR:
#355 (comment)

@irm-codebase
Copy link
Contributor

irm-codebase commented Jul 25, 2024

My high-level questions, just to confirm:

1. Do we only consider **energy** demand? During the process of extracting electricity demand (and assuming all demands that could possibly be met by electricity are met by electricity), some demands that cannot be met by electricity will be filtered out.

2. Do we assume that all low enthalpy heat demand cannot be met by electricity?

3. Regarding the "energy demand" of Basic chemicals: what carriers are they?

4. On the one hand, we estimate electricity demand from `jrc_energy`, while on the other hand, we estimate Basic chemicals related demand from `jrc_prod`. Will there be overlap or double-counting?

I'll try to help here, but I am unfamiliar with the chemicals section of the code. I can only help with the jrc helper functions and so on. If there are more questions, I can help when I'm back from my vacation.

  1. For chemicals, no. Any "energy relevant" carrier matters here. I do not remember the SCEC specifics, but these could be: ammonia, H2, CO2, etc. Please check the SCEC code and include all the ones used there for Chem. Ind.
  2. Low enthalpy heat can be met by whatever technology the model chooses (heatpumps, boilers, wood, etc). Just use the same method as the iron and steel sector.
  3. Check the SCEC code please. That is probably there, or in the configuration files.
  4. Please see the SCEC code, or ask @brynpickering if you suspect double counting is occurring. My guess is "no", if you use the correct subsections.

Copy link
Member

@brynpickering brynpickering left a comment

Choose a reason for hiding this comment

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

THanks for this @tud-mchen6! I would restructure the chemicals industry script a bit to move constants around and to distribute it into smaller functions that you can then give nice docstrings for (for future maintainability, e.g. so others don't wonder the same things you have wondered when making this contribution!)

from utils import filling
from utils import jrc_idees_parser as jrc

H2_LHV_KTOE = 2.863 # 0.0333 TWh/kt LHV -> 2.863ktoe/kt
Copy link
Member

Choose a reason for hiding this comment

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

Some of these values are also in the steel script. To avoid the maintenance burden, perhaps we move these to a single file (e.g. utils/constants.py?)

will be required for iron ore processed using H-DRI, but is not required by EAF.

This function does the following:
1.
Copy link
Member

Choose a reason for hiding this comment

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

Fill?

"Methanol": 1.373,
}

energy_demand = { # MWh/t
Copy link
Member

Choose a reason for hiding this comment

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

Move to config (there are user assumptions here)

)

# Gather relevant params for Basic chemicals in the Chemicals Industry
h2_demand = { # t/t
Copy link
Member

Choose a reason for hiding this comment

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

move to top of file (they are constants)

"Ammonia": 0.178,
"Methanol": 0.189,
}
methanol_demand = {
Copy link
Member

Choose a reason for hiding this comment

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

move to top of file (they are constants)

"Ammonia": 17,
"Methanol": 2,
}
molar_mass = {
Copy link
Member

Choose a reason for hiding this comment

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

move to top of file (they are constants)

"Methanol": 1.5, # auxiliary demand, could just be assumed as already included in existing electricity demand
}

mass = { # Bazzanella and Ausfelder, 2017
Copy link
Member

Choose a reason for hiding this comment

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

move to top of file (they are constants)

"Ammonia": 17.01,
"Methanol": 32.04,
}
moles = {k: mass[k] / molar_mass[k] for k in mass}
Copy link
Member

Choose a reason for hiding this comment

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

I would separate the mass-to-molar mass calc into its own function

new_chemicals_demand.to_netcdf(output_path)


def transform_jrc_chemicals_subsector_demand(
Copy link
Member

Choose a reason for hiding this comment

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

I don't think we're using "subsector" any more. See the steel script

chem_co2_consumption = chem_co2_consumption.assign_attrs(units="t").assign_coords(
carrier_name="co2"
)
# TODO: find out how co2 is called in jrc
Copy link
Member

Choose a reason for hiding this comment

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

Yeah, this is why we provide CO2 demand as constants in a dictionary earlier in the script.

@brynpickering
Copy link
Member

In answer to your questions:

Do we only consider energy demand? During the process of extracting electricity demand (and assuming all demands that could possibly be met by electricity are met by electricity), some demands that cannot be met by electricity will be filtered out.

We completely overhaul the chemical industry stuff and as a result only keep direct electricity consumption, which refers to all energy requirements to process chemicals. I believe that the non-electricity consumption in JRC-IDEES refers to creating relevant chemicals, which we completely replace with our own demands for CO2, hydrogen, and auxiliary electricity. This probably requires some review though.

Do we assume that all low enthalpy heat demand cannot be met by electricity?

It gets turned into "space heat demand" later, which can be met by any available technologies for that.

Regarding the "energy demand" of Basic chemicals: what carriers are they?

Electricity.

On the one hand, we estimate electricity demand from jrc_energy, while on the other hand, we estimate Basic chemicals related demand from jrc_prod. Will there be overlap or double-counting?

The electricity demand from jrc_energy refers to demand to process basic chemicals. The electricity demand we get from processing jrc_prod is for creating those basic chemicals. They should be mutually exclusive sets of demands that can be added together without double counting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Update chemical industry demand
3 participants