diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json index 52882a1..9339f64 100644 --- a/dev/.documenter-siteinfo.json +++ b/dev/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.10.5","generation_timestamp":"2024-10-23T13:14:49","documenter_version":"1.7.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.10.5","generation_timestamp":"2024-10-28T12:23:18","documenter_version":"1.7.0"}} \ No newline at end of file diff --git a/dev/index.html b/dev/index.html index 28ebd5a..a8732fd 100644 --- a/dev/index.html +++ b/dev/index.html @@ -6,4 +6,4 @@ url = {https://github.com/ait-energy/IESopt}, type = {Software}, year = {2021-2024}, -} +} diff --git a/dev/pages/changelog/index.html b/dev/pages/changelog/index.html index 1c0bcbc..20ad88d 100644 --- a/dev/pages/changelog/index.html +++ b/dev/pages/changelog/index.html @@ -1,2 +1,2 @@ -Changelog · -- IESopt --

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[1.0.5] - 2024-09-11

Bug fixes in custom objective building, and better exception handling for log files.

[1.0.4] - 2024-07-26

Migrate full core component parameter docstrings.

[1.0.3] - 2024-06-18

Relax version requirements on IESoptLib to include all v0.2.z versions.

[1.0.2] - 2024-06-10

Fix solver setup for various workflows.

Changed

  • IESoptLib and HiGHS are again required dependencies.

[1.0.1] - 2024-06-09

Added extensions to properly handle loading IESoptLib and various solvers.

Changed

  • IESoptLib and HiGHS are no longer required dependencies.

Fixed

  • Dynamic loading of weakdeps now works properly.

[1.0.0] - 2024-06-01

Added

  • Initial public release of IESopt.jl
+Changelog · -- IESopt --

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[1.0.5] - 2024-09-11

Bug fixes in custom objective building, and better exception handling for log files.

[1.0.4] - 2024-07-26

Migrate full core component parameter docstrings.

[1.0.3] - 2024-06-18

Relax version requirements on IESoptLib to include all v0.2.z versions.

[1.0.2] - 2024-06-10

Fix solver setup for various workflows.

Changed

  • IESoptLib and HiGHS are again required dependencies.

[1.0.1] - 2024-06-09

Added extensions to properly handle loading IESoptLib and various solvers.

Changed

  • IESoptLib and HiGHS are no longer required dependencies.

Fixed

  • Dynamic loading of weakdeps now works properly.

[1.0.0] - 2024-06-01

Added

  • Initial public release of IESopt.jl
diff --git a/dev/pages/dev_docs/index.html b/dev/pages/dev_docs/index.html index cf0bf48..9fb65ef 100644 --- a/dev/pages/dev_docs/index.html +++ b/dev/pages/dev_docs/index.html @@ -1,2 +1,2 @@ -Developer Documentation · -- IESopt --

Developer Documentation

The following sections provide rough guidelines on how to work with IESopt, and mostly IESopt.jl, improving the documentation, testing, and implementing new features.

Helping out

Looking for things to contribute, with a low entry barrier (besides any open issue)? Check for To be added (especially in the documentation), or TODO (especially in the code).

Getting started

General

  1. Install Julia.
  2. Install VSCode, and some extensions (this step is optional, but highly recommended).
  3. Clone/fork the repository.
  4. Happy coding (... see below)!

If you are new to Julia, or not entirely sure how everything works - let's talk. We are happy to help you get started, and to guide you through the process. Stuff like Revise.jl can be a huge help, and we can show you how to use it. Further, if you are coming from, e.g., a standard Python background, the advantages of a dynamic REPL-driven development may be new to you.

Tips and tricks

Architecture

See ARCHITECTURE.md for more information.

Coding conventions

Branches

We mainly use a "feature branch workflow", similar to "trunk based development". We strive to keep the main branch as clean as possible (docs and tests should build and pass), and work on a separate development (trunk) branch. For larger changes, consider starting new feature branches. Where possible we use PRs (or merge requests) to get changes into the main branch, while doing a (light) code review for each other.

Naming conventions

Julia

We make use of the following naming conventions, which slightly differ from the Julia naming conventions, but are similar to other large projects out there:

  • Types and similar items use CamelCase, e.g., MyType.
  • Functions and variables use snake_case, e.g., my_function(...).
  • Functions that modify their arguments should end with an exclamation mark, e.g., optimize!(...).
  • Functions and variables should actually make use of underscores, whenever reasonable (and not only when absolutely necessary), e.g., set_to_zero!(...) (not settozero!(...) like the Julia naming conventions may suggest).
  • Constants are written in UPPERCASE, e.g., MY_CONSTANT.

Python

To be added (black with --line-length 88, ruff, standard naming conventions, ...).

Conventional commits

Refer to the Conventional Commits specification for a detailed explanation. In short, we use the following format:

  • feat: implemented new feature X
  • fix: fixed the bug X
  • refactor: refactored the code X
  • docs: updated the documentation X
  • test: added a new test for X
  • chore: updated the dependencies X

As indicated we use docs, but test (and not tests), which can be remembered by looking at the folder names: docs/ and test/.

Version numbers

Documenter.jl (as of May, 22nd, 2024) aggressively states: "Documenter, like any good Julia package, follows semantic versioning (SemVer)."

Unfortunately, semantic versioning may not be as well suited as one might think for a package like IESopt.jl. Some reasons are:

  • While the (Julia) API has been stable for a long time (in a sense of: backwards-compatible), we consider the YAML configuration syntax as main part of IESopt's "API". This syntax has changed multiple times, and will likely change in the future. Maintaining full backwards compatibility for this is not feasible all the time. This induces a need for a major version bump, even though the Julia API has not changed.
  • A mere bug fix, even a small one, in IESopt.jl may very likely induce changed results of any model run. A user could see vastly different results between v1.3.10 and v1.3.11, even though the changes are minimal. This envolves not taking patch updates lightly, which is not the case in many other packages.

However, as indicated, the use of semantic versioning is still "expected" by large parts of the Julia community, and not doing so may make it harder for some users, and/or some interactions with other packages. So...

  1. IESopt.jl makes use of semantic versioning!
  2. You are advised to consider the above points when deciding on version bumps.
  3. Advise users and make sure you properly document changes.
  4. Expect rising major version numbers.

Working with VSCode

The following set of extensions may be helpful, either for development or documentation purposes:

Improving the documentation

Docstrings of public entries of IESopt.jl are taken from the code, see src/.... Besides that, the documentation is contained in the docs/src/... folder, and built based on docs/make.jl, using Documenter.jl.

Diátaxis

Consider checking out the excellent "project" Diátaxis, by Daniele Procida. We try to adhere to the principles outlined there, and you may find them useful as well. For a quick intro, you may consider starting here: The difference between a tutorial and how-to guide.

Setup

Make sure that you

  1. have a working installation of Julia (otherwise go to julialang.org and install it; we recommend sticking to Juliaup if asked), and
  2. have a terminal of your choice launched at IESopt.jl/.

Then, run the following command once to set up the environment used for the documentation:

julia --project=docs -e 'import Pkg; Pkg.instantiate()'

Building the documentation

Launch an interactive web server that shows you the documentation while you are working on it:

julia --project=docs -e 'using LiveServer; servedocs(; launch_browser=true)'

Note: While the above is your best choice in 95% of all cases, you can also manually build the documentation using

julia --project=docs docs/make.jl

which may be useful if you modify source files (which LiveServer.jl currently does not track in a convenient way). Note however that this will not automatically reload the documentation in your browser (but may in VSCode if you right-click the index.html file and select Preview, using the Live Preview extension), and may fail to properly account for image/... paths.

Code formatting

We provide a custom .JuliaFormatter.toml file that should be used to format the code. The easiest way to use it is to:

  1. Add JuliaFormatter to your Julia base environment by running ] add JuliaFormatter in the package mode of your Julia REPL (without an active IESopt environment).
  2. Run using JuliaFormatter in the Julia REPL (this now works even if you activated the IESopt environment).
  3. Run format(".") in the Julia REPL to format all files in your current directory. This takes a bit of compile time, but after the first run, it should be fairly fast.

Make sure you checked the formatting, before finalizing your changes or opening a PR. If you forgot to include formatting in your actual commits (we all do...), and cannot reasonably ammend them, add all formatting changes at the end in a single commit with the message:

git commit -m "chore: formatting"

Testing

Running tests locally

Launch a new Julia REPL (hit Alt+J and then Alt+O in VSCode), enter Package mode (by pressing ] in your REPL, now showing (IESopt) pkg>), and then execute all tests by running:

(IESopt) pkg> test
+Developer Documentation · -- IESopt --

Developer Documentation

The following sections provide rough guidelines on how to work with IESopt, and mostly IESopt.jl, improving the documentation, testing, and implementing new features.

Helping out

Looking for things to contribute, with a low entry barrier (besides any open issue)? Check for To be added (especially in the documentation), or TODO (especially in the code).

Getting started

General

  1. Install Julia.
  2. Install VSCode, and some extensions (this step is optional, but highly recommended).
  3. Clone/fork the repository.
  4. Happy coding (... see below)!

If you are new to Julia, or not entirely sure how everything works - let's talk. We are happy to help you get started, and to guide you through the process. Stuff like Revise.jl can be a huge help, and we can show you how to use it. Further, if you are coming from, e.g., a standard Python background, the advantages of a dynamic REPL-driven development may be new to you.

Tips and tricks

Architecture

See ARCHITECTURE.md for more information.

Coding conventions

Branches

We mainly use a "feature branch workflow", similar to "trunk based development". We strive to keep the main branch as clean as possible (docs and tests should build and pass), and work on a separate development (trunk) branch. For larger changes, consider starting new feature branches. Where possible we use PRs (or merge requests) to get changes into the main branch, while doing a (light) code review for each other.

Naming conventions

Julia

We make use of the following naming conventions, which slightly differ from the Julia naming conventions, but are similar to other large projects out there:

  • Types and similar items use CamelCase, e.g., MyType.
  • Functions and variables use snake_case, e.g., my_function(...).
  • Functions that modify their arguments should end with an exclamation mark, e.g., optimize!(...).
  • Functions and variables should actually make use of underscores, whenever reasonable (and not only when absolutely necessary), e.g., set_to_zero!(...) (not settozero!(...) like the Julia naming conventions may suggest).
  • Constants are written in UPPERCASE, e.g., MY_CONSTANT.

Python

To be added (black with --line-length 88, ruff, standard naming conventions, ...).

Conventional commits

Refer to the Conventional Commits specification for a detailed explanation. In short, we use the following format:

  • feat: implemented new feature X
  • fix: fixed the bug X
  • refactor: refactored the code X
  • docs: updated the documentation X
  • test: added a new test for X
  • chore: updated the dependencies X

As indicated we use docs, but test (and not tests), which can be remembered by looking at the folder names: docs/ and test/.

Version numbers

Documenter.jl (as of May, 22nd, 2024) aggressively states: "Documenter, like any good Julia package, follows semantic versioning (SemVer)."

Unfortunately, semantic versioning may not be as well suited as one might think for a package like IESopt.jl. Some reasons are:

  • While the (Julia) API has been stable for a long time (in a sense of: backwards-compatible), we consider the YAML configuration syntax as main part of IESopt's "API". This syntax has changed multiple times, and will likely change in the future. Maintaining full backwards compatibility for this is not feasible all the time. This induces a need for a major version bump, even though the Julia API has not changed.
  • A mere bug fix, even a small one, in IESopt.jl may very likely induce changed results of any model run. A user could see vastly different results between v1.3.10 and v1.3.11, even though the changes are minimal. This envolves not taking patch updates lightly, which is not the case in many other packages.

However, as indicated, the use of semantic versioning is still "expected" by large parts of the Julia community, and not doing so may make it harder for some users, and/or some interactions with other packages. So...

  1. IESopt.jl makes use of semantic versioning!
  2. You are advised to consider the above points when deciding on version bumps.
  3. Advise users and make sure you properly document changes.
  4. Expect rising major version numbers.

Working with VSCode

The following set of extensions may be helpful, either for development or documentation purposes:

Improving the documentation

Docstrings of public entries of IESopt.jl are taken from the code, see src/.... Besides that, the documentation is contained in the docs/src/... folder, and built based on docs/make.jl, using Documenter.jl.

Diátaxis

Consider checking out the excellent "project" Diátaxis, by Daniele Procida. We try to adhere to the principles outlined there, and you may find them useful as well. For a quick intro, you may consider starting here: The difference between a tutorial and how-to guide.

Setup

Make sure that you

  1. have a working installation of Julia (otherwise go to julialang.org and install it; we recommend sticking to Juliaup if asked), and
  2. have a terminal of your choice launched at IESopt.jl/.

Then, run the following command once to set up the environment used for the documentation:

julia --project=docs -e 'import Pkg; Pkg.instantiate()'

Building the documentation

Launch an interactive web server that shows you the documentation while you are working on it:

julia --project=docs -e 'using LiveServer; servedocs(; launch_browser=true)'

Note: While the above is your best choice in 95% of all cases, you can also manually build the documentation using

julia --project=docs docs/make.jl

which may be useful if you modify source files (which LiveServer.jl currently does not track in a convenient way). Note however that this will not automatically reload the documentation in your browser (but may in VSCode if you right-click the index.html file and select Preview, using the Live Preview extension), and may fail to properly account for image/... paths.

Code formatting

We provide a custom .JuliaFormatter.toml file that should be used to format the code. The easiest way to use it is to:

  1. Add JuliaFormatter to your Julia base environment by running ] add JuliaFormatter in the package mode of your Julia REPL (without an active IESopt environment).
  2. Run using JuliaFormatter in the Julia REPL (this now works even if you activated the IESopt environment).
  3. Run format(".") in the Julia REPL to format all files in your current directory. This takes a bit of compile time, but after the first run, it should be fairly fast.

Make sure you checked the formatting, before finalizing your changes or opening a PR. If you forgot to include formatting in your actual commits (we all do...), and cannot reasonably ammend them, add all formatting changes at the end in a single commit with the message:

git commit -m "chore: formatting"

Testing

Running tests locally

Launch a new Julia REPL (hit Alt+J and then Alt+O in VSCode), enter Package mode (by pressing ] in your REPL, now showing (IESopt) pkg>), and then execute all tests by running:

(IESopt) pkg> test
diff --git a/dev/pages/manual___reference/api/index.html b/dev/pages/manual___reference/api/index.html index a01cc45..d9468a4 100644 --- a/dev/pages/manual___reference/api/index.html +++ b/dev/pages/manual___reference/api/index.html @@ -1,12 +1,12 @@ -API · -- IESopt --

API

This contains the following raw documentation entries:


Julia

Modules

IESopt.IESoptModule
IESopt

A general purpose solver agnostic energy system optimization framework.

source

Types

IESopt.CarrierType
struct Carrier
+API · -- IESopt --

API

This contains the following raw documentation entries:


Julia

Modules

IESopt.IESoptModule
IESopt

A general purpose solver agnostic energy system optimization framework.

source

Types

IESopt.CarrierType
struct Carrier
     name::String
     unit::Union{String, Nothing}
-end

Represents a single (energy) carrier with a given name.

This is mostly used to represent various commodities that (easily) represent some form of energy (e.g. gas, water, ...), but also enables modelling commodities that are not (treated as) representing some type of energy (e.g. CO2). Specify unit to bind that carrier to an (arbitrary) unit that allows easier plotting and result analysis.

source
IESopt.SnapshotType
struct Snapshot
+end

Represents a single (energy) carrier with a given name.

This is mostly used to represent various commodities that (easily) represent some form of energy (e.g. gas, water, ...), but also enables modelling commodities that are not (treated as) representing some type of energy (e.g. CO2). Specify unit to bind that carrier to an (arbitrary) unit that allows easier plotting and result analysis.

source
IESopt.SnapshotType
struct Snapshot
     name
     id
     weight
-end

Represent a specific timestamp, that can be tied to timeseries values.

Each Snapshot expects a name, that can be used to hold a timestamp (as String; therefore supporting arbitrary formats). The weight (default = 1.0) specifies the "probabilistic weight" of this Snapshot or the length of the timeperiod that begins there (a weight of 2 can therefore represent a 2-hour-resolution; this also allows a variable temporal resolution throughout the year/month/...).

source
IESopt.ConnectionType

A Connection is used to model arbitrary flows of energy between Nodes. It allows for limits, costs, delays, ...

Parameters

NameMandatoryValuesUnitDefaultDescription
node_fromyesstring--This Connection models a flow from node_from to node_to (both are Nodes).
node_toyesstring--This Connection models a flow from node_from to node_to (both are Nodes).
carriernostring--Carrier of this Connection. If not given, automatically picks the carrier of the Nodes it connects. This parameter is not necessary, and only exists to allow for a more explicit definition.
capacitynonumeric, col@file, decision:valuepower$+\infty$The symmetric bound on this Connection's flow. Results in lb = -capacity and ub = capacity. Must not be specified if lb, ub, or both are explicitly stated.
lbnonumeric, col@file, decision:valuepower$-\infty$Lower bound of this Connection's flow.
ubnonumeric, col@file, decision:valuepower$+\infty$Upper bound of this Connection's flow.
costnonumericmonetary (per energy)-Cost of every unit of energy flow over this connection that is added to the model's objective function. Keep in mind that negative flows will induce negative costs, which can be used to model revenues. Further, a bidirectional Connection (if lb < 0, which is the default, or if capacity is used) with a positive cost will lead to negative costs for the reverse flow. If you do not want this, split the Connection into two separate ones, each being unidirectional (with lb: 0). Remember, that these can share the same "capacity" (which is then set asub), even when using decision:value or col@file as value.
lossno$\in [0, 1]$-0Fractional loss when transfering energy. This loss occurs "at the destination", which means that for a loss of 5%, set as loss: 0.05, and considering a Snapshot where the Connection has a flow value of 100, it will "extract" 100 from node_from and "inject" 95 into node_to. Since the flow variable is given as power, this would, e.g., translate to consuming 200 units of energy at node_from and injecting 190 units at node_to, if the Snapshot duration is 2 hours.
build_prioritynonumeric-0Priority 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.

Detailed Model Reference

Variables

flow
How to?

Access this variable by using:

# Julia
+end

Represent a specific timestamp, that can be tied to timeseries values.

Each Snapshot expects a name, that can be used to hold a timestamp (as String; therefore supporting arbitrary formats). The weight (default = 1.0) specifies the "probabilistic weight" of this Snapshot or the length of the timeperiod that begins there (a weight of 2 can therefore represent a 2-hour-resolution; this also allows a variable temporal resolution throughout the year/month/...).

source
IESopt.ConnectionType

A Connection is used to model arbitrary flows of energy between Nodes. It allows for limits, costs, delays, ...

Parameters

NameMandatoryValuesUnitDefaultDescription
node_fromyesstring--This Connection models a flow from node_from to node_to (both are Nodes).
node_toyesstring--This Connection models a flow from node_from to node_to (both are Nodes).
carriernostring--Carrier of this Connection. If not given, automatically picks the carrier of the Nodes it connects. This parameter is not necessary, and only exists to allow for a more explicit definition.
capacitynonumeric, col@file, decision:valuepower$+\infty$The symmetric bound on this Connection's flow. Results in lb = -capacity and ub = capacity. Must not be specified if lb, ub, or both are explicitly stated.
lbnonumeric, col@file, decision:valuepower$-\infty$Lower bound of this Connection's flow.
ubnonumeric, col@file, decision:valuepower$+\infty$Upper bound of this Connection's flow.
costnonumericmonetary (per energy)-Cost of every unit of energy flow over this connection that is added to the model's objective function. Keep in mind that negative flows will induce negative costs, which can be used to model revenues. Further, a bidirectional Connection (if lb < 0, which is the default, or if capacity is used) with a positive cost will lead to negative costs for the reverse flow. If you do not want this, split the Connection into two separate ones, each being unidirectional (with lb: 0). Remember, that these can share the same "capacity" (which is then set asub), even when using decision:value or col@file as value.
lossno$\in [0, 1]$-0Fractional loss when transfering energy. This loss occurs "at the destination", which means that for a loss of 5%, set as loss: 0.05, and considering a Snapshot where the Connection has a flow value of 100, it will "extract" 100 from node_from and "inject" 95 into node_to. Since the flow variable is given as power, this would, e.g., translate to consuming 200 units of energy at node_from and injecting 190 units at node_to, if the Snapshot duration is 2 hours.
build_prioritynonumeric-0Priority 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.

Detailed Model Reference

Variables

flow
How to?

Access this variable by using:

# Julia
 component(model, "your_connection").var.flow
# Python
 model.get_component("your_connection").var.flow

You can find the full implementation and all details here: IESopt.jl.

Add the variable representing the flow of this connection to the model. This can be accessed via connection.var.flow[t].

Additionally, the flow gets "injected" at the Nodes that the connection is connecting, resulting in

\[\begin{aligned} & \text{connection.node}_{from}\text{.injection}_t = \text{connection.node}_{from}\text{.injection}_t - \text{flow}_t, \qquad \forall t \in T \\ @@ -20,7 +20,7 @@ & \text{flow}_t \leq \text{ub}, \qquad \forall t \in T \end{aligned}\]

math

Constraint safety

The lower and upper bound constraint are subject to penalized slacks.

Objectives

cost
How to?

Access this objective by using:

# Julia
 component(model, "your_connection").obj.cost
# Python
-model.get_component("your_connection").obj.cost

You can find the full implementation and all details here: IESopt.jl.

Add the (potential) cost of this connection to the global objective function.

The connection.cost setting introduces a fixed cost of "transportation" to the flow of this Connection. It is based on the directed flow. This means that flows in the "opposite" direction will lead to negative costs:

\[\sum_{t \in T} \text{flow}_t \cdot \text{cost}_t \cdot \omega_t\]

math

Here $\omega_t$ is the weight of Snapshot t.

Costs for flows in both directions

If you need to apply a cost term to the absolute value of the flow, consider splitting the Connection into two different ones, in opposing directions, and including lb = 0.

source
IESopt.DecisionType

A Decision represents a basic decision variable in the model that can be used as input for various other core component's settings, as well as have associated costs.

Parameters

