Profile

Caution

Proper transformation (from Julia docs to Python docs) of math mode rendering, and therefore the “detailed model reference”, is partially broken. Until this is fixed, please refer to the original Julia documentation for any math mode rendering.

Overview

Note

This section of the documentation is auto-generated from the code of the Julia-based core model. Refer to IESopt.jl and its documentation for any further details (which may require some familiarity with Julia).

A Profile allows representing “model boundaries” - parts of initial problem that are not endogenously modelled - with a support for time series data. Examples are hydro reservoir inflows, electricity demand, importing gas, and so on. Besides modelling fixed profiles, they also allow different ways to modify the value endogenously.

Basic Examples

A Profile that depicts a fixed electricity demand:

demand_XY:
  type: Profile
  carrier: electricity
  node_from: grid
  value: demand_XY@input_file

A Profile that handles cost of fuel:

fuel_gas:
  type: Profile
  carrier: gas
  node_to: country_gas_grid
  mode: create
  cost: 100.0

A Profile that handles CO2 emission costs:

co2_cost:
  type: Profile
  carrier: co2
  node_from: total_co2
  mode: destroy
  cost: 150.0

A Profile that handles selling electricity:

sell_electricity:
  type: Profile
  carrier: electricity
  node_from: internal_grid_node
  mode: destroy
  cost: -30.0

Parameters

carrier

Carrier of this Profile. Must match the Carrier of the Node that this connects to.

Mandatory:

yes

Values:

string

Unit:
Default:

value

The concrete value of this Profile - either static or as time series. Only applicable if mode: fixed.

Mandatory:

no

Values:

numeric, col@file

Unit:

power

Default:

node_from

Name of the Node that this Profile draws energy from. Exactly one of node_from and node_to must be set.

Mandatory:

no

Values:

string

Unit:
Default:

node_to

Name of the Node that this Profile feeds energy to. Exactly one of node_from and node_to must be set.

Mandatory:

no

Values:

string

Unit:
Default:

mode

The mode of operation of this Profile. fixed uses the supplied value, ranged allows ranging between lb and ub, while create (must specify node_to) and destroy (must specify node_from) handle arbitrary energy flows that are bounded from below by 0. Use fixed if you want to fix the value of the Profile to a specific value, e.g., a given energy demand. Use create to “import” energy into the model, e.g., from a not explicitly modelled gas market, indcucing a certain cost for buying that energy. Use destroy to “export” energy from the model, e.g., to handle CO2 going into the atmosphere (which may be taxed, etc., by the cost of this Profile). Use ranged if you need more fine grained control over the value of the Profile, than what create and destroy allow (e.g., a grid limited energy supplier).

Mandatory:

no

Values:
Unit:
Default:

fixed

lb

The lower bound of the range of this Profile (must be used together with mode: ranged).

Mandatory:

no

Values:

numeric

Unit:

power

Default:

\(-\infty\)

ub

The upper bound of the range of this Profile (must be used together with mode: ranged).

Mandatory:

no

Values:

numeric

Unit:

power

Default:

\(+\infty\)

cost

Cost per unit of energy that this Profile injects or withdraws from a Node. Refer to the basic examples to see how this can be combined with mode for different use cases.

Mandatory:

no

Values:

numeric

Unit:

monetary per energy

Default:

0

build_priority

Priority for the build order of components. Components with higher build_priority are built before. This can be useful for addons, that connect multiple components and rely on specific components being initialized before others.

Mandatory:

no

Values:

numeric

Unit:
Default:

0

Detailed model reference

Variables

aux_value

Add the variable that is used in this Profiles value to the model. The variable var_value[t] is constructed and is linked to the correct Nodes. There are different ways, IESopt interprets this, based on the setting of profile.mode:

  1. fixed: The value is already handled by the constant term of profile.exp.value and NO variable is constructed.

  2. create, destroy, or ranged: This models the creation or destruction of energy - used mainly to represent model boundaries, and energy that comes into the model or leaves the model’s scope. It is however important that create should mostly be used feeding into a Node (profile.node_from = nothing) and destroy withdrawing from a Node (profile.node_to = nothing). If lb and ub are defined, ranged can be used that allows a more detailled control over the Profile, specifying upper and lower bounds for every Snapshot. See _profile_con_value_bounds!(profile::Profile) for details on the specific bounds for each case. This variable is added to the profile.exp.value. Additionally, the energy (that profile.exp.value represents) gets “injected” at the Nodes that the profile is connected to, resulting in $\( \begin{aligned} & \text{profile.node}_{from}\text{.injection}_t = \text{profile.node}_{from}\text{.injection}_t - \text{value}_t, \qquad \forall t \in T \\ & \text{profile.node}_{to}\text{.injection}_t = \text{profile.node}_{to}\text{.injection}_t + \text{value}_t, \qquad \forall t \in T \end{aligned} \)$ math

Expressions

value

Cosntruct the JuMP.AffExpr that keeps the total value of this Profile for each Snapshot. This is skipped if the value of this Profile is handled by an Expression. Otherwise it is intialized based on profile.value.

Constraints

value_bounds

Add the constraint defining the bounds of this profile to the model. This heavily depends on the mode setting, as it does nothing if the mode is set to fixed, or the value is actually controlled by an Expression. The variable can be accessed via profile.var.aux_value[t], but using the normal result extraction is recommended, since that properly handles the profile.exp.value instead. Otherwise:

if profile.mode === :create or profile.mode === :destroy

\[ > \begin{aligned} > & \text{aux_value}_t \geq 0, \qquad \forall t \in T > \end{aligned} > \]

math if profile.mode === :ranged

\[\begin{split} > \begin{aligned} > & \text{value}_t \geq \text{lb}_t, \qquad \forall t \in T \\ > & \text{value}_t \leq \text{ub}_t, \qquad \forall t \in T > \end{aligned} > \end{split}\]

math Here, lb and ub can be left empty, which drops the respective constraint.

Objectives

cost

Add the (potential) cost of this Profile to the global objective function. The profile.cost setting specifies a potential cost for the creation (“resource costs”, i.e. importing gas into the model) or destruction (“penalties”, i.e. costs linked to the emission of CO2). It can have a unique value for every Snapshot, i.e. allowing to model a time-varying gas price throughout the year. The contribution to the global objective function is as follows: $\( \sum_{t\in T} \text{value}_t \cdot \text{profile.cost}_t \cdot \omega_t \)\( math Here \)\omega_t\( is the `weight` of `Snapshot` `t`, and \)\text{value}_t$ actually refers to the value of profile.exp.value[t] (and not only on the maybe non-existing variable).