Skip to content

Commit

Permalink
Merge pull request #13 from iiasa/feature/disutility
Browse files Browse the repository at this point in the history
Migrate .model.disutility
  • Loading branch information
khaeru authored Apr 7, 2021
2 parents 847dd7c + 55143b4 commit 4835a76
Show file tree
Hide file tree
Showing 13 changed files with 985 additions and 19 deletions.
11 changes: 4 additions & 7 deletions .github/workflows/pytest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ on:
branches: [ main ]

env:
GAMS_VERSION: 25.1.1
# For setuptools-scm. With fetch --tags below, this ensures that enough
# history is fetched to contain the latest tag, so that setuptools-scm can
# generate the version number. Update:
Expand Down Expand Up @@ -91,12 +90,10 @@ jobs:
${{ matrix.os }}-gams${{ env.GAMS_VERSION }}-
${{ matrix.os }}-
- name: Install GAMS
# Use the scripts from the checked-out ixmp repo
env:
CI_OS: ${{ matrix.os }}
run: ixmp/ci/install-gams.sh
shell: bash
- uses: iiasa/actions/setup-gams@main
with:
version: 25.1.1
license: ${{ secrets.GAMS_LICENSE }}

- name: Upgrade pip, wheel, setuptools-scm
run: python -m pip install --upgrade pip wheel setuptools-scm
Expand Down
120 changes: 120 additions & 0 deletions doc/api/disutility.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
.. currentmodule:: message_ix_models.model.disutility

Consumer disutility
*******************

This module provides a generalized consumer disutility formulation, currently used by :mod:`message_data.model.transport`.
The formulation rests on the concept of “consumer groups”; each consumer group may have a distinct disutility associated with using the outputs of each technology.
A set of ‘pseudo-’/‘virtual’/non-physical “usage technologies” converts the outputs of the actual technologies into the commodities demanded by each group, while also requiring input of a costly “disutility” commodity.


Method & usage
==============

Use this code by calling :func:`add`, which takes arguments that describe the concrete usage:

Consumer groups
This is a list of :class:`.Code` objects describing the consumer groups.
The list must be 1-dimensional, but can be composed (as in :mod:`message_data.model.transport`) from multiple dimensions.

Technologies
This is a list of :class:`.Code` objects describing the technologies for which the consumers in the different groups experience disutility.
Each object must be have 'input' and 'output' annotations (:attr:`.Code.anno`); each of these is a :class:`dict` with the keys 'commodity', 'input', and 'unit', describing the source or sink for the technology.

Template
This is also a :class:`.Code` object, similar to those in ``technologies``; see below.

The code creates a source technology for the “disutility” commodity.
The code does *not* perform the following step(s) needed to completely parametrize the formulation:

- Set consumer group-specific ``demand`` parameter values for new commodities.
- Set the amounts of “disutility” commodities used as ``input`` to the new usage technologies.

These must be parametrized based on the particular application.

Detailed example
================

This example is similar to the one used in :func:`.test_disutility.test_minimal`:

.. code-block:: python
# Two consumer groups
groups = [Code(id="g0"), Code(id="g1")]
# Two technologies, for which groups may have different disutilities.
techs = [Code(id="t0"), Code(id="t1")]
# Add generalized disutility formulation to some technologies
disutility.add(
scenario,
groups=groups,
technologies=techs,
template=Code(
# Template for IDs of conversion technologies
id="usage of {technology} by {group}",
# Templates for inputs of conversion technologies
input=dict(
# Technology-specific output commodity
commodity="output of {technology}",
level="useful",
unit="kg",
),
# Templates for outputs of conversion technologies
output=dict(
# Consumer-group–specific demand commodity
commodity="demand of group {group}",
level="useful",
unit="kg",
),
),
**options,
)
:func:`add` uses :func:`get_spec` to generate a specification that adds the following:

- For the set ``commodity``:

- The single element “disutility”.
- One element per `technologies`, using the `template` “input” annotation, e.g. “output of t0” generated from ``output of {technology}`` and the id “t0”.
These **may** already be present in the `scenario`; if not, the spec causes them to be added.
- One elements per `groups`, using the `template` “output” annotation, e.g. “demand of group g1” generated from ``demand of group {group}`` and the id “g1”.
These **may** already be present in the `scenario`; if not, the spec causes them to be added.

- For the set ``technology``:

- The single element “disutility source”.
- One element per each combination of disutility-affected technology (`technologies`) and consumer group (`groups`).
For example, “usage of t0 by g1” generated from ``usage of {technology} by {group}``, and the ids “t0” and “g1”.

The spec is applied to the target scenario using :func:`.model.build.apply_spec`.
If the arguments produce a spec that is inconsistent with the target scenario, an exception will by raised at this point.


Next, :func:`add` uses :func:`data_conversion` and :func:`data_source` to generate:

- ``output`` and ``var_cost`` parameter data for “disutility source”.
This technology outputs the unitless commodity “disutility” at a cost of 1.0 per unit.

- ``input`` and ``output`` parameter data for the new usage technologies.
For example, the new technology “usage of t0 by g1”…

- …takes input from the *technology-specific* commodity “output of t0”.
- …takes input from the common commodity “disutility”, in an amount specific to group “g1”.
- …outputs to a *group-specific* commodity “demand of group g1”.

Note that the `technologies` towards which the groups have disutility are assumed to already be configured to ``output`` to the corresponding commodities.
For example, the technology “t0” outputs to the commodity “output of t0”; the ``output`` values for this technology are **not** added/introduced by :func:`add`.


Code reference
==============

See also :mod:`message_ix_models.tests.model.test_disutility`.

.. automodule:: message_ix_models.model.disutility
:members:
4 changes: 2 additions & 2 deletions doc/api/model-build.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ The following modules use this workflow and can be examples for developing simil
Code reference
==============

.. currentmodule:: message_data.model.build
.. currentmodule:: message_ix_models.model.build

.. automodule:: message_data.model.build
.. automodule:: message_ix_models.model.build
:members:
8 changes: 8 additions & 0 deletions doc/api/util.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,18 @@ Commonly used:
.. autosummary::

as_codes
broadcast
copy_column
ffill
load_package_data
load_private_data
make_io
make_matched_dfs
make_source_tech
merge_data
package_data_path
private_data_path
same_node
~context.Context
~scenarioinfo.ScenarioInfo

Expand Down
1 change: 1 addition & 0 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ These models are built in the `MESSAGEix framework <https://docs.messageix.org>`
api/model
api/model-bare
api/model-build
api/disutility
api/project
api/tools
api/util
Expand Down
6 changes: 4 additions & 2 deletions doc/whatsnew.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
What's new
**********

.. Next release
.. ============
Next release
============

- Add :mod:`.model.disutility`, code for setting up structure and data for generalized consumer disutility (:pull:`13`)

2021.3.24
=========
Expand Down
Loading

0 comments on commit 4835a76

Please sign in to comment.