Skip to content

Commit

Permalink
Merge pull request #255 from iiasa/costs/mod-reduction
Browse files Browse the repository at this point in the history
Add functionality in `tools.costs` to specify cost reduction scenarios and values
  • Loading branch information
khaeru authored Dec 3, 2024
2 parents aa49621 + 5993c55 commit 3038862
Show file tree
Hide file tree
Showing 5 changed files with 355 additions and 215 deletions.
3 changes: 2 additions & 1 deletion doc/whatsnew.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Next release
- Expand :doc:`repro` with sections on :ref:`repro-doc` and :ref:`versioning`, including :ref:`a list of external model names and ‘versions’ <model-names>` like “MESSAGEix-GLOBIOM 2.0” (:issue:`224`, :pull:`226`).
- Update :doc:`/transport/index` (:pull:`213`).
- Add "LED", "SSP4", and "SSP5" as values for the :program:`--ssp=…` option in :func:`.common_params` (:pull:`233`).
- Fix and update :doc:`/api/tools-costs` (:pull:`219`, :pull:`206`, :pull:`221`, :pull:`227`, :pull:`222`)
- Fix and update :doc:`/api/tools-costs` (:pull:`219`, :pull:`206`, :pull:`221`, :pull:`227`, :pull:`222`, :pull:`255`)

- Fix naming of GDP and population columns in SSP data aggregation (:pull:`219`).
- Edit inputs for storage, CSP, hydrogen, and industry technologies (:pull:`206`).
Expand All @@ -24,6 +24,7 @@ Next release
- Reconfigure use and implementation of technology variants/modules to be more agnostic (:pull:`221`).
- Change cost decay to reach reduction percentage specified on the year 2100 (:pull:`227`).
- Add `cooling` technology variant/module (:pull:`222`).
- Add functionality to specify cost reduction values and cost reduction scenarios in a module (:pull:`255`).
- Improve and extend :doc:`/material/index` (:pull:`218`, :pull:`253`).

- Release of MESSAGEix-Materials 1.1.0 (:doc:`/material/v1.1.0`).
Expand Down
4 changes: 4 additions & 0 deletions message_ix_models/data/costs/materials/cost_reduction.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Cost reduction in 2100,,,,,,
# ,,,,,,
# Units: % ,,,,,,
message_technology,technology_type,very_low,low,medium,high,very_high
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
message_technology,SSP1,SSP2,SSP3,SSP4,SSP5,LED
69 changes: 60 additions & 9 deletions message_ix_models/tests/tools/costs/test_decay.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
from typing import Literal

import pandas as pd
import pytest

from message_ix_models.tools.costs import Config
from message_ix_models.tools.costs.decay import (
get_cost_reduction_data,
_get_module_cost_reduction,
_get_module_scenarios_reduction,
get_technology_reduction_scenarios_data,
project_ref_region_inv_costs_using_reduction_rates,
)
from message_ix_models.tools.costs.regional_differentiation import (
apply_regional_differentiation,
get_raw_technology_mapping,
subset_module_map,
)


Expand All @@ -21,20 +25,65 @@
("cooling", {"coal_ppl__cl_fresh", "gas_cc__air", "nuc_lc__ot_fresh"}),
),
)
def test_get_cost_reduction_data(module: str, t_exp) -> None:
# The function runs without error
result = get_cost_reduction_data(module)
def test_get_module_scenarios_reduction(
module: Literal["energy", "materials", "cooling"], t_exp: set[str]
) -> None:
tech_map = energy_map = get_raw_technology_mapping("energy")

# if module is not energy, run subset_module_map
if module != "energy":
module_map = get_raw_technology_mapping(module)
module_sub = subset_module_map(module_map)

# Remove energy technologies that exist in module mapping
energy_map = energy_map.query(
"message_technology not in @module_sub.message_technology"
)

tech_map = pd.concat([energy_map, module_sub], ignore_index=True)

result = _get_module_scenarios_reduction(module, energy_map, tech_map)

# Expected MESSAGEix-GLOBIOM technologies are present in the data
assert t_exp <= set(result.message_technology.unique())

# Values of the "cost reduction" columns are between 0 and 1
stats = result.cost_reduction.describe()
assert 0 <= stats["min"] and stats["max"] <= 1

@pytest.mark.parametrize(
"module, t_exp",
(
("energy", {"coal_ppl", "gas_ppl", "gas_cc", "solar_res1"}),
("materials", {"biomass_NH3", "MTO_petro", "furnace_foil_steel"}),
("cooling", {"coal_ppl__cl_fresh", "gas_cc__air", "nuc_lc__ot_fresh"}),
),
)
def test_get_module_cost_reduction(
module: Literal["energy", "materials", "cooling"], t_exp: set[str]
) -> None:
tech_map = energy_map = get_raw_technology_mapping("energy")

# if module is not energy, run subset_module_map
if module != "energy":
module_map = get_raw_technology_mapping(module)
module_sub = subset_module_map(module_map)

# Remove energy technologies that exist in module mapping
energy_map = energy_map.query(
"message_technology not in @module_sub.message_technology"
)

tech_map = pd.concat([energy_map, module_sub], ignore_index=True)

# The function runs without error
result = _get_module_cost_reduction(module, energy_map, tech_map)

# Expected MESSAGEix-GLOBIOM technologies are present in the data
assert t_exp <= set(result.message_technology.unique())


@pytest.mark.parametrize("module", ("energy", "materials", "cooling"))
def test_get_technology_reduction_scenarios_data(module: str) -> None:
def test_get_technology_reduction_scenarios_data(
module: Literal["energy", "materials", "cooling"],
) -> None:
config = Config()
# The function runs without error
result = get_technology_reduction_scenarios_data(config.y0, module=module)
Expand Down Expand Up @@ -62,7 +111,9 @@ def test_get_technology_reduction_scenarios_data(module: str) -> None:
),
)
def test_project_ref_region_inv_costs_using_reduction_rates(
module: Literal["energy", "materials", "cooling"], t_exp, t_excluded
module: Literal["energy", "materials", "cooling"],
t_exp: set[str],
t_excluded: set[str],
) -> None:
# Set up
config = Config(module=module)
Expand Down
Loading

0 comments on commit 3038862

Please sign in to comment.