iiasa / message-ix-models

Tools for the MESSAGEix-GLOBIOM family of models
https://docs.messageix.org/models
Apache License 2.0
17 stars 34 forks source link

Add variant/module for cooling technologies in `tools.costs` #222

Closed measrainsey closed 1 month ago

measrainsey commented 2 months ago

Add a variant/module to project costs for cooling technologies

This PR adds a new module within tools.costs called cooling. @adrivinca has provided input data for these technologies -- these technologies are currently all mapped to a technology in the energy module (based on the assumption that these cooling technologies are sort of addons that follow the same regional differentiation as their non-addon counterpart). However, the cooling technologies have their own base year reference region costs.

This PR's branch is derived from the costs/reduction-year branch, which has its own PR #227. Once that one is merged, I will rebase.

How to review

For @adrivinca: Verify if the implementation is correct and if the outputs make sense.

For @khaeru and/or @glatterf42 : Read the diff and note that the CI checks all pass.

PR checklist

adrivinca commented 2 months ago

Thanks @measrainsey for advancing this work! We tried and it seems it works well for what concerns the cooling techs.

just a note for the general module that could maybe improved with a fix or just notified to developers: One limitation of the fix cost generator is that is does not take into account of the technology lifetime in the vintage-activity years. This way the output dataframe is way larger than actually needed and might take up space. (for example with cooling technologies with 30 years lifetime) the fix_cost df would be five time smaller than the actual one.

I understand that including the lifetime in the process would require adding the information in the initial data, and maybe we don't want it. Otherwise I would suggest write a note about it and the users one could post-apply some formulas like in message_ix_models.model.water.util.map_yv_ya_lt() and just filter the output

measrainsey commented 1 month ago

Thanks @measrainsey for advancing this work! We tried and it seems it works well for what concerns the cooling techs.

just a note for the general module that could maybe improved with a fix or just notified to developers: One limitation of the fix cost generator is that is does not take into account of the technology lifetime in the vintage-activity years. This way the output dataframe is way larger than actually needed and might take up space. (for example with cooling technologies with 30 years lifetime) the fix_cost df would be five time smaller than the actual one.

I understand that including the lifetime in the process would require adding the information in the initial data, and maybe we don't want it. Otherwise I would suggest write a note about it and the users one could post-apply some formulas like in message_ix_models.model.water.util.map_yv_ya_lt() and just filter the output

Sorry I forgot to respond to this comment/review here as Adriano and I had a side conversation about this topic! But I'll put my thoughts here anyways to preserve them on this platform. Additionally, this issue of lifetime was also brought to my attention by Oliver, so I might have to address this at some point.

While my initial thoughts/feelings was to keep technology lifetime outside of this tool so that the tool can remain agnostic to so many inputs/parameters (as perhaps technology lifetimes can vary across scenarios, hypothetically) and as lean as possible, I can see that keeping costs projection for a technology beyond its lifetime can (a) cause confusion and (b) lead to very large output dataframes, like Adriano mentioned.

It seems the best way to make sure lifetimes and vintages are accounted for would be to have the tool call upon the vintage_and_active_years() function from a scenario object. Given that at the moment the costs tool does not interact with MESSAGEix scenario objects at all (this is done by the user post-tool), I would like to leave this issue of lifetimes as a larger TODO on my list and not have it addressed within this PR.

khaeru commented 1 month ago

Otherwise I would suggest write a note about it and the users one could post-apply some formulas like in message_ix_models.model.water.util.map_yv_ya_lt() and just filter the output

It seems the best way to make sure lifetimes and vintages are accounted for would be to have the tool call upon the vintage_and_active_years() function from a scenario object. Given that at the moment the costs tool does not interact with MESSAGEix scenario objects at all (this is done by the user post-tool), I would like to leave this issue of lifetimes as a larger TODO on my list and not have it addressed within this PR.

We also have ScenarioInfo.yv_ya. The ScenarioInfo class (and the .water.utils function mentioned by @adrivinca) are specifically for working with data in the absence of (e.g. before the creation of) a concrete Scenario object, so I think this is quite possible. But it's also fine to omit it from this PR and leave a note at an appropriate place in the docs like:

.. note:: The data produced are for all valid combinations of :math:`(y^V, y^A)`—including those that are beyond the `technical_lifetime` of the |t| to which they apply.
   This may produce large data frames.
   If this is problematic, user code **may** filter the data for valid combinations.
measrainsey commented 1 month ago

We also have ScenarioInfo.yv_ya. The ScenarioInfo class (and the .water.utils function mentioned by @adrivinca) are specifically for working with data in the absence of (e.g. before the creation of) a concrete Scenario object, so I think this is quite possible. But it's also fine to omit it from this PR and leave a note at an appropriate place in the docs like:

