Skip to content

Commit

Permalink
Improvement of input/output dictionary for retrofit (#4)
Browse files Browse the repository at this point in the history
Changed requirements for type definition
- No longer required to specify co2_proxy as input/output
- Specifying co2_proxy has no effect
  • Loading branch information
JulStraus authored Aug 16, 2024
1 parent 02a6710 commit e9f3a95
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 28 deletions.
9 changes: 8 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
# Release Notes

## Unversioned
## Version 0.7.1 (2024-08-16)

* Removed requirement for specifying the `co2_proxy` resource as output of the `NetworkNodeWithRetrofit` node and input to the `CCSRetroFit` node through addding methods for `EMB.outputs` and `EMB.inputs`.
This implies that both are no longer specified within the `input` and `output` dictionary, and all functionality directly accessing the fields may result in errors.
* Adjusted documentation to deploy to the proper site.
* Removed pre-release statements.

## Version 0.7.0 (2024-08-15)

* Adjusted documentation to deploy to the proper site.
* Removed pre-release statements.
Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "EnergyModelsCO2"
uuid = "84b3f4d7-d799-4a5d-b06c-25c90dcfcad7"
authors = ["Sigmund Eggen Holm <[email protected]> and contributors"]
version = "0.7.0"
version = "0.7.1"

[deps]
EnergyModelsBase = "5d7e687e-f956-46f3-9045-6f5a5fd49f50"
Expand Down
2 changes: 2 additions & 0 deletions docs/src/library/internals/d-methods-EMB.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ EnergyModelsBase.constraints_data

```@docs
EnergyModelsBase.previous_level
EnergyModelsBase.inputs
EnergyModelsBase.outputs
```

## Check methods
Expand Down
8 changes: 5 additions & 3 deletions docs/src/nodes/retrofit.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,11 @@ The standard fields are given as:
All values have to be non-negative.
!!! info "Meaning in boths nodes"
- [`RefNetworkNodeRetrofit`](@ref):\
Requires the incorporation of the CO₂ proxy resource in the `output` dictionary, although the exact value is not relevant.
No special meaning.
The CO₂ proxy resource is automatically included in the `output` dictionary through providing additional methods to `EMB.outputs`.
- [`CCSRetroFit`](@ref):\
Requires the incorporation of the CO₂ proxy resource in the `input` dictionary and the CO₂ resource in the `output` dictionary, although the exact values are not relevant.
The CO₂ proxy resource is automatically included in the `input` dictionary through providing additional methods to `EMB.inputs`.
Requires the incorporation of the CO₂ resource in the `output` dictionary, although the exact value is not relevant.
It is furthermore possible to specify additional reenergy required for capturing CO₂ using a conversion factor (*e.g.*, MWh/t CO₂).
- **`data::Vector{Data}`**:\
An entry for providing additional data to the model.
Expand Down Expand Up @@ -396,7 +398,7 @@ This constraint is given by:

```math
\texttt{flow\_in}[n, t, p] =
outputs(n, p) \times \texttt{cap\_use}[n, t]
inputs(n, p) \times \texttt{cap\_use}[n, t]
\qquad \forall p \in inputs(n) \setminus \{co2\_proxy(n)\}
```

Expand Down
9 changes: 4 additions & 5 deletions examples/ccs_retrofit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ function generate_co2_retrofit_example_data()
FixedProfile(5.5), # Variable OPEX in €/MWh
FixedProfile(0), # Fixed OPEX in €/MW/a
Dict(NG => 1.66), # Input to the node with input ratio
Dict(Power => 1, CO2_proxy => 0), # Output from the node with input ratio
# Line above: CO2_proxy is required as output for variable definition, but the
# value does not matter
Dict(Power => 1), # Output from the node with input ratio
# Line above: CO2_proxy does not have to be specified as we add a method to
# `EMB.outputs`
CO2_proxy, # Instance of the `CO2_proxy`
Data[CaptureEnergyEmissions(1.0)], # Capture data for the node.
# All energy emissions are captured
Expand All @@ -87,8 +87,7 @@ function generate_co2_retrofit_example_data()
FixedProfile(0), # Variable OPEX in €/t
FixedProfile(0), # Fixed OPEX in €/(t/h)/a
Dict(NG => 1.0, CO2_proxy => 0), # Input to the node with input ratio
# Line above: CO2_proxy is required as input for variable definition, but the
# value does not matter
# Line above: CO2_proxy is not required as input as we utilize an inner constructor
Dict(CO2 => 0),
# Line above: CO2 is required as input for variable definition, but the
# value does not matter
Expand Down
33 changes: 20 additions & 13 deletions src/data_functions.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@

"""
EMB.constraints_data(m, n::NetworkNodeWithRetrofit, 𝒯, 𝒫, modeltype, data::EmissionsData)
EMB.constraints_data(
m,
n::NetworkNodeWithRetrofit,
𝒯,
𝒫,
modeltype::EnergyModel,
data::EmissionsData
)
Constraints functions for calculating both the emissions and amount of CO₂ captured in the
process when CO₂ capture is included as retrofit. It works similar to the approach of
Expand All @@ -14,7 +21,7 @@ function EMB.constraints_data(
n::NetworkNodeWithRetrofit,
𝒯,
𝒫,
modeltype,
modeltype::EnergyModel,
data::CaptureProcessEnergyEmissions,
)

Expand Down Expand Up @@ -49,7 +56,7 @@ function EMB.constraints_data(
n::NetworkNodeWithRetrofit,
𝒯,
𝒫,
modeltype,
modeltype::EnergyModel,
data::CaptureEnergyEmissions,
)

Expand Down Expand Up @@ -85,7 +92,7 @@ function EMB.constraints_data(
n::NetworkNodeWithRetrofit,
𝒯,
𝒫,
modeltype,
modeltype::EnergyModel,
data::CaptureProcessEmissions,
)

Expand Down Expand Up @@ -118,7 +125,7 @@ function EMB.constraints_data(
end

"""
EMB.constraints_data(m, n::CCSRetroFit, 𝒯, 𝒫, modeltype, data::EmissionsData)
EMB.constraints_data(m, n::CCSRetroFit, 𝒯, 𝒫, modeltype::EnergyModel, data::EmissionsData)
Constraints functions for calculating both the emissions and amount of CO₂ captured in the
CO₂ capture unit.
Expand All @@ -141,14 +148,14 @@ function EMB.constraints_data(
n::CCSRetroFit,
𝒯,
𝒫,
modeltype,
modeltype::EnergyModel,
data::CaptureProcessEnergyEmissions,
)

# Declaration of the required subsets.
CO2 = co2_instance(modeltype)
CO2_proxy = co2_proxy(n)
𝒫ⁱⁿ = inputs(n)
𝒫ⁱⁿ = setdiff(inputs(n), [CO2_proxy])
𝒫ᵉᵐ = setdiff(filter(EMB.is_resource_emit, 𝒫), [CO2])

# Calculate the total amount of CO2 to be considered for capture
Expand Down Expand Up @@ -193,14 +200,14 @@ function EMB.constraints_data(
n::CCSRetroFit,
𝒯,
𝒫,
modeltype,
modeltype::EnergyModel,
data::CaptureEnergyEmissions,
)

# Declaration of the required subsets.
CO2 = co2_instance(modeltype)
CO2_proxy = co2_proxy(n)
𝒫ⁱⁿ = inputs(n)
𝒫ⁱⁿ = setdiff(inputs(n), [CO2_proxy])
𝒫ᵉᵐ = setdiff(filter(EMB.is_resource_emit, 𝒫), [CO2])

# Calculate the total amount of CO2 to be considered for capture
Expand Down Expand Up @@ -244,14 +251,14 @@ function EMB.constraints_data(
n::CCSRetroFit,
𝒯,
𝒫,
modeltype,
modeltype::EnergyModel,
data::CaptureProcessEmissions,
)

# Declaration of the required subsets.
CO2 = co2_instance(modeltype)
CO2_proxy = co2_proxy(n)
𝒫ⁱⁿ = inputs(n)
𝒫ⁱⁿ = setdiff(inputs(n), [CO2_proxy])
𝒫ᵉᵐ = setdiff(filter(EMB.is_resource_emit, 𝒫), [CO2])

# Calculate the total amount of CO2 to be considered for capture
Expand Down Expand Up @@ -289,12 +296,12 @@ function EMB.constraints_data(
)
)
end
function EMB.constraints_data(m, n::CCSRetroFit, 𝒯, 𝒫, modeltype, data::CaptureFlueGas)
function EMB.constraints_data(m, n::CCSRetroFit, 𝒯, 𝒫, modeltype::EnergyModel, data::CaptureFlueGas)

