Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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
53 changes: 53 additions & 0 deletions src/PowerOperationsModels.jl
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,10 @@ include("services_models/reserve_group.jl")
include("services_models/transmission_interface.jl")
include("services_models/services_constructor.jl")

# Hybrid System Models (after services_models since they share reserve infrastructure)
include("hybrid_system_models/hybrid_systems.jl")
include("hybrid_system_models/hybridsystem_constructor.jl")

# Two-Terminal HVDC Models
# NOTE: AC_branches.jl and branch_constructor.jl in twoterminal_hvdc_models/ are
# identical copies of the files in ac_transmission_models/ — do NOT include them.
Expand Down Expand Up @@ -647,6 +651,55 @@ export ReserveDeploymentBalanceDownCharge
export EnergyLimitParameter
export EnergyTargetParameter

######## Hybrid System Formulations ########
export AbstractHybridFormulation
export AbstractHybridFormulationWithReserves
export HybridDispatchWithReserves

# variables
export HybridChargingReserveVariable
export HybridDischargingReserveVariable
export HybridRenewableActivePower
export HybridRenewableReserveVariable
export HybridReserveVariableIn
export HybridReserveVariableOut
export HybridStorageChargePower
export HybridStorageDischargePower
export HybridStorageReservation
export HybridThermalActivePower
export HybridThermalReserveVariable

# expressions
export HybridServedReserveInDownExpression
export HybridServedReserveInUpExpression
export HybridServedReserveOutDownExpression
export HybridServedReserveOutUpExpression
export HybridTotalReserveInDownExpression
export HybridTotalReserveInUpExpression
export HybridTotalReserveOutDownExpression
export HybridTotalReserveOutUpExpression

# constraints
export HybridEnergyAssetBalanceConstraint
export HybridRenewableActivePowerLimitConstraint
export HybridRenewableReserveLimitConstraint
export HybridReserveAssignmentConstraint
export HybridReserveBalanceConstraint
export HybridStatusInOnConstraint
export HybridStatusOutOnConstraint
export HybridStorageBalanceConstraint
export HybridStorageChargingReservePowerLimitConstraint
export HybridStorageDischargingReservePowerLimitConstraint
export HybridStorageStatusChargeOnConstraint
export HybridStorageStatusDischargeOnConstraint
export HybridThermalOnVariableLbConstraint
export HybridThermalOnVariableUbConstraint
export HybridThermalReserveLimitConstraint

# parameters
export HybridElectricLoadTimeSeriesParameter
export HybridRenewableActivePowerTimeSeriesParameter

