Skip to content

Commit e817c34

Browse files
authored
Merge pull request #394 from iiasa/scenariomip/workflow
Sketch a ScenarioMIP workflow
2 parents e5939f0 + 58254ec commit e817c34

6 files changed

Lines changed: 208 additions & 5 deletions

File tree

doc/conf.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -208,11 +208,11 @@ def local_inv(name: str, *parts: str) -> str | None:
208208
"genno": ("https://genno.readthedocs.io/en/stable", None),
209209
"ixmp": ("https://docs.messageix.org/projects/ixmp/en/latest/", None),
210210
"message-ix": ("https://docs.messageix.org/en/latest/", None),
211-
"m-data": (
212-
f"https://{_token}:@docs.messageix.org/projects/models-internal/en/latest/",
213-
# Use a local copy of objects.inv, if the user has one
214-
local_inv("message_data"),
215-
),
211+
# "m-data": (
212+
# f"https://{_token}:@docs.messageix.org/projects/models-internal/en/latest/",
213+
# # Use a local copy of objects.inv, if the user has one
214+
# local_inv("message_data"),
215+
# ),
216216
"pandas": ("https://pandas.pydata.org/pandas-docs/stable/", None),
217217
"pint": ("https://pint.readthedocs.io/en/stable/", None),
218218
"platformdirs": ("https://platformdirs.readthedocs.io/en/latest", None),

doc/project/scenariomip.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,13 @@ Project information
1010
===================
1111

1212
- Website: https://wcrp-cmip.org/mips/scenariomip/
13+
14+
Code reference
15+
==============
16+
17+
.. autosummary::
18+
:toctree: _autosummary
19+
:template: autosummary-module.rst
20+
:recursive:
21+
22+
message_ix_models.project.scenariomip

doc/whatsnew.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ Next release
1616
- Add :func:`.buildings.build.prepare_data_B`;
1717
rename :py:`prepare_data()` to :func:`~.buildings.build.prepare_data_A`.
1818

