You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There appears to be an issue with how variable costs (and emission costs) are represented in the objective function.
Some background:
Decision Variables in Temoa: Temoa has two main sets of decision variables: those related to capacity ("V_Capacity") and those related to dispatch ("V_FlowOut"). These variables are connected through several equations, including the Capacity_Constraint (discussed further below).
Modeling Discrete Future Years: Temoa typically models a discrete set of future years (e.g., 2020, 2025, 2030, etc.).
Accounting for End-of-Life Technologies: Temoa includes logic to account for situations where technologies reach their end-of-life during the middle of a model period (e.g., in 2023). In such cases, the effective capacities—and consequently, the dispatch—of these technologies are scaled down proportionally to the fraction of the model period during which they are active (e.g., for 2023 in a 2020–2025 period, the fraction would be 3/5=0.6).
Some notes on variable names
ModelProcessLife, or MPL, represents the number of years during the period in question over which the technology remains operational. This is the lesser of the period length and the remaining process lifetime of the technology. For example, in the case above, MPL would be min(5,3)=3.
ProcessLifeFrac is the fraction representing the ratio of the two arguments in MPL, e.g., 3/5=0.6.
Guts
The Capacity_Constraint is as follows: capacity * value(M.CapacityToActivity[r, t]) * value(M.SegFrac[s, d]) * value(M.ProcessLifeFrac[r, p, t, v]) * M.V_Capacity[r, p, t, v] >= useful_activity
If we assume the technology only has one input commodity and one output commodity, and if we assume this technology is not governed by capacity factors, this simplifies to:
Here, we see the fixed costs are scaled by MPL, which makes sense. We take the capacity, V_Capacity, which has not yet been scaled for end-of-life effects, and scale it by MPL. Logic: you pay fixed costs only in the years in which that technology exists.
Here, we see the variable costs are scaled by MPL as well. And I believe this is a bug. The activity (V_FlowOut) has already taken into account the end-of-life effects by the presence of PLF in the Capacity_Constraint. Therefore, it should be multiplied here by the period length (e.g., 5 years), not the MPL (e.g., 3 years).
Example
Let's imagine an NGCC plant w/ 1 GW capacity operating in a model period of length 5 years (e.g. 2020-2025) and the technology reaches its EOL 3 years into that period (2023). Then we have:
This makes sense. That plant can operate at it's namplelate capacity of 1 GW in 3 of the 5 years, resulting in an average annual activity of 0.6 GWh.
Given that, the objective function should multiply this activity by the period length (5 years = 3 GWh), and not the MPL of 3 years (1.8 GWh).
Impact
Fairly minimal. This bug effectively discounts variable costs for technologies in the model period in which they reach their EOL. This discount is proportional to its MPL.
Proposed Fix
Fairly straightforward. The MPL parameter in the variable cost and emission cost logic within the objective function should be replaced by the period length, M.PeriodLength[p]
The text was updated successfully, but these errors were encountered:
I agree that this is a bug. Ignoring capacity entirely, with the current math, if a technology retires at 3/5 years
MPL = 3
PLF = 3/5 = 0.6
and it outputs 1 unit of flow per year at a cost of $1 per unit of flow, it's total cost for that period will be:
flow * cost * mpl
= 1 * $1 * 3
= $3
The commodity balance constraint does not adjust for EOL. The model is operating assuming that this flow is being supplied over all 5 years of that period, and so the cost should be the full $5.
I think you are on-point. It would be nice to make a tiny test case to prove (a) that it's broke (but that is pretty convincing) and (b) show the fix works. I have a small dataset "smallville" that might be useful if someone wants to mod it for a unit test... I'm thinking 2 techs (one cheap that is limited by MPL) and one expensive for 1 time period should show this.
Ran a wee test on utopia already and pretty satisfied that it is indeed broken in both discounted and undiscounted terms, and that the change above fixes both.
There appears to be an issue with how variable costs (and emission costs) are represented in the objective function.
Some background:
Some notes on variable names
ModelProcessLife
, orMPL
, represents the number of years during the period in question over which the technology remains operational. This is the lesser of the period length and the remaining process lifetime of the technology. For example, in the case above, MPL would be min(5,3)=3.ProcessLifeFrac
is the fraction representing the ratio of the two arguments in MPL, e.g., 3/5=0.6.Guts
The Capacity_Constraint is as follows:
capacity * value(M.CapacityToActivity[r, t]) * value(M.SegFrac[s, d]) * value(M.ProcessLifeFrac[r, p, t, v]) * M.V_Capacity[r, p, t, v] >= useful_activity
If we assume the technology only has one input commodity and one output commodity, and if we assume this technology is not governed by capacity factors, this simplifies to:
1 * value(M.CapacityToActivity[r, t]) * value(M.SegFrac[s, d]) * value(M.ProcessLifeFrac[r, p, t, v]) * M.V_Capacity[r, p, t, v] >= M.V_FlowOut[r, p, s, d, i, t, v, o]
This implies the following:
OK. So this brings us to the objective function.
Fixed Costs
Notes:
fixed_costs = sum( M.V_Capacity[r, p, S_t, S_v] * ( value(M.CostFixed[r, p, S_t, S_v]) * ( value(MPL[r, p, S_t, S_v]) ) )
Here, we see the fixed costs are scaled by MPL, which makes sense. We take the capacity, V_Capacity, which has not yet been scaled for end-of-life effects, and scale it by MPL. Logic: you pay fixed costs only in the years in which that technology exists.
Variable Costs
variable_costs = sum( M.V_FlowOut[r, p, s, d, S_i, S_t, S_v, S_o] * ( value(M.CostVariable[r, p, S_t, S_v]) * ( value(MPL[r, p, S_t, S_v]) ) )
Here, we see the variable costs are scaled by MPL as well. And I believe this is a bug. The activity (V_FlowOut) has already taken into account the end-of-life effects by the presence of PLF in the Capacity_Constraint. Therefore, it should be multiplied here by the period length (e.g., 5 years), not the MPL (e.g., 3 years).
Example
Let's imagine an NGCC plant w/ 1 GW capacity operating in a model period of length 5 years (e.g. 2020-2025) and the technology reaches its EOL 3 years into that period (2023). Then we have:
Capacity constraint:
value(M.CapacityToActivity[r, t]) * value(M.SegFrac[s, d]) * value(M.ProcessLifeFrac[r, p, t, v]) * M.V_Capacity[r, p, t, v] >= M.V_FlowOut[r, p, s, d, i, t, v, o]
simplifies to:
8760 GWh/GW * 1/8760 * 0.6 * 1 GW >= M.V_FlowOut
which is equivalent to
V_FlowOut <= 0.6 GWh
This makes sense. That plant can operate at it's namplelate capacity of 1 GW in 3 of the 5 years, resulting in an average annual activity of 0.6 GWh.
Given that, the objective function should multiply this activity by the period length (5 years = 3 GWh), and not the MPL of 3 years (1.8 GWh).
Impact
Fairly minimal. This bug effectively discounts variable costs for technologies in the model period in which they reach their EOL. This discount is proportional to its MPL.
Proposed Fix
Fairly straightforward. The MPL parameter in the variable cost and emission cost logic within the objective function should be replaced by the period length,
M.PeriodLength[p]
The text was updated successfully, but these errors were encountered: