Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
TimerOutputs = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f"

[sources]
InfrastructureSystems = {url = "https://github.com/NREL-Sienna/InfrastructureSystems.jl", rev = "IS4"}

[weakdeps]
PowerFlows = "94fada2c-0ca5-4b90-a1fb-4bc5b59ccfc7"

Expand Down
12 changes: 12 additions & 0 deletions src/PowerOperationsModels.jl
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ import InfrastructureOptimizationModels:
add_proportional_cost!,
add_proportional_cost_maybe_time_variant!,
skip_proportional_cost,
# variable cost
add_variable_cost!,
# Network model instantiation (POM extends for concrete network formulations)
instantiate_network_model!,
# Parameter addition (POM provides concrete implementations)
Expand Down Expand Up @@ -520,6 +522,10 @@ export HVDCLosses
export ConverterDCPower
export ConverterCurrentDirection

# Load Variables
export ShiftUpActivePowerVariable
export ShiftDownActivePowerVariable

######## Hydro Formulations ########
export HydroDispatchRunOfRiver
export HydroDispatchRunOfRiverBudget
Expand Down Expand Up @@ -666,6 +672,11 @@ export DurationConstraint
export CommitmentConstraint
export StartTypeConstraint
export StartupTimeLimitTemperatureConstraint
export ShiftedActivePowerBalanceConstraint
export ShiftUpActivePowerVariableLimitsConstraint
export ShiftDownActivePowerVariableLimitsConstraint
export RealizedShiftedLoadMinimumBoundConstraint
export NonAnticipativityConstraint

#################################################################################
# Exports - Expression Types (defined in core/expressions.jl)
Expand Down Expand Up @@ -732,6 +743,7 @@ export ThermalSecurityConstrainedStandardUnitCommitment
export StaticPowerLoad
export PowerLoadInterruption
export PowerLoadDispatch
export PowerLoadShift