19+
- Add stub of :func:`.scenariomip.workflow.generate` (:pull:`394`).
20+
1921
v2026.4.17
2022
==========
2123

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""CMIP7-ScenarioMIP."""
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
"""Generate the ScenarioMIP workflow."""
2+
3+
import logging
4+
from typing import TYPE_CHECKING, Optional
5+
6+
from message_ix_models.workflow import Workflow
7+
8+
if TYPE_CHECKING:
9+
from message_ix import Scenario
10+
11+
from message_ix_models import Context
12+
13+
log = logging.getLogger(__name__)
14+
15+
16+
def step_01(context: "Context", scenario: "Scenario") -> "Scenario":
17+
"""Clean Timeseries."""
18+
log.info("Not implemented: step_01(…)")
19+
return scenario
20+
21+
22+
def step_02(context: "Context", scenario: "Scenario") -> "Scenario":
23+
"""Add Land-use Emulator."""
24+
log.info("Not implemented: step_02(…)")
25+
return scenario
26+
27+
28+
def step_03(context: "Context", scenario: "Scenario") -> "Scenario":
29+
"""Add Biomass Trade."""
30+
log.info("Not implemented: step_03(…)")
31+
return scenario
32+
33+
34+
def step_04(context: "Context", scenario: "Scenario") -> "Scenario":
35+
"""Solve for Historic Reporting."""
36+
log.info("Not implemented: step_04(…)")
37+
return scenario
38+
39+
40+
def step_05(context: "Context", scenario: "Scenario") -> "Scenario":
41+
"""Build Materials."""
42+
log.info("Not implemented: step_05(…)")
43+
return scenario
44+
45+
46+
def step_06(context: "Context", scenario: "Scenario") -> "Scenario":
47+
"""Add DAC (Direct Air Capture)."""
48+
log.info("Not implemented: step_06(…)")
49+
return scenario
50+
51+
52+
def step_07(context: "Context", scenario: "Scenario") -> "Scenario":
53+
"""Add Non-CO2 GHGs."""
54+
log.info("Not implemented: step_07(…)")
55+
return scenario
56+
57+
58+
def step_08(context: "Context", scenario: "Scenario") -> "Scenario":
59+
"""Add Water."""
60+
log.info("Not implemented: step_08(…)")
61+
return scenario
62+
63+
64+
def step_09(context: "Context", scenario: "Scenario") -> "Scenario":
65+
"""Add Techno-economic Parameters."""
66+
log.info("Not implemented: step_09(…)")
67+
return scenario
68+
69+
70+
def step_10(context: "Context", scenario: "Scenario") -> "Scenario":
71+
"""Add Balance Equalities (some petrochemical trade balances?)."""
72+
log.info("Not implemented: step_10(…)")
73+
return scenario
74+
75+
76+
def step_11(context: "Context", scenario: "Scenario") -> "Scenario":
77+
"""OBSOLETE."""
78+
log.info("Not implemented: step_11(…)")
79+
return scenario
80+
81+
82+
def step_12(context: "Context", scenario: "Scenario") -> "Scenario":
83+
"""Gas Mix Limitations (constrain gas use in industries)."""
84+
log.info("Not implemented: step_12(…)")
85+
return scenario
86+
87+
88+
def step_13(context: "Context", scenario: "Scenario") -> "Scenario":
89+
"""Add Slack and Constraints (so we need to update the slacks)."""
90+
log.info("Not implemented: step_13(…)")
91+
return scenario
92+
93+
94+
def step_14(context: "Context", scenario: "Scenario") -> "Scenario":
95+
"""Add Shipping."""
96+
log.info("Not implemented: step_14(…)")
97+
return scenario
98+
99+
100+
def step_15(context: "Context", scenario: "Scenario") -> "Scenario":
101+
log.info("Not implemented: step_15(…)")
102+
return scenario
103+
104+
105+
def step_16(context: "Context", scenario: "Scenario") -> "Scenario":
106+
"""Calibrate Macro."""
107+
log.info("Not implemented: step_16(…)")
108+
return scenario
109+
110+
111+
#: Order of steps in the workflow.
112+
STEP_ORDER = [
113+
step_01,
114+
step_02,
115+
step_03,
116+
step_04,
117+
step_05,
118+
step_06,
119+
step_07,
120+
step_08,
121+
step_09,
122+
step_10,
123+
step_11,
124+
step_12,
125+
step_13,
126+
step_14,
127+
step_15,
128+
step_16,
129+
]
130+
131+
132+
def generate(context: "Context", step_order: Optional[list] = None) -> "Workflow":
133+
"""Generate the ScenarioMIP workflow.
134+
135+
Parameters
136+
----------
137+
step_order
138+
Order of steps in the workflow. If not given, :data:`STEP_ORDER` is used.
139+
"""
140+
wf = Workflow(context)
141+
142+
prev = wf.add_step("base", None)
143+
144+
step_order = step_order or STEP_ORDER
145+
146+
for i, func in enumerate(step_order, start=1):
147+
prev = wf.add_step(f"step_{i}", prev, func)
148+
149+
# "all" is an alias for the last step, whatever it is
150+
wf.add("all", prev)
151+
152+
return wf
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import pytest
2+
3+
from message_ix_models import Context
4+
from message_ix_models.project.scenariomip import workflow as w
5+
from message_ix_models.project.scenariomip.workflow import generate
6+
from message_ix_models.testing import bare_res
7+
8+
9+
@pytest.mark.parametrize(
10+
"step_order, last_log",
11+
(
12+
# Default steps
13+
(None, "Not implemented: step_16(…)"),
14+
# Some other order
15+
([w.step_16, w.step_01], "Not implemented: step_01(…)"),
16+
),
17+
)
18+
def test_generate(
19+
caplog: pytest.LogCaptureFixture,
20+
request: pytest.FixtureRequest,
21+
test_context: Context,
22+
step_order: list | None,
23+
last_log: str,
24+
) -> None:
25+
# Create a empty RES scenario for testing
26+
s = bare_res(request, test_context)
27+
28+
# Set the workflow to start from this scenario
29+
test_context.set_scenario(s)
30+
31+
# Function runs, returns a workflow
32+
wf = generate(test_context, step_order)
33+
34+
# Workflow runs, does nothing
35+
wf.run("all")
36+
37+
# Final log message is as expected
38+
assert last_log == caplog.messages[-1]

0 commit comments

Comments
 (0)