diff --git a/Project.toml b/Project.toml index 2bc710952..a6d2b1048 100644 --- a/Project.toml +++ b/Project.toml @@ -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.1-dev.15" +version = "0.4.1-dev.16" [deps] CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" diff --git a/docs/src/Tutorials/Tutorial_8_outputs.md b/docs/src/Tutorials/Tutorial_8_outputs.md index b344c3aab..e6b9f130f 100644 --- a/docs/src/Tutorials/Tutorial_8_outputs.md +++ b/docs/src/Tutorials/Tutorial_8_outputs.md @@ -28,7 +28,6 @@ using StatsPlots case = joinpath("example_systems/1_three_zones"); ``` - ```julia include("example_systems/1_three_zones/Run.jl") ``` @@ -40,15 +39,12 @@ include("example_systems/1_three_zones/Run.jl") Demand (load) data Successfully Read! Fuels_data.csv Successfully Read! - Thermal.csv Successfully Read. Vre.csv Successfully Read. Storage.csv Successfully Read. Resource_energy_share_requirement.csv Successfully Read. Resource_capacity_reserve_margin.csv Successfully Read. Resource_minimum_capacity_requirement.csv Successfully Read. - - Summary of resources loaded into the model: ------------------------------------------------------- @@ -89,8 +85,7 @@ include("example_systems/1_three_zones/Run.jl") CSV Files Successfully Read In From /Users/mayamutic/Desktop/GenX-Tutorials/Tutorials/example_systems/1_three_zones Generating the Optimization Model - - Thermal.csv Successfully Read. + Thermal.csv Successfully Read. Vre.csv Successfully Read. Storage.csv Successfully Read. Resource_energy_share_requirement.csv Successfully Read. @@ -115,6 +110,7 @@ include("example_systems/1_three_zones/Run.jl") Minimum Capacity Requirement Module Time elapsed for model building is 5.887781667 + Solving Model Running HiGHS 1.6.0: Copyright (c) 2023 HiGHS under MIT licence terms Presolving model @@ -251,6 +247,7 @@ include("example_systems/1_three_zones/Run.jl") Objective value : 9.4121364078e+03 HiGHS run time : 107.89 LP solved for primal + Writing Output Time elapsed for writing costs is 0.8427745 @@ -312,17 +309,12 @@ include("example_systems/1_three_zones/Run.jl") Time elapsed for writing is 6.909353542 - Below are all 33 files output by running GenX: - ```julia results = cd(readdir,joinpath(case,"results")) ``` - - - 33-element Vector{String}: "CO2_prices_and_penalties.csv" "ChargingCost.csv" @@ -351,17 +343,15 @@ results = cd(readdir,joinpath(case,"results")) "time_weights.csv" "tlosses.csv" - - ### Power -The file `power.csv`, shown below, outputs the power in MW discharged by each node at each time step. Note that if TimeDomainReduction is in use the file will be shorter. The first row states which zone each node is part of, and the total power per year is located in the second row. After that, each row represents one time step of the series. - +The file `power.csv`, shown below, contains the power output in MW discharged by each node at each time step. Note that if `TimeDomainReduction` is enabled, the file will have fewer rows compared to the number of time steps in the `system/Demand_data.csv` file. In this case, the corresponding `Demand_data.csv` file that matches the time series in `power.csv` can be found in the `TDR_results` folder. The first row of `power.csv` indicates the zone each node belongs to, while the second row contains the total power per year. Each subsequent row represents one time step in the series. ```julia power = CSV.read(joinpath(case,"results/power.csv"),DataFrame,missingstring="NA") ``` -``` @raw html + +```@raw html
1850×12 DataFrame
1825 rows omitted
RowResourceMA_natural_gas_combined_cycleCT_natural_gas_combined_cycleME_natural_gas_combined_cycleMA_solar_pvCT_onshore_windCT_solar_pvME_onshore_windMA_batteryCT_batteryME_batteryTotal
String15Float64Float64Float64Float64Float64Float64Float64Float64Float64Float64Float64
1Zone1.02.03.01.02.02.03.01.02.03.00.0
2AnnualSum1.04015e73.42459e68.94975e52.47213e72.90683e72.69884e72.625e75.06354e61.45833e74.90368e61.463e8
3t1-0.0-0.0-0.0-0.08510.78-0.05300.610.02537.45673.3417022.2
4t2-0.0-0.0-0.0-0.08420.78-0.06282.040.02537.450.017240.3
5t3-0.0-0.0-0.0-0.08367.78-0.02409.840.02537.451828.2415143.3
6t4-0.0-0.0-0.0-0.08353.78-0.02762.241591.462537.450.015244.9
7t5-0.0-0.0-0.0-0.07482.39-0.00.01617.462980.641384.6213465.1
8t6-0.0-0.0-0.0-0.02429.93-0.02797.241717.965535.370.012480.5
9t7-0.0-0.0-0.0-0.011868.8-0.01374.731320.78871.4431340.6716776.4
10t8-0.0-0.0-0.0-0.02656.93-0.00.02115.965535.371452.6211760.9
11t9-0.0-0.0-0.03061.280.03110.82982.24868.8175389.440.015412.6
12t10-0.0-0.0-0.06100.227597.995543.690.00.00.01521.1220763.0
13t11-0.0-0.0-0.08314.290.06341.983080.240.02458.820.020195.3
1839t1837-0.0-0.0-0.06712.182541.66736.37305.6081410.33763.7261427.8219897.6
1840t1838-0.0-0.0-0.06514.150.06847.243153.240.03464.220.019978.9
1841t1839-0.0-0.0-0.05582.073848.886280.20.0195.4222048.31571.1219526.0
1842t1840-0.0-0.0-0.03688.139349.984892.73490.611006.020.00.022427.4
1843t1841-0.0-0.0-0.0509.228124.991351.083653.061218.52507.81828.2419192.9
1844t1842-0.0-0.0-0.0-0.02918.2-0.06896.822194.615535.37256.86317801.9
1845t1843-0.0-0.0-0.0-0.06800.37-0.07324.661838.113950.1541.947219955.2
1846t1844-0.0-0.0-0.0-0.09505.82-0.05683.661744.782567.93838.07720340.3
1847t1845-0.0-0.0-0.0-0.03491.93-0.05128.561597.615535.371107.4916861.0
1848t1846-0.0-0.0-0.0-0.012135.6-0.05021.751341.111140.561125.920764.9
1849t1847-0.0-0.0-0.0-0.08875.71-0.03605.98974.612665.481783.7917905.6
1850t1848-0.0-0.0-0.0-0.013549.1-0.04098.0541.61205.311478.2719872.3
``` @@ -386,11 +376,16 @@ for i in range(2,4) power_plot = [power_plot; power_plot_temp] end -demands = CSV.read(joinpath(case,"system/Demand_data.csv"),DataFrame,missingstring="NA") +demands = CSV.read(joinpath(case,"TDR_results/Demand_data.csv"),DataFrame,missingstring="NA") demands_tot = demands[!,"Demand_MW_z1"]+demands[!,"Demand_MW_z2"]+demands[!,"Demand_MW_z3"] power_plot[!,"Demand_Total"] = repeat(demands_tot[tstart:tend],4); ``` +Note that since the `power.csv` file is generated by running GenX with `TimeDomainReduction: 1`, the demands time series must be taken from the `Demand_data.csv` file located in the `TDR_results` folder. + +GenX also has the ability to output the reconstructed version of power generation by setting `OutputFullTimeSeries: 1` in `genx_settings.yml`. In this case, a second version of the `power.csv` file will be created inside the `results/Full_TimeSeries` folder. To plot the reconstructed version against the demand, ensure you use the `Demand_data.csv` from the `settings` folder, not the one in the `TDR_results` folder. + +Finally, if `TimeDomainReduction: 0` is set, the `power.csv` file will contain the full time series of power generation, and the `Demand_data.csv` should be taken from the `settings` folder. ```julia power_plot |> @@ -402,11 +397,9 @@ power_plot |> ``` ![svg](./files/t8_cap.svg) - We can separate it by zone in the following plot: - ```julia Zone1 = [power[2,2] power[2,5] 0 power[2,9]] Zone2 = [power[2,3] power[2,7] power[2,6] power[2,10]] @@ -448,7 +441,6 @@ end ``` - ```julia Plots.heatmap(heat,yticks=0:4:24,xticks=([15:30:364;], ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sept","Oct","Nov","Dec"]), @@ -458,7 +450,6 @@ Plots.heatmap(heat,yticks=0:4:24,xticks=([15:30:364;], ![svg](./files/t8_heatmap.svg) - ### Cost and Revenue The basic cost of each power plant and the revenue it generates can be found in files `costs.csv`, `NetRevenue.csv`,and `EnergyRevenue.csv`. `NetRevenue.csv` breaks down each specific cost per node in each zone, which is useful to visualize what the cost is coming from. @@ -468,14 +459,10 @@ The basic cost of each power plant and the revenue it generates can be found in netrevenue = CSV.read(joinpath(case,"results/NetRevenue.csv"),DataFrame,missingstring="NA") ``` - - ``` @raw html
10×28 DataFrame
RowregionResourcezoneClusterR_IDInv_cost_MWInv_cost_MWhInv_cost_charge_MWFixed_OM_cost_MWFixed_OM_cost_MWhFixed_OM_cost_charge_MWVar_OM_cost_outFuel_costVar_OM_cost_inStartCostCharge_costCO2SequestrationCostEnergyRevenueSubsidyRevenueOperatingReserveRevenueOperatingRegulationRevenueReserveMarginRevenueESRRevenueEmissionsCostRegSubsidyRevenueRevenueCostProfit
String3String31Int64Int64Int64Float64Float64Float64Float64Float64Float64Float64Float64Float64Float64Float64Float64Float64Float64Float64Float64Float64Float64Float64Float64Float64Float64Float64
1MAMA_natural_gas_combined_cycle1115.54734e80.00.08.72561e70.00.03.69253e72.10416e80.03.84832e70.00.02.77103e90.00.00.00.00.01.84321e90.02.77103e92.77103e91.43051e-6
2CTCT_natural_gas_combined_cycle2121.42906e80.00.02.11911e70.00.01.22258e74.97792e70.07.75292e60.00.08.4423e80.00.00.00.00.06.10375e80.08.4423e88.4423e81.19209e-7
3MEME_natural_gas_combined_cycle3133.52336e70.00.08.77661e60.00.04.02739e62.26505e70.03.33663e60.00.02.19267e80.00.00.00.00.01.45243e80.02.19267e82.19267e80.0
4MAMA_solar_pv1141.27007e90.00.02.79327e80.00.00.00.00.00.00.00.01.5494e90.00.00.00.00.00.00.01.5494e91.5494e9-2.86102e-6
5CTCT_onshore_wind2151.40748e90.00.06.25617e80.00.02.90683e60.00.00.00.00.02.036e90.00.00.00.00.00.00.02.036e92.036e9-5.00679e-6
6CTCT_solar_pv2161.35108e90.00.02.97142e80.00.00.00.00.00.00.00.01.64822e90.00.00.00.00.00.00.01.64822e91.64822e99.53674e-7
7MEME_onshore_wind3171.03673e90.00.04.60821e80.00.02.625e60.00.00.00.00.01.50017e90.00.00.00.00.00.00.01.50017e91.50017e92.38419e-6
8MAMA_battery1084.29792e72.23673e80.01.07426e75.59033e70.07.59532e50.08.97367e50.01.3432e80.04.48833e80.00.00.00.00.00.00.04.48833e84.69275e8-2.0442e7
9CTCT_battery2091.08405e85.73615e80.02.70957e71.43365e80.02.1875e60.02.58447e60.05.24177e80.01.31941e90.00.00.00.00.00.00.01.31941e91.38143e9-6.20165e7
10MEME_battery30103.58043e71.03994e80.08.94925e62.59915e70.07.35552e50.08.69036e50.03.81057e70.02.03732e80.00.00.00.00.00.00.02.03732e82.14449e8-1.0717e7
``` - - ```julia xnames = netrevenue[!,2] names1 = ["Investment cost" "Fixed OM cost" "Variable OM cost" "Fuel cost" "Start Cost" "Battery charge cost" "CO2 Sequestration Cost" "Revenue"] @@ -491,8 +478,6 @@ StatsPlots.scatter!(xnames,netrevenue[!,"Revenue"],label="Revenue",color="black" ![svg](./files/t8_cost.svg) - - ### Emissions The file `emmissions.csv` gives the total CO2 emmissions per zone for each hour GenX runs. The first three rows give the marginal CO2 abatement cost in $/ton CO2. @@ -502,14 +487,10 @@ The file `emmissions.csv` gives the total CO2 emmissions per zone for each hour emm1 = CSV.read(joinpath(case,"results/emissions.csv"),DataFrame) ``` - - ``` @raw html
1852×5 DataFrame
1827 rows omitted
RowZone123Total
String15Float64Float64Float64Float64
1CO2_Price_1444.9210.00.00.0
2CO2_Price_20.0468.6680.00.0
3CO2_Price_30.00.0240.860.0
4AnnualSum4.14279e61.30236e66.03017e56.04816e6
5t10.00.00.00.0
6t20.00.00.00.0
7t30.00.00.00.0
8t40.00.00.00.0
9t50.00.00.00.0
10t60.00.00.00.0
11t70.00.00.00.0
12t80.00.00.00.0
13t90.00.00.00.0
1841t18370.00.00.00.0
1842t18380.00.00.00.0
1843t18390.00.00.00.0
1844t18400.00.00.00.0
1845t18410.00.00.00.0
1846t18420.00.00.00.0
1847t18430.00.00.00.0
1848t18440.00.00.00.0
1849t18450.00.00.00.0
1850t18460.00.00.00.0
1851t18470.00.00.00.0
1852t18480.00.00.00.0
``` - - ```julia # Pre-processing tstart = 470 @@ -519,7 +500,6 @@ names_emm = ["Zone 1","Zone 2","Zone 3"] emm_tot = DataFrame([emm1[3:end,2] emm1[3:end,3] emm1[3:end,4]], ["Zone 1","Zone 2","Zone 3"]) - emm_plot = DataFrame([collect((tstart-3):(tend-3)) emm_tot[tstart:tend,1] repeat([names_emm[1]],(tend-tstart+1))], ["Hour","MW","Zone"]); @@ -530,7 +510,6 @@ end ``` - ```julia emm_plot |> @vlplot(mark={:line}, @@ -541,11 +520,8 @@ emm_plot |> ![svg](./files/t8_emm1.svg) - - Let's try changing the CO2 cap, as in Tutorial 7, and plotting the resulting emmissions. - ```julia genx_settings_TZ = YAML.load(open((joinpath(case,"settings/genx_settings.yml")))) genx_settings_TZ["CO2Cap"] = 0 @@ -555,7 +531,6 @@ include("example_systems/1_three_zones/Run.jl") # run outside of notebook ``` - Configuring Settings Time Series Data Already Clustered. Configuring Solver @@ -576,15 +551,12 @@ include("example_systems/1_three_zones/Run.jl") Total number of resources: 10 ------------------------------------------------------- - Thermal.csv Successfully Read. Vre.csv Successfully Read. Storage.csv Successfully Read. Resource_energy_share_requirement.csv Successfully Read. Resource_capacity_reserve_margin.csv Successfully Read. Resource_minimum_capacity_requirement.csv Successfully Read. - - Generators_variability.csv Successfully Read! Validating time basis Minimum_capacity_requirement.csv Successfully Read! @@ -607,6 +579,7 @@ include("example_systems/1_three_zones/Run.jl") Minimum Capacity Requirement Module Time elapsed for model building is 0.531860834 + Solving Model Running HiGHS 1.6.0: Copyright (c) 2023 HiGHS under MIT licence terms Presolving model @@ -740,6 +713,7 @@ include("example_systems/1_three_zones/Run.jl") Objective value : 5.5855435982e+03 HiGHS run time : 66.51 LP solved for primal + Writing Output Time elapsed for writing costs is 0.099885792 @@ -799,20 +773,13 @@ include("example_systems/1_three_zones/Run.jl") Time elapsed for writing is 0.530491792 - - ```julia emm2 = CSV.read(joinpath(case,"results_1/emissions.csv"),DataFrame) ``` - - ``` @raw html
1849×5 DataFrame
1824 rows omitted
RowZone123Total
String15Float64Float64Float64Float64
1AnnualSum1.68155e71.41088e74310.213.09286e7
2t1997.1690.00.0997.169
3t2997.1690.00.0997.169
4t3997.1690.00.0997.169
5t4997.1690.00.0997.169
6t5997.1690.00.0997.169
7t6997.1690.00.0997.169
8t7997.1690.00.0997.169
9t8997.1690.00.0997.169
10t9997.1690.00.0997.169
11t101471.460.00.01471.46
12t11997.1690.00.0997.169
13t121115.810.00.01115.81
1838t18372789.351012.990.03802.34
1839t18382835.211012.990.03848.2
1840t18392520.571012.990.03533.56
1841t18401496.47445.850.01942.32
1842t18412571.261012.990.03584.25
1843t18422835.211012.990.03848.2
1844t18432835.211012.990.03848.2
1845t18442625.42960.1840.03585.6
1846t18452506.32342.3910.02848.71
1847t18462277.59342.3910.02619.98
1848t18471960.08524.5260.02484.6
1849t18481566.77342.3910.01909.16
``` - - - ```julia # Pre-processing tstart = 470 @@ -822,7 +789,6 @@ names_emm = ["Zone 1","Zone 2","Zone 3"] emm_tot2 = DataFrame([emm2[3:end,2] emm2[3:end,3] emm2[3:end,4]], ["Zone 1","Zone 2","Zone 3"]) - emm_plot2 = DataFrame([collect((tstart-3):(tend-3)) emm_tot2[tstart:tend,1] repeat([names_emm[1]],(tend-tstart+1))], ["Hour","MW","Zone"]); @@ -858,12 +824,9 @@ Plots.plot(collect((tstart-3):(tend-3)),emm1sum[tstart:tend],size=(800,400),labe Plots.plot!(collect((tstart-3):(tend-3)),emm2sum[tstart:tend],label="No CO2 Cap",linewidth = 1.5) ``` ![svg](./files/t8_emm_comp.svg) - - Finally, set the CO2 Cap back to 2: - ```julia genx_settings_TZ["CO2Cap"] = 2 YAML.write_file((joinpath(case,"settings/genx_settings.yml")), genx_settings_TZ) diff --git a/docs/src/Tutorials/files/t8_cap.svg b/docs/src/Tutorials/files/t8_cap.svg index c40ef607c..a8747901c 100644 --- a/docs/src/Tutorials/files/t8_cap.svg +++ b/docs/src/Tutorials/files/t8_cap.svg @@ -1 +1 @@ -1224364860728496108120132144156168Time Step (hours)02,0004,0006,0008,00010,00012,00014,00016,00018,00020,00022,00024,00026,000Demand (MW)WindSolarNatural_GasBatteryDemandResource_TypeResource Capacity per Hour with Demand Curve, all Zones \ No newline at end of file +1224364860728496108120132144156168Time Step (hours)02,0004,0006,0008,00010,00012,00014,00016,00018,00020,00022,00024,00026,000Load (MW)WindSolarNatural_GasBatteryDemandResource_TypeResource Capacity per Hour with Load Demand Curve, all Zones \ No newline at end of file