diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cba6852..c489959 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: false matrix: - # Since EnergyModelsBase doesn't have binary dependencies, + # Since EnergyModelsCO2 doesn't have binary dependencies, # only test on a subset of possible platforms. include: - version: '1' # The latest point-release (Linux) @@ -22,18 +22,18 @@ jobs: - version: '1' # The latest point-release (Windows) os: windows-latest arch: x64 - - version: '1.9' # 1.9 + - version: 'lts' # lts os: ubuntu-latest arch: x64 - - version: '1.9' # 1.9 + - version: 'lts' # lts os: ubuntu-latest arch: x86 # - version: 'nightly' # os: ubuntu-latest # arch: x64 steps: - - uses: actions/checkout@v3 - - uses: julia-actions/setup-julia@v1 + - uses: actions/checkout@v4 + - uses: julia-actions/setup-julia@v2 with: version: ${{ matrix.version }} arch: ${{ matrix.arch }} @@ -50,8 +50,4 @@ jobs: - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 with: - depwarn: error - - uses: julia-actions/julia-processcoverage@v1 - - uses: codecov/codecov-action@v3 - with: - file: lcov.info \ No newline at end of file + depwarn: error \ No newline at end of file diff --git a/NEWS.md b/NEWS.md index 27a6166..0b6542b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,13 @@ # Release Notes +## Version 0.7.3 (2024-10-16) + +* Minor changes to the documentation and docstrings. +* Minor rewriting of constraints and fixing variables. +* Adjusted to [`EnergyModelsBase` v0.8.1](https://github.com/EnergyModelsX/EnergyModelsBase.jl/releases/tag/v0.8.1): + * Use of the function `scale_op_sp`. + * Rework based on the introduction of `:stor_level_Δ_sp` in `EnergyModelsBase` as sparse variable. + ## Version 0.7.2 (2024-09-03) * Dependency increase for `EnergyModelsBase` as the changes do not directly affect `EnergyModelsCO2`. diff --git a/Project.toml b/Project.toml index 3616497..8bc949b 100644 --- a/Project.toml +++ b/Project.toml @@ -1,15 +1,16 @@ name = "EnergyModelsCO2" uuid = "84b3f4d7-d799-4a5d-b06c-25c90dcfcad7" authors = ["Sigmund Eggen Holm and contributors"] -version = "0.7.2" +version = "0.7.3" [deps] EnergyModelsBase = "5d7e687e-f956-46f3-9045-6f5a5fd49f50" JuMP = "4076af6c-e467-56ae-b986-b466b2749572" +SparseVariables = "2749762c-80ed-4b14-8f33-f0736679b02b" TimeStruct = "f9ed5ce0-9f41-4eaa-96da-f38ab8df101c" [compat] -EnergyModelsBase = "0.8" +EnergyModelsBase = "0.8.1" JuMP = "1.5" -TimeStruct = "0.8" -julia = "1.6" +TimeStruct = "0.9" +julia = "1.10" diff --git a/docs/src/nodes/retrofit.md b/docs/src/nodes/retrofit.md index 09abe8e..20e9b37 100644 --- a/docs/src/nodes/retrofit.md +++ b/docs/src/nodes/retrofit.md @@ -29,11 +29,11 @@ Both introduced nodes use the same fields, although their meaning may potentiall The standard fields are given as: - **`id`**:\ - The field **`id`** is only used for providing a name to the node. + The field `id` is only used for providing a name to the node. This is similar to the approach utilized in `EnergyModelsBase`. - **`cap::TimeProfile`**:\ The installed capacity corresponds to the potential usage of the node.\ - If the node should contain investments through the application of [`EnergyModelsInvestments`](https://energymodelsx.github.io/EnergyModelsInvestments.jl/stable/), it is important to note that you can only use `FixedProfile` or `StrategicProfile` for the capacity, but not `RepresentativeProfile` or `OperationalProfile`. + If the node should contain investments through the application of [`EnergyModelsInvestments`](https://energymodelsx.github.io/EnergyModelsInvestments.jl/), it is important to note that you can only use `FixedProfile` or `StrategicProfile` for the capacity, but not `RepresentativeProfile` or `OperationalProfile`. In addition, all values have to be non-negative. !!! info "Meaning in boths nodes" - [`RefNetworkNodeRetrofit`](@ref):\ @@ -67,7 +67,7 @@ The standard fields are given as: - **`data::Vector{Data}`**:\ An entry for providing additional data to the model. The `data` vector must include [`CaptureData`](@extref EnergyModelsBase.CaptureData) for both [`RefNetworkNodeRetrofit`](@ref) and [`CCSRetroFit`](@ref). - It can include additional investment data when [`EnergyModelsInvestments`](https://energymodelsx.github.io/EnergyModelsInvestments.jl/stable/) is used. + It can include additional investment data when [`EnergyModelsInvestments`](https://energymodelsx.github.io/EnergyModelsInvestments.jl/) is used. !!! info "Meaning of the capture rate in both nodes" - [`RefNetworkNodeRetrofit`](@ref):\ The capture rate corresponds to the fraction of the flue gas which is sent to the `CCSRetroFit` node. @@ -113,6 +113,7 @@ The variables include: - [``\texttt{cap\_inst}``](@extref EnergyModelsBase man-opt_var-cap) - [``\texttt{flow\_in}``](@extref EnergyModelsBase man-opt_var-flow) - [``\texttt{flow\_out}``](@extref EnergyModelsBase man-opt_var-flow) +- [``\texttt{emissions\_node}``](@ref EnergyModelsBase man-opt_var-emissions) #### [Additional variables](@id nodes-CCS_retrofit-math-add) @@ -135,16 +136,16 @@ These standard constraints are: \texttt{cap\_use}[n, t] \leq \texttt{cap\_inst}[n, t] ``` - !!! tip "Using investments" - The function `constraints_capacity_installed` is also used in [`EnergyModelsInvestments`](https://energymodelsx.github.io/EnergyModelsInvestments.jl/stable/) to incorporate the potential for investment. - Nodes with investments are then no longer constrained by the parameter capacity. - - `constraints_capacity_installed`: ```math \texttt{cap\_inst}[n, t] = capacity(n, t) ``` + !!! tip "Using investments" + The function `constraints_capacity_installed` is also used in [`EnergyModelsInvestments`](https://energymodelsx.github.io/EnergyModelsInvestments.jl/) to incorporate the potential for investment. + Nodes with investments are then no longer constrained by the parameter capacity. + - `constraints_flow_in`: ```math @@ -171,15 +172,19 @@ These standard constraints are: ``` !!! tip "Why do we use `first()`" - The variable ``\texttt{cap\_inst}`` ise declared over all operational periods (see the section on *[Capacity variables](@extref EnergyModelsBase man-opt_var-cap)* for further explanations). + The variable ``\texttt{cap\_inst}`` is declared over all operational periods (see the section on *[Capacity variables](@extref EnergyModelsBase man-opt_var-cap)* for further explanations). Hence, we use the function ``first(t_{inv})`` to retrieve the installed capacity in the first operational period of a given strategic period ``t_{inv}`` in the function `constraints_opex_fixed`. - `constraints_opex_var`: ```math - \texttt{opex\_var}[n, t_{inv}] = \sum_{t \in t_{inv}} opex_var(n, t) \times \texttt{cap\_use}[n, t] \times EMB.multiple(t_{inv}, t) + \texttt{opex\_var}[n, t_{inv}] = \sum_{t \in t_{inv}} opex_var(n, t) \times \texttt{cap\_use}[n, t] \times scale\_op\_sp(t_{inv}, t) ``` + !!! tip "The function `scale_op_sp`" + The function [``scale\_op\_sp(t_{inv}, t)``](@extref EnergyModelsBase.scale_op_sp) calculates the scaling factor between operational and strategic periods. + It also takes into account potential operational scenarios and their probability as well as representative periods. + - `constraints_data`:\ This function is only called for specified data of the nodes, see above. This function is extended with multiple methods for both `CCSRetroFit` and `RefNetworkNodeRetrofit`. diff --git a/docs/src/nodes/source.md b/docs/src/nodes/source.md index d4a514b..da1f2da 100644 --- a/docs/src/nodes/source.md +++ b/docs/src/nodes/source.md @@ -15,11 +15,11 @@ Hence, it utilizes the same functions declared in `EnergyModelsBase`. The standard fields are given as: - **`id`**:\ - The field **`id`** is only used for providing a name to the node. + The field `id` is only used for providing a name to the node. This is similar to the approach utilized in `EnergyModelsBase`. - **`cap::TimeProfile`**:\ The installed capacity corresponds to the potential usage of the node.\ - If the node should contain investments through the application of [`EnergyModelsInvestments`](https://energymodelsx.github.io/EnergyModelsInvestments.jl/stable/), it is important to note that you can only use `FixedProfile` or `StrategicProfile` for the capacity, but not `RepresentativeProfile` or `OperationalProfile`. + If the node should contain investments through the application of [`EnergyModelsInvestments`](https://energymodelsx.github.io/EnergyModelsInvestments.jl/), it is important to note that you can only use `FixedProfile` or `StrategicProfile` for the capacity, but not `RepresentativeProfile` or `OperationalProfile`. In addition, all values have to be non-negative. - **`opex_var::TimeProfile`**:\ The variable operational expenses are based on the capacity utilization through the variable [`:cap_use`](@extref EnergyModelsBase man-opt_var-cap). @@ -36,7 +36,7 @@ The standard fields are given as: All values have to be non-negative. - **`data::Vector{Data}`**:\ An entry for providing additional data to the model. - In the current version, it is only relevant for additional investment data when [`EnergyModelsInvestments`](https://energymodelsx.github.io/EnergyModelsInvestments.jl/stable/) is used or for additional emission data through [`EmissionsProcess`](@extref EnergyModelsBase.EmissionsProcess). + In the current version, it is only relevant for additional investment data when [`EnergyModelsInvestments`](https://energymodelsx.github.io/EnergyModelsInvestments.jl/) is used or for additional emission data through [`EmissionsProcess`](@extref EnergyModelsBase.EmissionsProcess). The latter would correspond to uncaptured CO₂ that should be included in the analyses. !!! note The field `data` is not required as we include a constructor when the value is excluded. @@ -76,9 +76,11 @@ The variables include: - [``\texttt{cap\_use}``](@extref EnergyModelsBase man-opt_var-cap) - [``\texttt{cap\_inst}``](@extref EnergyModelsBase man-opt_var-cap) - [``\texttt{flow\_out}``](@extref EnergyModelsBase man-opt_var-flow) -- [``\texttt{emissions\_node}``](@extref EnergyModelsBase man-opt_var-emissions) if `EmissionsData` is added to the field `data`. - Note that CO₂ source nodes are not compatible with `CaptureData`. - Hence, you can only provide [`EmissionsProcess`](@extref EnergyModelsBase.EmissionsProcess) to the node. +- [``\texttt{emissions\_node}``](@extref EnergyModelsBase man-opt_var-emissions) if `EmissionsData` is added to the field `data` + +!!! note + CO₂ source nodes are not compatible with `CaptureData`. + Hence, you can only provide [`EmissionsProcess`](@extref EnergyModelsBase.EmissionsProcess) to the node. #### [Additional variables](@id nodes-co2_source-math-add) @@ -107,27 +109,33 @@ These standard constraints are: \texttt{cap\_inst}[n, t] = capacity(n, t) ``` + !!! tip "Using investments" + The function `constraints_capacity_installed` is also used in [`EnergyModelsInvestments`](https://energymodelsx.github.io/EnergyModelsInvestments.jl/) to incorporate the potential for investment. + Nodes with investments are then no longer constrained by the parameter capacity. + - `constraints_opex_fixed`: ```math \texttt{opex\_fixed}[n, t_{inv}] = opex\_fixed(n, t_{inv}) \times \texttt{cap\_inst}[n, first(t_{inv})] ``` + !!! tip "Why do we use `first()`" + The variable ``\texttt{cap\_inst}`` is declared over all operational periods (see the section on *[Capacity variables](@ref man-opt_var-cap)* for further explanations). + Hence, we use the function ``first(t_{inv})`` to retrieve the installed capacity in the first operational period of a given strategic period ``t_{inv}`` in the function `constraints_opex_fixed`. + - `constraints_opex_var`: ```math - \texttt{opex\_var}[n, t_{inv}] = \sum_{t \in t_{inv}} opex_var(n, t) \times \texttt{cap\_use}[n, t] \times EMB.multiple(t_{inv}, t) + \texttt{opex\_var}[n, t_{inv}] = \sum_{t \in t_{inv}} opex_var(n, t) \times \texttt{cap\_use}[n, t] \times scale\_op\_sp(t_{inv}, t) ``` + !!! tip "The function `scale_op_sp`" + The function [``scale\_op\_sp(t_{inv}, t)``](@extref EnergyModelsBase.scale_op_sp) calculates the scaling factor between operational and strategic periods. + It also takes into account potential operational scenarios and their probability as well as representative periods. + - `constraints_data`:\ This function is only called for specified data of the CO₂ source, see above. -The function `constraints_capacity_installed` is also used in [`EnergyModelsInvestments`](https://energymodelsx.github.io/EnergyModelsInvestments.jl/stable/) to incorporate the potential for investment. -Nodes with investments are then no longer constrained by the parameter capacity. - -The variable ``\texttt{cap\_inst}`` is declared over all operational periods (see the section on *[Capacity variables](@extref EnergyModelsBase man-opt_var-cap)* for further explanations). -Hence, we use the function ``first(t_{inv})`` to retrieve the installed capacity in the first operational period of a given strategic period ``t_{inv}`` in the function `constraints_opex_fixed`. - The function `constraints_flow_out` is extended with a new method for CO₂ source nodes to allow the inclusion of CO₂: ```math diff --git a/docs/src/nodes/storage.md b/docs/src/nodes/storage.md index 14a9f2c..c7a2d6c 100644 --- a/docs/src/nodes/storage.md +++ b/docs/src/nodes/storage.md @@ -22,7 +22,7 @@ This storage behavior is called [`EnergyModelsCO2.AccumulatingStrategic`](@ref). The standard fields are given as: - **`id`**:\ - The field **`id`** is only used for providing a name to the node. This is similar to the approach utilized in `EnergyModelsBase`. + The field `id` is only used for providing a name to the node. This is similar to the approach utilized in `EnergyModelsBase`. - **`charge::EMB.UnionCapacity`**:\ The charge storage parameters must include a capacity for charging. More information can be found on *[storage parameters](@extref EnergyModelsBase lib-pub-nodes-stor_par)*. @@ -30,7 +30,7 @@ The standard fields are given as: The level storage parameters must include a capacity for charging. More information can be found on *[storage parameters](@extref EnergyModelsBase lib-pub-nodes-stor_par)*. !!! note "Permitted values for storage parameters in `charge` and `level`" - If the node should contain investments through the application of [`EnergyModelsInvestments`](https:// energymodelsx.github.io/EnergyModelsInvestments.jl/stable/), it is important to note that you can only use `FixedProfile` or `StrategicProfile` for the capacity, but not `RepresentativeProfile` or `OperationalProfile`. + If the node should contain investments through the application of [`EnergyModelsInvestments`](https://energymodelsx.github.io/EnergyModelsInvestments.jl/), it is important to note that you can only use `FixedProfile` or `StrategicProfile` for the capacity, but not `RepresentativeProfile` or `OperationalProfile`. Similarly, you can only use `FixedProfile` or `StrategicProfile` for the fixed OPEX, but not `RepresentativeProfile` or `OperationalProfile`. The variable operating expenses can be provided as `OperationalProfile` as well. In addition, all capacity and fixed OPEX values have to be non-negative. @@ -45,7 +45,7 @@ The standard fields are given as: All values have to be non-negative. - **`data::Vector{Data}`**:\ An entry for providing additional data to the model. - In the current version, it is only relevant for additional investment data when [`EnergyModelsInvestments`](https://energymodelsx.github.io/EnergyModelsInvestments.jl/stable/) is used. + In the current version, it is only relevant for additional investment data when [`EnergyModelsInvestments`](https://energymodelsx.github.io/EnergyModelsInvestments.jl/) is used. !!! danger "The field `output`" CO₂ storage nodes do not allow for the specification of an outlet field. @@ -82,18 +82,21 @@ The variables include: - [``\texttt{stor\_level\_inst}``](@extref EnergyModelsBase man-opt_var-cap) - [``\texttt{stor\_charge\_use}``](@extref EnergyModelsBase man-opt_var-cap) - [``\texttt{stor\_charge\_inst}``](@extref EnergyModelsBase man-opt_var-cap) +- [``\texttt{stor\_discharge\_use}``](@extref EnergyModelsBase man-opt_var-cap) - [``\texttt{flow\_in}``](@extref EnergyModelsBase man-opt_var-flow) - [``\texttt{flow\_out}``](@extref EnergyModelsBase man-opt_var-flow) - [``\texttt{stor\_level\_Δ\_op}``](@extref EnergyModelsBase man-opt_var-cap) - [``\texttt{stor\_level\_Δ\_rp}``](@extref EnergyModelsBase man-opt_var-cap) if the `TimeStruct` includes `RepresentativePeriods` - [``\texttt{emissions\_node}``](@extref EnergyModelsBase man-opt_var-emissions) -Neither ``\texttt{stor\_discharge\_inst}`` nor ``\texttt{stor\_discharge\_use}`` are created for `CO2Storage` nodes as we do not specify a `discharge` field. +``\texttt{stor\_discharge\_inst}`` is not created for `CO2Storage` nodes as we do not specify a `discharge` field. +The variables ``\texttt{stor\_discharge\_use}`` are created by default in `EnergyModelsBase`. +They are however fixed to 0 for [`CO2Storage`](@ref) nodes #### [Additional variables](@id nodes-co2_storage-math-add) [`CO2Storage`](@ref) nodes have to keep track of the stored CO₂ in each strategic period. -Hence, a single additional variable is declared through dispatching on the method [`EnergyModelsBase.variables_node()`](@ref): +Hence, a single additional variable is declared through dispatching on the method [`EnergyModelsBase.variables_node()`](@ref) and utilizing [`SparseVariables`](https://github.com/sintefore/SparseVariables.jl): - ``\texttt{stor\_level\_Δ\_sp}[n, t_{inv}]``: Stored CO₂ in storage node ``n`` in strategic period ``t_{inv}`` with a typical unit of t/a.\ The stored CO₂ in each strategic period is a rate specifying how much CO₂ is stored within a given strategic period. @@ -120,10 +123,10 @@ These standard constraints are: ``` !!! tip "Using investments" - The function `constraints_capacity_installed` is also used in [`EnergyModelsInvestments`](https://energymodelsx.github.io/EnergyModelsInvestments.jl/stable/) to incorporate the potential for investment. + The function `constraints_capacity_installed` is also used in [`EnergyModelsInvestments`](https://energymodelsx.github.io/EnergyModelsInvestments.jl/) to incorporate the potential for investment. Nodes with investments are then no longer constrained by the parameter capacity. -- `constraints_level`: +- `constraints_level`:\ The level constraints are in general following the default approach with minor modifications. They are explained in detail below in *[Level constraints](@ref nodes-co2_storage-math-con-add-level)*. @@ -146,20 +149,20 @@ These standard constraints are: ```math \begin{aligned} \texttt{opex\_var}&[n, t_{inv}] = \\ \sum_{t \in t_{inv}}& - opex\_var(level(n), t) \times \texttt{stor\_level}[n, t] \times EMB.multiple(t_{inv}, t) + \\ & - opex\_var(charge(n), t) \times \texttt{stor\_charge\_use}[n, t] \times EMB.multiple(t_{inv}, t) + opex\_var(level(n), t) \times \texttt{stor\_level}[n, t] \times scale\_op\_sp(t_{inv}, t) + \\ & + opex\_var(charge(n), t) \times \texttt{stor\_charge\_use}[n, t] \times scale\_op\_sp(t_{inv}, t) \end{aligned} ``` - !!! tip "The function `EMB.multiple`" - The function [``EMB.multiple(t_{inv}, t)``](@extref EnergyModelsBase.multiple) calculates the scaling factor between operational and strategic periods. - It also takes into accoun potential operational scenarios and their probability as well as representative periods. + !!! tip "The function `scale_op_sp`" + The function [``scale\_op\_sp(t_{inv}, t)``](@extref EnergyModelsBase.scale_op_sp) calculates the scaling factor between operational and strategic periods. + It also takes into account potential operational scenarios and their probability as well as representative periods. - `constraints_data`:\ This function is only called for specified data of the CO₂ storage node, see above. !!! info "Implementation of OPEX" - The fixed and variable OPEX constribubtion for the level and the charge capacities are only included if the corresponding *[storage parameters](@extref EnergyModelsBase lib-pub-nodes-stor_par)* have a field `opex_fixed` and `opex_var`, respectively. + The fixed and variable OPEX contribution for the level and the charge capacities are only included if the corresponding *[storage parameters](@extref EnergyModelsBase lib-pub-nodes-stor_par)* have a field `opex_fixed` and `opex_var`, respectively. Otherwise, they are omitted. The function `constraints_capacity` is extended with a new method for CO₂ storage nodes to allow for accounting for the upper bound of stored CO₂ in strategic periods. @@ -212,10 +215,14 @@ These are hence fixed for all other [`ResourceEmit`](@extref EnergyModelsBase.Re \texttt{emissions\_node}[n, t, p_{em}] = 0 \qquad \forall p_{em} \in P^{em} \setminus \{\text{CO}_2\} ``` -Similarly, all outlet flows are fixed to 0: +Similarly, all outlet flows and the discharge rates are fixed to 0: ```math -\texttt{flow\_out}[n, t, p] = 0 \qquad \forall p \in outputs(n, p) +\begin{aligned} + \texttt{flow\_out}[n, t, p] & = 0 \qquad \forall p \in outputs(n, p) \\ + + \texttt{stor\_discharge\_use}[n, t] & = 0 +\end{aligned} ``` ##### [Level constraints](@id nodes-co2_storage-math-con-add-level) @@ -231,11 +238,10 @@ The constraints introduced in `constraints_level_aux` are given by ```math \begin{aligned} - \texttt{stor\_level\_Δ\_op}[n, t] & = - \texttt{flow\_in}[n, t, \text{CO}_2] - \texttt{emissions\_node}[n, t, \text{CO}_2] \\ + \texttt{stor\_level\_Δ\_op}[n, t] & = \texttt{stor\_charge\_use}[n, t] \\ \texttt{stor\_level\_Δ\_sp}[n, t_{inv}] & = \sum_{t \in t_{inv}} - \texttt{stor\_level\_Δ\_op}[n, t] \times EMB.multiple(t_{inv}, t) + \texttt{stor\_level\_Δ\_op}[n, t] \times scale\_op\_sp(t_{inv}, t) \end{aligned} ``` @@ -245,7 +251,7 @@ If the time structure includes representative periods, we also calculate the cha ```math \texttt{stor\_level\_Δ\_rp}[n, t_{rp}] = \sum_{t \in t_{rp}} - \texttt{stor\_level\_Δ\_op}[n, t] \times EMB.multiple(t_{rp}, t) + \texttt{stor\_level\_Δ\_op}[n, t] \times scale\_op\_sp(t_{inv}, t) ``` The general level constraint is calculated in the function `constraints_level_iterate` (from `EnergyModelsBase`): diff --git a/examples/co2_storage.jl b/examples/co2_storage.jl index 2d427f1..1ecd507 100644 --- a/examples/co2_storage.jl +++ b/examples/co2_storage.jl @@ -109,11 +109,8 @@ function process_co2_storage_results(m, case) first_op = [first(t_inv) for t_inv ∈ 𝒯ᴵⁿᵛ] # Storage variables - storage_use = JuMP.Containers.rowtable( # Storage usage in a strategic period - value, - m[:stor_level_Δ_sp][co2_stor, :]/1e3; - header=[:t, :storage_use] - ) + # Storage usage in a strategic period + storage_use = [value.(m[:stor_level_Δ_sp][co2_stor, t_inv]) for t_inv ∈ 𝒯ᴵⁿᵛ]./1e3 storage_level = JuMP.Containers.rowtable( # Storage level at beginning value, m[:stor_level][co2_stor, first_op]/1e3; @@ -123,7 +120,7 @@ function process_co2_storage_results(m, case) # Set up the individual named tuples as a single named tuple table = [( - t = repr(con_1.t), storage_use = round(con_1.storage_use; digits=1), + t = repr(con_2.t), storage_use = round(con_1; digits=1), storage_level = round(con_2.storage_level; digits=1), ) for (con_1, con_2) ∈ zip(storage_use, storage_level) ] diff --git a/src/EnergyModelsCO2.jl b/src/EnergyModelsCO2.jl index 69dc2b1..b4a3828 100644 --- a/src/EnergyModelsCO2.jl +++ b/src/EnergyModelsCO2.jl @@ -6,6 +6,7 @@ module EnergyModelsCO2 using EnergyModelsBase using JuMP +using SparseVariables using TimeStruct const EMB = EnergyModelsBase diff --git a/src/constraint_functions.jl b/src/constraint_functions.jl index fc9e755..37b0777 100644 --- a/src/constraint_functions.jl +++ b/src/constraint_functions.jl @@ -57,13 +57,13 @@ function EMB.constraints_level_aux(m, n::CO2Storage, 𝒯, 𝒫, modeltype::Ener # Constraint for the change in the level in a given operational period @constraint(m, [t ∈ 𝒯], m[:stor_level_Δ_op][n, t] == - m[:flow_in][n, t, p_stor] - m[:emissions_node][n, t, p_stor] + m[:stor_charge_use][n, t] ) # Constraint for the change in the level in a strategic period @constraint(m, [t_inv ∈ 𝒯ᴵⁿᵛ], m[:stor_level_Δ_sp][n, t_inv] == - sum(m[:stor_level_Δ_op][n, t] * EMB.multiple(t_inv, t) for t ∈ t_inv) + sum(m[:stor_level_Δ_op][n, t] * scale_op_sp(t_inv, t) for t ∈ t_inv) ) # Set the lower bound for the operational change in the level (:stor_level_Δ_op) to diff --git a/src/model.jl b/src/model.jl index bd275d5..1d77450 100644 --- a/src/model.jl +++ b/src/model.jl @@ -11,7 +11,9 @@ function EMB.variables_node(m, 𝒩::Vector{<:CO2Storage}, 𝒯, modeltype::Ener 𝒯ᴵⁿᵛ = strategic_periods(𝒯) # Variable for keeping track of the increased storage_level during a # strategic period. - @variable(m, stor_level_Δ_sp[𝒩, 𝒯ᴵⁿᵛ] >= 0) + for t_inv ∈ 𝒯ᴵⁿᵛ, n ∈ 𝒩 + insertvar!(m[:stor_level_Δ_sp], n, t_inv) + end end """ @@ -56,8 +58,11 @@ function EMB.create_node(m, n::CO2Storage, 𝒯, 𝒫, modeltype::EnergyModel) ) # The CO2Storage has no outputs. - for t ∈ 𝒯, p ∈ outputs(n) - fix(m[:flow_out][n, t, p], 0,; force=true) + for t ∈ 𝒯 + fix(m[:stor_discharge_use][n, t], 0,; force=true) + for p ∈ outputs(n) + fix(m[:flow_out][n, t, p], 0,; force=true) + end end # Bounds for the storage level and storage rate used. diff --git a/test/runtests.jl b/test/runtests.jl index dd9648e..94dd9f0 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -11,19 +11,19 @@ const EMC = EnergyModelsCO2 TEST_ATOL = 1e-6 @testset "CO2" begin - @testset "CO2 - Storage" begin + @testset "CO2 | Storage" begin include("test_co2storage.jl") end - @testset "CO2 - Capture retrofit" begin + @testset "CO2 | Capture retrofit" begin include("test_ccs_retrofit.jl") end - @testset "CO2 - Checks" begin + @testset "CO2 | Checks" begin include("test_checks.jl") end - @testset "CO2 - examples" begin + @testset "CO2 | examples" begin include("test_examples.jl") end end