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.
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
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@fileunit: 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
How to access this expression?
# Using Julia (`IESopt.jl`):
import IESopt
model = IESopt.run(...) # assuming this is your model
IESopt.get_component(model, "your_profile").exp.value
# Using Python (`iesopt`):
import iesopt
model = iesopt.run(...) # assuming this is your model
model.get_component("your_profile").exp.value
Full implementation and all details: profile/exp_value @ IESopt.jl
Construct the
JuMP.AffExprthat keeps the total value of thisProfilefor eachSnapshot.
This is skipped if the
valueof thisProfileis handled by anExpression. Otherwise it is initialized based onprofile.value.
Variables
aux_value
How to access this variable?
# Using Julia (`IESopt.jl`):
import IESopt
model = IESopt.run(...) # assuming this is your model
IESopt.get_component(model, "your_profile").var.aux_value
# Using Python (`iesopt`):
import iesopt
model = iesopt.run(...) # assuming this is your model
model.get_component("your_profile").var.aux_value
Full implementation and all details: profile/var_aux_value @ IESopt.jl
Add the variable that is used in this
Profiles value toprofile.model.
The variable
var_value[t]is constructed and is linked to the correctNodes. There are different ways, IESopt interprets this, based on the setting ofprofile.mode:
fixed: The value is already handled by the constant term of
profile.exp.valueand NO variable is constructed.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
createshould mostly be used feeding into aNode(profile.node_from = nothing) anddestroywithdrawing from aNode(profile.node_to = nothing). Iflbandubare defined,rangedcan be used that allows a more detailed control over theProfile, specifying upper and lower bounds for everySnapshot. 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 (thatprofile.exp.valuerepresents) gets “injected” at theNodes that theprofileis connected to, resulting in
Constraints
value_bounds
How to access this constraint?
# Using Julia (`IESopt.jl`):
import IESopt
model = IESopt.run(...) # assuming this is your model
IESopt.get_component(model, "your_profile").con.value_bounds
# Using Python (`iesopt`):
import iesopt
model = iesopt.run(...) # assuming this is your model
model.get_component("your_profile").con.value_bounds
Full implementation and all details: profile/con_value_bounds @ IESopt.jl
Add the constraint defining the bounds of this
profiletoprofile.model.
This heavily depends on the
modesetting, as it does nothing if themodeis set tofixed, or thevalueis actually controlled by anExpression. The variable can be accessed viaprofile.var.aux_value[t], but using the normal result extraction is recommended, since that properly handles theprofile.exp.valueinstead.
Otherwise:
if profile.mode === :create or profile.mode === :destroy
if profile.mode === :ranged
Here,
lbandubcan be left empty, which drops the respective constraint.
Objectives
cost
How to access this objective?
# Using Julia (`IESopt.jl`):
import IESopt
model = IESopt.run(...) # assuming this is your model
IESopt.get_component(model, "your_profile").obj.cost
# Using Python (`iesopt`):
import iesopt
model = iesopt.run(...) # assuming this is your model
model.get_component("your_profile").obj.cost
Full implementation and all details: profile/obj_cost @ IESopt.jl
Add the (potential) cost of this
Profileto the global objective function.
The
profile.costsetting 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 everySnapshot, i.e. allowing to model a time-varying gas price throughout the year.
The contribution to the global objective function is as follows:
Here \(\omega_t\) is the
weightofSnapshott, and \(\text{value}_t\) actually refers to the value ofprofile.exp.value[t](and not only on the maybe non-existing variable).