# Declaration of the required subsets.
CO2 = co2_instance(modeltype)
CO2_proxy = co2_proxy(n)
𝒫ⁱⁿ = inputs(n)
𝒫ⁱⁿ = setdiff(inputs(n), [CO2_proxy])
𝒫ᵉᵐ = setdiff(filter(EMB.is_resource_emit, 𝒫), [CO2])

# Calculate the total amount of CO2 to be considered for capture
Expand Down
34 changes: 34 additions & 0 deletions src/datastructures.jl
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ It corresponds to a [`RefNetworkNode`](@extref EnergyModelsBase.RefNetworkNode)
which the CO₂ is not emitted. Instead, it is transferred to a `co2_proxy` that is fed
subsequently to a node ([`CCSRetroFit`](@ref)) in which it is either captured, or emitted.
The `co2_proxy` does not have to be specified as `output` resource.
# Fields
- **`id`** is the name/identifier of the node.
- **`cap::TimeProfile`** is the installed capacity.
Expand All @@ -166,12 +168,29 @@ struct RefNetworkNodeRetrofit <: NetworkNodeWithRetrofit
data::Array{<:Data}
end

"""
EMB.outputs(n::CCSRetroFit)
When the node is a [`NetworkNodeWithRetrofit`](@ref), it returns the `co2_proxy` resource in
addition to the keys of the `output` dictionary.
"""
EMB.outputs(n::NetworkNodeWithRetrofit) = unique(append!(Resource[n.co2_proxy], keys(n.output)))
"""
EMB.outputs(n::NetworkNodeWithRetrofit, p::Resource)
When the node is a [`NetworkNodeWithRetrofit`](@ref), it returns the value of `output`
resource `p`. If `p` is the `co2_proxy` resource, it returns 0.
"""
EMB.outputs(n::NetworkNodeWithRetrofit, p::Resource) = haskey(n.output, p) ? n.output[p] : 0