NameMandatoryValuesUnitDefaultDescription
lbnonumeric-0Minimum size of the decision value (considered for each "unit" if count allows multiple "units").
ubnonumeric-$+\infty$Maximum size of the decision value (considered for each "unit" if count allows multiple "units").
costnonumericmonetary (per value)0Cost that the decision value induces, given as $cost \cdot value$.
fixed_valuenonumeric--If mode: fixed, this value is used as the fixed value of the decision. This can be useful if this Decision was used in a previous optimization and its value should be fixed to that value in the next optimization (applying it where ever it is used, instead of needing to find all usages). Furthermore, this allows extracting the dual value of the constraint that fixes the value, assisting in approaches like Benders decomposition. Note that this does not change the induced cost in any way.
fixed_costno-monetary-This setting activates a "fixed cost" component for this decision variable, which requires that the model's problem type allows for binary variables (e.g., MILP). This can be used to model fixed costs that are only incurred if the decision variable is active (e.g., a fixed cost for an investment that is only incurred if the investment is made). If the decision is 0, no fixed costs have to be paid; however, if the decision is greater than 0, the fixed cost is incurred. Note that after deciding to activate the decision, the overall value is still determined in the usual (continuous) way, incuring the (variable) cost as well. More complex cost functions can be modelled by switching to mode sos1 or sos2 and using the sos parameter.
modenolinear, binary, integer, sos1, sos2, fixed-linearType of the decision variable that is constructed. linear results in a continuous decision, integer results in a integer variable, binary constrains it to be either 0 or 1. sos1 and sos2 can be used to activate SOS1 or SOS2 mode (used for piecewise linear costs). See fixed_value if setting this to fixed.
sosnolist--TODO (meanwhile, refer to the SOS or PiecewiseLinearCost example).
build_prioritynonumeric-1000Priority 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.

Detailed Model Reference

Variables

fixed
How to?

Access this variable by using:

# Julia
+model.get_component("your_connection").obj.cost

You can find the full implementation and all details here: IESopt.jl.

Add the (potential) cost of this connection to the global objective function.

The connection.cost setting introduces a fixed cost of "transportation" to the flow of this Connection. It is based on the directed flow. This means that flows in the "opposite" direction will lead to negative costs:

\[\sum_{t \in T} \text{flow}_t \cdot \text{cost}_t \cdot \omega_t\]

math

Here $\omega_t$ is the weight of Snapshot t.

Costs for flows in both directions

If you need to apply a cost term to the absolute value of the flow, consider splitting the Connection into two different ones, in opposing directions, and including lb = 0.

source
IESopt.DecisionType

A Decision represents a basic decision variable in the model that can be used as input for various other core component's settings, as well as have associated costs.

Parameters

NameMandatoryValuesUnitDefaultDescription
lbnonumeric-0Minimum size of the decision value (considered for each "unit" if count allows multiple "units").
ubnonumeric-$+\infty$Maximum size of the decision value (considered for each "unit" if count allows multiple "units").
costnonumericmonetary (per value)0Cost that the decision value induces, given as $cost \cdot value$.
fixed_valuenonumeric--If mode: fixed, this value is used as the fixed value of the decision. This can be useful if this Decision was used in a previous optimization and its value should be fixed to that value in the next optimization (applying it where ever it is used, instead of needing to find all usages). Furthermore, this allows extracting the dual value of the constraint that fixes the value, assisting in approaches like Benders decomposition. Note that this does not change the induced cost in any way.
fixed_costno-monetary-This setting activates a "fixed cost" component for this decision variable, which requires that the model's problem type allows for binary variables (e.g., MILP). This can be used to model fixed costs that are only incurred if the decision variable is active (e.g., a fixed cost for an investment that is only incurred if the investment is made). If the decision is 0, no fixed costs have to be paid; however, if the decision is greater than 0, the fixed cost is incurred. Note that after deciding to activate the decision, the overall value is still determined in the usual (continuous) way, incuring the (variable) cost as well. More complex cost functions can be modelled by switching to mode sos1 or sos2 and using the sos parameter.
modenolinear, binary, integer, sos1, sos2, fixed-linearType of the decision variable that is constructed. linear results in a continuous decision, integer results in a integer variable, binary constrains it to be either 0 or 1. sos1 and sos2 can be used to activate SOS1 or SOS2 mode (used for piecewise linear costs). See fixed_value if setting this to fixed.
sosnolist--TODO (meanwhile, refer to the SOS or PiecewiseLinearCost example).
build_prioritynonumeric-1000Priority 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.

Detailed Model Reference

Variables

fixed
How to?

Access this variable by using:

# Julia
 component(model, "your_decision").var.fixed
# Python
 model.get_component("your_decision").var.fixed

You can find the full implementation and all details here: IESopt.jl.

to be added

sos
How to?

Access this variable by using:

# Julia
 component(model, "your_decision").var.sos
# Python
@@ -40,7 +40,7 @@
 component(model, "your_decision").obj.sos
# Python
 model.get_component("your_decision").obj.sos

You can find the full implementation and all details here: IESopt.jl.

Add the cost defined by the SOS-based value of this Decision to the model.

value
How to?

Access this objective by using:

# Julia
 component(model, "your_decision").obj.value
# Python
-model.get_component("your_decision").obj.value

You can find the full implementation and all details here: IESopt.jl.

Add the cost defined by the value of this Decision to the model:

\[\text{value} \cdot \text{cost}\]

math

source
IESopt.NodeType

A Node represents a basic intersection/hub for energy flows. This can for example be some sort of bus (for electrical systems). It enforces a nodal balance equation (= "energy that flows into it must flow out") for every Snapshot. Enabling the internal state of the Node allows it to act as energy storage, modifying the nodal balance equation. This allows using Nodes for various storage tasks (like batteries, hydro reservoirs, heat storages, ...).

Basic Examples

A Node that represents an electrical bus:

bus:
+model.get_component("your_decision").obj.value

You can find the full implementation and all details here: IESopt.jl.

Add the cost defined by the value of this Decision to the model:

\[\text{value} \cdot \text{cost}\]

math

source
IESopt.NodeType

A Node represents a basic intersection/hub for energy flows. This can for example be some sort of bus (for electrical systems). It enforces a nodal balance equation (= "energy that flows into it must flow out") for every Snapshot. Enabling the internal state of the Node allows it to act as energy storage, modifying the nodal balance equation. This allows using Nodes for various storage tasks (like batteries, hydro reservoirs, heat storages, ...).

Basic Examples

A Node that represents an electrical bus:

bus:
   type: Node
   carrier: electricity

A Node that represents a simplified hydrogen storage:

store:
   type: Node
@@ -71,7 +71,7 @@
 model.get_component("your_node").con.state_bounds

You can find the full implementation and all details here: IESopt.jl.

Add the constraint defining the bounds of the node's state to the model, if node.has_state == true.

\[\begin{aligned} & \text{state}_t \geq \text{state}_{lb}, \qquad \forall t \in T \\ & \text{state}_t \leq \text{state}_{ub}, \qquad \forall t \in T -\end{aligned}\]

math

Constraint safety

The lower and upper bound constraint are subject to penalized slacks.

Objectives

source
IESopt.ProfileType

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:
+\end{aligned}\]

math

Constraint safety

The lower and upper bound constraint are subject to penalized slacks.

Objectives

source
IESopt.ProfileType

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
@@ -106,7 +106,7 @@
     & \text{value}_t \leq \text{ub}_t, \qquad \forall t \in T
 \end{aligned}\]

math

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

Objectives

cost
How to?

Access this objective by using:

# Julia
 component(model, "your_profile").obj.cost
# Python
-model.get_component("your_profile").obj.cost

You can find the full implementation and all details here: 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\]

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

source
IESopt.UnitType

A Unit allows transforming one (or many) forms of energy into another one (or many), given some constraints and costs.

Basic Examples

A Unit that represents a basic gas turbine:

