Skip to content

Commit

Permalink
Merge pull request #1092 from NREL-Sienna/jd/parallel_build_testing
Browse files Browse the repository at this point in the history
build in parallel test
  • Loading branch information
jd-lara authored Mar 27, 2024
2 parents 8adee35 + 24761c5 commit 3c4d320
Show file tree
Hide file tree
Showing 48 changed files with 1,268 additions and 706 deletions.
41 changes: 28 additions & 13 deletions docs/src/formulation_library/General.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,38 +56,53 @@ No constraints are created for `DeviceModel(<:DeviceType, FixedOutput)`

---

## `VariableCost` Options
## `FunctionData` Options

PowerSimulations can represent variable costs using a variety of different methods depending on the data available in each device. The following describes the objective function terms that are populated for each variable cost option.

### Scalar `VariableCost`
### `LinearFunctionData`

`variable_cost <: Float64`: creates a fixed marginal cost term in the objective function
`variable_cost = LinearFunctionData(c)`: creates a fixed marginal cost term in the objective function

```math
\begin{aligned}
& \text{min} \sum_{t} C * G_t
& \text{min} \sum_{t} c * G_t
\end{aligned}
```

### Polynomial `VariableCost`
### `QuadraticFunctionData` and `PolynomialFunctionData`

`variable_cost <: Tuple{Float64, Float64}`: creates a polynomial cost term in the objective function where

- ``C_g``=`variable_cost[1]`
- ``C_g^\prime``=`variable_cost[2]`
`variable_cost::QuadraticFunctionData` and `variable_cost::PolynomialFunctionData`: create a polynomial cost term in the objective function

```math
\begin{aligned}
& \text{min} \sum_{t} C * G_t + C^\prime * G_t^2
& \text{min} \sum_{t} \sum_{n} C_n * G_t^n
\end{aligned}
```

### Piecewise Linear `VariableCost`
where

- For `QuadraticFunctionData`:
- ``C_0`` = `get_constant_term(variable_cost)`
- ``C_1`` = `get_proportional_term(variable_cost)`
- ``C_2`` = `get_quadratic_term(variable_cost)`
- For `PolynomialFunctionData`:
- ``C_n`` = `get_coefficients(variable_cost)[n]`

### `PiecewiseLinearPointData` and `PiecewiseLinearSlopeData`

`variable_cost::PiecewiseLinearPointData` and `variable_cost::PiecewiseLinearSlopeData`: create a piecewise linear cost term in the objective function

```math
\begin{aligned}
& \text{min} \sum_{t} f(G_t)
\end{aligned}
```

`variable_cost <: Vector{Tuple{Float64, Float64}}`: creates a piecewise linear cost term in the objective function
where

TODO: add formulation
- For `variable_cost::PiecewiseLinearPointData`, ``f(x)`` is the piecewise linear function obtained by connecting the `(x, y)` points `get_points(variable_cost)` in order.
- For `variable_cost = PiecewiseLinearSlopeData([x0, x1, x2, ...], y0, [s0, s1, s2, ...])`, ``f(x)`` is the piecewise linear function obtained by starting at `(x0, y0)`, drawing a segment at slope `s0` to `x=x1`, drawing a segment at slope `s1` to `x=x2`, etc.

___

Expand Down
4 changes: 2 additions & 2 deletions docs/src/formulation_library/Load.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ mdtable(combo_table, latex = false)

**Objective:**

Creates an objective function term based on the [`VariableCost` Options](@ref) where the quantity term is defined as ``Pg``.
Creates an objective function term based on the [`FunctionData` Options](@ref) where the quantity term is defined as ``Pg``.

**Expressions:**

Expand Down Expand Up @@ -143,7 +143,7 @@ mdtable(combo_table, latex = false)

**Objective:**

Creates an objective function term based on the [`VariableCost` Options](@ref) where the quantity term is defined as ``Pg``.
Creates an objective function term based on the [`FunctionData` Options](@ref) where the quantity term is defined as ``Pg``.

**Expressions:**

Expand Down
4 changes: 2 additions & 2 deletions docs/src/formulation_library/RenewableGen.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ mdtable(combo_table, latex = false)

**Objective:**

Creates an objective function term based on the [`VariableCost` Options](@ref) where the quantity term is defined as ``- Pg_t`` to incentivize generation from `RenewableGen` devices.
Creates an objective function term based on the [`FunctionData` Options](@ref) where the quantity term is defined as ``- Pg_t`` to incentivize generation from `RenewableGen` devices.

**Expressions:**

