Skip to content

Commit

Permalink
Update documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
datejada committed Jan 28, 2025
1 parent 3b8acca commit 97107fd
Show file tree
Hide file tree
Showing 7 changed files with 356 additions and 425 deletions.
449 changes: 119 additions & 330 deletions docs/src/10-how-to-use.md

Large diffs are not rendered by default.

11 changes: 6 additions & 5 deletions docs/src/20-tutorials.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,21 +102,22 @@ There is currently no reason to manually create and maintain these structures yo

To avoid having to update this documentation whenever we make changes to the internals of TulipaEnergyModel before the v1.0.0 release, we will keep this section empty until then.

### Change optimizer and specify parameters
## Change optimizer and specify parameters

By default, the model is solved using the [HiGHS](https://github.com/jump-dev/HiGHS.jl) optimizer (or solver).
To change this, we can give the functions `run_scenario` or `solve_model!` a
different optimizer.

!!! warning
HiGHS is the only open source solver that we recommend. GLPK and Cbc are missing features and are not (fully) tested for Tulipa.
HiGHS is the only open source solver that we recommend. GLPK and Cbc are not (fully) tested for Tulipa.

For instance, we run the [GLPK](https://github.com/jump-dev/GLPK.jl) optimizer below:
For instance, let's run the Tiny example using the [GLPK](https://github.com/jump-dev/GLPK.jl) optimizer:

```@example
using DuckDB, TulipaIO, TulipaEnergyModel, GLPK
input_dir = "../../test/inputs/Tiny" # hide
# input_dir should be the path to Tiny as a string (something like "test/inputs/Tiny")
connection = DBInterface.connect(DuckDB.DB)
read_csv_folder(connection, input_dir; schemas = TulipaEnergyModel.schema_per_table_name)
energy_problem = run_scenario(connection, optimizer = GLPK.Optimizer)
Expand All @@ -130,8 +131,8 @@ using GLPK
solution = solve_model!(energy_problem, GLPK.Optimizer)
```

Notice that, in any of these cases, we need to explicitly add the GLPK package
ourselves and add `using GLPK` before using `GLPK.Optimizer`.
!!! info
Notice that, in any of these cases, we need to explicitly add the GLPK package ourselves and add `using GLPK` before using `GLPK.Optimizer`.

In any of these cases, default parameters for the `GLPK` optimizer are used,
which you can query using [`default_parameters`](@ref).
Expand Down
204 changes: 124 additions & 80 deletions docs/src/30-concepts.md

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions docs/src/40-formulation.md
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ v^{\text{intra-storage}}_{a,k_y,b^{\text{first}}_{k_y}} \geq p^{\text{init stora

This constraint allows us to consider the storage seasonality throughout the model's timeframe (e.g., a year). The parameter $p^{\text{map}}_{p_y,k_y}$ determines how much of the representative period $k_y$ is in the period $p_y$, and you can use a clustering technique to calculate it. For _TulipaEnergyModel.jl_, we recommend using [_TulipaClustering.jl_](https://github.com/TulipaEnergy/TulipaClustering.jl) to compute the clusters for the representative periods and their map.

For the sake of simplicity, we show the constraint assuming the inter-storage level between two consecutive periods $p_y$; however, _TulipaEnergyModel.jl_ can handle more flexible period block definition through the timeframe definition in the model using the information in the file [`assets-timeframe-partitions.csv`](@ref assets-timeframe-partitions).
For the sake of simplicity, we show the constraint assuming the inter-storage level between two consecutive periods $p_y$; however, _TulipaEnergyModel.jl_ can handle more flexible period block definition through the timeframe definition in the model using the information in the timeframe partitions file, see [schemas](@ref schemas).

```math
\begin{aligned}
Expand Down Expand Up @@ -679,23 +679,23 @@ v^{\text{flow}}_{f,k_y,b_{k_y}} \geq - p^{\text{availability profile}}_{f,y,k_y,
v^{\text{inv}}_{a,y} \leq \frac{p^{\text{inv limit}}_{a,y}}{p^{\text{capacity}}_{a}} \quad \forall y \in \mathcal{Y}, \forall a \in \mathcal{A}^{\text{i}}_y
```

If the parameter `investment_integer` in the [`assets-data.csv`](@ref assets-data) file is set to true, then the right-hand side of this constraint uses a least integer function (floor function) to guarantee that the limit is integer.
If the parameter `investment_integer` is set to true, then the right-hand side of this constraint uses a least integer function (floor function) to guarantee that the limit is integer.

#### Maximum Energy Investment Limit for Assets

```math
v^{\text{inv energy}}_{a,y} \leq \frac{p^{\text{inv limit energy}}_{a,y}}{p^{\text{energy capacity}}_{a}} \quad \forall y \in \mathcal{Y}, \forall a \in \mathcal{A}^{\text{i}}_y \cap \mathcal{A}^{\text{se}}_y
```

If the parameter `investment_integer_storage_energy` in the [`assets-data.csv`](@ref assets-data) file is set to true, then the right-hand side of this constraint uses a least integer function (floor function) to guarantee that the limit is integer.
If the parameter `investment_integer_storage_energy` is set to true, then the right-hand side of this constraint uses a least integer function (floor function) to guarantee that the limit is integer.

#### Maximum Investment Limit for Flows

```math
v^{\text{inv}}_{f,y} \leq \frac{p^{\text{inv limit}}_{f,y}}{p^{\text{capacity}}_{f}} \quad \forall y \in \mathcal{Y}, \forall f \in \mathcal{F}^{\text{ti}}_y
```

If the parameter `investment_integer` in the [`flows-data.csv`](@ref flows-data) file is set to true, then the right-hand side of this constraint uses a least integer function (floor function) to guarantee that the limit is integer.
If the parameter `investment_integer` is set to true, then the right-hand side of this constraint uses a least integer function (floor function) to guarantee that the limit is integer.

### [Inter-temporal Energy Constraints](@id inter-temporal-energy-constraints)

Expand Down
18 changes: 18 additions & 0 deletions docs/src/50-schemas.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# [Model Parameters](@id schemas)

The optimization model parameters with the input data must follow the schema below for each table. To create these tables we currently use CSV files that follow this same schema and then convert them into tables using TulipaIO, as shown in the basic example of the [Tutorials](@ref basic-example) section.

The schemas can be accessed at any time after loading the package by typing `TulipaEnergyModel.schema_per_table_name` in the Julia console. Here is the complete list of model parameters in the schemas per table (or CSV file):

```@eval
using Markdown, TulipaEnergyModel
Markdown.parse(
join(["- **`$filename`**\n" *
join(
[" - `$f: $t`" for (f, t) in schema],
"\n",
) for (filename, schema) in TulipaEnergyModel.schema_per_table_name
] |> sort, "\n")
)
```
74 changes: 74 additions & 0 deletions docs/src/60-structures.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# [Model Structures](@id structures)

```@contents
Pages = ["60-structures.md"]
Depth = 3
```

The list of relevant structures used in this package are listed below:

## EnergyProblem

The `EnergyProblem` structure is a wrapper around various other relevant structures.
It hides the complexity behind the energy problem, making the usage more friendly, although more verbose.

### Fields

- `db_connection`: A DuckDB connection to the input tables in the model
- `graph`: The Graph object that defines the geometry of the energy problem.
- `model`: A JuMP.Model object representing the optimization model.
- `objective_value`: The objective value of the solved problem (Float64).
- `variables`: A [TulipaVariable](@ref TulipaVariable) structure to store all the information related to the variables in the model.
- `constraints`: A [TulipaConstraint](@ref TulipaConstraint) structure to store all the information related to the constraints in the model.
- `representative_periods`: A vector of [Representative Periods](@ref representative-periods).
- `solved`: A boolean indicating whether the `model` has been solved or not.
- `termination_status`: The termination status of the optimization model.
- `timeframe`: A structure with the number of periods in the `representative_periods` and the mapping between the periods and their representatives.
- `model_parameters`: A [ModelParameters](@ref ModelParameters) structure to store all the parameters that are exclusive of the model.
- `years`: A vector with the information of all the milestone years.

### Constructor

The `EnergyProblem` can also be constructed using the minimal constructor below.

- `EnergyProblem(connection)`: Constructs a new `EnergyProblem` object with the given `connection` that has been created and the data loaded into it using [TulipaIO](https://github.com/TulipaEnergy/TulipaIO.jl). The `graph`, `representative_periods`, `timeframe`, and `years` are computed using `create_internal_structures`.

See the [basic example tutorial](@ref basic-example) to see how these can be used.

## GraphAssetData

This structure holds all the information of a given asset.
These are stored inside the Graph.
Given a graph `graph`, an asset `a` can be accessed through `graph[a]`.

## GraphFlowData

This structure holds all the information of a given flow.
These are stored inside the Graph.
Given a graph `graph`, a flow from asset `u` to asset `v` can be accessed through `graph[u, v]`.

## [Timeframe](@id timeframe)

The timeframe is the total period we want to analyze with the model. Usually this is a year, but it can be any length of time. A timeframe has two fields:

- `num_periods`: The timeframe is defined by a certain number of periods. For instance, a year can be defined by 365 periods, each describing a day.
- `map_periods_to_rp`: Indicates the periods of the timeframe that map into a [representative period](@ref representative-periods) and the weight of the representative period to construct that period.

## [Representative Periods](@id representative-periods)

The [timeframe](@ref timeframe) (e.g., a full year) is described by a selection of representative periods, for instance, days or weeks, that nicely summarize other similar periods. For example, we could model the year into 3 days, by clustering all days of the year into 3 representative days. Each one of these days is called a representative period. _TulipaEnergyModel.jl_ has the flexibility to consider representative periods of different lengths for the same timeframe (e.g., a year can be represented by a set of 4 days and 2 weeks). To obtain the representative periods, we recommend using [TulipaClustering](https://github.com/TulipaEnergy/TulipaClustering.jl).

A representative period has three fields:

- `weight`: Indicates how many representative periods are contained in the [timeframe](@ref timeframe); this is inferred automatically from `map_periods_to_rp` in the [timeframe](@ref timeframe).
- `timesteps`: The number of timesteps blocks in the representative period.
- `resolution`: The duration in time of each timestep.

The number of timesteps and resolution work together to define the coarseness of the period.
Nothing is defined outside of these timesteps; for instance, if the representative period represents a day and you want to specify a variable or constraint with a coarseness of 30 minutes. You need to define the number of timesteps to 48 and the resolution to `0.5`.

## [Time Blocks](@id time-blocks)

A time block is a range for which a variable or constraint is defined.
It is a range of numbers, i.e., all integer numbers inside an interval.
Time blocks are used for the periods in the [timeframe](@ref timeframe) and the timesteps in the [representative period](@ref representative-periods). Time blocks are disjunct (not overlapping), but do not have to be sequential.
17 changes: 11 additions & 6 deletions src/structures.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ mutable struct TulipaVariable
end
end

"""
Structure to hold the JuMP constraints for the TulipaEnergyModel
"""
mutable struct TulipaConstraint
indices::DataFrame
table_name::String
Expand Down Expand Up @@ -311,16 +314,18 @@ Structure to hold all parts of an energy problem. It is a wrapper around various
It hides the complexity behind the energy problem, making the usage more friendly, although more verbose.
# Fields
- `db_connection`: A DuckDB connection to the input tables in the model
- `graph`: The Graph object that defines the geometry of the energy problem.
- `representative_periods`: A vector of [Representative Periods](@ref representative-periods).
- `constraints_partitions`: Dictionaries that connect pairs of asset and representative periods to [time partitions (vectors of time blocks)](@ref Partition)
- `timeframe`: The number of periods of the `representative_periods`.
- `dataframes`: The data frames used to linearize the variables and constraints. These are used internally in the model only.
- `model_parameters`: The model parameters.
- `model`: A JuMP.Model object representing the optimization model.
- `objective_value`: The objective value of the solved problem (Float64).
- `variables`: A [TulipaVariable](@ref TulipaVariable) structure to store all the information related to the variables in the model.
- `constraints`: A [TulipaConstraint](@ref TulipaConstraint) structure to store all the information related to the constraints in the model.
- `representative_periods`: A vector of [Representative Periods](@ref representative-periods).
- `solved`: A boolean indicating whether the `model` has been solved or not.
- `objective_value`: The objective value of the solved problem.
- `termination_status`: The termination status of the optimization model.
- `timeframe`: A structure with the number of periods in the `representative_periods` and the mapping between the periods and their representatives.
- `model_parameters`: A [ModelParameters](@ref ModelParameters) structure to store all the parameters that are exclusive of the model.
- `years`: A vector with the information of all the milestone years.
# Constructor
- `EnergyProblem(connection)`: Constructs a new `EnergyProblem` object with the given connection. The `constraints_partitions` field is computed from the `representative_periods`, and the other fields are initialized with default values.
Expand Down

0 comments on commit 97107fd

Please sign in to comment.