.. note:: The data produced are for all valid combinations of :math:`(y^V, y^A)`—including those that are beyond the `technical_lifetime` of the |t| to which they apply.
   This may produce large data frames.
   If this is problematic, user code **may** filter the data for valid combinations.

Thanks @khaeru for your suggestion. I have created an issue #237 to track progress on this, and for the time being, I have added a note in the documentation:

https://github.com/iiasa/message-ix-models/blob/70db1b2e0dc0113218edbfe8df40c0a4b97b16e3/doc/api/tools-costs.rst?plain=1#L151-L154

glatterf42 commented 1 month ago

Nope, good from my side :)

measrainsey commented 1 month ago

Hi all, thanks for approving the PR!

Just a quick note that this branch is based off of the branch in #227, so that PR should probably be approved and merged before this one, I presume?

glatterf42 commented 1 month ago

You could also merge this PR into the branch it originated from. This would increase the size of the other PR, but we could focus on the changes not already reviewed. However, as far as I can tell, the other PR is already quite close to being merged, so I don't think it hurts to wait before merging this one.

codecov[bot] commented 1 month ago

Codecov Report

All modified and coverable lines are covered by tests :white_check_mark:

Project coverage is 75.5%. Comparing base (2dbdec6) to head (687c4c4). Report is 13 commits behind head on main.

Additional details and impacted files ```diff @@ Coverage Diff @@ ## main #222 +/- ## ======================================= - Coverage 75.5% 75.5% -0.1% ======================================= Files 203 203 Lines 15503 15503 ======================================= - Hits 11707 11706 -1 - Misses 3796 3797 +1 ``` | [Files with missing lines](https://app.codecov.io/gh/iiasa/message-ix-models/pull/222?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=iiasa) | Coverage Δ | | |---|---|---| | [message\_ix\_models/tests/tools/costs/test\_decay.py](https://app.codecov.io/gh/iiasa/message-ix-models/pull/222?src=pr&el=tree&filepath=message_ix_models%2Ftests%2Ftools%2Fcosts%2Ftest_decay.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=iiasa#diff-bWVzc2FnZV9peF9tb2RlbHMvdGVzdHMvdG9vbHMvY29zdHMvdGVzdF9kZWNheS5weQ==) | `100.0% <100.0%> (ø)` | | | [message\_ix\_models/tests/tools/costs/test\_gdp.py](https://app.codecov.io/gh/iiasa/message-ix-models/pull/222?src=pr&el=tree&filepath=message_ix_models%2Ftests%2Ftools%2Fcosts%2Ftest_gdp.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=iiasa#diff-bWVzc2FnZV9peF9tb2RlbHMvdGVzdHMvdG9vbHMvY29zdHMvdGVzdF9nZHAucHk=) | `100.0% <100.0%> (ø)` | | | [...ge\_ix\_models/tests/tools/costs/test\_projections.py](https://app.codecov.io/gh/iiasa/message-ix-models/pull/222?src=pr&el=tree&filepath=message_ix_models%2Ftests%2Ftools%2Fcosts%2Ftest_projections.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=iiasa#diff-bWVzc2FnZV9peF9tb2RlbHMvdGVzdHMvdG9vbHMvY29zdHMvdGVzdF9wcm9qZWN0aW9ucy5weQ==) | `100.0% <ø> (ø)` | | | [...tests/tools/costs/test\_regional\_differentiation.py](https://app.codecov.io/gh/iiasa/message-ix-models/pull/222?src=pr&el=tree&filepath=message_ix_models%2Ftests%2Ftools%2Fcosts%2Ftest_regional_differentiation.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=iiasa#diff-bWVzc2FnZV9peF9tb2RlbHMvdGVzdHMvdG9vbHMvY29zdHMvdGVzdF9yZWdpb25hbF9kaWZmZXJlbnRpYXRpb24ucHk=) | `100.0% <100.0%> (ø)` | | | [message\_ix\_models/tools/costs/config.py](https://app.codecov.io/gh/iiasa/message-ix-models/pull/222?src=pr&el=tree&filepath=message_ix_models%2Ftools%2Fcosts%2Fconfig.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=iiasa#diff-bWVzc2FnZV9peF9tb2RlbHMvdG9vbHMvY29zdHMvY29uZmlnLnB5) | `97.2% <100.0%> (ø)` | | | [...\_ix\_models/tools/costs/regional\_differentiation.py](https://app.codecov.io/gh/iiasa/message-ix-models/pull/222?src=pr&el=tree&filepath=message_ix_models%2Ftools%2Fcosts%2Fregional_differentiation.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=iiasa#diff-bWVzc2FnZV9peF9tb2RlbHMvdG9vbHMvY29zdHMvcmVnaW9uYWxfZGlmZmVyZW50aWF0aW9uLnB5) | `97.9% <ø> (ø)` | | ... and [1 file with indirect coverage changes](https://app.codecov.io/gh/iiasa/message-ix-models/pull/222/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=iiasa)