Skip to content

Commit

Permalink
Merge pull request #39 from NREL-Sienna/jd/psy4v2
Browse files Browse the repository at this point in the history
  • Loading branch information
jd-lara authored Jun 28, 2024
2 parents 676061f + 2974384 commit 717ecc2
Show file tree
Hide file tree
Showing 16 changed files with 203 additions and 163 deletions.
8 changes: 4 additions & 4 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "StorageSystemsSimulations"
uuid = "e2f1a126-19d0-4674-9252-42b2384f8e3c"
authors = ["Jose Daniel Lara, Rodrigo Henriquez-Auba, Sourabh Dalvi"]
version = "0.9.0"
version = "0.10.0"

[deps]
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Expand All @@ -18,10 +18,10 @@ PowerSystems = "bcd98974-b02a-5e2f-9ee0-a103f5c450dd"
Dates = "1"
DataStructures = "~0.18"
DocStringExtensions = "~0.8, ~0.9"
InfrastructureSystems = "1"
InfrastructureSystems = "2"
JuMP = "1"
LinearAlgebra = "1"
MathOptInterface = "1"
PowerSimulations = "^0.27"
PowerSystems = "3"
PowerSimulations = "^0.28"
PowerSystems = "4"
julia = "^1.6"
2 changes: 1 addition & 1 deletion docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ StorageSystemsSimulations = "e2f1a126-19d0-4674-9252-42b2384f8e3c"

[compat]
Documenter = "1"
InfrastructureSystems = "1"
InfrastructureSystems = "2"
12 changes: 6 additions & 6 deletions docs/src/formulation_library/StorageDispatchWithReserves.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ StorageDispatchWithReserves

## Attributes

- `"reservation"`: Forces the battery to operate exclusively on charge or discharge mode through the entire operation interval. We recommend setting this to false for models with relatively large resolutions (e.g., 1-Hr) since the storage can take simultaneous charge or discharge positions on average over the period.
- `"cycling_limits"`: This limits the battery's energy cycling. The calculation uses the total energy charge/discharge and the number of cycles. Currently, the formulation only supports a fixed value per operation period. Additional variables for [`StorageChargeCyclingSlackVariable`](@ref) and [`StorageDischargeCyclingSlackVariable`](@ref) are included in the model if `use_slacks` is set to `true`.
- `"energy_target"`: Set a target at the end of the model horizon for the state of charge. Currently, the formulation only supports a fixed value per operation period. Additional variables for [`StorageEnergyShortageVariable`](@ref) and [`StorageEnergySurplusVariable`](@ref) are included in the model if `use_slacks` is set to `true`.
- `"reservation"`: Forces the storage to operate exclusively on charge or discharge mode through the entire operation interval. We recommend setting this to false for models with relatively longer time resolutions (e.g., 1-Hr) since the storage can take simultaneous charge or discharge positions on average over the period.
- `"cycling_limits"`: This limits the storage's energy cycling. A single charging (discharging) cycle is fully charging (discharging) the storage once. The calculation uses the total energy charge/discharge and the number of cycles. Currently, the formulation only supports a fixed value per operation period. Additional variables for [`StorageChargeCyclingSlackVariable`](@ref) and [`StorageDischargeCyclingSlackVariable`](@ref) are included in the model if `use_slacks` is set to `true`.
- `"energy_target"`: Set a target at the end of the model horizon for the storage's state of charge. Currently, the formulation only supports a fixed value per operation period. Additional variables for [`StorageEnergyShortageVariable`](@ref) and [`StorageEnergySurplusVariable`](@ref) are included in the model if `use_slacks` is set to `true`.

!!! warning

Combining the cycle limits and energy target attributes is not recommended. Both
attributes impose constraints on the energy; there is no guarantee that the constraints can be satisfied simultaneously.
Combining cycle limits and energy target attributes is not recommended. Both
attributes impose constraints on energy. There is no guarantee that the constraints can be satisfied simultaneously.

- `"complete_coverage"`: This attribute implements constraints that require the battery to cover the sum of all the ancillary services it participates in simultaneously. It is equivalent to holding energy in case all the services get deployed simultaneously. This constraint is added to the constraints that cover each service independently and corresponds to a more conservative operation regime.
- `"regularization"`: This attribute smooths the charge/discharge profiles to avoid bang-bang solutions via a penalty on the absolute value of the intra-temporal variations of the charge and discharge power. The model can stall in models with large amounts of curtailment or long periods with negative or zero prices due to numerical degeneracy. The regularization term is scaled by the power limits to normalize the term and avoid additional penalties to larger storage units.
- `"regularization"`: This attribute smooths the charge/discharge profiles to avoid bang-bang solutions via a penalty on the absolute value of the intra-temporal variations of the charge and discharge power. Solving for optimal storage dispatch can stall in models with large amounts of curtailment or long periods with negative or zero prices due to numerical degeneracy. The regularization term is scaled by the storage device's power limits to normalize the term and avoid additional penalties to larger storage units.

!!! danger

Expand Down
6 changes: 3 additions & 3 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ CurrentModule = StorageSystemsSimulations
## Overview

`StorageSimulations.jl` is a `PowerSimulations.jl` extension to support formulations and models
related to energ storage.
related to energy storage.

