Skip to content

Commit

Permalink
Add co2 and fuel modules
Browse files Browse the repository at this point in the history
The fuel module accounts for fuel consumption and fuel costs, and also
models the relationship between fuel consumption and power output at
different load via a piecewise linear-approximation.

The CO2 module replaces emissions.jl, and allows us to track the CO2
emissions from power plants based on the fuel consumption, CO2 capture
rate (during the startup and normal operation), and whether the
feedstock is biomass.

See documentation in co2.jl and fuel.jl for detailed descriptions.
  • Loading branch information
fc4uk authored and lbonaldo committed Sep 18, 2023
1 parent 82b438e commit c1ac911
Show file tree
Hide file tree
Showing 28 changed files with 826 additions and 87 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased

### Added
- Feature CO2 and fuel module (#536)
Adds a fuel module which enables modeling of fuel usage via (1) a constant heat rate and (2)
piecewise-linear approximation of heat rate curves.
Adds a CO2 module that determines the CO2 emissions based on fuel consumption, CO2 capture
fraction, and whether the feedstock is biomass.
- Feature electrolysis basic (#525)
Adds hydrogen electrolyzer model which enables the addition of hydrogen electrolyzer
demands along with optional clean supply constraints.
Expand Down
2 changes: 2 additions & 0 deletions Example_Systems/PiecewiseFuel_CO2_Example/CO2_cap.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
,Network_zones,CO_2_Cap_Zone_1,CO_2_Max_tons_MWh_1,CO_2_Max_Mtons_1
NE,z1,1,0,0
25 changes: 25 additions & 0 deletions Example_Systems/PiecewiseFuel_CO2_Example/Demand_data.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Voll,Demand_Segment,Cost_of_Demand_Curtailment_per_MW,Max_Demand_Curtailment,$/MWh,Rep_Periods,Timesteps_per_Rep_Period,Sub_Weights,Time_Index,Demand_MW_z1
2000,1,1,1,2000,1,24,8760,1,10000
,2,0.9,0.04,1800,,,,2,9500
,3,0.55,0.024,1100,,,,3,9000
,4,0.2,0.003,400,,,,4,8500
,,,,,,,,5,8000
,,,,,,,,6,7500
,,,,,,,,7,8000
,,,,,,,,8,8500
,,,,,,,,9,9000
,,,,,,,,10,9500
,,,,,,,,11,10000
,,,,,,,,12,10500
,,,,,,,,13,11000
,,,,,,,,14,11500
,,,,,,,,15,12000
,,,,,,,,16,12500
,,,,,,,,17,13000
,,,,,,,,18,14000
,,,,,,,,19,15000
,,,,,,,,20,16000
,,,,,,,,21,17000
,,,,,,,,22,16000
,,,,,,,,23,15000
,,,,,,,,24,14000
26 changes: 26 additions & 0 deletions Example_Systems/PiecewiseFuel_CO2_Example/Fuels_data.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
Time_Index,NG,Biomass
0,0.05306,0.095
1,4,8
2,4,8
3,4,8
4,4,8
5,4,8
6,4,8
7,4,8
8,4,8
9,4,8
10,4,8
11,4,8
12,4,8
13,4,8
14,4,8
15,4,8
16,4,8
17,4,8
18,4,8
19,4,8
20,4,8
21,4,8
22,4,8
23,4,8
24,4,8
4 changes: 4 additions & 0 deletions Example_Systems/PiecewiseFuel_CO2_Example/Generators_data.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Resource,Zone,THERM,MUST_RUN,STOR,FLEX,HYDRO,VRE,LDS,Num_VRE_Bins,New_Build,Existing_Cap_MW,Existing_Cap_MWh,Existing_Charge_Cap_MW,Max_Cap_MW,Max_Cap_MWh,Max_Charge_Cap_MW,Min_Cap_MW,Inv_Cost_per_MWyr,Inv_Cost_per_MWhyr,Inv_Cost_Charge_per_MWyr,Fixed_OM_Cost_per_MWyr,Fixed_OM_Cost_per_MWhyr,Fixed_OM_Cost_Charge_per_MWyr,Var_OM_Cost_per_MWh,Var_OM_Cost_per_MWh_In,Heat_Rate_MMBTU_per_MWh,Fuel,Cap_Size,Start_Cost_per_MW,Start_Fuel_MMBTU_per_MW,Up_Time,Down_Time,Ramp_Up_Percentage,Ramp_Dn_Percentage,Min_Power,Eff_Up,Eff_Down,Resource_Type,region,cluster,PWFU_Fuel_Usage_Zero_Load_MMBTU_per_h,PWFU_Heat_Rate_MMBTU_per_MWh_1,PWFU_Heat_Rate_MMBTU_per_MWh_2,PWFU_Load_Point_MW_1,PWFU_Load_Point_MW_2,CO2_Capture_Fraction,CO2_Capture_Fraction_Startup,CCS_Disposal_Cost_per_Metric_Ton,Biomass
onshore_wind,1,0,0,0,0,0,1,0,1,0,15000,0,0,-1,-1,-1,0,0,0,0,0,0,0,0,0,0,None,100,0,0,0,0,1,1,0,1,1,onshore_wind_turbine,NE,1,0,0,0,0,0,0,0,0,0
natural_gas_combined_cycle_ccs,1,1,0,0,0,0,0,0,0,0,15000,0,0,-1,-1,-1,0,0,0,0,0,0,0,5,0,0,NG,250,91,2,6,6,0.64,0.64,0.468,1,1,natural_gas_fired_combined_cycle_ccs,NE,1,400,6,7.2,160,250,0.9,0.6,20,0
biomass_ccs,1,1,0,0,0,0,0,0,0,0,300,0,0,-1,-1,-1,0,0,0,0,0,0,0,10,0,10,Biomass,300,91,2,6,6,0.64,0.64,0.468,1,1,biomass_ccs,NE,1,0,0,0,0,0,0.9,0.6,20,1
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Time_Index,onshore_wind
1,0.889717042
2,0.877715468
3,0.903424203
4,0.895153165
5,0.757258117
6,0.630928695
7,0.557177782
8,0.6072492
9,0.423417866
10,0.007470775
11,0.002535942
12,0.002153709
13,0.00445132
14,0.007711587
15,0.100848213
16,0.201802149
17,0.141933054
18,0.567022562
19,0.946024895
20,0.923394203
21,0.953386247
22,0.929205418
23,0.849528909
24,0.665570974
Binary file not shown.
17 changes: 17 additions & 0 deletions Example_Systems/PiecewiseFuel_CO2_Example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# PiecewiseFuel_CO2

**PiecewiseFuel_CO2** is a 24 hr example and contains only one zone. It is condensed for easy and quick testing of CO2, biomass, and piecewise fuel usage related functions of the GenX. This testing
system only includes natural gas ccs, wind, and biomass with ccs, all set at a fixed initial
capacity, and does not allow for building additional capacity. For natural gas ccs generator, we provide picewise fuel usage (PWFU) parameters to represent the fuel consumption at differernt load point. Please refer to "PiecewiseFuelUsage_data_description.pptx" for a sylized visual representation of PWFU segments and corresponding data requirements. When UC >= 1 and PWFU parameters are provided in "Generator_data.csv", the standard heat rate (i.e., Heat_Rate_MMBTU_per_MWh) will not be used unless UC = 0.

To run the model, first navigate to the example directory at `GenX/Example_Systems/PiecewiseFuel_CO2`:

`cd("Example_Systems/PiecewiseFuel_CO2")`

Next, ensure that your settings in `GenX_settings.yml` are correct. The linear clustering unit commitment method (UC = 2) is used. The default settings use the solver HiGHS (`Solver: HiGHS`). A mass-based carbon cap of 0 t CO<sub>2</sub> (net-zero) is specified in the `CO2_cap.csv` input file.

Once the settings are confirmed, run the model with the `Run.jl` script in the example directory:

`include("Run.jl")`

Once the model has completed, results will write to the `Results` directory.
3 changes: 3 additions & 0 deletions Example_Systems/PiecewiseFuel_CO2_Example/Run.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
using GenX

run_genx_case!(dirname(@__FILE__))
101 changes: 101 additions & 0 deletions Example_Systems/PiecewiseFuel_CO2_Example/Settings/genx_settings.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
## Model settings
# --------------

# Number of segments used in piecewise linear approximation of transmission losses;
# 1 = linear
# >2 = piecewise quadratic
Trans_Loss_Segments: 1

# Unit committment of thermal power plants;
# 0 = not active
# 1 = active using integer clustering
# 2 = active using linearized clustering
UCommit: 2

## Policy settings
# ---------------

# Regulation (primary) and operating (secondary) reserves
# 0 = not active
# 1 = active systemwide
# Reserves: 0

# Minimum qualifying renewables penetration
# 0 = not active
# 1 = active systemwide
# EnergyShareRequirement: 0

# Number of capacity reserve margin constraints
# 0 = not active
# 1 = active systemwide
# CapacityReserveMargin: 0

# CO2 emissions cap
# 0 = not active (no CO2 emission limit)
# 1 = mass-based emission limit constraint
# 2 = demand + rate-based emission limit constraint
# 3 = generation + rate-based emission limit constraint
CO2Cap: 1

# Let lost energy be accounted for in Energy Share Requirement and CO2 constraints
# 0 = not active (DO NOT account for energy lost);
# 1 = active systemwide (DO account for energy lost)
# StorageLosses: 0

# Activate minimum technology carveout constraints
# 0 = not active
# 1 = active
# MinCapReq: 0

# Activate maximum technology limits
# 0 = not active
# 1 = active
# MaxCapReq: 0
#
# Transmission network expansion
# 0 = not active
# 1 = active systemwide
# NetworkExpansion: 1

# Hydrogen electrolyzer hourly supply matching required?
# 0 = constraint ot active
# 1 = constraint active for all electrolyzer resources
#HydrogenHourlyMatching: 0

## Solver settings
# ----------------

# Available solvers: Gurobi, CPLEX, Clps
#Solver: HiGHS

# Internally scale demand, capacity and power variables in GW rather than MW.
# 0 = not active
# 1 = active systemwide
ParameterScale: 1

# Time domain reduce (i.e. cluster) inputs based on demand, resource availability profiles, and fuel prices;
# 0 = not active (use input data as provided)
# 1 = active (cluster input data, or use data that has already been clustered)
#TimeDomainReduction: 0

# Directory where results from time domain reduction will be saved.
# If results already exist, these will be used without running time domain reduction script again.
#TimeDomainReductionFolder: "TDR_Results"

## Output settings
# ----------------

# Write shadow prices of LP or relaxed MILP
# 0 = not active
# 1 = active
WriteShadowPrices: 1

# Overwrite existing results in output folder or create a new one;
# 0 = create new folder
# 1 = overwrite existing results
# OverwriteResults: 0

# Write the model formulation as an output;
# 0 = active
# 1 = not active
# PrintModel: 0
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Gurobi Solver Parameters
# Common solver settings
Feasib_Tol: 1.0e-05 # Constraint (primal) feasibility tolerances.
Optimal_Tol: 1e-5 # Dual feasibility tolerances.
TimeLimit: 110000 # Limits total time solver.
Pre_Solve: 1 # Controls presolve level.
Method: 2 # Algorithm used to solve continuous models (including MIP root relaxation).

#Gurobi-specific solver settings
MIPGap: 1e-3 # Relative (p.u. of optimal) mixed integer optimality tolerance for MIP problems (ignored otherwise).
BarConvTol: 1.0e-08 # Barrier convergence tolerance (determines when barrier terminates).
NumericFocus: 0 # Numerical precision emphasis.
Crossover: 0 # Barrier crossver strategy.
PreDual: 0 # Decides whether presolve should pass the primal or dual linear programming problem to the LP optimization algorithm.
AggFill: 10 # Allowed fill during presolve aggregation.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# HiGHS Solver Parameters
# Common solver settings
Feasib_Tol: 1.0e-05 # Primal feasibility tolerance # [type: double, advanced: false, range: [1e-10, inf], default: 1e-07]
Optimal_Tol: 1.0e-05 # Dual feasibility tolerance # [type: double, advanced: false, range: [1e-10, inf], default: 1e-07]
TimeLimit: 1.0e23 # Time limit # [type: double, advanced: false, range: [0, inf], default: inf]
Pre_Solve: choose # Presolve option: "off", "choose" or "on" # [type: string, advanced: false, default: "choose"]
Method: choose #HiGHS-specific solver settings # Solver option: "simplex", "choose" or "ipm" # [type: string, advanced: false, default: "choose"]

#highs-specific solver settings

# run the crossover routine for ipx
# [type: string, advanced: "on", range: {"off", "on"}, default: "off"]
run_crossover: "off"
10 changes: 8 additions & 2 deletions docs/src/core.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,14 @@ Pages = ["transmission.jl"]
Modules = [GenX]
Pages = ["ucommit.jl"]
```
## Emissions
## CO2
```@autodocs
Modules = [GenX]
Pages = ["emissions.jl"]
Pages = ["co2.jl"]
```

## Fuel
```@autodocs
Modules = [GenX]
Pages = ["fuel.jl"]
```
13 changes: 13 additions & 0 deletions docs/src/data_documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -384,11 +384,24 @@ This file contains cost and performance parameters for various generators and ot
|MinCapTag\_*| Eligibility of resources to participate in Minimum Technology Carveout constraint. \* corresponds to the ith row of the file `Minimum_capacity_requirement.csv`. Note that this eligibility must be 0 for co-located VRE-STOR resources (policy inputs are read from the specific VRE-STOR dataframe).|
|**MaxCapReq = 1**|
|MaxCapTag\_*| Eligibility of resources to participate in Maximum Technology Carveout constraint. \* corresponds to the ith row of the file `Maximum_capacity_requirement.csv`. Note that this eligibility must be 0 for co-located VRE-STOR resources (policy inputs are read from the specific VRE-STOR dataframe).|
|**PiecewiseFuelUsage-related parameters required if any resources have nonzero PWFU fuel usage, heat rates, and load points**|
|PWFU\_Fuel\_Usage\_Zero\_Load\_MMBTU\_per\_h|The fuel usage (MMBTU/h) for the first PWFU segemnt (y-intercept) at zero load.|
|PWFU\_Heat\_Rate\_MMBTU\_per\_MWh\_*i| The slope of fuel usage function of the segment i.|
|PWFU\_Load\_Point\_MW\_*i| The end of segment i (MW).|
|**Electrolyzer related parameters required if the set ELECTROLYZER is not empty**|
|Hydrogen_MWh_Per_Tonne| Electrolyzer efficiency in megawatt-hours (MWh) of electricity per metric tonne of hydrogen produced (MWh/t)|
|Electrolyzer_Min_kt| Minimum annual quantity of hydrogen that must be produced by electrolyzer in kilotonnes (kt)|
|Hydrogen_Price_Per_Tonne| Price (or value) of hydrogen per metric tonne ($/t)|
|Qualified_Hydrogen_Supply| {0,1}, Indicates that generator or storage resources is eligible to supply electrolyzers in the same zone (used for hourly clean supply constraint)|
|**CO2-related parameters required if any resources have nonzero CO2_Capture_Fraction**|
|CO2\_Capture\_Fraction |[0,1], The CO2 capture fraction of CCS-equipped power plants during steady state operation. This value should be 0 for generators without CCS. |
|CO2\_Capture\_Fraction\_Startup |[0,1], The CO2 capture fraction of CCS-equipped power plants during the startup events. This value should be 0 for generators without CCS |
|Biomass | {0, 1}, Flag to indicate if generator uses biomass as feedstock (optional input column).|
||Biomass = 0: Not part of set (default). |
||Biomass = 1: Uses biomass as fuel.|
|CCS\_Disposal\_Cost\_per\_Metric_Ton | Cost associated with CCS disposal ($/tCO2), including pipeline, injection and storage costs of CCS-equipped generators.|



### 2.2 Optional inputs files

Expand Down
2 changes: 1 addition & 1 deletion src/configure_settings/configure_settings.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ function default_settings()
"MethodofMorris" => 0,
"IncludeLossesInESR" => 0,
"EnableJuMPStringNames" => false,
"HydrogenHourlyMatching" => 0,
"HydrogenHourlyMatching" => 0
)
end

Expand Down
8 changes: 4 additions & 4 deletions src/load_inputs/load_fuels_data.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
@doc raw"""
load_fuels_data!(setup::Dict, path::AbstractString, inputs::Dict)
load_fuels_data!(setup::Dict, path::AbstractString, inputs::Dict)
Read input parameters related to fuel costs and CO$_2$ content of fuels
"""
function load_fuels_data!(setup::Dict, path::AbstractString, inputs::Dict)
Expand Down Expand Up @@ -32,9 +31,10 @@ function load_fuels_data!(setup::Dict, path::AbstractString, inputs::Dict)
scale_factor = setup["ParameterScale"] == 1 ? ModelScalingFactor : 1

for i = 1:length(fuels)
# fuel cost is in $/MMBTU w/o scaling, $/Billon BTU w/ scaling
fuel_costs[fuels[i]] = costs[:,i] / scale_factor
# fuel_CO2 is kton/MMBTU with scaling, or ton/MMBTU without scaling.
fuel_CO2[fuels[i]] = CO2_content[i] / scale_factor
# No need to scale fuel_CO2, fuel_CO2 is ton/MMBTU or kton/Billion BTU
fuel_CO2[fuels[i]] = CO2_content[i]
end

inputs["fuels"] = fuels
Expand Down
Loading

0 comments on commit c1ac911

Please sign in to comment.