Consumer disutility (model.disutility
)
This module provides a generalized consumer disutility formulation, currently used by 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 add()
, which takes arguments that describe the concrete usage:
- Consumer groups
This is a list of
Code
objects describing the consumer groups. The list must be 1-dimensional, but can be composed (as inmessage_data.model.transport
) from multiple dimensions.- Technologies
This is a list of
Code
objects describing the technologies for which the consumers in the different groups experience disutility. Each object must be have ‘input’ and ‘output’ annotations (annotations
); each of these is adict
with the keys ‘commodity’, ‘input’, and ‘unit’, describing the source or sink for the technology.- Template
This is also a
Code
object, similar to those intechnologies
; 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 test_disutility.test_minimal()
:
# 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,
)
add()
uses 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 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, add()
uses data_conversion()
and data_source()
to generate:
output
andvar_cost
parameter data for “disutility source”. This technology outputs the unitless commodity “disutility” at a cost of 1.0 per unit.input
andoutput
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 add()
.
(Dis)utility is generally dimensionless.
In pint
and thus also message_ix_models
, this should be represented by ""
.
However, to work around iiasa/ixmp#425, data_conversion()
and data_source()
return data with "-"
as units.
See GH #45 for more information.
Code reference
See also message_ix_models.tests.model.test_disutility
.
- message_ix_models.model.disutility.add(scenario: Scenario, groups: Sequence[Code], technologies: Sequence[Code], template: Code, **options) Spec [source]
Add disutility formulation to scenario.
- message_ix_models.model.disutility.data_conversion(info, spec: Spec) MutableMapping[str, DataFrame] [source]
Generate input and output data for disutility conversion technologies.
- message_ix_models.model.disutility.data_source(info, spec) Mapping[str, DataFrame] [source]
Generate data for a technology that emits the “disutility” commodity.
- message_ix_models.model.disutility.dp_for(col_name: str, info: ScenarioInfo) Series [source]
pandas.DataFrame.assign()
helper forduration_period
.Returns a callable to be passed to
pandas.DataFrame.assign()
. The callable takes a data frame as the first argument, and returns apandas.Series
based on theduration_period
parameter in info, aligned to col_name in the data frame.Currently (2021-04-07) unused.
- message_ix_models.model.disutility.get_data(scenario, spec, **kwargs) Mapping[str, DataFrame] [source]
Get data for disutility formulation.
Calls
data_conversion()
anddata_source()
.- Parameters:
spec (
dict
) – The output ofget_spec()
.