gas_turbine:
+model.get_component("your_profile").obj.cost

You can find the full implementation and all details here: 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\]

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

source
IESopt.UnitType

A Unit allows transforming one (or many) forms of energy into another one (or many), given some constraints and costs.

Basic Examples

A Unit that represents a basic gas turbine:

gas_turbine:
   type: Unit
   inputs: {gas: gas_grid}
   outputs: {electricity: node, co2: total_co2}
@@ -176,4 +176,4 @@
 component(model, "your_unit").obj.ramp_cost
# Python
 model.get_component("your_unit").obj.ramp_cost

You can find the full implementation and all details here: IESopt.jl.

Add the (potential) cost of this unit's ramping to the global objective function.

To allow for finer control, costs of up- and downwards ramping can be specified separately (using unit.ramp_up_cost and unit.ramp_down_cost):

\[\sum_{t \in T} \text{ramp}_{\text{up}, t} \cdot \text{rampcost}_{\text{up}} + \text{ramp}_{\text{down}, t} \cdot \text{rampcost}_{\text{down}}\]

math

startup_cost
How to?

Access this objective by using:

# Julia
 component(model, "your_unit").obj.startup_cost
# Python
-model.get_component("your_unit").obj.startup_cost

You can find the full implementation and all details here: IESopt.jl.

Add the (potential) cost of this unit's startup behaviour (configured by unit.startup_cost if unit.unit_commitment != :off).

\[\sum_{t \in T} \text{startup}_t \cdot \text{startupcost}\]

math

source

Functions

IESopt.runFunction
run(filename::String; verbosity=nothing, kwargs...)

Build, optimize, and return a model.

Arguments

  • filename::String: The path to the top-level configuration file.
  • verbosity: The verbosity level to use. Supports true (= verbose mode), "warning" (= warnings and above), and false (suppressing logs).

If verbosity = true, the verbosity setting of the solver defaults to true as well, otherwise it defaults to false (the verbosity setting of the solver can also be directly controled using the verbosity_solve setting in the top-level config file).

Keyword Arguments

Keyword arguments are passed to the generate! function.

source
IESopt.generate!Function
generate!(filename::String)

Builds and returns a model using the IESopt framework.

This loads the configuration file specified by filename. Requires full specification of the solver entry in config.

source
generate!(model::JuMP.Model, filename::String)

Builds a model using the IESopt framework, "into" the provided model.

This loads the configuration file specified by filename. Be careful when creating your model in any other way than in the provided examples, as this can conflict with IESopt internals (especially for model/optimizer combinations that do not support bridges). Returns the model for convenience, even though it is modified in place.

source
IESopt.optimize!Function
optimize!(model::JuMP.Model; save_results::Bool=true, kwargs...)

Use JuMP.optimize! to optimize the given model, optionally serializing the model afterwards for later use.

source
IESopt.componentFunction
function component(model::JuMP.Model, component_name::String)

Get the component component_name from model.

source
IESopt.compute_IISFunction
function compute_IIS(model::JuMP.Model; filename::String = "")

Compute the IIS and print it. If filename is specified it will instead write all constraints to the given file. This will fail if the solver does not support IIS computation.

source
IESopt.overviewFunction
overview(file::String)

Extracts the most important information from an IESopt model file, and returns it as a dictionary.

source
IESopt.packFunction
pack(file::String; out::String="", method=:store)

Packs the IESopt model specified by the top-level config file file into single file.

The out argument specifies the output file name. If not specified, a temporary file is created. Returns the output file name. The method argument specifies the compression method to use. The default is :store, which means no compression is used. The other option is :deflate, which uses the DEFLATE compression method. The default (:auto) applies :store to all files below 1 MB, :deflate otherwise.

source
IESopt.unpackFunction
unpack(file::String; out::String="", force_overwrite::Bool=false)

Unpacks the IESopt model specified by file.

The out argument specifies the output directory. If not specified, a temporary directory is created. Returns the path to the top-level config file. The force_overwrite argument specifies whether to overwrite existing files.

source

Python

To be added.

+model.get_component("your_unit").obj.startup_cost

You can find the full implementation and all details here: IESopt.jl.

Add the (potential) cost of this unit's startup behaviour (configured by unit.startup_cost if unit.unit_commitment != :off).

\[\sum_{t \in T} \text{startup}_t \cdot \text{startupcost}\]

math

source

Functions

IESopt.runFunction
run(filename::String; verbosity=nothing, kwargs...)

Build, optimize, and return a model.

Arguments

  • filename::String: The path to the top-level configuration file.
  • verbosity: The verbosity level to use. Supports true (= verbose mode), "warning" (= warnings and above), and false (suppressing logs).

If verbosity = true, the verbosity setting of the solver defaults to true as well, otherwise it defaults to false (the verbosity setting of the solver can also be directly controled using the verbosity_solve setting in the top-level config file).

Keyword Arguments

Keyword arguments are passed to the generate! function.

source
IESopt.generate!Function
generate!(filename::String)

Builds and returns a model using the IESopt framework.

This loads the configuration file specified by filename. Requires full specification of the solver entry in config.

source
generate!(model::JuMP.Model, filename::String)

Builds a model using the IESopt framework, "into" the provided model.

This loads the configuration file specified by filename. Be careful when creating your model in any other way than in the provided examples, as this can conflict with IESopt internals (especially for model/optimizer combinations that do not support bridges). Returns the model for convenience, even though it is modified in place.

source
IESopt.optimize!Function
optimize!(model::JuMP.Model; save_results::Bool=true, kwargs...)

Use JuMP.optimize! to optimize the given model, optionally serializing the model afterwards for later use.

source
IESopt.componentFunction
function component(model::JuMP.Model, component_name::String)

Get the component component_name from model.

source
IESopt.compute_IISFunction
function compute_IIS(model::JuMP.Model; filename::String = "")

Compute the IIS and print it. If filename is specified it will instead write all constraints to the given file. This will fail if the solver does not support IIS computation.

source
IESopt.overviewFunction
overview(file::String)

Extracts the most important information from an IESopt model file, and returns it as a dictionary.

source
IESopt.packFunction
pack(file::String; out::String="", method=:store)

Packs the IESopt model specified by the top-level config file file into single file.

The out argument specifies the output file name. If not specified, a temporary file is created. Returns the output file name. The method argument specifies the compression method to use. The default is :store, which means no compression is used. The other option is :deflate, which uses the DEFLATE compression method. The default (:auto) applies :store to all files below 1 MB, :deflate otherwise.

source
IESopt.unpackFunction
unpack(file::String; out::String="", force_overwrite::Bool=false)

Unpacks the IESopt model specified by file.

The out argument specifies the output directory. If not specified, a temporary directory is created. Returns the path to the top-level config file. The force_overwrite argument specifies whether to overwrite existing files.

source

Python

To be added.

diff --git a/dev/pages/manual___reference/core_components/index.html b/dev/pages/manual___reference/core_components/index.html index ecadd2f..7620d6e 100644 --- a/dev/pages/manual___reference/core_components/index.html +++ b/dev/pages/manual___reference/core_components/index.html @@ -13,7 +13,7 @@ & \text{flow}_t \leq \text{ub}, \qquad \forall t \in T \end{aligned}\]

math

Constraint safety

The lower and upper bound constraint are subject to penalized slacks.

Objectives

cost
How to?

Access this objective by using:

# Julia
 component(model, "your_connection").obj.cost
# Python
-model.get_component("your_connection").obj.cost

You can find the full implementation and all details here: IESopt.jl.

Add the (potential) cost of this connection to the global objective function.

