Profile

Note

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

If you spot incorrect math-mode rendering, or similar issues, please file an issue, since rendering documentation from Julia to Python is not the easiest task.

Overview

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.

Parameters

carrier

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

  • mandatory: yes

  • default: \(-\)

  • values: string

  • unit: -

value

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

  • mandatory: no

  • default: \(-\)

  • values: numeric, col@file

  • unit: power

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

  • default: \(-\)

  • values: string

  • unit: -

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

  • default: \(-\)

  • values: string

  • unit: -

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

  • default: \(fixed\)

  • values: -

  • unit: -

lb

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

  • mandatory: no

  • default: \(-\infty\)

  • values: numeric

  • unit: power

ub

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

  • mandatory: no

  • default: \(+\infty\)

  • values: numeric

  • unit: power

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

  • default: \(0\)

  • values: numeric

  • unit: monetary per energy

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

  • default: \(0\)

  • values: numeric

  • unit: -

Detailed reference

Expressions

value

Full implementation and all details: profile/exp_value @ IESopt.jl

Construct 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 initialized based on profile.value.

Variables

aux_value

Full implementation and all details: profile/var_aux_value @ IESopt.jl

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 detailed 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{split} \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} \end{split}\]

Constraints

value_bounds

Full implementation and all details: profile/con_value_bounds @ IESopt.jl

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} \]

 

 

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}\]

 

 

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

Objectives

cost

Full implementation and all details: profile/obj_cost @ IESopt.jl

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 \]

 

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).