Operational Storage Model can have multiple combinations of different restrictions. For instance,
An Operational Storage Model can have multiple combinations of different restrictions. For instance,
it might be relevant to a study to consider cycling limits or employ energy targets coming from a planning model. To manage all these variations `StorageSimulations.jl` heavily uses the `DeviceModel` attributes feature.

For example, the formulation `StorageDispatchWithReserves` can be parametrized as follows:

```julia
DeviceModel(
StorageType, # E.g. BatteryEMS or GenericStorage
StorageType, # E.g. EnergyReservoirStorage
StorageDispatchWithReserves;
attributes=Dict(
"reservation" => true,
Expand Down
4 changes: 2 additions & 2 deletions docs/src/tutorials/single_stage_model.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ set_available!(orcd, false)
```

```@example op_problem
batt = get_component(BatteryEMS, c_sys5_bat, "Bat2")
batt = get_component(EnergyReservoirStorage, c_sys5_bat, "Bat2")
operation_cost = get_operation_cost(batt)
```
Expand All @@ -48,7 +48,7 @@ set_device_model!(template_uc, Line, StaticBranch)

```@example op_problem
storage_model = DeviceModel(
BatteryEMS,
EnergyReservoirStorage,
StorageDispatchWithReserves;
attributes=Dict(
"reservation" => true,
Expand Down
1 change: 1 addition & 0 deletions src/StorageSystemsSimulations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const PSI = PowerSimulations
const PSY = PowerSystems
const PM = PSI.PM
const IS = InfrastructureSystems
const ISOPT = InfrastructureSystems.Optimization

using DocStringExtensions
@template (FUNCTIONS, METHODS) = """
Expand Down
4 changes: 2 additions & 2 deletions src/core/feedforward.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ struct EnergyTargetFeedforward <: PSI.AbstractAffectFeedforward
affected_values::Vector{DataType},
target_period::Int,
penalty_cost::Float64,
meta=PSI.CONTAINER_KEY_EMPTY_META,
meta=ISOPT.CONTAINER_KEY_EMPTY_META,
) where {T}
values_vector = Vector{PSI.VariableKey}(undef, length(affected_values))
for (ix, v) in enumerate(affected_values)
Expand Down Expand Up @@ -135,7 +135,7 @@ struct EnergyLimitFeedforward <: PSI.AbstractAffectFeedforward
source::Type{T},
affected_values::Vector{DataType},
number_of_periods::Int,
meta=PSI.CONTAINER_KEY_EMPTY_META,
meta=ISOPT.CONTAINER_KEY_EMPTY_META,
) where {T}
values_vector = Vector{PSI.VariableKey}(undef, length(affected_values))
for (ix, v) in enumerate(affected_values)
Expand Down
2 changes: 1 addition & 1 deletion src/core/formulations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ The formulation supports the following attributes. See Documentation for more de
```julia
DeviceModel(
StorageType, # E.g. BatteryEMS or GenericStorage
StorageType, # E.g. EnergyReservoirStorage or GenericStorage
StorageDispatchWithReserves;
attributes=Dict(
"reservation" => true,
Expand Down
8 changes: 4 additions & 4 deletions src/storage_constructor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ function PSI.construct_device!(
model::PSI.DeviceModel{St, D},
network_model::PSI.NetworkModel{S},
) where {St <: PSY.Storage, D <: StorageDispatchWithReserves, S <: PM.AbstractPowerModel}
devices = PSI.get_available_components(St, sys)
devices = PSI.get_available_components(model, sys)
_active_power_variables_and_expressions(container, devices, model, network_model)
PSI.add_variables!(container, PSI.ReactivePowerVariable, devices, D())

Expand Down Expand Up @@ -252,7 +252,7 @@ function PSI.construct_device!(
model::PSI.DeviceModel{St, D},
network_model::PSI.NetworkModel{S},
) where {St <: PSY.Storage, D <: StorageDispatchWithReserves, S <: PM.AbstractPowerModel}
devices = PSI.get_available_components(St, sys)
devices = PSI.get_available_components(model, sys)
_active_power_and_energy_bounds(container, devices, model, network_model)

PSI.add_constraints!(
Expand Down Expand Up @@ -318,7 +318,7 @@ function PSI.construct_device!(
D <: StorageDispatchWithReserves,
S <: PM.AbstractActivePowerModel,
}
devices = PSI.get_available_components(St, sys)
devices = PSI.get_available_components(model, sys)
_active_power_variables_and_expressions(container, devices, model, network_model)

if PSI.get_attribute(model, "regularization")
Expand All @@ -345,7 +345,7 @@ function PSI.construct_device!(
D <: StorageDispatchWithReserves,
S <: PM.AbstractActivePowerModel,
}
devices = PSI.get_available_components(St, sys)
devices = PSI.get_available_components(model, sys)
_active_power_and_energy_bounds(container, devices, model, network_model)

# Energy Balanace limits
Expand Down
Loading

2 comments on commit 717ecc2

@jd-lara
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 register()

@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/110039

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.10.0 -m "<description of version>" 717ecc24aec5513204ef4e095715ff09a04832f5
git push origin v0.10.0

Please sign in to comment.