Split the units machinery out of ProductionVariableCostCurve; add LossCurve - #603
Split the units machinery out of ProductionVariableCostCurve; add LossCurve#603luke-kiernan wants to merge 1 commit into
Conversation
…sCurve
Loss curves on HVDC lines and converters (PowerSystems.jl) were declared as
bare `ValueCurve`s, which carry no units, so whether a curve's axes were in MW,
system base, or device base was ambiguous — and consumers disagreed in practice
(PSB builds an `InterconnectingConverter` loss curve in system base while an
open POM PR reads the same curve as device base).
Carrying units is not specific to costs, so the machinery that does it is now
split out one level:
ValueCurveWithUnits{T, U} # value_curve + units type parameter
├── ProductionVariableCostCurve # adds vom_cost
│ ├── CostCurve
│ └── FuelCurve
└── LossCurve
`ValueCurveWithUnits` owns everything the two families share — the units type
parameter and `get_power_units`, the value-curve accessors, convexity,
equality/hashing, `serialize`/`deserialize` including the `power_units` key, and
the expanded `show`. `ProductionVariableCostCurve` keeps only what makes a curve
a *cost*: `get_vom_cost` and the cost-specific per-field deserializers.
That division is load-bearing, not cosmetic. Curve-valued cost fields
(`ThermalGenerationCost.variable`, `HydroGenerationCost.variable`) are typed on
`ProductionVariableCostCurve`, so they still reject a `LossCurve`; and losses
have no VOM cost, so inheriting `get_vom_cost` would have promised a field that
isn't there. Sharing at the `ValueCurveWithUnits` level gets the common
implementation without either problem.
No behavior change for `CostCurve`/`FuelCurve`: the methods moved to the
supertype, none were removed or altered.
Part of the fix for PowerSystems.jl#1728.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR refactors the unit-system type-parameter machinery out of ProductionVariableCostCurve into a new shared supertype (ValueCurveWithUnits) and introduces LossCurve so loss-related curves can carry an explicit (dispatchable) x-axis unit system, addressing ambiguous axes for HVDC loss curves.
Changes:
- Added
ValueCurveWithUnits{T,U}to own shared accessors, equality/hash, serialization, andshowbehavior for unit-parameterized curves. - Updated
ProductionVariableCostCurve{T,U}to subtypeValueCurveWithUnits{T,U}and kept only cost-specific functionality (e.g.,vom_costfield deserialization). - Added
LossCurve{T,U}plus new tests covering construction, display, serialization round-trips, andzerobehavior.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| test/test_cost_functions.jl | Adds LossCurve test coverage (construction, units typing, show output, serialization, zero). |
| src/value_curve_with_units.jl | Introduces new shared abstract supertype and common methods (accessors, TS helpers, equality/hash, serialization, show). |
| src/production_variable_cost_curve.jl | Re-bases PVCC on ValueCurveWithUnits and moves shared logic out; retains PVCC-specific deserializers and compact show. |
| src/loss_curve.jl | Adds the new LossCurve type, constructors, AnyLossCurve, zero, and compact show. |
| src/InfrastructureSystems.jl | Wires new source files into module load order via include. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| Base.isequal(a::T, b::T) where {T <: ValueCurveWithUnits} = isequal_from_fields(a, b) | ||
|
|
||
| Base.hash(a::ValueCurveWithUnits, h::UInt) = hash_from_fields(a, h) |
|
Reverted to draft--revisit after the schema stuff lands, so that the folks working on integrating that stuff don't have to deal with a moving target. |
|
@luke-kiernan you can restart this now |
|
Superseded by #621, which reimplements this on top of current |
Supports PowerSystems.jl#1728, where loss curves on HVDC lines and converters are bare
ValueCurves carrying no units, leaving their axes ambiguous.Carrying units isn't specific to costs, so that machinery is split out one level:
The new supertype owns what both families share (units parameter, value-curve accessors, equality/hashing, serialization, display).
ProductionVariableCostCurvekeeps only what makes a curve a cost:get_vom_costand the cost-specific field deserializers.LossCurveis deliberately not underProductionVariableCostCurve:ThermalGenerationCost.variable/HydroGenerationCost.variableare typed on it, andget_vom_costis defined on it — a loss curve has no VOM cost.No behavior or serialization change for
CostCurve/FuelCurve; methods moved, none removed or altered.Tests: 1462 pass. The
Test generated structsfailure is pre-existing onIS4(verified against a clean baseline, unrelated).Pairs with a PowerSystems.jl PR against
psy6.🤖 Generated with Claude Code