Skip to content

Commit

Permalink
Merge 4dae5fb into 900a9f8
Browse files Browse the repository at this point in the history
  • Loading branch information
khaeru authored Aug 27, 2021
2 parents 900a9f8 + 4dae5fb commit c1be92a
Show file tree
Hide file tree
Showing 8 changed files with 371 additions and 8 deletions.
1 change: 1 addition & 0 deletions RELEASE_NOTES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Next release
All changes
-----------

- Add a tool for :doc:`tools/check` (:pull:`506`).
- Adjust test suite for pyam v1.1.0 compatibility (:pull:`499`).
- Add Westeros :doc:`tutorial <tutorials>` on historical parameters (:pull:`478`).
- Update reference for activity and capacity soft constraints (:pull:`474`).
Expand Down
2 changes: 0 additions & 2 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ Then, continue with the:
tutorials




.. _core:

Mathematical specification
Expand Down
27 changes: 27 additions & 0 deletions doc/tools/check.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Pre-solve checks
****************

.. currentmodule:: message_ix.tools

.. autofunction:: check

.. currentmodule:: message_ix.tools._check

.. _checks-summary:

.. automodule:: message_ix.tools._check
:members: gaps_input, gaps_tl, tl_integer

.. autoclass:: Result

Individual checks
=================

Gaps in certain parameters (:func:`gaps_*` check functions) can cause the GAMS implementation to treat that specific technology to be disabled in one period, between other periods where it *is* enabled.
This may prevent solution of the model.

.. autosummary::

gaps_input
gaps_tl
tl_integer
13 changes: 8 additions & 5 deletions message_ix/reporting/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,11 +189,14 @@ def from_scenario(cls, scenario, **kwargs):
solved = scenario.has_solution()

if not solved:
log.warning(
f'Scenario "{scenario.model}/{scenario.scenario}" has no solution'
)
log.warning("Some reporting may not function as expected")
fail_action = logging.DEBUG
if kwargs.pop("solved", True):
log.warning(
f'Scenario "{scenario.model}/{scenario.scenario}" has no solution'
)
log.warning("Some reporting may not function as expected")
fail_action = logging.DEBUG
else:
fail_action = logging.NOTSET
else:
fail_action = "raise"

Expand Down
3 changes: 2 additions & 1 deletion message_ix/tests/test_tutorials.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import sys
from shutil import copyfile
from typing import List, Tuple

import numpy as np
import pytest
Expand All @@ -17,7 +18,7 @@
# 3. Dictionary with extra keyword arguments to run_notebook().

# FIXME check objective function of the rest of tutorials.
tutorials = [
tutorials: List[Tuple] = [
# IPython kernel
(
("westeros", "westeros_baseline"),
Expand Down
96 changes: 96 additions & 0 deletions message_ix/tests/tools/test_check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import pytest

from message_ix import Scenario, make_df
from message_ix.testing import make_dantzig, make_westeros
from message_ix.tools import check


def test_check_dantzig(test_mp):
scen = make_dantzig(test_mp)

# Checks all True
results = check(scen)
assert results[0]


@pytest.fixture
def westeros(test_mp):
yield make_westeros(test_mp)


# Minimal config to make Westeros reportable
WESTEROS_CONFIG = {"units": {"replace": {"-": ""}}}


def test_gaps_input(westeros):
# Delete one value
to_delete = make_df(
"input",
node_loc="Westeros",
technology="bulb",
year_vtg=690,
year_act=710,
mode="standard",
node_origin="Westeros",
commodity="electricity",
level="final",
time="year",
time_origin="year",
).dropna(axis=1)
with westeros.transact():
westeros.remove_par("input", to_delete)

# Checks fail
results = check(westeros, config=WESTEROS_CONFIG)
assert not results[0]


def test_check_tl_integer(westeros):
# Change one value
tl = "technical_lifetime"
with westeros.transact():
westeros.add_par(
tl,
make_df(
tl,
node_loc="Westeros",
technology="bulb",
year_vtg=700,
value=1.1,
unit="y",
),
)

# Checks fail
results = check(westeros, config=WESTEROS_CONFIG)
assert not results[0]

assert """FAIL Non-integer values for ``technical_lifetime``:
See https://github.com/iiasa/message_ix/issues/503.
- 1.1 at indices: nl=Westeros t=bulb yv=700""" in map(
str, results
)


@pytest.mark.parametrize(
"url, config",
[
# ("ixmp://platform/model/scenario#version", dict()),
],
)
def test_check_existing(url, config):
"""Check existing scenarios.
For local use only: extend the list of parameters, above, but do not commit
additions to ``main``.
"""
# import pint
# from iam_units import registry
#
# pint.set_application_registry(registry)

scen, mp = Scenario.from_url(url)
results = check(scen, config=config)

# Checks all pass
assert results[0], "\n".join(map(str, results))
5 changes: 5 additions & 0 deletions message_ix/tools/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from ._check import check

__all__ = [
"check",
]
Loading

0 comments on commit c1be92a

Please sign in to comment.