#################################################################################
# Exports - Constraint Types (defined in core/constraints.jl)
#################################################################################
Expand Down
59 changes: 59 additions & 0 deletions src/core/constraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1100,3 +1100,62 @@ The specified constraints are formulated as:
```
"""
struct ShiftDownActivePowerVariableLimitsConstraint <: PowerVariableLimitsConstraint end

#################################################################################
# Hybrid System Constraints
#################################################################################

"""
Couples the hybrid PCC reserve variables (out + in) to the system-level
`ActivePowerReserveVariable` of each service the hybrid participates in.
"""
struct HybridReserveAssignmentConstraint <: ConstraintType end

"""
Couples the hybrid PCC reserve variables (out + in) to the sum of per-subcomponent reserve
allocations (thermal + renewable + charging + discharging).
"""
struct HybridReserveBalanceConstraint <: ConstraintType end

"""
Equates the hybrid's PCC active-power injection to the sum of internal subcomponent
flows (thermal + renewable + storage discharge - storage charge - load) net of served
reserves.
"""
struct HybridEnergyAssetBalanceConstraint <: ConstraintType end

"Status link between the hybrid PCC `ActivePowerOutVariable` and the reservation variable."
struct HybridStatusOutOnConstraint <: ConstraintType end

"Status link between the hybrid PCC `ActivePowerInVariable` and the reservation variable."
struct HybridStatusInOnConstraint <: ConstraintType end

"Upper-bound link between thermal subcomponent power and its commitment status."
struct HybridThermalOnVariableUbConstraint <: ConstraintType end

"Lower-bound link between thermal subcomponent power and its commitment status."
struct HybridThermalOnVariableLbConstraint <: ConstraintType end

"Range constraint on thermal subcomponent power including up/down reserves."
struct HybridThermalReserveLimitConstraint <: ConstraintType end

"Upper bound on renewable subcomponent power from the time-series forecast."
struct HybridRenewableActivePowerLimitConstraint <: ConstraintType end

"Range constraint on renewable subcomponent power including up/down reserves."
struct HybridRenewableReserveLimitConstraint <: ConstraintType end

"Energy balance for the storage subcomponent of a hybrid system, including reserve deployment."
struct HybridStorageBalanceConstraint <: ConstraintType end

"Mutually-exclusive charge limit for the hybrid storage subcomponent (no reserves case)."
struct HybridStorageStatusChargeOnConstraint <: ConstraintType end

"Mutually-exclusive discharge limit for the hybrid storage subcomponent (no reserves case)."
struct HybridStorageStatusDischargeOnConstraint <: ConstraintType end

"Charge-side power limit for the hybrid storage subcomponent including reserve carve-outs."
struct HybridStorageChargingReservePowerLimitConstraint <: ConstraintType end

"Discharge-side power limit for the hybrid storage subcomponent including reserve carve-outs."
struct HybridStorageDischargingReservePowerLimitConstraint <: ConstraintType end
31 changes: 31 additions & 0 deletions src/core/expressions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,35 @@ struct ReserveDeploymentBalanceUpCharge <: StorageReserveChargeExpression end
struct ReserveDeploymentBalanceDownDischarge <: StorageReserveDischargeExpression end
struct ReserveDeploymentBalanceDownCharge <: StorageReserveChargeExpression end

#################################################################################
# Hybrid System Expressions
#################################################################################

"""
Hybrid-boundary aggregation of reserve quantities offered through the discharge (out) and
charge (in) sides of a `PSY.HybridSystem`. These expressions accumulate the per-subcomponent
reserve variables into the hybrid-system PCC reserve.
"""
abstract type HybridTotalReserveExpression <: ExpressionType end
abstract type HybridTotalReserveUpExpression <: HybridTotalReserveExpression end
abstract type HybridTotalReserveDownExpression <: HybridTotalReserveExpression end

struct HybridTotalReserveOutUpExpression <: HybridTotalReserveUpExpression end
struct HybridTotalReserveOutDownExpression <: HybridTotalReserveDownExpression end
struct HybridTotalReserveInUpExpression <: HybridTotalReserveUpExpression end
struct HybridTotalReserveInDownExpression <: HybridTotalReserveDownExpression end

"""
Served (deployed-fraction) variants of the hybrid total reserve expressions, used by the
energy-asset-balance accounting to discount the deployed portion of held reserve.
"""
abstract type HybridServedReserveExpression <: ExpressionType end

struct HybridServedReserveOutUpExpression <: HybridServedReserveExpression end
struct HybridServedReserveOutDownExpression <: HybridServedReserveExpression end
struct HybridServedReserveInUpExpression <: HybridServedReserveExpression end
struct HybridServedReserveInDownExpression <: HybridServedReserveExpression end

# Method extensions for output writing
should_write_resulting_value(::Type{InterfaceTotalFlow}) = true
should_write_resulting_value(::Type{PTDFBranchFlow}) = true
Expand All @@ -111,6 +140,8 @@ should_write_resulting_value(::Type{TotalHydroFlowRateTurbineOutgoing}) = true
should_write_resulting_value(::Type{StorageReserveDischargeExpression}) = true
should_write_resulting_value(::Type{StorageReserveChargeExpression}) = true

should_write_resulting_value(::Type{<:HybridServedReserveExpression}) = true

# Method extensions for unit conversion
convert_output_to_natural_units(::Type{InterfaceTotalFlow}) = true
convert_output_to_natural_units(::Type{PostContingencyBranchFlow}) = true
Expand Down
42 changes: 42 additions & 0 deletions src/core/formulations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -403,3 +403,45 @@ The formulation supports the following attributes when used in a [`PowerSimulati
See the [`StorageDispatchWithReserves` Mathematical Model](@ref) for the full mathematical description.
"""
struct StorageDispatchWithReserves <: AbstractStorageFormulation end

############################ Hybrid System Formulations ###################################
abstract type AbstractHybridFormulation <: IOM.AbstractDeviceFormulation end
abstract type AbstractHybridFormulationWithReserves <: AbstractHybridFormulation end

"""
Formulation type for hybrid systems with internal sub-component dispatch and reserve
participation. A `PSY.HybridSystem` may contain a thermal unit, a renewable unit, an
electric load, and storage; each subcomponent contributes to the hybrid's PCC injection.

Reserve participation is wired through the storage subcomponent using POM's existing
`ReserveCoverageConstraint`/`ReserveDischargeConstraint`/`ReserveChargeConstraint`/
`StorageTotalReserveConstraint` infrastructure (with hybrid-specific dispatch methods);
the thermal and renewable subcomponents use dedicated hybrid reserve-limit constraints.

# Example

```julia
DeviceModel(
PSY.HybridSystem,
HybridDispatchWithReserves;
attributes = Dict(
"reservation" => true,
"energy_target" => false,
),
)
```

# Attributes

