diff --git a/docs/make.jl b/docs/make.jl index c4167f2175..a3ab4aedf4 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -17,10 +17,10 @@ pages = OrderedDict( "Commertial solvers" => "Getting_Started/commercial_solvers.md", ], "Tutorials" => [ - "Tutorials Overview" => "Tutorials/tutorials_intro.md", + "Tutorials Overview" => "Tutorials/Tutorials_intro.md", "Tutorial 1: Configuring Settings" => "Tutorials/Tutorial_1_configuring_settings.md", "Tutorial 2: Network Visualization" => "Tutorials/Tutorial_2_network_visualization.md", - "Tutorial 3: K-Means and Time Domain Reduction" => "Tutorials/tutorial_3/Tutorial_3_K-means_time_domain_reduction.md", + "Tutorial 3: K-Means and Time Domain Reduction" => "Tutorials/Tutorial_3_K-means_time_domain_reduction.md", "Tutorial 4: Model Generation" => "Tutorials/Tutorial_4_model_generation.md", "Tutorial 5: Solving the Model" => "Tutorials/Tutorial_5_solve_model.md", "Tutorial 6: Post Processing" => "Tutorials/Tutorial_6_solver_settings.md", diff --git a/docs/src/Tutorials/Tutorial_1_configuring_settings.md b/docs/src/Tutorials/Tutorial_1_configuring_settings.md index 80e8b19bf4..4267a92308 100644 --- a/docs/src/Tutorials/Tutorial_1_configuring_settings.md +++ b/docs/src/Tutorials/Tutorial_1_configuring_settings.md @@ -34,9 +34,7 @@ using YAML genx_settings_SNE = YAML.load(open("example_systems/1_three_zones/settings/genx_settings.yml")) ``` - - - +``` Dict{Any, Any} with 19 entries: "NetworkExpansion" => 1 "ModelingToGenerateAlternativeIterations" => 3 @@ -57,7 +55,7 @@ genx_settings_SNE = YAML.load(open("example_systems/1_three_zones/settings/genx_ "MinCapReq" => 1 "CO2Cap" => 2 "WriteShadowPrices" => 1 - +``` Since all settings have defaults, you only need to specify the settings you would like to change. In fact, you can leave your settings file completely blank and it will still run! Let's try editing `genx_settings` in `SmallNewEngland/OneZone` to contain no parameters: @@ -81,6 +79,7 @@ Now, we run GenX and output the file `capacity.csv` from the `Results` folder. T include("example_systems/1_three_zones/Run.jl") ``` +``` Configuring Settings Configuring Solver Loading Inputs @@ -90,13 +89,11 @@ include("example_systems/1_three_zones/Run.jl") Fuels_data.csv Successfully Read! - [ Info: Thermal.csv Successfully Read. - [ Info: Vre.csv Successfully Read. - [ Info: Storage.csv Successfully Read. - [ Info: Resource_minimum_capacity_requirement.csv Successfully Read. - + [ Info: Thermal.csv Successfully Read. + [ Info: Vre.csv Successfully Read. + [ Info: Storage.csv Successfully Read. + [ Info: Resource_minimum_capacity_requirement.csv Successfully Read. - Summary of resources loaded into the model: ------------------------------------------------------- Resource type Number of resources @@ -124,7 +121,7 @@ include("example_systems/1_three_zones/Run.jl") Storage Core Resources Module Storage Resources with Symmetric Charge/Discharge Capacity Module Thermal (No Unit Commitment) Resources Module - +``` ```julia diff --git a/docs/src/Tutorials/tutorial_3/Tutorial_3_K-means_time_domain_reduction.md b/docs/src/Tutorials/Tutorial_3_K-means_time_domain_reduction.md similarity index 98% rename from docs/src/Tutorials/tutorial_3/Tutorial_3_K-means_time_domain_reduction.md rename to docs/src/Tutorials/Tutorial_3_K-means_time_domain_reduction.md index 849188bfc8..b742a0e244 100644 --- a/docs/src/Tutorials/tutorial_3/Tutorial_3_K-means_time_domain_reduction.md +++ b/docs/src/Tutorials/Tutorial_3_K-means_time_domain_reduction.md @@ -13,7 +13,7 @@ A good tool to reduce computation time of GenX is to use [Time Domain Reduction * [Extreme Periods](#ExtPeriods) * [Objective Values and Representative Periods](#ObjVals) -### Time Domain Reduction +### Time Domain Reduction To see how Time Domain Reduction works, let's look at the `Doad_data` in `example_systems/1_three_zones`: @@ -55,6 +55,7 @@ When TDR is used, the file `time_domain_reduction_settings.yml` is called with a ```julia time_domain_reduction_settings = YAML.load(open(joinpath(case,"settings/time_domain_reduction_settings.yml"))) +``` ``` Dict{Any, Any} with 15 entries: "IterativelyAddPeriods" => 1 @@ -72,6 +73,7 @@ time_domain_reduction_settings = YAML.load(open(joinpath(case,"settings/time_dom "ScalingMethod" => "S" "ClusterMethod" => "kmeans" "WeightTotal" => 8760 +``` Important here to note are `MinPeriods` and `MaxPeriods`. As TDR is performed, it is required to keep the number of representative periods to be between the min and max specified in the settings. This is to ensure that computation time is actually decreased and that the k-means algorithm doesn't just form one large cluster of all points. Additionally, `TimestepsPerRepPeriod` is set to 168, the number of hours in a week (`WeightTotal` includes all 8,760 timesteps, the number of hours in a year.) By specifying the number of timesteps in each representative period to be a week, we form 52 clusters from which the algorithm will choose 8-11. @@ -79,7 +81,6 @@ For descriptions of all settings, see [`cluster_inputs`](@ref) in the documentat Now back to pre-TDR. Below shows the load per timestep in megawatts for the entire dataset, i.e. with only one representative period of 8760 hours. This is done for Zone 1: - ```julia loads |> @vlplot(:line, @@ -87,12 +88,13 @@ loads |> width=600,height=400,linewidth=.01) ``` -![svg](output_14_0.svg) +![svg](./files/output_14_0.svg) -As in Tutorial 1, we can open the `genx_settings.yml` file for `1_three_zones` to see how `TimeDomainReduction` is set. If it's set to 1, this means TDR is being used. +As in [Tutorial 1: Configuring Settings](@ref), we can open the `genx_settings.yml` file for `1_three_zones` to see how `TimeDomainReduction` is set. If it's set to 1, this means TDR is being used. ```julia genx_settings_TZ = YAML.load(open((joinpath(case,"settings/genx_settings.yml")))) +``` ``` Dict{Any, Any} with 19 entries: "NetworkExpansion" => 1 @@ -114,7 +116,7 @@ genx_settings_TZ = YAML.load(open((joinpath(case,"settings/genx_settings.yml"))) "MinCapReq" => 1 "CO2Cap" => 2 "WriteShadowPrices" => 1 - +``` To visualize how TDR decreases computation time, let's start by running `SmallNewEngland/OneZone` without TDR. In the third section of this tutorial, we'll run the example again using TDR. @@ -461,9 +463,9 @@ recon_noex[!,:MW] = convert.(Float64,recon_noex[!,:MW]); ### Objective Values and Representative Periods -Each time `Run.jl` is run, a `Results` folder is produced. This folder contains numerous .csv files with output variable from the GenX model. For more information on all outputs, see the documentation here. +Each time `Run.jl` is run, a `Results` folder is produced. This folder contains numerous .csv files with output variable from the GenX model. For more information on all outputs, see the documentation [here](https://genxproject.github.io/GenX/dev/data_documentation/#Outputs). -This section focuses on the __objective value__ of the model. In optimization problems, the objective value is the main value minimized or maximized within the constraints of the model, according to the __objective function__ specified in the problem formulation. In the case of GenX, the objective function is the total annual electricity system cost. A detailed description of the optimization problem is here in the documentation. +This section focuses on the __objective value__ of the model. In optimization problems, the objective value is the main value minimized or maximized within the constraints of the model, according to the __objective function__ specified in the problem formulation. In the case of GenX, the objective function is the total annual electricity system cost. A detailed description of the optimization problem is [here](https://genxproject.github.io/GenX/dev/objective_function/) in the documentation. For the purpose of this tutorial, we focus on the objective value as a way to evaluate how well the representative periods actually "represent" the entire model. To see how well the objective value of representative periods aligns with that of the total period, we can run `SmallNewEngland/OneZone` with a variety of minimum and maximum total periods. diff --git a/docs/src/Tutorials/Tutorial_4_model_generation.md b/docs/src/Tutorials/Tutorial_4_model_generation.md index 3f57c6fc3e..e9af453d39 100644 --- a/docs/src/Tutorials/Tutorial_4_model_generation.md +++ b/docs/src/Tutorials/Tutorial_4_model_generation.md @@ -160,7 +160,7 @@ Setup includes the settings from `genx_settings.yml` along with the default sett genx_settings = GenX.get_settings_path(case, "genx_settings.yml") # Settings YAML file path setup = GenX.configure_settings(genx_settings) # Combines genx_settings with defaults not specified in the file ``` - +``` Configuring Settings Dict{Any, Any} with 24 entries: "NetworkExpansion" => 0 @@ -187,7 +187,7 @@ setup = GenX.configure_settings(genx_settings) # Combines genx_settings with def "StorageLosses" => 1 "IncludeLossesInESR" => 0 "UCommit" => 2 - +``` It's here that we create the folder `TDR_Results` before generating the model. This occurs if TimeDomainReduction is set to 1 in the setup. @@ -205,7 +205,7 @@ if setup["TimeDomainReduction"] == 1 end end ``` - +``` Clustering Time Series Data (Grouped)... Reading Input CSV Files Network.csv Successfully Read! @@ -223,15 +223,15 @@ end Dict{String, Any} with 9 entries: "RMSE" => Dict("Load_MW_z1"=>1100.54, "NG"=>0.312319, "onshore_wind_… - "OutputDF" => 1848×9 DataFrame… + "OutputDF" => DataFrame… "ColToZoneMap" => Dict("Load_MW_z1"=>1, "battery_z1"=>1, "natural_gas_combin… "ClusterObject" => KmeansResult{Matrix{Float64}, Float64, Int64}([-1.38728 -1… "TDRsetup" => Dict{Any, Any}("IterativelyAddPeriods"=>1, "ExtremePeriods… "Assignments" => [1, 1, 1, 1, 2, 2, 2, 2, 2, 3 … 6, 4, 3, 5, 5, 9, 10, 10… - "InputDF" => 672×49 DataFrame… + "InputDF" => [672×49 DataFrame "Weights" => [673.846, 1010.77, 673.846, 842.308, 842.308, 1853.08, 185… "Centers" => Any[1, 7, 12, 15, 23, 24, 28, 29, 48, 50, 51] - +``` The optimizer argument is taken from setup: @@ -256,7 +256,7 @@ The "inputs" argument is generated by the function `load_inputs` from the case i ```julia inputs = GenX.load_inputs(setup, case) ``` - +``` Reading Input CSV Files Network.csv Successfully Read! Load_data.csv Successfully Read! @@ -276,7 +276,7 @@ inputs = GenX.load_inputs(setup, case) "LOSS_LINES" => [1] "RET_CAP_CHARGE" => Int64[] "pC_D_Curtail" => [50.0] - "dfGen" => 4×68 DataFrame… + "dfGen" => [4×68 DataFram "pTrans_Max_Possible" => [2.95] "pNet_Map" => [1.0;;] "omega" => [4.01099, 4.01099, 4.01099, 4.01099, 4.01099, 4.0109… @@ -298,7 +298,7 @@ inputs = GenX.load_inputs(setup, case) "TRANS_LOSS_SEGS" => 1 "H" => 168 ⋮ => ⋮ - +``` Now that we have our arguments, we're ready to generate the model itself. @@ -343,10 +343,10 @@ Next, the dummy variable vZERO, the objective function, the power balance expres # Initialize Total Generation per Zone @expression(EP, eGenerationByZone[z=1:Z, t=1:T], 0) ``` - +``` 1×1848 Matrix{Int64}: 0 0 0 0 0 0 0 0 0 0 0 0 0 … 0 0 0 0 0 0 0 0 0 0 0 0 - +``` Next, we go through some of the settings in setup and, if they've been set to be utilized (i.e. have a nonzero value), define expressions from their corresponding input files: @@ -366,16 +366,17 @@ end if setup["MaxCapReq"] == 1 @expression(EP, eMaxCapRes[maxcap = 1:inputs["NumberOfMaxCapReqs"]], 0) end +``` ``` 3-element Vector{Int64}: 0 0 0 - +``` The other settings will be used later on. -Next, we define the model infrastructure using functions found in `src/core`. These take entries from inputs and setup to create more expressions in our model (EP). To see what the functions do in more detail, see the source code and core documentation. +Next, we define the model infrastructure using functions found in `src/core`. These take entries from inputs and setup to create more expressions in our model (EP). To see what the functions do in more detail, see the source code and [core documentation](https://genxproject.github.io/GenX/dev/core/#Discharge). ```julia @@ -400,13 +401,13 @@ if Z > 1 GenX.transmission!(EP, inputs, setup) end ``` - +``` Discharge Module Non-served Energy Module Investment Discharge Module Unit Commitment Module Emissions Module (for CO2 Policy modularization - +``` We then define variables and expressions based on the resources in the inputs and setup arguments. The details of these can be found in the `src/resources` folder and the "resources" folder under Model Function Reference in the documentation: @@ -456,7 +457,7 @@ end ``` -Finally, we define expressions and variables using policies outlined in the inputs. These functions can be found in `src/policies` and in the policies documentation: +Finally, we define expressions and variables using policies outlined in the inputs. These functions can be found in `src/policies` and in the [policies documentation](https://genxproject.github.io/GenX/dev/policies/): ```julia @@ -490,7 +491,7 @@ if setup["MaxCapReq"] == 1 end ``` - +``` Energy Share Requirement Policies Module Capacity Reserve Margin Policies Module Minimum Capacity Requirement Module @@ -501,7 +502,7 @@ end cZoneMaxCapReq[2] : -vRETCAP[3] + vCAP[3] ≤ 100 cZoneMaxCapReq[3] : -vRETCAP[4] + vCAP[4] ≤ 60 - +``` The expressions and variables for the model have all been defined! All that's left to do is define the constraints and objective function. @@ -526,7 +527,7 @@ Our constraint is the [Power Balance](@ref), which is set here to have to meet t @constraint(EP, cPowerBalance[t=1:T, z=1:Z], EP[:ePowerBalance][t,z] == inputs["pD"][t,z]) ``` - +``` 1848×1 Matrix{ConstraintRef{Model, MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}, ScalarShape}}: cPowerBalance[1,1] : vP[2,1] + vP[3,1] + vP[4,1] + vNSE[1,1,1] - vCHARGE[4,1] = 11.162 cPowerBalance[2,1] : vP[2,2] + vP[3,2] + vP[4,2] + vNSE[1,2,1] - vCHARGE[4,2] = 10.556 @@ -554,7 +555,7 @@ Our constraint is the [Power Balance](@ref), which is set here to have to meet t cPowerBalance[1846,1] : vP[2,1846] + vP[3,1846] + vP[4,1846] + vNSE[1,1846,1] - vCHARGE[4,1846] = 14.663 cPowerBalance[1847,1] : vP[2,1847] + vP[3,1847] + vP[4,1847] + vNSE[1,1847,1] - vCHARGE[4,1847] = 13.62 cPowerBalance[1848,1] : vP[2,1848] + vP[3,1848] + vP[4,1848] + vNSE[1,1848,1] - vCHARGE[4,1848] = 12.388 - +``` After this final constraint is defined, `generate_model` finishes compiling the EP, and `run_genx_simple` (or multistage) uses `solve_model` to solve the EP. This will be described in Tutorial 5. diff --git a/docs/src/Tutorials/tutorials_intro.md b/docs/src/Tutorials/Tutorials_intro.md similarity index 100% rename from docs/src/Tutorials/tutorials_intro.md rename to docs/src/Tutorials/Tutorials_intro.md diff --git a/docs/src/Tutorials/files/Julia.png b/docs/src/Tutorials/files/Julia.png deleted file mode 100644 index 99e459c126..0000000000 Binary files a/docs/src/Tutorials/files/Julia.png and /dev/null differ diff --git a/docs/src/Tutorials/files/addGenX.png b/docs/src/Tutorials/files/addGenX.png deleted file mode 100644 index 7ebb796576..0000000000 Binary files a/docs/src/Tutorials/files/addGenX.png and /dev/null differ diff --git a/docs/src/Tutorials/files/addIJulia.png b/docs/src/Tutorials/files/addIJulia.png deleted file mode 100644 index 65864a38d6..0000000000 Binary files a/docs/src/Tutorials/files/addIJulia.png and /dev/null differ diff --git a/docs/src/Tutorials/files/jupyter_screen.png b/docs/src/Tutorials/files/jupyter_screen.png deleted file mode 100644 index b628dbf017..0000000000 Binary files a/docs/src/Tutorials/files/jupyter_screen.png and /dev/null differ diff --git a/docs/src/Tutorials/files/opennotebook.png b/docs/src/Tutorials/files/opennotebook.png deleted file mode 100644 index 87362f5f15..0000000000 Binary files a/docs/src/Tutorials/files/opennotebook.png and /dev/null differ diff --git a/docs/src/Tutorials/tutorial_3/output_14_0.svg b/docs/src/Tutorials/files/output_14_0.svg similarity index 100% rename from docs/src/Tutorials/tutorial_3/output_14_0.svg rename to docs/src/Tutorials/files/output_14_0.svg diff --git a/docs/src/Tutorials/files/us_outline.png b/docs/src/Tutorials/files/us_outline.png deleted file mode 100644 index 000dd925d2..0000000000 Binary files a/docs/src/Tutorials/files/us_outline.png and /dev/null differ diff --git a/docs/src/Tutorials/files/usingIJulia.png b/docs/src/Tutorials/files/usingIJulia.png deleted file mode 100644 index 6a615c30b8..0000000000 Binary files a/docs/src/Tutorials/files/usingIJulia.png and /dev/null differ diff --git a/docs/src/Tutorials/tutorial_3/output_14_0.png b/docs/src/Tutorials/tutorial_3/output_14_0.png deleted file mode 100644 index 5aa2274a42..0000000000 Binary files a/docs/src/Tutorials/tutorial_3/output_14_0.png and /dev/null differ diff --git a/docs/src/User_Guide/multi_stage_input.md b/docs/src/User_Guide/multi_stage_input.md index 34b4132f59..6d9d9fca3f 100644 --- a/docs/src/User_Guide/multi_stage_input.md +++ b/docs/src/User_Guide/multi_stage_input.md @@ -12,6 +12,7 @@ The table below summarizes the key differences in the two model setups. | Objective function cost basis | Net present value | Annualized costs | | Price/dual variable information available? | No | Yes | + ### Additional inputs needed for multi-stage modeling #### Input data files @@ -58,6 +59,9 @@ Instead of one set of input files, there is one directory of input files that ne | WACC | The line-specific weighted average cost of capital. | +!!! warning "Warning" + If `New_Build` and `Can_Retire` are both set to 0, the model will not transfer built capacity from one stage to the next, but will instead set capacity to the value of existing capacity from the input files for each stage. Therefore, the user must ensure that the capacity is correctly set in the input files for each stage. Not following this guideline may result in incorrect or unexpected results, particularly when setting a a non-zero value for the `Min_Retired_Cap_MW` parameter. + #### Settings Files A separate settings.yml file includes a list of parameters to be specified to formulate the multi-stage planning model.