Expand Down Expand Up @@ -113,7 +113,7 @@ mdtable(combo_table, latex = false)

**Objective:**

Creates an objective function term based on the [`VariableCost` Options](@ref) where the quantity term is defined as ``- Pg_t`` to incentivize generation from `RenewableGen` devices.
Creates an objective function term based on the [`FunctionData` Options](@ref) where the quantity term is defined as ``- Pg_t`` to incentivize generation from `RenewableGen` devices.

**Expressions:**

Expand Down
1 change: 1 addition & 0 deletions src/PowerSimulations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ include("core/parameters.jl")
include("core/service_model.jl")
include("core/device_model.jl")
include("core/variables.jl")
include("core/event_keys.jl")
include("core/auxiliary_variables.jl")
include("core/constraints.jl")
include("core/expressions.jl")
Expand Down
3 changes: 3 additions & 0 deletions src/core/constraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ struct ActivePowerVariableLimitsConstraint <: PowerVariableLimitsConstraint end
struct ReactivePowerVariableLimitsConstraint <: PowerVariableLimitsConstraint end
struct ActivePowerVariableTimeSeriesLimitsConstraint <: PowerVariableLimitsConstraint end

abstract type EventConstraint <: ConstraintType end
struct OutageConstraint <: EventConstraint end

# These apply to the processing of constraint duals
should_write_resulting_value(::Type{<:ConstraintType}) = true
convert_result_to_natural_units(::Type{<:ConstraintType}) = false
5 changes: 5 additions & 0 deletions src/core/device_model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ mutable struct DeviceModel{D <: PSY.Device, B <: AbstractDeviceFormulation}
services::Vector{ServiceModel}
time_series_names::Dict{Type{<:TimeSeriesParameter}, String}
attributes::Dict{String, Any}
subsystem::Union{Nothing, String}

function DeviceModel(
::Type{D},
Expand All @@ -75,6 +76,7 @@ mutable struct DeviceModel{D <: PSY.Device, B <: AbstractDeviceFormulation}
Vector{ServiceModel}(),
time_series_names,
attributes_,
nothing,
)
end
end
Expand All @@ -94,6 +96,9 @@ get_time_series_names(m::DeviceModel) = m.time_series_names
get_attributes(m::DeviceModel) = m.attributes
get_attribute(::Nothing, ::String) = nothing
get_attribute(m::DeviceModel, key::String) = get(m.attributes, key, nothing)
get_subsystem(m::DeviceModel) = m.subsystem

set_subsystem!(m::DeviceModel, id::String) = m.subsystem = id