"""
CCSRetroFit <: Network
This node allows for investments into CO₂ capture retrofit to a [`RefNetworkNodeRetrofit`](@ref)
node. The capture process is implemented through the variable `:cap_use`
The `co2_proxy` does not have to be specified as `input` resource.
# Fields
- **`id`** is the name/identifier of the node.
- **`cap::TimeProfile`** is the installed capacity.
Expand All @@ -196,6 +215,21 @@ struct CCSRetroFit <: NetworkNode
data::Array{<:Data}
end

"""
EMB.inputs(n::CCSRetroFit)
When the node is a [`CCSRetroFit`](@ref), it returns the `co2_proxy` resource in addition to
the keys of the `input` dictionary.
"""
EMB.inputs(n::CCSRetroFit) = unique(append!(Resource[n.co2_proxy], keys(n.input)))
"""
EMB.inputs(n::CCSRetroFit, p::Resource)
When the node is a [`CCSRetroFit`](@ref), it returns the value of `input` resource `p`.
If `p` is the `co2_proxy` resource, it returns 0.
"""
EMB.inputs(n::CCSRetroFit, p::Resource) = haskey(n.input, p) ? n.input[p] : 0

"""
co2_proxy(n::EMB.Node)
Expand Down
4 changes: 2 additions & 2 deletions src/model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ Set all constraints for a `CCSRetroFit`.
function EMB.create_node(m, n::CCSRetroFit, 𝒯, 𝒫, modeltype::EnergyModel)

# Declaration of the required subsets
𝒫ⁱⁿ = inputs(n)
CO2_proxy = co2_proxy(n)
𝒫ⁱⁿ = setdiff(inputs(n), [CO2_proxy])
𝒯ᴵⁿᵛ = strategic_periods(𝒯)

# Iterate through all data and set up the constraints corresponding to the data
Expand All @@ -87,7 +87,7 @@ function EMB.create_node(m, n::CCSRetroFit, 𝒯, 𝒫, modeltype::EnergyModel)

# Inlet constraints for all other resources
# The value for `CO2_proxy` is calculated in `constraints_data`.
@constraint(m, [t 𝒯, p EMB.res_not(𝒫ⁱⁿ, CO2_proxy)],
@constraint(m, [t 𝒯, p 𝒫ⁱⁿ],
m[:flow_in][n, t, p] == m[:cap_use][n, t] * inputs(n, p)
)

Expand Down
6 changes: 3 additions & 3 deletions test/test_ccs_retrofit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function CO2_retrofit(emissions_data; process_unit=nothing)
FixedProfile(5.5),
FixedProfile(0),
Dict(NG => 2),
Dict(Power => 1, CO2_proxy => 0),
Dict(Power => 1),
CO2_proxy,
[emissions_data["process"]],
)
Expand All @@ -31,7 +31,7 @@ function CO2_retrofit(emissions_data; process_unit=nothing)
FixedProfile(5),
FixedProfile(0),
FixedProfile(0),
Dict(NG => 0.05, CO2_proxy => 0),
Dict(NG => 0.05),
Dict(CO2 => 0),
CO2_proxy,
[emissions_data["ccs"]],
Expand Down Expand Up @@ -351,7 +351,7 @@ end
FixedProfile(5.5),
FixedProfile(0),
Dict(NG => 2),
Dict(Power => 1, CO2_proxy => 0),
Dict(Power => 1),
CO2_proxy,
[CaptureEnergyEmissions(Dict(CO2 => 0.1), 0.9)],
)
Expand Down

2 comments on commit e9f3a95

@JulStraus
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/113230

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.7.1 -m "<description of version>" e9f3a95aefb6eddf50509f27901a1ad640c40e49
git push origin v0.7.1

Please sign in to comment.