The connection.cost setting introduces a fixed cost of "transportation" to the flow of this Connection. It is based on the directed flow. This means that flows in the "opposite" direction will lead to negative costs:

\[\sum_{t \in T} \text{flow}_t \cdot \text{cost}_t \cdot \omega_t\]

math

Here $\omega_t$ is the weight of Snapshot t.

Costs for flows in both directions

If you need to apply a cost term to the absolute value of the flow, consider splitting the Connection into two different ones, in opposing directions, and including lb = 0.

source
IESopt.DecisionType

A Decision represents a basic decision variable in the model that can be used as input for various other core component's settings, as well as have associated costs.

Parameters

NameMandatoryValuesUnitDefaultDescription
lbnonumeric-0Minimum size of the decision value (considered for each "unit" if count allows multiple "units").
ubnonumeric-$+\infty$Maximum size of the decision value (considered for each "unit" if count allows multiple "units").
costnonumericmonetary (per value)0Cost that the decision value induces, given as $cost \cdot value$.
fixed_valuenonumeric--If mode: fixed, this value is used as the fixed value of the decision. This can be useful if this Decision was used in a previous optimization and its value should be fixed to that value in the next optimization (applying it where ever it is used, instead of needing to find all usages). Furthermore, this allows extracting the dual value of the constraint that fixes the value, assisting in approaches like Benders decomposition. Note that this does not change the induced cost in any way.
fixed_costno-monetary-This setting activates a "fixed cost" component for this decision variable, which requires that the model's problem type allows for binary variables (e.g., MILP). This can be used to model fixed costs that are only incurred if the decision variable is active (e.g., a fixed cost for an investment that is only incurred if the investment is made). If the decision is 0, no fixed costs have to be paid; however, if the decision is greater than 0, the fixed cost is incurred. Note that after deciding to activate the decision, the overall value is still determined in the usual (continuous) way, incuring the (variable) cost as well. More complex cost functions can be modelled by switching to mode sos1 or sos2 and using the sos parameter.
modenolinear, binary, integer, sos1, sos2, fixed-linearType of the decision variable that is constructed. linear results in a continuous decision, integer results in a integer variable, binary constrains it to be either 0 or 1. sos1 and sos2 can be used to activate SOS1 or SOS2 mode (used for piecewise linear costs). See fixed_value if setting this to fixed.
sosnolist--TODO (meanwhile, refer to the SOS or PiecewiseLinearCost example).
build_prioritynonumeric-1000Priority 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.

Detailed Model Reference

Variables

fixed
How to?

Access this variable by using:

# Julia
+model.get_component("your_connection").obj.cost

You can find the full implementation and all details here: IESopt.jl.

Add the (potential) cost of this connection to the global objective function.

The connection.cost setting introduces a fixed cost of "transportation" to the flow of this Connection. It is based on the directed flow. This means that flows in the "opposite" direction will lead to negative costs:

\[\sum_{t \in T} \text{flow}_t \cdot \text{cost}_t \cdot \omega_t\]

math

Here $\omega_t$ is the weight of Snapshot t.

Costs for flows in both directions

If you need to apply a cost term to the absolute value of the flow, consider splitting the Connection into two different ones, in opposing directions, and including lb = 0.

source
IESopt.DecisionType

A Decision represents a basic decision variable in the model that can be used as input for various other core component's settings, as well as have associated costs.

Parameters

NameMandatoryValuesUnitDefaultDescription
lbnonumeric-0Minimum size of the decision value (considered for each "unit" if count allows multiple "units").
ubnonumeric-$+\infty$Maximum size of the decision value (considered for each "unit" if count allows multiple "units").
costnonumericmonetary (per value)0Cost that the decision value induces, given as $cost \cdot value$.
fixed_valuenonumeric--If mode: fixed, this value is used as the fixed value of the decision. This can be useful if this Decision was used in a previous optimization and its value should be fixed to that value in the next optimization (applying it where ever it is used, instead of needing to find all usages). Furthermore, this allows extracting the dual value of the constraint that fixes the value, assisting in approaches like Benders decomposition. Note that this does not change the induced cost in any way.
fixed_costno-monetary-This setting activates a "fixed cost" component for this decision variable, which requires that the model's problem type allows for binary variables (e.g., MILP). This can be used to model fixed costs that are only incurred if the decision variable is active (e.g., a fixed cost for an investment that is only incurred if the investment is made). If the decision is 0, no fixed costs have to be paid; however, if the decision is greater than 0, the fixed cost is incurred. Note that after deciding to activate the decision, the overall value is still determined in the usual (continuous) way, incuring the (variable) cost as well. More complex cost functions can be modelled by switching to mode sos1 or sos2 and using the sos parameter.
modenolinear, binary, integer, sos1, sos2, fixed-linearType of the decision variable that is constructed. linear results in a continuous decision, integer results in a integer variable, binary constrains it to be either 0 or 1. sos1 and sos2 can be used to activate SOS1 or SOS2 mode (used for piecewise linear costs). See fixed_value if setting this to fixed.
sosnolist--TODO (meanwhile, refer to the SOS or PiecewiseLinearCost example).
build_prioritynonumeric-1000Priority 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.

Detailed Model Reference

Variables

fixed
How to?

Access this variable by using:

# Julia
 component(model, "your_decision").var.fixed
# Python
 model.get_component("your_decision").var.fixed

You can find the full implementation and all details here: IESopt.jl.

to be added

sos
How to?

Access this variable by using:

# Julia
 component(model, "your_decision").var.sos
# Python
@@ -33,7 +33,7 @@
 component(model, "your_decision").obj.sos
# Python
 model.get_component("your_decision").obj.sos

You can find the full implementation and all details here: IESopt.jl.

Add the cost defined by the SOS-based value of this Decision to the model.

value
How to?

Access this objective by using:

# Julia
 component(model, "your_decision").obj.value
# Python
-model.get_component("your_decision").obj.value

You can find the full implementation and all details here: IESopt.jl.

Add the cost defined by the value of this Decision to the model:

\[\text{value} \cdot \text{cost}\]

math

source
IESopt.NodeType

A Node represents a basic intersection/hub for energy flows. This can for example be some sort of bus (for electrical systems). It enforces a nodal balance equation (= "energy that flows into it must flow out") for every Snapshot. Enabling the internal state of the Node allows it to act as energy storage, modifying the nodal balance equation. This allows using Nodes for various storage tasks (like batteries, hydro reservoirs, heat storages, ...).

Basic Examples

A Node that represents an electrical bus:

bus:
+model.get_component("your_decision").obj.value

You can find the full implementation and all details here: IESopt.jl.

Add the cost defined by the value of this Decision to the model:

\[\text{value} \cdot \text{cost}\]

math

source
IESopt.NodeType

A Node represents a basic intersection/hub for energy flows. This can for example be some sort of bus (for electrical systems). It enforces a nodal balance equation (= "energy that flows into it must flow out") for every Snapshot. Enabling the internal state of the Node allows it to act as energy storage, modifying the nodal balance equation. This allows using Nodes for various storage tasks (like batteries, hydro reservoirs, heat storages, ...).

Basic Examples

A Node that represents an electrical bus:

bus:
   type: Node
   carrier: electricity

A Node that represents a simplified hydrogen storage:

store:
   type: Node
@@ -64,7 +64,7 @@
 model.get_component("your_node").con.state_bounds

You can find the full implementation and all details here: IESopt.jl.

Add the constraint defining the bounds of the node's state to the model, if node.has_state == true.

\[\begin{aligned} & \text{state}_t \geq \text{state}_{lb}, \qquad \forall t \in T \\ & \text{state}_t \leq \text{state}_{ub}, \qquad \forall t \in T -\end{aligned}\]

math

Constraint safety

The lower and upper bound constraint are subject to penalized slacks.

Objectives

source
IESopt.ProfileType

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:
+\end{aligned}\]

math

Constraint safety

The lower and upper bound constraint are subject to penalized slacks.

Objectives

source
IESopt.ProfileType

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
@@ -99,7 +99,7 @@
     & \text{value}_t \leq \text{ub}_t, \qquad \forall t \in T
 \end{aligned}\]

math

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

Objectives

cost
How to?

Access this objective by using:

# Julia
 component(model, "your_profile").obj.cost
# Python
-model.get_component("your_profile").obj.cost

You can find the full implementation and all details here: 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\]

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

source
IESopt.UnitType

A Unit allows transforming one (or many) forms of energy into another one (or many), given some constraints and costs.

Basic Examples

A Unit that represents a basic gas turbine:

gas_turbine:
+model.get_component("your_profile").obj.cost

You can find the full implementation and all details here: 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\]

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

source
IESopt.UnitType

A Unit allows transforming one (or many) forms of energy into another one (or many), given some constraints and costs.

Basic Examples

A Unit that represents a basic gas turbine:

gas_turbine:
   type: Unit
   inputs: {gas: gas_grid}
   outputs: {electricity: node, co2: total_co2}
@@ -169,4 +169,4 @@
 component(model, "your_unit").obj.ramp_cost
# Python
 model.get_component("your_unit").obj.ramp_cost

You can find the full implementation and all details here: IESopt.jl.

Add the (potential) cost of this unit's ramping to the global objective function.

To allow for finer control, costs of up- and downwards ramping can be specified separately (using unit.ramp_up_cost and unit.ramp_down_cost):

\[\sum_{t \in T} \text{ramp}_{\text{up}, t} \cdot \text{rampcost}_{\text{up}} + \text{ramp}_{\text{down}, t} \cdot \text{rampcost}_{\text{down}}\]

math

startup_cost
How to?

Access this objective by using:

# Julia
 component(model, "your_unit").obj.startup_cost
# Python
-model.get_component("your_unit").obj.startup_cost

You can find the full implementation and all details here: IESopt.jl.

Add the (potential) cost of this unit's startup behaviour (configured by unit.startup_cost if unit.unit_commitment != :off).

\[\sum_{t \in T} \text{startup}_t \cdot \text{startupcost}\]

math

source
+model.get_component("your_unit").obj.startup_cost

You can find the full implementation and all details here: IESopt.jl.

Add the (potential) cost of this unit's startup behaviour (configured by unit.startup_cost if unit.unit_commitment != :off).

\[\sum_{t \in T} \text{startup}_t \cdot \text{startupcost}\]

math

source
diff --git a/dev/pages/manual___reference/templates/index.html b/dev/pages/manual___reference/templates/index.html index 474e0e0..a86ee52 100644 --- a/dev/pages/manual___reference/templates/index.html +++ b/dev/pages/manual___reference/templates/index.html @@ -1,2 +1,2 @@ -Templates · -- IESopt --
+Templates · -- IESopt --
diff --git a/dev/pages/manual___reference/yaml/index.html b/dev/pages/manual___reference/yaml/index.html index 9f84f5e..abb385b 100644 --- a/dev/pages/manual___reference/yaml/index.html +++ b/dev/pages/manual___reference/yaml/index.html @@ -1,2 +1,2 @@ -YAML · -- IESopt --

YAML

To be added (based on docstrings from, e.g., the configs).

+YAML · -- IESopt --

YAML

To be added (based on docstrings from, e.g., the configs).

diff --git a/dev/pages/references/index.html b/dev/pages/references/index.html index 673dfa8..0a0b51e 100644 --- a/dev/pages/references/index.html +++ b/dev/pages/references/index.html @@ -9,4 +9,4 @@ !!! details "Expand: Show citation" > Add your (APA styled!) citation here -

Project Template

To be added.

Creating citation badges

You can use shields.io to create badges, or use standardized ones that you already have (e.g., from Zenodo), otherwhise stick to the ones provided below.

Pure: (publications.ait.ac.at)

