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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

### Added
- Add `eCFom` and `eCInv` to track FOM and investment costs separately (#809).

### Changed
- Rename `Transmission_NetExport` to `Transmission_NetImport` in `power_balance.csv` (#853).

## [0.4.5] - 2025-07-07

### Added
Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "GenX"
uuid = "5d317b1e-30ec-4ed6-a8ce-8d2d88d7cfac"
authors = ["Bonaldo, Luca", "Chakrabarti, Sambuddha", "Cheng, Fangwei", "Ding, Yifu", "Jenkins, Jesse D.", "Luo, Qian", "Macdonald, Ruaridh", "Mallapragada, Dharik", "Manocha, Aneesha", "Mantegna, Gabe ", "Morris, Jack", "Patankar, Neha", "Pecci, Filippo", "Schwartz, Aaron", "Schwartz, Jacob", "Schivley, Greg", "Sepulveda, Nestor", "Xu, Qingyu", "Zhou, Justin"]
version = "0.4.5"
version = "0.4.5-dev.1"

[deps]
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
Expand Down
9 changes: 7 additions & 2 deletions docs/src/User_Guide/model_output.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,17 @@ Reports optimal objective function value and contribution of each term by zone.
| cTotal |Total objective function value |USD |
| cFix |Total annualized investment and fixed operating & maintainenance (FOM) costs associated with all resources |USD |
| cVar |Total annual variable cost associated with all resources; includes fuel costs for thermal plants |USD |
| cFuel |System level total fuel cost |USD |
| cNSE |Total annual cost of non-served energy |USD |
| cStart |Total annual cost of start-up of thermal power plants| USD |
| cUnmetRsv |Total annual cost of not meeting time-dependent operating reserve (spinning) requirements |USD |
| cNetworkExp |Total cost of network expansion |USD |
| cEmissionsRevenue |Total and zonal emissions revenue |USD |
| cEmissionsCost |Total an zonal emissions cost |USD |
| cUnmetPolicyPenalty |Total annual cost of not meeting policy-based requirements (e.g. ESR, Capacity Reserve Margin, CO2 emissions, etc.) |USD |
| cCO2 |Total annual cost of CO2 sequestration |USD |
| cInv |Total annualized investment costs associated with all resources |USD |
| cFom |Total annual fixed operating & maintainenance (FOM) costs associated with all resources |USD |
| cGridConnection |Total annual cost of grid connection for VRE-storage resources |USD |
| cHydrogenRevenue |Total annual revenue from hydrogen sales |USD |

### 1.3 emissions.csv

Expand Down
34 changes: 26 additions & 8 deletions src/model/core/discharge/investment_discharge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -111,21 +111,39 @@ function investment_discharge!(EP::Model, inputs::Dict, setup::Dict)
eExistingCap[y]
end)

### Need editting ##
@expression(EP, eCFix[y in 1:G],
if y in NEW_CAP # Resources eligible for new capacity (Non-Retrofit)
## Objective Function Expressions ##

# Annuitized investment cost expression - only applies to resources eligible for new capacity
@expression(EP, eCInv[y in 1:G],
if y in NEW_CAP
investment_cost = inv_cost_per_mwyr(gen[y])
if y in COMMIT
inv_cost_per_mwyr(gen[y]) * cap_size(gen[y]) * vCAP[y] +
fixed_om_cost_per_mwyr(gen[y]) * eTotalCap[y]
investment_cost * cap_size(gen[y]) * vCAP[y]
else
inv_cost_per_mwyr(gen[y]) * vCAP[y] +
fixed_om_cost_per_mwyr(gen[y]) * eTotalCap[y]
investment_cost * vCAP[y]
end
else
fixed_om_cost_per_mwyr(gen[y]) * eTotalCap[y]
0
end)

# Fixed O&M cost expression - applies to all resources
@expression(EP, eCFom[y in 1:G],
fixed_om_cost_per_mwyr(gen[y]) * eTotalCap[y])

# Total fixed cost expression - combines investment and fixed O&M costs
@expression(EP, eCFix[y in 1:G],
if y in NEW_CAP
# For resources with new capacity: investment cost + fixed O&M cost
EP[:eCInv][y] + EP[:eCFom][y]
else
# For existing resources: only fixed O&M cost
EP[:eCFom][y]
end)

# Sum individual resource contributions to fixed costs to get total fixed costs
@expression(EP, eTotalCFix, sum(EP[:eCFix][y] for y in 1:G))
@expression(EP, eTotalCInv, sum(EP[:eCInv][y] for y in 1:G))
@expression(EP, eTotalCFom, sum(EP[:eCFom][y] for y in 1:G))

# Add term to objective function expression
if MultiStage == 1
Expand Down
43 changes: 32 additions & 11 deletions src/model/resources/flexible_ccs/allamcyclelox.jl
Original file line number Diff line number Diff line change
Expand Up @@ -172,27 +172,48 @@ function allamcyclelox!(EP::Model, inputs::Dict, setup::Dict)

# LOX storage tank capacity -> if they are not in WITH_LOX
@constraint(EP, [y in setdiff(ALLAM_CYCLE_LOX, WITH_LOX)], eTotalCap_AllamcycleLOX[y,lox] == 0 )
# Fixed cost of each component in Allam Cycle w/ LOX
# Set of generator eligible for new sCO2 turbine
# Allam Cycle is eligible for unit commitment
@expression(EP, eCFix_Allam[y in ALLAM_CYCLE_LOX, i in 1:3],

## Objective Function Expressions ##

# Annuitized investment cost expression - only applies to resources eligible for new capacity
@expression(EP, eCInv_Allam[y in ALLAM_CYCLE_LOX, i in 1:3],
if y in NEW_CAP_Allam # Resources eligible for new capacity
if y in COMMIT_Allam # Resource eligible for Unit commitment
allam_dict[y,"inv_cost"][i] * allam_dict[y,"cap_size"][i] * EP[:vCAP_AllamCycleLOX][y, i]+
allam_dict[y,"fom_cost"][i] * eTotalCap_AllamcycleLOX[y,i]
allam_dict[y,"inv_cost"][i] * allam_dict[y,"cap_size"][i] * EP[:vCAP_AllamCycleLOX][y, i]
else
allam_dict[y,"inv_cost"][i] * EP[:vCAP_AllamCycleLOX][y, i]+
allam_dict[y,"fom_cost"][i] * eTotalCap_AllamcycleLOX[y,i]
allam_dict[y,"inv_cost"][i] * EP[:vCAP_AllamCycleLOX][y, i]
end
else
allam_dict[y,"fom_cost"][i] * eTotalCap_AllamcycleLOX[y,i]
0
end)

# Fixed O&M cost expression - applies to all resources
@expression(EP, eCFom_Allam[y in ALLAM_CYCLE_LOX, i in 1:3],
allam_dict[y,"fom_cost"][i] * eTotalCap_AllamcycleLOX[y,i])

# Total fixed cost expression - combines investment and fixed O&M costs
@expression(EP, eCFix_Allam[y in ALLAM_CYCLE_LOX, i in 1:3],
if y in NEW_CAP_Allam # Resources eligible for new capacity
# For resources with new capacity: investment cost + fixed O&M cost
EP[:eCInv_Allam][y,i] + EP[:eCFom_Allam][y,i]
else
# For existing resources: only fixed O&M cost
EP[:eCFom_Allam][y,i]
end)

# connect eCFix_Allam_Plant to eCFix
# Sum individual resource contributions to fixed costs to get total fixed costs
@expression(EP, eCFix_Allam_Plant[y in ALLAM_CYCLE_LOX], sum(EP[:eCFix_Allam][y,i] for i in 1:3))
@expression(EP, eCInv_Allam_Plant[y in ALLAM_CYCLE_LOX], sum(EP[:eCInv_Allam][y,i] for i in 1:3))
@expression(EP, eCFom_Allam_Plant[y in ALLAM_CYCLE_LOX], sum(EP[:eCFom_Allam][y,i] for i in 1:3))

@expression(EP, eTotalCFix_Allam, sum(EP[:eCFix_Allam_Plant][y] for y in ALLAM_CYCLE_LOX ))
# add this to eTotalCFix
@expression(EP, eTotalCInv_Allam, sum(EP[:eCInv_Allam_Plant][y] for y in ALLAM_CYCLE_LOX))
@expression(EP, eTotalCFom_Allam, sum(EP[:eCFom_Allam_Plant][y] for y in ALLAM_CYCLE_LOX))

# add this to eTotalCFix, eTotalCInv, and eTotalCFom
add_to_expression!(EP[:eTotalCFix], eTotalCFix_Allam)
add_to_expression!(EP[:eTotalCInv], eTotalCInv_Allam)
add_to_expression!(EP[:eTotalCFom], eTotalCFom_Allam)

# add to Obj
add_to_expression!(EP[:eObj], eTotalCFix_Allam)
Expand Down
31 changes: 22 additions & 9 deletions src/model/resources/storage/investment_charge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -89,20 +89,33 @@ function investment_charge!(EP::Model, inputs::Dict, setup::Dict)
end)

## Objective Function Expressions ##

# Fixed costs for resource "y" = annuitized investment cost plus fixed O&M costs
# If resource is not eligible for new charge capacity, fixed costs are only O&M costs

# Annuitized investment cost expression for charge capacity - only applies to resources eligible for new charge capacity
@expression(EP, eCInvCharge[y in STOR_ASYMMETRIC],
if y in NEW_CAP_CHARGE
inv_cost_charge_per_mwyr(gen[y]) * vCAPCHARGE[y]
else
0
end)

# Fixed O&M cost expression for charge capacity - applies to all resources
@expression(EP, eCFomCharge[y in STOR_ASYMMETRIC],
fixed_om_cost_charge_per_mwyr(gen[y]) * eTotalCapCharge[y])

# Total fixed cost expression for charge capacity - combines investment and fixed O&M costs
@expression(EP, eCFixCharge[y in STOR_ASYMMETRIC],
if y in NEW_CAP_CHARGE # Resources eligible for new charge capacity
inv_cost_charge_per_mwyr(gen[y]) * vCAPCHARGE[y] +
fixed_om_cost_charge_per_mwyr(gen[y]) * eTotalCapCharge[y]
if y in NEW_CAP_CHARGE
# For resources with new charge capacity: investment cost + fixed O&M cost
EP[:eCInvCharge][y] + EP[:eCFomCharge][y]
else
fixed_om_cost_charge_per_mwyr(gen[y]) * eTotalCapCharge[y]
# For existing resources: only fixed O&M cost
EP[:eCFomCharge][y]
end)

# Sum individual resource contributions to fixed costs to get total fixed costs
@expression(EP, eTotalCFixCharge, sum(EP[:eCFixCharge][y] for y in STOR_ASYMMETRIC))

@expression(EP, eTotalCInvCharge, sum(EP[:eCInvCharge][y] for y in STOR_ASYMMETRIC))
@expression(EP, eTotalCFomCharge, sum(EP[:eCFomCharge][y] for y in STOR_ASYMMETRIC))
# Add term to objective function expression
if MultiStage == 1
# OPEX multiplier scales fixed costs to account for multiple years between two model stages
Expand Down
30 changes: 22 additions & 8 deletions src/model/resources/storage/investment_energy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -90,19 +90,33 @@ function investment_energy!(EP::Model, inputs::Dict, setup::Dict)
end)

## Objective Function Expressions ##

# Fixed costs for resource "y" = annuitized investment cost plus fixed O&M costs
# If resource is not eligible for new energy capacity, fixed costs are only O&M costs

# Annuitized investment cost expression for energy capacity - only applies to resources eligible for new energy capacity
@expression(EP, eCInvEnergy[y in STOR_ALL],
if y in NEW_CAP_ENERGY
inv_cost_per_mwhyr(gen[y]) * vCAPENERGY[y]
else
0
end)

# Fixed O&M cost expression for energy capacity - applies to all resources based on total energy capacity
@expression(EP, eCFomEnergy[y in STOR_ALL],
fixed_om_cost_per_mwhyr(gen[y]) * eTotalCapEnergy[y])

# Total fixed cost expression for energy capacity - combines investment and fixed O&M costs
@expression(EP, eCFixEnergy[y in STOR_ALL],
if y in NEW_CAP_ENERGY # Resources eligible for new capacity
inv_cost_per_mwhyr(gen[y]) * vCAPENERGY[y] +
fixed_om_cost_per_mwhyr(gen[y]) * eTotalCapEnergy[y]
if y in NEW_CAP_ENERGY
# For resources with new energy capacity: investment cost + fixed O&M cost
EP[:eCInvEnergy][y] + EP[:eCFomEnergy][y]
else
fixed_om_cost_per_mwhyr(gen[y]) * eTotalCapEnergy[y]
# For existing resources: only fixed O&M cost
EP[:eCFomEnergy][y]
end)

# Sum individual resource contributions to fixed costs to get total fixed costs
@expression(EP, eTotalCFixEnergy, sum(EP[:eCFixEnergy][y] for y in STOR_ALL))
@expression(EP, eTotalCInvEnergy, sum(EP[:eCInvEnergy][y] for y in STOR_ALL))
@expression(EP, eTotalCFomEnergy, sum(EP[:eCFomEnergy][y] for y in STOR_ALL))

# Add term to objective function expression
if MultiStage == 1
Expand Down
Loading
Loading