# Renewable Formulations
export RenewableFullDispatch
Expand Down
53 changes: 53 additions & 0 deletions src/core/constraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1047,3 +1047,56 @@ The specified constraints are formulated as:
```
"""
struct StorageRegularizationConstraintDischarge <: ConstraintType end

"""
Struct to create the constraint to balance shifted power over the user-defined time horizons.
For more information check the [`PowerLoadShift`](@ref) formulation.
The specified constraints are formulated as:
```math
\\sum_{t \\in \\text{time horizon}_k } p_t^\\text{shift,up} - p_t^\\text{shift,dn} = 0 , \\quad \\forall k \\text{ time horizons}
```
"""
struct ShiftedActivePowerBalanceConstraint <: ConstraintType end

"""
Struct to create the constraint to balance shifted power over the user-defined time horizons.
For more information check the [`PowerLoadShift`](@ref) formulation.
The specified constraints are formulated as:
```math
p_t^\\text{realized} \\ge 0.0 , \\quad \\forall k \\text{ time horizons}
```
"""
struct RealizedShiftedLoadMinimumBoundConstraint <: ConstraintType end

"""
Struct to create the non-anticipativity constraint for the [`PowerLoadShift`](@ref) formulation.
This enforces that shift up can only occur after an equal or greater amount of shift down has
already been committed, preventing the optimizer from shifting load up before it has been
shifted down. The constraint is formulated as:

```math
\\sum_{\\tau=1}^{t} \\left( p_\\tau^\\text{shift,dn} - p_\\tau^\\text{shift,up} \\right) \\ge 0,
\\quad \\forall t \\in \\{1,\\dots,T\\}
```
"""
struct NonAnticipativityConstraint <: ConstraintType end

"""
Struct to create the constraint to limit shifted power active power between upper and lower bounds.
For more information check the [`PowerLoadShift`](@ref) formulation.
The specified constraints are formulated as:
```math
0 \\le p_t^\\text{shift, up} \\le P_t^\\text{upper}, \\quad \\forall t \\in \\{1,\\dots,T\\}
```
"""
struct ShiftUpActivePowerVariableLimitsConstraint <: PowerVariableLimitsConstraint end

"""
Struct to create the constraint to limit shifted power active power between upper and lower bounds.
For more information check the [`PowerLoadShift`](@ref) formulation.
The specified constraints are formulated as:
```math
0 \\le p_t^\\text{shift, dn} \\le P_t^\\text{lower}, \\quad \\forall t \\in \\{1,\\dots,T\\}
```
"""
struct ShiftDownActivePowerVariableLimitsConstraint <: PowerVariableLimitsConstraint end
3 changes: 3 additions & 0 deletions src/core/expressions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ struct ComponentReserveDownBalanceExpression <: ExpressionType end
struct InterfaceTotalFlow <: ExpressionType end
struct PTDFBranchFlow <: ExpressionType end
struct PostContingencyNodalActivePowerDeployment <: PostContingencyExpressions end
struct RealizedShiftedLoad <: ExpressionType end

#################################################################################
# Hydro Expressions
Expand Down Expand Up @@ -100,6 +101,7 @@ struct ReserveDeploymentBalanceDownCharge <: StorageReserveChargeExpression end
# Method extensions for output writing
should_write_resulting_value(::Type{InterfaceTotalFlow}) = true
should_write_resulting_value(::Type{PTDFBranchFlow}) = true
should_write_resulting_value(::Type{RealizedShiftedLoad}) = true

should_write_resulting_value(::Type{HydroServedReserveUpExpression}) = true
should_write_resulting_value(::Type{HydroServedReserveDownExpression}) = true
Expand All @@ -114,3 +116,4 @@ convert_output_to_natural_units(::Type{InterfaceTotalFlow}) = true
convert_output_to_natural_units(::Type{PostContingencyBranchFlow}) = true
convert_output_to_natural_units(::Type{PostContingencyActivePowerGeneration}) = true
convert_output_to_natural_units(::Type{PTDFBranchFlow}) = true
convert_output_to_natural_units(::Type{RealizedShiftedLoad}) = true
5 changes: 5 additions & 0 deletions src/core/formulations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ Formulation type to enable (continuous) load interruption dispatch
"""
struct PowerLoadDispatch <: AbstractControllablePowerLoadFormulation end

"""
Formulation type to enable load shifting
"""
struct PowerLoadShift <: AbstractControllablePowerLoadFormulation end

############################ Regulation Device Formulations ################################
abstract type AbstractRegulationFormulation <: AbstractDeviceFormulation end
struct ReserveLimitedRegulation <: AbstractRegulationFormulation end
Expand Down
12 changes: 12 additions & 0 deletions src/core/parameters.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ Parameter to define active power in time series
"""
struct ActivePowerInTimeSeriesParameter <: TimeSeriesParameter end

"""
Parameter to define active power in time series
"""
struct ShiftUpActivePowerTimeSeriesParameter <: TimeSeriesParameter end

"""
Parameter to define active power in time series
"""
struct ShiftDownActivePowerTimeSeriesParameter <: TimeSeriesParameter end

"""
Parameter to define requirement time series
"""
Expand Down Expand Up @@ -238,6 +248,8 @@ convert_output_to_natural_units(::Type{ReactivePowerTimeSeriesParameter}) = true
convert_output_to_natural_units(::Type{RequirementTimeSeriesParameter}) = true
convert_output_to_natural_units(::Type{UpperBoundValueParameter}) = true
convert_output_to_natural_units(::Type{LowerBoundValueParameter}) = true
convert_result_to_natural_units(::Type{ShiftUpActivePowerTimeSeriesParameter}) = true
convert_result_to_natural_units(::Type{ShiftDownActivePowerTimeSeriesParameter}) = true
Comment on lines +251 to +252
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

convert_result_to_natural_units is not used anywhere else in this codebase (only convert_output_to_natural_units is extended for parameters). As written, this will define a new local function and the ShiftUp/ShiftDown time-series parameters likely won't be converted to natural units when outputs/results are written. Consider changing these to convert_output_to_natural_units(::Type{ShiftUpActivePowerTimeSeriesParameter}) = true and likewise for ShiftDown (or use the existing conversion hook used by other parameters).

Suggested change
convert_result_to_natural_units(::Type{ShiftUpActivePowerTimeSeriesParameter}) = true
convert_result_to_natural_units(::Type{ShiftDownActivePowerTimeSeriesParameter}) = true
convert_output_to_natural_units(::Type{ShiftUpActivePowerTimeSeriesParameter}) = true
convert_output_to_natural_units(::Type{ShiftDownActivePowerTimeSeriesParameter}) = true

Copilot uses AI. Check for mistakes.
convert_output_to_natural_units(::Type{ReservoirLimitParameter}) = true
convert_output_to_natural_units(::Type{ReservoirTargetParameter}) = true
convert_output_to_natural_units(::Type{EnergyTargetTimeSeriesParameter}) = true
Expand Down
16 changes: 16 additions & 0 deletions src/core/variables.jl
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,22 @@ Docs abbreviation: ``\\theta``
"""
struct VoltageAngle <: VariableType end

#########################################
###### Power Load Shift Variables #######
#########################################

"""
Struct to dispatch the creation of Shifted Active Power Variables
Docs abbreviation: ``p^\\text{shift,up}``
"""
struct ShiftUpActivePowerVariable <: VariableType end

"""
Struct to dispatch the creation of Shifted Down Active Power Variables
Docs abbreviation: ``p^\\text{shift,dn}``
"""
struct ShiftDownActivePowerVariable <: VariableType end

#########################################
####### DC Converter Variables ##########
#########################################
Expand Down
Loading
Loading