[![CITATION](https://img.shields.io/badge/PURE-publications.ait.ac.at-none?style=social)](ADDYOURLINKHERE)

DOI:

[![CITATION](https://img.shields.io/badge/DOI-10.XXXX%2Fname.YYYY.ZZZZZZ-none?style=social)](https://doi.org/10.XXXX/name.YYYY.ZZZZZZ)
+

Project Template

To be added.

Creating citation badges

You can use shields.io to create badges, or use standardized ones that you already have (e.g., from Zenodo), otherwhise stick to the ones provided below.

Pure: (publications.ait.ac.at)

[![CITATION](https://img.shields.io/badge/PURE-publications.ait.ac.at-none?style=social)](ADDYOURLINKHERE)

DOI:

[![CITATION](https://img.shields.io/badge/DOI-10.XXXX%2Fname.YYYY.ZZZZZZ-none?style=social)](https://doi.org/10.XXXX/name.YYYY.ZZZZZZ)
diff --git a/dev/pages/tutorials/creating_new_components/index.html b/dev/pages/tutorials/creating_new_components/index.html index d0639e2..48cd17b 100644 --- a/dev/pages/tutorials/creating_new_components/index.html +++ b/dev/pages/tutorials/creating_new_components/index.html @@ -1,2 +1,2 @@ -Custom Components · -- IESopt --
+Custom Components · -- IESopt --
diff --git a/dev/pages/tutorials/creating_new_components/templates_1/index.html b/dev/pages/tutorials/creating_new_components/templates_1/index.html index 465aebd..1c88003 100644 --- a/dev/pages/tutorials/creating_new_components/templates_1/index.html +++ b/dev/pages/tutorials/creating_new_components/templates_1/index.html @@ -219,4 +219,4 @@ # If `heat_from` is specified, we now have to account for two inputs. set("_inputs", "{electricity: $(elec_from), heat: $(heat_from)}") set("_conversion", "1 electricity + $(cop - 1) heat -> $(cop) heat") - end

Next steps

While the above template is already quite powerful, it can become hard to maintain and understand if it grows too large. In the next tutorial, we will cover how to separate the functions part of the template into a separate file, and later will see how this approach can then be extended even further (a concept that we call Addons), which allows intercepting steps of the model build process.

But ... before we go there, let's start "small". Check out the section Templates: Part II, where we walk through the process of "out-sourcing" the functions part of the template.

+ end

Next steps

While the above template is already quite powerful, it can become hard to maintain and understand if it grows too large. In the next tutorial, we will cover how to separate the functions part of the template into a separate file, and later will see how this approach can then be extended even further (a concept that we call Addons), which allows intercepting steps of the model build process.

But ... before we go there, let's start "small". Check out the section Templates: Part II, where we walk through the process of "out-sourcing" the functions part of the template.

diff --git a/dev/pages/tutorials/creating_new_components/templates_2/index.html b/dev/pages/tutorials/creating_new_components/templates_2/index.html index e16bc2f..88d3728 100644 --- a/dev/pages/tutorials/creating_new_components/templates_2/index.html +++ b/dev/pages/tutorials/creating_new_components/templates_2/index.html @@ -1,2 +1,2 @@ -Templates: Part II · -- IESopt --
+Templates: Part II · -- IESopt --
diff --git a/dev/pages/tutorials/first_model/index.html b/dev/pages/tutorials/first_model/index.html index a5cc7af..7343aa4 100644 --- a/dev/pages/tutorials/first_model/index.html +++ b/dev/pages/tutorials/first_model/index.html @@ -1,2 +1,2 @@ -First steps · -- IESopt --

First steps

Need help?

To be added.

Overview

IESopt (the framework) consists of various sub-projects. It is a component-based optimization framework, where each component can be seen as block containing some predefined functionality. There are five "core components": Connection, Decision, Node, Profile, and Unit. These will be used to define arbitrary energy system models, similar to how a general commodity flow model works. Furthermore, they can be combined to create more complicated (non-core) components.

In their most basic form, core components can be described as:

  • A Connection is used to model arbitrary flows of energy between Nodes. It allows for limits, costs, delays, ...
  • A Decision represents a basic decision variable in the model that can be used as input for various other core component's settings, as well as have associated costs.
  • A Node represents a basic intersection/hub for energy flows. This can for example be some sort of bus (for electrical systems).
  • A Profile allows representing exogenous functionality with a support for time series data.
  • A Unit allows transforming one (or many) forms of energy into another one (or many), given some constraints and costs.

For most models, the Units will pack the most raw functionality, while the other components represent the structure of the overall model.

Your first model

To be added (translate from internal version).

Model config

To be added (translate from internal version).

Energy carriers

To be added (translate from internal version).

Model components

To be added (translate from internal version).

Final config file

To be added (translate from internal version).

Running the optimization

To be added (translate from internal version).

Extracting results

To be added (translate from internal version).

General result structure

To be added (translate from internal version).

Changing the model config

To be added (translate from internal version).

Adapting components

To be added (translate from internal version).

Analyzing the results

To be added (translate from internal version).

Extracting results directly into pd.DataFrames

To be added (translate from internal version).

Final thoughts

To be added (translate from internal version).

+First steps · -- IESopt --

First steps

Need help?

To be added.

Overview

IESopt (the framework) consists of various sub-projects. It is a component-based optimization framework, where each component can be seen as block containing some predefined functionality. There are five "core components": Connection, Decision, Node, Profile, and Unit. These will be used to define arbitrary energy system models, similar to how a general commodity flow model works. Furthermore, they can be combined to create more complicated (non-core) components.

In their most basic form, core components can be described as:

  • A Connection is used to model arbitrary flows of energy between Nodes. It allows for limits, costs, delays, ...
  • A Decision represents a basic decision variable in the model that can be used as input for various other core component's settings, as well as have associated costs.
  • A Node represents a basic intersection/hub for energy flows. This can for example be some sort of bus (for electrical systems).
  • A Profile allows representing exogenous functionality with a support for time series data.
  • A Unit allows transforming one (or many) forms of energy into another one (or many), given some constraints and costs.

For most models, the Units will pack the most raw functionality, while the other components represent the structure of the overall model.

Your first model

To be added (translate from internal version).

Model config

To be added (translate from internal version).

Energy carriers

To be added (translate from internal version).

Model components

To be added (translate from internal version).

Final config file

To be added (translate from internal version).

Running the optimization

To be added (translate from internal version).

Extracting results

To be added (translate from internal version).

General result structure

To be added (translate from internal version).

Changing the model config

To be added (translate from internal version).

Adapting components

To be added (translate from internal version).

Analyzing the results

To be added (translate from internal version).

Extracting results directly into pd.DataFrames

To be added (translate from internal version).

Final thoughts

To be added (translate from internal version).

diff --git a/dev/pages/tutorials/next_steps/index.html b/dev/pages/tutorials/next_steps/index.html index fd04bc2..c2432d1 100644 --- a/dev/pages/tutorials/next_steps/index.html +++ b/dev/pages/tutorials/next_steps/index.html @@ -1,2 +1,2 @@ -Next steps · -- IESopt --
+Next steps · -- IESopt --
diff --git a/dev/pages/tutorials/results/index.html b/dev/pages/tutorials/results/index.html index 76b0a9e..9ce033c 100644 --- a/dev/pages/tutorials/results/index.html +++ b/dev/pages/tutorials/results/index.html @@ -1,2 +1,2 @@ -Result extraction · -- IESopt --
+Result extraction · -- IESopt --
diff --git a/dev/pages/tutorials/setup/index.html b/dev/pages/tutorials/setup/index.html index 12234e1..3256770 100644 --- a/dev/pages/tutorials/setup/index.html +++ b/dev/pages/tutorials/setup/index.html @@ -1,2 +1,2 @@ -Installation · -- IESopt --
+Installation · -- IESopt --
diff --git a/dev/pages/user_guide/custom_functionality/addons/index.html b/dev/pages/user_guide/custom_functionality/addons/index.html index 828f342..b9d2b5a 100644 --- a/dev/pages/user_guide/custom_functionality/addons/index.html +++ b/dev/pages/user_guide/custom_functionality/addons/index.html @@ -1,2 +1,2 @@ -Addons · -- IESopt --
+Addons · -- IESopt --
diff --git a/dev/pages/user_guide/custom_functionality/templates/index.html b/dev/pages/user_guide/custom_functionality/templates/index.html index a275604..e28bd62 100644 --- a/dev/pages/user_guide/custom_functionality/templates/index.html +++ b/dev/pages/user_guide/custom_functionality/templates/index.html @@ -11,4 +11,4 @@ b_node: type: Node

To be added (more details).

Validate

To be added (explanation).

validation: |
   @check parameters["carrier"] isa String
-  @check parameters["carrier"] in ["heat", "electricity"]

To be added (more examples).

Prepare

To be added (explanation).

Finalize

To be added (explanation).

+ @check parameters["carrier"] in ["heat", "electricity"]

To be added (more examples).

Prepare

To be added (explanation).

Finalize

To be added (explanation).

diff --git a/dev/pages/user_guide/general/index.html b/dev/pages/user_guide/general/index.html index 8c7b5b3..aa2e6e5 100644 --- a/dev/pages/user_guide/general/index.html +++ b/dev/pages/user_guide/general/index.html @@ -1,2 +1,2 @@ -General · -- IESopt --
+General · -- IESopt --
diff --git a/dev/pages/user_guide/sectors/electricity/index.html b/dev/pages/user_guide/sectors/electricity/index.html index 48b5496..f4ad752 100644 --- a/dev/pages/user_guide/sectors/electricity/index.html +++ b/dev/pages/user_guide/sectors/electricity/index.html @@ -1,2 +1,2 @@ -Electricity · -- IESopt --
+Electricity · -- IESopt --
diff --git a/dev/pages/user_guide/sectors/gas/index.html b/dev/pages/user_guide/sectors/gas/index.html index 9b47b87..048560d 100644 --- a/dev/pages/user_guide/sectors/gas/index.html +++ b/dev/pages/user_guide/sectors/gas/index.html @@ -1,2 +1,2 @@ -Gas · -- IESopt --

Gas

To be added.

+Gas · -- IESopt --

Gas

To be added.

diff --git a/dev/pages/user_guide/sectors/heat/index.html b/dev/pages/user_guide/sectors/heat/index.html index a676902..805aaed 100644 --- a/dev/pages/user_guide/sectors/heat/index.html +++ b/dev/pages/user_guide/sectors/heat/index.html @@ -1,2 +1,2 @@ -Heat · -- IESopt --
+Heat · -- IESopt --
diff --git a/dev/pages/user_guide/solvers/index.html b/dev/pages/user_guide/solvers/index.html index 471381d..8dbc00f 100644 --- a/dev/pages/user_guide/solvers/index.html +++ b/dev/pages/user_guide/solvers/index.html @@ -51,4 +51,4 @@ lpmethod: 4 solutiontype: 2 barrier_convergetol: 1.e-5 - feasopt_tolerance: 1.e-6 + feasopt_tolerance: 1.e-6