function get_reference_bus(
m::DeviceModel{T, U},
Expand Down
22 changes: 22 additions & 0 deletions src/core/event_keys.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
abstract type EventType end

struct EventKey{T <: EventType, U <: Union{PSY.Component, PSY.System}}
meta::String
end

function EventKey(
::Type{T},
::Type{U},
) where {T <: EventType, U <: Union{PSY.Component, PSY.System}}
if isabstracttype(U)
error("Type $U can't be abstract")
end
return EventKey{T, U}("")
end

get_entry_type(
::EventKey{T, U},
) where {T <: EventType, U <: Union{PSY.Component, PSY.System}} = T
get_component_type(
::EventKey{T, U},
) where {T <: EventType, U <: Union{PSY.Component, PSY.System}} = U
11 changes: 11 additions & 0 deletions src/core/initial_conditions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,14 @@ struct InitialTimeDurationOn <: InitialConditionType end
struct InitialTimeDurationOff <: InitialConditionType end
struct InitialEnergyLevel <: InitialConditionType end
struct AreaControlError <: InitialConditionType end

# Decide whether to run the initial conditions reconciliation algorithm based on the presence of any of these
requires_reconciliation(::Type{<:InitialConditionType}) = false

requires_reconciliation(::Type{InitialTimeDurationOn}) = true
requires_reconciliation(::Type{InitialTimeDurationOff}) = true
requires_reconciliation(::Type{DeviceStatus}) = true
requires_reconciliation(::Type{DevicePower}) = true # to capture a case when device is off in HA but producing power in ED
requires_reconciliation(::Type{DeviceAboveMinPower}) = true # ramping limits may make power differences in thermal compact devices between models infeasible
requires_reconciliation(::Type{InitialEnergyLevel}) = true # large differences in initial storage levels could lead to infeasibilities
# Not requiring reconciliation for AreaControlError
7 changes: 6 additions & 1 deletion src/core/network_model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ mutable struct NetworkModel{T <: PM.AbstractPowerModel}
duals::Vector{DataType}
radial_network_reduction::PNM.RadialNetworkReduction
reduce_radial_branches::Bool
subsystem::Union{Nothing, String}

function NetworkModel(
::Type{T};
Expand All @@ -52,6 +53,7 @@ mutable struct NetworkModel{T <: PM.AbstractPowerModel}
duals,
PNM.RadialNetworkReduction(),
reduce_radial_branches,
nothing,
)
end
end
Expand All @@ -67,6 +69,9 @@ get_reference_buses(m::NetworkModel{T}) where {T <: PM.AbstractPowerModel} =
get_subnetworks(m::NetworkModel) = m.subnetworks
get_bus_area_map(m::NetworkModel) = m.bus_area_map
has_subnetworks(m::NetworkModel) = !isempty(m.bus_area_map)
get_subsystem(m::NetworkModel) = m.subsystem

set_subsystem!(m::NetworkModel, id::String) = m.subsystem = id

function add_dual!(model::NetworkModel, dual)
dual in model.duals && error("dual = $dual is already stored")
Expand Down Expand Up @@ -139,7 +144,7 @@ function _assign_subnetworks_to_buses(
subnetworks = model.subnetworks
temp_bus_map = Dict{Int, Int}()
radial_network_reduction = PSI.get_radial_network_reduction(model)
for bus in PSI.get_available_components(PSY.ACBus, sys)
for bus in PSI.get_available_components(model, PSY.ACBus, sys)
bus_no = PSY.get_number(bus)
mapped_bus_no = PNM.get_mapped_bus_number(radial_network_reduction, bus)
if haskey(temp_bus_map, bus_no)
Expand Down
11 changes: 7 additions & 4 deletions src/core/optimization_container.jl
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ end

function init_optimization_container!(
container::OptimizationContainer,
::Type{T},
network_model::NetworkModel{T},
sys::PSY.System,
) where {T <: PM.AbstractPowerModel}
PSY.set_units_base_system!(sys, "SYSTEM_BASE")
Expand All @@ -358,10 +358,13 @@ function init_optimization_container!(
container.time_steps = 1:get_horizon(settings)

if T <: CopperPlatePowerModel || T <: AreaBalancePowerModel
total_number_of_devices = length(get_available_components(PSY.Device, sys))
total_number_of_devices =
length(get_available_components(network_model, PSY.Device, sys))
else
total_number_of_devices = length(get_available_components(PSY.Device, sys))
total_number_of_devices += length(get_available_components(PSY.ACBranch, sys))
total_number_of_devices =
length(get_available_components(network_model, PSY.Device, sys))
total_number_of_devices +=
length(get_available_components(network_model, PSY.ACBranch, sys))
end

# The 10e6 limit is based on the sizes of the lp benchmark problems http://plato.asu.edu/ftp/lpcom.html
Expand Down
2 changes: 2 additions & 0 deletions src/core/parameters.jl
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,8 @@ struct CostFunctionParameter <: ObjectiveFunctionParameter end

abstract type AuxVariableValueParameter <: RightHandSideParameter end

struct EventParameter <: ParameterType end

should_write_resulting_value(::Type{<:ParameterType}) = false
should_write_resulting_value(::Type{<:RightHandSideParameter}) = true

Expand Down
5 changes: 5 additions & 0 deletions src/core/service_model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ mutable struct ServiceModel{D <: PSY.Service, B <: AbstractServiceFormulation}
time_series_names::Dict{Type{<:TimeSeriesParameter}, String}
attributes::Dict{String, Any}
contributing_devices_map::Dict{Type{<:PSY.Component}, Vector{<:PSY.Component}}
subsystem::Union{Nothing, String}
function ServiceModel(
::Type{D},
::Type{B},
Expand All @@ -64,6 +65,7 @@ mutable struct ServiceModel{D <: PSY.Service, B <: AbstractServiceFormulation}
time_series_names,
attributes_for_model,
contributing_devices_map,
nothing,
)
end
end
Expand All @@ -86,6 +88,9 @@ get_contributing_devices_map(m::ServiceModel, key) =
get(m.contributing_devices_map, key, nothing)
get_contributing_devices(m::ServiceModel) =
[z for x in values(m.contributing_devices_map) for z in x]
get_subsystem(m::ServiceModel) = m.subsystem

set_subsystem!(m::ServiceModel, id::String) = m.subsystem = id

function ServiceModel(
service_type::Type{D},
Expand Down
Loading

0 comments on commit 3c4d320

Please sign in to comment.