- `"reservation"`: forces the storage subcomponent to operate exclusively on charge or
discharge mode through the entire operation interval.
Comment thread
acostarelli marked this conversation as resolved.
Outdated
- `"energy_target"`: adds `StateofChargeTargetConstraint` at the storage subcomponent
(slack variables included if `use_slacks=true`).

!!! note

Cycling limits are not exposed as a hybrid attribute in this version. If cycling
behavior is required for the storage subcomponent, file a follow-up to wire POM's
`StorageCyclingCharge`/`StorageCyclingDischarge` through the hybrid path.
"""
struct HybridDispatchWithReserves <: AbstractHybridFormulationWithReserves end
15 changes: 15 additions & 0 deletions src/core/parameters.jl
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,18 @@ Parameter to record that the component changed in the availability status
"""
struct AvailableStatusChangeCountdownParameter <: EventParameter end

#################################################################################
# Hybrid System Parameters
#################################################################################

"Time-series parameter for the maximum active power available from a hybrid system's
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@jd-lara This is a change from how things are currently defined in HSS with the time series attached to the hybrid, not the subcomponent, but I guess that works and is simpler for this case?

renewable subcomponent, normalized by the renewable unit's `max_active_power` rating."
struct HybridRenewableActivePowerTimeSeriesParameter <: TimeSeriesParameter end

"Time-series parameter for a hybrid system's electric-load subcomponent demand,
normalized by the load's `max_active_power`."
struct HybridElectricLoadTimeSeriesParameter <: TimeSeriesParameter end

#################################################################################
# Method extensions for should_write_resulting_value
#################################################################################
Expand Down Expand Up @@ -256,3 +268,6 @@ convert_output_to_natural_units(::Type{EnergyTargetTimeSeriesParameter}) = true
convert_output_to_natural_units(::Type{EnergyBudgetTimeSeriesParameter}) = true
convert_output_to_natural_units(::Type{InflowTimeSeriesParameter}) = false
convert_output_to_natural_units(::Type{OutflowTimeSeriesParameter}) = false
convert_output_to_natural_units(::Type{HybridRenewableActivePowerTimeSeriesParameter}) =
true
convert_output_to_natural_units(::Type{HybridElectricLoadTimeSeriesParameter}) = true
49 changes: 49 additions & 0 deletions src/core/variables.jl
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,55 @@ Auxiliary Variable for Storage Models that solve for total energy output
"""
struct StorageEnergyOutput <: AuxVariableType end

#################################################################################
# Hybrid System Variables
#################################################################################

"""
Abstract type for variables representing flows internal to a `PSY.HybridSystem`.
"""
abstract type HybridSubcomponentVariableType <: VariableType end

"Active power dispatched by the thermal subcomponent of a hybrid system."
struct HybridThermalActivePower <: HybridSubcomponentVariableType end

"Active power dispatched by the renewable subcomponent of a hybrid system."
struct HybridRenewableActivePower <: HybridSubcomponentVariableType end

"Active power consumed by the storage subcomponent (charge) of a hybrid system."
struct HybridStorageChargePower <: HybridSubcomponentVariableType end

"Active power produced by the storage subcomponent (discharge) of a hybrid system."
struct HybridStorageDischargePower <: HybridSubcomponentVariableType end

"Binary reservation variable for the storage subcomponent of a hybrid system."
struct HybridStorageReservation <: HybridSubcomponentVariableType end

"Reserve quantity offered to the grid through the hybrid's outflow (discharge) side."
struct HybridReserveVariableOut <: VariableType end

"Reserve quantity offered to the grid through the hybrid's inflow (charge) side."
struct HybridReserveVariableIn <: VariableType end

"""
Abstract type for per-subcomponent reserve allocation variables inside a hybrid system.
Used to split the hybrid-boundary reserve commitment across the thermal, renewable, and
storage subcomponents.
"""
abstract type HybridComponentReserveVariableType <: VariableType end

"Reserve allocated to the thermal subcomponent of a hybrid system."
struct HybridThermalReserveVariable <: HybridComponentReserveVariableType end

"Reserve allocated to the renewable subcomponent of a hybrid system."
struct HybridRenewableReserveVariable <: HybridComponentReserveVariableType end

"Reserve allocated to the charging side of a hybrid system's storage subcomponent."
struct HybridChargingReserveVariable <: HybridComponentReserveVariableType end

"Reserve allocated to the discharging side of a hybrid system's storage subcomponent."
struct HybridDischargingReserveVariable <: HybridComponentReserveVariableType end

const MULTI_START_VARIABLES = (HotStartVariable, WarmStartVariable, ColdStartVariable)

should_write_resulting_value(::Type{PiecewiseLinearCostVariable}) = false
Expand Down
Loading
Loading