.. currentmodule:: message_ix_models.model.disutility Consumer disutility (:mod:`model.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.annotations`); 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`. .. _disutility-units: (Dis)utility is generally dimensionless. In :mod:`.pint` and thus also :mod:`message_ix_models`, this should be represented by ``""``. However, to work around `iiasa/ixmp#425 <https://github.com/iiasa/ixmp/issues/425>`__, :func:`data_conversion` and :func:`data_source` return data with ``"-"`` as units. See :issue:`45` for more information. Code reference ============== See also :mod:`message_ix_models.tests.model.test_disutility`. .. automodule:: message_ix_models.model.disutility :members: